12 #include "montecarlo/dataobjs/GGSTHitVolInfo.h"
13 #include "montecarlo/dataobjs/GGSTParameters.h"
17 #include "G4LogicalVolume.hh"
19 #include "G4SystemOfUnits.hh"
21 #include "ROOT/TBufferMerger.hxx"
30 inline void hash_combine_impl(uint64_t &h, uint64_t k) {
31 constexpr uint64_t m = UINT64_C(0xc6a4a7935bd1e995);
45 template <
class T>
inline void hash_combine(uint64_t &seed, T
const &v) {
47 hash_combine_impl(seed, hasher(v));
52 uint64_t operator()(GGSRootFileService::VolumeKey
const &key)
const noexcept {
54 hash_combine(seed, key.name);
55 hash_combine(seed, key.physVol);
56 hash_combine(seed, key.position[0]);
57 hash_combine(seed, key.position[1]);
58 hash_combine(seed, key.position[2]);
65 G4ThreadLocal TFile *GGSRootFileService::_currVolStorageTFile =
nullptr;
66 G4ThreadLocal std::string GGSRootFileService::_currDetVolName =
"";
67 G4ThreadLocal GGSRootFileService::FileInfoContainer::iterator GGSRootFileService::_currVolStorageFileInfo;
68 G4ThreadLocal GGSRootFileService::HitDetMap::iterator GGSRootFileService::_currDetector;
69 G4ThreadLocal
GGSTHitDetInfo *GGSRootFileService::_currPersDetector =
nullptr;
76 GGSRootFileService::GGSRootFileService()
77 : _suffix(
""), _defaultOutBase(
"GGSRootOutput"), _singleFileForMT(true), _messenger(this,
"/GGS/rootOutput/") {
78 _messenger.DeclareMethod(
"setMultiFileForMT", &GGSRootFileService::_SetMultiFileMode,
79 "Set the output mode for MT mode to one file per thread");
83 G4Mutex mutexForGetFile = G4MUTEX_INITIALIZER;
87 G4AutoLock lock(mutexForGetFile);
89 std::filesystem::path absPath;
92 if (baseName.string() ==
"") {
93 absPath = _defaultOutBase;
99 absPath = _GetAbsolutePath(absPath);
102 absPath = _AppendSuffixAndExt(absPath, run);
105 auto CreateNewTFile = [
this, &absPath](FileInfoContainer::iterator fileInfoIter) -> TFile * {
106 std::shared_ptr<TFile> newTFile =
nullptr;
107 if (G4Threading::IsMultithreadedApplication() && _singleFileForMT) {
109 if (!fileInfoIter->bufferMerger) {
110 fileInfoIter->bufferMerger = std::make_unique<ROOT::TBufferMerger>(absPath.string().c_str());
112 newTFile = fileInfoIter->bufferMerger->GetFile();
115 if (fileInfoIter->tFilesInfo.size() != 0) {
116 G4Exception(
"GGSRootFileService::GetFileForThisRun",
"TFile clash", G4ExceptionSeverity::FatalException,
117 (
"A TFile is already existing for file " + absPath.string() +
" in ST mode; can't create it again")
120 newTFile = std::make_shared<TFile>(absPath.string().c_str(),
"RECREATE");
122 fileInfoIter->tFilesInfo.emplace_back();
123 auto &tFileInfo = fileInfoIter->tFilesInfo.back();
124 tFileInfo.tFile = newTFile;
125 tFileInfo.defaultEventsTree =
nullptr;
126 tFileInfo.threadNo = G4Threading::G4GetThreadId();
127 tFileInfo.nRequests = 1;
129 return newTFile.get();
133 int iThread = G4Threading::G4GetThreadId();
134 auto fileInfoIter = _filesInfo.begin();
135 for (; fileInfoIter != _filesInfo.end(); ++fileInfoIter) {
136 if (absPath == fileInfoIter->absPath) {
138 for (
auto &tFileInfo : fileInfoIter->tFilesInfo) {
139 if (tFileInfo.threadNo == iThread) {
140 ++(tFileInfo.nRequests);
141 return tFileInfo.tFile.get();
145 return CreateNewTFile(fileInfoIter);
150 _filesInfo.emplace_back();
151 fileInfoIter = --(_filesInfo.end());
152 fileInfoIter->absPath = absPath;
155 TFile *newTFile = CreateNewTFile(fileInfoIter);
158 _currVolStorageTFile =
nullptr;
159 _currDetVolName =
"";
165 G4Mutex mutexForCloseFile = G4MUTEX_INITIALIZER;
169 G4AutoLock lock(mutexForCloseFile);
171 std::filesystem::path absPath;
174 if (baseName.string() ==
"") {
175 absPath = _defaultOutBase;
179 absPath = _GetAbsolutePath(absPath);
182 absPath = _AppendSuffixAndExt(absPath, run);
185 auto WriteGeneralSimInfo = [
this](TFile *outFile) {
187 outFile->WriteObjectAny(&_simInfo,
"GGSTSimInfo", _simInfo.GetName());
200 outFile->WriteObject(&geoParams,
"GGSGeoParams");
206 dynamic_cast<const GGSGeneratorAction *
>(GGSRunManager::GetRunManager()->GetUserPrimaryGeneratorAction());
210 generatorParams.
GetParam<std::string>(
"generator");
211 outFile->WriteObject(&generatorParams,
"GGSGenParams");
217 int iThread = G4Threading::G4GetThreadId();
218 for (
auto fileInfoIter = _filesInfo.begin(); fileInfoIter != _filesInfo.end(); ++fileInfoIter) {
219 if (fileInfoIter->absPath == absPath) {
220 for (
auto tFileInfoIter = fileInfoIter->tFilesInfo.begin(); tFileInfoIter != fileInfoIter->tFilesInfo.end();
222 if (tFileInfoIter->threadNo == iThread) {
223 --(tFileInfoIter->nRequests);
224 if (tFileInfoIter->nRequests == 0) {
225 if (tFileInfoIter->defaultEventsTree) {
226 tFileInfoIter->defaultEventsTree->Write();
230 if (!(fileInfoIter->bufferMerger)) {
231 if (fileInfoIter->detectorsArray) {
232 tFileInfoIter->tFile->WriteObject(fileInfoIter->detectorsArray,
"GGSHitDetInfo",
"SingleKey");
234 WriteGeneralSimInfo(tFileInfoIter->tFile.get());
239 GGSSmartLog::MuteOutput();
240 tFileInfoIter->tFile->Write();
241 GGSSmartLog::UnmuteOutput();
242 tFileInfoIter = --(fileInfoIter->tFilesInfo.erase(tFileInfoIter));
248 if (fileInfoIter->tFilesInfo.size() == 0) {
249 if (fileInfoIter->bufferMerger) {
251 fileInfoIter->bufferMerger.reset();
253 auto outFile = std::unique_ptr<TFile>(TFile::Open(fileInfoIter->absPath.string().c_str(),
"UPDATE"));
254 if (fileInfoIter->detectorsArray) {
255 outFile->WriteObject(fileInfoIter->detectorsArray,
"GGSHitDetInfo",
"SingleKey");
257 WriteGeneralSimInfo(outFile.get());
260 fileInfoIter = --(_filesInfo.erase(fileInfoIter));
269 G4AutoLock lock(mutexForGetFile);
271 for (
auto &fileInfo : _filesInfo) {
272 for (
auto &tFileInfo : fileInfo.tFilesInfo) {
273 if (file == tFileInfo.tFile.get()) {
274 if (tFileInfo.defaultEventsTree ==
nullptr) {
275 tFileInfo.defaultEventsTree =
new TTree(
"GGSEventsTree",
"GGS events tree. Info: ", 99, file);
277 return tFileInfo.defaultEventsTree;
284 std::filesystem::path GGSRootFileService::_GetAbsolutePath(
const std::filesystem::path &baseName) {
286 std::filesystem::path absPath(baseName);
288 absPath = absolute(baseName);
293 std::filesystem::path GGSRootFileService::_AppendSuffixAndExt(
const std::filesystem::path &baseName,
const G4Run *run) {
295 std::filesystem::path absPath(baseName);
296 absPath.replace_extension();
299 if (G4Threading::IsMultithreadedApplication() && !_singleFileForMT) {
300 absPath +=
"_Thread" + std::to_string(G4Threading::G4GetThreadId());
304 int runID = run->GetRunID();
306 absPath +=
"_Run" + std::to_string(runID);
311 absPath +=
"_" + _suffix;
320 void GGSRootFileService::_SetMultiFileMode() {
321 const std::string routineName(
"GGSRootFileService::_SetMultiFileMode");
322 if (G4Threading::IsMultithreadedApplication()) {
323 _singleFileForMT =
false;
325 GGSCOUT(WARNING) <<
"ST application: ignoring multi-file output setting" <<
GGSENDL;
329 void GGSRootFileService::_FillDefaultEventsTrees() {
332 for (
auto &fileInfo : _filesInfo) {
333 for (
auto &tFileInfo : fileInfo.tFilesInfo) {
334 if (tFileInfo.tFile && tFileInfo.defaultEventsTree && tFileInfo.threadNo == G4Threading::G4GetThreadId()) {
335 tFileInfo.tFile->cd();
336 tFileInfo.defaultEventsTree->Fill();
343 G4Mutex mutexForStoreVolume = G4MUTEX_INITIALIZER;
346 const G4ThreeVector &position,
int id) {
347 static const std::string routineName(
"GGSRootFileService::StoreVolume");
349 G4AutoLock lock(mutexForStoreVolume);
350 std::string detVolName = detector.substr(0, detector.find_first_of(
'.'));
353 bool fileChanged =
false, found =
false;
354 if (tFilePtr != _currVolStorageTFile) {
356 _currVolStorageTFile = tFilePtr;
358 for (_currVolStorageFileInfo = _filesInfo.begin(); _currVolStorageFileInfo != _filesInfo.end();
359 ++_currVolStorageFileInfo) {
360 for (
auto &tFileInfo : _currVolStorageFileInfo->tFilesInfo) {
361 if (tFileInfo.tFile.get() == tFilePtr) {
371 G4Exception(
"GGSRootFileService::StoreVolume",
"TFile not found", G4ExceptionSeverity::FatalException,
372 (std::string(
"TFile for ") + tFilePtr->GetName() +
" is not managed by GGSRootFileService").c_str());
377 if (fileChanged || _currDetVolName != detVolName) {
378 _currDetVolName = detVolName;
379 int currPersDetectorIndex = 0;
380 for (_currDetector = _currVolStorageFileInfo->detectorsMap.begin();
381 _currDetector != _currVolStorageFileInfo->detectorsMap.end(); ++_currDetector, ++currPersDetectorIndex) {
382 if (_currDetector->first == _currDetVolName) {
386 if (_currDetector == _currVolStorageFileInfo->detectorsMap.end()) {
388 _currVolStorageFileInfo->detectorsMap.push_back(
389 std::make_pair<std::string, HitVolMap>(std::string(_currDetVolName), HitVolMap()));
390 _currDetector = _currVolStorageFileInfo->detectorsMap.end();
392 if (_currVolStorageFileInfo->detectorsArray ==
nullptr) {
393 _currVolStorageFileInfo->detectorsArray =
new TClonesArray(
"GGSTHitDetInfo");
395 currPersDetectorIndex = _currVolStorageFileInfo->detectorsArray->GetEntries();
396 _currPersDetector =
new ((*(_currVolStorageFileInfo->detectorsArray))[currPersDetectorIndex])
GGSTHitDetInfo;
397 _currPersDetector->
detectorName = _currDetVolName.data();
400 _currPersDetector = (
GGSTHitDetInfo *)(_currVolStorageFileInfo->detectorsArray->At(currPersDetectorIndex));
407 std::string volAndId = volume->GetName() + std::to_string(
id);
410 _currDetector->second.emplace(VolumeKey(volAndId, volume, position), _currPersDetector->
volumes.GetEntries());
411 if (insertResult.second) {
415 volInfo->
volumeName = volume->GetName().data();
416 for (
int i = 0; i < 3; i++) {
417 volInfo->
volumePos[i] = position[i] / cm;
421 return _currPersDetector->
volumes.GetEntries() - 1;
424 return insertResult.first->second;
Float_t volumePos[3]
Position of the touchable in world volume coordinates [cm].
Int_t id
ID of the volume.
const std::map< std::string, std::vector< bool > > & GetVectBoolParameters()
Getter method for vector-of-booleans geometry parameters.
void SetVectBoolGeoParams(const std::map< std::string, std::vector< bool >> &vectBoolGeoParams)
Sets the vector-of-booleans geometry parameters.
Class to store detector informations.
const std::map< std::string, int > & GetIntParameters()
Getter method for integer geometry parameters.
int StoreVolume(TFile *tFilePtr, const std::string &detector, const G4VPhysicalVolume *volume, const G4ThreeVector &position, int id)
Set persistence for the specified volume.
const std::map< std::string, double > & GetRealParameters()
Getter method for real geometry parameters.
Base class for GGS generator actions.
Abstract class needed to load GGS geometry.
TFile * GetFileForThisRun(const std::filesystem::path &baseName, const G4Run *run)
Opens a file for a given run and returns a pointer to it.
static GGSGeoPluginManager & GetInstance()
Get the singleton instance.
T GetParam(const std::string &name) const
Gets a parameter.
void SetStringGeoParams(const std::map< std::string, std::string > &stringGeoParams)
Sets the string geometry parameters.
const std::map< std::string, std::vector< std::string > > & GetVectStringParameters()
Getter method for vector-of-strings geometry parameters.
void CloseFileForThisRun(const std::filesystem::path &baseName, const G4Run *run)
Closes the ROOT output file.
void SetRealGeoParams(const std::map< std::string, double > &realGeoParams)
Sets the real geometry parameters.
const std::map< std::string, std::vector< int > > & GetVectIntParameters()
Getter method for vector-of-integers geometry parameters.
const std::map< std::string, std::string > & GetStringParameters()
Getter method for string geometry parameters.
TClonesArray volumes
Array of GGSTHitVolInfo objects.
Singleton for a centralized ROOT files management.
const std::map< std::string, std::vector< double > > & GetVectRealParameters()
Getter method for vector-of-reals geometry parameters.
void SetVectRealGeoParams(const std::map< std::string, std::vector< double >> &vectRealGeoParams)
Sets the vector-of-reals geometry parameters.
void SetVectStringGeoParams(const std::map< std::string, std::vector< std::string >> &vectStringGeoParams)
Sets the vector-of-strings geometry parameters.
const std::map< std::string, bool > & GetBoolParameters()
Getter method for boolean geometry parameters.
Class for storing the geometry parameters on Root output file.
TTree * GetDefaultTree(TFile *file)
Gets the default tree for this file.
static GGSRootFileService & GetInstance()
Get reference to GGSRootFileService unique instance.
void SetVectIntGeoParams(const std::map< std::string, std::vector< int >> &vectIntGeoParams)
Sets the vector-of-integers geometry parameters.
TString volumeName
Name of the physical volume.
GGSVGeometryConstruction * GetGeoConstruction()
Returns the geometry construction object.
void SetBoolGeoParams(const std::map< std::string, bool > &boolGeoParams)
Sets the boolean geometry parameters.
GGSTHitVolInfo.h GGSTHitVolInfo class declaration.
TString detectorName
Name of detector associated to integrated hits.
Class for writing parameters into the output Root file.
void SetIntGeoParams(const std::map< std::string, int > &intGeoParams)
Sets the integer geometry parameters.