Compare commits
2 commits
324f479434
...
62d264b11c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
62d264b11c | ||
|
|
1cb4fa4956 |
12 changed files with 626 additions and 147 deletions
|
|
@ -1,3 +1,27 @@
|
|||
// #pragma once
|
||||
|
||||
// #include "G4VUserDetectorConstruction.hh"
|
||||
// #include "ASensitiveDetector.hh"
|
||||
// #include "AMessenger.hh"
|
||||
|
||||
// class G4VPhysicalVolume;
|
||||
|
||||
// class ADetectorConstruction : public G4VUserDetectorConstruction
|
||||
// {
|
||||
// public:
|
||||
// ADetectorConstruction();
|
||||
// ~ADetectorConstruction() override;
|
||||
|
||||
// G4VPhysicalVolume* Construct() override;
|
||||
// void ConstructSDandField() override;
|
||||
|
||||
// ASensitiveDetector* GetSensitiveDetector() const { return fSD; }
|
||||
|
||||
// private:
|
||||
// ASensitiveDetector* fSD;
|
||||
// AMessenger* fMessenger;
|
||||
// };
|
||||
|
||||
#ifndef ADETECTORCONSTRUCTION_HH
|
||||
#define ADETECTORCONSTRUCTION_HH
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,31 @@
|
|||
// #pragma once
|
||||
|
||||
// #include "G4VSensitiveDetector.hh"
|
||||
// #include "G4THitsCollection.hh"
|
||||
// #include "G4Step.hh"
|
||||
// #include <fstream>
|
||||
// #include <vector>
|
||||
// #include <string>
|
||||
|
||||
// class ASensitiveDetector : public G4VSensitiveDetector
|
||||
// {
|
||||
// public:
|
||||
// ASensitiveDetector(const G4String& name);
|
||||
// ~ASensitiveDetector() override;
|
||||
|
||||
// void Initialize(G4HCofThisEvent*) override;
|
||||
// G4bool ProcessHits(G4Step* step, G4TouchableHistory*) override;
|
||||
// void EndOfEvent(G4HCofThisEvent*) override;
|
||||
|
||||
// void SetOutputFilename(const G4String& filename) { fOutputFilename = filename; }
|
||||
// void SetOutputColumns(const std::vector<G4String>& cols) { fOutputColumns = cols; }
|
||||
|
||||
// private:
|
||||
// std::ofstream fOutputFile;
|
||||
// G4String fOutputFilename;
|
||||
// std::vector<G4String> fOutputColumns;
|
||||
// };
|
||||
|
||||
#ifndef ASENSITIVEDETECTOR_HH
|
||||
#define ASENSITIVEDETECTOR_HH
|
||||
|
||||
|
|
@ -20,7 +48,9 @@ class AMessenger;
|
|||
//
|
||||
// Makro für die OutputMap – gleiche Logik wie beim Kollegen
|
||||
//
|
||||
#define OUTMAP [](const HitInfo& hit, std::ostream& out)
|
||||
//#define OUTMAP [](const HitInfo& hit, std::ostream& out)
|
||||
#define OUTMAP [&, safeString, safeDouble, safeVec3](const HitInfo& hit, std::ostream& out)
|
||||
|
||||
|
||||
class ASensitiveDetector : public G4VSensitiveDetector
|
||||
{
|
||||
|
|
@ -95,6 +125,15 @@ public:
|
|||
{}
|
||||
};
|
||||
|
||||
struct StepHit
|
||||
{
|
||||
G4int eventID;
|
||||
G4int trackID;
|
||||
G4double edep; // MeV
|
||||
G4double z; // cm
|
||||
G4double r; // cm
|
||||
};
|
||||
|
||||
private:
|
||||
//
|
||||
// OutputMap: string → Lambda(hit, out)
|
||||
|
|
@ -106,7 +145,8 @@ private:
|
|||
// interne Daten
|
||||
//
|
||||
std::vector<G4String> fOutputColumns;
|
||||
std::unordered_map<G4int, HitInfo> fTrackHitMap;
|
||||
//std::unordered_map<G4int, HitInfo> fTrackHitMap;
|
||||
std::vector<StepHit> fStepHits;
|
||||
|
||||
//
|
||||
// interne Hilfsfunktionen
|
||||
|
|
|
|||
20
macros/BGO_map_energy.mac
Normal file
20
macros/BGO_map_energy.mac
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
# Anzahl Threads
|
||||
/run/numberOfThreads 1
|
||||
|
||||
# Output-Datei
|
||||
/my/outputFilename out/BGO_shower_100MeV
|
||||
|
||||
# Particle Type
|
||||
/my/particleType e-
|
||||
|
||||
# Particle Energy
|
||||
/my/particleEnergy 100 MeV
|
||||
|
||||
# Output-Spalten
|
||||
/my/outputColumns event track parent part pdg ekin edep z r
|
||||
|
||||
# Initialisierung
|
||||
/run/initialize
|
||||
|
||||
# Simulation starten (10000 Hits)
|
||||
/run/beamOn 50000
|
||||
20
macros/BGO_map_test.mac
Normal file
20
macros/BGO_map_test.mac
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
# Anzahl Threads
|
||||
/run/numberOfThreads 1
|
||||
|
||||
# Output-Datei setzen **vor** /run/initialize
|
||||
/my/outputFilename out/BGO_shower_test1
|
||||
|
||||
# Particle Type
|
||||
/my/particleType e-
|
||||
|
||||
# Particle Energy
|
||||
/my/particleEnergy 100 MeV
|
||||
|
||||
# Output-Spalten
|
||||
/my/outputColumns event track parent part pdg ekin edep z r
|
||||
|
||||
# Initialisierung
|
||||
/run/initialize
|
||||
|
||||
# Simulation starten
|
||||
/run/beamOn 10
|
||||
25
macros/bgo_test.mac
Normal file
25
macros/bgo_test.mac
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
# --- Öffne die Visualisierung ---
|
||||
/vis/open OGLSX
|
||||
/vis/viewer/set/background white
|
||||
/vis/scene/create
|
||||
|
||||
# --- Alle Volumes sichtbar machen ---
|
||||
# Zeige das World-Volume und alles darin rekursiv
|
||||
/vis/scene/add/volume /World recursive
|
||||
/vis/scene/endOfEventAction accumulate
|
||||
|
||||
# --- Darstellung einstellen ---
|
||||
/vis/representation/set wireframe
|
||||
/vis/scene/add/axes 0 0 0 1 m
|
||||
|
||||
# --- Kameraeinstellungen ---
|
||||
/vis/viewer/set/viewpointThetaPhi 60 30
|
||||
/vis/viewer/set/autoRefresh true
|
||||
|
||||
# --- Farben und Transparenz optional ---
|
||||
# (BGO ist standardmäßig rot, du kannst eigene Farben setzen)
|
||||
/vis/scene/modifyVolume BGO_vol visAttributes/solidColor 1 0 0 1
|
||||
|
||||
# --- Initialisierung der Run-Manager ---
|
||||
/run/initialize
|
||||
|
||||
17
macros/trajectoryrun.mac
Normal file
17
macros/trajectoryrun.mac
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
/run/numberOfThreads 1
|
||||
|
||||
# --- Output Datei setzen ---
|
||||
/my/outputFilename outfiles/trajectory-01
|
||||
|
||||
# --- 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
|
||||
|
||||
13
macros/vis_bgo.mac
Normal file
13
macros/vis_bgo.mac
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
/control/execute bgo.gdml
|
||||
|
||||
/run/initialize
|
||||
|
||||
/vis/open OGL 600x600-0+x600
|
||||
/vis/viewer/set/viewpointVector 1 1 1
|
||||
/vis/viewer/set/autoRefresh true
|
||||
/vis/drawVolume
|
||||
/vis/scene/add/trajectories smooth
|
||||
/vis/scene/endOfEventAction accumulate
|
||||
/vis/scene/add/scale 10 cm
|
||||
/vis/scene/add/axes
|
||||
/vis/scene/add/eventID
|
||||
27
macros/vis_shower.mac
Normal file
27
macros/vis_shower.mac
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
run/initialize
|
||||
|
||||
# --- Open visualization window ---
|
||||
/vis/open OGLI 600x600-0+0
|
||||
/vis/viewer/set/viewpointVector 1 1 1
|
||||
/vis/viewer/set/autoRefresh true
|
||||
|
||||
# --- Draw volumes first ---
|
||||
/vis/drawVolume
|
||||
|
||||
# --- Add other elements ---
|
||||
/vis/scene/add/trajectories smooth
|
||||
/vis/scene/endOfEventAction accumulate
|
||||
/vis/scene/add/scale 10 cm
|
||||
/vis/scene/add/axes
|
||||
/vis/scene/add/eventID
|
||||
|
||||
# --- Set colors (erst jetzt, nachdem die Szene existiert) ---
|
||||
/vis/att/set SSD1 color orange 0.6
|
||||
/vis/att/set SSD2 color orange 0.6
|
||||
/vis/att/set SSD3 color orange 0.6
|
||||
/vis/att/set SSD4 color orange 0.6
|
||||
/vis/att/set BGO1 color green 0.6
|
||||
/vis/att/set BGO2 color green 0.6
|
||||
/vis/att/set BGO3 color green 0.6
|
||||
|
||||
/vis/viewer/refresh
|
||||
59
sim.cc
59
sim.cc
|
|
@ -1,3 +1,62 @@
|
|||
// #include "G4RunManager.hh"
|
||||
// #include "G4MTRunManager.hh"
|
||||
// #include "G4UImanager.hh"
|
||||
// #include "G4VisExecutive.hh"
|
||||
// #include "G4UIExecutive.hh"
|
||||
|
||||
// #include "APhysicsList.hh"
|
||||
// #include "ADetectorConstruction.hh"
|
||||
// #include "AActionInitialization.hh"
|
||||
|
||||
// int main(int argc, char** argv)
|
||||
// {
|
||||
// G4UIExecutive* ui = nullptr;
|
||||
// if (argc == 1)
|
||||
// ui = new G4UIExecutive(argc, argv);
|
||||
|
||||
// #ifdef G4MULTITHREADED
|
||||
// auto* runManager = new G4MTRunManager;
|
||||
// #else
|
||||
// auto* runManager = new G4RunManager;
|
||||
// #endif
|
||||
|
||||
// // Physics
|
||||
// runManager->SetUserInitialization(new APhysicsList());
|
||||
|
||||
// // Detector
|
||||
// auto* detector = new ADetectorConstruction();
|
||||
// runManager->SetUserInitialization(detector);
|
||||
|
||||
// // Actions (SD wird korrekt übergeben)
|
||||
// runManager->SetUserInitialization(
|
||||
// new AActionInitialization(detector->GetSensitiveDetector())
|
||||
// );
|
||||
|
||||
// // Visualization
|
||||
// auto* visManager = new G4VisExecutive();
|
||||
// visManager->Initialize();
|
||||
|
||||
// auto* UImanager = G4UImanager::GetUIpointer();
|
||||
|
||||
// if (ui)
|
||||
// {
|
||||
// UImanager->ApplyCommand("/control/execute vis.mac");
|
||||
// ui->SessionStart();
|
||||
// delete ui;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// UImanager->ApplyCommand(
|
||||
// G4String("/control/execute ") + argv[1]
|
||||
// );
|
||||
// }
|
||||
|
||||
// delete visManager;
|
||||
// delete runManager;
|
||||
// return 0;
|
||||
// }
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include "G4RunManager.hh"
|
||||
#include "G4MTRunManager.hh"
|
||||
|
|
|
|||
|
|
@ -1,3 +1,75 @@
|
|||
// #include "ADetectorConstruction.hh"
|
||||
|
||||
// #include "G4NistManager.hh"
|
||||
// #include "G4PVPlacement.hh"
|
||||
// #include "G4LogicalVolume.hh"
|
||||
// #include "G4VisAttributes.hh"
|
||||
// #include "G4SystemOfUnits.hh"
|
||||
// #include "G4SDManager.hh"
|
||||
|
||||
// #include "G4Box.hh"
|
||||
// #include "G4Tubs.hh"
|
||||
|
||||
// #include "ASensitiveDetector.hh"
|
||||
// #include "AMessenger.hh"
|
||||
|
||||
// ADetectorConstruction::ADetectorConstruction()
|
||||
// {
|
||||
// // Sensitives Detektorobjekt erstellen
|
||||
// fSD = new ASensitiveDetector("shower_setup");
|
||||
|
||||
// // Messenger initialisieren und an SD übergeben
|
||||
// fMessenger = new AMessenger(fSD, nullptr);
|
||||
// }
|
||||
|
||||
// ADetectorConstruction::~ADetectorConstruction()
|
||||
// {
|
||||
// delete fSD;
|
||||
// delete fMessenger;
|
||||
// }
|
||||
|
||||
// G4VPhysicalVolume* ADetectorConstruction::Construct()
|
||||
// {
|
||||
// auto* nist = G4NistManager::Instance();
|
||||
// G4bool checkOverlaps = true;
|
||||
|
||||
// // Weltmaterial
|
||||
// auto* worldMat = nist->FindOrBuildMaterial("G4_Galactic");
|
||||
|
||||
// // Weltvolumen
|
||||
// auto* solidWorld = new G4Box("World", 0.5*m, 0.5*m, 0.5*m);
|
||||
// auto* logicWorld = new G4LogicalVolume(solidWorld, worldMat, "World");
|
||||
// auto* physWorld = new G4PVPlacement(nullptr, {}, logicWorld,
|
||||
// "World", nullptr, false, 0, checkOverlaps);
|
||||
|
||||
// logicWorld->SetVisAttributes(G4VisAttributes::GetInvisible());
|
||||
|
||||
// // BGO-Material
|
||||
// auto* bgo = nist->FindOrBuildMaterial("G4_BGO");
|
||||
|
||||
// // Zylindrisches BGO-Volumen
|
||||
// auto* solidBGO = new G4Tubs("BGO", 0, 8*cm, 5*cm, 0, 360*deg);
|
||||
// auto* logicBGO = new G4LogicalVolume(solidBGO, bgo, "BGO_logic");
|
||||
|
||||
// new G4PVPlacement(nullptr, G4ThreeVector(0,0,5*cm), logicBGO,
|
||||
// "BGO_phys", logicWorld, false, 0, checkOverlaps);
|
||||
|
||||
// // Sensitives Detektor-Volumen setzen
|
||||
// logicBGO->SetSensitiveDetector(fSD);
|
||||
|
||||
// // Transparente Visualisierung: grünlich mit 50% Deckkraft
|
||||
// auto* visAttr = new G4VisAttributes(G4Colour(0.0, 1.0, 0.0, 0.5));
|
||||
// visAttr->SetForceSolid(true); // Volumen ausfüllen
|
||||
// logicBGO->SetVisAttributes(visAttr);
|
||||
|
||||
// return physWorld;
|
||||
// }
|
||||
|
||||
// void ADetectorConstruction::ConstructSDandField()
|
||||
// {
|
||||
// G4SDManager::GetSDMpointer()->AddNewDetector(fSD);
|
||||
// }
|
||||
|
||||
#include "ADetectorConstruction.hh"
|
||||
#include "ASensitiveDetector.hh"
|
||||
#include "AMessenger.hh"
|
||||
|
|
@ -10,6 +82,7 @@
|
|||
#include "G4Color.hh"
|
||||
#include "G4SDManager.hh"
|
||||
#include "G4SystemOfUnits.hh"
|
||||
#include "G4Tubs.hh"
|
||||
|
||||
ADetectorConstruction::ADetectorConstruction()
|
||||
{
|
||||
|
|
@ -44,60 +117,87 @@ G4VPhysicalVolume* ADetectorConstruction::Construct()
|
|||
G4VPhysicalVolume* physWorld = new G4PVPlacement(
|
||||
nullptr, G4ThreeVector(), logicWorld, "physWorld", nullptr, false, 0, checkOverlaps);
|
||||
|
||||
// --- Layergrößen ---
|
||||
G4double sizeXY = 5.0*cm;
|
||||
G4double thSSD = 0.5*mm;
|
||||
G4double thBGO = 20.0*mm;
|
||||
G4double gap = 5.0*mm;
|
||||
// // --- Layergrößen ---
|
||||
// G4double sizeXY = 5.0*cm;
|
||||
// G4double thSSD = 0.5*mm;
|
||||
// G4double thBGO = 20.0*mm;
|
||||
// G4double gap = 5.0*mm;
|
||||
|
||||
// --- Startposition ---
|
||||
G4double zPos = 0.0;
|
||||
// // --- Startposition ---
|
||||
// G4double zPos = 0.0;
|
||||
|
||||
// // --- Visualisierung ---
|
||||
// G4VisAttributes* ssdVis = new G4VisAttributes(G4Color(0.,0.,1.,0.6));
|
||||
// ssdVis->SetForceSolid(true);
|
||||
|
||||
// G4VisAttributes* bgoVis = new G4VisAttributes(G4Color(0.,1.,0.,0.6));
|
||||
// bgoVis->SetForceSolid(true);
|
||||
|
||||
// // --- Indizes für eindeutige Namen ---
|
||||
// int ssdIndex = 1;
|
||||
// int bgoIndex = 1;
|
||||
|
||||
// // --- 7 Layer bauen ---
|
||||
// for(int i = 0; i < 7; i++)
|
||||
// {
|
||||
// bool isSSD = (i % 2 == 0);
|
||||
// G4double thickness = isSSD ? thSSD : thBGO;
|
||||
// G4Material* mat = isSSD ? ssdMat : bgoMat;
|
||||
|
||||
// // Eindeutiger Name
|
||||
// G4String baseName = isSSD ? "SSD" + std::to_string(ssdIndex++)
|
||||
// : "BGO" + std::to_string(bgoIndex++);
|
||||
|
||||
// // Solid + Logical Volume
|
||||
// G4Box* solid = new G4Box(baseName, 0.5*sizeXY, 0.5*sizeXY, 0.5*thickness);
|
||||
// G4LogicalVolume* lv = new G4LogicalVolume(solid, mat, baseName + "_logic");
|
||||
|
||||
// // Platzierung
|
||||
// new G4PVPlacement(nullptr,
|
||||
// G4ThreeVector(0.,0.,zPos + 0.5*thickness),
|
||||
// lv,
|
||||
// baseName + "_phys",
|
||||
// logicWorld,
|
||||
// false,
|
||||
// i,
|
||||
// checkOverlaps);
|
||||
|
||||
// // Visualisierung
|
||||
// lv->SetVisAttributes(isSSD ? ssdVis : bgoVis);
|
||||
|
||||
// // Für SD merken
|
||||
// detectorVolumes.push_back(lv);
|
||||
|
||||
// // Update z-Position
|
||||
// zPos += thickness + gap;
|
||||
|
||||
// --- Zylinder-Detektor ---
|
||||
G4double radius = 8.0*cm;
|
||||
G4double height = 10.0*cm;
|
||||
G4double startAngle = 0*deg;
|
||||
G4double spanningAngle = 360*deg;
|
||||
|
||||
G4Tubs* solidCylinder = new G4Tubs("BGO_Cylinder", 0, radius, height/2, startAngle, spanningAngle);
|
||||
G4LogicalVolume* logicCylinder = new G4LogicalVolume(solidCylinder, bgoMat, "BGO_Cylinder_logic");
|
||||
|
||||
// --- Visualisierung ---
|
||||
G4VisAttributes* ssdVis = new G4VisAttributes(G4Color(0.,0.,1.,0.6));
|
||||
ssdVis->SetForceSolid(true);
|
||||
G4VisAttributes* visAttr = new G4VisAttributes(G4Color(0.,1.,0.,0.6)); // grün
|
||||
visAttr->SetForceSolid(true);
|
||||
logicCylinder->SetVisAttributes(visAttr);
|
||||
|
||||
G4VisAttributes* bgoVis = new G4VisAttributes(G4Color(0.,1.,0.,0.6));
|
||||
bgoVis->SetForceSolid(true);
|
||||
|
||||
// --- Indizes für eindeutige Namen ---
|
||||
int ssdIndex = 1;
|
||||
int bgoIndex = 1;
|
||||
|
||||
// --- 7 Layer bauen ---
|
||||
for(int i = 0; i < 7; i++)
|
||||
{
|
||||
bool isSSD = (i % 2 == 0);
|
||||
G4double thickness = isSSD ? thSSD : thBGO;
|
||||
G4Material* mat = isSSD ? ssdMat : bgoMat;
|
||||
|
||||
// Eindeutiger Name
|
||||
G4String baseName = isSSD ? "SSD" + std::to_string(ssdIndex++)
|
||||
: "BGO" + std::to_string(bgoIndex++);
|
||||
|
||||
// Solid + Logical Volume
|
||||
G4Box* solid = new G4Box(baseName, 0.5*sizeXY, 0.5*sizeXY, 0.5*thickness);
|
||||
G4LogicalVolume* lv = new G4LogicalVolume(solid, mat, baseName + "_logic");
|
||||
|
||||
// Platzierung
|
||||
new G4PVPlacement(nullptr,
|
||||
G4ThreeVector(0.,0.,zPos + 0.5*thickness),
|
||||
lv,
|
||||
baseName + "_phys",
|
||||
// --- Platzierung ---
|
||||
new G4PVPlacement(
|
||||
nullptr,
|
||||
G4ThreeVector(0., 0., height/2), // Mittelpunkt so verschieben, dass Unterkante z=0
|
||||
logicCylinder,
|
||||
"BGO_Cylinder_phys",
|
||||
logicWorld,
|
||||
false,
|
||||
i,
|
||||
checkOverlaps);
|
||||
0,
|
||||
checkOverlaps
|
||||
);
|
||||
|
||||
// Visualisierung
|
||||
lv->SetVisAttributes(isSSD ? ssdVis : bgoVis);
|
||||
|
||||
// Für SD merken
|
||||
detectorVolumes.push_back(lv);
|
||||
|
||||
// Update z-Position
|
||||
zPos += thickness + gap;
|
||||
}
|
||||
detectorVolumes.push_back(logicCylinder);
|
||||
|
||||
return physWorld;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ void AMessenger::SetNewValue(G4UIcommand* cmd, G4String value)
|
|||
{
|
||||
if (cmd == fOutputFileCmd)
|
||||
{
|
||||
fSD->SetOutputFilename(value);
|
||||
fSD->SetOutputFilename(value); // jetzt public
|
||||
}
|
||||
else if(cmd == fEnergyCmd && fGenerator)
|
||||
{
|
||||
|
|
@ -62,7 +62,14 @@ void AMessenger::SetNewValue(G4UIcommand* cmd, G4String value)
|
|||
{
|
||||
cols.push_back(token);
|
||||
}
|
||||
fSD->SetOutputColumns(cols);
|
||||
fSD->SetOutputColumns(cols); // jetzt public
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// void AMessenger::SetNewValue(G4UIcommand* cmd, G4String value)
|
||||
// {
|
||||
// if(cmd == fOutputFileCmd && fSD) {
|
||||
// fSD->SetOutputFilename(value); // muss in SD eine Variable setzen
|
||||
// fSD->OpenFile(); // optional, Datei gleich öffnen
|
||||
// }
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -1,3 +1,44 @@
|
|||
// #include "ASensitiveDetector.hh"
|
||||
// #include "G4Step.hh"
|
||||
// #include "G4SystemOfUnits.hh"
|
||||
// #include <iomanip>
|
||||
|
||||
// ASensitiveDetector::ASensitiveDetector(const G4String& name)
|
||||
// : G4VSensitiveDetector(name)
|
||||
// {
|
||||
// }
|
||||
|
||||
// ASensitiveDetector::~ASensitiveDetector()
|
||||
// {
|
||||
// if(fOutputFile.is_open())
|
||||
// fOutputFile.close();
|
||||
// }
|
||||
|
||||
// void ASensitiveDetector::Initialize(G4HCofThisEvent*)
|
||||
// {
|
||||
// if(!fOutputFile.is_open() && !fOutputFilename.empty())
|
||||
// fOutputFile.open(fOutputFilename);
|
||||
// }
|
||||
|
||||
// G4bool ASensitiveDetector::ProcessHits(G4Step* step, G4TouchableHistory*)
|
||||
// {
|
||||
// // Beispiel: speichere Position und Energieverlust
|
||||
// auto pos = step->GetPreStepPoint()->GetPosition();
|
||||
// auto edep = step->GetTotalEnergyDeposit();
|
||||
|
||||
// if(fOutputFile.is_open())
|
||||
// fOutputFile << std::fixed << std::setprecision(3)
|
||||
// << pos.z()/cm << " " << pos.perp()/cm << " " << edep/MeV << G4endl;
|
||||
|
||||
// return true;
|
||||
// }
|
||||
|
||||
// void ASensitiveDetector::EndOfEvent(G4HCofThisEvent*)
|
||||
// {
|
||||
// fOutputFile.flush();
|
||||
// }
|
||||
|
||||
|
||||
#include "ASensitiveDetector.hh"
|
||||
#include "AMessenger.hh"
|
||||
#include "G4Event.hh"
|
||||
|
|
@ -21,114 +62,190 @@ ASensitiveDetector::~ASensitiveDetector() {}
|
|||
|
||||
void ASensitiveDetector::Initialize(G4HCofThisEvent*)
|
||||
{
|
||||
fTrackHitMap.clear();
|
||||
//fTrackHitMap.clear();
|
||||
fStepHits.clear();
|
||||
}
|
||||
|
||||
// void ASensitiveDetector::InitializeOutputMap()
|
||||
// {
|
||||
// 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; }},
|
||||
// {"r", OUTMAP {
|
||||
// G4double r = std::sqrt(hit.postPos.x()*hit.postPos.x() + hit.postPos.y()*hit.postPos.y());
|
||||
// out << r/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; }}
|
||||
// };
|
||||
// }
|
||||
|
||||
void ASensitiveDetector::InitializeOutputMap()
|
||||
{
|
||||
// Lambda für sicheren Zugriff auf hit-Felder
|
||||
auto safeString = [](const G4String& s) -> G4String {
|
||||
return s.empty() ? "undefined" : s;
|
||||
};
|
||||
|
||||
auto safeDouble = [](G4double value, G4double scale=1.0) -> G4double {
|
||||
return value; // optional: prüfen auf NaN oder negative Werte
|
||||
};
|
||||
|
||||
auto safeVec3 = [](const G4ThreeVector& v, G4double scale=1.0) -> G4ThreeVector {
|
||||
return v / scale;
|
||||
};
|
||||
|
||||
outputMap = {
|
||||
{"event", OUTMAP { out << hit.eventID; }},
|
||||
{"track", OUTMAP { out << hit.trackID; }},
|
||||
{"parent", OUTMAP { out << hit.parentID; }},
|
||||
|
||||
{"part", OUTMAP { out << hit.particleName; }},
|
||||
{"part", OUTMAP { out << safeString(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; }},
|
||||
|
||||
{"ekin", OUTMAP { out << safeDouble(hit.ekin/MeV); }},
|
||||
{"edep", OUTMAP { out << safeDouble(hit.edep/MeV); }},
|
||||
{"x", OUTMAP { out << safeDouble(hit.postPos.x()/mm); }},
|
||||
{"y", OUTMAP { out << safeDouble(hit.postPos.y()/mm); }},
|
||||
{"z", OUTMAP { out << safeDouble(hit.postPos.z()/mm); }},
|
||||
{"pos", OUTMAP {
|
||||
auto v = safeVec3(hit.postPos, mm);
|
||||
out << v.x() << " " << v.y() << " " << v.z();
|
||||
}},
|
||||
{"r", OUTMAP {
|
||||
G4double r = std::sqrt(hit.postPos.x()*hit.postPos.x() + hit.postPos.y()*hit.postPos.y());
|
||||
out << r;
|
||||
}},
|
||||
{"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(); }},
|
||||
|
||||
{"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; }}
|
||||
{"proc", OUTMAP { out << safeString(hit.processName); }},
|
||||
{"det", OUTMAP { out << safeString(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;
|
||||
|
||||
// fCurrentEventID = event->GetEventID();
|
||||
// G4int id = trk->GetTrackID();
|
||||
|
||||
// HitInfo& hit = fTrackHitMap[id];
|
||||
|
||||
// // Basisdaten
|
||||
// hit.eventID = fCurrentEventID;
|
||||
// hit.trackID = id;
|
||||
// hit.parentID = trk->GetParentID();
|
||||
// if(trk->GetDefinition()) {
|
||||
// hit.particleName = trk->GetDefinition()->GetParticleName();
|
||||
// hit.pdg = trk->GetDefinition()->GetPDGEncoding();
|
||||
// }
|
||||
// hit.ekin = trk->GetKineticEnergy();
|
||||
|
||||
// // Primärteilchen (sicher prüfen)
|
||||
// if(auto vertex = event->GetPrimaryVertex()) {
|
||||
// if(auto prim = vertex->GetPrimary()) {
|
||||
// if(auto code = prim->GetG4code()) {
|
||||
// hit.primaryName = code->GetParticleName();
|
||||
// hit.primaryEnergy = prim->GetKineticEnergy();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// // Energie aufsummieren
|
||||
// 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";
|
||||
// }
|
||||
// }
|
||||
|
||||
// return true;
|
||||
// }
|
||||
|
||||
G4bool ASensitiveDetector::ProcessHits(G4Step* step, G4TouchableHistory*)
|
||||
{
|
||||
if(!step) return false;
|
||||
|
||||
G4Track* trk = step->GetTrack();
|
||||
if(!trk) return false;
|
||||
G4double edep = step->GetTotalEnergyDeposit();
|
||||
if(edep <= 0) return false; // nur echte Deposits
|
||||
|
||||
const G4Event* event = G4RunManager::GetRunManager()->GetCurrentEvent();
|
||||
if(!event) return false;
|
||||
|
||||
fCurrentEventID = event->GetEventID();
|
||||
G4int id = trk->GetTrackID();
|
||||
|
||||
HitInfo& hit = fTrackHitMap[id];
|
||||
|
||||
// Basisdaten
|
||||
hit.eventID = fCurrentEventID;
|
||||
hit.trackID = id;
|
||||
hit.parentID = trk->GetParentID();
|
||||
if(trk->GetDefinition()) {
|
||||
hit.particleName = trk->GetDefinition()->GetParticleName();
|
||||
hit.pdg = trk->GetDefinition()->GetPDGEncoding();
|
||||
}
|
||||
hit.ekin = trk->GetKineticEnergy();
|
||||
|
||||
// Primärteilchen (sicher prüfen)
|
||||
if(auto vertex = event->GetPrimaryVertex()) {
|
||||
if(auto prim = vertex->GetPrimary()) {
|
||||
if(auto code = prim->GetG4code()) {
|
||||
hit.primaryName = code->GetParticleName();
|
||||
hit.primaryEnergy = prim->GetKineticEnergy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Energie aufsummieren
|
||||
hit.edep += step->GetTotalEnergyDeposit();
|
||||
|
||||
// PreStep/PostStep prüfen
|
||||
auto pre = step->GetPreStepPoint();
|
||||
auto post = step->GetPostStepPoint();
|
||||
if(pre && post) {
|
||||
if(!post) return false;
|
||||
|
||||
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";
|
||||
auto pos = post->GetPosition();
|
||||
|
||||
// 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";
|
||||
}
|
||||
}
|
||||
StepHit hit;
|
||||
hit.eventID = G4RunManager::GetRunManager()
|
||||
->GetCurrentEvent()->GetEventID();
|
||||
hit.trackID = step->GetTrack()->GetTrackID();
|
||||
hit.edep = edep / MeV;
|
||||
hit.z = pos.z() / cm;
|
||||
hit.r = std::sqrt(pos.x()*pos.x() + pos.y()*pos.y()) / cm;
|
||||
|
||||
fStepHits.push_back(hit);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void ASensitiveDetector::EndOfEvent(G4HCofThisEvent*)
|
||||
{
|
||||
// Thread-ID für Datei
|
||||
|
|
@ -156,19 +273,29 @@ void ASensitiveDetector::EndOfEvent(G4HCofThisEvent*)
|
|||
}
|
||||
|
||||
// Hits schreiben
|
||||
for(auto& [id, hit] : fTrackHitMap) {
|
||||
for(size_t i=0; i<fOutputColumns.size(); ++i) {
|
||||
const auto& col = fOutputColumns[i];
|
||||
if(outputMap.count(col))
|
||||
outputMap[col](hit, out);
|
||||
else
|
||||
out << "NA";
|
||||
// for(auto& [id, hit] : fTrackHitMap) {
|
||||
// for(size_t i=0; i<fOutputColumns.size(); ++i) {
|
||||
// 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";
|
||||
// if(i+1 < fOutputColumns.size()) out << "\t";
|
||||
// }
|
||||
// out << "\n";
|
||||
// }
|
||||
|
||||
// // Map zurücksetzen
|
||||
// fTrackHitMap.clear();
|
||||
|
||||
for(const auto& hit : fStepHits) {
|
||||
out << hit.eventID << "\t"
|
||||
<< hit.trackID << "\t"
|
||||
<< hit.edep << "\t"
|
||||
<< hit.z << "\t"
|
||||
<< hit.r << "\n";
|
||||
}
|
||||
|
||||
// Map zurücksetzen
|
||||
fTrackHitMap.clear();
|
||||
fStepHits.clear();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue