From 5b0d51d580cd4948cd8f46fcc47e3d5256f68d16 Mon Sep 17 00:00:00 2001 From: lobis Date: Mon, 20 Jun 2022 10:42:19 +0200 Subject: [PATCH 001/173] Adding constructor to TRestGeant4Event and adding to manager --- include/SimulationManager.h | 25 ++++++++++++++++++++++--- src/Application.cxx | 2 +- src/EventAction.cxx | 18 ------------------ src/SimulationManager.cxx | 35 ++++++++++++++++++++++++++++++++--- 4 files changed, 55 insertions(+), 25 deletions(-) diff --git a/include/SimulationManager.h b/include/SimulationManager.h index 45bf3048..6ced46c4 100644 --- a/include/SimulationManager.h +++ b/include/SimulationManager.h @@ -8,19 +8,38 @@ #include #include +#include + +class OutputManager; + class SimulationManager { public: SimulationManager(); ~SimulationManager(); TRestRun* fRestRun = nullptr; - TRestGeant4Track* fRestGeant4Track = nullptr; - TRestGeant4Event *fRestGeant4Event = nullptr, *fRestGeant4SubEvent = nullptr; - TRestGeant4Metadata* fRestGeant4Metadata = nullptr; TRestGeant4PhysicsLists* fRestGeant4PhysicsLists = nullptr; + TRestGeant4Metadata* fRestGeant4Metadata = nullptr; TH1D initialEnergySpectrum; TH1D initialAngularDistribution; + + static OutputManager* GetOutputManager() { return fOutputManager; } + + TRestGeant4Event fEvent; // Branch on EventTree + + private: + static thread_local OutputManager* fOutputManager; + std::queue > fEventContainer; +}; + +class OutputManager { + public: + void UpdateEvent(); + + private: + std::unique_ptr fEvent{}; + const SimulationManager* fSimulationManager = nullptr; }; #endif // REST_SIMULATIONMANAGER_H diff --git a/src/Application.cxx b/src/Application.cxx index ff4b7d57..d9058022 100644 --- a/src/Application.cxx +++ b/src/Application.cxx @@ -119,7 +119,7 @@ void Application::Run(const CommandLineParameters& commandLineParameters) { fSimulationManager->fRestGeant4Event = new TRestGeant4Event(); fSimulationManager->fRestGeant4SubEvent = new TRestGeant4Event(); - fSimulationManager->fRestRun->AddEventBranch(fSimulationManager->fRestGeant4SubEvent); + fSimulationManager->fRestRun->AddEventBranch(&fSimulationManager->fEvent); fSimulationManager->fRestGeant4Track = new TRestGeant4Track(); diff --git a/src/EventAction.cxx b/src/EventAction.cxx index 33538c40..fd4760ca 100644 --- a/src/EventAction.cxx +++ b/src/EventAction.cxx @@ -55,25 +55,7 @@ void EventAction::BeginOfEventAction(const G4Event* event) { restTrack->Initialize(); - restG4Event->SetID(eventID); - restG4Event->SetOK(true); - time_t system_time = time(nullptr); - restG4Event->SetTime((Double_t)system_time); - - // Defining if the hits in a given volume will be stored - for (int i = 0; i < restG4Metadata->GetNumberOfActiveVolumes(); i++) { - if (restG4Metadata->GetStorageChance(i) >= 1.00) { - restG4Event->ActivateVolumeForStorage(i); - } else { - Double_t randomNumber = G4UniformRand(); - if (restG4Metadata->GetStorageChance(i) >= randomNumber) { - restG4Event->ActivateVolumeForStorage(i); - } else { - restG4Event->DisableVolumeForStorage(i); - } - } - } } void EventAction::EndOfEventAction(const G4Event* event) { diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index e5850d53..0bab1972 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -1,6 +1,8 @@ #include "SimulationManager.h" +#include +#include #include using namespace std; @@ -15,9 +17,36 @@ SimulationManager::SimulationManager() { SimulationManager::~SimulationManager() { delete fRestRun; - delete fRestGeant4Track; - delete fRestGeant4Event; - delete fRestGeant4SubEvent; delete fRestGeant4Metadata; delete fRestGeant4PhysicsLists; } + +// OutputManager +void OutputManager::UpdateEvent() { + auto event = G4EventManager::GetEventManager()->GetConstCurrentEvent(); + fEvent = make_unique(event, *fSimulationManager->fRestGeant4Metadata); +} + +// Geant4Lib constructors +TRestGeant4Event::TRestGeant4Event(const G4Event* event, const TRestGeant4Metadata& metadata) + : TRestGeant4Event() { + SetID(event->GetEventID()); + SetOK(true); + time_t system_time = time(nullptr); + + SetTime((Double_t)system_time); + + // Defining if the hits in a given volume will be stored + for (int i = 0; i < metadata.GetNumberOfActiveVolumes(); i++) { + if (metadata.GetStorageChance(i) >= 1.00) { + ActivateVolumeForStorage(i); + } else { + Double_t randomNumber = G4UniformRand(); + if (metadata.GetStorageChance(i) >= randomNumber) { + ActivateVolumeForStorage(i); + } else { + DisableVolumeForStorage(i); + } + } + } +} \ No newline at end of file From f8ecc76f0bdfb78868c3917b24c3279727da283c Mon Sep 17 00:00:00 2001 From: lobis Date: Mon, 20 Jun 2022 10:48:38 +0200 Subject: [PATCH 002/173] Initialization of OutputManager --- include/SimulationManager.h | 2 ++ src/RunAction.cxx | 2 ++ src/SimulationManager.cxx | 11 +++++++++++ 3 files changed, 15 insertions(+) diff --git a/include/SimulationManager.h b/include/SimulationManager.h index 6ced46c4..25de4f23 100644 --- a/include/SimulationManager.h +++ b/include/SimulationManager.h @@ -24,6 +24,7 @@ class SimulationManager { TH1D initialEnergySpectrum; TH1D initialAngularDistribution; + void InitializeOutputManager(); static OutputManager* GetOutputManager() { return fOutputManager; } TRestGeant4Event fEvent; // Branch on EventTree @@ -35,6 +36,7 @@ class SimulationManager { class OutputManager { public: + OutputManager(const SimulationManager*); void UpdateEvent(); private: diff --git a/src/RunAction.cxx b/src/RunAction.cxx index ee6cd5ae..295fea51 100644 --- a/src/RunAction.cxx +++ b/src/RunAction.cxx @@ -26,6 +26,8 @@ void RunAction::BeginOfRunAction(const G4Run*) { G4cout << G4RunManager::GetRunManager()->GetNumberOfEventsToBeProcessed() << " events to be simulated" << endl; G4cout << "=======================================================================" << endl; + + fSimulationManager->InitializeOutputManager(); // inform the runManager to save random number seed G4RunManager::GetRunManager()->SetRandomNumberStore(false); } diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index 0bab1972..e9774856 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -22,6 +22,17 @@ SimulationManager::~SimulationManager() { } // OutputManager +OutputManager::OutputManager(const SimulationManager* simulationManager) + : fSimulationManager(simulationManager) { + // this class should only exist on the threads performing the simulation + if (G4Threading::IsMasterThread() && G4Threading::IsMultithreadedApplication()) { + G4cout << "Error in 'OutputManager', this instance should never exist" << endl; + exit(1); + } +} + +void SimulationManager::InitializeOutputManager() { fOutputManager = new OutputManager(this); } + void OutputManager::UpdateEvent() { auto event = G4EventManager::GetEventManager()->GetConstCurrentEvent(); fEvent = make_unique(event, *fSimulationManager->fRestGeant4Metadata); From a3c08460478591ebf7881fa384a0307027c8fe4c Mon Sep 17 00:00:00 2001 From: lobis Date: Mon, 20 Jun 2022 12:11:31 +0200 Subject: [PATCH 003/173] Added StackingAction, updated event insertion logic --- include/EventAction.h | 5 - include/SimulationManager.h | 13 +- include/StackingAction.h | 35 +++++ src/ActionInitialization.cxx | 3 +- src/EventAction.cxx | 291 +---------------------------------- src/SimulationManager.cxx | 89 ++++++++++- src/StackingAction.cxx | 66 ++++++++ src/TrackingAction.cxx | 5 +- 8 files changed, 211 insertions(+), 296 deletions(-) create mode 100644 include/StackingAction.h create mode 100644 src/StackingAction.cxx diff --git a/include/EventAction.h b/include/EventAction.h index dc01232d..02c2ae90 100644 --- a/include/EventAction.h +++ b/include/EventAction.h @@ -26,11 +26,6 @@ class EventAction : public G4UserEventAction { SimulationManager* fSimulationManager; TStopwatch fTimer; - Double_t absDouble(Double_t x) { - if (x > 0) return x; - return -x; - } - int SetTrackSubEventIDs(); void FillSubEvent(Int_t subId); // old method `FillSubEvent` has been split into `FillSubEvent` and `ReOrderTrackIds` for speed diff --git a/include/SimulationManager.h b/include/SimulationManager.h index 25de4f23..1d0216df 100644 --- a/include/SimulationManager.h +++ b/include/SimulationManager.h @@ -29,8 +29,14 @@ class SimulationManager { TRestGeant4Event fEvent; // Branch on EventTree + size_t InsertEvent(std::unique_ptr& event); + + void WriteEvents(); + void WriteEventsAndCloseFile(); + private: static thread_local OutputManager* fOutputManager; + std::mutex fEventContainerMutex; std::queue > fEventContainer; }; @@ -38,10 +44,15 @@ class OutputManager { public: OutputManager(const SimulationManager*); void UpdateEvent(); + void FinishAndSubmitEvent(); + bool IsEmptyEvent() const; + bool IsValidEvent() const; private: std::unique_ptr fEvent{}; - const SimulationManager* fSimulationManager = nullptr; + SimulationManager* fSimulationManager = nullptr; + + friend class StackingAction; }; #endif // REST_SIMULATIONMANAGER_H diff --git a/include/StackingAction.h b/include/StackingAction.h new file mode 100644 index 00000000..b6202e54 --- /dev/null +++ b/include/StackingAction.h @@ -0,0 +1,35 @@ + +#ifndef REST_STACKINGACTION_H +#define REST_STACKINGACTION_H + +#include +#include +#include +#include + +class OutputManager; +class SimulationManager; + +class StackingAction : public G4UserStackingAction { + public: + explicit StackingAction(SimulationManager*); + ~StackingAction(); + + G4ClassificationOfNewTrack ClassifyNewTrack(const G4Track*); + void NewStage(); + + inline std::set GetParticlesToIgnore() const { return fParticlesToIgnore; } + inline void AddParticleToIgnore(const G4ParticleDefinition* particle) { + fParticlesToIgnore.insert(particle); + } + + private: + SimulationManager* fSimulationManager; + + const G4double fMaxAllowedLifetime; + G4String fMaxAllowedLifetimeWithUnit; + + std::set fParticlesToIgnore; +}; + +#endif // REST_STACKINGACTION_H diff --git a/src/ActionInitialization.cxx b/src/ActionInitialization.cxx index 42e691e7..d2c67a0f 100644 --- a/src/ActionInitialization.cxx +++ b/src/ActionInitialization.cxx @@ -10,6 +10,7 @@ #include "RunAction.h" #include "SimulationManager.h" // #include "StackingAction.h" +#include "StackingAction.h" #include "SteppingAction.h" // #include "SteppingVerbose.h" #include "G4RunManager.hh" @@ -88,7 +89,7 @@ void ActionInitialization::Build() const { SetUserAction(runAction); SetUserAction(eventAction); SetUserAction(new SteppingAction(fSimulationManager)); - // SetUserAction(new StackingAction); + SetUserAction(new StackingAction(fSimulationManager)); SetUserAction(trackingAction); /* diff --git a/src/EventAction.cxx b/src/EventAction.cxx index fd4760ca..7ac42dfd 100644 --- a/src/EventAction.cxx +++ b/src/EventAction.cxx @@ -24,13 +24,11 @@ EventAction::EventAction(SimulationManager* simulationManager) EventAction::~EventAction() {} void EventAction::BeginOfEventAction(const G4Event* event) { + fSimulationManager->GetOutputManager()->UpdateEvent(); + const auto eventID = event->GetEventID(); - auto simulationManager = fSimulationManager; - TRestRun* restRun = simulationManager->fRestRun; - TRestGeant4Track* restTrack = simulationManager->fRestGeant4Track; - TRestGeant4Event* restG4Event = simulationManager->fRestGeant4Event; - TRestGeant4Event* subRestG4Event = simulationManager->fRestGeant4SubEvent; - TRestGeant4Metadata* restG4Metadata = simulationManager->fRestGeant4Metadata; + TRestRun* restRun = fSimulationManager->fRestRun; + TRestGeant4Metadata* restG4Metadata = fSimulationManager->fRestGeant4Metadata; if (restG4Metadata->GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Debug) { G4cout << "DEBUG: Start of event ID " << eventID << " (" << eventID + 1 << " of " @@ -52,286 +50,13 @@ void EventAction::BeginOfEventAction(const G4Event* event) { fTimer.Continue(); } } - - restTrack->Initialize(); - - } void EventAction::EndOfEventAction(const G4Event* event) { - auto simulationManager = fSimulationManager; - TRestRun* restRun = simulationManager->fRestRun; - TRestGeant4Track* restTrack = simulationManager->fRestGeant4Track; - TRestGeant4Event* restG4Event = simulationManager->fRestGeant4Event; - TRestGeant4Event* subRestG4Event = simulationManager->fRestGeant4SubEvent; - TRestGeant4Metadata* restG4Metadata = simulationManager->fRestGeant4Metadata; - - G4int eventID = event->GetEventID(); - - if (restG4Metadata->GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Extreme) { - restG4Event->PrintEvent(); - } - - Double_t minimumEnergyStored = restG4Metadata->GetMinimumEnergyStored(); - Double_t maximumEnergyStored = restG4Metadata->GetMaximumEnergyStored(); - - int nSubs = SetTrackSubEventIDs(); - - Bool_t isSensitive = false; - - for (int subId = 0; subId < nSubs + 1; subId++) { - FillSubEvent(subId); - - Double_t total_deposited_energy = subRestG4Event->GetTotalDepositedEnergy(); - Double_t sensitive_volume_deposited_energy = subRestG4Event->GetSensitiveVolumeEnergy(); - - if (minimumEnergyStored < 0) minimumEnergyStored = 0; - if (maximumEnergyStored == 0) maximumEnergyStored = total_deposited_energy + 1.; - - isSensitive = - (sensitive_volume_deposited_energy > 0 && total_deposited_energy > minimumEnergyStored && - total_deposited_energy < maximumEnergyStored) || - restG4Metadata->GetSaveAllEvents(); - - if (restG4Metadata->GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Info) { - string debug_level = "INFO"; - if (restG4Metadata->GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Debug) { - debug_level = "DEBUG"; - } - - if (isSensitive || - restG4Metadata->GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Debug) { - G4cout << debug_level - << ": Energy deposited in ACTIVE and SENSITIVE volumes: " << total_deposited_energy - << " keV" << endl; - G4cout << debug_level - << ": Energy deposited in SENSITIVE volume: " << sensitive_volume_deposited_energy - << " keV" << endl; - } - } - - if (isSensitive) { - sensitive_volume_hits_count += 1; - - // call `ReOrderTrackIds` which before was integrated into `FillSubEvent` - // it takes a while to run, so we only do it if we are going to save the event - ReOrderTrackIds(subId); - - // fill analysis tree - TRestAnalysisTree* analysis_tree = restRun->GetAnalysisTree(); - if (analysis_tree) { - analysis_tree->SetEventInfo(subRestG4Event); - analysis_tree->Fill(); - } else { - // analysis tree is not found (nullptr) - if (restG4Metadata->GetVerboseLevel() >= - TRestStringOutput::REST_Verbose_Level::REST_Warning) { - G4cout << "WARNING: Analysis tree is not found ('nullptr'). Cannot write event info" - << endl; - } - } - // fill event tree - TTree* eventTree = restRun->GetEventTree(); - if (eventTree) { - eventTree->Fill(); - } else { - // event tree is not found (nullptr) - if (restG4Metadata->GetVerboseLevel() >= - TRestStringOutput::REST_Verbose_Level::REST_Warning) { - G4cout << "WARNING: Event tree is not found ('nullptr'). Cannot write event info" << endl; - } - } - } - } - - if (restG4Metadata->GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Info) { - string debugLevel = "INFO"; - if (restG4Metadata->GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Debug) { - debugLevel = "DEBUG"; - } - - if (isSensitive || - restG4Metadata->GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Debug) { - G4cout << debugLevel - << ": Events depositing energy in sensitive volume: " << sensitive_volume_hits_count << "/" - << eventID + 1 << endl; - G4cout << debugLevel << ": End of event ID " << eventID << " (" << eventID + 1 << " of " - << G4RunManager::GetRunManager()->GetNumberOfEventsToBeProcessed() << ")" << endl; - G4cout << endl; - } - } -} - -/* - * TODO: - * this method takes a very long time and is acting as a bottleneck on some instances (high track - * number), see if it can be optimised. - * */ -void EventAction::FillSubEvent(Int_t subId) { - TRestRun* restRun = fSimulationManager->fRestRun; - TRestGeant4Track* restTrack = fSimulationManager->fRestGeant4Track; - TRestGeant4Event* restG4Event = fSimulationManager->fRestGeant4Event; - TRestGeant4Event* subRestG4Event = fSimulationManager->fRestGeant4SubEvent; - TRestGeant4Metadata* restG4Metadata = fSimulationManager->fRestGeant4Metadata; - - subRestG4Event->Initialize(); - subRestG4Event->ClearVolumes(); - - subRestG4Event->SetID(restG4Event->GetID()); - subRestG4Event->SetSubID(subId); - - subRestG4Event->SetRunOrigin(restRun->GetRunNumber()); - subRestG4Event->SetSubRunOrigin(0); - - time_t systime = time(nullptr); - subRestG4Event->SetTimeStamp((Double_t)systime); + fSimulationManager->GetOutputManager()->FinishAndSubmitEvent(); - subRestG4Event->SetPrimaryEventOrigin(restG4Event->GetPrimaryEventOrigin()); - for (int n = 0; n < restG4Event->GetNumberOfPrimaries(); n++) { - subRestG4Event->SetPrimaryEventParticleName(restG4Event->GetPrimaryEventParticleName(n)); - subRestG4Event->SetPrimaryEventDirection(restG4Event->GetPrimaryEventDirection(n)); - subRestG4Event->SetPrimaryEventEnergy(restG4Event->GetPrimaryEventEnergy(n)); + if (!G4Threading::IsMultithreadedApplication() || // + (G4Threading::IsMultithreadedApplication() && G4Threading::G4GetThreadId() == 0)) { + fSimulationManager->WriteEvents(); } - - for (int n = 0; n < restG4Event->GetNumberOfActiveVolumes(); n++) { - subRestG4Event->AddActiveVolume((string)restG4Metadata->GetActiveVolumeName(n)); - if (restG4Event->isVolumeStored(n)) - subRestG4Event->ActivateVolumeForStorage(n); - else - subRestG4Event->DisableVolumeForStorage(n); - } - - for (int n = 0; n < restG4Event->GetNumberOfTracks(); n++) { - const auto& track = restG4Event->GetTrack(n); - if (track.GetSubEventID() == subId) { - if (track.GetNumberOfHits() > 0 || restG4Metadata->RegisterEmptyTracks()) { - subRestG4Event->AddTrack(track); - } - } - } - - if (restG4Metadata->isVolumeStored(restG4Metadata->GetSensitiveVolume())) { - Int_t sensVolID = restG4Metadata->GetActiveVolumeID(restG4Metadata->GetSensitiveVolume()); - subRestG4Event->SetSensitiveVolumeEnergy(subRestG4Event->GetEnergyDepositedInVolume(sensVolID)); - } -} - -void EventAction::ReOrderTrackIds(Int_t subId) { - TRestRun* restRun = fSimulationManager->fRestRun; - TRestGeant4Track* restTrack = fSimulationManager->fRestGeant4Track; - TRestGeant4Event* restG4Event = fSimulationManager->fRestGeant4Event; - TRestGeant4Event* subRestG4Event = fSimulationManager->fRestGeant4SubEvent; - TRestGeant4Metadata* restG4Metadata = fSimulationManager->fRestGeant4Metadata; - - // We define as event timestamp the system time. - // We will be always able to extract the global simulation time from Geant4 tracks. - time_t systime = time(nullptr); - subRestG4Event->SetTimeStamp(systime); - - if (subId > 0) { - for (int n = 0; n < restG4Event->GetNumberOfTracks(); n++) { - const auto& track = restG4Event->GetTrack(n); - if (track.GetSubEventID() == subId - 1) { - if (track.isRadiactiveDecay()) { - subRestG4Event->SetSubEventTag(track.GetParticleName()); - } - } - } - } - - // Re-ordering track IDs - Int_t lowestID = subRestG4Event->GetLowestTrackID(); - Int_t nTracks = subRestG4Event->GetNumberOfTracks(); - - for (int i = 0; i < nTracks; i++) { - const auto& track = subRestG4Event->GetTrackPointer(i); - track->SetTrackID(track->GetTrackID() - lowestID + 1); - track->SetParentID(track->GetParentID() - lowestID + 1); - if (track->GetParentID() < 0) { - track->SetParentID(0); - } - } - - for (int i = 0; i < nTracks; i++) { - TRestGeant4Track* track = subRestG4Event->GetTrackPointer(i); - Int_t id = track->GetTrackID(); - - if (id - i != 1) { - // Changing track ids - track->SetTrackID(i + 1); - for (int t = i + 1; t < subRestG4Event->GetNumberOfTracks(); t++) { - TRestGeant4Track* trackAux = subRestG4Event->GetTrackPointer(t); - if (trackAux->GetTrackID() == i + 1) { - trackAux->SetTrackID(id); - } - } - - // Changing parent ids - for (int t = 0; t < subRestG4Event->GetNumberOfTracks(); t++) { - TRestGeant4Track* trackAux = subRestG4Event->GetTrackPointer(t); - if (trackAux->GetParentID() == id) { - trackAux->SetParentID(i + 1); - } else if (trackAux->GetParentID() == i + 1) { - trackAux->SetParentID(id); - } - } - } - } -} - -int EventAction::SetTrackSubEventIDs() { - TRestRun* restRun = fSimulationManager->fRestRun; - TRestGeant4Track* restTrack = fSimulationManager->fRestGeant4Track; - TRestGeant4Event* restG4Event = fSimulationManager->fRestGeant4Event; - TRestGeant4Event* subRestG4Event = fSimulationManager->fRestGeant4SubEvent; - TRestGeant4Metadata* restG4Metadata = fSimulationManager->fRestGeant4Metadata; - - Int_t nTracks = restG4Event->GetNumberOfTracks(); - Double_t timeDelay = restG4Metadata->GetSubEventTimeDelay(); // in unit us - - // reorder tracks - map tracks; - for (int n = 0; n < nTracks; n++) { - TRestGeant4Track* track = restG4Event->GetTrackPointer(n); - tracks[track->GetTrackID()] = track; - } - - // scan backwards to the parent tracks and set the track's sub event id - int maxSubEventID = 0; - for (auto iter = tracks.begin(); iter != tracks.end(); iter++) { - TRestGeant4Track* track = iter->second; - if (track->GetParentID() == 0) { - track->SetSubEventID(0); - } else { - double trackTimeLengthTotal = 0; - int parentID = track->GetParentID(); - TRestGeant4Track* trackAux = tracks[parentID]; - while (true) { - if (trackAux) { - trackTimeLengthTotal += trackAux->GetTrackTimeLength(); - if (trackTimeLengthTotal > timeDelay) { - int subEventIDAux = trackAux->GetSubEventID() + 1; - track->SetSubEventID(subEventIDAux); - if (maxSubEventID < subEventIDAux) { - maxSubEventID = subEventIDAux; - } - break; - } else { - if (trackAux->GetParentID() == 0) { - track->SetSubEventID(0); - break; - } else { - trackAux = tracks[trackAux->GetParentID()]; - continue; - } - } - } else { - G4cout << "error! parent track is null" << endl; - abort(); - } - } - } - } - - return maxSubEventID; } diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index e9774856..38d9b7a1 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -15,15 +15,52 @@ SimulationManager::SimulationManager() { } } +void SimulationManager::InitializeOutputManager() { fOutputManager = new OutputManager(this); } + SimulationManager::~SimulationManager() { delete fRestRun; delete fRestGeant4Metadata; delete fRestGeant4PhysicsLists; } +size_t SimulationManager::InsertEvent(std::unique_ptr& event) { + fEventContainerMutex.lock(); + fEventContainer.push(std::move(event)); + auto size = fEventContainer.size(); + fEventContainerMutex.unlock(); + return size; +} + +void SimulationManager::WriteEvents() { + if (G4Threading::IsMultithreadedApplication()) { + lock_guard guard(fEventContainerMutex); + } + + if (fEventContainer.empty()) { + return; + } + + while (!fEventContainer.empty()) { + fEvent = *fEventContainer.front(); + + const auto eventTree = fRestRun->GetEventTree(); + if (eventTree != nullptr) { + eventTree->Fill(); + } + + const auto analysisTree = fRestRun->GetAnalysisTree(); + if (analysisTree != nullptr) { + analysisTree->SetEventInfo(&fEvent); + analysisTree->Fill(); + } + + fEventContainer.pop(); + } +} + // OutputManager OutputManager::OutputManager(const SimulationManager* simulationManager) - : fSimulationManager(simulationManager) { + : fSimulationManager(const_cast(simulationManager)) { // this class should only exist on the threads performing the simulation if (G4Threading::IsMasterThread() && G4Threading::IsMultithreadedApplication()) { G4cout << "Error in 'OutputManager', this instance should never exist" << endl; @@ -31,14 +68,31 @@ OutputManager::OutputManager(const SimulationManager* simulationManager) } } -void SimulationManager::InitializeOutputManager() { fOutputManager = new OutputManager(this); } - void OutputManager::UpdateEvent() { auto event = G4EventManager::GetEventManager()->GetConstCurrentEvent(); fEvent = make_unique(event, *fSimulationManager->fRestGeant4Metadata); } -// Geant4Lib constructors +bool OutputManager::IsEmptyEvent() const { return !fEvent || fEvent->fTrack.empty(); } + +bool OutputManager::IsValidEvent() const { + if (IsEmptyEvent()) return false; + if (fSimulationManager->fRestGeant4Metadata->GetSaveAllEvents()) return true; + if (fEvent->GetSensitiveVolumeEnergy() <= 0) return false; + return true; +} + +void OutputManager::FinishAndSubmitEvent() { + if (IsEmptyEvent()) return; + + if (IsValidEvent()) { + size_t numberOfInsertedEvents = fSimulationManager->InsertEvent(fEvent); + } + UpdateEvent(); +} + +// Geant4Lib + TRestGeant4Event::TRestGeant4Event(const G4Event* event, const TRestGeant4Metadata& metadata) : TRestGeant4Event() { SetID(event->GetEventID()); @@ -60,4 +114,31 @@ TRestGeant4Event::TRestGeant4Event(const G4Event* event, const TRestGeant4Metada } } } +} + +TRestGeant4Track::TRestGeant4Track(const G4Track* track) : TRestGeant4Track() { + fTrackID = track->GetTrackID(); + fParentID = track->GetParentID(); + + auto particle = track->GetParticleDefinition(); + fParticleName = particle->GetParticleName(); + /* + fParticleID = particle->GetPDGEncoding(); + fParticleType = particle->GetParticleType(); + fParticleSubType = particle->GetParticleSubType(); + */ + if (track->GetCreatorProcess()) { + fCreatorProcess = track->GetCreatorProcess()->GetProcessName(); + } else { + fCreatorProcess = "IsPrimaryParticle"; + } + + fKineticEnergy = track->GetKineticEnergy() / CLHEP::keV; + + fWeight = track->GetWeight(); + + fGlobalTimestamp = track->GetGlobalTime() / CLHEP::second; + + const G4ThreeVector& trackOrigin = track->GetPosition(); + fTrackOrigin = {trackOrigin.x(), trackOrigin.y(), trackOrigin.z()}; } \ No newline at end of file diff --git a/src/StackingAction.cxx b/src/StackingAction.cxx new file mode 100644 index 00000000..8dbbe36d --- /dev/null +++ b/src/StackingAction.cxx @@ -0,0 +1,66 @@ + +#include "StackingAction.h" + +#include +#include +#include +#include +#include +#include + +#include "SimulationManager.h" + +StackingAction::StackingAction(SimulationManager* simulationManager) : fSimulationManager(simulationManager) { + fMaxAllowedLifetimeWithUnit = G4BestUnit(fMaxAllowedLifetime, "Time"); + + fParticlesToIgnore = { + G4NeutrinoE::Definition(), G4AntiNeutrinoE::Definition(), G4NeutrinoMu::Definition(), + G4AntiNeutrinoMu::Definition(), G4NeutrinoTau::Definition(), G4AntiNeutrinoTau::Definition(), + }; + for (const auto& particle : fParticlesToIgnore) { + // + } +} + +G4ClassificationOfNewTrack StackingAction::ClassifyNewTrack(const G4Track* track) { + if (track->GetParentID() <= 0) { + // always process the first track regardless + return fUrgent; + } + + auto particle = track->GetParticleDefinition(); + if (fParticlesToIgnore.find(particle) != fParticlesToIgnore.end()) { + // ignore this track + return fKill; + } + + if (track->GetCreatorProcess()->GetProcessType() != G4ProcessType::fDecay) { + return fUrgent; + } + + if (particle->GetParticleType() == "nucleus" && !particle->GetPDGStable()) { + // unstable nucleus + if (particle->GetPDGLifeTime() > fMaxAllowedLifetime) { + G4String energy = G4BestUnit(track->GetKineticEnergy(), "Energy"); + G4String lifeTime = G4BestUnit(particle->GetPDGLifeTime(), "Time"); + + return fSimulationManager->fRestGeant4Metadata->isFullChainActivated() ? fWaiting : fKill; + } + } + return fUrgent; +} + +void StackingAction::NewStage() { + /* + * Called after processing all Urgent tracks + * Close event and start a new sub event if there are waiting tracks + */ + + const auto outputManager = fSimulationManager->GetOutputManager(); + + const Int_t subEventID = outputManager->fEvent->GetSubID(); + outputManager->FinishAndSubmitEvent(); + outputManager->fEvent->SetSubID(subEventID + 1); +} + +StackingAction::~StackingAction() = default; diff --git a/src/TrackingAction.cxx b/src/TrackingAction.cxx index c2eaefd1..3de599fd 100644 --- a/src/TrackingAction.cxx +++ b/src/TrackingAction.cxx @@ -31,10 +31,11 @@ TrackingAction::TrackingAction(SimulationManager* simulationManager, RunAction* fFullChain = restG4Metadata->isFullChainActivated(); - if (fFullChain) + if (fFullChain) { G4cout << "Full chain is active" << G4endl; - else + } else { G4cout << "Full chain is NOT active" << G4endl; + } } TrackingAction::~TrackingAction() {} From 71c9cdcaaa0fbab0184c4fcd38584988485a430b Mon Sep 17 00:00:00 2001 From: lobis Date: Mon, 20 Jun 2022 16:40:53 +0200 Subject: [PATCH 004/173] Compilation works --- include/SimulationManager.h | 10 ++ include/StackingAction.h | 5 +- include/TrackingAction.h | 10 +- src/ActionInitialization.cxx | 10 +- src/Application.cxx | 4 - src/DetectorConstruction.cxx | 3 +- src/PrimaryGeneratorAction.cxx | 145 ++++------------------------- src/SimulationManager.cxx | 163 ++++++++++++++++++++++++++++++++- src/StackingAction.cxx | 2 + src/SteppingAction.cxx | 99 +------------------- src/TrackingAction.cxx | 81 +--------------- 11 files changed, 208 insertions(+), 324 deletions(-) diff --git a/include/SimulationManager.h b/include/SimulationManager.h index 1d0216df..58199b21 100644 --- a/include/SimulationManager.h +++ b/include/SimulationManager.h @@ -45,8 +45,18 @@ class OutputManager { OutputManager(const SimulationManager*); void UpdateEvent(); void FinishAndSubmitEvent(); + bool IsEmptyEvent() const; + bool IsValidEvent() const; + bool IsValidTrack(const G4Track*) const; // TODO + bool IsValidStep(const G4Step*) const; // TODO + + void RecordTrack(const G4Track*); + void UpdateTrack(const G4Track*); + + void RecordStep(const G4Step*); + private: std::unique_ptr fEvent{}; diff --git a/include/StackingAction.h b/include/StackingAction.h index b6202e54..bdfa1ec7 100644 --- a/include/StackingAction.h +++ b/include/StackingAction.h @@ -7,6 +7,8 @@ #include #include +#include "SimulationManager.h" + class OutputManager; class SimulationManager; @@ -25,8 +27,7 @@ class StackingAction : public G4UserStackingAction { private: SimulationManager* fSimulationManager; - - const G4double fMaxAllowedLifetime; + double fMaxAllowedLifetime; G4String fMaxAllowedLifetimeWithUnit; std::set fParticlesToIgnore; diff --git a/include/TrackingAction.h b/include/TrackingAction.h index 9991bdec..ae2d2f3f 100644 --- a/include/TrackingAction.h +++ b/include/TrackingAction.h @@ -16,7 +16,7 @@ class SimulationManager; class TrackingAction : public G4UserTrackingAction { public: - TrackingAction(SimulationManager*, RunAction*, EventAction*); + TrackingAction(SimulationManager*); ~TrackingAction(); virtual void PreUserTrackingAction(const G4Track*); @@ -24,14 +24,6 @@ class TrackingAction : public G4UserTrackingAction { private: SimulationManager* fSimulationManager; - RunAction* fRun; - EventAction* fEvent; - - G4double fCharge, fMass; - - G4bool fFullChain; - - Double_t fGlobalTime; }; #endif diff --git a/src/ActionInitialization.cxx b/src/ActionInitialization.cxx index d2c67a0f..0983cd03 100644 --- a/src/ActionInitialization.cxx +++ b/src/ActionInitialization.cxx @@ -81,16 +81,12 @@ void ActionInitialization::Build() const { primaryGenerator->SetAngularDistribution(&(fSimulationManager->initialAngularDistribution)); } - auto runAction = new RunAction(fSimulationManager); - auto eventAction = new EventAction(fSimulationManager); - auto trackingAction = new TrackingAction(fSimulationManager, runAction, eventAction); - SetUserAction(primaryGenerator); - SetUserAction(runAction); - SetUserAction(eventAction); + SetUserAction(new RunAction(fSimulationManager)); + SetUserAction(new EventAction(fSimulationManager)); SetUserAction(new SteppingAction(fSimulationManager)); SetUserAction(new StackingAction(fSimulationManager)); - SetUserAction(trackingAction); + SetUserAction(new TrackingAction(fSimulationManager)); /* G4EventManager::GetEventManager()->SetNumberOfAdditionalWaitingStacks(1); // optical stack diff --git a/src/Application.cxx b/src/Application.cxx index d9058022..f1603d47 100644 --- a/src/Application.cxx +++ b/src/Application.cxx @@ -117,12 +117,8 @@ void Application::Run(const CommandLineParameters& commandLineParameters) { fSimulationManager->fRestRun->FormOutputFile(); - fSimulationManager->fRestGeant4Event = new TRestGeant4Event(); - fSimulationManager->fRestGeant4SubEvent = new TRestGeant4Event(); fSimulationManager->fRestRun->AddEventBranch(&fSimulationManager->fEvent); - fSimulationManager->fRestGeant4Track = new TRestGeant4Track(); - // choose the Random engine CLHEP::HepRandom::setTheEngine(new CLHEP::RanecuEngine); long seed = fSimulationManager->fRestGeant4Metadata->GetSeed(); diff --git a/src/DetectorConstruction.cxx b/src/DetectorConstruction.cxx index 65a84716..b318c631 100644 --- a/src/DetectorConstruction.cxx +++ b/src/DetectorConstruction.cxx @@ -26,7 +26,6 @@ DetectorConstruction::DetectorConstruction(SimulationManager* simulationManager) DetectorConstruction::~DetectorConstruction() { delete parser; } G4VPhysicalVolume* DetectorConstruction::Construct() { - TRestGeant4Event* restG4Event = fSimulationManager->fRestGeant4Event; TRestGeant4Metadata* restG4Metadata = fSimulationManager->fRestGeant4Metadata; cout << "Isotope table " << endl; @@ -189,7 +188,7 @@ G4VPhysicalVolume* DetectorConstruction::Construct() { } cout << "Activating volume : " << actVolName << endl; - restG4Event->AddActiveVolume((string)actVolName); + // restG4Event->AddActiveVolume((string)actVolName); if (!pVol) { cout << "DetectorConstruction. Volume " << actVolName << " is not defined in the geometry" << endl; diff --git a/src/PrimaryGeneratorAction.cxx b/src/PrimaryGeneratorAction.cxx index 2bb18bbc..4a3c715e 100644 --- a/src/PrimaryGeneratorAction.cxx +++ b/src/PrimaryGeneratorAction.cxx @@ -92,9 +92,6 @@ void PrimaryGeneratorAction::SetGeneratorSpatialDensity(TString str) { void PrimaryGeneratorAction::GeneratePrimaries(G4Event* event) { auto simulationManager = fSimulationManager; TRestRun* restRun = simulationManager->fRestRun; - TRestGeant4Track* restTrack = simulationManager->fRestGeant4Track; - TRestGeant4Event* restG4Event = simulationManager->fRestGeant4Event; - TRestGeant4Event* subRestG4Event = simulationManager->fRestGeant4SubEvent; TRestGeant4Metadata* restG4Metadata = simulationManager->fRestGeant4Metadata; TRestGeant4PhysicsLists* restPhysList = simulationManager->fRestGeant4PhysicsLists; @@ -106,7 +103,6 @@ void PrimaryGeneratorAction::GeneratePrimaries(G4Event* event) { // position inside // we should have already written the information from previous event to disk // (in endOfEventAction) - restG4Event->Initialize(); for (int i = 0; i < restG4Metadata->GetNumberOfSources(); i++) { restG4Metadata->GetParticleSource(i)->Update(); @@ -120,7 +116,7 @@ void PrimaryGeneratorAction::GeneratePrimaries(G4Event* event) { for (int i = 0; i < restG4Metadata->GetNumberOfSources(); i++) { vector particles = restG4Metadata->GetParticleSource(i)->GetParticles(); - for (auto p : particles) { + for (const auto& p : particles) { // ParticleDefinition should be always declared first (after position). SetParticleDefinition(i, p); @@ -137,9 +133,6 @@ void PrimaryGeneratorAction::GeneratePrimaries(G4Event* event) { G4ParticleDefinition* PrimaryGeneratorAction::SetParticleDefinition(Int_t n, TRestGeant4Particle p) { auto simulationManager = fSimulationManager; TRestRun* restRun = simulationManager->fRestRun; - TRestGeant4Track* restTrack = simulationManager->fRestGeant4Track; - TRestGeant4Event* restG4Event = simulationManager->fRestGeant4Event; - TRestGeant4Event* subRestG4Event = simulationManager->fRestGeant4SubEvent; TRestGeant4Metadata* restG4Metadata = simulationManager->fRestGeant4Metadata; TRestGeant4PhysicsLists* restPhysList = simulationManager->fRestGeant4PhysicsLists; @@ -179,7 +172,7 @@ G4ParticleDefinition* PrimaryGeneratorAction::SetParticleDefinition(Int_t n, TRe fParticleGun->SetParticleDefinition(fParticle); - restG4Event->SetPrimaryEventParticleName(particle_name); + // restG4Event->SetPrimaryEventParticleName(particle_name); return fParticle; } @@ -187,9 +180,6 @@ G4ParticleDefinition* PrimaryGeneratorAction::SetParticleDefinition(Int_t n, TRe void PrimaryGeneratorAction::SetParticleDirection(Int_t n, TRestGeant4Particle p) { auto simulationManager = fSimulationManager; TRestRun* restRun = simulationManager->fRestRun; - TRestGeant4Track* restTrack = simulationManager->fRestGeant4Track; - TRestGeant4Event* restG4Event = simulationManager->fRestGeant4Event; - TRestGeant4Event* subRestG4Event = simulationManager->fRestGeant4SubEvent; TRestGeant4Metadata* restG4Metadata = simulationManager->fRestGeant4Metadata; G4ThreeVector direction; @@ -234,43 +224,7 @@ void PrimaryGeneratorAction::SetParticleDirection(Int_t n, TRestGeant4Particle p } if (angular_dist_type == g4_metadata_parameters::angular_dist_types::ISOTROPIC) { - // if (generator_type == g4_metadata_parameters::generator_types::VIRTUAL_BOX) { - // if (face == 0) direction.set(0, -1, 0); - // if (face == 1) direction.set(0, 1, 0); - // if (face == 2) direction.set(-1, 0, 0); - // if (face == 3) direction.set(1, 0, 0); - // if (face == 4) direction.set(0, 0, -1); - // if (face == 5) direction.set(0, 0, 1); - - // Double_t theta = GetCosineLowRandomThetaAngle(); - // // recording the primaries distribution - // G4ThreeVector referenceOrigin = direction; - - // // We rotate the origin direction by the angular distribution angle - // G4ThreeVector orthoVector = direction.orthogonal(); - // direction.rotate(theta, orthoVector); - - // // We rotate a random angle along the original direction - // Double_t randomAngle = G4UniformRand() * 2 * M_PI; - // direction.rotate(randomAngle, referenceOrigin); - //} else if (generator_type == g4_metadata_parameters::generator_types::VIRTUAL_SPHERE) { - // direction = -fParticleGun->GetParticlePosition().unit(); - - // Double_t theta = GetCosineLowRandomThetaAngle(); - - // G4ThreeVector referenceOrigin = direction; - - // // We rotate the origin direction by the angular distribution angle - // G4ThreeVector orthoVector = direction.orthogonal(); - // direction.rotate(theta, orthoVector); - - // // We rotate a random angle along the original direction - // Double_t randomAngle = G4UniformRand() * 2 * M_PI; - // direction.rotate(randomAngle, referenceOrigin); - - //} else { direction = GetIsotropicVector(); - //} } else if (angular_dist_type == g4_metadata_parameters::angular_dist_types::TH1D) { Double_t angle = 0; Double_t value = G4UniformRand() * (fAngularDistribution->Integral()); @@ -313,42 +267,6 @@ void PrimaryGeneratorAction::SetParticleDirection(Int_t n, TRestGeant4Particle p << endl; direction.set(1, 0, 0); } - - // if (generator_type == g4_metadata_parameters::generator_types::VIRTUAL_BOX) { - // if (face == 0) direction.set(0, -1, 0); - // if (face == 1) direction.set(0, 1, 0); - // if (face == 2) direction.set(-1, 0, 0); - // if (face == 3) direction.set(1, 0, 0); - // if (face == 4) direction.set(0, 0, -1); - // if (face == 5) direction.set(0, 0, 1); - //} - - // if (generator_type == g4_metadata_parameters::generator_types::VIRTUAL_WALL) { - // /* - // The default plane (virtualWall) is an XY plane so the default normal vector is (0,0,1). - // We will rotate this vector according to the generator rotation so that keeps being normal to the - // plane - // */ - // TVector3 normal(0, 0, 1); - - // normal.RotateX(M_PI * restG4Metadata->GetGeneratorRotation().X() / 180); - // normal.RotateY(M_PI * restG4Metadata->GetGeneratorRotation().Y() / 180); - // normal.RotateZ(M_PI * restG4Metadata->GetGeneratorRotation().Z() / 180); - - // /* - // Depending on which rotation we chose for the plane the normal vector can now point outwards of - // the detector. We rotate so that it always looks towards the center (0,0,0) - // */ - // TVector3 generator_position = restG4Metadata->GetGeneratorPosition().Unit(); - // if (generator_position.x() * normal.x() + generator_position.y() * normal.y() + - // generator_position.z() * normal.z() > - // 0) { - // normal = (-1) * normal; - // } - - // direction.set(normal.x(), normal.y(), normal.z()); - //} - G4ThreeVector referenceOrigin = direction; // We generate the distribution angle (theta) using a rotation around the orthogonal vector @@ -369,10 +287,11 @@ void PrimaryGeneratorAction::SetParticleDirection(Int_t n, TRestGeant4Particle p } else if (angular_dist_type == g4_metadata_parameters::angular_dist_types::BACK_TO_BACK) { // This should never crash. In TRestG4Metadata we have defined that if the // first source is backtoback we set it to isotropic - TVector3 v = restG4Event->GetPrimaryEventDirection(n - 1); - v = v.Unit(); + // TVector3 v = restG4Event->GetPrimaryEventDirection(n - 1); + // v = v.Unit(); - direction.set(-v.X(), -v.Y(), -v.Z()); + // direction.set(-v.X(), -v.Y(), -v.Z()); + exit(1); } else { G4cout << "WARNING: Generator angular distribution was not recognized. " "Launching particle to (1,0,0)" @@ -381,15 +300,15 @@ void PrimaryGeneratorAction::SetParticleDirection(Int_t n, TRestGeant4Particle p // storing the direction in TRestG4Event class TVector3 eventDirection(direction.x(), direction.y(), direction.z()); - restG4Event->SetPrimaryEventDirection(eventDirection); - - if (restG4Metadata->GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Debug) { - cout << "DEBUG: Event direction (normalized): " - << "(" << restG4Event->GetPrimaryEventDirection(n).X() << ", " - << restG4Event->GetPrimaryEventDirection(n).Y() << ", " - << restG4Event->GetPrimaryEventDirection(n).Z() << ")" << endl; - } - + // restG4Event->SetPrimaryEventDirection(eventDirection); + /* + if (restG4Metadata->GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Debug) { + cout << "DEBUG: Event direction (normalized): " + << "(" << restG4Event->GetPrimaryEventDirection(n).X() << ", " + << restG4Event->GetPrimaryEventDirection(n).Y() << ", " + << restG4Event->GetPrimaryEventDirection(n).Z() << ")" << endl; + } + */ // setting particle direction fParticleGun->SetParticleMomentumDirection(direction); } @@ -398,9 +317,6 @@ void PrimaryGeneratorAction::SetParticleEnergy(Int_t n, TRestGeant4Particle p) { auto simulationManager = fSimulationManager; TRestRun* restRun = simulationManager->fRestRun; - TRestGeant4Track* restTrack = simulationManager->fRestGeant4Track; - TRestGeant4Event* restG4Event = simulationManager->fRestGeant4Event; - TRestGeant4Event* subRestG4Event = simulationManager->fRestGeant4SubEvent; TRestGeant4Metadata* restG4Metadata = simulationManager->fRestGeant4Metadata; Double_t energy = 0; @@ -475,7 +391,7 @@ void PrimaryGeneratorAction::SetParticleEnergy(Int_t n, TRestGeant4Particle p) { if (n == 0) lastEnergy = energy; fParticleGun->SetParticleEnergy(energy); - restG4Event->SetPrimaryEventEnergy(energy / keV); + // restG4Event->SetPrimaryEventEnergy(energy / keV); if (restG4Metadata->GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Debug) cout << "DEBUG: Particle energy: " << energy / keV << " keV" << endl; @@ -485,9 +401,6 @@ void PrimaryGeneratorAction::SetParticlePosition() { auto simulationManager = fSimulationManager; TRestRun* restRun = simulationManager->fRestRun; - TRestGeant4Track* restTrack = simulationManager->fRestGeant4Track; - TRestGeant4Event* restG4Event = simulationManager->fRestGeant4Event; - TRestGeant4Event* subRestG4Event = simulationManager->fRestGeant4SubEvent; TRestGeant4Metadata* restG4Metadata = simulationManager->fRestGeant4Metadata; double x = 0, y = 0, z = 0; @@ -500,7 +413,7 @@ void PrimaryGeneratorAction::SetParticlePosition() { g4_metadata_parameters::generator_shapes_map[g4_metadata_parameters::CleanString( generator_shape_name)]; - while (1) { + while (true) { if (generator_type == g4_metadata_parameters::generator_types::POINT) { GenPositionOnPoint(x, y, z); } else if (generator_type == g4_metadata_parameters::generator_types::SURFACE) { @@ -553,8 +466,8 @@ void PrimaryGeneratorAction::SetParticlePosition() { // storing the direction in TRestG4Event class TVector3 eventPosition(x, y, z); - restG4Event->SetPrimaryEventOrigin(eventPosition); - + // restG4Event->SetPrimaryEventOrigin(eventPosition); + /* if (restG4Metadata->GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Debug) { cout << "DEBUG: Event origin: " << "(" << restG4Event->GetPrimaryEventOrigin().X() << ", " @@ -562,29 +475,11 @@ void PrimaryGeneratorAction::SetParticlePosition() { << ")" << " mm" << endl; } - + */ // setting particle position fParticleGun->SetParticlePosition(G4ThreeVector(x, y, z)); } -////_____________________________________________________________________________ -// void PrimaryGeneratorAction::SetParticlePosition(int n) { -// // Storing particle's position to that retrieved from TRestG4Particle -// TVector3 pos = p.GetOrigin(); -// restG4Event->SetPrimaryEventOrigin(pos); -// -// if (restG4Metadata->GetVerboseLevel() >= REST_Debug) { -// cout << "DEBUG: Event origin: " -// << "(" << restG4Event->GetPrimaryEventOrigin().X() << ", " -// << restG4Event->GetPrimaryEventOrigin().Y() << ", " << restG4Event->GetPrimaryEventOrigin().Z() -// << ")" -// << " mm" << endl; -// } -// -// // Setting particle position -// fParticleGun->SetParticlePosition(G4ThreeVector(pos.X(), pos.Y(), pos.Z())); -//} - G4ThreeVector PrimaryGeneratorAction::GetIsotropicVector() { G4double a, b, c; G4double n; diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index 38d9b7a1..5cb8000d 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -3,10 +3,14 @@ #include #include +#include +#include #include using namespace std; +thread_local OutputManager* SimulationManager::fOutputManager = nullptr; + SimulationManager::SimulationManager() { // Only master thread should create the SimulationManager if (!G4Threading::IsMasterThread()) { @@ -91,6 +95,41 @@ void OutputManager::FinishAndSubmitEvent() { UpdateEvent(); } +void OutputManager::RecordTrack(const G4Track* track) { + if (!IsValidTrack(track)) { + return; + } + fEvent->InsertTrack(track); + + if (fEvent->fSubEventID > 0) { + const auto& lastTrack = fEvent->fTrack.back(); + assert(lastTrack.GetTrackID() == track->GetTrackID()); + // TODO + /* + bool isSubEventPrimary = fEvent->IsTrackSubEventPrimary(lastTrack.fTrackID); + if (isSubEventPrimary) { + spdlog::debug( + "OutputManager::RecordTrack - Setting track ID {} as SubEventPrimaryTrack of EventID {} " + "(SubEventID {}). Track info: {} - Created by " + "{} - ParentID: {}", + lastTrack.fTrackID, fEvent->fEventID, fEvent->fSubEventID, lastTrack.fParticleName, + lastTrack.fCreatorProcess, lastTrack.fParentID); + } + */ + } +} + +void OutputManager::UpdateTrack(const G4Track* track) { + if (!IsValidTrack(track)) { + return; + } + fEvent->UpdateTrack(track); +} + +void OutputManager::RecordStep(const G4Step* step) { + fEvent->InsertStep(step, *fSimulationManager->fRestGeant4Metadata); +} + // Geant4Lib TRestGeant4Event::TRestGeant4Event(const G4Event* event, const TRestGeant4Metadata& metadata) @@ -116,6 +155,48 @@ TRestGeant4Event::TRestGeant4Event(const G4Event* event, const TRestGeant4Metada } } +bool TRestGeant4Event::InsertTrack(const G4Track* track) { + if (fInitialStep.GetNumberOfHits() != 1) { + cout << "fInitialStep does not have exactly one step! Problem with stepping verbose" << endl; + exit(1); + } + fTrack.emplace_back(track); + fTrack.back().SetHits(fInitialStep); + + fTrackIDToTrackIndex[track->GetTrackID()] = fTrack.size() - 1; + + if (fTrack.empty()) { + /* + // primary for the sub-event + fSubEventPrimaryParticleName = track->GetParticleDefinition()->GetParticleName(); + fSubEventPrimaryEnergy = track->GetKineticEnergy() / CLHEP::keV; + const auto& position = track->GetPosition(); + fSubEventPrimaryPosition = + TVector3(position.x() / CLHEP::mm, position.y() / CLHEP::mm, position.z() / CLHEP::mm); + const auto& momentum = track->GetMomentumDirection(); + fSubEventPrimaryMomentum = + TVector3(momentum.x() / CLHEP::mm, momentum.y() / CLHEP::mm, momentum.z() / CLHEP::mm); + */ + } + return true; +} + +void TRestGeant4Event::UpdateTrack(const G4Track* track) { fTrack.back().UpdateTrack(track); } + +void TRestGeant4Event::InsertStep(const G4Step* step, TRestGeant4Metadata& metadata) { + if (step->GetTrack()->GetCurrentStepNumber() == 0) { + // initial step (from SteppingVerbose) is generated before TrackingAction can insert the first track + fInitialStep = TRestGeant4Hits(); + fInitialStep.InsertStep(step, metadata); + } else { + fTrack.back().InsertStep(step, metadata); + } +} + +bool OutputManager::IsValidTrack(const G4Track*) const { return true; } + +bool OutputManager::IsValidStep(const G4Step*) const { return true; } + TRestGeant4Track::TRestGeant4Track(const G4Track* track) : TRestGeant4Track() { fTrackID = track->GetTrackID(); fParentID = track->GetParentID(); @@ -141,4 +222,84 @@ TRestGeant4Track::TRestGeant4Track(const G4Track* track) : TRestGeant4Track() { const G4ThreeVector& trackOrigin = track->GetPosition(); fTrackOrigin = {trackOrigin.x(), trackOrigin.y(), trackOrigin.z()}; -} \ No newline at end of file +} + +void TRestGeant4Track::InsertStep(const G4Step* step, TRestGeant4Metadata& metadata) { + fHits.InsertStep(step, metadata); +} + +void TRestGeant4Track::UpdateTrack(const G4Track* track) { + if (track->GetTrackID() != fTrackID) { + G4cout << "Geant4Track::UpdateTrack - mismatch of trackID!" << endl; + exit(1); + } + + fTrackLength = track->GetTrackLength() / CLHEP::mm; + + // auto steppingAction = (SteppingAction*)G4EventManager::GetEventManager()->GetUserSteppingAction(); + // auto secondaries = steppingAction->GetfSecondary(); + // fNumberOfSecondaries = (int)secondaries->size(); +} + +void TRestGeant4Hits::InsertStep(const G4Step* step, TRestGeant4Metadata& metadata) { + const G4Track* track = step->GetTrack(); + + const auto& geometryInfo = metadata.GetGeant4GeometryInfo(); + // Variables that describe a step are taken. + const auto& volumeName = geometryInfo.GetAlternativeNameFromGeant4PhysicalName( + (TString &&) step->GetPreStepPoint()->GetPhysicalVolume()->GetName()); + + const auto& particle = step->GetTrack()->GetDefinition(); + const auto& particleID = particle->GetPDGEncoding(); + const auto& particleName = particle->GetParticleName(); + + metadata.fGeant4PhysicsInfo.InsertParticleName(particleID, particleName); + + const auto process = step->GetPostStepPoint()->GetProcessDefinedStep(); + const auto& processID = process->GetProcessType() * 1000 + process->GetProcessSubType(); + const auto& processName = process->GetProcessName(); + + metadata.fGeant4PhysicsInfo.InsertProcessName(processID, processName); + + const auto totalEnergyDeposit = step->GetTotalEnergyDeposit() / CLHEP::keV; + const auto trackKineticEnergy = step->GetTrack()->GetKineticEnergy() / CLHEP::keV; + + auto sensitiveVolumeName = + geometryInfo.GetAlternativeNameFromGeant4PhysicalName(metadata.GetSensitiveVolume()); + + if (particle->GetParticleName() == "geantino" && sensitiveVolumeName.Data() == volumeName) { + metadata.SetSaveAllEvents(true); + } + + if (!step->GetPostStepPoint()->GetProcessDefinedStep()) { + G4cout << endl; + G4cout << endl; + G4cout << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl; + G4cout << "An ERROR was detected on the G4Step process definition." << endl; + G4cout << "This is a sign of problem in the restG4 particle definition" << endl; + G4cout << endl; + G4cout << "E.g. A definition of a gamma with 0keV energy" << endl; + G4cout << endl; + G4cout << "Please, review your TRestGeant4Metadata RML definition" << endl; + G4cout << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl; + G4cout << endl; + G4cout << endl; + + exit(0); + } + + G4Track* aTrack = step->GetTrack(); + + Double_t x = aTrack->GetPosition().x() / CLHEP::mm; + Double_t y = aTrack->GetPosition().y() / CLHEP::mm; + Double_t z = aTrack->GetPosition().z() / CLHEP::mm; + + if (metadata.GetSensitiveVolume() == volumeName) { + // restG4Event->AddEnergyToSensitiveVolume(totalEnergyDeposit); + } + + const TVector3 hitPosition(x, y, z); + const Double_t hitGlobalTime = step->GetPreStepPoint()->GetGlobalTime() / CLHEP::second; + const G4ThreeVector& momentum = step->GetPreStepPoint()->GetMomentumDirection(); + const TVector3 momentumDirection = TVector3(momentum.x(), momentum.y(), momentum.z()); //.Unit(); +} diff --git a/src/StackingAction.cxx b/src/StackingAction.cxx index 8dbbe36d..d68fc680 100644 --- a/src/StackingAction.cxx +++ b/src/StackingAction.cxx @@ -11,6 +11,8 @@ #include "SimulationManager.h" StackingAction::StackingAction(SimulationManager* simulationManager) : fSimulationManager(simulationManager) { + fMaxAllowedLifetime = 100; // TODO: update this + fMaxAllowedLifetimeWithUnit = G4BestUnit(fMaxAllowedLifetime, "Time"); fParticlesToIgnore = { diff --git a/src/SteppingAction.cxx b/src/SteppingAction.cxx index ccbfbd0a..34e1b051 100644 --- a/src/SteppingAction.cxx +++ b/src/SteppingAction.cxx @@ -22,101 +22,6 @@ SteppingAction::SteppingAction(SimulationManager* simulationManager) SteppingAction::~SteppingAction() {} -void SteppingAction::UserSteppingAction(const G4Step* aStep) { - TRestGeant4Track* restTrack = fSimulationManager->fRestGeant4Track; - TRestGeant4Event* restG4Event = fSimulationManager->fRestGeant4Event; - TRestGeant4Metadata* restG4Metadata = fSimulationManager->fRestGeant4Metadata; - - const auto& geometryInfo = restG4Metadata->GetGeant4GeometryInfo(); - // Variables that describe a step are taken. - const auto& volumeName = geometryInfo.GetAlternativeNameFromGeant4PhysicalName( - (TString &&) aStep->GetPreStepPoint()->GetPhysicalVolume()->GetName()); - - const auto& particle = aStep->GetTrack()->GetDefinition(); - const auto& particleID = particle->GetPDGEncoding(); - const auto& particleName = particle->GetParticleName(); - - restG4Metadata->fGeant4PhysicsInfo.InsertParticleName(particleID, particleName); - - const auto process = aStep->GetPostStepPoint()->GetProcessDefinedStep(); - const auto& processID = process->GetProcessType() * 1000 + process->GetProcessSubType(); - const auto& processName = process->GetProcessName(); - - restG4Metadata->fGeant4PhysicsInfo.InsertProcessName(processID, processName); - - const auto totalEnergyDeposit = aStep->GetTotalEnergyDeposit() / keV; - const auto trackKineticEnergy = aStep->GetTrack()->GetKineticEnergy() / keV; - - auto sensitiveVolumeName = - geometryInfo.GetAlternativeNameFromGeant4PhysicalName(restG4Metadata->GetSensitiveVolume()); - - if (restTrack->GetParticleName() == "geantino" && sensitiveVolumeName.Data() == volumeName) { - restG4Metadata->SetSaveAllEvents(true); - } - - if (!aStep->GetPostStepPoint()->GetProcessDefinedStep()) { - G4cout << endl; - G4cout << endl; - G4cout << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl; - G4cout << "An ERROR was detected on the G4Step process definition." << endl; - G4cout << "This is a sign of problem in the restG4 particle definition" << endl; - G4cout << endl; - G4cout << "E.g. A definition of a gamma with 0keV energy" << endl; - G4cout << endl; - G4cout << "Please, review your TRestGeant4Metadata RML definition" << endl; - G4cout << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl; - G4cout << endl; - G4cout << endl; - - exit(0); - } - - G4Track* aTrack = aStep->GetTrack(); - - Double_t x = aTrack->GetPosition().x() / mm; - Double_t y = aTrack->GetPosition().y() / mm; - Double_t z = aTrack->GetPosition().z() / mm; - - if (restG4Metadata->GetSensitiveVolume() == volumeName) { - restG4Event->AddEnergyToSensitiveVolume(totalEnergyDeposit); - } - - const TVector3 hitPosition(x, y, z); - const Double_t hitGlobalTime = aStep->GetPreStepPoint()->GetGlobalTime() / second; - const G4ThreeVector& momentum = aStep->GetPreStepPoint()->GetMomentumDirection(); - const TVector3 momentumDirection = TVector3(momentum.x(), momentum.y(), momentum.z()); //.Unit(); - - Int_t volume = -1; - Bool_t alreadyStored = false; - // We check if the hit must be stored and keep it on restG4Track - for (int volID = 0; volID < restG4Metadata->GetNumberOfActiveVolumes(); volID++) { - if (restG4Event->isVolumeStored(volID)) { - if (restG4Metadata->GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Extreme) { - G4cout << "Step volume :" << volumeName << "::(" - << (G4String)restG4Metadata->GetActiveVolumeName(volID) << ")" << G4endl; - } - - // We store the hit if we have activated in the config - const Bool_t isActiveVolume = (volumeName == restG4Metadata->GetActiveVolumeName(volID)); - if (isActiveVolume) { - volume = volID; - if (restG4Metadata->GetVerboseLevel() >= - TRestStringOutput::REST_Verbose_Level::REST_Extreme) { - G4cout << "Storing hit" << G4endl; - } - restTrack->AddG4Hit(hitPosition, totalEnergyDeposit, hitGlobalTime, processID, volID, - trackKineticEnergy, momentumDirection); - alreadyStored = true; - restG4Metadata->fGeant4GeometryInfo.InsertVolumeName(volID, volumeName); - } - } - } - - // See issue #65. - // If the radioactive decay occurs in a non-active volume then the id will be -1 - const Bool_t isDecay = (processName == (G4String) "RadioactiveDecay"); - if (!alreadyStored && isDecay) { - restTrack->AddG4Hit(hitPosition, totalEnergyDeposit, hitGlobalTime, processID, volume, - trackKineticEnergy, momentumDirection); - } +void SteppingAction::UserSteppingAction(const G4Step* step) { + fSimulationManager->GetOutputManager()->RecordStep(step); } \ No newline at end of file diff --git a/src/TrackingAction.cxx b/src/TrackingAction.cxx index 3de599fd..93c5d963 100644 --- a/src/TrackingAction.cxx +++ b/src/TrackingAction.cxx @@ -8,92 +8,19 @@ #include #include -#include "EventAction.h" -#include "RunAction.h" #include "SimulationManager.h" using namespace std; -G4double prevTime = 0; -G4String aux; - -TrackingAction::TrackingAction(SimulationManager* simulationManager, RunAction* runAction, - EventAction* eventAction) - : G4UserTrackingAction(), - fSimulationManager(simulationManager), - fRun(runAction), - fEvent(eventAction) - -{ - TRestGeant4Metadata* restG4Metadata = fSimulationManager->fRestGeant4Metadata; - - fFullChain = false; - - fFullChain = restG4Metadata->isFullChainActivated(); - - if (fFullChain) { - G4cout << "Full chain is active" << G4endl; - } else { - G4cout << "Full chain is NOT active" << G4endl; - } -} +TrackingAction::TrackingAction(SimulationManager* simulationManager) + : G4UserTrackingAction(), fSimulationManager(simulationManager) {} TrackingAction::~TrackingAction() {} void TrackingAction::PreUserTrackingAction(const G4Track* track) { - TRestRun* restRun = fSimulationManager->fRestRun; - TRestGeant4Track* restTrack = fSimulationManager->fRestGeant4Track; - TRestGeant4Event* restG4Event = fSimulationManager->fRestGeant4Event; - TRestGeant4Event* subRestG4Event = fSimulationManager->fRestGeant4SubEvent; - TRestGeant4Metadata* restG4Metadata = fSimulationManager->fRestGeant4Metadata; - TRestGeant4PhysicsLists* restPhysList = fSimulationManager->fRestGeant4PhysicsLists; - - if (restG4Metadata->GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Extreme) { - if (track->GetTrackID() % 10 == 0) { - cout << "EXTREME: Processing track " << track->GetTrackID() << endl; - } - } - G4ParticleDefinition* particle = track->GetDefinition(); - G4String name = particle->GetParticleName(); - fCharge = particle->GetPDGCharge(); - - restTrack->RemoveHits(); - - restTrack->SetTrackID(track->GetTrackID()); - restTrack->SetParentID(track->GetParentID()); - restTrack->SetKineticEnergy(track->GetKineticEnergy() / keV); - restTrack->SetParticleName(name); - restTrack->SetGlobalTrackTime(track->GetGlobalTime() / second); - - G4ThreeVector trkOrigin = track->GetPosition(); - restTrack->SetTrackOrigin(trkOrigin.x(), trkOrigin.y(), trkOrigin.z()); - - // We finish after the de-excitation of the resulting nucleus (we skip the - // full chain, just first decay) On future we must add an option through - // TRestGeant4Metadata to store a given number of decays - - Int_t ID = track->GetTrackID(); - if (!fFullChain && fCharge > 2 && ID > 1 && -#ifdef GEANT4_VERSION_LESS_11_0_0 - !name.contains("[") -#else - !G4StrUtil::contains(name, "[") -#endif - ) { - auto tr = (G4Track*)track; - tr->SetTrackStatus(fStopAndKill); - } + fSimulationManager->GetOutputManager()->RecordTrack(track); } void TrackingAction::PostUserTrackingAction(const G4Track* track) { - TRestGeant4Track* restTrack = fSimulationManager->fRestGeant4Track; - TRestGeant4Event* restG4Event = fSimulationManager->fRestGeant4Event; - - restTrack->SetTrackTimeLength(track->GetLocalTime() / microsecond); - - // G4cout << "Storing track : Number of hits : " << - // restTrack->GetNumberOfHits() << G4endl; - - // if (restTrack->GetNumberOfHits() > 0 || restG4Metadata->RegisterEmptyTracks()) - restG4Event->AddTrack(*restTrack); + fSimulationManager->GetOutputManager()->UpdateTrack(track); } From 8b6fac0c940f367cc17d8c44d870bccb614ab307 Mon Sep 17 00:00:00 2001 From: lobis Date: Mon, 20 Jun 2022 16:58:55 +0200 Subject: [PATCH 005/173] Added stepping verbose --- include/ActionInitialization.h | 2 +- include/SteppingVerbose.h | 30 ++++++++++++++++++++++++++++++ src/ActionInitialization.cxx | 9 +++++---- src/Application.cxx | 4 ++++ src/SimulationManager.cxx | 8 ++++---- src/SteppingVerbose.cxx | 29 +++++++++++++++++++++++++++++ 6 files changed, 73 insertions(+), 9 deletions(-) create mode 100644 include/SteppingVerbose.h create mode 100644 src/SteppingVerbose.cxx diff --git a/include/ActionInitialization.h b/include/ActionInitialization.h index b451edd5..ca2f6971 100644 --- a/include/ActionInitialization.h +++ b/include/ActionInitialization.h @@ -16,7 +16,7 @@ class ActionInitialization : public G4VUserActionInitialization { virtual void BuildForMaster() const; virtual void Build() const; - // virtual G4VSteppingVerbose* InitializeSteppingVerbose() const; + virtual G4VSteppingVerbose* InitializeSteppingVerbose() const; private: SimulationManager* fSimulationManager; diff --git a/include/SteppingVerbose.h b/include/SteppingVerbose.h new file mode 100644 index 00000000..89674ddc --- /dev/null +++ b/include/SteppingVerbose.h @@ -0,0 +1,30 @@ +// +// Created by lobis on 6/20/2022. +// + +#ifndef REST_STEPPINGVERBOSE_H +#define REST_STEPPINGVERBOSE_H + +#include +#include +#include + +class SimulationManager; +class G4Step; + +class SteppingVerbose : public G4SteppingVerbose { + public: + SteppingVerbose(SimulationManager*); + ~SteppingVerbose(); + + virtual void TrackingStarted(); + virtual void StepInfo(); + + int GetSteppingVerbose() { return fManager->GetverboseLevel(); } + void SetSteppingVerbose(int level) { fManager->SetVerboseLevel(level); } + + private: + SimulationManager* fSimulationManager; +}; + +#endif // REST_STEPPINGVERBOSE_H diff --git a/src/ActionInitialization.cxx b/src/ActionInitialization.cxx index 0983cd03..9a992742 100644 --- a/src/ActionInitialization.cxx +++ b/src/ActionInitialization.cxx @@ -6,14 +6,13 @@ #include "DetectorConstruction.h" #include "EventAction.h" +#include "G4RunManager.hh" #include "PrimaryGeneratorAction.h" #include "RunAction.h" #include "SimulationManager.h" -// #include "StackingAction.h" #include "StackingAction.h" #include "SteppingAction.h" -// #include "SteppingVerbose.h" -#include "G4RunManager.hh" +#include "SteppingVerbose.h" #include "TrackingAction.h" using namespace std; @@ -93,4 +92,6 @@ void ActionInitialization::Build() const { */ } -// G4VSteppingVerbose* ActionInitialization::InitializeSteppingVerbose() const { return new SteppingVerbose; } \ No newline at end of file +G4VSteppingVerbose* ActionInitialization::InitializeSteppingVerbose() const { + return new SteppingVerbose(fSimulationManager); +} \ No newline at end of file diff --git a/src/Application.cxx b/src/Application.cxx index f1603d47..341d52ac 100644 --- a/src/Application.cxx +++ b/src/Application.cxx @@ -13,6 +13,7 @@ #include #include +#include #include #include #include @@ -27,6 +28,7 @@ #include "RunAction.h" #include "SimulationManager.h" #include "SteppingAction.h" +#include "SteppingVerbose.h" #include "TrackingAction.h" #ifdef G4VIS_USE @@ -124,6 +126,8 @@ void Application::Run(const CommandLineParameters& commandLineParameters) { long seed = fSimulationManager->fRestGeant4Metadata->GetSeed(); CLHEP::HepRandom::setTheSeed(seed); + G4VSteppingVerbose::SetInstance(new SteppingVerbose(fSimulationManager)); + auto runManager = new G4RunManager; auto detector = new DetectorConstruction(fSimulationManager); diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index 5cb8000d..3e5db47f 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -143,11 +143,11 @@ TRestGeant4Event::TRestGeant4Event(const G4Event* event, const TRestGeant4Metada // Defining if the hits in a given volume will be stored for (int i = 0; i < metadata.GetNumberOfActiveVolumes(); i++) { if (metadata.GetStorageChance(i) >= 1.00) { - ActivateVolumeForStorage(i); + // ActivateVolumeForStorage(i); } else { Double_t randomNumber = G4UniformRand(); if (metadata.GetStorageChance(i) >= randomNumber) { - ActivateVolumeForStorage(i); + // ActivateVolumeForStorage(i); } else { DisableVolumeForStorage(i); } @@ -157,8 +157,8 @@ TRestGeant4Event::TRestGeant4Event(const G4Event* event, const TRestGeant4Metada bool TRestGeant4Event::InsertTrack(const G4Track* track) { if (fInitialStep.GetNumberOfHits() != 1) { - cout << "fInitialStep does not have exactly one step! Problem with stepping verbose" << endl; - exit(1); + // cout << "fInitialStep does not have exactly one step! Problem with stepping verbose" << endl; + // exit(1); } fTrack.emplace_back(track); fTrack.back().SetHits(fInitialStep); diff --git a/src/SteppingVerbose.cxx b/src/SteppingVerbose.cxx new file mode 100644 index 00000000..a2ee521b --- /dev/null +++ b/src/SteppingVerbose.cxx @@ -0,0 +1,29 @@ +// +// Created by lobis on 6/20/2022. +// + +#include "SteppingVerbose.h" + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "DetectorConstruction.h" +#include "EventAction.h" + +SteppingVerbose::SteppingVerbose(SimulationManager* simulationManager) + : G4SteppingVerbose(), fSimulationManager(simulationManager) {} +SteppingVerbose::~SteppingVerbose() {} + +void SteppingVerbose::TrackingStarted() { + CopyState(); + fSimulationManager->GetOutputManager()->RecordStep(fStep); +} + +void SteppingVerbose::StepInfo() {} From 7ddf769d227c39b64f312641bf7dc136268213d7 Mon Sep 17 00:00:00 2001 From: lobis Date: Mon, 20 Jun 2022 17:30:56 +0200 Subject: [PATCH 006/173] Fixed problem with stepping verbose --- src/RunAction.cxx | 4 +++ src/SimulationManager.cxx | 55 +++++++++++++++++++++++---------------- 2 files changed, 37 insertions(+), 22 deletions(-) diff --git a/src/RunAction.cxx b/src/RunAction.cxx index 295fea51..0592cdb4 100644 --- a/src/RunAction.cxx +++ b/src/RunAction.cxx @@ -2,6 +2,7 @@ #include "RunAction.h" #include +#include #include #include @@ -27,6 +28,9 @@ void RunAction::BeginOfRunAction(const G4Run*) { << endl; G4cout << "=======================================================================" << endl; + auto steppingVerbose = ((SteppingVerbose*)G4VSteppingVerbose::GetInstance()); + steppingVerbose->SetSteppingVerbose(1); + fSimulationManager->InitializeOutputManager(); // inform the runManager to save random number seed G4RunManager::GetRunManager()->SetRandomNumberStore(false); diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index 3e5db47f..c39e3767 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -157,8 +157,8 @@ TRestGeant4Event::TRestGeant4Event(const G4Event* event, const TRestGeant4Metada bool TRestGeant4Event::InsertTrack(const G4Track* track) { if (fInitialStep.GetNumberOfHits() != 1) { - // cout << "fInitialStep does not have exactly one step! Problem with stepping verbose" << endl; - // exit(1); + cout << "fInitialStep does not have exactly one step! Problem with stepping verbose" << endl; + exit(1); } fTrack.emplace_back(track); fTrack.back().SetHits(fInitialStep); @@ -256,8 +256,15 @@ void TRestGeant4Hits::InsertStep(const G4Step* step, TRestGeant4Metadata& metada metadata.fGeant4PhysicsInfo.InsertParticleName(particleID, particleName); const auto process = step->GetPostStepPoint()->GetProcessDefinedStep(); - const auto& processID = process->GetProcessType() * 1000 + process->GetProcessSubType(); - const auto& processName = process->GetProcessName(); + G4String processName = "Init"; + G4String processTypeName = "Init"; + G4int processID = -1; + if (track->GetCurrentStepNumber() != + 0) { // 0 = Init step (G4SteppingVerbose) process is not defined for this step + processName = process->GetProcessName(); + processTypeName = G4VProcess::GetProcessTypeName(process->GetProcessType()); + processID = process->GetProcessType() * 1000 + process->GetProcessSubType(); + } metadata.fGeant4PhysicsInfo.InsertProcessName(processID, processName); @@ -271,23 +278,6 @@ void TRestGeant4Hits::InsertStep(const G4Step* step, TRestGeant4Metadata& metada metadata.SetSaveAllEvents(true); } - if (!step->GetPostStepPoint()->GetProcessDefinedStep()) { - G4cout << endl; - G4cout << endl; - G4cout << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl; - G4cout << "An ERROR was detected on the G4Step process definition." << endl; - G4cout << "This is a sign of problem in the restG4 particle definition" << endl; - G4cout << endl; - G4cout << "E.g. A definition of a gamma with 0keV energy" << endl; - G4cout << endl; - G4cout << "Please, review your TRestGeant4Metadata RML definition" << endl; - G4cout << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl; - G4cout << endl; - G4cout << endl; - - exit(0); - } - G4Track* aTrack = step->GetTrack(); Double_t x = aTrack->GetPosition().x() / CLHEP::mm; @@ -301,5 +291,26 @@ void TRestGeant4Hits::InsertStep(const G4Step* step, TRestGeant4Metadata& metada const TVector3 hitPosition(x, y, z); const Double_t hitGlobalTime = step->GetPreStepPoint()->GetGlobalTime() / CLHEP::second; const G4ThreeVector& momentum = step->GetPreStepPoint()->GetMomentumDirection(); - const TVector3 momentumDirection = TVector3(momentum.x(), momentum.y(), momentum.z()); //.Unit(); + const TVector3 momentumDirection = TVector3(momentum.x(), momentum.y(), momentum.z()).Unit(); + + // ------- + AddHit(hitPosition, totalEnergyDeposit, hitGlobalTime); // this increases fNHits + + fProcessID.Set(fNHits); + fProcessID[fNHits - 1] = processID; + + fVolumeID.Set(fNHits); + fVolumeID[fNHits - 1] = 0; + + fKineticEnergy.Set(fNHits); + fKineticEnergy[fNHits - 1] = 0; + + fMomentumDirectionX.Set(fNHits); + fMomentumDirectionX[fNHits - 1] = momentumDirection.X(); + + fMomentumDirectionY.Set(fNHits); + fMomentumDirectionY[fNHits - 1] = momentumDirection.Y(); + + fMomentumDirectionZ.Set(fNHits); + fMomentumDirectionZ[fNHits - 1] = momentumDirection.Z(); } From afbeca1aa10e6b3dee92c13c5db71198b4d6b8b8 Mon Sep 17 00:00:00 2001 From: lobis Date: Tue, 21 Jun 2022 09:56:11 +0200 Subject: [PATCH 007/173] Added SensitiveDetector class --- include/DetectorConstruction.h | 3 +- include/SensitiveDetector.h | 21 +++++++++++++ include/SimulationManager.h | 5 +-- src/DetectorConstruction.cxx | 57 ++++++++++++++++++++++++++++++++++ src/SensitiveDetector.cxx | 39 +++++++++++++++++++++++ src/SimulationManager.cxx | 9 ++++++ 6 files changed, 131 insertions(+), 3 deletions(-) create mode 100644 include/SensitiveDetector.h create mode 100644 src/SensitiveDetector.cxx diff --git a/include/DetectorConstruction.h b/include/DetectorConstruction.h index 8065a752..cc15d4c8 100644 --- a/include/DetectorConstruction.h +++ b/include/DetectorConstruction.h @@ -42,7 +42,8 @@ class DetectorConstruction : public G4VUserDetectorConstruction { ~DetectorConstruction(); public: - G4VPhysicalVolume* Construct(); + G4VPhysicalVolume* Construct() override; + void ConstructSDandField() override; friend class TRestGeant4GeometryInfo; }; diff --git a/include/SensitiveDetector.h b/include/SensitiveDetector.h new file mode 100644 index 00000000..090a35e9 --- /dev/null +++ b/include/SensitiveDetector.h @@ -0,0 +1,21 @@ + +#ifndef REST_SENSITIVEDETECTOR_H +#define REST_SENSITIVEDETECTOR_H + +#include + +class G4TouchableHistory; +class SimulationManager; + +class SensitiveDetector : public G4VSensitiveDetector { + public: + explicit SensitiveDetector(SimulationManager* simulationManager, const G4String& name); + virtual ~SensitiveDetector() = default; + + virtual void Initialize(G4HCofThisEvent*) {} + virtual G4bool ProcessHits(G4Step* aStep, G4TouchableHistory*); + + private: + SimulationManager* fSimulationManager; +}; +#endif // REST_SENSITIVEDETECTOR_H diff --git a/include/SimulationManager.h b/include/SimulationManager.h index 58199b21..62ac249a 100644 --- a/include/SimulationManager.h +++ b/include/SimulationManager.h @@ -49,14 +49,15 @@ class OutputManager { bool IsEmptyEvent() const; bool IsValidEvent() const; - bool IsValidTrack(const G4Track*) const; // TODO - bool IsValidStep(const G4Step*) const; // TODO + bool IsValidTrack(const G4Track*) const; // TODO + bool IsValidStep(const G4Step*) const; // TODO void RecordTrack(const G4Track*); void UpdateTrack(const G4Track*); void RecordStep(const G4Step*); + void AddSensitiveEnergy(Double_t energy, const char* physicalVolumeName); private: std::unique_ptr fEvent{}; diff --git a/src/DetectorConstruction.cxx b/src/DetectorConstruction.cxx index b318c631..20d1c16c 100644 --- a/src/DetectorConstruction.cxx +++ b/src/DetectorConstruction.cxx @@ -1,14 +1,17 @@ #include "DetectorConstruction.h" +#include #include #include #include #include +#include #include #include #include +#include #include #include #include @@ -218,6 +221,60 @@ G4VPhysicalVolume* DetectorConstruction::GetPhysicalVolume(const G4String& physV return nullptr; } +void DetectorConstruction::ConstructSDandField() { + const TRestGeant4Metadata& metadata = *fSimulationManager->fRestGeant4Metadata; + vector + sensitiveVolumes; // user submitted sensitive volumes, may not exist or not be physical (be logical) + for (const auto& volume : {metadata.GetSensitiveVolume()}) { + sensitiveVolumes.emplace_back(volume); + } + + if (sensitiveVolumes.empty()) { + return; + } + + set logicalVolumesSelected; + for (const auto& userSensitiveVolume : sensitiveVolumes) { + G4LogicalVolume* logicalVolume = nullptr; + G4VPhysicalVolume* physicalVolume = + G4PhysicalVolumeStore::GetInstance()->GetVolume(userSensitiveVolume, false); + if (!physicalVolume) { + // perhaps user selected a logical volume with this name + logicalVolume = G4LogicalVolumeStore::GetInstance()->GetVolume(userSensitiveVolume, false); + } else { + logicalVolume = physicalVolume->GetLogicalVolume(); + } + if (logicalVolume == nullptr) { + auto logicalVolumes = + metadata.GetGeant4GeometryInfo().GetAllLogicalVolumesMatchingExpression(userSensitiveVolume); + if (logicalVolumes.empty()) { + cout << "Error on sensitive detector setup" << endl; + exit(1); + } else { + for (const auto& logicalVolumeName : logicalVolumes) { + auto logicalVolumeRegex = + G4LogicalVolumeStore::GetInstance()->GetVolume(logicalVolumeName.Data(), false); + logicalVolumesSelected.insert(logicalVolume); + } + continue; + } + } + logicalVolumesSelected.insert(logicalVolume); + } + + G4SDManager* SDManager = G4SDManager::GetSDMpointer(); + + for (G4LogicalVolume* logicalVolume : logicalVolumesSelected) { + auto name = logicalVolume->GetName(); + G4VSensitiveDetector* sensitiveDetector = new SensitiveDetector(fSimulationManager, name); + SDManager->AddNewDetector(sensitiveDetector); + logicalVolume->SetSensitiveDetector(sensitiveDetector); + + auto region = new G4Region(name); + logicalVolume->SetRegion(region); + } +} + void TRestGeant4GeometryInfo::PopulateFromGeant4World(const G4VPhysicalVolume* world) { auto detector = (DetectorConstruction*)G4RunManager::GetRunManager()->GetUserDetectorConstruction(); TRestGeant4Metadata* restG4Metadata = detector->fSimulationManager->fRestGeant4Metadata; diff --git a/src/SensitiveDetector.cxx b/src/SensitiveDetector.cxx new file mode 100644 index 00000000..653011aa --- /dev/null +++ b/src/SensitiveDetector.cxx @@ -0,0 +1,39 @@ + +#include "SensitiveDetector.h" + +#include +#include +#include +#include +#include + +#include "SimulationManager.h" + +using namespace std; + +SensitiveDetector::SensitiveDetector(SimulationManager* simulationManager, const G4String& name) + : fSimulationManager(simulationManager), G4VSensitiveDetector(name) {} + +G4bool SensitiveDetector::ProcessHits(G4Step* step, G4TouchableHistory*) { + // return value will always be ignored, its present for backwards compatibility (I guess) + const bool isGeantino = step->GetTrack()->GetParticleDefinition() == G4Geantino::Definition(); + + if (isGeantino) { + const auto volumeName = (TString)step->GetPreStepPoint()->GetPhysicalVolume()->GetName(); + const auto length = step->GetStepLength() / CLHEP::mm; + fSimulationManager->GetOutputManager()->AddSensitiveEnergy(length, volumeName); + return true; + } else { + auto energy = step->GetTotalEnergyDeposit() / keV; + + if (energy <= 0) { + return true; + } + + const auto volumeName = (TString)step->GetPreStepPoint()->GetPhysicalVolume()->GetName(); + + fSimulationManager->GetOutputManager()->AddSensitiveEnergy(energy, volumeName); + + return true; + } +} \ No newline at end of file diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index c39e3767..67c75fc6 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -91,6 +91,7 @@ void OutputManager::FinishAndSubmitEvent() { if (IsValidEvent()) { size_t numberOfInsertedEvents = fSimulationManager->InsertEvent(fEvent); + cout << "inserted event: " << numberOfInsertedEvents << endl; } UpdateEvent(); } @@ -130,6 +131,14 @@ void OutputManager::RecordStep(const G4Step* step) { fEvent->InsertStep(step, *fSimulationManager->fRestGeant4Metadata); } +void OutputManager::AddSensitiveEnergy(Double_t energy, const char* physicalVolumeName) { + fEvent->AddEnergyToSensitiveVolume(energy); + /* + const TString physicalVolumeNameNew = fSimulationManager->fRestGeant4Metadata->GetGeant4GeometryInfo() + .GetAlternativeNameFromGeant4PhysicalName(physicalVolumeName); + */ +} + // Geant4Lib TRestGeant4Event::TRestGeant4Event(const G4Event* event, const TRestGeant4Metadata& metadata) From 1eca511294cf77e5a2d3ebf5cb04b0c294f059ee Mon Sep 17 00:00:00 2001 From: lobis Date: Tue, 21 Jun 2022 11:02:09 +0200 Subject: [PATCH 008/173] using `size_t` for numbers --- src/SimulationManager.cxx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index 67c75fc6..4136a3fa 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -91,7 +91,6 @@ void OutputManager::FinishAndSubmitEvent() { if (IsValidEvent()) { size_t numberOfInsertedEvents = fSimulationManager->InsertEvent(fEvent); - cout << "inserted event: " << numberOfInsertedEvents << endl; } UpdateEvent(); } From d7c20f8425321b8175124e578a9f485eef9f6b89 Mon Sep 17 00:00:00 2001 From: lobis Date: Tue, 21 Jun 2022 11:38:48 +0200 Subject: [PATCH 009/173] Storing per process energy in TRestGeant4Event --- include/SimulationManager.h | 1 + src/SimulationManager.cxx | 21 ++++++++++++++++++--- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/include/SimulationManager.h b/include/SimulationManager.h index 62ac249a..db936925 100644 --- a/include/SimulationManager.h +++ b/include/SimulationManager.h @@ -58,6 +58,7 @@ class OutputManager { void RecordStep(const G4Step*); void AddSensitiveEnergy(Double_t energy, const char* physicalVolumeName); + void AddEnergyToVolumeForProcess(Double_t energy, const char* volumeName, const char* processName); private: std::unique_ptr fEvent{}; diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index 4136a3fa..4a4d6147 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -138,6 +138,18 @@ void OutputManager::AddSensitiveEnergy(Double_t energy, const char* physicalVolu */ } +void OutputManager::AddEnergyToVolumeForProcess(Double_t energy, const char* volumeName, + const char* processName) { + if (energy <= 0) { + return; + } + fEvent->fTotalDepositedEnergy += energy; + if (fEvent->fEnergyInVolumePerProcess[volumeName].count(processName) == 0) { + fEvent->fEnergyInVolumePerProcess[volumeName][processName] = 0; + } + fEvent->fEnergyInVolumePerProcess[volumeName][processName] += energy; +} + // Geant4Lib TRestGeant4Event::TRestGeant4Event(const G4Event* event, const TRestGeant4Metadata& metadata) @@ -276,7 +288,7 @@ void TRestGeant4Hits::InsertStep(const G4Step* step, TRestGeant4Metadata& metada metadata.fGeant4PhysicsInfo.InsertProcessName(processID, processName); - const auto totalEnergyDeposit = step->GetTotalEnergyDeposit() / CLHEP::keV; + const auto energy = step->GetTotalEnergyDeposit() / CLHEP::keV; const auto trackKineticEnergy = step->GetTrack()->GetKineticEnergy() / CLHEP::keV; auto sensitiveVolumeName = @@ -293,7 +305,7 @@ void TRestGeant4Hits::InsertStep(const G4Step* step, TRestGeant4Metadata& metada Double_t z = aTrack->GetPosition().z() / CLHEP::mm; if (metadata.GetSensitiveVolume() == volumeName) { - // restG4Event->AddEnergyToSensitiveVolume(totalEnergyDeposit); + // restG4Event->AddEnergyToSensitiveVolume(energy); } const TVector3 hitPosition(x, y, z); @@ -302,7 +314,7 @@ void TRestGeant4Hits::InsertStep(const G4Step* step, TRestGeant4Metadata& metada const TVector3 momentumDirection = TVector3(momentum.x(), momentum.y(), momentum.z()).Unit(); // ------- - AddHit(hitPosition, totalEnergyDeposit, hitGlobalTime); // this increases fNHits + AddHit(hitPosition, energy, hitGlobalTime); // this increases fNHits fProcessID.Set(fNHits); fProcessID[fNHits - 1] = processID; @@ -321,4 +333,7 @@ void TRestGeant4Hits::InsertStep(const G4Step* step, TRestGeant4Metadata& metada fMomentumDirectionZ.Set(fNHits); fMomentumDirectionZ[fNHits - 1] = momentumDirection.Z(); + + // ----- + SimulationManager::GetOutputManager()->AddEnergyToVolumeForProcess(energy, volumeName, processName); } From 6e1ec9a70510061645a27bd9df13231d02aaa578 Mon Sep 17 00:00:00 2001 From: lobis Date: Tue, 21 Jun 2022 11:40:31 +0200 Subject: [PATCH 010/173] Simplified installation output --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7185b4aa..a15a8544 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -87,8 +87,8 @@ file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/examples DESTINATION ${CMAKE_CURRENT_BINARY_DIR} ) -install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/examples/ - DESTINATION ./examples/restG4/ +install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/examples + DESTINATION examples/restG4/ COMPONENT install ) From d383bf63e4be0498cc9e01ca1298dad4a89faca8 Mon Sep 17 00:00:00 2001 From: lobis Date: Tue, 21 Jun 2022 12:22:15 +0200 Subject: [PATCH 011/173] Added subevent tag for decays, avoid counting "" as decay in validation --- examples/07.FullChainDecay/Validate.C | 6 +++++- src/SimulationManager.cxx | 19 ++++++------------- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/examples/07.FullChainDecay/Validate.C b/examples/07.FullChainDecay/Validate.C index d01296ec..f6d5e621 100644 --- a/examples/07.FullChainDecay/Validate.C +++ b/examples/07.FullChainDecay/Validate.C @@ -10,7 +10,11 @@ Int_t Validate(const char* filename, Int_t nDaughters) { std::set eventTagsUnique; for (int n = 0; n < run.GetEntries(); n++) { run.GetEntry(n); - eventTagsUnique.insert((string)event->GetSubEventTag()); + const string tag = event->GetSubEventTag().Data(); + if (tag.empty()) { + continue; + } + eventTagsUnique.insert(tag); } cout << "Daughter isotopes: " << eventTagsUnique.size() << endl; diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index 4a4d6147..db92db2e 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -180,24 +180,17 @@ bool TRestGeant4Event::InsertTrack(const G4Track* track) { cout << "fInitialStep does not have exactly one step! Problem with stepping verbose" << endl; exit(1); } + + if (fTrack.empty() && fSubEventID > 0) { + // Add decay particle name as subevent tag + fSubEventTag = track->GetParticleDefinition()->GetParticleName(); + } + fTrack.emplace_back(track); fTrack.back().SetHits(fInitialStep); fTrackIDToTrackIndex[track->GetTrackID()] = fTrack.size() - 1; - if (fTrack.empty()) { - /* - // primary for the sub-event - fSubEventPrimaryParticleName = track->GetParticleDefinition()->GetParticleName(); - fSubEventPrimaryEnergy = track->GetKineticEnergy() / CLHEP::keV; - const auto& position = track->GetPosition(); - fSubEventPrimaryPosition = - TVector3(position.x() / CLHEP::mm, position.y() / CLHEP::mm, position.z() / CLHEP::mm); - const auto& momentum = track->GetMomentumDirection(); - fSubEventPrimaryMomentum = - TVector3(momentum.x() / CLHEP::mm, momentum.y() / CLHEP::mm, momentum.z() / CLHEP::mm); - */ - } return true; } From f9e1a691f8ed90ebb78382d49575eec39228d236 Mon Sep 17 00:00:00 2001 From: lobis Date: Tue, 21 Jun 2022 12:48:45 +0200 Subject: [PATCH 012/173] reverted cmake change --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a15a8544..7185b4aa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -87,8 +87,8 @@ file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/examples DESTINATION ${CMAKE_CURRENT_BINARY_DIR} ) -install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/examples - DESTINATION examples/restG4/ +install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/examples/ + DESTINATION ./examples/restG4/ COMPONENT install ) From 278054161c964efeacb215b34c773201cf2447de Mon Sep 17 00:00:00 2001 From: lobis Date: Tue, 21 Jun 2022 12:58:47 +0200 Subject: [PATCH 013/173] Added missing event origin --- src/SimulationManager.cxx | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index db92db2e..f2213042 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -181,9 +181,18 @@ bool TRestGeant4Event::InsertTrack(const G4Track* track) { exit(1); } - if (fTrack.empty() && fSubEventID > 0) { - // Add decay particle name as subevent tag - fSubEventTag = track->GetParticleDefinition()->GetParticleName(); + if (fTrack.empty()) { + // First track of event (primary) + fPrimaryParticleName.emplace_back(track->GetParticleDefinition()->GetParticleName()); + fPrimaryEventEnergy.emplace_back(track->GetKineticEnergy() / CLHEP::keV); + const auto& position = track->GetPosition(); + fPrimaryEventOrigin = {position.x() / CLHEP::mm, position.y() / CLHEP::mm, position.z() / CLHEP::mm}; + const auto& momentum = track->GetMomentumDirection(); + fPrimaryEventDirection.emplace_back(momentum.x() / CLHEP::mm, momentum.y() / CLHEP::mm, + momentum.z() / CLHEP::mm); + if (fSubEventID > 0) { + fSubEventTag = track->GetParticleDefinition()->GetParticleName(); + } } fTrack.emplace_back(track); From a81a8fce8aad6b84672fe0472fd70e60a947f8ff Mon Sep 17 00:00:00 2001 From: lobis Date: Tue, 21 Jun 2022 13:01:40 +0200 Subject: [PATCH 014/173] Updated reference values of example --- examples/01.NLDBD/Validate.C | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/01.NLDBD/Validate.C b/examples/01.NLDBD/Validate.C index e4df5cfd..d86cbed3 100644 --- a/examples/01.NLDBD/Validate.C +++ b/examples/01.NLDBD/Validate.C @@ -56,19 +56,19 @@ Int_t Validate(const char* filename) { double nEvents = run.GetEntries(); double averageTotalEnergy = 0; - const double averageTotalEnergyRef = (!isReferenceGeant4Version) ? 2280.96 : 2221.55; + const double averageTotalEnergyRef = (!isReferenceGeant4Version) ? 2457.00 : 2221.55; double averageSensitiveEnergy = 0; const double averageSensitiveEnergyRef = (!isReferenceGeant4Version) ? 2280.96 : 2221.55; double averageNumberOfHits = 0; - const double averageNumberOfHitsRef = (!isReferenceGeant4Version) ? 3071.17 : 342.37; + const double averageNumberOfHitsRef = (!isReferenceGeant4Version) ? 5535.16 : 342.37; double averageNumberOfTracks = 0; - const double averageNumberOfTracksRef = (!isReferenceGeant4Version) ? 2161.43 : 10.11; + const double averageNumberOfTracksRef = (!isReferenceGeant4Version) ? 2300 : 10.11; TVector3 averagePosition = {}; - const TVector3 averagePositionRef = (!isReferenceGeant4Version) ? TVector3(-38.8987, 27.5536, 91.3969) + const TVector3 averagePositionRef = (!isReferenceGeant4Version) ? TVector3(-41.4266, 28.2394, 89.3622) : TVector3(-17.8046, -32.5019, -31.8353); const double tolerance = 0.001; From a3932ac7a162ee79a82092b8d2ca54a7e6d93c5a Mon Sep 17 00:00:00 2001 From: lobis Date: Tue, 21 Jun 2022 13:26:43 +0200 Subject: [PATCH 015/173] Updated example ref values --- examples/01.NLDBD/Validate.C | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/01.NLDBD/Validate.C b/examples/01.NLDBD/Validate.C index d86cbed3..b52fa279 100644 --- a/examples/01.NLDBD/Validate.C +++ b/examples/01.NLDBD/Validate.C @@ -56,20 +56,20 @@ Int_t Validate(const char* filename) { double nEvents = run.GetEntries(); double averageTotalEnergy = 0; - const double averageTotalEnergyRef = (!isReferenceGeant4Version) ? 2457.00 : 2221.55; + const double averageTotalEnergyRef = (!isReferenceGeant4Version) ? 2457.00 : 2457.00; double averageSensitiveEnergy = 0; const double averageSensitiveEnergyRef = (!isReferenceGeant4Version) ? 2280.96 : 2221.55; double averageNumberOfHits = 0; - const double averageNumberOfHitsRef = (!isReferenceGeant4Version) ? 5535.16 : 342.37; + const double averageNumberOfHitsRef = (!isReferenceGeant4Version) ? 5535.16 : 361.33; double averageNumberOfTracks = 0; - const double averageNumberOfTracksRef = (!isReferenceGeant4Version) ? 2300 : 10.11; + const double averageNumberOfTracksRef = (!isReferenceGeant4Version) ? 2300 : 10.83; TVector3 averagePosition = {}; const TVector3 averagePositionRef = (!isReferenceGeant4Version) ? TVector3(-41.4266, 28.2394, 89.3622) - : TVector3(-17.8046, -32.5019, -31.8353); + : TVector3(-22.0472, -32.7535, -33.8159); const double tolerance = 0.001; From c8aae98864ca10ee31dbc4c6e096f319ab9b0e06 Mon Sep 17 00:00:00 2001 From: lobis Date: Tue, 21 Jun 2022 13:27:47 +0200 Subject: [PATCH 016/173] Updated reference value for decay (was counting "" as decay) --- .github/workflows/validation.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/validation.yml b/.github/workflows/validation.yml index da4cd212..217ac66e 100644 --- a/.github/workflows/validation.yml +++ b/.github/workflows/validation.yml @@ -478,7 +478,7 @@ jobs: source ${{ env.REST_PATH }}/thisREST.sh cd ${{ env.REST_PATH }}/examples/restG4/07.FullChainDecay/ restG4 fullChain.rml -o Run00001_U238_FullChainDecay.root - restRoot -b -q Validate.C'("Run00001_U238_FullChainDecay.root", 15)' + restRoot -b -q Validate.C'("Run00001_U238_FullChainDecay.root", 14)' restG4 singleDecay.rml -o Run00002_U238_SingleChainDecay.root restRoot -b -q Validate.C'("Run00002_U238_SingleChainDecay.root", 1)' export REST_ISOTOPE=Be7 From dbddf420f85c81370eb165dd1d7551d0f962eaba Mon Sep 17 00:00:00 2001 From: lobis Date: Wed, 22 Jun 2022 11:34:43 +0200 Subject: [PATCH 017/173] Inserted correctly volume ID and hit KE --- examples/01.NLDBD/Validate.C | 2 +- src/DetectorConstruction.cxx | 1 + src/SimulationManager.cxx | 17 ++++------------- 3 files changed, 6 insertions(+), 14 deletions(-) diff --git a/examples/01.NLDBD/Validate.C b/examples/01.NLDBD/Validate.C index b52fa279..8f7c9a73 100644 --- a/examples/01.NLDBD/Validate.C +++ b/examples/01.NLDBD/Validate.C @@ -68,7 +68,7 @@ Int_t Validate(const char* filename) { const double averageNumberOfTracksRef = (!isReferenceGeant4Version) ? 2300 : 10.83; TVector3 averagePosition = {}; - const TVector3 averagePositionRef = (!isReferenceGeant4Version) ? TVector3(-41.4266, 28.2394, 89.3622) + const TVector3 averagePositionRef = (!isReferenceGeant4Version) ? TVector3(-38.8987, 27.5536, 91.3969) : TVector3(-22.0472, -32.7535, -33.8159); const double tolerance = 0.001; diff --git a/src/DetectorConstruction.cxx b/src/DetectorConstruction.cxx index 20d1c16c..26ca358a 100644 --- a/src/DetectorConstruction.cxx +++ b/src/DetectorConstruction.cxx @@ -301,6 +301,7 @@ void TRestGeant4GeometryInfo::PopulateFromGeant4World(const G4VPhysicalVolume* w fLogicalToMaterialMap[nameLogical] = nameMaterial; fLogicalToPhysicalMap[nameLogical].emplace_back(namePhysical); fPhysicalToPositionInWorldMap[namePhysical] = {position.x(), position.y(), position.z()}; + InsertVolumeName(i, namePhysical); if (!fIsAssembly && GetAlternativeNameFromGeant4PhysicalName(namePhysical) != namePhysical) { fIsAssembly = true; diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index f2213042..b0d4332e 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -280,7 +280,7 @@ void TRestGeant4Hits::InsertStep(const G4Step* step, TRestGeant4Metadata& metada const auto process = step->GetPostStepPoint()->GetProcessDefinedStep(); G4String processName = "Init"; G4String processTypeName = "Init"; - G4int processID = -1; + Int_t processID = 0; if (track->GetCurrentStepNumber() != 0) { // 0 = Init step (G4SteppingVerbose) process is not defined for this step processName = process->GetProcessName(); @@ -306,10 +306,6 @@ void TRestGeant4Hits::InsertStep(const G4Step* step, TRestGeant4Metadata& metada Double_t y = aTrack->GetPosition().y() / CLHEP::mm; Double_t z = aTrack->GetPosition().z() / CLHEP::mm; - if (metadata.GetSensitiveVolume() == volumeName) { - // restG4Event->AddEnergyToSensitiveVolume(energy); - } - const TVector3 hitPosition(x, y, z); const Double_t hitGlobalTime = step->GetPreStepPoint()->GetGlobalTime() / CLHEP::second; const G4ThreeVector& momentum = step->GetPreStepPoint()->GetMomentumDirection(); @@ -318,14 +314,9 @@ void TRestGeant4Hits::InsertStep(const G4Step* step, TRestGeant4Metadata& metada // ------- AddHit(hitPosition, energy, hitGlobalTime); // this increases fNHits - fProcessID.Set(fNHits); - fProcessID[fNHits - 1] = processID; - - fVolumeID.Set(fNHits); - fVolumeID[fNHits - 1] = 0; - - fKineticEnergy.Set(fNHits); - fKineticEnergy[fNHits - 1] = 0; + fProcessID.emplace_back(processID); + fVolumeID.emplace_back(geometryInfo.GetIDFromVolume(volumeName)); + fKineticEnergy.emplace_back(step->GetPreStepPoint()->GetKineticEnergy() / CLHEP::keV); fMomentumDirectionX.Set(fNHits); fMomentumDirectionX[fNHits - 1] = momentumDirection.X(); From 98e80f00bbc7ae18247380a3f98a2f7d705d00ff Mon Sep 17 00:00:00 2001 From: lobis Date: Wed, 22 Jun 2022 12:04:32 +0200 Subject: [PATCH 018/173] Added variable for decay logic, no changes --- src/StackingAction.cxx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/StackingAction.cxx b/src/StackingAction.cxx index d68fc680..fe604084 100644 --- a/src/StackingAction.cxx +++ b/src/StackingAction.cxx @@ -25,6 +25,8 @@ StackingAction::StackingAction(SimulationManager* simulationManager) : fSimulati } G4ClassificationOfNewTrack StackingAction::ClassifyNewTrack(const G4Track* track) { + const G4ClassificationOfNewTrack decayClassification = + fSimulationManager->fRestGeant4Metadata->isFullChainActivated() ? fWaiting : fKill; if (track->GetParentID() <= 0) { // always process the first track regardless return fUrgent; @@ -45,10 +47,10 @@ G4ClassificationOfNewTrack StackingAction::ClassifyNewTrack(const G4Track* track if (particle->GetPDGLifeTime() > fMaxAllowedLifetime) { G4String energy = G4BestUnit(track->GetKineticEnergy(), "Energy"); G4String lifeTime = G4BestUnit(particle->GetPDGLifeTime(), "Time"); - - return fSimulationManager->fRestGeant4Metadata->isFullChainActivated() ? fWaiting : fKill; + return decayClassification; } } + return fUrgent; } From 317f3be27bd157b05d5fee27374ff430f99b8106 Mon Sep 17 00:00:00 2001 From: lobis Date: Wed, 22 Jun 2022 12:42:33 +0200 Subject: [PATCH 019/173] Ignoring hits not in active volume --- include/SimulationManager.h | 3 +++ src/SimulationManager.cxx | 15 ++++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/include/SimulationManager.h b/include/SimulationManager.h index db936925..0acdcdc1 100644 --- a/include/SimulationManager.h +++ b/include/SimulationManager.h @@ -60,9 +60,12 @@ class OutputManager { void AddSensitiveEnergy(Double_t energy, const char* physicalVolumeName); void AddEnergyToVolumeForProcess(Double_t energy, const char* volumeName, const char* processName); + inline bool IsActiveVolume(const char* volumeName) const { return fActiveVolumes.count(volumeName) > 0; } + private: std::unique_ptr fEvent{}; SimulationManager* fSimulationManager = nullptr; + std::set fActiveVolumes = {}; friend class StackingAction; }; diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index b0d4332e..5c0ae1b6 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -70,6 +70,12 @@ OutputManager::OutputManager(const SimulationManager* simulationManager) G4cout << "Error in 'OutputManager', this instance should never exist" << endl; exit(1); } + + // initialize active volume lookup set + for (size_t i = 0; i < fSimulationManager->fRestGeant4Metadata->GetNumberOfActiveVolumes(); i++) { + const TString& activeVolume = fSimulationManager->fRestGeant4Metadata->GetActiveVolumeName(i); + fActiveVolumes.insert(activeVolume.Data()); + } } void OutputManager::UpdateEvent() { @@ -143,11 +149,12 @@ void OutputManager::AddEnergyToVolumeForProcess(Double_t energy, const char* vol if (energy <= 0) { return; } - fEvent->fTotalDepositedEnergy += energy; if (fEvent->fEnergyInVolumePerProcess[volumeName].count(processName) == 0) { fEvent->fEnergyInVolumePerProcess[volumeName][processName] = 0; } fEvent->fEnergyInVolumePerProcess[volumeName][processName] += energy; + + fEvent->fTotalDepositedEnergy += energy; } // Geant4Lib @@ -271,6 +278,12 @@ void TRestGeant4Hits::InsertStep(const G4Step* step, TRestGeant4Metadata& metada const auto& volumeName = geometryInfo.GetAlternativeNameFromGeant4PhysicalName( (TString &&) step->GetPreStepPoint()->GetPhysicalVolume()->GetName()); + if (!SimulationManager::GetOutputManager()->IsActiveVolume(volumeName) && + step->GetTrack()->GetCurrentStepNumber() != 0) { + // we always store the first step + return; + } + const auto& particle = step->GetTrack()->GetDefinition(); const auto& particleID = particle->GetPDGEncoding(); const auto& particleName = particle->GetParticleName(); From f75cb08a2f53cc416d3ac7a2cc269add491cb11a Mon Sep 17 00:00:00 2001 From: lobis Date: Wed, 22 Jun 2022 12:46:44 +0200 Subject: [PATCH 020/173] Updated validation with new change of active volumes --- examples/01.NLDBD/Validate.C | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/01.NLDBD/Validate.C b/examples/01.NLDBD/Validate.C index 8f7c9a73..42b7814f 100644 --- a/examples/01.NLDBD/Validate.C +++ b/examples/01.NLDBD/Validate.C @@ -56,13 +56,13 @@ Int_t Validate(const char* filename) { double nEvents = run.GetEntries(); double averageTotalEnergy = 0; - const double averageTotalEnergyRef = (!isReferenceGeant4Version) ? 2457.00 : 2457.00; + const double averageTotalEnergyRef = (!isReferenceGeant4Version) ? 2280.96 : 2221.55; double averageSensitiveEnergy = 0; const double averageSensitiveEnergyRef = (!isReferenceGeant4Version) ? 2280.96 : 2221.55; double averageNumberOfHits = 0; - const double averageNumberOfHitsRef = (!isReferenceGeant4Version) ? 5535.16 : 361.33; + const double averageNumberOfHitsRef = (!isReferenceGeant4Version) ? 5371.17 : 361.33; double averageNumberOfTracks = 0; const double averageNumberOfTracksRef = (!isReferenceGeant4Version) ? 2300 : 10.83; From b4583a1707d96aa4e6dc96b66df03d8eb26158e5 Mon Sep 17 00:00:00 2001 From: lobis Date: Wed, 22 Jun 2022 12:59:07 +0200 Subject: [PATCH 021/173] Updated validation with new change of active volumes for reference G4 --- examples/01.NLDBD/Validate.C | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/01.NLDBD/Validate.C b/examples/01.NLDBD/Validate.C index 42b7814f..a2f96c4c 100644 --- a/examples/01.NLDBD/Validate.C +++ b/examples/01.NLDBD/Validate.C @@ -62,14 +62,14 @@ Int_t Validate(const char* filename) { const double averageSensitiveEnergyRef = (!isReferenceGeant4Version) ? 2280.96 : 2221.55; double averageNumberOfHits = 0; - const double averageNumberOfHitsRef = (!isReferenceGeant4Version) ? 5371.17 : 361.33; + const double averageNumberOfHitsRef = (!isReferenceGeant4Version) ? 5371.17 : 353.2; double averageNumberOfTracks = 0; const double averageNumberOfTracksRef = (!isReferenceGeant4Version) ? 2300 : 10.83; TVector3 averagePosition = {}; const TVector3 averagePositionRef = (!isReferenceGeant4Version) ? TVector3(-38.8987, 27.5536, 91.3969) - : TVector3(-22.0472, -32.7535, -33.8159); + : TVector3(-17.8046, -32.5019, -31.8353); const double tolerance = 0.001; From 46c1e3c9e1d7af75ff02bdba98f56c7ad476f021 Mon Sep 17 00:00:00 2001 From: lobis Date: Wed, 22 Jun 2022 13:21:26 +0200 Subject: [PATCH 022/173] Added example 06 to examples --- test/src/examples.cxx | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/test/src/examples.cxx b/test/src/examples.cxx index bc43cd37..fe787df8 100644 --- a/test/src/examples.cxx +++ b/test/src/examples.cxx @@ -177,6 +177,31 @@ TEST(restG4, Example_05_PandaX) { fs::current_path(originalPath); } +TEST(restG4, Example_06_IonRecoils) { + // cd into example + const auto originalPath = fs::current_path(); + const auto thisExamplePath = examplesPath / "06.IonRecoils"; + fs::current_path(thisExamplePath); + + CommandLineParameters parameters; + parameters.rmlFile = "recoils.rml"; + parameters.outputFile = thisExamplePath / "recoils.root"; + + Application app; + app.Run(parameters); + + // Run validation macro + const TString macro(thisExamplePath / "Validate.C"); + gROOT->ProcessLine(TString::Format(".L %s", macro.Data())); // Load macro + int error = 0; + const int result = + gROOT->ProcessLine(TString::Format("Validate(\"%s\")", parameters.outputFile.Data()), &error); + EXPECT_EQ(error, 0); + EXPECT_EQ(result, 0); + + fs::current_path(originalPath); +} + TEST(restG4, Example_07_Decay_FullChain) { // cd into example const auto originalPath = fs::current_path(); From aaab4a8775b032ac151698f770251bbf5cfb90ae Mon Sep 17 00:00:00 2001 From: lobis Date: Mon, 4 Jul 2022 18:35:00 +0200 Subject: [PATCH 023/173] SimulationManager - inserted references in event and tracks --- src/SimulationManager.cxx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index 5c0ae1b6..5e7aa7b8 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -81,6 +81,7 @@ OutputManager::OutputManager(const SimulationManager* simulationManager) void OutputManager::UpdateEvent() { auto event = G4EventManager::GetEventManager()->GetConstCurrentEvent(); fEvent = make_unique(event, *fSimulationManager->fRestGeant4Metadata); + fEvent->InitializeReferences(fSimulationManager->fRestRun); } bool OutputManager::IsEmptyEvent() const { return !fEvent || fEvent->fTrack.empty(); } @@ -207,6 +208,8 @@ bool TRestGeant4Event::InsertTrack(const G4Track* track) { fTrackIDToTrackIndex[track->GetTrackID()] = fTrack.size() - 1; + fTrack.back().SetEvent(this); + return true; } From 221352900cfd88a9dda20ee3863e9bdb63ad21de Mon Sep 17 00:00:00 2001 From: Luis Obis Date: Wed, 6 Jul 2022 13:32:21 +0200 Subject: [PATCH 024/173] TRestGeant4PhysicsInfo - more tests --- src/SimulationManager.cxx | 6 +++++- test/src/examples.cxx | 11 +++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index a2399b24..5527afbb 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -273,6 +273,10 @@ void TRestGeant4Track::UpdateTrack(const G4Track* track) { // fNumberOfSecondaries = (int)secondaries->size(); } +Int_t TRestGeant4PhysicsInfo::GetProcessIDFromGeant4Process(const G4VProcess* process) { + return process->GetProcessType() * 1000 + process->GetProcessSubType(); +} + void TRestGeant4Hits::InsertStep(const G4Step* step, TRestGeant4Metadata& metadata) { const G4Track* track = step->GetTrack(); @@ -301,7 +305,7 @@ void TRestGeant4Hits::InsertStep(const G4Step* step, TRestGeant4Metadata& metada 0) { // 0 = Init step (G4SteppingVerbose) process is not defined for this step processName = process->GetProcessName(); processTypeName = G4VProcess::GetProcessTypeName(process->GetProcessType()); - processID = process->GetProcessType() * 1000 + process->GetProcessSubType(); + processID = TRestGeant4PhysicsInfo::GetProcessIDFromGeant4Process(process); } metadata.fGeant4PhysicsInfo.InsertProcessName(processID, processName); diff --git a/test/src/examples.cxx b/test/src/examples.cxx index fe787df8..121acba8 100644 --- a/test/src/examples.cxx +++ b/test/src/examples.cxx @@ -121,6 +121,16 @@ TEST(restG4, TRestGeant4GeometryInfo_TRestGeant4PhysicsInfo) { cout << "Printing physics info" << endl; physicsInfo.Print(); + + const auto particles = physicsInfo.GetAllParticles(); + EXPECT_EQ(particles.size() == 2, true); + EXPECT_EQ(particles.count("e-") > 0, true); + EXPECT_EQ(particles.count("gamma") > 0, true); + + const auto processes = physicsInfo.GetAllProcesses(); + EXPECT_EQ(processes.count("Init") > 0, true); + EXPECT_EQ(processes.count("Transportation") > 0, true); + EXPECT_EQ(processes.count("compt") > 0, true); } TEST(restG4, Example_04_Muons) { @@ -178,6 +188,7 @@ TEST(restG4, Example_05_PandaX) { } TEST(restG4, Example_06_IonRecoils) { + GTEST_SKIP_("Not working yet, needs fixing"); // cd into example const auto originalPath = fs::current_path(); const auto thisExamplePath = examplesPath / "06.IonRecoils"; From 474edaa2192f68fa61d5f38c7eef33183f31375d Mon Sep 17 00:00:00 2001 From: Luis Obis Date: Wed, 6 Jul 2022 14:30:00 +0200 Subject: [PATCH 025/173] TRestGeant4Event - added new members to better track subevent info, updated validations --- examples/07.FullChainDecay/Validate.C | 19 ++++++----- src/SimulationManager.cxx | 46 ++++++++++++++++----------- 2 files changed, 36 insertions(+), 29 deletions(-) diff --git a/examples/07.FullChainDecay/Validate.C b/examples/07.FullChainDecay/Validate.C index f6d5e621..f0aa6074 100644 --- a/examples/07.FullChainDecay/Validate.C +++ b/examples/07.FullChainDecay/Validate.C @@ -7,25 +7,24 @@ Int_t Validate(const char* filename, Int_t nDaughters) { TRestGeant4Event* event = run.GetInputEvent(); - std::set eventTagsUnique; + std::set uniqueSubEventPrimaryParticleNames; for (int n = 0; n < run.GetEntries(); n++) { run.GetEntry(n); - const string tag = event->GetSubEventTag().Data(); - if (tag.empty()) { + if (!event->IsSubEvent()) { continue; } - eventTagsUnique.insert(tag); + uniqueSubEventPrimaryParticleNames.insert(event->GetSubEventPrimaryEventParticleName().Data()); } - cout << "Daughter isotopes: " << eventTagsUnique.size() << endl; - for (const auto& tag : eventTagsUnique) { - cout << tag << " "; + cout << "Daughter isotopes: " << uniqueSubEventPrimaryParticleNames.size() << endl; + for (const auto& primary : uniqueSubEventPrimaryParticleNames) { + cout << primary << " "; } cout << endl; - if (eventTagsUnique.size() != nDaughters) { - cout << "Wrong number of isotopes found! " << eventTagsUnique.size() << " vs. reference value of " - << nDaughters << endl; + if (uniqueSubEventPrimaryParticleNames.size() != nDaughters) { + cout << "Wrong number of isotopes found! " << uniqueSubEventPrimaryParticleNames.size() + << " vs. reference value of " << nDaughters << endl; return 1; } diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index 5527afbb..d18c4210 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -84,7 +84,7 @@ void OutputManager::UpdateEvent() { fEvent->InitializeReferences(fSimulationManager->fRestRun); } -bool OutputManager::IsEmptyEvent() const { return !fEvent || fEvent->fTrack.empty(); } +bool OutputManager::IsEmptyEvent() const { return !fEvent || fEvent->fTracks.empty(); } bool OutputManager::IsValidEvent() const { if (IsEmptyEvent()) return false; @@ -109,7 +109,7 @@ void OutputManager::RecordTrack(const G4Track* track) { fEvent->InsertTrack(track); if (fEvent->fSubEventID > 0) { - const auto& lastTrack = fEvent->fTrack.back(); + const auto& lastTrack = fEvent->fTracks.back(); assert(lastTrack.GetTrackID() == track->GetTrackID()); // TODO /* @@ -168,6 +168,17 @@ TRestGeant4Event::TRestGeant4Event(const G4Event* event, const TRestGeant4Metada SetTime((Double_t)system_time); + auto primaryVertex = event->GetPrimaryVertex(); + const auto& position = primaryVertex->GetPosition(); + fPrimaryPosition = {position.x() / CLHEP::mm, position.y() / CLHEP::mm, position.z() / CLHEP::mm}; + for (int i = 0; i < primaryVertex->GetNumberOfParticle(); i++) { + const auto& primaryParticle = primaryVertex->GetPrimary(i); + fPrimaryParticleNames.emplace_back(primaryParticle->GetParticleDefinition()->GetParticleName()); + fPrimaryEnergies.emplace_back(primaryParticle->GetKineticEnergy() / CLHEP::keV); + const auto& momentum = primaryParticle->GetMomentumDirection(); + fPrimaryDirections.emplace_back(momentum.x(), momentum.y(), momentum.z()); + } + // Defining if the hits in a given volume will be stored for (int i = 0; i < metadata.GetNumberOfActiveVolumes(); i++) { if (metadata.GetStorageChance(i) >= 1.00) { @@ -189,31 +200,28 @@ bool TRestGeant4Event::InsertTrack(const G4Track* track) { exit(1); } - if (fTrack.empty()) { - // First track of event (primary) - fPrimaryParticleName.emplace_back(track->GetParticleDefinition()->GetParticleName()); - fPrimaryEventEnergy.emplace_back(track->GetKineticEnergy() / CLHEP::keV); + if (fTracks.empty() && IsSubEvent()) { + // First track of sub-event (primary) + fSubEventPrimaryParticleName = track->GetParticleDefinition()->GetParticleName(); + fSubEventPrimaryEnergy = track->GetKineticEnergy() / CLHEP::keV; const auto& position = track->GetPosition(); - fPrimaryEventOrigin = {position.x() / CLHEP::mm, position.y() / CLHEP::mm, position.z() / CLHEP::mm}; + fSubEventPrimaryPosition = {position.x() / CLHEP::mm, position.y() / CLHEP::mm, + position.z() / CLHEP::mm}; const auto& momentum = track->GetMomentumDirection(); - fPrimaryEventDirection.emplace_back(momentum.x() / CLHEP::mm, momentum.y() / CLHEP::mm, - momentum.z() / CLHEP::mm); - if (fSubEventID > 0) { - fSubEventTag = track->GetParticleDefinition()->GetParticleName(); - } + fSubEventPrimaryDirection = {momentum.x(), momentum.y(), momentum.z()}; } - fTrack.emplace_back(track); - fTrack.back().SetHits(fInitialStep); + fTracks.emplace_back(track); + fTracks.back().SetHits(fInitialStep); - fTrackIDToTrackIndex[track->GetTrackID()] = fTrack.size() - 1; + fTrackIDToTrackIndex[track->GetTrackID()] = fTracks.size() - 1; - fTrack.back().SetEvent(this); + fTracks.back().SetEvent(this); return true; } -void TRestGeant4Event::UpdateTrack(const G4Track* track) { fTrack.back().UpdateTrack(track); } +void TRestGeant4Event::UpdateTrack(const G4Track* track) { fTracks.back().UpdateTrack(track); } void TRestGeant4Event::InsertStep(const G4Step* step, TRestGeant4Metadata& metadata) { if (step->GetTrack()->GetCurrentStepNumber() == 0) { @@ -221,7 +229,7 @@ void TRestGeant4Event::InsertStep(const G4Step* step, TRestGeant4Metadata& metad fInitialStep = TRestGeant4Hits(); fInitialStep.InsertStep(step, metadata); } else { - fTrack.back().InsertStep(step, metadata); + fTracks.back().InsertStep(step, metadata); } } @@ -329,7 +337,7 @@ void TRestGeant4Hits::InsertStep(const G4Step* step, TRestGeant4Metadata& metada const TVector3 hitPosition(x, y, z); const Double_t hitGlobalTime = step->GetPreStepPoint()->GetGlobalTime() / CLHEP::second; const G4ThreeVector& momentum = step->GetPreStepPoint()->GetMomentumDirection(); - const TVector3 momentumDirection = TVector3(momentum.x(), momentum.y(), momentum.z()).Unit(); + const TVector3 momentumDirection = TVector3(momentum.x(), momentum.y(), momentum.z()); // ------- AddHit(hitPosition, energy, hitGlobalTime); // this increases fNHits From 95292b3577818f294a0630f14baae9c77fb83938 Mon Sep 17 00:00:00 2001 From: Luis Obis Date: Wed, 6 Jul 2022 16:59:12 +0200 Subject: [PATCH 026/173] removed metadata injection from constructors --- src/SimulationManager.cxx | 51 +++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 23 deletions(-) diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index d18c4210..d587b081 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -80,7 +80,7 @@ OutputManager::OutputManager(const SimulationManager* simulationManager) void OutputManager::UpdateEvent() { auto event = G4EventManager::GetEventManager()->GetConstCurrentEvent(); - fEvent = make_unique(event, *fSimulationManager->fRestGeant4Metadata); + fEvent = make_unique(event); fEvent->InitializeReferences(fSimulationManager->fRestRun); } @@ -133,9 +133,7 @@ void OutputManager::UpdateTrack(const G4Track* track) { fEvent->UpdateTrack(track); } -void OutputManager::RecordStep(const G4Step* step) { - fEvent->InsertStep(step, *fSimulationManager->fRestGeant4Metadata); -} +void OutputManager::RecordStep(const G4Step* step) { fEvent->InsertStep(step); } void OutputManager::AddSensitiveEnergy(Double_t energy, const char* physicalVolumeName) { fEvent->AddEnergyToSensitiveVolume(energy); @@ -160,8 +158,7 @@ void OutputManager::AddEnergyToVolumeForProcess(Double_t energy, const char* vol // Geant4Lib -TRestGeant4Event::TRestGeant4Event(const G4Event* event, const TRestGeant4Metadata& metadata) - : TRestGeant4Event() { +TRestGeant4Event::TRestGeant4Event(const G4Event* event) : TRestGeant4Event() { SetID(event->GetEventID()); SetOK(true); time_t system_time = time(nullptr); @@ -179,13 +176,17 @@ TRestGeant4Event::TRestGeant4Event(const G4Event* event, const TRestGeant4Metada fPrimaryDirections.emplace_back(momentum.x(), momentum.y(), momentum.z()); } + return; + + // TODO: move this // Defining if the hits in a given volume will be stored - for (int i = 0; i < metadata.GetNumberOfActiveVolumes(); i++) { - if (metadata.GetStorageChance(i) >= 1.00) { + const auto metadata = GetGeant4Metadata(); + for (int i = 0; i < metadata->GetNumberOfActiveVolumes(); i++) { + if (metadata->GetStorageChance(i) >= 1.00) { // ActivateVolumeForStorage(i); } else { Double_t randomNumber = G4UniformRand(); - if (metadata.GetStorageChance(i) >= randomNumber) { + if (metadata->GetStorageChance(i) >= randomNumber) { // ActivateVolumeForStorage(i); } else { DisableVolumeForStorage(i); @@ -213,23 +214,23 @@ bool TRestGeant4Event::InsertTrack(const G4Track* track) { fTracks.emplace_back(track); fTracks.back().SetHits(fInitialStep); + fTracks.back().SetEvent(this); fTrackIDToTrackIndex[track->GetTrackID()] = fTracks.size() - 1; - fTracks.back().SetEvent(this); - return true; } void TRestGeant4Event::UpdateTrack(const G4Track* track) { fTracks.back().UpdateTrack(track); } -void TRestGeant4Event::InsertStep(const G4Step* step, TRestGeant4Metadata& metadata) { +void TRestGeant4Event::InsertStep(const G4Step* step) { if (step->GetTrack()->GetCurrentStepNumber() == 0) { // initial step (from SteppingVerbose) is generated before TrackingAction can insert the first track fInitialStep = TRestGeant4Hits(); - fInitialStep.InsertStep(step, metadata); + fInitialStep.SetEvent(this); + fInitialStep.InsertStep(step); } else { - fTracks.back().InsertStep(step, metadata); + fTracks.back().InsertStep(step); } } @@ -264,9 +265,7 @@ TRestGeant4Track::TRestGeant4Track(const G4Track* track) : TRestGeant4Track() { fTrackOrigin = {trackOrigin.x(), trackOrigin.y(), trackOrigin.z()}; } -void TRestGeant4Track::InsertStep(const G4Step* step, TRestGeant4Metadata& metadata) { - fHits.InsertStep(step, metadata); -} +void TRestGeant4Track::InsertStep(const G4Step* step) { fHits.InsertStep(step); } void TRestGeant4Track::UpdateTrack(const G4Track* track) { if (track->GetTrackID() != fTrackID) { @@ -285,10 +284,16 @@ Int_t TRestGeant4PhysicsInfo::GetProcessIDFromGeant4Process(const G4VProcess* pr return process->GetProcessType() * 1000 + process->GetProcessSubType(); } -void TRestGeant4Hits::InsertStep(const G4Step* step, TRestGeant4Metadata& metadata) { +void TRestGeant4Hits::InsertStep(const G4Step* step) { const G4Track* track = step->GetTrack(); - const auto& geometryInfo = metadata.GetGeant4GeometryInfo(); + TRestGeant4Metadata* metadata = GetGeant4Metadata(); + if (metadata == nullptr) { + cout << "ERROR METADATA IS NULL!" << endl; + exit(1); + } + const auto& geometryInfo = metadata->GetGeant4GeometryInfo(); + // Variables that describe a step are taken. const auto& volumeName = geometryInfo.GetAlternativeNameFromGeant4PhysicalName( (TString &&) step->GetPreStepPoint()->GetPhysicalVolume()->GetName()); @@ -303,7 +308,7 @@ void TRestGeant4Hits::InsertStep(const G4Step* step, TRestGeant4Metadata& metada const auto& particleID = particle->GetPDGEncoding(); const auto& particleName = particle->GetParticleName(); - metadata.fGeant4PhysicsInfo.InsertParticleName(particleID, particleName); + metadata->fGeant4PhysicsInfo.InsertParticleName(particleID, particleName); const auto process = step->GetPostStepPoint()->GetProcessDefinedStep(); G4String processName = "Init"; @@ -316,16 +321,16 @@ void TRestGeant4Hits::InsertStep(const G4Step* step, TRestGeant4Metadata& metada processID = TRestGeant4PhysicsInfo::GetProcessIDFromGeant4Process(process); } - metadata.fGeant4PhysicsInfo.InsertProcessName(processID, processName); + metadata->fGeant4PhysicsInfo.InsertProcessName(processID, processName); const auto energy = step->GetTotalEnergyDeposit() / CLHEP::keV; const auto trackKineticEnergy = step->GetTrack()->GetKineticEnergy() / CLHEP::keV; auto sensitiveVolumeName = - geometryInfo.GetAlternativeNameFromGeant4PhysicalName(metadata.GetSensitiveVolume()); + geometryInfo.GetAlternativeNameFromGeant4PhysicalName(metadata->GetSensitiveVolume()); if (particle->GetParticleName() == "geantino" && sensitiveVolumeName.Data() == volumeName) { - metadata.SetSaveAllEvents(true); + metadata->SetSaveAllEvents(true); } G4Track* aTrack = step->GetTrack(); From 8f0269fafdc43244e15307c90651a8bcdffd4a9a Mon Sep 17 00:00:00 2001 From: Luis Obis Date: Wed, 6 Jul 2022 17:08:23 +0200 Subject: [PATCH 027/173] updating decay validation to include primary decaying particle too --- .github/workflows/validation.yml | 2 +- examples/07.FullChainDecay/Validate.C | 15 ++++++++------- test/src/examples.cxx | 2 +- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/.github/workflows/validation.yml b/.github/workflows/validation.yml index 217ac66e..da4cd212 100644 --- a/.github/workflows/validation.yml +++ b/.github/workflows/validation.yml @@ -478,7 +478,7 @@ jobs: source ${{ env.REST_PATH }}/thisREST.sh cd ${{ env.REST_PATH }}/examples/restG4/07.FullChainDecay/ restG4 fullChain.rml -o Run00001_U238_FullChainDecay.root - restRoot -b -q Validate.C'("Run00001_U238_FullChainDecay.root", 14)' + restRoot -b -q Validate.C'("Run00001_U238_FullChainDecay.root", 15)' restG4 singleDecay.rml -o Run00002_U238_SingleChainDecay.root restRoot -b -q Validate.C'("Run00002_U238_SingleChainDecay.root", 1)' export REST_ISOTOPE=Be7 diff --git a/examples/07.FullChainDecay/Validate.C b/examples/07.FullChainDecay/Validate.C index f0aa6074..ab452444 100644 --- a/examples/07.FullChainDecay/Validate.C +++ b/examples/07.FullChainDecay/Validate.C @@ -7,23 +7,24 @@ Int_t Validate(const char* filename, Int_t nDaughters) { TRestGeant4Event* event = run.GetInputEvent(); - std::set uniqueSubEventPrimaryParticleNames; + std::set uniqueDecayingParticleNames; for (int n = 0; n < run.GetEntries(); n++) { run.GetEntry(n); if (!event->IsSubEvent()) { - continue; + uniqueDecayingParticleNames.insert(event->GetPrimaryEventParticleName().Data()); + } else { + uniqueDecayingParticleNames.insert(event->GetSubEventPrimaryEventParticleName().Data()); } - uniqueSubEventPrimaryParticleNames.insert(event->GetSubEventPrimaryEventParticleName().Data()); } - cout << "Daughter isotopes: " << uniqueSubEventPrimaryParticleNames.size() << endl; - for (const auto& primary : uniqueSubEventPrimaryParticleNames) { + cout << "Decaying isotopes: " << uniqueDecayingParticleNames.size() << endl; + for (const auto& primary : uniqueDecayingParticleNames) { cout << primary << " "; } cout << endl; - if (uniqueSubEventPrimaryParticleNames.size() != nDaughters) { - cout << "Wrong number of isotopes found! " << uniqueSubEventPrimaryParticleNames.size() + if (uniqueDecayingParticleNames.size() != nDaughters) { + cout << "Wrong number of isotopes found! " << uniqueDecayingParticleNames.size() << " vs. reference value of " << nDaughters << endl; return 1; } diff --git a/test/src/examples.cxx b/test/src/examples.cxx index 121acba8..ed2563df 100644 --- a/test/src/examples.cxx +++ b/test/src/examples.cxx @@ -241,7 +241,7 @@ TEST(restG4, Example_07_Decay_FullChain) { gROOT->ProcessLine(TString::Format(".L %s", macro.Data())); // Load macro int error = 0; const int result = - gROOT->ProcessLine(TString::Format("Validate(\"%s\", %d)", parameters.outputFile.Data(), 16), &error); + gROOT->ProcessLine(TString::Format("Validate(\"%s\", %d)", parameters.outputFile.Data(), 17), &error); EXPECT_EQ(error, 0); EXPECT_EQ(result, 0); From 41b01cb5285db1c037ac026c9cce3243a4663b9d Mon Sep 17 00:00:00 2001 From: Luis Obis Date: Wed, 6 Jul 2022 17:22:27 +0200 Subject: [PATCH 028/173] fixed decay validation --- .github/workflows/validation.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/validation.yml b/.github/workflows/validation.yml index da4cd212..b4f2a2c8 100644 --- a/.github/workflows/validation.yml +++ b/.github/workflows/validation.yml @@ -269,7 +269,7 @@ jobs: source ${{ env.REST_PATH }}/thisREST.sh cd ${{ env.REST_PATH }}/examples/restG4/07.FullChainDecay/ restG4 fullChain.rml -o Run00001_U238_FullChainDecay.root - restRoot -b -q Validate.C'("Run00001_U238_FullChainDecay.root", 16)' + restRoot -b -q Validate.C'("Run00001_U238_FullChainDecay.root", 17)' restG4 singleDecay.rml -o Run00002_U238_SingleChainDecay.root restRoot -b -q Validate.C'("Run00002_U238_SingleChainDecay.root", 1)' export REST_ISOTOPE=Be7 From b57b08e41ae1d9b7e27c51d035b81998a7b12e53 Mon Sep 17 00:00:00 2001 From: Luis Obis <35803280+lobis@users.noreply.github.com> Date: Wed, 6 Jul 2022 17:25:48 +0200 Subject: [PATCH 029/173] Update validation.yml --- .github/workflows/validation.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/validation.yml b/.github/workflows/validation.yml index da4cd212..b4f2a2c8 100644 --- a/.github/workflows/validation.yml +++ b/.github/workflows/validation.yml @@ -269,7 +269,7 @@ jobs: source ${{ env.REST_PATH }}/thisREST.sh cd ${{ env.REST_PATH }}/examples/restG4/07.FullChainDecay/ restG4 fullChain.rml -o Run00001_U238_FullChainDecay.root - restRoot -b -q Validate.C'("Run00001_U238_FullChainDecay.root", 16)' + restRoot -b -q Validate.C'("Run00001_U238_FullChainDecay.root", 17)' restG4 singleDecay.rml -o Run00002_U238_SingleChainDecay.root restRoot -b -q Validate.C'("Run00002_U238_SingleChainDecay.root", 1)' export REST_ISOTOPE=Be7 From 4ef91b6c63c68e047dd2e4d0b8b2fc308df63e27 Mon Sep 17 00:00:00 2001 From: lobis Date: Thu, 7 Jul 2022 10:38:35 +0200 Subject: [PATCH 030/173] using G4RunManagerFactory --- src/Application.cxx | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/Application.cxx b/src/Application.cxx index 341d52ac..1f953672 100644 --- a/src/Application.cxx +++ b/src/Application.cxx @@ -12,6 +12,7 @@ #include #include +#include #include #include #include @@ -128,7 +129,16 @@ void Application::Run(const CommandLineParameters& commandLineParameters) { G4VSteppingVerbose::SetInstance(new SteppingVerbose(fSimulationManager)); - auto runManager = new G4RunManager; + auto runManagerType = G4RunManagerType::Default; + if (commandLineParameters.serialMode) { + runManagerType = G4RunManagerType::SerialOnly; + cout << "Using serial run manager" << endl; + } else { + runManagerType = G4RunManagerType::MTOnly; + cout << "Using MT run manager" << endl; + } + + auto runManager = G4RunManagerFactory::CreateRunManager(runManagerType); auto detector = new DetectorConstruction(fSimulationManager); From 3c3c10819076f389d1c9a29039a965ec6d24f72a Mon Sep 17 00:00:00 2001 From: lobis Date: Thu, 7 Jul 2022 10:45:23 +0200 Subject: [PATCH 031/173] updated MT logic --- src/Application.cxx | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/Application.cxx b/src/Application.cxx index 1f953672..a21df9b4 100644 --- a/src/Application.cxx +++ b/src/Application.cxx @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -130,16 +131,21 @@ void Application::Run(const CommandLineParameters& commandLineParameters) { G4VSteppingVerbose::SetInstance(new SteppingVerbose(fSimulationManager)); auto runManagerType = G4RunManagerType::Default; - if (commandLineParameters.serialMode) { + if (!commandLineParameters.serialMode) { + runManagerType = G4RunManagerType::MTOnly; + cout << "Using MT run manager with " << commandLineParameters.nThreads << " threads" << endl; + } else { runManagerType = G4RunManagerType::SerialOnly; cout << "Using serial run manager" << endl; - } else { - runManagerType = G4RunManagerType::MTOnly; - cout << "Using MT run manager" << endl; } auto runManager = G4RunManagerFactory::CreateRunManager(runManagerType); + if (!commandLineParameters.serialMode) { + ROOT::EnableThreadSafety(); + runManager->SetNumberOfThreads(commandLineParameters.nThreads); + } + auto detector = new DetectorConstruction(fSimulationManager); runManager->SetUserInitialization(detector); From ded49ff47ae1df2172f4b2ef5349f6c5426b93bd Mon Sep 17 00:00:00 2001 From: lobis Date: Thu, 7 Jul 2022 10:59:28 +0200 Subject: [PATCH 032/173] cleaned UI command logic --- src/Application.cxx | 47 +++++++++++---------------------------------- 1 file changed, 11 insertions(+), 36 deletions(-) diff --git a/src/Application.cxx b/src/Application.cxx index a21df9b4..fe9c2070 100644 --- a/src/Application.cxx +++ b/src/Application.cxx @@ -49,9 +49,7 @@ void Application::Run(const CommandLineParameters& commandLineParameters) { Bool_t saveAllEvents; - Int_t nEvents; - - auto timeStart = chrono::steady_clock::now(); + const auto timeStart = chrono::steady_clock::now(); const auto originalDirectory = filesystem::current_path(); @@ -60,7 +58,7 @@ void Application::Run(const CommandLineParameters& commandLineParameters) { CommandLineSetup::Print(commandLineParameters); /// Separating relative path and pure RML filename - char* inputConfigFile = const_cast(commandLineParameters.rmlFile.Data()); + const char* inputConfigFile = const_cast(commandLineParameters.rmlFile.Data()); if (!TRestTools::CheckFileIsAccessible(inputConfigFile)) { cout << "Input rml file: " << inputConfigFile << " not found, please check file name" << endl; @@ -167,27 +165,22 @@ void Application::Run(const CommandLineParameters& commandLineParameters) { visManager->Initialize(); #endif - nEvents = fSimulationManager->fRestGeant4Metadata->GetNumberOfEvents(); + const auto nEvents = fSimulationManager->fRestGeant4Metadata->GetNumberOfEvents(); + if (nEvents < 0) { + cout << "Error: \"nEvents\" parameter value (" << nEvents << ") is not valid." << endl; + exit(1); + } time_t systime = time(nullptr); fSimulationManager->fRestRun->SetStartTimeStamp((Double_t)systime); - cout << "Number of events : " << nEvents << endl; + cout << "Number of events: " << nEvents << endl; if (nEvents > 0) // batch mode { - G4String command = "/tracking/verbose 0"; - UI->ApplyCommand(command); - command = "/run/initialize"; - UI->ApplyCommand(command); - - char tmp[256]; - sprintf(tmp, "/run/beamOn %d", nEvents); - - command = tmp; - UI->ApplyCommand(command); - + UI->ApplyCommand("/tracking/verbose 0"); + UI->ApplyCommand("/run/initialize"); + UI->ApplyCommand("/run/beamOn " + to_string(nEvents)); fSimulationManager->fRestRun->GetOutputFile()->cd(); - } else if (nEvents == 0) // define visualization and UI terminal for interactive mode @@ -204,24 +197,6 @@ void Application::Run(const CommandLineParameters& commandLineParameters) { #endif } - else // nEvents == -1 - { - cout << "++++++++++ ERROR +++++++++" << endl; - cout << "++++++++++ ERROR +++++++++" << endl; - cout << "++++++++++ ERROR +++++++++" << endl; - cout << "The number of events to be simulated was not recognized properly!" << endl; - cout << "Make sure you did not forget the number of events entry in TRestGeant4Metadata." << endl; - cout << endl; - cout << " ... or the parameter is properly constructed/interpreted." << endl; - cout << endl; - cout << "It should be something like : " << endl; - cout << endl; - cout << R"( )" << endl; - cout << "++++++++++ ERROR +++++++++" << endl; - cout << "++++++++++ ERROR +++++++++" << endl; - cout << "++++++++++ ERROR +++++++++" << endl; - cout << endl; - } fSimulationManager->fRestRun->GetOutputFile()->cd(); #ifdef G4VIS_USE From f9de5962ca123327b5a30e0354eb0739516ba633 Mon Sep 17 00:00:00 2001 From: lobis Date: Thu, 7 Jul 2022 11:07:46 +0200 Subject: [PATCH 033/173] fix MT initialization --- src/ActionInitialization.cxx | 2 ++ src/RunAction.cxx | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ActionInitialization.cxx b/src/ActionInitialization.cxx index 9a992742..82a6862d 100644 --- a/src/ActionInitialization.cxx +++ b/src/ActionInitialization.cxx @@ -80,6 +80,8 @@ void ActionInitialization::Build() const { primaryGenerator->SetAngularDistribution(&(fSimulationManager->initialAngularDistribution)); } + fSimulationManager->InitializeOutputManager(); + SetUserAction(primaryGenerator); SetUserAction(new RunAction(fSimulationManager)); SetUserAction(new EventAction(fSimulationManager)); diff --git a/src/RunAction.cxx b/src/RunAction.cxx index 0592cdb4..b7b8ee7a 100644 --- a/src/RunAction.cxx +++ b/src/RunAction.cxx @@ -31,7 +31,6 @@ void RunAction::BeginOfRunAction(const G4Run*) { auto steppingVerbose = ((SteppingVerbose*)G4VSteppingVerbose::GetInstance()); steppingVerbose->SetSteppingVerbose(1); - fSimulationManager->InitializeOutputManager(); // inform the runManager to save random number seed G4RunManager::GetRunManager()->SetRandomNumberStore(false); } From 2fce67941f04040fbe459d0c34964e348369b8de Mon Sep 17 00:00:00 2001 From: lobis Date: Thu, 7 Jul 2022 12:30:35 +0200 Subject: [PATCH 034/173] Compatibility with older versions --- src/Application.cxx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Application.cxx b/src/Application.cxx index fe9c2070..3c6f4d89 100644 --- a/src/Application.cxx +++ b/src/Application.cxx @@ -13,7 +13,9 @@ #include #include +#ifndef GEANT4_WITHOUT_G4RunManagerFactory #include +#endif #include #include #include @@ -128,6 +130,7 @@ void Application::Run(const CommandLineParameters& commandLineParameters) { G4VSteppingVerbose::SetInstance(new SteppingVerbose(fSimulationManager)); +#ifndef GEANT4_WITHOUT_G4RunManagerFactory auto runManagerType = G4RunManagerType::Default; if (!commandLineParameters.serialMode) { runManagerType = G4RunManagerType::MTOnly; @@ -143,6 +146,10 @@ void Application::Run(const CommandLineParameters& commandLineParameters) { ROOT::EnableThreadSafety(); runManager->SetNumberOfThreads(commandLineParameters.nThreads); } +#else + cout << "Using serial run manager" << endl; + auto runManager = new G4RunManager(); +#endif auto detector = new DetectorConstruction(fSimulationManager); From 1d8a5b218be12a4204ace6752aa1e9d40c5ce4d0 Mon Sep 17 00:00:00 2001 From: lobis Date: Thu, 7 Jul 2022 14:24:54 +0200 Subject: [PATCH 035/173] Multithreading example --- src/RunAction.cxx | 11 +++++++---- test/src/examples.cxx | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/src/RunAction.cxx b/src/RunAction.cxx index b7b8ee7a..186f85ec 100644 --- a/src/RunAction.cxx +++ b/src/RunAction.cxx @@ -38,8 +38,11 @@ void RunAction::BeginOfRunAction(const G4Run*) { void RunAction::EndOfRunAction(const G4Run*) { TRestRun* restRun = fSimulationManager->fRestRun; - G4cout << "============================= Run Summary =============================" << endl; - G4cout << restRun->GetEntries() << " events stored out of " - << G4RunManager::GetRunManager()->GetNumberOfEventsToBeProcessed() << " simulated events" << endl; - G4cout << "=======================================================================" << endl; + if (G4Threading::IsMasterThread() || !G4Threading::IsMultithreadedApplication()) { + G4cout << "============================= Run Summary =============================" << endl; + G4cout << restRun->GetEntries() << " events stored out of " + << G4RunManager::GetRunManager()->GetNumberOfEventsToBeProcessed() << " simulated events" + << endl; + G4cout << "=======================================================================" << endl; + } } diff --git a/test/src/examples.cxx b/test/src/examples.cxx index ed2563df..467dbf06 100644 --- a/test/src/examples.cxx +++ b/test/src/examples.cxx @@ -162,6 +162,38 @@ TEST(restG4, Example_04_Muons) { cout << "Number of entries: " << run.GetEntries() << endl; } +TEST(restG4, Example_04_Muons_MT) { + // cd into example + const auto originalPath = fs::current_path(); + const auto thisExamplePath = examplesPath / "04.MuonScan"; + fs::current_path(thisExamplePath); + + CommandLineParameters parameters; + parameters.rmlFile = "CosmicMuonsFromWall.rml"; + parameters.outputFile = thisExamplePath / "muons.root"; // TODO: fix not working with local path + + parameters.nThreads = 4; + parameters.serialMode = false; + + Application app; + app.Run(parameters); + + // Run validation macro + const TString macro(thisExamplePath / "ValidateWall.C"); + gROOT->ProcessLine(TString::Format(".L %s", macro.Data())); // Load macro + int error = 0; + const int result = + gROOT->ProcessLine(TString::Format("ValidateWall(\"%s\")", parameters.outputFile.Data()), &error); + EXPECT_EQ(error, 0); + EXPECT_EQ(result, 0); + + fs::current_path(originalPath); + + // use output file to check additional things + TRestRun run(parameters.outputFile.Data()); + cout << "Number of entries: " << run.GetEntries() << endl; +} + TEST(restG4, Example_05_PandaX) { // cd into example const auto originalPath = fs::current_path(); From 746f3e6123bc95d9a309f58113023a27e6324dc6 Mon Sep 17 00:00:00 2001 From: lobis Date: Thu, 7 Jul 2022 19:57:45 +0200 Subject: [PATCH 036/173] storing momentum as TVector3 --- src/SimulationManager.cxx | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index d587b081..7eb68152 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -342,24 +342,13 @@ void TRestGeant4Hits::InsertStep(const G4Step* step) { const TVector3 hitPosition(x, y, z); const Double_t hitGlobalTime = step->GetPreStepPoint()->GetGlobalTime() / CLHEP::second; const G4ThreeVector& momentum = step->GetPreStepPoint()->GetMomentumDirection(); - const TVector3 momentumDirection = TVector3(momentum.x(), momentum.y(), momentum.z()); - // ------- AddHit(hitPosition, energy, hitGlobalTime); // this increases fNHits fProcessID.emplace_back(processID); fVolumeID.emplace_back(geometryInfo.GetIDFromVolume(volumeName)); fKineticEnergy.emplace_back(step->GetPreStepPoint()->GetKineticEnergy() / CLHEP::keV); + fMomentumDirection.emplace_back(momentum.x(), momentum.y(), momentum.z()); - fMomentumDirectionX.Set(fNHits); - fMomentumDirectionX[fNHits - 1] = momentumDirection.X(); - - fMomentumDirectionY.Set(fNHits); - fMomentumDirectionY[fNHits - 1] = momentumDirection.Y(); - - fMomentumDirectionZ.Set(fNHits); - fMomentumDirectionZ[fNHits - 1] = momentumDirection.Z(); - - // ----- SimulationManager::GetOutputManager()->AddEnergyToVolumeForProcess(energy, volumeName, processName); } From 3ede16a60ac217b3801e90ecd8e6ebf4e8373957 Mon Sep 17 00:00:00 2001 From: lobis Date: Thu, 7 Jul 2022 20:18:33 +0200 Subject: [PATCH 037/173] Added track length on stepping action --- src/SimulationManager.cxx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index 7eb68152..318d136e 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -350,5 +350,7 @@ void TRestGeant4Hits::InsertStep(const G4Step* step) { fKineticEnergy.emplace_back(step->GetPreStepPoint()->GetKineticEnergy() / CLHEP::keV); fMomentumDirection.emplace_back(momentum.x(), momentum.y(), momentum.z()); + fTrack->IncreaseTrackLength(step->GetStepLength() / CLHEP::mm); + SimulationManager::GetOutputManager()->AddEnergyToVolumeForProcess(energy, volumeName, processName); } From e7d10edda7f74ad3001c751783375c297f5bc7b8 Mon Sep 17 00:00:00 2001 From: lobis Date: Thu, 7 Jul 2022 20:35:41 +0200 Subject: [PATCH 038/173] TRestGeant4Track: added secondaries --- include/SteppingAction.h | 2 ++ src/SimulationManager.cxx | 20 +++++++++++--------- src/SteppingAction.cxx | 5 +++++ 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/include/SteppingAction.h b/include/SteppingAction.h index da9772c2..84425dee 100644 --- a/include/SteppingAction.h +++ b/include/SteppingAction.h @@ -20,6 +20,8 @@ class SteppingAction : public G4UserSteppingAction { void UserSteppingAction(const G4Step*) override; + std::vector* GetSecondaries() const; + private: SimulationManager* fSimulationManager; }; diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index 318d136e..26b0a678 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -7,6 +7,8 @@ #include #include +#include "SteppingAction.h" + using namespace std; thread_local OutputManager* SimulationManager::fOutputManager = nullptr; @@ -275,9 +277,12 @@ void TRestGeant4Track::UpdateTrack(const G4Track* track) { fTrackLength = track->GetTrackLength() / CLHEP::mm; - // auto steppingAction = (SteppingAction*)G4EventManager::GetEventManager()->GetUserSteppingAction(); - // auto secondaries = steppingAction->GetfSecondary(); - // fNumberOfSecondaries = (int)secondaries->size(); + auto steppingAction = (SteppingAction*)G4EventManager::GetEventManager()->GetUserSteppingAction(); + const auto secondaries = steppingAction->GetSecondaries(); + + for (const auto& track : *secondaries) { + fSecondaryTrackIDs.emplace_back(track->GetTrackID()); + } } Int_t TRestGeant4PhysicsInfo::GetProcessIDFromGeant4Process(const G4VProcess* process) { @@ -288,10 +293,7 @@ void TRestGeant4Hits::InsertStep(const G4Step* step) { const G4Track* track = step->GetTrack(); TRestGeant4Metadata* metadata = GetGeant4Metadata(); - if (metadata == nullptr) { - cout << "ERROR METADATA IS NULL!" << endl; - exit(1); - } + const auto& geometryInfo = metadata->GetGeant4GeometryInfo(); // Variables that describe a step are taken. @@ -314,8 +316,8 @@ void TRestGeant4Hits::InsertStep(const G4Step* step) { G4String processName = "Init"; G4String processTypeName = "Init"; Int_t processID = 0; - if (track->GetCurrentStepNumber() != - 0) { // 0 = Init step (G4SteppingVerbose) process is not defined for this step + if (track->GetCurrentStepNumber() != 0) { + // 0 = Init step (G4SteppingVerbose) process is not defined for this step processName = process->GetProcessName(); processTypeName = G4VProcess::GetProcessTypeName(process->GetProcessType()); processID = TRestGeant4PhysicsInfo::GetProcessIDFromGeant4Process(process); diff --git a/src/SteppingAction.cxx b/src/SteppingAction.cxx index 9d1d4bac..cf4422a5 100644 --- a/src/SteppingAction.cxx +++ b/src/SteppingAction.cxx @@ -25,3 +25,8 @@ SteppingAction::~SteppingAction() {} void SteppingAction::UserSteppingAction(const G4Step* step) { fSimulationManager->GetOutputManager()->RecordStep(step); } + +vector* SteppingAction::GetSecondaries() const { + G4SteppingManager* steppingManager = fpSteppingManager; + return steppingManager->GetfSecondary(); +} From 6d624c2c4933e75e09114cba7a766fadde3c4091 Mon Sep 17 00:00:00 2001 From: lobis Date: Thu, 7 Jul 2022 21:01:13 +0200 Subject: [PATCH 039/173] track secondaries: Adding protection for nullptr --- src/PrimaryGeneratorAction.cxx | 13 +++++++++---- src/SimulationManager.cxx | 7 ++++--- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/PrimaryGeneratorAction.cxx b/src/PrimaryGeneratorAction.cxx index 4a3c715e..c3851d51 100644 --- a/src/PrimaryGeneratorAction.cxx +++ b/src/PrimaryGeneratorAction.cxx @@ -179,7 +179,6 @@ G4ParticleDefinition* PrimaryGeneratorAction::SetParticleDefinition(Int_t n, TRe void PrimaryGeneratorAction::SetParticleDirection(Int_t n, TRestGeant4Particle p) { auto simulationManager = fSimulationManager; - TRestRun* restRun = simulationManager->fRestRun; TRestGeant4Metadata* restG4Metadata = simulationManager->fRestGeant4Metadata; G4ThreeVector direction; @@ -316,7 +315,6 @@ void PrimaryGeneratorAction::SetParticleDirection(Int_t n, TRestGeant4Particle p void PrimaryGeneratorAction::SetParticleEnergy(Int_t n, TRestGeant4Particle p) { auto simulationManager = fSimulationManager; - TRestRun* restRun = simulationManager->fRestRun; TRestGeant4Metadata* restG4Metadata = simulationManager->fRestGeant4Metadata; Double_t energy = 0; @@ -400,7 +398,6 @@ void PrimaryGeneratorAction::SetParticleEnergy(Int_t n, TRestGeant4Particle p) { void PrimaryGeneratorAction::SetParticlePosition() { auto simulationManager = fSimulationManager; - TRestRun* restRun = simulationManager->fRestRun; TRestGeant4Metadata* restG4Metadata = simulationManager->fRestGeant4Metadata; double x = 0, y = 0, z = 0; @@ -497,7 +494,6 @@ G4ThreeVector PrimaryGeneratorAction::GetIsotropicVector() { return G4ThreeVector(a, b, c); } -// Double_t PrimaryGeneratorAction::GetAngle(G4ThreeVector x, G4ThreeVector y) { Double_t angle = y.angle(x); @@ -538,6 +534,7 @@ void PrimaryGeneratorAction::GenPositionOnGDMLVolume(double& x, double& y, doubl y = y + fDetector->GetGeneratorTranslation().y(); z = z + fDetector->GetGeneratorTranslation().z(); } + void PrimaryGeneratorAction::GenPositionOnGDMLSurface(double& x, double& y, double& z) { // TODO there is a problem, probably with G4 function GetPointOnSurface // It produces a point on the surface but it is not uniformly distributed @@ -553,6 +550,7 @@ void PrimaryGeneratorAction::GenPositionOnGDMLSurface(double& x, double& y, doub y = y + fDetector->GetGeneratorTranslation().y(); z = z + fDetector->GetGeneratorTranslation().z(); } + void PrimaryGeneratorAction::GenPositionOnBoxVolume(double& x, double& y, double& z) { TRestGeant4Metadata* restG4Metadata = fSimulationManager->fRestGeant4Metadata; @@ -576,14 +574,17 @@ void PrimaryGeneratorAction::GenPositionOnBoxVolume(double& x, double& y, double y = rndPos.y() + center.Y(); z = rndPos.z() + center.Z(); } + void PrimaryGeneratorAction::GenPositionOnBoxSurface(double& x, double& y, double& z) { cout << __PRETTY_FUNCTION__ << ": not implemented!" << endl; abort(); } + void PrimaryGeneratorAction::GenPositionOnSphereVolume(double& x, double& y, double& z) { cout << __PRETTY_FUNCTION__ << ": not implemented!" << endl; abort(); } + void PrimaryGeneratorAction::GenPositionOnSphereSurface(double& x, double& y, double& z) { TRestGeant4Metadata* restG4Metadata = fSimulationManager->fRestGeant4Metadata; @@ -597,10 +598,12 @@ void PrimaryGeneratorAction::GenPositionOnSphereSurface(double& x, double& y, do y = radius * rndPos.y() + center.Y(); z = radius * rndPos.z() + center.Z(); } + void PrimaryGeneratorAction::GenPositionOnCylinderVolume(double& x, double& y, double& z) { cout << __PRETTY_FUNCTION__ << ": not implemented!" << endl; abort(); } + void PrimaryGeneratorAction::GenPositionOnCylinderSurface(double& x, double& y, double& z) { TRestGeant4Metadata* restG4Metadata = fSimulationManager->fRestGeant4Metadata; @@ -625,6 +628,7 @@ void PrimaryGeneratorAction::GenPositionOnCylinderSurface(double& x, double& y, y = rndPos.y() + center.Y(); z = rndPos.z() + center.Z(); } + void PrimaryGeneratorAction::GenPositionOnPoint(double& x, double& y, double& z) { TRestGeant4Metadata* restG4Metadata = fSimulationManager->fRestGeant4Metadata; @@ -634,6 +638,7 @@ void PrimaryGeneratorAction::GenPositionOnPoint(double& x, double& y, double& z) y = position.Y(); z = position.Z(); } + void PrimaryGeneratorAction::GenPositionOnWall(double& x, double& y, double& z) { TRestGeant4Metadata* restG4Metadata = fSimulationManager->fRestGeant4Metadata; diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index 26b0a678..7726db9b 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -279,9 +279,10 @@ void TRestGeant4Track::UpdateTrack(const G4Track* track) { auto steppingAction = (SteppingAction*)G4EventManager::GetEventManager()->GetUserSteppingAction(); const auto secondaries = steppingAction->GetSecondaries(); - - for (const auto& track : *secondaries) { - fSecondaryTrackIDs.emplace_back(track->GetTrackID()); + if (secondaries != nullptr) { + for (const auto& track : *secondaries) { + fSecondaryTrackIDs.emplace_back(track->GetTrackID()); + } } } From f9741459b4c6fe1c5b6efc33a3b4cbcc556abe05 Mon Sep 17 00:00:00 2001 From: lobis Date: Thu, 7 Jul 2022 21:17:27 +0200 Subject: [PATCH 040/173] fix segfault --- src/SimulationManager.cxx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index 7726db9b..ebd1dd3d 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -279,10 +279,8 @@ void TRestGeant4Track::UpdateTrack(const G4Track* track) { auto steppingAction = (SteppingAction*)G4EventManager::GetEventManager()->GetUserSteppingAction(); const auto secondaries = steppingAction->GetSecondaries(); - if (secondaries != nullptr) { - for (const auto& track : *secondaries) { - fSecondaryTrackIDs.emplace_back(track->GetTrackID()); - } + for (const auto& track : *secondaries) { + fSecondaryTrackIDs.emplace_back(track->GetTrackID()); } } @@ -353,7 +351,9 @@ void TRestGeant4Hits::InsertStep(const G4Step* step) { fKineticEnergy.emplace_back(step->GetPreStepPoint()->GetKineticEnergy() / CLHEP::keV); fMomentumDirection.emplace_back(momentum.x(), momentum.y(), momentum.z()); - fTrack->IncreaseTrackLength(step->GetStepLength() / CLHEP::mm); + if (fTrack != nullptr) { + fTrack->IncreaseTrackLength(step->GetStepLength() / CLHEP::mm); + } SimulationManager::GetOutputManager()->AddEnergyToVolumeForProcess(energy, volumeName, processName); } From 7220198cbd22133a3fed087c019f5640aa112a55 Mon Sep 17 00:00:00 2001 From: lobis Date: Thu, 7 Jul 2022 21:34:33 +0200 Subject: [PATCH 041/173] TRestGeant4Track - removed redundant track length --- src/SimulationManager.cxx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index ebd1dd3d..52019dce 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -351,9 +351,5 @@ void TRestGeant4Hits::InsertStep(const G4Step* step) { fKineticEnergy.emplace_back(step->GetPreStepPoint()->GetKineticEnergy() / CLHEP::keV); fMomentumDirection.emplace_back(momentum.x(), momentum.y(), momentum.z()); - if (fTrack != nullptr) { - fTrack->IncreaseTrackLength(step->GetStepLength() / CLHEP::mm); - } - SimulationManager::GetOutputManager()->AddEnergyToVolumeForProcess(energy, volumeName, processName); } From e04bd0c0c3dd38a069a65896b456af6e177f5a6e Mon Sep 17 00:00:00 2001 From: lobis Date: Thu, 7 Jul 2022 21:37:32 +0200 Subject: [PATCH 042/173] general cleaning --- src/Application.cxx | 5 ----- src/EventAction.cxx | 2 +- src/PrimaryGeneratorAction.cxx | 4 ---- src/SensitiveDetector.cxx | 2 +- src/SimulationManager.cxx | 4 ++-- 5 files changed, 4 insertions(+), 13 deletions(-) diff --git a/src/Application.cxx b/src/Application.cxx index 3c6f4d89..7ba5b7c3 100644 --- a/src/Application.cxx +++ b/src/Application.cxx @@ -158,11 +158,6 @@ void Application::Run(const CommandLineParameters& commandLineParameters) { runManager->SetUserInitialization(new ActionInitialization(fSimulationManager)); - auto step = (SteppingAction*)G4RunManager::GetRunManager()->GetUserSteppingAction(); - - auto primaryGenerator = - (PrimaryGeneratorAction*)G4RunManager::GetRunManager()->GetUserPrimaryGeneratorAction(); - runManager->Initialize(); G4UImanager* UI = G4UImanager::GetUIpointer(); diff --git a/src/EventAction.cxx b/src/EventAction.cxx index 7ac42dfd..0f05956d 100644 --- a/src/EventAction.cxx +++ b/src/EventAction.cxx @@ -52,7 +52,7 @@ void EventAction::BeginOfEventAction(const G4Event* event) { } } -void EventAction::EndOfEventAction(const G4Event* event) { +void EventAction::EndOfEventAction(const G4Event*) { fSimulationManager->GetOutputManager()->FinishAndSubmitEvent(); if (!G4Threading::IsMultithreadedApplication() || // diff --git a/src/PrimaryGeneratorAction.cxx b/src/PrimaryGeneratorAction.cxx index c3851d51..c2f69219 100644 --- a/src/PrimaryGeneratorAction.cxx +++ b/src/PrimaryGeneratorAction.cxx @@ -91,9 +91,7 @@ void PrimaryGeneratorAction::SetGeneratorSpatialDensity(TString str) { void PrimaryGeneratorAction::GeneratePrimaries(G4Event* event) { auto simulationManager = fSimulationManager; - TRestRun* restRun = simulationManager->fRestRun; TRestGeant4Metadata* restG4Metadata = simulationManager->fRestGeant4Metadata; - TRestGeant4PhysicsLists* restPhysList = simulationManager->fRestGeant4PhysicsLists; if (restG4Metadata->GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Debug) { cout << "DEBUG: Primary generation" << endl; @@ -132,9 +130,7 @@ void PrimaryGeneratorAction::GeneratePrimaries(G4Event* event) { G4ParticleDefinition* PrimaryGeneratorAction::SetParticleDefinition(Int_t n, TRestGeant4Particle p) { auto simulationManager = fSimulationManager; - TRestRun* restRun = simulationManager->fRestRun; TRestGeant4Metadata* restG4Metadata = simulationManager->fRestGeant4Metadata; - TRestGeant4PhysicsLists* restPhysList = simulationManager->fRestGeant4PhysicsLists; auto particle_name = (string)p.GetParticleName(); diff --git a/src/SensitiveDetector.cxx b/src/SensitiveDetector.cxx index 653011aa..243767c6 100644 --- a/src/SensitiveDetector.cxx +++ b/src/SensitiveDetector.cxx @@ -12,7 +12,7 @@ using namespace std; SensitiveDetector::SensitiveDetector(SimulationManager* simulationManager, const G4String& name) - : fSimulationManager(simulationManager), G4VSensitiveDetector(name) {} + : G4VSensitiveDetector(name), fSimulationManager(simulationManager) {} G4bool SensitiveDetector::ProcessHits(G4Step* step, G4TouchableHistory*) { // return value will always be ignored, its present for backwards compatibility (I guess) diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index 52019dce..3e29a99e 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -279,8 +279,8 @@ void TRestGeant4Track::UpdateTrack(const G4Track* track) { auto steppingAction = (SteppingAction*)G4EventManager::GetEventManager()->GetUserSteppingAction(); const auto secondaries = steppingAction->GetSecondaries(); - for (const auto& track : *secondaries) { - fSecondaryTrackIDs.emplace_back(track->GetTrackID()); + for (const auto& secondaryTrack : *secondaries) { + fSecondaryTrackIDs.emplace_back(secondaryTrack->GetTrackID()); } } From 8609e615c96a2acd16012f12623cd22d75eec766 Mon Sep 17 00:00:00 2001 From: lobis Date: Fri, 8 Jul 2022 11:00:13 +0200 Subject: [PATCH 043/173] Updated track secondary handling --- include/SteppingAction.h | 2 -- src/SimulationManager.cxx | 20 +++++++++++--------- src/SteppingAction.cxx | 5 ----- 3 files changed, 11 insertions(+), 16 deletions(-) diff --git a/include/SteppingAction.h b/include/SteppingAction.h index 84425dee..da9772c2 100644 --- a/include/SteppingAction.h +++ b/include/SteppingAction.h @@ -20,8 +20,6 @@ class SteppingAction : public G4UserSteppingAction { void UserSteppingAction(const G4Step*) override; - std::vector* GetSecondaries() const; - private: SimulationManager* fSimulationManager; }; diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index 3e29a99e..ba463267 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -214,11 +214,19 @@ bool TRestGeant4Event::InsertTrack(const G4Track* track) { fSubEventPrimaryDirection = {momentum.x(), momentum.y(), momentum.z()}; } + fTrackIDToTrackIndex[track->GetTrackID()] = fTracks.size(); // before insertion + fTracks.emplace_back(track); - fTracks.back().SetHits(fInitialStep); - fTracks.back().SetEvent(this); - fTrackIDToTrackIndex[track->GetTrackID()] = fTracks.size() - 1; + auto& insertedTrack = fTracks.back(); + + insertedTrack.SetHits(fInitialStep); + insertedTrack.SetEvent(this); + + TRestGeant4Track* parentTrack = GetTrackByID(track->GetParentID()); + if (parentTrack) { + parentTrack->AddSecondaryTrackID(track->GetTrackID()); + } return true; } @@ -276,12 +284,6 @@ void TRestGeant4Track::UpdateTrack(const G4Track* track) { } fTrackLength = track->GetTrackLength() / CLHEP::mm; - - auto steppingAction = (SteppingAction*)G4EventManager::GetEventManager()->GetUserSteppingAction(); - const auto secondaries = steppingAction->GetSecondaries(); - for (const auto& secondaryTrack : *secondaries) { - fSecondaryTrackIDs.emplace_back(secondaryTrack->GetTrackID()); - } } Int_t TRestGeant4PhysicsInfo::GetProcessIDFromGeant4Process(const G4VProcess* process) { diff --git a/src/SteppingAction.cxx b/src/SteppingAction.cxx index cf4422a5..9d1d4bac 100644 --- a/src/SteppingAction.cxx +++ b/src/SteppingAction.cxx @@ -25,8 +25,3 @@ SteppingAction::~SteppingAction() {} void SteppingAction::UserSteppingAction(const G4Step* step) { fSimulationManager->GetOutputManager()->RecordStep(step); } - -vector* SteppingAction::GetSecondaries() const { - G4SteppingManager* steppingManager = fpSteppingManager; - return steppingManager->GetfSecondary(); -} From 24a9d2c2750ac3ede0b580952373e9ecf74b6726 Mon Sep 17 00:00:00 2001 From: lobis Date: Fri, 8 Jul 2022 11:15:18 +0200 Subject: [PATCH 044/173] TRestGeant4Track - renamed some members --- src/SimulationManager.cxx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index ba463267..ee90407a 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -265,14 +265,14 @@ TRestGeant4Track::TRestGeant4Track(const G4Track* track) : TRestGeant4Track() { fCreatorProcess = "PrimaryGenerator"; } - fKineticEnergy = track->GetKineticEnergy() / CLHEP::keV; + fInitialKineticEnergy = track->GetKineticEnergy() / CLHEP::keV; fWeight = track->GetWeight(); fGlobalTimestamp = track->GetGlobalTime() / CLHEP::second; const G4ThreeVector& trackOrigin = track->GetPosition(); - fTrackOrigin = {trackOrigin.x(), trackOrigin.y(), trackOrigin.z()}; + fInitialPosition = {trackOrigin.x(), trackOrigin.y(), trackOrigin.z()}; } void TRestGeant4Track::InsertStep(const G4Step* step) { fHits.InsertStep(step); } @@ -283,7 +283,8 @@ void TRestGeant4Track::UpdateTrack(const G4Track* track) { exit(1); } - fTrackLength = track->GetTrackLength() / CLHEP::mm; + fLength = track->GetTrackLength() / CLHEP::mm; + fTimeLength = track->GetGlobalTime() / CLHEP::second - fGlobalTimestamp; } Int_t TRestGeant4PhysicsInfo::GetProcessIDFromGeant4Process(const G4VProcess* process) { From a218e6f7c52252fcf352a2f58cbb5ed5db1f9882 Mon Sep 17 00:00:00 2001 From: lobis Date: Fri, 8 Jul 2022 12:10:03 +0200 Subject: [PATCH 045/173] Simplified primary generator --- include/PrimaryGeneratorAction.h | 16 +---- src/ActionInitialization.cxx | 57 +-------------- src/PrimaryGeneratorAction.cxx | 118 +++++++++++++++++++++---------- test/src/examples.cxx | 2 + 4 files changed, 86 insertions(+), 107 deletions(-) diff --git a/include/PrimaryGeneratorAction.h b/include/PrimaryGeneratorAction.h index 8e90634c..e99fa1ff 100644 --- a/include/PrimaryGeneratorAction.h +++ b/include/PrimaryGeneratorAction.h @@ -4,6 +4,7 @@ #include #include +#include #include #include @@ -13,21 +14,17 @@ #include #include "DetectorConstruction.h" -#include "TRestGeant4Particle.h" - -const int nSpct = 3000; class G4Event; class SimulationManager; class PrimaryGeneratorAction : public G4VUserPrimaryGeneratorAction { public: - PrimaryGeneratorAction(SimulationManager*, DetectorConstruction* pDetector); + PrimaryGeneratorAction(SimulationManager*); ~PrimaryGeneratorAction(); public: virtual void GeneratePrimaries(G4Event*); - G4ParticleGun* GetParticleGun() { return fParticleGun; }; void SetSpectrum(TH1D* spt, double eMin = 0, double eMax = 0); void SetGeneratorSpatialDensity(TString str); @@ -39,8 +36,7 @@ class PrimaryGeneratorAction : public G4VUserPrimaryGeneratorAction { std::vector fTempParticles; - G4ParticleGun* fParticleGun; - DetectorConstruction* fDetector; + G4ParticleGun fParticleGun; G4ParticleDefinition* fParticle = nullptr; TH1D* fSpectrum; @@ -78,14 +74,8 @@ class PrimaryGeneratorAction : public G4VUserPrimaryGeneratorAction { G4String fParType; G4String fGenType; - G4double fParEnergy; - G4double fParGenerator; G4String fSpctFilename; - - G4int gammaSpectrum[nSpct]; - - G4int nCollections; }; #endif diff --git a/src/ActionInitialization.cxx b/src/ActionInitialization.cxx index 82a6862d..96158b7f 100644 --- a/src/ActionInitialization.cxx +++ b/src/ActionInitialization.cxx @@ -25,64 +25,9 @@ ActionInitialization::~ActionInitialization() = default; void ActionInitialization::BuildForMaster() const { SetUserAction(new RunAction(fSimulationManager)); } void ActionInitialization::Build() const { - auto detector = (DetectorConstruction*)G4RunManager::GetRunManager()->GetUserDetectorConstruction(); - - auto primaryGenerator = new PrimaryGeneratorAction(fSimulationManager, detector); - - auto restG4Metadata = fSimulationManager->fRestGeant4Metadata; - - if (restG4Metadata->GetParticleSource(0)->GetEnergyDistType() == "TH1D") { - TString fileFullPath = (TString)restG4Metadata->GetParticleSource(0)->GetSpectrumFilename(); - - TFile fin(fileFullPath); - - TString sptName = restG4Metadata->GetParticleSource(0)->GetSpectrumName(); - - TH1D* h = (TH1D*)fin.Get(sptName); - - if (!h) { - RESTError << "REST ERROR when trying to find energy spectrum" << RESTendl; - RESTError << "File : " << fileFullPath << RESTendl; - RESTError << "Spectrum name : " << sptName << RESTendl; - exit(1); - } - - fSimulationManager->initialEnergySpectrum = *h; - - Double_t minEnergy = restG4Metadata->GetParticleSource(0)->GetMinEnergy(); - if (minEnergy < 0) minEnergy = 0; - - Double_t maxEnergy = restG4Metadata->GetParticleSource(0)->GetMaxEnergy(); - if (maxEnergy < 0) maxEnergy = 0; - - // We set the initial spectrum energy provided from TH1D - primaryGenerator->SetSpectrum(&(fSimulationManager->initialEnergySpectrum), minEnergy, maxEnergy); - } - - if (restG4Metadata->GetParticleSource(0)->GetAngularDistType() == "TH1D") { - TString fileFullPath = (TString)restG4Metadata->GetParticleSource(0)->GetAngularFilename(); - - TFile fin(fileFullPath); - - TString sptName = restG4Metadata->GetParticleSource(0)->GetAngularName(); - TH1D* h = (TH1D*)fin.Get(sptName); - - if (!h) { - cout << "REST ERROR when trying to find angular spectrum" << endl; - cout << "File : " << fileFullPath << endl; - cout << "Spectrum name : " << sptName << endl; - exit(1); - } - - fSimulationManager->initialAngularDistribution = *h; - - // We set the initial angular distribution provided from TH1D - primaryGenerator->SetAngularDistribution(&(fSimulationManager->initialAngularDistribution)); - } - fSimulationManager->InitializeOutputManager(); - SetUserAction(primaryGenerator); + SetUserAction(new PrimaryGeneratorAction(fSimulationManager)); SetUserAction(new RunAction(fSimulationManager)); SetUserAction(new EventAction(fSimulationManager)); SetUserAction(new SteppingAction(fSimulationManager)); diff --git a/src/PrimaryGeneratorAction.cxx b/src/PrimaryGeneratorAction.cxx index c2f69219..36137813 100644 --- a/src/PrimaryGeneratorAction.cxx +++ b/src/PrimaryGeneratorAction.cxx @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -17,19 +18,10 @@ using namespace std; -Int_t face = 0; - double GeneratorRndm() { return G4UniformRand(); } -PrimaryGeneratorAction::PrimaryGeneratorAction(SimulationManager* simulationManager, - DetectorConstruction* pDetector) - : G4VUserPrimaryGeneratorAction(), - fSimulationManager(simulationManager), - fParticleGun(nullptr), - fDetector(pDetector) { - G4int n_particle = 1; - fParticleGun = new G4ParticleGun(n_particle); - +PrimaryGeneratorAction::PrimaryGeneratorAction(SimulationManager* simulationManager) + : G4VUserPrimaryGeneratorAction(), fSimulationManager(simulationManager) { fGeneratorSpatialDensityFunction = nullptr; TRestGeant4Metadata* restG4Metadata = fSimulationManager->fRestGeant4Metadata; @@ -37,9 +29,58 @@ PrimaryGeneratorAction::PrimaryGeneratorAction(SimulationManager* simulationMana for (int i = 0; i < restG4Metadata->GetNumberOfSources(); i++) { restG4Metadata->GetParticleSource(i)->SetRndmMethod(GeneratorRndm); } + + if (restG4Metadata->GetParticleSource(0)->GetEnergyDistType() == "TH1D") { + TString fileFullPath = (TString)restG4Metadata->GetParticleSource(0)->GetSpectrumFilename(); + + TFile fin(fileFullPath); + + TString sptName = restG4Metadata->GetParticleSource(0)->GetSpectrumName(); + + TH1D* h = (TH1D*)fin.Get(sptName); + + if (!h) { + RESTError << "REST ERROR when trying to find energy spectrum" << RESTendl; + RESTError << "File : " << fileFullPath << RESTendl; + RESTError << "Spectrum name : " << sptName << RESTendl; + exit(1); + } + + fSimulationManager->initialEnergySpectrum = *h; + + Double_t minEnergy = restG4Metadata->GetParticleSource(0)->GetMinEnergy(); + if (minEnergy < 0) minEnergy = 0; + + Double_t maxEnergy = restG4Metadata->GetParticleSource(0)->GetMaxEnergy(); + if (maxEnergy < 0) maxEnergy = 0; + + // We set the initial spectrum energy provided from TH1D + SetSpectrum(&(fSimulationManager->initialEnergySpectrum), minEnergy, maxEnergy); + } + + if (restG4Metadata->GetParticleSource(0)->GetAngularDistType() == "TH1D") { + TString fileFullPath = (TString)restG4Metadata->GetParticleSource(0)->GetAngularFilename(); + + TFile fin(fileFullPath); + + TString sptName = restG4Metadata->GetParticleSource(0)->GetAngularName(); + TH1D* h = (TH1D*)fin.Get(sptName); + + if (!h) { + cout << "REST ERROR when trying to find angular spectrum" << endl; + cout << "File : " << fileFullPath << endl; + cout << "Spectrum name : " << sptName << endl; + exit(1); + } + + fSimulationManager->initialAngularDistribution = *h; + + // We set the initial angular distribution provided from TH1D + SetAngularDistribution(&(fSimulationManager->initialAngularDistribution)); + } } -PrimaryGeneratorAction::~PrimaryGeneratorAction() { delete fParticleGun; } +PrimaryGeneratorAction::~PrimaryGeneratorAction() = default; void PrimaryGeneratorAction::SetSpectrum(TH1D* spt, double eMin, double eMax) { auto xLabel = (TString)spt->GetXaxis()->GetTitle(); @@ -123,7 +164,7 @@ void PrimaryGeneratorAction::GeneratePrimaries(G4Event* event) { SetParticleDirection(i, p); - fParticleGun->GeneratePrimaryVertex(event); + fParticleGun.GeneratePrimaryVertex(event); } } } @@ -149,16 +190,16 @@ G4ParticleDefinition* PrimaryGeneratorAction::SetParticleDefinition(Int_t n, TRe fParticle = particleTable->FindParticle(particle_name); // There might be a better way to do this - for (int Z = 1; Z <= 110; Z++) + for (int Z = 1; Z <= 110; Z++) { for (int A = 2 * Z - 1; A <= 3 * Z; A++) { if (particle_name == G4IonTable::GetIonTable()->GetIonName(Z, A)) { // excited energy is in rest units keV, when input to geant4, we shall convert to MeV fParticle = G4IonTable::GetIonTable()->GetIon(Z, A, excited_energy / 1000); particle_name = G4IonTable::GetIonTable()->GetIonName(Z, A, excited_energy / 1000); - fParticleGun->SetParticleCharge(charge); + fParticleGun.SetParticleCharge(charge); } } - // } + } if (!fParticle) { cout << "Particle definition : " << particle_name << " not found!" << endl; @@ -166,9 +207,7 @@ G4ParticleDefinition* PrimaryGeneratorAction::SetParticleDefinition(Int_t n, TRe } } - fParticleGun->SetParticleDefinition(fParticle); - - // restG4Event->SetPrimaryEventParticleName(particle_name); + fParticleGun.SetParticleDefinition(fParticle); return fParticle; } @@ -305,7 +344,7 @@ void PrimaryGeneratorAction::SetParticleDirection(Int_t n, TRestGeant4Particle p } */ // setting particle direction - fParticleGun->SetParticleMomentumDirection(direction); + fParticleGun.SetParticleMomentumDirection(direction); } void PrimaryGeneratorAction::SetParticleEnergy(Int_t n, TRestGeant4Particle p) { @@ -383,7 +422,7 @@ void PrimaryGeneratorAction::SetParticleEnergy(Int_t n, TRestGeant4Particle p) { } if (n == 0) lastEnergy = energy; - fParticleGun->SetParticleEnergy(energy); + fParticleGun.SetParticleEnergy(energy); // restG4Event->SetPrimaryEventEnergy(energy / keV); @@ -440,7 +479,7 @@ void PrimaryGeneratorAction::SetParticlePosition() { << G4endl; } - // use the density funciton. If the density is small, then val2 is small, we are more + // use the density function. If the density is small, then val2 is small, we are more // likely to regenerate the particle position if (fGeneratorSpatialDensityFunction) { double val1 = G4UniformRand(); @@ -470,7 +509,7 @@ void PrimaryGeneratorAction::SetParticlePosition() { } */ // setting particle position - fParticleGun->SetParticlePosition(G4ThreeVector(x, y, z)); + fParticleGun.SetParticlePosition(G4ThreeVector(x, y, z)); } G4ThreeVector PrimaryGeneratorAction::GetIsotropicVector() { @@ -487,7 +526,7 @@ G4ThreeVector PrimaryGeneratorAction::GetIsotropicVector() { a /= n; b /= n; c /= n; - return G4ThreeVector(a, b, c); + return {a, b, c}; } Double_t PrimaryGeneratorAction::GetAngle(G4ThreeVector x, G4ThreeVector y) { @@ -513,38 +552,41 @@ Double_t PrimaryGeneratorAction::GetCosineLowRandomThetaAngle() { } void PrimaryGeneratorAction::GenPositionOnGDMLVolume(double& x, double& y, double& z) { - double xMin = fDetector->GetBoundingX_min(); - double xMax = fDetector->GetBoundingX_max(); - double yMin = fDetector->GetBoundingY_min(); - double yMax = fDetector->GetBoundingY_max(); - double zMin = fDetector->GetBoundingZ_min(); - double zMax = fDetector->GetBoundingZ_max(); + auto detector = (DetectorConstruction*)G4RunManager::GetRunManager()->GetUserDetectorConstruction(); + + double xMin = detector->GetBoundingX_min(); + double xMax = detector->GetBoundingX_max(); + double yMin = detector->GetBoundingY_min(); + double yMax = detector->GetBoundingY_max(); + double zMin = detector->GetBoundingZ_min(); + double zMax = detector->GetBoundingZ_max(); do { x = xMin + (xMax - xMin) * G4UniformRand(); y = yMin + (yMax - yMin) * G4UniformRand(); z = zMin + (zMax - zMin) * G4UniformRand(); - } while (fDetector->GetGeneratorSolid()->Inside(G4ThreeVector(x, y, z)) != kInside); + } while (detector->GetGeneratorSolid()->Inside(G4ThreeVector(x, y, z)) != kInside); - x = x + fDetector->GetGeneratorTranslation().x(); - y = y + fDetector->GetGeneratorTranslation().y(); - z = z + fDetector->GetGeneratorTranslation().z(); + x = x + detector->GetGeneratorTranslation().x(); + y = y + detector->GetGeneratorTranslation().y(); + z = z + detector->GetGeneratorTranslation().z(); } void PrimaryGeneratorAction::GenPositionOnGDMLSurface(double& x, double& y, double& z) { // TODO there is a problem, probably with G4 function GetPointOnSurface // It produces a point on the surface but it is not uniformly distributed // May be it is just an OPENGL drawing issue? + auto detector = (DetectorConstruction*)G4RunManager::GetRunManager()->GetUserDetectorConstruction(); - G4ThreeVector position = fDetector->GetGeneratorSolid()->GetPointOnSurface(); + G4ThreeVector position = detector->GetGeneratorSolid()->GetPointOnSurface(); x = position.x(); y = position.y(); z = position.z(); - x = x + fDetector->GetGeneratorTranslation().x(); - y = y + fDetector->GetGeneratorTranslation().y(); - z = z + fDetector->GetGeneratorTranslation().z(); + x = x + detector->GetGeneratorTranslation().x(); + y = y + detector->GetGeneratorTranslation().y(); + z = z + detector->GetGeneratorTranslation().z(); } void PrimaryGeneratorAction::GenPositionOnBoxVolume(double& x, double& y, double& z) { diff --git a/test/src/examples.cxx b/test/src/examples.cxx index 467dbf06..85464188 100644 --- a/test/src/examples.cxx +++ b/test/src/examples.cxx @@ -163,6 +163,8 @@ TEST(restG4, Example_04_Muons) { } TEST(restG4, Example_04_Muons_MT) { + GTEST_SKIP_("Multithreading needs to be implemented"); + // cd into example const auto originalPath = fs::current_path(); const auto thisExamplePath = examplesPath / "04.MuonScan"; From 10c66d6252e2f0b6e50ea76d978adb9436cc4788 Mon Sep 17 00:00:00 2001 From: lobis Date: Fri, 8 Jul 2022 12:22:08 +0200 Subject: [PATCH 046/173] unified some variable names --- include/DetectorConstruction.h | 31 +++++++++----------- include/PrimaryGeneratorAction.h | 6 ++-- src/DetectorConstruction.cxx | 50 ++++++++++++++++---------------- src/PrimaryGeneratorAction.cxx | 42 +++++++++++++-------------- 4 files changed, 62 insertions(+), 67 deletions(-) diff --git a/include/DetectorConstruction.h b/include/DetectorConstruction.h index cc15d4c8..3ab19aca 100644 --- a/include/DetectorConstruction.h +++ b/include/DetectorConstruction.h @@ -15,28 +15,23 @@ class DetectorConstruction : public G4VUserDetectorConstruction { private: SimulationManager* fSimulationManager; - G4GDMLParser* parser; - G4VSolid* generatorSolid; + G4GDMLParser* fGdmlParser; + G4VSolid* fGeneratorSolid; G4ThreeVector fGeneratorTranslation; - Double_t boundBox_xMin, boundBox_xMax; - Double_t boundBox_yMin, boundBox_yMax; - Double_t boundBox_zMin, boundBox_zMax; + Double_t fBoundBoxXMin, fBoundBoxXMax, fBoundBoxYMin, fBoundBoxYMax, fBoundBoxZMin, fBoundBoxZMax; public: - G4GDMLParser* GetGeometry() { return parser; } - G4VPhysicalVolume* GetPhysicalVolume(const G4String& physVolName); - G4VSolid* GetGeneratorSolid() { return generatorSolid; } - G4ThreeVector GetGeneratorTranslation() { return fGeneratorTranslation; } - - Double_t GetBoundingX_min() { return boundBox_xMin; } - Double_t GetBoundingX_max() { return boundBox_xMax; } - - Double_t GetBoundingY_min() { return boundBox_yMin; } - Double_t GetBoundingY_max() { return boundBox_yMax; } - - Double_t GetBoundingZ_min() { return boundBox_zMin; } - Double_t GetBoundingZ_max() { return boundBox_zMax; } + G4VPhysicalVolume* GetPhysicalVolume(const G4String& physVolName) const; + inline G4VSolid* GetGeneratorSolid() const { return fGeneratorSolid; } + inline G4ThreeVector GetGeneratorTranslation() const { return fGeneratorTranslation; } + + inline Double_t GetBoundBoxXMin() const { return fBoundBoxXMin; } + inline Double_t GetBoundBoxXMax() const { return fBoundBoxXMax; } + inline Double_t GetBoundBoxYMin() const { return fBoundBoxYMin; } + inline Double_t GetBoundBoxYMax() const { return fBoundBoxYMax; } + inline Double_t GetBoundBoxZMin() const { return fBoundBoxZMin; } + inline Double_t GetBoundBoxZMax() const { return fBoundBoxZMax; } DetectorConstruction(SimulationManager*); ~DetectorConstruction(); diff --git a/include/PrimaryGeneratorAction.h b/include/PrimaryGeneratorAction.h index e99fa1ff..f0a2188b 100644 --- a/include/PrimaryGeneratorAction.h +++ b/include/PrimaryGeneratorAction.h @@ -52,9 +52,9 @@ class PrimaryGeneratorAction : public G4VUserPrimaryGeneratorAction { Double_t lastEnergy; void SetParticlePosition(); - G4ParticleDefinition* SetParticleDefinition(Int_t particlesourceindex, TRestGeant4Particle p); - void SetParticleEnergy(Int_t particlesourceindex, TRestGeant4Particle p); - void SetParticleDirection(Int_t particlesourceindex, TRestGeant4Particle p); + G4ParticleDefinition* SetParticleDefinition(Int_t particlesourceindex, TRestGeant4Particle particle); + void SetParticleEnergy(Int_t particlesourceindex, TRestGeant4Particle particle); + void SetParticleDirection(Int_t particlesourceindex, TRestGeant4Particle particle); G4ThreeVector GetIsotropicVector(); Double_t GetAngle(G4ThreeVector x, G4ThreeVector y); diff --git a/src/DetectorConstruction.cxx b/src/DetectorConstruction.cxx index 26ca358a..971e4869 100644 --- a/src/DetectorConstruction.cxx +++ b/src/DetectorConstruction.cxx @@ -23,10 +23,10 @@ using namespace std; DetectorConstruction::DetectorConstruction(SimulationManager* simulationManager) : fSimulationManager(simulationManager) { G4cout << "Detector Construction" << G4endl; - parser = new G4GDMLParser(); + fGdmlParser = new G4GDMLParser(); } -DetectorConstruction::~DetectorConstruction() { delete parser; } +DetectorConstruction::~DetectorConstruction() { delete fGdmlParser; } G4VPhysicalVolume* DetectorConstruction::Construct() { TRestGeant4Metadata* restG4Metadata = fSimulationManager->fRestGeant4Metadata; @@ -47,11 +47,11 @@ G4VPhysicalVolume* DetectorConstruction::Construct() { string gdmlToRead = separatePathAndName.second; G4cout << "gdmlToRead: " << gdmlToRead << G4endl; - parser->Read(gdmlToRead, false); + fGdmlParser->Read(gdmlToRead, false); restG4Metadata->fGeant4GeometryInfo.PopulateFromGdml(gdmlToRead); - G4VPhysicalVolume* worldVolume = parser->GetWorldVolume(); + G4VPhysicalVolume* worldVolume = fGdmlParser->GetWorldVolume(); restG4Metadata->fGeant4GeometryInfo.PopulateFromGeant4World(worldVolume); @@ -135,7 +135,7 @@ G4VPhysicalVolume* DetectorConstruction::Construct() { fGeneratorTranslation.z()); } - generatorSolid = pVol->GetLogicalVolume()->GetSolid(); + fGeneratorSolid = pVol->GetLogicalVolume()->GetSolid(); // while ( fDetector->GetGeneratorSolid()->Inside( G4ThreeVector( x, y, z) ) // != kInside ); @@ -144,37 +144,37 @@ G4VPhysicalVolume* DetectorConstruction::Construct() { // The code below returns a value bigger than expected // If we try with a cylinder the maximum distance should be sqrt(R*R+L*L) // But the value returned by this is bigger TODO check this - boundBox_xMax = -1.e30; - boundBox_yMax = -1.e30; - boundBox_zMax = -1.e30; - boundBox_xMin = 1.e30; - boundBox_yMin = 1.e30; - boundBox_zMin = 1.e30; + fBoundBoxXMax = -1.e30; + fBoundBoxYMax = -1.e30; + fBoundBoxZMax = -1.e30; + fBoundBoxXMin = 1.e30; + fBoundBoxYMin = 1.e30; + fBoundBoxZMin = 1.e30; if (type == "volume") { cout << "Optimizing REST volume generation (Please wait. This might take " "few minutes depending on geometry complexity) " << flush; for (int n = 0; n < 100000; n++) { - G4ThreeVector point = generatorSolid->GetPointOnSurface(); + G4ThreeVector point = fGeneratorSolid->GetPointOnSurface(); - if (point.x() > boundBox_xMax) boundBox_xMax = point.x(); - if (point.y() > boundBox_yMax) boundBox_yMax = point.y(); - if (point.z() > boundBox_zMax) boundBox_zMax = point.z(); + if (point.x() > fBoundBoxXMax) fBoundBoxXMax = point.x(); + if (point.y() > fBoundBoxYMax) fBoundBoxYMax = point.y(); + if (point.z() > fBoundBoxZMax) fBoundBoxZMax = point.z(); - if (point.x() < boundBox_xMin) boundBox_xMin = point.x(); - if (point.y() < boundBox_yMin) boundBox_yMin = point.y(); - if (point.z() < boundBox_zMin) boundBox_zMin = point.z(); + if (point.x() < fBoundBoxXMin) fBoundBoxXMin = point.x(); + if (point.y() < fBoundBoxYMin) fBoundBoxYMin = point.y(); + if (point.z() < fBoundBoxZMin) fBoundBoxZMin = point.z(); } - boundBox_xMin = boundBox_xMin * 1.1; - boundBox_xMax = boundBox_xMax * 1.1; + fBoundBoxXMin = fBoundBoxXMin * 1.1; + fBoundBoxXMax = fBoundBoxXMax * 1.1; - boundBox_yMin = boundBox_yMin * 1.1; - boundBox_yMax = boundBox_yMax * 1.1; + fBoundBoxYMin = fBoundBoxYMin * 1.1; + fBoundBoxYMax = fBoundBoxYMax * 1.1; - boundBox_zMin = boundBox_zMin * 1.1; - boundBox_zMax = boundBox_zMax * 1.1; + fBoundBoxZMin = fBoundBoxZMin * 1.1; + fBoundBoxZMax = fBoundBoxZMax * 1.1; } } @@ -204,7 +204,7 @@ G4VPhysicalVolume* DetectorConstruction::Construct() { return worldVolume; } -G4VPhysicalVolume* DetectorConstruction::GetPhysicalVolume(const G4String& physVolName) { +G4VPhysicalVolume* DetectorConstruction::GetPhysicalVolume(const G4String& physVolName) const { G4PhysicalVolumeStore* physVolStore = G4PhysicalVolumeStore::GetInstance(); TRestGeant4Metadata* restG4Metadata = fSimulationManager->fRestGeant4Metadata; const auto& geometryInfo = restG4Metadata->GetGeant4GeometryInfo(); diff --git a/src/PrimaryGeneratorAction.cxx b/src/PrimaryGeneratorAction.cxx index 36137813..2d27db14 100644 --- a/src/PrimaryGeneratorAction.cxx +++ b/src/PrimaryGeneratorAction.cxx @@ -169,40 +169,40 @@ void PrimaryGeneratorAction::GeneratePrimaries(G4Event* event) { } } -G4ParticleDefinition* PrimaryGeneratorAction::SetParticleDefinition(Int_t n, TRestGeant4Particle p) { +G4ParticleDefinition* PrimaryGeneratorAction::SetParticleDefinition(Int_t n, TRestGeant4Particle particle) { auto simulationManager = fSimulationManager; TRestGeant4Metadata* restG4Metadata = simulationManager->fRestGeant4Metadata; - auto particle_name = (string)p.GetParticleName(); + auto particleName = (string)particle.GetParticleName(); - Double_t excited_energy = (double)p.GetExcitationLevel(); // in keV + Double_t excitedEnergy = (double)particle.GetExcitationLevel(); // in keV - Int_t charge = p.GetParticleCharge(); + Int_t charge = particle.GetParticleCharge(); if (restG4Metadata->GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Debug) { - cout << "DEBUG: Particle name: " << particle_name << endl; + cout << "DEBUG: Particle name: " << particleName << endl; // cout << "DEBUG: Particle charge: " << charge << endl; - cout << "DEBUG: Particle excited energy: " << excited_energy << " keV" << endl; + cout << "DEBUG: Particle excited energy: " << excitedEnergy << " keV" << endl; } G4ParticleTable* particleTable = G4ParticleTable::GetParticleTable(); if (!fParticle) { - fParticle = particleTable->FindParticle(particle_name); + fParticle = particleTable->FindParticle(particleName); // There might be a better way to do this for (int Z = 1; Z <= 110; Z++) { for (int A = 2 * Z - 1; A <= 3 * Z; A++) { - if (particle_name == G4IonTable::GetIonTable()->GetIonName(Z, A)) { + if (particleName == G4IonTable::GetIonTable()->GetIonName(Z, A)) { // excited energy is in rest units keV, when input to geant4, we shall convert to MeV - fParticle = G4IonTable::GetIonTable()->GetIon(Z, A, excited_energy / 1000); - particle_name = G4IonTable::GetIonTable()->GetIonName(Z, A, excited_energy / 1000); + fParticle = G4IonTable::GetIonTable()->GetIon(Z, A, excitedEnergy / 1000); + particleName = G4IonTable::GetIonTable()->GetIonName(Z, A, excitedEnergy / 1000); fParticleGun.SetParticleCharge(charge); } } } if (!fParticle) { - cout << "Particle definition : " << particle_name << " not found!" << endl; + cout << "Particle definition : " << particleName << " not found!" << endl; exit(1); } } @@ -212,7 +212,7 @@ G4ParticleDefinition* PrimaryGeneratorAction::SetParticleDefinition(Int_t n, TRe return fParticle; } -void PrimaryGeneratorAction::SetParticleDirection(Int_t n, TRestGeant4Particle p) { +void PrimaryGeneratorAction::SetParticleDirection(Int_t n, TRestGeant4Particle particle) { auto simulationManager = fSimulationManager; TRestGeant4Metadata* restG4Metadata = simulationManager->fRestGeant4Metadata; @@ -312,7 +312,7 @@ void PrimaryGeneratorAction::SetParticleDirection(Int_t n, TRestGeant4Particle p direction.rotate(randomAngle, referenceOrigin); } else if (angular_dist_type == g4_metadata_parameters::angular_dist_types::FLUX) { - TVector3 v = p.GetMomentumDirection(); + TVector3 v = particle.GetMomentumDirection(); v = v.Unit(); @@ -347,7 +347,7 @@ void PrimaryGeneratorAction::SetParticleDirection(Int_t n, TRestGeant4Particle p fParticleGun.SetParticleMomentumDirection(direction); } -void PrimaryGeneratorAction::SetParticleEnergy(Int_t n, TRestGeant4Particle p) { +void PrimaryGeneratorAction::SetParticleEnergy(Int_t n, TRestGeant4Particle particle) { auto simulationManager = fSimulationManager; TRestGeant4Metadata* restG4Metadata = simulationManager->fRestGeant4Metadata; @@ -381,7 +381,7 @@ void PrimaryGeneratorAction::SetParticleEnergy(Int_t n, TRestGeant4Particle p) { } if (energy_dist_type == g4_metadata_parameters::energy_dist_types::MONO) { - energy = p.GetEnergy() * keV; + energy = particle.GetEnergy() * keV; } else if (energy_dist_type == g4_metadata_parameters::energy_dist_types::FLAT) { TVector2 enRange = restG4Metadata->GetParticleSource(n)->GetEnergyRange(); energy = ((enRange.Y() - enRange.X()) * G4UniformRand() + enRange.X()) * keV; @@ -554,12 +554,12 @@ Double_t PrimaryGeneratorAction::GetCosineLowRandomThetaAngle() { void PrimaryGeneratorAction::GenPositionOnGDMLVolume(double& x, double& y, double& z) { auto detector = (DetectorConstruction*)G4RunManager::GetRunManager()->GetUserDetectorConstruction(); - double xMin = detector->GetBoundingX_min(); - double xMax = detector->GetBoundingX_max(); - double yMin = detector->GetBoundingY_min(); - double yMax = detector->GetBoundingY_max(); - double zMin = detector->GetBoundingZ_min(); - double zMax = detector->GetBoundingZ_max(); + double xMin = detector->GetBoundBoxXMin(); + double xMax = detector->GetBoundBoxXMax(); + double yMin = detector->GetBoundBoxYMin(); + double yMax = detector->GetBoundBoxYMax(); + double zMin = detector->GetBoundBoxZMin(); + double zMax = detector->GetBoundBoxZMax(); do { x = xMin + (xMax - xMin) * G4UniformRand(); From 1c0bed1c93491fef0daf10eb947514f909ad36a1 Mon Sep 17 00:00:00 2001 From: lobis Date: Fri, 8 Jul 2022 13:39:25 +0200 Subject: [PATCH 047/173] Simplified user distribution initialization --- include/PrimaryGeneratorAction.h | 13 +++-- include/SimulationManager.h | 13 +++-- src/Application.cxx | 2 + src/PrimaryGeneratorAction.cxx | 89 ++++++++++---------------------- src/RunAction.cxx | 10 ++-- src/SimulationManager.cxx | 41 +++++++++++++++ 6 files changed, 93 insertions(+), 75 deletions(-) diff --git a/include/PrimaryGeneratorAction.h b/include/PrimaryGeneratorAction.h index f0a2188b..9885bab0 100644 --- a/include/PrimaryGeneratorAction.h +++ b/include/PrimaryGeneratorAction.h @@ -26,10 +26,10 @@ class PrimaryGeneratorAction : public G4VUserPrimaryGeneratorAction { public: virtual void GeneratePrimaries(G4Event*); - void SetSpectrum(TH1D* spt, double eMin = 0, double eMax = 0); - void SetGeneratorSpatialDensity(TString str); + void SetEnergyDistributionHistogram(const TH1D* h, double eMin = 0, double eMax = 0); + inline void SetAngularDistributionHistogram(const TH1D* h) { fAngularDistributionHistogram = h; } - void SetAngularDistribution(TH1D* ang) { fAngularDistribution = ang; } + void SetGeneratorSpatialDensity(TString str); private: SimulationManager* fSimulationManager; @@ -39,8 +39,9 @@ class PrimaryGeneratorAction : public G4VUserPrimaryGeneratorAction { G4ParticleGun fParticleGun; G4ParticleDefinition* fParticle = nullptr; - TH1D* fSpectrum; - TH1D* fAngularDistribution; + const TH1D* fEnergyDistributionHistogram = nullptr; + const TH1D* fAngularDistributionHistogram = nullptr; + TF3* fGeneratorSpatialDensityFunction; Int_t startEnergyBin; @@ -74,8 +75,6 @@ class PrimaryGeneratorAction : public G4VUserPrimaryGeneratorAction { G4String fParType; G4String fGenType; - - G4String fSpctFilename; }; #endif diff --git a/include/SimulationManager.h b/include/SimulationManager.h index 0acdcdc1..a7024d99 100644 --- a/include/SimulationManager.h +++ b/include/SimulationManager.h @@ -21,9 +21,6 @@ class SimulationManager { TRestGeant4PhysicsLists* fRestGeant4PhysicsLists = nullptr; TRestGeant4Metadata* fRestGeant4Metadata = nullptr; - TH1D initialEnergySpectrum; - TH1D initialAngularDistribution; - void InitializeOutputManager(); static OutputManager* GetOutputManager() { return fOutputManager; } @@ -38,6 +35,16 @@ class SimulationManager { static thread_local OutputManager* fOutputManager; std::mutex fEventContainerMutex; std::queue > fEventContainer; + + /* Primary generation */ + public: + void InitializeUserDistributions(); + inline const TH1D* GetPrimaryEnergyDistribution() const { return &fPrimaryEnergyDistribution; } + inline const TH1D* GetPrimaryAngularDistribution() const { return &fPrimaryAngularDistribution; } + + private: + TH1D fPrimaryEnergyDistribution; + TH1D fPrimaryAngularDistribution; }; class OutputManager { diff --git a/src/Application.cxx b/src/Application.cxx index 7ba5b7c3..8bf99900 100644 --- a/src/Application.cxx +++ b/src/Application.cxx @@ -153,6 +153,8 @@ void Application::Run(const CommandLineParameters& commandLineParameters) { auto detector = new DetectorConstruction(fSimulationManager); + fSimulationManager->InitializeUserDistributions(); + runManager->SetUserInitialization(detector); runManager->SetUserInitialization(new PhysicsList(fSimulationManager->fRestGeant4PhysicsLists)); diff --git a/src/PrimaryGeneratorAction.cxx b/src/PrimaryGeneratorAction.cxx index 2d27db14..9a2830e5 100644 --- a/src/PrimaryGeneratorAction.cxx +++ b/src/PrimaryGeneratorAction.cxx @@ -18,72 +18,35 @@ using namespace std; -double GeneratorRndm() { return G4UniformRand(); } - PrimaryGeneratorAction::PrimaryGeneratorAction(SimulationManager* simulationManager) : G4VUserPrimaryGeneratorAction(), fSimulationManager(simulationManager) { fGeneratorSpatialDensityFunction = nullptr; TRestGeant4Metadata* restG4Metadata = fSimulationManager->fRestGeant4Metadata; + TRestGeant4ParticleSource* source = restG4Metadata->GetParticleSource(0); - for (int i = 0; i < restG4Metadata->GetNumberOfSources(); i++) { - restG4Metadata->GetParticleSource(i)->SetRndmMethod(GeneratorRndm); - } - - if (restG4Metadata->GetParticleSource(0)->GetEnergyDistType() == "TH1D") { - TString fileFullPath = (TString)restG4Metadata->GetParticleSource(0)->GetSpectrumFilename(); - - TFile fin(fileFullPath); - - TString sptName = restG4Metadata->GetParticleSource(0)->GetSpectrumName(); - - TH1D* h = (TH1D*)fin.Get(sptName); - - if (!h) { - RESTError << "REST ERROR when trying to find energy spectrum" << RESTendl; - RESTError << "File : " << fileFullPath << RESTendl; - RESTError << "Spectrum name : " << sptName << RESTendl; - exit(1); - } - - fSimulationManager->initialEnergySpectrum = *h; - - Double_t minEnergy = restG4Metadata->GetParticleSource(0)->GetMinEnergy(); + if (source->GetEnergyDistType() == "TH1D") { + Double_t minEnergy = source->GetMinEnergy(); if (minEnergy < 0) minEnergy = 0; - Double_t maxEnergy = restG4Metadata->GetParticleSource(0)->GetMaxEnergy(); + Double_t maxEnergy = source->GetMaxEnergy(); if (maxEnergy < 0) maxEnergy = 0; // We set the initial spectrum energy provided from TH1D - SetSpectrum(&(fSimulationManager->initialEnergySpectrum), minEnergy, maxEnergy); + SetEnergyDistributionHistogram(fSimulationManager->GetPrimaryEnergyDistribution(), minEnergy, + maxEnergy); } - if (restG4Metadata->GetParticleSource(0)->GetAngularDistType() == "TH1D") { - TString fileFullPath = (TString)restG4Metadata->GetParticleSource(0)->GetAngularFilename(); - - TFile fin(fileFullPath); - - TString sptName = restG4Metadata->GetParticleSource(0)->GetAngularName(); - TH1D* h = (TH1D*)fin.Get(sptName); - - if (!h) { - cout << "REST ERROR when trying to find angular spectrum" << endl; - cout << "File : " << fileFullPath << endl; - cout << "Spectrum name : " << sptName << endl; - exit(1); - } - - fSimulationManager->initialAngularDistribution = *h; - + if (source->GetAngularDistType() == "TH1D") { // We set the initial angular distribution provided from TH1D - SetAngularDistribution(&(fSimulationManager->initialAngularDistribution)); + SetAngularDistributionHistogram(fSimulationManager->GetPrimaryAngularDistribution()); } } PrimaryGeneratorAction::~PrimaryGeneratorAction() = default; -void PrimaryGeneratorAction::SetSpectrum(TH1D* spt, double eMin, double eMax) { - auto xLabel = (TString)spt->GetXaxis()->GetTitle(); +void PrimaryGeneratorAction::SetEnergyDistributionHistogram(const TH1D* h, double eMin, double eMax) { + auto xLabel = (TString)h->GetXaxis()->GetTitle(); if (xLabel.Contains("MeV")) { energyFactor = 1.e3; @@ -93,15 +56,15 @@ void PrimaryGeneratorAction::SetSpectrum(TH1D* spt, double eMin, double eMax) { energyFactor = 1.; } - fSpectrum = spt; - fSpectrumIntegral = fSpectrum->Integral(); + fEnergyDistributionHistogram = h; + fSpectrumIntegral = fEnergyDistributionHistogram->Integral(); startEnergyBin = 1; - endEnergyBin = fSpectrum->GetNbinsX(); + endEnergyBin = fEnergyDistributionHistogram->GetNbinsX(); if (eMin > 0) { for (int i = startEnergyBin; i <= endEnergyBin; i++) { - if (fSpectrum->GetBinCenter(i) > eMin) { + if (fEnergyDistributionHistogram->GetBinCenter(i) > eMin) { startEnergyBin = i; break; } @@ -110,14 +73,14 @@ void PrimaryGeneratorAction::SetSpectrum(TH1D* spt, double eMin, double eMax) { if (eMax > 0) { for (int i = startEnergyBin; i <= endEnergyBin; i++) { - if (fSpectrum->GetBinCenter(i) > eMax) { + if (fEnergyDistributionHistogram->GetBinCenter(i) > eMax) { endEnergyBin = i; break; } } } - fSpectrumIntegral = fSpectrum->Integral(startEnergyBin, endEnergyBin); + fSpectrumIntegral = fEnergyDistributionHistogram->Integral(startEnergyBin, endEnergyBin); } void PrimaryGeneratorAction::SetGeneratorSpatialDensity(TString str) { @@ -261,18 +224,20 @@ void PrimaryGeneratorAction::SetParticleDirection(Int_t n, TRestGeant4Particle p direction = GetIsotropicVector(); } else if (angular_dist_type == g4_metadata_parameters::angular_dist_types::TH1D) { Double_t angle = 0; - Double_t value = G4UniformRand() * (fAngularDistribution->Integral()); + Double_t value = G4UniformRand() * (fAngularDistributionHistogram->Integral()); Double_t sum = 0; // deltaAngle is the constant x distance between bins - Double_t deltaAngle = fAngularDistribution->GetBinCenter(2) - fAngularDistribution->GetBinCenter(1); + Double_t deltaAngle = + fAngularDistributionHistogram->GetBinCenter(2) - fAngularDistributionHistogram->GetBinCenter(1); // we sample the CDF (uniform between 0 and the distribution integral which should be equal to 1) // the inverse of CDF of the uniformly sampled value will follow a distribution given by the PDF, we // compute this inverse - for (int bin = 1; bin <= fAngularDistribution->GetNbinsX(); bin++) { - sum += fAngularDistribution->GetBinContent(bin); + for (int bin = 1; bin <= fAngularDistributionHistogram->GetNbinsX(); bin++) { + sum += fAngularDistributionHistogram->GetBinContent(bin); if (sum >= value) { - angle = fAngularDistribution->GetBinCenter(bin) + deltaAngle * (0.5 - G4UniformRand()); + angle = + fAngularDistributionHistogram->GetBinCenter(bin) + deltaAngle * (0.5 - G4UniformRand()); break; } } @@ -394,13 +359,15 @@ void PrimaryGeneratorAction::SetParticleEnergy(Int_t n, TRestGeant4Particle part } else if (energy_dist_type == g4_metadata_parameters::energy_dist_types::TH1D) { Double_t value = G4UniformRand() * fSpectrumIntegral; Double_t sum = 0; - Double_t deltaEnergy = fSpectrum->GetBinCenter(2) - fSpectrum->GetBinCenter(1); + Double_t deltaEnergy = + fEnergyDistributionHistogram->GetBinCenter(2) - fEnergyDistributionHistogram->GetBinCenter(1); for (int bin = startEnergyBin; bin <= endEnergyBin; bin++) { - sum += fSpectrum->GetBinContent(bin); + sum += fEnergyDistributionHistogram->GetBinContent(bin); if (sum > value) { energy = energyFactor * - (Double_t)(fSpectrum->GetBinCenter(bin) + deltaEnergy * (0.5 - G4UniformRand())) * + (Double_t)(fEnergyDistributionHistogram->GetBinCenter(bin) + + deltaEnergy * (0.5 - G4UniformRand())) * keV; break; } diff --git a/src/RunAction.cxx b/src/RunAction.cxx index 186f85ec..3f0c0058 100644 --- a/src/RunAction.cxx +++ b/src/RunAction.cxx @@ -23,10 +23,12 @@ RunAction::RunAction(SimulationManager* simulationManager) RunAction::~RunAction() {} void RunAction::BeginOfRunAction(const G4Run*) { - G4cout << "========================== Begin of Run Action ========================" << endl; - G4cout << G4RunManager::GetRunManager()->GetNumberOfEventsToBeProcessed() << " events to be simulated" - << endl; - G4cout << "=======================================================================" << endl; + if (G4Threading::IsMasterThread() || !G4Threading::IsMultithreadedApplication()) { + G4cout << "========================== Begin of Run Action ========================" << endl; + G4cout << G4RunManager::GetRunManager()->GetNumberOfEventsToBeProcessed() << " events to be simulated" + << endl; + G4cout << "=======================================================================" << endl; + } auto steppingVerbose = ((SteppingVerbose*)G4VSteppingVerbose::GetInstance()); steppingVerbose->SetSteppingVerbose(1); diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index ee90407a..a095a412 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -6,6 +6,7 @@ #include #include #include +#include #include "SteppingAction.h" @@ -64,6 +65,46 @@ void SimulationManager::WriteEvents() { } } +void SimulationManager::InitializeUserDistributions() { + auto random = []() { return (double)G4UniformRand(); }; // OK: return type is int + + for (int i = 0; i < fRestGeant4Metadata->GetNumberOfSources(); i++) { + fRestGeant4Metadata->GetParticleSource(i)->SetRndmMethod(random); + } + + TRestGeant4ParticleSource* source = fRestGeant4Metadata->GetParticleSource(0); + + if (source->GetEnergyDistType() == "TH1D") { + TFile file(source->GetSpectrumFilename()); + + auto distribution = (TH1D*)file.Get(source->GetSpectrumName()); + + if (!distribution) { + RESTError << "Error when trying to find energy spectrum" << RESTendl; + RESTError << "File: " << source->GetSpectrumFilename() << RESTendl; + RESTError << "Spectrum name: " << source->GetSpectrumName() << RESTendl; + exit(1); + } + + fPrimaryEnergyDistribution = *distribution; + } + + if (source->GetEnergyDistType() == "TH1D") { + TFile file(source->GetAngularFilename()); + + auto distribution = (TH1D*)file.Get(source->GetAngularName()); + + if (!distribution) { + RESTError << "Error when trying to find angular spectrum" << RESTendl; + RESTError << "File: " << source->GetAngularFilename() << RESTendl; + RESTError << "Spectrum name: " << source->GetAngularName() << RESTendl; + exit(1); + } + + fPrimaryAngularDistribution = *distribution; + } +} + // OutputManager OutputManager::OutputManager(const SimulationManager* simulationManager) : fSimulationManager(const_cast(simulationManager)) { From 3423472bd0b3bc3a1b920ee0909a52d8e52b9648 Mon Sep 17 00:00:00 2001 From: lobis Date: Fri, 8 Jul 2022 13:47:29 +0200 Subject: [PATCH 048/173] Application: removed unnecessary line --- src/Application.cxx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Application.cxx b/src/Application.cxx index 8bf99900..d60e4063 100644 --- a/src/Application.cxx +++ b/src/Application.cxx @@ -184,7 +184,6 @@ void Application::Run(const CommandLineParameters& commandLineParameters) { UI->ApplyCommand("/tracking/verbose 0"); UI->ApplyCommand("/run/initialize"); UI->ApplyCommand("/run/beamOn " + to_string(nEvents)); - fSimulationManager->fRestRun->GetOutputFile()->cd(); } else if (nEvents == 0) // define visualization and UI terminal for interactive mode From b483ecc3bfc1e07c67414928d3e824093d1a9e87 Mon Sep 17 00:00:00 2001 From: lobis Date: Fri, 8 Jul 2022 14:35:17 +0200 Subject: [PATCH 049/173] Application: fixing MT --- src/Application.cxx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Application.cxx b/src/Application.cxx index d60e4063..5642bea7 100644 --- a/src/Application.cxx +++ b/src/Application.cxx @@ -213,7 +213,9 @@ void Application::Run(const CommandLineParameters& commandLineParameters) { fSimulationManager->fRestRun->SetEndTimeStamp((Double_t)systime); const TString filename = TRestTools::ToAbsoluteName(fSimulationManager->fRestRun->GetOutputFileName().Data()); - fSimulationManager->fRestRun->UpdateOutputFile(); + + // fSimulationManager->fRestRun->UpdateOutputFile(); // TODO: this line gives segfault when using MT, why? + fSimulationManager->fRestRun->CloseFile(); fSimulationManager->fRestRun->PrintMetadata(); From e717100a811e1dacf9fa73d59c71ac96f32c25d5 Mon Sep 17 00:00:00 2001 From: lobis Date: Fri, 8 Jul 2022 14:40:28 +0200 Subject: [PATCH 050/173] Simplified geometry saving --- src/Application.cxx | 45 ++++++++------------------------------------- 1 file changed, 8 insertions(+), 37 deletions(-) diff --git a/src/Application.cxx b/src/Application.cxx index 5642bea7..81fbdc45 100644 --- a/src/Application.cxx +++ b/src/Application.cxx @@ -216,45 +216,16 @@ void Application::Run(const CommandLineParameters& commandLineParameters) { // fSimulationManager->fRestRun->UpdateOutputFile(); // TODO: this line gives segfault when using MT, why? - fSimulationManager->fRestRun->CloseFile(); - fSimulationManager->fRestRun->PrintMetadata(); - - ////////// Writing the geometry in TGeoManager format to the ROOT file - ////////// Need to fork and do it in child process, to prevent occasional seg.fault - pid_t pid; - pid = fork(); - if (pid < 0) { - perror("fork error:"); - exit(1); - } - // child process - if (pid == 0) { - // writing the geometry object - freopen("/dev/null", "w", stdout); - freopen("/dev/null", "w", stderr); - - REST_Display_CompatibilityMode = true; - - // We wait the father process ends properly - sleep(5); - - // Then we just add the geometry - auto file = new TFile(filename, "update"); - TGeoManager* geoManager = gdml->CreateGeoManager(); - - file->cd(); - geoManager->SetName("Geometry"); - geoManager->Write(); - file->Close(); - exit(0); + TGeoManager* geoManager = gdml->CreateGeoManager(); + if (geoManager) { + geoManager->Write("Geometry"); + delete geoManager; + } else { + cout << "Error: could not create geometry" << endl; } - // father process - else { - int stat_val = 0; - pid_t child_pid; - printf("Writing geometry ... \n"); - } + fSimulationManager->fRestRun->CloseFile(); + fSimulationManager->fRestRun->PrintMetadata(); cout << "============== Generated file: " << filename << " ==============" << endl; auto timeEnd = chrono::steady_clock::now(); From 0e24544f9434694255083a195d5ff1ae97f7caf0 Mon Sep 17 00:00:00 2001 From: lobis Date: Fri, 8 Jul 2022 14:47:51 +0200 Subject: [PATCH 051/173] Added 06 example to ref version --- .github/workflows/validation.yml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/.github/workflows/validation.yml b/.github/workflows/validation.yml index b4f2a2c8..e7eec8b5 100644 --- a/.github/workflows/validation.yml +++ b/.github/workflows/validation.yml @@ -459,6 +459,28 @@ jobs: restG4 NLDBD.rml -o Run00001_NLDBD_Test.root restRoot -b -q Validate.C'("Run00001_NLDBD_Test.root")' + + restG4-examples-06-reference: + name: "Example 06: Ion recoils" + runs-on: ubuntu-latest + container: + image: ghcr.io/lobis/root-geant4-garfield:rest-for-physics-reference-jun2022 + needs: [ framework-install-reference, check-installation-reference ] + steps: + - uses: actions/checkout@v3 + - name: Restore cache + uses: actions/cache@v3 + id: framework-install-restG4-cache-reference + with: + path: ${{ env.REST_PATH }} + key: ${{ env.BRANCH_NAME }}-${{ github.sha }} + - name: Run example + run: | + source ${{ env.REST_PATH }}/thisREST.sh + cd ${{ env.REST_PATH }}/examples/restG4/06.IonRecoils/ + restG4 recoils.rml -o Run00001_F20_Recoils.root + restRoot -b -q Validate.C'("Run00001_F20_Recoils.root")' + restG4-examples-07-reference: name: "Reference Example 07: Decay" runs-on: ubuntu-latest From f7bd4afc53f71e3c4f42f39f39ff2bd8539b20b4 Mon Sep 17 00:00:00 2001 From: lobis Date: Fri, 8 Jul 2022 14:48:42 +0200 Subject: [PATCH 052/173] Added 06 example to ref version - updated name --- .github/workflows/validation.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/validation.yml b/.github/workflows/validation.yml index e7eec8b5..4e11fae7 100644 --- a/.github/workflows/validation.yml +++ b/.github/workflows/validation.yml @@ -461,7 +461,7 @@ jobs: restG4-examples-06-reference: - name: "Example 06: Ion recoils" + name: "Reference Example 06: Ion recoils" runs-on: ubuntu-latest container: image: ghcr.io/lobis/root-geant4-garfield:rest-for-physics-reference-jun2022 From d6b7d7b7280f864e76a25edc99262a708046dc28 Mon Sep 17 00:00:00 2001 From: lobis Date: Mon, 11 Jul 2022 12:25:11 +0200 Subject: [PATCH 053/173] SimulationManager - made rest members private and create accessors --- include/SimulationManager.h | 19 ++++++-- src/Application.cxx | 89 +++++++++++++++++++--------------- src/DetectorConstruction.cxx | 8 +-- src/EventAction.cxx | 7 +-- src/PrimaryGeneratorAction.cxx | 24 ++++----- src/RunAction.cxx | 2 +- src/SimulationManager.cxx | 11 +++-- src/StackingAction.cxx | 2 +- 8 files changed, 90 insertions(+), 72 deletions(-) diff --git a/include/SimulationManager.h b/include/SimulationManager.h index a7024d99..9693024a 100644 --- a/include/SimulationManager.h +++ b/include/SimulationManager.h @@ -17,10 +17,6 @@ class SimulationManager { SimulationManager(); ~SimulationManager(); - TRestRun* fRestRun = nullptr; - TRestGeant4PhysicsLists* fRestGeant4PhysicsLists = nullptr; - TRestGeant4Metadata* fRestGeant4Metadata = nullptr; - void InitializeOutputManager(); static OutputManager* GetOutputManager() { return fOutputManager; } @@ -31,11 +27,26 @@ class SimulationManager { void WriteEvents(); void WriteEventsAndCloseFile(); + public: + inline TRestRun* GetRestRun() const { return fRestRun; } + inline TRestGeant4Metadata* GetRestMetadata() const { return fRestGeant4Metadata; } + inline TRestGeant4PhysicsLists* GetRestPhysicsLists() const { return fRestGeant4PhysicsLists; } + + inline void SetRestRun(TRestRun* run) { fRestRun = run; } + inline void SetRestMetadata(TRestGeant4Metadata* metadata) { fRestGeant4Metadata = metadata; } + inline void SetRestPhysicsLists(TRestGeant4PhysicsLists* physicsLists) { + fRestGeant4PhysicsLists = physicsLists; + } + private: static thread_local OutputManager* fOutputManager; std::mutex fEventContainerMutex; std::queue > fEventContainer; + TRestRun* fRestRun = nullptr; + TRestGeant4PhysicsLists* fRestGeant4PhysicsLists = nullptr; + TRestGeant4Metadata* fRestGeant4Metadata = nullptr; + /* Primary generation */ public: void InitializeUserDistributions(); diff --git a/src/Application.cxx b/src/Application.cxx index 81fbdc45..319cb094 100644 --- a/src/Application.cxx +++ b/src/Application.cxx @@ -73,11 +73,13 @@ void Application::Run(const CommandLineParameters& commandLineParameters) { filesystem::current_path(inputRmlPath); } - fSimulationManager->fRestGeant4Metadata = new TRestGeant4Metadata(inputRmlClean.c_str()); - fSimulationManager->fRestGeant4Metadata->SetGeant4Version(TRestTools::Execute("geant4-config --version")); + auto metadata = new TRestGeant4Metadata(inputRmlClean.c_str()); + fSimulationManager->SetRestMetadata(metadata); + + metadata->SetGeant4Version(TRestTools::Execute("geant4-config --version")); if (!commandLineParameters.geometryFile.IsNull()) { - fSimulationManager->fRestGeant4Metadata->SetGdmlFilename(commandLineParameters.geometryFile.Data()); + metadata->SetGdmlFilename(commandLineParameters.geometryFile.Data()); } // We need to process and generate a new GDML for several reasons. @@ -89,43 +91,59 @@ void Application::Run(const CommandLineParameters& commandLineParameters) { auto gdml = new TRestGDMLParser(); // This call will generate a new single file GDML output - gdml->Load((string)fSimulationManager->fRestGeant4Metadata->GetGdmlFilename()); + gdml->Load((string)metadata->GetGdmlFilename()); // We redefine the value of the GDML file to be used in DetectorConstructor. - fSimulationManager->fRestGeant4Metadata->SetGdmlFilename(gdml->GetOutputGDMLFile()); - fSimulationManager->fRestGeant4Metadata->SetGeometryPath(""); + metadata->SetGdmlFilename(gdml->GetOutputGDMLFile()); + metadata->SetGeometryPath(""); + + metadata->SetGdmlReference(gdml->GetGDMLVersion()); + metadata->SetMaterialsReference(gdml->GetEntityVersion("materials")); - fSimulationManager->fRestGeant4Metadata->SetGdmlReference(gdml->GetGDMLVersion()); - fSimulationManager->fRestGeant4Metadata->SetMaterialsReference(gdml->GetEntityVersion("materials")); + auto physicsLists = new TRestGeant4PhysicsLists(inputRmlClean.c_str()); + fSimulationManager->SetRestPhysicsLists(physicsLists); - fSimulationManager->fRestGeant4PhysicsLists = new TRestGeant4PhysicsLists(inputRmlClean.c_str()); + auto run = new TRestRun(); + fSimulationManager->SetRestRun(run); - fSimulationManager->fRestRun = new TRestRun(); - fSimulationManager->fRestRun->LoadConfigFromFile(inputRmlClean); + run->LoadConfigFromFile(inputRmlClean); if (!commandLineParameters.outputFile.IsNull()) { - fSimulationManager->fRestRun->SetOutputFileName(commandLineParameters.outputFile.Data()); + run->SetOutputFileName(commandLineParameters.outputFile.Data()); } filesystem::current_path(originalDirectory); - TString runTag = fSimulationManager->fRestRun->GetRunTag(); - if (runTag == "Null" || runTag == "") - fSimulationManager->fRestRun->SetRunTag(fSimulationManager->fRestGeant4Metadata->GetTitle()); + TString runTag = run->GetRunTag(); + if (runTag == "Null" || runTag == "") { + run->SetRunTag(metadata->GetTitle()); + } - fSimulationManager->fRestRun->SetRunType("restG4"); + run->SetRunType("restG4"); - fSimulationManager->fRestRun->AddMetadata(fSimulationManager->fRestGeant4Metadata); - fSimulationManager->fRestRun->AddMetadata(fSimulationManager->fRestGeant4PhysicsLists); - fSimulationManager->fRestRun->PrintMetadata(); + run->AddMetadata(fSimulationManager->GetRestMetadata()); + run->AddMetadata(fSimulationManager->GetRestPhysicsLists()); + run->PrintMetadata(); - fSimulationManager->fRestRun->FormOutputFile(); + run->FormOutputFile(); - fSimulationManager->fRestRun->AddEventBranch(&fSimulationManager->fEvent); + run->GetOutputFile()->cd(); + + cout << "Writing geometry into output file" << endl; + TGeoManager* geoManager = gdml->CreateGeoManager(); + if (geoManager) { + geoManager->Write("Geometry"); + // delete geoManager; + } else { + cout << "Error: could not save geometry" << endl; + exit(1); + } + + run->AddEventBranch(&fSimulationManager->fEvent); // choose the Random engine CLHEP::HepRandom::setTheEngine(new CLHEP::RanecuEngine); - long seed = fSimulationManager->fRestGeant4Metadata->GetSeed(); + long seed = metadata->GetSeed(); CLHEP::HepRandom::setTheSeed(seed); G4VSteppingVerbose::SetInstance(new SteppingVerbose(fSimulationManager)); @@ -156,7 +174,7 @@ void Application::Run(const CommandLineParameters& commandLineParameters) { fSimulationManager->InitializeUserDistributions(); runManager->SetUserInitialization(detector); - runManager->SetUserInitialization(new PhysicsList(fSimulationManager->fRestGeant4PhysicsLists)); + runManager->SetUserInitialization(new PhysicsList(fSimulationManager->GetRestPhysicsLists())); runManager->SetUserInitialization(new ActionInitialization(fSimulationManager)); @@ -169,14 +187,14 @@ void Application::Run(const CommandLineParameters& commandLineParameters) { visManager->Initialize(); #endif - const auto nEvents = fSimulationManager->fRestGeant4Metadata->GetNumberOfEvents(); + const auto nEvents = metadata->GetNumberOfEvents(); if (nEvents < 0) { cout << "Error: \"nEvents\" parameter value (" << nEvents << ") is not valid." << endl; exit(1); } time_t systime = time(nullptr); - fSimulationManager->fRestRun->SetStartTimeStamp((Double_t)systime); + run->SetStartTimeStamp((Double_t)systime); cout << "Number of events: " << nEvents << endl; if (nEvents > 0) // batch mode @@ -200,7 +218,7 @@ void Application::Run(const CommandLineParameters& commandLineParameters) { #endif } - fSimulationManager->fRestRun->GetOutputFile()->cd(); + run->GetOutputFile()->cd(); #ifdef G4VIS_USE delete visManager; @@ -210,22 +228,13 @@ void Application::Run(const CommandLineParameters& commandLineParameters) { delete runManager; systime = time(nullptr); - fSimulationManager->fRestRun->SetEndTimeStamp((Double_t)systime); - const TString filename = - TRestTools::ToAbsoluteName(fSimulationManager->fRestRun->GetOutputFileName().Data()); + run->SetEndTimeStamp((Double_t)systime); + const TString filename = TRestTools::ToAbsoluteName(run->GetOutputFileName().Data()); - // fSimulationManager->fRestRun->UpdateOutputFile(); // TODO: this line gives segfault when using MT, why? - - TGeoManager* geoManager = gdml->CreateGeoManager(); - if (geoManager) { - geoManager->Write("Geometry"); - delete geoManager; - } else { - cout << "Error: could not create geometry" << endl; - } + // run->UpdateOutputFile(); // TODO: this line gives segfault when using MT, why? - fSimulationManager->fRestRun->CloseFile(); - fSimulationManager->fRestRun->PrintMetadata(); + run->CloseFile(); + run->PrintMetadata(); cout << "============== Generated file: " << filename << " ==============" << endl; auto timeEnd = chrono::steady_clock::now(); diff --git a/src/DetectorConstruction.cxx b/src/DetectorConstruction.cxx index 971e4869..0f3767ac 100644 --- a/src/DetectorConstruction.cxx +++ b/src/DetectorConstruction.cxx @@ -29,7 +29,7 @@ DetectorConstruction::DetectorConstruction(SimulationManager* simulationManager) DetectorConstruction::~DetectorConstruction() { delete fGdmlParser; } G4VPhysicalVolume* DetectorConstruction::Construct() { - TRestGeant4Metadata* restG4Metadata = fSimulationManager->fRestGeant4Metadata; + TRestGeant4Metadata* restG4Metadata = fSimulationManager->GetRestMetadata(); cout << "Isotope table " << endl; cout << *(G4Isotope::GetIsotopeTable()) << endl; @@ -206,7 +206,7 @@ G4VPhysicalVolume* DetectorConstruction::Construct() { G4VPhysicalVolume* DetectorConstruction::GetPhysicalVolume(const G4String& physVolName) const { G4PhysicalVolumeStore* physVolStore = G4PhysicalVolumeStore::GetInstance(); - TRestGeant4Metadata* restG4Metadata = fSimulationManager->fRestGeant4Metadata; + TRestGeant4Metadata* restG4Metadata = fSimulationManager->GetRestMetadata(); const auto& geometryInfo = restG4Metadata->GetGeant4GeometryInfo(); vector::const_iterator physVol; for (physVol = physVolStore->begin(); physVol != physVolStore->end(); physVol++) { @@ -222,7 +222,7 @@ G4VPhysicalVolume* DetectorConstruction::GetPhysicalVolume(const G4String& physV } void DetectorConstruction::ConstructSDandField() { - const TRestGeant4Metadata& metadata = *fSimulationManager->fRestGeant4Metadata; + const TRestGeant4Metadata& metadata = *fSimulationManager->GetRestMetadata(); vector sensitiveVolumes; // user submitted sensitive volumes, may not exist or not be physical (be logical) for (const auto& volume : {metadata.GetSensitiveVolume()}) { @@ -277,7 +277,7 @@ void DetectorConstruction::ConstructSDandField() { void TRestGeant4GeometryInfo::PopulateFromGeant4World(const G4VPhysicalVolume* world) { auto detector = (DetectorConstruction*)G4RunManager::GetRunManager()->GetUserDetectorConstruction(); - TRestGeant4Metadata* restG4Metadata = detector->fSimulationManager->fRestGeant4Metadata; + TRestGeant4Metadata* restG4Metadata = detector->fSimulationManager->GetRestMetadata(); const int n = int(world->GetLogicalVolume()->GetNoDaughters()); for (int i = 0; i < n + 1; i++) { // world is the + 1 diff --git a/src/EventAction.cxx b/src/EventAction.cxx index 0f05956d..8a02a14e 100644 --- a/src/EventAction.cxx +++ b/src/EventAction.cxx @@ -16,9 +16,6 @@ using namespace std; EventAction::EventAction(SimulationManager* simulationManager) : G4UserEventAction(), fSimulationManager(simulationManager) { fTimer.Start(); - - TRestGeant4Metadata* restG4Metadata = fSimulationManager->fRestGeant4Metadata; - restG4Metadata->isFullChainActivated(); } EventAction::~EventAction() {} @@ -27,8 +24,8 @@ void EventAction::BeginOfEventAction(const G4Event* event) { fSimulationManager->GetOutputManager()->UpdateEvent(); const auto eventID = event->GetEventID(); - TRestRun* restRun = fSimulationManager->fRestRun; - TRestGeant4Metadata* restG4Metadata = fSimulationManager->fRestGeant4Metadata; + TRestRun* restRun = fSimulationManager->GetRestRun(); + TRestGeant4Metadata* restG4Metadata = fSimulationManager->GetRestMetadata(); if (restG4Metadata->GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Debug) { G4cout << "DEBUG: Start of event ID " << eventID << " (" << eventID + 1 << " of " diff --git a/src/PrimaryGeneratorAction.cxx b/src/PrimaryGeneratorAction.cxx index 9a2830e5..a2be2e03 100644 --- a/src/PrimaryGeneratorAction.cxx +++ b/src/PrimaryGeneratorAction.cxx @@ -22,7 +22,7 @@ PrimaryGeneratorAction::PrimaryGeneratorAction(SimulationManager* simulationMana : G4VUserPrimaryGeneratorAction(), fSimulationManager(simulationManager) { fGeneratorSpatialDensityFunction = nullptr; - TRestGeant4Metadata* restG4Metadata = fSimulationManager->fRestGeant4Metadata; + TRestGeant4Metadata* restG4Metadata = fSimulationManager->GetRestMetadata(); TRestGeant4ParticleSource* source = restG4Metadata->GetParticleSource(0); if (source->GetEnergyDistType() == "TH1D") { @@ -95,7 +95,7 @@ void PrimaryGeneratorAction::SetGeneratorSpatialDensity(TString str) { void PrimaryGeneratorAction::GeneratePrimaries(G4Event* event) { auto simulationManager = fSimulationManager; - TRestGeant4Metadata* restG4Metadata = simulationManager->fRestGeant4Metadata; + TRestGeant4Metadata* restG4Metadata = simulationManager->GetRestMetadata(); if (restG4Metadata->GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Debug) { cout << "DEBUG: Primary generation" << endl; @@ -134,7 +134,7 @@ void PrimaryGeneratorAction::GeneratePrimaries(G4Event* event) { G4ParticleDefinition* PrimaryGeneratorAction::SetParticleDefinition(Int_t n, TRestGeant4Particle particle) { auto simulationManager = fSimulationManager; - TRestGeant4Metadata* restG4Metadata = simulationManager->fRestGeant4Metadata; + TRestGeant4Metadata* restG4Metadata = simulationManager->GetRestMetadata(); auto particleName = (string)particle.GetParticleName(); @@ -177,7 +177,7 @@ G4ParticleDefinition* PrimaryGeneratorAction::SetParticleDefinition(Int_t n, TRe void PrimaryGeneratorAction::SetParticleDirection(Int_t n, TRestGeant4Particle particle) { auto simulationManager = fSimulationManager; - TRestGeant4Metadata* restG4Metadata = simulationManager->fRestGeant4Metadata; + TRestGeant4Metadata* restG4Metadata = simulationManager->GetRestMetadata(); G4ThreeVector direction; // TODO: maybe reduce code redundancy by defining some functions? @@ -315,7 +315,7 @@ void PrimaryGeneratorAction::SetParticleDirection(Int_t n, TRestGeant4Particle p void PrimaryGeneratorAction::SetParticleEnergy(Int_t n, TRestGeant4Particle particle) { auto simulationManager = fSimulationManager; - TRestGeant4Metadata* restG4Metadata = simulationManager->fRestGeant4Metadata; + TRestGeant4Metadata* restG4Metadata = simulationManager->GetRestMetadata(); Double_t energy = 0; @@ -400,7 +400,7 @@ void PrimaryGeneratorAction::SetParticleEnergy(Int_t n, TRestGeant4Particle part void PrimaryGeneratorAction::SetParticlePosition() { auto simulationManager = fSimulationManager; - TRestGeant4Metadata* restG4Metadata = simulationManager->fRestGeant4Metadata; + TRestGeant4Metadata* restG4Metadata = simulationManager->GetRestMetadata(); double x = 0, y = 0, z = 0; string generator_type_name = (string)restG4Metadata->GetGeneratorType(); @@ -557,7 +557,7 @@ void PrimaryGeneratorAction::GenPositionOnGDMLSurface(double& x, double& y, doub } void PrimaryGeneratorAction::GenPositionOnBoxVolume(double& x, double& y, double& z) { - TRestGeant4Metadata* restG4Metadata = fSimulationManager->fRestGeant4Metadata; + TRestGeant4Metadata* restG4Metadata = fSimulationManager->GetRestMetadata(); Double_t sidex = restG4Metadata->GetGeneratorSize().X(); Double_t sidey = restG4Metadata->GetGeneratorSize().Y(); @@ -591,7 +591,7 @@ void PrimaryGeneratorAction::GenPositionOnSphereVolume(double& x, double& y, dou } void PrimaryGeneratorAction::GenPositionOnSphereSurface(double& x, double& y, double& z) { - TRestGeant4Metadata* restG4Metadata = fSimulationManager->fRestGeant4Metadata; + TRestGeant4Metadata* restG4Metadata = fSimulationManager->GetRestMetadata(); G4ThreeVector rndPos = GetIsotropicVector(); @@ -610,7 +610,7 @@ void PrimaryGeneratorAction::GenPositionOnCylinderVolume(double& x, double& y, d } void PrimaryGeneratorAction::GenPositionOnCylinderSurface(double& x, double& y, double& z) { - TRestGeant4Metadata* restG4Metadata = fSimulationManager->fRestGeant4Metadata; + TRestGeant4Metadata* restG4Metadata = fSimulationManager->GetRestMetadata(); Double_t angle = 2 * M_PI * G4UniformRand(); @@ -635,7 +635,7 @@ void PrimaryGeneratorAction::GenPositionOnCylinderSurface(double& x, double& y, } void PrimaryGeneratorAction::GenPositionOnPoint(double& x, double& y, double& z) { - TRestGeant4Metadata* restG4Metadata = fSimulationManager->fRestGeant4Metadata; + TRestGeant4Metadata* restG4Metadata = fSimulationManager->GetRestMetadata(); TVector3 position = restG4Metadata->GetGeneratorPosition(); @@ -645,7 +645,7 @@ void PrimaryGeneratorAction::GenPositionOnPoint(double& x, double& y, double& z) } void PrimaryGeneratorAction::GenPositionOnWall(double& x, double& y, double& z) { - TRestGeant4Metadata* restG4Metadata = fSimulationManager->fRestGeant4Metadata; + TRestGeant4Metadata* restG4Metadata = fSimulationManager->GetRestMetadata(); Double_t sidex = restG4Metadata->GetGeneratorSize().X(); Double_t sidey = restG4Metadata->GetGeneratorSize().Y(); @@ -667,7 +667,7 @@ void PrimaryGeneratorAction::GenPositionOnWall(double& x, double& y, double& z) } void PrimaryGeneratorAction::GenPositionOnPlate(double& x, double& y, double& z) { - TRestGeant4Metadata* restG4Metadata = fSimulationManager->fRestGeant4Metadata; + TRestGeant4Metadata* restG4Metadata = fSimulationManager->GetRestMetadata(); Double_t radius = restG4Metadata->GetGeneratorSize().X(); diff --git a/src/RunAction.cxx b/src/RunAction.cxx index 3f0c0058..9737e64f 100644 --- a/src/RunAction.cxx +++ b/src/RunAction.cxx @@ -38,7 +38,7 @@ void RunAction::BeginOfRunAction(const G4Run*) { } void RunAction::EndOfRunAction(const G4Run*) { - TRestRun* restRun = fSimulationManager->fRestRun; + TRestRun* restRun = fSimulationManager->GetRestRun(); if (G4Threading::IsMasterThread() || !G4Threading::IsMultithreadedApplication()) { G4cout << "============================= Run Summary =============================" << endl; diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index a095a412..00ba57cd 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -115,8 +115,9 @@ OutputManager::OutputManager(const SimulationManager* simulationManager) } // initialize active volume lookup set - for (size_t i = 0; i < fSimulationManager->fRestGeant4Metadata->GetNumberOfActiveVolumes(); i++) { - const TString& activeVolume = fSimulationManager->fRestGeant4Metadata->GetActiveVolumeName(i); + const auto metadata = fSimulationManager->GetRestMetadata(); + for (size_t i = 0; i < metadata->GetNumberOfActiveVolumes(); i++) { + const TString& activeVolume = metadata->GetActiveVolumeName(i); fActiveVolumes.insert(activeVolume.Data()); } } @@ -124,14 +125,14 @@ OutputManager::OutputManager(const SimulationManager* simulationManager) void OutputManager::UpdateEvent() { auto event = G4EventManager::GetEventManager()->GetConstCurrentEvent(); fEvent = make_unique(event); - fEvent->InitializeReferences(fSimulationManager->fRestRun); + fEvent->InitializeReferences(fSimulationManager->GetRestRun()); } bool OutputManager::IsEmptyEvent() const { return !fEvent || fEvent->fTracks.empty(); } bool OutputManager::IsValidEvent() const { if (IsEmptyEvent()) return false; - if (fSimulationManager->fRestGeant4Metadata->GetSaveAllEvents()) return true; + if (fSimulationManager->GetRestMetadata()->GetSaveAllEvents()) return true; if (fEvent->GetSensitiveVolumeEnergy() <= 0) return false; return true; } @@ -181,7 +182,7 @@ void OutputManager::RecordStep(const G4Step* step) { fEvent->InsertStep(step); } void OutputManager::AddSensitiveEnergy(Double_t energy, const char* physicalVolumeName) { fEvent->AddEnergyToSensitiveVolume(energy); /* - const TString physicalVolumeNameNew = fSimulationManager->fRestGeant4Metadata->GetGeant4GeometryInfo() + const TString physicalVolumeNameNew = fSimulationManager->GetRestMetadata()->GetGeant4GeometryInfo() .GetAlternativeNameFromGeant4PhysicalName(physicalVolumeName); */ } diff --git a/src/StackingAction.cxx b/src/StackingAction.cxx index fe604084..7328e7e4 100644 --- a/src/StackingAction.cxx +++ b/src/StackingAction.cxx @@ -26,7 +26,7 @@ StackingAction::StackingAction(SimulationManager* simulationManager) : fSimulati G4ClassificationOfNewTrack StackingAction::ClassifyNewTrack(const G4Track* track) { const G4ClassificationOfNewTrack decayClassification = - fSimulationManager->fRestGeant4Metadata->isFullChainActivated() ? fWaiting : fKill; + fSimulationManager->GetRestMetadata()->isFullChainActivated() ? fWaiting : fKill; if (track->GetParentID() <= 0) { // always process the first track regardless return fUrgent; From 8c11bb9eb36649af6bdb10a6a65771f1b01ce6b9 Mon Sep 17 00:00:00 2001 From: lobis Date: Tue, 12 Jul 2022 11:55:56 +0200 Subject: [PATCH 054/173] Application - updated geometry writing --- include/Application.h | 4 ++++ src/Application.cxx | 28 ++++++++++++++++++---------- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/include/Application.h b/include/Application.h index 4acfb36b..bb0c2980 100644 --- a/include/Application.h +++ b/include/Application.h @@ -9,6 +9,8 @@ class G4VisManager; class G4UIExecutive; class G4RunManager; +class TGeoManager; + class Application { public: inline static CommandLineParameters ProcessCommandLineParameters(int argc, char** argv) { @@ -22,6 +24,8 @@ class Application { private: SimulationManager* fSimulationManager = nullptr; + + void WriteGeometry(TGeoManager* geometry, const char* filename, const char* option = "UPDATE"); }; #endif // REST_APPLICATION_H diff --git a/src/Application.cxx b/src/Application.cxx index 319cb094..62de0d23 100644 --- a/src/Application.cxx +++ b/src/Application.cxx @@ -1,6 +1,7 @@ #include "Application.h" +#include #include #include #include @@ -129,16 +130,6 @@ void Application::Run(const CommandLineParameters& commandLineParameters) { run->GetOutputFile()->cd(); - cout << "Writing geometry into output file" << endl; - TGeoManager* geoManager = gdml->CreateGeoManager(); - if (geoManager) { - geoManager->Write("Geometry"); - // delete geoManager; - } else { - cout << "Error: could not save geometry" << endl; - exit(1); - } - run->AddEventBranch(&fSimulationManager->fEvent); // choose the Random engine @@ -236,8 +227,25 @@ void Application::Run(const CommandLineParameters& commandLineParameters) { run->CloseFile(); run->PrintMetadata(); + auto geometry = gdml->CreateGeoManager(); + WriteGeometry(geometry, run->GetOutputFileName()); + delete geometry; + cout << "============== Generated file: " << filename << " ==============" << endl; auto timeEnd = chrono::steady_clock::now(); cout << "Elapsed time: " << chrono::duration_cast(timeEnd - timeStart).count() << " seconds" << endl; } + +void Application::WriteGeometry(TGeoManager* geometry, const char* filename, const char* option) { + auto file = TFile::Open(filename, option); + file->cd(); + cout << "Application::WriteGeometry - Writing geometry into '" << filename << "'" << endl; + if (!geometry) { + cout << "Application::WriteGeometry - Error - Unable to write geometry into file" << endl; + exit(1); + } + geometry->Write("Geometry"); + + file->Close(); +} From 309c4f97e49e056a43ab299567c591f776fc863d Mon Sep 17 00:00:00 2001 From: lobis Date: Tue, 12 Jul 2022 11:56:32 +0200 Subject: [PATCH 055/173] uncommented example --- test/src/examples.cxx | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/src/examples.cxx b/test/src/examples.cxx index 85464188..467dbf06 100644 --- a/test/src/examples.cxx +++ b/test/src/examples.cxx @@ -163,8 +163,6 @@ TEST(restG4, Example_04_Muons) { } TEST(restG4, Example_04_Muons_MT) { - GTEST_SKIP_("Multithreading needs to be implemented"); - // cd into example const auto originalPath = fs::current_path(); const auto thisExamplePath = examplesPath / "04.MuonScan"; From f5d5a6be136c60c24d55ff9cea7346d02b91c050 Mon Sep 17 00:00:00 2001 From: lobis Date: Tue, 12 Jul 2022 12:05:39 +0200 Subject: [PATCH 056/173] Added check for correct TGeoManager in file --- test/src/examples.cxx | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/test/src/examples.cxx b/test/src/examples.cxx index 467dbf06..c0ca3408 100644 --- a/test/src/examples.cxx +++ b/test/src/examples.cxx @@ -1,6 +1,7 @@ #include #include +#include #include #include #include @@ -50,7 +51,7 @@ TEST(restG4, Example_01_NLDBD) { fs::current_path(originalPath); } -TEST(restG4, TRestGeant4GeometryInfo_TRestGeant4PhysicsInfo) { +TEST(restG4, Metadata) { // Test "TRestGeant4GeometryInfo" and "TRestGeant4PhysicsInfo" even though its from Geant4Lib, we need a // simulation file, so we placed the test here @@ -78,6 +79,12 @@ TEST(restG4, TRestGeant4GeometryInfo_TRestGeant4PhysicsInfo) { } TRestRun run(resultsFile); + + /* Check TGeoManager is present on file */ + const TGeoManager* geometry = run.GetInputFile()->Get("Geometry"); + EXPECT_EQ(geometry != nullptr, true); + delete geometry; + // Test `TRestGeant4Metadata::GetUnambiguousGlobalInstance` auto geant4Metadata = (TRestGeant4Metadata*)run.GetMetadataClass("TRestGeant4Metadata"); EXPECT_EQ(geant4Metadata != nullptr, true); From 57f2fc65d753e9ca5681dbf5984864ea3598e811 Mon Sep 17 00:00:00 2001 From: lobis Date: Wed, 13 Jul 2022 11:07:01 +0200 Subject: [PATCH 057/173] DetectorConstruction.cxx - simplified paths --- src/DetectorConstruction.cxx | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/DetectorConstruction.cxx b/src/DetectorConstruction.cxx index 0f3767ac..dcdb7db8 100644 --- a/src/DetectorConstruction.cxx +++ b/src/DetectorConstruction.cxx @@ -15,6 +15,7 @@ #include #include #include +#include #include "SimulationManager.h" @@ -39,26 +40,24 @@ G4VPhysicalVolume* DetectorConstruction::Construct() { // Reading the geometry TString geometryFile = restG4Metadata->GetGdmlFilename(); - char originDirectory[256]; - sprintf(originDirectory, "%s", getenv("PWD")); - auto separatePathAndName = TRestTools::SeparatePathAndName((string)restG4Metadata->GetGdmlFilename()); - chdir(separatePathAndName.first.c_str()); + const auto startingPath = filesystem::current_path(); + + const auto [gdmlPath, gdmlToRead] = + TRestTools::SeparatePathAndName((string)restG4Metadata->GetGdmlFilename()); + filesystem::current_path(gdmlPath); - string gdmlToRead = separatePathAndName.second; G4cout << "gdmlToRead: " << gdmlToRead << G4endl; fGdmlParser->Read(gdmlToRead, false); - - restG4Metadata->fGeant4GeometryInfo.PopulateFromGdml(gdmlToRead); - G4VPhysicalVolume* worldVolume = fGdmlParser->GetWorldVolume(); + restG4Metadata->fGeant4GeometryInfo.PopulateFromGdml(gdmlToRead); restG4Metadata->fGeant4GeometryInfo.PopulateFromGeant4World(worldVolume); const auto& geometryInfo = restG4Metadata->GetGeant4GeometryInfo(); geometryInfo.Print(); - chdir(originDirectory); + filesystem::current_path(startingPath); // TODO : Take the name of the sensitive volume and use it here to define its // StepSize From 303673037c9facd905bd1f6ea84cb751d3771dd8 Mon Sep 17 00:00:00 2001 From: lobis Date: Wed, 13 Jul 2022 17:25:00 +0200 Subject: [PATCH 058/173] Attempt to fix segfaults on MT --- src/Application.cxx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Application.cxx b/src/Application.cxx index 62de0d23..225ba333 100644 --- a/src/Application.cxx +++ b/src/Application.cxx @@ -222,8 +222,7 @@ void Application::Run(const CommandLineParameters& commandLineParameters) { run->SetEndTimeStamp((Double_t)systime); const TString filename = TRestTools::ToAbsoluteName(run->GetOutputFileName().Data()); - // run->UpdateOutputFile(); // TODO: this line gives segfault when using MT, why? - + run->UpdateOutputFile(); run->CloseFile(); run->PrintMetadata(); From 1d9c8877979e689978ffdb97bdeb5a27f0defb41 Mon Sep 17 00:00:00 2001 From: lobis Date: Wed, 13 Jul 2022 17:55:35 +0200 Subject: [PATCH 059/173] updates locking --- include/PrimaryGeneratorAction.h | 8 ++++--- src/PrimaryGeneratorAction.cxx | 37 +++++++++++++++++++------------- 2 files changed, 27 insertions(+), 18 deletions(-) diff --git a/include/PrimaryGeneratorAction.h b/include/PrimaryGeneratorAction.h index 9885bab0..0d7e121b 100644 --- a/include/PrimaryGeneratorAction.h +++ b/include/PrimaryGeneratorAction.h @@ -12,6 +12,7 @@ #include #include #include +#include #include "DetectorConstruction.h" @@ -33,6 +34,7 @@ class PrimaryGeneratorAction : public G4VUserPrimaryGeneratorAction { private: SimulationManager* fSimulationManager; + std::mutex fMutex; std::vector fTempParticles; @@ -53,9 +55,9 @@ class PrimaryGeneratorAction : public G4VUserPrimaryGeneratorAction { Double_t lastEnergy; void SetParticlePosition(); - G4ParticleDefinition* SetParticleDefinition(Int_t particlesourceindex, TRestGeant4Particle particle); - void SetParticleEnergy(Int_t particlesourceindex, TRestGeant4Particle particle); - void SetParticleDirection(Int_t particlesourceindex, TRestGeant4Particle particle); + G4ParticleDefinition* SetParticleDefinition(Int_t particleSourceIndex, TRestGeant4Particle particle); + void SetParticleEnergy(Int_t particleSourceIndex, TRestGeant4Particle particle); + void SetParticleDirection(Int_t particleSourceIndex, TRestGeant4Particle particle); G4ThreeVector GetIsotropicVector(); Double_t GetAngle(G4ThreeVector x, G4ThreeVector y); diff --git a/src/PrimaryGeneratorAction.cxx b/src/PrimaryGeneratorAction.cxx index a2be2e03..b23c7ecf 100644 --- a/src/PrimaryGeneratorAction.cxx +++ b/src/PrimaryGeneratorAction.cxx @@ -94,6 +94,8 @@ void PrimaryGeneratorAction::SetGeneratorSpatialDensity(TString str) { } void PrimaryGeneratorAction::GeneratePrimaries(G4Event* event) { + std::lock_guard lock(fMutex); // TODO: remove this lock after fixing problems + auto simulationManager = fSimulationManager; TRestGeant4Metadata* restG4Metadata = simulationManager->GetRestMetadata(); @@ -132,7 +134,8 @@ void PrimaryGeneratorAction::GeneratePrimaries(G4Event* event) { } } -G4ParticleDefinition* PrimaryGeneratorAction::SetParticleDefinition(Int_t n, TRestGeant4Particle particle) { +G4ParticleDefinition* PrimaryGeneratorAction::SetParticleDefinition(Int_t particleSourceIndex, + TRestGeant4Particle particle) { auto simulationManager = fSimulationManager; TRestGeant4Metadata* restG4Metadata = simulationManager->GetRestMetadata(); @@ -175,7 +178,7 @@ G4ParticleDefinition* PrimaryGeneratorAction::SetParticleDefinition(Int_t n, TRe return fParticle; } -void PrimaryGeneratorAction::SetParticleDirection(Int_t n, TRestGeant4Particle particle) { +void PrimaryGeneratorAction::SetParticleDirection(Int_t particleSourceIndex, TRestGeant4Particle particle) { auto simulationManager = fSimulationManager; TRestGeant4Metadata* restG4Metadata = simulationManager->GetRestMetadata(); @@ -183,7 +186,8 @@ void PrimaryGeneratorAction::SetParticleDirection(Int_t n, TRestGeant4Particle p // TODO: maybe reduce code redundancy by defining some functions? // TODO: fix bug when giving TH1D with lowercase (e.g. Th1D). string conversion is OK but integral gives // exception. - string angular_dist_type_name = (string)restG4Metadata->GetParticleSource(n)->GetAngularDistType(); + string angular_dist_type_name = + (string)restG4Metadata->GetParticleSource(particleSourceIndex)->GetAngularDistType(); angular_dist_type_name = g4_metadata_parameters::CleanString(angular_dist_type_name); g4_metadata_parameters::angular_dist_types angular_dist_type; @@ -243,7 +247,7 @@ void PrimaryGeneratorAction::SetParticleDirection(Int_t n, TRestGeant4Particle p } // Recovering the direction provided at angularDist - TVector3 dirROOT = restG4Metadata->GetParticleSource(n)->GetDirection(); + TVector3 dirROOT = restG4Metadata->GetParticleSource(particleSourceIndex)->GetDirection(); direction.set(dirROOT.X(), dirROOT.Y(), dirROOT.Z()); if (direction.x() == 0 && direction.y() == 0 && direction.z() == 0) { @@ -286,7 +290,7 @@ void PrimaryGeneratorAction::SetParticleDirection(Int_t n, TRestGeant4Particle p } else if (angular_dist_type == g4_metadata_parameters::angular_dist_types::BACK_TO_BACK) { // This should never crash. In TRestG4Metadata we have defined that if the // first source is backtoback we set it to isotropic - // TVector3 v = restG4Event->GetPrimaryEventDirection(n - 1); + // TVector3 v = restG4Event->GetPrimaryEventDirection(particleSourceIndex - 1); // v = v.Unit(); // direction.set(-v.X(), -v.Y(), -v.Z()); @@ -303,23 +307,24 @@ void PrimaryGeneratorAction::SetParticleDirection(Int_t n, TRestGeant4Particle p /* if (restG4Metadata->GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Debug) { cout << "DEBUG: Event direction (normalized): " - << "(" << restG4Event->GetPrimaryEventDirection(n).X() << ", " - << restG4Event->GetPrimaryEventDirection(n).Y() << ", " - << restG4Event->GetPrimaryEventDirection(n).Z() << ")" << endl; + << "(" << restG4Event->GetPrimaryEventDirection(particleSourceIndex).X() << ", " + << restG4Event->GetPrimaryEventDirection(particleSourceIndex).Y() << ", " + << restG4Event->GetPrimaryEventDirection(particleSourceIndex).Z() << ")" << endl; } */ // setting particle direction fParticleGun.SetParticleMomentumDirection(direction); } -void PrimaryGeneratorAction::SetParticleEnergy(Int_t n, TRestGeant4Particle particle) { +void PrimaryGeneratorAction::SetParticleEnergy(Int_t particleSourceIndex, TRestGeant4Particle particle) { auto simulationManager = fSimulationManager; TRestGeant4Metadata* restG4Metadata = simulationManager->GetRestMetadata(); Double_t energy = 0; - auto energy_dist_type_name = (string)restG4Metadata->GetParticleSource(n)->GetEnergyDistType(); + auto energy_dist_type_name = + (string)restG4Metadata->GetParticleSource(particleSourceIndex)->GetEnergyDistType(); energy_dist_type_name = g4_metadata_parameters::CleanString(energy_dist_type_name); if (restG4Metadata->GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Debug) { @@ -348,10 +353,10 @@ void PrimaryGeneratorAction::SetParticleEnergy(Int_t n, TRestGeant4Particle part if (energy_dist_type == g4_metadata_parameters::energy_dist_types::MONO) { energy = particle.GetEnergy() * keV; } else if (energy_dist_type == g4_metadata_parameters::energy_dist_types::FLAT) { - TVector2 enRange = restG4Metadata->GetParticleSource(n)->GetEnergyRange(); + TVector2 enRange = restG4Metadata->GetParticleSource(particleSourceIndex)->GetEnergyRange(); energy = ((enRange.Y() - enRange.X()) * G4UniformRand() + enRange.X()) * keV; } else if (energy_dist_type == g4_metadata_parameters::energy_dist_types::LOG) { - TVector2 enRange = restG4Metadata->GetParticleSource(n)->GetEnergyRange(); + TVector2 enRange = restG4Metadata->GetParticleSource(particleSourceIndex)->GetEnergyRange(); auto max_energy = enRange.Y() * keV; auto min_energy = enRange.X() * keV; energy = exp((log(max_energy) - log(min_energy)) * G4UniformRand() + log(min_energy)); @@ -379,16 +384,18 @@ void PrimaryGeneratorAction::SetParticleEnergy(Int_t n, TRestGeant4Particle part energy = 1 * keV; } - string angular_dist_type_name = (string)restG4Metadata->GetParticleSource(n)->GetAngularDistType(); + string angular_dist_type_name = + (string)restG4Metadata->GetParticleSource(particleSourceIndex)->GetAngularDistType(); angular_dist_type_name = g4_metadata_parameters::CleanString(angular_dist_type_name); g4_metadata_parameters::angular_dist_types angular_dist_type; if (g4_metadata_parameters::angular_dist_types_map.count(angular_dist_type_name)) { angular_dist_type = g4_metadata_parameters::angular_dist_types_map[angular_dist_type_name]; - if (n > 0 && angular_dist_type == g4_metadata_parameters::angular_dist_types::BACK_TO_BACK) + if (particleSourceIndex > 0 && + angular_dist_type == g4_metadata_parameters::angular_dist_types::BACK_TO_BACK) energy = lastEnergy; } - if (n == 0) lastEnergy = energy; + if (particleSourceIndex == 0) lastEnergy = energy; fParticleGun.SetParticleEnergy(energy); // restG4Event->SetPrimaryEventEnergy(energy / keV); From ca499a07bafd52c0a427be2d0491ce3f03585e05 Mon Sep 17 00:00:00 2001 From: lobis Date: Mon, 18 Jul 2022 12:48:11 +0200 Subject: [PATCH 060/173] TRestGeant4PrimaryGeneratorInfo - updated initialization --- src/DetectorConstruction.cxx | 50 +++++++++++++++++------------------- 1 file changed, 24 insertions(+), 26 deletions(-) diff --git a/src/DetectorConstruction.cxx b/src/DetectorConstruction.cxx index dcdb7db8..be37ebe6 100644 --- a/src/DetectorConstruction.cxx +++ b/src/DetectorConstruction.cxx @@ -108,16 +108,17 @@ G4VPhysicalVolume* DetectorConstruction::Construct() { cout << "ERROR : Logical volume for sensitive \"" << sensitiveVolume << "\" not found!" << endl; } + const auto& primaryGeneratorInfo = restG4Metadata->GetGeant4PrimaryGeneratorInfo(); // Getting generation volume - string GenVol = (string)restG4Metadata->GetGeneratedFrom(); - cout << "Generated from volume : " << GenVol << endl; - string type = (string)restG4Metadata->GetGeneratorType(); - cout << "Generator type : " << type << endl; + cout << "Generated from volume : " << primaryGeneratorInfo.GetSpatialGeneratorFrom() << endl; + cout << "Generator type : " << primaryGeneratorInfo.GetSpatialGeneratorType() << endl; // TODO if we do not find the volume given in the config inside the geometry // we should RETURN error - if (type == "volume" && GenVol != "Not defined") { - G4VPhysicalVolume* pVol = GetPhysicalVolume(GenVol); + if (primaryGeneratorInfo.GetSpatialGeneratorType() == + TRestGeant4PrimaryGeneratorTypes::SpatialGeneratorTypes::VOLUME && + primaryGeneratorInfo.GetSpatialGeneratorFrom() != "Not defined") { + G4VPhysicalVolume* pVol = GetPhysicalVolume(primaryGeneratorInfo.GetSpatialGeneratorFrom()); if (pVol == nullptr) { cout << "ERROR : The generator volume was not found in the geometry" << endl; exit(1); @@ -129,27 +130,24 @@ G4VPhysicalVolume* DetectorConstruction::Construct() { // We set in TRestGeant4Metadata the center of the generator. If it is a point // we just want the value from the config file. // TODO : make this kind of keyword comparisons case insensitive? - if (type == "surface" || type == "volume") { - restG4Metadata->SetGeneratorPosition(fGeneratorTranslation.x(), fGeneratorTranslation.y(), - fGeneratorTranslation.z()); + if (primaryGeneratorInfo.GetSpatialGeneratorType() == + TRestGeant4PrimaryGeneratorTypes::SpatialGeneratorTypes::SURFACE || + primaryGeneratorInfo.GetSpatialGeneratorType() == + TRestGeant4PrimaryGeneratorTypes::SpatialGeneratorTypes::VOLUME) { + restG4Metadata->fGeant4PrimaryGeneratorInfo.fSpatialGeneratorPosition = { + fGeneratorTranslation.x(), fGeneratorTranslation.y(), fGeneratorTranslation.z()}; } fGeneratorSolid = pVol->GetLogicalVolume()->GetSolid(); - // while ( fDetector->GetGeneratorSolid()->Inside( G4ThreeVector( x, y, z) ) - // != kInside ); - - // We estimate the maximum distance of our volume - // The code below returns a value bigger than expected - // If we try with a cylinder the maximum distance should be sqrt(R*R+L*L) - // But the value returned by this is bigger TODO check this fBoundBoxXMax = -1.e30; fBoundBoxYMax = -1.e30; fBoundBoxZMax = -1.e30; fBoundBoxXMin = 1.e30; fBoundBoxYMin = 1.e30; fBoundBoxZMin = 1.e30; - if (type == "volume") { + if (primaryGeneratorInfo.GetSpatialGeneratorType() == + TRestGeant4PrimaryGeneratorTypes::SpatialGeneratorTypes::VOLUME) { cout << "Optimizing REST volume generation (Please wait. This might take " "few minutes depending on geometry complexity) " << flush; @@ -178,21 +176,21 @@ G4VPhysicalVolume* DetectorConstruction::Construct() { } for (int id = 0; id < restG4Metadata->GetNumberOfActiveVolumes(); id++) { - TString actVolName = restG4Metadata->GetActiveVolumeName(id); - G4VPhysicalVolume* pVol = GetPhysicalVolume((G4String)actVolName); + TString activeVolumeName = restG4Metadata->GetActiveVolumeName(id); + G4VPhysicalVolume* pVol = GetPhysicalVolume((G4String)activeVolumeName); if (pVol) { G4LogicalVolume* lVol = pVol->GetLogicalVolume(); - if (restG4Metadata->GetMaxStepSize(actVolName) > 0) { - G4cout << "Setting maxStepSize = " << restG4Metadata->GetMaxStepSize(actVolName) - << "mm for volume : " << actVolName << G4endl; - lVol->SetUserLimits(new G4UserLimits(restG4Metadata->GetMaxStepSize(actVolName) * mm)); + if (restG4Metadata->GetMaxStepSize(activeVolumeName) > 0) { + G4cout << "Setting maxStepSize = " << restG4Metadata->GetMaxStepSize(activeVolumeName) + << "mm for volume : " << activeVolumeName << G4endl; + lVol->SetUserLimits(new G4UserLimits(restG4Metadata->GetMaxStepSize(activeVolumeName) * mm)); } } - cout << "Activating volume : " << actVolName << endl; - // restG4Event->AddActiveVolume((string)actVolName); + cout << "Activating volume : " << activeVolumeName << endl; + // restG4Event->AddActiveVolume((string)activeVolumeName); if (!pVol) { - cout << "DetectorConstruction. Volume " << actVolName << " is not defined in the geometry" + cout << "DetectorConstruction. Volume " << activeVolumeName << " is not defined in the geometry" << endl; exit(1); } From 6c9112b75799f640084a0507fbdd6401852246f8 Mon Sep 17 00:00:00 2001 From: lobis Date: Mon, 18 Jul 2022 15:42:49 +0200 Subject: [PATCH 061/173] Simplified generator and TRestGeant4Metadata --- include/PrimaryGeneratorAction.h | 7 +- src/DetectorConstruction.cxx | 24 +-- src/PrimaryGeneratorAction.cxx | 317 +++++++++++++------------------ 3 files changed, 143 insertions(+), 205 deletions(-) diff --git a/include/PrimaryGeneratorAction.h b/include/PrimaryGeneratorAction.h index 0d7e121b..8f2b95b0 100644 --- a/include/PrimaryGeneratorAction.h +++ b/include/PrimaryGeneratorAction.h @@ -55,9 +55,10 @@ class PrimaryGeneratorAction : public G4VUserPrimaryGeneratorAction { Double_t lastEnergy; void SetParticlePosition(); - G4ParticleDefinition* SetParticleDefinition(Int_t particleSourceIndex, TRestGeant4Particle particle); - void SetParticleEnergy(Int_t particleSourceIndex, TRestGeant4Particle particle); - void SetParticleDirection(Int_t particleSourceIndex, TRestGeant4Particle particle); + G4ParticleDefinition* SetParticleDefinition(Int_t particleSourceIndex, + const TRestGeant4Particle& particle); + void SetParticleEnergy(Int_t particleSourceIndex, const TRestGeant4Particle& particle); + void SetParticleDirection(Int_t particleSourceIndex, const TRestGeant4Particle& particle); G4ThreeVector GetIsotropicVector(); Double_t GetAngle(G4ThreeVector x, G4ThreeVector y); diff --git a/src/DetectorConstruction.cxx b/src/DetectorConstruction.cxx index be37ebe6..6182a547 100644 --- a/src/DetectorConstruction.cxx +++ b/src/DetectorConstruction.cxx @@ -20,6 +20,7 @@ #include "SimulationManager.h" using namespace std; +using namespace TRestGeant4PrimaryGeneratorTypes; DetectorConstruction::DetectorConstruction(SimulationManager* simulationManager) : fSimulationManager(simulationManager) { @@ -113,27 +114,23 @@ G4VPhysicalVolume* DetectorConstruction::Construct() { cout << "Generated from volume : " << primaryGeneratorInfo.GetSpatialGeneratorFrom() << endl; cout << "Generator type : " << primaryGeneratorInfo.GetSpatialGeneratorType() << endl; + const auto spatialGeneratorTypeEnum = + StringToSpatialGeneratorTypes(primaryGeneratorInfo.GetSpatialGeneratorType().Data()); + // TODO if we do not find the volume given in the config inside the geometry // we should RETURN error - if (primaryGeneratorInfo.GetSpatialGeneratorType() == - TRestGeant4PrimaryGeneratorTypes::SpatialGeneratorTypes::VOLUME && + if (spatialGeneratorTypeEnum == TRestGeant4PrimaryGeneratorTypes::SpatialGeneratorTypes::VOLUME && primaryGeneratorInfo.GetSpatialGeneratorFrom() != "Not defined") { - G4VPhysicalVolume* pVol = GetPhysicalVolume(primaryGeneratorInfo.GetSpatialGeneratorFrom()); + G4VPhysicalVolume* pVol = GetPhysicalVolume(primaryGeneratorInfo.GetSpatialGeneratorFrom().Data()); if (pVol == nullptr) { - cout << "ERROR : The generator volume was not found in the geometry" << endl; + cout << "ERROR: The generator volume was not found in the geometry" << endl; exit(1); return worldVolume; } fGeneratorTranslation = pVol->GetTranslation(); - - // We set in TRestGeant4Metadata the center of the generator. If it is a point - // we just want the value from the config file. - // TODO : make this kind of keyword comparisons case insensitive? - if (primaryGeneratorInfo.GetSpatialGeneratorType() == - TRestGeant4PrimaryGeneratorTypes::SpatialGeneratorTypes::SURFACE || - primaryGeneratorInfo.GetSpatialGeneratorType() == - TRestGeant4PrimaryGeneratorTypes::SpatialGeneratorTypes::VOLUME) { + if (spatialGeneratorTypeEnum == TRestGeant4PrimaryGeneratorTypes::SpatialGeneratorTypes::SURFACE || + spatialGeneratorTypeEnum == TRestGeant4PrimaryGeneratorTypes::SpatialGeneratorTypes::VOLUME) { restG4Metadata->fGeant4PrimaryGeneratorInfo.fSpatialGeneratorPosition = { fGeneratorTranslation.x(), fGeneratorTranslation.y(), fGeneratorTranslation.z()}; } @@ -146,8 +143,7 @@ G4VPhysicalVolume* DetectorConstruction::Construct() { fBoundBoxXMin = 1.e30; fBoundBoxYMin = 1.e30; fBoundBoxZMin = 1.e30; - if (primaryGeneratorInfo.GetSpatialGeneratorType() == - TRestGeant4PrimaryGeneratorTypes::SpatialGeneratorTypes::VOLUME) { + if (spatialGeneratorTypeEnum == TRestGeant4PrimaryGeneratorTypes::SpatialGeneratorTypes::VOLUME) { cout << "Optimizing REST volume generation (Please wait. This might take " "few minutes depending on geometry complexity) " << flush; diff --git a/src/PrimaryGeneratorAction.cxx b/src/PrimaryGeneratorAction.cxx index b23c7ecf..2aa18c86 100644 --- a/src/PrimaryGeneratorAction.cxx +++ b/src/PrimaryGeneratorAction.cxx @@ -3,6 +3,7 @@ #include #include +#include #include #include @@ -17,6 +18,7 @@ #include "SimulationManager.h" using namespace std; +using namespace TRestGeant4PrimaryGeneratorTypes; PrimaryGeneratorAction::PrimaryGeneratorAction(SimulationManager* simulationManager) : G4VUserPrimaryGeneratorAction(), fSimulationManager(simulationManager) { @@ -135,7 +137,7 @@ void PrimaryGeneratorAction::GeneratePrimaries(G4Event* event) { } G4ParticleDefinition* PrimaryGeneratorAction::SetParticleDefinition(Int_t particleSourceIndex, - TRestGeant4Particle particle) { + const TRestGeant4Particle& particle) { auto simulationManager = fSimulationManager; TRestGeant4Metadata* restG4Metadata = simulationManager->GetRestMetadata(); @@ -178,57 +180,33 @@ G4ParticleDefinition* PrimaryGeneratorAction::SetParticleDefinition(Int_t partic return fParticle; } -void PrimaryGeneratorAction::SetParticleDirection(Int_t particleSourceIndex, TRestGeant4Particle particle) { +void PrimaryGeneratorAction::SetParticleDirection(Int_t particleSourceIndex, + const TRestGeant4Particle& particle) { auto simulationManager = fSimulationManager; TRestGeant4Metadata* restG4Metadata = simulationManager->GetRestMetadata(); + const auto& primaryGeneratorInfo = restG4Metadata->GetGeant4PrimaryGeneratorInfo(); G4ThreeVector direction; - // TODO: maybe reduce code redundancy by defining some functions? - // TODO: fix bug when giving TH1D with lowercase (e.g. Th1D). string conversion is OK but integral gives - // exception. - string angular_dist_type_name = + const string angularDistTypeName = (string)restG4Metadata->GetParticleSource(particleSourceIndex)->GetAngularDistType(); - angular_dist_type_name = g4_metadata_parameters::CleanString(angular_dist_type_name); - g4_metadata_parameters::angular_dist_types angular_dist_type; + const auto angularDistTypeEnum = StringToAngularDistributionTypes(angularDistTypeName); if (restG4Metadata->GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Debug) { - cout << "DEBUG: Angular distribution: " << angular_dist_type_name << endl; - } - // we first check if it is a valid parameter - if (g4_metadata_parameters::angular_dist_types_map.count(angular_dist_type_name)) { - angular_dist_type = g4_metadata_parameters::angular_dist_types_map[angular_dist_type_name]; - } else { - // if we get here it means the parameter is not valid, we can either assign a default value or stop - // execution default value - cout << "Invalid angular distribution (" + angular_dist_type_name + ") valid values are: "; - for (const auto& pair : g4_metadata_parameters::angular_dist_types_map) { - cout << pair.first << ", "; - } - cout << endl; - throw "Invalid angular distribution"; + cout << "DEBUG: Angular distribution: " << angularDistTypeName << endl; } + // generator type - string generator_type_name = (string)restG4Metadata->GetGeneratorType(); - generator_type_name = g4_metadata_parameters::CleanString(generator_type_name); - g4_metadata_parameters::generator_types generator_type; - if (g4_metadata_parameters::generator_types_map.count(generator_type_name)) { - generator_type = g4_metadata_parameters::generator_types_map[generator_type_name]; - } else { - // if we get here it means the parameter is not valid, we can either assign a default value or stop - // execution default value - cout << "Invalid generator type (" + generator_type_name + ") valid values are: "; - for (const auto& pair : g4_metadata_parameters::generator_types_map) { - cout << pair.first << ", "; - } - cout << endl; - throw "Invalid generator type"; - } + const string& spatialGeneratorTypeName = primaryGeneratorInfo.GetSpatialGeneratorType().Data(); + const auto spatialGeneratorTypeEnum = StringToSpatialGeneratorTypes(spatialGeneratorTypeName); - if (angular_dist_type == g4_metadata_parameters::angular_dist_types::ISOTROPIC) { + const string& spatialGeneratorShapeName = primaryGeneratorInfo.GetSpatialGeneratorShape().Data(); + const auto spatialGeneratorShapeEnum = StringToSpatialGeneratorShapes(spatialGeneratorShapeName); + + if (angularDistTypeEnum == AngularDistributionTypes::ISOTROPIC) { direction = GetIsotropicVector(); - } else if (angular_dist_type == g4_metadata_parameters::angular_dist_types::TH1D) { + } else if (angularDistTypeEnum == AngularDistributionTypes::TH1D) { Double_t angle = 0; - Double_t value = G4UniformRand() * (fAngularDistributionHistogram->Integral()); + Double_t value = G4UniformRand() * fAngularDistributionHistogram->Integral(); Double_t sum = 0; // deltaAngle is the constant x distance between bins Double_t deltaAngle = @@ -247,14 +225,12 @@ void PrimaryGeneratorAction::SetParticleDirection(Int_t particleSourceIndex, TRe } // Recovering the direction provided at angularDist - TVector3 dirROOT = restG4Metadata->GetParticleSource(particleSourceIndex)->GetDirection(); + const TVector3& dirROOT = restG4Metadata->GetParticleSource(particleSourceIndex)->GetDirection(); direction.set(dirROOT.X(), dirROOT.Y(), dirROOT.Z()); if (direction.x() == 0 && direction.y() == 0 && direction.z() == 0) { - cout << "----------------------------------------------------------------" - "-----" - << endl; - cout << "REST WARNNING : Particle being launched from the ORIGIN!! Wrong " + cout << "---------------------------------------------------------------------" << endl; + cout << "REST WARNING : Particle being launched from the ORIGIN!! Wrong " "momentum direction!" << endl; cout << "Setting direction to (1,0,0)" << endl; @@ -265,9 +241,7 @@ void PrimaryGeneratorAction::SetParticleDirection(Int_t particleSourceIndex, TRe "event\n with a distribution direction to the origin of " "coordinates" << endl; - cout << "----------------------------------------------------------------" - "-----" - << endl; + cout << "---------------------------------------------------------------------" << endl; direction.set(1, 0, 0); } G4ThreeVector referenceOrigin = direction; @@ -280,16 +254,16 @@ void PrimaryGeneratorAction::SetParticleDirection(Int_t particleSourceIndex, TRe Double_t randomAngle = G4UniformRand() * 2 * M_PI; direction.rotate(randomAngle, referenceOrigin); - } else if (angular_dist_type == g4_metadata_parameters::angular_dist_types::FLUX) { + } else if (angularDistTypeEnum == AngularDistributionTypes::FLUX) { TVector3 v = particle.GetMomentumDirection(); v = v.Unit(); direction.set(v.X(), v.Y(), v.Z()); - } else if (angular_dist_type == g4_metadata_parameters::angular_dist_types::BACK_TO_BACK) { + } else if (angularDistTypeEnum == AngularDistributionTypes::BACK_TO_BACK) { // This should never crash. In TRestG4Metadata we have defined that if the - // first source is backtoback we set it to isotropic + // first source is back to back we set it to isotropic // TVector3 v = restG4Event->GetPrimaryEventDirection(particleSourceIndex - 1); // v = v.Unit(); @@ -301,67 +275,42 @@ void PrimaryGeneratorAction::SetParticleDirection(Int_t particleSourceIndex, TRe << G4endl; } - // storing the direction in TRestG4Event class - TVector3 eventDirection(direction.x(), direction.y(), direction.z()); - // restG4Event->SetPrimaryEventDirection(eventDirection); - /* - if (restG4Metadata->GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Debug) { - cout << "DEBUG: Event direction (normalized): " - << "(" << restG4Event->GetPrimaryEventDirection(particleSourceIndex).X() << ", " - << restG4Event->GetPrimaryEventDirection(particleSourceIndex).Y() << ", " - << restG4Event->GetPrimaryEventDirection(particleSourceIndex).Z() << ")" << endl; - } - */ - // setting particle direction fParticleGun.SetParticleMomentumDirection(direction); } -void PrimaryGeneratorAction::SetParticleEnergy(Int_t particleSourceIndex, TRestGeant4Particle particle) { +void PrimaryGeneratorAction::SetParticleEnergy(Int_t particleSourceIndex, + const TRestGeant4Particle& particle) { auto simulationManager = fSimulationManager; TRestGeant4Metadata* restG4Metadata = simulationManager->GetRestMetadata(); + const auto& primaryGeneratorInfo = restG4Metadata->GetGeant4PrimaryGeneratorInfo(); - Double_t energy = 0; + const string angularDistTypeName = + restG4Metadata->GetParticleSource(particleSourceIndex)->GetAngularDistType().Data(); + const auto angularDistTypeEnum = StringToAngularDistributionTypes(angularDistTypeName); - auto energy_dist_type_name = - (string)restG4Metadata->GetParticleSource(particleSourceIndex)->GetEnergyDistType(); - energy_dist_type_name = g4_metadata_parameters::CleanString(energy_dist_type_name); + const string energyDistTypeName = + restG4Metadata->GetParticleSource(particleSourceIndex)->GetEnergyDistType().Data(); + const auto energyDistTypeEnum = StringToEnergyDistributionTypes(energyDistTypeName); if (restG4Metadata->GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Debug) { - cout << "DEBUG: Energy distribution: " << energy_dist_type_name << endl; + cout << "DEBUG: Energy distribution: " << energyDistTypeName << endl; } - g4_metadata_parameters::energy_dist_types energy_dist_type; - if (g4_metadata_parameters::energy_dist_types_map.count(energy_dist_type_name)) { - energy_dist_type = g4_metadata_parameters::energy_dist_types_map[energy_dist_type_name]; - } else { - // if we get here it means the parameter is not valid, we can either assign a default value or stop - // execution default value in this case is 1 keV - cout << "Invalid energy distribution (" + energy_dist_type_name + ") valid values are: "; - for (const auto& pair : g4_metadata_parameters::energy_dist_types_map) { - cout << pair.first << ", "; - } - cout << endl; - G4cout << "WARNING! Energy distribution type was not recognized. Setting " - "energy to 1keV" - << G4endl; - energy = 1 * keV; - // maybe it would be better to set type as mono and change energy of particle, or define the default - // energy there throw "Invalid energy distribution type"; - } + Double_t energy = 1 * keV; - if (energy_dist_type == g4_metadata_parameters::energy_dist_types::MONO) { + if (energyDistTypeEnum == EnergyDistributionTypes::MONO) { energy = particle.GetEnergy() * keV; - } else if (energy_dist_type == g4_metadata_parameters::energy_dist_types::FLAT) { + } else if (energyDistTypeEnum == EnergyDistributionTypes::FLAT) { TVector2 enRange = restG4Metadata->GetParticleSource(particleSourceIndex)->GetEnergyRange(); energy = ((enRange.Y() - enRange.X()) * G4UniformRand() + enRange.X()) * keV; - } else if (energy_dist_type == g4_metadata_parameters::energy_dist_types::LOG) { + } else if (energyDistTypeEnum == EnergyDistributionTypes::LOG) { TVector2 enRange = restG4Metadata->GetParticleSource(particleSourceIndex)->GetEnergyRange(); auto max_energy = enRange.Y() * keV; auto min_energy = enRange.X() * keV; energy = exp((log(max_energy) - log(min_energy)) * G4UniformRand() + log(min_energy)); - } else if (energy_dist_type == g4_metadata_parameters::energy_dist_types::TH1D) { + } else if (energyDistTypeEnum == EnergyDistributionTypes::TH1D) { Double_t value = G4UniformRand() * fSpectrumIntegral; Double_t sum = 0; Double_t deltaEnergy = @@ -384,18 +333,19 @@ void PrimaryGeneratorAction::SetParticleEnergy(Int_t particleSourceIndex, TRestG energy = 1 * keV; } - string angular_dist_type_name = - (string)restG4Metadata->GetParticleSource(particleSourceIndex)->GetAngularDistType(); - angular_dist_type_name = g4_metadata_parameters::CleanString(angular_dist_type_name); - g4_metadata_parameters::angular_dist_types angular_dist_type; + /* + * TODO: take a look into this if (g4_metadata_parameters::angular_dist_types_map.count(angular_dist_type_name)) { angular_dist_type = g4_metadata_parameters::angular_dist_types_map[angular_dist_type_name]; if (particleSourceIndex > 0 && angular_dist_type == g4_metadata_parameters::angular_dist_types::BACK_TO_BACK) energy = lastEnergy; } + */ - if (particleSourceIndex == 0) lastEnergy = energy; + if (particleSourceIndex == 0) { + lastEnergy = energy; + } fParticleGun.SetParticleEnergy(energy); // restG4Event->SetPrimaryEventEnergy(energy / keV); @@ -408,46 +358,45 @@ void PrimaryGeneratorAction::SetParticlePosition() { auto simulationManager = fSimulationManager; TRestGeant4Metadata* restG4Metadata = simulationManager->GetRestMetadata(); + const auto& primaryGeneratorInfo = restG4Metadata->GetGeant4PrimaryGeneratorInfo(); - double x = 0, y = 0, z = 0; - string generator_type_name = (string)restG4Metadata->GetGeneratorType(); - g4_metadata_parameters::generator_types generator_type = - g4_metadata_parameters::generator_types_map[g4_metadata_parameters::CleanString(generator_type_name)]; + const string& spatialGeneratorTypeName = primaryGeneratorInfo.GetSpatialGeneratorType().Data(); + const auto spatialGeneratorTypeEnum = StringToSpatialGeneratorTypes(spatialGeneratorTypeName); - string generator_shape_name = (string)restG4Metadata->GetGeneratorShape(); - g4_metadata_parameters::generator_shapes generator_shape = - g4_metadata_parameters::generator_shapes_map[g4_metadata_parameters::CleanString( - generator_shape_name)]; + const string& spatialGeneratorShapeName = primaryGeneratorInfo.GetSpatialGeneratorShape().Data(); + const auto spatialGeneratorShapeEnum = StringToSpatialGeneratorShapes(spatialGeneratorShapeName); + + double x = 0, y = 0, z = 0; while (true) { - if (generator_type == g4_metadata_parameters::generator_types::POINT) { + if (spatialGeneratorTypeEnum == SpatialGeneratorTypes::POINT) { GenPositionOnPoint(x, y, z); - } else if (generator_type == g4_metadata_parameters::generator_types::SURFACE) { - if (generator_shape == g4_metadata_parameters::generator_shapes::GDML) { + } else if (spatialGeneratorTypeEnum == SpatialGeneratorTypes::SURFACE) { + if (spatialGeneratorShapeEnum == SpatialGeneratorShapes::GDML) { GenPositionOnGDMLSurface(x, y, z); - } else if (generator_shape == g4_metadata_parameters::generator_shapes::BOX) { + } else if (spatialGeneratorShapeEnum == SpatialGeneratorShapes::BOX) { GenPositionOnBoxSurface(x, y, z); - } else if (generator_shape == g4_metadata_parameters::generator_shapes::CYLINDER) { + } else if (spatialGeneratorShapeEnum == SpatialGeneratorShapes::CYLINDER) { GenPositionOnCylinderSurface(x, y, z); - } else if (generator_shape == g4_metadata_parameters::generator_shapes::SPHERE) { + } else if (spatialGeneratorShapeEnum == SpatialGeneratorShapes::SPHERE) { GenPositionOnSphereSurface(x, y, z); - } else if (generator_shape == g4_metadata_parameters::generator_shapes::CIRCLE) { + } else if (spatialGeneratorShapeEnum == SpatialGeneratorShapes::CIRCLE) { GenPositionOnPlate(x, y, z); - } else if (generator_shape == g4_metadata_parameters::generator_shapes::WALL) { + } else if (spatialGeneratorShapeEnum == SpatialGeneratorShapes::WALL) { GenPositionOnWall(x, y, z); } - } else if (generator_type == g4_metadata_parameters::generator_types::VOLUME) { - if (generator_shape == g4_metadata_parameters::generator_shapes::GDML) { + } else if (spatialGeneratorTypeEnum == SpatialGeneratorTypes::VOLUME) { + if (spatialGeneratorShapeEnum == SpatialGeneratorShapes::GDML) { GenPositionOnGDMLVolume(x, y, z); - } else if (generator_shape == g4_metadata_parameters::generator_shapes::BOX) { + } else if (spatialGeneratorShapeEnum == SpatialGeneratorShapes::BOX) { GenPositionOnBoxVolume(x, y, z); - } else if (generator_shape == g4_metadata_parameters::generator_shapes::CYLINDER) { + } else if (spatialGeneratorShapeEnum == SpatialGeneratorShapes::CYLINDER) { GenPositionOnCylinderVolume(x, y, z); - } else if (generator_shape == g4_metadata_parameters::generator_shapes::SPHERE) { + } else if (spatialGeneratorShapeEnum == SpatialGeneratorShapes::SPHERE) { GenPositionOnSphereVolume(x, y, z); } } else { - G4cout << "WARNING! Generator type \"" << restG4Metadata->GetGeneratorType() + G4cout << "WARNING! Generator type \"" << spatialGeneratorTypeName << "\" was not recognized. Launching particle " "from origin (0,0,0)" << G4endl; @@ -461,7 +410,7 @@ void PrimaryGeneratorAction::SetParticlePosition() { if (val2 > 1) { cout << "error! Generator density function > 1 at position (" << x << ", " << y << ", " << z << "), check your definition!" << endl; - abort(); + exit(1); } if (val1 > val2) { continue; @@ -470,19 +419,6 @@ void PrimaryGeneratorAction::SetParticlePosition() { break; } - // storing the direction in TRestG4Event class - TVector3 eventPosition(x, y, z); - // restG4Event->SetPrimaryEventOrigin(eventPosition); - /* - if (restG4Metadata->GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Debug) { - cout << "DEBUG: Event origin: " - << "(" << restG4Event->GetPrimaryEventOrigin().X() << ", " - << restG4Event->GetPrimaryEventOrigin().Y() << ", " << restG4Event->GetPrimaryEventOrigin().Z() - << ")" - << " mm" << endl; - } - */ - // setting particle position fParticleGun.SetParticlePosition(G4ThreeVector(x, y, z)); } @@ -565,86 +501,90 @@ void PrimaryGeneratorAction::GenPositionOnGDMLSurface(double& x, double& y, doub void PrimaryGeneratorAction::GenPositionOnBoxVolume(double& x, double& y, double& z) { TRestGeant4Metadata* restG4Metadata = fSimulationManager->GetRestMetadata(); + const auto& primaryGeneratorInfo = restG4Metadata->GetGeant4PrimaryGeneratorInfo(); - Double_t sidex = restG4Metadata->GetGeneratorSize().X(); - Double_t sidey = restG4Metadata->GetGeneratorSize().Y(); - Double_t sidez = restG4Metadata->GetGeneratorSize().Z(); + Double_t sizeX = primaryGeneratorInfo.GetSpatialGeneratorSize().X(); + Double_t sizeY = primaryGeneratorInfo.GetSpatialGeneratorSize().Y(); + Double_t sizeZ = primaryGeneratorInfo.GetSpatialGeneratorSize().Z(); - x = sidex * (G4UniformRand() - 0.5); - y = sidey * (G4UniformRand() - 0.5); - z = sidez * (G4UniformRand() - 0.5); + x = sizeX * (G4UniformRand() - 0.5); + y = sizeY * (G4UniformRand() - 0.5); + z = sizeZ * (G4UniformRand() - 0.5); - G4ThreeVector rndPos = G4ThreeVector(x, y, z); + G4ThreeVector position = G4ThreeVector(x, y, z); - TVector3 rotaxis = restG4Metadata->GetGeneratorRotationAxis(); - G4ThreeVector rotaxisG4 = G4ThreeVector(rotaxis.x(), rotaxis.y(), rotaxis.z()); - rndPos.rotate(rotaxisG4, restG4Metadata->GetGeneratorRotationDegree()); + const TVector3& rotationAxis = primaryGeneratorInfo.GetSpatialGeneratorRotationAxis(); + G4ThreeVector rotationAxisG4 = G4ThreeVector(rotationAxis.x(), rotationAxis.y(), rotationAxis.z()); + position.rotate(rotationAxisG4, primaryGeneratorInfo.GetSpatialGeneratorRotationValue()); - TVector3 center = restG4Metadata->GetGeneratorPosition(); + const TVector3& center = primaryGeneratorInfo.GetSpatialGeneratorPosition(); - x = rndPos.x() + center.X(); - y = rndPos.y() + center.Y(); - z = rndPos.z() + center.Z(); + x = position.x() + center.X(); + y = position.y() + center.Y(); + z = position.z() + center.Z(); } void PrimaryGeneratorAction::GenPositionOnBoxSurface(double& x, double& y, double& z) { cout << __PRETTY_FUNCTION__ << ": not implemented!" << endl; - abort(); + exit(1); } void PrimaryGeneratorAction::GenPositionOnSphereVolume(double& x, double& y, double& z) { cout << __PRETTY_FUNCTION__ << ": not implemented!" << endl; - abort(); + exit(1); } void PrimaryGeneratorAction::GenPositionOnSphereSurface(double& x, double& y, double& z) { TRestGeant4Metadata* restG4Metadata = fSimulationManager->GetRestMetadata(); + const auto& primaryGeneratorInfo = restG4Metadata->GetGeant4PrimaryGeneratorInfo(); - G4ThreeVector rndPos = GetIsotropicVector(); + G4ThreeVector position = GetIsotropicVector(); - Double_t radius = restG4Metadata->GetGeneratorSize().X(); + const Double_t radius = primaryGeneratorInfo.GetSpatialGeneratorSize().X(); - TVector3 center = restG4Metadata->GetGeneratorPosition(); + const TVector3& center = primaryGeneratorInfo.GetSpatialGeneratorPosition(); - x = radius * rndPos.x() + center.X(); - y = radius * rndPos.y() + center.Y(); - z = radius * rndPos.z() + center.Z(); + x = radius * position.x() + center.X(); + y = radius * position.y() + center.Y(); + z = radius * position.z() + center.Z(); } void PrimaryGeneratorAction::GenPositionOnCylinderVolume(double& x, double& y, double& z) { cout << __PRETTY_FUNCTION__ << ": not implemented!" << endl; - abort(); + exit(1); } void PrimaryGeneratorAction::GenPositionOnCylinderSurface(double& x, double& y, double& z) { TRestGeant4Metadata* restG4Metadata = fSimulationManager->GetRestMetadata(); + const auto& primaryGeneratorInfo = restG4Metadata->GetGeant4PrimaryGeneratorInfo(); Double_t angle = 2 * M_PI * G4UniformRand(); - Double_t radius = restG4Metadata->GetGeneratorSize().x(); - Double_t length = restG4Metadata->GetGeneratorSize().y(); + const Double_t radius = primaryGeneratorInfo.GetSpatialGeneratorSize().X(); + const Double_t length = primaryGeneratorInfo.GetSpatialGeneratorSize().Y(); x = radius * cos(angle); y = radius * sin(angle); z = length * (G4UniformRand() - 0.5); - G4ThreeVector rndPos = G4ThreeVector(x, y, z); + G4ThreeVector position = G4ThreeVector(x, y, z); - TVector3 rotaxis = restG4Metadata->GetGeneratorRotationAxis(); - G4ThreeVector rotaxisG4 = G4ThreeVector(rotaxis.x(), rotaxis.y(), rotaxis.z()); - rndPos.rotate(rotaxisG4, restG4Metadata->GetGeneratorRotationDegree()); + const TVector3& rotationAxis = primaryGeneratorInfo.GetSpatialGeneratorRotationAxis(); + G4ThreeVector rotationAxisG4 = G4ThreeVector(rotationAxis.x(), rotationAxis.y(), rotationAxis.z()); + position.rotate(rotationAxisG4, primaryGeneratorInfo.GetSpatialGeneratorRotationValue()); - TVector3 center = restG4Metadata->GetGeneratorPosition(); + const TVector3& center = primaryGeneratorInfo.GetSpatialGeneratorPosition(); - x = rndPos.x() + center.X(); - y = rndPos.y() + center.Y(); - z = rndPos.z() + center.Z(); + x = position.x() + center.X(); + y = position.y() + center.Y(); + z = position.z() + center.Z(); } void PrimaryGeneratorAction::GenPositionOnPoint(double& x, double& y, double& z) { TRestGeant4Metadata* restG4Metadata = fSimulationManager->GetRestMetadata(); + const auto& primaryGeneratorInfo = restG4Metadata->GetGeant4PrimaryGeneratorInfo(); - TVector3 position = restG4Metadata->GetGeneratorPosition(); + const TVector3& position = primaryGeneratorInfo.GetSpatialGeneratorPosition(); x = position.X(); y = position.Y(); @@ -653,46 +593,47 @@ void PrimaryGeneratorAction::GenPositionOnPoint(double& x, double& y, double& z) void PrimaryGeneratorAction::GenPositionOnWall(double& x, double& y, double& z) { TRestGeant4Metadata* restG4Metadata = fSimulationManager->GetRestMetadata(); + const auto& primaryGeneratorInfo = restG4Metadata->GetGeant4PrimaryGeneratorInfo(); - Double_t sidex = restG4Metadata->GetGeneratorSize().X(); - Double_t sidey = restG4Metadata->GetGeneratorSize().Y(); + const Double_t sizeX = primaryGeneratorInfo.GetSpatialGeneratorSize().X(); + const Double_t sizeY = primaryGeneratorInfo.GetSpatialGeneratorSize().Y(); - x = sidex * (G4UniformRand() - 0.5); - y = sidey * (G4UniformRand() - 0.5); + x = sizeX * (G4UniformRand() - 0.5); + y = sizeY * (G4UniformRand() - 0.5); - G4ThreeVector rndPos = G4ThreeVector(x, y, 0); + G4ThreeVector position = G4ThreeVector(x, y, 0); - TVector3 rotaxis = restG4Metadata->GetGeneratorRotationAxis(); - G4ThreeVector rotaxisG4 = G4ThreeVector(rotaxis.x(), rotaxis.y(), rotaxis.z()); - rndPos.rotate(rotaxisG4, restG4Metadata->GetGeneratorRotationDegree()); + const TVector3& rotationAxis = primaryGeneratorInfo.GetSpatialGeneratorRotationAxis(); + G4ThreeVector rotationAxisG4 = G4ThreeVector(rotationAxis.x(), rotationAxis.y(), rotationAxis.z()); + position.rotate(rotationAxisG4, primaryGeneratorInfo.GetSpatialGeneratorRotationValue()); - TVector3 center = restG4Metadata->GetGeneratorPosition(); + const TVector3& center = primaryGeneratorInfo.GetSpatialGeneratorPosition(); - x = rndPos.x() + center.X(); - y = rndPos.y() + center.Y(); - z = rndPos.z() + center.Z(); + x = position.x() + center.X(); + y = position.y() + center.Y(); + z = position.z() + center.Z(); } void PrimaryGeneratorAction::GenPositionOnPlate(double& x, double& y, double& z) { TRestGeant4Metadata* restG4Metadata = fSimulationManager->GetRestMetadata(); + const auto& primaryGeneratorInfo = restG4Metadata->GetGeant4PrimaryGeneratorInfo(); - Double_t radius = restG4Metadata->GetGeneratorSize().X(); + const Double_t radius = primaryGeneratorInfo.GetSpatialGeneratorSize().X(); do { x = 2 * radius * (G4UniformRand() - 0.5); y = 2 * radius * (G4UniformRand() - 0.5); - // cout << "x : " << x << " y : " << y << endl; } while (x * x + y * y > radius * radius); - G4ThreeVector rndPos = G4ThreeVector(x, y, 0); + G4ThreeVector position = G4ThreeVector(x, y, 0); - TVector3 rotaxis = restG4Metadata->GetGeneratorRotationAxis(); - G4ThreeVector rotaxisG4 = G4ThreeVector(rotaxis.x(), rotaxis.y(), rotaxis.z()); - rndPos.rotate(rotaxisG4, restG4Metadata->GetGeneratorRotationDegree()); + const TVector3& rotationAxis = primaryGeneratorInfo.GetSpatialGeneratorRotationAxis(); + G4ThreeVector rotationAxisG4 = G4ThreeVector(rotationAxis.x(), rotationAxis.y(), rotationAxis.z()); + position.rotate(rotationAxisG4, primaryGeneratorInfo.GetSpatialGeneratorRotationValue()); - TVector3 center = restG4Metadata->GetGeneratorPosition(); + const TVector3& center = primaryGeneratorInfo.GetSpatialGeneratorPosition(); - x = rndPos.x() + center.X(); - y = rndPos.y() + center.Y(); - z = rndPos.z() + center.Z(); + x = position.x() + center.X(); + y = position.y() + center.Y(); + z = position.z() + center.Z(); } From d829348158cfa5671f95b8b0310c54c227be8016 Mon Sep 17 00:00:00 2001 From: lobis Date: Mon, 18 Jul 2022 15:46:21 +0200 Subject: [PATCH 062/173] PrimaryGeneratorAction - addressed TODO --- include/PrimaryGeneratorAction.h | 2 +- src/PrimaryGeneratorAction.cxx | 15 ++++----------- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/include/PrimaryGeneratorAction.h b/include/PrimaryGeneratorAction.h index 8f2b95b0..ec1925f2 100644 --- a/include/PrimaryGeneratorAction.h +++ b/include/PrimaryGeneratorAction.h @@ -60,7 +60,7 @@ class PrimaryGeneratorAction : public G4VUserPrimaryGeneratorAction { void SetParticleEnergy(Int_t particleSourceIndex, const TRestGeant4Particle& particle); void SetParticleDirection(Int_t particleSourceIndex, const TRestGeant4Particle& particle); - G4ThreeVector GetIsotropicVector(); + G4ThreeVector GetIsotropicVector() const; Double_t GetAngle(G4ThreeVector x, G4ThreeVector y); Double_t GetCosineLowRandomThetaAngle(); diff --git a/src/PrimaryGeneratorAction.cxx b/src/PrimaryGeneratorAction.cxx index 2aa18c86..d6d8fd20 100644 --- a/src/PrimaryGeneratorAction.cxx +++ b/src/PrimaryGeneratorAction.cxx @@ -333,23 +333,16 @@ void PrimaryGeneratorAction::SetParticleEnergy(Int_t particleSourceIndex, energy = 1 * keV; } - /* - * TODO: take a look into this - if (g4_metadata_parameters::angular_dist_types_map.count(angular_dist_type_name)) { - angular_dist_type = g4_metadata_parameters::angular_dist_types_map[angular_dist_type_name]; - if (particleSourceIndex > 0 && - angular_dist_type == g4_metadata_parameters::angular_dist_types::BACK_TO_BACK) - energy = lastEnergy; + if (particleSourceIndex > 0 && + angularDistTypeEnum == TRestGeant4PrimaryGeneratorTypes::AngularDistributionTypes::BACK_TO_BACK) { + energy = lastEnergy; } - */ if (particleSourceIndex == 0) { lastEnergy = energy; } fParticleGun.SetParticleEnergy(energy); - // restG4Event->SetPrimaryEventEnergy(energy / keV); - if (restG4Metadata->GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Debug) cout << "DEBUG: Particle energy: " << energy / keV << " keV" << endl; } @@ -422,7 +415,7 @@ void PrimaryGeneratorAction::SetParticlePosition() { fParticleGun.SetParticlePosition(G4ThreeVector(x, y, z)); } -G4ThreeVector PrimaryGeneratorAction::GetIsotropicVector() { +G4ThreeVector PrimaryGeneratorAction::GetIsotropicVector() const { G4double a, b, c; G4double n; do { From 0826ccaa61c0028e59c6e93379e1debb1cf8e9d5 Mon Sep 17 00:00:00 2001 From: lobis Date: Tue, 19 Jul 2022 10:43:08 +0200 Subject: [PATCH 063/173] DetectorConstruction - raised error when from vol not found --- src/DetectorConstruction.cxx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/DetectorConstruction.cxx b/src/DetectorConstruction.cxx index 6182a547..c9d749c1 100644 --- a/src/DetectorConstruction.cxx +++ b/src/DetectorConstruction.cxx @@ -117,13 +117,12 @@ G4VPhysicalVolume* DetectorConstruction::Construct() { const auto spatialGeneratorTypeEnum = StringToSpatialGeneratorTypes(primaryGeneratorInfo.GetSpatialGeneratorType().Data()); - // TODO if we do not find the volume given in the config inside the geometry - // we should RETURN error if (spatialGeneratorTypeEnum == TRestGeant4PrimaryGeneratorTypes::SpatialGeneratorTypes::VOLUME && primaryGeneratorInfo.GetSpatialGeneratorFrom() != "Not defined") { G4VPhysicalVolume* pVol = GetPhysicalVolume(primaryGeneratorInfo.GetSpatialGeneratorFrom().Data()); if (pVol == nullptr) { - cout << "ERROR: The generator volume was not found in the geometry" << endl; + cout << "ERROR: The generator volume '" << primaryGeneratorInfo.GetSpatialGeneratorFrom() + << "'was not found in the geometry" << endl; exit(1); return worldVolume; } From 104c933be7ca49b4feef423eaff483e532a21507 Mon Sep 17 00:00:00 2001 From: lobis Date: Tue, 19 Jul 2022 11:28:23 +0200 Subject: [PATCH 064/173] Starting to add formula support for angular/energy dist --- src/SimulationManager.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index 00ba57cd..ee27ee89 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -69,7 +69,7 @@ void SimulationManager::InitializeUserDistributions() { auto random = []() { return (double)G4UniformRand(); }; // OK: return type is int for (int i = 0; i < fRestGeant4Metadata->GetNumberOfSources(); i++) { - fRestGeant4Metadata->GetParticleSource(i)->SetRndmMethod(random); + fRestGeant4Metadata->GetParticleSource(i)->setRandomMethod(random); } TRestGeant4ParticleSource* source = fRestGeant4Metadata->GetParticleSource(0); From 5793f6ec5afd88fc086b324a327658825308e3a3 Mon Sep 17 00:00:00 2001 From: lobis Date: Tue, 19 Jul 2022 12:50:59 +0200 Subject: [PATCH 065/173] TRestGeant4Metadata - updated some member names --- src/PrimaryGeneratorAction.cxx | 23 +++++++++++++---------- src/SimulationManager.cxx | 26 ++++++++++++-------------- 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/src/PrimaryGeneratorAction.cxx b/src/PrimaryGeneratorAction.cxx index d6d8fd20..59b49f44 100644 --- a/src/PrimaryGeneratorAction.cxx +++ b/src/PrimaryGeneratorAction.cxx @@ -27,11 +27,11 @@ PrimaryGeneratorAction::PrimaryGeneratorAction(SimulationManager* simulationMana TRestGeant4Metadata* restG4Metadata = fSimulationManager->GetRestMetadata(); TRestGeant4ParticleSource* source = restG4Metadata->GetParticleSource(0); - if (source->GetEnergyDistType() == "TH1D") { - Double_t minEnergy = source->GetMinEnergy(); + if (source->GetEnergyDistributionType() == "TH1D") { + Double_t minEnergy = source->GetEnergyDistributionRangeMin(); if (minEnergy < 0) minEnergy = 0; - Double_t maxEnergy = source->GetMaxEnergy(); + Double_t maxEnergy = source->GetEnergyDistributionRangeMax(); if (maxEnergy < 0) maxEnergy = 0; // We set the initial spectrum energy provided from TH1D @@ -39,7 +39,7 @@ PrimaryGeneratorAction::PrimaryGeneratorAction(SimulationManager* simulationMana maxEnergy); } - if (source->GetAngularDistType() == "TH1D") { + if (source->GetAngularDistributionType() == "TH1D") { // We set the initial angular distribution provided from TH1D SetAngularDistributionHistogram(fSimulationManager->GetPrimaryAngularDistribution()); } @@ -188,7 +188,7 @@ void PrimaryGeneratorAction::SetParticleDirection(Int_t particleSourceIndex, G4ThreeVector direction; const string angularDistTypeName = - (string)restG4Metadata->GetParticleSource(particleSourceIndex)->GetAngularDistType(); + (string)restG4Metadata->GetParticleSource(particleSourceIndex)->GetAngularDistributionType(); const auto angularDistTypeEnum = StringToAngularDistributionTypes(angularDistTypeName); if (restG4Metadata->GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Debug) { @@ -286,11 +286,11 @@ void PrimaryGeneratorAction::SetParticleEnergy(Int_t particleSourceIndex, const auto& primaryGeneratorInfo = restG4Metadata->GetGeant4PrimaryGeneratorInfo(); const string angularDistTypeName = - restG4Metadata->GetParticleSource(particleSourceIndex)->GetAngularDistType().Data(); + restG4Metadata->GetParticleSource(particleSourceIndex)->GetAngularDistributionType().Data(); const auto angularDistTypeEnum = StringToAngularDistributionTypes(angularDistTypeName); const string energyDistTypeName = - restG4Metadata->GetParticleSource(particleSourceIndex)->GetEnergyDistType().Data(); + restG4Metadata->GetParticleSource(particleSourceIndex)->GetEnergyDistributionType().Data(); const auto energyDistTypeEnum = StringToEnergyDistributionTypes(energyDistTypeName); if (restG4Metadata->GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Debug) { @@ -302,10 +302,12 @@ void PrimaryGeneratorAction::SetParticleEnergy(Int_t particleSourceIndex, if (energyDistTypeEnum == EnergyDistributionTypes::MONO) { energy = particle.GetEnergy() * keV; } else if (energyDistTypeEnum == EnergyDistributionTypes::FLAT) { - TVector2 enRange = restG4Metadata->GetParticleSource(particleSourceIndex)->GetEnergyRange(); + TVector2 enRange = + restG4Metadata->GetParticleSource(particleSourceIndex)->GetEnergyDistributionRange(); energy = ((enRange.Y() - enRange.X()) * G4UniformRand() + enRange.X()) * keV; } else if (energyDistTypeEnum == EnergyDistributionTypes::LOG) { - TVector2 enRange = restG4Metadata->GetParticleSource(particleSourceIndex)->GetEnergyRange(); + TVector2 enRange = + restG4Metadata->GetParticleSource(particleSourceIndex)->GetEnergyDistributionRange(); auto max_energy = enRange.Y() * keV; auto min_energy = enRange.X() * keV; energy = exp((log(max_energy) - log(min_energy)) * G4UniformRand() + log(min_energy)); @@ -343,8 +345,9 @@ void PrimaryGeneratorAction::SetParticleEnergy(Int_t particleSourceIndex, } fParticleGun.SetParticleEnergy(energy); - if (restG4Metadata->GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Debug) + if (restG4Metadata->GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Debug) { cout << "DEBUG: Particle energy: " << energy / keV << " keV" << endl; + } } void PrimaryGeneratorAction::SetParticlePosition() { diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index ee27ee89..f1f0d1b3 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -66,38 +66,36 @@ void SimulationManager::WriteEvents() { } void SimulationManager::InitializeUserDistributions() { - auto random = []() { return (double)G4UniformRand(); }; // OK: return type is int + auto random = []() { return (double)G4UniformRand(); }; for (int i = 0; i < fRestGeant4Metadata->GetNumberOfSources(); i++) { - fRestGeant4Metadata->GetParticleSource(i)->setRandomMethod(random); + fRestGeant4Metadata->GetParticleSource(i)->SetRandomMethod(random); } TRestGeant4ParticleSource* source = fRestGeant4Metadata->GetParticleSource(0); - if (source->GetEnergyDistType() == "TH1D") { - TFile file(source->GetSpectrumFilename()); - - auto distribution = (TH1D*)file.Get(source->GetSpectrumName()); + if (source->GetEnergyDistributionType() == "TH1D") { + TFile file(source->GetEnergyDistributionFilename()); + auto distribution = (TH1D*)file.Get(source->GetEnergyDistributionNameInFile()); if (!distribution) { RESTError << "Error when trying to find energy spectrum" << RESTendl; - RESTError << "File: " << source->GetSpectrumFilename() << RESTendl; - RESTError << "Spectrum name: " << source->GetSpectrumName() << RESTendl; + RESTError << "File: " << source->GetEnergyDistributionFilename() << RESTendl; + RESTError << "Spectrum name: " << source->GetEnergyDistributionNameInFile() << RESTendl; exit(1); } fPrimaryEnergyDistribution = *distribution; } - if (source->GetEnergyDistType() == "TH1D") { - TFile file(source->GetAngularFilename()); - - auto distribution = (TH1D*)file.Get(source->GetAngularName()); + if (source->GetEnergyDistributionType() == "TH1D") { + TFile file(source->GetAngularDistributionFilename()); + auto distribution = (TH1D*)file.Get(source->GetAngularDistributionNameInFile()); if (!distribution) { RESTError << "Error when trying to find angular spectrum" << RESTendl; - RESTError << "File: " << source->GetAngularFilename() << RESTendl; - RESTError << "Spectrum name: " << source->GetAngularName() << RESTendl; + RESTError << "File: " << source->GetAngularDistributionFilename() << RESTendl; + RESTError << "Spectrum name: " << source->GetAngularDistributionNameInFile() << RESTendl; exit(1); } From c72f4fbd60ebd802d20e189619fbde53499434d3 Mon Sep 17 00:00:00 2001 From: lobis Date: Tue, 19 Jul 2022 13:50:59 +0200 Subject: [PATCH 066/173] Using random cos2 angle from formula instead of th1d --- examples/04.MuonScan/CosmicMuonsFromWall.rml | 2 +- include/PrimaryGeneratorAction.h | 3 + src/PrimaryGeneratorAction.cxx | 65 ++++++++------------ src/SimulationManager.cxx | 8 ++- 4 files changed, 37 insertions(+), 41 deletions(-) diff --git a/examples/04.MuonScan/CosmicMuonsFromWall.rml b/examples/04.MuonScan/CosmicMuonsFromWall.rml index a88d5574..8841f797 100644 --- a/examples/04.MuonScan/CosmicMuonsFromWall.rml +++ b/examples/04.MuonScan/CosmicMuonsFromWall.rml @@ -30,7 +30,7 @@ First concept author G. Luzón (16-11-2020) --> rotationAxis="(1,0,0)"> - + diff --git a/include/PrimaryGeneratorAction.h b/include/PrimaryGeneratorAction.h index ec1925f2..f796b07f 100644 --- a/include/PrimaryGeneratorAction.h +++ b/include/PrimaryGeneratorAction.h @@ -4,6 +4,7 @@ #include #include +#include #include #include @@ -54,6 +55,8 @@ class PrimaryGeneratorAction : public G4VUserPrimaryGeneratorAction { Double_t lastEnergy; + TRandom* fRandom = nullptr; + void SetParticlePosition(); G4ParticleDefinition* SetParticleDefinition(Int_t particleSourceIndex, const TRestGeant4Particle& particle); diff --git a/src/PrimaryGeneratorAction.cxx b/src/PrimaryGeneratorAction.cxx index 59b49f44..fccc318b 100644 --- a/src/PrimaryGeneratorAction.cxx +++ b/src/PrimaryGeneratorAction.cxx @@ -1,6 +1,7 @@ #include "PrimaryGeneratorAction.h" +#include #include #include #include @@ -125,12 +126,9 @@ void PrimaryGeneratorAction::GeneratePrimaries(G4Event* event) { for (const auto& p : particles) { // ParticleDefinition should be always declared first (after position). SetParticleDefinition(i, p); - // Particle Direction must be always set before energy SetParticleEnergy(i, p); - SetParticleDirection(i, p); - fParticleGun.GeneratePrimaryVertex(event); } } @@ -149,7 +147,6 @@ G4ParticleDefinition* PrimaryGeneratorAction::SetParticleDefinition(Int_t partic if (restG4Metadata->GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Debug) { cout << "DEBUG: Particle name: " << particleName << endl; - // cout << "DEBUG: Particle charge: " << charge << endl; cout << "DEBUG: Particle excited energy: " << excitedEnergy << " keV" << endl; } @@ -184,11 +181,14 @@ void PrimaryGeneratorAction::SetParticleDirection(Int_t particleSourceIndex, const TRestGeant4Particle& particle) { auto simulationManager = fSimulationManager; TRestGeant4Metadata* restG4Metadata = simulationManager->GetRestMetadata(); + TRestGeant4ParticleSource* source = restG4Metadata->GetParticleSource(0); + const auto& primaryGeneratorInfo = restG4Metadata->GetGeant4PrimaryGeneratorInfo(); - G4ThreeVector direction; - const string angularDistTypeName = - (string)restG4Metadata->GetParticleSource(particleSourceIndex)->GetAngularDistributionType(); + G4ThreeVector direction = {source->GetDirection().X(), source->GetDirection().Y(), + source->GetDirection().Z()}; + + const string angularDistTypeName = source->GetAngularDistributionType().Data(); const auto angularDistTypeEnum = StringToAngularDistributionTypes(angularDistTypeName); if (restG4Metadata->GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Debug) { @@ -216,7 +216,6 @@ void PrimaryGeneratorAction::SetParticleDirection(Int_t particleSourceIndex, // compute this inverse for (int bin = 1; bin <= fAngularDistributionHistogram->GetNbinsX(); bin++) { sum += fAngularDistributionHistogram->GetBinContent(bin); - if (sum >= value) { angle = fAngularDistributionHistogram->GetBinCenter(bin) + deltaAngle * (0.5 - G4UniformRand()); @@ -224,41 +223,32 @@ void PrimaryGeneratorAction::SetParticleDirection(Int_t particleSourceIndex, } } - // Recovering the direction provided at angularDist - const TVector3& dirROOT = restG4Metadata->GetParticleSource(particleSourceIndex)->GetDirection(); - direction.set(dirROOT.X(), dirROOT.Y(), dirROOT.Z()); - - if (direction.x() == 0 && direction.y() == 0 && direction.z() == 0) { - cout << "---------------------------------------------------------------------" << endl; - cout << "REST WARNING : Particle being launched from the ORIGIN!! Wrong " - "momentum direction!" - << endl; - cout << "Setting direction to (1,0,0)" << endl; - cout << "REST angular distribution is just implemented for virtualBox " - "and virtualSphere" - << endl; - cout << "Other spatial distributions can be set but it will launch the " - "event\n with a distribution direction to the origin of " - "coordinates" - << endl; - cout << "---------------------------------------------------------------------" << endl; - direction.set(1, 0, 0); - } G4ThreeVector referenceOrigin = direction; // We generate the distribution angle (theta) using a rotation around the orthogonal vector - G4ThreeVector orthoVector = direction.orthogonal(); - direction.rotate(angle, orthoVector); + direction.rotate(angle, direction.orthogonal()); // We rotate a full-2PI random angle along the original direction to generate a cone - Double_t randomAngle = G4UniformRand() * 2 * M_PI; - direction.rotate(randomAngle, referenceOrigin); + direction.rotate(G4UniformRand() * 2 * M_PI, referenceOrigin); - } else if (angularDistTypeEnum == AngularDistributionTypes::FLUX) { - TVector3 v = particle.GetMomentumDirection(); + } else if (angularDistTypeEnum == AngularDistributionTypes::FORMULA) { + auto formulaEnum = + StringToAngularDistributionFormulas(source->GetAngularDistributionFormulaString().Data()); + TF1 function = AngularDistributionFormulasToRootFormula(formulaEnum); + + G4ThreeVector referenceOrigin = direction; - v = v.Unit(); + if (fRandom == nullptr) { + fRandom = new TRandom(restG4Metadata->GetSeed() + G4Threading::G4GetThreadId()); + } + // We generate the distribution angle (theta) using a rotation around the orthogonal vector + direction.rotate(function.GetRandom(fRandom), direction.orthogonal()); + // We rotate a full-2PI random angle along the original direction to generate a cone + direction.rotate(G4UniformRand() * 2 * M_PI, referenceOrigin); + + } else if (angularDistTypeEnum == AngularDistributionTypes::FLUX) { + const TVector3& v = particle.GetMomentumDirection().Unit(); direction.set(v.X(), v.Y(), v.Z()); } else if (angularDistTypeEnum == AngularDistributionTypes::BACK_TO_BACK) { @@ -270,9 +260,8 @@ void PrimaryGeneratorAction::SetParticleDirection(Int_t particleSourceIndex, // direction.set(-v.X(), -v.Y(), -v.Z()); exit(1); } else { - G4cout << "WARNING: Generator angular distribution was not recognized. " - "Launching particle to (1,0,0)" - << G4endl; + G4cout << "WARNING: Generator angular distribution was not recognized. Particle direction set to (" + << direction.x() << ", " << direction.y() << ", " << direction.z() << ")" << G4endl; } fParticleGun.SetParticleMomentumDirection(direction); diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index f1f0d1b3..2b00269a 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -74,7 +74,9 @@ void SimulationManager::InitializeUserDistributions() { TRestGeant4ParticleSource* source = fRestGeant4Metadata->GetParticleSource(0); - if (source->GetEnergyDistributionType() == "TH1D") { + if (TRestGeant4PrimaryGeneratorTypes::StringToEnergyDistributionTypes( + source->GetEnergyDistributionType().Data()) == + TRestGeant4PrimaryGeneratorTypes::EnergyDistributionTypes::TH1D) { TFile file(source->GetEnergyDistributionFilename()); auto distribution = (TH1D*)file.Get(source->GetEnergyDistributionNameInFile()); @@ -88,7 +90,9 @@ void SimulationManager::InitializeUserDistributions() { fPrimaryEnergyDistribution = *distribution; } - if (source->GetEnergyDistributionType() == "TH1D") { + if (TRestGeant4PrimaryGeneratorTypes::StringToAngularDistributionTypes( + source->GetAngularDistributionType().Data()) == + TRestGeant4PrimaryGeneratorTypes::AngularDistributionTypes::TH1D) { TFile file(source->GetAngularDistributionFilename()); auto distribution = (TH1D*)file.Get(source->GetAngularDistributionNameInFile()); From b8a38598ec8faf75763f377e38d83b0bfd3143e0 Mon Sep 17 00:00:00 2001 From: lobis Date: Tue, 19 Jul 2022 14:12:41 +0200 Subject: [PATCH 067/173] PrimaryGeneratorAction - implemented generator energy from formula --- src/PrimaryGeneratorAction.cxx | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/src/PrimaryGeneratorAction.cxx b/src/PrimaryGeneratorAction.cxx index fccc318b..175755fd 100644 --- a/src/PrimaryGeneratorAction.cxx +++ b/src/PrimaryGeneratorAction.cxx @@ -28,19 +28,24 @@ PrimaryGeneratorAction::PrimaryGeneratorAction(SimulationManager* simulationMana TRestGeant4Metadata* restG4Metadata = fSimulationManager->GetRestMetadata(); TRestGeant4ParticleSource* source = restG4Metadata->GetParticleSource(0); - if (source->GetEnergyDistributionType() == "TH1D") { - Double_t minEnergy = source->GetEnergyDistributionRangeMin(); - if (minEnergy < 0) minEnergy = 0; + const string angularDistTypeName = source->GetAngularDistributionType().Data(); + const auto angularDistTypeEnum = StringToAngularDistributionTypes(angularDistTypeName); + + const string energyDistTypeName = source->GetEnergyDistributionType().Data(); + const auto energyDistTypeEnum = StringToEnergyDistributionTypes(energyDistTypeName); + + fRandom = new TRandom(restG4Metadata->GetSeed() + TRandom(G4Threading::G4GetThreadId()).Integer(1E9)); + if (energyDistTypeEnum == EnergyDistributionTypes::TH1D) { + Double_t minEnergy = source->GetEnergyDistributionRangeMin(); Double_t maxEnergy = source->GetEnergyDistributionRangeMax(); - if (maxEnergy < 0) maxEnergy = 0; // We set the initial spectrum energy provided from TH1D SetEnergyDistributionHistogram(fSimulationManager->GetPrimaryEnergyDistribution(), minEnergy, maxEnergy); } - if (source->GetAngularDistributionType() == "TH1D") { + if (angularDistTypeEnum == AngularDistributionTypes::TH1D) { // We set the initial angular distribution provided from TH1D SetAngularDistributionHistogram(fSimulationManager->GetPrimaryAngularDistribution()); } @@ -238,9 +243,6 @@ void PrimaryGeneratorAction::SetParticleDirection(Int_t particleSourceIndex, G4ThreeVector referenceOrigin = direction; - if (fRandom == nullptr) { - fRandom = new TRandom(restG4Metadata->GetSeed() + G4Threading::G4GetThreadId()); - } // We generate the distribution angle (theta) using a rotation around the orthogonal vector direction.rotate(function.GetRandom(fRandom), direction.orthogonal()); @@ -272,6 +274,7 @@ void PrimaryGeneratorAction::SetParticleEnergy(Int_t particleSourceIndex, auto simulationManager = fSimulationManager; TRestGeant4Metadata* restG4Metadata = simulationManager->GetRestMetadata(); + TRestGeant4ParticleSource* source = restG4Metadata->GetParticleSource(0); const auto& primaryGeneratorInfo = restG4Metadata->GetGeant4PrimaryGeneratorInfo(); const string angularDistTypeName = @@ -317,6 +320,14 @@ void PrimaryGeneratorAction::SetParticleEnergy(Int_t particleSourceIndex, break; } } + } else if (energyDistTypeEnum == EnergyDistributionTypes::FORMULA) { + auto formulaEnum = + StringToEnergyDistributionFormulas(source->GetEnergyDistributionFormulaString().Data()); + TF1 function = EnergyDistributionFormulasToRootFormula(formulaEnum); + + energy = function.GetRandom(source->GetEnergyDistributionRangeMin(), + source->GetEnergyDistributionRangeMax(), fRandom) * + keV; } else { G4cout << "WARNING! Energy distribution type was not recognized. Setting " "energy to 1keV" From 806dee64fd87b10bfe2709fec3914aaa2a25544e Mon Sep 17 00:00:00 2001 From: lobis Date: Tue, 19 Jul 2022 20:56:24 +0200 Subject: [PATCH 068/173] Updated parameter names preserving backwards comp --- examples/01.NLDBD/NLDBD.rml | 4 ++-- examples/02.TREXDM/FullChainFromReadout.rml | 4 ++-- examples/03.Fluorescence/electron.rml | 4 ++-- examples/03.Fluorescence/gamma.rml | 4 ++-- examples/04.MuonScan/CosmicMuonsFromCircle.rml | 4 ++-- examples/04.MuonScan/CosmicMuonsFromWall.rml | 4 ++-- examples/04.MuonScan/Muon.rml | 4 ++-- examples/05.PandaXIII/geometry/Th232_SS_01.rml | 4 ++-- examples/06.IonRecoils/recoils.rml | 4 ++-- examples/07.FullChainDecay/fullChain.rml | 4 ++-- examples/07.FullChainDecay/singleDecay.rml | 4 ++-- examples/08.Alphas/alphas.rml | 4 ++-- examples/09.Pb210_Shield/Pb210.rml | 4 ++-- examples/10.Geometries/Assembly.rml | 4 ++-- examples/11.Xrays/xrays.rml | 4 ++-- examples/v2.1.7/pandaXIII/biasing/externalTh232.rml | 4 ++-- examples/v2.1.7/pandaXIII/biasing/externalU238.rml | 4 ++-- .../pandaXIII/templates/biasedIsotopeFromVirtualBox.rml | 4 ++-- examples/v2.1.7/pandaXIII/templates/isotopeFromPoint.rml | 4 ++-- examples/v2.1.7/pandaXIII/templates/isotopeFromVCylinder.rml | 4 ++-- examples/v2.1.7/pandaXIII/templates/isotopeFromVolume.rml | 4 ++-- 21 files changed, 42 insertions(+), 42 deletions(-) diff --git a/examples/01.NLDBD/NLDBD.rml b/examples/01.NLDBD/NLDBD.rml index 52923f8c..12f3ecdc 100644 --- a/examples/01.NLDBD/NLDBD.rml +++ b/examples/01.NLDBD/NLDBD.rml @@ -56,8 +56,8 @@ By default REST units are mm, keV and degrees ///3. geant4 internal diff --git a/examples/02.TREXDM/FullChainFromReadout.rml b/examples/02.TREXDM/FullChainFromReadout.rml index 1c28400e..69e1eaa5 100644 --- a/examples/02.TREXDM/FullChainFromReadout.rml +++ b/examples/02.TREXDM/FullChainFromReadout.rml @@ -41,8 +41,8 @@ - - + + diff --git a/examples/03.Fluorescence/electron.rml b/examples/03.Fluorescence/electron.rml index 26197f00..e5be5635 100644 --- a/examples/03.Fluorescence/electron.rml +++ b/examples/03.Fluorescence/electron.rml @@ -42,8 +42,8 @@ By default REST units are mm, keV and degrees - - + + diff --git a/examples/03.Fluorescence/gamma.rml b/examples/03.Fluorescence/gamma.rml index 59db87ea..5145022b 100644 --- a/examples/03.Fluorescence/gamma.rml +++ b/examples/03.Fluorescence/gamma.rml @@ -41,8 +41,8 @@ By default REST units are mm, keV and degrees - - + + diff --git a/examples/04.MuonScan/CosmicMuonsFromCircle.rml b/examples/04.MuonScan/CosmicMuonsFromCircle.rml index 59e0a853..7b19aeb2 100644 --- a/examples/04.MuonScan/CosmicMuonsFromCircle.rml +++ b/examples/04.MuonScan/CosmicMuonsFromCircle.rml @@ -29,8 +29,8 @@ position="(0,100,0)mm" size="(400,0,0)mm" rotationAngle="90deg" rotationAxis="(1,0,0)"> - - + + diff --git a/examples/04.MuonScan/CosmicMuonsFromWall.rml b/examples/04.MuonScan/CosmicMuonsFromWall.rml index 8841f797..6cee5dae 100644 --- a/examples/04.MuonScan/CosmicMuonsFromWall.rml +++ b/examples/04.MuonScan/CosmicMuonsFromWall.rml @@ -29,8 +29,8 @@ First concept author G. Luzón (16-11-2020) --> - - + + diff --git a/examples/04.MuonScan/Muon.rml b/examples/04.MuonScan/Muon.rml index da6315d7..c0f3b38f 100644 --- a/examples/04.MuonScan/Muon.rml +++ b/examples/04.MuonScan/Muon.rml @@ -24,8 +24,8 @@ - - + + diff --git a/examples/05.PandaXIII/geometry/Th232_SS_01.rml b/examples/05.PandaXIII/geometry/Th232_SS_01.rml index 280c38e7..5a9d94c2 100644 --- a/examples/05.PandaXIII/geometry/Th232_SS_01.rml +++ b/examples/05.PandaXIII/geometry/Th232_SS_01.rml @@ -33,8 +33,8 @@ - - + + diff --git a/examples/06.IonRecoils/recoils.rml b/examples/06.IonRecoils/recoils.rml index 9f3f91b3..e92b309b 100644 --- a/examples/06.IonRecoils/recoils.rml +++ b/examples/06.IonRecoils/recoils.rml @@ -43,8 +43,8 @@ By default REST units are mm, keV and degrees - - + + diff --git a/examples/07.FullChainDecay/fullChain.rml b/examples/07.FullChainDecay/fullChain.rml index 47b36846..06e384c0 100644 --- a/examples/07.FullChainDecay/fullChain.rml +++ b/examples/07.FullChainDecay/fullChain.rml @@ -43,8 +43,8 @@ By default REST units are mm, keV and degrees - - + + diff --git a/examples/07.FullChainDecay/singleDecay.rml b/examples/07.FullChainDecay/singleDecay.rml index c91cc5dd..517d848a 100644 --- a/examples/07.FullChainDecay/singleDecay.rml +++ b/examples/07.FullChainDecay/singleDecay.rml @@ -43,8 +43,8 @@ By default REST units are mm, keV and degrees - - + + diff --git a/examples/08.Alphas/alphas.rml b/examples/08.Alphas/alphas.rml index c70cbf37..44deffa3 100644 --- a/examples/08.Alphas/alphas.rml +++ b/examples/08.Alphas/alphas.rml @@ -42,8 +42,8 @@ By default REST units are mm, keV and degrees - - + + diff --git a/examples/09.Pb210_Shield/Pb210.rml b/examples/09.Pb210_Shield/Pb210.rml index 0f06cb8e..6a040652 100644 --- a/examples/09.Pb210_Shield/Pb210.rml +++ b/examples/09.Pb210_Shield/Pb210.rml @@ -42,8 +42,8 @@ By default REST units are mm, keV and degrees - - + + diff --git a/examples/10.Geometries/Assembly.rml b/examples/10.Geometries/Assembly.rml index 7573e3fc..ec378f24 100644 --- a/examples/10.Geometries/Assembly.rml +++ b/examples/10.Geometries/Assembly.rml @@ -41,8 +41,8 @@ By default REST units are mm, keV and degrees - - + + diff --git a/examples/11.Xrays/xrays.rml b/examples/11.Xrays/xrays.rml index ea10513e..f8ba7d04 100644 --- a/examples/11.Xrays/xrays.rml +++ b/examples/11.Xrays/xrays.rml @@ -41,8 +41,8 @@ By default REST units are mm, keV and degrees - - + + diff --git a/examples/v2.1.7/pandaXIII/biasing/externalTh232.rml b/examples/v2.1.7/pandaXIII/biasing/externalTh232.rml index 960e4dab..f5e8b4d5 100644 --- a/examples/v2.1.7/pandaXIII/biasing/externalTh232.rml +++ b/examples/v2.1.7/pandaXIII/biasing/externalTh232.rml @@ -39,8 +39,8 @@ - - + + diff --git a/examples/v2.1.7/pandaXIII/biasing/externalU238.rml b/examples/v2.1.7/pandaXIII/biasing/externalU238.rml index f9d1f43c..8061aff7 100644 --- a/examples/v2.1.7/pandaXIII/biasing/externalU238.rml +++ b/examples/v2.1.7/pandaXIII/biasing/externalU238.rml @@ -38,8 +38,8 @@ - - + + diff --git a/examples/v2.1.7/pandaXIII/templates/biasedIsotopeFromVirtualBox.rml b/examples/v2.1.7/pandaXIII/templates/biasedIsotopeFromVirtualBox.rml index 2a9d4502..f76d1d6e 100644 --- a/examples/v2.1.7/pandaXIII/templates/biasedIsotopeFromVirtualBox.rml +++ b/examples/v2.1.7/pandaXIII/templates/biasedIsotopeFromVirtualBox.rml @@ -32,8 +32,8 @@ - - + + diff --git a/examples/v2.1.7/pandaXIII/templates/isotopeFromPoint.rml b/examples/v2.1.7/pandaXIII/templates/isotopeFromPoint.rml index cc21f729..de131199 100644 --- a/examples/v2.1.7/pandaXIII/templates/isotopeFromPoint.rml +++ b/examples/v2.1.7/pandaXIII/templates/isotopeFromPoint.rml @@ -32,8 +32,8 @@ - - + + diff --git a/examples/v2.1.7/pandaXIII/templates/isotopeFromVCylinder.rml b/examples/v2.1.7/pandaXIII/templates/isotopeFromVCylinder.rml index 2b66998e..f0f2b772 100644 --- a/examples/v2.1.7/pandaXIII/templates/isotopeFromVCylinder.rml +++ b/examples/v2.1.7/pandaXIII/templates/isotopeFromVCylinder.rml @@ -31,8 +31,8 @@ - - + + diff --git a/examples/v2.1.7/pandaXIII/templates/isotopeFromVolume.rml b/examples/v2.1.7/pandaXIII/templates/isotopeFromVolume.rml index 719d378d..5f471a53 100644 --- a/examples/v2.1.7/pandaXIII/templates/isotopeFromVolume.rml +++ b/examples/v2.1.7/pandaXIII/templates/isotopeFromVolume.rml @@ -33,8 +33,8 @@ - - + + From d17432650929355e9d29eb3bd08fff5175eb4100 Mon Sep 17 00:00:00 2001 From: lobis Date: Tue, 19 Jul 2022 21:51:42 +0200 Subject: [PATCH 069/173] EventAction - print update --- src/EventAction.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/EventAction.cxx b/src/EventAction.cxx index 8a02a14e..9bdede00 100644 --- a/src/EventAction.cxx +++ b/src/EventAction.cxx @@ -30,7 +30,7 @@ void EventAction::BeginOfEventAction(const G4Event* event) { if (restG4Metadata->GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Debug) { G4cout << "DEBUG: Start of event ID " << eventID << " (" << eventID + 1 << " of " << G4RunManager::GetRunManager()->GetNumberOfEventsToBeProcessed() << "). " - << restRun->GetEntries() << " Events stored." << endl; + << restRun->GetEntries() << " Events stored" << endl; } else { const int numberOfEventsToBePercent = G4RunManager::GetRunManager()->GetNumberOfEventsToBeProcessed() / 100; From b53998105fbe103dcaf0de84bec33d83f7cea7c2 Mon Sep 17 00:00:00 2001 From: Luis Obis Date: Wed, 20 Jul 2022 11:56:05 +0200 Subject: [PATCH 070/173] Fixed example 09 validation bug --- examples/09.Pb210_Shield/Pb210.rml | 16 ++++++++-------- src/SimulationManager.cxx | 18 +++++++++++++++--- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/examples/09.Pb210_Shield/Pb210.rml b/examples/09.Pb210_Shield/Pb210.rml index 6a040652..3b4f5ee0 100644 --- a/examples/09.Pb210_Shield/Pb210.rml +++ b/examples/09.Pb210_Shield/Pb210.rml @@ -68,22 +68,22 @@ By default REST units are mm, keV and degrees - + - - + + - - - - - + + + + + diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index 2b00269a..eb983d13 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -133,9 +133,21 @@ void OutputManager::UpdateEvent() { bool OutputManager::IsEmptyEvent() const { return !fEvent || fEvent->fTracks.empty(); } bool OutputManager::IsValidEvent() const { - if (IsEmptyEvent()) return false; - if (fSimulationManager->GetRestMetadata()->GetSaveAllEvents()) return true; - if (fEvent->GetSensitiveVolumeEnergy() <= 0) return false; + if (IsEmptyEvent()) { + return false; + } + if (fSimulationManager->GetRestMetadata()->GetSaveAllEvents()) { + return true; + } + if (fEvent->GetSensitiveVolumeEnergy() <= 0) { + return false; + } + if (fEvent->GetSensitiveVolumeEnergy() < + fSimulationManager->GetRestMetadata()->GetMinimumEnergyStored() || + fEvent->GetSensitiveVolumeEnergy() > + fSimulationManager->GetRestMetadata()->GetMaximumEnergyStored()) { + return false; + } return true; } From e7e7dda51e7227f74e7b168fe2475793b2a8ec19 Mon Sep 17 00:00:00 2001 From: Luis Obis Date: Wed, 20 Jul 2022 12:57:21 +0200 Subject: [PATCH 071/173] Updated example 06 to use average instead of one event --- examples/06.IonRecoils/Validate.C | 36 ++++++++++++++++++------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/examples/06.IonRecoils/Validate.C b/examples/06.IonRecoils/Validate.C index 0760288d..b5ff83ad 100644 --- a/examples/06.IonRecoils/Validate.C +++ b/examples/06.IonRecoils/Validate.C @@ -1,23 +1,29 @@ +#include -Int_t Validate(string fname) { - gSystem->Load("libRestFramework.so"); - gSystem->Load("libRestGeant4.so"); +Int_t Validate(const char* filename) { + cout << "Starting validation for '" << filename << "'" << endl; - TRestRun* run = new TRestRun(fname); + TRestRun run(filename); + TRestGeant4Event* event = run.GetInputEvent(); - TRestGeant4Event* ev = (TRestGeant4Event*)run->GetInputEvent(); - run->GetEntry(0); + double averageNumberOfHits = 0; + const double averageNumberOfHitsRef = 14413.5; + const double tolerance = 0.001; - Int_t nHitsEv0 = ev->GetNumberOfHits(); - cout << "Nhits : " << nHitsEv0 << endl; - if (nHitsEv0 < 5 || nHitsEv0 > 40) { - cout << "The number of hits in the recoil is not in the 5-40 range" << endl; - return 14; + for (int i = 0; i < run.GetEntries(); i++) { + run.GetEntry(i); + averageNumberOfHits += double(event->GetNumberOfHits()) / run.GetEntries(); } - Double_t duration = run->GetEndTimestamp() - run->GetStartTimestamp(); + cout << "Average number of hits: " << averageNumberOfHits << endl; + if (TMath::Abs(averageNumberOfHits - averageNumberOfHitsRef) / averageNumberOfHitsRef > tolerance) { + cout << "The average number of hits does not match the reference value of " << averageNumberOfHitsRef + << endl; + return 14; + } - cout << "Duration : " << duration << endl; + Double_t duration = run.GetEndTimestamp() - run.GetStartTimestamp(); + cout << "Duration: " << duration << endl; if (duration <= 5 || duration > 200) { cout << "The duration of the run in seconds is invalid" << endl; return 15; @@ -25,8 +31,8 @@ Int_t Validate(string fname) { cout.precision(12); - cout << "Time since simulation ended : " << time(NULL) - run->GetEndTimestamp() << endl; - Double_t delay = time(NULL) - run->GetEndTimestamp(); + cout << "Time since simulation ended: " << time(NULL) - run.GetEndTimestamp() << endl; + Double_t delay = time(NULL) - run.GetEndTimestamp(); if (delay < 0 || delay > 20) { cout << "The end timestamp is probably wrong" << endl; From 326ec123f1a25edd68ee8eae4ba4e23fe0868b54 Mon Sep 17 00:00:00 2001 From: Luis Obis Date: Wed, 20 Jul 2022 13:10:44 +0200 Subject: [PATCH 072/173] Updated examples --- examples/06.IonRecoils/recoils.rml | 16 ++++++++-------- test/src/examples.cxx | 29 ++++++++++++++++++++++++++++- 2 files changed, 36 insertions(+), 9 deletions(-) diff --git a/examples/06.IonRecoils/recoils.rml b/examples/06.IonRecoils/recoils.rml index e92b309b..f20a3763 100644 --- a/examples/06.IonRecoils/recoils.rml +++ b/examples/06.IonRecoils/recoils.rml @@ -71,22 +71,22 @@ By default REST units are mm, keV and degrees - + - - + + - - - - - + + + + + diff --git a/test/src/examples.cxx b/test/src/examples.cxx index c0ca3408..198dde81 100644 --- a/test/src/examples.cxx +++ b/test/src/examples.cxx @@ -227,7 +227,6 @@ TEST(restG4, Example_05_PandaX) { } TEST(restG4, Example_06_IonRecoils) { - GTEST_SKIP_("Not working yet, needs fixing"); // cd into example const auto originalPath = fs::current_path(); const auto thisExamplePath = examplesPath / "06.IonRecoils"; @@ -286,3 +285,31 @@ TEST(restG4, Example_07_Decay_FullChain) { fs::current_path(originalPath); } + +TEST(restG4, Example_09_Pb210_Shield) { + GTEST_SKIP_("This test should work, but we skip it because it takes too long"); + // cd into example + const auto originalPath = fs::current_path(); + const auto thisExamplePath = examplesPath / "09.Pb210_Shield"; + fs::current_path(thisExamplePath); + + CommandLineParameters parameters; + parameters.rmlFile = "Pb210.rml"; + parameters.outputFile = thisExamplePath / "shielding.root"; // TODO: fix not working with local path + + Application app; + app.Run(parameters); + + TRestRun run(parameters.outputFile.Data()); + + // Run validation macro + const TString macro(thisExamplePath / "Validate.C"); + gROOT->ProcessLine(TString::Format(".L %s", macro.Data())); // Load macro + int error = 0; + const int result = + gROOT->ProcessLine(TString::Format("Validate(\"%s\")", parameters.outputFile.Data()), &error); + EXPECT_EQ(error, 0); + EXPECT_EQ(result, 0); + + fs::current_path(originalPath); +} \ No newline at end of file From af203c8fd80f48cd356135c2e4aac88a983c6518 Mon Sep 17 00:00:00 2001 From: Luis Obis Date: Wed, 20 Jul 2022 13:19:41 +0200 Subject: [PATCH 073/173] Updated muon validation ref values --- examples/04.MuonScan/Validate.C | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/examples/04.MuonScan/Validate.C b/examples/04.MuonScan/Validate.C index c4ea54f0..039e3021 100644 --- a/examples/04.MuonScan/Validate.C +++ b/examples/04.MuonScan/Validate.C @@ -54,22 +54,22 @@ Int_t Validate(const char* filename) { double nEvents = run.GetEntries(); double averageTotalEnergy = 0; - constexpr double averageTotalEnergyRef = 18.0321; + constexpr double averageTotalEnergyRef = 18.8645; double averageSensitiveEnergy = 0; - constexpr double averageSensitiveEnergyRef = 8.78066; + constexpr double averageSensitiveEnergyRef = 9.01081; double averageNumberOfTracks = 0; - constexpr double averageNumberOfTracksRef = 4.924; + constexpr double averageNumberOfTracksRef = 1388.56; double averageNumberOfHitsVolume0 = 0; - constexpr double averageNumberOfHitsVolume0Ref = 60.712; + constexpr double averageNumberOfHitsVolume0Ref = 74.095; double averageNumberOfHitsVolume1 = 0; - constexpr double averageNumberOfHitsVolume1Ref = 68.061; + constexpr double averageNumberOfHitsVolume1Ref = 64.182; TVector3 averagePosition = {}; - const TVector3 averagePositionRef = {-0.0305454, -0.384008, -299.54}; + const TVector3 averagePositionRef = {0.100946, -0.26358, 300.348}; constexpr double tolerance = 0.001; @@ -92,8 +92,7 @@ Int_t Validate(const char* filename) { cout << "Average position: (" << averagePosition.x() << ", " << averagePosition.y() << ", " << averagePosition.z() << ") mm" << endl; - if (TMath::Abs(averageNumberOfTracks - averageNumberOfTracksRef) / averageNumberOfTracksRef > - tolerance) { + if (TMath::Abs(averageNumberOfTracks - averageNumberOfTracksRef) / averageNumberOfTracksRef > tolerance) { cout << "The average number of tracks does not match the reference value of " << averageNumberOfTracksRef << endl; return 8; @@ -128,8 +127,7 @@ Int_t Validate(const char* filename) { return 12; } - if (TMath::Abs(averagePosition.Mag() - averagePositionRef.Mag()) / averagePositionRef.Mag() > - tolerance) { + if (TMath::Abs(averagePosition.Mag() - averagePositionRef.Mag()) / averagePositionRef.Mag() > tolerance) { cout << "The average position does not match the reference value of " << "(" << averagePositionRef.x() << ", " << averagePositionRef.y() << ", " << averagePositionRef.z() << ") mm" << endl; From 0a8cf9929358e374ac2bd6b923324b5b3ce99cca Mon Sep 17 00:00:00 2001 From: Luis Obis Date: Wed, 20 Jul 2022 13:29:20 +0200 Subject: [PATCH 074/173] Updated reference value for old geant4 --- examples/06.IonRecoils/Validate.C | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/examples/06.IonRecoils/Validate.C b/examples/06.IonRecoils/Validate.C index b5ff83ad..a9f25b2b 100644 --- a/examples/06.IonRecoils/Validate.C +++ b/examples/06.IonRecoils/Validate.C @@ -6,8 +6,17 @@ Int_t Validate(const char* filename) { TRestRun run(filename); TRestGeant4Event* event = run.GetInputEvent(); + cout << "Testing reading of Geant4 metadata class" << endl; + TRestGeant4Metadata* geant4Metadata = (TRestGeant4Metadata*)run.GetMetadataClass("TRestGeant4Metadata"); + if (!geant4Metadata) { + cout << "Problem reading Geant4 metadata class!" << endl; + return 6; + } + geant4Metadata->PrintMetadata(); + const bool isReferenceGeant4Version = geant4Metadata->GetGeant4Version() == "10.4.3"; + double averageNumberOfHits = 0; - const double averageNumberOfHitsRef = 14413.5; + const double averageNumberOfHitsRef = (!isReferenceGeant4Version) ? 14413.5 : 11223.0; const double tolerance = 0.001; for (int i = 0; i < run.GetEntries(); i++) { From 7c090bffbecb161b3ef6b587c55912d675dff5fc Mon Sep 17 00:00:00 2001 From: Luis Obis Date: Wed, 20 Jul 2022 14:28:11 +0200 Subject: [PATCH 075/173] Reverted angular dist to fix bug --- examples/04.MuonScan/CosmicMuonsFromCircle.rml | 2 +- examples/04.MuonScan/CosmicMuonsFromWall.rml | 2 +- examples/04.MuonScan/ValidateCircle.C | 9 ++++++--- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/examples/04.MuonScan/CosmicMuonsFromCircle.rml b/examples/04.MuonScan/CosmicMuonsFromCircle.rml index 7b19aeb2..0f7ef388 100644 --- a/examples/04.MuonScan/CosmicMuonsFromCircle.rml +++ b/examples/04.MuonScan/CosmicMuonsFromCircle.rml @@ -30,7 +30,7 @@ rotationAngle="90deg" rotationAxis="(1,0,0)"> - + diff --git a/examples/04.MuonScan/CosmicMuonsFromWall.rml b/examples/04.MuonScan/CosmicMuonsFromWall.rml index 6cee5dae..39e80eb6 100644 --- a/examples/04.MuonScan/CosmicMuonsFromWall.rml +++ b/examples/04.MuonScan/CosmicMuonsFromWall.rml @@ -30,7 +30,7 @@ First concept author G. Luzón (16-11-2020) --> rotationAxis="(1,0,0)"> - + diff --git a/examples/04.MuonScan/ValidateCircle.C b/examples/04.MuonScan/ValidateCircle.C index 2a353bfc..ce5270db 100644 --- a/examples/04.MuonScan/ValidateCircle.C +++ b/examples/04.MuonScan/ValidateCircle.C @@ -7,7 +7,7 @@ Int_t ValidateCircle(const char* filename) { TRestGeant4Event* event = run.GetInputEvent(); if (run.GetRunTag() != "MuonsFromCircle") { - cout << "Run tag : " << run.GetRunTag() << endl; + cout << "Run tag: " << run.GetRunTag() << endl; cout << "The run tag of the basic validation test should be 'MuonsFromCircle'" << endl; return 1; } @@ -19,9 +19,7 @@ Int_t ValidateCircle(const char* filename) { run.GetEntry(n); Double_t x = event->GetPrimaryEventOrigin().X(); Double_t z = event->GetPrimaryEventOrigin().Z(); - const auto r = TMath::Sqrt(x * x + z * z) / 100; // cm - rMean += r / run.GetEntries(); if (r < rMin) { rMin = r; @@ -31,6 +29,11 @@ Int_t ValidateCircle(const char* filename) { } } + cout << "Number of entries: " << run.GetEntries() << endl; + cout << "Mean radius (cm): " << rMean << endl; + cout << "Minimum radius (cm): " << rMin << endl; + cout << "Maximum radius (cm): " << rMax << endl; + if (rMean < 2.75 || rMean > 3.25) { cout << "The average radius of the distribution is wrong!" << endl; cout << "R_mean (cm): " << rMean << endl; From 907ce016b87bd5b3c8391b6c6d7a5064ff6d27e7 Mon Sep 17 00:00:00 2001 From: lobis Date: Wed, 20 Jul 2022 19:08:15 +0200 Subject: [PATCH 076/173] Application - print geometry info before run info --- src/Application.cxx | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/Application.cxx b/src/Application.cxx index 225ba333..c364337c 100644 --- a/src/Application.cxx +++ b/src/Application.cxx @@ -50,8 +50,6 @@ void Application::Run(const CommandLineParameters& commandLineParameters) { delete fSimulationManager; fSimulationManager = new SimulationManager(); - Bool_t saveAllEvents; - const auto timeStart = chrono::steady_clock::now(); const auto originalDirectory = filesystem::current_path(); @@ -127,7 +125,6 @@ void Application::Run(const CommandLineParameters& commandLineParameters) { run->PrintMetadata(); run->FormOutputFile(); - run->GetOutputFile()->cd(); run->AddEventBranch(&fSimulationManager->fEvent); @@ -166,7 +163,6 @@ void Application::Run(const CommandLineParameters& commandLineParameters) { runManager->SetUserInitialization(detector); runManager->SetUserInitialization(new PhysicsList(fSimulationManager->GetRestPhysicsLists())); - runManager->SetUserInitialization(new ActionInitialization(fSimulationManager)); runManager->Initialize(); @@ -224,12 +220,13 @@ void Application::Run(const CommandLineParameters& commandLineParameters) { run->UpdateOutputFile(); run->CloseFile(); - run->PrintMetadata(); auto geometry = gdml->CreateGeoManager(); WriteGeometry(geometry, run->GetOutputFileName()); delete geometry; + run->PrintMetadata(); + cout << "============== Generated file: " << filename << " ==============" << endl; auto timeEnd = chrono::steady_clock::now(); cout << "Elapsed time: " << chrono::duration_cast(timeEnd - timeStart).count() From e7324b37ec6c7de3b2d2cc8860d1a2560db70c91 Mon Sep 17 00:00:00 2001 From: lobis Date: Wed, 20 Jul 2022 19:59:06 +0200 Subject: [PATCH 077/173] Added example to check generators --- .../12.Generators/CosineSquaredCircle.rml | 39 ++++++++++++ examples/12.Generators/Validate.C | 63 +++++++++++++++++++ examples/12.Generators/geometry/geometry.gdml | 26 ++++++++ examples/12.Generators/geometry/setup.gdml | 42 +++++++++++++ test/src/examples.cxx | 27 ++++++++ 5 files changed, 197 insertions(+) create mode 100644 examples/12.Generators/CosineSquaredCircle.rml create mode 100644 examples/12.Generators/Validate.C create mode 100644 examples/12.Generators/geometry/geometry.gdml create mode 100644 examples/12.Generators/geometry/setup.gdml diff --git a/examples/12.Generators/CosineSquaredCircle.rml b/examples/12.Generators/CosineSquaredCircle.rml new file mode 100644 index 00000000..a772846c --- /dev/null +++ b/examples/12.Generators/CosineSquaredCircle.rml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/12.Generators/Validate.C b/examples/12.Generators/Validate.C new file mode 100644 index 00000000..4a715972 --- /dev/null +++ b/examples/12.Generators/Validate.C @@ -0,0 +1,63 @@ +#include + +Int_t Validate(const char* filename) { + cout << "Starting validation for '" << filename << "'" << endl; + + TRestRun run(filename); + + cout << "Run tag: " << run.GetRunTag() << endl; + if (run.GetRunTag() != "CosineSquaredCircle") { + cout << "The run tag of the basic validation test should be 'CosineSquaredCircle'!" << endl; + return 1; + } + + cout << "Run entries: " << run.GetEntries() << endl; + if (run.GetEntries() != 200000) { + cout << "Bad number of entries: " << run.GetEntries() << endl; + return 2; + } + + auto metadata = (TRestGeant4Metadata*)run.GetMetadataClass("TRestGeant4Metadata"); + TRestGeant4Event* event = run.GetInputEvent(); + TVector3 sourceDirection = metadata->GetParticleSource()->GetDirection(); + cout << "original source direction: (" << sourceDirection.X() << ", " << sourceDirection.Y() << ", " + << sourceDirection.Z() << ")" << endl; + + TH1D thetaHist("thetaHist", "Theta angle from source direction", 100, 0, TMath::Pi()); + for (int i = 0; i < run.GetEntries(); i++) { + run.GetEntry(i); + TVector3 direction = event->GetPrimaryEventDirection(); + const auto theta = sourceDirection.Angle(direction); + thetaHist.Fill(theta); + } + thetaHist.Scale(1. / thetaHist.Integral(), "width"); + + auto cos2Lambda = [](double* xs, double* ps) { + if (xs[0] >= 0 && xs[0] <= TMath::Pi() / 2) { + return TMath::Power(TMath::Cos(xs[0]), 2) / (TMath::Pi() / 4.0); + } + return 0.0; + }; + const char* title = "AngularDistribution: Cos2"; + auto referenceFunction = TF1(title, cos2Lambda, 0.0, TMath::Pi()); + referenceFunction.SetTitle(title); + + TCanvas* canvas = new TCanvas(); + thetaHist.Draw(); + referenceFunction.Draw("same"); + canvas->Print("/tmp/thetaHist.pdf"); + + double diff = 0; + for (int i = 1; i < thetaHist.GetNbinsX(); i++) { + diff += TMath::Abs(thetaHist.GetBinContent(i) - referenceFunction.Eval(thetaHist.GetBinCenter(i))) / + thetaHist.GetNbinsX(); + } + cout << "Computed difference from reference function: " << diff << endl; + if (diff > 0.01) { + cout << "The computed difference from reference function is too large!" << endl; + return 3; + } + + cout << "All tests passed! [\033[32mOK\033[0m]\n"; + return 0; +} diff --git a/examples/12.Generators/geometry/geometry.gdml b/examples/12.Generators/geometry/geometry.gdml new file mode 100644 index 00000000..6a918e6e --- /dev/null +++ b/examples/12.Generators/geometry/geometry.gdml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/12.Generators/geometry/setup.gdml b/examples/12.Generators/geometry/setup.gdml new file mode 100644 index 00000000..1285174c --- /dev/null +++ b/examples/12.Generators/geometry/setup.gdml @@ -0,0 +1,42 @@ + + + + + + ]> + + + + + + + + + + + + + + + + + + + + &materials; + + &geometry; + + + + + + + diff --git a/test/src/examples.cxx b/test/src/examples.cxx index 198dde81..360c02fc 100644 --- a/test/src/examples.cxx +++ b/test/src/examples.cxx @@ -311,5 +311,32 @@ TEST(restG4, Example_09_Pb210_Shield) { EXPECT_EQ(error, 0); EXPECT_EQ(result, 0); + fs::current_path(originalPath); +} + +TEST(restG4, Example_12_Generators) { + // cd into example + const auto originalPath = fs::current_path(); + const auto thisExamplePath = examplesPath / "12.Generators"; + fs::current_path(thisExamplePath); + + CommandLineParameters parameters; + parameters.rmlFile = "CosineSquaredCircle.rml"; + parameters.outputFile = thisExamplePath / "cosine.root"; + + Application app; + app.Run(parameters); + + TRestRun run(parameters.outputFile.Data()); + + // Run validation macro + const TString macro(thisExamplePath / "Validate.C"); + gROOT->ProcessLine(TString::Format(".L %s", macro.Data())); // Load macro + int error = 0; + const int result = + gROOT->ProcessLine(TString::Format("Validate(\"%s\")", parameters.outputFile.Data()), &error); + EXPECT_EQ(error, 0); + EXPECT_EQ(result, 0); + fs::current_path(originalPath); } \ No newline at end of file From d0de8a47172a67642a8fbfd543b21dfd84a13730 Mon Sep 17 00:00:00 2001 From: lobis Date: Wed, 20 Jul 2022 20:00:09 +0200 Subject: [PATCH 078/173] Set XML version to `xml version="1.0"` --- examples/01.NLDBD/NLDBD.rml | 2 +- examples/03.Fluorescence/electron.rml | 2 +- examples/03.Fluorescence/gamma.rml | 2 +- examples/06.IonRecoils/recoils.rml | 2 +- examples/07.FullChainDecay/fullChain.rml | 2 +- examples/07.FullChainDecay/singleDecay.rml | 2 +- examples/08.Alphas/alphas.rml | 2 +- examples/09.Pb210_Shield/Pb210.rml | 2 +- examples/10.Geometries/Assembly.rml | 2 +- examples/11.Xrays/xrays.rml | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/examples/01.NLDBD/NLDBD.rml b/examples/01.NLDBD/NLDBD.rml index 12f3ecdc..e0fb251e 100644 --- a/examples/01.NLDBD/NLDBD.rml +++ b/examples/01.NLDBD/NLDBD.rml @@ -1,4 +1,4 @@ - + rotationAxis="(1,0,0)"> - + From 8e87d0689753076618760a0e754ca65fbe959446 Mon Sep 17 00:00:00 2001 From: lobis Date: Wed, 20 Jul 2022 20:44:34 +0200 Subject: [PATCH 082/173] Example 04 - updated validation ref values for new seed --- .../04.MuonScan/CosmicMuonsFromCircle.rml | 4 +- examples/04.MuonScan/ValidateCircle.C | 48 +++++++++---------- 2 files changed, 25 insertions(+), 27 deletions(-) diff --git a/examples/04.MuonScan/CosmicMuonsFromCircle.rml b/examples/04.MuonScan/CosmicMuonsFromCircle.rml index 234179de..ce81985c 100644 --- a/examples/04.MuonScan/CosmicMuonsFromCircle.rml +++ b/examples/04.MuonScan/CosmicMuonsFromCircle.rml @@ -18,9 +18,9 @@ - + - + diff --git a/examples/04.MuonScan/ValidateCircle.C b/examples/04.MuonScan/ValidateCircle.C index ce5270db..04ee70ca 100644 --- a/examples/04.MuonScan/ValidateCircle.C +++ b/examples/04.MuonScan/ValidateCircle.C @@ -12,48 +12,46 @@ Int_t ValidateCircle(const char* filename) { return 1; } - Double_t rMean = 0; - Double_t rMin = TMath::Infinity(); - Double_t rMax = 0; + double radiusAverage = 0, radiusMin = TMath::Infinity(), radiusMax = 0; + constexpr double radiusAverageRef = 2.92, radiusMinRef = 0.0, radiusMaxRef = 4.0; + constexpr double tolerance = 0.1; + for (Int_t n = 0; n < run.GetEntries(); n++) { run.GetEntry(n); Double_t x = event->GetPrimaryEventOrigin().X(); Double_t z = event->GetPrimaryEventOrigin().Z(); const auto r = TMath::Sqrt(x * x + z * z) / 100; // cm - rMean += r / run.GetEntries(); - if (r < rMin) { - rMin = r; + radiusAverage += r / run.GetEntries(); + if (r < radiusMin) { + radiusMin = r; } - if (r > rMax) { - rMax = r; + if (r > radiusMax) { + radiusMax = r; } } - cout << "Number of entries: " << run.GetEntries() << endl; - cout << "Mean radius (cm): " << rMean << endl; - cout << "Minimum radius (cm): " << rMin << endl; - cout << "Maximum radius (cm): " << rMax << endl; + cout << "Average radius (cm): " << radiusAverage << endl; + cout << "Minimum radius (cm): " << radiusMin << endl; + cout << "Maximum radius (cm): " << radiusMax << endl; - if (rMean < 2.75 || rMean > 3.25) { + if (TMath::Abs(radiusAverage - radiusAverageRef) > tolerance) { cout << "The average radius of the distribution is wrong!" << endl; - cout << "R_mean (cm): " << rMean << endl; - return 2; - } - - if (rMin > 0.5) { - cout << "The minimum radius of the distribution is wrong!" << endl; - cout << "R_min (cm): " << rMin << endl; + cout << "radiusAverage (cm): " << radiusAverage << endl; return 3; } - - if (rMax > 4.0 || rMax < 3.75) { - cout << "The maximum radius of the distribution is wrong!" << endl; - cout << "R_max (cm): " << rMax << endl; + if (TMath::Abs(radiusMin - radiusMinRef) > tolerance) { + cout << "The average radius of the distribution is wrong!" << endl; + cout << "radiusMin (cm): " << radiusMin << endl; return 4; } + if (TMath::Abs(radiusMax - radiusMaxRef) > tolerance) { + cout << "The average radius of the distribution is wrong!" << endl; + cout << "radiusMax (cm): " << radiusMax << endl; + return 5; + } cout << "Run entries: " << run.GetEntries() << endl; - if (run.GetEntries() < 600 || run.GetEntries() > 750) { + if (run.GetEntries() < 1300 || run.GetEntries() > 1450) { cout << "The number of entries is wrong!" << endl; cout << "Number of entries : " << run.GetEntries() << endl; return 5; From 56916f2904671fd2cd951fed0f5725142f509c6b Mon Sep 17 00:00:00 2001 From: lobis Date: Wed, 20 Jul 2022 20:46:49 +0200 Subject: [PATCH 083/173] Added new example to github action --- .github/workflows/validation.yml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/.github/workflows/validation.yml b/.github/workflows/validation.yml index 4e11fae7..695a9e0d 100644 --- a/.github/workflows/validation.yml +++ b/.github/workflows/validation.yml @@ -374,6 +374,27 @@ jobs: restManager --c analysis.rml --f xrays_simulation.root --o xrays_simulation_analysis.root restRoot -b -q GetQE.C'("xrays_simulation_analysis.root")' + restG4-examples-12: + name: "Example 12: Generators" + runs-on: ubuntu-latest + container: + image: ghcr.io/lobis/root-geant4-garfield:rest-for-physics + needs: [ check-installation, restG4-examples-01 ] + steps: + - uses: actions/checkout@v3 + - name: Restore cache + uses: actions/cache@v3 + id: framework-install-restG4-cache + with: + path: ${{ env.REST_PATH }} + key: ${{ env.BRANCH_NAME }}-${{ github.sha }} + - name: Run example + run: | + source ${{ env.REST_PATH }}/thisREST.sh + cd ${{ env.REST_PATH }}/examples/restG4/12.Generators/ + restG4 CosineSquaredCircle.rml -o CosineSquaredCircle.root + restRoot -b -q Validate.C'("CosineSquaredCircle.root")' + # Reference version of Geant4 framework-install-reference: From 65f7bc59abf47f19e5fb376ebd19d004d2620414 Mon Sep 17 00:00:00 2001 From: lobis Date: Thu, 21 Jul 2022 11:08:07 +0200 Subject: [PATCH 084/173] DetectorConstruction - cleaned output a bit --- src/DetectorConstruction.cxx | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/DetectorConstruction.cxx b/src/DetectorConstruction.cxx index c9d749c1..fc3310b4 100644 --- a/src/DetectorConstruction.cxx +++ b/src/DetectorConstruction.cxx @@ -60,7 +60,7 @@ G4VPhysicalVolume* DetectorConstruction::Construct() { filesystem::current_path(startingPath); - // TODO : Take the name of the sensitive volume and use it here to define its + // TODO: Take the name of the sensitive volume and use it here to define its // StepSize auto sensitiveVolume = (string)restG4Metadata->GetSensitiveVolume(); @@ -95,24 +95,27 @@ G4VPhysicalVolume* DetectorConstruction::Construct() { fieldMgr->CreateChordFinder(magField); if (physicalVolume) { - G4LogicalVolume* vol = physicalVolume->GetLogicalVolume(); + G4LogicalVolume* volume = physicalVolume->GetLogicalVolume(); // This method seems not available in my Geant4 version 10.4.2 // In future Geant4 versions it seems possible to define field at particular volumes - // vol->setFieldManager(localFieldMgr, true); - G4Material* mat = vol->GetMaterial(); + // volume->setFieldManager(localFieldMgr, true); + G4Material* material = volume->GetMaterial(); G4cout << "Sensitivity volume properties" << G4endl; G4cout << "==============" << G4endl; - G4cout << "Sensitivity volume name : " << mat->GetName() << G4endl; - G4cout << "Sensitivity volume temperature : " << mat->GetTemperature() << G4endl; - G4cout << "Sensitivity volume density : " << mat->GetDensity() / (g / cm3) << " g/cm3" << G4endl; + G4cout << "Sensitivity volume name: " << material->GetName() << G4endl; + G4cout << "Sensitivity volume temperature: " << material->GetTemperature() << " K" << G4endl; + G4cout << "Sensitivity volume density: " << material->GetDensity() / (g / cm3) << " g/cm3" << G4endl; } else { - cout << "ERROR : Logical volume for sensitive \"" << sensitiveVolume << "\" not found!" << endl; + cout << "ERROR: Logical volume for sensitive \"" << sensitiveVolume << "\" not found!" << endl; } const auto& primaryGeneratorInfo = restG4Metadata->GetGeant4PrimaryGeneratorInfo(); // Getting generation volume - cout << "Generated from volume : " << primaryGeneratorInfo.GetSpatialGeneratorFrom() << endl; - cout << "Generator type : " << primaryGeneratorInfo.GetSpatialGeneratorType() << endl; + const auto fromVolume = primaryGeneratorInfo.GetSpatialGeneratorFrom(); + if (fromVolume != "NO_SUCH_PARA") { + cout << "Generated from volume: " << primaryGeneratorInfo.GetSpatialGeneratorFrom() << endl; + } + cout << "Generator type: " << primaryGeneratorInfo.GetSpatialGeneratorType() << endl; const auto spatialGeneratorTypeEnum = StringToSpatialGeneratorTypes(primaryGeneratorInfo.GetSpatialGeneratorType().Data()); @@ -177,12 +180,12 @@ G4VPhysicalVolume* DetectorConstruction::Construct() { G4LogicalVolume* lVol = pVol->GetLogicalVolume(); if (restG4Metadata->GetMaxStepSize(activeVolumeName) > 0) { G4cout << "Setting maxStepSize = " << restG4Metadata->GetMaxStepSize(activeVolumeName) - << "mm for volume : " << activeVolumeName << G4endl; + << "mm for volume: " << activeVolumeName << G4endl; lVol->SetUserLimits(new G4UserLimits(restG4Metadata->GetMaxStepSize(activeVolumeName) * mm)); } } - cout << "Activating volume : " << activeVolumeName << endl; + cout << "Activating volume: " << activeVolumeName << endl; // restG4Event->AddActiveVolume((string)activeVolumeName); if (!pVol) { cout << "DetectorConstruction. Volume " << activeVolumeName << " is not defined in the geometry" @@ -191,8 +194,6 @@ G4VPhysicalVolume* DetectorConstruction::Construct() { } } - cout << "Detector constructed : " << worldVolume << endl; - return worldVolume; } From 3bce9b01648c6fb06150a27352d3f7a48a22e1bb Mon Sep 17 00:00:00 2001 From: lobis Date: Thu, 21 Jul 2022 12:26:28 +0200 Subject: [PATCH 085/173] Updated formula generator logic --- include/PrimaryGeneratorAction.h | 3 +++ src/PrimaryGeneratorAction.cxx | 21 +++++++-------------- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/include/PrimaryGeneratorAction.h b/include/PrimaryGeneratorAction.h index f796b07f..165607c8 100644 --- a/include/PrimaryGeneratorAction.h +++ b/include/PrimaryGeneratorAction.h @@ -45,6 +45,9 @@ class PrimaryGeneratorAction : public G4VUserPrimaryGeneratorAction { const TH1D* fEnergyDistributionHistogram = nullptr; const TH1D* fAngularDistributionHistogram = nullptr; + TF1* fEnergyDistributionFunction = nullptr; + TF1* fAngularDistributionFunction = nullptr; + TF3* fGeneratorSpatialDensityFunction; Int_t startEnergyBin; diff --git a/src/PrimaryGeneratorAction.cxx b/src/PrimaryGeneratorAction.cxx index 175755fd..4780ea0f 100644 --- a/src/PrimaryGeneratorAction.cxx +++ b/src/PrimaryGeneratorAction.cxx @@ -39,15 +39,16 @@ PrimaryGeneratorAction::PrimaryGeneratorAction(SimulationManager* simulationMana if (energyDistTypeEnum == EnergyDistributionTypes::TH1D) { Double_t minEnergy = source->GetEnergyDistributionRangeMin(); Double_t maxEnergy = source->GetEnergyDistributionRangeMax(); - - // We set the initial spectrum energy provided from TH1D SetEnergyDistributionHistogram(fSimulationManager->GetPrimaryEnergyDistribution(), minEnergy, maxEnergy); + } else if (energyDistTypeEnum == EnergyDistributionTypes::FORMULA) { + fEnergyDistributionFunction = (TF1*)source->GetEnergyDistributionFunction()->Clone(); } if (angularDistTypeEnum == AngularDistributionTypes::TH1D) { - // We set the initial angular distribution provided from TH1D SetAngularDistributionHistogram(fSimulationManager->GetPrimaryAngularDistribution()); + } else if (angularDistTypeEnum == AngularDistributionTypes::FORMULA) { + fAngularDistributionFunction = (TF1*)source->GetAngularDistributionFunction()->Clone(); } } @@ -237,14 +238,10 @@ void PrimaryGeneratorAction::SetParticleDirection(Int_t particleSourceIndex, direction.rotate(G4UniformRand() * 2 * M_PI, referenceOrigin); } else if (angularDistTypeEnum == AngularDistributionTypes::FORMULA) { - auto formulaEnum = - StringToAngularDistributionFormulas(source->GetAngularDistributionFormulaString().Data()); - TF1 function = AngularDistributionFormulasToRootFormula(formulaEnum); - G4ThreeVector referenceOrigin = direction; // We generate the distribution angle (theta) using a rotation around the orthogonal vector - direction.rotate(function.GetRandom(fRandom), direction.orthogonal()); + direction.rotate(fAngularDistributionFunction->GetRandom(fRandom), direction.orthogonal()); // We rotate a full-2PI random angle along the original direction to generate a cone direction.rotate(G4UniformRand() * 2 * M_PI, referenceOrigin); @@ -321,12 +318,8 @@ void PrimaryGeneratorAction::SetParticleEnergy(Int_t particleSourceIndex, } } } else if (energyDistTypeEnum == EnergyDistributionTypes::FORMULA) { - auto formulaEnum = - StringToEnergyDistributionFormulas(source->GetEnergyDistributionFormulaString().Data()); - TF1 function = EnergyDistributionFormulasToRootFormula(formulaEnum); - - energy = function.GetRandom(source->GetEnergyDistributionRangeMin(), - source->GetEnergyDistributionRangeMax(), fRandom) * + energy = fEnergyDistributionFunction->GetRandom(source->GetEnergyDistributionRangeMin(), + source->GetEnergyDistributionRangeMax(), fRandom) * keV; } else { G4cout << "WARNING! Energy distribution type was not recognized. Setting " From eac364a685a072343d8d535cdfbe1d699d80eb85 Mon Sep 17 00:00:00 2001 From: lobis Date: Thu, 21 Jul 2022 12:44:08 +0200 Subject: [PATCH 086/173] Using formula energy generator in example 12 --- examples/12.Generators/CosineSquaredCircle.rml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/12.Generators/CosineSquaredCircle.rml b/examples/12.Generators/CosineSquaredCircle.rml index 3002a196..b26c0f89 100644 --- a/examples/12.Generators/CosineSquaredCircle.rml +++ b/examples/12.Generators/CosineSquaredCircle.rml @@ -28,7 +28,7 @@ rotationAngle="90deg" rotationAxis="(1,0,0)"> - + From 16927827eef80bd0c57c5d5ea25cb0c54ca4419d Mon Sep 17 00:00:00 2001 From: lobis Date: Thu, 21 Jul 2022 13:01:55 +0200 Subject: [PATCH 087/173] increased tolerance on muon example --- examples/04.MuonScan/ValidateCircle.C | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/04.MuonScan/ValidateCircle.C b/examples/04.MuonScan/ValidateCircle.C index 04ee70ca..2d3c04ac 100644 --- a/examples/04.MuonScan/ValidateCircle.C +++ b/examples/04.MuonScan/ValidateCircle.C @@ -14,7 +14,7 @@ Int_t ValidateCircle(const char* filename) { double radiusAverage = 0, radiusMin = TMath::Infinity(), radiusMax = 0; constexpr double radiusAverageRef = 2.92, radiusMinRef = 0.0, radiusMaxRef = 4.0; - constexpr double tolerance = 0.1; + constexpr double tolerance = 1.0; for (Int_t n = 0; n < run.GetEntries(); n++) { run.GetEntry(n); From 964e4ad9ad80107fa533777a4bbaa763bd747b62 Mon Sep 17 00:00:00 2001 From: lobis Date: Mon, 25 Jul 2022 16:55:33 +0200 Subject: [PATCH 088/173] Fixed bug on energy generator --- examples/12.Generators/CosineSquaredCircle.rml | 2 +- src/PrimaryGeneratorAction.cxx | 17 ++++++++++++++--- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/examples/12.Generators/CosineSquaredCircle.rml b/examples/12.Generators/CosineSquaredCircle.rml index b26c0f89..b9183027 100644 --- a/examples/12.Generators/CosineSquaredCircle.rml +++ b/examples/12.Generators/CosineSquaredCircle.rml @@ -28,7 +28,7 @@ rotationAngle="90deg" rotationAxis="(1,0,0)"> - + diff --git a/src/PrimaryGeneratorAction.cxx b/src/PrimaryGeneratorAction.cxx index 4780ea0f..11fbe243 100644 --- a/src/PrimaryGeneratorAction.cxx +++ b/src/PrimaryGeneratorAction.cxx @@ -43,6 +43,19 @@ PrimaryGeneratorAction::PrimaryGeneratorAction(SimulationManager* simulationMana maxEnergy); } else if (energyDistTypeEnum == EnergyDistributionTypes::FORMULA) { fEnergyDistributionFunction = (TF1*)source->GetEnergyDistributionFunction()->Clone(); + auto newRangeXMin = fEnergyDistributionFunction->GetXmin(); + if (source->GetEnergyDistributionRangeMin() > fEnergyDistributionFunction->GetXmin()) { + newRangeXMin = source->GetEnergyDistributionRangeMin(); + } + auto newRangeXMax = fEnergyDistributionFunction->GetXmax(); + if (source->GetEnergyDistributionRangeMax() < fEnergyDistributionFunction->GetXmax()) { + newRangeXMax = source->GetEnergyDistributionRangeMax(); + } + if (newRangeXMin == newRangeXMax || newRangeXMin > newRangeXMax) { + cout << "PrimaryGeneratorAction - ERROR: energy distribution range is invalid" << endl; + exit(1); + } + fEnergyDistributionFunction->SetRange(newRangeXMin, newRangeXMax); } if (angularDistTypeEnum == AngularDistributionTypes::TH1D) { @@ -318,9 +331,7 @@ void PrimaryGeneratorAction::SetParticleEnergy(Int_t particleSourceIndex, } } } else if (energyDistTypeEnum == EnergyDistributionTypes::FORMULA) { - energy = fEnergyDistributionFunction->GetRandom(source->GetEnergyDistributionRangeMin(), - source->GetEnergyDistributionRangeMax(), fRandom) * - keV; + energy = fEnergyDistributionFunction->GetRandom(fRandom) * keV; } else { G4cout << "WARNING! Energy distribution type was not recognized. Setting " "energy to 1keV" From 17b2e1c8c91d4f1f52c0f8ab03393f2c629b3357 Mon Sep 17 00:00:00 2001 From: lobis Date: Mon, 25 Jul 2022 16:57:25 +0200 Subject: [PATCH 089/173] Added additional check for example 12 --- examples/12.Generators/Validate.C | 41 ++++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/examples/12.Generators/Validate.C b/examples/12.Generators/Validate.C index 0141dfe8..3f61add3 100644 --- a/examples/12.Generators/Validate.C +++ b/examples/12.Generators/Validate.C @@ -27,6 +27,10 @@ Int_t Validate(const char* filename) { constexpr double radiusAverageRef = 2.67045, radiusMinRef = 0.0, radiusMaxRef = 4.0; constexpr double tolerance = 0.1; + double energyPrimaryAverage = 0, energyPrimaryMin = TMath::Infinity(), energyPrimaryMax = 0; + constexpr double energyPrimaryAverageRef = 53818.8, energyPrimaryMinRef = 5000.45, + energyPrimaryMaxRef = 149998.0; + TH1D thetaHist("thetaHist", "Theta angle from source direction", 100, 0, TMath::Pi()); for (int i = 0; i < run.GetEntries(); i++) { run.GetEntry(i); @@ -44,6 +48,15 @@ Int_t Validate(const char* filename) { if (r > radiusMax) { radiusMax = r; } + + Double_t energy = event->GetPrimaryEventEnergy(); + energyPrimaryAverage += energy / run.GetEntries(); + if (energy < energyPrimaryMin) { + energyPrimaryMin = energy; + } + if (energy > energyPrimaryMax) { + energyPrimaryMax = energy; + } } thetaHist.Scale(1. / thetaHist.Integral(), "width"); @@ -51,22 +64,42 @@ Int_t Validate(const char* filename) { cout << "Minimum radius (cm): " << radiusMin << endl; cout << "Maximum radius (cm): " << radiusMax << endl; + cout << "Average energy (keV): " << energyPrimaryAverage << endl; + cout << "Minimum energy (keV): " << energyPrimaryMin << endl; + cout << "Maximum energy (keV): " << energyPrimaryMax << endl; + if (TMath::Abs(radiusAverage - radiusAverageRef) > tolerance) { cout << "The average radius of the distribution is wrong!" << endl; cout << "radiusAverage (cm): " << radiusAverage << endl; return 3; } if (TMath::Abs(radiusMin - radiusMinRef) > tolerance) { - cout << "The average radius of the distribution is wrong!" << endl; + cout << "The minimum radius of the distribution is wrong!" << endl; cout << "radiusMin (cm): " << radiusMin << endl; return 4; } if (TMath::Abs(radiusMax - radiusMaxRef) > tolerance) { - cout << "The average radius of the distribution is wrong!" << endl; + cout << "The maximum radius of the distribution is wrong!" << endl; cout << "radiusMax (cm): " << radiusMax << endl; return 5; } + if (TMath::Abs(energyPrimaryAverage - energyPrimaryAverageRef) > tolerance) { + cout << "The average energy of the distribution is wrong!" << endl; + cout << "radiusAverage (cm): " << radiusAverage << endl; + return 6; + } + if (TMath::Abs(energyPrimaryMin - energyPrimaryMinRef) > tolerance) { + cout << "The minimum energy of the distribution is wrong!" << endl; + cout << "radiusMin (cm): " << radiusMin << endl; + return 7; + } + if (TMath::Abs(energyPrimaryMax - energyPrimaryMaxRef) > tolerance) { + cout << "The maximum energy of the distribution is wrong!" << endl; + cout << "radiusMax (cm): " << radiusMax << endl; + return 8; + } + auto cos2Lambda = [](double* xs, double* ps) { if (xs[0] >= 0 && xs[0] <= TMath::Pi() / 2) { return TMath::Power(TMath::Cos(xs[0]), 2) / (TMath::Pi() / 4.0); @@ -90,9 +123,11 @@ Int_t Validate(const char* filename) { cout << "Computed difference from reference function: " << diff << endl; if (diff > 0.01) { cout << "The computed difference from reference function is too large!" << endl; - return 6; + return 9; } + // Validate energy distribution + cout << "All tests passed! [\033[32mOK\033[0m]\n"; return 0; } From 35f3cd8b3039113b90f9ce57b9bd487201100356 Mon Sep 17 00:00:00 2001 From: lobis Date: Mon, 25 Jul 2022 16:59:19 +0200 Subject: [PATCH 090/173] Added comment to example --- examples/12.Generators/CosineSquaredCircle.rml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/examples/12.Generators/CosineSquaredCircle.rml b/examples/12.Generators/CosineSquaredCircle.rml index b9183027..df825da4 100644 --- a/examples/12.Generators/CosineSquaredCircle.rml +++ b/examples/12.Generators/CosineSquaredCircle.rml @@ -28,6 +28,10 @@ rotationAngle="90deg" rotationAxis="(1,0,0)"> + + --> From bde868fffd678077a26c1215ceb761b3ec7bca70 Mon Sep 17 00:00:00 2001 From: lobis Date: Mon, 25 Jul 2022 17:17:05 +0200 Subject: [PATCH 091/173] Updated validation logic for example 12 --- examples/12.Generators/Validate.C | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/examples/12.Generators/Validate.C b/examples/12.Generators/Validate.C index 3f61add3..53f54bcf 100644 --- a/examples/12.Generators/Validate.C +++ b/examples/12.Generators/Validate.C @@ -28,8 +28,8 @@ Int_t Validate(const char* filename) { constexpr double tolerance = 0.1; double energyPrimaryAverage = 0, energyPrimaryMin = TMath::Infinity(), energyPrimaryMax = 0; - constexpr double energyPrimaryAverageRef = 53818.8, energyPrimaryMinRef = 5000.45, - energyPrimaryMaxRef = 149998.0; + constexpr double energyPrimaryAverageRef = 53818.8, energyPrimaryMinRef = 5000, + energyPrimaryMaxRef = 150000.0; TH1D thetaHist("thetaHist", "Theta angle from source direction", 100, 0, TMath::Pi()); for (int i = 0; i < run.GetEntries(); i++) { @@ -68,35 +68,35 @@ Int_t Validate(const char* filename) { cout << "Minimum energy (keV): " << energyPrimaryMin << endl; cout << "Maximum energy (keV): " << energyPrimaryMax << endl; - if (TMath::Abs(radiusAverage - radiusAverageRef) > tolerance) { + if (TMath::Abs(radiusAverage - radiusAverageRef) / radiusAverageRef > tolerance) { cout << "The average radius of the distribution is wrong!" << endl; cout << "radiusAverage (cm): " << radiusAverage << endl; return 3; } - if (TMath::Abs(radiusMin - radiusMinRef) > tolerance) { + if (TMath::Abs(radiusMin - radiusMinRef) / (radiusMinRef + 1) > tolerance) { cout << "The minimum radius of the distribution is wrong!" << endl; cout << "radiusMin (cm): " << radiusMin << endl; return 4; } - if (TMath::Abs(radiusMax - radiusMaxRef) > tolerance) { + if (TMath::Abs(radiusMax - radiusMaxRef) / radiusMaxRef > tolerance) { cout << "The maximum radius of the distribution is wrong!" << endl; cout << "radiusMax (cm): " << radiusMax << endl; return 5; } - if (TMath::Abs(energyPrimaryAverage - energyPrimaryAverageRef) > tolerance) { + if (TMath::Abs(energyPrimaryAverage - energyPrimaryAverageRef) / energyPrimaryAverageRef > tolerance) { cout << "The average energy of the distribution is wrong!" << endl; - cout << "radiusAverage (cm): " << radiusAverage << endl; + cout << "energyPrimaryAverage (keV): " << energyPrimaryAverage << endl; return 6; } - if (TMath::Abs(energyPrimaryMin - energyPrimaryMinRef) > tolerance) { + if (TMath::Abs(energyPrimaryMin - energyPrimaryMinRef) / energyPrimaryMinRef > tolerance) { cout << "The minimum energy of the distribution is wrong!" << endl; - cout << "radiusMin (cm): " << radiusMin << endl; + cout << "energyPrimaryMin (keV): " << energyPrimaryMin << endl; return 7; } - if (TMath::Abs(energyPrimaryMax - energyPrimaryMaxRef) > tolerance) { + if (TMath::Abs(energyPrimaryMax - energyPrimaryMaxRef) / energyPrimaryMaxRef > tolerance) { cout << "The maximum energy of the distribution is wrong!" << endl; - cout << "radiusMax (cm): " << radiusMax << endl; + cout << "energyPrimaryMax (keV): " << energyPrimaryMax << endl; return 8; } From 7c9d3add33671351d3d1fb5bd8d81e3d6fda62f8 Mon Sep 17 00:00:00 2001 From: Luis Obis Date: Wed, 27 Jul 2022 14:33:34 +0200 Subject: [PATCH 092/173] Added -n option to restG4 to set nEvents from cli --- include/CommandLineSetup.h | 14 ++++++----- src/Application.cxx | 4 +++ src/CommandLineSetup.cxx | 51 ++++++++++++++++++++++++++++++++++++-- 3 files changed, 61 insertions(+), 8 deletions(-) diff --git a/include/CommandLineSetup.h b/include/CommandLineSetup.h index b093be85..a7960e1d 100644 --- a/include/CommandLineSetup.h +++ b/include/CommandLineSetup.h @@ -9,12 +9,14 @@ class CommandLineParameters { public: - TString rmlFile; // -c (also default argument, does not need '-c') REQUIRED - TString outputFile; // -o output file OPTIONAL - TString geometryFile; // -g UNIQUE OPTIONAL - bool interactive = false; // -i FLAG (NO ARGUMENT) DEFAULT=FALSE OPTIONAL - bool serialMode = true; // -s FLAG (NO ARGUMENT) DEFAULT=TRUE OPTIONAL - int nThreads = 0; // -t Number of threads, only active if serialMode is set to false OPTIONAL + TString rmlFile; // -c (also default argument, does not need '-c') | REQUIRED + TString outputFile; // -o output file | OPTIONAL + TString geometryFile; // -g UNIQUE | OPTIONAL + bool interactive = false; // -i FLAG (NO ARGUMENT) DEFAULT=FALSE | OPTIONAL + bool serialMode = true; // -s FLAG (NO ARGUMENT) DEFAULT=TRUE | OPTIONAL + int nThreads = 0; // -t Number of threads, only active if serialMode is set to false | OPTIONAL + int nEvents = 0; // -n Number of events to be simulated | OPTIONAL + int nEventsOnFile = 0; // -N Number of entries desired to be on file | OPTIONAL int cmdArgc{}; char** cmdArgv = nullptr; diff --git a/src/Application.cxx b/src/Application.cxx index c364337c..86a080b9 100644 --- a/src/Application.cxx +++ b/src/Application.cxx @@ -77,6 +77,10 @@ void Application::Run(const CommandLineParameters& commandLineParameters) { metadata->SetGeant4Version(TRestTools::Execute("geant4-config --version")); + if (commandLineParameters.nEvents != 0) { + metadata->SetNumberOfEvents(commandLineParameters.nEvents); + } + if (!commandLineParameters.geometryFile.IsNull()) { metadata->SetGdmlFilename(commandLineParameters.geometryFile.Data()); } diff --git a/src/CommandLineSetup.cxx b/src/CommandLineSetup.cxx index 541acb97..d74d8e61 100644 --- a/src/CommandLineSetup.cxx +++ b/src/CommandLineSetup.cxx @@ -20,6 +20,13 @@ void CommandLineSetup::ShowUsage() { << "\t-h or --help | show usage (this text)" << endl << "\t-c example.rml | specify RML file (same as calling restG4 example.rml)" << endl << "\t-o output.root | specify output file" << endl + << "\t-n nEvents | specify number of events to be generated (overrides nEvents on rml file). " + "Incompatible with '-N' option" + << endl + << "\t-N nEventsOnFile | specify desired number of entries after simulation is completed. It will " + "adjust 'nEvents' accordingly to get this number. Final number of entries may be larger. " + "Incompatible with '-n' option" + << endl << "\t-g geometry.gdml | specify geometry file" << endl << "\t-i | set interactive mode (default=false)" << endl << "\t-s | set serial mode (no multithreading) (default=true)" << endl @@ -44,7 +51,7 @@ CommandLineParameters CommandLineSetup::ProcessParameters(int argc, char** argv) } while (true) { - const int option = getopt(argc, argv, "vg:c:m:o:ist:n:"); + const int option = getopt(argc, argv, "vg:c:m:o:ist:n:N:"); if (option == -1) break; switch (option) { case 'c': @@ -68,6 +75,7 @@ CommandLineParameters CommandLineSetup::ProcessParameters(int argc, char** argv) if (parameters.nThreads < 1) { cout << "CommandLineParameters::ProcessParameters - Number of threads must be > 0" << endl; + exit(1); } break; case 'o': @@ -80,10 +88,42 @@ CommandLineParameters CommandLineSetup::ProcessParameters(int argc, char** argv) } parameters.outputFile = optarg; break; + case 'n': + if (parameters.nEventsOnFile != 0) { + cout << "CommandLineParameters::ProcessParameters - '-n' and '-N' options are mutually " + "incompatible" + << endl; + exit(1); + } + parameters.nEvents = stoi(optarg); + if (parameters.nEvents < 1) { + cout + << "CommandLineParameters::ProcessParameters - number of generated events must be > 0" + << endl; + exit(1); + } + break; + case 'N': + if (parameters.nEvents != 0) { + cout << "CommandLineParameters::ProcessParameters - '-n' and '-N' options are mutually " + "incompatible" + << endl; + exit(1); + } + parameters.nEventsOnFile = stoi(optarg); + if (parameters.nEventsOnFile < 1) { + cout << "CommandLineParameters::ProcessParameters - number of desired entries must be > 0" + << endl; + exit(1); + } + cout << "NOT YET IMPLEMENTED" << endl; // TODO + exit(1); + break; case 'i': parameters.interactive = true; break; case 'g': + // TODO: implement if (!parameters.geometryFile.IsNull()) { cout << "CommandLineParameters::ProcessParameters - Cannot specify multiple geometry " "files via the -g flag. Please use at most one" @@ -116,6 +156,13 @@ void CommandLineSetup::Print(const CommandLineParameters& parameters) { << (!parameters.geometryFile.IsNull() ? "\t- Geometry file: " + parameters.geometryFile + "\n" : "") << (parameters.interactive ? "\t- Interactive: True\n" : "") // << "\t- Execution mode: " - << (parameters.serialMode ? "serial" : "multithreading (N = " + to_string(parameters.nThreads) + ")") + << (parameters.serialMode ? "serial\n" + : "multithreading (N = " + to_string(parameters.nThreads) + ")\n") + << (parameters.nEvents != 0 + ? "\t- Number of generated events: " + to_string(parameters.nEvents) + "\n" + : "") + << (parameters.nEventsOnFile != 0 + ? "\t- Number of desired file entries: " + to_string(parameters.nEventsOnFile) + "\n" + : "") << endl; } From 9a9bb2b369b0781db92df7dc1a42d2c02ac5d1c1 Mon Sep 17 00:00:00 2001 From: Luis Obis Date: Wed, 27 Jul 2022 16:45:31 +0200 Subject: [PATCH 093/173] Added option for "desired events on file" --- include/CommandLineSetup.h | 2 +- include/SimulationManager.h | 12 +++++++++++- src/Application.cxx | 5 ++++- src/CommandLineSetup.cxx | 12 +++++------- src/EventAction.cxx | 3 ++- src/RunAction.cxx | 17 ++++++++++++++--- src/SimulationManager.cxx | 29 +++++++++++++++++++++++++---- 7 files changed, 62 insertions(+), 18 deletions(-) diff --git a/include/CommandLineSetup.h b/include/CommandLineSetup.h index a7960e1d..cb7915e9 100644 --- a/include/CommandLineSetup.h +++ b/include/CommandLineSetup.h @@ -16,7 +16,7 @@ class CommandLineParameters { bool serialMode = true; // -s FLAG (NO ARGUMENT) DEFAULT=TRUE | OPTIONAL int nThreads = 0; // -t Number of threads, only active if serialMode is set to false | OPTIONAL int nEvents = 0; // -n Number of events to be simulated | OPTIONAL - int nEventsOnFile = 0; // -N Number of entries desired to be on file | OPTIONAL + int nDesiredEntries = 0; // -N Number of entries desired to be on file | OPTIONAL int cmdArgc{}; char** cmdArgv = nullptr; diff --git a/include/SimulationManager.h b/include/SimulationManager.h index 9693024a..9c7f0ef4 100644 --- a/include/SimulationManager.h +++ b/include/SimulationManager.h @@ -38,15 +38,20 @@ class SimulationManager { fRestGeant4PhysicsLists = physicsLists; } + void EndOfRun(); + private: static thread_local OutputManager* fOutputManager; - std::mutex fEventContainerMutex; + std::mutex fSimulationManagerMutex; std::queue > fEventContainer; TRestRun* fRestRun = nullptr; TRestGeant4PhysicsLists* fRestGeant4PhysicsLists = nullptr; TRestGeant4Metadata* fRestGeant4Metadata = nullptr; + int fNumberOfProcessedEvents = 0; + + std::vector fOutputManagerContainer = {}; /* Primary generation */ public: void InitializeUserDistributions(); @@ -80,12 +85,17 @@ class OutputManager { inline bool IsActiveVolume(const char* volumeName) const { return fActiveVolumes.count(volumeName) > 0; } + inline int GetEventCounter() const { return fThreadGeneratedEventCounter; } + private: std::unique_ptr fEvent{}; SimulationManager* fSimulationManager = nullptr; std::set fActiveVolumes = {}; + int fThreadGeneratedEventCounter = 0; + friend class StackingAction; + friend class EventAction; }; #endif // REST_SIMULATIONMANAGER_H diff --git a/src/Application.cxx b/src/Application.cxx index 86a080b9..43f97b71 100644 --- a/src/Application.cxx +++ b/src/Application.cxx @@ -80,7 +80,10 @@ void Application::Run(const CommandLineParameters& commandLineParameters) { if (commandLineParameters.nEvents != 0) { metadata->SetNumberOfEvents(commandLineParameters.nEvents); } - + if (commandLineParameters.nDesiredEntries != 0) { + metadata->SetNumberOfEvents(2147483647); // max + metadata->SetNumberOfDesiredEntries(commandLineParameters.nDesiredEntries); + } if (!commandLineParameters.geometryFile.IsNull()) { metadata->SetGdmlFilename(commandLineParameters.geometryFile.Data()); } diff --git a/src/CommandLineSetup.cxx b/src/CommandLineSetup.cxx index d74d8e61..e4a58a2a 100644 --- a/src/CommandLineSetup.cxx +++ b/src/CommandLineSetup.cxx @@ -89,7 +89,7 @@ CommandLineParameters CommandLineSetup::ProcessParameters(int argc, char** argv) parameters.outputFile = optarg; break; case 'n': - if (parameters.nEventsOnFile != 0) { + if (parameters.nDesiredEntries != 0) { cout << "CommandLineParameters::ProcessParameters - '-n' and '-N' options are mutually " "incompatible" << endl; @@ -110,14 +110,12 @@ CommandLineParameters CommandLineSetup::ProcessParameters(int argc, char** argv) << endl; exit(1); } - parameters.nEventsOnFile = stoi(optarg); - if (parameters.nEventsOnFile < 1) { + parameters.nDesiredEntries = stoi(optarg); + if (parameters.nDesiredEntries < 1) { cout << "CommandLineParameters::ProcessParameters - number of desired entries must be > 0" << endl; exit(1); } - cout << "NOT YET IMPLEMENTED" << endl; // TODO - exit(1); break; case 'i': parameters.interactive = true; @@ -161,8 +159,8 @@ void CommandLineSetup::Print(const CommandLineParameters& parameters) { << (parameters.nEvents != 0 ? "\t- Number of generated events: " + to_string(parameters.nEvents) + "\n" : "") - << (parameters.nEventsOnFile != 0 - ? "\t- Number of desired file entries: " + to_string(parameters.nEventsOnFile) + "\n" + << (parameters.nDesiredEntries != 0 + ? "\t- Number of desired file entries: " + to_string(parameters.nDesiredEntries) + "\n" : "") << endl; } diff --git a/src/EventAction.cxx b/src/EventAction.cxx index 9bdede00..6a8c96b1 100644 --- a/src/EventAction.cxx +++ b/src/EventAction.cxx @@ -21,12 +21,13 @@ EventAction::EventAction(SimulationManager* simulationManager) EventAction::~EventAction() {} void EventAction::BeginOfEventAction(const G4Event* event) { + fSimulationManager->GetOutputManager()->fThreadGeneratedEventCounter++; fSimulationManager->GetOutputManager()->UpdateEvent(); const auto eventID = event->GetEventID(); TRestRun* restRun = fSimulationManager->GetRestRun(); - TRestGeant4Metadata* restG4Metadata = fSimulationManager->GetRestMetadata(); + TRestGeant4Metadata* restG4Metadata = fSimulationManager->GetRestMetadata(); if (restG4Metadata->GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Debug) { G4cout << "DEBUG: Start of event ID " << eventID << " (" << eventID + 1 << " of " << G4RunManager::GetRunManager()->GetNumberOfEventsToBeProcessed() << "). " diff --git a/src/RunAction.cxx b/src/RunAction.cxx index 9737e64f..b1fe92e3 100644 --- a/src/RunAction.cxx +++ b/src/RunAction.cxx @@ -38,13 +38,24 @@ void RunAction::BeginOfRunAction(const G4Run*) { } void RunAction::EndOfRunAction(const G4Run*) { + fSimulationManager->EndOfRun(); + TRestRun* restRun = fSimulationManager->GetRestRun(); + const auto metadata = fSimulationManager->GetRestMetadata(); if (G4Threading::IsMasterThread() || !G4Threading::IsMultithreadedApplication()) { G4cout << "============================= Run Summary =============================" << endl; - G4cout << restRun->GetEntries() << " events stored out of " - << G4RunManager::GetRunManager()->GetNumberOfEventsToBeProcessed() << " simulated events" - << endl; + G4cout << restRun->GetEntries() << " events stored out of " << metadata->GetNumberOfEvents() + << " simulated events" << endl; G4cout << "=======================================================================" << endl; } + + // Sanity check + if (metadata->GetNumberOfDesiredEntries() == 0 && + metadata->GetNumberOfEvents() != G4RunManager::GetRunManager()->GetNumberOfEventsToBeProcessed()) { + G4cout << "ERROR: possible error when calculating number of processed events, please check " + "'RunAction::EndOfRunAction'" + << endl; + exit(1); + } } diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index eb983d13..e870e293 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -22,7 +22,21 @@ SimulationManager::SimulationManager() { } } -void SimulationManager::InitializeOutputManager() { fOutputManager = new OutputManager(this); } +void SimulationManager::InitializeOutputManager() { + lock_guard guard(fSimulationManagerMutex); + fOutputManager = new OutputManager(this); + fOutputManagerContainer.push_back(fOutputManager); +} + +void SimulationManager::EndOfRun() { + for (auto& outputManager : fOutputManagerContainer) { + fNumberOfProcessedEvents += outputManager->GetEventCounter(); + delete outputManager; + } + fOutputManagerContainer.clear(); + + GetRestMetadata()->SetNumberOfEvents(fNumberOfProcessedEvents); +} SimulationManager::~SimulationManager() { delete fRestRun; @@ -31,16 +45,15 @@ SimulationManager::~SimulationManager() { } size_t SimulationManager::InsertEvent(std::unique_ptr& event) { - fEventContainerMutex.lock(); + lock_guard guard(fSimulationManagerMutex); fEventContainer.push(std::move(event)); auto size = fEventContainer.size(); - fEventContainerMutex.unlock(); return size; } void SimulationManager::WriteEvents() { if (G4Threading::IsMultithreadedApplication()) { - lock_guard guard(fEventContainerMutex); + lock_guard guard(fSimulationManagerMutex); } if (fEventContainer.empty()) { @@ -63,6 +76,13 @@ void SimulationManager::WriteEvents() { fEventContainer.pop(); } + + const auto nDesiredEntries = GetRestMetadata()->GetNumberOfDesiredEntries(); + if (nDesiredEntries > 0 && fRestRun->GetEventTree()->GetEntries() >= nDesiredEntries) { + G4cout << "Aborting Run! We have reached the number of desired entries (" << nDesiredEntries << ")" + << endl; + G4RunManager::GetRunManager()->AbortRun(true); + } } void SimulationManager::InitializeUserDistributions() { @@ -125,6 +145,7 @@ OutputManager::OutputManager(const SimulationManager* simulationManager) } void OutputManager::UpdateEvent() { + // Called once per event at the start auto event = G4EventManager::GetEventManager()->GetConstCurrentEvent(); fEvent = make_unique(event); fEvent->InitializeReferences(fSimulationManager->GetRestRun()); From 22f58f6f80c85a860c7084fe2f61a4bf4fb28c1b Mon Sep 17 00:00:00 2001 From: Luis Obis Date: Wed, 27 Jul 2022 16:46:07 +0200 Subject: [PATCH 094/173] fixed potential segfault --- src/SimulationManager.cxx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index e870e293..6e9973a1 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -52,9 +52,7 @@ size_t SimulationManager::InsertEvent(std::unique_ptr& event) } void SimulationManager::WriteEvents() { - if (G4Threading::IsMultithreadedApplication()) { - lock_guard guard(fSimulationManagerMutex); - } + lock_guard guard(fSimulationManagerMutex); if (fEventContainer.empty()) { return; From 449fbbd664a3e439ff03f01f5e7e5027dd53955c Mon Sep 17 00:00:00 2001 From: Luis Obis Date: Wed, 27 Jul 2022 18:40:45 +0200 Subject: [PATCH 095/173] Fixed bug in MT --- include/SimulationManager.h | 8 +++++--- src/Application.cxx | 4 ++++ src/EventAction.cxx | 3 +-- src/RunAction.cxx | 2 +- src/SimulationManager.cxx | 25 ++++++++++++++++++++----- 5 files changed, 31 insertions(+), 11 deletions(-) diff --git a/include/SimulationManager.h b/include/SimulationManager.h index 9c7f0ef4..bda0068b 100644 --- a/include/SimulationManager.h +++ b/include/SimulationManager.h @@ -39,6 +39,7 @@ class SimulationManager { } void EndOfRun(); + inline bool GetAbortFlag() const { return fAbortFlag; } private: static thread_local OutputManager* fOutputManager; @@ -50,6 +51,7 @@ class SimulationManager { TRestGeant4Metadata* fRestGeant4Metadata = nullptr; int fNumberOfProcessedEvents = 0; + bool fAbortFlag = false; std::vector fOutputManagerContainer = {}; /* Primary generation */ @@ -85,17 +87,17 @@ class OutputManager { inline bool IsActiveVolume(const char* volumeName) const { return fActiveVolumes.count(volumeName) > 0; } - inline int GetEventCounter() const { return fThreadGeneratedEventCounter; } + inline int GetEventCounter() const { return fProcessedEventsCounter; } + void BeginOfEventAction(); private: std::unique_ptr fEvent{}; SimulationManager* fSimulationManager = nullptr; std::set fActiveVolumes = {}; - int fThreadGeneratedEventCounter = 0; + int fProcessedEventsCounter = 0; friend class StackingAction; - friend class EventAction; }; #endif // REST_SIMULATIONMANAGER_H diff --git a/src/Application.cxx b/src/Application.cxx index 43f97b71..73db11fa 100644 --- a/src/Application.cxx +++ b/src/Application.cxx @@ -106,6 +106,8 @@ void Application::Run(const CommandLineParameters& commandLineParameters) { metadata->SetGdmlReference(gdml->GetGDMLVersion()); metadata->SetMaterialsReference(gdml->GetEntityVersion("materials")); + metadata->PrintMetadata(); + auto physicsLists = new TRestGeant4PhysicsLists(inputRmlClean.c_str()); fSimulationManager->SetRestPhysicsLists(physicsLists); @@ -129,6 +131,7 @@ void Application::Run(const CommandLineParameters& commandLineParameters) { run->AddMetadata(fSimulationManager->GetRestMetadata()); run->AddMetadata(fSimulationManager->GetRestPhysicsLists()); + run->PrintMetadata(); run->FormOutputFile(); @@ -232,6 +235,7 @@ void Application::Run(const CommandLineParameters& commandLineParameters) { WriteGeometry(geometry, run->GetOutputFileName()); delete geometry; + metadata->PrintMetadata(); run->PrintMetadata(); cout << "============== Generated file: " << filename << " ==============" << endl; diff --git a/src/EventAction.cxx b/src/EventAction.cxx index 6a8c96b1..6c277f51 100644 --- a/src/EventAction.cxx +++ b/src/EventAction.cxx @@ -21,8 +21,7 @@ EventAction::EventAction(SimulationManager* simulationManager) EventAction::~EventAction() {} void EventAction::BeginOfEventAction(const G4Event* event) { - fSimulationManager->GetOutputManager()->fThreadGeneratedEventCounter++; - fSimulationManager->GetOutputManager()->UpdateEvent(); + fSimulationManager->GetOutputManager()->BeginOfEventAction(); const auto eventID = event->GetEventID(); TRestRun* restRun = fSimulationManager->GetRestRun(); diff --git a/src/RunAction.cxx b/src/RunAction.cxx index b1fe92e3..81ae3fb2 100644 --- a/src/RunAction.cxx +++ b/src/RunAction.cxx @@ -53,7 +53,7 @@ void RunAction::EndOfRunAction(const G4Run*) { // Sanity check if (metadata->GetNumberOfDesiredEntries() == 0 && metadata->GetNumberOfEvents() != G4RunManager::GetRunManager()->GetNumberOfEventsToBeProcessed()) { - G4cout << "ERROR: possible error when calculating number of processed events, please check " + G4cout << "FATAL ERROR: possible error when calculating number of processed events, please check " "'RunAction::EndOfRunAction'" << endl; exit(1); diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index 6e9973a1..171e2a5d 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -29,13 +29,19 @@ void SimulationManager::InitializeOutputManager() { } void SimulationManager::EndOfRun() { + if ((G4Threading::IsMultithreadedApplication() && G4Threading::G4GetThreadId() != -1)) { + return; // Only call this once from the main thread + } + + WriteEvents(); + for (auto& outputManager : fOutputManagerContainer) { fNumberOfProcessedEvents += outputManager->GetEventCounter(); delete outputManager; } - fOutputManagerContainer.clear(); - GetRestMetadata()->SetNumberOfEvents(fNumberOfProcessedEvents); + + fOutputManagerContainer.clear(); } SimulationManager::~SimulationManager() { @@ -76,10 +82,11 @@ void SimulationManager::WriteEvents() { } const auto nDesiredEntries = GetRestMetadata()->GetNumberOfDesiredEntries(); - if (nDesiredEntries > 0 && fRestRun->GetEventTree()->GetEntries() >= nDesiredEntries) { + if (nDesiredEntries > 0 && !fAbortFlag && fRestRun->GetEventTree()->GetEntries() >= nDesiredEntries) { G4cout << "Aborting Run! We have reached the number of desired entries (" << nDesiredEntries << ")" << endl; - G4RunManager::GetRunManager()->AbortRun(true); + G4RunManager::GetRunManager()->AbortRun(true); // This only aborts the current thread + fAbortFlag = true; } } @@ -142,8 +149,16 @@ OutputManager::OutputManager(const SimulationManager* simulationManager) } } +void OutputManager::BeginOfEventAction() { + // This should only be executed once at BeginOfEventAction + UpdateEvent(); + fProcessedEventsCounter++; + if (fSimulationManager->GetAbortFlag()) { + G4RunManager::GetRunManager()->AbortRun(true); + } +} + void OutputManager::UpdateEvent() { - // Called once per event at the start auto event = G4EventManager::GetEventManager()->GetConstCurrentEvent(); fEvent = make_unique(event); fEvent->InitializeReferences(fSimulationManager->GetRestRun()); From 37ac714d3e0593e5dc9fb43b842ab91f0f617181 Mon Sep 17 00:00:00 2001 From: Luis Obis Date: Wed, 27 Jul 2022 18:48:09 +0200 Subject: [PATCH 096/173] now all threads can write events (may make some simulations slower but less memory usage) --- src/EventAction.cxx | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/EventAction.cxx b/src/EventAction.cxx index 6c277f51..28f09090 100644 --- a/src/EventAction.cxx +++ b/src/EventAction.cxx @@ -52,8 +52,5 @@ void EventAction::BeginOfEventAction(const G4Event* event) { void EventAction::EndOfEventAction(const G4Event*) { fSimulationManager->GetOutputManager()->FinishAndSubmitEvent(); - if (!G4Threading::IsMultithreadedApplication() || // - (G4Threading::IsMultithreadedApplication() && G4Threading::G4GetThreadId() == 0)) { - fSimulationManager->WriteEvents(); - } + fSimulationManager->WriteEvents(); } From f10334fc164d1f955533ab2b78ae307806afa868 Mon Sep 17 00:00:00 2001 From: Luis Obis Date: Wed, 27 Jul 2022 19:01:59 +0200 Subject: [PATCH 097/173] Simplified serial/MT selection --- include/CommandLineSetup.h | 1 - src/Application.cxx | 11 ++++++----- src/CommandLineSetup.cxx | 7 +++---- test/src/examples.cxx | 1 - 4 files changed, 9 insertions(+), 11 deletions(-) diff --git a/include/CommandLineSetup.h b/include/CommandLineSetup.h index cb7915e9..7bce7e90 100644 --- a/include/CommandLineSetup.h +++ b/include/CommandLineSetup.h @@ -13,7 +13,6 @@ class CommandLineParameters { TString outputFile; // -o output file | OPTIONAL TString geometryFile; // -g UNIQUE | OPTIONAL bool interactive = false; // -i FLAG (NO ARGUMENT) DEFAULT=FALSE | OPTIONAL - bool serialMode = true; // -s FLAG (NO ARGUMENT) DEFAULT=TRUE | OPTIONAL int nThreads = 0; // -t Number of threads, only active if serialMode is set to false | OPTIONAL int nEvents = 0; // -n Number of events to be simulated | OPTIONAL int nDesiredEntries = 0; // -N Number of entries desired to be on file | OPTIONAL diff --git a/src/Application.cxx b/src/Application.cxx index 73db11fa..391b3bdc 100644 --- a/src/Application.cxx +++ b/src/Application.cxx @@ -148,17 +148,18 @@ void Application::Run(const CommandLineParameters& commandLineParameters) { #ifndef GEANT4_WITHOUT_G4RunManagerFactory auto runManagerType = G4RunManagerType::Default; - if (!commandLineParameters.serialMode) { - runManagerType = G4RunManagerType::MTOnly; - cout << "Using MT run manager with " << commandLineParameters.nThreads << " threads" << endl; - } else { + const bool serialMode = commandLineParameters.nThreads == 0; + if (serialMode) { runManagerType = G4RunManagerType::SerialOnly; cout << "Using serial run manager" << endl; + } else { + runManagerType = G4RunManagerType::MTOnly; + cout << "Using MT run manager with " << commandLineParameters.nThreads << " threads" << endl; } auto runManager = G4RunManagerFactory::CreateRunManager(runManagerType); - if (!commandLineParameters.serialMode) { + if (!serialMode) { ROOT::EnableThreadSafety(); runManager->SetNumberOfThreads(commandLineParameters.nThreads); } diff --git a/src/CommandLineSetup.cxx b/src/CommandLineSetup.cxx index e4a58a2a..af16e04c 100644 --- a/src/CommandLineSetup.cxx +++ b/src/CommandLineSetup.cxx @@ -65,12 +65,11 @@ CommandLineParameters CommandLineSetup::ProcessParameters(int argc, char** argv) break; case 's': // Serial mode - parameters.serialMode = true; + parameters.nThreads = 0; break; case 't': // TODO: implement this in the simulation // Multithreading mode - parameters.serialMode = false; parameters.nThreads = stoi(optarg); if (parameters.nThreads < 1) { cout << "CommandLineParameters::ProcessParameters - Number of threads must be > 0" @@ -154,8 +153,8 @@ void CommandLineSetup::Print(const CommandLineParameters& parameters) { << (!parameters.geometryFile.IsNull() ? "\t- Geometry file: " + parameters.geometryFile + "\n" : "") << (parameters.interactive ? "\t- Interactive: True\n" : "") // << "\t- Execution mode: " - << (parameters.serialMode ? "serial\n" - : "multithreading (N = " + to_string(parameters.nThreads) + ")\n") + << (parameters.nThreads == 0 ? "serial\n" + : "multithreading (N = " + to_string(parameters.nThreads) + ")\n") << (parameters.nEvents != 0 ? "\t- Number of generated events: " + to_string(parameters.nEvents) + "\n" : "") diff --git a/test/src/examples.cxx b/test/src/examples.cxx index e5ada7f5..93920eaf 100644 --- a/test/src/examples.cxx +++ b/test/src/examples.cxx @@ -180,7 +180,6 @@ TEST(restG4, Example_04_Muons_MT) { parameters.outputFile = thisExamplePath / "muons.root"; // TODO: fix not working with local path parameters.nThreads = 4; - parameters.serialMode = false; Application app; app.Run(parameters); From f58d8212db8ae31420459b89eee87f4f2fc72ec1 Mon Sep 17 00:00:00 2001 From: Luis Obis Date: Wed, 27 Jul 2022 19:44:48 +0200 Subject: [PATCH 098/173] Adding parse of time expression for new option -S --- include/CommandLineSetup.h | 1 + src/CommandLineSetup.cxx | 58 +++++++++++++++++++++++++++++++++++++- 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/include/CommandLineSetup.h b/include/CommandLineSetup.h index 7bce7e90..1a7a74a3 100644 --- a/include/CommandLineSetup.h +++ b/include/CommandLineSetup.h @@ -16,6 +16,7 @@ class CommandLineParameters { int nThreads = 0; // -t Number of threads, only active if serialMode is set to false | OPTIONAL int nEvents = 0; // -n Number of events to be simulated | OPTIONAL int nDesiredEntries = 0; // -N Number of entries desired to be on file | OPTIONAL + int timeLimitSeconds = 0; // -S Amount of time after which the simulation will stop | OPTIONAL int cmdArgc{}; char** cmdArgv = nullptr; diff --git a/src/CommandLineSetup.cxx b/src/CommandLineSetup.cxx index af16e04c..7a737365 100644 --- a/src/CommandLineSetup.cxx +++ b/src/CommandLineSetup.cxx @@ -4,6 +4,9 @@ #include "CommandLineSetup.h" +#include +#include +#include #include #include @@ -27,12 +30,53 @@ void CommandLineSetup::ShowUsage() { "adjust 'nEvents' accordingly to get this number. Final number of entries may be larger. " "Incompatible with '-n' option" << endl + << "\t-S timeLimit | Sets time limit for the simulation. If the time limit is reached before " + "simulation ends, it will end the simulation and save to disk all events. Follows expression " + "like '1h20m30s', '5m20s', '30s', ..." + << endl << "\t-g geometry.gdml | specify geometry file" << endl << "\t-i | set interactive mode (default=false)" << endl << "\t-s | set serial mode (no multithreading) (default=true)" << endl << "\t-t nThreads | set the number of threads, also enables multithreading" << endl; } +int GetSecondsFromTimeExpression(const char* expression) { + // expression is of the form "20h", "10m", "30s" etc. + TPRegexp timeRegex("^(\\d+)([hms])$$"); + TObjArray* subStrL = timeRegex.MatchS(expression); + const Int_t nrSubStr = subStrL->GetLast() + 1; + if (nrSubStr > 2) { + const int time = stoi(((TObjString*)subStrL->At(1))->GetString().Data()); + const TString modifier = ((TObjString*)subStrL->At(2))->GetString(); + + if (modifier == "h") { + return time * 60 * 60; + } else if (modifier == "m") { + return time * 60; + } else if (modifier == "s") { + return time; + } + } + + return 0; +} + +int GetSecondsFromFullTimeExpression(const char* expression) { + // expression is of the form "1h20m30s", "1h", "20m30s", "10s" etc. + int seconds = 0; + TPRegexp fullTimeRegex("^(\\d+h)?(\\d+m)?(\\d+s)?$"); + TObjArray* subStrL = fullTimeRegex.MatchS(expression); + + for (int i = 0; i < 3; i++) { + auto obj = (TObjString*)subStrL->At(i + 1); + if (obj != nullptr) { + seconds += GetSecondsFromTimeExpression(obj->GetString().Data()); + } + } + + return seconds; +} + CommandLineParameters CommandLineSetup::ProcessParameters(int argc, char** argv) { CommandLineParameters parameters; @@ -51,7 +95,7 @@ CommandLineParameters CommandLineSetup::ProcessParameters(int argc, char** argv) } while (true) { - const int option = getopt(argc, argv, "vg:c:m:o:ist:n:N:"); + const int option = getopt(argc, argv, "vg:c:m:o:ist:n:N:S:"); if (option == -1) break; switch (option) { case 'c': @@ -116,6 +160,15 @@ CommandLineParameters CommandLineSetup::ProcessParameters(int argc, char** argv) exit(1); } break; + case 'S': + parameters.timeLimitSeconds = GetSecondsFromFullTimeExpression(optarg); + if (parameters.timeLimitSeconds == 0) { + cout << "CommandLineParameters::ProcessParameters - time regex failed to match for " + "argument '" + << optarg << "'" << endl; + exit(1); + } + break; case 'i': parameters.interactive = true; break; @@ -161,5 +214,8 @@ void CommandLineSetup::Print(const CommandLineParameters& parameters) { << (parameters.nDesiredEntries != 0 ? "\t- Number of desired file entries: " + to_string(parameters.nDesiredEntries) + "\n" : "") + << (parameters.timeLimitSeconds != 0 + ? "\t- Time limit: " + to_string(parameters.timeLimitSeconds) + " seconds\n" + : "") << endl; } From f51a4fc0ff708c0ab5eb337462b499d93a4432da Mon Sep 17 00:00:00 2001 From: Luis Obis Date: Wed, 27 Jul 2022 20:36:50 +0200 Subject: [PATCH 099/173] working time limit to stop simulation --- include/Application.h | 4 ++-- include/SimulationManager.h | 8 +++++++ src/Application.cxx | 42 ++++++++++++++++++------------------- src/RunAction.cxx | 2 +- src/SimulationManager.cxx | 27 +++++++++++++++++++++--- 5 files changed, 56 insertions(+), 27 deletions(-) diff --git a/include/Application.h b/include/Application.h index bb0c2980..72178150 100644 --- a/include/Application.h +++ b/include/Application.h @@ -20,10 +20,10 @@ class Application { void Run(const CommandLineParameters& parameters); inline void Run(int argc, char** argv) { Run(ProcessCommandLineParameters(argc, argv)); } - ~Application() { delete fSimulationManager; } + ~Application() = default; private: - SimulationManager* fSimulationManager = nullptr; + SimulationManager fSimulationManager; void WriteGeometry(TGeoManager* geometry, const char* filename, const char* option = "UPDATE"); }; diff --git a/include/SimulationManager.h b/include/SimulationManager.h index bda0068b..02bb3f9f 100644 --- a/include/SimulationManager.h +++ b/include/SimulationManager.h @@ -40,6 +40,11 @@ class SimulationManager { void EndOfRun(); inline bool GetAbortFlag() const { return fAbortFlag; } + void StopSimulation(); + + inline double GetElapsedTime() const { + return 1E-9 * (std::chrono::steady_clock::now().time_since_epoch().count() - fTimeStartUnix); + } private: static thread_local OutputManager* fOutputManager; @@ -54,6 +59,8 @@ class SimulationManager { bool fAbortFlag = false; std::vector fOutputManagerContainer = {}; + long fTimeStartUnix = 0; + /* Primary generation */ public: void InitializeUserDistributions(); @@ -88,6 +95,7 @@ class OutputManager { inline bool IsActiveVolume(const char* volumeName) const { return fActiveVolumes.count(volumeName) > 0; } inline int GetEventCounter() const { return fProcessedEventsCounter; } + void BeginOfEventAction(); private: diff --git a/src/Application.cxx b/src/Application.cxx index 391b3bdc..5a18a55f 100644 --- a/src/Application.cxx +++ b/src/Application.cxx @@ -47,18 +47,13 @@ using namespace std; void Application::Run(const CommandLineParameters& commandLineParameters) { - delete fSimulationManager; - fSimulationManager = new SimulationManager(); - - const auto timeStart = chrono::steady_clock::now(); - const auto originalDirectory = filesystem::current_path(); cout << "Current working directory: " << originalDirectory << endl; CommandLineSetup::Print(commandLineParameters); - /// Separating relative path and pure RML filename + // Separating relative path and pure RML filename const char* inputConfigFile = const_cast(commandLineParameters.rmlFile.Data()); if (!TRestTools::CheckFileIsAccessible(inputConfigFile)) { @@ -73,17 +68,24 @@ void Application::Run(const CommandLineParameters& commandLineParameters) { } auto metadata = new TRestGeant4Metadata(inputRmlClean.c_str()); - fSimulationManager->SetRestMetadata(metadata); + fSimulationManager.SetRestMetadata(metadata); metadata->SetGeant4Version(TRestTools::Execute("geant4-config --version")); if (commandLineParameters.nEvents != 0) { metadata->SetNumberOfEvents(commandLineParameters.nEvents); } + constexpr auto maxPrimariesAllowed = 2147483647; if (commandLineParameters.nDesiredEntries != 0) { - metadata->SetNumberOfEvents(2147483647); // max + metadata->SetNumberOfEvents(maxPrimariesAllowed); metadata->SetNumberOfDesiredEntries(commandLineParameters.nDesiredEntries); } + if (commandLineParameters.timeLimitSeconds != 0) { + if (commandLineParameters.nEvents == 0) { + metadata->SetNumberOfEvents(maxPrimariesAllowed); + } + metadata->SetSimulationMaxTimeSeconds(commandLineParameters.timeLimitSeconds); + } if (!commandLineParameters.geometryFile.IsNull()) { metadata->SetGdmlFilename(commandLineParameters.geometryFile.Data()); } @@ -109,10 +111,10 @@ void Application::Run(const CommandLineParameters& commandLineParameters) { metadata->PrintMetadata(); auto physicsLists = new TRestGeant4PhysicsLists(inputRmlClean.c_str()); - fSimulationManager->SetRestPhysicsLists(physicsLists); + fSimulationManager.SetRestPhysicsLists(physicsLists); auto run = new TRestRun(); - fSimulationManager->SetRestRun(run); + fSimulationManager.SetRestRun(run); run->LoadConfigFromFile(inputRmlClean); @@ -129,22 +131,22 @@ void Application::Run(const CommandLineParameters& commandLineParameters) { run->SetRunType("restG4"); - run->AddMetadata(fSimulationManager->GetRestMetadata()); - run->AddMetadata(fSimulationManager->GetRestPhysicsLists()); + run->AddMetadata(fSimulationManager.GetRestMetadata()); + run->AddMetadata(fSimulationManager.GetRestPhysicsLists()); run->PrintMetadata(); run->FormOutputFile(); run->GetOutputFile()->cd(); - run->AddEventBranch(&fSimulationManager->fEvent); + run->AddEventBranch(&fSimulationManager.fEvent); // choose the Random engine CLHEP::HepRandom::setTheEngine(new CLHEP::RanecuEngine); long seed = metadata->GetSeed(); CLHEP::HepRandom::setTheSeed(seed); - G4VSteppingVerbose::SetInstance(new SteppingVerbose(fSimulationManager)); + G4VSteppingVerbose::SetInstance(new SteppingVerbose(&fSimulationManager)); #ifndef GEANT4_WITHOUT_G4RunManagerFactory auto runManagerType = G4RunManagerType::Default; @@ -168,13 +170,13 @@ void Application::Run(const CommandLineParameters& commandLineParameters) { auto runManager = new G4RunManager(); #endif - auto detector = new DetectorConstruction(fSimulationManager); + auto detector = new DetectorConstruction(&fSimulationManager); - fSimulationManager->InitializeUserDistributions(); + fSimulationManager.InitializeUserDistributions(); runManager->SetUserInitialization(detector); - runManager->SetUserInitialization(new PhysicsList(fSimulationManager->GetRestPhysicsLists())); - runManager->SetUserInitialization(new ActionInitialization(fSimulationManager)); + runManager->SetUserInitialization(new PhysicsList(fSimulationManager.GetRestPhysicsLists())); + runManager->SetUserInitialization(new ActionInitialization(&fSimulationManager)); runManager->Initialize(); @@ -240,9 +242,7 @@ void Application::Run(const CommandLineParameters& commandLineParameters) { run->PrintMetadata(); cout << "============== Generated file: " << filename << " ==============" << endl; - auto timeEnd = chrono::steady_clock::now(); - cout << "Elapsed time: " << chrono::duration_cast(timeEnd - timeStart).count() - << " seconds" << endl; + cout << "Elapsed time: " << fSimulationManager.GetElapsedTime() << " seconds" << endl; } void Application::WriteGeometry(TGeoManager* geometry, const char* filename, const char* option) { diff --git a/src/RunAction.cxx b/src/RunAction.cxx index 81ae3fb2..358e5c2e 100644 --- a/src/RunAction.cxx +++ b/src/RunAction.cxx @@ -51,7 +51,7 @@ void RunAction::EndOfRunAction(const G4Run*) { } // Sanity check - if (metadata->GetNumberOfDesiredEntries() == 0 && + if (metadata->GetNumberOfDesiredEntries() == 0 && metadata->GetSimulationMaxTimeSeconds() == 0 && metadata->GetNumberOfEvents() != G4RunManager::GetRunManager()->GetNumberOfEventsToBeProcessed()) { G4cout << "FATAL ERROR: possible error when calculating number of processed events, please check " "'RunAction::EndOfRunAction'" diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index 171e2a5d..80d7b4e0 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -20,6 +20,8 @@ SimulationManager::SimulationManager() { cout << "Only master thread should create the SimulationManager!" << endl; exit(1); } + + fTimeStartUnix = chrono::steady_clock::now().time_since_epoch().count(); } void SimulationManager::InitializeOutputManager() { @@ -48,6 +50,10 @@ SimulationManager::~SimulationManager() { delete fRestRun; delete fRestGeant4Metadata; delete fRestGeant4PhysicsLists; + + for (auto& outputManager : fOutputManagerContainer) { + delete outputManager; + } } size_t SimulationManager::InsertEvent(std::unique_ptr& event) { @@ -83,10 +89,9 @@ void SimulationManager::WriteEvents() { const auto nDesiredEntries = GetRestMetadata()->GetNumberOfDesiredEntries(); if (nDesiredEntries > 0 && !fAbortFlag && fRestRun->GetEventTree()->GetEntries() >= nDesiredEntries) { - G4cout << "Aborting Run! We have reached the number of desired entries (" << nDesiredEntries << ")" + G4cout << "Stopping Run! We have reached the number of desired entries (" << nDesiredEntries << ")" << endl; - G4RunManager::GetRunManager()->AbortRun(true); // This only aborts the current thread - fAbortFlag = true; + StopSimulation(); } } @@ -132,6 +137,12 @@ void SimulationManager::InitializeUserDistributions() { } } +void SimulationManager::StopSimulation() { + // Still needs to be propagated to other threads, this is done in the BeginOfEventAction + G4RunManager::GetRunManager()->AbortRun(true); + fAbortFlag = true; +} + // OutputManager OutputManager::OutputManager(const SimulationManager* simulationManager) : fSimulationManager(const_cast(simulationManager)) { @@ -153,9 +164,19 @@ void OutputManager::BeginOfEventAction() { // This should only be executed once at BeginOfEventAction UpdateEvent(); fProcessedEventsCounter++; + if (fSimulationManager->GetAbortFlag()) { G4RunManager::GetRunManager()->AbortRun(true); } + + if (fSimulationManager->GetRestMetadata()->GetSimulationMaxTimeSeconds() != 0 && + !fSimulationManager->GetAbortFlag() && + fSimulationManager->GetElapsedTime() > + fSimulationManager->GetRestMetadata()->GetSimulationMaxTimeSeconds()) { + G4cout << "Stopping Run! We have reached the time limit of " + << fSimulationManager->GetRestMetadata()->GetSimulationMaxTimeSeconds() << " seconds" << endl; + fSimulationManager->StopSimulation(); + } } void OutputManager::UpdateEvent() { From c199ebedd2c96eb9908ad6e9d2fea45483f51340 Mon Sep 17 00:00:00 2001 From: Luis Obis Date: Wed, 27 Jul 2022 21:01:33 +0200 Subject: [PATCH 100/173] Now simulation will attempt to save into disk after stop signal (CTRL+C) --- src/Application.cxx | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/Application.cxx b/src/Application.cxx index 5a18a55f..6d56e9a9 100644 --- a/src/Application.cxx +++ b/src/Application.cxx @@ -12,6 +12,7 @@ #include #include #include +#include #include #ifndef GEANT4_WITHOUT_G4RunManagerFactory @@ -46,7 +47,16 @@ using namespace std; +int interruptSignalHandler(const int signal, void* ptr) { + // See https://stackoverflow.com/a/43400143/11776908 + std::cout << "Stopping Run! Program was manually stopped by user (CTRL+C)!" << std::endl; + const auto manager = (SimulationManager*)(ptr); + manager->StopSimulation(); +} + void Application::Run(const CommandLineParameters& commandLineParameters) { + signal(SIGINT, (void (*)(int))interruptSignalHandler); + const auto originalDirectory = filesystem::current_path(); cout << "Current working directory: " << originalDirectory << endl; From 55a00cdc2dfc0a36847fbafda9868d9c50eb48d5 Mon Sep 17 00:00:00 2001 From: Luis Obis Date: Thu, 28 Jul 2022 00:26:40 +0200 Subject: [PATCH 101/173] Adding stuff to README --- README.md | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 3eeb6a37..a3efddc0 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,65 @@ [![pipeline status](https://gitlab.cern.ch/rest-for-physics/restg4/badges/master/pipeline.svg)](https://gitlab.cern.ch/rest-for-physics/restg4/-/commits/master) [![Validation](https://github.com/rest-for-physics/restG4/actions/workflows/validation.yml/badge.svg)](https://github.com/rest-for-physics/restG4/actions/workflows/validation.yml) -This README must be written yet! :( +## Table of Contents +- Usage +- Structure of the output file + +## Usage + +Typing `restG4 -h` will show all available options. + +### Basic Usage + +`restG4 simulation.rml` will launch a simulation using `simulation.rml` as the configuration file. The output file will +be saved to the specified path in the configuration. + +### Multithreading + +`restG4` makes use of the multithreading capabilities of Geant4 and can be used in multithreading mode to significantly +increase simulation speed. + +- `restG4 simulation.rml -t 8` will launch a simulation using 8 worker threads. + +By default `restG4` is executed in serial mode (one single thread) and is equivalent to the `-t 0` option. + +Simulation results are determined by the random seed and the number of threads, so using different number of threads +with the same seed will produce different results. Using the same seed and same number of threads produces the same +results. + +The multithreading implementation of `restG4` is new and although it looks to work properly it may have some bugs. If +you find one of such bugs, please post an issue [here](https://github.com/rest-for-physics/restG4/issues) with +the `multithreading` label. + +We encourage our users to use the multithreading feature especially when performing exploratory simulations. + +### Overriding values from the RML + +The CLI interface allows to set a few different parameters without having to modify the RML. + +- `restG4 simulation.rml -o output.root` to specify the output file. +- `restG4 simulation.rml -n 1000` to set the number of processed events + (`n` in Geant4's `/run/beamOn n` or `nEvents` in the rml configuration). +- `restG4 simulation.rml -g geometry.gdml` to specify the geometry file. + +### Ending the simulation early + +The simulation run will naturally end when the selected number of events have been processed. They can either be +specified in the RML file or via the `-n` flag on the CLI. However, the user can also specify additional conditions to +end the simulation early. + +- `restG4 simulation.rml -N 1000` will signal the simulation to stop once 1000 events have been marked as valid (saved + on the output file). The final simulation will probably have a slightly higher number of entries than the value + specified in the case of multithreading as the worker threads may still be working on valid events, or they may not + have been saved yet. The number of processed events (the equivalent of `nEvents`) will be adjusted to the real number + of processed events, overriding the selected value of the user, so the resulting simulation would be equivalent to a + plain simulation using this value as `nEvents`. This holds more accurately the large the `-N` parameter. +- `restG4 simulation.rml -S 1h20m30s` will signal the simulation to stop after 1 hour 20 minutes and 30 seconds have + elapsed since the start. You can specify any value using this format such as `1h15m`, `30s`, etc. +- Sending the interrupt signal (typically via `CTRL+C`) will signal the simulation to stop, and it will attempt to save + the results into disk before closing the process. + +## Structure of the output file + +TODO From f4726b78bb634a7797e1f5ed4ad0a18eadb2e156 Mon Sep 17 00:00:00 2001 From: lobis Date: Thu, 28 Jul 2022 16:48:40 +0200 Subject: [PATCH 102/173] Made invalid rml message more clear --- src/Application.cxx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Application.cxx b/src/Application.cxx index 6d56e9a9..356f6c24 100644 --- a/src/Application.cxx +++ b/src/Application.cxx @@ -47,11 +47,12 @@ using namespace std; -int interruptSignalHandler(const int signal, void* ptr) { +int interruptSignalHandler(const int, void* ptr) { // See https://stackoverflow.com/a/43400143/11776908 std::cout << "Stopping Run! Program was manually stopped by user (CTRL+C)!" << std::endl; const auto manager = (SimulationManager*)(ptr); manager->StopSimulation(); + return 0; } void Application::Run(const CommandLineParameters& commandLineParameters) { @@ -67,7 +68,8 @@ void Application::Run(const CommandLineParameters& commandLineParameters) { const char* inputConfigFile = const_cast(commandLineParameters.rmlFile.Data()); if (!TRestTools::CheckFileIsAccessible(inputConfigFile)) { - cout << "Input rml file: " << inputConfigFile << " not found, please check file name" << endl; + cout << "ERROR: Input rml file " << filesystem::weakly_canonical(inputConfigFile) + << " not found, please check file name." << endl; exit(1); } From 65e6ac810f873c4775034d22b2b38d6e287f2c88 Mon Sep 17 00:00:00 2001 From: lobis Date: Thu, 28 Jul 2022 19:00:27 +0200 Subject: [PATCH 103/173] DetectorConstruction - simplified --- src/DetectorConstruction.cxx | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/DetectorConstruction.cxx b/src/DetectorConstruction.cxx index fc3310b4..fc474340 100644 --- a/src/DetectorConstruction.cxx +++ b/src/DetectorConstruction.cxx @@ -52,8 +52,7 @@ G4VPhysicalVolume* DetectorConstruction::Construct() { fGdmlParser->Read(gdmlToRead, false); G4VPhysicalVolume* worldVolume = fGdmlParser->GetWorldVolume(); - restG4Metadata->fGeant4GeometryInfo.PopulateFromGdml(gdmlToRead); - restG4Metadata->fGeant4GeometryInfo.PopulateFromGeant4World(worldVolume); + restG4Metadata->fGeant4GeometryInfo.InitializeOnDetectorConstruction(gdmlToRead, worldVolume); const auto& geometryInfo = restG4Metadata->GetGeant4GeometryInfo(); geometryInfo.Print(); @@ -76,11 +75,7 @@ G4VPhysicalVolume* DetectorConstruction::Construct() { } if (!physicalVolume) { - G4cout << "RESTG4 error. Sensitive volume " << sensitiveVolume << " does not exist in geometry!!" - << G4endl; - G4cout << "RESTG4 error. Please, review geometry! Press a key to crash!!" << G4endl; - getchar(); - // We need to produce a clean exit at this point + G4cout << "ERROR: Sensitive volume '" << sensitiveVolume << "' not found" << G4endl; exit(1); } From 7e97c60c67385cdff9b8a0467cfadf400baccd9c Mon Sep 17 00:00:00 2001 From: lobis Date: Thu, 28 Jul 2022 19:12:16 +0200 Subject: [PATCH 104/173] Fixed bug in assembly geometry --- src/SimulationManager.cxx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index 80d7b4e0..569a1a03 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -409,9 +409,8 @@ void TRestGeant4Hits::InsertStep(const G4Step* step) { const auto& geometryInfo = metadata->GetGeant4GeometryInfo(); - // Variables that describe a step are taken. - const auto& volumeName = geometryInfo.GetAlternativeNameFromGeant4PhysicalName( - (TString &&) step->GetPreStepPoint()->GetPhysicalVolume()->GetName()); + const auto& volumeNameGeant4 = step->GetPreStepPoint()->GetPhysicalVolume()->GetName(); + const auto& volumeName = geometryInfo.GetAlternativeNameFromGeant4PhysicalName(volumeNameGeant4); if (!SimulationManager::GetOutputManager()->IsActiveVolume(volumeName) && step->GetTrack()->GetCurrentStepNumber() != 0) { @@ -461,7 +460,7 @@ void TRestGeant4Hits::InsertStep(const G4Step* step) { AddHit(hitPosition, energy, hitGlobalTime); // this increases fNHits fProcessID.emplace_back(processID); - fVolumeID.emplace_back(geometryInfo.GetIDFromVolume(volumeName)); + fVolumeID.emplace_back(geometryInfo.GetIDFromVolume(volumeNameGeant4)); fKineticEnergy.emplace_back(step->GetPreStepPoint()->GetKineticEnergy() / CLHEP::keV); fMomentumDirection.emplace_back(momentum.x(), momentum.y(), momentum.z()); From 5687905669e08455489bff83fbdf3562b4fa60d0 Mon Sep 17 00:00:00 2001 From: lobis Date: Thu, 28 Jul 2022 19:32:47 +0200 Subject: [PATCH 105/173] Simplified EventAction --- include/EventAction.h | 8 -------- src/EventAction.cxx | 1 - 2 files changed, 9 deletions(-) diff --git a/include/EventAction.h b/include/EventAction.h index 02c2ae90..177e490c 100644 --- a/include/EventAction.h +++ b/include/EventAction.h @@ -25,14 +25,6 @@ class EventAction : public G4UserEventAction { private: SimulationManager* fSimulationManager; TStopwatch fTimer; - - int SetTrackSubEventIDs(); - void FillSubEvent(Int_t subId); - // old method `FillSubEvent` has been split into `FillSubEvent` and `ReOrderTrackIds` for speed - void ReOrderTrackIds(Int_t subId); - - // variable used to track the number of events that hit the sensitive volume - UInt_t sensitive_volume_hits_count = 0; }; #endif diff --git a/src/EventAction.cxx b/src/EventAction.cxx index 28f09090..3169b692 100644 --- a/src/EventAction.cxx +++ b/src/EventAction.cxx @@ -51,6 +51,5 @@ void EventAction::BeginOfEventAction(const G4Event* event) { void EventAction::EndOfEventAction(const G4Event*) { fSimulationManager->GetOutputManager()->FinishAndSubmitEvent(); - fSimulationManager->WriteEvents(); } From 71f07a17e65d4318464b6cf5a8ed448365f436e1 Mon Sep 17 00:00:00 2001 From: lobis Date: Thu, 28 Jul 2022 20:15:16 +0200 Subject: [PATCH 106/173] Fixed bug on assembly geometry --- src/DetectorConstruction.cxx | 15 ++++++++++++--- src/SensitiveDetector.cxx | 10 +++++----- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/DetectorConstruction.cxx b/src/DetectorConstruction.cxx index fc474340..98dae0d6 100644 --- a/src/DetectorConstruction.cxx +++ b/src/DetectorConstruction.cxx @@ -68,7 +68,8 @@ G4VPhysicalVolume* DetectorConstruction::Construct() { // sensitive volume was not found, perhaps the user specified a logical volume auto physicalVolumes = geometryInfo.GetAllPhysicalVolumesFromLogical(sensitiveVolume); if (physicalVolumes.size() == 1) { - restG4Metadata->SetSensitiveVolume(physicalVolumes[0]); + restG4Metadata->SetSensitiveVolume( + geometryInfo.GetAlternativeNameFromGeant4PhysicalName(physicalVolumes[0])); sensitiveVolume = (string)restG4Metadata->GetSensitiveVolume(); physicalVolume = GetPhysicalVolume(sensitiveVolume); } @@ -226,7 +227,14 @@ void DetectorConstruction::ConstructSDandField() { G4LogicalVolume* logicalVolume = nullptr; G4VPhysicalVolume* physicalVolume = G4PhysicalVolumeStore::GetInstance()->GetVolume(userSensitiveVolume, false); - if (!physicalVolume) { + if (physicalVolume == nullptr) { + const G4String geant4VolumeName = + metadata.GetGeant4GeometryInfo() + .GetGeant4PhysicalNameFromAlternativeName(userSensitiveVolume.c_str()) + .Data(); + physicalVolume = G4PhysicalVolumeStore::GetInstance()->GetVolume(geant4VolumeName, false); + } + if (physicalVolume == nullptr) { // perhaps user selected a logical volume with this name logicalVolume = G4LogicalVolumeStore::GetInstance()->GetVolume(userSensitiveVolume, false); } else { @@ -236,7 +244,8 @@ void DetectorConstruction::ConstructSDandField() { auto logicalVolumes = metadata.GetGeant4GeometryInfo().GetAllLogicalVolumesMatchingExpression(userSensitiveVolume); if (logicalVolumes.empty()) { - cout << "Error on sensitive detector setup" << endl; + cout << "Error on sensitive detector setup for sensitive volume: " << userSensitiveVolume + << endl; exit(1); } else { for (const auto& logicalVolumeName : logicalVolumes) { diff --git a/src/SensitiveDetector.cxx b/src/SensitiveDetector.cxx index 243767c6..5e7f9dfe 100644 --- a/src/SensitiveDetector.cxx +++ b/src/SensitiveDetector.cxx @@ -16,10 +16,14 @@ SensitiveDetector::SensitiveDetector(SimulationManager* simulationManager, const G4bool SensitiveDetector::ProcessHits(G4Step* step, G4TouchableHistory*) { // return value will always be ignored, its present for backwards compatibility (I guess) + const auto volumeName = fSimulationManager->GetRestMetadata() + ->GetGeant4GeometryInfo() + .GetAlternativeNameFromGeant4PhysicalName( + step->GetPreStepPoint()->GetPhysicalVolume()->GetName()); + const bool isGeantino = step->GetTrack()->GetParticleDefinition() == G4Geantino::Definition(); if (isGeantino) { - const auto volumeName = (TString)step->GetPreStepPoint()->GetPhysicalVolume()->GetName(); const auto length = step->GetStepLength() / CLHEP::mm; fSimulationManager->GetOutputManager()->AddSensitiveEnergy(length, volumeName); return true; @@ -29,11 +33,7 @@ G4bool SensitiveDetector::ProcessHits(G4Step* step, G4TouchableHistory*) { if (energy <= 0) { return true; } - - const auto volumeName = (TString)step->GetPreStepPoint()->GetPhysicalVolume()->GetName(); - fSimulationManager->GetOutputManager()->AddSensitiveEnergy(energy, volumeName); - return true; } } \ No newline at end of file From 050f35e7e6d17fb06d3ccce50184f6be8d2fd0cd Mon Sep 17 00:00:00 2001 From: lobis Date: Thu, 28 Jul 2022 22:14:15 +0200 Subject: [PATCH 107/173] -n and -N options are no longer incompatible --- include/PrimaryGeneratorAction.h | 2 +- src/Application.cxx | 9 ++++----- src/CommandLineSetup.cxx | 12 ------------ src/PrimaryGeneratorAction.cxx | 4 ++-- 4 files changed, 7 insertions(+), 20 deletions(-) diff --git a/include/PrimaryGeneratorAction.h b/include/PrimaryGeneratorAction.h index 165607c8..4d61b101 100644 --- a/include/PrimaryGeneratorAction.h +++ b/include/PrimaryGeneratorAction.h @@ -80,7 +80,7 @@ class PrimaryGeneratorAction : public G4VUserPrimaryGeneratorAction { void GenPositionOnCylinderSurface(double& x, double& y, double& z); void GenPositionOnPoint(double& x, double& y, double& z); void GenPositionOnWall(double& x, double& y, double& z); - void GenPositionOnPlate(double& x, double& y, double& z); + void GenPositionOnDisk(double& x, double& y, double& z); G4String fParType; G4String fGenType; diff --git a/src/Application.cxx b/src/Application.cxx index 356f6c24..7e8e9d6d 100644 --- a/src/Application.cxx +++ b/src/Application.cxx @@ -84,18 +84,17 @@ void Application::Run(const CommandLineParameters& commandLineParameters) { metadata->SetGeant4Version(TRestTools::Execute("geant4-config --version")); + constexpr auto maxPrimariesAllowed = 2147483647; if (commandLineParameters.nEvents != 0) { metadata->SetNumberOfEvents(commandLineParameters.nEvents); } - constexpr auto maxPrimariesAllowed = 2147483647; - if (commandLineParameters.nDesiredEntries != 0) { + if (commandLineParameters.nEvents == 0) { metadata->SetNumberOfEvents(maxPrimariesAllowed); + } + if (commandLineParameters.nDesiredEntries != 0) { metadata->SetNumberOfDesiredEntries(commandLineParameters.nDesiredEntries); } if (commandLineParameters.timeLimitSeconds != 0) { - if (commandLineParameters.nEvents == 0) { - metadata->SetNumberOfEvents(maxPrimariesAllowed); - } metadata->SetSimulationMaxTimeSeconds(commandLineParameters.timeLimitSeconds); } if (!commandLineParameters.geometryFile.IsNull()) { diff --git a/src/CommandLineSetup.cxx b/src/CommandLineSetup.cxx index 7a737365..5d67a441 100644 --- a/src/CommandLineSetup.cxx +++ b/src/CommandLineSetup.cxx @@ -132,12 +132,6 @@ CommandLineParameters CommandLineSetup::ProcessParameters(int argc, char** argv) parameters.outputFile = optarg; break; case 'n': - if (parameters.nDesiredEntries != 0) { - cout << "CommandLineParameters::ProcessParameters - '-n' and '-N' options are mutually " - "incompatible" - << endl; - exit(1); - } parameters.nEvents = stoi(optarg); if (parameters.nEvents < 1) { cout @@ -147,12 +141,6 @@ CommandLineParameters CommandLineSetup::ProcessParameters(int argc, char** argv) } break; case 'N': - if (parameters.nEvents != 0) { - cout << "CommandLineParameters::ProcessParameters - '-n' and '-N' options are mutually " - "incompatible" - << endl; - exit(1); - } parameters.nDesiredEntries = stoi(optarg); if (parameters.nDesiredEntries < 1) { cout << "CommandLineParameters::ProcessParameters - number of desired entries must be > 0" diff --git a/src/PrimaryGeneratorAction.cxx b/src/PrimaryGeneratorAction.cxx index 11fbe243..108f50f4 100644 --- a/src/PrimaryGeneratorAction.cxx +++ b/src/PrimaryGeneratorAction.cxx @@ -381,7 +381,7 @@ void PrimaryGeneratorAction::SetParticlePosition() { } else if (spatialGeneratorShapeEnum == SpatialGeneratorShapes::SPHERE) { GenPositionOnSphereSurface(x, y, z); } else if (spatialGeneratorShapeEnum == SpatialGeneratorShapes::CIRCLE) { - GenPositionOnPlate(x, y, z); + GenPositionOnDisk(x, y, z); } else if (spatialGeneratorShapeEnum == SpatialGeneratorShapes::WALL) { GenPositionOnWall(x, y, z); } @@ -614,7 +614,7 @@ void PrimaryGeneratorAction::GenPositionOnWall(double& x, double& y, double& z) z = position.z() + center.Z(); } -void PrimaryGeneratorAction::GenPositionOnPlate(double& x, double& y, double& z) { +void PrimaryGeneratorAction::GenPositionOnDisk(double& x, double& y, double& z) { TRestGeant4Metadata* restG4Metadata = fSimulationManager->GetRestMetadata(); const auto& primaryGeneratorInfo = restG4Metadata->GetGeant4PrimaryGeneratorInfo(); From 1e11d2b55a9d7daaa4bb53d3e9ed4438a4df0062 Mon Sep 17 00:00:00 2001 From: lobis Date: Thu, 28 Jul 2022 23:56:21 +0200 Subject: [PATCH 108/173] Improved print statements --- include/SimulationManager.h | 10 +++++++++- src/Application.cxx | 9 +++++++-- src/EventAction.cxx | 15 +++++++++++---- src/SensitiveDetector.cxx | 2 ++ src/SimulationManager.cxx | 17 +++++++++++------ 5 files changed, 40 insertions(+), 13 deletions(-) diff --git a/include/SimulationManager.h b/include/SimulationManager.h index 02bb3f9f..52a901a0 100644 --- a/include/SimulationManager.h +++ b/include/SimulationManager.h @@ -22,7 +22,7 @@ class SimulationManager { TRestGeant4Event fEvent; // Branch on EventTree - size_t InsertEvent(std::unique_ptr& event); + void InsertEvent(std::unique_ptr& event); void WriteEvents(); void WriteEventsAndCloseFile(); @@ -46,6 +46,11 @@ class SimulationManager { return 1E-9 * (std::chrono::steady_clock::now().time_since_epoch().count() - fTimeStartUnix); } + void SyncStatsFromChild(); + + int GetNumberOfProcessedEvents() const { return fNumberOfProcessedEvents; } + int GetNumberOfStoredEvents() const { return fNumberOfStoredEvents; } + private: static thread_local OutputManager* fOutputManager; std::mutex fSimulationManagerMutex; @@ -56,6 +61,8 @@ class SimulationManager { TRestGeant4Metadata* fRestGeant4Metadata = nullptr; int fNumberOfProcessedEvents = 0; + int fNumberOfStoredEvents = 0; + bool fAbortFlag = false; std::vector fOutputManagerContainer = {}; @@ -95,6 +102,7 @@ class OutputManager { inline bool IsActiveVolume(const char* volumeName) const { return fActiveVolumes.count(volumeName) > 0; } inline int GetEventCounter() const { return fProcessedEventsCounter; } + inline void ResetEventCounter() { fProcessedEventsCounter = 0; } void BeginOfEventAction(); diff --git a/src/Application.cxx b/src/Application.cxx index 7e8e9d6d..ac486f55 100644 --- a/src/Application.cxx +++ b/src/Application.cxx @@ -242,6 +242,8 @@ void Application::Run(const CommandLineParameters& commandLineParameters) { run->SetEndTimeStamp((Double_t)systime); const TString filename = TRestTools::ToAbsoluteName(run->GetOutputFileName().Data()); + const auto nEntries = run->GetEntries(); + run->UpdateOutputFile(); run->CloseFile(); @@ -252,8 +254,11 @@ void Application::Run(const CommandLineParameters& commandLineParameters) { metadata->PrintMetadata(); run->PrintMetadata(); - cout << "============== Generated file: " << filename << " ==============" << endl; - cout << "Elapsed time: " << fSimulationManager.GetElapsedTime() << " seconds" << endl; + cout << "\t- Total simulation time is " << fSimulationManager.GetElapsedTime() << " seconds, " << nEvents + << " processed events (" << nEvents / fSimulationManager.GetElapsedTime() << " per second) and " + << nEntries << " events saved to output file (" << nEntries / fSimulationManager.GetElapsedTime() + << " per second)" << endl; + cout << "\t- Output file: " << filename << endl << endl; } void Application::WriteGeometry(TGeoManager* geometry, const char* filename, const char* option) { diff --git a/src/EventAction.cxx b/src/EventAction.cxx index 3169b692..ae99390f 100644 --- a/src/EventAction.cxx +++ b/src/EventAction.cxx @@ -40,9 +40,17 @@ void EventAction::BeginOfEventAction(const G4Event* event) { ((numberOfEventsToBePercent > 0 && (eventID + 1) % numberOfEventsToBePercent == 0) || fTimer.RealTime() > 10.0)) { fTimer.Start(); - G4cout << "ESSENTIAL: Start of event ID " << eventID << " (" << eventID + 1 << " of " - << restG4Metadata->GetNumberOfEvents() << "). " << restRun->GetEntries() - << " Events stored" << endl; + + fSimulationManager->SyncStatsFromChild(); + G4cout << double(fSimulationManager->GetNumberOfProcessedEvents()) / + double(restG4Metadata->GetNumberOfEvents()) * 100 + << "% - " << fSimulationManager->GetNumberOfProcessedEvents() + << " Events processed out of " << restG4Metadata->GetNumberOfEvents() + << " requested events (" + << fSimulationManager->GetNumberOfProcessedEvents() / fSimulationManager->GetElapsedTime() + << " per second). " << fSimulationManager->GetNumberOfStoredEvents() << " events stored (" + << fSimulationManager->GetNumberOfStoredEvents() / fSimulationManager->GetElapsedTime() + << " per second). " << fSimulationManager->GetElapsedTime() << " seconds elapsed" << endl; } else { fTimer.Continue(); } @@ -51,5 +59,4 @@ void EventAction::BeginOfEventAction(const G4Event* event) { void EventAction::EndOfEventAction(const G4Event*) { fSimulationManager->GetOutputManager()->FinishAndSubmitEvent(); - fSimulationManager->WriteEvents(); } diff --git a/src/SensitiveDetector.cxx b/src/SensitiveDetector.cxx index 5e7f9dfe..98054a93 100644 --- a/src/SensitiveDetector.cxx +++ b/src/SensitiveDetector.cxx @@ -24,6 +24,8 @@ G4bool SensitiveDetector::ProcessHits(G4Step* step, G4TouchableHistory*) { const bool isGeantino = step->GetTrack()->GetParticleDefinition() == G4Geantino::Definition(); if (isGeantino) { + // Since geantinos don't deposit energy, the length traveled inside the volumes is stored as energy + // (mm as keV) const auto length = step->GetStepLength() / CLHEP::mm; fSimulationManager->GetOutputManager()->AddSensitiveEnergy(length, volumeName); return true; diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index 569a1a03..30d2ad1e 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -56,11 +56,9 @@ SimulationManager::~SimulationManager() { } } -size_t SimulationManager::InsertEvent(std::unique_ptr& event) { +void SimulationManager::InsertEvent(std::unique_ptr& event) { lock_guard guard(fSimulationManagerMutex); fEventContainer.push(std::move(event)); - auto size = fEventContainer.size(); - return size; } void SimulationManager::WriteEvents() { @@ -143,6 +141,13 @@ void SimulationManager::StopSimulation() { fAbortFlag = true; } +void SimulationManager::SyncStatsFromChild() { + lock_guard guard(fSimulationManagerMutex); + fNumberOfProcessedEvents += fOutputManager->GetEventCounter(); + fOutputManager->ResetEventCounter(); + fNumberOfStoredEvents = fRestRun->GetEntries(); +} + // OutputManager OutputManager::OutputManager(const SimulationManager* simulationManager) : fSimulationManager(const_cast(simulationManager)) { @@ -192,6 +197,7 @@ bool OutputManager::IsValidEvent() const { return false; } if (fSimulationManager->GetRestMetadata()->GetSaveAllEvents()) { + // sometimes it enters this section even thought the flag is clearly set to false ??? return true; } if (fEvent->GetSensitiveVolumeEnergy() <= 0) { @@ -207,10 +213,9 @@ bool OutputManager::IsValidEvent() const { } void OutputManager::FinishAndSubmitEvent() { - if (IsEmptyEvent()) return; - if (IsValidEvent()) { - size_t numberOfInsertedEvents = fSimulationManager->InsertEvent(fEvent); + fSimulationManager->InsertEvent(fEvent); + fSimulationManager->WriteEvents(); } UpdateEvent(); } From cc6f62c8671ba1139dacf66410f3a259038eb5ea Mon Sep 17 00:00:00 2001 From: lobis Date: Fri, 29 Jul 2022 00:03:20 +0200 Subject: [PATCH 109/173] Removed problematic code when using geantino --- src/SimulationManager.cxx | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index 30d2ad1e..bd09b013 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -197,7 +197,6 @@ bool OutputManager::IsValidEvent() const { return false; } if (fSimulationManager->GetRestMetadata()->GetSaveAllEvents()) { - // sometimes it enters this section even thought the flag is clearly set to false ??? return true; } if (fEvent->GetSensitiveVolumeEnergy() <= 0) { @@ -448,10 +447,6 @@ void TRestGeant4Hits::InsertStep(const G4Step* step) { auto sensitiveVolumeName = geometryInfo.GetAlternativeNameFromGeant4PhysicalName(metadata->GetSensitiveVolume()); - if (particle->GetParticleName() == "geantino" && sensitiveVolumeName.Data() == volumeName) { - metadata->SetSaveAllEvents(true); - } - G4Track* aTrack = step->GetTrack(); Double_t x = aTrack->GetPosition().x() / CLHEP::mm; From 3f7f130e362e37b6b38f742604ffe6f440740677 Mon Sep 17 00:00:00 2001 From: lobis Date: Fri, 29 Jul 2022 00:19:45 +0200 Subject: [PATCH 110/173] Fixed bug introduced for assembly geometry --- src/DetectorConstruction.cxx | 6 +++--- src/SimulationManager.cxx | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/DetectorConstruction.cxx b/src/DetectorConstruction.cxx index 98dae0d6..6f26bb4f 100644 --- a/src/DetectorConstruction.cxx +++ b/src/DetectorConstruction.cxx @@ -294,11 +294,11 @@ void TRestGeant4GeometryInfo::PopulateFromGeant4World(const G4VPhysicalVolume* w TString nameMaterial = (TString)volume->GetLogicalVolume()->GetMaterial()->GetName(); auto position = volume->GetTranslation(); - fPhysicalToLogicalVolumeMap[namePhysical] = nameLogical; + fPhysicalToLogicalVolumeMap[physicalNewName] = nameLogical; fLogicalToMaterialMap[nameLogical] = nameMaterial; fLogicalToPhysicalMap[nameLogical].emplace_back(namePhysical); - fPhysicalToPositionInWorldMap[namePhysical] = {position.x(), position.y(), position.z()}; - InsertVolumeName(i, namePhysical); + fPhysicalToPositionInWorldMap[physicalNewName] = {position.x(), position.y(), position.z()}; + InsertVolumeName(i, physicalNewName); if (!fIsAssembly && GetAlternativeNameFromGeant4PhysicalName(namePhysical) != namePhysical) { fIsAssembly = true; diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index bd09b013..fbfd0b94 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -460,7 +460,7 @@ void TRestGeant4Hits::InsertStep(const G4Step* step) { AddHit(hitPosition, energy, hitGlobalTime); // this increases fNHits fProcessID.emplace_back(processID); - fVolumeID.emplace_back(geometryInfo.GetIDFromVolume(volumeNameGeant4)); + fVolumeID.emplace_back(geometryInfo.GetIDFromVolume(volumeName)); fKineticEnergy.emplace_back(step->GetPreStepPoint()->GetKineticEnergy() / CLHEP::keV); fMomentumDirection.emplace_back(momentum.x(), momentum.y(), momentum.z()); From 37a3a544e0d6c8a4229a505e4053f5e8f05a4658 Mon Sep 17 00:00:00 2001 From: lobis Date: Fri, 29 Jul 2022 12:17:13 +0200 Subject: [PATCH 111/173] Fixed bug with nEvents setting from rml --- src/Application.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Application.cxx b/src/Application.cxx index ac486f55..0f72956d 100644 --- a/src/Application.cxx +++ b/src/Application.cxx @@ -88,7 +88,7 @@ void Application::Run(const CommandLineParameters& commandLineParameters) { if (commandLineParameters.nEvents != 0) { metadata->SetNumberOfEvents(commandLineParameters.nEvents); } - if (commandLineParameters.nEvents == 0) { + if (metadata->GetNumberOfEvents() == 0) { metadata->SetNumberOfEvents(maxPrimariesAllowed); } if (commandLineParameters.nDesiredEntries != 0) { From 6337003ff81c406cf80a9a12b1f94a3a8313855f Mon Sep 17 00:00:00 2001 From: lobis Date: Fri, 29 Jul 2022 13:43:40 +0200 Subject: [PATCH 112/173] Simplified command line options --- include/Application.h | 31 +++-- include/CommandLineSetup.h | 37 ------ main.cxx | 7 +- src/Application.cxx | 243 ++++++++++++++++++++++++++++++++++--- src/CommandLineSetup.cxx | 209 ------------------------------- test/src/examples.cxx | 100 +++++++-------- 6 files changed, 303 insertions(+), 324 deletions(-) delete mode 100644 include/CommandLineSetup.h delete mode 100644 src/CommandLineSetup.cxx diff --git a/include/Application.h b/include/Application.h index 72178150..33af3681 100644 --- a/include/Application.h +++ b/include/Application.h @@ -2,7 +2,6 @@ #ifndef REST_APPLICATION_H #define REST_APPLICATION_H -#include "CommandLineSetup.h" #include "SimulationManager.h" class G4VisManager; @@ -11,14 +10,32 @@ class G4RunManager; class TGeoManager; +namespace CommandLineOptions { +struct Options { + std::string rmlFile{}; + std::string outputFile{}; + std::string geometryFile{}; + + bool interactive = false; + + int nThreads = 0; + + int nEvents = 0; + Long_t seed = 0; + + int nDesiredEntries = 0; + int timeLimitSeconds = 0; +}; + +Options ProcessCommandLineOptions(int argc, char* const argv[]); +void PrintOptions(const Options& options); +void ShowUsage(); + +} // namespace CommandLineOptions + class Application { public: - inline static CommandLineParameters ProcessCommandLineParameters(int argc, char** argv) { - return CommandLineSetup::ProcessParameters(argc, argv); - } - - void Run(const CommandLineParameters& parameters); - inline void Run(int argc, char** argv) { Run(ProcessCommandLineParameters(argc, argv)); } + void Run(const CommandLineOptions::Options& options); ~Application() = default; diff --git a/include/CommandLineSetup.h b/include/CommandLineSetup.h deleted file mode 100644 index 1a7a74a3..00000000 --- a/include/CommandLineSetup.h +++ /dev/null @@ -1,37 +0,0 @@ -// -// Created by lobis on 10/8/2021. -// - -#ifndef REST_COMMANDLINESETUP_H -#define REST_COMMANDLINESETUP_H - -#include - -class CommandLineParameters { - public: - TString rmlFile; // -c (also default argument, does not need '-c') | REQUIRED - TString outputFile; // -o output file | OPTIONAL - TString geometryFile; // -g UNIQUE | OPTIONAL - bool interactive = false; // -i FLAG (NO ARGUMENT) DEFAULT=FALSE | OPTIONAL - int nThreads = 0; // -t Number of threads, only active if serialMode is set to false | OPTIONAL - int nEvents = 0; // -n Number of events to be simulated | OPTIONAL - int nDesiredEntries = 0; // -N Number of entries desired to be on file | OPTIONAL - int timeLimitSeconds = 0; // -S Amount of time after which the simulation will stop | OPTIONAL - - int cmdArgc{}; - char** cmdArgv = nullptr; - - CommandLineParameters() = default; -}; - -class CommandLineSetup { - public: - CommandLineSetup() = delete; - - static CommandLineParameters ProcessParameters(int argc, char* argv[]); - - static void ShowUsage(); - static void Print(const CommandLineParameters&); -}; - -#endif // REST_COMMANDLINESETUP_H diff --git a/main.cxx b/main.cxx index 7b31b381..bced63ce 100644 --- a/main.cxx +++ b/main.cxx @@ -3,7 +3,10 @@ using namespace std; -int main(int argc, char** argv) { +int main(int argc, char* argv[]) { Application app; - app.Run(argc, argv); + + CommandLineOptions::Options options = CommandLineOptions::ProcessCommandLineOptions(argc, argv); + + app.Run(options); } diff --git a/src/Application.cxx b/src/Application.cxx index 0f72956d..1803e81e 100644 --- a/src/Application.cxx +++ b/src/Application.cxx @@ -5,6 +5,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -26,7 +29,6 @@ #include #include "ActionInitialization.h" -#include "CommandLineSetup.h" #include "DetectorConstruction.h" #include "EventAction.h" #include "PhysicsList.h" @@ -47,25 +49,225 @@ using namespace std; +namespace CommandLineOptions { + +void ShowUsage() { + cout << "Usage example: restG4 example.rml" << endl + << endl + << "there are other convenient optional parameters that override the ones in the rml file:" << endl + << "\t--help (-h) | show usage (this text)" << endl + << "\t--config (-c) example.rml | specify RML file (same as calling restG4 example.rml)" << endl + << "\t--output (-o) output.root | specify output file" << endl + << "\t--events (-n) nEvents | specify number of events to be processed (overrides nEvents on rml " + "file)" + << endl + << "\t--entries (-e) | specify the desired number of entries. The simulation will stop after " + "reaching this number of saved events. Final number may be larger" + << endl + << "\t--time timeLimit | Sets time limit for the simulation in the format '1h20m30s', '5m20s', " + "'30s', ... If the time limit is reached before simulation ends, it will end the simulation and " + "save to disk all events" + << endl + << "\t--geometry (-g) geometry.gdml | specify geometry file" << endl + << "\t--seed (-s) seed | specify random seed (positive integer)" << endl + << "\t--interactive (-i) | set interactive mode (disabled by default)" << endl + << "\t--threads (-t, -j) | set the number of threads, also enables multithreading which is disabled " + "by default" + << endl; +} + +void PrintOptions(const Options& options) { + cout << "Command line parameters configuration:" << endl + << "\t- RML file: " << options.rmlFile << endl + << (!options.outputFile.empty() ? "\t- Output file: " + options.outputFile + "\n" : "") + << (!options.geometryFile.empty() ? "\t- Geometry file: " + options.geometryFile + "\n" : "") + << (options.interactive ? "\t- Interactive: True\n" : "") // + << "\t- Execution mode: " + << (options.nThreads == 0 ? "serial\n" + : "multithreading (N = " + to_string(options.nThreads) + ")\n") + << (options.nEvents != 0 ? "\t- Number of generated events: " + to_string(options.nEvents) + "\n" + : "") + << (options.seed != 0 ? "\t- Random seed: " + to_string(options.seed) + "\n" : "") + << (options.nDesiredEntries != 0 + ? "\t- Number of desired file entries: " + to_string(options.nDesiredEntries) + "\n" + : "") + << (options.timeLimitSeconds != 0 + ? "\t- Time limit: " + to_string(options.timeLimitSeconds) + " seconds\n" + : "") + << endl; +} + +int GetSecondsFromTimeExpression(const char* expression) { + // expression is of the form "20h", "10m", "30s" etc. + TPRegexp timeRegex("^(\\d+)([hms])$$"); + TObjArray* subStrL = timeRegex.MatchS(expression); + const Int_t nrSubStr = subStrL->GetLast() + 1; + if (nrSubStr > 2) { + const int time = stoi(((TObjString*)subStrL->At(1))->GetString().Data()); + const TString modifier = ((TObjString*)subStrL->At(2))->GetString(); + + if (modifier == "h") { + return time * 60 * 60; + } else if (modifier == "m") { + return time * 60; + } else if (modifier == "s") { + return time; + } + } + + return 0; +} + +int GetSecondsFromFullTimeExpression(const char* expression) { + // expression is of the form "1h20m30s", "1h", "20m30s", "10s" etc. + int seconds = 0; + TPRegexp fullTimeRegex("^(\\d+h)?(\\d+m)?(\\d+s)?$"); + TObjArray* subStrL = fullTimeRegex.MatchS(expression); + + for (int i = 0; i < 3; i++) { + auto obj = (TObjString*)subStrL->At(i + 1); + if (obj != nullptr) { + seconds += GetSecondsFromTimeExpression(obj->GetString().Data()); + } + } + + return seconds; +} + +Options ProcessCommandLineOptions(int argc, char* const argv[]) { + // See https://cplusplus.com/articles/DEN36Up4/ + Options options; + + if (argc <= 2) { + // Invoked without parameter + ShowUsage(); + exit(0); + } + + for (int i = 1; i < argc; ++i) { + string arg = argv[i]; + if ((arg == "-h") || (arg == "--help")) { + ShowUsage(); + exit(0); + } else if ((arg == "-c") || (arg == "--config")) { + if (i + 1 < argc) { // Make sure we aren't at the end of argv! + options.rmlFile = + argv[i++]; // Increment 'i' so we don't get the argument as the next argv[i]. + } else { + cerr << "--config option requires one argument" << endl; + exit(1); + } + } else if ((arg == "-o") || (arg == "--output")) { + if (i + 1 < argc) { // Make sure we aren't at the end of argv! + options.outputFile = + argv[i++]; // Increment 'i' so we don't get the argument as the next argv[i]. + } else { + cerr << "--output option requires one argument" << endl; + exit(1); + } + } else if ((arg == "-g") || (arg == "--geometry")) { + if (i + 1 < argc) { // Make sure we aren't at the end of argv! + options.geometryFile = + argv[i++]; // Increment 'i' so we don't get the argument as the next argv[i]. + } else { + cerr << "--geometry option requires one argument" << endl; + exit(1); + } + } else if ((arg == "-i") || (arg == "--interactive")) { + options.interactive = true; + // TODO: not yet implemented + cout << "--interactive option not yet implemented" << endl; + exit(1); + } else if ((arg == "-j") || (arg == "--threads") || (arg == "-t")) { + if (i + 1 < argc) { // Make sure we aren't at the end of argv! + options.nThreads = + stoi(argv[i++]); // Increment 'i' so we don't get the argument as the next argv[i]. + if (options.nThreads < 1) { + cout << "--threads option error: number of threads must be > 0" << endl; + exit(1); + } + } else { + cerr << "--threads option requires one argument." << endl; + exit(1); + } + } else if ((arg == "-n") || (arg == "--events")) { + if (i + 1 < argc) { // Make sure we aren't at the end of argv! + options.nEvents = + stoi(argv[i++]); // Increment 'i' so we don't get the argument as the next argv[i]. + if (options.nEvents <= 0) { + cout << "--events option error: number of events must be > 0" << endl; + exit(1); + } + } else { + cerr << "--events option requires one argument." << endl; + exit(1); + } + } else if ((arg == "-e") || (arg == "--entries")) { + if (i + 1 < argc) { // Make sure we aren't at the end of argv! + options.nDesiredEntries = + stoi(argv[i++]); // Increment 'i' so we don't get the argument as the next argv[i]. + if (options.nDesiredEntries <= 0) { + cout << "--entries option error: number of entries must be > 0" << endl; + exit(1); + } + } else { + cerr << "--entries option requires one argument." << endl; + exit(1); + } + } else if ((arg == "-s") || (arg == "--seed")) { + if (i + 1 < argc) { // Make sure we aren't at the end of argv! + options.seed = + stoi(argv[i++]); // Increment 'i' so we don't get the argument as the next argv[i]. + if (options.seed <= 0) { + cout << "--seed option error: seed must be positive number" << endl; + exit(1); + } + } else { + cerr << "--seed option requires one argument." << endl; + exit(1); + } + } else if (arg == "--time") { + if (i + 1 < argc) { // Make sure we aren't at the end of argv! + options.timeLimitSeconds = GetSecondsFromFullTimeExpression( + argv[i++]); // Increment 'i' so we don't get the argument as the next argv[i]. + if (options.timeLimitSeconds <= 0) { + cout << "--time option error: time limit must be of the format 1h20m30s, 10m20s, 1h, etc." + << endl; + exit(1); + } + } else { + cerr << "--time option requires one argument." << endl; + exit(1); + } + } else { + options.rmlFile = argv[i]; // invoked as restG4 , restG4 -j 4 , etc. + } + } + + return options; +} + +} // namespace CommandLineOptions + int interruptSignalHandler(const int, void* ptr) { // See https://stackoverflow.com/a/43400143/11776908 - std::cout << "Stopping Run! Program was manually stopped by user (CTRL+C)!" << std::endl; + cout << "Stopping Run! Program was manually stopped by user (CTRL+C)!" << endl; const auto manager = (SimulationManager*)(ptr); manager->StopSimulation(); return 0; } -void Application::Run(const CommandLineParameters& commandLineParameters) { +void Application::Run(const CommandLineOptions::Options& options) { signal(SIGINT, (void (*)(int))interruptSignalHandler); const auto originalDirectory = filesystem::current_path(); cout << "Current working directory: " << originalDirectory << endl; - CommandLineSetup::Print(commandLineParameters); + CommandLineOptions::PrintOptions(options); // Separating relative path and pure RML filename - const char* inputConfigFile = const_cast(commandLineParameters.rmlFile.Data()); + const char* inputConfigFile = options.rmlFile.c_str(); if (!TRestTools::CheckFileIsAccessible(inputConfigFile)) { cout << "ERROR: Input rml file " << filesystem::weakly_canonical(inputConfigFile) @@ -84,21 +286,24 @@ void Application::Run(const CommandLineParameters& commandLineParameters) { metadata->SetGeant4Version(TRestTools::Execute("geant4-config --version")); + if (options.seed != 0) { + metadata->SetSeed(options.seed); + } constexpr auto maxPrimariesAllowed = 2147483647; - if (commandLineParameters.nEvents != 0) { - metadata->SetNumberOfEvents(commandLineParameters.nEvents); + if (options.nEvents != 0) { + metadata->SetNumberOfEvents(options.nEvents); } if (metadata->GetNumberOfEvents() == 0) { metadata->SetNumberOfEvents(maxPrimariesAllowed); } - if (commandLineParameters.nDesiredEntries != 0) { - metadata->SetNumberOfDesiredEntries(commandLineParameters.nDesiredEntries); + if (options.nDesiredEntries != 0) { + metadata->SetNumberOfDesiredEntries(options.nDesiredEntries); } - if (commandLineParameters.timeLimitSeconds != 0) { - metadata->SetSimulationMaxTimeSeconds(commandLineParameters.timeLimitSeconds); + if (options.timeLimitSeconds != 0) { + metadata->SetSimulationMaxTimeSeconds(options.timeLimitSeconds); } - if (!commandLineParameters.geometryFile.IsNull()) { - metadata->SetGdmlFilename(commandLineParameters.geometryFile.Data()); + if (!options.geometryFile.empty()) { + metadata->SetGdmlFilename(options.geometryFile); } // We need to process and generate a new GDML for several reasons. @@ -129,8 +334,8 @@ void Application::Run(const CommandLineParameters& commandLineParameters) { run->LoadConfigFromFile(inputRmlClean); - if (!commandLineParameters.outputFile.IsNull()) { - run->SetOutputFileName(commandLineParameters.outputFile.Data()); + if (!options.outputFile.empty()) { + run->SetOutputFileName(options.outputFile); } filesystem::current_path(originalDirectory); @@ -161,20 +366,20 @@ void Application::Run(const CommandLineParameters& commandLineParameters) { #ifndef GEANT4_WITHOUT_G4RunManagerFactory auto runManagerType = G4RunManagerType::Default; - const bool serialMode = commandLineParameters.nThreads == 0; + const bool serialMode = options.nThreads == 0; if (serialMode) { runManagerType = G4RunManagerType::SerialOnly; cout << "Using serial run manager" << endl; } else { runManagerType = G4RunManagerType::MTOnly; - cout << "Using MT run manager with " << commandLineParameters.nThreads << " threads" << endl; + cout << "Using MT run manager with " << options.nThreads << " threads" << endl; } auto runManager = G4RunManagerFactory::CreateRunManager(runManagerType); if (!serialMode) { ROOT::EnableThreadSafety(); - runManager->SetNumberOfThreads(commandLineParameters.nThreads); + runManager->SetNumberOfThreads(options.nThreads); } #else cout << "Using serial run manager" << endl; @@ -219,7 +424,7 @@ void Application::Run(const CommandLineParameters& commandLineParameters) { { #ifdef G4UI_USE cout << "Entering vis mode.." << endl; - auto ui = new G4UIExecutive(commandLineParameters.cmdArgc, commandLineParameters.cmdArgv); + auto ui = new G4UIExecutive(options.cmdArgc, options.cmdArgv); #ifdef G4VIS_USE cout << "Executing G4 macro : /control/execute macros/vis.mac" << endl; UI->ApplyCommand("/control/execute macros/vis.mac"); diff --git a/src/CommandLineSetup.cxx b/src/CommandLineSetup.cxx deleted file mode 100644 index 5d67a441..00000000 --- a/src/CommandLineSetup.cxx +++ /dev/null @@ -1,209 +0,0 @@ -// -// Created by lobis on 10/8/2021. -// - -#include "CommandLineSetup.h" - -#include -#include -#include -#include -#include - -#include - -using namespace std; - -void CommandLineSetup::ShowUsage() { - cout << "restG4 requires at least one parameter, the rml configuration file" << endl - << endl - << "example: restG4 example.rml" << endl - << endl - << "there are other convenient optional parameters that override the ones in the rml file:" << endl - << "\t-h or --help | show usage (this text)" << endl - << "\t-c example.rml | specify RML file (same as calling restG4 example.rml)" << endl - << "\t-o output.root | specify output file" << endl - << "\t-n nEvents | specify number of events to be generated (overrides nEvents on rml file). " - "Incompatible with '-N' option" - << endl - << "\t-N nEventsOnFile | specify desired number of entries after simulation is completed. It will " - "adjust 'nEvents' accordingly to get this number. Final number of entries may be larger. " - "Incompatible with '-n' option" - << endl - << "\t-S timeLimit | Sets time limit for the simulation. If the time limit is reached before " - "simulation ends, it will end the simulation and save to disk all events. Follows expression " - "like '1h20m30s', '5m20s', '30s', ..." - << endl - << "\t-g geometry.gdml | specify geometry file" << endl - << "\t-i | set interactive mode (default=false)" << endl - << "\t-s | set serial mode (no multithreading) (default=true)" << endl - << "\t-t nThreads | set the number of threads, also enables multithreading" << endl; -} - -int GetSecondsFromTimeExpression(const char* expression) { - // expression is of the form "20h", "10m", "30s" etc. - TPRegexp timeRegex("^(\\d+)([hms])$$"); - TObjArray* subStrL = timeRegex.MatchS(expression); - const Int_t nrSubStr = subStrL->GetLast() + 1; - if (nrSubStr > 2) { - const int time = stoi(((TObjString*)subStrL->At(1))->GetString().Data()); - const TString modifier = ((TObjString*)subStrL->At(2))->GetString(); - - if (modifier == "h") { - return time * 60 * 60; - } else if (modifier == "m") { - return time * 60; - } else if (modifier == "s") { - return time; - } - } - - return 0; -} - -int GetSecondsFromFullTimeExpression(const char* expression) { - // expression is of the form "1h20m30s", "1h", "20m30s", "10s" etc. - int seconds = 0; - TPRegexp fullTimeRegex("^(\\d+h)?(\\d+m)?(\\d+s)?$"); - TObjArray* subStrL = fullTimeRegex.MatchS(expression); - - for (int i = 0; i < 3; i++) { - auto obj = (TObjString*)subStrL->At(i + 1); - if (obj != nullptr) { - seconds += GetSecondsFromTimeExpression(obj->GetString().Data()); - } - } - - return seconds; -} - -CommandLineParameters CommandLineSetup::ProcessParameters(int argc, char** argv) { - CommandLineParameters parameters; - - parameters.cmdArgc = argc; - parameters.cmdArgv = argv; - - if (argc >= 2) { - // presumably invoked as `restG4 example.rml` or `restG4 --help` - TString argument = argv[1]; - if (argument.EqualTo("--help") || argument.EqualTo("-h")) { - ShowUsage(); - exit(0); - } else { - parameters.rmlFile = argument; - } - } - - while (true) { - const int option = getopt(argc, argv, "vg:c:m:o:ist:n:N:S:"); - if (option == -1) break; - switch (option) { - case 'c': - if (!parameters.rmlFile.IsNull()) { - cout << "CommandLineParameters::ProcessParameters - Cannot specify multiple rml files " - " Please use at most one" - << endl; - exit(1); - } - parameters.rmlFile = optarg; - break; - case 's': - // Serial mode - parameters.nThreads = 0; - break; - case 't': - // TODO: implement this in the simulation - // Multithreading mode - parameters.nThreads = stoi(optarg); - if (parameters.nThreads < 1) { - cout << "CommandLineParameters::ProcessParameters - Number of threads must be > 0" - << endl; - exit(1); - } - break; - case 'o': - if (!parameters.outputFile.IsNull()) { - cout << "CommandLineParameters::ProcessParameters - Cannot specify multiple output files " - "via the -o flag." - " Please use at most one" - << endl; - exit(1); - } - parameters.outputFile = optarg; - break; - case 'n': - parameters.nEvents = stoi(optarg); - if (parameters.nEvents < 1) { - cout - << "CommandLineParameters::ProcessParameters - number of generated events must be > 0" - << endl; - exit(1); - } - break; - case 'N': - parameters.nDesiredEntries = stoi(optarg); - if (parameters.nDesiredEntries < 1) { - cout << "CommandLineParameters::ProcessParameters - number of desired entries must be > 0" - << endl; - exit(1); - } - break; - case 'S': - parameters.timeLimitSeconds = GetSecondsFromFullTimeExpression(optarg); - if (parameters.timeLimitSeconds == 0) { - cout << "CommandLineParameters::ProcessParameters - time regex failed to match for " - "argument '" - << optarg << "'" << endl; - exit(1); - } - break; - case 'i': - parameters.interactive = true; - break; - case 'g': - // TODO: implement - if (!parameters.geometryFile.IsNull()) { - cout << "CommandLineParameters::ProcessParameters - Cannot specify multiple geometry " - "files via the -g flag. Please use at most one" - << endl; - exit(1); - } - parameters.geometryFile = optarg; - break; - default: - // invalid option - cout << "Error processing command line arguments" << endl; - exit(1); - } - } - - // validation - if (parameters.rmlFile.IsNull()) { - cout << "CommandLineParameters::ProcessParameters - Need to define an RML config file (-c)" << endl; - ShowUsage(); - exit(1); - } - - return parameters; -} - -void CommandLineSetup::Print(const CommandLineParameters& parameters) { - cout << "Command line parameters configuration:" << endl - << "\t- RML file: " << parameters.rmlFile << endl - << (!parameters.outputFile.IsNull() ? "\t- Output file: " + parameters.outputFile + "\n" : "") - << (!parameters.geometryFile.IsNull() ? "\t- Geometry file: " + parameters.geometryFile + "\n" : "") - << (parameters.interactive ? "\t- Interactive: True\n" : "") // - << "\t- Execution mode: " - << (parameters.nThreads == 0 ? "serial\n" - : "multithreading (N = " + to_string(parameters.nThreads) + ")\n") - << (parameters.nEvents != 0 - ? "\t- Number of generated events: " + to_string(parameters.nEvents) + "\n" - : "") - << (parameters.nDesiredEntries != 0 - ? "\t- Number of desired file entries: " + to_string(parameters.nDesiredEntries) + "\n" - : "") - << (parameters.timeLimitSeconds != 0 - ? "\t- Time limit: " + to_string(parameters.timeLimitSeconds) + " seconds\n" - : "") - << endl; -} diff --git a/test/src/examples.cxx b/test/src/examples.cxx index 93920eaf..182c7038 100644 --- a/test/src/examples.cxx +++ b/test/src/examples.cxx @@ -28,14 +28,14 @@ TEST(restG4, Example_01_NLDBD) { const auto thisExamplePath = examplesPath / "01.NLDBD"; fs::current_path(thisExamplePath); - CommandLineParameters parameters; - parameters.rmlFile = "NLDBD.rml"; - parameters.outputFile = + CommandLineOptions::Options options; + options.rmlFile = "NLDBD.rml"; + options.outputFile = thisExamplePath / "NLDBD_simulation.root"; // TODO: fix not working with local path { // Run simulation Application app; - app.Run(parameters); + app.Run(options); } { // Run validation macro @@ -43,7 +43,7 @@ TEST(restG4, Example_01_NLDBD) { gROOT->ProcessLine(TString::Format(".L %s", macro.Data())); // Load macro int error = 0; const int result = - gROOT->ProcessLine(TString::Format("Validate(\"%s\")", parameters.outputFile.Data()), &error); + gROOT->ProcessLine(TString::Format("Validate(\"%s\")", options.outputFile.c_str()), &error); EXPECT_EQ(error, 0); EXPECT_EQ(result, 0); } @@ -66,12 +66,12 @@ TEST(restG4, Metadata) { cout << "Results file not found, generating file..." << endl; fs::current_path(thisExamplePath); - CommandLineParameters parameters; - parameters.rmlFile = "NLDBD.rml"; - parameters.outputFile = resultsFile; + CommandLineOptions::Options options; + options.rmlFile = "NLDBD.rml"; + options.outputFile = resultsFile; Application app; - app.Run(parameters); + app.Run(options); fs::current_path(originalPath); } else { @@ -146,26 +146,26 @@ TEST(restG4, Example_04_Muons) { const auto thisExamplePath = examplesPath / "04.MuonScan"; fs::current_path(thisExamplePath); - CommandLineParameters parameters; - parameters.rmlFile = "CosmicMuonsFromWall.rml"; - parameters.outputFile = thisExamplePath / "muons.root"; // TODO: fix not working with local path + CommandLineOptions::Options options; + options.rmlFile = "CosmicMuonsFromWall.rml"; + options.outputFile = thisExamplePath / "muons.root"; // TODO: fix not working with local path Application app; - app.Run(parameters); + app.Run(options); // Run validation macro const TString macro(thisExamplePath / "ValidateWall.C"); gROOT->ProcessLine(TString::Format(".L %s", macro.Data())); // Load macro int error = 0; const int result = - gROOT->ProcessLine(TString::Format("ValidateWall(\"%s\")", parameters.outputFile.Data()), &error); + gROOT->ProcessLine(TString::Format("ValidateWall(\"%s\")", options.outputFile.c_str()), &error); EXPECT_EQ(error, 0); EXPECT_EQ(result, 0); fs::current_path(originalPath); // use output file to check additional things - TRestRun run(parameters.outputFile.Data()); + TRestRun run(options.outputFile.c_str()); cout << "Number of entries: " << run.GetEntries() << endl; } @@ -175,28 +175,28 @@ TEST(restG4, Example_04_Muons_MT) { const auto thisExamplePath = examplesPath / "04.MuonScan"; fs::current_path(thisExamplePath); - CommandLineParameters parameters; - parameters.rmlFile = "CosmicMuonsFromWall.rml"; - parameters.outputFile = thisExamplePath / "muons.root"; // TODO: fix not working with local path + CommandLineOptions::Options options; + options.rmlFile = "CosmicMuonsFromWall.rml"; + options.outputFile = thisExamplePath / "muons.root"; // TODO: fix not working with local path - parameters.nThreads = 4; + options.nThreads = 4; Application app; - app.Run(parameters); + app.Run(options); // Run validation macro const TString macro(thisExamplePath / "ValidateWall.C"); gROOT->ProcessLine(TString::Format(".L %s", macro.Data())); // Load macro int error = 0; const int result = - gROOT->ProcessLine(TString::Format("ValidateWall(\"%s\")", parameters.outputFile.Data()), &error); + gROOT->ProcessLine(TString::Format("ValidateWall(\"%s\")", options.outputFile.c_str()), &error); EXPECT_EQ(error, 0); EXPECT_EQ(result, 0); fs::current_path(originalPath); // use output file to check additional things - TRestRun run(parameters.outputFile.Data()); + TRestRun run(options.outputFile.c_str()); cout << "Number of entries: " << run.GetEntries() << endl; } @@ -206,19 +206,19 @@ TEST(restG4, Example_05_PandaX) { const auto thisExamplePath = examplesPath / "05.PandaXIII"; fs::current_path(thisExamplePath); - CommandLineParameters parameters; - parameters.rmlFile = "Xe136bb0n.rml"; - parameters.outputFile = thisExamplePath / "Xe136bb0n.root"; // TODO: fix not working with local path + CommandLineOptions::Options options; + options.rmlFile = "Xe136bb0n.rml"; + options.outputFile = thisExamplePath / "Xe136bb0n.root"; // TODO: fix not working with local path Application app; - app.Run(parameters); + app.Run(options); // Run validation macro const TString macro(thisExamplePath / "Validate.C"); gROOT->ProcessLine(TString::Format(".L %s", macro.Data())); // Load macro int error = 0; const int result = - gROOT->ProcessLine(TString::Format("Validate(\"%s\")", parameters.outputFile.Data()), &error); + gROOT->ProcessLine(TString::Format("Validate(\"%s\")", options.outputFile.c_str()), &error); EXPECT_EQ(error, 0); EXPECT_EQ(result, 0); @@ -231,19 +231,19 @@ TEST(restG4, Example_06_IonRecoils) { const auto thisExamplePath = examplesPath / "06.IonRecoils"; fs::current_path(thisExamplePath); - CommandLineParameters parameters; - parameters.rmlFile = "recoils.rml"; - parameters.outputFile = thisExamplePath / "recoils.root"; + CommandLineOptions::Options options; + options.rmlFile = "recoils.rml"; + options.outputFile = thisExamplePath / "recoils.root"; Application app; - app.Run(parameters); + app.Run(options); // Run validation macro const TString macro(thisExamplePath / "Validate.C"); gROOT->ProcessLine(TString::Format(".L %s", macro.Data())); // Load macro int error = 0; const int result = - gROOT->ProcessLine(TString::Format("Validate(\"%s\")", parameters.outputFile.Data()), &error); + gROOT->ProcessLine(TString::Format("Validate(\"%s\")", options.outputFile.c_str()), &error); EXPECT_EQ(error, 0); EXPECT_EQ(result, 0); @@ -256,15 +256,15 @@ TEST(restG4, Example_07_Decay_FullChain) { const auto thisExamplePath = examplesPath / "07.FullChainDecay"; fs::current_path(thisExamplePath); - CommandLineParameters parameters; - parameters.rmlFile = "fullChain.rml"; - parameters.outputFile = thisExamplePath / "fullChain.root"; // TODO: fix not working with local path + CommandLineOptions::Options options; + options.rmlFile = "fullChain.rml"; + options.outputFile = thisExamplePath / "fullChain.root"; // TODO: fix not working with local path Application app; - app.Run(parameters); + app.Run(options); // print processes - TRestRun run(parameters.outputFile.Data()); + TRestRun run(options.outputFile.c_str()); auto geant4Metadata = (TRestGeant4Metadata*)run.GetMetadataClass("TRestGeant4Metadata"); EXPECT_EQ(geant4Metadata != nullptr, true); @@ -278,7 +278,7 @@ TEST(restG4, Example_07_Decay_FullChain) { gROOT->ProcessLine(TString::Format(".L %s", macro.Data())); // Load macro int error = 0; const int result = - gROOT->ProcessLine(TString::Format("Validate(\"%s\", %d)", parameters.outputFile.Data(), 17), &error); + gROOT->ProcessLine(TString::Format("Validate(\"%s\", %d)", options.outputFile.c_str(), 17), &error); EXPECT_EQ(error, 0); EXPECT_EQ(result, 0); @@ -292,21 +292,21 @@ TEST(restG4, Example_09_Pb210_Shield) { const auto thisExamplePath = examplesPath / "09.Pb210_Shield"; fs::current_path(thisExamplePath); - CommandLineParameters parameters; - parameters.rmlFile = "Pb210.rml"; - parameters.outputFile = thisExamplePath / "shielding.root"; // TODO: fix not working with local path + CommandLineOptions::Options options; + options.rmlFile = "Pb210.rml"; + options.outputFile = thisExamplePath / "shielding.root"; // TODO: fix not working with local path Application app; - app.Run(parameters); + app.Run(options); - TRestRun run(parameters.outputFile.Data()); + TRestRun run(options.outputFile.c_str()); // Run validation macro const TString macro(thisExamplePath / "Validate.C"); gROOT->ProcessLine(TString::Format(".L %s", macro.Data())); // Load macro int error = 0; const int result = - gROOT->ProcessLine(TString::Format("Validate(\"%s\")", parameters.outputFile.Data()), &error); + gROOT->ProcessLine(TString::Format("Validate(\"%s\")", options.outputFile.c_str()), &error); EXPECT_EQ(error, 0); EXPECT_EQ(result, 0); @@ -319,21 +319,21 @@ TEST(restG4, Example_12_Generators) { const auto thisExamplePath = examplesPath / "12.Generators"; fs::current_path(thisExamplePath); - CommandLineParameters parameters; - parameters.rmlFile = "CosineSquaredCircle.rml"; - parameters.outputFile = thisExamplePath / "cosine.root"; + CommandLineOptions::Options options; + options.rmlFile = "CosineSquaredCircle.rml"; + options.outputFile = thisExamplePath / "cosine.root"; Application app; - app.Run(parameters); + app.Run(options); - TRestRun run(parameters.outputFile.Data()); + TRestRun run(options.outputFile); // Run validation macro const TString macro(thisExamplePath / "Validate.C"); gROOT->ProcessLine(TString::Format(".L %s", macro.Data())); // Load macro int error = 0; const int result = - gROOT->ProcessLine(TString::Format("Validate(\"%s\")", parameters.outputFile.Data()), &error); + gROOT->ProcessLine(TString::Format("Validate(\"%s\")", options.outputFile.c_str()), &error); EXPECT_EQ(error, 0); EXPECT_EQ(result, 0); From a78047d529b61a4347e25c2cf0f2975599fca622 Mon Sep 17 00:00:00 2001 From: lobis Date: Fri, 29 Jul 2022 14:04:30 +0200 Subject: [PATCH 113/173] fixed small bug --- test/src/examples.cxx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/test/src/examples.cxx b/test/src/examples.cxx index 182c7038..2c610fba 100644 --- a/test/src/examples.cxx +++ b/test/src/examples.cxx @@ -1,6 +1,5 @@ #include -#include #include #include #include @@ -30,8 +29,7 @@ TEST(restG4, Example_01_NLDBD) { CommandLineOptions::Options options; options.rmlFile = "NLDBD.rml"; - options.outputFile = - thisExamplePath / "NLDBD_simulation.root"; // TODO: fix not working with local path + options.outputFile = thisExamplePath / "NLDBD_simulation.root"; // TODO: fix not working with local path { // Run simulation Application app; From 36462865bb8cb5ed350f3854bdd7fba4fa4a8a71 Mon Sep 17 00:00:00 2001 From: lobis Date: Fri, 29 Jul 2022 14:05:11 +0200 Subject: [PATCH 114/173] Added cli banner --- main.cxx | 14 ++++++++++++++ src/Application.cxx | 1 - 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/main.cxx b/main.cxx index bced63ce..a6208eb5 100644 --- a/main.cxx +++ b/main.cxx @@ -3,7 +3,21 @@ using namespace std; +constexpr auto banner = + " ##### # \n" + " ##### ###### #### ##### # # # # \n" + " # # # # # # # # \n" + " # # ##### #### # # #### # # \n" + " ##### # # # # # ####### \n" + " # # # # # # # # # \n" + " # # ###### #### # ##### # \n" + "\n" + "🔍 Source code: https://github.com/rest-for-physics/restG4\n" + "🐞 Bug reports: https://github.com/rest-for-physics/restG4/issues\n"; + int main(int argc, char* argv[]) { + cout << banner << endl; + Application app; CommandLineOptions::Options options = CommandLineOptions::ProcessCommandLineOptions(argc, argv); diff --git a/src/Application.cxx b/src/Application.cxx index 1803e81e..7060a7a7 100644 --- a/src/Application.cxx +++ b/src/Application.cxx @@ -53,7 +53,6 @@ namespace CommandLineOptions { void ShowUsage() { cout << "Usage example: restG4 example.rml" << endl - << endl << "there are other convenient optional parameters that override the ones in the rml file:" << endl << "\t--help (-h) | show usage (this text)" << endl << "\t--config (-c) example.rml | specify RML file (same as calling restG4 example.rml)" << endl From 1f070e87068e9c7a14d40e87c5a58feeb30f98ba Mon Sep 17 00:00:00 2001 From: lobis Date: Fri, 29 Jul 2022 14:16:33 +0200 Subject: [PATCH 115/173] Fixed bug with G4UI_USE --- include/Application.h | 4 ++++ src/Application.cxx | 6 ++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/include/Application.h b/include/Application.h index 33af3681..aa6b954b 100644 --- a/include/Application.h +++ b/include/Application.h @@ -25,6 +25,10 @@ struct Options { int nDesiredEntries = 0; int timeLimitSeconds = 0; + + // reference to original argc and argv necessary to pass to G4UIExecutive + int argc; + char** argv; }; Options ProcessCommandLineOptions(int argc, char* const argv[]); diff --git a/src/Application.cxx b/src/Application.cxx index 7060a7a7..8fd3535c 100644 --- a/src/Application.cxx +++ b/src/Application.cxx @@ -134,8 +134,9 @@ int GetSecondsFromFullTimeExpression(const char* expression) { } Options ProcessCommandLineOptions(int argc, char* const argv[]) { - // See https://cplusplus.com/articles/DEN36Up4/ Options options; + options.argc = argc; + options.argv = const_cast(argv); if (argc <= 2) { // Invoked without parameter @@ -143,6 +144,7 @@ Options ProcessCommandLineOptions(int argc, char* const argv[]) { exit(0); } + // See https://cplusplus.com/articles/DEN36Up4/ for (int i = 1; i < argc; ++i) { string arg = argv[i]; if ((arg == "-h") || (arg == "--help")) { @@ -423,7 +425,7 @@ void Application::Run(const CommandLineOptions::Options& options) { { #ifdef G4UI_USE cout << "Entering vis mode.." << endl; - auto ui = new G4UIExecutive(options.cmdArgc, options.cmdArgv); + auto ui = new G4UIExecutive(options.argc, options.argv); #ifdef G4VIS_USE cout << "Executing G4 macro : /control/execute macros/vis.mac" << endl; UI->ApplyCommand("/control/execute macros/vis.mac"); From 9390d6ec8522cf14d2daa970bd67320e39e5e57c Mon Sep 17 00:00:00 2001 From: lobis Date: Fri, 29 Jul 2022 15:50:30 +0200 Subject: [PATCH 116/173] Fixed arg parsing --- src/Application.cxx | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Application.cxx b/src/Application.cxx index 8fd3535c..39c50118 100644 --- a/src/Application.cxx +++ b/src/Application.cxx @@ -145,7 +145,7 @@ Options ProcessCommandLineOptions(int argc, char* const argv[]) { } // See https://cplusplus.com/articles/DEN36Up4/ - for (int i = 1; i < argc; ++i) { + for (int i = 1; i < argc; i++) { string arg = argv[i]; if ((arg == "-h") || (arg == "--help")) { ShowUsage(); @@ -153,7 +153,7 @@ Options ProcessCommandLineOptions(int argc, char* const argv[]) { } else if ((arg == "-c") || (arg == "--config")) { if (i + 1 < argc) { // Make sure we aren't at the end of argv! options.rmlFile = - argv[i++]; // Increment 'i' so we don't get the argument as the next argv[i]. + argv[++i]; // Increment 'i' so we don't get the argument as the next argv[i]. } else { cerr << "--config option requires one argument" << endl; exit(1); @@ -161,7 +161,7 @@ Options ProcessCommandLineOptions(int argc, char* const argv[]) { } else if ((arg == "-o") || (arg == "--output")) { if (i + 1 < argc) { // Make sure we aren't at the end of argv! options.outputFile = - argv[i++]; // Increment 'i' so we don't get the argument as the next argv[i]. + argv[++i]; // Increment 'i' so we don't get the argument as the next argv[i]. } else { cerr << "--output option requires one argument" << endl; exit(1); @@ -169,7 +169,7 @@ Options ProcessCommandLineOptions(int argc, char* const argv[]) { } else if ((arg == "-g") || (arg == "--geometry")) { if (i + 1 < argc) { // Make sure we aren't at the end of argv! options.geometryFile = - argv[i++]; // Increment 'i' so we don't get the argument as the next argv[i]. + argv[++i]; // Increment 'i' so we don't get the argument as the next argv[i]. } else { cerr << "--geometry option requires one argument" << endl; exit(1); @@ -182,7 +182,7 @@ Options ProcessCommandLineOptions(int argc, char* const argv[]) { } else if ((arg == "-j") || (arg == "--threads") || (arg == "-t")) { if (i + 1 < argc) { // Make sure we aren't at the end of argv! options.nThreads = - stoi(argv[i++]); // Increment 'i' so we don't get the argument as the next argv[i]. + stoi(argv[++i]); // Increment 'i' so we don't get the argument as the next argv[i]. if (options.nThreads < 1) { cout << "--threads option error: number of threads must be > 0" << endl; exit(1); @@ -194,7 +194,7 @@ Options ProcessCommandLineOptions(int argc, char* const argv[]) { } else if ((arg == "-n") || (arg == "--events")) { if (i + 1 < argc) { // Make sure we aren't at the end of argv! options.nEvents = - stoi(argv[i++]); // Increment 'i' so we don't get the argument as the next argv[i]. + stoi(argv[++i]); // Increment 'i' so we don't get the argument as the next argv[i]. if (options.nEvents <= 0) { cout << "--events option error: number of events must be > 0" << endl; exit(1); @@ -206,7 +206,7 @@ Options ProcessCommandLineOptions(int argc, char* const argv[]) { } else if ((arg == "-e") || (arg == "--entries")) { if (i + 1 < argc) { // Make sure we aren't at the end of argv! options.nDesiredEntries = - stoi(argv[i++]); // Increment 'i' so we don't get the argument as the next argv[i]. + stoi(argv[++i]); // Increment 'i' so we don't get the argument as the next argv[i]. if (options.nDesiredEntries <= 0) { cout << "--entries option error: number of entries must be > 0" << endl; exit(1); @@ -218,7 +218,7 @@ Options ProcessCommandLineOptions(int argc, char* const argv[]) { } else if ((arg == "-s") || (arg == "--seed")) { if (i + 1 < argc) { // Make sure we aren't at the end of argv! options.seed = - stoi(argv[i++]); // Increment 'i' so we don't get the argument as the next argv[i]. + stoi(argv[++i]); // Increment 'i' so we don't get the argument as the next argv[i]. if (options.seed <= 0) { cout << "--seed option error: seed must be positive number" << endl; exit(1); @@ -230,7 +230,7 @@ Options ProcessCommandLineOptions(int argc, char* const argv[]) { } else if (arg == "--time") { if (i + 1 < argc) { // Make sure we aren't at the end of argv! options.timeLimitSeconds = GetSecondsFromFullTimeExpression( - argv[i++]); // Increment 'i' so we don't get the argument as the next argv[i]. + argv[++i]); // Increment 'i' so we don't get the argument as the next argv[i]. if (options.timeLimitSeconds <= 0) { cout << "--time option error: time limit must be of the format 1h20m30s, 10m20s, 1h, etc." << endl; From 1540be0adab302b76093ebfc791cc0861314ecdd Mon Sep 17 00:00:00 2001 From: lobis Date: Fri, 29 Jul 2022 16:19:16 +0200 Subject: [PATCH 117/173] Fixed bug when calling with single parameter --- src/Application.cxx | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/Application.cxx b/src/Application.cxx index 39c50118..9f9fd557 100644 --- a/src/Application.cxx +++ b/src/Application.cxx @@ -138,7 +138,7 @@ Options ProcessCommandLineOptions(int argc, char* const argv[]) { options.argc = argc; options.argv = const_cast(argv); - if (argc <= 2) { + if (argc < 2) { // Invoked without parameter ShowUsage(); exit(0); @@ -245,6 +245,11 @@ Options ProcessCommandLineOptions(int argc, char* const argv[]) { } } + if (options.rmlFile.empty()) { + cerr << "Input RML file not specified" << endl; + exit(1); + } + return options; } @@ -271,8 +276,8 @@ void Application::Run(const CommandLineOptions::Options& options) { const char* inputConfigFile = options.rmlFile.c_str(); if (!TRestTools::CheckFileIsAccessible(inputConfigFile)) { - cout << "ERROR: Input rml file " << filesystem::weakly_canonical(inputConfigFile) - << " not found, please check file name." << endl; + cerr << "Input RML file " << filesystem::weakly_canonical(inputConfigFile) + << " not found, please check file name!" << endl; exit(1); } From d3494b93b760cf490365a175b9a769bde1edf7dc Mon Sep 17 00:00:00 2001 From: lobis Date: Fri, 29 Jul 2022 16:21:11 +0200 Subject: [PATCH 118/173] Updated some error messages --- src/Application.cxx | 2 +- src/DetectorConstruction.cxx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Application.cxx b/src/Application.cxx index 9f9fd557..cd1bc5d1 100644 --- a/src/Application.cxx +++ b/src/Application.cxx @@ -411,7 +411,7 @@ void Application::Run(const CommandLineOptions::Options& options) { const auto nEvents = metadata->GetNumberOfEvents(); if (nEvents < 0) { - cout << "Error: \"nEvents\" parameter value (" << nEvents << ") is not valid." << endl; + cerr << "'nEvents' parameter value (" << nEvents << ") is not valid" << endl; exit(1); } diff --git a/src/DetectorConstruction.cxx b/src/DetectorConstruction.cxx index 6f26bb4f..6bc668fc 100644 --- a/src/DetectorConstruction.cxx +++ b/src/DetectorConstruction.cxx @@ -244,7 +244,7 @@ void DetectorConstruction::ConstructSDandField() { auto logicalVolumes = metadata.GetGeant4GeometryInfo().GetAllLogicalVolumesMatchingExpression(userSensitiveVolume); if (logicalVolumes.empty()) { - cout << "Error on sensitive detector setup for sensitive volume: " << userSensitiveVolume + cerr << "Error on sensitive detector setup for sensitive volume: " << userSensitiveVolume << endl; exit(1); } else { From b0b4a8e9a439ab8bde01b9e848d06cdb1bf42c9f Mon Sep 17 00:00:00 2001 From: lobis Date: Fri, 29 Jul 2022 16:32:42 +0200 Subject: [PATCH 119/173] Starting to support multiple sensitive volumes --- src/DetectorConstruction.cxx | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/DetectorConstruction.cxx b/src/DetectorConstruction.cxx index 6bc668fc..cbfb410a 100644 --- a/src/DetectorConstruction.cxx +++ b/src/DetectorConstruction.cxx @@ -59,16 +59,13 @@ G4VPhysicalVolume* DetectorConstruction::Construct() { filesystem::current_path(startingPath); - // TODO: Take the name of the sensitive volume and use it here to define its - // StepSize auto sensitiveVolume = (string)restG4Metadata->GetSensitiveVolume(); - G4VPhysicalVolume* physicalVolume = GetPhysicalVolume(sensitiveVolume); if (!physicalVolume) { // sensitive volume was not found, perhaps the user specified a logical volume auto physicalVolumes = geometryInfo.GetAllPhysicalVolumesFromLogical(sensitiveVolume); if (physicalVolumes.size() == 1) { - restG4Metadata->SetSensitiveVolume( + restG4Metadata->InsertSensitiveVolume( geometryInfo.GetAlternativeNameFromGeant4PhysicalName(physicalVolumes[0])); sensitiveVolume = (string)restG4Metadata->GetSensitiveVolume(); physicalVolume = GetPhysicalVolume(sensitiveVolume); From eefbc20360e514b6b31b88a9125ef5b41892371e Mon Sep 17 00:00:00 2001 From: lobis Date: Fri, 29 Jul 2022 16:36:01 +0200 Subject: [PATCH 120/173] Updated print for DetectorConstruction --- src/DetectorConstruction.cxx | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/src/DetectorConstruction.cxx b/src/DetectorConstruction.cxx index cbfb410a..4d991e46 100644 --- a/src/DetectorConstruction.cxx +++ b/src/DetectorConstruction.cxx @@ -87,19 +87,15 @@ G4VPhysicalVolume* DetectorConstruction::Construct() { fieldMgr->SetDetectorField(magField); fieldMgr->CreateChordFinder(magField); - if (physicalVolume) { + if (physicalVolume != nullptr) { G4LogicalVolume* volume = physicalVolume->GetLogicalVolume(); - // This method seems not available in my Geant4 version 10.4.2 - // In future Geant4 versions it seems possible to define field at particular volumes - // volume->setFieldManager(localFieldMgr, true); G4Material* material = volume->GetMaterial(); - G4cout << "Sensitivity volume properties" << G4endl; - G4cout << "==============" << G4endl; - G4cout << "Sensitivity volume name: " << material->GetName() << G4endl; - G4cout << "Sensitivity volume temperature: " << material->GetTemperature() << " K" << G4endl; - G4cout << "Sensitivity volume density: " << material->GetDensity() / (g / cm3) << " g/cm3" << G4endl; + G4cout << "Sensitive volume properties:" << G4endl; + G4cout << "\t- Material: " << material->GetName() << G4endl; + G4cout << "\t- Temperature: " << material->GetTemperature() << " K" << G4endl; + G4cout << "\t- Density: " << material->GetDensity() / (g / cm3) << " g/cm3" << G4endl; } else { - cout << "ERROR: Logical volume for sensitive \"" << sensitiveVolume << "\" not found!" << endl; + cerr << "Physical volume for sensitive volume '" << sensitiveVolume << "' not found!" << endl; } const auto& primaryGeneratorInfo = restG4Metadata->GetGeant4PrimaryGeneratorInfo(); From ffb6b6fda1da927f05076b04b17e2b07a405295c Mon Sep 17 00:00:00 2001 From: lobis Date: Fri, 29 Jul 2022 19:01:30 +0200 Subject: [PATCH 121/173] Updated storage section tu support multiple sensitive volumes (work in progress) --- examples/01.NLDBD/NLDBD.rml | 24 ++++++++++--------- examples/01.NLDBD/Validate.C | 3 ++- examples/02.TREXDM/FullChainFromReadout.rml | 8 +++---- examples/03.Fluorescence/electron.rml | 7 +++--- examples/03.Fluorescence/gamma.rml | 7 +++--- .../04.MuonScan/CosmicMuonsFromCircle.rml | 9 +++---- examples/04.MuonScan/CosmicMuonsFromWall.rml | 9 +++---- examples/04.MuonScan/Muon.rml | 8 +++---- examples/05.PandaXIII/Xe136bb0n.rml | 6 ++--- examples/06.IonRecoils/recoils.rml | 7 +++--- examples/07.FullChainDecay/fullChain.rml | 7 +++--- examples/07.FullChainDecay/singleDecay.rml | 7 +++--- examples/08.Alphas/alphas.rml | 7 +++--- examples/09.Pb210_Shield/Pb210.rml | 7 +++--- examples/10.Geometries/Assembly.rml | 6 ++--- examples/11.Xrays/xrays.rml | 7 +++--- .../12.Generators/CosineSquaredCircle.rml | 8 ++++--- src/Application.cxx | 2 -- src/DetectorConstruction.cxx | 6 +++-- 19 files changed, 80 insertions(+), 65 deletions(-) diff --git a/examples/01.NLDBD/NLDBD.rml b/examples/01.NLDBD/NLDBD.rml index e0fb251e..0a75be16 100644 --- a/examples/01.NLDBD/NLDBD.rml +++ b/examples/01.NLDBD/NLDBD.rml @@ -67,10 +67,12 @@ By default REST units are mm, keV and degrees - + - - + + + + @@ -86,24 +88,24 @@ By default REST units are mm, keV and degrees // Use only one EM physics list - + - - + + - - - - - + + + + + diff --git a/examples/01.NLDBD/Validate.C b/examples/01.NLDBD/Validate.C index a2f96c4c..ec5c0d50 100644 --- a/examples/01.NLDBD/Validate.C +++ b/examples/01.NLDBD/Validate.C @@ -47,7 +47,8 @@ Int_t Validate(const char* filename) { const bool isReferenceGeant4Version = geant4Metadata->GetGeant4Version() == "10.4.3"; if (geant4Metadata->GetNumberOfActiveVolumes() != 1) { - cout << "The number of registered does not match the reference value of 1" << endl; + cout << "The number of active volumes does not match the reference value of 1. Value: " + << geant4Metadata->GetNumberOfActiveVolumes() << endl; return 7; } diff --git a/examples/02.TREXDM/FullChainFromReadout.rml b/examples/02.TREXDM/FullChainFromReadout.rml index 69e1eaa5..b46d0b05 100644 --- a/examples/02.TREXDM/FullChainFromReadout.rml +++ b/examples/02.TREXDM/FullChainFromReadout.rml @@ -46,11 +46,11 @@ - - + - - + + + diff --git a/examples/03.Fluorescence/electron.rml b/examples/03.Fluorescence/electron.rml index d3e31f20..9aab09d7 100644 --- a/examples/03.Fluorescence/electron.rml +++ b/examples/03.Fluorescence/electron.rml @@ -47,10 +47,11 @@ By default REST units are mm, keV and degrees - + - - + + + diff --git a/examples/03.Fluorescence/gamma.rml b/examples/03.Fluorescence/gamma.rml index eb20b1fd..71b8a741 100644 --- a/examples/03.Fluorescence/gamma.rml +++ b/examples/03.Fluorescence/gamma.rml @@ -46,10 +46,11 @@ By default REST units are mm, keV and degrees - + - - + + + diff --git a/examples/04.MuonScan/CosmicMuonsFromCircle.rml b/examples/04.MuonScan/CosmicMuonsFromCircle.rml index ce81985c..b17919bf 100644 --- a/examples/04.MuonScan/CosmicMuonsFromCircle.rml +++ b/examples/04.MuonScan/CosmicMuonsFromCircle.rml @@ -34,11 +34,12 @@ - + - - - + + + + diff --git a/examples/04.MuonScan/CosmicMuonsFromWall.rml b/examples/04.MuonScan/CosmicMuonsFromWall.rml index 6cee5dae..7e14e6dd 100644 --- a/examples/04.MuonScan/CosmicMuonsFromWall.rml +++ b/examples/04.MuonScan/CosmicMuonsFromWall.rml @@ -34,11 +34,12 @@ First concept author G. Luzón (16-11-2020) --> - + - - - + + + + diff --git a/examples/04.MuonScan/Muon.rml b/examples/04.MuonScan/Muon.rml index c0f3b38f..bc475503 100644 --- a/examples/04.MuonScan/Muon.rml +++ b/examples/04.MuonScan/Muon.rml @@ -29,11 +29,11 @@ - + - - - + + + diff --git a/examples/05.PandaXIII/Xe136bb0n.rml b/examples/05.PandaXIII/Xe136bb0n.rml index 72d8b2ed..66ea0a63 100644 --- a/examples/05.PandaXIII/Xe136bb0n.rml +++ b/examples/05.PandaXIII/Xe136bb0n.rml @@ -34,10 +34,10 @@ - + - - + + diff --git a/examples/06.IonRecoils/recoils.rml b/examples/06.IonRecoils/recoils.rml index 31694359..53497c02 100644 --- a/examples/06.IonRecoils/recoils.rml +++ b/examples/06.IonRecoils/recoils.rml @@ -48,10 +48,11 @@ By default REST units are mm, keV and degrees - + - - + + + diff --git a/examples/07.FullChainDecay/fullChain.rml b/examples/07.FullChainDecay/fullChain.rml index 6dd82222..545232ad 100644 --- a/examples/07.FullChainDecay/fullChain.rml +++ b/examples/07.FullChainDecay/fullChain.rml @@ -48,10 +48,11 @@ By default REST units are mm, keV and degrees - + - - + + + diff --git a/examples/07.FullChainDecay/singleDecay.rml b/examples/07.FullChainDecay/singleDecay.rml index c4d9d834..b6eb1f9d 100644 --- a/examples/07.FullChainDecay/singleDecay.rml +++ b/examples/07.FullChainDecay/singleDecay.rml @@ -48,10 +48,11 @@ By default REST units are mm, keV and degrees - + - - + + + diff --git a/examples/08.Alphas/alphas.rml b/examples/08.Alphas/alphas.rml index f7816d38..8debd92a 100644 --- a/examples/08.Alphas/alphas.rml +++ b/examples/08.Alphas/alphas.rml @@ -47,10 +47,11 @@ By default REST units are mm, keV and degrees - + - - + + + diff --git a/examples/09.Pb210_Shield/Pb210.rml b/examples/09.Pb210_Shield/Pb210.rml index 00605be5..d77e45d5 100644 --- a/examples/09.Pb210_Shield/Pb210.rml +++ b/examples/09.Pb210_Shield/Pb210.rml @@ -47,10 +47,11 @@ By default REST units are mm, keV and degrees - + - - + + + diff --git a/examples/10.Geometries/Assembly.rml b/examples/10.Geometries/Assembly.rml index db6c46c3..5c0d2eb7 100644 --- a/examples/10.Geometries/Assembly.rml +++ b/examples/10.Geometries/Assembly.rml @@ -46,10 +46,10 @@ By default REST units are mm, keV and degrees - + - - + + diff --git a/examples/11.Xrays/xrays.rml b/examples/11.Xrays/xrays.rml index 8648a501..040baae3 100644 --- a/examples/11.Xrays/xrays.rml +++ b/examples/11.Xrays/xrays.rml @@ -46,10 +46,11 @@ By default REST units are mm, keV and degrees - + - - + + + diff --git a/examples/12.Generators/CosineSquaredCircle.rml b/examples/12.Generators/CosineSquaredCircle.rml index df825da4..b9f3ea9f 100644 --- a/examples/12.Generators/CosineSquaredCircle.rml +++ b/examples/12.Generators/CosineSquaredCircle.rml @@ -35,10 +35,12 @@ - + + - - + + + diff --git a/src/Application.cxx b/src/Application.cxx index cd1bc5d1..97a8653c 100644 --- a/src/Application.cxx +++ b/src/Application.cxx @@ -330,8 +330,6 @@ void Application::Run(const CommandLineOptions::Options& options) { metadata->SetGdmlReference(gdml->GetGDMLVersion()); metadata->SetMaterialsReference(gdml->GetEntityVersion("materials")); - metadata->PrintMetadata(); - auto physicsLists = new TRestGeant4PhysicsLists(inputRmlClean.c_str()); fSimulationManager.SetRestPhysicsLists(physicsLists); diff --git a/src/DetectorConstruction.cxx b/src/DetectorConstruction.cxx index 4d991e46..9ec0c8fa 100644 --- a/src/DetectorConstruction.cxx +++ b/src/DetectorConstruction.cxx @@ -53,6 +53,8 @@ G4VPhysicalVolume* DetectorConstruction::Construct() { G4VPhysicalVolume* worldVolume = fGdmlParser->GetWorldVolume(); restG4Metadata->fGeant4GeometryInfo.InitializeOnDetectorConstruction(gdmlToRead, worldVolume); + restG4Metadata->ReadDetector(); + restG4Metadata->PrintMetadata(); // now we have detector info const auto& geometryInfo = restG4Metadata->GetGeant4GeometryInfo(); geometryInfo.Print(); @@ -269,8 +271,8 @@ void TRestGeant4GeometryInfo::PopulateFromGeant4World(const G4VPhysicalVolume* w auto detector = (DetectorConstruction*)G4RunManager::GetRunManager()->GetUserDetectorConstruction(); TRestGeant4Metadata* restG4Metadata = detector->fSimulationManager->GetRestMetadata(); - const int n = int(world->GetLogicalVolume()->GetNoDaughters()); - for (int i = 0; i < n + 1; i++) { // world is the + 1 + const size_t n = int(world->GetLogicalVolume()->GetNoDaughters()); + for (size_t i = 0; i < n + 1; i++) { // world is the + 1 G4VPhysicalVolume* volume; if (i == n) { volume = const_cast(world); From a2cfc3bef27fee4021a2a42f929370b655588325 Mon Sep 17 00:00:00 2001 From: lobis Date: Fri, 29 Jul 2022 20:14:27 +0200 Subject: [PATCH 122/173] Fixed bug with strings in active volume check --- examples/04.MuonScan/Validate.C | 2 +- include/SimulationManager.h | 3 --- src/SimulationManager.cxx | 10 +--------- 3 files changed, 2 insertions(+), 13 deletions(-) diff --git a/examples/04.MuonScan/Validate.C b/examples/04.MuonScan/Validate.C index 039e3021..a2e38568 100644 --- a/examples/04.MuonScan/Validate.C +++ b/examples/04.MuonScan/Validate.C @@ -45,7 +45,7 @@ Int_t Validate(const char* filename) { geant4Metadata->PrintMetadata(); if (geant4Metadata->GetNumberOfActiveVolumes() != 2) { - cout << "The number of registered does not match the reference value of 2" << endl; + cout << "The number of active volumes does not match the reference value of 2" << endl; return 7; } diff --git a/include/SimulationManager.h b/include/SimulationManager.h index 52a901a0..82a47ae4 100644 --- a/include/SimulationManager.h +++ b/include/SimulationManager.h @@ -99,8 +99,6 @@ class OutputManager { void AddSensitiveEnergy(Double_t energy, const char* physicalVolumeName); void AddEnergyToVolumeForProcess(Double_t energy, const char* volumeName, const char* processName); - inline bool IsActiveVolume(const char* volumeName) const { return fActiveVolumes.count(volumeName) > 0; } - inline int GetEventCounter() const { return fProcessedEventsCounter; } inline void ResetEventCounter() { fProcessedEventsCounter = 0; } @@ -109,7 +107,6 @@ class OutputManager { private: std::unique_ptr fEvent{}; SimulationManager* fSimulationManager = nullptr; - std::set fActiveVolumes = {}; int fProcessedEventsCounter = 0; diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index fbfd0b94..6375de39 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -156,13 +156,6 @@ OutputManager::OutputManager(const SimulationManager* simulationManager) G4cout << "Error in 'OutputManager', this instance should never exist" << endl; exit(1); } - - // initialize active volume lookup set - const auto metadata = fSimulationManager->GetRestMetadata(); - for (size_t i = 0; i < metadata->GetNumberOfActiveVolumes(); i++) { - const TString& activeVolume = metadata->GetActiveVolumeName(i); - fActiveVolumes.insert(activeVolume.Data()); - } } void OutputManager::BeginOfEventAction() { @@ -416,8 +409,7 @@ void TRestGeant4Hits::InsertStep(const G4Step* step) { const auto& volumeNameGeant4 = step->GetPreStepPoint()->GetPhysicalVolume()->GetName(); const auto& volumeName = geometryInfo.GetAlternativeNameFromGeant4PhysicalName(volumeNameGeant4); - if (!SimulationManager::GetOutputManager()->IsActiveVolume(volumeName) && - step->GetTrack()->GetCurrentStepNumber() != 0) { + if (!metadata->IsActiveVolume(volumeName) && step->GetTrack()->GetCurrentStepNumber() != 0) { // we always store the first step return; } From a642e3e7f265ea1653f31c8e50d8d43524f45108 Mon Sep 17 00:00:00 2001 From: lobis Date: Fri, 29 Jul 2022 23:01:40 +0200 Subject: [PATCH 123/173] Added method to reduce number of tracks not needed for analysis --- include/SimulationManager.h | 2 ++ src/SimulationManager.cxx | 48 +++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/include/SimulationManager.h b/include/SimulationManager.h index 82a47ae4..8df42b94 100644 --- a/include/SimulationManager.h +++ b/include/SimulationManager.h @@ -110,6 +110,8 @@ class OutputManager { int fProcessedEventsCounter = 0; + void RemoveUnwantedTracks(); + friend class StackingAction; }; diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index 6375de39..d3ed138d 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -206,6 +206,9 @@ bool OutputManager::IsValidEvent() const { void OutputManager::FinishAndSubmitEvent() { if (IsValidEvent()) { + if (fSimulationManager->GetRestMetadata()->GetRemoveUnwantedTracks()) { + RemoveUnwantedTracks(); + } fSimulationManager->InsertEvent(fEvent); fSimulationManager->WriteEvents(); } @@ -458,3 +461,48 @@ void TRestGeant4Hits::InsertStep(const G4Step* step) { SimulationManager::GetOutputManager()->AddEnergyToVolumeForProcess(energy, volumeName, processName); } + +void OutputManager::RemoveUnwantedTracks() { + const auto& metadata = fSimulationManager->GetRestMetadata(); + set trackIDsToKeep; // We populate this container with the tracks we want to keep + for (const auto& track : fEvent->fTracks) { + // If one children track is kept, we keep all the parents + if (trackIDsToKeep.count(track.GetTrackID() > 0)) { + continue; + } + const auto hits = track.GetHits(); + for (int i = 0; i < hits.GetNumberOfHits(); i++) { + const auto energy = hits.GetEnergy(i); + if (energy <= 0) { + continue; + } + const auto volumeID = hits.GetVolumeId(i); + const auto volume = metadata->GetGeant4GeometryInfo().GetVolumeFromID(volumeID); + if (metadata->IsKeepTracksVolume(volume)) { + trackIDsToKeep.insert(track.GetTrackID()); + auto parentTrack = track.GetParentTrack(); + while (parentTrack != nullptr) { + trackIDsToKeep.insert(parentTrack->GetTrackID()); + parentTrack = parentTrack->GetParentTrack(); + } + } + } + } + const size_t numberOfTracksBefore = fEvent->fTracks.size(); + + vector tracksAfterRemoval; + for (const auto& track : fEvent->fTracks) { + // we do this to preserve original order + if (trackIDsToKeep.count(track.GetTrackID()) > 0) { + tracksAfterRemoval.push_back(*(fEvent->GetTrackByID(track.GetTrackID()))); + } + } + + fEvent->fTracks = tracksAfterRemoval; + const size_t numberOfTracksAfter = fEvent->fTracks.size(); + + /* + cout << "EventID: " << fEvent->GetID() << " Removed " << numberOfTracksBefore - numberOfTracksAfter + << " tracks out of " << numberOfTracksBefore << endl; + */ +} \ No newline at end of file From c9bbb01163c904bb879f512e5218693cd45e548d Mon Sep 17 00:00:00 2001 From: lobis Date: Fri, 29 Jul 2022 23:09:26 +0200 Subject: [PATCH 124/173] Fixed multiple sensitive detectors not working --- src/DetectorConstruction.cxx | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/src/DetectorConstruction.cxx b/src/DetectorConstruction.cxx index 9ec0c8fa..f43b467f 100644 --- a/src/DetectorConstruction.cxx +++ b/src/DetectorConstruction.cxx @@ -207,31 +207,22 @@ G4VPhysicalVolume* DetectorConstruction::GetPhysicalVolume(const G4String& physV void DetectorConstruction::ConstructSDandField() { const TRestGeant4Metadata& metadata = *fSimulationManager->GetRestMetadata(); - vector - sensitiveVolumes; // user submitted sensitive volumes, may not exist or not be physical (be logical) - for (const auto& volume : {metadata.GetSensitiveVolume()}) { - sensitiveVolumes.emplace_back(volume); - } - - if (sensitiveVolumes.empty()) { - return; - } set logicalVolumesSelected; - for (const auto& userSensitiveVolume : sensitiveVolumes) { + for (const auto& userSensitiveVolume : metadata.GetSensitiveVolumes()) { G4LogicalVolume* logicalVolume = nullptr; G4VPhysicalVolume* physicalVolume = - G4PhysicalVolumeStore::GetInstance()->GetVolume(userSensitiveVolume, false); + G4PhysicalVolumeStore::GetInstance()->GetVolume(userSensitiveVolume.Data(), false); if (physicalVolume == nullptr) { const G4String geant4VolumeName = metadata.GetGeant4GeometryInfo() - .GetGeant4PhysicalNameFromAlternativeName(userSensitiveVolume.c_str()) + .GetGeant4PhysicalNameFromAlternativeName(userSensitiveVolume.Data()) .Data(); physicalVolume = G4PhysicalVolumeStore::GetInstance()->GetVolume(geant4VolumeName, false); } if (physicalVolume == nullptr) { // perhaps user selected a logical volume with this name - logicalVolume = G4LogicalVolumeStore::GetInstance()->GetVolume(userSensitiveVolume, false); + logicalVolume = G4LogicalVolumeStore::GetInstance()->GetVolume(userSensitiveVolume.Data(), false); } else { logicalVolume = physicalVolume->GetLogicalVolume(); } From a9203571fe9dba3adb2ef91e137599803cd9407e Mon Sep 17 00:00:00 2001 From: Luis Obis Date: Sat, 30 Jul 2022 15:34:15 +0200 Subject: [PATCH 125/173] Fixed bad print when exiting simulation early --- src/Application.cxx | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/Application.cxx b/src/Application.cxx index 97a8653c..cc9fa106 100644 --- a/src/Application.cxx +++ b/src/Application.cxx @@ -463,10 +463,13 @@ void Application::Run(const CommandLineOptions::Options& options) { metadata->PrintMetadata(); run->PrintMetadata(); - cout << "\t- Total simulation time is " << fSimulationManager.GetElapsedTime() << " seconds, " << nEvents - << " processed events (" << nEvents / fSimulationManager.GetElapsedTime() << " per second) and " - << nEntries << " events saved to output file (" << nEntries / fSimulationManager.GetElapsedTime() - << " per second)" << endl; + const auto nEventsAtEnd = + metadata->GetNumberOfEvents(); // This could be different from original if exit early + + cout << "\t- Total simulation time is " << fSimulationManager.GetElapsedTime() << " seconds, " + << nEventsAtEnd << " processed events (" << nEventsAtEnd / fSimulationManager.GetElapsedTime() + << " per second) and " << nEntries << " events saved to output file (" + << nEntries / fSimulationManager.GetElapsedTime() << " per second)" << endl; cout << "\t- Output file: " << filename << endl << endl; } From 15d423d14cc522beb15f8d1ca3afe95836afd2ec Mon Sep 17 00:00:00 2001 From: Luis Obis Date: Sat, 30 Jul 2022 15:34:41 +0200 Subject: [PATCH 126/173] Fixed random seed to avoid occasional pipeline failure --- examples/04.MuonScan/CosmicMuonsFromWall.rml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/04.MuonScan/CosmicMuonsFromWall.rml b/examples/04.MuonScan/CosmicMuonsFromWall.rml index 7e14e6dd..dd178577 100644 --- a/examples/04.MuonScan/CosmicMuonsFromWall.rml +++ b/examples/04.MuonScan/CosmicMuonsFromWall.rml @@ -22,6 +22,7 @@ First concept author G. Luzón (16-11-2020) --> + @@ -39,7 +40,7 @@ First concept author G. Luzón (16-11-2020) --> - + From 40b4e1a23df7ba09442d574822f718ce12501395 Mon Sep 17 00:00:00 2001 From: Luis Obis Date: Sat, 30 Jul 2022 15:45:26 +0200 Subject: [PATCH 127/173] Handled more errors for `restG4` CLI --- src/Application.cxx | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/Application.cxx b/src/Application.cxx index cc9fa106..b6238cfc 100644 --- a/src/Application.cxx +++ b/src/Application.cxx @@ -241,6 +241,19 @@ Options ProcessCommandLineOptions(int argc, char* const argv[]) { exit(1); } } else { + const string argument = argv[i]; + if (argument[0] == '-') { + cerr << "Bad CLI option '" << argument << "'" << endl << endl; + ShowUsage(); + exit(1); + } + if (!options.rmlFile.empty()) { + // more than one rml specified + cerr << "Attempting to set configuration RML file to '" << argument + << "' but it is already defined as '" << options.rmlFile + << "'. It can only be specified once" << endl; + exit(1); + } options.rmlFile = argv[i]; // invoked as restG4 , restG4 -j 4 , etc. } } From 2336afc1d6d3298fa03b3b8b2046c2318f8a26a8 Mon Sep 17 00:00:00 2001 From: lobis Date: Sat, 30 Jul 2022 21:01:16 +0200 Subject: [PATCH 128/173] Added extra option for RemoveUnwantedTracks, fixed possible issue in activating default volumes --- src/DetectorConstruction.cxx | 17 +++++++---------- src/SimulationManager.cxx | 3 ++- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/DetectorConstruction.cxx b/src/DetectorConstruction.cxx index f43b467f..89aec4cf 100644 --- a/src/DetectorConstruction.cxx +++ b/src/DetectorConstruction.cxx @@ -98,6 +98,7 @@ G4VPhysicalVolume* DetectorConstruction::Construct() { G4cout << "\t- Density: " << material->GetDensity() / (g / cm3) << " g/cm3" << G4endl; } else { cerr << "Physical volume for sensitive volume '" << sensitiveVolume << "' not found!" << endl; + exit(1); } const auto& primaryGeneratorInfo = restG4Metadata->GetGeant4PrimaryGeneratorInfo(); @@ -167,20 +168,16 @@ G4VPhysicalVolume* DetectorConstruction::Construct() { for (int id = 0; id < restG4Metadata->GetNumberOfActiveVolumes(); id++) { TString activeVolumeName = restG4Metadata->GetActiveVolumeName(id); G4VPhysicalVolume* pVol = GetPhysicalVolume((G4String)activeVolumeName); - if (pVol) { + if (pVol != nullptr) { G4LogicalVolume* lVol = pVol->GetLogicalVolume(); if (restG4Metadata->GetMaxStepSize(activeVolumeName) > 0) { - G4cout << "Setting maxStepSize = " << restG4Metadata->GetMaxStepSize(activeVolumeName) - << "mm for volume: " << activeVolumeName << G4endl; + RESTInfo << "Setting maxStepSize of " << restG4Metadata->GetMaxStepSize(activeVolumeName) * mm + << "mm for volume '" << activeVolumeName << "'" << RESTendl; lVol->SetUserLimits(new G4UserLimits(restG4Metadata->GetMaxStepSize(activeVolumeName) * mm)); } - } - - cout << "Activating volume: " << activeVolumeName << endl; - // restG4Event->AddActiveVolume((string)activeVolumeName); - if (!pVol) { - cout << "DetectorConstruction. Volume " << activeVolumeName << " is not defined in the geometry" - << endl; + } else { + cerr << "DetectorConstruction::Construct - Volume '" << activeVolumeName + << "' is not defined in the geometry" << endl; exit(1); } } diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index d3ed138d..491b051e 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -473,7 +473,8 @@ void OutputManager::RemoveUnwantedTracks() { const auto hits = track.GetHits(); for (int i = 0; i < hits.GetNumberOfHits(); i++) { const auto energy = hits.GetEnergy(i); - if (energy <= 0) { + if (!fSimulationManager->GetRestMetadata()->GetRemoveUnwantedTracksKeepZeroEnergyTracks() && + energy <= 0) { continue; } const auto volumeID = hits.GetVolumeId(i); From bb0c2c8891c0b8a1b9569f7db9509e56f0351ab9 Mon Sep 17 00:00:00 2001 From: lobis Date: Sat, 30 Jul 2022 22:44:14 +0200 Subject: [PATCH 129/173] Fixed bug with default energy range --- src/SimulationManager.cxx | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index 491b051e..b33969d9 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -192,13 +192,12 @@ bool OutputManager::IsValidEvent() const { if (fSimulationManager->GetRestMetadata()->GetSaveAllEvents()) { return true; } - if (fEvent->GetSensitiveVolumeEnergy() <= 0) { + const auto energy = fEvent->GetSensitiveVolumeEnergy(); + if (energy <= 0) { return false; } - if (fEvent->GetSensitiveVolumeEnergy() < - fSimulationManager->GetRestMetadata()->GetMinimumEnergyStored() || - fEvent->GetSensitiveVolumeEnergy() > - fSimulationManager->GetRestMetadata()->GetMaximumEnergyStored()) { + if (energy < fSimulationManager->GetRestMetadata()->GetMinimumEnergyStored() || + energy > fSimulationManager->GetRestMetadata()->GetMaximumEnergyStored()) { return false; } return true; From 98aa33917a521c4263ce82684296e5d0bd58a4dc Mon Sep 17 00:00:00 2001 From: lobis Date: Sun, 31 Jul 2022 02:37:33 +0200 Subject: [PATCH 130/173] Allow to pass `-t 0` to signal serial mode (previously it was an error) --- src/Application.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Application.cxx b/src/Application.cxx index b6238cfc..a21a8597 100644 --- a/src/Application.cxx +++ b/src/Application.cxx @@ -183,8 +183,8 @@ Options ProcessCommandLineOptions(int argc, char* const argv[]) { if (i + 1 < argc) { // Make sure we aren't at the end of argv! options.nThreads = stoi(argv[++i]); // Increment 'i' so we don't get the argument as the next argv[i]. - if (options.nThreads < 1) { - cout << "--threads option error: number of threads must be > 0" << endl; + if (options.nThreads < 0) { + cout << "--threads option error: number of threads must be >= 0" << endl; exit(1); } } else { From 0dcbe5a7858dd0c3644bc675ab4d7a81ce5848c5 Mon Sep 17 00:00:00 2001 From: lobis Date: Sun, 31 Jul 2022 03:42:48 +0200 Subject: [PATCH 131/173] Working on periodic print thread --- include/SimulationManager.h | 11 +++++++++-- src/RunAction.cxx | 2 +- src/SimulationManager.cxx | 32 ++++++++++++++++++++++++++++---- 3 files changed, 38 insertions(+), 7 deletions(-) diff --git a/include/SimulationManager.h b/include/SimulationManager.h index 8df42b94..39379f0b 100644 --- a/include/SimulationManager.h +++ b/include/SimulationManager.h @@ -9,6 +9,7 @@ #include #include +#include class OutputManager; @@ -27,6 +28,8 @@ class SimulationManager { void WriteEvents(); void WriteEventsAndCloseFile(); + std::thread* fPeriodicPrintThread; + public: inline TRestRun* GetRestRun() const { return fRestRun; } inline TRestGeant4Metadata* GetRestMetadata() const { return fRestGeant4Metadata; } @@ -38,7 +41,9 @@ class SimulationManager { fRestGeant4PhysicsLists = physicsLists; } - void EndOfRun(); + void BeginOfRunAction(); + void EndOfRunAction(); + inline bool GetAbortFlag() const { return fAbortFlag; } void StopSimulation(); @@ -46,11 +51,13 @@ class SimulationManager { return 1E-9 * (std::chrono::steady_clock::now().time_since_epoch().count() - fTimeStartUnix); } - void SyncStatsFromChild(); + void SyncStatsFromChild(OutputManager*); int GetNumberOfProcessedEvents() const { return fNumberOfProcessedEvents; } int GetNumberOfStoredEvents() const { return fNumberOfStoredEvents; } + std::vector GetOutputManagerContainer() const { return fOutputManagerContainer; } + private: static thread_local OutputManager* fOutputManager; std::mutex fSimulationManagerMutex; diff --git a/src/RunAction.cxx b/src/RunAction.cxx index 358e5c2e..6b5697e4 100644 --- a/src/RunAction.cxx +++ b/src/RunAction.cxx @@ -38,7 +38,7 @@ void RunAction::BeginOfRunAction(const G4Run*) { } void RunAction::EndOfRunAction(const G4Run*) { - fSimulationManager->EndOfRun(); + fSimulationManager->EndOfRunAction(); TRestRun* restRun = fSimulationManager->GetRestRun(); const auto metadata = fSimulationManager->GetRestMetadata(); diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index b33969d9..2ef3a4d2 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -30,7 +30,31 @@ void SimulationManager::InitializeOutputManager() { fOutputManagerContainer.push_back(fOutputManager); } -void SimulationManager::EndOfRun() { +void PeriodicPrint(SimulationManager* simulationManager) { + const auto restG4Metadata = simulationManager->GetRestMetadata(); + + for (auto& outputManager : simulationManager->GetOutputManagerContainer()) { + simulationManager->SyncStatsFromChild(outputManager); + } + + G4cout << double(simulationManager->GetNumberOfProcessedEvents()) / + double(restG4Metadata->GetNumberOfEvents()) * 100 + << "% - " << simulationManager->GetNumberOfProcessedEvents() << " Events processed out of " + << restG4Metadata->GetNumberOfEvents() << " requested events (" + << simulationManager->GetNumberOfProcessedEvents() / simulationManager->GetElapsedTime() + << " per second). " << simulationManager->GetNumberOfStoredEvents() << " events stored (" + << simulationManager->GetNumberOfStoredEvents() / simulationManager->GetElapsedTime() + << " per second). " << simulationManager->GetElapsedTime() << " seconds elapsed" << G4endl; +} + +void SimulationManager::BeginOfRunAction() { + if (GetRestMetadata()->PrintProgress() || + GetRestMetadata()->GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Essential) { + fPeriodicPrintThread = new thread(&PeriodicPrint, this); + } +} + +void SimulationManager::EndOfRunAction() { if ((G4Threading::IsMultithreadedApplication() && G4Threading::G4GetThreadId() != -1)) { return; // Only call this once from the main thread } @@ -141,10 +165,10 @@ void SimulationManager::StopSimulation() { fAbortFlag = true; } -void SimulationManager::SyncStatsFromChild() { +void SimulationManager::SyncStatsFromChild(OutputManager* outputManager = fOutputManager) { lock_guard guard(fSimulationManagerMutex); - fNumberOfProcessedEvents += fOutputManager->GetEventCounter(); - fOutputManager->ResetEventCounter(); + fNumberOfProcessedEvents += outputManager->GetEventCounter(); + outputManager->ResetEventCounter(); fNumberOfStoredEvents = fRestRun->GetEntries(); } From ff69014cf6da49d565bc7431c32cd2e2baa022a5 Mon Sep 17 00:00:00 2001 From: lobis Date: Sun, 31 Jul 2022 06:48:13 +0200 Subject: [PATCH 132/173] Updated print to periodic function --- include/EventAction.h | 1 - include/SimulationManager.h | 7 +++++- src/EventAction.cxx | 27 +--------------------- src/RunAction.cxx | 2 ++ src/SimulationManager.cxx | 46 +++++++++++++++++++++++++------------ 5 files changed, 40 insertions(+), 43 deletions(-) diff --git a/include/EventAction.h b/include/EventAction.h index 177e490c..2b6489a4 100644 --- a/include/EventAction.h +++ b/include/EventAction.h @@ -24,7 +24,6 @@ class EventAction : public G4UserEventAction { private: SimulationManager* fSimulationManager; - TStopwatch fTimer; }; #endif diff --git a/include/SimulationManager.h b/include/SimulationManager.h index 39379f0b..4ff98ecd 100644 --- a/include/SimulationManager.h +++ b/include/SimulationManager.h @@ -29,6 +29,7 @@ class SimulationManager { void WriteEventsAndCloseFile(); std::thread* fPeriodicPrintThread; + bool fPeriodicPrintThreadEndFlag = false; public: inline TRestRun* GetRestRun() const { return fRestRun; } @@ -41,6 +42,8 @@ class SimulationManager { fRestGeant4PhysicsLists = physicsLists; } + bool GetPeriodicPrintThreadEndFlag() const { return fPeriodicPrintThreadEndFlag; } + void BeginOfRunAction(); void EndOfRunAction(); @@ -51,7 +54,7 @@ class SimulationManager { return 1E-9 * (std::chrono::steady_clock::now().time_since_epoch().count() - fTimeStartUnix); } - void SyncStatsFromChild(OutputManager*); + void SyncStatsFromChild(OutputManager* = fOutputManager); int GetNumberOfProcessedEvents() const { return fNumberOfProcessedEvents; } int GetNumberOfStoredEvents() const { return fNumberOfStoredEvents; } @@ -111,6 +114,8 @@ class OutputManager { void BeginOfEventAction(); + int GetCurrentEventID() const { return fEvent->GetID(); } + private: std::unique_ptr fEvent{}; SimulationManager* fSimulationManager = nullptr; diff --git a/src/EventAction.cxx b/src/EventAction.cxx index ae99390f..6766148a 100644 --- a/src/EventAction.cxx +++ b/src/EventAction.cxx @@ -14,9 +14,7 @@ using namespace std; EventAction::EventAction(SimulationManager* simulationManager) - : G4UserEventAction(), fSimulationManager(simulationManager) { - fTimer.Start(); -} + : G4UserEventAction(), fSimulationManager(simulationManager) {} EventAction::~EventAction() {} @@ -31,29 +29,6 @@ void EventAction::BeginOfEventAction(const G4Event* event) { G4cout << "DEBUG: Start of event ID " << eventID << " (" << eventID + 1 << " of " << G4RunManager::GetRunManager()->GetNumberOfEventsToBeProcessed() << "). " << restRun->GetEntries() << " Events stored" << endl; - } else { - const int numberOfEventsToBePercent = - G4RunManager::GetRunManager()->GetNumberOfEventsToBeProcessed() / 100; - if ((restG4Metadata->PrintProgress() || - restG4Metadata->GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Essential) && - // print roughly every 1% of events or whenever 10 seconds without printing have elapsed - ((numberOfEventsToBePercent > 0 && (eventID + 1) % numberOfEventsToBePercent == 0) || - fTimer.RealTime() > 10.0)) { - fTimer.Start(); - - fSimulationManager->SyncStatsFromChild(); - G4cout << double(fSimulationManager->GetNumberOfProcessedEvents()) / - double(restG4Metadata->GetNumberOfEvents()) * 100 - << "% - " << fSimulationManager->GetNumberOfProcessedEvents() - << " Events processed out of " << restG4Metadata->GetNumberOfEvents() - << " requested events (" - << fSimulationManager->GetNumberOfProcessedEvents() / fSimulationManager->GetElapsedTime() - << " per second). " << fSimulationManager->GetNumberOfStoredEvents() << " events stored (" - << fSimulationManager->GetNumberOfStoredEvents() / fSimulationManager->GetElapsedTime() - << " per second). " << fSimulationManager->GetElapsedTime() << " seconds elapsed" << endl; - } else { - fTimer.Continue(); - } } } diff --git a/src/RunAction.cxx b/src/RunAction.cxx index 6b5697e4..48417576 100644 --- a/src/RunAction.cxx +++ b/src/RunAction.cxx @@ -30,6 +30,8 @@ void RunAction::BeginOfRunAction(const G4Run*) { G4cout << "=======================================================================" << endl; } + fSimulationManager->BeginOfRunAction(); + auto steppingVerbose = ((SteppingVerbose*)G4VSteppingVerbose::GetInstance()); steppingVerbose->SetSteppingVerbose(1); diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index 2ef3a4d2..887e02c4 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -9,7 +9,6 @@ #include #include "SteppingAction.h" - using namespace std; thread_local OutputManager* SimulationManager::fOutputManager = nullptr; @@ -30,27 +29,37 @@ void SimulationManager::InitializeOutputManager() { fOutputManagerContainer.push_back(fOutputManager); } -void PeriodicPrint(SimulationManager* simulationManager) { +void PeriodicPrint(SimulationManager* simulationManager, + const G4RunManager* runManager = G4RunManager::GetRunManager()) { const auto restG4Metadata = simulationManager->GetRestMetadata(); + const int numberOfEventsToBePercent = runManager->GetNumberOfEventsToBeProcessed() / 100; - for (auto& outputManager : simulationManager->GetOutputManagerContainer()) { - simulationManager->SyncStatsFromChild(outputManager); - } + while (!simulationManager->GetPeriodicPrintThreadEndFlag()) { + for (auto& outputManager : simulationManager->GetOutputManagerContainer()) { + simulationManager->SyncStatsFromChild(outputManager); + } - G4cout << double(simulationManager->GetNumberOfProcessedEvents()) / - double(restG4Metadata->GetNumberOfEvents()) * 100 - << "% - " << simulationManager->GetNumberOfProcessedEvents() << " Events processed out of " - << restG4Metadata->GetNumberOfEvents() << " requested events (" - << simulationManager->GetNumberOfProcessedEvents() / simulationManager->GetElapsedTime() - << " per second). " << simulationManager->GetNumberOfStoredEvents() << " events stored (" - << simulationManager->GetNumberOfStoredEvents() / simulationManager->GetElapsedTime() - << " per second). " << simulationManager->GetElapsedTime() << " seconds elapsed" << G4endl; + G4cout << double(simulationManager->GetNumberOfProcessedEvents()) / + double(restG4Metadata->GetNumberOfEvents()) * 100 + << "% - " << simulationManager->GetNumberOfProcessedEvents() << " Events processed out of " + << restG4Metadata->GetNumberOfEvents() << " requested events (" + << simulationManager->GetNumberOfProcessedEvents() / simulationManager->GetElapsedTime() + << " per second). " << simulationManager->GetNumberOfStoredEvents() << " events stored (" + << simulationManager->GetNumberOfStoredEvents() / simulationManager->GetElapsedTime() + << " per second). " << simulationManager->GetElapsedTime() << " seconds elapsed" << G4endl; + + std::this_thread::sleep_for(std::chrono::seconds(2)); + } } void SimulationManager::BeginOfRunAction() { + if ((G4Threading::IsMultithreadedApplication() && G4Threading::G4GetThreadId() != -1)) { + return; // Only call this once from the main thread + } + if (GetRestMetadata()->PrintProgress() || GetRestMetadata()->GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Essential) { - fPeriodicPrintThread = new thread(&PeriodicPrint, this); + fPeriodicPrintThread = new thread(&PeriodicPrint, this, G4RunManager::GetRunManager()); } } @@ -59,6 +68,8 @@ void SimulationManager::EndOfRunAction() { return; // Only call this once from the main thread } + fPeriodicPrintThreadEndFlag = true; + WriteEvents(); for (auto& outputManager : fOutputManagerContainer) { @@ -68,6 +79,11 @@ void SimulationManager::EndOfRunAction() { GetRestMetadata()->SetNumberOfEvents(fNumberOfProcessedEvents); fOutputManagerContainer.clear(); + + if (fPeriodicPrintThread != nullptr) { + fPeriodicPrintThread->join(); // need to join thread, it may block for up to 1 second (thread period) + delete fPeriodicPrintThread; + } } SimulationManager::~SimulationManager() { @@ -165,7 +181,7 @@ void SimulationManager::StopSimulation() { fAbortFlag = true; } -void SimulationManager::SyncStatsFromChild(OutputManager* outputManager = fOutputManager) { +void SimulationManager::SyncStatsFromChild(OutputManager* outputManager) { lock_guard guard(fSimulationManagerMutex); fNumberOfProcessedEvents += outputManager->GetEventCounter(); outputManager->ResetEventCounter(); From 38e968a1fa4dbcef6ab87bbba6b140c391c7e7fc Mon Sep 17 00:00:00 2001 From: lobis Date: Sun, 31 Jul 2022 07:31:25 +0200 Subject: [PATCH 133/173] Attempt to fix segfault --- src/EventAction.cxx | 21 +++++++++++++++++++++ src/SimulationManager.cxx | 23 ++++++++++++----------- 2 files changed, 33 insertions(+), 11 deletions(-) diff --git a/src/EventAction.cxx b/src/EventAction.cxx index 6766148a..a8f5b416 100644 --- a/src/EventAction.cxx +++ b/src/EventAction.cxx @@ -30,6 +30,27 @@ void EventAction::BeginOfEventAction(const G4Event* event) { << G4RunManager::GetRunManager()->GetNumberOfEventsToBeProcessed() << "). " << restRun->GetEntries() << " Events stored" << endl; } +#ifdef GEANT4_WITHOUT_G4RunManagerFactory // For old Geant4 where the thread print gives segfault + else { + const int numberOfEventsToBePercent = + G4RunManager::GetRunManager()->GetNumberOfEventsToBeProcessed() / 100; + if ((restG4Metadata->PrintProgress() || + restG4Metadata->GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Essential) && + // print roughly every 1% of events or whenever 10 seconds without printing have elapsed + (numberOfEventsToBePercent > 0 && (eventID + 1) % numberOfEventsToBePercent == 0)) { + fSimulationManager->SyncStatsFromChild(); + G4cout << double(fSimulationManager->GetNumberOfProcessedEvents()) / + double(restG4Metadata->GetNumberOfEvents()) * 100 + << "% - " << fSimulationManager->GetNumberOfProcessedEvents() + << " Events processed out of " << restG4Metadata->GetNumberOfEvents() + << " requested events (" + << fSimulationManager->GetNumberOfProcessedEvents() / fSimulationManager->GetElapsedTime() + << " per second). " << fSimulationManager->GetNumberOfStoredEvents() << " events stored (" + << fSimulationManager->GetNumberOfStoredEvents() / fSimulationManager->GetElapsedTime() + << " per second). " << fSimulationManager->GetElapsedTime() << " seconds elapsed" << endl; + } + } +#endif } void EventAction::EndOfEventAction(const G4Event*) { diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index 887e02c4..2dd8ae87 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -29,12 +29,12 @@ void SimulationManager::InitializeOutputManager() { fOutputManagerContainer.push_back(fOutputManager); } -void PeriodicPrint(SimulationManager* simulationManager, - const G4RunManager* runManager = G4RunManager::GetRunManager()) { +void PeriodicPrint(SimulationManager* simulationManager) { const auto restG4Metadata = simulationManager->GetRestMetadata(); - const int numberOfEventsToBePercent = runManager->GetNumberOfEventsToBeProcessed() / 100; while (!simulationManager->GetPeriodicPrintThreadEndFlag()) { + std::this_thread::sleep_for(std::chrono::seconds(2)); + for (auto& outputManager : simulationManager->GetOutputManagerContainer()) { simulationManager->SyncStatsFromChild(outputManager); } @@ -47,8 +47,6 @@ void PeriodicPrint(SimulationManager* simulationManager, << " per second). " << simulationManager->GetNumberOfStoredEvents() << " events stored (" << simulationManager->GetNumberOfStoredEvents() / simulationManager->GetElapsedTime() << " per second). " << simulationManager->GetElapsedTime() << " seconds elapsed" << G4endl; - - std::this_thread::sleep_for(std::chrono::seconds(2)); } } @@ -57,10 +55,13 @@ void SimulationManager::BeginOfRunAction() { return; // Only call this once from the main thread } +#ifndef GEANT4_WITHOUT_G4RunManagerFactory + // gives segfault in old Geant4 versions such as 10.4.3, didn't look into it if (GetRestMetadata()->PrintProgress() || GetRestMetadata()->GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Essential) { - fPeriodicPrintThread = new thread(&PeriodicPrint, this, G4RunManager::GetRunManager()); + fPeriodicPrintThread = new thread(&PeriodicPrint, this); } +#endif } void SimulationManager::EndOfRunAction() { @@ -72,6 +73,11 @@ void SimulationManager::EndOfRunAction() { WriteEvents(); + if (fPeriodicPrintThread != nullptr) { + fPeriodicPrintThread->join(); // need to join thread, it may block for up to 1 thread period + delete fPeriodicPrintThread; + } + for (auto& outputManager : fOutputManagerContainer) { fNumberOfProcessedEvents += outputManager->GetEventCounter(); delete outputManager; @@ -79,11 +85,6 @@ void SimulationManager::EndOfRunAction() { GetRestMetadata()->SetNumberOfEvents(fNumberOfProcessedEvents); fOutputManagerContainer.clear(); - - if (fPeriodicPrintThread != nullptr) { - fPeriodicPrintThread->join(); // need to join thread, it may block for up to 1 second (thread period) - delete fPeriodicPrintThread; - } } SimulationManager::~SimulationManager() { From 7c99e9ee9a0c6b0d81680f925e69da5e1c842a12 Mon Sep 17 00:00:00 2001 From: lobis Date: Sun, 31 Jul 2022 08:00:27 +0200 Subject: [PATCH 134/173] Attempt to fix segfault --- src/RunAction.cxx | 2 +- src/SimulationManager.cxx | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/RunAction.cxx b/src/RunAction.cxx index 48417576..094c8cf3 100644 --- a/src/RunAction.cxx +++ b/src/RunAction.cxx @@ -55,7 +55,7 @@ void RunAction::EndOfRunAction(const G4Run*) { // Sanity check if (metadata->GetNumberOfDesiredEntries() == 0 && metadata->GetSimulationMaxTimeSeconds() == 0 && metadata->GetNumberOfEvents() != G4RunManager::GetRunManager()->GetNumberOfEventsToBeProcessed()) { - G4cout << "FATAL ERROR: possible error when calculating number of processed events, please check " + cerr << "FATAL ERROR: possible error when calculating number of processed events, please check " "'RunAction::EndOfRunAction'" << endl; exit(1); diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index 2dd8ae87..6f34754c 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -51,7 +51,7 @@ void PeriodicPrint(SimulationManager* simulationManager) { } void SimulationManager::BeginOfRunAction() { - if ((G4Threading::IsMultithreadedApplication() && G4Threading::G4GetThreadId() != -1)) { + if (G4Threading::IsMultithreadedApplication() && G4Threading::G4GetThreadId() != -1) { return; // Only call this once from the main thread } @@ -65,7 +65,7 @@ void SimulationManager::BeginOfRunAction() { } void SimulationManager::EndOfRunAction() { - if ((G4Threading::IsMultithreadedApplication() && G4Threading::G4GetThreadId() != -1)) { + if (G4Threading::IsMultithreadedApplication() && G4Threading::G4GetThreadId() != -1) { return; // Only call this once from the main thread } @@ -74,7 +74,9 @@ void SimulationManager::EndOfRunAction() { WriteEvents(); if (fPeriodicPrintThread != nullptr) { - fPeriodicPrintThread->join(); // need to join thread, it may block for up to 1 thread period + if (fPeriodicPrintThread->joinable()) { + fPeriodicPrintThread->join(); // need to join thread, it may block for up to 1 thread period + } delete fPeriodicPrintThread; } From 22e5257f5684607bafb0dff50d2ad821555653d9 Mon Sep 17 00:00:00 2001 From: lobis Date: Sun, 31 Jul 2022 08:40:01 +0200 Subject: [PATCH 135/173] Handle null pointers --- include/SimulationManager.h | 2 +- src/SimulationManager.cxx | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/include/SimulationManager.h b/include/SimulationManager.h index 4ff98ecd..3b1809e5 100644 --- a/include/SimulationManager.h +++ b/include/SimulationManager.h @@ -28,7 +28,7 @@ class SimulationManager { void WriteEvents(); void WriteEventsAndCloseFile(); - std::thread* fPeriodicPrintThread; + std::thread* fPeriodicPrintThread = nullptr; bool fPeriodicPrintThreadEndFlag = false; public: diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index 6f34754c..3694dc30 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -185,6 +185,9 @@ void SimulationManager::StopSimulation() { } void SimulationManager::SyncStatsFromChild(OutputManager* outputManager) { + if (outputManager == nullptr) { + return; + } lock_guard guard(fSimulationManagerMutex); fNumberOfProcessedEvents += outputManager->GetEventCounter(); outputManager->ResetEventCounter(); From 3030586ee96f930471ae3aed022d99038369d27c Mon Sep 17 00:00:00 2001 From: Luis Obis Date: Sun, 31 Jul 2022 18:01:09 +0200 Subject: [PATCH 136/173] Added error message for when output path is not accessible --- src/Application.cxx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Application.cxx b/src/Application.cxx index a21a8597..2033a4b3 100644 --- a/src/Application.cxx +++ b/src/Application.cxx @@ -370,6 +370,11 @@ void Application::Run(const CommandLineOptions::Options& options) { run->PrintMetadata(); run->FormOutputFile(); + if (run->GetOutputFile() == nullptr || !run->GetOutputFile()->IsWritable()) { + cerr << "Problem writing output file '" << run->GetOutputFileName() + << "'. Perhaps location does not exist or is not writable?" << endl; + exit(1); + } run->GetOutputFile()->cd(); run->AddEventBranch(&fSimulationManager.fEvent); From 7febe626c5f563f3f678ac19045140ba1a49e373 Mon Sep 17 00:00:00 2001 From: lobis Date: Mon, 1 Aug 2022 18:55:16 +0200 Subject: [PATCH 137/173] Updated examples --- examples/06.IonRecoils/recoils.rml | 7 +++---- examples/07.FullChainDecay/fullChain.rml | 7 +++---- examples/07.FullChainDecay/singleDecay.rml | 21 ++++++++++----------- src/Application.cxx | 2 +- 4 files changed, 17 insertions(+), 20 deletions(-) diff --git a/examples/06.IonRecoils/recoils.rml b/examples/06.IonRecoils/recoils.rml index 53497c02..941d2a49 100644 --- a/examples/06.IonRecoils/recoils.rml +++ b/examples/06.IonRecoils/recoils.rml @@ -68,11 +68,10 @@ By default REST units are mm, keV and degrees - // Use only one EM physics list - - - + + diff --git a/examples/07.FullChainDecay/fullChain.rml b/examples/07.FullChainDecay/fullChain.rml index 545232ad..6ede4297 100644 --- a/examples/07.FullChainDecay/fullChain.rml +++ b/examples/07.FullChainDecay/fullChain.rml @@ -68,11 +68,10 @@ By default REST units are mm, keV and degrees - // Use only one EM physics list - - - + + diff --git a/examples/07.FullChainDecay/singleDecay.rml b/examples/07.FullChainDecay/singleDecay.rml index b6eb1f9d..2d3a7df3 100644 --- a/examples/07.FullChainDecay/singleDecay.rml +++ b/examples/07.FullChainDecay/singleDecay.rml @@ -68,26 +68,25 @@ By default REST units are mm, keV and degrees - // Use only one EM physics list - - - + + - - + + - - - - - + + + + + diff --git a/src/Application.cxx b/src/Application.cxx index 38249035..9fc7847d 100644 --- a/src/Application.cxx +++ b/src/Application.cxx @@ -88,7 +88,7 @@ void PrintOptions(const Options& options) { : "") << (options.seed != 0 ? "\t- Random seed: " + to_string(options.seed) + "\n" : "") << (options.nDesiredEntries != 0 - ? "\t- Number of desired file entries: " + to_string(options.nDesiredEntries) + "\n" + ? "\t- Number of desired entries: " + to_string(options.nDesiredEntries) + "\n" : "") << (options.timeLimitSeconds != 0 ? "\t- Time limit: " + to_string(options.timeLimitSeconds) + " seconds\n" From 6532cd88142b1484bb67072b7f0229ff83298456 Mon Sep 17 00:00:00 2001 From: lobis Date: Mon, 1 Aug 2022 19:45:08 +0200 Subject: [PATCH 138/173] Added validation for output file --- include/Application.h | 1 + src/Application.cxx | 35 ++++++++++++++++++++++++++++++++++- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/include/Application.h b/include/Application.h index aa6b954b..ad311354 100644 --- a/include/Application.h +++ b/include/Application.h @@ -47,6 +47,7 @@ class Application { SimulationManager fSimulationManager; void WriteGeometry(TGeoManager* geometry, const char* filename, const char* option = "UPDATE"); + void ValidateOutputFile(const std::string& outputFile) const; }; #endif // REST_APPLICATION_H diff --git a/src/Application.cxx b/src/Application.cxx index 9fc7847d..7ca9c38a 100644 --- a/src/Application.cxx +++ b/src/Application.cxx @@ -466,7 +466,7 @@ void Application::Run(const CommandLineOptions::Options& options) { systime = time(nullptr); run->SetEndTimeStamp((Double_t)systime); - const TString filename = TRestTools::ToAbsoluteName(run->GetOutputFileName().Data()); + const string filename = TRestTools::ToAbsoluteName(run->GetOutputFileName().Data()); const auto nEntries = run->GetEntries(); @@ -488,6 +488,9 @@ void Application::Run(const CommandLineOptions::Options& options) { << " per second) and " << nEntries << " events saved to output file (" << nEntries / fSimulationManager.GetElapsedTime() << " per second)" << endl; cout << "\t- Output file: " << filename << endl << endl; + + // Do some checks + ValidateOutputFile(filename); } void Application::WriteGeometry(TGeoManager* geometry, const char* filename, const char* option) { @@ -502,3 +505,33 @@ void Application::WriteGeometry(TGeoManager* geometry, const char* filename, con file->Close(); } + +void Application::ValidateOutputFile(const string& filename) const { + bool error = false; + const auto file = TFile::Open(filename.c_str(), "READ"); + if (file == nullptr) { + cerr << "Output file not found" << endl; + exit(1); + } + + const auto eventTree = file->Get("EventTree"); + if (eventTree == nullptr) { + error = true; + cerr << "EventTree not found in output file" << endl; + } + const auto analysisTree = file->Get("AnalysisTree"); + if (analysisTree == nullptr) { + error = true; + cerr << "AnalysisTree not found in output file" << endl; + } + const auto geometry = file->Get("Geometry"); + if (geometry == nullptr) { + error = true; + cerr << "Geometry not found in output file" << endl; + } + + if (error) { + file->ls(); + exit(1); + } +} From 5d3930f513e135b98b99cf3a757fd0c2c6a4d391 Mon Sep 17 00:00:00 2001 From: lobis Date: Mon, 1 Aug 2022 20:30:08 +0200 Subject: [PATCH 139/173] Extended validation to check for metadata keys --- src/Application.cxx | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/src/Application.cxx b/src/Application.cxx index 7ca9c38a..415a7a89 100644 --- a/src/Application.cxx +++ b/src/Application.cxx @@ -493,6 +493,8 @@ void Application::Run(const CommandLineOptions::Options& options) { ValidateOutputFile(filename); } +constexpr const char* geometryName = "Geometry"; + void Application::WriteGeometry(TGeoManager* geometry, const char* filename, const char* option) { auto file = TFile::Open(filename, option); file->cd(); @@ -501,35 +503,54 @@ void Application::WriteGeometry(TGeoManager* geometry, const char* filename, con cout << "Application::WriteGeometry - Error - Unable to write geometry into file" << endl; exit(1); } - geometry->Write("Geometry"); + geometry->Write(geometryName); file->Close(); } void Application::ValidateOutputFile(const string& filename) const { bool error = false; - const auto file = TFile::Open(filename.c_str(), "READ"); + + const auto run = TRestRun(filename); + const auto file = run.GetInputFile(); if (file == nullptr) { cerr << "Output file not found" << endl; exit(1); } - const auto eventTree = file->Get("EventTree"); + const auto eventTree = run.GetEventTree(); if (eventTree == nullptr) { error = true; - cerr << "EventTree not found in output file" << endl; + cerr << "'EventTree' not found in output file" << endl; } - const auto analysisTree = file->Get("AnalysisTree"); + const auto analysisTree = run.GetAnalysisTree(); if (analysisTree == nullptr) { error = true; - cerr << "AnalysisTree not found in output file" << endl; + cerr << "'AnalysisTree' not found in output file" << endl; } - const auto geometry = file->Get("Geometry"); + + const auto geometry = file->Get(geometryName); if (geometry == nullptr) { error = true; cerr << "Geometry not found in output file" << endl; } + map metadataCount; + for (const auto& obj : *file->GetListOfKeys()) { + const auto key = dynamic_cast(obj); + metadataCount[key->GetClassName()]++; + } + for (const auto name : {"TRestGeant4Metadata", "TRestGeant4PhysicsLists", "TRestRun", "TRestAnalysisTree", + "TGeoManager", "TTree"}) { + if (metadataCount[name] != 1) { + error = true; + if (metadataCount[name] <= 0) { + cerr << "'" << name << "' not found in output file" << endl; + } else { + cerr << "Multiple instances of '" << name << "' in the same output file" << endl; + } + } + } if (error) { file->ls(); exit(1); From ab6f9715b5baed092a57bbc5971cb02f1777b295 Mon Sep 17 00:00:00 2001 From: lobis Date: Wed, 3 Aug 2022 12:23:16 +0200 Subject: [PATCH 140/173] Reordered prints --- src/Application.cxx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Application.cxx b/src/Application.cxx index 415a7a89..6a95edd1 100644 --- a/src/Application.cxx +++ b/src/Application.cxx @@ -15,9 +15,9 @@ #include #include #include -#include #include +#include #ifndef GEANT4_WITHOUT_G4RunManagerFactory #include #endif @@ -483,14 +483,14 @@ void Application::Run(const CommandLineOptions::Options& options) { const auto nEventsAtEnd = metadata->GetNumberOfEvents(); // This could be different from original if exit early - cout << "\t- Total simulation time is " << fSimulationManager.GetElapsedTime() << " seconds, " + // Do some checks + ValidateOutputFile(filename); + + cout << "\n\t- Total simulation time is " << fSimulationManager.GetElapsedTime() << " seconds, " << nEventsAtEnd << " processed events (" << nEventsAtEnd / fSimulationManager.GetElapsedTime() << " per second) and " << nEntries << " events saved to output file (" << nEntries / fSimulationManager.GetElapsedTime() << " per second)" << endl; cout << "\t- Output file: " << filename << endl << endl; - - // Do some checks - ValidateOutputFile(filename); } constexpr const char* geometryName = "Geometry"; From e057db33d719249440a4d00bfb17eed137c0c42a Mon Sep 17 00:00:00 2001 From: lobis Date: Tue, 30 Aug 2022 22:44:55 +0200 Subject: [PATCH 141/173] work in progress on alternative shaping process --- include/SimulationManager.h | 3 ++- src/SimulationManager.cxx | 15 ++++++--------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/include/SimulationManager.h b/include/SimulationManager.h index 3b1809e5..cc9973e6 100644 --- a/include/SimulationManager.h +++ b/include/SimulationManager.h @@ -107,7 +107,8 @@ class OutputManager { void RecordStep(const G4Step*); void AddSensitiveEnergy(Double_t energy, const char* physicalVolumeName); - void AddEnergyToVolumeForProcess(Double_t energy, const char* volumeName, const char* processName); + void AddEnergyToVolumeForParticleForProcess(Double_t energy, const char* volumeName, + const char* particleName, const char* processName); inline int GetEventCounter() const { return fProcessedEventsCounter; } inline void ResetEventCounter() { fProcessedEventsCounter = 0; } diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index 3694dc30..b5806232 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -301,17 +301,13 @@ void OutputManager::AddSensitiveEnergy(Double_t energy, const char* physicalVolu */ } -void OutputManager::AddEnergyToVolumeForProcess(Double_t energy, const char* volumeName, - const char* processName) { +void OutputManager::AddEnergyToVolumeForParticleForProcess(Double_t energy, const char* volumeName, + const char* particleName, + const char* processName) { if (energy <= 0) { return; } - if (fEvent->fEnergyInVolumePerProcess[volumeName].count(processName) == 0) { - fEvent->fEnergyInVolumePerProcess[volumeName][processName] = 0; - } - fEvent->fEnergyInVolumePerProcess[volumeName][processName] += energy; - - fEvent->fTotalDepositedEnergy += energy; + fEvent->fEnergyInVolumePerParticlePerProcess[volumeName][particleName][processName] += energy; } // Geant4Lib @@ -504,7 +500,8 @@ void TRestGeant4Hits::InsertStep(const G4Step* step) { fKineticEnergy.emplace_back(step->GetPreStepPoint()->GetKineticEnergy() / CLHEP::keV); fMomentumDirection.emplace_back(momentum.x(), momentum.y(), momentum.z()); - SimulationManager::GetOutputManager()->AddEnergyToVolumeForProcess(energy, volumeName, processName); + SimulationManager::GetOutputManager()->AddEnergyToVolumeForParticleForProcess(energy, volumeName, + particleName, processName); } void OutputManager::RemoveUnwantedTracks() { From 503ec5c669b41b7408e8fe07ccc55ec610d6e225 Mon Sep 17 00:00:00 2001 From: lobis Date: Thu, 1 Sep 2022 11:42:16 +0200 Subject: [PATCH 142/173] Time is now correctly stored as us instead of s --- src/SimulationManager.cxx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index b5806232..7012b885 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -421,7 +421,7 @@ TRestGeant4Track::TRestGeant4Track(const G4Track* track) : TRestGeant4Track() { fWeight = track->GetWeight(); - fGlobalTimestamp = track->GetGlobalTime() / CLHEP::second; + fGlobalTimestamp = track->GetGlobalTime() / CLHEP::microsecond; const G4ThreeVector& trackOrigin = track->GetPosition(); fInitialPosition = {trackOrigin.x(), trackOrigin.y(), trackOrigin.z()}; @@ -436,7 +436,7 @@ void TRestGeant4Track::UpdateTrack(const G4Track* track) { } fLength = track->GetTrackLength() / CLHEP::mm; - fTimeLength = track->GetGlobalTime() / CLHEP::second - fGlobalTimestamp; + fTimeLength = track->GetGlobalTime() / CLHEP::microsecond - fGlobalTimestamp; } Int_t TRestGeant4PhysicsInfo::GetProcessIDFromGeant4Process(const G4VProcess* process) { @@ -490,7 +490,7 @@ void TRestGeant4Hits::InsertStep(const G4Step* step) { Double_t z = aTrack->GetPosition().z() / CLHEP::mm; const TVector3 hitPosition(x, y, z); - const Double_t hitGlobalTime = step->GetPreStepPoint()->GetGlobalTime() / CLHEP::second; + const Double_t hitGlobalTime = step->GetPreStepPoint()->GetGlobalTime() / CLHEP::microsecond; const G4ThreeVector& momentum = step->GetPreStepPoint()->GetMomentumDirection(); AddHit(hitPosition, energy, hitGlobalTime); // this increases fNHits From 5b697ff814c2d386d3fbda49bf5c63e67c718e9e Mon Sep 17 00:00:00 2001 From: lobis Date: Thu, 1 Sep 2022 13:29:37 +0200 Subject: [PATCH 143/173] Attempt to fix pipeline --- examples/04.MuonScan/Validate.C | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/04.MuonScan/Validate.C b/examples/04.MuonScan/Validate.C index a2e38568..23807ef3 100644 --- a/examples/04.MuonScan/Validate.C +++ b/examples/04.MuonScan/Validate.C @@ -1,5 +1,7 @@ #include +#include +#include Int_t Validate(const char* filename) { cout << "Starting validation for '" << filename << "'" << endl; From f8fb120fe4dba093d7512f6f027defd8fd7fc153 Mon Sep 17 00:00:00 2001 From: lobis Date: Mon, 5 Sep 2022 18:18:27 +0200 Subject: [PATCH 144/173] fixed bug with total energy not computed --- src/SimulationManager.cxx | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index 7012b885..1dcd81f0 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -304,10 +304,7 @@ void OutputManager::AddSensitiveEnergy(Double_t energy, const char* physicalVolu void OutputManager::AddEnergyToVolumeForParticleForProcess(Double_t energy, const char* volumeName, const char* particleName, const char* processName) { - if (energy <= 0) { - return; - } - fEvent->fEnergyInVolumePerParticlePerProcess[volumeName][particleName][processName] += energy; + fEvent->AddEnergyInVolumeForParticleForProcess(energy, volumeName, particleName, processName); } // Geant4Lib From 00b15334e80e23b919fcad736eb07bea7fe3b48e Mon Sep 17 00:00:00 2001 From: lobis Date: Mon, 5 Sep 2022 18:35:11 +0200 Subject: [PATCH 145/173] simplified RML --- examples/10.Geometries/Assembly.rml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/examples/10.Geometries/Assembly.rml b/examples/10.Geometries/Assembly.rml index 5c0d2eb7..ee1ada4b 100644 --- a/examples/10.Geometries/Assembly.rml +++ b/examples/10.Geometries/Assembly.rml @@ -68,22 +68,22 @@ By default REST units are mm, keV and degrees - + - - + + - - - - - + + + + + From ecb5761e4a6ef009393b61b4ff1848491de15e67 Mon Sep 17 00:00:00 2001 From: lobis Date: Mon, 5 Sep 2022 20:23:27 +0200 Subject: [PATCH 146/173] added example for IAXO --- examples/10.Geometries/Assembly.rml | 2 +- examples/13.IAXO/Neutrons.rml | 69 +++++++++++++++++++ .../iaxo => 13.IAXO/geometry}/setup.gdml | 0 test/src/examples.cxx | 29 +++++++- 4 files changed, 98 insertions(+), 2 deletions(-) create mode 100644 examples/13.IAXO/Neutrons.rml rename examples/{10.Geometries/geometry/iaxo => 13.IAXO/geometry}/setup.gdml (100%) diff --git a/examples/10.Geometries/Assembly.rml b/examples/10.Geometries/Assembly.rml index ee1ada4b..aad6795a 100644 --- a/examples/10.Geometries/Assembly.rml +++ b/examples/10.Geometries/Assembly.rml @@ -30,7 +30,7 @@ By default REST units are mm, keV and degrees - + diff --git a/examples/13.IAXO/Neutrons.rml b/examples/13.IAXO/Neutrons.rml new file mode 100644 index 00000000..0855b622 --- /dev/null +++ b/examples/13.IAXO/Neutrons.rml @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/10.Geometries/geometry/iaxo/setup.gdml b/examples/13.IAXO/geometry/setup.gdml similarity index 100% rename from examples/10.Geometries/geometry/iaxo/setup.gdml rename to examples/13.IAXO/geometry/setup.gdml diff --git a/test/src/examples.cxx b/test/src/examples.cxx index 2c610fba..e9f1cfe9 100644 --- a/test/src/examples.cxx +++ b/test/src/examples.cxx @@ -285,7 +285,7 @@ TEST(restG4, Example_07_Decay_FullChain) { TEST(restG4, Example_09_Pb210_Shield) { GTEST_SKIP_("This test should work, but we skip it because it takes too long"); - // cd into example + // cd into example const auto originalPath = fs::current_path(); const auto thisExamplePath = examplesPath / "09.Pb210_Shield"; fs::current_path(thisExamplePath); @@ -311,6 +311,33 @@ TEST(restG4, Example_09_Pb210_Shield) { fs::current_path(originalPath); } +TEST(restG4, Example_10_Geometry) { + // cd into example + const auto originalPath = fs::current_path(); + const auto thisExamplePath = examplesPath / "10.Geometries"; + fs::current_path(thisExamplePath); + + CommandLineOptions::Options options; + options.rmlFile = "Assembly.rml"; + options.outputFile = thisExamplePath / "geometries.root"; + + Application app; + app.Run(options); + + TRestRun run(options.outputFile); + + // Run validation macro + const TString macro(thisExamplePath / "Validate.C"); + gROOT->ProcessLine(TString::Format(".L %s", macro.Data())); // Load macro + int error = 0; + const int result = + gROOT->ProcessLine(TString::Format("Validate(\"%s\")", options.outputFile.c_str()), &error); + EXPECT_EQ(error, 0); + EXPECT_EQ(result, 0); + + fs::current_path(originalPath); +} + TEST(restG4, Example_12_Generators) { // cd into example const auto originalPath = fs::current_path(); From ef5cde77a0c7afe8bf0fd0362b12148d24aa9e3f Mon Sep 17 00:00:00 2001 From: lobis Date: Mon, 5 Sep 2022 21:00:59 +0200 Subject: [PATCH 147/173] added example 13 to github pipeline --- .github/workflows/validation.yml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/.github/workflows/validation.yml b/.github/workflows/validation.yml index 695a9e0d..376c4b51 100644 --- a/.github/workflows/validation.yml +++ b/.github/workflows/validation.yml @@ -395,6 +395,27 @@ jobs: restG4 CosineSquaredCircle.rml -o CosineSquaredCircle.root restRoot -b -q Validate.C'("CosineSquaredCircle.root")' + restG4-examples-13: + name: "Example 13: IAXO" + runs-on: ubuntu-latest + container: + image: ghcr.io/lobis/root-geant4-garfield:rest-for-physics + needs: [ check-installation, restG4-examples-10 ] + steps: + - uses: actions/checkout@v3 + - name: Restore cache + uses: actions/cache@v3 + id: framework-install-restG4-cache + with: + path: ${{ env.REST_PATH }} + key: ${{ env.BRANCH_NAME }}-${{ github.sha }} + - name: Run example + run: | + source ${{ env.REST_PATH }}/thisREST.sh + cd ${{ env.REST_PATH }}/examples/restG4/13.IAXO/ + restG4 Neutrons.rml -o Neutrons.root -e 1 + restRoot -b -q Validate.C'("Neutrons.root")' + # Reference version of Geant4 framework-install-reference: From d6a0452d16edf1888446c8b02c8e0917ee55eb4b Mon Sep 17 00:00:00 2001 From: lobis Date: Mon, 5 Sep 2022 21:16:44 +0200 Subject: [PATCH 148/173] added validation macro for new example 13 --- examples/13.IAXO/Validate.C | 53 +++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 examples/13.IAXO/Validate.C diff --git a/examples/13.IAXO/Validate.C b/examples/13.IAXO/Validate.C new file mode 100644 index 00000000..bf665efc --- /dev/null +++ b/examples/13.IAXO/Validate.C @@ -0,0 +1,53 @@ + +Int_t Validate(const char* filename) { + gSystem->Load("libRestFramework.so"); + gSystem->Load("libRestGeant4.so"); + + TRestRun run(filename); + + cout << "Entries: " << run.GetEntries() << endl; + + if (run.GetEntries() != 1) { + cout << "Bad number of entries: " << run.GetEntries() << endl; + return 1; + } + + auto metadata = (TRestGeant4Metadata*)run.GetMetadataClass("TRestGeant4Metadata"); + + const auto geometryInfo = metadata->GetGeant4GeometryInfo(); + + geometryInfo.Print(); + + if (geometryInfo.GetAllPhysicalVolumes().size() != 374) { + cout << "Incorrect number of physical volumes " << geometryInfo.GetAllPhysicalVolumes().size() + << endl; + } + if (geometryInfo.GetAllLogicalVolumes().size() != 22) { + cout << "Incorrect number of logical volumes " << geometryInfo.GetAllLogicalVolumes().size() << endl; + } + + // event information + TRestGeant4Event* event = run.GetInputEvent(); + run.GetEntry(0); + + if (event->GetNumberOfTracks() != 28059) { + cout << "Incorrect number of tracks: " << event->GetNumberOfTracks() << endl; + } + if (event->GetNumberOfHits() != 87189) { + cout << "Incorrect number of hits: " << event->GetNumberOfHits() << endl; + } + + if (TMath::Abs(event->GetSensitiveVolumeEnergy() - 72.436883) > 1e-4) { + cout << "Incorrect sensitive volume energy: " << event->GetSensitiveVolumeEnergy() << endl; + } + + const auto scintillatorEnergy = event->GetEnergyInVolume( + "VetoSystem_vetoSystemBack_vetoLayerBack1_assembly-17.veto3_scintillatorVolume-800.0mm-f1a5df6c"); + if (TMath::Abs(scintillatorEnergy - 1348.3876) > 1e-4) { + cout << "Incorrect scintillator volume energy: " << scintillatorEnergy << endl; + } + + cout << "All tests passed! [\033[32mOK\033[0m]\n"; + + return 0; +} From 5b7cb787a87dd16f3fd56ee078c18577dd6afa59 Mon Sep 17 00:00:00 2001 From: lobis Date: Mon, 5 Sep 2022 21:47:32 +0200 Subject: [PATCH 149/173] added more checks to validation --- examples/13.IAXO/Validate.C | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/examples/13.IAXO/Validate.C b/examples/13.IAXO/Validate.C index bf665efc..869ce91a 100644 --- a/examples/13.IAXO/Validate.C +++ b/examples/13.IAXO/Validate.C @@ -21,9 +21,11 @@ Int_t Validate(const char* filename) { if (geometryInfo.GetAllPhysicalVolumes().size() != 374) { cout << "Incorrect number of physical volumes " << geometryInfo.GetAllPhysicalVolumes().size() << endl; + return 2; } if (geometryInfo.GetAllLogicalVolumes().size() != 22) { cout << "Incorrect number of logical volumes " << geometryInfo.GetAllLogicalVolumes().size() << endl; + return 3; } // event information @@ -32,19 +34,43 @@ Int_t Validate(const char* filename) { if (event->GetNumberOfTracks() != 28059) { cout << "Incorrect number of tracks: " << event->GetNumberOfTracks() << endl; + return 4; } if (event->GetNumberOfHits() != 87189) { cout << "Incorrect number of hits: " << event->GetNumberOfHits() << endl; + return 5; } if (TMath::Abs(event->GetSensitiveVolumeEnergy() - 72.436883) > 1e-4) { cout << "Incorrect sensitive volume energy: " << event->GetSensitiveVolumeEnergy() << endl; + return 6; } - const auto scintillatorEnergy = event->GetEnergyInVolume( - "VetoSystem_vetoSystemBack_vetoLayerBack1_assembly-17.veto3_scintillatorVolume-800.0mm-f1a5df6c"); - if (TMath::Abs(scintillatorEnergy - 1348.3876) > 1e-4) { + const auto scintillatorVolumeName = + "VetoSystem_vetoSystemBack_vetoLayerBack1_assembly-17.veto3_scintillatorVolume-800.0mm-f1a5df6c"; + const auto scintillatorEnergy = event->GetEnergyInVolume(scintillatorVolumeName); + const auto scintillatorEnergyRef = 1348.3876; + if (TMath::Abs(scintillatorEnergy - scintillatorEnergyRef) > 1e-4) { cout << "Incorrect scintillator volume energy: " << scintillatorEnergy << endl; + return 7; + } + + double scintillatorEnergyFromTracks = 0; + for (const auto& track : event->GetTracks()) { + const auto hits = track.GetHits(); + for (int i = 0; i < hits.GetNumberOfHits(); i++) { + const auto volumeName = geometryInfo.GetVolumeFromID(hits.GetVolumeId(i)); + if (volumeName != scintillatorVolumeName) { + continue; + } + const auto energy = hits.GetEnergy(i); + scintillatorEnergyFromTracks += energy; + } + } + + if (TMath::Abs(scintillatorEnergyFromTracks - scintillatorEnergyRef) > 1e-4) { + cout << "Incorrect scintillator volume energy from tracks: " << scintillatorEnergyFromTracks << endl; + return 8; } cout << "All tests passed! [\033[32mOK\033[0m]\n"; From a01a0de888fedb375e29fdd8ba04895b14b5eeab Mon Sep 17 00:00:00 2001 From: lobis Date: Tue, 6 Sep 2022 14:09:57 +0200 Subject: [PATCH 150/173] added example 13 to tests --- test/src/examples.cxx | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/test/src/examples.cxx b/test/src/examples.cxx index e9f1cfe9..3c164cb1 100644 --- a/test/src/examples.cxx +++ b/test/src/examples.cxx @@ -364,3 +364,31 @@ TEST(restG4, Example_12_Generators) { fs::current_path(originalPath); } + +TEST(restG4, Example_13_IAXO) { + // cd into example + const auto originalPath = fs::current_path(); + const auto thisExamplePath = examplesPath / "13.IAXO"; + fs::current_path(thisExamplePath); + + CommandLineOptions::Options options; + options.rmlFile = "Neutrons.rml"; + options.outputFile = thisExamplePath / "Neutrons.root"; + options.nDesiredEntries = 1; + + Application app; + app.Run(options); + + TRestRun run(options.outputFile); + + // Run validation macro + const TString macro(thisExamplePath / "Validate.C"); + gROOT->ProcessLine(TString::Format(".L %s", macro.Data())); // Load macro + int error = 0; + const int result = + gROOT->ProcessLine(TString::Format("Validate(\"%s\")", options.outputFile.c_str()), &error); + EXPECT_EQ(error, 0); + EXPECT_EQ(result, 0); + + fs::current_path(originalPath); +} From 2375268dd55dbe88f0297eab8f06535e38480e34 Mon Sep 17 00:00:00 2001 From: lobis Date: Tue, 6 Sep 2022 14:10:17 +0200 Subject: [PATCH 151/173] correctly insert process type --- src/SimulationManager.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index 1dcd81f0..669ad3ea 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -472,7 +472,7 @@ void TRestGeant4Hits::InsertStep(const G4Step* step) { processID = TRestGeant4PhysicsInfo::GetProcessIDFromGeant4Process(process); } - metadata->fGeant4PhysicsInfo.InsertProcessName(processID, processName); + metadata->fGeant4PhysicsInfo.InsertProcessName(processID, processName, processTypeName); const auto energy = step->GetTotalEnergyDeposit() / CLHEP::keV; const auto trackKineticEnergy = step->GetTrack()->GetKineticEnergy() / CLHEP::keV; From fbf98714579d76c5ad33633f430c3c65b8792e29 Mon Sep 17 00:00:00 2001 From: Luis Obis Date: Tue, 6 Sep 2022 21:17:09 +0200 Subject: [PATCH 152/173] working on remove unwanted tracks bug --- examples/13.IAXO/Neutrons.rml | 2 +- examples/13.IAXO/Validate.C | 4 ++-- src/SimulationManager.cxx | 5 +---- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/examples/13.IAXO/Neutrons.rml b/examples/13.IAXO/Neutrons.rml index 0855b622..5379fe4d 100644 --- a/examples/13.IAXO/Neutrons.rml +++ b/examples/13.IAXO/Neutrons.rml @@ -27,7 +27,7 @@ Author: Luis Obis (lobis@unizar.es) - + diff --git a/examples/13.IAXO/Validate.C b/examples/13.IAXO/Validate.C index 869ce91a..370450df 100644 --- a/examples/13.IAXO/Validate.C +++ b/examples/13.IAXO/Validate.C @@ -34,11 +34,11 @@ Int_t Validate(const char* filename) { if (event->GetNumberOfTracks() != 28059) { cout << "Incorrect number of tracks: " << event->GetNumberOfTracks() << endl; - return 4; + // return 4; } if (event->GetNumberOfHits() != 87189) { cout << "Incorrect number of hits: " << event->GetNumberOfHits() << endl; - return 5; + // return 5; } if (TMath::Abs(event->GetSensitiveVolumeEnergy() - 72.436883) > 1e-4) { diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index 669ad3ea..b652c128 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -516,8 +516,7 @@ void OutputManager::RemoveUnwantedTracks() { energy <= 0) { continue; } - const auto volumeID = hits.GetVolumeId(i); - const auto volume = metadata->GetGeant4GeometryInfo().GetVolumeFromID(volumeID); + const auto volume = metadata->GetGeant4GeometryInfo().GetVolumeFromID(hits.GetVolumeId(i)); if (metadata->IsKeepTracksVolume(volume)) { trackIDsToKeep.insert(track.GetTrackID()); auto parentTrack = track.GetParentTrack(); @@ -541,8 +540,6 @@ void OutputManager::RemoveUnwantedTracks() { fEvent->fTracks = tracksAfterRemoval; const size_t numberOfTracksAfter = fEvent->fTracks.size(); - /* cout << "EventID: " << fEvent->GetID() << " Removed " << numberOfTracksBefore - numberOfTracksAfter << " tracks out of " << numberOfTracksBefore << endl; - */ } \ No newline at end of file From a7db11984f6751d16fa212fda407082ad947c3f9 Mon Sep 17 00:00:00 2001 From: Luis Obis Date: Thu, 8 Sep 2022 13:25:06 +0200 Subject: [PATCH 153/173] fixed bad parenthesis --- src/SimulationManager.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index b652c128..a148efce 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -506,7 +506,7 @@ void OutputManager::RemoveUnwantedTracks() { set trackIDsToKeep; // We populate this container with the tracks we want to keep for (const auto& track : fEvent->fTracks) { // If one children track is kept, we keep all the parents - if (trackIDsToKeep.count(track.GetTrackID() > 0)) { + if (trackIDsToKeep.count(track.GetTrackID()) > 0) { continue; } const auto hits = track.GetHits(); From 54421db39c96cd440963912d16d394fceabfd97b Mon Sep 17 00:00:00 2001 From: Luis Obis Date: Thu, 8 Sep 2022 13:37:48 +0200 Subject: [PATCH 154/173] added check for number of tracks and hits --- examples/13.IAXO/Validate.C | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/13.IAXO/Validate.C b/examples/13.IAXO/Validate.C index 370450df..c5cd0e6d 100644 --- a/examples/13.IAXO/Validate.C +++ b/examples/13.IAXO/Validate.C @@ -32,13 +32,13 @@ Int_t Validate(const char* filename) { TRestGeant4Event* event = run.GetInputEvent(); run.GetEntry(0); - if (event->GetNumberOfTracks() != 28059) { + if (event->GetNumberOfTracks() != 1738 /* 28059 */) { cout << "Incorrect number of tracks: " << event->GetNumberOfTracks() << endl; - // return 4; + return 4; } - if (event->GetNumberOfHits() != 87189) { + if (event->GetNumberOfHits() != 15202 /* 87189 */) { cout << "Incorrect number of hits: " << event->GetNumberOfHits() << endl; - // return 5; + return 5; } if (TMath::Abs(event->GetSensitiveVolumeEnergy() - 72.436883) > 1e-4) { From 73b708d370a4832845b0af81fc4dc4ddd504d731 Mon Sep 17 00:00:00 2001 From: lobis Date: Fri, 9 Sep 2022 13:05:54 +0200 Subject: [PATCH 155/173] Correctly update fTrackIDToTrackIndex when removing tracks --- src/SimulationManager.cxx | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index a148efce..9b0ed2a2 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -510,7 +510,7 @@ void OutputManager::RemoveUnwantedTracks() { continue; } const auto hits = track.GetHits(); - for (int i = 0; i < hits.GetNumberOfHits(); i++) { + for (int i = 0; i < int(hits.GetNumberOfHits()); i++) { const auto energy = hits.GetEnergy(i); if (!fSimulationManager->GetRestMetadata()->GetRemoveUnwantedTracksKeepZeroEnergyTracks() && energy <= 0) { @@ -538,8 +538,15 @@ void OutputManager::RemoveUnwantedTracks() { } fEvent->fTracks = tracksAfterRemoval; - const size_t numberOfTracksAfter = fEvent->fTracks.size(); + fEvent->fTrackIDToTrackIndex.clear(); + for (int i = 0; i < int(fEvent->fTracks.size()); i++) { + fEvent->fTrackIDToTrackIndex[fEvent->fTracks[i].GetTrackID()] = i; + } + + /* + const size_t numberOfTracksAfter = fEvent->fTracks.size(); cout << "EventID: " << fEvent->GetID() << " Removed " << numberOfTracksBefore - numberOfTracksAfter << " tracks out of " << numberOfTracksBefore << endl; + */ } \ No newline at end of file From 48d42f08b6aea55bcec6d0601ece859fdbde5594 Mon Sep 17 00:00:00 2001 From: lobis Date: Fri, 9 Sep 2022 14:14:42 +0200 Subject: [PATCH 156/173] added comment --- src/SimulationManager.cxx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index 9b0ed2a2..7caa07ed 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -363,7 +363,7 @@ bool TRestGeant4Event::InsertTrack(const G4Track* track) { fSubEventPrimaryDirection = {momentum.x(), momentum.y(), momentum.z()}; } - fTrackIDToTrackIndex[track->GetTrackID()] = fTracks.size(); // before insertion + fTrackIDToTrackIndex[track->GetTrackID()] = int(fTracks.size()); // before insertion fTracks.emplace_back(track); @@ -539,6 +539,7 @@ void OutputManager::RemoveUnwantedTracks() { fEvent->fTracks = tracksAfterRemoval; + // Updated indices fEvent->fTrackIDToTrackIndex.clear(); for (int i = 0; i < int(fEvent->fTracks.size()); i++) { fEvent->fTrackIDToTrackIndex[fEvent->fTracks[i].GetTrackID()] = i; From 393929c3d9653fd6d97e73ee2e92708db5a3c997 Mon Sep 17 00:00:00 2001 From: lobis Date: Mon, 12 Sep 2022 16:45:16 +0200 Subject: [PATCH 157/173] SimulationManager - added back activation volumes with random chance --- src/SimulationManager.cxx | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index 7caa07ed..84c6aecf 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -9,6 +9,7 @@ #include #include "SteppingAction.h" + using namespace std; thread_local OutputManager* SimulationManager::fOutputManager = nullptr; @@ -327,20 +328,20 @@ TRestGeant4Event::TRestGeant4Event(const G4Event* event) : TRestGeant4Event() { fPrimaryDirections.emplace_back(momentum.x(), momentum.y(), momentum.z()); } - return; - // TODO: move this // Defining if the hits in a given volume will be stored const auto metadata = GetGeant4Metadata(); - for (int i = 0; i < metadata->GetNumberOfActiveVolumes(); i++) { - if (metadata->GetStorageChance(i) >= 1.00) { - // ActivateVolumeForStorage(i); - } else { - Double_t randomNumber = G4UniformRand(); - if (metadata->GetStorageChance(i) >= randomNumber) { - // ActivateVolumeForStorage(i); + if (metadata != nullptr) { + for (int i = 0; i < metadata->GetNumberOfActiveVolumes(); i++) { + if (metadata->GetStorageChance(i) >= 1.00) { + ActivateVolumeForStorage(i); } else { - DisableVolumeForStorage(i); + Double_t randomNumber = G4UniformRand(); + if (metadata->GetStorageChance(i) >= randomNumber) { + ActivateVolumeForStorage(i); + } else { + DisableVolumeForStorage(i); + } } } } From 0a0c8c5efd7023e8754c6d90d5c91413a031e272 Mon Sep 17 00:00:00 2001 From: lobis Date: Mon, 12 Sep 2022 16:55:42 +0200 Subject: [PATCH 158/173] moved code relative to Geant4Lib into separate file --- src/DataModel.cxx | 254 ++++++++++++++++++++++++++++++++++++++ src/SimulationManager.cxx | 245 ------------------------------------ 2 files changed, 254 insertions(+), 245 deletions(-) create mode 100644 src/DataModel.cxx diff --git a/src/DataModel.cxx b/src/DataModel.cxx new file mode 100644 index 00000000..6c07626f --- /dev/null +++ b/src/DataModel.cxx @@ -0,0 +1,254 @@ + +#include +#include +#include +#include +#include + +#include "SimulationManager.h" +#include "SteppingAction.h" + +using namespace std; + +TRestGeant4Event::TRestGeant4Event(const G4Event* event) : TRestGeant4Event() { + SetID(event->GetEventID()); + SetOK(true); + time_t system_time = time(nullptr); + + SetTime((Double_t)system_time); + + auto primaryVertex = event->GetPrimaryVertex(); + const auto& position = primaryVertex->GetPosition(); + fPrimaryPosition = {position.x() / CLHEP::mm, position.y() / CLHEP::mm, position.z() / CLHEP::mm}; + for (int i = 0; i < primaryVertex->GetNumberOfParticle(); i++) { + const auto& primaryParticle = primaryVertex->GetPrimary(i); + fPrimaryParticleNames.emplace_back(primaryParticle->GetParticleDefinition()->GetParticleName()); + fPrimaryEnergies.emplace_back(primaryParticle->GetKineticEnergy() / CLHEP::keV); + const auto& momentum = primaryParticle->GetMomentumDirection(); + fPrimaryDirections.emplace_back(momentum.x(), momentum.y(), momentum.z()); + } + + // TODO: move this + // Defining if the hits in a given volume will be stored + const auto metadata = GetGeant4Metadata(); + if (metadata != nullptr) { + for (int i = 0; i < metadata->GetNumberOfActiveVolumes(); i++) { + if (metadata->GetStorageChance(i) >= 1.00) { + ActivateVolumeForStorage(i); + } else { + Double_t randomNumber = G4UniformRand(); + if (metadata->GetStorageChance(i) >= randomNumber) { + ActivateVolumeForStorage(i); + } else { + DisableVolumeForStorage(i); + } + } + } + } +} + +bool TRestGeant4Event::InsertTrack(const G4Track* track) { + if (fInitialStep.GetNumberOfHits() != 1) { + cout << "fInitialStep does not have exactly one step! Problem with stepping verbose" << endl; + exit(1); + } + + if (fTracks.empty() && IsSubEvent()) { + // First track of sub-event (primary) + fSubEventPrimaryParticleName = track->GetParticleDefinition()->GetParticleName(); + fSubEventPrimaryEnergy = track->GetKineticEnergy() / CLHEP::keV; + const auto& position = track->GetPosition(); + fSubEventPrimaryPosition = {position.x() / CLHEP::mm, position.y() / CLHEP::mm, + position.z() / CLHEP::mm}; + const auto& momentum = track->GetMomentumDirection(); + fSubEventPrimaryDirection = {momentum.x(), momentum.y(), momentum.z()}; + } + + fTrackIDToTrackIndex[track->GetTrackID()] = int(fTracks.size()); // before insertion + + fTracks.emplace_back(track); + + auto& insertedTrack = fTracks.back(); + + insertedTrack.SetHits(fInitialStep); + insertedTrack.SetEvent(this); + + TRestGeant4Track* parentTrack = GetTrackByID(track->GetParentID()); + if (parentTrack) { + parentTrack->AddSecondaryTrackID(track->GetTrackID()); + } + + return true; +} + +void TRestGeant4Event::UpdateTrack(const G4Track* track) { fTracks.back().UpdateTrack(track); } + +void TRestGeant4Event::InsertStep(const G4Step* step) { + if (step->GetTrack()->GetCurrentStepNumber() == 0) { + // initial step (from SteppingVerbose) is generated before TrackingAction can insert the first track + fInitialStep = TRestGeant4Hits(); + fInitialStep.SetEvent(this); + fInitialStep.InsertStep(step); + } else { + fTracks.back().InsertStep(step); + } +} + +bool OutputManager::IsValidTrack(const G4Track*) const { return true; } + +bool OutputManager::IsValidStep(const G4Step*) const { return true; } + +TRestGeant4Track::TRestGeant4Track(const G4Track* track) : TRestGeant4Track() { + fTrackID = track->GetTrackID(); + fParentID = track->GetParentID(); + + auto particle = track->GetParticleDefinition(); + fParticleName = particle->GetParticleName(); + /* + fParticleID = particle->GetPDGEncoding(); + fParticleType = particle->GetParticleType(); + fParticleSubType = particle->GetParticleSubType(); + */ + if (track->GetCreatorProcess() != nullptr) { + fCreatorProcess = track->GetCreatorProcess()->GetProcessName(); + } else { + fCreatorProcess = "PrimaryGenerator"; + } + + fInitialKineticEnergy = track->GetKineticEnergy() / CLHEP::keV; + + fWeight = track->GetWeight(); + + fGlobalTimestamp = track->GetGlobalTime() / CLHEP::microsecond; + + const G4ThreeVector& trackOrigin = track->GetPosition(); + fInitialPosition = {trackOrigin.x(), trackOrigin.y(), trackOrigin.z()}; +} + +void TRestGeant4Track::InsertStep(const G4Step* step) { fHits.InsertStep(step); } + +void TRestGeant4Track::UpdateTrack(const G4Track* track) { + if (track->GetTrackID() != fTrackID) { + G4cout << "Geant4Track::UpdateTrack - mismatch of trackID!" << endl; + exit(1); + } + + fLength = track->GetTrackLength() / CLHEP::mm; + fTimeLength = track->GetGlobalTime() / CLHEP::microsecond - fGlobalTimestamp; +} + +Int_t TRestGeant4PhysicsInfo::GetProcessIDFromGeant4Process(const G4VProcess* process) { + return process->GetProcessType() * 1000 + process->GetProcessSubType(); +} + +void TRestGeant4Hits::InsertStep(const G4Step* step) { + const G4Track* track = step->GetTrack(); + + TRestGeant4Metadata* metadata = GetGeant4Metadata(); + + const auto& geometryInfo = metadata->GetGeant4GeometryInfo(); + + const auto& volumeNameGeant4 = step->GetPreStepPoint()->GetPhysicalVolume()->GetName(); + const auto& volumeName = geometryInfo.GetAlternativeNameFromGeant4PhysicalName(volumeNameGeant4); + + if (!metadata->IsActiveVolume(volumeName) && step->GetTrack()->GetCurrentStepNumber() != 0) { + // we always store the first step + return; + } + + const auto& particle = step->GetTrack()->GetDefinition(); + const auto& particleID = particle->GetPDGEncoding(); + const auto& particleName = particle->GetParticleName(); + + metadata->fGeant4PhysicsInfo.InsertParticleName(particleID, particleName); + + const auto process = step->GetPostStepPoint()->GetProcessDefinedStep(); + G4String processName = "Init"; + G4String processTypeName = "Init"; + Int_t processID = 0; + if (track->GetCurrentStepNumber() != 0) { + // 0 = Init step (G4SteppingVerbose) process is not defined for this step + processName = process->GetProcessName(); + processTypeName = G4VProcess::GetProcessTypeName(process->GetProcessType()); + processID = TRestGeant4PhysicsInfo::GetProcessIDFromGeant4Process(process); + } + + metadata->fGeant4PhysicsInfo.InsertProcessName(processID, processName, processTypeName); + + const auto energy = step->GetTotalEnergyDeposit() / CLHEP::keV; + const auto trackKineticEnergy = step->GetTrack()->GetKineticEnergy() / CLHEP::keV; + + auto sensitiveVolumeName = + geometryInfo.GetAlternativeNameFromGeant4PhysicalName(metadata->GetSensitiveVolume()); + + G4Track* aTrack = step->GetTrack(); + + Double_t x = aTrack->GetPosition().x() / CLHEP::mm; + Double_t y = aTrack->GetPosition().y() / CLHEP::mm; + Double_t z = aTrack->GetPosition().z() / CLHEP::mm; + + const TVector3 hitPosition(x, y, z); + const Double_t hitGlobalTime = step->GetPreStepPoint()->GetGlobalTime() / CLHEP::microsecond; + const G4ThreeVector& momentum = step->GetPreStepPoint()->GetMomentumDirection(); + + AddHit(hitPosition, energy, hitGlobalTime); // this increases fNHits + + fProcessID.emplace_back(processID); + fVolumeID.emplace_back(geometryInfo.GetIDFromVolume(volumeName)); + fKineticEnergy.emplace_back(step->GetPreStepPoint()->GetKineticEnergy() / CLHEP::keV); + fMomentumDirection.emplace_back(momentum.x(), momentum.y(), momentum.z()); + + SimulationManager::GetOutputManager()->AddEnergyToVolumeForParticleForProcess(energy, volumeName, + particleName, processName); +} + +void OutputManager::RemoveUnwantedTracks() { + const auto& metadata = fSimulationManager->GetRestMetadata(); + set trackIDsToKeep; // We populate this container with the tracks we want to keep + for (const auto& track : fEvent->fTracks) { + // If one children track is kept, we keep all the parents + if (trackIDsToKeep.count(track.GetTrackID()) > 0) { + continue; + } + const auto hits = track.GetHits(); + for (int i = 0; i < int(hits.GetNumberOfHits()); i++) { + const auto energy = hits.GetEnergy(i); + if (!fSimulationManager->GetRestMetadata()->GetRemoveUnwantedTracksKeepZeroEnergyTracks() && + energy <= 0) { + continue; + } + const auto volume = metadata->GetGeant4GeometryInfo().GetVolumeFromID(hits.GetVolumeId(i)); + if (metadata->IsKeepTracksVolume(volume)) { + trackIDsToKeep.insert(track.GetTrackID()); + auto parentTrack = track.GetParentTrack(); + while (parentTrack != nullptr) { + trackIDsToKeep.insert(parentTrack->GetTrackID()); + parentTrack = parentTrack->GetParentTrack(); + } + } + } + } + const size_t numberOfTracksBefore = fEvent->fTracks.size(); + + vector tracksAfterRemoval; + for (const auto& track : fEvent->fTracks) { + // we do this to preserve original order + if (trackIDsToKeep.count(track.GetTrackID()) > 0) { + tracksAfterRemoval.push_back(*(fEvent->GetTrackByID(track.GetTrackID()))); + } + } + + fEvent->fTracks = tracksAfterRemoval; + + // Updated indices + fEvent->fTrackIDToTrackIndex.clear(); + for (int i = 0; i < int(fEvent->fTracks.size()); i++) { + fEvent->fTrackIDToTrackIndex[fEvent->fTracks[i].GetTrackID()] = i; + } + + /* + const size_t numberOfTracksAfter = fEvent->fTracks.size(); + cout << "EventID: " << fEvent->GetID() << " Removed " << numberOfTracksBefore - numberOfTracksAfter + << " tracks out of " << numberOfTracksBefore << endl; + */ +} diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index 84c6aecf..584f9dbc 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -307,248 +307,3 @@ void OutputManager::AddEnergyToVolumeForParticleForProcess(Double_t energy, cons const char* processName) { fEvent->AddEnergyInVolumeForParticleForProcess(energy, volumeName, particleName, processName); } - -// Geant4Lib - -TRestGeant4Event::TRestGeant4Event(const G4Event* event) : TRestGeant4Event() { - SetID(event->GetEventID()); - SetOK(true); - time_t system_time = time(nullptr); - - SetTime((Double_t)system_time); - - auto primaryVertex = event->GetPrimaryVertex(); - const auto& position = primaryVertex->GetPosition(); - fPrimaryPosition = {position.x() / CLHEP::mm, position.y() / CLHEP::mm, position.z() / CLHEP::mm}; - for (int i = 0; i < primaryVertex->GetNumberOfParticle(); i++) { - const auto& primaryParticle = primaryVertex->GetPrimary(i); - fPrimaryParticleNames.emplace_back(primaryParticle->GetParticleDefinition()->GetParticleName()); - fPrimaryEnergies.emplace_back(primaryParticle->GetKineticEnergy() / CLHEP::keV); - const auto& momentum = primaryParticle->GetMomentumDirection(); - fPrimaryDirections.emplace_back(momentum.x(), momentum.y(), momentum.z()); - } - - // TODO: move this - // Defining if the hits in a given volume will be stored - const auto metadata = GetGeant4Metadata(); - if (metadata != nullptr) { - for (int i = 0; i < metadata->GetNumberOfActiveVolumes(); i++) { - if (metadata->GetStorageChance(i) >= 1.00) { - ActivateVolumeForStorage(i); - } else { - Double_t randomNumber = G4UniformRand(); - if (metadata->GetStorageChance(i) >= randomNumber) { - ActivateVolumeForStorage(i); - } else { - DisableVolumeForStorage(i); - } - } - } - } -} - -bool TRestGeant4Event::InsertTrack(const G4Track* track) { - if (fInitialStep.GetNumberOfHits() != 1) { - cout << "fInitialStep does not have exactly one step! Problem with stepping verbose" << endl; - exit(1); - } - - if (fTracks.empty() && IsSubEvent()) { - // First track of sub-event (primary) - fSubEventPrimaryParticleName = track->GetParticleDefinition()->GetParticleName(); - fSubEventPrimaryEnergy = track->GetKineticEnergy() / CLHEP::keV; - const auto& position = track->GetPosition(); - fSubEventPrimaryPosition = {position.x() / CLHEP::mm, position.y() / CLHEP::mm, - position.z() / CLHEP::mm}; - const auto& momentum = track->GetMomentumDirection(); - fSubEventPrimaryDirection = {momentum.x(), momentum.y(), momentum.z()}; - } - - fTrackIDToTrackIndex[track->GetTrackID()] = int(fTracks.size()); // before insertion - - fTracks.emplace_back(track); - - auto& insertedTrack = fTracks.back(); - - insertedTrack.SetHits(fInitialStep); - insertedTrack.SetEvent(this); - - TRestGeant4Track* parentTrack = GetTrackByID(track->GetParentID()); - if (parentTrack) { - parentTrack->AddSecondaryTrackID(track->GetTrackID()); - } - - return true; -} - -void TRestGeant4Event::UpdateTrack(const G4Track* track) { fTracks.back().UpdateTrack(track); } - -void TRestGeant4Event::InsertStep(const G4Step* step) { - if (step->GetTrack()->GetCurrentStepNumber() == 0) { - // initial step (from SteppingVerbose) is generated before TrackingAction can insert the first track - fInitialStep = TRestGeant4Hits(); - fInitialStep.SetEvent(this); - fInitialStep.InsertStep(step); - } else { - fTracks.back().InsertStep(step); - } -} - -bool OutputManager::IsValidTrack(const G4Track*) const { return true; } - -bool OutputManager::IsValidStep(const G4Step*) const { return true; } - -TRestGeant4Track::TRestGeant4Track(const G4Track* track) : TRestGeant4Track() { - fTrackID = track->GetTrackID(); - fParentID = track->GetParentID(); - - auto particle = track->GetParticleDefinition(); - fParticleName = particle->GetParticleName(); - /* - fParticleID = particle->GetPDGEncoding(); - fParticleType = particle->GetParticleType(); - fParticleSubType = particle->GetParticleSubType(); - */ - if (track->GetCreatorProcess() != nullptr) { - fCreatorProcess = track->GetCreatorProcess()->GetProcessName(); - } else { - fCreatorProcess = "PrimaryGenerator"; - } - - fInitialKineticEnergy = track->GetKineticEnergy() / CLHEP::keV; - - fWeight = track->GetWeight(); - - fGlobalTimestamp = track->GetGlobalTime() / CLHEP::microsecond; - - const G4ThreeVector& trackOrigin = track->GetPosition(); - fInitialPosition = {trackOrigin.x(), trackOrigin.y(), trackOrigin.z()}; -} - -void TRestGeant4Track::InsertStep(const G4Step* step) { fHits.InsertStep(step); } - -void TRestGeant4Track::UpdateTrack(const G4Track* track) { - if (track->GetTrackID() != fTrackID) { - G4cout << "Geant4Track::UpdateTrack - mismatch of trackID!" << endl; - exit(1); - } - - fLength = track->GetTrackLength() / CLHEP::mm; - fTimeLength = track->GetGlobalTime() / CLHEP::microsecond - fGlobalTimestamp; -} - -Int_t TRestGeant4PhysicsInfo::GetProcessIDFromGeant4Process(const G4VProcess* process) { - return process->GetProcessType() * 1000 + process->GetProcessSubType(); -} - -void TRestGeant4Hits::InsertStep(const G4Step* step) { - const G4Track* track = step->GetTrack(); - - TRestGeant4Metadata* metadata = GetGeant4Metadata(); - - const auto& geometryInfo = metadata->GetGeant4GeometryInfo(); - - const auto& volumeNameGeant4 = step->GetPreStepPoint()->GetPhysicalVolume()->GetName(); - const auto& volumeName = geometryInfo.GetAlternativeNameFromGeant4PhysicalName(volumeNameGeant4); - - if (!metadata->IsActiveVolume(volumeName) && step->GetTrack()->GetCurrentStepNumber() != 0) { - // we always store the first step - return; - } - - const auto& particle = step->GetTrack()->GetDefinition(); - const auto& particleID = particle->GetPDGEncoding(); - const auto& particleName = particle->GetParticleName(); - - metadata->fGeant4PhysicsInfo.InsertParticleName(particleID, particleName); - - const auto process = step->GetPostStepPoint()->GetProcessDefinedStep(); - G4String processName = "Init"; - G4String processTypeName = "Init"; - Int_t processID = 0; - if (track->GetCurrentStepNumber() != 0) { - // 0 = Init step (G4SteppingVerbose) process is not defined for this step - processName = process->GetProcessName(); - processTypeName = G4VProcess::GetProcessTypeName(process->GetProcessType()); - processID = TRestGeant4PhysicsInfo::GetProcessIDFromGeant4Process(process); - } - - metadata->fGeant4PhysicsInfo.InsertProcessName(processID, processName, processTypeName); - - const auto energy = step->GetTotalEnergyDeposit() / CLHEP::keV; - const auto trackKineticEnergy = step->GetTrack()->GetKineticEnergy() / CLHEP::keV; - - auto sensitiveVolumeName = - geometryInfo.GetAlternativeNameFromGeant4PhysicalName(metadata->GetSensitiveVolume()); - - G4Track* aTrack = step->GetTrack(); - - Double_t x = aTrack->GetPosition().x() / CLHEP::mm; - Double_t y = aTrack->GetPosition().y() / CLHEP::mm; - Double_t z = aTrack->GetPosition().z() / CLHEP::mm; - - const TVector3 hitPosition(x, y, z); - const Double_t hitGlobalTime = step->GetPreStepPoint()->GetGlobalTime() / CLHEP::microsecond; - const G4ThreeVector& momentum = step->GetPreStepPoint()->GetMomentumDirection(); - - AddHit(hitPosition, energy, hitGlobalTime); // this increases fNHits - - fProcessID.emplace_back(processID); - fVolumeID.emplace_back(geometryInfo.GetIDFromVolume(volumeName)); - fKineticEnergy.emplace_back(step->GetPreStepPoint()->GetKineticEnergy() / CLHEP::keV); - fMomentumDirection.emplace_back(momentum.x(), momentum.y(), momentum.z()); - - SimulationManager::GetOutputManager()->AddEnergyToVolumeForParticleForProcess(energy, volumeName, - particleName, processName); -} - -void OutputManager::RemoveUnwantedTracks() { - const auto& metadata = fSimulationManager->GetRestMetadata(); - set trackIDsToKeep; // We populate this container with the tracks we want to keep - for (const auto& track : fEvent->fTracks) { - // If one children track is kept, we keep all the parents - if (trackIDsToKeep.count(track.GetTrackID()) > 0) { - continue; - } - const auto hits = track.GetHits(); - for (int i = 0; i < int(hits.GetNumberOfHits()); i++) { - const auto energy = hits.GetEnergy(i); - if (!fSimulationManager->GetRestMetadata()->GetRemoveUnwantedTracksKeepZeroEnergyTracks() && - energy <= 0) { - continue; - } - const auto volume = metadata->GetGeant4GeometryInfo().GetVolumeFromID(hits.GetVolumeId(i)); - if (metadata->IsKeepTracksVolume(volume)) { - trackIDsToKeep.insert(track.GetTrackID()); - auto parentTrack = track.GetParentTrack(); - while (parentTrack != nullptr) { - trackIDsToKeep.insert(parentTrack->GetTrackID()); - parentTrack = parentTrack->GetParentTrack(); - } - } - } - } - const size_t numberOfTracksBefore = fEvent->fTracks.size(); - - vector tracksAfterRemoval; - for (const auto& track : fEvent->fTracks) { - // we do this to preserve original order - if (trackIDsToKeep.count(track.GetTrackID()) > 0) { - tracksAfterRemoval.push_back(*(fEvent->GetTrackByID(track.GetTrackID()))); - } - } - - fEvent->fTracks = tracksAfterRemoval; - - // Updated indices - fEvent->fTrackIDToTrackIndex.clear(); - for (int i = 0; i < int(fEvent->fTracks.size()); i++) { - fEvent->fTrackIDToTrackIndex[fEvent->fTracks[i].GetTrackID()] = i; - } - - /* - const size_t numberOfTracksAfter = fEvent->fTracks.size(); - cout << "EventID: " << fEvent->GetID() << " Removed " << numberOfTracksBefore - numberOfTracksAfter - << " tracks out of " << numberOfTracksBefore << endl; - */ -} \ No newline at end of file From ed9b0b4e277d7ee762fb57909d74547244cff42c Mon Sep 17 00:00:00 2001 From: lobis Date: Mon, 12 Sep 2022 17:10:44 +0200 Subject: [PATCH 159/173] renamed "Desired" to "Requested" --- include/Application.h | 2 +- src/Application.cxx | 23 +++++++---------------- src/RunAction.cxx | 6 +++--- src/SimulationManager.cxx | 8 ++++---- test/src/examples.cxx | 2 +- 5 files changed, 16 insertions(+), 25 deletions(-) diff --git a/include/Application.h b/include/Application.h index ad311354..0b002d64 100644 --- a/include/Application.h +++ b/include/Application.h @@ -23,7 +23,7 @@ struct Options { int nEvents = 0; Long_t seed = 0; - int nDesiredEntries = 0; + int nRequestedEntries = 0; int timeLimitSeconds = 0; // reference to original argc and argv necessary to pass to G4UIExecutive diff --git a/src/Application.cxx b/src/Application.cxx index 6a95edd1..f8d0c9f0 100644 --- a/src/Application.cxx +++ b/src/Application.cxx @@ -2,30 +2,22 @@ #include "Application.h" #include -#include -#include -#include #include #include #include #include #include -#include #include #include -#include #include -#include #include #ifndef GEANT4_WITHOUT_G4RunManagerFactory #include #endif #include #include -#include #include -#include #include #include "ActionInitialization.h" @@ -37,7 +29,6 @@ #include "SimulationManager.h" #include "SteppingAction.h" #include "SteppingVerbose.h" -#include "TrackingAction.h" #ifdef G4VIS_USE #include "G4VisExecutive.hh" @@ -60,7 +51,7 @@ void ShowUsage() { << "\t--events (-n) nEvents | specify number of events to be processed (overrides nEvents on rml " "file)" << endl - << "\t--entries (-e) | specify the desired number of entries. The simulation will stop after " + << "\t--entries (-e) | specify the requested number of entries. The simulation will stop after " "reaching this number of saved events. Final number may be larger" << endl << "\t--time timeLimit | Sets time limit for the simulation in the format '1h20m30s', '5m20s', " @@ -87,8 +78,8 @@ void PrintOptions(const Options& options) { << (options.nEvents != 0 ? "\t- Number of generated events: " + to_string(options.nEvents) + "\n" : "") << (options.seed != 0 ? "\t- Random seed: " + to_string(options.seed) + "\n" : "") - << (options.nDesiredEntries != 0 - ? "\t- Number of desired entries: " + to_string(options.nDesiredEntries) + "\n" + << (options.nRequestedEntries != 0 + ? "\t- Number of requested entries: " + to_string(options.nRequestedEntries) + "\n" : "") << (options.timeLimitSeconds != 0 ? "\t- Time limit: " + to_string(options.timeLimitSeconds) + " seconds\n" @@ -205,9 +196,9 @@ Options ProcessCommandLineOptions(int argc, char* const argv[]) { } } else if ((arg == "-e") || (arg == "--entries")) { if (i + 1 < argc) { // Make sure we aren't at the end of argv! - options.nDesiredEntries = + options.nRequestedEntries = stoi(argv[++i]); // Increment 'i' so we don't get the argument as the next argv[i]. - if (options.nDesiredEntries <= 0) { + if (options.nRequestedEntries <= 0) { cout << "--entries option error: number of entries must be > 0" << endl; exit(1); } @@ -315,8 +306,8 @@ void Application::Run(const CommandLineOptions::Options& options) { if (metadata->GetNumberOfEvents() == 0) { metadata->SetNumberOfEvents(maxPrimariesAllowed); } - if (options.nDesiredEntries != 0) { - metadata->SetNumberOfDesiredEntries(options.nDesiredEntries); + if (options.nRequestedEntries != 0) { + metadata->SetNumberOfRequestedEntries(options.nRequestedEntries); } if (options.timeLimitSeconds != 0) { metadata->SetSimulationMaxTimeSeconds(options.timeLimitSeconds); diff --git a/src/RunAction.cxx b/src/RunAction.cxx index 094c8cf3..2f1b7daa 100644 --- a/src/RunAction.cxx +++ b/src/RunAction.cxx @@ -53,11 +53,11 @@ void RunAction::EndOfRunAction(const G4Run*) { } // Sanity check - if (metadata->GetNumberOfDesiredEntries() == 0 && metadata->GetSimulationMaxTimeSeconds() == 0 && + if (metadata->GetNumberOfRequestedEntries() == 0 && metadata->GetSimulationMaxTimeSeconds() == 0 && metadata->GetNumberOfEvents() != G4RunManager::GetRunManager()->GetNumberOfEventsToBeProcessed()) { cerr << "FATAL ERROR: possible error when calculating number of processed events, please check " - "'RunAction::EndOfRunAction'" - << endl; + "'RunAction::EndOfRunAction'" + << endl; exit(1); } } diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index 584f9dbc..7162a626 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -129,10 +129,10 @@ void SimulationManager::WriteEvents() { fEventContainer.pop(); } - const auto nDesiredEntries = GetRestMetadata()->GetNumberOfDesiredEntries(); - if (nDesiredEntries > 0 && !fAbortFlag && fRestRun->GetEventTree()->GetEntries() >= nDesiredEntries) { - G4cout << "Stopping Run! We have reached the number of desired entries (" << nDesiredEntries << ")" - << endl; + const auto nRequestedEntries = GetRestMetadata()->GetNumberOfRequestedEntries(); + if (nRequestedEntries > 0 && !fAbortFlag && fRestRun->GetEventTree()->GetEntries() >= nRequestedEntries) { + G4cout << "Stopping Run! We have reached the number of requested entries (" << nRequestedEntries + << ")" << endl; StopSimulation(); } } diff --git a/test/src/examples.cxx b/test/src/examples.cxx index 3c164cb1..3f39b31b 100644 --- a/test/src/examples.cxx +++ b/test/src/examples.cxx @@ -374,7 +374,7 @@ TEST(restG4, Example_13_IAXO) { CommandLineOptions::Options options; options.rmlFile = "Neutrons.rml"; options.outputFile = thisExamplePath / "Neutrons.root"; - options.nDesiredEntries = 1; + options.nRequestedEntries = 1; Application app; app.Run(options); From 19223f3743118ecd3e03e82295f9693dae08b0dc Mon Sep 17 00:00:00 2001 From: lobis Date: Mon, 12 Sep 2022 17:16:37 +0200 Subject: [PATCH 160/173] made periodic print thread unique_ptr --- include/SimulationManager.h | 2 +- src/SimulationManager.cxx | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/include/SimulationManager.h b/include/SimulationManager.h index cc9973e6..a0594854 100644 --- a/include/SimulationManager.h +++ b/include/SimulationManager.h @@ -28,7 +28,7 @@ class SimulationManager { void WriteEvents(); void WriteEventsAndCloseFile(); - std::thread* fPeriodicPrintThread = nullptr; + std::unique_ptr fPeriodicPrintThread = nullptr; bool fPeriodicPrintThreadEndFlag = false; public: diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index 7162a626..9bc4776f 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -60,7 +60,7 @@ void SimulationManager::BeginOfRunAction() { // gives segfault in old Geant4 versions such as 10.4.3, didn't look into it if (GetRestMetadata()->PrintProgress() || GetRestMetadata()->GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Essential) { - fPeriodicPrintThread = new thread(&PeriodicPrint, this); + fPeriodicPrintThread = make_unique(&PeriodicPrint, this); } #endif } @@ -78,7 +78,6 @@ void SimulationManager::EndOfRunAction() { if (fPeriodicPrintThread->joinable()) { fPeriodicPrintThread->join(); // need to join thread, it may block for up to 1 thread period } - delete fPeriodicPrintThread; } for (auto& outputManager : fOutputManagerContainer) { From d6e7c81831ee69d5e0e7563ddec04ff3c8f0e230 Mon Sep 17 00:00:00 2001 From: lobis Date: Mon, 12 Sep 2022 17:31:40 +0200 Subject: [PATCH 161/173] attempt to fix pipeline --- src/DataModel.cxx | 254 -------------------------------------- src/SimulationManager.cxx | 245 ++++++++++++++++++++++++++++++++++++ 2 files changed, 245 insertions(+), 254 deletions(-) delete mode 100644 src/DataModel.cxx diff --git a/src/DataModel.cxx b/src/DataModel.cxx deleted file mode 100644 index 6c07626f..00000000 --- a/src/DataModel.cxx +++ /dev/null @@ -1,254 +0,0 @@ - -#include -#include -#include -#include -#include - -#include "SimulationManager.h" -#include "SteppingAction.h" - -using namespace std; - -TRestGeant4Event::TRestGeant4Event(const G4Event* event) : TRestGeant4Event() { - SetID(event->GetEventID()); - SetOK(true); - time_t system_time = time(nullptr); - - SetTime((Double_t)system_time); - - auto primaryVertex = event->GetPrimaryVertex(); - const auto& position = primaryVertex->GetPosition(); - fPrimaryPosition = {position.x() / CLHEP::mm, position.y() / CLHEP::mm, position.z() / CLHEP::mm}; - for (int i = 0; i < primaryVertex->GetNumberOfParticle(); i++) { - const auto& primaryParticle = primaryVertex->GetPrimary(i); - fPrimaryParticleNames.emplace_back(primaryParticle->GetParticleDefinition()->GetParticleName()); - fPrimaryEnergies.emplace_back(primaryParticle->GetKineticEnergy() / CLHEP::keV); - const auto& momentum = primaryParticle->GetMomentumDirection(); - fPrimaryDirections.emplace_back(momentum.x(), momentum.y(), momentum.z()); - } - - // TODO: move this - // Defining if the hits in a given volume will be stored - const auto metadata = GetGeant4Metadata(); - if (metadata != nullptr) { - for (int i = 0; i < metadata->GetNumberOfActiveVolumes(); i++) { - if (metadata->GetStorageChance(i) >= 1.00) { - ActivateVolumeForStorage(i); - } else { - Double_t randomNumber = G4UniformRand(); - if (metadata->GetStorageChance(i) >= randomNumber) { - ActivateVolumeForStorage(i); - } else { - DisableVolumeForStorage(i); - } - } - } - } -} - -bool TRestGeant4Event::InsertTrack(const G4Track* track) { - if (fInitialStep.GetNumberOfHits() != 1) { - cout << "fInitialStep does not have exactly one step! Problem with stepping verbose" << endl; - exit(1); - } - - if (fTracks.empty() && IsSubEvent()) { - // First track of sub-event (primary) - fSubEventPrimaryParticleName = track->GetParticleDefinition()->GetParticleName(); - fSubEventPrimaryEnergy = track->GetKineticEnergy() / CLHEP::keV; - const auto& position = track->GetPosition(); - fSubEventPrimaryPosition = {position.x() / CLHEP::mm, position.y() / CLHEP::mm, - position.z() / CLHEP::mm}; - const auto& momentum = track->GetMomentumDirection(); - fSubEventPrimaryDirection = {momentum.x(), momentum.y(), momentum.z()}; - } - - fTrackIDToTrackIndex[track->GetTrackID()] = int(fTracks.size()); // before insertion - - fTracks.emplace_back(track); - - auto& insertedTrack = fTracks.back(); - - insertedTrack.SetHits(fInitialStep); - insertedTrack.SetEvent(this); - - TRestGeant4Track* parentTrack = GetTrackByID(track->GetParentID()); - if (parentTrack) { - parentTrack->AddSecondaryTrackID(track->GetTrackID()); - } - - return true; -} - -void TRestGeant4Event::UpdateTrack(const G4Track* track) { fTracks.back().UpdateTrack(track); } - -void TRestGeant4Event::InsertStep(const G4Step* step) { - if (step->GetTrack()->GetCurrentStepNumber() == 0) { - // initial step (from SteppingVerbose) is generated before TrackingAction can insert the first track - fInitialStep = TRestGeant4Hits(); - fInitialStep.SetEvent(this); - fInitialStep.InsertStep(step); - } else { - fTracks.back().InsertStep(step); - } -} - -bool OutputManager::IsValidTrack(const G4Track*) const { return true; } - -bool OutputManager::IsValidStep(const G4Step*) const { return true; } - -TRestGeant4Track::TRestGeant4Track(const G4Track* track) : TRestGeant4Track() { - fTrackID = track->GetTrackID(); - fParentID = track->GetParentID(); - - auto particle = track->GetParticleDefinition(); - fParticleName = particle->GetParticleName(); - /* - fParticleID = particle->GetPDGEncoding(); - fParticleType = particle->GetParticleType(); - fParticleSubType = particle->GetParticleSubType(); - */ - if (track->GetCreatorProcess() != nullptr) { - fCreatorProcess = track->GetCreatorProcess()->GetProcessName(); - } else { - fCreatorProcess = "PrimaryGenerator"; - } - - fInitialKineticEnergy = track->GetKineticEnergy() / CLHEP::keV; - - fWeight = track->GetWeight(); - - fGlobalTimestamp = track->GetGlobalTime() / CLHEP::microsecond; - - const G4ThreeVector& trackOrigin = track->GetPosition(); - fInitialPosition = {trackOrigin.x(), trackOrigin.y(), trackOrigin.z()}; -} - -void TRestGeant4Track::InsertStep(const G4Step* step) { fHits.InsertStep(step); } - -void TRestGeant4Track::UpdateTrack(const G4Track* track) { - if (track->GetTrackID() != fTrackID) { - G4cout << "Geant4Track::UpdateTrack - mismatch of trackID!" << endl; - exit(1); - } - - fLength = track->GetTrackLength() / CLHEP::mm; - fTimeLength = track->GetGlobalTime() / CLHEP::microsecond - fGlobalTimestamp; -} - -Int_t TRestGeant4PhysicsInfo::GetProcessIDFromGeant4Process(const G4VProcess* process) { - return process->GetProcessType() * 1000 + process->GetProcessSubType(); -} - -void TRestGeant4Hits::InsertStep(const G4Step* step) { - const G4Track* track = step->GetTrack(); - - TRestGeant4Metadata* metadata = GetGeant4Metadata(); - - const auto& geometryInfo = metadata->GetGeant4GeometryInfo(); - - const auto& volumeNameGeant4 = step->GetPreStepPoint()->GetPhysicalVolume()->GetName(); - const auto& volumeName = geometryInfo.GetAlternativeNameFromGeant4PhysicalName(volumeNameGeant4); - - if (!metadata->IsActiveVolume(volumeName) && step->GetTrack()->GetCurrentStepNumber() != 0) { - // we always store the first step - return; - } - - const auto& particle = step->GetTrack()->GetDefinition(); - const auto& particleID = particle->GetPDGEncoding(); - const auto& particleName = particle->GetParticleName(); - - metadata->fGeant4PhysicsInfo.InsertParticleName(particleID, particleName); - - const auto process = step->GetPostStepPoint()->GetProcessDefinedStep(); - G4String processName = "Init"; - G4String processTypeName = "Init"; - Int_t processID = 0; - if (track->GetCurrentStepNumber() != 0) { - // 0 = Init step (G4SteppingVerbose) process is not defined for this step - processName = process->GetProcessName(); - processTypeName = G4VProcess::GetProcessTypeName(process->GetProcessType()); - processID = TRestGeant4PhysicsInfo::GetProcessIDFromGeant4Process(process); - } - - metadata->fGeant4PhysicsInfo.InsertProcessName(processID, processName, processTypeName); - - const auto energy = step->GetTotalEnergyDeposit() / CLHEP::keV; - const auto trackKineticEnergy = step->GetTrack()->GetKineticEnergy() / CLHEP::keV; - - auto sensitiveVolumeName = - geometryInfo.GetAlternativeNameFromGeant4PhysicalName(metadata->GetSensitiveVolume()); - - G4Track* aTrack = step->GetTrack(); - - Double_t x = aTrack->GetPosition().x() / CLHEP::mm; - Double_t y = aTrack->GetPosition().y() / CLHEP::mm; - Double_t z = aTrack->GetPosition().z() / CLHEP::mm; - - const TVector3 hitPosition(x, y, z); - const Double_t hitGlobalTime = step->GetPreStepPoint()->GetGlobalTime() / CLHEP::microsecond; - const G4ThreeVector& momentum = step->GetPreStepPoint()->GetMomentumDirection(); - - AddHit(hitPosition, energy, hitGlobalTime); // this increases fNHits - - fProcessID.emplace_back(processID); - fVolumeID.emplace_back(geometryInfo.GetIDFromVolume(volumeName)); - fKineticEnergy.emplace_back(step->GetPreStepPoint()->GetKineticEnergy() / CLHEP::keV); - fMomentumDirection.emplace_back(momentum.x(), momentum.y(), momentum.z()); - - SimulationManager::GetOutputManager()->AddEnergyToVolumeForParticleForProcess(energy, volumeName, - particleName, processName); -} - -void OutputManager::RemoveUnwantedTracks() { - const auto& metadata = fSimulationManager->GetRestMetadata(); - set trackIDsToKeep; // We populate this container with the tracks we want to keep - for (const auto& track : fEvent->fTracks) { - // If one children track is kept, we keep all the parents - if (trackIDsToKeep.count(track.GetTrackID()) > 0) { - continue; - } - const auto hits = track.GetHits(); - for (int i = 0; i < int(hits.GetNumberOfHits()); i++) { - const auto energy = hits.GetEnergy(i); - if (!fSimulationManager->GetRestMetadata()->GetRemoveUnwantedTracksKeepZeroEnergyTracks() && - energy <= 0) { - continue; - } - const auto volume = metadata->GetGeant4GeometryInfo().GetVolumeFromID(hits.GetVolumeId(i)); - if (metadata->IsKeepTracksVolume(volume)) { - trackIDsToKeep.insert(track.GetTrackID()); - auto parentTrack = track.GetParentTrack(); - while (parentTrack != nullptr) { - trackIDsToKeep.insert(parentTrack->GetTrackID()); - parentTrack = parentTrack->GetParentTrack(); - } - } - } - } - const size_t numberOfTracksBefore = fEvent->fTracks.size(); - - vector tracksAfterRemoval; - for (const auto& track : fEvent->fTracks) { - // we do this to preserve original order - if (trackIDsToKeep.count(track.GetTrackID()) > 0) { - tracksAfterRemoval.push_back(*(fEvent->GetTrackByID(track.GetTrackID()))); - } - } - - fEvent->fTracks = tracksAfterRemoval; - - // Updated indices - fEvent->fTrackIDToTrackIndex.clear(); - for (int i = 0; i < int(fEvent->fTracks.size()); i++) { - fEvent->fTrackIDToTrackIndex[fEvent->fTracks[i].GetTrackID()] = i; - } - - /* - const size_t numberOfTracksAfter = fEvent->fTracks.size(); - cout << "EventID: " << fEvent->GetID() << " Removed " << numberOfTracksBefore - numberOfTracksAfter - << " tracks out of " << numberOfTracksBefore << endl; - */ -} diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index 9bc4776f..5c6569fb 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -306,3 +306,248 @@ void OutputManager::AddEnergyToVolumeForParticleForProcess(Double_t energy, cons const char* processName) { fEvent->AddEnergyInVolumeForParticleForProcess(energy, volumeName, particleName, processName); } + +// Geant4lib + +TRestGeant4Event::TRestGeant4Event(const G4Event* event) : TRestGeant4Event() { + SetID(event->GetEventID()); + SetOK(true); + time_t system_time = time(nullptr); + + SetTime((Double_t)system_time); + + auto primaryVertex = event->GetPrimaryVertex(); + const auto& position = primaryVertex->GetPosition(); + fPrimaryPosition = {position.x() / CLHEP::mm, position.y() / CLHEP::mm, position.z() / CLHEP::mm}; + for (int i = 0; i < primaryVertex->GetNumberOfParticle(); i++) { + const auto& primaryParticle = primaryVertex->GetPrimary(i); + fPrimaryParticleNames.emplace_back(primaryParticle->GetParticleDefinition()->GetParticleName()); + fPrimaryEnergies.emplace_back(primaryParticle->GetKineticEnergy() / CLHEP::keV); + const auto& momentum = primaryParticle->GetMomentumDirection(); + fPrimaryDirections.emplace_back(momentum.x(), momentum.y(), momentum.z()); + } + + // TODO: move this + // Defining if the hits in a given volume will be stored + const auto metadata = GetGeant4Metadata(); + if (metadata != nullptr) { + for (int i = 0; i < metadata->GetNumberOfActiveVolumes(); i++) { + if (metadata->GetStorageChance(i) >= 1.00) { + ActivateVolumeForStorage(i); + } else { + Double_t randomNumber = G4UniformRand(); + if (metadata->GetStorageChance(i) >= randomNumber) { + ActivateVolumeForStorage(i); + } else { + DisableVolumeForStorage(i); + } + } + } + } +} + +bool TRestGeant4Event::InsertTrack(const G4Track* track) { + if (fInitialStep.GetNumberOfHits() != 1) { + cout << "fInitialStep does not have exactly one step! Problem with stepping verbose" << endl; + exit(1); + } + + if (fTracks.empty() && IsSubEvent()) { + // First track of sub-event (primary) + fSubEventPrimaryParticleName = track->GetParticleDefinition()->GetParticleName(); + fSubEventPrimaryEnergy = track->GetKineticEnergy() / CLHEP::keV; + const auto& position = track->GetPosition(); + fSubEventPrimaryPosition = {position.x() / CLHEP::mm, position.y() / CLHEP::mm, + position.z() / CLHEP::mm}; + const auto& momentum = track->GetMomentumDirection(); + fSubEventPrimaryDirection = {momentum.x(), momentum.y(), momentum.z()}; + } + + fTrackIDToTrackIndex[track->GetTrackID()] = int(fTracks.size()); // before insertion + + fTracks.emplace_back(track); + + auto& insertedTrack = fTracks.back(); + + insertedTrack.SetHits(fInitialStep); + insertedTrack.SetEvent(this); + + TRestGeant4Track* parentTrack = GetTrackByID(track->GetParentID()); + if (parentTrack) { + parentTrack->AddSecondaryTrackID(track->GetTrackID()); + } + + return true; +} + +void TRestGeant4Event::UpdateTrack(const G4Track* track) { fTracks.back().UpdateTrack(track); } + +void TRestGeant4Event::InsertStep(const G4Step* step) { + if (step->GetTrack()->GetCurrentStepNumber() == 0) { + // initial step (from SteppingVerbose) is generated before TrackingAction can insert the first track + fInitialStep = TRestGeant4Hits(); + fInitialStep.SetEvent(this); + fInitialStep.InsertStep(step); + } else { + fTracks.back().InsertStep(step); + } +} + +bool OutputManager::IsValidTrack(const G4Track*) const { return true; } + +bool OutputManager::IsValidStep(const G4Step*) const { return true; } + +TRestGeant4Track::TRestGeant4Track(const G4Track* track) : TRestGeant4Track() { + fTrackID = track->GetTrackID(); + fParentID = track->GetParentID(); + + auto particle = track->GetParticleDefinition(); + fParticleName = particle->GetParticleName(); + /* + fParticleID = particle->GetPDGEncoding(); + fParticleType = particle->GetParticleType(); + fParticleSubType = particle->GetParticleSubType(); + */ + if (track->GetCreatorProcess() != nullptr) { + fCreatorProcess = track->GetCreatorProcess()->GetProcessName(); + } else { + fCreatorProcess = "PrimaryGenerator"; + } + + fInitialKineticEnergy = track->GetKineticEnergy() / CLHEP::keV; + + fWeight = track->GetWeight(); + + fGlobalTimestamp = track->GetGlobalTime() / CLHEP::microsecond; + + const G4ThreeVector& trackOrigin = track->GetPosition(); + fInitialPosition = {trackOrigin.x(), trackOrigin.y(), trackOrigin.z()}; +} + +void TRestGeant4Track::InsertStep(const G4Step* step) { fHits.InsertStep(step); } + +void TRestGeant4Track::UpdateTrack(const G4Track* track) { + if (track->GetTrackID() != fTrackID) { + G4cout << "Geant4Track::UpdateTrack - mismatch of trackID!" << endl; + exit(1); + } + + fLength = track->GetTrackLength() / CLHEP::mm; + fTimeLength = track->GetGlobalTime() / CLHEP::microsecond - fGlobalTimestamp; +} + +Int_t TRestGeant4PhysicsInfo::GetProcessIDFromGeant4Process(const G4VProcess* process) { + return process->GetProcessType() * 1000 + process->GetProcessSubType(); +} + +void TRestGeant4Hits::InsertStep(const G4Step* step) { + const G4Track* track = step->GetTrack(); + + TRestGeant4Metadata* metadata = GetGeant4Metadata(); + + const auto& geometryInfo = metadata->GetGeant4GeometryInfo(); + + const auto& volumeNameGeant4 = step->GetPreStepPoint()->GetPhysicalVolume()->GetName(); + const auto& volumeName = geometryInfo.GetAlternativeNameFromGeant4PhysicalName(volumeNameGeant4); + + if (!metadata->IsActiveVolume(volumeName) && step->GetTrack()->GetCurrentStepNumber() != 0) { + // we always store the first step + return; + } + + const auto& particle = step->GetTrack()->GetDefinition(); + const auto& particleID = particle->GetPDGEncoding(); + const auto& particleName = particle->GetParticleName(); + + metadata->fGeant4PhysicsInfo.InsertParticleName(particleID, particleName); + + const auto process = step->GetPostStepPoint()->GetProcessDefinedStep(); + G4String processName = "Init"; + G4String processTypeName = "Init"; + Int_t processID = 0; + if (track->GetCurrentStepNumber() != 0) { + // 0 = Init step (G4SteppingVerbose) process is not defined for this step + processName = process->GetProcessName(); + processTypeName = G4VProcess::GetProcessTypeName(process->GetProcessType()); + processID = TRestGeant4PhysicsInfo::GetProcessIDFromGeant4Process(process); + } + + metadata->fGeant4PhysicsInfo.InsertProcessName(processID, processName, processTypeName); + + const auto energy = step->GetTotalEnergyDeposit() / CLHEP::keV; + const auto trackKineticEnergy = step->GetTrack()->GetKineticEnergy() / CLHEP::keV; + + auto sensitiveVolumeName = + geometryInfo.GetAlternativeNameFromGeant4PhysicalName(metadata->GetSensitiveVolume()); + + G4Track* aTrack = step->GetTrack(); + + Double_t x = aTrack->GetPosition().x() / CLHEP::mm; + Double_t y = aTrack->GetPosition().y() / CLHEP::mm; + Double_t z = aTrack->GetPosition().z() / CLHEP::mm; + + const TVector3 hitPosition(x, y, z); + const Double_t hitGlobalTime = step->GetPreStepPoint()->GetGlobalTime() / CLHEP::microsecond; + const G4ThreeVector& momentum = step->GetPreStepPoint()->GetMomentumDirection(); + + AddHit(hitPosition, energy, hitGlobalTime); // this increases fNHits + + fProcessID.emplace_back(processID); + fVolumeID.emplace_back(geometryInfo.GetIDFromVolume(volumeName)); + fKineticEnergy.emplace_back(step->GetPreStepPoint()->GetKineticEnergy() / CLHEP::keV); + fMomentumDirection.emplace_back(momentum.x(), momentum.y(), momentum.z()); + + SimulationManager::GetOutputManager()->AddEnergyToVolumeForParticleForProcess(energy, volumeName, + particleName, processName); +} + +void OutputManager::RemoveUnwantedTracks() { + const auto& metadata = fSimulationManager->GetRestMetadata(); + set trackIDsToKeep; // We populate this container with the tracks we want to keep + for (const auto& track : fEvent->fTracks) { + // If one children track is kept, we keep all the parents + if (trackIDsToKeep.count(track.GetTrackID()) > 0) { + continue; + } + const auto hits = track.GetHits(); + for (int i = 0; i < int(hits.GetNumberOfHits()); i++) { + const auto energy = hits.GetEnergy(i); + if (!fSimulationManager->GetRestMetadata()->GetRemoveUnwantedTracksKeepZeroEnergyTracks() && + energy <= 0) { + continue; + } + const auto volume = metadata->GetGeant4GeometryInfo().GetVolumeFromID(hits.GetVolumeId(i)); + if (metadata->IsKeepTracksVolume(volume)) { + trackIDsToKeep.insert(track.GetTrackID()); + auto parentTrack = track.GetParentTrack(); + while (parentTrack != nullptr) { + trackIDsToKeep.insert(parentTrack->GetTrackID()); + parentTrack = parentTrack->GetParentTrack(); + } + } + } + } + const size_t numberOfTracksBefore = fEvent->fTracks.size(); + + vector tracksAfterRemoval; + for (const auto& track : fEvent->fTracks) { + // we do this to preserve original order + if (trackIDsToKeep.count(track.GetTrackID()) > 0) { + tracksAfterRemoval.push_back(*(fEvent->GetTrackByID(track.GetTrackID()))); + } + } + + fEvent->fTracks = tracksAfterRemoval; + + // Updated indices + fEvent->fTrackIDToTrackIndex.clear(); + for (int i = 0; i < int(fEvent->fTracks.size()); i++) { + fEvent->fTrackIDToTrackIndex[fEvent->fTracks[i].GetTrackID()] = i; + } + + /* + const size_t numberOfTracksAfter = fEvent->fTracks.size(); + cout << "EventID: " << fEvent->GetID() << " Removed " << numberOfTracksBefore - numberOfTracksAfter + << " tracks out of " << numberOfTracksBefore << endl; + */ +} From 483cb20183e32797111025f0d8a8609d2206b8c4 Mon Sep 17 00:00:00 2001 From: lobis Date: Tue, 13 Sep 2022 12:00:56 +0200 Subject: [PATCH 162/173] Revert "attempt to fix pipeline" This reverts commit d6e7c81831ee69d5e0e7563ddec04ff3c8f0e230. --- src/DataModel.cxx | 254 ++++++++++++++++++++++++++++++++++++++ src/SimulationManager.cxx | 245 ------------------------------------ 2 files changed, 254 insertions(+), 245 deletions(-) create mode 100644 src/DataModel.cxx diff --git a/src/DataModel.cxx b/src/DataModel.cxx new file mode 100644 index 00000000..6c07626f --- /dev/null +++ b/src/DataModel.cxx @@ -0,0 +1,254 @@ + +#include +#include +#include +#include +#include + +#include "SimulationManager.h" +#include "SteppingAction.h" + +using namespace std; + +TRestGeant4Event::TRestGeant4Event(const G4Event* event) : TRestGeant4Event() { + SetID(event->GetEventID()); + SetOK(true); + time_t system_time = time(nullptr); + + SetTime((Double_t)system_time); + + auto primaryVertex = event->GetPrimaryVertex(); + const auto& position = primaryVertex->GetPosition(); + fPrimaryPosition = {position.x() / CLHEP::mm, position.y() / CLHEP::mm, position.z() / CLHEP::mm}; + for (int i = 0; i < primaryVertex->GetNumberOfParticle(); i++) { + const auto& primaryParticle = primaryVertex->GetPrimary(i); + fPrimaryParticleNames.emplace_back(primaryParticle->GetParticleDefinition()->GetParticleName()); + fPrimaryEnergies.emplace_back(primaryParticle->GetKineticEnergy() / CLHEP::keV); + const auto& momentum = primaryParticle->GetMomentumDirection(); + fPrimaryDirections.emplace_back(momentum.x(), momentum.y(), momentum.z()); + } + + // TODO: move this + // Defining if the hits in a given volume will be stored + const auto metadata = GetGeant4Metadata(); + if (metadata != nullptr) { + for (int i = 0; i < metadata->GetNumberOfActiveVolumes(); i++) { + if (metadata->GetStorageChance(i) >= 1.00) { + ActivateVolumeForStorage(i); + } else { + Double_t randomNumber = G4UniformRand(); + if (metadata->GetStorageChance(i) >= randomNumber) { + ActivateVolumeForStorage(i); + } else { + DisableVolumeForStorage(i); + } + } + } + } +} + +bool TRestGeant4Event::InsertTrack(const G4Track* track) { + if (fInitialStep.GetNumberOfHits() != 1) { + cout << "fInitialStep does not have exactly one step! Problem with stepping verbose" << endl; + exit(1); + } + + if (fTracks.empty() && IsSubEvent()) { + // First track of sub-event (primary) + fSubEventPrimaryParticleName = track->GetParticleDefinition()->GetParticleName(); + fSubEventPrimaryEnergy = track->GetKineticEnergy() / CLHEP::keV; + const auto& position = track->GetPosition(); + fSubEventPrimaryPosition = {position.x() / CLHEP::mm, position.y() / CLHEP::mm, + position.z() / CLHEP::mm}; + const auto& momentum = track->GetMomentumDirection(); + fSubEventPrimaryDirection = {momentum.x(), momentum.y(), momentum.z()}; + } + + fTrackIDToTrackIndex[track->GetTrackID()] = int(fTracks.size()); // before insertion + + fTracks.emplace_back(track); + + auto& insertedTrack = fTracks.back(); + + insertedTrack.SetHits(fInitialStep); + insertedTrack.SetEvent(this); + + TRestGeant4Track* parentTrack = GetTrackByID(track->GetParentID()); + if (parentTrack) { + parentTrack->AddSecondaryTrackID(track->GetTrackID()); + } + + return true; +} + +void TRestGeant4Event::UpdateTrack(const G4Track* track) { fTracks.back().UpdateTrack(track); } + +void TRestGeant4Event::InsertStep(const G4Step* step) { + if (step->GetTrack()->GetCurrentStepNumber() == 0) { + // initial step (from SteppingVerbose) is generated before TrackingAction can insert the first track + fInitialStep = TRestGeant4Hits(); + fInitialStep.SetEvent(this); + fInitialStep.InsertStep(step); + } else { + fTracks.back().InsertStep(step); + } +} + +bool OutputManager::IsValidTrack(const G4Track*) const { return true; } + +bool OutputManager::IsValidStep(const G4Step*) const { return true; } + +TRestGeant4Track::TRestGeant4Track(const G4Track* track) : TRestGeant4Track() { + fTrackID = track->GetTrackID(); + fParentID = track->GetParentID(); + + auto particle = track->GetParticleDefinition(); + fParticleName = particle->GetParticleName(); + /* + fParticleID = particle->GetPDGEncoding(); + fParticleType = particle->GetParticleType(); + fParticleSubType = particle->GetParticleSubType(); + */ + if (track->GetCreatorProcess() != nullptr) { + fCreatorProcess = track->GetCreatorProcess()->GetProcessName(); + } else { + fCreatorProcess = "PrimaryGenerator"; + } + + fInitialKineticEnergy = track->GetKineticEnergy() / CLHEP::keV; + + fWeight = track->GetWeight(); + + fGlobalTimestamp = track->GetGlobalTime() / CLHEP::microsecond; + + const G4ThreeVector& trackOrigin = track->GetPosition(); + fInitialPosition = {trackOrigin.x(), trackOrigin.y(), trackOrigin.z()}; +} + +void TRestGeant4Track::InsertStep(const G4Step* step) { fHits.InsertStep(step); } + +void TRestGeant4Track::UpdateTrack(const G4Track* track) { + if (track->GetTrackID() != fTrackID) { + G4cout << "Geant4Track::UpdateTrack - mismatch of trackID!" << endl; + exit(1); + } + + fLength = track->GetTrackLength() / CLHEP::mm; + fTimeLength = track->GetGlobalTime() / CLHEP::microsecond - fGlobalTimestamp; +} + +Int_t TRestGeant4PhysicsInfo::GetProcessIDFromGeant4Process(const G4VProcess* process) { + return process->GetProcessType() * 1000 + process->GetProcessSubType(); +} + +void TRestGeant4Hits::InsertStep(const G4Step* step) { + const G4Track* track = step->GetTrack(); + + TRestGeant4Metadata* metadata = GetGeant4Metadata(); + + const auto& geometryInfo = metadata->GetGeant4GeometryInfo(); + + const auto& volumeNameGeant4 = step->GetPreStepPoint()->GetPhysicalVolume()->GetName(); + const auto& volumeName = geometryInfo.GetAlternativeNameFromGeant4PhysicalName(volumeNameGeant4); + + if (!metadata->IsActiveVolume(volumeName) && step->GetTrack()->GetCurrentStepNumber() != 0) { + // we always store the first step + return; + } + + const auto& particle = step->GetTrack()->GetDefinition(); + const auto& particleID = particle->GetPDGEncoding(); + const auto& particleName = particle->GetParticleName(); + + metadata->fGeant4PhysicsInfo.InsertParticleName(particleID, particleName); + + const auto process = step->GetPostStepPoint()->GetProcessDefinedStep(); + G4String processName = "Init"; + G4String processTypeName = "Init"; + Int_t processID = 0; + if (track->GetCurrentStepNumber() != 0) { + // 0 = Init step (G4SteppingVerbose) process is not defined for this step + processName = process->GetProcessName(); + processTypeName = G4VProcess::GetProcessTypeName(process->GetProcessType()); + processID = TRestGeant4PhysicsInfo::GetProcessIDFromGeant4Process(process); + } + + metadata->fGeant4PhysicsInfo.InsertProcessName(processID, processName, processTypeName); + + const auto energy = step->GetTotalEnergyDeposit() / CLHEP::keV; + const auto trackKineticEnergy = step->GetTrack()->GetKineticEnergy() / CLHEP::keV; + + auto sensitiveVolumeName = + geometryInfo.GetAlternativeNameFromGeant4PhysicalName(metadata->GetSensitiveVolume()); + + G4Track* aTrack = step->GetTrack(); + + Double_t x = aTrack->GetPosition().x() / CLHEP::mm; + Double_t y = aTrack->GetPosition().y() / CLHEP::mm; + Double_t z = aTrack->GetPosition().z() / CLHEP::mm; + + const TVector3 hitPosition(x, y, z); + const Double_t hitGlobalTime = step->GetPreStepPoint()->GetGlobalTime() / CLHEP::microsecond; + const G4ThreeVector& momentum = step->GetPreStepPoint()->GetMomentumDirection(); + + AddHit(hitPosition, energy, hitGlobalTime); // this increases fNHits + + fProcessID.emplace_back(processID); + fVolumeID.emplace_back(geometryInfo.GetIDFromVolume(volumeName)); + fKineticEnergy.emplace_back(step->GetPreStepPoint()->GetKineticEnergy() / CLHEP::keV); + fMomentumDirection.emplace_back(momentum.x(), momentum.y(), momentum.z()); + + SimulationManager::GetOutputManager()->AddEnergyToVolumeForParticleForProcess(energy, volumeName, + particleName, processName); +} + +void OutputManager::RemoveUnwantedTracks() { + const auto& metadata = fSimulationManager->GetRestMetadata(); + set trackIDsToKeep; // We populate this container with the tracks we want to keep + for (const auto& track : fEvent->fTracks) { + // If one children track is kept, we keep all the parents + if (trackIDsToKeep.count(track.GetTrackID()) > 0) { + continue; + } + const auto hits = track.GetHits(); + for (int i = 0; i < int(hits.GetNumberOfHits()); i++) { + const auto energy = hits.GetEnergy(i); + if (!fSimulationManager->GetRestMetadata()->GetRemoveUnwantedTracksKeepZeroEnergyTracks() && + energy <= 0) { + continue; + } + const auto volume = metadata->GetGeant4GeometryInfo().GetVolumeFromID(hits.GetVolumeId(i)); + if (metadata->IsKeepTracksVolume(volume)) { + trackIDsToKeep.insert(track.GetTrackID()); + auto parentTrack = track.GetParentTrack(); + while (parentTrack != nullptr) { + trackIDsToKeep.insert(parentTrack->GetTrackID()); + parentTrack = parentTrack->GetParentTrack(); + } + } + } + } + const size_t numberOfTracksBefore = fEvent->fTracks.size(); + + vector tracksAfterRemoval; + for (const auto& track : fEvent->fTracks) { + // we do this to preserve original order + if (trackIDsToKeep.count(track.GetTrackID()) > 0) { + tracksAfterRemoval.push_back(*(fEvent->GetTrackByID(track.GetTrackID()))); + } + } + + fEvent->fTracks = tracksAfterRemoval; + + // Updated indices + fEvent->fTrackIDToTrackIndex.clear(); + for (int i = 0; i < int(fEvent->fTracks.size()); i++) { + fEvent->fTrackIDToTrackIndex[fEvent->fTracks[i].GetTrackID()] = i; + } + + /* + const size_t numberOfTracksAfter = fEvent->fTracks.size(); + cout << "EventID: " << fEvent->GetID() << " Removed " << numberOfTracksBefore - numberOfTracksAfter + << " tracks out of " << numberOfTracksBefore << endl; + */ +} diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index 5c6569fb..9bc4776f 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -306,248 +306,3 @@ void OutputManager::AddEnergyToVolumeForParticleForProcess(Double_t energy, cons const char* processName) { fEvent->AddEnergyInVolumeForParticleForProcess(energy, volumeName, particleName, processName); } - -// Geant4lib - -TRestGeant4Event::TRestGeant4Event(const G4Event* event) : TRestGeant4Event() { - SetID(event->GetEventID()); - SetOK(true); - time_t system_time = time(nullptr); - - SetTime((Double_t)system_time); - - auto primaryVertex = event->GetPrimaryVertex(); - const auto& position = primaryVertex->GetPosition(); - fPrimaryPosition = {position.x() / CLHEP::mm, position.y() / CLHEP::mm, position.z() / CLHEP::mm}; - for (int i = 0; i < primaryVertex->GetNumberOfParticle(); i++) { - const auto& primaryParticle = primaryVertex->GetPrimary(i); - fPrimaryParticleNames.emplace_back(primaryParticle->GetParticleDefinition()->GetParticleName()); - fPrimaryEnergies.emplace_back(primaryParticle->GetKineticEnergy() / CLHEP::keV); - const auto& momentum = primaryParticle->GetMomentumDirection(); - fPrimaryDirections.emplace_back(momentum.x(), momentum.y(), momentum.z()); - } - - // TODO: move this - // Defining if the hits in a given volume will be stored - const auto metadata = GetGeant4Metadata(); - if (metadata != nullptr) { - for (int i = 0; i < metadata->GetNumberOfActiveVolumes(); i++) { - if (metadata->GetStorageChance(i) >= 1.00) { - ActivateVolumeForStorage(i); - } else { - Double_t randomNumber = G4UniformRand(); - if (metadata->GetStorageChance(i) >= randomNumber) { - ActivateVolumeForStorage(i); - } else { - DisableVolumeForStorage(i); - } - } - } - } -} - -bool TRestGeant4Event::InsertTrack(const G4Track* track) { - if (fInitialStep.GetNumberOfHits() != 1) { - cout << "fInitialStep does not have exactly one step! Problem with stepping verbose" << endl; - exit(1); - } - - if (fTracks.empty() && IsSubEvent()) { - // First track of sub-event (primary) - fSubEventPrimaryParticleName = track->GetParticleDefinition()->GetParticleName(); - fSubEventPrimaryEnergy = track->GetKineticEnergy() / CLHEP::keV; - const auto& position = track->GetPosition(); - fSubEventPrimaryPosition = {position.x() / CLHEP::mm, position.y() / CLHEP::mm, - position.z() / CLHEP::mm}; - const auto& momentum = track->GetMomentumDirection(); - fSubEventPrimaryDirection = {momentum.x(), momentum.y(), momentum.z()}; - } - - fTrackIDToTrackIndex[track->GetTrackID()] = int(fTracks.size()); // before insertion - - fTracks.emplace_back(track); - - auto& insertedTrack = fTracks.back(); - - insertedTrack.SetHits(fInitialStep); - insertedTrack.SetEvent(this); - - TRestGeant4Track* parentTrack = GetTrackByID(track->GetParentID()); - if (parentTrack) { - parentTrack->AddSecondaryTrackID(track->GetTrackID()); - } - - return true; -} - -void TRestGeant4Event::UpdateTrack(const G4Track* track) { fTracks.back().UpdateTrack(track); } - -void TRestGeant4Event::InsertStep(const G4Step* step) { - if (step->GetTrack()->GetCurrentStepNumber() == 0) { - // initial step (from SteppingVerbose) is generated before TrackingAction can insert the first track - fInitialStep = TRestGeant4Hits(); - fInitialStep.SetEvent(this); - fInitialStep.InsertStep(step); - } else { - fTracks.back().InsertStep(step); - } -} - -bool OutputManager::IsValidTrack(const G4Track*) const { return true; } - -bool OutputManager::IsValidStep(const G4Step*) const { return true; } - -TRestGeant4Track::TRestGeant4Track(const G4Track* track) : TRestGeant4Track() { - fTrackID = track->GetTrackID(); - fParentID = track->GetParentID(); - - auto particle = track->GetParticleDefinition(); - fParticleName = particle->GetParticleName(); - /* - fParticleID = particle->GetPDGEncoding(); - fParticleType = particle->GetParticleType(); - fParticleSubType = particle->GetParticleSubType(); - */ - if (track->GetCreatorProcess() != nullptr) { - fCreatorProcess = track->GetCreatorProcess()->GetProcessName(); - } else { - fCreatorProcess = "PrimaryGenerator"; - } - - fInitialKineticEnergy = track->GetKineticEnergy() / CLHEP::keV; - - fWeight = track->GetWeight(); - - fGlobalTimestamp = track->GetGlobalTime() / CLHEP::microsecond; - - const G4ThreeVector& trackOrigin = track->GetPosition(); - fInitialPosition = {trackOrigin.x(), trackOrigin.y(), trackOrigin.z()}; -} - -void TRestGeant4Track::InsertStep(const G4Step* step) { fHits.InsertStep(step); } - -void TRestGeant4Track::UpdateTrack(const G4Track* track) { - if (track->GetTrackID() != fTrackID) { - G4cout << "Geant4Track::UpdateTrack - mismatch of trackID!" << endl; - exit(1); - } - - fLength = track->GetTrackLength() / CLHEP::mm; - fTimeLength = track->GetGlobalTime() / CLHEP::microsecond - fGlobalTimestamp; -} - -Int_t TRestGeant4PhysicsInfo::GetProcessIDFromGeant4Process(const G4VProcess* process) { - return process->GetProcessType() * 1000 + process->GetProcessSubType(); -} - -void TRestGeant4Hits::InsertStep(const G4Step* step) { - const G4Track* track = step->GetTrack(); - - TRestGeant4Metadata* metadata = GetGeant4Metadata(); - - const auto& geometryInfo = metadata->GetGeant4GeometryInfo(); - - const auto& volumeNameGeant4 = step->GetPreStepPoint()->GetPhysicalVolume()->GetName(); - const auto& volumeName = geometryInfo.GetAlternativeNameFromGeant4PhysicalName(volumeNameGeant4); - - if (!metadata->IsActiveVolume(volumeName) && step->GetTrack()->GetCurrentStepNumber() != 0) { - // we always store the first step - return; - } - - const auto& particle = step->GetTrack()->GetDefinition(); - const auto& particleID = particle->GetPDGEncoding(); - const auto& particleName = particle->GetParticleName(); - - metadata->fGeant4PhysicsInfo.InsertParticleName(particleID, particleName); - - const auto process = step->GetPostStepPoint()->GetProcessDefinedStep(); - G4String processName = "Init"; - G4String processTypeName = "Init"; - Int_t processID = 0; - if (track->GetCurrentStepNumber() != 0) { - // 0 = Init step (G4SteppingVerbose) process is not defined for this step - processName = process->GetProcessName(); - processTypeName = G4VProcess::GetProcessTypeName(process->GetProcessType()); - processID = TRestGeant4PhysicsInfo::GetProcessIDFromGeant4Process(process); - } - - metadata->fGeant4PhysicsInfo.InsertProcessName(processID, processName, processTypeName); - - const auto energy = step->GetTotalEnergyDeposit() / CLHEP::keV; - const auto trackKineticEnergy = step->GetTrack()->GetKineticEnergy() / CLHEP::keV; - - auto sensitiveVolumeName = - geometryInfo.GetAlternativeNameFromGeant4PhysicalName(metadata->GetSensitiveVolume()); - - G4Track* aTrack = step->GetTrack(); - - Double_t x = aTrack->GetPosition().x() / CLHEP::mm; - Double_t y = aTrack->GetPosition().y() / CLHEP::mm; - Double_t z = aTrack->GetPosition().z() / CLHEP::mm; - - const TVector3 hitPosition(x, y, z); - const Double_t hitGlobalTime = step->GetPreStepPoint()->GetGlobalTime() / CLHEP::microsecond; - const G4ThreeVector& momentum = step->GetPreStepPoint()->GetMomentumDirection(); - - AddHit(hitPosition, energy, hitGlobalTime); // this increases fNHits - - fProcessID.emplace_back(processID); - fVolumeID.emplace_back(geometryInfo.GetIDFromVolume(volumeName)); - fKineticEnergy.emplace_back(step->GetPreStepPoint()->GetKineticEnergy() / CLHEP::keV); - fMomentumDirection.emplace_back(momentum.x(), momentum.y(), momentum.z()); - - SimulationManager::GetOutputManager()->AddEnergyToVolumeForParticleForProcess(energy, volumeName, - particleName, processName); -} - -void OutputManager::RemoveUnwantedTracks() { - const auto& metadata = fSimulationManager->GetRestMetadata(); - set trackIDsToKeep; // We populate this container with the tracks we want to keep - for (const auto& track : fEvent->fTracks) { - // If one children track is kept, we keep all the parents - if (trackIDsToKeep.count(track.GetTrackID()) > 0) { - continue; - } - const auto hits = track.GetHits(); - for (int i = 0; i < int(hits.GetNumberOfHits()); i++) { - const auto energy = hits.GetEnergy(i); - if (!fSimulationManager->GetRestMetadata()->GetRemoveUnwantedTracksKeepZeroEnergyTracks() && - energy <= 0) { - continue; - } - const auto volume = metadata->GetGeant4GeometryInfo().GetVolumeFromID(hits.GetVolumeId(i)); - if (metadata->IsKeepTracksVolume(volume)) { - trackIDsToKeep.insert(track.GetTrackID()); - auto parentTrack = track.GetParentTrack(); - while (parentTrack != nullptr) { - trackIDsToKeep.insert(parentTrack->GetTrackID()); - parentTrack = parentTrack->GetParentTrack(); - } - } - } - } - const size_t numberOfTracksBefore = fEvent->fTracks.size(); - - vector tracksAfterRemoval; - for (const auto& track : fEvent->fTracks) { - // we do this to preserve original order - if (trackIDsToKeep.count(track.GetTrackID()) > 0) { - tracksAfterRemoval.push_back(*(fEvent->GetTrackByID(track.GetTrackID()))); - } - } - - fEvent->fTracks = tracksAfterRemoval; - - // Updated indices - fEvent->fTrackIDToTrackIndex.clear(); - for (int i = 0; i < int(fEvent->fTracks.size()); i++) { - fEvent->fTrackIDToTrackIndex[fEvent->fTracks[i].GetTrackID()] = i; - } - - /* - const size_t numberOfTracksAfter = fEvent->fTracks.size(); - cout << "EventID: " << fEvent->GetID() << " Removed " << numberOfTracksBefore - numberOfTracksAfter - << " tracks out of " << numberOfTracksBefore << endl; - */ -} From ecd748f4787e2e97fb041a53aff8a8b1da5482f6 Mon Sep 17 00:00:00 2001 From: lobis Date: Tue, 13 Sep 2022 12:03:33 +0200 Subject: [PATCH 163/173] removed problematic code --- src/DataModel.cxx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/DataModel.cxx b/src/DataModel.cxx index 6c07626f..8ab3993a 100644 --- a/src/DataModel.cxx +++ b/src/DataModel.cxx @@ -28,6 +28,7 @@ TRestGeant4Event::TRestGeant4Event(const G4Event* event) : TRestGeant4Event() { fPrimaryDirections.emplace_back(momentum.x(), momentum.y(), momentum.z()); } + /* // TODO: move this // Defining if the hits in a given volume will be stored const auto metadata = GetGeant4Metadata(); @@ -45,6 +46,7 @@ TRestGeant4Event::TRestGeant4Event(const G4Event* event) : TRestGeant4Event() { } } } + */ } bool TRestGeant4Event::InsertTrack(const G4Track* track) { From 1dfa1ee9d9517a3f38dec0a3292b8608cd2a07c8 Mon Sep 17 00:00:00 2001 From: lobis Date: Tue, 13 Sep 2022 12:07:45 +0200 Subject: [PATCH 164/173] fix small mistake in print --- src/DataModel.cxx | 2 +- src/SimulationManager.cxx | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/DataModel.cxx b/src/DataModel.cxx index 8ab3993a..8423466a 100644 --- a/src/DataModel.cxx +++ b/src/DataModel.cxx @@ -197,7 +197,7 @@ void TRestGeant4Hits::InsertStep(const G4Step* step) { fProcessID.emplace_back(processID); fVolumeID.emplace_back(geometryInfo.GetIDFromVolume(volumeName)); - fKineticEnergy.emplace_back(step->GetPreStepPoint()->GetKineticEnergy() / CLHEP::keV); + fKineticEnergy.emplace_back(trackKineticEnergy); fMomentumDirection.emplace_back(momentum.x(), momentum.y(), momentum.z()); SimulationManager::GetOutputManager()->AddEnergyToVolumeForParticleForProcess(energy, volumeName, diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index 9bc4776f..27fcdc89 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -1,9 +1,7 @@ #include "SimulationManager.h" -#include #include -#include #include #include #include From 0d36aa326260e573cf92bd76ba4793702853d954 Mon Sep 17 00:00:00 2001 From: lobis Date: Tue, 13 Sep 2022 12:19:21 +0200 Subject: [PATCH 165/173] cleanup code for saving objects to file --- src/Application.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Application.cxx b/src/Application.cxx index f8d0c9f0..b93f58ec 100644 --- a/src/Application.cxx +++ b/src/Application.cxx @@ -494,7 +494,7 @@ void Application::WriteGeometry(TGeoManager* geometry, const char* filename, con cout << "Application::WriteGeometry - Error - Unable to write geometry into file" << endl; exit(1); } - geometry->Write(geometryName); + geometry->Write(geometryName, TObject::kWriteDelete); file->Close(); } From 03c12d95886f15830ad952ca32a08a0ecfab6e52 Mon Sep 17 00:00:00 2001 From: lobis Date: Tue, 13 Sep 2022 12:54:49 +0200 Subject: [PATCH 166/173] .gitlab-ci.yml - update decay value --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index a1100f33..7f412c43 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -124,7 +124,7 @@ Load REST Libraries: - cd ${CI_PROJECT_DIR}/install/examples/restG4/07.FullChainDecay/ - restG4 fullChain.rml - restG4 singleDecay.rml - - restRoot -b -q Validate.C'("Run00001_U238_FullChainDecay.root", 16)' + - restRoot -b -q Validate.C'("Run00001_U238_FullChainDecay.root", 17)' - restRoot -b -q Validate.C'("Run00002_U238_SingleChainDecay.root", 1)' - export REST_ISOTOPE="Be7" - restG4 singleDecay.rml From 1d0bf694036f1133df5c1e402d78a6810d46044b Mon Sep 17 00:00:00 2001 From: lobis Date: Tue, 13 Sep 2022 13:26:49 +0200 Subject: [PATCH 167/173] saving geometry earlier in run --- include/Application.h | 1 - src/Application.cxx | 31 ++++++++++++------------------- 2 files changed, 12 insertions(+), 20 deletions(-) diff --git a/include/Application.h b/include/Application.h index 0b002d64..0408982a 100644 --- a/include/Application.h +++ b/include/Application.h @@ -46,7 +46,6 @@ class Application { private: SimulationManager fSimulationManager; - void WriteGeometry(TGeoManager* geometry, const char* filename, const char* option = "UPDATE"); void ValidateOutputFile(const std::string& outputFile) const; }; diff --git a/src/Application.cxx b/src/Application.cxx index b93f58ec..40c490b6 100644 --- a/src/Application.cxx +++ b/src/Application.cxx @@ -267,6 +267,8 @@ int interruptSignalHandler(const int, void* ptr) { return 0; } +constexpr const char* geometryName = "Geometry"; + void Application::Run(const CommandLineOptions::Options& options) { signal(SIGINT, (void (*)(int))interruptSignalHandler); @@ -424,6 +426,16 @@ void Application::Run(const CommandLineOptions::Options& options) { time_t systime = time(nullptr); run->SetStartTimeStamp((Double_t)systime); + run->UpdateOutputFile(); + + cout << "Writing geometry" << endl; + gdml->CreateGeoManager(); + if (!gGeoManager) { + cout << "Writing geometry - Error - Unable to write geometry (geometry not found)" << endl; + exit(1); + } + gGeoManager->Write(geometryName, TObject::kWriteDelete); + cout << "Number of events: " << nEvents << endl; if (nEvents > 0) // batch mode { @@ -464,10 +476,6 @@ void Application::Run(const CommandLineOptions::Options& options) { run->UpdateOutputFile(); run->CloseFile(); - auto geometry = gdml->CreateGeoManager(); - WriteGeometry(geometry, run->GetOutputFileName()); - delete geometry; - metadata->PrintMetadata(); run->PrintMetadata(); @@ -484,21 +492,6 @@ void Application::Run(const CommandLineOptions::Options& options) { cout << "\t- Output file: " << filename << endl << endl; } -constexpr const char* geometryName = "Geometry"; - -void Application::WriteGeometry(TGeoManager* geometry, const char* filename, const char* option) { - auto file = TFile::Open(filename, option); - file->cd(); - cout << "Application::WriteGeometry - Writing geometry into '" << filename << "'" << endl; - if (!geometry) { - cout << "Application::WriteGeometry - Error - Unable to write geometry into file" << endl; - exit(1); - } - geometry->Write(geometryName, TObject::kWriteDelete); - - file->Close(); -} - void Application::ValidateOutputFile(const string& filename) const { bool error = false; From 3a83f72553aadede6b0815d876861f8f1f9bd54f Mon Sep 17 00:00:00 2001 From: lobis Date: Tue, 13 Sep 2022 13:29:59 +0200 Subject: [PATCH 168/173] writing geometry with TObject::kWriteDelete flag instead of kOverwrite --- src/Application.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Application.cxx b/src/Application.cxx index 40c490b6..1ac76142 100644 --- a/src/Application.cxx +++ b/src/Application.cxx @@ -434,7 +434,7 @@ void Application::Run(const CommandLineOptions::Options& options) { cout << "Writing geometry - Error - Unable to write geometry (geometry not found)" << endl; exit(1); } - gGeoManager->Write(geometryName, TObject::kWriteDelete); + gGeoManager->Write(geometryName, TObject::kOverwrite); cout << "Number of events: " << nEvents << endl; if (nEvents > 0) // batch mode From 824e9496c56a1bca571d6d6931c19c5223330308 Mon Sep 17 00:00:00 2001 From: lobis Date: Tue, 13 Sep 2022 18:54:39 +0200 Subject: [PATCH 169/173] updated example 13 (IAXO) - using good geometry --- examples/13.IAXO/Validate.C | 13 +- examples/13.IAXO/geometry/setup.gdml | 714 +++++++++++++-------------- 2 files changed, 357 insertions(+), 370 deletions(-) diff --git a/examples/13.IAXO/Validate.C b/examples/13.IAXO/Validate.C index c5cd0e6d..74736b2a 100644 --- a/examples/13.IAXO/Validate.C +++ b/examples/13.IAXO/Validate.C @@ -18,7 +18,7 @@ Int_t Validate(const char* filename) { geometryInfo.Print(); - if (geometryInfo.GetAllPhysicalVolumes().size() != 374) { + if (geometryInfo.GetAllPhysicalVolumes().size() != 309) { cout << "Incorrect number of physical volumes " << geometryInfo.GetAllPhysicalVolumes().size() << endl; return 2; @@ -32,24 +32,25 @@ Int_t Validate(const char* filename) { TRestGeant4Event* event = run.GetInputEvent(); run.GetEntry(0); - if (event->GetNumberOfTracks() != 1738 /* 28059 */) { + if (event->GetNumberOfTracks() != 405) { cout << "Incorrect number of tracks: " << event->GetNumberOfTracks() << endl; return 4; } - if (event->GetNumberOfHits() != 15202 /* 87189 */) { + if (event->GetNumberOfHits() != 6345) { cout << "Incorrect number of hits: " << event->GetNumberOfHits() << endl; return 5; } - if (TMath::Abs(event->GetSensitiveVolumeEnergy() - 72.436883) > 1e-4) { + constexpr Double_t sensitiveVolumeEnergyRef = 30.2461; + if (TMath::Abs(event->GetSensitiveVolumeEnergy() - sensitiveVolumeEnergyRef) > 1e-4) { cout << "Incorrect sensitive volume energy: " << event->GetSensitiveVolumeEnergy() << endl; return 6; } const auto scintillatorVolumeName = - "VetoSystem_vetoSystemBack_vetoLayerBack1_assembly-17.veto3_scintillatorVolume-800.0mm-f1a5df6c"; + "VetoSystem_vetoSystemWest_vetoLayerWest2_assembly-16.veto3_scintillatorVolume-1500.0mm-f1a5df6b"; const auto scintillatorEnergy = event->GetEnergyInVolume(scintillatorVolumeName); - const auto scintillatorEnergyRef = 1348.3876; + const auto scintillatorEnergyRef = 3367.0536; if (TMath::Abs(scintillatorEnergy - scintillatorEnergyRef) > 1e-4) { cout << "Incorrect scintillator volume energy: " << scintillatorEnergy << endl; return 7; diff --git a/examples/13.IAXO/geometry/setup.gdml b/examples/13.IAXO/geometry/setup.gdml index 577a0a44..3040e444 100644 --- a/examples/13.IAXO/geometry/setup.gdml +++ b/examples/13.IAXO/geometry/setup.gdml @@ -1,6 +1,5 @@ - + @@ -205,188 +204,177 @@ - - - + + + - - - - - - - - + + + + + + + + - - - - + + + + - - + + - + - + - + - + - - - + + + - - - + + + - - + + - - - - - - + + + + + + - - + + - - + + - - - - - - - - + + + + + + + + - - + + - - + + - - + + - - + + - - + + - - - - + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + - - - - + + + + - - - - - - - - - - - - - - - - - - - - - + @@ -435,7 +423,7 @@ - + @@ -445,28 +433,28 @@ - + - + - + - + - + - + @@ -483,7 +471,7 @@ - + @@ -493,80 +481,79 @@ - + - + - + - + - + - + - + - + - + - - + + - - + + - - - + + + - - - + + + - - - + + + - + - + - + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + @@ -576,333 +563,331 @@ - + - + - + - + - + - + - - - + + + + + + + + + + + + + + + + - - - - + + - - - - + + - - - - + + + + + + + + + + + - - - - - + + + - - - + + + - - - + + + - - - + + + - - - - - + - + + - + - + + - + - + + - - - - + + - - - - + + - - - - + + + - - - - + + + - - + + + - - - + + + + + - - - + + + - - - + + + - - - - - + - + + - + - + + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - - + + - - + + - + - + - + - + - + - + - + - - - - - - - - + + + + - - - + + + - - - + + + - + - - - + + + - - - + + + - - - + + + - - + + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - - + - + - - + - + - - + + + + + + + + + + + + + + + + + + - + - - + + - - + + - - + + - - + + - - + + @@ -911,13 +896,14 @@ - + + From 299b6c3f2b9742addb95670613408d4a8451e82f Mon Sep 17 00:00:00 2001 From: Luis Obis Date: Wed, 14 Sep 2022 15:25:52 +0200 Subject: [PATCH 170/173] Better formatting of print --- src/SimulationManager.cxx | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index 27fcdc89..895b2f14 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -38,13 +38,18 @@ void PeriodicPrint(SimulationManager* simulationManager) { simulationManager->SyncStatsFromChild(outputManager); } - G4cout << double(simulationManager->GetNumberOfProcessedEvents()) / - double(restG4Metadata->GetNumberOfEvents()) * 100 + G4cout << TString::Format("%5.2f", double(simulationManager->GetNumberOfProcessedEvents()) / + double(restG4Metadata->GetNumberOfEvents()) * 100) + .Data() << "% - " << simulationManager->GetNumberOfProcessedEvents() << " Events processed out of " << restG4Metadata->GetNumberOfEvents() << " requested events (" - << simulationManager->GetNumberOfProcessedEvents() / simulationManager->GetElapsedTime() + << TString::Format("%.2e", simulationManager->GetNumberOfProcessedEvents() / + simulationManager->GetElapsedTime()) + .Data() << " per second). " << simulationManager->GetNumberOfStoredEvents() << " events stored (" - << simulationManager->GetNumberOfStoredEvents() / simulationManager->GetElapsedTime() + << TString::Format("%.2e", simulationManager->GetNumberOfStoredEvents() / + simulationManager->GetElapsedTime()) + .Data() << " per second). " << simulationManager->GetElapsedTime() << " seconds elapsed" << G4endl; } } From 23c16744568a2519fc5a10bf2ba84cd66c3c1f3f Mon Sep 17 00:00:00 2001 From: Luis Obis Date: Wed, 14 Sep 2022 15:26:53 +0200 Subject: [PATCH 171/173] Better formatting of print --- src/SimulationManager.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index 895b2f14..c992d841 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -41,7 +41,7 @@ void PeriodicPrint(SimulationManager* simulationManager) { G4cout << TString::Format("%5.2f", double(simulationManager->GetNumberOfProcessedEvents()) / double(restG4Metadata->GetNumberOfEvents()) * 100) .Data() - << "% - " << simulationManager->GetNumberOfProcessedEvents() << " Events processed out of " + << "% - " << simulationManager->GetNumberOfProcessedEvents() << " events processed out of " << restG4Metadata->GetNumberOfEvents() << " requested events (" << TString::Format("%.2e", simulationManager->GetNumberOfProcessedEvents() / simulationManager->GetElapsedTime()) From 6486d1b5a571dc4cfe564c06615b8aa965856e60 Mon Sep 17 00:00:00 2001 From: Luis Obis Date: Wed, 14 Sep 2022 15:50:51 +0200 Subject: [PATCH 172/173] added method for better time printing --- src/Application.cxx | 2 +- src/SimulationManager.cxx | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Application.cxx b/src/Application.cxx index 1ac76142..00c465c4 100644 --- a/src/Application.cxx +++ b/src/Application.cxx @@ -485,7 +485,7 @@ void Application::Run(const CommandLineOptions::Options& options) { // Do some checks ValidateOutputFile(filename); - cout << "\n\t- Total simulation time is " << fSimulationManager.GetElapsedTime() << " seconds, " + cout << "\n\t- Total simulation time is " << ToTimeStringLong(fSimulationManager.GetElapsedTime()) << ", " << nEventsAtEnd << " processed events (" << nEventsAtEnd / fSimulationManager.GetElapsedTime() << " per second) and " << nEntries << " events saved to output file (" << nEntries / fSimulationManager.GetElapsedTime() << " per second)" << endl; diff --git a/src/SimulationManager.cxx b/src/SimulationManager.cxx index c992d841..f1ddab4b 100644 --- a/src/SimulationManager.cxx +++ b/src/SimulationManager.cxx @@ -50,7 +50,8 @@ void PeriodicPrint(SimulationManager* simulationManager) { << TString::Format("%.2e", simulationManager->GetNumberOfStoredEvents() / simulationManager->GetElapsedTime()) .Data() - << " per second). " << simulationManager->GetElapsedTime() << " seconds elapsed" << G4endl; + << " per second). " << ToTimeStringLong(simulationManager->GetElapsedTime()) << " elapsed" + << G4endl; } } @@ -221,7 +222,8 @@ void OutputManager::BeginOfEventAction() { fSimulationManager->GetElapsedTime() > fSimulationManager->GetRestMetadata()->GetSimulationMaxTimeSeconds()) { G4cout << "Stopping Run! We have reached the time limit of " - << fSimulationManager->GetRestMetadata()->GetSimulationMaxTimeSeconds() << " seconds" << endl; + << ToTimeStringLong(fSimulationManager->GetRestMetadata()->GetSimulationMaxTimeSeconds()) + << endl; fSimulationManager->StopSimulation(); } } From 5c5a8bda72616ecf2d74f9f4cb54c48d871b4a87 Mon Sep 17 00:00:00 2001 From: Luis Obis Date: Wed, 14 Sep 2022 16:42:18 +0200 Subject: [PATCH 173/173] avoid hardcoding max int value --- src/Application.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Application.cxx b/src/Application.cxx index 00c465c4..1d08deed 100644 --- a/src/Application.cxx +++ b/src/Application.cxx @@ -301,7 +301,7 @@ void Application::Run(const CommandLineOptions::Options& options) { if (options.seed != 0) { metadata->SetSeed(options.seed); } - constexpr auto maxPrimariesAllowed = 2147483647; + constexpr int maxPrimariesAllowed = numeric_limits::max(); if (options.nEvents != 0) { metadata->SetNumberOfEvents(options.nEvents); }