GRSISort "v4.0.0.5"
An extension of the ROOT analysis Framework
Loading...
Searching...
No Matches
TGRSIFrame.cxx
Go to the documentation of this file.
1#include "TGRSIFrame.h"
2#include "RVersion.h"
3#if ROOT_VERSION_CODE >= ROOT_VERSION(6, 14, 0)
4
5#include <iostream>
6#include <sstream>
7#include <stdexcept>
8
9#include "TFile.h"
10#include "TChain.h"
11#include "ROOT/RDataFrame.hxx"
12#include "ROOT/RDFHelpers.hxx"
13
14#include "TRunInfo.h"
15#include "TPPG.h"
16#include "TDataFrameLibrary.h"
17
18// This assumes the options have been set from argc and argv before! That's true when using grsiframe, other programs need to ensure this happens.
20 : fOptions(TGRSIOptions::Get())
21{
22#if ROOT_VERSION_CODE >= ROOT_VERSION(6, 24, 0)
23 // this increases RDF's verbosity level as long as the `fVerbosity` variable is in scope, i.e. until TGRSIFrame is destroyed
24 if(fOptions->Debug()) {
25#if ROOT_VERSION_CODE >= ROOT_VERSION(6, 36, 0)
26 fVerbosity = new ROOT::RLogScopedVerbosity(ROOT::Detail::RDF::RDFLogChannel(), ROOT::ELogLevel::kInfo);
27#else
28 fVerbosity = new ROOT::Experimental::RLogScopedVerbosity(ROOT::Detail::RDF::RDFLogChannel(), ROOT::Experimental::ELogLevel::kInfo);
29#endif
30 }
31#endif
32
33 // check if we have a tree-name, otherwise get it from the first input file
34 std::string treeName = fOptions->TreeName();
35 if(treeName.empty()) {
36 TFile check(fOptions->RootInputFiles()[0].c_str());
37 if(check.Get("AnalysisTree") != nullptr) {
38 treeName = "AnalysisTree";
39 } else if(check.Get("FragmentTree") != nullptr) {
40 treeName = "FragmentTree";
41 }
42 check.Close();
43 }
44 if(treeName.empty()) {
45 std::ostringstream str;
46 str << "Failed to find 'AnalysisTree' or 'FragmentTree' in '" << fOptions->RootInputFiles()[0] << "', either provide a different tree name via --tree-name flag or check input file" << std::endl;
47 throw std::runtime_error(str.str());
48 }
49
50 // only enable multi threading if number of threads isn't one
51 if(fOptions->GetMaxWorkers() == 1) {
52 ROOT::DisableImplicitMT();
53 } else {
54 // if the number of threads is set to zero, the number of threads used is automatically decided by the implementation
55 ROOT::EnableImplicitMT(fOptions->GetMaxWorkers());
56 }
57
58 auto* chain = new TChain(treeName.c_str());
59
60 fPpg = new TPPG;
61
62 // loop over input files, add them to the chain, and read the runinfo and calibration from them
63 bool first = true;
64 for(const auto& fileName : fOptions->RootInputFiles()) {
65 if(chain->Add(fileName.c_str(), 0) >= 1) { // setting nentries parameter to zero make TChain load the file header and return a 1 if the file was opened successfully
66 TFile* file = TFile::Open(fileName.c_str());
67 if(first) {
68 first = false;
69 TRunInfo::ReadInfoFromFile(file);
70 } else {
71 TRunInfo::AddCurrent();
72 }
73 auto* ppg = static_cast<TPPG*>(file->Get("PPG"));
74 if(ppg != nullptr) {
75 fPpg->Add(ppg);
76 }
77 TChannel::ReadCalFromFile(file);
78 file->Close();
79 } else {
80 std::cout << "Failed to open '" << fileName << "'" << std::endl;
81 }
82 }
83
84 std::cout << "Looped over " << chain->GetNtrees() << "/" << fOptions->RootInputFiles().size() << " files and got:" << std::endl;
86 fPpg->Print("odb");
87
88 fTotalEntries = chain->GetEntries();
89
90 fDataFrame = new ROOT::RDataFrame(*chain);
91
92 // create an input list to pass to the helper
93 auto* inputList = new TList;
94 inputList->Add(fPpg);
95 inputList->Add(TRunInfo::Get());
96 inputList->Add(TGRSIOptions::AnalysisOptions());
97 inputList->Add(TGRSIOptions::UserSettings());
98 int index = 0;
99 for(const auto& valFile : fOptions->ValInputFiles()) {
100 inputList->Add(new TNamed(Form("valFile%d", index++), valFile.c_str()));
101 }
102 index = 0;
103 for(const auto& calFile : fOptions->CalInputFiles()) {
104 inputList->Add(new TNamed(Form("calFile%d", index++), calFile.c_str()));
105 }
106 index = 0;
107 for(const auto& cutFile : fOptions->InputCutFiles()) {
108 inputList->Add(new TNamed(Form("cutFile%d", index++), cutFile.c_str()));
109 }
110
111 /// Try to load an external library with the correct function in it.
112 /// If that library does not exist, try to compile it.
113 /// To handle all that we use the class TDataFrameLibrary (very similar to TParserLibrary)
114 auto* helper = TDataFrameLibrary::Get()->CreateHelper(inputList);
115 fOutputPrefix = helper->Prefix();
116 // this actually moves the helper to the data frame, so from here on "helper" doesn't refer to the object we created anymore
117 // aka don't use helper after this!
118 fOutput = helper->Book(fDataFrame);
119}
120
122{
123 // get runinfo and get run and sub-run number
124 auto* runInfo = TRunInfo::Get();
125
126 // get output file name
127 std::string outputFileName = Form("%s%s.root", fOutputPrefix.c_str(), TRunInfo::CreateLabel(true).c_str());
128 std::cout << "Writing to " << outputFileName << std::endl;
129
130 TFile outputFile(outputFileName.c_str(), "recreate");
131
132 // stop redirect before we start the progress bar (storing the files we redirect stdout and stderr to first)
133 const auto* outFile = redirect->OutFile();
134 const auto* errFile = redirect->ErrFile();
135
136 delete redirect;
137 // this is needed so the function that created the redirect know it has ended
138 // not really needed right now as we create a new redirect further down, but we have it here in case that gets changed
139 redirect = nullptr;
140
141#if ROOT_VERSION_CODE < ROOT_VERSION(6, 30, 0)
142 std::string progressBar;
143 const auto barWidth = 100;
144 if(!fOptions->Debug()) {
145 // create a progress bar with percentage
146 auto entries = fDataFrame->Count();
147 std::mutex barMutex; // Only one thread at a time can lock a mutex. Let's use this to avoid concurrent printing.
148 const auto everyN = fTotalEntries / barWidth;
149 // entries.OnPartialResultSlot(everyN, [&everyN, &fTotalEntries = fTotalEntries, &barWidth, &progressBar, &barMutex](unsigned int /*slot*/, ULong64_t& /*partialList*/) {
150 entries.OnPartialResultSlot(everyN, [&everyN, &fTotalEntries = fTotalEntries, &progressBar, &barMutex](unsigned int /*slot*/, ULong64_t& /*partialList*/) {
151 std::lock_guard<std::mutex> lock(barMutex); // lock_guard locks the mutex at construction, releases it at destruction
152 static int counter = 1;
153 progressBar.push_back('#');
154 // re-print the line with the progress bar
155 std::cout << "\r[" << std::left << std::setw(barWidth) << progressBar << ' ' << std::setw(3) << (counter * everyN * 100) / fTotalEntries << " %]" << std::flush;
156 ++counter;
157 });
158 }
159#else
160 ROOT::RDF::Experimental::AddProgressBar(*fDataFrame);
161#endif
162
163 if(fOutput != nullptr) {
164 // accessing the result from Book causes the actual processing of the helper
165 // so we try and catch any exception
166 try {
167 for(auto& list : *fOutput) {
168 // try and switch to the directory this list should be written to
169 if(gDirectory->GetDirectory(list.first.c_str()) && gDirectory->cd(list.first.c_str())) {
170 list.second.Write();
171 } else {
172 // directory this list should be written to doesn't exist, so create it
173 gDirectory->mkdir(list.first.c_str());
174 if(gDirectory->cd(list.first.c_str())) {
175 list.second.Write();
176 } else {
177 std::cout << "Error, failed to find or create path " << list.first << ", writing into " << gDirectory->GetPath() << std::endl;
178 }
179 }
180 // switch back to topmost directory
181 while(gDirectory->GetDirectory("..")) { gDirectory->cd(".."); }
182 }
183#if ROOT_VERSION_CODE < ROOT_VERSION(6, 30, 0)
184 std::cout << "\r[" << std::left << std::setw(barWidth) << progressBar << ' ' << "100 %]" << std::flush;
185#endif
187 std::cout << DRED << "Exception in " << __PRETTY_FUNCTION__ << ": " << e.detail() << RESET_COLOR << std::endl; // NOLINT(cppcoreguidelines-pro-type-const-cast, cppcoreguidelines-pro-bounds-array-to-pointer-decay)
188 throw e;
189 }
190 } else {
191 std::cout << "Error, output list is nullptr!" << std::endl;
192 }
193
194 // start new redirect, appending to the previous files we had redirected to
195 redirect = new TRedirect(outFile, errFile, true);
196
197 runInfo->Write();
198 if(fPpg != nullptr) {
199 fPpg->Write();
200 } else {
201 std::cerr << "failed to find TPPG, can't write it!" << std::endl;
202 }
204 TGRSIOptions::UserSettings()->Write("UserSettings", TObject::kOverwrite);
206 outputFile.Close();
207 std::cout << "Closed '" << outputFile.GetName() << "'" << std::endl;
208}
209
211{
212 // does nothing
213}
214#endif
#define DRED
Definition Globals.h:18
#define RESET_COLOR
Definition Globals.h:5
void DummyFunctionToLocateTGRSIFrameLibrary()
bool WriteToFile(const std::string &file)
static int WriteToRoot(TFile *fileptr=nullptr)
TGRSIHelper * CreateHelper(TList *list)
TPPG * fPpg
Definition TGRSIFrame.h:47
std::string fOutputPrefix
Definition TGRSIFrame.h:43
TGRSIOptions * fOptions
Definition TGRSIFrame.h:46
void Run(TRedirect *&redirect)
Long64_t fTotalEntries
Definition TGRSIFrame.h:50
ROOT::RDataFrame * fDataFrame
Definition TGRSIFrame.h:49
ROOT::RDF::RResultPtr< std::map< std::string, TList > > fOutput
Definition TGRSIFrame.h:44
std::string & Prefix()
Definition TGRSIHelper.h:40
std::string detail() const noexcept
Definition TGRSIMap.h:112
static TUserSettings * UserSettings()
static TAnalysisOptions * AnalysisOptions()
std::string TreeName() const
bool Debug() const
Definition TPPG.h:132
Int_t Write(const char *name=nullptr, Int_t option=0, Int_t bufsize=0) override
Definition TPPG.h:149
const char * OutFile()
Definition TRedirect.h:39
const char * ErrFile()
Definition TRedirect.h:40
void Print(Option_t *opt="") const override
Definition TRunInfo.cxx:72
static std::string CreateLabel(bool quiet=false)
Definition TRunInfo.cxx:582
static TRunInfo * Get(bool verbose=false)
Definition TSingleton.h:33