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 #ifdef WITH_PROOF
12 #include "TProof.h"
13 #endif
14 #include "KVDataSetAnalyser.h"
15 
16 using namespace std;
17 
19 
20 
21 
23 void KVEventSelector::Begin(TTree* /*tree*/)
24 {
25  ParseOptions();
26  // Need to parse options here for use in Terminate
27  // Also, on PROOF, any KVDataAnalyser instance has to be passed to the workers
28  // via the TSelector input list.
29 
30  if (IsOptGiven("CombinedOutputFile")) {
31  fCombinedOutputFile = GetOpt("CombinedOutputFile");
32  }
33 #ifdef WITH_PROOF
34  else if (gProof) {
35  // when running with PROOF, if the user calls SetCombinedOutputFile()
36  // in InitAnalysis(), it will only be executed on the workers (in SlaveBegin()).
37  // therefore we call InitAnalysis() here, but deactivate CreateTreeFile(),
38  // AddTree() and AddHisto() in order to avoid interference with workers
39  fDisableCreateTreeFile = kTRUE;
40  if (gDataAnalyser) {
41  gDataAnalyser->RegisterUserClass(this);
42  gDataAnalyser->preInitAnalysis();
43  }
44  InitAnalysis(); //user initialisations for analysis
45  if (gDataAnalyser) gDataAnalyser->postInitAnalysis();
46  fDisableCreateTreeFile = kFALSE;
47  }
48 #endif
49  if (gDataAnalyser) {
50  if (GetInputList()) {
51  gDataAnalyser->AddJobDescriptionList(GetInputList());
52  //GetInputList()->ls();
53  }
54  }
55  if (IsOptGiven("AuxFiles")) {
56  SetUpAuxEventChain();
57  if (GetInputList()) GetInputList()->Add(fAuxChain);
58  }
59 }
60 
61 
62 
64 
66 {
67  if (GetInputList() && GetInputList()->FindObject("JobDescriptionList")) {
68  KVNameValueList* jdl = dynamic_cast<KVNameValueList*>(GetInputList()->FindObject("JobDescriptionList"));
69  if (jdl) {
70  KVDataAnalysisTask* task = nullptr;
71  if (jdl->HasParameter("DataRepository")) {
72  if (!gDataRepositoryManager) {
74  gDataRepositoryManager->Init();
75  }
76  gDataRepositoryManager->GetRepository(jdl->GetStringValue("DataRepository"))->cd();
77  gDataSetManager->GetDataSet(jdl->GetStringValue("DataSet"))->cd();
78  task = gDataSet->GetAnalysisTask(jdl->GetStringValue("AnalysisTask"));
79  }
80  else {
81  if (!gDataSetManager) {
82  gDataSetManager = new KVDataSetManager;
83  gDataSetManager->Init();
84  }
85  task = gDataSetManager->GetAnalysisTaskAny(jdl->GetStringValue("AnalysisTask"));
86  }
87  gDataAnalyser = KVDataAnalyser::GetAnalyser(task->GetDataAnalyser());
88  if (gDataSet && gDataAnalyser->InheritsFrom("KVDataSetAnalyser"))
89  dynamic_cast<KVDataSetAnalyser*>(gDataAnalyser)->SetDataSet(gDataSet);
90  gDataAnalyser->SetAnalysisTask(task);
91  gDataAnalyser->RegisterUserClass(this);
92  gDataAnalyser->SetProofMode((KVDataAnalyser::EProofMode)jdl->GetIntValue("PROOFMode"));
93  }
94  }
95 
96  ParseOptions();
97 
98  if (IsOptGiven("CombinedOutputFile")) {
99  fCombinedOutputFile = GetOpt("CombinedOutputFile");
100  Info("SlaveBegin", "Output file name = %s", fCombinedOutputFile.Data());
101  }
102 
103  // tell the data analyser who we are
104  if (gDataAnalyser) {
105  gDataAnalyser->RegisterUserClass(this);
106  gDataAnalyser->preInitAnalysis();
107  }
108  // make sure histo/tree creation are enabled
109  fDisableCreateTreeFile = kFALSE;
110  InitAnalysis(); //user initialisations for analysis
111  if (gDataAnalyser) gDataAnalyser->postInitAnalysis();
112 
113  if (IsOptGiven("AuxFiles")) {
114  // auxiliary files with PROOF
115  if (GetInputList()) {
116  fAuxChain = (TTree*)GetInputList()->FindObject(GetOpt("AuxTreeName"));
117  InitFriendTree(fAuxChain, GetOpt("AuxBranchName"));
118  }
119  }
120  Info("SlaveBegin", "fOutput->ls()");
121  GetOutputList()->ls();
122 }
123 
124 
125 
127 
129 {
130  if (gDataAnalyser && gDataAnalyser->AbortProcessingLoop()) {
131  // abort requested by external process
132  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);
133  return kFALSE;
134  }
135 
136  fTreeEntry = entry;
137 
138  if (gDataAnalyser && gDataAnalyser->CheckStatusUpdateInterval(fEventsRead))
139  gDataAnalyser->DoStatusUpdate(fEventsRead);
140 
141  GetEntry(entry);
142  if (gDataAnalyser) gDataAnalyser->preAnalysis();
143  fEventsRead++;
144  if (GetEvent()) {
145  SetAnalysisFrame();//let user define any necessary reference frames for particles
146  //apply particle selection criteria
147  if (fPartCond.IsSet()) {
148  for (auto& part : EventOKIterator(GetEvent())) {
149  part.SetIsOK(fPartCond.Test(part));
150  }
151  }
152 
153  // initialise global variables at first event
154  if (fFirstEvent) {
155  for (auto p : fGlobalVariables) dynamic_cast<KVGVList*>(p)->Init();
156  fFirstEvent = kFALSE;
157  }
158  RecalculateGlobalVariables();
159  }
160 
161  Bool_t ok_anal = kTRUE;
162  if (!fGlobalVariableAbortEventAnalysis) {
163  // if global variables are defined, events are only analysed if no global variables
164  // in the list have failed an event selection condition
165  ok_anal = Analysis(); //user analysis
166  if (gDataAnalyser) gDataAnalyser->postAnalysis();
167  }
168  CheckEndOfRun();
169 
170  return ok_anal;
171 }
172 
173 
174 
176 
178 {
179  if (AtEndOfRun()) {
180  Info("Process", "End of file reached after %lld events", fEventsRead);
181  if (gDataAnalyser) gDataAnalyser->preEndRun();
182  EndRun();
183  if (gDataAnalyser) gDataAnalyser->postEndRun();
184  fNotifyCalled = kFALSE;//Notify will be called when next file is opened (in TChain)
185  }
186 }
187 
188 
189 
191 
193 {
194  if (writeFile) {
195  auto sav_dir = gDirectory;//save current working directory
196 
197  writeFile->cd();
198  // loop over all histos and trees, writing them in the output file
199  if (lhisto.GetEntries()) {
200  lhisto.R__FOR_EACH(TH1, Write)();
201  }
202  if (ltree.GetEntries()) {
203  ltree.R__FOR_EACH(TTree, Write)(0, TObject::kOverwrite);
204  }
205  writeFile->Close();
206 #ifdef WITH_PROOF
207  if (gDataAnalyser->GetProofMode() != KVDataAnalyser::EProofMode::None) {
208  fOutput->Add(mergeFile);
209  }
210 #endif
211  sav_dir->cd();
212  }
213 }
214 
215 
216 
218 
220 {
221  TDatime now;
222  Info("Terminate", "Analysis ends at %s", now.AsString());
223 
224  if (gDataAnalyser) gDataAnalyser->preEndAnalysis();
225  EndAnalysis(); //user end of analysis routine
226  if (gDataAnalyser) gDataAnalyser->postEndAnalysis();
227 
228  if (GetInputList() && fAuxChain) GetInputList()->Remove(fAuxChain);
229  SafeDelete(fAuxChain);
230 }
231 
232 
233 
234 
235 
236 
246 
248 {
249  //Use this method if you change e.g. the particle selection criteria in your
250  //Analysis() method and want to recalculate the values of all global variables
251  //for your new selection.
252  //
253  //WARNING: the global variables are calculated automatically for you for each event
254  //before method Analysis() is called. In order for the correct particles to be included in
255  //this calculation, make sure that at the END of Analysis() you reset the selection
256  //criteria.
257 
258  fGlobalVariableAbortEventAnalysis = false;
259  for (auto p : fGlobalVariables) {
260  auto gvl = dynamic_cast<KVGVList*>(p);
261  gvl->CalculateGlobalVariables(GetEvent());
262  // check if a variable event selection failed
263  if (gvl->AbortEventAnalysis()) {
264  fGlobalVariableAbortEventAnalysis = true;
265  return;
266  }
267  }
268 }
269 
270 
271 
272 
276 
278 {
279  // Declare a histogram to be used in analysis.
280  // This method must be called when using PROOF.
281 
282  if (fDisableCreateTreeFile) return;
283 
284  lhisto.Add(histo);
285 
286  if (writeFile) histo->SetDirectory(writeFile); // if output file is initialized, associate histo with it
287  else create_output_file();// try to initialize output file
288 }
289 
290 
291 
295 
297 {
298  // Declare a TTree to be used in analysis.
299  // This method must be called when using PROOF.
300 
301  if (fDisableCreateTreeFile) return;
302 
303  tree->SetAutoSave();
304  ltree.Add(tree);
305 
306  if (writeFile) tree->SetDirectory(writeFile); // if output file is initialized, associate tree with it
307  else create_output_file();// try to initialize output file
308 }
309 
310 
311 
316 
318 {
319  // Create the file for saving histos and/or trees created during analysis.
320  //
321  // The name of the file must first be set using SetJobOutputFileName()
322 
323  if (fCombinedOutputFile == "") return;
324 
325  auto sav_dir = gDirectory;//save current working directory
326  if (gDataAnalyser->GetProofMode() == KVDataAnalyser::EProofMode::None) {
327  // Analysis running in 'normal' (non-PROOF) mode
328  writeFile = TFile::Open(fCombinedOutputFile, "RECREATE");
329  }
330 #ifdef WITH_PROOF
331  else {
332  // Analysis running with PROOF(Lite)
333  mergeFile = new TProofOutputFile(fCombinedOutputFile, "M");
334  mergeFile->SetOutputFileName(fCombinedOutputFile);
335  writeFile = mergeFile->OpenFile("RECREATE");
336  if (writeFile && writeFile->IsZombie()) SafeDelete(writeFile);
337  }
338 #endif
339  sav_dir->cd();//return to previous working directory
340 
341  if (!writeFile) {
342  TString amsg = TString::Format("%s::create_output_file: could not create output ROOT file '%s'!",
343  ClassName(), fCombinedOutputFile.Data());
344  Abort(amsg, kAbortProcess);
345  }
346 
347  // any previously declared histograms or trees must now be associated with the output file
348  if (lhisto.GetEntries()) {
349  lhisto.R__FOR_EACH(TH1, SetDirectory)(writeFile);
350  }
351  if (ltree.GetEntries()) {
352  ltree.R__FOR_EACH(TTree, SetDirectory)(writeFile);
353  }
354 }
355 
356 
357 
359 
361 {
362  Deprecate("Calling this method is no longer required, and any filename given will be ignored."
363  " Call SetJobOutputFileName() to define the output filename.");
364  return kTRUE;
365 }
366 
367 
368 
369 
370 
371 
373 
374 void KVEventSelector::FillHisto(const Char_t* histo_name, Double_t one, Double_t two, Double_t three, Double_t four)
375 {
376  TH1* h1 = 0;
377  if ((h1 = GetHisto(histo_name))) {
378  if (h1->InheritsFrom("TH3"))
379  FillTH3((TH3*)h1, one, two, three, four);
380  else if (h1->InheritsFrom("TProfile2D"))
381  FillTProfile2D((TProfile2D*)h1, one, two, three, four);
382  else if (h1->InheritsFrom("TH2"))
383  FillTH2((TH2*)h1, one, two, three);
384  else if (h1->InheritsFrom("TProfile"))
385  FillTProfile((TProfile*)h1, one, two, three);
386  else if (h1->InheritsFrom("TH1"))
387  FillTH1(h1, one, two);
388  else
389  Warning("FillHisto", "%s -> Classe non prevue ...", lhisto.FindObject(histo_name)->ClassName());
390  }
391  else {
392  Warning("FillHisto", "%s introuvable", histo_name);
393  }
394 }
395 
396 
397 
399 
400 void KVEventSelector::FillHisto(const Char_t* histo_name, const Char_t* label, Double_t weight)
401 {
402  TH1* h1 = 0;
403  if ((h1 = GetHisto(histo_name))) {
404  h1->Fill(label, weight);
405  }
406  else {
407  Warning("FillHisto", "%s introuvable", histo_name);
408  }
409 }
410 
411 
412 
413 
415 
417 {
418 
419  h1->Fill(one, two);
420 
421 }
422 
423 
424 
425 
427 
429 {
430 
431  h1->Fill(one, two, three);
432 
433 }
434 
435 
436 
437 
439 
441 {
442 
443  h2->Fill(one, two, three);
444 
445 }
446 
447 
448 
449 
451 
453 {
454 
455  h2->Fill(one, two, three, four);
456 }
457 
458 
459 
460 
462 
464 {
465 
466  h3->Fill(one, two, three, four);
467 }
468 
469 
470 
480 
482 {
483  // Called by SlaveBegin() when user gives the following options:
484  //
485  //~~~~~~~~~~~~~~~~
486  // AuxFiles: list of files containing "friend" TTrees to be made available during analysis
487  // AuxDir: directory in which to find AuxFiles
488  // AuxTreeName: name of tree in AuxFiles containing KVEvent objects
489  // AuxBranchName: name of branch in AuxFiles containing KVEvent objects
490  //~~~~~~~~~~~~~~~~
491 
492  if (!IsOptGiven("AuxDir") || !IsOptGiven("AuxTreeName") || !IsOptGiven("AuxBranchName")) {
493  Error("SetUpAuxEventChain", "if AuxFiles option given, you must define AuxDir, AuxTreeName and AuxBranchName");
494  return;
495  }
496  KVString filelist = GetOpt("AuxFiles");
497  KVString filedir = GetOpt("AuxDir");
498  if (!filedir.EndsWith("/")) filedir += "/";
499  TChain* auxchain = new TChain(GetOpt("AuxTreeName"));
500  filelist.Begin("|");
501  while (!filelist.End()) {
502  KVString path = filedir + filelist.Next();
503  auxchain->Add(path);
504  }
505  InitFriendTree(auxchain, GetOpt("AuxBranchName"));
506 }
507 
508 
509 
511 
512 void KVEventSelector::FillTree(const Char_t* tree_name)
513 {
514  if (!strcmp(tree_name, "")) {
515  ltree.R__FOR_EACH(TTree, Fill)();
516  }
517  else {
518  TTree* tt = 0;
519  if ((tt = GetTree(tree_name))) {
520  tt->Fill();
521  }
522  else {
523  Warning("FillTree", "%s unknown", tree_name);
524  }
525  }
526 }
527 
528 
529 
530 
531 
542 
544 {
545  // Analyse comma-separated list of options given to TTree::Process
546  // and store all `"option=value"` pairs in fOptionList.
547  // Options can then be accessed using IsOptGiven(), GetOptString(), etc.
548  //
549  //~~~~~~~~~~~~~~~
550  // BranchName=xxxx : change name of branch in TTree containing data
551  // EventsReadInterval=N: print "+++ 12345 events processed +++" every N events
552  //~~~~~~~~~~~~~~~
553  //
554 
555  fOptionList.ParseOptions(GetOption());
556 
557  // check for branch name
558  if (IsOptGiven("BranchName")) SetBranchName(GetOpt("BranchName"));
559  // check for events read interval
560  if (IsOptGiven("EventsReadInterval")) SetEventsReadInterval(GetOpt("EventsReadInterval").Atoi());
561 }
562 
563 
564 
566 
568 {
569  Event = nullptr;
570  // Set branch addresses and branch pointers
571  if (!tree) return;
572  fChain = tree;
573  fChain->SetMakeClass(1);
574  // When using PROOF, need to set tree pointer in KVDataAnalyser
575  if (gDataAnalyser->GetProofMode() != KVDataAnalyser::EProofMode::None) {
576  gDataAnalyser->SetAnalysedTree(tree);
577  }
578 
579  if (strcmp(GetBranchName(), "") && fChain->GetBranch(GetBranchName())) {
580  Info("Init", "Analysing data in branch : %s", GetBranchName());
581  fChain->SetBranchAddress(GetBranchName(), &Event, &b_Event);
582  }
583  else {
584  Error("Init", "Failed to link KVEvent object with a branch. Expected branch name=%s",
585  GetBranchName());
586  }
587  //user additional branches addressing
588  SetAdditionalBranchAddress();
589  fEventsRead = 0;
590 
591 }
592 
593 
594 
610 
612 {
613  // @param tree
614  // @param branchname
615  //
616  // Set up a "friend" TTree/TChain containing KVEvent-derived objects in branch 'branchname'
617  // N.B. this is not a "friend" in the sense of TTree::AddFriend, the main TTree and the
618  // "friend" TTree can have different numbers of entries
619  //
620  // After calling this method at the beginning of the analysis, you can
621  // access any of the events stored in the "friend" by doing:
622  //
623  //~~~{.cpp}
624  // GetFriendTreeEntry(entry_number);
625  // KVEvent* friend_event = GetFriendEvent();
626  //~~~
627 
628  AuxEvent = 0;
629  fAuxChain = tree;
630  fAuxChain->SetBranchAddress(branchname, &AuxEvent);
631  fAuxChain->Print();
632  fAuxChain->GetEntry(0);
633  fAuxChain->GetTree()->GetEntry(0);
634 }
635 
636 
637 
639 
641 {
642  if (fNotifyCalled) return kTRUE; // avoid multiple calls at beginning of analysis
643  fNotifyCalled = kTRUE;
644 
645  Info("Notify", "Beginning analysis of file %s (%lld events)", fChain->GetCurrentFile()->GetName(), fChain->GetTree()->GetEntries());
646 
647  if (gDataAnalyser) gDataAnalyser->preInitRun();
648  InitRun(); //user initialisations for run
649  if (gDataAnalyser) gDataAnalyser->postInitRun();
650 
652 
653  return kTRUE;
654 }
655 
656 
#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
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:617
General purpose analysis base class for TTree containing KVEvent objects.
Bool_t Process(Long64_t entry) override
void FillTProfile2D(TProfile2D *h2, Double_t one, Double_t two, Double_t three, Double_t four)
void InitFriendTree(TTree *tree, const TString &branchname)
void Init(TTree *tree) override
virtual void CheckEndOfRun()
void FillTH2(TH2 *h2, Double_t one, Double_t two, Double_t three)
Bool_t Notify() override
Bool_t CreateTreeFile(const Char_t *filename="")
void add_histo(TH1 *histo)
output file for trees and histos
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 SlaveTerminate() override
void FillTH1(TH1 *h1, Double_t one, Double_t two)
void add_tree(TTree *tree)
void SlaveBegin(TTree *tree) override
void RecalculateGlobalVariables()
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="")
void Terminate() override
#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)