Compare commits
4 commits
f003c1697a
...
324f479434
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
324f479434 | ||
|
|
8809c2e595 | ||
|
|
02f57fd562 | ||
|
|
a25c6ee795 |
11 changed files with 342 additions and 162 deletions
|
|
@ -1,16 +1,24 @@
|
||||||
#ifndef AACTIONINITIALIZATION_H
|
#ifndef AACTIONINITIALIZATION_H
|
||||||
#define AACTIONINITIALIZATION_H
|
#define AACTIONINITIALIZATION_H
|
||||||
|
|
||||||
|
#pragma once
|
||||||
#include "G4VUserActionInitialization.hh"
|
#include "G4VUserActionInitialization.hh"
|
||||||
|
|
||||||
|
class ARunAction;
|
||||||
|
class APrimaryGenerator;
|
||||||
|
class ASensitiveDetector;
|
||||||
|
|
||||||
class AActionInitialization : public G4VUserActionInitialization
|
class AActionInitialization : public G4VUserActionInitialization
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
AActionInitialization();
|
AActionInitialization(ASensitiveDetector* sd);
|
||||||
virtual ~AActionInitialization();
|
virtual ~AActionInitialization();
|
||||||
|
|
||||||
virtual void Build() const override;
|
virtual void Build() const override;
|
||||||
virtual void BuildForMaster() const override;
|
virtual void BuildForMaster() const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
ASensitiveDetector* fSD; // Pointer auf den Sensitive Detector
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,8 @@ public:
|
||||||
virtual G4VPhysicalVolume* Construct();
|
virtual G4VPhysicalVolume* Construct();
|
||||||
void ConstructSDandField();
|
void ConstructSDandField();
|
||||||
|
|
||||||
|
ASensitiveDetector* GetSensitiveDetector() const { return fSD; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<G4LogicalVolume*> detectorVolumes;
|
std::vector<G4LogicalVolume*> detectorVolumes;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,25 @@
|
||||||
#ifndef AMESSENGER_HH
|
#pragma once
|
||||||
#define AMESSENGER_HH
|
|
||||||
|
|
||||||
#include "G4UImessenger.hh"
|
#include "G4UImessenger.hh"
|
||||||
#include "G4UIcmdWithAString.hh"
|
#include "G4UIcmdWithAString.hh"
|
||||||
|
#include "G4UIcmdWithADoubleAndUnit.hh"
|
||||||
|
|
||||||
class ASensitiveDetector;
|
class ASensitiveDetector;
|
||||||
|
class APrimaryGenerator;
|
||||||
|
|
||||||
class AMessenger : public G4UImessenger
|
class AMessenger : public G4UImessenger
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
AMessenger(ASensitiveDetector* sd);
|
AMessenger(ASensitiveDetector* sd, APrimaryGenerator* generator = nullptr);
|
||||||
~AMessenger();
|
~AMessenger();
|
||||||
|
|
||||||
virtual void SetNewValue(G4UIcommand* cmd, G4String value) override;
|
void SetNewValue(G4UIcommand* cmd, G4String value) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ASensitiveDetector* fSD;
|
ASensitiveDetector* fSD;
|
||||||
G4UIcmdWithAString* fOutputFileCmd;
|
APrimaryGenerator* fGenerator; // Referenz zum Primärgenerator
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
G4UIcmdWithAString* fOutputFileCmd;
|
||||||
|
G4UIcmdWithAString* fParticleTypeCmd;
|
||||||
|
G4UIcmdWithADoubleAndUnit* fEnergyCmd;
|
||||||
|
G4UIcmdWithAString* fOutputColumnsCmd;
|
||||||
|
};
|
||||||
|
|
@ -13,10 +13,15 @@ public:
|
||||||
APrimaryGenerator();
|
APrimaryGenerator();
|
||||||
~APrimaryGenerator();
|
~APrimaryGenerator();
|
||||||
|
|
||||||
virtual void GeneratePrimaries(G4Event *);
|
virtual void GeneratePrimaries(G4Event * anEvent) override;
|
||||||
|
|
||||||
|
void SetParticleEnergy(G4double energy) { fParticleEnergy = energy; }
|
||||||
|
void SetParticleName(const G4String& name) { fParticleName = name; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
G4ParticleGun *fParticleGun;
|
G4ParticleGun *fParticleGun;
|
||||||
|
G4double fParticleEnergy;
|
||||||
|
G4String fParticleName;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -8,14 +8,20 @@
|
||||||
#include "G4Track.hh"
|
#include "G4Track.hh"
|
||||||
#include "G4SystemOfUnits.hh"
|
#include "G4SystemOfUnits.hh"
|
||||||
#include "G4UnitsTable.hh"
|
#include "G4UnitsTable.hh"
|
||||||
#include "G4UImessenger.hh"
|
|
||||||
#include "G4UIcmdWithAString.hh"
|
|
||||||
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <functional>
|
||||||
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
class AMessenger;
|
class AMessenger;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Makro für die OutputMap – gleiche Logik wie beim Kollegen
|
||||||
|
//
|
||||||
|
#define OUTMAP [](const HitInfo& hit, std::ostream& out)
|
||||||
|
|
||||||
class ASensitiveDetector : public G4VSensitiveDetector
|
class ASensitiveDetector : public G4VSensitiveDetector
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
@ -23,39 +29,89 @@ public:
|
||||||
~ASensitiveDetector();
|
~ASensitiveDetector();
|
||||||
|
|
||||||
virtual void Initialize(G4HCofThisEvent* hce) override;
|
virtual void Initialize(G4HCofThisEvent* hce) override;
|
||||||
|
virtual G4bool ProcessHits(G4Step* step, G4TouchableHistory* touch) override;
|
||||||
virtual void EndOfEvent(G4HCofThisEvent* hce) override;
|
virtual void EndOfEvent(G4HCofThisEvent* hce) override;
|
||||||
virtual G4bool ProcessHits(G4Step* step, G4TouchableHistory* touchHist) override;
|
|
||||||
//Filename
|
void SetOutputFilename(const G4String& f) { fOutputFilename = f; }
|
||||||
void SetOutputFilename(const G4String& name) { fOutputFilename = name; }
|
void SetOutputColumns(const std::vector<G4String>& cols) { fOutputColumns = cols; }
|
||||||
void SetMessenger(AMessenger* messenger) { fMessenger = messenger; }
|
void SetMessenger(AMessenger* m) { fMessenger = m; }
|
||||||
void RegisterVolumeName(G4LogicalVolume* lv, const std::string& cleanName) {
|
|
||||||
fCleanNames[lv] = cleanName;}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
AMessenger* fMessenger = nullptr; // jetzt optional
|
AMessenger* fMessenger = nullptr;
|
||||||
G4String fOutputFilename = "outfiles/shower_setup.txt";
|
G4String fOutputFilename;
|
||||||
G4int fCurrentEventID = -1; // speichert die aktuelle Event-ID
|
G4int fCurrentEventID = -1;
|
||||||
|
|
||||||
struct HitInfo {
|
public:
|
||||||
G4int eventID;
|
//
|
||||||
G4int trackID;
|
// HitInfo enthält ALLE üblichen Parameter
|
||||||
G4int parentID;
|
//
|
||||||
G4String particleName;
|
struct HitInfo
|
||||||
G4double particleEnergy;
|
{
|
||||||
G4String primaryParticleName;
|
// --- Basis-identifikation ---
|
||||||
G4double primaryEnergy;
|
G4int eventID; // Nummer des Events
|
||||||
G4double energyDeposited;
|
G4int trackID; // Track ID
|
||||||
G4String detectorName;
|
G4int parentID; // Parent Track ID
|
||||||
G4String cleanDetectorName;
|
|
||||||
|
|
||||||
HitInfo()
|
// --- Teilchen ---
|
||||||
: trackID(-1), parentID(-1), particleEnergy(0.), primaryEnergy(0.), energyDeposited(0.) {}
|
G4String particleName; // Name des Teilchens
|
||||||
|
G4int pdg; // PDG-Code
|
||||||
|
G4double particleEnergy;// kinetische Energie am Vertex
|
||||||
|
|
||||||
|
// --- Primärinformation ---
|
||||||
|
G4String primaryName; // Name des Primärteilchens
|
||||||
|
G4double primaryEnergy; // Primärenergie
|
||||||
|
|
||||||
|
// --- Energien ---
|
||||||
|
G4double edep; // Deposited Energy
|
||||||
|
G4double ekin; // aktuelle kinetische Energie
|
||||||
|
|
||||||
|
// --- Positionen ---
|
||||||
|
G4ThreeVector prePos; // Position vor dem Step
|
||||||
|
G4ThreeVector postPos; // Position nach dem Step
|
||||||
|
|
||||||
|
// --- Richtung ---
|
||||||
|
G4ThreeVector preDir; // Richtung vor dem Step
|
||||||
|
G4ThreeVector postDir; // Richtung nach dem Step
|
||||||
|
|
||||||
|
// --- Zeiten ---
|
||||||
|
G4double globalTime; // absolute Zeit
|
||||||
|
G4double localTime; // lokale Zeit
|
||||||
|
|
||||||
|
// --- Step-Information ---
|
||||||
|
G4double stepLength; // Step-Länge
|
||||||
|
G4String processName; // Prozess, der diesen Step erzeugt hat
|
||||||
|
|
||||||
|
// --- Detektor ---
|
||||||
|
G4String detectorName; // voller Name
|
||||||
|
G4String cleanName; // aufgeräumter Name ohne _phys
|
||||||
|
|
||||||
|
HitInfo() :
|
||||||
|
eventID(0), trackID(0), parentID(0),
|
||||||
|
pdg(0),
|
||||||
|
particleEnergy(0.), primaryEnergy(0.),
|
||||||
|
edep(0.), ekin(0.),
|
||||||
|
globalTime(0.), localTime(0.),
|
||||||
|
stepLength(0.)
|
||||||
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
G4String fDetectorName;
|
private:
|
||||||
std::unordered_map<G4LogicalVolume*, std::string> fCleanNames;
|
//
|
||||||
std::unordered_map<G4int, HitInfo> fTrackHitMap; // TrackID → HitInfo
|
// OutputMap: string → Lambda(hit, out)
|
||||||
|
//
|
||||||
|
using OutputLambda = std::function<void(const HitInfo&, std::ostream&)>;
|
||||||
|
std::map<std::string, OutputLambda> outputMap;
|
||||||
|
|
||||||
|
//
|
||||||
|
// interne Daten
|
||||||
|
//
|
||||||
|
std::vector<G4String> fOutputColumns;
|
||||||
|
std::unordered_map<G4int, HitInfo> fTrackHitMap;
|
||||||
|
|
||||||
|
//
|
||||||
|
// interne Hilfsfunktionen
|
||||||
|
//
|
||||||
|
void InitializeOutputMap();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
17
macros/defrun.mac
Normal file
17
macros/defrun.mac
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
/run/numberOfThreads 2
|
||||||
|
|
||||||
|
# --- Output Datei setzen ---
|
||||||
|
/my/outputFilename outfiles/test1000_100MeV_e
|
||||||
|
|
||||||
|
# --- Particle Type setzen ---
|
||||||
|
/my/particleType e-
|
||||||
|
|
||||||
|
# --- Particle Energy setzen ---
|
||||||
|
/my/particleEnergy 100 MeV
|
||||||
|
|
||||||
|
# --- Spalten setzen (ohne Kommata) ---
|
||||||
|
/my/outputColumns event track parent part pdg ekin edep x y z dir step proc det
|
||||||
|
|
||||||
|
/run/initialize
|
||||||
|
/run/beamOn 10
|
||||||
|
|
||||||
6
sim.cc
6
sim.cc
|
|
@ -26,10 +26,12 @@ int main(int argc, char** argv)
|
||||||
runManager->SetUserInitialization(new APhysicsList());
|
runManager->SetUserInitialization(new APhysicsList());
|
||||||
|
|
||||||
// Detector
|
// Detector
|
||||||
runManager->SetUserInitialization(new ADetectorConstruction());
|
ADetectorConstruction* detector = new ADetectorConstruction();
|
||||||
|
runManager->SetUserInitialization(detector);
|
||||||
|
|
||||||
// Actions
|
// Actions
|
||||||
runManager->SetUserInitialization(new AActionInitialization());
|
runManager->SetUserInitialization(new AActionInitialization(detector->GetSensitiveDetector()));
|
||||||
|
|
||||||
|
|
||||||
// Visualization
|
// Visualization
|
||||||
G4VisManager* visManager = new G4VisExecutive();
|
G4VisManager* visManager = new G4VisExecutive();
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
#include "AActionInitialization.hh"
|
#include "AActionInitialization.hh"
|
||||||
|
#include "AMessenger.hh"
|
||||||
#include "APrimaryGenerator.hh"
|
#include "APrimaryGenerator.hh"
|
||||||
#include "ARunAction.hh"
|
#include "ARunAction.hh"
|
||||||
|
|
||||||
AActionInitialization::AActionInitialization()
|
AActionInitialization::AActionInitialization(ASensitiveDetector* sd)
|
||||||
: G4VUserActionInitialization()
|
: G4VUserActionInitialization(), fSD(sd)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -12,7 +13,10 @@ AActionInitialization::~AActionInitialization() {}
|
||||||
void AActionInitialization::Build() const
|
void AActionInitialization::Build() const
|
||||||
{
|
{
|
||||||
// Primärgenerator
|
// Primärgenerator
|
||||||
SetUserAction(new APrimaryGenerator());
|
APrimaryGenerator* primaryGen = new APrimaryGenerator();
|
||||||
|
SetUserAction(primaryGen);
|
||||||
|
|
||||||
|
AMessenger* messenger = new AMessenger(fSD, primaryGen);
|
||||||
|
|
||||||
// RunAction
|
// RunAction
|
||||||
SetUserAction(new ARunAction());
|
SetUserAction(new ARunAction());
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,42 @@
|
||||||
#include "AMessenger.hh"
|
#include "AMessenger.hh"
|
||||||
#include "ASensitiveDetector.hh"
|
#include "ASensitiveDetector.hh"
|
||||||
|
#include "APrimaryGenerator.hh"
|
||||||
|
#include "G4SystemOfUnits.hh"
|
||||||
|
|
||||||
AMessenger::AMessenger(ASensitiveDetector* sd)
|
AMessenger::AMessenger(ASensitiveDetector* sd, APrimaryGenerator* generator)
|
||||||
: fSD(sd)
|
: fSD(sd), fGenerator(generator)
|
||||||
{
|
{
|
||||||
// eigenes UI Kommando
|
// eigenes UI Kommando
|
||||||
fOutputFileCmd = new G4UIcmdWithAString("/my/outputFilename", this);
|
fOutputFileCmd = new G4UIcmdWithAString("/my/outputFilename", this);
|
||||||
fOutputFileCmd->SetGuidance("Set output filename for SD text output.");
|
fOutputFileCmd->SetGuidance("Set output filename for SD text output.");
|
||||||
fOutputFileCmd->SetParameterName("filename", false);
|
fOutputFileCmd->SetParameterName("filename", false);
|
||||||
|
|
||||||
|
// Kommando für Teilchentyp
|
||||||
|
fParticleTypeCmd = new G4UIcmdWithAString("/my/particleType", this);
|
||||||
|
fParticleTypeCmd->SetGuidance("Set particle type (e-, e+, gamma, proton, neutron).");
|
||||||
|
fParticleTypeCmd->SetParameterName("particle", false);
|
||||||
|
fParticleTypeCmd->AvailableForStates(G4State_PreInit, G4State_Idle);
|
||||||
|
|
||||||
|
// Kommando für Teilchenenergie
|
||||||
|
fEnergyCmd = new G4UIcmdWithADoubleAndUnit("/my/particleEnergy", this);
|
||||||
|
fEnergyCmd->SetGuidance("Set particle energy.");
|
||||||
|
fEnergyCmd->SetParameterName("energy", false);
|
||||||
|
fEnergyCmd->SetUnitCategory("Energy");
|
||||||
|
fEnergyCmd->AvailableForStates(G4State_PreInit, G4State_Idle);
|
||||||
|
|
||||||
|
//Kommando für Parameterreihenfolge
|
||||||
|
fOutputColumnsCmd = new G4UIcmdWithAString("/my/outputColumns", this);
|
||||||
|
fOutputColumnsCmd->SetGuidance("Set output columns and order (comma separated). E.g.: particle,Epart,Dname,Edep");
|
||||||
|
fOutputColumnsCmd->SetParameterName("columns", false);
|
||||||
|
fOutputColumnsCmd->AvailableForStates(G4State_PreInit, G4State_Idle);
|
||||||
}
|
}
|
||||||
|
|
||||||
AMessenger::~AMessenger()
|
AMessenger::~AMessenger()
|
||||||
{
|
{
|
||||||
delete fOutputFileCmd;
|
delete fOutputFileCmd;
|
||||||
|
delete fParticleTypeCmd;
|
||||||
|
delete fEnergyCmd;
|
||||||
|
delete fOutputColumnsCmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AMessenger::SetNewValue(G4UIcommand* cmd, G4String value)
|
void AMessenger::SetNewValue(G4UIcommand* cmd, G4String value)
|
||||||
|
|
@ -21,4 +45,24 @@ void AMessenger::SetNewValue(G4UIcommand* cmd, G4String value)
|
||||||
{
|
{
|
||||||
fSD->SetOutputFilename(value);
|
fSD->SetOutputFilename(value);
|
||||||
}
|
}
|
||||||
|
else if(cmd == fEnergyCmd && fGenerator)
|
||||||
|
{
|
||||||
|
fGenerator->SetParticleEnergy(fEnergyCmd->GetNewDoubleValue(value));
|
||||||
|
}
|
||||||
|
else if (cmd == fParticleTypeCmd && fGenerator)
|
||||||
|
{
|
||||||
|
fGenerator->SetParticleName(value);
|
||||||
|
}
|
||||||
|
else if(cmd == fOutputColumnsCmd && fSD)
|
||||||
|
{
|
||||||
|
std::vector<G4String> cols;
|
||||||
|
std::istringstream iss(value);
|
||||||
|
G4String token;
|
||||||
|
while(iss >> token)
|
||||||
|
{
|
||||||
|
cols.push_back(token);
|
||||||
|
}
|
||||||
|
fSD->SetOutputColumns(cols);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,29 +3,16 @@
|
||||||
APrimaryGenerator::APrimaryGenerator()
|
APrimaryGenerator::APrimaryGenerator()
|
||||||
{
|
{
|
||||||
fParticleGun = new G4ParticleGun(1); // 1 particles per event
|
fParticleGun = new G4ParticleGun(1); // 1 particles per event
|
||||||
|
fParticleEnergy = 100.*MeV; // Default-Energie
|
||||||
|
fParticleName = "e-"; //default
|
||||||
|
|
||||||
//Particle position
|
G4ThreeVector pos(0.,0.,-1.*cm);
|
||||||
G4double x = 0. * m;
|
G4ThreeVector mom(0.,0.,1.);
|
||||||
G4double y = 0. * m;
|
|
||||||
G4double z = -1. * cm;
|
|
||||||
|
|
||||||
G4ThreeVector pos(x, y, z);
|
|
||||||
|
|
||||||
//Particle direction
|
|
||||||
G4double px = 0.;
|
|
||||||
G4double py = 0.;
|
|
||||||
G4double pz = 1.;
|
|
||||||
|
|
||||||
G4ThreeVector mom(px,py,pz);
|
|
||||||
|
|
||||||
//Particle type
|
|
||||||
G4ParticleTable* particleTable = G4ParticleTable::GetParticleTable();
|
G4ParticleTable* particleTable = G4ParticleTable::GetParticleTable();
|
||||||
// possibilities: "e+","e-","gamma", ,"proton", "neutron"
|
|
||||||
G4ParticleDefinition* particle = particleTable->FindParticle("e-");
|
G4ParticleDefinition* particle = particleTable->FindParticle("e-");
|
||||||
|
|
||||||
fParticleGun->SetParticlePosition(pos);
|
fParticleGun->SetParticlePosition(pos);
|
||||||
fParticleGun->SetParticleMomentumDirection(mom);
|
fParticleGun->SetParticleMomentumDirection(mom);
|
||||||
fParticleGun->SetParticleEnergy(100 * MeV); //or GeV
|
|
||||||
fParticleGun->SetParticleDefinition(particle);
|
fParticleGun->SetParticleDefinition(particle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -36,6 +23,15 @@ APrimaryGenerator::~APrimaryGenerator()
|
||||||
|
|
||||||
void APrimaryGenerator::GeneratePrimaries(G4Event *anEvent)
|
void APrimaryGenerator::GeneratePrimaries(G4Event *anEvent)
|
||||||
{
|
{
|
||||||
//Create vertex
|
G4ParticleTable* particleTable = G4ParticleTable::GetParticleTable();
|
||||||
|
G4ParticleDefinition* particle = particleTable->FindParticle(fParticleName);
|
||||||
|
if (!particle)
|
||||||
|
{
|
||||||
|
G4cerr << "Unknown particle: " << fParticleName << ". Using e- as default." << G4endl;
|
||||||
|
particle = particleTable->FindParticle("e-");
|
||||||
|
}
|
||||||
|
|
||||||
|
fParticleGun->SetParticleDefinition(particle);
|
||||||
|
fParticleGun->SetParticleEnergy(fParticleEnergy); // dynamisch vom Macro
|
||||||
fParticleGun->GeneratePrimaryVertex(anEvent);
|
fParticleGun->GeneratePrimaryVertex(anEvent);
|
||||||
}
|
}
|
||||||
|
|
@ -1,131 +1,174 @@
|
||||||
#include "ASensitiveDetector.hh"
|
#include "ASensitiveDetector.hh"
|
||||||
#include "AMessenger.hh"
|
#include "AMessenger.hh"
|
||||||
#include "G4RunManager.hh"
|
|
||||||
#include "G4Event.hh"
|
#include "G4Event.hh"
|
||||||
#include "G4PrimaryVertex.hh"
|
#include "G4RunManager.hh"
|
||||||
#include "G4PrimaryParticle.hh"
|
#include "G4Threading.hh"
|
||||||
#include "G4SystemOfUnits.hh"
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
ASensitiveDetector::ASensitiveDetector(G4String name)
|
ASensitiveDetector::ASensitiveDetector(G4String name)
|
||||||
: G4VSensitiveDetector(name), fDetectorName(name)
|
: G4VSensitiveDetector(name), fOutputFilename("outfiles/shower_setup")
|
||||||
{
|
{
|
||||||
fOutputFilename = "outfiles/shower_setup.txt";
|
|
||||||
std::filesystem::create_directories("outfiles");
|
std::filesystem::create_directories("outfiles");
|
||||||
|
InitializeOutputMap();
|
||||||
|
|
||||||
|
if(fOutputColumns.empty()) {
|
||||||
|
fOutputColumns = {"event", "track", "parent", "part", "edep", "det"};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ASensitiveDetector::~ASensitiveDetector()
|
ASensitiveDetector::~ASensitiveDetector() {}
|
||||||
{
|
|
||||||
|
|
||||||
}
|
void ASensitiveDetector::Initialize(G4HCofThisEvent*)
|
||||||
|
|
||||||
void ASensitiveDetector::Initialize(G4HCofThisEvent* /*hce*/)
|
|
||||||
{
|
{
|
||||||
fTrackHitMap.clear();
|
fTrackHitMap.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
G4bool ASensitiveDetector::ProcessHits(G4Step* step, G4TouchableHistory* /*touchHist*/)
|
void ASensitiveDetector::InitializeOutputMap()
|
||||||
{
|
{
|
||||||
const G4Event* event = G4RunManager::GetRunManager()->GetCurrentEvent();
|
outputMap = {
|
||||||
|
{"event", OUTMAP { out << hit.eventID; }},
|
||||||
|
{"track", OUTMAP { out << hit.trackID; }},
|
||||||
|
{"parent", OUTMAP { out << hit.parentID; }},
|
||||||
|
|
||||||
|
{"part", OUTMAP { out << hit.particleName; }},
|
||||||
|
{"pdg", OUTMAP { out << hit.pdg; }},
|
||||||
|
{"ekin", OUTMAP { out << hit.ekin / MeV; }},
|
||||||
|
{"edep", OUTMAP { out << hit.edep / MeV; }},
|
||||||
|
|
||||||
|
{"x", OUTMAP { out << hit.postPos.x() / mm; }},
|
||||||
|
{"y", OUTMAP { out << hit.postPos.y() / mm; }},
|
||||||
|
{"z", OUTMAP { out << hit.postPos.z() / mm; }},
|
||||||
|
{"pos", OUTMAP { out << hit.postPos.x()/mm<<" "<<hit.postPos.y()/mm<<" "<<hit.postPos.z()/mm; }},
|
||||||
|
|
||||||
|
{"dx", OUTMAP { out << hit.postDir.x(); }},
|
||||||
|
{"dy", OUTMAP { out << hit.postDir.y(); }},
|
||||||
|
{"dz", OUTMAP { out << hit.postDir.z(); }},
|
||||||
|
{"dir", OUTMAP { out << hit.postDir.x()<<" "<<hit.postDir.y()<<" "<<hit.postDir.z(); }},
|
||||||
|
|
||||||
|
{"global_t", OUTMAP { out << hit.globalTime; }},
|
||||||
|
{"local_t", OUTMAP { out << hit.localTime; }},
|
||||||
|
|
||||||
|
{"step", OUTMAP { out << hit.stepLength / mm; }},
|
||||||
|
{"proc", OUTMAP { out << hit.processName; }},
|
||||||
|
|
||||||
|
{"det", OUTMAP { out << hit.cleanName; }}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
G4bool ASensitiveDetector::ProcessHits(G4Step* step, G4TouchableHistory*)
|
||||||
|
{
|
||||||
|
if(!step) return false;
|
||||||
|
|
||||||
|
G4Track* trk = step->GetTrack();
|
||||||
|
if(!trk) return false;
|
||||||
|
|
||||||
|
const G4Event* event = G4RunManager::GetRunManager()->GetCurrentEvent();
|
||||||
if(!event) return false;
|
if(!event) return false;
|
||||||
|
|
||||||
// Event-ID direkt hier setzen
|
|
||||||
fCurrentEventID = event->GetEventID();
|
fCurrentEventID = event->GetEventID();
|
||||||
|
G4int id = trk->GetTrackID();
|
||||||
|
|
||||||
G4Track* track = step->GetTrack();
|
HitInfo& hit = fTrackHitMap[id];
|
||||||
G4int trackID = track->GetTrackID();
|
|
||||||
|
|
||||||
auto it = fTrackHitMap.find(trackID);
|
// Basisdaten
|
||||||
if (it == fTrackHitMap.end())
|
|
||||||
{
|
|
||||||
HitInfo hit;
|
|
||||||
hit.eventID = fCurrentEventID;
|
hit.eventID = fCurrentEventID;
|
||||||
hit.trackID = trackID;
|
hit.trackID = id;
|
||||||
hit.parentID = track->GetParentID();
|
hit.parentID = trk->GetParentID();
|
||||||
hit.particleName = track->GetDefinition()->GetParticleName();
|
if(trk->GetDefinition()) {
|
||||||
hit.particleEnergy = track->GetVertexKineticEnergy();
|
hit.particleName = trk->GetDefinition()->GetParticleName();
|
||||||
hit.detectorName = step->GetPreStepPoint()->GetTouchable()->GetVolume()->GetName();
|
hit.pdg = trk->GetDefinition()->GetPDGEncoding();
|
||||||
std::string detNameStr = hit.detectorName;
|
}
|
||||||
size_t pos = detNameStr.find("_phys");
|
hit.ekin = trk->GetKineticEnergy();
|
||||||
if (pos != std::string::npos)
|
|
||||||
detNameStr = detNameStr.substr(0, pos); // nur Basisname
|
// Primärteilchen (sicher prüfen)
|
||||||
hit.cleanDetectorName = detNameStr;
|
if(auto vertex = event->GetPrimaryVertex()) {
|
||||||
// Primary particle info
|
if(auto prim = vertex->GetPrimary()) {
|
||||||
G4PrimaryVertex* pv = event->GetPrimaryVertex();
|
if(auto code = prim->GetG4code()) {
|
||||||
if (pv)
|
hit.primaryName = code->GetParticleName();
|
||||||
{
|
hit.primaryEnergy = prim->GetKineticEnergy();
|
||||||
G4PrimaryParticle* pp = pv->GetPrimary();
|
}
|
||||||
if (pp && pp->GetG4code())
|
}
|
||||||
hit.primaryParticleName = pp->GetG4code()->GetParticleName();
|
|
||||||
if (pp)
|
|
||||||
hit.primaryEnergy = pp->GetKineticEnergy();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hit.energyDeposited = step->GetTotalEnergyDeposit();
|
// Energie aufsummieren
|
||||||
fTrackHitMap[trackID] = hit;
|
hit.edep += step->GetTotalEnergyDeposit();
|
||||||
|
|
||||||
|
// PreStep/PostStep prüfen
|
||||||
|
auto pre = step->GetPreStepPoint();
|
||||||
|
auto post = step->GetPostStepPoint();
|
||||||
|
if(pre && post) {
|
||||||
|
|
||||||
|
hit.prePos = pre->GetPosition();
|
||||||
|
hit.postPos = post->GetPosition();
|
||||||
|
hit.preDir = pre->GetMomentumDirection();
|
||||||
|
hit.postDir = post->GetMomentumDirection();
|
||||||
|
hit.globalTime = post->GetGlobalTime();
|
||||||
|
hit.localTime = post->GetLocalTime();
|
||||||
|
hit.stepLength = step->GetStepLength();
|
||||||
|
hit.processName = post->GetProcessDefinedStep() ? post->GetProcessDefinedStep()->GetProcessName() : "none";
|
||||||
|
|
||||||
|
// Detektorname prüfen
|
||||||
|
if(pre->GetTouchable()) {
|
||||||
|
auto vol = pre->GetTouchable()->GetVolume();
|
||||||
|
if(vol) {
|
||||||
|
auto full = vol->GetName();
|
||||||
|
hit.detectorName = full;
|
||||||
|
auto pos = full.find("_phys");
|
||||||
|
hit.cleanName = (pos == std::string::npos ? full : full.substr(0, pos));
|
||||||
|
} else {
|
||||||
|
hit.detectorName = "none";
|
||||||
|
hit.cleanName = "none";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
hit.detectorName = "none";
|
||||||
|
hit.cleanName = "none";
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
it->second.energyDeposited += step->GetTotalEnergyDeposit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ASensitiveDetector::EndOfEvent(G4HCofThisEvent*)
|
||||||
void ASensitiveDetector::EndOfEvent(G4HCofThisEvent* /*hce*/)
|
|
||||||
{
|
{
|
||||||
if (fOutputFilename.empty()) fOutputFilename = "outfiles/shower_setup.txt";
|
// Thread-ID für Datei
|
||||||
std::filesystem::create_directories("outfiles");
|
G4int tid = G4Threading::G4GetThreadId();
|
||||||
|
|
||||||
std::ofstream out(fOutputFilename, std::ios::app);
|
// Thread-local Datei
|
||||||
|
thread_local std::ofstream out;
|
||||||
|
|
||||||
|
// Datei öffnen, wenn noch nicht offen
|
||||||
if(!out.is_open()) {
|
if(!out.is_open()) {
|
||||||
G4cerr << "Cannot open file " << fOutputFilename << "!" << G4endl;
|
std::filesystem::create_directories("outfiles");
|
||||||
|
std::string threadFile = fOutputFilename + "_" + std::to_string(tid) + ".hits";
|
||||||
|
out.open(threadFile, std::ios::app);
|
||||||
|
if(!out.is_open()) {
|
||||||
|
G4cerr << "Cannot open output file: " << threadFile << G4endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool headerWritten = false;
|
// Header einmal pro Datei
|
||||||
if (!headerWritten) {
|
for(size_t i=0; i<fOutputColumns.size(); ++i) {
|
||||||
out << "eventID\ttrackID\tparentID\tparticle\tEpart\tPrimparticle\tEprim\tDname\tEdep\n";
|
out << fOutputColumns[i];
|
||||||
headerWritten = true;
|
if(i+1 < fOutputColumns.size()) out << "\t";
|
||||||
|
}
|
||||||
|
out << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hits nur für das aktuelle Event
|
// Hits schreiben
|
||||||
std::vector<HitInfo> hits;
|
for(auto& [id, hit] : fTrackHitMap) {
|
||||||
for (const auto& [trackID, hit] : fTrackHitMap) {
|
for(size_t i=0; i<fOutputColumns.size(); ++i) {
|
||||||
hits.push_back(hit);
|
const auto& col = fOutputColumns[i];
|
||||||
|
if(outputMap.count(col))
|
||||||
|
outputMap[col](hit, out);
|
||||||
|
else
|
||||||
|
out << "NA";
|
||||||
|
|
||||||
|
if(i+1 < fOutputColumns.size()) out << "\t";
|
||||||
|
}
|
||||||
|
out << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sortieren: parentID -> trackID
|
// Map zurücksetzen
|
||||||
std::sort(hits.begin(), hits.end(), [](const HitInfo& a, const HitInfo& b) {
|
|
||||||
if (a.parentID != b.parentID)
|
|
||||||
return a.parentID < b.parentID;
|
|
||||||
return a.trackID < b.trackID;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Schreiben
|
|
||||||
for (const auto& hit : hits)
|
|
||||||
{
|
|
||||||
out << hit.eventID
|
|
||||||
<< "\t" << hit.trackID
|
|
||||||
<< "\t" << hit.parentID
|
|
||||||
<< "\t" << hit.particleName
|
|
||||||
<< "\t" << hit.particleEnergy / MeV
|
|
||||||
<< "\t" << hit.primaryParticleName
|
|
||||||
<< "\t" << hit.primaryEnergy / MeV
|
|
||||||
<< "\t" << hit.cleanDetectorName
|
|
||||||
<< "\t" << hit.energyDeposited / MeV
|
|
||||||
<< "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
out.close();
|
|
||||||
|
|
||||||
// Map leeren für nächstes Event
|
|
||||||
fTrackHitMap.clear();
|
fTrackHitMap.clear();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue