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 // Author: Ivana Hrivnacova, 15/09/2020 (ivana@ipno.in2p3.fr) 28 29 #include "G4RootNtupleFileManager.hh" 30 #include "G4RootFileManager.hh" 31 #include "G4RootNtupleManager.hh" 32 #include "G4RootMainNtupleManager.hh" 33 #include "G4RootPNtupleManager.hh" 34 #include "G4VAnalysisManager.hh" 35 #include "G4AnalysisManagerState.hh" 36 #include "G4AnalysisUtilities.hh" 37 38 #include "G4Threading.hh" 39 #include "G4AutoLock.hh" 40 41 using namespace G4Analysis; 42 using std::make_shared; 43 using std::to_string; 44 45 46 47 G4RootNtupleFileManager* G4RootNtupleFileManager::fgMasterInstance = nullptr; 48 49 //_____________________________________________________________________________ 50 G4RootNtupleFileManager::G4RootNtupleFileManager(const G4AnalysisManagerState& state) 51 : G4VNtupleFileManager(state, "root") 52 { 53 if ( G4Threading::IsMasterThread() ) fgMasterInstance = this; 54 55 // Do not merge ntuples by default 56 // Merging may require user code migration as analysis manager 57 // must be created both on master and workers. 58 auto mergeNtuples = false; 59 SetNtupleMergingMode(mergeNtuples, fNofNtupleFiles); 60 } 61 62 //_____________________________________________________________________________ 63 G4RootNtupleFileManager::~G4RootNtupleFileManager() 64 { 65 if ( fState.GetIsMaster() ) fgMasterInstance = nullptr; 66 } 67 68 // 69 // private methods 70 // 71 72 //_____________________________________________________________________________ 73 void G4RootNtupleFileManager::SetNtupleMergingMode(G4bool mergeNtuples, 74 G4int nofNtupleFiles) 75 76 { 77 Message(kVL4, "set", "ntuple merging mode"); 78 79 auto canMerge = true; 80 81 // Illegal situations 82 if ( mergeNtuples && ( ! G4Threading::IsMultithreadedApplication() ) ) { 83 Warn("Merging ntuples is not applicable in sequential application.\n" 84 "Setting was ignored.", 85 fkClass, "SetNtupleMergingMode"); 86 canMerge = false; 87 } 88 89 // Illegal situations 90 if (mergeNtuples && G4Threading::IsMultithreadedApplication() && (fgMasterInstance == nullptr)) { 91 Warn("Merging ntuples requires G4AnalysisManager instance on master.\n" 92 "Setting was ignored.", 93 fkClass, "SetNtupleMergingMode"); 94 canMerge = false; 95 } 96 97 G4String mergingMode; 98 if ( ( ! mergeNtuples ) || ( ! canMerge ) ) { 99 fNtupleMergeMode = G4NtupleMergeMode::kNone; 100 mergingMode = "G4NtupleMergeMode::kNone"; 101 } 102 else { 103 // Set the number of reduced ntuple files 104 fNofNtupleFiles = nofNtupleFiles; 105 106 // Check the number of reduced ntuple files 107 if ( fNofNtupleFiles < 0 ) { 108 Warn("Number of reduced files must be [0, nofThreads].\n" 109 "Cannot set " + to_string(nofNtupleFiles) +" files.\n" + 110 "Setting was ignored.", 111 fkClass, "SetNtupleMergingMode"); 112 fNofNtupleFiles = 0; 113 } 114 115 // Forced merging mode 116 G4bool isMaster = ! G4Threading::IsWorkerThread(); 117 // G4bool isMaster = fState.GetIsMaster(); 118 if ( isMaster ) { 119 fNtupleMergeMode = G4NtupleMergeMode::kMain; 120 mergingMode = "G4NtupleMergeMode::kMain"; 121 } else { 122 fNtupleMergeMode = G4NtupleMergeMode::kSlave; 123 mergingMode = "G4NtupleMergeMode::kSlave"; 124 } 125 } 126 127 Message(kVL2, "set", "ntuple merging mode", mergingMode); 128 } 129 130 //_____________________________________________________________________________ 131 G4int G4RootNtupleFileManager::GetNtupleFileNumber() 132 { 133 if (fNofNtupleFiles == 0) return 0; 134 135 G4int nofMainManagers = fNofNtupleFiles; 136 if (nofMainManagers == 0) nofMainManagers = 1; 137 138 auto fileNumber = G4Threading::G4GetThreadId() % nofMainManagers; 139 return fileNumber; 140 } 141 142 //_____________________________________________________________________________ 143 G4bool G4RootNtupleFileManager::CloseNtupleFiles() 144 { 145 // Take into account main ntuple files if present 146 auto mainNumber = ( fNofNtupleFiles > 0 ) ? 0 : -1; 147 148 auto result = true; 149 auto ntupleVector = fNtupleManager->GetNtupleDescriptionVector(); 150 for ( auto ntupleDescription : ntupleVector) { 151 for (G4int i = mainNumber; i < fNofNtupleFiles; ++i ) { 152 result &= fFileManager->CloseNtupleFile(ntupleDescription, i); 153 } 154 } 155 return result; 156 } 157 158 // 159 // public methods 160 // 161 162 //_____________________________________________________________________________ 163 void G4RootNtupleFileManager::SetNtupleMerging(G4bool mergeNtuples, 164 G4int nofNtupleFiles) 165 166 { 167 if ( fIsInitialized ) { 168 Warn("Cannot change merging mode.\n" 169 "The function must be called before OpenFile().", 170 fkClass, "SetNtupleMerging"); 171 return; 172 } 173 174 // Set ntuple merging mode 175 SetNtupleMergingMode(mergeNtuples, nofNtupleFiles); 176 } 177 178 //_____________________________________________________________________________ 179 void G4RootNtupleFileManager::SetNtupleRowWise(G4bool rowWise, G4bool rowMode) 180 { 181 182 // Print info even when setting makes no effect 183 // (as we do not get printed the default setting in the output) 184 G4String rowWiseMode; 185 if ( rowWise ) { 186 rowWiseMode = "row-wise with extra branch"; 187 } 188 else if ( rowMode ) { 189 rowWiseMode = "row-wise"; 190 } 191 else { 192 rowWiseMode = "column-wise"; 193 } 194 195 Message(kVL1, "set", "ntuple merging row mode", rowWiseMode); 196 197 // Do nothing if the mode is not changed 198 if ( fNtupleRowWise == rowWise && fNtupleRowMode == rowMode ) return; 199 200 fNtupleRowWise = rowWise; 201 fNtupleRowMode = rowMode; 202 203 if ( fNtupleManager ) { 204 fNtupleManager->SetNtupleRowWise(rowWise, rowMode); 205 } 206 207 if ( fSlaveNtupleManager ) { 208 fSlaveNtupleManager->SetNtupleRowWise(rowWise, rowMode); 209 } 210 } 211 212 //_____________________________________________________________________________ 213 void G4RootNtupleFileManager::SetBasketSize(unsigned int basketSize) 214 { 215 fFileManager->SetBasketSize(basketSize); 216 } 217 218 //_____________________________________________________________________________ 219 void G4RootNtupleFileManager::SetBasketEntries(unsigned int basketEntries) 220 { 221 fFileManager->SetBasketEntries(basketEntries); 222 } 223 224 //_____________________________________________________________________________ 225 std::shared_ptr<G4VNtupleManager> G4RootNtupleFileManager::CreateNtupleManager() 226 { 227 // Create and return ntuple manager. 228 // If ntuple merging is activated, managers of different types are created 229 // on master/worker. 230 231 Message(kVL4, "create", "ntuple manager"); 232 233 // Check that file manager and anaysis manager are set ! 234 235 std::shared_ptr<G4VNtupleManager> activeNtupleManager = nullptr; 236 switch ( fNtupleMergeMode ) 237 { 238 case G4NtupleMergeMode::kNone: 239 fNtupleManager 240 = make_shared<G4RootNtupleManager>( 241 fState, fBookingManager, 0, 0, fNtupleRowWise, fNtupleRowMode); 242 fNtupleManager->SetFileManager(fFileManager); 243 activeNtupleManager = fNtupleManager; 244 break; 245 246 case G4NtupleMergeMode::kMain: { 247 G4int nofMainManagers = fNofNtupleFiles; 248 if (nofMainManagers == 0) { 249 // create one manager if merging required into the histos & profiles files 250 nofMainManagers = 1; 251 } 252 fNtupleManager 253 = make_shared<G4RootNtupleManager>( 254 fState, fBookingManager, nofMainManagers, fNofNtupleFiles, fNtupleRowWise, fNtupleRowMode); 255 fNtupleManager->SetFileManager(fFileManager); 256 activeNtupleManager = fNtupleManager; 257 break; 258 } 259 260 case G4NtupleMergeMode::kSlave: 261 fNtupleManager = fgMasterInstance->fNtupleManager; 262 // The master class is used only in Get* functions 263 auto mainNtupleManager 264 = fNtupleManager->GetMainNtupleManager(GetNtupleFileNumber()); 265 fSlaveNtupleManager 266 = make_shared<G4RootPNtupleManager>( 267 fState, fBookingManager, mainNtupleManager, fNtupleRowWise, fNtupleRowMode); 268 activeNtupleManager = fSlaveNtupleManager; 269 break; 270 } 271 272 G4String mergeMode; 273 switch ( fNtupleMergeMode ) { 274 case G4NtupleMergeMode::kNone: 275 mergeMode = ""; 276 break; 277 case G4NtupleMergeMode::kMain: 278 mergeMode = "main "; 279 break; 280 case G4NtupleMergeMode::kSlave: 281 mergeMode = "slave "; 282 break; 283 } 284 Message(kVL3, "create", mergeMode + "ntuple manager"); 285 286 fIsInitialized = true; 287 288 return activeNtupleManager; 289 } 290 291 //_____________________________________________________________________________ 292 G4bool G4RootNtupleFileManager::ActionAtOpenFile([[maybe_unused]] const G4String& fileName) 293 { 294 // Check if fNtupleBookingManager is set 295 296 if ( fNtupleMergeMode == G4NtupleMergeMode::kNone || 297 fNtupleMergeMode == G4NtupleMergeMode::kMain ) { 298 299 G4String objectType = "analysis file"; 300 if ( fNtupleMergeMode == G4NtupleMergeMode::kMain ) { 301 objectType = "main analysis file"; 302 } 303 Message(kVL4, "open", objectType, fileName); 304 305 // Creating files is triggered from CreateNtuple 306 fNtupleManager->CreateNtuplesFromBooking( 307 fBookingManager->GetNtupleBookingVector()); 308 309 Message(kVL1, "open", objectType, fileName); 310 } 311 312 // Creating ntuples from main is triggered from the first Fill call 313 // if ( fNtupleMergeMode == G4NtupleMergeMode::kSlave ) { 314 // // G4cout << "Going to create slave ntuples from main" << G4endl; 315 // fSlaveNtupleManager->CreateNtuplesFromMain(); 316 // } 317 318 return true; 319 } 320 321 //_____________________________________________________________________________ 322 G4bool G4RootNtupleFileManager::ActionAtWrite() 323 { 324 if ( fNtupleMergeMode == G4NtupleMergeMode::kNone ) { 325 return true; 326 } 327 328 auto result = true; 329 330 G4String ntupleType; 331 if ( fNtupleMergeMode == G4NtupleMergeMode::kMain ) ntupleType = "main ntuples"; 332 if ( fNtupleMergeMode == G4NtupleMergeMode::kSlave ) ntupleType = "slave ntuples"; 333 334 Message(kVL4, "merge", ntupleType); 335 336 if ( fNtupleMergeMode == G4NtupleMergeMode::kMain ) { 337 result &= fNtupleManager->Merge(); 338 } 339 340 if ( fNtupleMergeMode == G4NtupleMergeMode::kSlave ) { 341 result &= fSlaveNtupleManager->Merge(); 342 } 343 344 Message(kVL2, "merge", ntupleType, "", result); 345 346 return result; 347 } 348 349 //_____________________________________________________________________________ 350 G4bool G4RootNtupleFileManager::ActionAtCloseFile() 351 { 352 if ( fNtupleMergeMode == G4NtupleMergeMode::kSlave) { 353 fSlaveNtupleManager->SetNewCycle(false); 354 return true; 355 } 356 357 return CloseNtupleFiles(); 358 } 359 360 //_____________________________________________________________________________ 361 G4bool G4RootNtupleFileManager::Reset() 362 { 363 // Reset ntuples 364 365 auto result = true; 366 367 if ( fNtupleMergeMode == G4NtupleMergeMode::kNone || 368 fNtupleMergeMode == G4NtupleMergeMode::kMain ) { 369 result &= fNtupleManager->Reset(); 370 } 371 372 if ( fNtupleMergeMode == G4NtupleMergeMode::kSlave ) { 373 fSlaveNtupleManager->Reset(); 374 } 375 376 return result; 377 } 378