Skip to content

Commit c79d9ed

Browse files
authored
Merge pull request #95 from rest-for-physics/lobis-merge
Macro to merge simulation files
2 parents 9ba07e6 + 014e28e commit c79d9ed

File tree

6 files changed

+183
-10
lines changed

6 files changed

+183
-10
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ install(FILES ${MAC} DESTINATION ./macros/geant4)
5959

6060
set(rest_macros ${rest_macros} "restGeant4_ViewEvent")
6161
set(rest_macros ${rest_macros} "restGeant4_ViewGeometry")
62+
set(rest_macros ${rest_macros} "restGeant4_MergeRestG4Files")
6263
set(rest_macros
6364
${rest_macros}
6465
PARENT_SCOPE)

inc/TRestGeant4Metadata.h

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ class TRestGeant4Metadata : public TRestMetadata {
5656
void ReadDetector();
5757
void ReadBiasing();
5858

59+
// Metadata is the result of a merge of other metadata
60+
bool fIsMerge = false;
61+
5962
/// Class used to store and retrieve geometry info
6063
TRestGeant4GeometryInfo fGeant4GeometryInfo;
6164

@@ -306,7 +309,7 @@ class TRestGeant4Metadata : public TRestMetadata {
306309

307310
/// Returns the probability per event to register (write to disk) hits in a GDML volume given its geometry
308311
/// name.
309-
Double_t GetStorageChance(TString volume);
312+
Double_t GetStorageChance(const TString& volume);
310313

311314
Double_t GetMaxStepSize(const TString& volume);
312315

@@ -364,20 +367,25 @@ class TRestGeant4Metadata : public TRestMetadata {
364367
/// Returns the world magnetic field in Tesla
365368
inline TVector3 GetMagneticField() const { return fMagneticField; }
366369

367-
Int_t GetActiveVolumeID(TString name);
370+
Int_t GetActiveVolumeID(const TString& name);
368371

369372
Bool_t isVolumeStored(const TString& volume) const;
370373

371374
void SetActiveVolume(const TString& name, Double_t chance, Double_t maxStep = 0);
372375

373376
void PrintMetadata() override;
374377

378+
void Merge(const TRestGeant4Metadata&);
379+
375380
TRestGeant4Metadata();
376381
TRestGeant4Metadata(const char* configFilename, const std::string& name = "");
377382

378383
~TRestGeant4Metadata();
379384

380-
ClassDefOverride(TRestGeant4Metadata, 13);
385+
TRestGeant4Metadata(const TRestGeant4Metadata& metadata);
386+
TRestGeant4Metadata& operator=(const TRestGeant4Metadata& metadata);
387+
388+
ClassDefOverride(TRestGeant4Metadata, 14);
381389

382390
// Allow modification of otherwise inaccessible / immutable members that shouldn't be modified by the user
383391
friend class SteppingAction;

inc/TRestGeant4PhysicsInfo.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
class G4VProcess;
1212

1313
class TRestGeant4PhysicsInfo {
14-
ClassDef(TRestGeant4PhysicsInfo, 2);
14+
ClassDef(TRestGeant4PhysicsInfo, 3);
1515

1616
private:
1717
std::map<Int_t, TString> fProcessNamesMap = {};
@@ -22,8 +22,6 @@ class TRestGeant4PhysicsInfo {
2222

2323
std::map<TString, TString> fProcessTypesMap = {}; // process name -> process type
2424

25-
std::mutex fMutex; //!
26-
2725
public:
2826
TString GetProcessName(Int_t id) const;
2927
Int_t GetProcessID(const TString& processName) const;
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
#include <string>
2+
#include <vector>
3+
4+
#include "TRestGeant4Event.h"
5+
#include "TRestGeant4Metadata.h"
6+
#include "TRestTask.h"
7+
8+
#ifndef RestTask_Geant4_MergeRestG4Files
9+
#define RestTask_Geant4_MergeRestG4Files
10+
11+
//*******************************************************************************************************
12+
//***
13+
//*** Your HELP is needed to verify, validate and document this macro.
14+
//*** This macro might need update/revision.
15+
//***
16+
//*******************************************************************************************************
17+
18+
/*
19+
* Author: Luis Obis (lobis@unizar.es)
20+
* Description: Macro used to merge simulation files, before any analysis is performed
21+
* All files are understood to have the same configuration (same generator, same detector, etc.)
22+
* They can only differ in the random seed, run number or number of events.
23+
*/
24+
25+
// Usage:
26+
// restGeant4_MergeRestG4Files merge_result.root /path/to/directory/with/files/*.root
27+
28+
using namespace std;
29+
30+
void REST_Geant4_MergeRestG4Files(const char* outputFilename, const char* inputFilesDirectory) {
31+
// TODO: use glob pattern instead of directory. Already tried this but conflicts with TRestTask...
32+
33+
cout << "Output file: " << outputFilename << endl;
34+
// print input
35+
cout << "Input files directory: " << inputFilesDirectory << endl;
36+
37+
// find all .root files in the directory
38+
vector<string> inputFiles = TRestTools::GetFilesMatchingPattern(string(inputFilesDirectory) + "/*.root");
39+
40+
cout << "Number of input files: " << inputFiles.size() << endl;
41+
for (auto file : inputFiles) {
42+
cout << " - " << file << endl;
43+
}
44+
45+
if (inputFiles.size() == 0) {
46+
cerr << "No input files found" << endl;
47+
exit(1);
48+
}
49+
50+
// open the first file
51+
TRestGeant4Metadata mergeMetadata;
52+
53+
auto mergeRun = new TRestRun();
54+
mergeRun->SetName("run");
55+
mergeRun->SetOutputFileName(outputFilename);
56+
mergeRun->FormOutputFile();
57+
mergeRun->GetOutputFile()->cd();
58+
mergeRun->SetRunType("restG4");
59+
60+
TRestGeant4Event* mergeEvent = nullptr;
61+
auto mergeEventTree = mergeRun->GetEventTree();
62+
mergeEventTree->Branch("TRestGeant4EventBranch", "TRestGeant4Event", &mergeEvent);
63+
64+
set<Int_t> eventIds;
65+
66+
// iterate over all other files
67+
for (int i = 0; i < inputFiles.size(); i++) {
68+
cout << "Processing file " << i + 1 << "/" << inputFiles.size() << endl;
69+
70+
map<Int_t, Int_t>
71+
eventIdUpdates; // repeatedId -> newId. Make sure if there are repeated event ids in a file
72+
// (because of sub-events) they keep the same event id after modification
73+
auto run = TRestRun(inputFiles[i].c_str());
74+
auto metadata = (TRestGeant4Metadata*)run.GetMetadataClass("TRestGeant4Metadata");
75+
if (i == 0) {
76+
mergeMetadata = *metadata;
77+
} else {
78+
mergeMetadata.Merge(*metadata);
79+
}
80+
TRestGeant4Event* event = nullptr;
81+
auto eventTree = run.GetEventTree();
82+
eventTree->SetBranchAddress("TRestGeant4EventBranch", &event);
83+
for (int j = 0; j < eventTree->GetEntries(); j++) {
84+
eventTree->GetEntry(j);
85+
*mergeEvent = *event;
86+
87+
Int_t eventId = mergeEvent->GetID();
88+
if (eventIdUpdates.find(eventId) != eventIdUpdates.end()) {
89+
eventId = eventIdUpdates[eventId];
90+
cout << "WARNING: event ID " << mergeEvent->GetID() << " with sub-event ID "
91+
<< mergeEvent->GetSubID() << " already exists. It was already changed to " << eventId
92+
<< endl;
93+
} else if (eventIds.find(eventId) != eventIds.end()) {
94+
const Int_t maxEventId = *max_element(eventIds.begin(), eventIds.end());
95+
eventId = maxEventId + 1;
96+
eventIdUpdates[mergeEvent->GetID()] = eventId;
97+
cout << "WARNING: event ID " << mergeEvent->GetID() << " with sub-event ID "
98+
<< mergeEvent->GetSubID() << " already exists. Changing to " << eventId << endl;
99+
}
100+
mergeEvent->SetID(eventId);
101+
eventIds.insert(mergeEvent->GetID());
102+
103+
mergeEventTree->Fill();
104+
mergeRun->GetAnalysisTree()->Fill();
105+
}
106+
}
107+
108+
cout << "Output filename: " << mergeRun->GetOutputFileName() << endl;
109+
cout << "Output file: " << mergeRun->GetOutputFile() << endl;
110+
111+
mergeRun->GetOutputFile()->cd();
112+
113+
gGeoManager->Write("Geometry", TObject::kOverwrite);
114+
115+
mergeMetadata.SetName("geant4Metadata");
116+
mergeMetadata.Write();
117+
mergeRun->UpdateOutputFile();
118+
mergeRun->CloseFile();
119+
}
120+
121+
#endif

src/TRestGeant4Metadata.cxx

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1485,7 +1485,7 @@ void TRestGeant4Metadata::PrintMetadata() {
14851485

14861486
///////////////////////////////////////////////
14871487
/// \brief Returns the id of an active volume giving as parameter its name.
1488-
Int_t TRestGeant4Metadata::GetActiveVolumeID(TString name) {
1488+
Int_t TRestGeant4Metadata::GetActiveVolumeID(const TString& name) {
14891489
Int_t id;
14901490
for (id = 0; id < (Int_t)fActiveVolumes.size(); id++) {
14911491
if (fActiveVolumes[id] == name) return id;
@@ -1536,7 +1536,7 @@ Bool_t TRestGeant4Metadata::isVolumeStored(const TString& volume) const {
15361536
///////////////////////////////////////////////
15371537
/// \brief Returns the probability of an active volume being stored
15381538
///
1539-
Double_t TRestGeant4Metadata::GetStorageChance(TString volume) {
1539+
Double_t TRestGeant4Metadata::GetStorageChance(const TString& volume) {
15401540
Int_t id;
15411541
for (id = 0; id < (Int_t)fActiveVolumes.size(); id++) {
15421542
if (fActiveVolumes[id] == volume) return fChance[id];
@@ -1571,3 +1571,46 @@ size_t TRestGeant4Metadata::GetGeant4VersionMajor() const {
15711571
}
15721572
return std::stoi(majorVersion.Data());
15731573
}
1574+
1575+
void TRestGeant4Metadata::Merge(const TRestGeant4Metadata& metadata) {
1576+
fIsMerge = true;
1577+
1578+
fNEvents += metadata.fNEvents;
1579+
fNRequestedEntries += metadata.fNRequestedEntries;
1580+
fSeed = 0; // seed makes no sense in a merged file
1581+
}
1582+
1583+
TRestGeant4Metadata::TRestGeant4Metadata(const TRestGeant4Metadata& metadata) { *this = metadata; }
1584+
1585+
TRestGeant4Metadata& TRestGeant4Metadata::operator=(const TRestGeant4Metadata& metadata) {
1586+
fIsMerge = metadata.fIsMerge;
1587+
fGeant4GeometryInfo = metadata.fGeant4GeometryInfo;
1588+
fGeant4PhysicsInfo = metadata.fGeant4PhysicsInfo;
1589+
fGeant4PrimaryGeneratorInfo = metadata.fGeant4PrimaryGeneratorInfo;
1590+
fGeant4Version = metadata.fGeant4Version;
1591+
fGdmlReference = metadata.fGdmlReference;
1592+
fMaterialsReference = metadata.fMaterialsReference;
1593+
fEnergyRangeStored = metadata.fEnergyRangeStored;
1594+
fActiveVolumes = metadata.fActiveVolumes;
1595+
fChance = metadata.fChance;
1596+
fMaxStepSize = metadata.fMaxStepSize;
1597+
// fParticleSource = metadata.fParticleSource; // segfaults (pointers!)
1598+
fNBiasingVolumes = metadata.fNBiasingVolumes;
1599+
fBiasingVolumes = metadata.fBiasingVolumes;
1600+
fMaxTargetStepSize = metadata.fMaxTargetStepSize;
1601+
fSubEventTimeDelay = metadata.fSubEventTimeDelay;
1602+
fFullChain = metadata.fFullChain;
1603+
fSensitiveVolumes = metadata.fSensitiveVolumes;
1604+
fNEvents = metadata.fNEvents;
1605+
fNRequestedEntries = metadata.fNRequestedEntries;
1606+
fSimulationMaxTimeSeconds = metadata.fSimulationMaxTimeSeconds;
1607+
fSeed = metadata.fSeed;
1608+
fSaveAllEvents = metadata.fSaveAllEvents;
1609+
fRemoveUnwantedTracks = metadata.fRemoveUnwantedTracks;
1610+
fRemoveUnwantedTracksKeepZeroEnergyTracks = metadata.fRemoveUnwantedTracksKeepZeroEnergyTracks;
1611+
fRemoveUnwantedTracksVolumesToKeep = metadata.fRemoveUnwantedTracksVolumesToKeep;
1612+
fKillVolumes = metadata.fKillVolumes;
1613+
fRegisterEmptyTracks = metadata.fRegisterEmptyTracks;
1614+
fMagneticField = metadata.fMagneticField;
1615+
return *this;
1616+
}

src/TRestGeant4PhysicsInfo.cxx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ using namespace std;
77

88
ClassImp(TRestGeant4PhysicsInfo);
99

10+
std::mutex insertMutex;
11+
1012
set<TString> TRestGeant4PhysicsInfo::GetAllParticles() const {
1113
set<TString> particles = {};
1214
for (const auto& [_, name] : fParticleNamesMap) {
@@ -59,7 +61,7 @@ void TRestGeant4PhysicsInfo::InsertProcessName(Int_t id, const TString& processN
5961
if (fProcessNamesMap.count(id) > 0) {
6062
return;
6163
}
62-
std::lock_guard<std::mutex> lock(fMutex);
64+
std::lock_guard<std::mutex> lock(insertMutex);
6365
fProcessNamesMap[id] = processName;
6466
fProcessNamesReverseMap[processName] = id;
6567

@@ -70,7 +72,7 @@ void TRestGeant4PhysicsInfo::InsertParticleName(Int_t id, const TString& particl
7072
if (fParticleNamesMap.count(id) > 0) {
7173
return;
7274
}
73-
std::lock_guard<std::mutex> lock(fMutex);
75+
std::lock_guard<std::mutex> lock(insertMutex);
7476
fParticleNamesMap[id] = particleName;
7577
fParticleNamesReverseMap[particleName] = id;
7678
}

0 commit comments

Comments
 (0)