From 51ad8459db0b60ada2b673a920444acfc7db8d43 Mon Sep 17 00:00:00 2001 From: kochebina Date: Mon, 16 Feb 2026 11:35:18 +0100 Subject: [PATCH 1/2] Enable offline Digi --- source/digits_hits/include/GateOutputMgr.hh | 2 +- .../digits_hits/src/GateCoincidenceSorter.cc | 34 ++++++++++++++++--- source/digits_hits/src/GateOutputMgr.cc | 23 ++++++++----- 3 files changed, 46 insertions(+), 13 deletions(-) diff --git a/source/digits_hits/include/GateOutputMgr.hh b/source/digits_hits/include/GateOutputMgr.hh index 854313bd2..dbf7ea628 100644 --- a/source/digits_hits/include/GateOutputMgr.hh +++ b/source/digits_hits/include/GateOutputMgr.hh @@ -101,7 +101,7 @@ public: //! Static getter and setter to know the current mode of the digitizer inline static DigiMode GetDigiMode() { return m_digiMode;} - inline static void SetDigiMode(DigiMode mode) { m_digiMode = mode; } + inline static void SetDigiMode(DigiMode mode) { m_digiMode = mode;} GateVOutputModule* GetModule(G4String); //! Call in startDAQ, this function search for all output module inserted diff --git a/source/digits_hits/src/GateCoincidenceSorter.cc b/source/digits_hits/src/GateCoincidenceSorter.cc index 061068b77..61dbb04b0 100644 --- a/source/digits_hits/src/GateCoincidenceSorter.cc +++ b/source/digits_hits/src/GateCoincidenceSorter.cc @@ -278,13 +278,27 @@ void GateCoincidenceSorter::Digitize() //------ put input digis in sorted input buffer---------- + if (nVerboseLevel > 1) { + G4cout<<"GateCoincidenceSorter::Digitize. Putting input digis in sorted input buffer"<begin();gpl_iter != IDCvector->end();gpl_iter++) { // make a copy of the digi digi = new GateDigi(**gpl_iter); + if (nVerboseLevel > 1) { + G4cout<<"[GateCoincidenceSorter::Digitize] EventID "<< digi->GetEventID()< 2) { + G4cout << "[GateCoincidenceSorter::Digitize] Input digi \n" + << *digi << Gateendl << Gateendl ; + + } if(m_presortBuffer.empty()) - m_presortBuffer.push_back(digi); + m_presortBuffer.push_back(digi); else if(digi->GetTime() < m_presortBuffer.back()->GetTime()) // check that even isn't earlier than the earliest event in the buffer { if(!m_presortWarning) @@ -298,13 +312,18 @@ void GateCoincidenceSorter::Digitize() while(digi->GetTime() < (*buf_iter)->GetTime()) buf_iter++; m_presortBuffer.insert(buf_iter, digi); - // G4cout<<"presortBuffer filled in position "<GetTime()<GetTime()/ns< 3) + { + G4cout<<"presortBuffer filled in position "<GetTime()<GetTime()/ns< 1) + G4cout<<"[GateCoincidenceSorter::Digitize] Analyzing the presort buffer..."< m_presortBufferSize;i--) @@ -375,6 +394,13 @@ void GateCoincidenceSorter::Digitize() delete digi; } + if (nVerboseLevel>1) { + G4cout << "[GateCoincidenceSorter::Digitizer]: returning output coincidence digi collection with " << m_OutputCoincidenceDigiCollection->GetSize () << " entries\n"; + //for (iter=m_OutputCoincidenceDigiCollection->begin(); iter!= m_OutputCoincidenceDigiCollection->end() ; ++iter) + //G4cout << **iter << Gateendl; + //G4cout << Gateendl; + } + StoreDigiCollection(m_OutputCoincidenceDigiCollection); } diff --git a/source/digits_hits/src/GateOutputMgr.cc b/source/digits_hits/src/GateOutputMgr.cc index e587b3f32..289bd9440 100644 --- a/source/digits_hits/src/GateOutputMgr.cc +++ b/source/digits_hits/src/GateOutputMgr.cc @@ -88,12 +88,10 @@ GateOutputMgr::GateOutputMgr(const G4String name) AddOutputModule((GateVOutputModule*)gateFastAnalysis); } #endif - - if (m_digiMode==kruntimeMode) { - GateAnalysis* gateAnalysis = new GateAnalysis("analysis", this,m_digiMode); + //commented for offline digi by OK for GND feb 2026 if (m_digiMode==kruntimeMode) { + GateAnalysis* gateAnalysis = new GateAnalysis("analysis", this,m_digiMode); AddOutputModule((GateVOutputModule*)gateAnalysis); - - } + //} #ifdef G4ANALYSIS_USE_FILE @@ -160,7 +158,6 @@ GateVOutputModule* GateOutputMgr::FindOutputModule(G4String name) for(G4int i=0;iGetName(); - //G4cout << moduleName << " "<< name<< G4endl; if(moduleName == name) return m_outputModules[i]; } @@ -262,14 +259,24 @@ void GateOutputMgr::RecordBeginOfAcquisition() G4cout << "GateOutputMgr::RecordBeginOfAcquisition\n"; //OK GND GateDigitizerMgr* digitizerMgr=GateDigitizerMgr::GetInstance(); + /*if (m_digiMode==kruntimeMode) + {*/ if((digitizerMgr->m_recordSingles|| digitizerMgr->m_recordCoincidences) && !this->FindOutputModule("analysis")->IsEnabled() && !this->FindOutputModule("fastanalysis")->IsEnabled()) { GateError("***ERROR*** Digitizer Manager is not initialized properly. Please, enable analysis or fastanalysis Output Modules to write down Singles or Coincidences.\n Use, /gate/output/analysis/enable or /gate/output/fastanalysis/enable.\n"); } - - + /*} + else + { + G4cout<<"**************************"<m_recordSingles << " "<< digitizerMgr->m_recordCoincidences<m_recordSingles|| !digitizerMgr->m_recordCoincidences) + { + GateError("***ERROR: Digi MODE *** Digitizer Manager is not initialized properly. The output flag is set to 0 for both Signles and Coincidences. \n"); + } + } +*/ #ifdef G4ANALYSIS_USE_ROOT if (m_digiMode==kofflineMode) GateHitFileReader::GetInstance()->PrepareAcquisition(); From 362110b6f453ab9b8c4777cced4048f0e14fbead Mon Sep 17 00:00:00 2001 From: kochebina Date: Wed, 8 Jul 2026 11:40:26 +0200 Subject: [PATCH 2/2] 1st working version --- Gate.cc | 41 ++++++- .../digits_hits/include/GateDigitizerMgr.hh | 16 ++- .../digits_hits/include/GateHitFileReader.hh | 37 ++++-- .../include/GateHitFileReaderMessenger.hh | 2 + source/digits_hits/include/GateToRoot.hh | 3 + .../src/GateDigitizerInitializationModule.cc | 107 +++++++++++------- source/digits_hits/src/GateDigitizerMgr.cc | 39 ++++++- source/digits_hits/src/GateHitFileReader.cc | 101 ++++++++++++----- source/digits_hits/src/GateOutputMgr.cc | 6 +- source/digits_hits/src/GateToRoot.cc | 28 +++++ source/general/src/GateApplicationMgr.cc | 26 ++++- .../general/src/GatePrimaryGeneratorAction.cc | 74 ++++++++---- 12 files changed, 363 insertions(+), 117 deletions(-) diff --git a/Gate.cc b/Gate.cc index b906f184f..a4193e105 100644 --- a/Gate.cc +++ b/Gate.cc @@ -6,7 +6,7 @@ * \brief To launch GATE: * - 'Gate' or 'Gate --qt' using the Qt visualization * - 'Gate your_macro.mac' or 'Gate --qt your_macro.mac' using the Qt visualization - * - 'Gate -d your_macro.mac' using the DigiGate + * - 'Gate your_macro.mac --d hits.root' for Offline Digitizer * - 'Gate -a [activity,10]' using the parameterized macro creating an alias in your macro */ @@ -36,7 +36,7 @@ #include "GateOutputMgr.hh" #include "GatePrimaryGeneratorAction.hh" #include "GateUserActions.hh" -#include "GateDigitizer.hh" +#include "GateDigitizerMgr.hh" #include "GateClock.hh" #include "GateUIcontrolMessenger.hh" #ifdef G4ANALYSIS_USE_ROOT @@ -69,7 +69,12 @@ void printHelpAndQuit( G4String msg ) GateMessage( "Core", 0, " -h, --help print the help" << G4endl ); GateMessage( "Core", 0, " -v, --version print the version" << G4endl ); GateMessage( "Core", 0, " -a, --param set alias. format is '[alias1,value1] [alias2,value2] ...'" << G4endl ); - GateMessage( "Core", 0, " --d use the DigiMode" << G4endl ); + //GateMessage( "Core", 0, " --d use the DigiMode" << G4endl ); + GateMessage( "Core", 0, +" --d FILE use Offline Digi mode with input ROOT file" +<< G4endl ); + + GateMessage( "Core", 0, " --qt use the Qt visualization mode" << G4endl ); exit( EXIT_FAILURE ); } @@ -200,6 +205,7 @@ int main( int argc, char* argv[] ) // analyzing arguments static G4int isDigiMode = 0; // DigiMode false by default + G4String digiInputFile = ""; static G4int isQt = 0; // Enable Qt or not G4String listOfParameters = ""; // List of parameters for parameterized macro DigiMode aDigiMode = kruntimeMode; @@ -214,7 +220,7 @@ int main( int argc, char* argv[] ) static struct option longOptions[] = { { "help", no_argument, 0, 'h' }, { "version", no_argument, 0, 'v' }, - { "d", no_argument, &isDigiMode, 1 }, + { "d", required_argument, 0, 'd' }, //{ "d", no_argument, &isDigiMode, 1 }, { "qt", no_argument, &isQt, 1 }, { "param", required_argument, 0, 'a' } }; @@ -262,6 +268,10 @@ int main( int argc, char* argv[] ) case 'a': listOfParameters = optarg; break; + case 'd': + isDigiMode = 1; + digiInputFile = optarg; + break; default: printHelpAndQuit( "Out of switch options" ); break; @@ -272,6 +282,20 @@ int main( int argc, char* argv[] ) if( isDigiMode ) aDigiMode = kofflineMode; + if (isDigiMode) + { + if (digiInputFile.empty()) + { + G4cerr << "Error: Offline Digi mode requires an input ROOT file.\n" + << "Usage: Gate main.mac --d input.root\n"; + return EXIT_FAILURE; + } + + GateHitFileReader::GetInstance()->SetFileName(digiInputFile); + GateDigitizerMgr::GetInstance()->SetOfflineMode(true); + } + + // Analyzing parameterized macro std::queue< G4String > commandQueue = decodeParameters( listOfParameters ); @@ -317,12 +341,17 @@ int main( int argc, char* argv[] ) #endif if( aDigiMode == kofflineMode ) -#ifdef G4ANALYSIS_USE_ROOT + { +#ifndef G4ANALYSIS_USE_ROOT + abortIfRootNotFound(); +#endif + } + /*#ifdef G4ANALYSIS_USE_ROOT GateHitFileReader::GetInstance(); #else abortIfRootNotFound(); #endif - + */ GateSourceMgr* sourceMgr = GateSourceMgr::GetInstance(); GateApplicationMgr* appMgr = GateApplicationMgr::GetInstance(); GateClock::GetInstance()->SetTime( 0 ); diff --git a/source/digits_hits/include/GateDigitizerMgr.hh b/source/digits_hits/include/GateDigitizerMgr.hh index e5f9c5778..79ae804b0 100644 --- a/source/digits_hits/include/GateDigitizerMgr.hh +++ b/source/digits_hits/include/GateDigitizerMgr.hh @@ -88,9 +88,6 @@ public: GateSinglesDigitizer* FindSinglesDigitizer(G4String mName); /// End of methods for Singles - - - /// Methods for Coincidences //Sorters @@ -105,12 +102,20 @@ public: GateCoincidenceDigitizer* FindCoincidenceDigitizer(G4String mName); /// End of methods for Coincidences -private: +public: + void SetOfflineMode(bool b) { mOfflineMode = b; } + bool IsOfflineMode() const { return mOfflineMode; } - GateDigitizerMgrMessenger *fMessenger; + GateHitsCollection* GetOfflineHitsCollection(); + void SetOfflineHitsCollection(GateHitsCollection* hc); + void ClearOfflineHitsCollection(); +private: + GateDigitizerMgrMessenger *fMessenger; static GateDigitizerMgr* theDigitizerMgr; + GateHitsCollection* mOfflineHitsCollection = nullptr; + bool mOfflineMode = false; protected: G4String m_elementTypeName; //!< Type-name for DigitizerMgr --> used only for cout and help messengers @@ -135,5 +140,6 @@ public: G4bool m_alreadyRun; + }; #endif diff --git a/source/digits_hits/include/GateHitFileReader.hh b/source/digits_hits/include/GateHitFileReader.hh index b15e51e4a..ab5e01817 100644 --- a/source/digits_hits/include/GateHitFileReader.hh +++ b/source/digits_hits/include/GateHitFileReader.hh @@ -15,12 +15,9 @@ See LICENSE.md for further details #ifdef G4ANALYSIS_USE_ROOT #include "globals.hh" -#include - -#include "G4Event.hh" - +#include "GateHit.hh" class G4Event; -class GateHit; + #include "TROOT.h" @@ -53,6 +50,7 @@ public: */ static GateHitFileReader* GetInstance(); + ~GateHitFileReader(); //!< Public destructor private: @@ -72,7 +70,7 @@ public: //! This method is meant to be called by output manager before calling the methods RecordEndOfEvent() of the output modules. //! It creates a new hit-collection, based on the queue of hits previously filled by PrepareNextEvent() - void PrepareEndOfEvent(); + //void PrepareEndOfEvent(); //! This method must be called (normally by the application manager) after completion of a DigiGate acquisition @@ -84,13 +82,28 @@ public: //! Set the hit file name void SetFileName(const G4String aName) { m_fileName = aName; }; + + const std::vector& GetHitVector() const + { + return m_hitVector; + } + + std::vector& GetHitVector() + { + return m_hitVector; + } + + bool IsFinished() const + { + return m_finished; + } + /*! \brief Overload of the base-class virtual method to print-out a description of the reader \param indent: the print-out indentation (cosmetic parameter) */ virtual void Describe(size_t indent=0); - - + void ReleaseHits(); protected: //! Reads a set of hit data from the hit-tree, and stores them into the root-hit buffer @@ -111,15 +124,21 @@ protected: //!< The hit-data are loaded into this buffer by LoadHitData() //!< They are then transformed into a crystal-hit by PrepareNextEvent() - std::queue m_hitQueue; //!< Queue of waiting hits for the current event + //std::queue m_hitQueue; //!< Queue of waiting hits for the current event //!< For each event, the queue is filled (from data read out of the hit-file) at //!< the beginning of each event by PrepareNextEvent(). It is emptied into //!< a crystal-hit collection at the end of each event by PrepareEndOfEvent() + + std::vector m_hitVector; + + GateHitFileReaderMessenger *m_messenger; //!< Messenger; private: static GateHitFileReader* instance; //!< Instance of the GateHitFielReader singleton + bool m_finished; + }; #endif diff --git a/source/digits_hits/include/GateHitFileReaderMessenger.hh b/source/digits_hits/include/GateHitFileReaderMessenger.hh index dc939833f..65d494488 100644 --- a/source/digits_hits/include/GateHitFileReaderMessenger.hh +++ b/source/digits_hits/include/GateHitFileReaderMessenger.hh @@ -40,6 +40,8 @@ class GateHitFileReaderMessenger: public GateClockDependentMessenger void SetNewValue(G4UIcommand*, G4String); + + //! Get the clock-dependent object inline GateHitFileReader* GetHitFileReader() { return (GateHitFileReader*) GetClockDependent(); } diff --git a/source/digits_hits/include/GateToRoot.hh b/source/digits_hits/include/GateToRoot.hh index d26384c43..bec46ae6c 100644 --- a/source/digits_hits/include/GateToRoot.hh +++ b/source/digits_hits/include/GateToRoot.hh @@ -109,6 +109,9 @@ public: void RecordOpticalData(const G4Event *event); // v. cuplov - optical photons + + void SetOfflineOutputFileName(); + void RecordVoxels(const G4Step *); void BookBeginOfAquisition(); diff --git a/source/digits_hits/src/GateDigitizerInitializationModule.cc b/source/digits_hits/src/GateDigitizerInitializationModule.cc index d0902f908..bcd788d75 100644 --- a/source/digits_hits/src/GateDigitizerInitializationModule.cc +++ b/source/digits_hits/src/GateDigitizerInitializationModule.cc @@ -28,6 +28,7 @@ #include "G4SDManager.hh" #include "G4DigiManager.hh" #include "G4ios.hh" +#include "GateDigitizerMgr.hh" GateDigitizerInitializationModule::GateDigitizerInitializationModule(GateSinglesDigitizer *digitizer) :GateVDigitizerModule("DigiInit","digitizerMgr/"+digitizer->GetSD()->GetName()+"/SinglesDigitizer/"+digitizer->m_digitizerName+"/digiInit",digitizer, digitizer->GetSD()), @@ -51,6 +52,8 @@ GateDigitizerInitializationModule::~GateDigitizerInitializationModule() void GateDigitizerInitializationModule::Digitize() { + G4cout<<"GateDigitizerInitializationModule::Digitize()"<GetOutputName() ); // to create the Digi Collection G4DigiManager* DigiMan = G4DigiManager::GetDMpointer(); @@ -65,7 +68,29 @@ void GateDigitizerInitializationModule::Digitize() } - GateHitsCollection* inHC = (GateHitsCollection*) (DigiMan->GetHitsCollection(m_HCID));// DigiMan->GetHitsCollectionID(HCname))); + GateHitsCollection* inHC; + GateDigitizerMgr* digitizerMgr=GateDigitizerMgr::GetInstance(); + + + if (GateDigitizerMgr::GetInstance()->IsOfflineMode() && + digitizerMgr->GetOfflineHitsCollection() == nullptr) + { + GateMessage("OfflineDigi", 1, + "No offline hits, skipping digitization."); + return; + } + + + if (GateDigitizerMgr::GetInstance()->IsOfflineMode()) + inHC = digitizerMgr->GetOfflineHitsCollection(); + else + inHC = (GateHitsCollection*)DigiMan->GetHitsCollection(m_HCID); + + G4cout << "Retrieved HC = " << inHC + << " entries = " << inHC->entries() + << G4endl; + + if (inHC) @@ -74,63 +99,67 @@ void GateDigitizerInitializationModule::Digitize() for (G4int i=0;iGetEdep() !=0 ) + GateHit *hit = (*inHC)[i]; + G4cout<<"Hit eventID "<GetEventID() <GetEdep() !=0 ) { GateDigi* Digi = new GateDigi(); - Digi->SetMother( (*inHC)[i] ); - Digi->SetRunID( (*inHC)[i]->GetRunID() ); - Digi->SetEventID( (*inHC)[i]->GetEventID() ); - Digi->SetTrackID( (*inHC)[i]->GetTrackID() ); - Digi->SetSourceID( (*inHC)[i]->GetSourceID() ); - Digi->SetSourcePosition( (*inHC)[i]->GetSourcePosition() ); - Digi->SetTime( (*inHC)[i]->GetTime() ); - Digi->SetEnergy( (*inHC)[i]->GetEdep() ); - Digi->SetMaxEnergy( (*inHC)[i]->GetEdep() ); - Digi->SetLocalPos( (*inHC)[i]->GetLocalPos() ); - Digi->SetGlobalPos( (*inHC)[i]->GetGlobalPos() ); - Digi->SetPDGEncoding( (*inHC)[i]->GetPDGEncoding() ); - Digi->SetOutputVolumeID( (*inHC)[i]->GetOutputVolumeID() ); - Digi->SetNPhantomCompton( (*inHC)[i]->GetNPhantomCompton() ); - Digi->SetNCrystalCompton( (*inHC)[i]->GetNCrystalCompton() ); - Digi->SetNPhantomRayleigh( (*inHC)[i]->GetNPhantomRayleigh() ); - Digi->SetNCrystalRayleigh( (*inHC)[i]->GetNCrystalRayleigh() ); - Digi->SetComptonVolumeName( (*inHC)[i]->GetComptonVolumeName() ); - Digi->SetRayleighVolumeName( (*inHC)[i]->GetRayleighVolumeName() ); - Digi->SetVolumeID( (*inHC)[i]->GetVolumeID() ); - Digi->SetSystemID( (*inHC)[i]->GetSystemID() ); - Digi->SetScannerPos( (*inHC)[i]->GetScannerPos() ); - Digi->SetScannerRotAngle( (*inHC)[i]->GetScannerRotAngle() ); + Digi->SetMother( hit ); + Digi->SetRunID( hit->GetRunID() ); + Digi->SetEventID( hit->GetEventID() ); + Digi->SetTrackID( hit->GetTrackID() ); + Digi->SetSourceID( hit->GetSourceID() ); + Digi->SetSourcePosition( hit->GetSourcePosition() ); + Digi->SetTime( hit->GetTime() ); + Digi->SetEnergy( hit->GetEdep() ); + Digi->SetMaxEnergy( hit->GetEdep() ); + Digi->SetLocalPos( hit->GetLocalPos() ); + Digi->SetGlobalPos( hit->GetGlobalPos() ); + Digi->SetPDGEncoding( hit->GetPDGEncoding() ); + Digi->SetOutputVolumeID( hit->GetOutputVolumeID() ); + Digi->SetNPhantomCompton( hit->GetNPhantomCompton() ); + Digi->SetNCrystalCompton( hit->GetNCrystalCompton() ); + Digi->SetNPhantomRayleigh( hit->GetNPhantomRayleigh() ); + Digi->SetNCrystalRayleigh( hit->GetNCrystalRayleigh() ); + Digi->SetComptonVolumeName( hit->GetComptonVolumeName() ); + Digi->SetRayleighVolumeName( hit->GetRayleighVolumeName() ); + Digi->SetVolumeID( hit->GetVolumeID() ); + Digi->SetSystemID( hit->GetSystemID() ); + Digi->SetScannerPos( hit->GetScannerPos() ); + Digi->SetScannerRotAngle( hit->GetScannerRotAngle() ); #ifdef GATE_USE_OPTICAL - Digi->SetOptical( (*inHC)[i]->GetPDGEncoding() == -22); + Digi->SetOptical( hit->GetPDGEncoding() == -22); #endif - Digi->SetNSeptal( (*inHC)[i]->GetNSeptal() ); // HDS : septal penetration + Digi->SetNSeptal( hit->GetNSeptal() ); // HDS : septal penetration // AE : Added for IdealComptonPhot adder which take into account several Comptons in the same volume - Digi->SetPostStepProcess((*inHC)[i]->GetPostStepProcess()); - Digi->SetEnergyIniTrack((*inHC)[i]->GetEnergyIniTrack()); - Digi->SetEnergyFin((*inHC)[i]->GetEnergyFin()); - Digi->SetProcessCreator((*inHC)[i]->GetProcess()); - Digi->SetTrackID((*inHC)[i]->GetTrackID()); - Digi->SetParentID((*inHC)[i]->GetParentID()); - Digi->SetSourceEnergy((*inHC)[i]->GetSourceEnergy()); - Digi->SetSourcePDG((*inHC)[i]->GetSourcePDG()); - Digi->SetNCrystalConv( (*inHC)[i]->GetNCrystalConv() ); + Digi->SetPostStepProcess(hit->GetPostStepProcess()); + Digi->SetEnergyIniTrack(hit->GetEnergyIniTrack()); + Digi->SetEnergyFin(hit->GetEnergyFin()); + Digi->SetProcessCreator(hit->GetProcess()); + Digi->SetTrackID(hit->GetTrackID()); + Digi->SetParentID(hit->GetParentID()); + Digi->SetSourceEnergy(hit->GetSourceEnergy()); + Digi->SetSourcePDG(hit->GetSourcePDG()); + Digi->SetNCrystalConv( hit->GetNCrystalConv() ); //------------------------------------------------- - if ((*inHC)[i]->GetComptonVolumeName().empty()) { + if (hit->GetComptonVolumeName().empty()) { Digi->SetComptonVolumeName( "NULL" ); Digi->SetSourceID( -1 ); } - if ((*inHC)[i]->GetRayleighVolumeName().empty()) { + if (hit->GetRayleighVolumeName().empty()) { Digi->SetRayleighVolumeName( "NULL" ); Digi->SetSourceID( -1 ); } /* // if (nVerboseLevel>1) G4cout << "[GateDigitizerInitializationModule::Digitize]: \n" - << "\tprocessed " << *(*inHC)[i] << Gateendl + << "\tprocessed " << *hit << Gateendl << "\tcreated new Digi:\n" << Digi << Gateendl << *Digi << Gateendl; diff --git a/source/digits_hits/src/GateDigitizerMgr.cc b/source/digits_hits/src/GateDigitizerMgr.cc index 54076c8de..d36522f41 100644 --- a/source/digits_hits/src/GateDigitizerMgr.cc +++ b/source/digits_hits/src/GateDigitizerMgr.cc @@ -417,9 +417,8 @@ GateCoincidenceDigitizer* GateDigitizerMgr::FindCoincidenceDigitizer(G4String mN ///////////////// void GateDigitizerMgr::RunDigitizers() { - //G4cout<<"GateDigitizerMgr::RunDigitizers"<IsZombie()) + { + G4String msg = + "Could not open hit file '" + m_fileName + "'"; + G4Exception("GateHitFileReader::PrepareBeforeAcquisition", "PrepareBeforeAcquisition", FatalException, msg); + } // Get the hit tree m_hitTree = (TTree*)( m_hitFile->Get(GateHitConvertor::GetOutputAlias()) ); if (!m_hitTree) { - G4String msg = "Could not find a tree of hits in the ROOT file '" + m_fileName + ".root'!"; + G4String msg = "Could not find a tree of hits in the ROOT file '" + m_fileName + "'!"; G4Exception( "GateHitFileReader::PrepareBeforeAcquisition", "PrepareBeforeAcquisition", FatalException, msg); } // Reset the entry counters @@ -103,6 +112,15 @@ void GateHitFileReader::PrepareAcquisition() // Load the first hit into the root-hit structure LoadHitData(); + + G4cout << "PrepareAcquisition:" + << " entries=" << m_entries + << " current=" << m_currentEntry + << " run=" << m_hitBuffer.runID + << " event=" << m_hitBuffer.eventID + << G4endl; + + } @@ -118,52 +136,69 @@ void GateHitFileReader::PrepareAcquisition() should not be used for the current run but rather for a later run */ G4int GateHitFileReader::PrepareNextEvent(G4Event* ) -{ +{ //G4cout<<"PrepareNextEvent "<ClearOfflineHitsCollection(); + for (auto hit : m_hitVector) + delete hit; + + m_hitVector.clear(); + + + G4cout << " GateHitFileReader::PrepareNextEvent\n"; + G4cout << "PrepareNextEvent: " + << m_hitBuffer.runID << " " + << m_hitBuffer.eventID << G4endl; + // Store the current runID and eventID G4int currentEventID = m_hitBuffer.eventID; G4int currentRunID = m_hitBuffer.runID; // We've reached the end-of-file if ( (currentEventID==-1) && (currentRunID==-1) ) - return 0; + { + m_finished = true; + return 0; + } // Load the hits for the current event // We loop until the data that have been read are found to be for a different event or run while ( (currentEventID == m_hitBuffer.eventID) && (currentRunID == m_hitBuffer.runID) ) { - // Create a new hit and store it into the hit-queue GateHit* aHit = m_hitBuffer.CreateHit(); - m_hitQueue.push(aHit); + m_hitVector.push_back(aHit); + + //m_hitVector.push(aHit); // Load the next set of hit-data into the root-hit structure LoadHitData(); - } - if (currentRunID==m_hitBuffer.runID){ - // We got a set of hits for the current run -> return 1 - return 1; - } - else - { - // We got a set of hits for a later run -> return 0 - return 0; } + + + if (!m_hitVector.empty()) + return 1; + return 0; } + +//Obsolete // This method is meant to be called by output manager before calling the methods RecordEndOfEvent() of the output modules. // It creates a new hit-collection, based on the queue of hits previously filled by PrepareNextEvent() -void GateHitFileReader::PrepareEndOfEvent() +/*void GateHitFileReader::PrepareEndOfEvent() { // We loop until the hit-queue is empty // Each hit is inserted into the crystalSD hit-collection, then removed from the queue - while (m_hitQueue.size()) { - GateOutputMgr::GetInstance()->GetHitCollection()->insert(m_hitQueue.front()); - m_hitQueue.pop(); + while (m_hitVector.size()) { + GateOutputMgr::GetInstance()->GetHitCollection()->insert(m_hitVector.front()); + //m_hitVector.pop(); } -} +} +*/ // This method must be called (normally by the application manager) after completion of a DigiGate acquisition @@ -177,10 +212,15 @@ void GateHitFileReader::TerminateAfterAcquisition() } // If the hit queue was not empty (it should be), clear it up - while (m_hitQueue.size()) { - delete m_hitQueue.front(); - m_hitQueue.pop(); + /*while (m_hitVector.size()) { + delete m_hitVector.front(); + m_hitVector.pop(); } +*/ + for (auto hit : m_hitVector) + delete hit; + + m_hitVector.clear(); // Note that we don't delete the tree: it was based on the file so // I assume it was destroyed at the same time as the file was closed (true?) @@ -192,6 +232,7 @@ void GateHitFileReader::TerminateAfterAcquisition() // Reads a set of hit data from the hit-tree, and stores them into the root-hit buffer void GateHitFileReader::LoadHitData() { + // We've reached the end of file: set indicators to tell the caller that the reading failed if (m_currentEntry>=m_entries){ m_hitBuffer.runID=-1; @@ -206,8 +247,8 @@ void GateHitFileReader::LoadHitData() m_hitBuffer.runID=-1; m_hitBuffer.eventID=-1; } -} +} @@ -228,4 +269,6 @@ void GateHitFileReader::Describe(size_t indent) } + + #endif diff --git a/source/digits_hits/src/GateOutputMgr.cc b/source/digits_hits/src/GateOutputMgr.cc index 289bd9440..ce4206501 100644 --- a/source/digits_hits/src/GateOutputMgr.cc +++ b/source/digits_hits/src/GateOutputMgr.cc @@ -189,8 +189,9 @@ void GateOutputMgr::RecordEndOfEvent(const G4Event* event) GateMessage("Output", 5, "GateOutputMgr::RecordEndOfEvent\n";); #ifdef G4ANALYSIS_USE_ROOT - if (m_digiMode==kofflineMode) - GateHitFileReader::GetInstance()->PrepareEndOfEvent(); + + // if (m_digiMode==kofflineMode) + // GateHitFileReader::GetInstance()->PrepareEndOfEvent(); #endif for (size_t iMod=0; iMod 2) diff --git a/source/digits_hits/src/GateToRoot.cc b/source/digits_hits/src/GateToRoot.cc index 9a1758991..55ecf543f 100644 --- a/source/digits_hits/src/GateToRoot.cc +++ b/source/digits_hits/src/GateToRoot.cc @@ -54,6 +54,7 @@ #include "GateVVolume.hh" #include "GateToRootMessenger.hh" #include "GateVGeometryVoxelStore.hh" +#include "GateHitFileReader.hh" #include "TROOT.h" #include "TApplication.h" @@ -374,6 +375,11 @@ void GateToRoot::RecordBeginOfAcquisition() { ////////// // Open the output file if (nVerboseLevel > 0) G4cout << "GateToRoot: ROOT: files creation...\n"; + + if (m_digiMode == kofflineMode) + SetOfflineOutputFileName(); + + switch (m_digiMode) { case kruntimeMode: // In run-time mode, we open the file in RECREATE mode @@ -1816,6 +1822,28 @@ void GateToRoot::RecordTracks(GateSteppingAction *mySteppingAction) { } + + +void GateToRoot::SetOfflineOutputFileName() +{ + G4String input = GateHitFileReader::GetInstance()->GetFileName(); + + // Remove ".root" if present + if (input.length() > 5 && + input.substr(input.length() - 5) == ".root") + { + input = input.substr(0, input.length() - 5); + } + + m_fileName = input + "_digi"; + + G4cout << G4endl + << "Offline Digi mode:" << G4endl + << " Input : " << GateHitFileReader::GetInstance()->GetFileName() << G4endl + << " Output: " << m_fileName << ".root" << G4endl + << G4endl; +} + /*PY Descourt 08/09/2009 */ //-------------------------------------------------------------------------- diff --git a/source/general/src/GateApplicationMgr.cc b/source/general/src/GateApplicationMgr.cc index 4fe2e6086..8875286d2 100644 --- a/source/general/src/GateApplicationMgr.cc +++ b/source/general/src/GateApplicationMgr.cc @@ -21,6 +21,8 @@ #include "GateVSource.hh" #include "GateSourceMgr.hh" #include "GateOutputMgr.hh" +#include "GateHitFileReader.hh" + #include /* min and max */ GateApplicationMgr* GateApplicationMgr::instance = 0; @@ -361,11 +363,14 @@ void GateApplicationMgr::StartDAQ() m_clusterStop = mTimeSlices.back(); if (mOutputMode) - GateOutputMgr::GetInstance()->RecordBeginOfAcquisition(); + GateOutputMgr::GetInstance()->RecordBeginOfAcquisition(); + + + bool offlineFinished = false; G4int slice=0; m_time = mTimeSlices.front(); - while(m_time < mTimeSlices.back()) + while(m_time < mTimeSlices.back() && !offlineFinished) { // Informational message about the current slice @@ -380,8 +385,10 @@ void GateApplicationMgr::StartDAQ() GateMessage("Geometry", 5, " Time is going to change : = " << m_time/s << Gateendl;); theClock->SetTime(m_time); + + if (mReadNumberOfPrimariesInAFileIsUsed) { - GateRunManager::GetRunManager()->SetRunIDCounter(slice); // Must explicitly keep the RunID in sync with the slice # + GateRunManager::GetRunManager()->SetRunIDCounter(slice); // Must explicitly keep the RunID in sync with the slice # GateRunManager::GetRunManager()->BeamOn(mNumberOfPrimariesPerRun[slice]); m_time = mTimeSlices[slice+1]; } @@ -400,6 +407,7 @@ void GateApplicationMgr::StartDAQ() - int(mTimeSlices[slice]/mTimeStepInTotalAmountOfPrimariesMode); } GateRunManager::GetRunManager()->SetRunIDCounter(slice); // Must explicitly keep the RunID in sync with the slice # + //G4cout << "Calling BeamOn(" << mRequestedAmountOfPrimariesPerRun << ")" << G4endl; GateRunManager::GetRunManager()->BeamOn(mRequestedAmountOfPrimariesPerRun); // otherwise RunID is automatically incremented m_time = mTimeSlices[slice+1]; } @@ -408,9 +416,21 @@ void GateApplicationMgr::StartDAQ() while(m_timeSetRunIDCounter(slice); // Must explicitly keep the RunID in sync with the slice # + //G4cout << "Calling BeamOn(INT_MAX)" << G4endl; + GateRunManager::GetRunManager()->BeamOn(INT_MAX); // otherwise RunID is automatically incremented + #ifdef G4ANALYSIS_USE_ROOT + if (GateOutputMgr::GetInstance()->GetDigiMode()==kofflineMode && + GateHitFileReader::GetInstance()->IsFinished()) + { + offlineFinished = true; + break; + } + #endif theClock->SetTimeNoGeoUpdate(m_time); } + + } slice++; diff --git a/source/general/src/GatePrimaryGeneratorAction.cc b/source/general/src/GatePrimaryGeneratorAction.cc index bca4bebbe..d0b768572 100644 --- a/source/general/src/GatePrimaryGeneratorAction.cc +++ b/source/general/src/GatePrimaryGeneratorAction.cc @@ -23,9 +23,9 @@ See LICENSE.md for further details #include "GateApplicationMgr.hh" #include "GateSourceMgr.hh" -//#include "GateOutputMgr.hh" -//#include "GateHitFileReader.hh" - +#include "GateOutputMgr.hh" +#include "GateHitFileReader.hh" +#include "GateDigitizerMgr.hh" #include "GateConfiguration.h" //--------------------------------------------------------------------------- @@ -70,7 +70,10 @@ void GatePrimaryGeneratorAction::GeneratePrimaries(G4Event* event) // else // GenerateDigitisationPrimaries(event); if (!m_useGPS) { - GenerateSimulationPrimaries(event); + if (GateOutputMgr::GetInstance()->GetDigiMode() == kruntimeMode) + GenerateSimulationPrimaries(event); + else + GenerateDigitisationPrimaries(event); } else { static int i=0; @@ -122,34 +125,61 @@ void GatePrimaryGeneratorAction::GenerateSimulationPrimaries(G4Event* event) } //--------------------------------------------------------------------------- -/* + //--------------------------------------------------------------------------- void GatePrimaryGeneratorAction::GenerateDigitisationPrimaries(G4Event* event) { - + G4cout << "Offline Digi: GenerateDigitisationPrimaries()" << G4endl; #ifdef G4ANALYSIS_USE_ROOT -GateHitFileReader* digiSource = GateHitFileReader::GetInstance(); + GateHitFileReader* reader = GateHitFileReader::GetInstance(); -G4int numEvent = digiSource->PrepareNextEvent(event); + G4int ok = reader->PrepareNextEvent(event); + G4cout<<"OK ? "<< ok <SetOfflineHitsCollection(nullptr); -//! stop the run if no particle has been generated by the source manager -if (numEvent == 0) { -GateRunManager* runManager = GateRunManager::GetRunManager(); + GateRunManager::GetRunManager()->AbortRun(true); -runManager->AbortRun(true); -if (m_nVerboseLevel>1) G4cout << "GatePrimaryGeneratorAction::GeneratePrimaries: numVertices == 0, run aborted \n"; -} else { -m_nEvents++; -if (m_nVerboseLevel>0) { -if ((m_nEvents%m_printModulo) == 0) { -G4cout << "GatePrimaryGeneratorAction::GeneratePrimaries: m_nEvents " << m_nEvents << Gateendl; -} -} -} + return; + } + // Build the hit collection for this event + GateHitsCollection* hc = + new GateHitsCollection("crystal", "CrystalCollection"); + + for (auto hit : reader->GetHitVector()) + hc->insert(hit); + + G4cout<< "hc size "<< hc->GetSize ()<GetHitVector().clear(); + + GateDigitizerMgr::GetInstance()->SetOfflineHitsCollection(hc); + + G4cout << "Stored HC = " << hc + << " entries = " << hc->entries() + << G4endl; + + for (size_t i = 0; i < hc->entries(); ++i) + { + G4cout << "HC hit " << i + << " eventID " + << (*hc)[i]->GetEventID() + << G4endl; + } + + + m_nEvents++; + + + /*G4cout << "Finished = " + << GateHitFileReader::GetInstance()->IsFinished() + << G4endl;*/ #endif } -*/ + //--------------------------------------------------------------------------- //---------------------------------------------------------------------------