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, 04/10/2016 (ivana@ipno.in2p3.fr) 28 29 #include "G4NtupleBookingManager.hh" 30 #include "G4RootPNtupleManager.hh" 31 #include "G4AnalysisUtilities.hh" 32 33 #include "tools/wroot/file" 34 #include "tools/wroot/ntuple" 35 36 using namespace G4Analysis; 37 using std::to_string; 38 39 // mutex in a file scope 40 namespace { 41 42 //Mutex to lock master manager when adding ntuple row and ending fill 43 G4Mutex pntupleMutex = G4MUTEX_INITIALIZER; 44 //Mutex to lock master manager when createing main ntuples at new cycle 45 G4Mutex createMainMutex = G4MUTEX_INITIALIZER; 46 47 //_____________________________________________________________________________ 48 void NotExistWarning(const G4String& what, G4int id, 49 std::string_view className, 50 std::string_view functionName) 51 { 52 Warn(what + " id= " + to_string(id) + " does not exist.", 53 className, functionName); 54 55 } 56 57 } 58 59 //_____________________________________________________________________________ 60 G4RootPNtupleManager::G4RootPNtupleManager(const G4AnalysisManagerState& state, 61 std::shared_ptr<G4NtupleBookingManager> bookingManger, 62 std::shared_ptr<G4RootMainNtupleManager> main, 63 G4bool rowWise, G4bool rowMode) 64 : G4BaseNtupleManager(state), 65 fBookingManager(std::move(bookingManger)), 66 fMainNtupleManager(std::move(main)), 67 fRowWise(rowWise), 68 fRowMode(rowMode) 69 {} 70 71 //_____________________________________________________________________________ 72 G4RootPNtupleManager::~G4RootPNtupleManager() 73 { 74 for ( auto ntupleDescription : fNtupleDescriptionVector ) { 75 delete ntupleDescription; 76 } 77 } 78 79 // 80 // private functions 81 // 82 83 //_____________________________________________________________________________ 84 G4RootPNtupleDescription* 85 G4RootPNtupleManager::GetNtupleDescriptionInFunction( 86 G4int id, std::string_view functionName, G4bool warn) const 87 { 88 auto index = id - fFirstId; 89 if ( index < 0 || index >= G4int(fNtupleDescriptionVector.size()) ) { 90 if ( warn) { 91 NotExistWarning("ntuple description", id, fkClass, functionName); 92 } 93 return nullptr; 94 } 95 96 return fNtupleDescriptionVector[index]; 97 } 98 99 //_____________________________________________________________________________ 100 tools::wroot::base_pntuple* 101 G4RootPNtupleManager::GetNtupleInFunction( 102 G4int id, std::string_view functionName, G4bool warn) const 103 { 104 auto ntupleDescription = GetNtupleDescriptionInFunction(id, functionName); 105 if (ntupleDescription == nullptr) return nullptr; 106 107 if (ntupleDescription->GetBasePNtuple() == nullptr) { 108 if ( warn ) { 109 NotExistWarning("ntuple", id, fkClass, functionName); 110 } 111 return nullptr; 112 } 113 return ntupleDescription->GetBasePNtuple(); 114 } 115 116 //_____________________________________________________________________________ 117 tools::wroot::ntuple* 118 G4RootPNtupleManager::GetMainNtupleInFunction( 119 G4int id, std::string_view functionName, G4bool warn) const 120 { 121 auto& mainNtupleVector = fMainNtupleManager->GetNtupleVector(); 122 123 auto index = id - fFirstId; 124 if ( index < 0 || index >= G4int(mainNtupleVector.size()) ) { 125 if ( warn) { 126 NotExistWarning("main ntuple", id, fkClass, functionName); 127 } 128 return nullptr; 129 } 130 131 return mainNtupleVector[index]; 132 } 133 134 // 135 // protected functions 136 // 137 138 //_____________________________________________________________________________ 139 void G4RootPNtupleManager::CreateNtupleFromMain( 140 G4RootPNtupleDescription* ntupleDescription, 141 tools::wroot::ntuple* mainNtuple) 142 { 143 // Do not create pntuple if ntuple was deleted 144 if (mainNtuple == nullptr) { 145 ntupleDescription->SetNtuple(nullptr); 146 ntupleDescription->SetBasePNtuple(nullptr); 147 return; 148 } 149 150 Message(kVL4, "create from main", "pntuple", mainNtuple->name()); 151 152 auto file = fMainNtupleManager->GetNtupleFile(&ntupleDescription->GetDescription()); 153 if ( ! file ) { 154 Warn("Cannot create pntuple. Main ntuple file does not exist.", 155 fkClass, "CreateNtupleFromMain"); 156 return; 157 } 158 159 ntupleDescription->GetDescription().SetFile(file); 160 161 // Get parameters from ntupleDescription 162 mainNtuple->get_branches(ntupleDescription->GetMainBranches()); 163 164 auto rfile = std::get<0>(*file); 165 G4bool verbose = true; 166 if ( fRowWise ) { 167 auto mainBranch = mainNtuple->get_row_wise_branch(); 168 auto mtNtuple 169 = new tools::wroot::mt_ntuple_row_wise( 170 G4cout, rfile->byte_swap(), rfile->compression(), 171 mainNtuple->dir().seek_directory(), 172 *mainBranch, mainBranch->basket_size(), 173 ntupleDescription->GetDescription().GetNtupleBooking(), verbose); 174 175 ntupleDescription->SetNtuple( 176 static_cast<tools::wroot::imt_ntuple*>(mtNtuple)); 177 ntupleDescription->SetBasePNtuple( 178 static_cast<tools::wroot::base_pntuple*>(mtNtuple)); 179 } 180 else { 181 std::vector<tools::uint32> basketSizes; 182 tools_vforcit(tools::wroot::branch*, ntupleDescription->GetMainBranches(), it) { 183 basketSizes.push_back((*it)->basket_size()); 184 } 185 auto basketEntries = fMainNtupleManager->GetBasketEntries(); 186 187 auto mtNtuple = 188 new tools::wroot::mt_ntuple_column_wise( 189 G4cout, rfile->byte_swap(), rfile->compression(), 190 mainNtuple->dir().seek_directory(), 191 ntupleDescription->GetMainBranches(), basketSizes, 192 ntupleDescription->GetDescription().GetNtupleBooking(), 193 fRowMode, basketEntries, verbose); 194 195 ntupleDescription->SetNtuple( 196 static_cast<tools::wroot::imt_ntuple*>(mtNtuple)); 197 ntupleDescription->SetBasePNtuple( 198 static_cast<tools::wroot::base_pntuple*>(mtNtuple)); 199 } 200 201 ntupleDescription->GetDescription().SetIsNtupleOwner(true); 202 // // pntuple object is not deleted automatically 203 fNtupleVector.push_back(ntupleDescription->GetNtuple()); 204 205 Message(kVL3, "create from main", "pntuple", mainNtuple->name()); 206 } 207 208 //_____________________________________________________________________________ 209 void G4RootPNtupleManager::CreateNtupleDescriptionsFromBooking() 210 { 211 // Create ntuple descriptions from booking. 212 // This function is called from the first Fill call. 213 214 // Create pntuple descriptions from ntuple booking. 215 auto g4NtupleBookings = fBookingManager->GetNtupleBookingVector(); 216 217 for ( auto g4NtupleBooking : g4NtupleBookings ) { 218 auto ntupleDescription = new G4RootPNtupleDescription(g4NtupleBooking); 219 // Save g4booking, activation in pntuple booking 220 fNtupleDescriptionVector.push_back(ntupleDescription); 221 } 222 } 223 224 //_____________________________________________________________________________ 225 void G4RootPNtupleManager::CreateNtuplesFromMain() 226 { 227 // Create slave ntuples from main ntuple. 228 // This function is called from the first Fill call. 229 230 auto& mainNtupleVector = fMainNtupleManager->GetNtupleVector(); 231 232 G4int lcounter = 0; 233 for ( auto mainNtuple : mainNtupleVector ) { 234 auto& ntupleDescription = fNtupleDescriptionVector[lcounter++]; 235 CreateNtupleFromMain(ntupleDescription, mainNtuple); 236 } 237 } 238 239 //_____________________________________________________________________________ 240 void G4RootPNtupleManager::CreateNtuplesIfNeeded() 241 { 242 // The ntuples on workers are created at first FillColumn or AddRow 243 // (if only columns of vector type) call. 244 // When writing multiple times in teh same file, the main ntuples have 245 // to be recreated as well. 246 247 // G4cout << "G4RootPNtupleManager::CreateNtuplesIfNeeded: " 248 // << " fCreateNtuple: " << fCreateNtuples << " " 249 // << " fNewCycle: " << fNewCycle 250 // << " fMainNtupleManager->GetNewCycle(): " << fMainNtupleManager->GetNewCycle() 251 // << " fNtupleDescriptionVector.size(): " << fNtupleDescriptionVector.size() 252 // << " fNtupleVector.size(): " << fNtupleVector.size() 253 // << G4endl; 254 255 if (fCreateNtuples) { 256 // create ntuple descriptions 257 CreateNtupleDescriptionsFromBooking(); 258 259 // create main ntuples if needed 260 G4AutoLock lock(&createMainMutex); 261 if (fMainNtupleManager->GetNewCycle()) { 262 fMainNtupleManager->CreateNtuplesFromBooking(); 263 } 264 lock.unlock(); 265 266 // create slave ntuples 267 CreateNtuplesFromMain(); 268 fCreateNtuples = false; 269 } 270 271 if (fNewCycle) { 272 // create main ntuples if needed 273 G4AutoLock lock(&createMainMutex); 274 if (fMainNtupleManager->GetNewCycle()) { 275 fMainNtupleManager->CreateNtuplesFromBooking(); 276 } 277 lock.unlock(); 278 279 // create slave ntuples 280 CreateNtuplesFromMain(); 281 fNewCycle = false; 282 } 283 } 284 285 //_____________________________________________________________________________ 286 G4int G4RootPNtupleManager::CreateNtuple(G4NtupleBooking* /*booking*/) 287 { 288 // Create pntuple from g4 ntuple booking. 289 // Nothing to be done here. 290 291 return G4Analysis::kInvalidId; 292 } 293 294 //_____________________________________________________________________________ 295 G4bool G4RootPNtupleManager::FillNtupleIColumn( 296 G4int ntupleId, G4int columnId, G4int value) 297 { 298 return FillNtupleTColumn<int>(ntupleId, columnId, value); 299 } 300 301 //_____________________________________________________________________________ 302 G4bool G4RootPNtupleManager::FillNtupleFColumn( 303 G4int ntupleId, G4int columnId, G4float value) 304 { 305 return FillNtupleTColumn<float>(ntupleId, columnId, value); 306 } 307 308 //_____________________________________________________________________________ 309 G4bool G4RootPNtupleManager::FillNtupleDColumn( 310 G4int ntupleId, G4int columnId, G4double value) 311 { 312 return FillNtupleTColumn<double>(ntupleId, columnId, value); 313 } 314 315 //_____________________________________________________________________________ 316 G4bool G4RootPNtupleManager::FillNtupleSColumn( 317 G4int ntupleId, G4int columnId, const G4String& value) 318 { 319 return FillNtupleTColumn<std::string>(ntupleId, columnId, value); 320 } 321 322 //_____________________________________________________________________________ 323 G4bool G4RootPNtupleManager::AddNtupleRow(G4int ntupleId) 324 { 325 if ( fState.GetIsActivation() && ( ! GetActivation(ntupleId) ) ) { 326 //G4cout << "Skipping AddNtupleRow for " << ntupleId << G4endl; 327 return false; 328 } 329 330 if ( IsVerbose(kVL4) ) { 331 Message(kVL4, "add", "pntuple row", " ntupleId " + to_string(ntupleId)); 332 } 333 334 // Creating ntuples on workers is triggered with the first FillColumn 335 // or AddRow (in only columns of vector type call) 336 CreateNtuplesIfNeeded(); 337 338 auto ntupleDescription = GetNtupleDescriptionInFunction(ntupleId, "AddNtupleRow"); 339 if (ntupleDescription == nullptr) return false; 340 341 auto rfile = std::get<0>(*ntupleDescription->GetDescription().GetFile()); 342 343 G4AutoLock lock(&pntupleMutex); 344 lock.unlock(); 345 mutex toolsLock(lock); 346 auto result 347 = ntupleDescription->GetNtuple()->add_row(toolsLock, *rfile); 348 349 if ( ! result ) { 350 Warn("NtupleId " + to_string(ntupleId) + "adding row failed.", 351 fkClass, "AddNtupleRow"); 352 } 353 354 ntupleDescription->GetDescription().SetHasFill(true); 355 356 if ( IsVerbose(kVL3) ) { 357 Message(kVL3, "add", "pntuple row", " ntupleId " + to_string(ntupleId)); 358 } 359 360 361 return true; 362 } 363 364 //_____________________________________________________________________________ 365 G4bool G4RootPNtupleManager::Merge() 366 { 367 for ( auto ntupleDescription : fNtupleDescriptionVector) { 368 369 // skip inactivated ntuples 370 if (! ntupleDescription->GetDescription().GetActivation() || 371 (ntupleDescription->GetNtuple() == nullptr)) { 372 // G4cout << "skipping inactive ntuple " << G4endl; 373 continue; 374 } 375 376 if ( IsVerbose(kVL4) ) { 377 Message(kVL4, "merge", "pntuple", 378 ntupleDescription->GetDescription().GetNtupleBooking().name()); 379 } 380 381 auto rfile = std::get<0>(*ntupleDescription->GetDescription().GetFile()); 382 383 G4AutoLock lock(&pntupleMutex); 384 lock.unlock(); 385 mutex toolsLock(lock); 386 auto result 387 = ntupleDescription->GetNtuple()->end_fill(toolsLock, *rfile); 388 389 if ( ! result ) { 390 Warn("Ntuple " + ntupleDescription->GetDescription().GetNtupleBooking().name() + 391 "end fill has failed.", fkClass, "Merge"); 392 } 393 394 if ( IsVerbose(kVL3) ) { 395 Message(kVL3, "merge", "pntuple", 396 ntupleDescription->GetDescription().GetNtupleBooking().name()); 397 } 398 399 } 400 401 // Set new cycle 402 fNewCycle = true; 403 404 return true; 405 } 406 407 //_____________________________________________________________________________ 408 G4bool G4RootPNtupleManager::Reset() 409 { 410 // Reset ntuple description, this will delete ntuple if present and 411 // we have its ownership. 412 // The ntuples will be recreated with new cycle or new open file. 413 414 for ( auto ntupleDescription : fNtupleDescriptionVector ) { 415 ntupleDescription->Reset(); 416 } 417 418 fNtupleVector.clear(); 419 420 return true; 421 } 422 423 //_____________________________________________________________________________ 424 void G4RootPNtupleManager::Clear() 425 { 426 for ( auto ntupleDescription : fNtupleDescriptionVector ) { 427 delete ntupleDescription->GetNtuple(); 428 } 429 430 fNtupleDescriptionVector.clear(); 431 fNtupleVector.clear(); 432 433 Message(kVL2, "clear", "pntuples"); 434 } 435 436 //_____________________________________________________________________________ 437 G4bool G4RootPNtupleManager::Delete(G4int id) 438 { 439 if ( IsVerbose(G4Analysis::kVL4) ) { 440 Message(G4Analysis::kVL4, "delete", "pntuple ntupleId " + to_string(id)); 441 } 442 443 auto ntupleDescription = GetNtupleDescriptionInFunction(id, "Delete", true); 444 445 if (ntupleDescription == nullptr) return false; 446 447 // Delete/clear ntuple data 448 delete ntupleDescription->GetNtuple(); 449 ntupleDescription->SetNtuple(nullptr); 450 ntupleDescription->SetBasePNtuple(nullptr); 451 ntupleDescription->GetMainBranches().clear(); 452 453 // Update ntuple vector 454 auto index = id - GetFirstId(); 455 fNtupleVector[index] = nullptr; 456 457 Message(G4Analysis::kVL2, "delete", "pntuple ntupleId " + to_string(id)); 458 459 return true; 460 } 461 462 //_____________________________________________________________________________ 463 464 void G4RootPNtupleManager::SetActivation( 465 G4bool activation) 466 { 467 for ( auto ntupleDescription : fNtupleDescriptionVector ) { 468 ntupleDescription->GetDescription().SetActivation(activation); 469 } 470 } 471 472 //_____________________________________________________________________________ 473 474 void G4RootPNtupleManager::SetActivation( 475 G4int ntupleId, G4bool activation) 476 { 477 auto ntupleDescription = GetNtupleDescriptionInFunction(ntupleId, "SetActivation"); 478 if (ntupleDescription == nullptr) return; 479 480 ntupleDescription->GetDescription().SetActivation(activation); 481 } 482 483 //_____________________________________________________________________________ 484 G4bool G4RootPNtupleManager::GetActivation( 485 G4int ntupleId) const 486 { 487 auto ntupleDescription = GetNtupleDescriptionInFunction(ntupleId, "GetActivation"); 488 if (ntupleDescription == nullptr) return false; 489 490 return ntupleDescription->GetDescription().GetActivation(); 491 } 492 493 //_____________________________________________________________________________ 494 void G4RootPNtupleManager::SetNewCycle(G4bool value) 495 { 496 fNewCycle = value; 497 } 498 499 //_____________________________________________________________________________ 500 G4bool G4RootPNtupleManager::GetNewCycle() const 501 { 502 return fNewCycle; 503 } 504 505 //_____________________________________________________________________________ 506 void G4RootPNtupleManager::SetNtupleRowWise(G4bool rowWise, G4bool rowMode) 507 { 508 fRowWise = rowWise; 509 fRowMode = rowMode; 510 } 511