Geant4 Cross Reference |
1 // 2 // ******************************************************************** 3 // * License and Disclaimer * 4 // * * 5 // * The Geant4 software is copyright of the Copyright Holders of * 6 // * the Geant4 Collaboration. It is provided under the terms and * 7 // * conditions of the Geant4 Software License, included in the file * 8 // * LICENSE and available at http://cern.ch/geant4/license . These * 9 // * include a list of copyright holders. * 10 // * * 11 // * Neither the authors of this software system, nor their employing * 12 // * institutes,nor the agencies providing financial support for this * 13 // * work make any representation or warranty, express or implied, * 14 // * regarding this software system or assume any liability for its * 15 // * use. Please see the license in the file LICENSE and URL above * 16 // * for the full disclaimer and the limitation of liability. * 17 // * * 18 // * This code implementation is the result of the scientific and * 19 // * technical work of the GEANT4 collaboration. * 20 // * By using, copying, modifying or distributing the software (or * 21 // * any work based on the software) you agree to acknowledge its * 22 // * use in resulting scientific publications, and indicate your * 23 // * acceptance of all terms of the Geant4 Software license. * 24 // ******************************************************************** 25 // 26 // ******************************************************************** 27 // 28 // CaTS (Calorimetry and Tracking Simulation) 29 // 30 // Authors : Hans Wenzel 31 // Soon Yung Jun 32 // (Fermi National Accelerator Laboratory) 33 // 34 // History 35 // October 18th, 2021 : first implementation 36 // November 10th, 2021 : implement writing one file 37 // per worker thread which are then merged 38 // 39 // ******************************************************************** 40 // 41 /// \file RootIO.cc 42 /// \brief Implementation of the CaTS::RootIO class 43 44 #ifdef WITH_ROOT 45 // Project headers 46 #include "RootIO.hh" 47 #include "ConfigurationManager.hh" 48 #include "Event.hh" 49 // Geant4 headers 50 #include <G4String.hh> 51 #include <G4ios.hh> 52 #include <G4Threading.hh> 53 #include <G4RunManager.hh> 54 // Root headers 55 #include "TBranch.h" 56 #include "TFile.h" 57 #include "TObject.h" 58 #include "TSystem.h" 59 #include "TTree.h" 60 #include "TROOT.h" 61 // c++ headers 62 #include <string> 63 #include <stdio.h> 64 65 G4ThreadLocal RootIO* RootIO::fgInstance = nullptr; 66 // mutex in a file scope 67 namespace { 68 // Mutex to lock RootIO constructor 69 G4Mutex RootIOMutex = G4MUTEX_INITIALIZER; 70 } // namespace 71 72 RootIO::RootIO() { 73 G4AutoLock lock(&RootIOMutex); 74 TSystem ts; 75 gSystem->Load("libCaTSClassesDict"); 76 if (G4Threading::IsMultithreadedApplication()) { 77 if (G4Threading::IsWorkerThread()) { 78 G4String fFilename = ConfigurationManager::getInstance()->getfname() + 79 "_Thread_" + 80 std::to_string(G4Threading::G4GetThreadId()) + ".root"; 81 G4cout << "RootIO:: Opening File: " << fFilename << G4endl; 82 fFile = new TFile(fFilename.c_str(), "RECREATE"); 83 TTree::SetMaxTreeSize(1000 * Long64_t(2000000000)); 84 // Create a ROOT Tree and one superbranch 85 ftree = new TTree("Events", "ROOT tree containing Hit collections"); 86 ftree->SetAutoSave(1000000000); // autosave when 1 Gbyte written 87 Int_t branchStyle = 1; 88 TTree::SetBranchStyle(branchStyle); 89 } 90 } else { 91 G4String fFilename = ConfigurationManager::getInstance()->getfname() + ".root"; 92 G4cout << "RootIO:: Opening File: " << fFilename << G4endl; 93 fFile = new TFile(fFilename.c_str(), "RECREATE"); 94 TTree::SetMaxTreeSize(1000 * Long64_t(2000000000)); 95 // Create a ROOT Tree and one superbranch 96 ftree = new TTree("Events", "ROOT tree containing Hit collections"); 97 ftree->SetAutoSave(1000000000); // autosave when 1 Gbyte written 98 Int_t branchStyle = 1; 99 TTree::SetBranchStyle(branchStyle); 100 } 101 } 102 103 RootIO* RootIO::GetInstance() { 104 if (fgInstance == nullptr) { 105 static G4ThreadLocalSingleton<RootIO> inst; 106 fgInstance = inst.Instance(); 107 } 108 return fgInstance; 109 } 110 111 void RootIO::Write(Event* fevent) { 112 if (ConfigurationManager::getInstance()->isEnable_verbose()) 113 G4cout << "writing Event: " << fevent->GetEventNumber() << G4endl; 114 if ((fevent->GetEventNumber()) % 1000 == 0) 115 G4cout << "writing Event: " << fevent->GetEventNumber() << G4endl; 116 if (!fevtinitialized) { 117 Int_t bufsize = 64000; 118 fevtbranch = ftree->Branch("event.", &fevent, bufsize, 0); 119 fevtbranch->SetAutoDelete(kFALSE); 120 fevtinitialized = true; 121 } 122 fFile = ftree->GetCurrentFile(); // just in case we switched to a new file 123 fnb += ftree->Fill(); 124 fFile->Write("", TObject::kOverwrite); 125 } 126 127 void RootIO::Close() { 128 G4cout << " Closing File: " << G4endl; 129 fFile = ftree->GetCurrentFile(); 130 fFile->Close(); 131 } 132 133 void RootIO::Merge() { 134 if (G4Threading::IsMasterThread()) { 135 unsigned int nthreads = G4RunManager::GetRunManager()->GetNumberOfThreads(); 136 G4cout << "RootIO::Merging: " << nthreads << " threads" << G4endl; 137 G4String filename = ConfigurationManager::getInstance()->getfname(); 138 G4String tmpfn; 139 std::vector<TFile*> filevec; 140 std::vector<Event*> evtvec; 141 std::vector<TTree*> treevec; 142 std::vector<TBranch*> branchvec; 143 TList* list = new TList; 144 TTree* newtree; 145 for (unsigned int i = 0; i < nthreads; i++) { 146 tmpfn = filename + "_Thread_" + std::to_string(i) + ".root"; 147 filevec.push_back(new TFile(tmpfn.c_str())); 148 treevec.push_back((TTree*) (filevec[i]->Get("Events"))); 149 list->Add(treevec[i]); 150 if (i == nthreads - 1) { 151 G4String tmpfn2 = filename + "_Merged.root"; 152 TFile* fm = new TFile(tmpfn2.c_str(), "RECREATE"); 153 newtree = TTree::MergeTrees(list); 154 newtree->SetName("Events"); 155 Event* eventm = new Event(); 156 newtree->SetBranchAddress("event.", &eventm); 157 TBranch* fevtbranchm = newtree->GetBranch("event."); 158 int neventm = fevtbranchm->GetEntries(); 159 G4cout << "Nr. of Events: " << neventm << G4endl; 160 newtree->Write(); 161 fm->Close(); 162 } 163 } 164 for (unsigned int i = 0; i < nthreads; i++) { 165 tmpfn = filename + "_Thread_" + std::to_string(i) + ".root"; 166 if (remove(tmpfn.c_str()) != 0) { 167 G4cout << "Error deleting file: " << tmpfn << G4endl; 168 } else { 169 G4cout << "File: " << tmpfn << " successfully deleted" << G4endl; 170 } 171 } 172 } 173 } 174 #endif 175