KaliVeda
Toolkit for HIC analysis
KVEventSelector.cpp
1 #include "KVNucleusEvent.h"
2 #define KVEventSelector_cxx
3 #include "KVEventSelector.h"
4 #include <KVClassMonitor.h>
5 #include <TStyle.h>
6 #include "TPluginManager.h"
7 #include "TSystem.h"
8 #include "KVDataRepositoryManager.h"
9 #include "KVDataRepository.h"
10 #include "KVDataSetManager.h"
11 #include "TProof.h"
12 #include "KVDataSetAnalyser.h"
13 
14 using namespace std;
15 
17 
18 
19 
21 void KVEventSelector::Begin(TTree* /*tree*/)
22 {
23  ParseOptions();
24  // Need to parse options here for use in Terminate
25  // Also, on PROOF, any KVDataAnalyser instance has to be passed to the workers
26  // via the TSelector input list.
27 
28  if (IsOptGiven("CombinedOutputFile")) {
29  fCombinedOutputFile = GetOpt("CombinedOutputFile");
30  }
31  else if (gProof) {
32  // when running with PROOF, if the user calls SetCombinedOutputFile()
33  // in InitAnalysis(), it will only be executed on the workers (in SlaveBegin()).
34  // therefore we call InitAnalysis() here, but deactivate CreateTreeFile(),
35  // AddTree() and AddHisto() in order to avoid interference with workers
36  fDisableCreateTreeFile = kTRUE;
37  if (gDataAnalyser) {
38  gDataAnalyser->RegisterUserClass(this);
39  gDataAnalyser->preInitAnalysis();
40  }
41  InitAnalysis(); //user initialisations for analysis
42  if (gDataAnalyser) gDataAnalyser->postInitAnalysis();
43  fDisableCreateTreeFile = kFALSE;
44  }
45 
46  if (gDataAnalyser) {
47  if (GetInputList()) {
48  gDataAnalyser->AddJobDescriptionList(GetInputList());
49  //GetInputList()->ls();
50  }
51  }
52  if (IsOptGiven("AuxFiles")) {
53  SetUpAuxEventChain();
54  if (GetInputList()) GetInputList()->Add(fAuxChain);
55  }
56 }
57 
58 
59 
61 
63 {
64  if (GetInputList() && GetInputList()->FindObject("JobDescriptionList")) {
65  KVNameValueList* jdl = dynamic_cast<KVNameValueList*>(GetInputList()->FindObject("JobDescriptionList"));
66  if (jdl) {
67  KVDataAnalysisTask* task = nullptr;
68  if (jdl->HasParameter("DataRepository")) {
69  if (!gDataRepositoryManager) {
71  gDataRepositoryManager->Init();
72  }
73  gDataRepositoryManager->GetRepository(jdl->GetStringValue("DataRepository"))->cd();
74  gDataSetManager->GetDataSet(jdl->GetStringValue("DataSet"))->cd();
75  task = gDataSet->GetAnalysisTask(jdl->GetStringValue("AnalysisTask"));
76  }
77  else {
78  if (!gDataSetManager) {
79  gDataSetManager = new KVDataSetManager;
80  gDataSetManager->Init();
81  }
82  task = gDataSetManager->GetAnalysisTaskAny(jdl->GetStringValue("AnalysisTask"));
83  }
84  gDataAnalyser = KVDataAnalyser::GetAnalyser(task->GetDataAnalyser());
85  if (gDataSet && gDataAnalyser->InheritsFrom("KVDataSetAnalyser"))
86  dynamic_cast<KVDataSetAnalyser*>(gDataAnalyser)->SetDataSet(gDataSet);
87  gDataAnalyser->SetAnalysisTask(task);
88  gDataAnalyser->RegisterUserClass(this);
89  gDataAnalyser->SetProofMode((KVDataAnalyser::EProofMode)jdl->GetIntValue("PROOFMode"));
90  }
91  }
92 
93  ParseOptions();
94 
95  if (IsOptGiven("CombinedOutputFile")) {
96  fCombinedOutputFile = GetOpt("CombinedOutputFile");
97  Info("SlaveBegin", "Output file name = %s", fCombinedOutputFile.Data());
98  }
99 
100  // tell the data analyser who we are
101  if (gDataAnalyser) {
102  gDataAnalyser->RegisterUserClass(this);
103  gDataAnalyser->preInitAnalysis();
104  }
105  // make sure histo/tree creation are enabled
106  fDisableCreateTreeFile = kFALSE;
107  InitAnalysis(); //user initialisations for analysis
108  if (gDataAnalyser) gDataAnalyser->postInitAnalysis();
109 
110  if (IsOptGiven("AuxFiles")) {
111  // auxiliary files with PROOF
112  if (GetInputList()) {
113  fAuxChain = (TTree*)GetInputList()->FindObject(GetOpt("AuxTreeName"));
114  InitFriendTree(fAuxChain, GetOpt("AuxBranchName"));
115  }
116  }
117  Info("SlaveBegin", "fOutput->ls()");
118  GetOutputList()->ls();
119 }
120 
121 
122 
124 
126 {
127  if (gDataAnalyser && gDataAnalyser->AbortProcessingLoop()) {
128  // abort requested by external process
129  Abort(Form("Job received KILL signal from batch system after %lld events - batch job probably needs more CPU time (see end of job statistics)", fEventsRead), kAbortFile);
130  return kFALSE;
131  }
132 
133  fTreeEntry = entry;
134 
135  if (gDataAnalyser && gDataAnalyser->CheckStatusUpdateInterval(fEventsRead))
136  gDataAnalyser->DoStatusUpdate(fEventsRead);
137 
138  GetEntry(entry);
139  if (gDataAnalyser) gDataAnalyser->preAnalysis();
140  fEventsRead++;
141  if (GetEvent()) {
142  SetAnalysisFrame();//let user define any necessary reference frames for particles
143  //apply particle selection criteria
144  if (fPartCond.IsSet()) {
145  for (auto& part : EventOKIterator(GetEvent())) {
146  part.SetIsOK(fPartCond.Test(part));
147  }
148  }
149 
150  // initialise global variables at first event
151  if (fFirstEvent) {
152  for (auto p : fGlobalVariables) dynamic_cast<KVGVList*>(p)->Init();
153  fFirstEvent = kFALSE;
154  }
155  RecalculateGlobalVariables();
156  }
157 
158  Bool_t ok_anal = kTRUE;
159  if (!fGlobalVariableAbortEventAnalysis) {
160  // if global variables are defined, events are only analysed if no global variables
161  // in the list have failed an event selection condition
162  ok_anal = Analysis(); //user analysis
163  if (gDataAnalyser) gDataAnalyser->postAnalysis();
164  }
165  CheckEndOfRun();
166 
167  return ok_anal;
168 }
169 
170 
171 
173 
175 {
176  if (AtEndOfRun()) {
177  Info("Process", "End of file reached after %lld events", fEventsRead);
178  if (gDataAnalyser) gDataAnalyser->preEndRun();
179  EndRun();
180  if (gDataAnalyser) gDataAnalyser->postEndRun();
181  fNotifyCalled = kFALSE;//Notify will be called when next file is opened (in TChain)
182  }
183 }
184 
185 
186 
188 
190 {
191  if (writeFile) {
192  auto sav_dir = gDirectory;//save current working directory
193 
194  writeFile->cd();
195  // loop over all histos and trees, writing them in the output file
196  if (lhisto.GetEntries()) {
197  lhisto.R__FOR_EACH(TH1, Write)();
198  }
199  if (ltree.GetEntries()) {
200  ltree.R__FOR_EACH(TTree, Write)(0, TObject::kOverwrite);
201  }
202  writeFile->Close();
203  if (gDataAnalyser->GetProofMode() != KVDataAnalyser::EProofMode::None) {
204  fOutput->Add(mergeFile);
205  }
206 
207  sav_dir->cd();
208  }
209 }
210 
211 
212 
214 
216 {
217  TDatime now;
218  Info("Terminate", "Analysis ends at %s", now.AsString());
219 
220  if (gDataAnalyser) gDataAnalyser->preEndAnalysis();
221  EndAnalysis(); //user end of analysis routine
222  if (gDataAnalyser) gDataAnalyser->postEndAnalysis();
223 
224  if (GetInputList() && fAuxChain) GetInputList()->Remove(fAuxChain);
225  SafeDelete(fAuxChain);
226 }
227 
228 
229 
230 
231 
232 
242 
244 {
245  //Use this method if you change e.g. the particle selection criteria in your
246  //Analysis() method and want to recalculate the values of all global variables
247  //for your new selection.
248  //
249  //WARNING: the global variables are calculated automatically for you for each event
250  //before method Analysis() is called. In order for the correct particles to be included in
251  //this calculation, make sure that at the END of Analysis() you reset the selection
252  //criteria.
253 
254  fGlobalVariableAbortEventAnalysis = false;
255  for (auto p : fGlobalVariables) {
256  auto gvl = dynamic_cast<KVGVList*>(p);
257  gvl->CalculateGlobalVariables(GetEvent());
258  // check if a variable event selection failed
259  if (gvl->AbortEventAnalysis()) {
260  fGlobalVariableAbortEventAnalysis = true;
261  return;
262  }
263  }
264 }
265 
266 
267 
268 
269 
270 
271 
272 
273 
274 
275 
276 
277 
281 
283 {
284  // Declare a histogram to be used in analysis.
285  // This method must be called when using PROOF.
286 
287  if (fDisableCreateTreeFile) return;
288 
289  lhisto.Add(histo);
290 
291  if (writeFile) histo->SetDirectory(writeFile); // if output file is initialized, associate histo with it
292  else create_output_file();// try to initialize output file
293 }
294 
295 
296 
300 
302 {
303  // Declare a TTree to be used in analysis.
304  // This method must be called when using PROOF.
305 
306  if (fDisableCreateTreeFile) return;
307 
308  tree->SetAutoSave();
309  ltree.Add(tree);
310 
311  if (writeFile) tree->SetDirectory(writeFile); // if output file is initialized, associate tree with it
312  else create_output_file();// try to initialize output file
313 }
314 
315 
316 
321 
323 {
324  // Create the file for saving histos and/or trees created during analysis.
325  //
326  // The name of the file must first be set using SetJobOutputFileName()
327 
328  if (fCombinedOutputFile == "") return;
329 
330  auto sav_dir = gDirectory;//save current working directory
331  if (gDataAnalyser->GetProofMode() == KVDataAnalyser::EProofMode::None) {
332  // Analysis running in 'normal' (non-PROOF) mode
333  writeFile = TFile::Open(fCombinedOutputFile, "RECREATE");
334  }
335  else {
336  // Analysis running with PROOF(Lite)
337  mergeFile = new TProofOutputFile(fCombinedOutputFile, "M");
338  mergeFile->SetOutputFileName(fCombinedOutputFile);
339  writeFile = mergeFile->OpenFile("RECREATE");
340  if (writeFile && writeFile->IsZombie()) SafeDelete(writeFile);
341  }
342  sav_dir->cd();//return to previous working directory
343 
344  if (!writeFile) {
345  TString amsg = TString::Format("%s::create_output_file: could not create output ROOT file '%s'!",
346  ClassName(), fCombinedOutputFile.Data());
347  Abort(amsg, kAbortProcess);
348  }
349 
350  // any previously declared histograms or trees must now be associated with the output file
351  if (lhisto.GetEntries()) {
352  lhisto.R__FOR_EACH(TH1, SetDirectory)(writeFile);
353  }
354  if (ltree.GetEntries()) {
355  ltree.R__FOR_EACH(TTree, SetDirectory)(writeFile);
356  }
357 }
358 
359 
360 
362 
364 {
365  Deprecate("Calling this method is no longer required, and any filename given will be ignored."
366  " Call SetJobOutputFileName() to define the output filename.");
367  return kTRUE;
368 }
369 
370 
371 
373 
374 TTree* KVEventSelector::AddTree(const TString& name, const TString& title)
375 {
376  auto t = new TTree(name, title);
377  add_tree(t);
378  return t;
379 }
380 
381 
382 
383 
385 
386 void KVEventSelector::FillHisto(const Char_t* histo_name, Double_t one, Double_t two, Double_t three, Double_t four)
387 {
388  TH1* h1 = 0;
389  if ((h1 = GetHisto(histo_name))) {
390  if (h1->InheritsFrom("TH3"))
391  FillTH3((TH3*)h1, one, two, three, four);
392  else if (h1->InheritsFrom("TProfile2D"))
393  FillTProfile2D((TProfile2D*)h1, one, two, three, four);
394  else if (h1->InheritsFrom("TH2"))
395  FillTH2((TH2*)h1, one, two, three);
396  else if (h1->InheritsFrom("TProfile"))
397  FillTProfile((TProfile*)h1, one, two, three);
398  else if (h1->InheritsFrom("TH1"))
399  FillTH1(h1, one, two);
400  else
401  Warning("FillHisto", "%s -> Classe non prevue ...", lhisto.FindObject(histo_name)->ClassName());
402  }
403  else {
404  Warning("FillHisto", "%s introuvable", histo_name);
405  }
406 }
407 
408 
409 
411 
412 void KVEventSelector::FillHisto(const Char_t* histo_name, const Char_t* label, Double_t weight)
413 {
414  TH1* h1 = 0;
415  if ((h1 = GetHisto(histo_name))) {
416  h1->Fill(label, weight);
417  }
418  else {
419  Warning("FillHisto", "%s introuvable", histo_name);
420  }
421 }
422 
423 
424 
425 
427 
429 {
430 
431  h1->Fill(one, two);
432 
433 }
434 
435 
436 
437 
439 
441 {
442 
443  h1->Fill(one, two, three);
444 
445 }
446 
447 
448 
449 
451 
453 {
454 
455  h2->Fill(one, two, three);
456 
457 }
458 
459 
460 
461 
463 
465 {
466 
467  h2->Fill(one, two, three, four);
468 }
469 
470 
471 
472 
474 
476 {
477 
478  h3->Fill(one, two, three, four);
479 }
480 
481 
482 
492 
494 {
495  // Called by SlaveBegin() when user gives the following options:
496  //
497  //~~~~~~~~~~~~~~~~
498  // AuxFiles: list of files containing "friend" TTrees to be made available during analysis
499  // AuxDir: directory in which to find AuxFiles
500  // AuxTreeName: name of tree in AuxFiles containing KVEvent objects
501  // AuxBranchName: name of branch in AuxFiles containing KVEvent objects
502  //~~~~~~~~~~~~~~~~
503 
504  if (!IsOptGiven("AuxDir") || !IsOptGiven("AuxTreeName") || !IsOptGiven("AuxBranchName")) {
505  Error("SetUpAuxEventChain", "if AuxFiles option given, you must define AuxDir, AuxTreeName and AuxBranchName");
506  return;
507  }
508  KVString filelist = GetOpt("AuxFiles");
509  KVString filedir = GetOpt("AuxDir");
510  if (!filedir.EndsWith("/")) filedir += "/";
511  TChain* auxchain = new TChain(GetOpt("AuxTreeName"));
512  filelist.Begin("|");
513  while (!filelist.End()) {
514  KVString path = filedir + filelist.Next();
515  auxchain->Add(path);
516  }
517  InitFriendTree(auxchain, GetOpt("AuxBranchName"));
518 }
519 
520 
521 
523 
524 void KVEventSelector::FillTree(const Char_t* tree_name)
525 {
526  if (!strcmp(tree_name, "")) {
527  ltree.R__FOR_EACH(TTree, Fill)();
528  }
529  else {
530  TTree* tt = 0;
531  if ((tt = GetTree(tree_name))) {
532  tt->Fill();
533  }
534  else {
535  Warning("FillTree", "%s unknown", tree_name);
536  }
537  }
538 }
539 
540 
541 
542 
543 
554 
556 {
557  // Analyse comma-separated list of options given to TTree::Process
558  // and store all `"option=value"` pairs in fOptionList.
559  // Options can then be accessed using IsOptGiven(), GetOptString(), etc.
560  //
561  //~~~~~~~~~~~~~~~
562  // BranchName=xxxx : change name of branch in TTree containing data
563  // EventsReadInterval=N: print "+++ 12345 events processed +++" every N events
564  //~~~~~~~~~~~~~~~
565  //
566 
567  fOptionList.ParseOptions(GetOption());
568 
569  // check for branch name
570  if (IsOptGiven("BranchName")) SetBranchName(GetOpt("BranchName"));
571  // check for events read interval
572  if (IsOptGiven("EventsReadInterval")) SetEventsReadInterval(GetOpt("EventsReadInterval").Atoi());
573 }
574 
575 
576 
578 
580 {
581  Event = nullptr;
582  // Set branch addresses and branch pointers
583  if (!tree) return;
584  fChain = tree;
585  fChain->SetMakeClass(1);
586  // When using PROOF, need to set tree pointer in KVDataAnalyser
587  if (gDataAnalyser->GetProofMode() != KVDataAnalyser::EProofMode::None) {
588  gDataAnalyser->SetAnalysedTree(tree);
589  }
590 
591  if (strcmp(GetBranchName(), "") && fChain->GetBranch(GetBranchName())) {
592  Info("Init", "Analysing data in branch : %s", GetBranchName());
593  fChain->SetBranchAddress(GetBranchName(), &Event, &b_Event);
594  }
595  else {
596  Error("Init", "Failed to link KVEvent object with a branch. Expected branch name=%s",
597  GetBranchName());
598  }
599  //user additional branches addressing
600  SetAdditionalBranchAddress();
601  fEventsRead = 0;
602 
603 }
604 
605 
606 
622 
624 {
625  // @param tree
626  // @param branchname
627  //
628  // Set up a "friend" TTree/TChain containing KVEvent-derived objects in branch 'branchname'
629  // N.B. this is not a "friend" in the sense of TTree::AddFriend, the main TTree and the
630  // "friend" TTree can have different numbers of entries
631  //
632  // After calling this method at the beginning of the analysis, you can
633  // access any of the events stored in the "friend" by doing:
634  //
635  //~~~{.cpp}
636  // GetFriendTreeEntry(entry_number);
637  // KVEvent* friend_event = GetFriendEvent();
638  //~~~
639 
640  AuxEvent = 0;
641  fAuxChain = tree;
642  fAuxChain->SetBranchAddress(branchname, &AuxEvent);
643  fAuxChain->Print();
644  fAuxChain->GetEntry(0);
645  fAuxChain->GetTree()->GetEntry(0);
646 }
647 
648 
649 
651 
653 {
654  if (fNotifyCalled) return kTRUE; // avoid multiple calls at beginning of analysis
655  fNotifyCalled = kTRUE;
656 
657  Info("Notify", "Beginning analysis of file %s (%lld events)", fChain->GetCurrentFile()->GetName(), fChain->GetTree()->GetEntries());
658 
659  if (gDataAnalyser) gDataAnalyser->preInitRun();
660  InitRun(); //user initialisations for run
661  if (gDataAnalyser) gDataAnalyser->postInitRun();
662 
664 
665  return kTRUE;
666 }
667 
668 
#define SafeDelete(p)
bool Bool_t
char Char_t
constexpr Bool_t kFALSE
double Double_t
constexpr Bool_t kTRUE
#define gDirectory
winID h TVirtualViewer3D TVirtualGLPainter p
char name[80]
R__EXTERN TProof * gProof
char * Form(const char *fmt,...)
Class for iterating over "OK" nuclei in events accessed through base pointer/reference.
static KVClassMonitor * GetInstance()
Return pointer to unique instance of class monitor class.
void SetInitStatistics()
virtual void SetAnalysedTree(TTree *)
virtual void postEndRun()
void DoStatusUpdate(Long64_t nevents) const
Print infos on events treated, disk usage, memory usage.
virtual void AddJobDescriptionList(TList *)
virtual void preInitAnalysis()
virtual void postAnalysis()
void SetAnalysisTask(KVDataAnalysisTask *at)
void SetProofMode(EProofMode e)
virtual Bool_t CheckStatusUpdateInterval(Long64_t nevents) const
virtual void preAnalysis()
static KVDataAnalyser * GetAnalyser(const Char_t *plugin)
EProofMode GetProofMode() const
virtual void preEndRun()
virtual void postInitRun()
static Bool_t AbortProcessingLoop()
virtual void postEndAnalysis()
virtual void preEndAnalysis()
virtual void preInitRun()
virtual void RegisterUserClass(TObject *)
virtual void postInitAnalysis()
Define and manage data analysis tasks.
virtual const Char_t * GetDataAnalyser() const
Manages access to one or more data repositories.
KVDataRepository * GetRepository(const Char_t *name) const
Pilots user analysis of experimental data.
Manage all datasets contained in a given data repository.
virtual Bool_t Init(KVDataRepository *=0)
KVDataAnalysisTask * GetAnalysisTaskAny(const Char_t *keywords) const
KVDataSet * GetDataSet(Int_t) const
Return pointer to DataSet using index in list of all datasets, index>=0.
KVDataAnalysisTask * GetAnalysisTask(Int_t) const
Definition: KVDataSet.cpp:598
General purpose analysis base class for TTree containing KVEvent objects.
void FillTProfile2D(TProfile2D *h2, Double_t one, Double_t two, Double_t three, Double_t four)
void InitFriendTree(TTree *tree, const TString &branchname)
virtual void CheckEndOfRun()
void FillTH2(TH2 *h2, Double_t one, Double_t two, Double_t three)
Bool_t CreateTreeFile(const Char_t *filename="")
void AddTree(TTree *tree)
virtual void SlaveBegin(TTree *tree)
virtual void SlaveTerminate()
virtual void Terminate()
virtual Bool_t Notify()
void add_histo(TH1 *histo)
for merging with PROOF
void FillHisto(const Char_t *sname, Double_t one, Double_t two=1, Double_t three=1, Double_t four=1)
void FillTProfile(TProfile *h1, Double_t one, Double_t two, Double_t three)
void FillTH1(TH1 *h1, Double_t one, Double_t two)
virtual void Init(TTree *tree)
void add_tree(TTree *tree)
void RecalculateGlobalVariables()
virtual Bool_t Process(Long64_t entry)
virtual void ParseOptions()
void FillTH3(TH3 *h3, Double_t one, Double_t two, Double_t three, Double_t four)
void FillTree(const Char_t *tree_name="")
#define KVGVLIST_OPTIMIZE_GVLIST
Definition: KVGVList.h:227
void CalculateGlobalVariables(KVEvent *e)
Definition: KVGVList.cpp:206
Handles lists of named parameters with different types, a list of KVNamedParameter objects.
Int_t GetIntValue(const Char_t *name) const
const Char_t * GetStringValue(const Char_t *name) const
Bool_t HasParameter(const Char_t *name) const
Extension of ROOT TString class which allows backwards compatibility with ROOT v3....
Definition: KVString.h:73
void Begin(TString delim) const
Definition: KVString.cpp:565
Bool_t End() const
Definition: KVString.cpp:634
KVString Next(Bool_t strip_whitespace=kFALSE) const
Definition: KVString.cpp:695
virtual Int_t Add(const char *name, Long64_t nentries=TTree::kMaxEntries)
const char * AsString() const
static TFile * Open(const char *name, Option_t *option="", const char *ftitle="", Int_t compress=ROOT::RCompressionSetting::EDefaults::kUseCompiledDefault, Int_t netopt=0)
virtual void SetDirectory(TDirectory *dir)
virtual Int_t Fill(const char *name, Double_t w)
virtual Int_t Fill(const char *namex, const char *namey, Double_t w)
virtual Int_t Fill(const char *namex, const char *namey, const char *namez, Double_t w)
virtual Bool_t InheritsFrom(const char *classname) const
virtual Int_t Fill(const char *namex, const char *namey, Double_t z, Double_t w=1.)
Bool_t EndsWith(const char *pat, ECaseCompare cmp=kExact) const
static TString Format(const char *fmt,...)
long long Long64_t
RooCmdArg ClassName(const char *name)
TH1F * h1
void Init()
str tree_name
void Error(const char *location, const char *fmt,...)
void Info(const char *location, const char *fmt,...)
void Warning(const char *location, const char *fmt,...)
auto * tt
ClassImp(TPyArg)