File indexing completed on 2026-09-20 08:28:21
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040 #ifdef WITH_ROOT
0041
0042 #include "RootIO.hh"
0043 #include "ConfigurationManager.hh"
0044 #include "Event.hh"
0045 #include "PhotonSD.hh"
0046 #include "PhotonHit.hh"
0047 #include "InteractionHit.hh"
0048 #include "lArTPCHit.hh"
0049 #include "TrackerHit.hh"
0050 #include "MscHit.hh"
0051 #include "CalorimeterHit.hh"
0052 #include "DRCalorimeterHit.hh"
0053
0054 #include "G4Event.hh"
0055 #include "G4ios.hh"
0056 #include "G4Threading.hh"
0057 #include "G4RunManager.hh"
0058 #include "G4HCofThisEvent.hh"
0059 #include "G4VHit.hh"
0060 #include "G4VHitsCollection.hh"
0061 #include "G4SDManager.hh"
0062
0063 #include "TBranch.h"
0064 #include "TFile.h"
0065 #include "TObject.h"
0066 #include "TROOT.h"
0067 #include "TSystem.h"
0068 #include "TTree.h"
0069
0070
0071 namespace
0072 {
0073
0074 G4Mutex RootIOMutex = G4MUTEX_INITIALIZER;
0075 }
0076
0077
0078 RootIO::RootIO()
0079 {
0080 G4AutoLock lock(&RootIOMutex);
0081
0082 ROOT::EnableThreadSafety();
0083 gSystem->Load("libCaTSClassesDict");
0084
0085 fFileName = ConfigurationManager::getInstance()->getfname() + ".root";
0086
0087 if (G4Threading::IsWorkerThread())
0088 {
0089 fFileName += std::to_string(G4Threading::G4GetThreadId());
0090 }
0091
0092 if (G4Threading::IsWorkerThread() ||
0093 !G4Threading::IsMultithreadedApplication())
0094 {
0095 G4cout << "RootIO:: Opening File: " << fFileName << G4endl;
0096 fFile = TFile::Open(fFileName.c_str(), "RECREATE");
0097 fTree = new TTree("Events", "ROOT tree containing Hit collections");
0098 }
0099 }
0100
0101
0102 RootIO* RootIO::GetInstance()
0103 {
0104 static G4ThreadLocal RootIO instance;
0105 return &instance;
0106 }
0107
0108
0109 void RootIO::Write(const G4Event* event)
0110 {
0111 G4bool verbose = ConfigurationManager::getInstance()->isEnable_verbose();
0112
0113 G4HCofThisEvent* HCE = event->GetHCofThisEvent();
0114 if (HCE == nullptr)
0115 {
0116 return;
0117 }
0118
0119
0120 Event* CaTSEvt = new Event();
0121 CaTSEvt->SetEventNr(event->GetEventID());
0122
0123 if (verbose)
0124 {
0125 G4cout << "Number of collections: " << HCE->GetNumberOfCollections()
0126 << G4endl;
0127 }
0128
0129 for (int i = 0; i < HCE->GetNumberOfCollections(); i++)
0130 {
0131 G4VHitsCollection* hc = HCE->GetHC(i);
0132 std::vector<G4String> y = Split(hc->GetName(), '_');
0133 G4String Classname = y[1];
0134
0135 if (verbose)
0136 {
0137 G4cout << "Classname: " << Classname << " Collection size: "
0138 << hc->GetSize() << G4endl;
0139 }
0140
0141 if (Classname == "lArTPC")
0142 {
0143 AddHits<lArTPCHit>(hc, CaTSEvt);
0144 }
0145 else if (Classname == "PhotonDetector")
0146 {
0147 AddHits<PhotonHit>(hc, CaTSEvt);
0148 }
0149 else if (Classname == "Target")
0150 {
0151 AddHits<InteractionHit>(hc, CaTSEvt);
0152 }
0153 else if (Classname == "Tracker")
0154 {
0155 AddHits<TrackerHit>(hc, CaTSEvt);
0156 }
0157 else if (Classname == "Msc")
0158 {
0159 AddHits<MscHit>(hc, CaTSEvt);
0160 }
0161 else if (Classname == "Calorimeter")
0162 {
0163 AddHits<CalorimeterHit>(hc, CaTSEvt);
0164 }
0165 else if (Classname == "DRCalorimeter")
0166 {
0167 AddHits<DRCalorimeterHit>(hc, CaTSEvt);
0168 }
0169 else
0170 {
0171 G4cout << "SD type: " << Classname << " unknown" << G4endl;
0172 }
0173 }
0174
0175 if (verbose)
0176 {
0177 G4cout << "writing Event: " << CaTSEvt->GetEventNumber() << G4endl;
0178 }
0179
0180 G4AutoLock lock(&RootIOMutex);
0181 if (!fEvtBranch)
0182 {
0183 Int_t bufsize = 64000;
0184 fEvtBranch = fTree->Branch("event.", &CaTSEvt, bufsize, 0);
0185 }
0186 else
0187 {
0188 fEvtBranch->SetAddress(&CaTSEvt);
0189 }
0190
0191 fTree->Fill();
0192 fFile->Write("", TObject::kOverwrite);
0193
0194 CaTSEvt->Reset();
0195 delete CaTSEvt;
0196 }
0197
0198
0199 void RootIO::Close()
0200 {
0201 G4cout << " Closing File: " << fFileName << G4endl;
0202 fFile->Close();
0203 fEvtBranch = nullptr;
0204 }
0205
0206
0207 void RootIO::Merge()
0208 {
0209 if (G4Threading::IsMasterThread())
0210 {
0211 auto nthreads = G4RunManager::GetRunManager()->GetNumberOfThreads();
0212 G4cout << "RootIO::Merging: " << nthreads << " threads" << G4endl;
0213
0214 std::vector<TFile*> files;
0215 std::vector<TTree*> trees;
0216 TList* list = new TList;
0217
0218 for (int i = 0; i < nthreads; i++)
0219 {
0220 G4String fileName = fFileName + std::to_string(i);
0221 files.push_back(TFile::Open(fileName.c_str()));
0222 trees.push_back((TTree*) (files[i]->Get("Events")));
0223 list->Add(trees[i]);
0224
0225 if (i == nthreads - 1)
0226 {
0227 auto* file = TFile::Open(fFileName.c_str(), "RECREATE");
0228
0229 auto tree = TTree::MergeTrees(list);
0230 tree->SetName("Events");
0231
0232 Event* event = new Event();
0233 tree->SetBranchAddress("event.", &event);
0234 TBranch* branch = tree->GetBranch("event.");
0235 int nevents = branch->GetEntries();
0236 G4cout << "Number of Events: " << nevents << G4endl;
0237
0238 tree->Write();
0239 file->Close();
0240 }
0241
0242 if(std::remove(fileName.c_str()) !=0)
0243 {
0244 G4cout << "Error deleting file: " << fileName << G4endl;
0245 }
0246 }
0247 }
0248 }
0249
0250
0251 std::vector<G4String> RootIO::Split(const G4String& s, char delim)
0252 {
0253 std::stringstream ss(s);
0254 G4String item;
0255 std::vector<G4String> elems;
0256
0257 while (std::getline(ss, item, delim))
0258 {
0259 elems.push_back(item);
0260 }
0261 return elems;
0262 }
0263
0264 #endif