75 std::size_t comment =
line.find(
'#');
78 std::size_t firstNotSpace =
line.find_first_not_of(
" \t");
79 if (firstNotSpace != std::string::npos)
86 std::size_t lastNotSpace =
line.find_last_not_of(
" \t");
87 if (lastNotSpace != std::string::npos)
88 line =
line.substr(0, lastNotSpace + 1);
100 static const std::string kCutIntr =
" if ";
102 std::size_t equal =
line.find(
"=");
103 if (equal == std::string::npos)
104 return "Error: missing '='";
107 std::string histName =
line.substr(0, equal);
109 if (histName.empty())
110 return "Error: no histName found";
113 std::size_t cutPos =
line.find(kCutIntr, equal);
114 std::string histExpression;
115 if (cutPos == std::string::npos)
116 histExpression =
line.substr(equal + 1);
118 histExpression =
line.substr(equal + 1, cutPos - equal - 1);
120 if (histExpression.empty())
121 return "Error: no expression found";
125 if (cutPos != std::string::npos) {
126 histCut =
line.substr(cutPos + kCutIntr.size());
129 return "Error: missing cut expression after 'if'";
135 auto check =
fHists.insert(std::make_pair((
const std::string&)histName,
136 std::make_pair(histExpression, histCut)));
140 return "Duplicate histogram name";
155 const std::vector<std::string>& inputFiles,
156 const std::vector<std::string>& expressions,
157 const std::string& treeName =
""):
158 fInputFiles(inputFiles), fOutputFile(
output), fTreeName(treeName)
160 for (
const std::string& expr: expressions) {
162 if (!errMessage.empty())
163 throw std::runtime_error(errMessage +
" in " + expr);
173 std::string treeName =
"";
174 std::unique_ptr<TFile> inputFile{
TFile::Open(firstInputFile.c_str())};
177 for (
TObject* keyAsObj : *inputFile->GetListOfKeys()) {
178 TKey* key =
static_cast<TKey*
>(keyAsObj);
186 if (treeName.empty())
189 ::Error(
"TSimpleAnalysis::Analyze",
"Multiple trees inside %s", firstInputFile.c_str());
195 if (treeName.empty()) {
196 ::Error(
"TSimpleAnalysis::Analyze",
"No tree inside %s", firstInputFile.c_str());
208 static const char* errors[] {
211 "invalid entry number",
212 "cannot open the file",
219 TIter next(fileElements);
221 if (chEl->GetLoadResult() < 0) {
222 ::Error(
"TSimpleAnalysis::Run",
"Load failure in file %s: %s",
223 chEl->GetTitle(), errors[-(chEl->GetLoadResult())]);
243 if (!probe->IsZombie()) {
277 auto generateHisto = [&](
const std::pair<TChain*, TDirectory*>& job) {
278 TChain* chain = job.first;
281 std::vector<TH1F *> vPtrHisto(
fHists.size());
286 for (
const auto &histo :
fHists) {
287 const std::string& expr = histo.second.first;
288 const std::string& histoName = histo.first;
289 const std::string& cut = histo.second.second;
291 chain->
Draw((expr +
">>" + histoName).c_str(), cut.c_str(),
"goff");
292 TH1F *ptrHisto = (
TH1F*)taskDir->
Get(histoName.c_str());
296 return std::vector<TH1F *>();
298 vPtrHisto[i] = ptrHisto;
314 std::vector<std::pair<TChain*, TDirectory*>> vChains;
319 ch->
Add(inputfile.c_str());
325 vChains.emplace_back(std::make_pair(ch, taskDir));
328 auto vFileswHists = pool.
Map(generateHisto, vChains);
332 for (
auto&& histsOfJob: vFileswHists) {
333 if (histsOfJob.empty())
339 std::vector<TH1F *> vPtrHisto{vFileswHists[0]};
341 for (
unsigned j = 0; j <
fHists.size(); j++) {
342 for (
unsigned i = 1; i < vFileswHists.size(); i++) {
343 if (!vFileswHists[i][j]) {
346 vPtrHisto[j] =
nullptr;
350 vPtrHisto[j]->Add(vFileswHists[i][j]);
353 vPtrHisto[j]->Write();
362 chain->
Add(inputfile.c_str());
365 auto vHisto = generateHisto({chain,
gDirectory});
370 for (
auto histo: vHisto) {
386 if (
line.find(
"=") == std::string::npos) {
400 std::string notEmptyLine;
403 getline(
fIn, notEmptyLine);
406 }
while (
fIn && notEmptyLine.empty());
431 std::string errMessage;
433 switch (readingSection) {
463 if (!errMessage.empty()) {
464 ::Error(
"TSimpleAnalysis::Configure",
"%s in %s:%d", errMessage.c_str(),
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
R__EXTERN Int_t gErrorIgnoreLevel
static void DeleteCommentsAndSpaces(std::string &line)
Delete comments, leading and trailing white spaces in a string.
static bool CheckChainLoadResult(TChain *chain)
Returns true if there are no errors in TChain::LoadTree()
bool RunSimpleAnalysis(const char *configurationFile)
Function that allows to create the TSimpleAnalysis object and execute its Configure and Analyze funct...
static std::string ExtractTreeName(std::string &firstInputFile)
Extract the name of the tree from the first input file when the tree name isn't in the configuration ...
This class provides a simple interface to execute the same task multiple times in parallel threads,...
auto Map(F func, unsigned nTimes, R redfunc, unsigned nChunks) -> std::vector< typename std::result_of< F()>::type >
Execute a function nTimes in parallel, dividing the execution in nChunks and providing a result per c...
A TChainElement describes a component of a TChain.
A chain is a collection of files containing TTree objects.
virtual Long64_t Draw(const char *varexp, const TCut &selection, Option_t *option="", Long64_t nentries=kMaxEntries, Long64_t firstentry=0)
Draw expression varexp for selected entries.
TObjArray * GetListOfFiles() const
virtual Int_t Add(TChain *chain)
Add all files referenced by the passed chain to this chain.
TClass instances represent classes, structs and namespaces in the ROOT type system.
Bool_t InheritsFrom(const char *cl) const
Return kTRUE if this class inherits from a class with name "classname".
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Bool_t cd(const char *path=nullptr) override
Change current directory to "this" directory.
Describe directory structure in memory.
virtual TObject * Get(const char *namecycle)
Return pointer to object identified by namecycle.
virtual TDirectory * mkdir(const char *name, const char *title="", Bool_t returnExistingDirectory=kFALSE)
Create a sub-directory "a" or a hierarchy of sub-directories "a/b/c/...".
virtual Bool_t cd(const char *path=nullptr)
Change current directory to "this" directory.
A ROOT file is a suite of consecutive data records (TKey instances) with a well defined format.
static TFile * Open(const char *name, Option_t *option="", const char *ftitle="", Int_t compress=ROOT::RCompressionSetting::EDefaults::kUseCompiledDefault, Int_t netopt=0)
Create / open a file.
1-D histogram with a float per channel (see TH1 documentation)}
Book space in a file, create I/O buffers, to fill them, (un)compress them.
virtual const char * GetClassName() const
virtual const char * GetName() const
Returns name of object.
Mother of all ROOT objects.
R__ALWAYS_INLINE Bool_t IsZombie() const
A TSimpleAnalysis object creates histograms from a TChain.
std::string fConfigFile
Name of the configuration file.
std::vector< std::string > fInputFiles
.root input files
std::string GetLine(int &numbLine)
Skip subsequent empty lines read from fIn and returns the next not empty line.
@ kReadingInput
Reading the name of the .root input files.
@ kReadingOutput
Reading the name of the output file.
@ kReadingTreeName
Reading the name of the tree.
@ kReadingExpressions
Reading the expressions.
std::string HandleExpressionConfig(const std::string &line)
Handle the expression lines of the input file in order to pass the elements to the members of the obj...
std::ifstream fIn
Stream for the input file.
TSimpleAnalysis(const std::string &file)
bool Run()
Execute all the TChain::Draw() as configured and stores the output histograms.
std::string fOutputFile
Output file in which are stored the histograms.
bool HandleInputFileNameConfig(const std::string &line)
Returns false if not a tree name, otherwise sets the name of the tree.
bool SetTreeName()
Disambiguate tree name from first input file and set up fTreeName if it is empty.
bool Configure()
This function has the aim of setting the arguments read from the input file.
std::map< std::string, std::pair< std::string, std::string > > fHists
std::string fTreeName
Name of the input tree.
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
void EnableThreadSafety()
Enables the global mutex to make ROOT thread safe/aware.
static void output(int code)