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 "KVDataSetRepository.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 
177 void KVEventSelector::CheckEndOfRun()
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 (GetHistoList().GetEntries()) {
200  GetHistoList().R__FOR_EACH(TH1, Write)();
201  }
202  if (GetTreeList().GetEntries()) {
203  GetTreeList().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 
239 
240 void KVEventSelector::RecalculateGlobalVariables()
241 {
242  // Calculates all global variables in all global variable lists
243 
244  fGlobalVariableAbortEventAnalysis = false;
245  for (auto p : fGlobalVariables) {
246  auto gvl = dynamic_cast<KVGVList*>(p);
247  gvl->CalculateGlobalVariables(GetEvent());
248  // check if a variable event selection failed
249  if (gvl->AbortEventAnalysis()) {
250  fGlobalVariableAbortEventAnalysis = true;
251  return;
252  }
253  }
254 }
255 
256 
257 
258 
262 
263 void KVEventSelector::add_histo(TH1* histo)
264 {
265  // Declare a histogram to be used in analysis.
266  // This method must be called when using PROOF.
267 
268  if (fDisableCreateTreeFile) return;
269 
270  GetHistoList().Add(histo);
271 
272  if (writeFile) histo->SetDirectory(writeFile); // if output file is initialized, associate histo with it
273  else create_output_file();// try to initialize output file
274 }
275 
276 
277 
281 
282 void KVEventSelector::add_tree(TTree* tree)
283 {
284  // Declare a TTree to be used in analysis.
285  // This method must be called when using PROOF.
286 
287  if (fDisableCreateTreeFile) return;
288 
289  tree->SetAutoSave();
290  GetTreeList().Add(tree);
291 
292  if (writeFile) tree->SetDirectory(writeFile); // if output file is initialized, associate tree with it
293  else create_output_file();// try to initialize output file
294 }
295 
296 
297 
302 
303 void KVEventSelector::create_output_file()
304 {
305  // Create the file for saving histos and/or trees created during analysis.
306  //
307  // The name of the file must first be set using SetJobOutputFileName()
308 
309  if (fCombinedOutputFile == "") return;
310 
311  auto sav_dir = gDirectory;//save current working directory
312  if (gDataAnalyser->GetProofMode() == KVDataAnalyser::EProofMode::None) {
313  // Analysis running in 'normal' (non-PROOF) mode
314  writeFile = TFile::Open(fCombinedOutputFile, "RECREATE");
315  }
316 #ifdef WITH_PROOF
317  else {
318  // Analysis running with PROOF(Lite)
319  mergeFile = new TProofOutputFile(fCombinedOutputFile, "M");
320  mergeFile->SetOutputFileName(fCombinedOutputFile);
321  writeFile = mergeFile->OpenFile("RECREATE");
322  if (writeFile && writeFile->IsZombie()) SafeDelete(writeFile);
323  }
324 #endif
325  sav_dir->cd();//return to previous working directory
326 
327  if (!writeFile) {
328  TString amsg = TString::Format("%s::create_output_file: could not create output ROOT file '%s'!",
329  ClassName(), fCombinedOutputFile.Data());
330  Abort(amsg, kAbortProcess);
331  }
332 
333  // any previously declared histograms or trees must now be associated with the output file
334  if (GetHistoList().GetEntries()) {
335  GetHistoList().R__FOR_EACH(TH1, SetDirectory)(writeFile);
336  }
337  if (GetTreeList().GetEntries()) {
338  GetTreeList().R__FOR_EACH(TTree, SetDirectory)(writeFile);
339  }
340 }
341 
342 
343 
353 
354 void KVEventSelector::SetUpAuxEventChain()
355 {
356  // Called by SlaveBegin() when user gives the following options:
357  //
358  //~~~~~~~~~~~~~~~~
359  // AuxFiles: list of files containing "friend" TTrees to be made available during analysis
360  // AuxDir: directory in which to find AuxFiles
361  // AuxTreeName: name of tree in AuxFiles containing KVEvent objects
362  // AuxBranchName: name of branch in AuxFiles containing KVEvent objects
363  //~~~~~~~~~~~~~~~~
364 
365  if (!IsOptGiven("AuxDir") || !IsOptGiven("AuxTreeName") || !IsOptGiven("AuxBranchName")) {
366  KVError::Error(this, "SetUpAuxEventChain", "if AuxFiles option given, you must define AuxDir, AuxTreeName and AuxBranchName");
367  return;
368  }
369  KVString filelist = GetOpt("AuxFiles");
370  KVString filedir = GetOpt("AuxDir");
371  if (!filedir.EndsWith("/")) filedir += "/";
372  TChain* auxchain = new TChain(GetOpt("AuxTreeName"));
373  filelist.Begin("|");
374  while (!filelist.End()) {
375  KVString path = filedir + filelist.Next();
376  auxchain->Add(path);
377  }
378  InitFriendTree(auxchain, GetOpt("AuxBranchName"));
379 }
380 
381 
382 
393 
394 void KVEventSelector::ParseOptions()
395 {
396  // Analyse comma-separated list of options given to TTree::Process
397  // and store all `"option=value"` pairs in fOptionList.
398  // Options can then be accessed using IsOptGiven(), GetOptString(), etc.
399  //
400  //~~~~~~~~~~~~~~~
401  // BranchName=xxxx : change name of branch in TTree containing data
402  // EventsReadInterval=N: print "+++ 12345 events processed +++" every N events
403  //~~~~~~~~~~~~~~~
404  //
405 
406  fOptionList.ParseOptions(GetOption());
407 
408  // check for branch name
409  if (IsOptGiven("BranchName")) SetBranchName(GetOpt("BranchName"));
410  // check for events read interval
411  if (IsOptGiven("EventsReadInterval")) SetEventsReadInterval(GetOpt("EventsReadInterval").Atoi());
412 }
413 
414 
415 
417 
419 {
420  Event = nullptr;
421  // Set branch addresses and branch pointers
422  if (!tree) return;
423  fChain = tree;
424  fChain->SetMakeClass(1);
425  // When using PROOF, need to set tree pointer in KVDataAnalyser
426  if (gDataAnalyser->GetProofMode() != KVDataAnalyser::EProofMode::None) {
427  gDataAnalyser->SetAnalysedTree(tree);
428  }
429 
430  if (strcmp(GetBranchName(), "") && fChain->GetBranch(GetBranchName())) {
431  Info("Init", "Analysing data in branch : %s", GetBranchName());
432  fChain->SetBranchAddress(GetBranchName(), &Event, &b_Event);
433  }
434  else {
435  KVError::Error(this, "Init", "Failed to link KVEvent object with a branch. Expected branch name=%s",
436  GetBranchName());
437  }
438  //user additional branches addressing
439  SetAdditionalBranchAddress();
440  fEventsRead = 0;
441 
442 }
443 
444 
445 
461 
462 void KVEventSelector::InitFriendTree(TTree* tree, const TString& branchname)
463 {
464  // @param tree
465  // @param branchname
466  //
467  // Set up a "friend" TTree/TChain containing KVEvent-derived objects in branch 'branchname'
468  // N.B. this is not a "friend" in the sense of TTree::AddFriend, the main TTree and the
469  // "friend" TTree can have different numbers of entries
470  //
471  // After calling this method at the beginning of the analysis, you can
472  // access any of the events stored in the "friend" by doing:
473  //
474  //~~~{.cpp}
475  // GetFriendTreeEntry(entry_number);
476  // KVEvent* friend_event = GetFriendEvent();
477  //~~~
478 
479  AuxEvent = 0;
480  fAuxChain = tree;
481  fAuxChain->SetBranchAddress(branchname, &AuxEvent);
482  fAuxChain->Print();
483  fAuxChain->GetEntry(0);
484  fAuxChain->GetTree()->GetEntry(0);
485 }
486 
487 
488 
490 
492 {
493  if (fNotifyCalled) return kTRUE; // avoid multiple calls at beginning of analysis
494  fNotifyCalled = kTRUE;
495 
496  Info("Notify", "Beginning analysis of file %s (%lld events)", fChain->GetCurrentFile()->GetName(), fChain->GetTree()->GetEntries());
497 
498  if (gDataAnalyser) gDataAnalyser->preInitRun();
499  InitRun(); //user initialisations for run
500  if (gDataAnalyser) gDataAnalyser->postInitRun();
501 
503 
504  return kTRUE;
505 }
506 
507 
#define SafeDelete(p)
bool Bool_t
constexpr Bool_t kFALSE
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.
KVDataSetRepository * GetRepository(const TString &name) const
Pilots user analysis of experimental data.
Manage all datasets contained in a given data repository.
Bool_t Init(KVDataSetRepository *=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:584
General purpose analysis base class for TTree containing KVEvent objects.
Bool_t Process(Long64_t entry) override
void Init(TTree *tree) override
Bool_t Notify() override
void SlaveTerminate() override
void SlaveBegin(TTree *tree) override
void Terminate() override
Manage a list of global variables.
Definition: KVGVList.h:225
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 Bool_t InheritsFrom(const char *classname) const
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)
void Error(UserClass p, const char *location, const char *va_(fmt),...)
Definition: KVError.h:116
void Init()
void Info(const char *location, const char *fmt,...)
ClassImp(TPyArg)