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 zero
51 if(fOptions->GetMaxWorkers() > 0) {
52 ROOT::EnableImplicitMT(fOptions->GetMaxWorkers());
53 }
54
55 auto* chain = new TChain(treeName.c_str());
56
57 fPpg = new TPPG;
58
59 // loop over input files, add them to the chain, and read the runinfo and calibration from them
60 bool first = true;
61 for(const auto& fileName : fOptions->RootInputFiles()) {
62 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
63 TFile* file = TFile::Open(fileName.c_str());
64 if(first) {
65 first = false;
66 TRunInfo::ReadInfoFromFile(file);
67 } else {
68 TRunInfo::AddCurrent();
69 }
70 auto* ppg = static_cast<TPPG*>(file->Get("PPG"));
71 if(ppg != nullptr) {
72 fPpg->Add(ppg);
73 }
74 TChannel::ReadCalFromFile(file);
75 file->Close();
76 } else {
77 std::cout << "Failed to open '" << fileName << "'" << std::endl;
78 }
79 }
80
81 std::cout << "Looped over " << chain->GetNtrees() << "/" << fOptions->RootInputFiles().size() << " files and got:" << std::endl;
83 fPpg->Print("odb");
84
85 fTotalEntries = chain->GetEntries();
86
87 fDataFrame = new ROOT::RDataFrame(*chain);
88
89 // create an input list to pass to the helper
90 auto* inputList = new TList;
91 inputList->Add(fPpg);
92 inputList->Add(TRunInfo::Get());
93 inputList->Add(TGRSIOptions::AnalysisOptions());
94 inputList->Add(TGRSIOptions::UserSettings());
95 int index = 0;
96 for(const auto& valFile : fOptions->ValInputFiles()) {
97 inputList->Add(new TNamed(Form("valFile%d", index++), valFile.c_str()));
98 }
99 index = 0;
100 for(const auto& calFile : fOptions->CalInputFiles()) {
101 inputList->Add(new TNamed(Form("calFile%d", index++), calFile.c_str()));
102 }
103 index = 0;
104 for(const auto& cutFile : fOptions->InputCutFiles()) {
105 inputList->Add(new TNamed(Form("cutFile%d", index++), cutFile.c_str()));
106 }
107
108 /// Try to load an external library with the correct function in it.
109 /// If that library does not exist, try to compile it.
110 /// To handle all that we use the class TDataFrameLibrary (very similar to TParserLibrary)
111 auto* helper = TDataFrameLibrary::Get()->CreateHelper(inputList);
112 fOutputPrefix = helper->Prefix();
113 // this actually moves the helper to the data frame, so from here on "helper" doesn't refer to the object we created anymore
114 // aka don't use helper after this!
115 fOutput = helper->Book(fDataFrame);
116}
117
119{
120 // get runinfo and get run and sub-run number
121 auto* runInfo = TRunInfo::Get();
122
123 // get output file name
124 std::string outputFileName = Form("%s%s.root", fOutputPrefix.c_str(), TRunInfo::CreateLabel(true).c_str());
125 std::cout << "Writing to " << outputFileName << std::endl;
126
127 TFile outputFile(outputFileName.c_str(), "recreate");
128
129 // stop redirect before we start the progress bar (storing the files we redirect stdout and stderr to first)
130 const auto* outFile = redirect->OutFile();
131 const auto* errFile = redirect->ErrFile();
132
133 delete redirect;
134 // this is needed so the function that created the redirect know it has ended
135 // not really needed right now as we create a new redirect further down, but we have it here in case that gets changed
136 redirect = nullptr;
137
138#if ROOT_VERSION_CODE < ROOT_VERSION(6, 30, 0)
139 std::string progressBar;
140 const auto barWidth = 100;
141 if(!fOptions->Debug()) {
142 // create a progress bar with percentage
143 auto entries = fDataFrame->Count();
144 std::mutex barMutex; // Only one thread at a time can lock a mutex. Let's use this to avoid concurrent printing.
145 const auto everyN = fTotalEntries / barWidth;
146 // entries.OnPartialResultSlot(everyN, [&everyN, &fTotalEntries = fTotalEntries, &barWidth, &progressBar, &barMutex](unsigned int /*slot*/, ULong64_t& /*partialList*/) {
147 entries.OnPartialResultSlot(everyN, [&everyN, &fTotalEntries = fTotalEntries, &progressBar, &barMutex](unsigned int /*slot*/, ULong64_t& /*partialList*/) {
148 std::lock_guard<std::mutex> lock(barMutex); // lock_guard locks the mutex at construction, releases it at destruction
149 static int counter = 1;
150 progressBar.push_back('#');
151 // re-print the line with the progress bar
152 std::cout << "\r[" << std::left << std::setw(barWidth) << progressBar << ' ' << std::setw(3) << (counter * everyN * 100) / fTotalEntries << " %]" << std::flush;
153 ++counter;
154 });
155 }
156#else
157 ROOT::RDF::Experimental::AddProgressBar(*fDataFrame);
158#endif
159
160 if(fOutput != nullptr) {
161 // accessing the result from Book causes the actual processing of the helper
162 // so we try and catch any exception
163 try {
164 for(auto& list : *fOutput) {
165 // try and switch to the directory this list should be written to
166 if(gDirectory->GetDirectory(list.first.c_str()) && gDirectory->cd(list.first.c_str())) {
167 list.second.Write();
168 } else {
169 // directory this list should be written to doesn't exist, so create it
170 gDirectory->mkdir(list.first.c_str());
171 if(gDirectory->cd(list.first.c_str())) {
172 list.second.Write();
173 } else {
174 std::cout << "Error, failed to find or create path " << list.first << ", writing into " << gDirectory->GetPath() << std::endl;
175 }
176 }
177 // switch back to topmost directory
178 while(gDirectory->GetDirectory("..")) { gDirectory->cd(".."); }
179 }
180#if ROOT_VERSION_CODE < ROOT_VERSION(6, 30, 0)
181 std::cout << "\r[" << std::left << std::setw(barWidth) << progressBar << ' ' << "100 %]" << std::flush;
182#endif
184 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)
185 throw e;
186 }
187 } else {
188 std::cout << "Error, output list is nullptr!" << std::endl;
189 }
190
191 // start new redirect, appending to the previous files we had redirected to
192 redirect = new TRedirect(outFile, errFile, true);
193
194 runInfo->Write();
195 if(fPpg != nullptr) {
196 fPpg->Write();
197 } else {
198 std::cerr << "failed to find TPPG, can't write it!" << std::endl;
199 }
201 TGRSIOptions::UserSettings()->Write("UserSettings", TObject::kOverwrite);
203 outputFile.Close();
204 std::cout << "Closed '" << outputFile.GetName() << "'" << std::endl;
205}
206
208{
209 // does nothing
210}
211#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