Compare commits
No commits in common. "324f4794348d97e6f17d0dea96fd0a3f55553ffa" and "f003c1697a2406fe8c4ec219f7ebc09e4a4d8c7c" have entirely different histories.
324f479434
...
f003c1697a
11 changed files with 162 additions and 342 deletions
|
|
@ -1,24 +1,16 @@
|
||||||
#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(ASensitiveDetector* sd);
|
AActionInitialization();
|
||||||
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,8 +32,6 @@ 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,25 +1,22 @@
|
||||||
#pragma once
|
#ifndef AMESSENGER_HH
|
||||||
|
#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, APrimaryGenerator* generator = nullptr);
|
AMessenger(ASensitiveDetector* sd);
|
||||||
~AMessenger();
|
~AMessenger();
|
||||||
|
|
||||||
void SetNewValue(G4UIcommand* cmd, G4String value) override;
|
virtual void SetNewValue(G4UIcommand* cmd, G4String value) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ASensitiveDetector* fSD;
|
ASensitiveDetector* fSD;
|
||||||
APrimaryGenerator* fGenerator; // Referenz zum Primärgenerator
|
|
||||||
|
|
||||||
G4UIcmdWithAString* fOutputFileCmd;
|
G4UIcmdWithAString* fOutputFileCmd;
|
||||||
G4UIcmdWithAString* fParticleTypeCmd;
|
};
|
||||||
G4UIcmdWithADoubleAndUnit* fEnergyCmd;
|
|
||||||
G4UIcmdWithAString* fOutputColumnsCmd;
|
#endif
|
||||||
};
|
|
||||||
|
|
|
||||||
|
|
@ -13,15 +13,10 @@ public:
|
||||||
APrimaryGenerator();
|
APrimaryGenerator();
|
||||||
~APrimaryGenerator();
|
~APrimaryGenerator();
|
||||||
|
|
||||||
virtual void GeneratePrimaries(G4Event * anEvent) override;
|
virtual void GeneratePrimaries(G4Event *);
|
||||||
|
|
||||||
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,20 +8,14 @@
|
||||||
#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:
|
||||||
|
|
@ -29,89 +23,39 @@ 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;
|
||||||
void SetOutputFilename(const G4String& f) { fOutputFilename = f; }
|
//Filename
|
||||||
void SetOutputColumns(const std::vector<G4String>& cols) { fOutputColumns = cols; }
|
void SetOutputFilename(const G4String& name) { fOutputFilename = name; }
|
||||||
void SetMessenger(AMessenger* m) { fMessenger = m; }
|
void SetMessenger(AMessenger* messenger) { fMessenger = messenger; }
|
||||||
|
void RegisterVolumeName(G4LogicalVolume* lv, const std::string& cleanName) {
|
||||||
|
fCleanNames[lv] = cleanName;}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
AMessenger* fMessenger = nullptr;
|
AMessenger* fMessenger = nullptr; // jetzt optional
|
||||||
G4String fOutputFilename;
|
G4String fOutputFilename = "outfiles/shower_setup.txt";
|
||||||
G4int fCurrentEventID = -1;
|
G4int fCurrentEventID = -1; // speichert die aktuelle Event-ID
|
||||||
|
|
||||||
public:
|
struct HitInfo {
|
||||||
//
|
G4int eventID;
|
||||||
// HitInfo enthält ALLE üblichen Parameter
|
G4int trackID;
|
||||||
//
|
G4int parentID;
|
||||||
struct HitInfo
|
G4String particleName;
|
||||||
{
|
G4double particleEnergy;
|
||||||
// --- Basis-identifikation ---
|
G4String primaryParticleName;
|
||||||
G4int eventID; // Nummer des Events
|
G4double primaryEnergy;
|
||||||
G4int trackID; // Track ID
|
G4double energyDeposited;
|
||||||
G4int parentID; // Parent Track ID
|
G4String detectorName;
|
||||||
|
G4String cleanDetectorName;
|
||||||
|
|
||||||
// --- Teilchen ---
|
HitInfo()
|
||||||
G4String particleName; // Name des Teilchens
|
: trackID(-1), parentID(-1), particleEnergy(0.), primaryEnergy(0.), energyDeposited(0.) {}
|
||||||
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.)
|
|
||||||
{}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
G4String fDetectorName;
|
||||||
//
|
std::unordered_map<G4LogicalVolume*, std::string> fCleanNames;
|
||||||
// OutputMap: string → Lambda(hit, out)
|
std::unordered_map<G4int, HitInfo> fTrackHitMap; // TrackID → HitInfo
|
||||||
//
|
|
||||||
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
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
/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,12 +26,10 @@ int main(int argc, char** argv)
|
||||||
runManager->SetUserInitialization(new APhysicsList());
|
runManager->SetUserInitialization(new APhysicsList());
|
||||||
|
|
||||||
// Detector
|
// Detector
|
||||||
ADetectorConstruction* detector = new ADetectorConstruction();
|
runManager->SetUserInitialization(new ADetectorConstruction());
|
||||||
runManager->SetUserInitialization(detector);
|
|
||||||
|
|
||||||
// Actions
|
// Actions
|
||||||
runManager->SetUserInitialization(new AActionInitialization(detector->GetSensitiveDetector()));
|
runManager->SetUserInitialization(new AActionInitialization());
|
||||||
|
|
||||||
|
|
||||||
// Visualization
|
// Visualization
|
||||||
G4VisManager* visManager = new G4VisExecutive();
|
G4VisManager* visManager = new G4VisExecutive();
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,9 @@
|
||||||
#include "AActionInitialization.hh"
|
#include "AActionInitialization.hh"
|
||||||
#include "AMessenger.hh"
|
|
||||||
#include "APrimaryGenerator.hh"
|
#include "APrimaryGenerator.hh"
|
||||||
#include "ARunAction.hh"
|
#include "ARunAction.hh"
|
||||||
|
|
||||||
AActionInitialization::AActionInitialization(ASensitiveDetector* sd)
|
AActionInitialization::AActionInitialization()
|
||||||
: G4VUserActionInitialization(), fSD(sd)
|
: G4VUserActionInitialization()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -13,10 +12,7 @@ AActionInitialization::~AActionInitialization() {}
|
||||||
void AActionInitialization::Build() const
|
void AActionInitialization::Build() const
|
||||||
{
|
{
|
||||||
// Primärgenerator
|
// Primärgenerator
|
||||||
APrimaryGenerator* primaryGen = new APrimaryGenerator();
|
SetUserAction(new APrimaryGenerator());
|
||||||
SetUserAction(primaryGen);
|
|
||||||
|
|
||||||
AMessenger* messenger = new AMessenger(fSD, primaryGen);
|
|
||||||
|
|
||||||
// RunAction
|
// RunAction
|
||||||
SetUserAction(new ARunAction());
|
SetUserAction(new ARunAction());
|
||||||
|
|
|
||||||
|
|
@ -1,42 +1,18 @@
|
||||||
#include "AMessenger.hh"
|
#include "AMessenger.hh"
|
||||||
#include "ASensitiveDetector.hh"
|
#include "ASensitiveDetector.hh"
|
||||||
#include "APrimaryGenerator.hh"
|
|
||||||
#include "G4SystemOfUnits.hh"
|
|
||||||
|
|
||||||
AMessenger::AMessenger(ASensitiveDetector* sd, APrimaryGenerator* generator)
|
AMessenger::AMessenger(ASensitiveDetector* sd)
|
||||||
: fSD(sd), fGenerator(generator)
|
: fSD(sd)
|
||||||
{
|
{
|
||||||
// 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)
|
||||||
|
|
@ -45,24 +21,4 @@ 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,16 +3,29 @@
|
||||||
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
|
|
||||||
|
|
||||||
G4ThreeVector pos(0.,0.,-1.*cm);
|
//Particle position
|
||||||
G4ThreeVector mom(0.,0.,1.);
|
G4double x = 0. * m;
|
||||||
G4ParticleTable* particleTable = G4ParticleTable::GetParticleTable();
|
G4double y = 0. * m;
|
||||||
G4ParticleDefinition* particle = particleTable->FindParticle("e-");
|
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();
|
||||||
|
// possibilities: "e+","e-","gamma", ,"proton", "neutron"
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -23,15 +36,6 @@ APrimaryGenerator::~APrimaryGenerator()
|
||||||
|
|
||||||
void APrimaryGenerator::GeneratePrimaries(G4Event *anEvent)
|
void APrimaryGenerator::GeneratePrimaries(G4Event *anEvent)
|
||||||
{
|
{
|
||||||
G4ParticleTable* particleTable = G4ParticleTable::GetParticleTable();
|
//Create vertex
|
||||||
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,174 +1,131 @@
|
||||||
#include "ASensitiveDetector.hh"
|
#include "ASensitiveDetector.hh"
|
||||||
#include "AMessenger.hh"
|
#include "AMessenger.hh"
|
||||||
#include "G4Event.hh"
|
|
||||||
#include "G4RunManager.hh"
|
#include "G4RunManager.hh"
|
||||||
#include "G4Threading.hh"
|
#include "G4Event.hh"
|
||||||
|
#include "G4PrimaryVertex.hh"
|
||||||
|
#include "G4PrimaryParticle.hh"
|
||||||
|
#include "G4SystemOfUnits.hh"
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
ASensitiveDetector::ASensitiveDetector(G4String name)
|
ASensitiveDetector::ASensitiveDetector(G4String name)
|
||||||
: G4VSensitiveDetector(name), fOutputFilename("outfiles/shower_setup")
|
: G4VSensitiveDetector(name), fDetectorName(name)
|
||||||
{
|
{
|
||||||
|
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ASensitiveDetector::InitializeOutputMap()
|
G4bool ASensitiveDetector::ProcessHits(G4Step* step, G4TouchableHistory* /*touchHist*/)
|
||||||
{
|
{
|
||||||
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();
|
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();
|
|
||||||
|
|
||||||
HitInfo& hit = fTrackHitMap[id];
|
G4Track* track = step->GetTrack();
|
||||||
|
G4int trackID = track->GetTrackID();
|
||||||
|
|
||||||
// Basisdaten
|
auto it = fTrackHitMap.find(trackID);
|
||||||
hit.eventID = fCurrentEventID;
|
if (it == fTrackHitMap.end())
|
||||||
hit.trackID = id;
|
{
|
||||||
hit.parentID = trk->GetParentID();
|
HitInfo hit;
|
||||||
if(trk->GetDefinition()) {
|
hit.eventID = fCurrentEventID;
|
||||||
hit.particleName = trk->GetDefinition()->GetParticleName();
|
hit.trackID = trackID;
|
||||||
hit.pdg = trk->GetDefinition()->GetPDGEncoding();
|
hit.parentID = track->GetParentID();
|
||||||
}
|
hit.particleName = track->GetDefinition()->GetParticleName();
|
||||||
hit.ekin = trk->GetKineticEnergy();
|
hit.particleEnergy = track->GetVertexKineticEnergy();
|
||||||
|
hit.detectorName = step->GetPreStepPoint()->GetTouchable()->GetVolume()->GetName();
|
||||||
// Primärteilchen (sicher prüfen)
|
std::string detNameStr = hit.detectorName;
|
||||||
if(auto vertex = event->GetPrimaryVertex()) {
|
size_t pos = detNameStr.find("_phys");
|
||||||
if(auto prim = vertex->GetPrimary()) {
|
if (pos != std::string::npos)
|
||||||
if(auto code = prim->GetG4code()) {
|
detNameStr = detNameStr.substr(0, pos); // nur Basisname
|
||||||
hit.primaryName = code->GetParticleName();
|
hit.cleanDetectorName = detNameStr;
|
||||||
hit.primaryEnergy = prim->GetKineticEnergy();
|
// Primary particle info
|
||||||
}
|
G4PrimaryVertex* pv = event->GetPrimaryVertex();
|
||||||
|
if (pv)
|
||||||
|
{
|
||||||
|
G4PrimaryParticle* pp = pv->GetPrimary();
|
||||||
|
if (pp && pp->GetG4code())
|
||||||
|
hit.primaryParticleName = pp->GetG4code()->GetParticleName();
|
||||||
|
if (pp)
|
||||||
|
hit.primaryEnergy = pp->GetKineticEnergy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hit.energyDeposited = step->GetTotalEnergyDeposit();
|
||||||
|
fTrackHitMap[trackID] = hit;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
// Energie aufsummieren
|
{
|
||||||
hit.edep += step->GetTotalEnergyDeposit();
|
it->second.energyDeposited += 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";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ASensitiveDetector::EndOfEvent(G4HCofThisEvent*)
|
|
||||||
|
void ASensitiveDetector::EndOfEvent(G4HCofThisEvent* /*hce*/)
|
||||||
{
|
{
|
||||||
// Thread-ID für Datei
|
if (fOutputFilename.empty()) fOutputFilename = "outfiles/shower_setup.txt";
|
||||||
G4int tid = G4Threading::G4GetThreadId();
|
std::filesystem::create_directories("outfiles");
|
||||||
|
|
||||||
// Thread-local Datei
|
std::ofstream out(fOutputFilename, std::ios::app);
|
||||||
thread_local std::ofstream out;
|
if (!out.is_open()) {
|
||||||
|
G4cerr << "Cannot open file " << fOutputFilename << "!" << G4endl;
|
||||||
// Datei öffnen, wenn noch nicht offen
|
return;
|
||||||
if(!out.is_open()) {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Header einmal pro Datei
|
|
||||||
for(size_t i=0; i<fOutputColumns.size(); ++i) {
|
|
||||||
out << fOutputColumns[i];
|
|
||||||
if(i+1 < fOutputColumns.size()) out << "\t";
|
|
||||||
}
|
|
||||||
out << "\n";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hits schreiben
|
static bool headerWritten = false;
|
||||||
for(auto& [id, hit] : fTrackHitMap) {
|
if (!headerWritten) {
|
||||||
for(size_t i=0; i<fOutputColumns.size(); ++i) {
|
out << "eventID\ttrackID\tparentID\tparticle\tEpart\tPrimparticle\tEprim\tDname\tEdep\n";
|
||||||
const auto& col = fOutputColumns[i];
|
headerWritten = true;
|
||||||
if(outputMap.count(col))
|
|
||||||
outputMap[col](hit, out);
|
|
||||||
else
|
|
||||||
out << "NA";
|
|
||||||
|
|
||||||
if(i+1 < fOutputColumns.size()) out << "\t";
|
|
||||||
}
|
|
||||||
out << "\n";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Map zurücksetzen
|
// Hits nur für das aktuelle Event
|
||||||
|
std::vector<HitInfo> hits;
|
||||||
|
for (const auto& [trackID, hit] : fTrackHitMap) {
|
||||||
|
hits.push_back(hit);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sortieren: parentID -> trackID
|
||||||
|
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