From 676fd8d57a489450b8815d7eebd66846a1a8d946 Mon Sep 17 00:00:00 2001 From: kochebina Date: Thu, 9 Jul 2026 12:47:30 +0200 Subject: [PATCH 1/3] 1st working version --- Gate.cc | 29 +++++-- .../digits_hits/include/GateDigitizerMgr.hh | 17 +++- .../digits_hits/include/GateHitFileReader.hh | 21 ++++- source/digits_hits/include/GateToRoot.hh | 2 + .../src/GateDigitizerInitializationModule.cc | 26 +++++- source/digits_hits/src/GateDigitizerMgr.cc | 34 ++++++++ source/digits_hits/src/GateHitFileReader.cc | 72 +++++++++-------- source/digits_hits/src/GateOutputMgr.cc | 8 +- source/digits_hits/src/GateToRoot.cc | 29 +++++++ source/general/src/GateApplicationMgr.cc | 27 ++++++- .../general/src/GatePrimaryGeneratorAction.cc | 79 +++++++++++++------ 11 files changed, 269 insertions(+), 75 deletions(-) diff --git a/Gate.cc b/Gate.cc index b906f184f..dc7270575 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,9 @@ 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 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 +202,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 +217,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' }, { "qt", no_argument, &isQt, 1 }, { "param", required_argument, 0, 'a' } }; @@ -262,6 +265,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; @@ -271,7 +278,19 @@ int main( int argc, char* argv[] ) // Checking if the DigiMode is activated 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 ); diff --git a/source/digits_hits/include/GateDigitizerMgr.hh b/source/digits_hits/include/GateDigitizerMgr.hh index e5f9c5778..7b22066d0 100644 --- a/source/digits_hits/include/GateDigitizerMgr.hh +++ b/source/digits_hits/include/GateDigitizerMgr.hh @@ -105,11 +105,26 @@ public: GateCoincidenceDigitizer* FindCoincidenceDigitizer(G4String mName); /// End of methods for Coincidences + + //Methods for OfflineDigi + + void SetOfflineMode(bool b) { mOfflineMode = b; } + bool IsOfflineMode() const { return mOfflineMode; } + + GateHitsCollection* GetOfflineHitsCollection(); + + void SetOfflineHitsCollection(GateHitsCollection* hc); + void ClearOfflineHitsCollection(); + + + + private: GateDigitizerMgrMessenger *fMessenger; - + GateHitsCollection* mOfflineHitsCollection = nullptr; + bool mOfflineMode = false; static GateDigitizerMgr* theDigitizerMgr; protected: diff --git a/source/digits_hits/include/GateHitFileReader.hh b/source/digits_hits/include/GateHitFileReader.hh index b15e51e4a..a8530bae2 100644 --- a/source/digits_hits/include/GateHitFileReader.hh +++ b/source/digits_hits/include/GateHitFileReader.hh @@ -91,6 +91,21 @@ public: virtual void Describe(size_t indent=0); + const std::vector& GetHitVector() const + { + return m_hitVector; + } + + std::vector& GetHitVector() + { + return m_hitVector; + } + + bool IsFinished() const + { + return m_finished; + } + protected: //! Reads a set of hit data from the hit-tree, and stores them into the root-hit buffer @@ -111,15 +126,13 @@ 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 - //!< 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/GateToRoot.hh b/source/digits_hits/include/GateToRoot.hh index 18f85be23..ddb20631d 100644 --- a/source/digits_hits/include/GateToRoot.hh +++ b/source/digits_hits/include/GateToRoot.hh @@ -109,6 +109,8 @@ 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..adf16ae8e 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()), @@ -65,7 +66,30 @@ 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) diff --git a/source/digits_hits/src/GateDigitizerMgr.cc b/source/digits_hits/src/GateDigitizerMgr.cc index 54076c8de..fbfccba1f 100644 --- a/source/digits_hits/src/GateDigitizerMgr.cc +++ b/source/digits_hits/src/GateDigitizerMgr.cc @@ -538,6 +538,40 @@ void GateDigitizerMgr::RunCoincidenceDigitizers() //m_alreadyRun=true; } + +GateHitsCollection* GateDigitizerMgr::GetOfflineHitsCollection() +{ + + G4cout<< "GateDigitizerMgr::GetHitsCollection"<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 +113,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; + + } @@ -120,13 +139,22 @@ void GateHitFileReader::PrepareAcquisition() G4int GateHitFileReader::PrepareNextEvent(G4Event* ) { G4cout << " GateHitFileReader::PrepareNextEvent\n"; + + for (auto hit : m_hitVector) + delete hit; + + m_hitVector.clear(); + // 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 @@ -134,35 +162,18 @@ G4int GateHitFileReader::PrepareNextEvent(G4Event* ) // 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); // 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 + if (!m_hitVector.empty()) + return 1; return 0; - } } -// 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() -{ - // 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(); - } -} @@ -176,11 +187,10 @@ void GateHitFileReader::TerminateAfterAcquisition() m_hitFile=0; } - // If the hit queue was not empty (it should be), clear it up - while (m_hitQueue.size()) { - delete m_hitQueue.front(); - m_hitQueue.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?) diff --git a/source/digits_hits/src/GateOutputMgr.cc b/source/digits_hits/src/GateOutputMgr.cc index bf1c4b3f4..bc8226dbd 100644 --- a/source/digits_hits/src/GateOutputMgr.cc +++ b/source/digits_hits/src/GateOutputMgr.cc @@ -90,10 +90,11 @@ GateOutputMgr::GateOutputMgr(const G4String name) } #endif - if (m_digiMode==kruntimeMode) { + GateAnalysis* gateAnalysis = new GateAnalysis("analysis", this,m_digiMode); AddOutputModule((GateVOutputModule*)gateAnalysis); + if (m_digiMode==kruntimeMode) { GateMultiPhotonAnalysis* gateMultiPhotonAnalysis = new GateMultiPhotonAnalysis("multianalysis", this, m_digiMode); AddOutputModule((GateVOutputModule*)gateMultiPhotonAnalysis); @@ -195,11 +196,6 @@ void GateOutputMgr::RecordEndOfEvent(const G4Event* event) { GateMessage("Output", 5, "GateOutputMgr::RecordEndOfEvent\n";); -#ifdef G4ANALYSIS_USE_ROOT - if (m_digiMode==kofflineMode) - GateHitFileReader::GetInstance()->PrepareEndOfEvent(); -#endif - for (size_t iMod=0; iModIsEnabled() ) { diff --git a/source/digits_hits/src/GateToRoot.cc b/source/digits_hits/src/GateToRoot.cc index 2626daf8d..5f3c5a374 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" @@ -376,6 +377,10 @@ 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 @@ -1818,6 +1823,30 @@ 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..7aa316f46 100644 --- a/source/general/src/GateApplicationMgr.cc +++ b/source/general/src/GateApplicationMgr.cc @@ -21,6 +21,7 @@ #include "GateVSource.hh" #include "GateSourceMgr.hh" #include "GateOutputMgr.hh" +#include "GateHitFileReader.hh" #include /* min and max */ GateApplicationMgr* GateApplicationMgr::instance = 0; @@ -326,6 +327,7 @@ void GateApplicationMgr::StartDAQComplete(G4ThreeVector param) //------------------------------------------------------------------------------------------ + //------------------------------------------------------------------------------------------ void GateApplicationMgr::StartDAQ() { @@ -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++; @@ -428,6 +448,7 @@ void GateApplicationMgr::StartDAQ() //------------------------------------------------------------------------------------------ + //------------------------------------------------------------------------------------------ void GateApplicationMgr::StartDAQCluster(G4ThreeVector param) { diff --git a/source/general/src/GatePrimaryGeneratorAction.cc b/source/general/src/GatePrimaryGeneratorAction.cc index bca4bebbe..31243d376 100644 --- a/source/general/src/GatePrimaryGeneratorAction.cc +++ b/source/general/src/GatePrimaryGeneratorAction.cc @@ -23,8 +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" @@ -66,11 +67,12 @@ void GatePrimaryGeneratorAction::SetVerboseLevel(G4int value) //--------------------------------------------------------------------------- void GatePrimaryGeneratorAction::GeneratePrimaries(G4Event* event) { - // if (GateOutputMgr::GetInstance()->GetDigiMode() == kruntimeMode) - // else - // GenerateDigitisationPrimaries(event); + if (!m_useGPS) { - GenerateSimulationPrimaries(event); + if (GateOutputMgr::GetInstance()->GetDigiMode() == kruntimeMode) + GenerateSimulationPrimaries(event); + else + GenerateDigitisationPrimaries(event); } else { static int i=0; @@ -122,36 +124,65 @@ 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 } -*/ + //--------------------------------------------------------------------------- + + //--------------------------------------------------------------------------- void GatePrimaryGeneratorAction::AddEvent() { From 8837b3649f7aeb87d21a66513d46a73419809539 Mon Sep 17 00:00:00 2001 From: kochebina Date: Thu, 9 Jul 2026 15:37:01 +0200 Subject: [PATCH 2/3] cleaned --- .../src/GateDigitizerInitializationModule.cc | 7 ------ source/digits_hits/src/GateDigitizerMgr.cc | 5 ---- source/digits_hits/src/GateHitFileReader.cc | 24 ++----------------- source/general/src/GateApplicationMgr.cc | 17 ++++++++++++- .../general/src/GatePrimaryGeneratorAction.cc | 17 +------------ 5 files changed, 19 insertions(+), 51 deletions(-) diff --git a/source/digits_hits/src/GateDigitizerInitializationModule.cc b/source/digits_hits/src/GateDigitizerInitializationModule.cc index adf16ae8e..d99e7f992 100644 --- a/source/digits_hits/src/GateDigitizerInitializationModule.cc +++ b/source/digits_hits/src/GateDigitizerInitializationModule.cc @@ -84,13 +84,6 @@ void GateDigitizerInitializationModule::Digitize() else inHC = (GateHitsCollection*)DigiMan->GetHitsCollection(m_HCID); - G4cout << "Retrieved HC = " << inHC - << " entries = " << inHC->entries() - << G4endl; - - - - if (inHC) { diff --git a/source/digits_hits/src/GateDigitizerMgr.cc b/source/digits_hits/src/GateDigitizerMgr.cc index fbfccba1f..18dadf165 100644 --- a/source/digits_hits/src/GateDigitizerMgr.cc +++ b/source/digits_hits/src/GateDigitizerMgr.cc @@ -542,19 +542,14 @@ void GateDigitizerMgr::RunCoincidenceDigitizers() GateHitsCollection* GateDigitizerMgr::GetOfflineHitsCollection() { - G4cout<< "GateDigitizerMgr::GetHitsCollection"<IsOpen())) - { - G4String msg = "Could not open the requested hit file '" + m_fileName + ".root'!"; - G4Exception( "GateHitFileReader::PrepareBeforeAcquisition", "PrepareBeforeAcquisition", FatalException, msg ); - } - */ + if (!m_hitFile || m_hitFile->IsZombie()) { G4String msg = @@ -114,14 +103,6 @@ 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; - - } @@ -138,7 +119,6 @@ void GateHitFileReader::PrepareAcquisition() */ G4int GateHitFileReader::PrepareNextEvent(G4Event* ) { - G4cout << " GateHitFileReader::PrepareNextEvent\n"; for (auto hit : m_hitVector) delete hit; diff --git a/source/general/src/GateApplicationMgr.cc b/source/general/src/GateApplicationMgr.cc index 7aa316f46..4f6141b77 100644 --- a/source/general/src/GateApplicationMgr.cc +++ b/source/general/src/GateApplicationMgr.cc @@ -336,6 +336,21 @@ void GateApplicationMgr::StartDAQ() // filename given. In this case we disable the output module and send a warning. GateOutputMgr::GetInstance()->CheckFileNameForAllOutput(); + if (mOutputMode) + { + + GateMessage("Acquisition", 0," ! OFFLINE DIGI MODE ! \n"); + GateMessage("Acquisition", 0, "============= Source initialization =============\n"); + GateMessage("Acquisition", 0, "IGNORED\n"); + + GateMessage("Acquisition", 0," \n"); + GateMessage("Acquisition", 0, "============= Acquisition starts! =============\n"); + GateMessage("Acquisition", 0, "IGNORED\n"); + + } + else + { + GateMessage("Acquisition", 0," \n"); GateMessage("Acquisition", 0, "============= Source initialization =============\n"); @@ -356,7 +371,7 @@ void GateApplicationMgr::StartDAQ() GateRandomEngine* theRandomEngine = GateRandomEngine::GetInstance(); theRandomEngine->Initialize(); if (theRandomEngine->GetVerbosity()>=1) theRandomEngine->ShowStatus(); - + } GateClock* theClock = GateClock::GetInstance(); m_clusterStart = mTimeSlices.front(); diff --git a/source/general/src/GatePrimaryGeneratorAction.cc b/source/general/src/GatePrimaryGeneratorAction.cc index 31243d376..71e223d8e 100644 --- a/source/general/src/GatePrimaryGeneratorAction.cc +++ b/source/general/src/GatePrimaryGeneratorAction.cc @@ -128,13 +128,11 @@ void GatePrimaryGeneratorAction::GenerateSimulationPrimaries(G4Event* event) //--------------------------------------------------------------------------- void GatePrimaryGeneratorAction::GenerateDigitisationPrimaries(G4Event* event) { - G4cout << "Offline Digi: GenerateDigitisationPrimaries()" << G4endl; #ifdef G4ANALYSIS_USE_ROOT GateHitFileReader* reader = GateHitFileReader::GetInstance(); G4int ok = reader->PrepareNextEvent(event); - G4cout<<"OK ? "<< ok <SetOfflineHitsCollection(nullptr); @@ -150,27 +148,14 @@ void GatePrimaryGeneratorAction::GenerateDigitisationPrimaries(G4Event* event) 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++; + m_nEvents++; /*G4cout << "Finished = " From 68198a4cf51cd6b761d528a0ca827869d0ba14fa Mon Sep 17 00:00:00 2001 From: kochebina Date: Fri, 17 Jul 2026 13:21:50 +0200 Subject: [PATCH 3/3] working version with Hits and Signles --- Gate.cc | 36 +- .../digits_hits/include/GateDigitizerMgr.hh | 15 +- ...FileReader.hh => GateOfflineFileReader.hh} | 74 ++-- ...r.hh => GateOfflineFileReaderMessenger.hh} | 24 +- .../digits_hits/include/GateVOutputModule.hh | 4 +- source/digits_hits/src/GateActions.cc | 5 +- source/digits_hits/src/GateAnalysis.cc | 1 - .../digits_hits/src/GateCoincidenceSorter.cc | 56 +++- .../src/GateDigitizerInitializationModule.cc | 4 +- source/digits_hits/src/GateDigitizerMgr.cc | 29 +- source/digits_hits/src/GateHitFileReader.cc | 221 ------------ .../digits_hits/src/GateOfflineFileReader.cc | 315 ++++++++++++++++++ ...r.cc => GateOfflineFileReaderMessenger.cc} | 14 +- source/digits_hits/src/GateOutputMgr.cc | 8 +- source/digits_hits/src/GateToRoot.cc | 13 +- source/general/include/GateRootDefs.hh | 7 +- source/general/src/GateApplicationMgr.cc | 14 +- .../general/src/GatePrimaryGeneratorAction.cc | 72 +++- source/general/src/GateRootDefs.cc | 140 ++++++++ 19 files changed, 690 insertions(+), 362 deletions(-) rename source/digits_hits/include/{GateHitFileReader.hh => GateOfflineFileReader.hh} (58%) rename source/digits_hits/include/{GateHitFileReaderMessenger.hh => GateOfflineFileReaderMessenger.hh} (54%) delete mode 100644 source/digits_hits/src/GateHitFileReader.cc create mode 100644 source/digits_hits/src/GateOfflineFileReader.cc rename source/digits_hits/src/{GateHitFileReaderMessenger.cc => GateOfflineFileReaderMessenger.cc} (74%) diff --git a/Gate.cc b/Gate.cc index dc7270575..6c8810bfe 100644 --- a/Gate.cc +++ b/Gate.cc @@ -41,7 +41,7 @@ #include "GateUIcontrolMessenger.hh" #ifdef G4ANALYSIS_USE_ROOT #include "TPluginManager.h" -#include "GateHitFileReader.hh" +#include "GateOfflineFileReader.hh" #endif #ifdef G4VIS_USE #include "G4VisExecutive.hh" @@ -69,9 +69,8 @@ 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 FILE use Offline Digi mode with input ROOT file" -<< G4endl ); + GateMessage( "Core", 0, " --d FILE use Offline Digi mode with input ROOT hit file" << G4endl ); + GateMessage( "Core", 0, " --d-from-singles FILE use Offline Digi mode with input ROOT singles file" << G4endl ); GateMessage( "Core", 0, " --qt use the Qt visualization mode" << G4endl ); exit( EXIT_FAILURE ); } @@ -217,7 +216,8 @@ int main( int argc, char* argv[] ) static struct option longOptions[] = { { "help", no_argument, 0, 'h' }, { "version", no_argument, 0, 'v' }, - { "d", required_argument, 0, 'd' }, + { "d-fromHits", required_argument, 0, 'd' }, + { "d-fromSingles", required_argument, 0, 's' }, { "qt", no_argument, &isQt, 1 }, { "param", required_argument, 0, 'a' } }; @@ -265,19 +265,25 @@ int main( int argc, char* argv[] ) case 'a': listOfParameters = optarg; break; - case 'd': - isDigiMode = 1; - digiInputFile = optarg; - break; - default: + case 'd': + isDigiMode = 1; + digiInputFile = optarg; + break; + case 's': + isDigiMode = 2; + digiInputFile = optarg; + break; + default: printHelpAndQuit( "Out of switch options" ); break; } } // Checking if the DigiMode is activated - if( isDigiMode ) - aDigiMode = kofflineMode; + if (isDigiMode == 1) + aDigiMode = kofflineMode; + else if (isDigiMode == 2) + aDigiMode = kofflineSinglesMode; if (isDigiMode) { @@ -288,8 +294,8 @@ int main( int argc, char* argv[] ) return EXIT_FAILURE; } - GateHitFileReader::GetInstance()->SetFileName(digiInputFile); - GateDigitizerMgr::GetInstance()->SetOfflineMode(true); + GateOfflineFileReader::GetInstance()->SetFileName(digiInputFile); + GateDigitizerMgr::GetInstance()->SetOfflineMode(aDigiMode); } // Analyzing parameterized macro std::queue< G4String > commandQueue = decodeParameters( listOfParameters ); @@ -337,7 +343,7 @@ int main( int argc, char* argv[] ) if( aDigiMode == kofflineMode ) #ifdef G4ANALYSIS_USE_ROOT - GateHitFileReader::GetInstance(); + GateOfflineFileReader::GetInstance(); #else abortIfRootNotFound(); #endif diff --git a/source/digits_hits/include/GateDigitizerMgr.hh b/source/digits_hits/include/GateDigitizerMgr.hh index 7b22066d0..48c6d15ec 100644 --- a/source/digits_hits/include/GateDigitizerMgr.hh +++ b/source/digits_hits/include/GateDigitizerMgr.hh @@ -36,7 +36,7 @@ #include "GateCoinDigitizerInitializationModule.hh" #include "GateCoincidenceDigitizer.hh" - +#include "GateVOutputModule.hh" class GateDigitizerMgrMessenger; class GateVSystem; @@ -108,15 +108,17 @@ public: //Methods for OfflineDigi - void SetOfflineMode(bool b) { mOfflineMode = b; } - bool IsOfflineMode() const { return mOfflineMode; } + void SetOfflineMode(DigiMode mode) { mOfflineMode = mode; } + DigiMode GetDigiMode() const { return mOfflineMode;} - GateHitsCollection* GetOfflineHitsCollection(); + GateHitsCollection* GetOfflineHitsCollection(); void SetOfflineHitsCollection(GateHitsCollection* hc); void ClearOfflineHitsCollection(); - + GateDigiCollection* GetOfflineDigiCollection(); + void SetOfflineDigiCollection(GateDigiCollection* hc); + void ClearOfflineDigiCollection(); private: @@ -124,7 +126,8 @@ private: GateDigitizerMgrMessenger *fMessenger; GateHitsCollection* mOfflineHitsCollection = nullptr; - bool mOfflineMode = false; + GateDigiCollection* mOfflineDigiCollection = nullptr; + DigiMode mOfflineMode = kruntimeMode; // = false; static GateDigitizerMgr* theDigitizerMgr; protected: diff --git a/source/digits_hits/include/GateHitFileReader.hh b/source/digits_hits/include/GateOfflineFileReader.hh similarity index 58% rename from source/digits_hits/include/GateHitFileReader.hh rename to source/digits_hits/include/GateOfflineFileReader.hh index a8530bae2..da9eef289 100644 --- a/source/digits_hits/include/GateHitFileReader.hh +++ b/source/digits_hits/include/GateOfflineFileReader.hh @@ -7,8 +7,8 @@ See LICENSE.md for further details ----------------------*/ -#ifndef GateHitFileReader_h -#define GateHitFileReader_h 1 +#ifndef GateOfflineFileReader_h +#define GateOfflineFileReader_h 1 #include "GateConfiguration.h" @@ -30,33 +30,33 @@ class GateHit; #include "GateRootDefs.hh" #include "GateClockDependent.hh" -class GateHitFileReaderMessenger; +class GateOfflineFileReaderMessenger; -/*! \class GateHitFileReader +/*! \class GateOfflineFileReader \brief Reads hits data from a ROOT simulation-output file and recreates hit-collections for digitisation - - GateHitFileReader - by Daniel.Strul@iphe.unil.ch (Oct. 2002) + - GateOfflineFileReader - by Daniel.Strul@iphe.unil.ch (Oct. 2002) - - The GateHitFileReader is a singleton. It is designed to be used in the DigiGate mode. - In this mode, the GateHitFileReader will read hits data from a ROOT simulation-output file. + - The GateOfflineFileReader is a singleton. It is designed to be used in the DigiGate mode. + In this mode, the GateOfflineFileReader will read hits data from a ROOT simulation-output file. Based on these data, it will recreate hit-collections that can be fed to the digitizer to reprocess the hits. */ -class GateHitFileReader : public GateClockDependent +class GateOfflineFileReader : public GateClockDependent { public: - /*! This function allows to retrieve the current instance of the GateHitFileReader singleton + /*! This function allows to retrieve the current instance of the GateOfflineFileReader singleton - If the GateHitFileReader already exists, GetInstance only returns a pointer to this singleton. + If the GateOfflineFileReader already exists, GetInstance only returns a pointer to this singleton. If this singleton does not exist yet, GetInstance creates it by calling the private - GateHitFileReader constructor + GateOfflineFileReader constructor */ - static GateHitFileReader* GetInstance(); + static GateOfflineFileReader* GetInstance(); - ~GateHitFileReader(); //!< Public destructor + ~GateOfflineFileReader(); //!< Public destructor private: - GateHitFileReader(); //!< Private constructor: this function should only be called from GetInstance() + GateOfflineFileReader(); //!< Private constructor: this function should only be called from GetInstance() public: //! This method must be called (normally by the application manager) before starting a new DigiGate acquisition @@ -68,12 +68,8 @@ public: \returns 1 -> series of hits OK for the current run, 0 -> either no hits or series of hits for the NEXT run */ - G4int PrepareNextEvent(G4Event* event); - - //! 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(); - + G4int PrepareNextEventFromHits(G4Event* event); + G4int PrepareNextEventFromSingles(G4Event* event); //! This method must be called (normally by the application manager) after completion of a DigiGate acquisition //! It closes the ROOT input file @@ -91,48 +87,48 @@ public: virtual void Describe(size_t indent=0); - const std::vector& GetHitVector() const - { - return m_hitVector; - } + const std::vector& GetHitVector() const { return m_hitVector;} + std::vector& GetHitVector() { return m_hitVector; } - std::vector& GetHitVector() - { - return m_hitVector; - } + const std::vector& GetDigiVector() const { return m_digiVector;} + std::vector& GetDigiVector() { return m_digiVector; } - bool IsFinished() const - { - return m_finished; - } + bool IsFinished() const { return m_finished; } protected: //! Reads a set of hit data from the hit-tree, and stores them into the root-hit buffer void LoadHitData(); - + void LoadSinglesData(); protected: - + bool m_finished; G4String m_fileName; //!< Name of the input hit-file - TFile* m_hitFile; //!< the input hit file + TFile* m_inptuFile; //!< the input hit file - TTree* m_hitTree; //!< the input hit tree + TTree* m_inputTree; //!< the input hit tree Stat_t m_entries; //!< Number of entries in the tree G4int m_currentEntry; //!< Current entry in the tree + GateRootHitBuffer m_hitBuffer; //!< Buffer to store the data read from the hit-tree //!< Each field of this structure is a buffer for one of the branches of the tree //!< The hit-data are loaded into this buffer by LoadHitData() //!< They are then transformed into a crystal-hit by PrepareNextEvent() + GateRootSingleBuffer m_singleBuffer; //!< Buffer to store the data read from the hit-tree + //!< Each field of this structure is a buffer for one of the branches of the tree + //!< The hit-data are loaded into this buffer by LoadHitData() + //!< They are then transformed into a crystal-hit by PrepareNextEvent() + std::vector m_hitVector; + std::vector m_digiVector; + - GateHitFileReaderMessenger *m_messenger; //!< Messenger; + GateOfflineFileReaderMessenger *m_messenger; //!< Messenger; private: - static GateHitFileReader* instance; //!< Instance of the GateHitFielReader singleton - bool m_finished; + static GateOfflineFileReader* instance; //!< Instance of the GateHitFielReader singleton }; #endif diff --git a/source/digits_hits/include/GateHitFileReaderMessenger.hh b/source/digits_hits/include/GateOfflineFileReaderMessenger.hh similarity index 54% rename from source/digits_hits/include/GateHitFileReaderMessenger.hh rename to source/digits_hits/include/GateOfflineFileReaderMessenger.hh index dc939833f..f8180fa42 100644 --- a/source/digits_hits/include/GateHitFileReaderMessenger.hh +++ b/source/digits_hits/include/GateOfflineFileReaderMessenger.hh @@ -7,8 +7,8 @@ See LICENSE.md for further details ----------------------*/ -#ifndef GateHitFileReaderMessenger_h -#define GateHitFileReaderMessenger_h 1 +#ifndef GateOfflineFileReaderMessenger_h +#define GateOfflineFileReaderMessenger_h 1 #include "GateConfiguration.h" @@ -16,15 +16,15 @@ See LICENSE.md for further details #include "GateClockDependentMessenger.hh" -class GateHitFileReader; +class GateOfflineFileReader; -/*! \class GateHitFileReaderMessenger - \brief Messenger used to command a GateHitFileReader +/*! \class GateOfflineFileReaderMessenger + \brief Messenger used to command a GateOfflineFileReader - - GateHitFileReaderMessenger - by Daniel.Strul@iphe.unil.ch + - GateOfflineFileReaderMessenger - by Daniel.Strul@iphe.unil.ch - - The GateHitFileReaderMessenger inherits from the abilities/responsabilities + - The GateOfflineFileReaderMessenger inherits from the abilities/responsabilities of the GateClockDependentMessenger base-class, i.e. the creation and management of a Gate UI directory for a Gate object, plus the UI command 'describe' @@ -32,17 +32,17 @@ class GateHitFileReader; definition of the name of the hit file */ -class GateHitFileReaderMessenger: public GateClockDependentMessenger +class GateOfflineFileReaderMessenger: public GateClockDependentMessenger { public: - GateHitFileReaderMessenger(GateHitFileReader* itsHitFileReader); - ~GateHitFileReaderMessenger(); + GateOfflineFileReaderMessenger(GateOfflineFileReader* itsOfflineFileReader); + ~GateOfflineFileReaderMessenger(); void SetNewValue(G4UIcommand*, G4String); //! Get the clock-dependent object - inline GateHitFileReader* GetHitFileReader() - { return (GateHitFileReader*) GetClockDependent(); } + inline GateOfflineFileReader* GetOfflineFileReader() + { return (GateOfflineFileReader*) GetClockDependent(); } protected: G4UIcmdWithAString* SetFileNameCmd; diff --git a/source/digits_hits/include/GateVOutputModule.hh b/source/digits_hits/include/GateVOutputModule.hh index 01bc12271..9d7aa4bfe 100644 --- a/source/digits_hits/include/GateVOutputModule.hh +++ b/source/digits_hits/include/GateVOutputModule.hh @@ -26,7 +26,9 @@ class GateVVolume; enum DigiMode { kruntimeMode, - kofflineMode + kofflineMode, // Hits -> Singles -> Coincidences + kofflineSinglesMode // Singles -> Coincidences, + }; class GateVOutputModule diff --git a/source/digits_hits/src/GateActions.cc b/source/digits_hits/src/GateActions.cc index 415baabbc..83702df12 100644 --- a/source/digits_hits/src/GateActions.cc +++ b/source/digits_hits/src/GateActions.cc @@ -191,10 +191,7 @@ inline void GateEventAction::EndOfEventAction(const G4Event* anEvent) { GateMessage("Core", 2, "End Of Event " << anEvent->GetEventID() << "\n"); - //OK GND 2022 TODO - //I would like to RunDigitizers here but some aHit attributes are filled in OutputMng/GateAnalysis->RecordEndOfEvent - //GateDigitizerMgr* digitizerMgr = GateDigitizerMgr::GetInstance(); - // digitizerMgr->RunDigitizers(); + #ifdef G4ANALYSIS_USE_GENERAL // Here we fill the histograms of the OutputMgr manager diff --git a/source/digits_hits/src/GateAnalysis.cc b/source/digits_hits/src/GateAnalysis.cc index 27026d8c9..d705f5c9d 100644 --- a/source/digits_hits/src/GateAnalysis.cc +++ b/source/digits_hits/src/GateAnalysis.cc @@ -726,7 +726,6 @@ void GateAnalysis::RecordEndOfEvent(const G4Event* event) if(!digitizerMgr->m_alreadyRun) { - if (digitizerMgr->m_recordSingles|| digitizerMgr->m_recordCoincidences) { diff --git a/source/digits_hits/src/GateCoincidenceSorter.cc b/source/digits_hits/src/GateCoincidenceSorter.cc index 061068b77..4a52c0e0b 100644 --- a/source/digits_hits/src/GateCoincidenceSorter.cc +++ b/source/digits_hits/src/GateCoincidenceSorter.cc @@ -180,11 +180,9 @@ void GateCoincidenceSorter::SetAcceptancePolicy4CC(const G4String &policy) void GateCoincidenceSorter::Digitize() { - // G4cout<<"GateCoincidenceSorter::Digitize "<< GetOutputName() <::iterator buf_iter; // presort buffer iterator @@ -205,21 +203,35 @@ void GateCoincidenceSorter::Digitize() //G4cout<<"Unindefined system"<GetSystem(); } - //G4cout<GetName()<m_outputDigiCollectionID; //G4cout<<"inputCollID "<GetDigiCollection(inputCollID)); + GateDigiCollection* IDC; + + if (GateDigitizerMgr::GetInstance()->GetDigiMode() == kofflineSinglesMode && + digitizerMgr->GetOfflineDigiCollection() == nullptr) + { + GateMessage("OfflineDigi", 1, + "No offline singles, skipping digitization."); + return; + } + + + if (GateDigitizerMgr::GetInstance()->GetDigiMode() == kofflineSinglesMode) + IDC = digitizerMgr->GetOfflineDigiCollection(); + else + IDC = (GateDigiCollection*)fDM->GetDigiCollection(inputCollID); + if (!IDC) return ; + std::vector< GateDigi* >* IDCvector = IDC->GetVector (); std::vector::iterator gpl_iter; + //Output digi collection m_OutputCoincidenceDigiCollection = new GateCoincidenceDigiCollection("GateCoincidenceSorter",m_outputName); // to create the Digi Collection @@ -227,7 +239,7 @@ void GateCoincidenceSorter::Digitize() if (!IsEnabled()) return; - + if(m_eventIDCoinc){ GateCoincidenceDigi *coincidence; @@ -247,6 +259,15 @@ void GateCoincidenceSorter::Digitize() for(gpl_iter = IDCvector->begin();gpl_iter != IDCvector->end();gpl_iter++) { digi = new GateDigi(**gpl_iter); + + if (GateDigitizerMgr::GetInstance()->GetDigiMode() == kofflineMode || GateDigitizerMgr::GetInstance()->GetDigiMode() == kofflineSinglesMode) + { + //G4cout<<"Setting system ID 2 "<< m_system->GetItsNumber()<SetSystemID(m_system->GetItsNumber()); + digi->SetOutputVolumeID(m_system->ComputeOutputVolumeID(digi->GetVolumeID())); + } + + if(!isCoincCreated){ isCoincCreated=true; coincidence = new GateCoincidenceDigi(digi,window,offset); @@ -282,7 +303,13 @@ void GateCoincidenceSorter::Digitize() { // make a copy of the digi digi = new GateDigi(**gpl_iter); - + if (GateDigitizerMgr::GetInstance()->GetDigiMode() != kruntimeMode ) + { + //G4cout<<"Setting system ID 3 "<< m_system->GetItsNumber()<SetSystemID(m_system->GetItsNumber()); + //G4cout<<"Volume ID "<GetVolumeID()<SetOutputVolumeID(m_system->ComputeOutputVolumeID(digi->GetVolumeID())); + } if(m_presortBuffer.empty()) 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 @@ -374,7 +401,6 @@ void GateCoincidenceSorter::Digitize() } delete digi; } - StoreDigiCollection(m_OutputCoincidenceDigiCollection); } @@ -414,6 +440,7 @@ void GateCoincidenceSorter::ProcessCompletedCoincidenceWindow4CC(GateCoincidence // look for valid coincidences bool GateCoincidenceSorter::ProcessCompletedCoincidenceWindow(GateCoincidenceDigi *coincidence) { + G4int i, j, nDigis; G4int nGoods, maxGoods; G4double E, maxE; @@ -460,9 +487,10 @@ bool GateCoincidenceSorter::ProcessCompletedCoincidenceWindow(GateCoincidenceDig // count the goods (iterate over all pairs because we're considering the multi as a unit, not breaking it up into pairs) nGoods = 0; for(i=0; i<(coincidence->IsDelayed()?1:(nDigis-1)); i++) - for(j=i+1; jat(i),coincidence->at(j))) nGoods++; + } if( nGoods == 0 ) // all of the remaining options expect at least one good { @@ -545,12 +573,12 @@ bool GateCoincidenceSorter::ProcessCompletedCoincidenceWindow(GateCoincidenceDig } } maxGoods = PairWithFirstDigiOnly?(nDigis-1):(nDigis*(nDigis-1)/2); - if(m_multiplesPolicy==kTakeWinnerIfAllAreGoods) + + if(m_multiplesPolicy==kTakeWinnerIfAllAreGoods)/// Default { if(nGoods==maxGoods) { - m_OutputCoincidenceDigiCollection->insert(CreateSubDigi(coincidence, winner_i, winner_j)); - + m_OutputCoincidenceDigiCollection->insert(CreateSubDigi(coincidence, winner_i, winner_j)); return false; } else { diff --git a/source/digits_hits/src/GateDigitizerInitializationModule.cc b/source/digits_hits/src/GateDigitizerInitializationModule.cc index d99e7f992..9815536d9 100644 --- a/source/digits_hits/src/GateDigitizerInitializationModule.cc +++ b/source/digits_hits/src/GateDigitizerInitializationModule.cc @@ -70,7 +70,7 @@ void GateDigitizerInitializationModule::Digitize() GateDigitizerMgr* digitizerMgr=GateDigitizerMgr::GetInstance(); - if (GateDigitizerMgr::GetInstance()->IsOfflineMode() && + if (GateDigitizerMgr::GetInstance()->GetDigiMode() == kofflineMode && digitizerMgr->GetOfflineHitsCollection() == nullptr) { GateMessage("OfflineDigi", 1, @@ -79,7 +79,7 @@ void GateDigitizerInitializationModule::Digitize() } - if (GateDigitizerMgr::GetInstance()->IsOfflineMode()) + if (GateDigitizerMgr::GetInstance()->GetDigiMode() == kofflineMode) inHC = digitizerMgr->GetOfflineHitsCollection(); else inHC = (GateHitsCollection*)DigiMan->GetHitsCollection(m_HCID); diff --git a/source/digits_hits/src/GateDigitizerMgr.cc b/source/digits_hits/src/GateDigitizerMgr.cc index 18dadf165..60858ed86 100644 --- a/source/digits_hits/src/GateDigitizerMgr.cc +++ b/source/digits_hits/src/GateDigitizerMgr.cc @@ -20,6 +20,7 @@ #include "GateDigitizerMgrMessenger.hh" #include "GateDigitizerInitializationModule.hh" #include "GateHit.hh" +#include "GateDigi.hh" #include "GateOutputMgr.hh" #include "GateToRoot.hh" @@ -541,13 +542,10 @@ void GateDigitizerMgr::RunCoincidenceDigitizers() GateHitsCollection* GateDigitizerMgr::GetOfflineHitsCollection() { - if (mOfflineHitsCollection) return mOfflineHitsCollection; - } - void GateDigitizerMgr::SetOfflineHitsCollection(GateHitsCollection* hc) { if (mOfflineHitsCollection) @@ -556,7 +554,6 @@ void GateDigitizerMgr::SetOfflineHitsCollection(GateHitsCollection* hc) mOfflineHitsCollection = hc; } - void GateDigitizerMgr::ClearOfflineHitsCollection() { delete mOfflineHitsCollection; @@ -564,6 +561,30 @@ void GateDigitizerMgr::ClearOfflineHitsCollection() } +GateDigiCollection* GateDigitizerMgr::GetOfflineDigiCollection() +{ + if (mOfflineDigiCollection) + return mOfflineDigiCollection; +} + + +void GateDigitizerMgr::SetOfflineDigiCollection(GateDigiCollection* hc) +{ + if (mOfflineDigiCollection) + delete mOfflineDigiCollection; + + mOfflineDigiCollection = hc; +} + + +void GateDigitizerMgr::ClearOfflineDigiCollection() +{ + delete mOfflineDigiCollection; + mOfflineDigiCollection = nullptr; +} + + + diff --git a/source/digits_hits/src/GateHitFileReader.cc b/source/digits_hits/src/GateHitFileReader.cc deleted file mode 100644 index 8a0ffd64a..000000000 --- a/source/digits_hits/src/GateHitFileReader.cc +++ /dev/null @@ -1,221 +0,0 @@ -/*---------------------- - Copyright (C): OpenGATE Collaboration - -This software is distributed under the terms -of the GNU Lesser General Public Licence (LGPL) -See LICENSE.md for further details -----------------------*/ - -#include "GateHitFileReader.hh" - -#ifdef G4ANALYSIS_USE_ROOT - -#include "TBranch.h" -#include "GateHit.hh" -#include "GateOutputVolumeID.hh" -#include "GateOutputMgr.hh" -#include "GateTools.hh" -#include "GateHitFileReaderMessenger.hh" -#include "GateHitConvertor.hh" - -GateHitFileReader* GateHitFileReader::instance = 0; - -// Private constructor: this function should only be called from GetInstance() -GateHitFileReader::GateHitFileReader() - : GateClockDependent("hitreader",false) - , m_fileName("gate.root") - , m_hitFile(0) - , m_hitTree(0) - , m_entries(0) - , m_currentEntry(0) - , m_finished(false) -{ - // Clear the root-hit structure - m_hitBuffer.Clear(); - - // Create the messenger; - m_messenger = new GateHitFileReaderMessenger(this); -} - - - - - -// Public destructor -GateHitFileReader::~GateHitFileReader() -{ - // Clear the file and the queue if it was still open - TerminateAfterAcquisition(); - - // delete the messenger - delete m_messenger; -} - - - - -/* This function allows to retrieve the current instance of the GateHitFileReader singleton - - If the GateHitFileReader already exists, GetInstance only returns a pointer to this singleton. - If this singleton does not exist yet, GetInstance creates it by calling the private - GateHitFileReader constructor -*/ -GateHitFileReader* GateHitFileReader::GetInstance() -{ - if (instance == 0) - instance = new GateHitFileReader(); - return instance; -} - - - - - -// This method must be called (normally by the application manager) before starting a new DigiGate acquisition -void GateHitFileReader::PrepareAcquisition() -{ - m_finished = false; - // Open the input file - - m_hitFile = TFile::Open(m_fileName.c_str(), "READ"); - - if (!m_hitFile || m_hitFile->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 + "'!"; - G4Exception( "GateHitFileReader::PrepareBeforeAcquisition", "PrepareBeforeAcquisition", FatalException, msg); - } - // Reset the entry counters - m_currentEntry=0; - m_entries = m_hitTree->GetEntries(); - - - // Set the addresses of the branch buffers: each buffer is a field of the root-hit structure - GateHitTree::SetBranchAddresses(m_hitTree,m_hitBuffer); - - // Load the first hit into the root-hit structure - LoadHitData(); - -} - - - - -/* This method is meant to be called by the primary generator action at the beginning of each event. - It read a series of hit data from the ROOT file, and stores them into a queue of hits/ - - It returns 1 if it managed to read a series of hits for the current run - It can return 0 in two cases: - - either it failed to read a series of hits (end-of-file) - - or the series of hits has a different runID from the current runID, so that this series - should not be used for the current run but rather for a later run -*/ -G4int GateHitFileReader::PrepareNextEvent(G4Event* ) -{ - - for (auto hit : m_hitVector) - delete hit; - - m_hitVector.clear(); - - // 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) ) - { - 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_hitVector.push_back(aHit); - - // Load the next set of hit-data into the root-hit structure - LoadHitData(); - } - - if (!m_hitVector.empty()) - return 1; - return 0; -} - - - - - -// This method must be called (normally by the application manager) after completion of a DigiGate acquisition -// It closes the ROOT input file -void GateHitFileReader::TerminateAfterAcquisition() -{ - // Close the file - if (m_hitFile) { - delete m_hitFile; - m_hitFile=0; - } - - 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?) - m_hitTree=0; -} - - - -// 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; - m_hitBuffer.eventID=-1; - return; - } - - // Read a new set of hit-data: if it failed, set indicators to tell the caller that the reading failed - if (m_hitTree->GetEntry(m_currentEntry++)<=0) { - G4cerr << "[GateHitFileReader::LoadHitData]:\n" - << "\tCould not read the next hit!\n"; - m_hitBuffer.runID=-1; - m_hitBuffer.eventID=-1; - } -} - - - - - -/* Overload of the base-class virtual method to print-out a description of the reader - - indent: the print-out indentation (cosmetic parameter) -*/ -void GateHitFileReader::Describe(size_t indent) -{ - GateClockDependent::Describe(indent); - G4cout << GateTools::Indent(indent) << "Hit-file name: " << m_fileName << Gateendl; - G4cout << GateTools::Indent(indent) << "Hit-file status: " << (m_hitFile ? "open" : "closed" ) << Gateendl; - if (m_hitTree) { - G4cout << GateTools::Indent(indent) << "Hit-tree entries: " << m_entries << Gateendl; - G4cout << GateTools::Indent(indent) << "Current entry: " << m_currentEntry << Gateendl; - } -} - - -#endif diff --git a/source/digits_hits/src/GateOfflineFileReader.cc b/source/digits_hits/src/GateOfflineFileReader.cc new file mode 100644 index 000000000..2e9055923 --- /dev/null +++ b/source/digits_hits/src/GateOfflineFileReader.cc @@ -0,0 +1,315 @@ +/*---------------------- + Copyright (C): OpenGATE Collaboration + +This software is distributed under the terms +of the GNU Lesser General Public Licence (LGPL) +See LICENSE.md for further details +----------------------*/ + +#include "GateOfflineFileReader.hh" + +#ifdef G4ANALYSIS_USE_ROOT + +#include "TBranch.h" +#include "GateHit.hh" +#include "GateOutputVolumeID.hh" +#include "GateOutputMgr.hh" +#include "GateTools.hh" +#include "GateOfflineFileReaderMessenger.hh" + +GateOfflineFileReader* GateOfflineFileReader::instance = 0; + +// Private constructor: this function should only be called from GetInstance() +GateOfflineFileReader::GateOfflineFileReader() + : GateClockDependent("hitreader",false) + , m_fileName("gate.root") + , m_inptuFile(0) + , m_inputTree(0) + , m_entries(0) + , m_currentEntry(0) + , m_finished(false) +{ + // Clear the root file structure + m_hitBuffer.Clear(); + m_singleBuffer.Clear(); + + // Create the messenger; + m_messenger = new GateOfflineFileReaderMessenger(this); +} + + + + + +// Public destructor +GateOfflineFileReader::~GateOfflineFileReader() +{ + // Clear the file and the queue if it was still open + TerminateAfterAcquisition(); + + // delete the messenger + delete m_messenger; +} + + + + +/* This function allows to retrieve the current instance of the GateOfflineFileReader singleton + + If the GateOfflineFileReader already exists, GetInstance only returns a pointer to this singleton. + If this singleton does not exist yet, GetInstance creates it by calling the private + GateOfflineFileReader constructor +*/ +GateOfflineFileReader* GateOfflineFileReader::GetInstance() +{ + if (instance == 0) + instance = new GateOfflineFileReader(); + return instance; +} + + + + + +// This method must be called (normally by the application manager) before starting a new DigiGate acquisition +void GateOfflineFileReader::PrepareAcquisition() +{ + + //G4cout<<"GateOfflineFileReader::PrepareAcquisition "<< G4endl; + m_finished = false; + // Open the input file + + m_inptuFile = TFile::Open(m_fileName.c_str(), "READ"); + + if (!m_inptuFile || m_inptuFile->IsZombie()) + { + G4String msg = + "Could not open hit file '" + m_fileName + "'"; + G4Exception("GateOfflineFileReader::PrepareBeforeAcquisition", "PrepareBeforeAcquisition", FatalException, msg); + } + // Get the hit tree + if (GateOutputMgr::GetInstance()->GetDigiMode()==kofflineMode ) + { + m_inputTree = (TTree*)( m_inptuFile->Get("Hits")) ; + } + else + { + m_inputTree = (TTree*)( m_inptuFile->Get("Singles")) ; + } + +// G4cout<<"m_inputTree "<Get("Hits")) ; + + if (!m_inputTree) + { + G4String msg = "Could not find a tree of hits in the ROOT file '" + m_fileName + "'!"; + G4Exception( "GateOfflineFileReader::PrepareBeforeAcquisition", "PrepareBeforeAcquisition", FatalException, msg); + } + // Reset the entry counters + m_currentEntry=0; + m_entries = m_inputTree->GetEntries(); + + + // Set the addresses of the branch buffers: each buffer is a field of the root-hit structure + if (GateOutputMgr::GetInstance()->GetDigiMode()==kofflineMode) + GateHitTree::SetBranchAddresses(m_inputTree,m_hitBuffer); + else + GateSingleTree::SetBranchAddresses(m_inputTree,m_singleBuffer); + + + //GateHitTree::SetBranchAddresses(m_inputTree,m_hitBuffer); + + // Load the first hit into the root-hit structure + if (GateOutputMgr::GetInstance()->GetDigiMode()==kofflineMode) + LoadHitData(); + else + LoadSinglesData(); + + +} + + + + +/* This method is meant to be called by the primary generator action at the beginning of each event. + It read a series of hit data from the ROOT file, and stores them into a queue of hits/ + + It returns 1 if it managed to read a series of hits for the current run + It can return 0 in two cases: + - either it failed to read a series of hits (end-of-file) + - or the series of hits has a different runID from the current runID, so that this series + should not be used for the current run but rather for a later run +*/ +G4int GateOfflineFileReader::PrepareNextEventFromHits(G4Event* ) +{ + + //G4cout<<"GateOfflineFileReader::PrepareNextEvent "<GetDigiMode()==kofflineMode ) + { + for (auto hit : m_hitVector) + delete hit; + m_hitVector.clear(); + } + else + { + for (auto digi : m_digiVector) + delete digi; + m_digiVector.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?) + m_inputTree=0; +} + + + +// Reads a set of hit data from the hit-tree, and stores them into the root-hit buffer +void GateOfflineFileReader::LoadHitData() +{ + + //G4cout<<"GateOfflineFileReader::LoadHitData "<< m_entries <=m_entries){ + m_hitBuffer.runID=-1; + m_hitBuffer.eventID=-1; + return; + } + + // Read a new set of hit-data: if it failed, set indicators to tell the caller that the reading failed + if (m_inputTree->GetEntry(m_currentEntry++)<=0) { + G4cerr << "[GateOfflineFileReader::LoadHitData]:\n" + << "\tCould not read the next hit!\n"; + m_hitBuffer.runID=-1; + m_hitBuffer.eventID=-1; + } +} + +// Reads a set of hit data from the hit-tree, and stores them into the root-hit buffer +void GateOfflineFileReader::LoadSinglesData() +{ + + //G4cout<<"GateOfflineFileReader::LoadSinglesData "<< m_entries <=m_entries){ + m_singleBuffer.runID=-1; + m_singleBuffer.eventID=-1; + return; + } + + // Read a new set of Singles-data: if it failed, set indicators to tell the caller that the reading failed + if (m_inputTree->GetEntry(m_currentEntry++)<=0) { + G4cerr << "[GateOfflineFileReader::LoadSinglesData]:\n" + << "\tCould not read the next Singles!\n"; + m_singleBuffer.runID=-1; + m_singleBuffer.eventID=-1; + } +} + + + +/* Overload of the base-class virtual method to print-out a description of the reader + + indent: the print-out indentation (cosmetic parameter) +*/ +void GateOfflineFileReader::Describe(size_t indent) +{ + GateClockDependent::Describe(indent); + G4cout << GateTools::Indent(indent) << "Input file name: " << m_fileName << Gateendl; + G4cout << GateTools::Indent(indent) << "Input file status: " << (m_inptuFile ? "open" : "closed" ) << Gateendl; + if (m_inputTree) { + G4cout << GateTools::Indent(indent) << "Input tree entries: " << m_entries << Gateendl; + G4cout << GateTools::Indent(indent) << "Current entry: " << m_currentEntry << Gateendl; + } +} + + +#endif diff --git a/source/digits_hits/src/GateHitFileReaderMessenger.cc b/source/digits_hits/src/GateOfflineFileReaderMessenger.cc similarity index 74% rename from source/digits_hits/src/GateHitFileReaderMessenger.cc rename to source/digits_hits/src/GateOfflineFileReaderMessenger.cc index a4a1fe05c..64875444f 100644 --- a/source/digits_hits/src/GateHitFileReaderMessenger.cc +++ b/source/digits_hits/src/GateOfflineFileReaderMessenger.cc @@ -6,11 +6,11 @@ of the GNU Lesser General Public Licence (LGPL) See LICENSE.md for further details ----------------------*/ -#include "GateHitFileReaderMessenger.hh" +#include "../include/GateOfflineFileReaderMessenger.hh" #ifdef G4ANALYSIS_USE_ROOT -#include "GateHitFileReader.hh" +#include "GateOfflineFileReader.hh" #include "G4UIdirectory.hh" #include "G4UIcmdWithAString.hh" #include "G4UIcmdWithAnInteger.hh" @@ -22,8 +22,8 @@ See LICENSE.md for further details //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... -GateHitFileReaderMessenger::GateHitFileReaderMessenger(GateHitFileReader* itsHitFileReader) - : GateClockDependentMessenger(itsHitFileReader) +GateOfflineFileReaderMessenger::GateOfflineFileReaderMessenger(GateOfflineFileReader* itsOfflineFileReader) + : GateClockDependentMessenger(itsOfflineFileReader) { SetDirectoryGuidance("Control the parameters of the hit-file reader used for DigiGate"); @@ -38,17 +38,17 @@ GateHitFileReaderMessenger::GateHitFileReaderMessenger(GateHitFileReader* itsHit //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... -GateHitFileReaderMessenger::~GateHitFileReaderMessenger() +GateOfflineFileReaderMessenger::~GateOfflineFileReaderMessenger() { delete SetFileNameCmd; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... -void GateHitFileReaderMessenger::SetNewValue(G4UIcommand* command,G4String newValue) +void GateOfflineFileReaderMessenger::SetNewValue(G4UIcommand* command,G4String newValue) { if (command == SetFileNameCmd) - GetHitFileReader()->SetFileName(newValue); + GetOfflineFileReader()->SetFileName(newValue); else GateClockDependentMessenger::SetNewValue(command,newValue); diff --git a/source/digits_hits/src/GateOutputMgr.cc b/source/digits_hits/src/GateOutputMgr.cc index bc8226dbd..af05cc49b 100644 --- a/source/digits_hits/src/GateOutputMgr.cc +++ b/source/digits_hits/src/GateOutputMgr.cc @@ -35,7 +35,7 @@ #include "GateDigitizer.hh" #include "GateCrystalSD.hh" #include "GatePhantomSD.hh" -#include "GateHitFileReader.hh" +#include "../include/GateOfflineFileReader.hh" #include "GateRandomEngine.hh" #include "GateARFDataToRoot.hh" #include "GateToRoot.hh" @@ -283,8 +283,8 @@ void GateOutputMgr::RecordBeginOfAcquisition() #ifdef G4ANALYSIS_USE_ROOT - if (m_digiMode==kofflineMode) - GateHitFileReader::GetInstance()->PrepareAcquisition(); + if (m_digiMode==kofflineMode||m_digiMode==kofflineSinglesMode) + GateOfflineFileReader::GetInstance()->PrepareAcquisition(); #endif @@ -317,7 +317,7 @@ void GateOutputMgr::RecordEndOfAcquisition() #ifdef G4ANALYSIS_USE_ROOT if (m_digiMode==kofflineMode) - GateHitFileReader::GetInstance()->TerminateAfterAcquisition(); + GateOfflineFileReader::GetInstance()->TerminateAfterAcquisition(); #endif m_acquisitionStarted = false; diff --git a/source/digits_hits/src/GateToRoot.cc b/source/digits_hits/src/GateToRoot.cc index 5f3c5a374..24c19de81 100644 --- a/source/digits_hits/src/GateToRoot.cc +++ b/source/digits_hits/src/GateToRoot.cc @@ -54,7 +54,7 @@ #include "GateVVolume.hh" #include "GateToRootMessenger.hh" #include "GateVGeometryVoxelStore.hh" -#include "GateHitFileReader.hh" +#include "GateOfflineFileReader.hh" #include "TROOT.h" #include "TApplication.h" @@ -378,9 +378,9 @@ void GateToRoot::RecordBeginOfAcquisition() { // Open the output file if (nVerboseLevel > 0) G4cout << "GateToRoot: ROOT: files creation...\n"; - if (m_digiMode == kofflineMode) - SetOfflineOutputFileName(); + if (m_digiMode == kofflineMode || m_digiMode == kofflineSinglesMode) + SetOfflineOutputFileName(); switch (m_digiMode) { case kruntimeMode: // In run-time mode, we open the file in RECREATE mode @@ -395,6 +395,7 @@ void GateToRoot::RecordBeginOfAcquisition() { break; case kofflineMode: + case kofflineSinglesMode: // In DigiGate mode, we first check that the file does not exist. If it does, we abort as we want to make sure the ROOT file is not overwritten by accident // v. cuplov - m_fileName from SetFileName is defined without ".root" (see changes in GateToRoot.hh) @@ -1826,7 +1827,9 @@ void GateToRoot::RecordTracks(GateSteppingAction *mySteppingAction) { void GateToRoot::SetOfflineOutputFileName() { - G4String input = GateHitFileReader::GetInstance()->GetFileName(); + + //G4cout<<"GateToRoot::SetOfflineOutputFileName("<< G4endl; + G4String input = GateOfflineFileReader::GetInstance()->GetFileName(); // Remove ".root" if present if (input.length() > 5 && @@ -1839,7 +1842,7 @@ void GateToRoot::SetOfflineOutputFileName() G4cout << G4endl << "Offline Digi mode:" << G4endl - << " Input : " << GateHitFileReader::GetInstance()->GetFileName() << G4endl + << " Input : " << GateOfflineFileReader::GetInstance()->GetFileName() << G4endl << " Output: " << m_fileName << ".root" << G4endl << G4endl; } diff --git a/source/general/include/GateRootDefs.hh b/source/general/include/GateRootDefs.hh index 349b85548..16d7d42ca 100644 --- a/source/general/include/GateRootDefs.hh +++ b/source/general/include/GateRootDefs.hh @@ -53,12 +53,12 @@ namespace GateRootDefs } /*! \class GateRootHitBuffer - \brief ROOT structure to store hits for GateToRoot and GateHitFileReader + \brief ROOT structure to store hits for GateToRoot and GateOfflineFileReader - GateRootHitBuffer - by Giovanni.Santin@cern.ch (May 1, 2002) - This structure was initally declared in GateToRoot. To insure consistency between - GateToRoot and GatHitFileReader, I have made it a separate class. + GateToRoot and GatOfflineFileReader, I have made it a separate class. */ class GateRootHitBuffer { @@ -296,7 +296,7 @@ class GateRootSingleBuffer void Clear(); //!< Reset the fields of the structure void Fill(GateDigi* aDigi); - + GateDigi* CreateDigi(); inline void SetCCFlag (G4bool val) {m_CCflag=val;} @@ -368,6 +368,7 @@ class GateSingleTree : public TTree virtual inline ~GateSingleTree() {} void Init(GateRootSingleBuffer& buffer); + static void SetBranchAddresses(TTree* singleTree,GateRootSingleBuffer& buffer); }; diff --git a/source/general/src/GateApplicationMgr.cc b/source/general/src/GateApplicationMgr.cc index 4f6141b77..40dd8bbb1 100644 --- a/source/general/src/GateApplicationMgr.cc +++ b/source/general/src/GateApplicationMgr.cc @@ -21,8 +21,8 @@ #include "GateVSource.hh" #include "GateSourceMgr.hh" #include "GateOutputMgr.hh" -#include "GateHitFileReader.hh" #include /* min and max */ +#include "../../digits_hits/include/GateOfflineFileReader.hh" GateApplicationMgr* GateApplicationMgr::instance = 0; //------------------------------------------------------------------------------------------ @@ -336,7 +336,8 @@ void GateApplicationMgr::StartDAQ() // filename given. In this case we disable the output module and send a warning. GateOutputMgr::GetInstance()->CheckFileNameForAllOutput(); - if (mOutputMode) + + if (GateOutputMgr::GetInstance()->GetDigiMode()!=kruntimeMode) { GateMessage("Acquisition", 0," ! OFFLINE DIGI MODE ! \n"); @@ -387,7 +388,8 @@ void GateApplicationMgr::StartDAQ() m_time = mTimeSlices.front(); while(m_time < mTimeSlices.back() && !offlineFinished) { - + if (GateOutputMgr::GetInstance()->GetDigiMode()==kruntimeMode) + { // Informational message about the current slice GateMessage("Acquisition", 0, "Slice " << slice << " from " << mTimeSlices[slice]/s << " to " @@ -395,7 +397,7 @@ void GateApplicationMgr::StartDAQ() << " s [slice=" << GetTimeSlice(slice)/s << " s]\n"); - + } m_time = mTimeSlices[slice]; GateMessage("Geometry", 5, " Time is going to change : = " << m_time/s << Gateendl;); theClock->SetTime(m_time); @@ -435,8 +437,8 @@ void GateApplicationMgr::StartDAQ() GateRunManager::GetRunManager()->BeamOn(INT_MAX); // otherwise RunID is automatically incremented #ifdef G4ANALYSIS_USE_ROOT - if (GateOutputMgr::GetInstance()->GetDigiMode()==kofflineMode && - GateHitFileReader::GetInstance()->IsFinished()) + if ((GateOutputMgr::GetInstance()->GetDigiMode()==kofflineMode || GateOutputMgr::GetInstance()->GetDigiMode()==kofflineSinglesMode) && + GateOfflineFileReader::GetInstance()->IsFinished()) { offlineFinished = true; break; diff --git a/source/general/src/GatePrimaryGeneratorAction.cc b/source/general/src/GatePrimaryGeneratorAction.cc index 71e223d8e..979ec67da 100644 --- a/source/general/src/GatePrimaryGeneratorAction.cc +++ b/source/general/src/GatePrimaryGeneratorAction.cc @@ -16,6 +16,8 @@ See LICENSE.md for further details #include "G4ios.hh" #include "GatePrimaryGeneratorAction.hh" + +#include "../../digits_hits/include/GateOfflineFileReader.hh" #include "GatePrimaryGeneratorMessenger.hh" #include "GateDetectorConstruction.hh" @@ -24,7 +26,6 @@ See LICENSE.md for further details #include "GateSourceMgr.hh" #include "GateOutputMgr.hh" -#include "GateHitFileReader.hh" #include "GateDigitizerMgr.hh" #include "GateConfiguration.h" @@ -68,6 +69,7 @@ void GatePrimaryGeneratorAction::SetVerboseLevel(G4int value) void GatePrimaryGeneratorAction::GeneratePrimaries(G4Event* event) { + //G4cout<<"GatePrimaryGeneratorAction::GeneratePrimaries"<GetDigiMode() == kruntimeMode) GenerateSimulationPrimaries(event); @@ -128,38 +130,72 @@ void GatePrimaryGeneratorAction::GenerateSimulationPrimaries(G4Event* event) //--------------------------------------------------------------------------- void GatePrimaryGeneratorAction::GenerateDigitisationPrimaries(G4Event* event) { + + //G4cout<<"GatePrimaryGeneratorAction::GenerateDigitisationPrimaries"<GetDigiMode()==kofflineMode ) //Hits + { + + G4int ok = reader->PrepareNextEventFromHits(event); + if (!ok) + { + GateDigitizerMgr::GetInstance()->SetOfflineHitsCollection(nullptr); + GateRunManager::GetRunManager()->AbortRun(true); + return; + } + // Build the hit collection for this event + + GateHitsCollection* hc = + new GateHitsCollection("toto", "fufu"); //the names are not important + + for (auto hit : reader->GetHitVector()) + hc->insert(hit); + + + // The collection now owns the hits + reader->GetHitVector().clear(); + + GateDigitizerMgr::GetInstance()->SetOfflineHitsCollection(hc); + } + else // singles + { + + G4int ok = reader->PrepareNextEventFromSingles(event); + if (!ok) + { + GateDigitizerMgr::GetInstance()->SetOfflineDigiCollection(nullptr); + GateRunManager::GetRunManager()->AbortRun(true); + + return; + } + // Build the hit collection for this event + + GateDigiCollection* dc = + new GateDigiCollection("toto", "fufu"); //the names are not important - G4int ok = reader->PrepareNextEvent(event); + for (auto digi : reader->GetDigiVector()) + dc->insert(digi); - if (!ok) - { - GateDigitizerMgr::GetInstance()->SetOfflineHitsCollection(nullptr); - GateRunManager::GetRunManager()->AbortRun(true); + // The collection now owns the hits + reader->GetDigiVector().clear(); - return; - } - // Build the hit collection for this event - GateHitsCollection* hc = - new GateHitsCollection("crystal", "CrystalCollection"); + GateDigitizerMgr::GetInstance()->SetOfflineDigiCollection(dc); + } - for (auto hit : reader->GetHitVector()) - hc->insert(hit); - // The collection now owns the hits - reader->GetHitVector().clear(); - GateDigitizerMgr::GetInstance()->SetOfflineHitsCollection(hc); m_nEvents++; /*G4cout << "Finished = " - << GateHitFileReader::GetInstance()->IsFinished() + << GateOfflineFileReader::GetInstance()->IsFinished() << G4endl;*/ #endif } diff --git a/source/general/src/GateRootDefs.cc b/source/general/src/GateRootDefs.cc index aa8028855..736c97225 100644 --- a/source/general/src/GateRootDefs.cc +++ b/source/general/src/GateRootDefs.cc @@ -590,7 +590,147 @@ void GateRootSingleBuffer::Fill(GateDigi* aDigi) aDigi->GetVolumeID().StoreDaughterIDs(volumeID,ROOT_VOLUMEIDSIZE); } +void GateSingleTree::SetBranchAddresses(TTree* singleTree, + GateRootSingleBuffer& buffer) +{ + singleTree->SetBranchAddress("runID", &buffer.runID); + singleTree->SetBranchAddress("eventID", &buffer.eventID); + singleTree->SetBranchAddress("sourceID", &buffer.sourceID); + + singleTree->SetBranchAddress("sourcePosX", &buffer.sourcePosX); + singleTree->SetBranchAddress("sourcePosY", &buffer.sourcePosY); + singleTree->SetBranchAddress("sourcePosZ", &buffer.sourcePosZ); + + singleTree->SetBranchAddress("time", &buffer.time); + singleTree->SetBranchAddress("energy", &buffer.energy); + + singleTree->SetBranchAddress("globalPosX", &buffer.globalPosX); + singleTree->SetBranchAddress("globalPosY", &buffer.globalPosY); + singleTree->SetBranchAddress("globalPosZ", &buffer.globalPosZ); + + if (GateSystemListManager::GetInstance()->GetIsAnySystemDefined()) + for (size_t d = 0; d < ROOT_OUTPUTIDSIZE; ++d) + singleTree->SetBranchAddress(outputIDName[d], + (void*)(buffer.outputID + d)); + + if (GateRootDefs::GetRecordSeptalFlag()) + singleTree->SetBranchAddress("septalNb", &buffer.septalNb); + + if (!buffer.GetCCFlag()) + { + singleTree->SetBranchAddress("comptonPhantom", &buffer.comptonPhantom); + singleTree->SetBranchAddress("comptonCrystal", &buffer.comptonCrystal); + singleTree->SetBranchAddress("RayleighPhantom", &buffer.RayleighPhantom); + singleTree->SetBranchAddress("RayleighCrystal", &buffer.RayleighCrystal); + + singleTree->SetBranchAddress("axialPos", &buffer.axialPos); + singleTree->SetBranchAddress("rotationAngle", &buffer.rotationAngle); + + singleTree->SetBranchAddress("comptVolName", buffer.comptonVolumeName); + singleTree->SetBranchAddress("RayleighVolName", buffer.RayleighVolumeName); + } + else + { + singleTree->SetBranchAddress("sourceEnergy", &buffer.sourceEnergy); + singleTree->SetBranchAddress("sourcePDG", &buffer.sourcePDG); + singleTree->SetBranchAddress("nCrystalConv", &buffer.nCrystalConv); + singleTree->SetBranchAddress("nCrystalCompt", &buffer.nCrystalCompt); + singleTree->SetBranchAddress("nCrystalRayl", &buffer.nCrystalRayl); + + singleTree->SetBranchAddress("localPosX", &buffer.localPosX); + singleTree->SetBranchAddress("localPosY", &buffer.localPosY); + singleTree->SetBranchAddress("localPosZ", &buffer.localPosZ); + + singleTree->SetBranchAddress("energyFinal", &buffer.energyFin); + singleTree->SetBranchAddress("energyIni", &buffer.energyIni); + } + + if (buffer.GetSpatialRes2DStdDevFlag()) + { + singleTree->SetBranchAddress("spatialRes2DStdDevX", + &buffer.spatialRes2DStdDevX); + singleTree->SetBranchAddress("spatialRes2DStdDevY", + &buffer.spatialRes2DStdDevY); + singleTree->SetBranchAddress("spatialRes2DStdDevZ", + &buffer.spatialRes2DStdDevZ); + } + + singleTree->SetBranchAddress("volumeID", buffer.volumeID); +} + +GateDigi* GateRootSingleBuffer::CreateDigi() +{ + // Create a volumeID from the ROOT single data + + GateVolumeID aVolumeID(volumeID,ROOT_VOLUMEIDSIZE); + + GateOutputVolumeID anOutputVolumeID; + if (GateSystemListManager::GetInstance()->GetIsAnySystemDefined()) + for (size_t d = 0; d < ROOT_OUTPUTIDSIZE; ++d) + anOutputVolumeID[d] = outputID[d]; + + // Create a new digi + GateDigi* aDigi = new GateDigi(); + // Initialize the digi + aDigi->SetRunID(runID); + aDigi->SetEventID(eventID); + aDigi->SetSourceID(sourceID); + + aDigi->SetSourcePosition(G4ThreeVector(sourcePosX*mm, sourcePosY*mm, sourcePosZ*mm)); + + aDigi->SetTime(time*s); + aDigi->SetEnergy(energy*MeV); + + aDigi->SetGlobalPos(G4ThreeVector(globalPosX*mm, globalPosY*mm, globalPosZ*mm)); + + aDigi->SetOutputVolumeID(anOutputVolumeID); + + aDigi->SetVolumeID(aVolumeID); + + // Septal penetration + aDigi->SetNSeptal(septalNb); + + if (!GetCCFlag()) + { + aDigi->SetNPhantomCompton(comptonPhantom); + aDigi->SetNCrystalCompton(comptonCrystal); + aDigi->SetNPhantomRayleigh(RayleighPhantom); + aDigi->SetNCrystalRayleigh(RayleighCrystal); + + aDigi->SetScannerPos(G4ThreeVector(0., 0., axialPos*mm)); + aDigi->SetScannerRotAngle(rotationAngle*deg); + + aDigi->SetComptonVolumeName(comptonVolumeName); + aDigi->SetRayleighVolumeName(RayleighVolumeName); + } + else + { + aDigi->SetSourceEnergy(sourceEnergy*MeV); + aDigi->SetSourcePDG(sourcePDG); + + aDigi->SetNCrystalConv(nCrystalConv); + aDigi->SetNCrystalCompton(nCrystalCompt); + aDigi->SetNCrystalRayleigh(nCrystalRayl); + + aDigi->SetLocalPos(G4ThreeVector(localPosX*mm, localPosY*mm, localPosZ*mm)); + + aDigi->SetEnergyFin(energyFin); + aDigi->SetEnergyIniTrack(energyIni); + } + + if (GetSpatialRes2DStdDevFlag()) + { + aDigi->SetSpatialRes2DStdDevX(spatialRes2DStdDevX*mm); + aDigi->SetSpatialRes2DStdDevY(spatialRes2DStdDevY*mm); + aDigi->SetSpatialRes2DStdDevZ(spatialRes2DStdDevZ*mm); + } + + + + + return aDigi; +}