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
|
#ifndef ADETECTORCONSTRUCTION_HH
|
||||||
#define 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
|
#ifndef ASENSITIVEDETECTOR_HH
|
||||||
#define ASENSITIVEDETECTOR_HH
|
#define ASENSITIVEDETECTOR_HH
|
||||||
|
|
||||||
|
|
@ -20,7 +48,9 @@ class AMessenger;
|
||||||
//
|
//
|
||||||
// Makro für die OutputMap – gleiche Logik wie beim Kollegen
|
// 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
|
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:
|
private:
|
||||||
//
|
//
|
||||||
// OutputMap: string → Lambda(hit, out)
|
// OutputMap: string → Lambda(hit, out)
|
||||||
|
|
@ -106,7 +145,8 @@ private:
|
||||||
// interne Daten
|
// interne Daten
|
||||||
//
|
//
|
||||||
std::vector<G4String> fOutputColumns;
|
std::vector<G4String> fOutputColumns;
|
||||||
std::unordered_map<G4int, HitInfo> fTrackHitMap;
|
//std::unordered_map<G4int, HitInfo> fTrackHitMap;
|
||||||
|
std::vector<StepHit> fStepHits;
|
||||||
|
|
||||||
//
|
//
|
||||||
// interne Hilfsfunktionen
|
// 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 <iostream>
|
||||||
#include "G4RunManager.hh"
|
#include "G4RunManager.hh"
|
||||||
#include "G4MTRunManager.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 "ADetectorConstruction.hh"
|
||||||
#include "ASensitiveDetector.hh"
|
#include "ASensitiveDetector.hh"
|
||||||
#include "AMessenger.hh"
|
#include "AMessenger.hh"
|
||||||
|
|
@ -10,6 +82,7 @@
|
||||||
#include "G4Color.hh"
|
#include "G4Color.hh"
|
||||||
#include "G4SDManager.hh"
|
#include "G4SDManager.hh"
|
||||||
#include "G4SystemOfUnits.hh"
|
#include "G4SystemOfUnits.hh"
|
||||||
|
#include "G4Tubs.hh"
|
||||||
|
|
||||||
ADetectorConstruction::ADetectorConstruction()
|
ADetectorConstruction::ADetectorConstruction()
|
||||||
{
|
{
|
||||||
|
|
@ -44,60 +117,87 @@ G4VPhysicalVolume* ADetectorConstruction::Construct()
|
||||||
G4VPhysicalVolume* physWorld = new G4PVPlacement(
|
G4VPhysicalVolume* physWorld = new G4PVPlacement(
|
||||||
nullptr, G4ThreeVector(), logicWorld, "physWorld", nullptr, false, 0, checkOverlaps);
|
nullptr, G4ThreeVector(), logicWorld, "physWorld", nullptr, false, 0, checkOverlaps);
|
||||||
|
|
||||||
// --- Layergrößen ---
|
// // --- Layergrößen ---
|
||||||
G4double sizeXY = 5.0*cm;
|
// G4double sizeXY = 5.0*cm;
|
||||||
G4double thSSD = 0.5*mm;
|
// G4double thSSD = 0.5*mm;
|
||||||
G4double thBGO = 20.0*mm;
|
// G4double thBGO = 20.0*mm;
|
||||||
G4double gap = 5.0*mm;
|
// G4double gap = 5.0*mm;
|
||||||
|
|
||||||
// --- Startposition ---
|
// // --- Startposition ---
|
||||||
G4double zPos = 0.0;
|
// 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 ---
|
// --- Visualisierung ---
|
||||||
G4VisAttributes* ssdVis = new G4VisAttributes(G4Color(0.,0.,1.,0.6));
|
G4VisAttributes* visAttr = new G4VisAttributes(G4Color(0.,1.,0.,0.6)); // grün
|
||||||
ssdVis->SetForceSolid(true);
|
visAttr->SetForceSolid(true);
|
||||||
|
logicCylinder->SetVisAttributes(visAttr);
|
||||||
|
|
||||||
G4VisAttributes* bgoVis = new G4VisAttributes(G4Color(0.,1.,0.,0.6));
|
// --- Platzierung ---
|
||||||
bgoVis->SetForceSolid(true);
|
new G4PVPlacement(
|
||||||
|
nullptr,
|
||||||
|
G4ThreeVector(0., 0., height/2), // Mittelpunkt so verschieben, dass Unterkante z=0
|
||||||
|
logicCylinder,
|
||||||
|
"BGO_Cylinder_phys",
|
||||||
|
logicWorld,
|
||||||
|
false,
|
||||||
|
0,
|
||||||
|
checkOverlaps
|
||||||
|
);
|
||||||
|
|
||||||
// --- Indizes für eindeutige Namen ---
|
detectorVolumes.push_back(logicCylinder);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
return physWorld;
|
return physWorld;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ void AMessenger::SetNewValue(G4UIcommand* cmd, G4String value)
|
||||||
{
|
{
|
||||||
if (cmd == fOutputFileCmd)
|
if (cmd == fOutputFileCmd)
|
||||||
{
|
{
|
||||||
fSD->SetOutputFilename(value);
|
fSD->SetOutputFilename(value); // jetzt public
|
||||||
}
|
}
|
||||||
else if(cmd == fEnergyCmd && fGenerator)
|
else if(cmd == fEnergyCmd && fGenerator)
|
||||||
{
|
{
|
||||||
|
|
@ -62,7 +62,14 @@ void AMessenger::SetNewValue(G4UIcommand* cmd, G4String value)
|
||||||
{
|
{
|
||||||
cols.push_back(token);
|
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 "ASensitiveDetector.hh"
|
||||||
#include "AMessenger.hh"
|
#include "AMessenger.hh"
|
||||||
#include "G4Event.hh"
|
#include "G4Event.hh"
|
||||||
|
|
@ -21,114 +62,190 @@ ASensitiveDetector::~ASensitiveDetector() {}
|
||||||
|
|
||||||
void ASensitiveDetector::Initialize(G4HCofThisEvent*)
|
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()
|
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 = {
|
outputMap = {
|
||||||
{"event", OUTMAP { out << hit.eventID; }},
|
{"event", OUTMAP { out << hit.eventID; }},
|
||||||
{"track", OUTMAP { out << hit.trackID; }},
|
{"track", OUTMAP { out << hit.trackID; }},
|
||||||
{"parent", OUTMAP { out << hit.parentID; }},
|
{"parent", OUTMAP { out << hit.parentID; }},
|
||||||
|
{"part", OUTMAP { out << safeString(hit.particleName); }},
|
||||||
{"part", OUTMAP { out << hit.particleName; }},
|
|
||||||
{"pdg", OUTMAP { out << hit.pdg; }},
|
{"pdg", OUTMAP { out << hit.pdg; }},
|
||||||
{"ekin", OUTMAP { out << hit.ekin / MeV; }},
|
{"ekin", OUTMAP { out << safeDouble(hit.ekin/MeV); }},
|
||||||
{"edep", OUTMAP { out << hit.edep / MeV; }},
|
{"edep", OUTMAP { out << safeDouble(hit.edep/MeV); }},
|
||||||
|
{"x", OUTMAP { out << safeDouble(hit.postPos.x()/mm); }},
|
||||||
{"x", OUTMAP { out << hit.postPos.x() / mm; }},
|
{"y", OUTMAP { out << safeDouble(hit.postPos.y()/mm); }},
|
||||||
{"y", OUTMAP { out << hit.postPos.y() / mm; }},
|
{"z", OUTMAP { out << safeDouble(hit.postPos.z()/mm); }},
|
||||||
{"z", OUTMAP { out << hit.postPos.z() / mm; }},
|
{"pos", OUTMAP {
|
||||||
{"pos", OUTMAP { out << hit.postPos.x()/mm<<" "<<hit.postPos.y()/mm<<" "<<hit.postPos.z()/mm; }},
|
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(); }},
|
{"dx", OUTMAP { out << hit.postDir.x(); }},
|
||||||
{"dy", OUTMAP { out << hit.postDir.y(); }},
|
{"dy", OUTMAP { out << hit.postDir.y(); }},
|
||||||
{"dz", OUTMAP { out << hit.postDir.z(); }},
|
{"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; }},
|
{"global_t", OUTMAP { out << hit.globalTime; }},
|
||||||
{"local_t", OUTMAP { out << hit.localTime; }},
|
{"local_t", OUTMAP { out << hit.localTime; }},
|
||||||
|
|
||||||
{"step", OUTMAP { out << hit.stepLength / mm; }},
|
{"step", OUTMAP { out << hit.stepLength / mm; }},
|
||||||
{"proc", OUTMAP { out << hit.processName; }},
|
{"proc", OUTMAP { out << safeString(hit.processName); }},
|
||||||
|
{"det", OUTMAP { out << safeString(hit.cleanName); }}
|
||||||
{"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;
|
||||||
|
|
||||||
|
// 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*)
|
G4bool ASensitiveDetector::ProcessHits(G4Step* step, G4TouchableHistory*)
|
||||||
{
|
{
|
||||||
if(!step) return false;
|
if(!step) return false;
|
||||||
|
|
||||||
G4Track* trk = step->GetTrack();
|
G4double edep = step->GetTotalEnergyDeposit();
|
||||||
if(!trk) return false;
|
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();
|
auto post = step->GetPostStepPoint();
|
||||||
if(pre && post) {
|
if(!post) return false;
|
||||||
|
|
||||||
hit.prePos = pre->GetPosition();
|
auto pos = post->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
|
StepHit hit;
|
||||||
if(pre->GetTouchable()) {
|
hit.eventID = G4RunManager::GetRunManager()
|
||||||
auto vol = pre->GetTouchable()->GetVolume();
|
->GetCurrentEvent()->GetEventID();
|
||||||
if(vol) {
|
hit.trackID = step->GetTrack()->GetTrackID();
|
||||||
auto full = vol->GetName();
|
hit.edep = edep / MeV;
|
||||||
hit.detectorName = full;
|
hit.z = pos.z() / cm;
|
||||||
auto pos = full.find("_phys");
|
hit.r = std::sqrt(pos.x()*pos.x() + pos.y()*pos.y()) / cm;
|
||||||
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";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
fStepHits.push_back(hit);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ASensitiveDetector::EndOfEvent(G4HCofThisEvent*)
|
void ASensitiveDetector::EndOfEvent(G4HCofThisEvent*)
|
||||||
{
|
{
|
||||||
// Thread-ID für Datei
|
// Thread-ID für Datei
|
||||||
|
|
@ -156,19 +273,29 @@ void ASensitiveDetector::EndOfEvent(G4HCofThisEvent*)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hits schreiben
|
// Hits schreiben
|
||||||
for(auto& [id, hit] : fTrackHitMap) {
|
// for(auto& [id, hit] : fTrackHitMap) {
|
||||||
for(size_t i=0; i<fOutputColumns.size(); ++i) {
|
// for(size_t i=0; i<fOutputColumns.size(); ++i) {
|
||||||
const auto& col = fOutputColumns[i];
|
// const auto& col = fOutputColumns[i];
|
||||||
if(outputMap.count(col))
|
// if(outputMap.count(col))
|
||||||
outputMap[col](hit, out);
|
// outputMap[col](hit, out);
|
||||||
else
|
// else
|
||||||
out << "NA";
|
// out << "NA";
|
||||||
|
|
||||||
if(i+1 < fOutputColumns.size()) out << "\t";
|
// if(i+1 < fOutputColumns.size()) out << "\t";
|
||||||
}
|
// }
|
||||||
out << "\n";
|
// 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
|
fStepHits.clear();
|
||||||
fTrackHitMap.clear();
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue