REST-for-Physics  v2.3
Rare Event Searches ToolKit for Physics
TRestRun.cxx
1 //
27 
28 #include "TRestRun.h"
29 #ifdef WIN32
30 #include <io.h>
31 #include <process.h>
32 #include <windows.h>
33 #undef GetClassName
34 #else
35 #include <sys/stat.h>
36 #include <unistd.h>
37 #endif // !WIN32
38 
39 #include <filesystem>
40 
41 #include "TRestDataBase.h"
42 #include "TRestEventProcess.h"
43 #include "TRestManager.h"
44 #include "TRestVersion.h"
45 
46 using namespace std;
47 
48 std::mutex mutex_read;
49 
50 ClassImp(TRestRun);
51 
52 TRestRun::TRestRun() { Initialize(); }
53 
54 TRestRun::TRestRun(const string& filename) {
55  if (filename.find(".root") != string::npos) {
56  Initialize();
57  OpenInputFile(filename);
58  } else if (filename.find(".rml") != string::npos) {
59  Initialize();
60  LoadConfigFromFile(filename);
61  } else {
62  RESTError << "TRestRun::TRestRun(): input file error!" << RESTendl;
63  }
64 }
65 
66 TRestRun::~TRestRun() { CloseFile(); }
67 
72  SetSectionName(this->ClassName());
73 
74  time_t timev;
75  time(&timev);
76  fStartTime = (Double_t)timev;
77  fEndTime = 0; // We need a static value to avoid overwriting the time if another process sets the time
78 
79  fRunUser = REST_USER;
80  fRunNumber = 0; // run number where input file is from and where output file
81  // will be saved
82  fParentRunNumber = 0; // subrun number where input file is from
83  fRunType = "Null";
84  fExperimentName = "Null";
85  fRunTag = "Null";
86  fRunDescription = "Null";
87 
88  fInputFileName = "null";
89  fOutputFileName = "rest_default.root";
90 
91  fBytesRead = 0;
92  fTotalBytes = -1;
93  fOverwrite = true;
94  fEntriesSaved = -1;
95  fNFilesSplit = 0;
96 
97  fInputMetadata.clear();
98  fMetadata.clear();
99  fInputFileNames.clear();
100  fInputFile = nullptr;
101  fOutputFile = nullptr;
102  fInputEvent = nullptr;
103  fAnalysisTree = nullptr;
104  fEventTree = nullptr;
105  fCurrentEvent = 0;
106  fEventBranchLoc = -1;
107  fFileProcess = nullptr;
108  fSaveHistoricData = true;
109 }
110 
123  RESTDebug << "Initializing TRestRun from config file, version: " << REST_RELEASE << RESTendl;
124  fFromRML = true;
125  ReSetVersion();
126 
127  // 1. Read basic parameter
128  fRunUser = REST_USER;
129  // fRunType = GetParameter("runType", "ANALYSIS").c_str();
130  // fRunDescription = GetParameter("runDescription", "").c_str();
131  // fExperimentName = GetParameter("experiment", "preserve").c_str();
132  // fRunTag = GetParameter("runTag", "noTag").c_str();
133  ReadAllParameters();
134 
135  // 2. Initialize runnumber and input file name. They follow non-trivial logic
136  fRunNumber = -1;
137  fParentRunNumber = 0;
138  string runNstr = GetParameter("runNumber", "-1");
139  string inputName = GetParameter("inputFileName", "");
140  inputName = TRestTools::RemoveMultipleSlash(inputName);
141  string inputNameOld = GetParameter("inputFile", "default");
142  if (inputNameOld != "default") {
143  RESTWarning << "Parameter \"inputFile\" in rml is obsolete! Please update it to \"inputFileName\""
144  << RESTendl;
145  if (inputName.empty()) {
146  inputName = inputNameOld;
147  }
148  }
149  if (ToUpper(runNstr) == "AUTO" && ToUpper(inputName) == "AUTO") {
150  RESTError << "TRestRun: run number and input file name cannot both be "
151  "\"AUTO\""
152  << RESTendl;
153  exit(1);
154  }
155 
156  if (ToUpper(inputName) != "AUTO") {
157  fInputFileName = inputName;
158  fInputFileNames = Vector_cast<string, TString>(TRestTools::GetFilesMatchingPattern(inputName));
159  }
160 
161  if (ToUpper(runNstr) != "AUTO") {
162  fRunNumber = atoi(runNstr.c_str());
163  }
164 
165  if (ToUpper(inputName) == "AUTO") {
166  TRestDataBase* db = gDataBase;
167  auto files = db->query_run_files(fRunNumber);
168  fInputFileName = db->query_run(fRunNumber).value; // run entry value is file pattern
169  fInputFileNames = Vector_cast<DBFile, TString>(files);
170  }
171 
172  if (ToUpper(runNstr) == "AUTO") {
173  TRestDataBase* db = gDataBase;
174  auto runs = db->search_run_with_file((string)fInputFileName);
175  if (!runs.empty()) {
176  fRunNumber = runs[0];
177  } else {
178  fRunNumber = -1;
179  }
180 
181  // add a new run
182  if (fRunNumber == 0) {
183  fRunNumber = db->get_lastrun() + 1;
184  DBEntry entry;
185  entry.runNr = fRunNumber;
186  entry.description = fRunDescription;
187  entry.tag = fRunTag;
188  entry.type = fRunType;
189  entry.version = REST_RELEASE;
190  db->set_run(entry);
191  }
192  }
193 
194  // get some run information
195  if (fRunNumber != -1) {
196  DBEntry entry = gDataBase->query_run(fRunNumber);
197  if (!entry.IsZombie()) {
198  fStartTime = entry.tstart;
199  fEndTime = entry.tend;
200  fRunDescription = entry.description;
201  fRunTag = entry.tag;
202  fRunType = entry.type;
203  }
204  }
205 
206  if (fInputFileNames.empty()) {
207  if (fInputFileName != "") {
208  RESTError << "cannot find the input file!" << RESTendl;
209  exit(1);
210  } else {
211  RESTWarning << "no input file added" << RESTendl;
212  }
213  // throw;
214  }
215 
216  // 3. Construct output file name
217  string outputDir = (string)GetDataPath();
218  string outputName = GetParameter("outputFileName", "default");
219  string outputNameOld = GetParameter("outputFile", "default");
220  if (outputNameOld != "default") {
221  RESTWarning << "Parameter \"outputFile\" in rml is obsolete! Please update it to \"outputFileName\""
222  << RESTendl;
223  if (outputName == "default") {
224  outputName = outputNameOld;
225  }
226  }
227  if (ToUpper(outputName) == "DEFAULT") {
228  string expName = RemoveWhiteSpaces((string)GetExperimentName());
229  string runType = RemoveWhiteSpaces((string)GetRunType());
230  char runParentStr[256];
231  sprintf(runParentStr, "%05d", fParentRunNumber);
232  char runNumberStr[256];
233  sprintf(runNumberStr, "%05d", fRunNumber);
234 
235  fOutputFileName = outputDir + "Run_" + expName + "_" + fRunUser + "_" + runType + "_" + fRunTag +
236  "_" + (TString)runNumberStr + "_" + (TString)runParentStr + "_V" + REST_RELEASE +
237  ".root";
238 
239  // fOverwrite = ToUpper(GetParameter("overwrite", "on")) != "OFF";
240  while (!fOverwrite && TRestTools::fileExists((string)fOutputFileName)) {
241  fParentRunNumber++;
242  sprintf(runParentStr, "%05d", fParentRunNumber);
243  fOutputFileName = outputDir + "Run_" + expName + "_" + fRunUser + "_" + runType + "_" + fRunTag +
244  "_" + (TString)runNumberStr + "_" + (TString)runParentStr + "_V" +
245  REST_RELEASE + ".root";
246  }
247  } else if (ToUpper(outputName) == "NULL" || outputName == "/dev/null") {
248  fOutputFileName = "/dev/null";
249  } else if (TRestTools::isAbsolutePath(outputName)) {
250  fOutputFileName = outputName;
251  outputDir = TRestTools::SeparatePathAndName((string)fOutputFileName).first;
252  } else {
253  fOutputFileName = outputDir + "/" + outputName;
254  }
255  // remove multiple slashes from fOutputFileName
256  fOutputFileName = (TString)TRestTools::RemoveMultipleSlash((string)fOutputFileName);
257 
258  if (!TRestTools::fileExists(outputDir)) {
259  int z = system((TString) "mkdir -p " + outputDir);
260  if (z != 0) RESTError << "Problem creating directory : " << outputDir << RESTendl;
261  }
262  if (!TRestTools::isPathWritable(outputDir)) {
263  RESTWarning << "TRestRun: Output path '" << outputDir << "' does not exist or it is not writable."
264  << RESTendl;
265  }
266 
267  // 4. Loop over sections to initialize metadata
268  TiXmlElement* e = fElement->FirstChildElement();
269  while (e != nullptr) {
270  string key = e->Value();
271  if (key == "addMetadata") {
272  if (e->Attribute("file") != nullptr) {
273  ImportMetadata(e->Attribute("file"), e->Attribute("name"), e->Attribute("type"), true);
274  } else {
275  RESTWarning << "Wrong definition of addMetadata! Metadata name or file name "
276  "is not given!"
277  << RESTendl;
278  }
279  } else if (Count(key, "TRest") > 0) {
280  if (e->Attribute("file") != nullptr && TRestTools::isRootFile(e->Attribute("file"))) {
281  RESTWarning << "TRestRun: A root file is being included in section <" << key
282  << " ! To import metadata from this file, use <addMetadata" << RESTendl;
283  RESTWarning << "Skipping..." << RESTendl;
284  }
285 
287  if (meta == nullptr) {
288  RESTWarning << "failed to add metadata \"" << key << "\"" << RESTendl;
289  e = e->NextSiblingElement();
290  continue;
291  }
292  meta->SetConfigFile(fConfigFileName);
293  meta->SetHostmgr(fHostmgr);
294  fMetadata.push_back(meta);
295  meta->LoadConfigFromElement(e, fElementGlobal);
296  }
297  e = e->NextSiblingElement();
298  }
299 
300  // 5. Open input file(s). We open input file at the last stage in case the file name pattern
301  // reading requires TRestDetector
302  OpenInputFile(0);
303  RESTDebug << "TRestRun::EndOfInit. InputFile pattern: \"" << fInputFileName << "\"" << RESTendl;
304  RESTInfo << "which matches :" << RESTendl;
305  for (const auto& inputFileName : fInputFileNames) {
306  RESTInfo << inputFileName << RESTendl;
307  }
308  RESTEssential << "(" << fInputFileNames.size() << " added files)" << RESTendl;
309 }
310 
315  if (fInputFileNames.size() > (unsigned int)i) {
316  TString Filename = fInputFileNames[i];
317  RESTInfo << "opening... " << Filename << RESTendl;
318  OpenInputFile((string)Filename);
319  }
320 }
321 
331 void TRestRun::OpenInputFile(const TString& filename, const string& mode) {
332  CloseFile();
333  if (!filename.Contains("http") && !TRestTools::fileExists((string)filename)) {
334  RESTError << "input file \"" << filename << "\" does not exist!" << RESTendl;
335  exit(1);
336  }
337 
338  if (!filename.Contains("http")) ReadFileInfo((string)filename);
339 
340  // add to fInputFileNames in case it is opening a new file
341  bool inList = false;
342  for (const auto& inputFileName : fInputFileNames) {
343  if (inputFileName == filename) {
344  inList = true;
345  break;
346  }
347  }
348 
349  if (!inList) {
350  fInputFileNames.push_back(filename);
351  }
352 
353  if (TRestTools::isRootFile((string)filename)) {
354  fInputFile = TFile::Open(filename, mode.c_str());
355 
356  if (GetMetadataClass("TRestRun", fInputFile)) {
357  // This should be the values in RML (if it was initialized using RML)
358  TString runTypeTmp = fRunType;
359  // TString runUserTmp = fRunUser;
360  TString runTagTmp = fRunTag;
361  TString runDescriptionTmp = fRunDescription;
362  TString experimentNameTmp = fExperimentName;
363  TString outputFileNameTmp = fOutputFileName;
364  TString inputFileNameTmp = fInputFileName;
365  TString cFileNameTmp = fConfigFileName;
366 
367  // We define fVersion to -1 to identify old REST files that did not have yet
368  // versioning system
369  this->UnSetVersion();
370 
371  // Now we load the values in the previous run file
372  // If successfully read the input file, the version code will be changed
373  // from -1 --> certain number
374  this->Read(GetMetadataClass("TRestRun", fInputFile)->GetName());
375 
376  if (inputFileNameTmp != "null") fInputFileName = inputFileNameTmp;
377  if (outputFileNameTmp != "rest_default.root") fOutputFileName = outputFileNameTmp;
378  if (cFileNameTmp != "null") fConfigFileName = cFileNameTmp;
379 
380  // If the value was initialized from RML and is not preserve, we recover
381  // back the value in RML
382  if (fFromRML) {
383  if (runTypeTmp != "Null" && runTypeTmp != "preserve") fRunType = runTypeTmp;
384 
385  // We should not recover the user. Only when writing. If not when I open a file
386  // with restRoot just to read, and Print the run content from other user in my
387  // own account, it will say it was me!
388  // if (runUserTmp != "Null" && runTypeTmp != "preserve") fRunUser = runUserTmp;
389 
390  if (runTagTmp != "Null" && runTagTmp != "preserve") fRunTag = runTagTmp;
391  if (runDescriptionTmp != "Null" && runDescriptionTmp != "preserve")
392  fRunDescription = runDescriptionTmp;
393  if (experimentNameTmp != "Null" && experimentNameTmp != "preserve")
394  fExperimentName = experimentNameTmp;
395  }
396 
397  // If version is lower than 2.2.1 we do not read/transfer the metadata to
398  // output file?
399  // Actually g4 files from v2.1.x is all compatible with the v2.2.x version
400  // Only 2.2.0 is without auto schema evolution, whose metadata cannot be read
401  if (fSaveHistoricData) {
402  if (this->GetVersionCode() >= REST_VERSION(2, 2, 1) ||
403  this->GetVersionCode() <= REST_VERSION(2, 1, 8)) {
404  ReadInputFileMetadata();
405  } else {
406  RESTWarning << "-- W : The metadata version found on input file is lower "
407  "than 2.2.1!"
408  << RESTendl;
409  RESTWarning << "-- W : metadata from input file will not be read" << RESTendl;
410  }
411  }
412 
413  RESTDebug << "Initializing input file : version code : " << this->GetVersionCode() << RESTendl;
414  RESTDebug << "Input file version : " << this->GetVersion() << RESTendl;
415  ReadInputFileTrees();
416  fCurrentEvent = 0;
417  } else {
418  RESTWarning << "TRestRun object not found in file! The input file may be incomplete!" << RESTendl;
419  ReadInputFileTrees();
420  }
421  } else {
422  fInputFile = nullptr;
423  fAnalysisTree = nullptr;
424  if (fFileProcess != nullptr) {
425  fFileProcess->OpenInputFiles(Vector_cast<TString, string>(fInputFileNames));
426  fFileProcess->InitProcess();
427  }
428  }
429 
430  if (fAnalysisTree == nullptr && fFileProcess == nullptr)
431  RESTInfo << "Input file is not REST root file, an external process is needed!" << RESTendl;
432 }
433 
434 void TRestRun::AddInputFileExternal(const string& file) {
435  mutex_read.lock();
436  if (fFileProcess != nullptr) {
437  bool add = fFileProcess->AddInputFile(file);
438  if (!add) {
439  RESTError << "failed to add input file!" << RESTendl;
440  }
441  fInputFileNames.emplace_back(file);
442  }
443  mutex_read.unlock();
444 }
445 
446 void TRestRun::ReadInputFileMetadata() {
447  TFile* f = fInputFile;
448  if (f != nullptr) {
449  fInputMetadata.clear();
450 
451  TIter nextkey(f->GetListOfKeys());
452  TKey* key;
453  // we should make sure the input metadata has unique names
454  set<string> addedNames;
455  while ((key = (TKey*)nextkey())) {
456  RESTDebug << "Reading key with name : " << key->GetName() << RESTendl;
457  RESTDebug << "Key type (class) : " << key->GetClassName() << RESTendl;
458 
459  if (!TClass::GetClass(key->GetClassName()) ||
460  !TClass::GetClass(key->GetClassName())->IsLoaded()) {
461  RESTError << "-- Class " << key->GetClassName() << " has no dictionary!" << RESTendl;
462  RESTError << "- Any relevant REST library missing? " << RESTendl;
463  RESTError << "- File reading will continue without loading key: " << key->GetName()
464  << RESTendl;
465  continue;
466  }
467 
468  if (addedNames.count(key->GetName()) != 0) {
469  continue;
470  }
471 
472  TRestMetadata* a = (TRestMetadata*)f->Get(key->GetName());
473  RESTDebug << "Key of type : " << a->ClassName() << "(" << a << ")" << RESTendl;
474 
475  if (!a) {
476  RESTError << "TRestRun::ReadInputFileMetadata." << RESTendl;
477  RESTError << "Key name : " << key->GetName() << RESTendl;
478  RESTError << "Hidden key? Please, report this problem." << RESTendl;
479  } else if (a->InheritsFrom("TRestMetadata") && a->ClassName() != (TString) "TRestRun") {
480  /*
481  //we make sure there is no repeated class added
482  // However, we might have two processes with the same class name
483  operating at different steps of the data chain
484  // We just avoid to write TRestRun from previous file to the list of
485  metadata structures
486 
487  bool flag = false;
488  for (int i = 0; i < fInputMetadata.size(); i++) {
489  if (a->ClassName() == fInputMetadata[i]->ClassName()) {
490  flag = true;
491  break;
492  }
493  }
494  if (!flag) {
495  fInputMetadata.push_back(a);
496  }
497  */
499  fInputMetadata.push_back(a);
500  fMetadata.push_back(a);
501  addedNames.insert(key->GetName());
502  }
503  }
504  }
505 }
506 
507 void TRestRun::ReadInputFileTrees() {
508  if (fInputFile != nullptr) {
509  RESTDebug << "Finding TRestAnalysisTree.." << RESTendl;
510  TTree* _eventTree = nullptr;
511  string filename = fInputFile->GetName();
512 
513  if (fInputFile->Get("AnalysisTree") != nullptr) {
514  fAnalysisTree = (TRestAnalysisTree*)fInputFile->Get("AnalysisTree");
515 
516  if (fNFilesSplit > 0) { // fNFilesSplit=1: split to 1 additional file
517  RESTEssential << "Linking analysis tree from split data files" << RESTendl;
518  fAnalysisTree = (TRestAnalysisTree*)fAnalysisTree->Clone(); // we must make a copy to have
519  // TBrowser correctly browsed.
520  for (int i = 1; i <= fNFilesSplit; i++) {
521  string filename = fInputFile->GetName() + (string) "." + ToString(i);
522  RESTInfo << filename << " --> ";
523  RESTInfo << (fAnalysisTree->AddChainFile(filename) ? "success" : "failed") << RESTendl;
524  }
525  if (fAnalysisTree->GetChain() == nullptr ||
526  fAnalysisTree->GetChain()->GetNtrees() != fNFilesSplit + 1) {
527  RESTError << "Error adding split files, files missing?" << RESTendl;
528  RESTError << "Your data could be incomplete!" << RESTendl;
529  }
530  }
531 
532  // Note: we call GetEntries() to initialize total entry number
533  // Otherwise the child analysis tree's observables will be reset
534  // on the next call of GetEntries()
535  fAnalysisTree->GetEntries();
536  // Call GetEntry() to initialize observables and connect branches
537  fAnalysisTree->GetEntry(0);
538 
539  _eventTree = (TTree*)fInputFile->Get("EventTree");
540  } else if (fInputFile->FindKey("TRestAnalysisTree") != nullptr) {
541  // This is v2.1.6- version of input file, we directly find EventTree and
542  // AnalysisTree. The old name pattern is "TRestXXXEventTree-eventBranch"
543  // and "TRestAnalysisTree"
544  RESTWarning << "Loading root file from old version REST!" << RESTendl;
545  fAnalysisTree = (TRestAnalysisTree*)fInputFile->Get("TRestAnalysisTree");
546  fAnalysisTree->GetEntry(0);
547 
548  TIter nextkey(fInputFile->GetListOfKeys());
549  TKey* key;
550  while ((key = (TKey*)nextkey())) {
551  // cout << key->GetName() << endl;
552  if (((string)key->GetName()).find("EventTree") != string::npos) {
553  _eventTree = (TTree*)fInputFile->Get(key->GetName());
554  string eventName = Replace(key->GetName(), "Tree", "", 0);
555  TBranch* br = _eventTree->GetBranch("eventBranch");
556  br->SetName((eventName + "Branch").c_str());
557  br->SetTitle((eventName + "Branch").c_str());
558  break;
559  }
560  }
561  RESTDebug << "Old REST file successfully recovered!" << RESTendl;
562  } else {
563  RESTWarning << "(OpenInputFile) : AnalysisTree was not found" << RESTendl;
564  RESTWarning << "Inside file : " << filename << RESTendl;
565  RESTWarning << "This may not be a REST output file!" << RESTendl;
566  }
567 
568  if (_eventTree != nullptr) {
569  if (fNFilesSplit > 0) {
570  // eventTree shall be initialized as TChain
571  delete _eventTree;
572  RESTEssential << "Linking event tree from split data files" << RESTendl;
573  TChain* _fEventTree = new TChain("EventTree");
574  RESTInfo << fInputFile->GetName() << " --> ";
575  RESTInfo << (_fEventTree->Add(fInputFile->GetName()) ? "success" : "failed") << RESTendl;
576 
577  for (int i = 1; i <= fNFilesSplit; i++) {
578  string filename = fInputFile->GetName() + (string) "." + ToString(i);
579  RESTInfo << filename << " --> ";
580  RESTInfo << (_fEventTree->Add(filename.c_str()) ? "success" : "failed") << RESTendl;
581  }
582  fEventTree = _fEventTree;
583  } else {
584  fEventTree = _eventTree;
585  }
586 
587  RESTDebug << "Finding event branch.." << RESTendl;
588  if (fInputEvent == nullptr) {
589  TObjArray* branches = fEventTree->GetListOfBranches();
590  // get the last event branch as input event branch
591  if (branches->GetLast() > -1) {
592  TBranch* br = (TBranch*)branches->At(branches->GetLast());
593 
594  if (br == nullptr || Count(br->GetName(), "EventBranch") == 0) {
595  RESTInfo << "No event branch inside file : " << filename << RESTendl;
596  RESTInfo << "This file may be a pure analysis file" << RESTendl;
597  } else {
598  string type = Replace(br->GetName(), "Branch", "", 0);
599  TClass* cl = TClass::GetClass(type.c_str());
600  if (cl->HasDictionary()) {
601  fInputEvent = REST_Reflection::Assembly(type);
602  } else if (fInputEvent != nullptr) {
603  delete fInputEvent;
604  fInputEvent = nullptr;
605  }
606 
607  if (fInputEvent == nullptr) {
608  RESTError << "TRestRun:OpenInputFile. Cannot initialize input event, event "
609  "tree not read"
610  << RESTendl;
611  RESTError
612  << "Please install corresponding libraries to provide root dictionaries for "
613  "class reading."
614  << RESTendl;
615  return;
616  }
617 
618  fInputEvent->InitializeWithMetadata(this);
619  fEventTree->SetBranchAddress(br->GetName(), &fInputEvent);
620  fEventBranchLoc = branches->GetLast();
621  RESTDebug << "found event branch of event type: " << fInputEvent->ClassName()
622  << RESTendl;
623  }
624  }
625  } else {
626  string brname = (string)fInputEvent->ClassName() + "Branch";
627  if (fEventTree->GetBranch(brname.c_str()) == nullptr) {
628  RESTWarning << "REST WARNING (OpenInputFile) : No matched event branch "
629  "inside file : "
630  << filename << RESTendl;
631  RESTWarning << "Branch required: " << brname << RESTendl;
632  } else {
633  fEventTree->SetBranchAddress(brname.c_str(), &fInputEvent);
634  RESTDebug << brname << " is found and set!" << RESTendl;
635  }
636  }
637  } else {
638  RESTDebug << "TRestRun:OpenInputFile. EventTree was not found" << RESTendl;
639  RESTDebug << "This is a pure analysis file!" << RESTendl;
640  fInputEvent = nullptr;
641  }
642  }
643 }
644 
652 void TRestRun::ReadFileInfo(const string& filename) {
653  RESTDebug << "begin collecting basic file info..." << filename << RESTendl;
654 
655  // basic file info: modify time, total bytes, etc.
656  struct stat buf;
657  FILE* fp = fopen(filename.c_str(), "rb");
658  if (!fp) {
659  RESTError << "TRestRun::ReadFileInfo. Something went wrong with fopen()!" << strerror(errno)
660  << RESTendl;
661  exit(1);
662  }
663  int fd = fileno(fp);
664  fstat(fd, &buf);
665  fclose(fp);
666  if (fEndTime == 0) {
667  fEndTime = buf.st_mtime;
668  }
669 
670  if (TRestTools::isRootFile((string)filename)) {
671  fTotalBytes = buf.st_size;
672  }
673 
674  RESTDebug << "begin matching file name pattern for more file info..." << RESTendl;
675  // format example:
676  // run[fRunNumber]_cobo[aaa]_frag[bbb]_Vm[TRestDetector::fAmplificationVoltage].graw
677  // we are going to match it with inputfile:
678  // run00042_cobo1_frag0000_Vm350.graw
679  string format = GetParameter("inputFormat", "");
680  string name = TRestTools::SeparatePathAndName(filename).second;
681 
682  vector<string> formatSectionList;
683  vector<string> formatPrefixList;
684 
685  int pos = -1;
686  int pos1 = 0;
687  int pos2 = 0;
688  while (true) {
689  pos1 = format.find("[", pos + 1);
690  pos2 = format.find("]", pos1);
691  if (pos1 == -1 || pos2 == -1) {
692  formatPrefixList.push_back(format.substr(pos + 1, -1));
693  break;
694  }
695 
696  formatSectionList.push_back(format.substr(pos1 + 1, pos2 - pos1 - 1));
697  formatPrefixList.push_back(format.substr(pos + 1, pos1 - pos - 1));
698 
699  pos = pos2;
700  }
701 
702  pos = -1;
703  for (unsigned int i = 0; i < formatSectionList.size() && i < formatPrefixList.size() - 1; i++) {
704  if (i != 0 && formatPrefixList[i].empty()) {
705  RESTWarning << "file format reference contains error!" << RESTendl;
706  return;
707  }
708  int pos1 = name.find(formatPrefixList[i], pos + 1) + formatPrefixList[i].size();
709  if (formatPrefixList[i].empty()) pos1 = 0;
710  int pos2 = name.find(formatPrefixList[i + 1], pos1);
711  if (formatPrefixList[i + 1].empty()) pos2 = name.length();
712  if (pos1 == -1 || pos2 == -1) {
713  RESTWarning << "File pattern matching: file format mismatch!" << RESTendl;
714  return;
715  }
716 
717  string infoFromFileName = name.substr(pos1, pos2 - pos1);
718 
719  RESTDebug << "File pattern matching. key: " << formatSectionList[i] << " (between the mark \""
720  << formatPrefixList[i] << "\" and \"" << formatPrefixList[i + 1]
721  << "\"), value: " << infoFromFileName << RESTendl;
722 
723  // run[fRunNumber]_cobo[aaa]_frag[bbb]_Vm[TRestDetector::fAmplificationVoltage].graw
724  bool inforead = false;
725  if (!inforead) {
726  // 1. store special file pattern parameters as TRestRun data member: fRunNumber
727  if (DataMemberNameToParameterName(formatSectionList[i]) != "") {
728  RESTValue member = RESTValue(this, this->ClassName()).GetDataMember(formatSectionList[i]);
729  if (!member.IsZombie()) {
730  member.ParseString(infoFromFileName);
731  inforead = true;
732  } else {
733  RESTWarning << "TRestRun: file name format field \"" << formatSectionList[i]
734  << "\"(value = " << infoFromFileName
735  << ") not registered, data member does not exist in TRestRun!" << RESTendl;
736  }
737  }
738  }
739 
740  if (!inforead) {
741  // 2. store special file pattern parameters as data member of the loaded
742  // metadata class, e.g., TRestDetector::fAmplificationVoltage
743  vector<string> classDataMember = Split(formatSectionList[i], "::");
744  if (classDataMember.size() > 1) {
745  TRestMetadata* meta = GetMetadataClass(classDataMember[0]);
746  if (meta != nullptr) {
747  RESTValue member = RESTValue(meta, meta->ClassName()).GetDataMember(classDataMember[1]);
748  if (!member.IsZombie()) {
749  member.ParseString(infoFromFileName);
750  meta->UpdateMetadataMembers();
751  inforead = true;
752  } else {
753  RESTWarning << "TRestRun: file name format field \"" << formatSectionList[i]
754  << "\"(value = " << infoFromFileName
755  << ") not registered, metadata exist but without such datamember field!"
756  << RESTendl;
757  }
758  } else {
759  RESTWarning << "TRestRun: file name format field \"" << formatSectionList[i]
760  << "\"(value = " << infoFromFileName
761  << ") not registered, metadata does not exist!" << RESTendl;
762  }
763  }
764  }
765 
766  // if (!inforead) {
767  // 3. store file format fields to REST_ARGS as global parameter: aaa, bbb
768  // REST_ARGS[formatsectionlist[i]] = infoFromFileName;
769  // }
770 
771  pos = pos2 - 1;
772  }
773 }
774 
782  fCurrentEvent = 0;
783  if (fFileProcess != nullptr) {
784  fFileProcess->ResetEntry();
785  }
786 }
787 
796 Int_t TRestRun::GetNextEvent(TRestEvent* targetEvent, TRestAnalysisTree* targetTree) {
797  bool messageShown = false;
798  TRestEvent* eve = fInputEvent;
799 
800  if (fFileProcess != nullptr) {
801  RESTDebug << "TRestRun: getting next event from external process" << RESTendl;
802  GetEventExt:
803  mutex_read.lock();
804  fFileProcess->BeginOfEventProcess();
805  eve = fFileProcess->ProcessEvent(nullptr);
806  fFileProcess->EndOfEventProcess();
807  mutex_read.unlock();
808  fBytesRead = fFileProcess->GetTotalBytesRead();
809  // if (targettree != nullptr) {
810  // for (int n = 0; n < fAnalysisTree->GetNumberOfObservables(); n++)
811  // targettree->SetObservable(n, fAnalysisTree->GetObservable(n));
812  //}
813  fCurrentEvent++;
814  } else {
815  if (eve == nullptr) {
816  RESTDebug << "TRestRun::GetNextEvent(): input event has not been initialized!" << RESTendl;
817  } else {
818  RESTDebug << "TRestRun: getting next event from root file" << RESTendl;
819  if (fAnalysisTree == nullptr) {
820  RESTWarning << "error to get event from input file, missing analysis tree from input file"
821  << RESTendl;
822  eve = nullptr;
823  } else {
824  if (fCurrentEvent >= fAnalysisTree->GetTree()->GetEntriesFast()) {
825  eve = nullptr;
826  } else {
827  if (targetTree != nullptr) {
828  // normal reading procedure
829  eve->Initialize();
830  fBytesRead += fAnalysisTree->GetEntry(fCurrentEvent);
831  targetTree->SetEventInfo(fAnalysisTree);
832  for (int n = 0; n < fAnalysisTree->GetNumberOfObservables(); n++)
833  targetTree->SetObservable(n, fAnalysisTree->GetObservable(n));
834  }
835  if (fEventTree != nullptr) {
836  if (fEventTree->IsA() == TChain::Class()) {
837  Long64_t entry = fEventTree->LoadTree(fCurrentEvent);
838  fBytesRead += ((TBranch*)fEventTree->GetTree()->GetListOfBranches()->UncheckedAt(
839  fEventBranchLoc))
840  ->GetEntry(entry);
841  } else {
842  fBytesRead +=
843  ((TBranch*)fEventTree->GetListOfBranches()->UncheckedAt(fEventBranchLoc))
844  ->GetEntry(fCurrentEvent);
845  }
846  }
847  fCurrentEvent++;
848  }
849  }
850  }
851  }
852 
853  // cout << fHangUpEndFile << endl;
854 
855  if (eve == nullptr) {
856  if (fHangUpEndFile && fFileProcess != nullptr) {
857  // if hangup is set, we continue calling ProcessEvent() of the
858  // external process, until there is non-null event yielded
859  if (!messageShown) {
860  RESTEssential << "external process file reading reaches end, waiting for more files"
861  << RESTendl;
862  }
863  usleep(1000000);
864  messageShown = true;
865  fCurrentEvent--;
866  goto GetEventExt;
867  }
868  fInputEvent = eve;
869  // if (fFileProcess != nullptr) fFileProcess->EndProcess();
870  return -1;
871  }
872 
873  fInputEvent = eve;
874 
875  if (fInputEvent->GetID() == 0 && fInputEvent->GetSubID() == 0) {
876  fInputEvent->SetID(fCurrentEvent - 1);
877  }
878 
879  if (fInputEvent->GetRunOrigin() == 0) {
880  fInputEvent->SetRunOrigin(fRunNumber);
881  }
882 
883  targetEvent->Initialize();
884  fInputEvent->CloneTo(targetEvent);
885 
886  return 0;
887 }
888 
892 std::vector<std::string> TRestRun::GetEventTypesList() {
893  std::vector<std::string> list;
894  TObjArray* branches = GetEventTree()->GetListOfBranches();
895  for (int i = 0; i <= branches->GetLast(); i++) {
896  auto branch = (TBranch*)branches->At(i);
897  if (((std::string)branch->GetName()).find("EventBranch") != string::npos) {
898  std::string eventType = Replace((string)branch->GetName(), "Branch", "");
899  list.emplace_back(eventType);
900  }
901  }
902  return list;
903 }
904 
908 void TRestRun::GetEntry(Long64_t entry) {
909  if (entry >= GetEntries()) {
910  RESTWarning << "TRestRun::GetEntry. Entry requested out of limits" << RESTendl;
911  RESTWarning << "Total number of entries is : " << GetEntries() << RESTendl;
912  }
913 
914  if (fAnalysisTree != nullptr) {
915  fAnalysisTree->GetEntry(entry);
916  }
917  if (fEventTree != nullptr) {
918  fEventTree->GetEntry(entry);
919  }
920 
921  if (fInputEvent != nullptr) {
922  fInputEvent->InitializeReferences(this);
923  }
924 
925  fCurrentEvent = entry;
926 }
927 
940 TString TRestRun::FormFormat(const TString& FilenameFormat) {
941  string inString = (string)FilenameFormat;
942  string outString = (string)FilenameFormat;
943 
944  RESTDebug << "TRestRun::FormFormat. In string : " << inString << RESTendl;
945 
946  int pos = 0;
947  while (true) {
948  int pos1 = inString.find("[", pos);
949  int pos2 = inString.find("]", pos1);
950  if (pos1 == -1 || pos2 == -1) break;
951 
952  string targetstr = inString.substr(pos1, pos2 - pos1 + 1); // with []
953  string target = inString.substr(pos1 + 1, pos2 - pos1 - 1); // without []
954  string replacestr = GetRunInformation(target);
955 
956  RESTDebug << "TRestRun::FormFormat. target : " << target << RESTendl;
957  RESTDebug << "TRestRun::FormFormat. replacestr : " << replacestr << RESTendl;
958 
959  // If we form an output file we are willing to form the output filename
960  // using the latest version. But the version is set just before we
961  // call Write.
962  if (target == "fVersion") replacestr = (string)REST_RELEASE;
963  if (target == "fCommit") replacestr = (string)REST_COMMIT;
964 
965  if (replacestr != target) {
966  if (target == "fRunNumber" || target == "fParentRunNumber") {
967  replacestr = Form("%05d", StringToInteger(replacestr));
968  }
969  outString = Replace(outString, targetstr, replacestr, 0);
970  }
971  pos = pos2 + 1;
972  }
973 
974  return outString;
975 }
976 
985 TFile* TRestRun::MergeToOutputFile(vector<string> filenames, string outputfilename) {
986  RESTDebug << "TRestRun::FormOutputFile. target : " << outputfilename << RESTendl;
987  string filename;
988  TFileMerger* m = new TFileMerger(false);
989  if (outputfilename.empty()) {
990  filename = fOutputFileName;
991  RESTInfo << "Creating file : " << filename << RESTendl;
992  m->OutputFile(filename.c_str(), "RECREATE");
993  } else {
994  filename = outputfilename;
995  RESTInfo << "Updating file : " << filename << RESTendl;
996  m->OutputFile(filename.c_str(), "UPDATE");
997  }
998 
999  RESTDebug << "TRestRun::FormOutputFile. Starting to add files" << RESTendl;
1000 
1001  for (unsigned int i = 0; i < filenames.size(); i++) {
1002  m->AddFile(filenames[i].c_str(), false);
1003  }
1004 
1005  if (m->Merge()) {
1006  for (unsigned int i = 0; i < filenames.size(); i++) {
1007  remove(filenames[i].c_str());
1008  }
1009  } else {
1010  fOutputFileName = "";
1011  RESTError << "(Merge files) failed to merge process files." << RESTendl;
1012  exit(1);
1013  }
1014 
1015  delete m;
1016 
1017  // we rename the created output file
1018  fOutputFileName = FormFormat(filename);
1019  rename(filename.c_str(), fOutputFileName);
1020 
1021  // write metadata into the output file
1022  fOutputFile = new TFile(fOutputFileName, "update");
1023  RESTDebug << "TRestRun::FormOutputFile. Calling WriteWithDataBase()" << RESTendl;
1024  this->WriteWithDataBase();
1025 
1026  RESTcout << this->ClassName() << " Created ..." << RESTendl;
1027  RESTcout << "- Path : " << TRestTools::SeparatePathAndName((string)fOutputFileName).first << RESTendl;
1028  RESTcout << "- Filename : " << TRestTools::SeparatePathAndName((string)fOutputFileName).second
1029  << RESTendl;
1030  return fOutputFile;
1031 }
1032 
1037  CloseFile();
1038 
1039  fOutputFileName = FormFormat(fOutputFileName);
1040  // remove unwanted "./" etc. from the path while resolving them
1041  fOutputFileName = std::filesystem::weakly_canonical(fOutputFileName.Data());
1042 
1043  fOutputFile = new TFile(fOutputFileName, "recreate");
1044  fAnalysisTree = new TRestAnalysisTree("AnalysisTree", "AnalysisTree");
1045  fEventTree = new TTree("EventTree", "EventTree");
1046 
1047  fAnalysisTree->Write(nullptr, TObject::kOverwrite);
1048  fEventTree->Write(nullptr, TObject::kOverwrite);
1049  this->WriteWithDataBase();
1050 
1051  RESTcout << "TRestRun: Output File Created." << RESTendl;
1052  RESTcout << "- Path : " << TRestTools::SeparatePathAndName((string)fOutputFileName).first << RESTendl;
1053  RESTcout << "- Filename : " << TRestTools::SeparatePathAndName((string)fOutputFileName).second
1054  << RESTendl;
1055  return fOutputFile;
1056 }
1057 
1058 TFile* TRestRun::UpdateOutputFile() {
1059  if (fOutputFile != nullptr) {
1060  if (fOutputFile->IsOpen()) {
1061  fOutputFile->ReOpen("update");
1062  }
1063 
1064  fOutputFile->cd();
1065 
1066  fAnalysisTree->Write(nullptr, kOverwrite);
1067  fEventTree->Write(nullptr, kOverwrite);
1068 
1069  this->WriteWithDataBase();
1070 
1071  RESTcout << "TRestRun: Output File Updated." << RESTendl;
1072  RESTcout << "- Path : " << TRestTools::SeparatePathAndName((string)fOutputFileName).first << RESTendl;
1073  RESTcout << "- Filename : " << TRestTools::SeparatePathAndName((string)fOutputFileName).second
1074  << RESTendl;
1075  return fOutputFile;
1076 
1077  } else {
1078  RESTError << "TRestRun::UpdateOutputFile(): output file is closed" << RESTendl;
1079  }
1080  return nullptr;
1081 }
1082 
1093  TRestAnalysisTree* tree = nullptr;
1094 
1095  RESTDebug << "TRestRun::WriteWithDataBase. Getting entries in analysisTree" << RESTendl;
1096 
1097  // record the entries saved
1098  fEntriesSaved = -1;
1099  if (fOutputFile != nullptr) {
1100  tree = (TRestAnalysisTree*)fOutputFile->Get("AnalysisTree");
1101  if (tree != nullptr) {
1102  fEntriesSaved = tree->GetEntries();
1103  }
1104  }
1105  RESTDebug << "TRestRun::WriteWithDataBase. Entries found : " << fEntriesSaved << RESTendl;
1106 
1107  // If time was not written by any other process we record the current time
1108  if (fEndTime == 0) {
1109  time_t timev;
1110  time(&timev);
1111  fEndTime = (Double_t)timev;
1112  }
1113 
1114  fRunUser = REST_USER;
1115 
1116  // save metadata objects in file
1117 
1118  RESTDebug << "TRestRun::WriteWithDataBase. Calling this->Write(0, kOverwrite)" << RESTendl;
1119  this->Write(nullptr, kOverwrite);
1120 
1121  RESTDebug << "TRestRun::WriteWithDataBase. Succeed" << RESTendl;
1122  RESTDebug << "TRestRun::WriteWithDataBase. fMetadata.size() == " << fMetadata.size() << RESTendl;
1123  for (auto& metadata : fMetadata) {
1124  bool historic = false;
1125  RESTDebug << "TRestRun::WriteWithDataBase. fInputMetadata.size() == " << fInputMetadata.size()
1126  << RESTendl;
1127  for (const auto& inputMetadata : fInputMetadata) {
1128  RESTDebug << metadata->GetName() << " == " << inputMetadata->GetName() << RESTendl;
1129  if (metadata == inputMetadata) {
1130  historic = true;
1131  break;
1132  }
1133  }
1134 
1135  if (!historic) {
1136  RESTDebug << "NO historic" << RESTendl;
1137  metadata->Write(metadata->GetName(), kOverwrite);
1138  } else {
1139  RESTDebug << "IS historic" << RESTendl;
1140  if (fSaveHistoricData) metadata->Write(metadata->GetName(), kOverwrite);
1141  }
1142  }
1143 
1144  // write to database
1145  RESTDebug << "TResRun::WriteWithDataBase. Run number is : " << fRunNumber << RESTendl;
1146  if (fRunNumber != -1) {
1147  int fileid = gDataBase->set_runfile(fRunNumber, (string)fOutputFileName);
1148  RESTcout << "DataBase Entry Added! Run Number: " << fRunNumber << ", File ID: " << fileid << RESTendl;
1149  }
1150 }
1151 
1156  fEntriesSaved = -1;
1157  if (fAnalysisTree != nullptr) {
1158  fEntriesSaved = fAnalysisTree->GetEntries();
1159  if (fAnalysisTree->GetEntries() > 0 && fInputFile == nullptr) {
1160  if (fOutputFile != nullptr) {
1161  fOutputFile->cd();
1162  fAnalysisTree->Write(nullptr, kOverwrite);
1163  this->Write(nullptr, kOverwrite);
1164  }
1165  }
1166  delete fAnalysisTree;
1167  fAnalysisTree = nullptr;
1168  }
1169 
1170  if (fEventTree != nullptr) {
1171  if (fEventTree->GetEntries() > 0 && fInputFile == nullptr) fEventTree->Write(nullptr, kOverwrite);
1172  delete fEventTree;
1173  fEventTree = nullptr;
1174  }
1175 
1176  for (unsigned int i = 0; i < fMetadata.size(); i++) {
1177  for (unsigned int j = 0; j < fInputMetadata.size(); j++) {
1178  if (fMetadata[i] == fInputMetadata[j]) {
1179  delete fMetadata[i];
1180  fMetadata.erase(fMetadata.begin() + i);
1181  i--;
1182  fInputMetadata.erase(fInputMetadata.begin() + j);
1183  break;
1184  }
1185  }
1186  }
1187 
1188  if (fOutputFile != nullptr) {
1189  fOutputFile->Write(0, TObject::kOverwrite);
1190  fOutputFile->Close();
1191  delete fOutputFile;
1192  fOutputFile = nullptr;
1193  }
1194  if (fInputFile != nullptr) {
1195  fInputFile->Close();
1196  fInputFile = nullptr;
1197  }
1198 }
1199 
1204  if (fFileProcess == nullptr && p != nullptr) {
1205  fFileProcess = p;
1206 
1207  fFileProcess->OpenInputFiles(Vector_cast<TString, string>(fInputFileNames));
1208  fFileProcess->InitProcess();
1209  fInputEvent = fFileProcess->GetOutputEvent();
1210  if (fInputEvent == nullptr) {
1211  RESTError << "The external process \"" << p->GetName() << "\" doesn't yield any output event!"
1212  << RESTendl;
1213  exit(1);
1214  } else {
1215  fInputEvent->SetRunOrigin(fRunNumber);
1216  fInputEvent->SetSubRunOrigin(fParentRunNumber);
1217  fInputEvent->SetTimeStamp(fStartTime);
1218  }
1219  fInputFile = nullptr;
1220  // we make sure external processes can access to analysis tree
1221  fAnalysisTree = new TRestAnalysisTree("externalProcessAna", "externalProcessAna");
1222  p->SetAnalysisTree(fAnalysisTree);
1223  fTotalBytes = p->GetTotalBytes();
1224 
1225  GetNextEvent(fInputEvent, nullptr);
1226  // fAnalysisTree->CreateBranches();
1227  RESTInfo << "The external file process has been set! Name : " << fFileProcess->GetName() << RESTendl;
1228  } else {
1229  if (fFileProcess != nullptr) {
1230  RESTError << "There can only be one file process!" << RESTendl;
1231  exit(1);
1232  }
1233  if (p == nullptr) {
1234  RESTWarning << "Given file process is null, skipping..." << RESTendl;
1235  }
1236  }
1237 }
1238 
1246  if (event != nullptr) {
1247  if (fEventTree != nullptr) {
1248  if (fInputEvent != nullptr) {
1249  fEventTree->SetBranchAddress((TString)fInputEvent->ClassName() + "Branch", nullptr);
1250  fEventTree->SetBranchStatus((TString)fInputEvent->ClassName() + "Branch", false);
1251  }
1252  TObjArray* branches = fEventTree->GetListOfBranches();
1253  string branchName = (string)event->ClassName() + "Branch";
1254  for (int i = 0; i <= branches->GetLast(); i++) {
1255  auto branch = (TBranch*)branches->At(i);
1256  if ((string)branch->GetName() == branchName) {
1257  RESTDebug << "Setting input event.. Type: " << event->ClassName() << " Address: " << event
1258  << RESTendl;
1259  fInputEvent = event;
1260  fEventTree->SetBranchAddress(branchName.c_str(), &fInputEvent);
1261  fEventTree->SetBranchStatus(branchName.c_str(), false);
1262  fEventBranchLoc = i;
1263  break;
1264  } else if (i == branches->GetLast()) {
1265  RESTWarning << "REST Warning : (TRestRun) cannot find corresponding "
1266  "branch in event tree!"
1267  << RESTendl;
1268  RESTWarning << "Event Type : " << event->ClassName() << RESTendl;
1269  RESTWarning << "Input event not set!" << RESTendl;
1270  }
1271  }
1272  } else {
1273  fInputEvent = event;
1274  }
1275  this->GetEntry(fCurrentEvent);
1276  }
1277 }
1278 
1283  if (event != nullptr) {
1284  if (fEventTree != nullptr) {
1285  string eventName = (string)event->ClassName();
1286  string branchName = eventName + "Branch";
1287  fEventTree->Branch(branchName.c_str(), event);
1288  fEventTree->SetTitle((eventName + "Tree").c_str());
1289  }
1290  }
1291 }
1292 
1298 void TRestRun::ImportMetadata(const TString& File, const TString& name, const TString& type, Bool_t store) {
1299  const TString thisFile = SearchFile(File.Data());
1300  if (thisFile == "") {
1301  RESTError << "(ImportMetadata): The file " << thisFile << " does not exist!" << RESTendl;
1302  RESTError << RESTendl;
1303  return;
1304  }
1305  if (!TRestTools::isRootFile(thisFile.Data())) {
1306  RESTError << "(ImportMetadata) : The file " << thisFile << " is not root file!" << RESTendl;
1307  RESTError << "If you want to initialize metadata from rml file, use <TRest section!" << RESTendl;
1308  return;
1309  }
1310 
1311  TFile* file = TFile::Open(thisFile);
1312  // TODO give error in case we try to obtain a class that is not TRestMetadata
1313  if (type == "" && name == "") {
1314  RESTError << "(ImportMetadata) : metadata type and name is not "
1315  "specified!"
1316  << RESTendl;
1317  return;
1318  }
1319 
1320  TRestMetadata* meta = nullptr;
1321  if (name != "") {
1322  meta = GetMetadata(name, file);
1323  } else if (type != "") {
1324  meta = GetMetadataClass(type, file);
1325  }
1326 
1327  if (meta == nullptr) {
1328  cout << "REST ERROR (ImportMetadata) : " << name << " does not exist." << endl;
1329  cout << "Inside root file : " << File << endl;
1330  GetChar();
1331  file->Close();
1332  delete file;
1333  return;
1334  }
1335 
1336  if (store)
1337  meta->Store();
1338  else
1339  meta->DoNotStore();
1340 
1341  fMetadata.push_back(meta);
1342  meta->LoadConfigFromBuffer();
1343  file->Close();
1344  delete file;
1345 }
1346 
1347 Int_t TRestRun::Write(const char* name, Int_t option, Int_t bufsize) {
1348  ReSetVersion();
1349  return TRestMetadata::Write(name, option, bufsize);
1350 }
1351 
1352 Double_t TRestRun::GetRunLength() const {
1353  if (fEndTime - fStartTime == -1) {
1354  cout << "Run time is not set\n";
1355  }
1356  return fEndTime - fStartTime;
1357 }
1358 
1359 Long64_t TRestRun::GetTotalBytes() {
1360  if (fFileProcess != nullptr) {
1361  fTotalBytes = fFileProcess->GetTotalBytes();
1362  }
1363  return fTotalBytes;
1364 }
1365 
1366 Long64_t TRestRun::GetEntries() const {
1367  if (fAnalysisTree != nullptr) {
1368  return fAnalysisTree->GetEntries();
1369  }
1370  return fEntriesSaved;
1371  // return REST_MAXIMUM_EVENTS;
1372 }
1373 
1374 // Getters
1375 TRestEvent* TRestRun::GetEventWithID(Int_t eventID, Int_t subEventID, const TString& tag) {
1376  if (fAnalysisTree != nullptr) {
1377  int nEntries = fAnalysisTree->GetEntries();
1378 
1379  // set analysis tree to read only three branches
1380  fAnalysisTree->SetBranchStatus("*", false);
1381  fAnalysisTree->SetBranchStatus("eventID", true);
1382  fAnalysisTree->SetBranchStatus("subEventID", true);
1383  fAnalysisTree->SetBranchStatus("subEventTag", true);
1384 
1385  // just look through the whole analysis tree and find the entry
1386  // this is not good!
1387  for (int i = 0; i < nEntries; i++) {
1388  fAnalysisTree->GetEntry(i);
1389  if (fAnalysisTree->GetEventID() == eventID) {
1390  if (subEventID != -1 && fAnalysisTree->GetSubEventID() != subEventID) continue;
1391  if (tag != "" && fAnalysisTree->GetSubEventTag() != tag) continue;
1392  if (fEventTree != nullptr) fEventTree->GetEntry(i);
1393  fAnalysisTree->SetBranchStatus("*", true);
1394  fAnalysisTree->GetEntry(i);
1395  fCurrentEvent = i;
1396  return fInputEvent;
1397  }
1398  }
1399  // reset the branch status
1400  fAnalysisTree->SetBranchStatus("*", true);
1401  }
1402  return nullptr;
1403 }
1404 
1405 std::vector<int> TRestRun::GetEventEntriesWithConditions(const string& cuts, int startingIndex,
1406  int maxNumber) {
1407  int max = maxNumber;
1408  if (max < 0) max = GetEntries();
1409 
1410  std::vector<int> eventIds;
1411  // parsing cuts
1412  std::vector<string> observables;
1413  std::vector<string> operators;
1414  std::vector<Double_t> values;
1415  // it is necessary that this vector is sorted from longest to shortest
1416  const std::vector<string> validOperators = {"==", "<=", ">=", "=", ">", "<"};
1417 
1418  vector<string> cutsVector = Split(cuts, "&&", false, true);
1419 
1420  for (unsigned int i = 0; i < cutsVector.size(); i++) {
1421  string cut = cutsVector[i];
1422  for (unsigned int j = 0; j < validOperators.size(); j++) {
1423  if (cut.find(validOperators[j]) != string::npos) {
1424  operators.push_back(validOperators[j]);
1425  observables.push_back((string)cut.substr(0, cut.find(validOperators[j])));
1426  values.push_back(std::stod((string)cut.substr(
1427  cut.find(validOperators[j]) + validOperators[j].length(), string::npos)));
1428  break;
1429  }
1430  }
1431  }
1432 
1433  // check if observable name corresponds to a valid observable on the tree
1434  if (fAnalysisTree == nullptr) {
1435  return eventIds;
1436  }
1437  Int_t nEntries = fAnalysisTree->GetEntries();
1438  auto branches = fAnalysisTree->GetListOfBranches();
1439  std::set<string> branchNames;
1440  for (int i = 0; i < branches->GetEntries(); i++) {
1441  branchNames.insert((string)branches->At(i)->GetName());
1442  }
1443  // verify all observables in cuts are branch names
1444  for (unsigned int i = 0; i < observables.size(); i++) {
1445  // verify operators
1446  if (std::find(validOperators.begin(), validOperators.end(), operators[i]) == validOperators.end()) {
1447  // invalid operation
1448  cout << "invalid operation '" << operators[i] << "' for 'TRestRun::GetEventIdsWithConditions'"
1449  << endl;
1450  return eventIds;
1451  }
1452  // verify observables
1453  if (branchNames.count(observables[i]) == 0) {
1454  // invalid observable name
1455  cout << "invalid observable '" << observables[i] << "' for 'TRestRun::GetEventIdsWithConditions'"
1456  << endl;
1457  cout << "valid branch names: ";
1458  for (auto branchName : branchNames) {
1459  cout << branchName << " ";
1460  }
1461  cout << endl;
1462  return eventIds;
1463  }
1464  }
1465  // read only the necessary branches
1466  fAnalysisTree->SetBranchStatus("*", false);
1467  for (unsigned int i = 0; i < observables.size(); i++) {
1468  fAnalysisTree->SetBranchStatus(observables[i].c_str(), true);
1469  }
1470  // comparison code
1471  Double_t valueToCompareFrom;
1472  bool comparisonResult;
1473  int i;
1474  for (int iNoOffset = 0; iNoOffset < nEntries; iNoOffset++) {
1475  i = (iNoOffset + startingIndex) % nEntries;
1476  fAnalysisTree->GetEntry(i);
1477  comparisonResult = true;
1478  for (unsigned int j = 0; j < observables.size(); j++) {
1479  valueToCompareFrom = fAnalysisTree->GetDblObservableValue(observables[j].c_str());
1480  if (operators[j] == "=" || operators[j] == "==") {
1481  comparisonResult = comparisonResult && (valueToCompareFrom == values[j]);
1482  } else if (operators[j] == "<") {
1483  comparisonResult = comparisonResult && (valueToCompareFrom < values[j]);
1484  } else if (operators[j] == "<=") {
1485  comparisonResult = comparisonResult && (valueToCompareFrom <= values[j]);
1486  } else if (operators[j] == ">") {
1487  comparisonResult = comparisonResult && (valueToCompareFrom > values[j]);
1488  } else if (operators[j] == ">=") {
1489  comparisonResult = comparisonResult && (valueToCompareFrom >= values[j]);
1490  }
1491  }
1492 
1493  if (comparisonResult) {
1494  if ((int)eventIds.size() < max) {
1495  eventIds.push_back(i);
1496  } else {
1497  break;
1498  }
1499  }
1500  }
1501  // reset branch status
1502  fAnalysisTree->SetBranchStatus("*", true);
1503  return eventIds;
1504 }
1505 
1506 std::vector<int> TRestRun::GetEventIdsWithConditions(const string& cuts, int startingIndex, int maxNumber) {
1507  int max = maxNumber;
1508  if (max < 0) max = GetEntries();
1509 
1510  auto indices = GetEventEntriesWithConditions(cuts, startingIndex, max);
1511  std::vector<int> ids;
1512  for (unsigned int i = 0; i < indices.size(); i++) {
1513  GetEntry(indices[i]);
1514  ids.push_back(fAnalysisTree->GetEventID());
1515  }
1516  return ids;
1517 }
1518 
1526  // we retrieve only one index starting from position set by the counter and increase by one
1527  if (fEventIndexCounter >= GetEntries()) {
1528  fEventIndexCounter = 0;
1529  }
1530  auto indices = GetEventEntriesWithConditions(cuts, fEventIndexCounter++, 1);
1531  if (indices.size() == 0) {
1532  // no events found
1533  return nullptr;
1534  } else {
1535  fAnalysisTree->GetEntry(indices[0]);
1536  fEventTree->GetEntry(indices[0]);
1537  fCurrentEvent = indices[0];
1538  return fInputEvent;
1539  }
1540 }
1541 
1542 string TRestRun::GetRunInformation(const string& info) {
1543  string result = GetParameter(info, "");
1544  if (result != "") {
1545  return result;
1546  }
1547 
1548  result = GetDataMemberValue(info);
1549  if (result != "") {
1550  return result;
1551  }
1552 
1553  result = GetDataMemberValue(ParameterNameToDataMemberName(info));
1554  if (result != "") {
1555  return result;
1556  }
1557 
1558  if (fHostmgr && fHostmgr->GetProcessRunner() != nullptr) {
1559  result = fHostmgr->GetProcessRunner()->GetProcInfo(info);
1560  if (result != "") {
1561  return result;
1562  }
1563  }
1564 
1565  return info;
1566 }
1567 
1568 TRestMetadata* TRestRun::GetMetadataClass(const TString& type, TFile* file) {
1569  if (file != nullptr) {
1570  TIter nextkey(file->GetListOfKeys());
1571  TKey* key;
1572  while ((key = (TKey*)nextkey())) {
1573  string kName = key->GetClassName();
1574 
1575  if (REST_Reflection::GetClassQuick(kName.c_str()) != nullptr &&
1576  REST_Reflection::GetClassQuick(kName.c_str())->InheritsFrom(type)) {
1577  TRestMetadata* metadata = file->Get<TRestMetadata>(key->GetName());
1578 
1579  if (metadata != nullptr && metadata->InheritsFrom("TRestMetadata")) {
1580  return metadata;
1581  } else {
1582  RESTWarning << "TRestRun::GetMetadataClass() : The object to import is "
1583  "not inherited from TRestMetadata"
1584  << RESTendl;
1585  }
1586  }
1587  }
1588  } else {
1589  for (unsigned int i = 0; i < fMetadata.size(); i++)
1590  if (fMetadata[i]->InheritsFrom(type)) return fMetadata[i];
1591 
1592  if (fInputFile != nullptr && this->GetVersionCode() >= TRestTools::ConvertVersionCode("2.2.1")) {
1593  return GetMetadataClass(type, fInputFile);
1594  }
1595  }
1596 
1597  return nullptr;
1598 }
1599 
1600 TRestMetadata* TRestRun::GetMetadata(const TString& name, TFile* file) {
1601  if (file != nullptr) {
1602  TIter nextkey(file->GetListOfKeys());
1603  TKey* key;
1604  while ((key = (TKey*)nextkey())) {
1605  string kName = key->GetName();
1606 
1607  if (kName == name) {
1608  TRestMetadata* metadata = file->Get<TRestMetadata>(name);
1609 
1610  if (metadata->InheritsFrom("TRestMetadata")) {
1611  return metadata;
1612  } else {
1613  RESTWarning << "TRestRun::GetMetadata() : The object to import is not "
1614  "inherited from TRestMetadata"
1615  << RESTendl;
1616  }
1617  }
1618  }
1619  } else {
1620  for (unsigned int i = 0; i < fMetadata.size(); i++) {
1621  if (fMetadata[i]->GetName() == name) {
1622  return fMetadata[i];
1623  }
1624  }
1625  }
1626 
1627  return nullptr;
1628 }
1629 
1630 std::vector<std::string> TRestRun::GetMetadataNames() {
1631  std::vector<std::string> strings;
1632 
1633  for (int n = 0; n < GetNumberOfMetadata(); n++) strings.push_back(fMetadata[n]->GetName());
1634 
1635  return strings;
1636 }
1637 
1638 std::vector<std::string> TRestRun::GetMetadataTitles() {
1639  std::vector<std::string> strings;
1640 
1641  for (int n = 0; n < GetNumberOfMetadata(); n++) strings.push_back(fMetadata[n]->GetTitle());
1642 
1643  return strings;
1644 }
1645 
1652 string TRestRun::ReplaceMetadataMembers(const string& instr, Int_t precision) {
1653  if (instr.find("[", 0) == string::npos) return instr;
1654  string outstring = instr;
1655 
1656  int startPosition = 0;
1657  int endPosition = 0;
1658  while ((startPosition = outstring.find("[", endPosition)) != (int)string::npos) {
1659  endPosition = outstring.find("]", startPosition + 1);
1660  string s = outstring.substr(startPosition + 1, endPosition - startPosition - 1);
1661  int cont = count(s.begin(), s.end(), '[') - count(s.begin(), s.end(), ']');
1662 
1663  if (cont < 0) RESTError << "This is a coding error at ReplaceMetadataMembers!" << RESTendl;
1664 
1665  // We search for the enclosing ']'. Since we might find a vector index inside.
1666  while (cont > 0) {
1667  endPosition = outstring.find("]", endPosition + 1);
1668  s = outstring.substr(startPosition + 1, endPosition - startPosition - 1);
1669  cont = count(s.begin(), s.end(), '[') - count(s.begin(), s.end(), ']');
1670  if (endPosition == (int)string::npos) break;
1671  }
1672  if (endPosition == (int)string::npos) break;
1673 
1674  string expressionToReplace = outstring.substr(startPosition + 1, endPosition - startPosition - 1);
1675  string value = ReplaceMetadataMember(expressionToReplace);
1676 
1677  outstring.replace(startPosition, endPosition - startPosition + 1, value);
1678  endPosition = 0;
1679  }
1680 
1681  outstring = Replace(outstring, "{{", "[");
1682  outstring = Replace(outstring, "}}", "]");
1683 
1684  return REST_StringHelper::ReplaceMathematicalExpressions(outstring, precision);
1685 }
1686 
1690 //
1703 string TRestRun::ReplaceMetadataMember(const string& instr, Int_t precision) {
1704  if (instr.find("::") == string::npos && instr.find("->") == string::npos) {
1705  return "{{" + instr + "}}";
1706  }
1707  vector<string> results = Split(instr, "::", false, true);
1708  if (results.size() == 1) results = Split(instr, "->", false, true);
1709 
1710  if (results.size() == 2) {
1711  size_t index = 0;
1712  int pos1 = results[1].find("[", 0);
1713  int pos2 = results[1].find("]", pos1);
1714  if (pos1 > 0 && pos2 > 0) {
1715  string indexStr = results[1].substr(pos1 + 1, pos2 - pos1 - 1); // without []
1716 
1717  index = StringToInteger(indexStr);
1718  if (index < 0) index = 0;
1719 
1720  results[1] = results[1].substr(0, pos1);
1721  }
1722 
1723  if (GetMetadata(results[0])) {
1724  if (index >= this->GetMetadata(results[0])->GetDataMemberValues(results[1], precision).size()) {
1725  RESTWarning << "TRestRun::ReplaceMetadataMember. Index out of range!" << RESTendl;
1726  RESTWarning << "Returning the first element" << RESTendl;
1727  index = 0;
1728  }
1729  return this->GetMetadata(results[0])->GetDataMemberValues(results[1], precision)[index];
1730  }
1731 
1732  if (GetMetadataClass(results[0])) {
1733  if (index >=
1734  this->GetMetadataClass(results[0])->GetDataMemberValues(results[1], precision).size()) {
1735  RESTWarning << "TRestRun::ReplaceMetadataMember. Index out of range!" << RESTendl;
1736  RESTWarning << "Returning the first element" << RESTendl;
1737  index = 0;
1738  }
1739  return this->GetMetadataClass(results[0])->GetDataMemberValues(results[1], precision)[index];
1740  }
1741 
1742  } else
1743  RESTError << "TRestRun::ReplaceMetadataMember. Wrong number of elements found" << RESTendl;
1744 
1745  RESTWarning << "TRestRun::ReplaceMetadataMember. " << instr << " not found!" << RESTendl;
1746  return "";
1747 }
1748 
1752 //
1768 Bool_t TRestRun::EvaluateMetadataMember(const string& instr) {
1769  if (instr == "") return true;
1770 
1771  std::vector<string> oper = {"=", "==", "<=", "<", ">=", ">", "!="};
1772 
1773  string expOp = "";
1774  std::vector<string> results;
1775  for (unsigned int n = 0; n < oper.size(); n++) {
1776  size_t pos = 0;
1777  if (instr.find("->") != string::npos) pos = instr.find("->") + 2;
1778 
1779  if (instr.find(oper[n], pos) != string::npos) {
1780  expOp = oper[n];
1781  results = Split(instr, oper[n], false, true, pos);
1782  break;
1783  }
1784  }
1785 
1786  if (expOp == "") {
1787  RESTWarning << "TRestRun::EvaluateMetadataMember. Not valid operator found in expression : " << instr
1788  << RESTendl;
1789  return false;
1790  }
1791 
1792  if (results.size() != 2) {
1793  RESTWarning << "TRestRun::EvaluateMetadataMember. Not valid expression : " << instr << RESTendl;
1794  return false;
1795  }
1796 
1797  if (!isANumber(results[1])) {
1798  if (ReplaceMetadataMember(results[0]).find(results[1]) != string::npos)
1799  return true;
1800  else
1801  return false;
1802  }
1803 
1804  Double_t lvalue = StringToDouble(ReplaceMetadataMember(results[0]));
1805  Double_t rvalue = StringToDouble(results[1]);
1806 
1807  if (expOp == "=" && lvalue == rvalue) return true;
1808  if (expOp == "==" && lvalue == rvalue) return true;
1809  if (expOp == "<=" && lvalue <= rvalue) return true;
1810  if (expOp == "<" && lvalue < rvalue) return true;
1811  if (expOp == ">=" && lvalue >= rvalue) return true;
1812  if (expOp == ">" && lvalue > rvalue) return true;
1813  if (expOp == "!=" && lvalue != rvalue) return true;
1814 
1815  return false;
1816 }
1817 
1822  // cout.precision(10);
1824 
1825  RESTMetadata << "Version : " << this->GetVersion() << RESTendl;
1826  RESTMetadata << "Parent run number : " << GetParentRunNumber() << RESTendl;
1827  RESTMetadata << "Run number : " << GetRunNumber() << RESTendl;
1828  RESTMetadata << "Experiment/project : " << GetExperimentName() << RESTendl;
1829  RESTMetadata << "Run type : " << GetRunType() << RESTendl;
1830  RESTMetadata << "Run tag : " << GetRunTag() << RESTendl;
1831  RESTMetadata << "Run user : " << GetRunUser() << RESTendl;
1832  RESTMetadata << "Run description : " << GetRunDescription() << RESTendl;
1833  RESTMetadata << "Start Date/Time : " << ToDateTimeString(GetStartTimestamp()) << " ("
1834  << GetStartTimestamp() << ")" << RESTendl;
1835  RESTMetadata << "End Date/Time : " << ToDateTimeString(GetEndTimestamp()) << " (" << GetEndTimestamp()
1836  << ")" << RESTendl;
1837  RESTMetadata << "Input file : " << TRestTools::GetPureFileName((string)GetInputFileNamePattern())
1838  << RESTendl;
1839  RESTMetadata << "Output file : " << TRestTools::GetPureFileName((string)GetOutputFileName()) << RESTendl;
1840  if (fInputFile != nullptr) {
1841  RESTMetadata << "Data file : " << fInputFile->GetName();
1842  if (fNFilesSplit > 0) {
1843  RESTMetadata << " (Splitted into " << fNFilesSplit + 1 << " files)" << RESTendl;
1844  } else {
1845  RESTMetadata << RESTendl;
1846  }
1847  }
1848  RESTMetadata << "Number of events : " << fEntriesSaved << RESTendl;
1849  // metadata << "Input filename : " << fInputFilename << endl;
1850  // metadata << "Output filename : " << fOutputFilename << endl;
1851  // metadata << "Number of initial events : " << GetNumberOfEvents() << endl;
1852  // metadata << "Number of processed events : " << fProcessedEvents << endl;
1853  RESTMetadata << "---------------------------------------" << RESTendl;
1854  RESTMetadata << RESTendl;
1855 }
1856 
1861  cout.precision(10);
1862 
1863  cout << "------------------------" << endl;
1864  cout << "---- Run start date ----" << endl;
1865  cout << "------------------------" << endl;
1866  cout << "Unix time : " << fStartTime << endl;
1867  time_t tt = (time_t)fStartTime;
1868  struct tm* tm = localtime(&tt);
1869 
1870  char date[20];
1871  strftime(date, sizeof(date), "%Y-%m-%d", tm);
1872  cout << "Date : " << date << endl;
1873 
1874  char time[20];
1875  strftime(time, sizeof(time), "%H:%M:%S", tm);
1876  cout << "Time : " << time << endl;
1877  cout << "++++++++++++++++++++++++" << endl;
1878 }
1879 
1880 void TRestRun::PrintEndDate() {
1881  cout << "----------------------" << endl;
1882  cout << "---- Run end date ----" << endl;
1883  cout << "----------------------" << endl;
1884  cout << "Unix time : " << fEndTime << endl;
1885  time_t tt = (time_t)fEndTime;
1886  struct tm* tm = localtime(&tt);
1887 
1888  char date[20];
1889  strftime(date, sizeof(date), "%Y-%m-%d", tm);
1890  cout << "Date : " << date << endl;
1891 
1892  char time[20];
1893  strftime(time, sizeof(time), "%H:%M:%S", tm);
1894  cout << "Time : " << time << endl;
1895  cout << "++++++++++++++++++++++++" << endl;
1896 }
1897 
1903  Int_t nErrors = 0;
1904  for (unsigned int n = 0; n < fMetadata.size(); n++)
1905  if (fMetadata[n]->GetError()) nErrors++;
1906 
1907  if (nErrors) {
1908  cout << endl;
1909  RESTError << "Found a total of " << nErrors << " metadata errors" << RESTendl;
1910  for (unsigned int n = 0; n < fMetadata.size(); n++)
1911  if (fMetadata[n]->GetError()) {
1912  cout << endl;
1913  RESTError << "Class: " << fMetadata[n]->ClassName() << " Name: " << fMetadata[n]->GetName()
1914  << RESTendl;
1915  RESTError << "Number of errors: " << fMetadata[n]->GetNumberOfErrors() << RESTendl;
1916  RESTError << "Message: " << fMetadata[n]->GetErrorMessage() << RESTendl;
1917  }
1918  cout << endl;
1919  } else {
1920  cout << "No errors found!" << endl;
1921  }
1922 }
1923 
1929  Int_t nWarnings = 0;
1930  for (unsigned int n = 0; n < fMetadata.size(); n++)
1931  if (fMetadata[n]->GetWarning()) nWarnings++;
1932 
1933  if (nWarnings) {
1934  cout << endl;
1935  RESTWarning << "Found a total of " << nWarnings << " metadata warnings" << RESTendl;
1936  for (unsigned int n = 0; n < fMetadata.size(); n++)
1937  if (fMetadata[n]->GetWarning()) {
1938  cout << endl;
1939  RESTWarning << "Class: " << fMetadata[n]->ClassName() << " Name: " << fMetadata[n]->GetName()
1940  << RESTendl;
1941  RESTWarning << "Number of warnings: " << fMetadata[n]->GetNumberOfWarnings() << RESTendl;
1942  RESTWarning << "Message: " << fMetadata[n]->GetWarningMessage() << RESTendl;
1943  }
1944  cout << endl;
1945  } else {
1946  cout << "No warnings found!" << endl;
1947  }
1948 }
bool IsZombie() const
If this object type wrapper is invalid.
TRestReflector GetDataMember(const std::string &name)
Find the class's datamember as TRestReflector object, including those from base class.
void ParseString(const std::string &str) const
Set the value of the wrapped object from std::string.
REST core data-saving helper based on TTree.
void SetObservable(Int_t id, RESTValue obs)
Set the value of observable whose id is as specified.
virtual std::vector< int > search_run_with_file(std::string filepattern)
search runs according to the file name. return a list of run numbers
virtual int get_lastrun()
get the latest run id in database
virtual std::vector< DBFile > query_run_files(int runnumber)
return all the files of the run
virtual int set_run(DBEntry info, bool overwrite=true)
add/update a run, with run info as struct DBEntry. returns the added run id
virtual int set_runfile(int runnumber, std::string filename)
add/update a runfile to the specified run
virtual DBEntry query_run(int runnumber)
A base class for any REST event process.
void SetAnalysisTree(TRestAnalysisTree *tree)
Set analysis tree of this process, then add observables to it.
virtual Long64_t GetTotalBytes() const
A base class for any REST event.
Definition: TRestEvent.h:38
virtual void Initialize()=0
Definition: TRestEvent.cxx:73
A base class for any REST metadata class.
Definition: TRestMetadata.h:74
virtual void PrintMetadata()
Implemented it in the derived metadata class to print out specific metadata information.
void DoNotStore()
If this method is called the metadata information will not be stored in disk.
void SetHostmgr(TRestManager *m)
Set the host manager for this class.
Int_t LoadConfigFromBuffer()
Initialize data from a string element buffer.
Int_t LoadConfigFromElement(TiXmlElement *eSectional, TiXmlElement *eGlobal, std::map< std::string, std::string > envs={})
Main starter method.
void SetConfigFile(std::string configFilename)
set config file path from external
void Store()
If this method is called the metadata information will be stored in disk.
virtual void UpdateMetadataMembers()
Method to allow implementation of specific metadata members updates at inherited classes.
virtual Int_t Write(const char *name=nullptr, Int_t option=0, Int_t bufsize=0)
overwriting the write() method with fStore considered
Data provider and manager in REST.
Definition: TRestRun.h:18
void PrintWarnings()
Prints out all the warnings registered by metadata classes accessible to TRestRun,...
Definition: TRestRun.cxx:1928
void AddEventBranch(TRestEvent *event)
Add an event branch in output EventTree.
Definition: TRestRun.cxx:1282
void OpenInputFile(int i)
Open the i th file in the file list.
Definition: TRestRun.cxx:314
void CloseFile()
Close both input file and output file, setting trees to nullptr also.
Definition: TRestRun.cxx:1155
TFile * FormOutputFile()
Create a new TFile as REST output file. Writing metadata objects into it.
Definition: TRestRun.cxx:1036
void ResetEntry()
Reset file reading progress.
Definition: TRestRun.cxx:781
TString FormFormat(const TString &filenameFormat)
Form output file name according to file info list, proc info list and run data.
Definition: TRestRun.cxx:940
void SetInputEvent(TRestEvent *event)
Retarget input event in the tree.
Definition: TRestRun.cxx:1245
std::string ReplaceMetadataMember(const std::string &instr, Int_t precision=0)
It will replace the data member from the corresponding metadata class type or name defined in the inp...
Definition: TRestRun.cxx:1703
void GetEntry(Long64_t entry)
Calls GetEntry() for both AnalysisTree and EventTree.
Definition: TRestRun.cxx:908
void InitFromConfigFile() override
Initialize logic of TRestRun.
Definition: TRestRun.cxx:122
void Initialize() override
REST run class.
Definition: TRestRun.cxx:71
void PrintErrors()
Prints out all the warnings registered by metadata classes accessible to TRestRun,...
Definition: TRestRun.cxx:1902
std::string ReplaceMetadataMembers(const std::string &instr, Int_t precision=8)
It will replace the data members contained inside the string given as input. The data members in the ...
Definition: TRestRun.cxx:1652
void PrintMetadata() override
Prints the basic run information.
Definition: TRestRun.cxx:1821
TFile * MergeToOutputFile(std::vector< std::string > fileFullNames, std::string outputFileName="")
Form REST output file by merging a list of files together.
Definition: TRestRun.cxx:985
std::vector< std::string > GetEventTypesList()
It returns a list of available event types inside the file.
Definition: TRestRun.cxx:892
void ImportMetadata(const TString &rootFile, const TString &name, const TString &type, Bool_t store)
Open the root file and import the metadata of the given name.
Definition: TRestRun.cxx:1298
Bool_t EvaluateMetadataMember(const std::string &instr)
It will evaluate the expression given including the data member from the corresponding metadata class...
Definition: TRestRun.cxx:1768
void SetExtProcess(TRestEventProcess *p)
Set external file process.
Definition: TRestRun.cxx:1203
void PrintStartDate()
Prints the run start date and time in human format.
Definition: TRestRun.cxx:1860
void WriteWithDataBase()
Write this object into TFile and add a new entry in database.
Definition: TRestRun.cxx:1092
Int_t Write(const char *name=nullptr, Int_t option=0, Int_t bufsize=0) override
overwriting the write() method with fStore considered
Definition: TRestRun.cxx:1347
void ReadFileInfo(const std::string &filename)
Extract file info from a file, and save it in the file info list.
Definition: TRestRun.cxx:652
Int_t GetNextEvent(TRestEvent *targetEvent, TRestAnalysisTree *targetTree)
Get next event by writing event data into target event and target tree.
Definition: TRestRun.cxx:796
TRestEvent * GetNextEventWithConditions(const std::string &)
Load the next event that satisfies the conditions specified by a string.
Definition: TRestRun.cxx:1525
static std::pair< std::string, std::string > SeparatePathAndName(const std::string &fullname)
Separate path and filename in a full path+filename string, returns a pair of string.
Definition: TRestTools.cxx:813
static std::string GetPureFileName(const std::string &fullPathFileName)
Removes all directories in the full path filename description given in the argument.
Definition: TRestTools.cxx:863
static bool fileExists(const std::string &filename)
Returns true if the file (or directory) with path filename exists.
Definition: TRestTools.cxx:728
static std::vector< std::string > GetFilesMatchingPattern(std::string pattern, bool unlimited=false)
Returns a list of files whose name match the pattern string. Key word is "*". e.g....
Definition: TRestTools.cxx:976
static int ConvertVersionCode(std::string in)
Convert version to a unique string.
static bool isPathWritable(const std::string &path)
Returns true if the path given by argument is writable.
Definition: TRestTools.cxx:778
static bool isAbsolutePath(const std::string &path)
Check if the path is absolute path or not.
Definition: TRestTools.cxx:795
static std::string RemoveMultipleSlash(std::string)
Returns the input string but without multiple slashes ("/")
Definition: TRestTools.cxx:844
static bool isRootFile(const std::string &filename)
Returns true if the filename has *.root* extension.
Definition: TRestTools.cxx:733
TClass * GetClassQuick(std::string type)
TRestReflector Assembly(const std::string &typeName)
Assembly an object of type: typeName, returning the allocated memory address and size.
Int_t GetChar(std::string hint="Press a KEY to continue ...")
Helps to pause the program, printing a message before pausing.
std::vector< std::string > Split(std::string in, std::string separator, bool allowBlankString=false, bool removeWhiteSpaces=false, int startPos=-1)
Split the input string according to the given separator. Returning a vector of fragments.
Double_t StringToDouble(std::string in)
Gets a double from a string.
std::string ToUpper(std::string in)
Convert string to its upper case. Alternative of TString::ToUpper.
Int_t StringToInteger(std::string in)
Gets an integer from a string.
Int_t Count(std::string s, std::string sbstring)
Counts the number of occurences of substring inside the input string in.
std::string ParameterNameToDataMemberName(std::string name)
Convert parameter name to datamember name, following REST parameter naming convention.
std::string DataMemberNameToParameterName(std::string name)
Convert data member name to parameter name, following REST parameter naming convention.
Int_t isANumber(std::string in)
Returns 1 only if a valid number is found in the string in. If not it returns 0.
std::string RemoveWhiteSpaces(std::string in)
Returns the input string removing all white spaces.
std::string ToDateTimeString(time_t time)
Format time_t into string.
std::string Replace(std::string in, std::string thisString, std::string byThisString, size_t fromPosition=0, Int_t N=0)
Replace any occurences of thisSring by byThisString inside string in.
std::string ReplaceMathematicalExpressions(std::string buffer, Int_t precision=0, std::string errorMessage="")
Evaluates and replaces valid mathematical expressions found in the input string buffer.