HighLAND
AnalysisLoop.cxx
1 #include "AnalysisLoop.hxx"
2 #include <TClonesArray.h>
3 #include <unistd.h>
4 #include <iostream>
5 #include <sstream>
6 #include <stdlib.h>
7 #include "Parameters.hxx"
8 #include "Header.hxx"
9 #include "DocStringManager.hxx"
10 //#include "AnalysisUtils.hxx"
11 //#include "GeometryManager.hxx"
12 #include "MultiThread.hxx"
13 #include "VersionManager.hxx"
14 
15 #include "ZeroToyMaker.hxx"
16 
17 #include <sys/time.h>
18 
19 // save all trees every 5000 entries
20 const int NENTRIES_TREESAVE=5000;
21 
22 SelectionManager* _selMan=NULL;
23 
24 //********************************************************************
25 AnalysisLoop::AnalysisLoop(AnalysisAlgorithm* ana, int argc, char *argv[]){
26 //********************************************************************
27 
28  _ana = ana;
29 
30  std::string programName = argv[0];
31  std::string paramFile = "";
32 
33  _entry_nmax = 0;
34  _entry_imin = 0;
35  _entry_count = 0;
36  _outputFileName = "";
37  _inputFileName = "";
38  _inputSkimFileName = "";
39  _cosmicMode = false;
40  _versionCheck = true;
41  _fillTrees=true;
42  bool logMemory = false;
43 
44  for (;;) {
45  int c = getopt(argc, argv, "crvmn:e:o:p:s:");
46  if (c < 0)
47  break;
48  switch (c) {
49  case 'c': {
50  _cosmicMode = true;
51  break;
52  }
53  case 'v': {
54  _versionCheck = false;
55  break;
56  }
57  case 'r': {
58  _fillTrees = false;
59  break;
60  }
61  case 'm': {
62  logMemory = true;
63  break;
64  }
65  case 'n': {
66  std::istringstream tmp(optarg);
67  tmp >> _entry_nmax;
68  break;
69  }
70  case 'o': {
71  _outputFileName = optarg;
72  break;
73  }
74  case 'e': {
75  _inputSkimFileName = optarg;
76  break;
77  }
78  case 'p': {
79  paramFile = optarg;
80  break;
81  }
82  case 's': {
83  std::istringstream tmp(optarg);
84  tmp >> _entry_imin;
85  break;
86  }
87  default: {
88  PrintUsage(programName);
89  }
90  }
91  }
92 
93  // Check that an output file was specified
94  if (_outputFileName == "") {
95  std::cerr << "ERROR: No output file" << std::endl << std::endl;
96  PrintUsage(programName);
97  }
98 
99  // Check that there is an input file.
100  if (argc <= optind) {
101  std::cerr << "ERROR: No input file" << std::endl << std::endl;
102  PrintUsage(programName);
103  } else if (argc != optind + 1) {
104  std::cerr << "ERROR: Only one input file may be specified. To process multiple ROOT files, " << std::endl
105  << " list them in a text file, and specify that text file as the input." << std::endl << std::endl;
106  PrintUsage(programName);
107  }
108 
109  _inputFileName = argv[optind++];
110 
111  // Set up the parameter override file if it was specified
112  if (paramFile != "") {
113  ND::params().ReadParamOverrideFile(paramFile);
114  }
115 
116  // Read the parameters files following the package hierarchy
117  // first the top level package. Set the parameters as fixed
118  // ND::params().LoadParametersFiles(anaUtils::GetPackageHierarchy(), true);
119 
120  // Make sure no parameters have been accessed yet
122 
123  _weightSyst = NULL;
124 
125  _enableTruthTree = true;
126  _memory.Enable(logMemory);
127  /*
128  // Add package versions
129  ND::versioning().AddPackage("psychePolicy", anaUtils::GetSoftwareVersionFromPath((std::string)getenv("PSYCHEPOLICYROOT")));
130  ND::versioning().AddPackage("psycheEventModel", anaUtils::GetSoftwareVersionFromPath((std::string)getenv("PSYCHEEVENTMODELROOT")));
131  ND::versioning().AddPackage("psycheCore", anaUtils::GetSoftwareVersionFromPath((std::string)getenv("PSYCHECOREROOT")));
132  ND::versioning().AddPackage("psycheUtils", anaUtils::GetSoftwareVersionFromPath((std::string)getenv("PSYCHEUTILSROOT")));
133  ND::versioning().AddPackage("psycheND280Utils", anaUtils::GetSoftwareVersionFromPath((std::string)getenv("PSYCHEND280UTILSROOT")));
134  ND::versioning().AddPackage("psycheIO", anaUtils::GetSoftwareVersionFromPath((std::string)getenv("PSYCHEIOROOT")));
135  ND::versioning().AddPackage("psycheSelections", anaUtils::GetSoftwareVersionFromPath((std::string)getenv("PSYCHESELECTIONSROOT")));
136  ND::versioning().AddPackage("psycheSystematics", anaUtils::GetSoftwareVersionFromPath((std::string)getenv("PSYCHESYSTEMATICSROOT")));
137  ND::versioning().AddPackage("highlandEventModel", anaUtils::GetSoftwareVersionFromPath((std::string)getenv("HIGHLANDEVENTMODELROOT")));
138  ND::versioning().AddPackage("highlandTools", anaUtils::GetSoftwareVersionFromPath((std::string)getenv("HIGHLANDTOOLSROOT")));
139  ND::versioning().AddPackage("highlandCore", anaUtils::GetSoftwareVersionFromPath((std::string)getenv("HIGHLANDCOREROOT")));
140  ND::versioning().AddPackage("highlandCorrections", anaUtils::GetSoftwareVersionFromPath((std::string)getenv("HIGHLANDCORRECTIONSROOT")));
141  ND::versioning().AddPackage("highlandIO", anaUtils::GetSoftwareVersionFromPath((std::string)getenv("HIGHLANDIOROOT")));
142  */
143 #ifdef MULTITHREAD
144  std::cout << "For runnning in highland2 you must comment out the line #define MULTITHREAD psycheCore/vXrY/srx/MultiThread.hxx and recompile everything !!!" << std::endl;
145  exit(0);
146 #endif
147 
148  _selMan = new SelectionManager();
149 }
150 
151 //********************************************************************
153 //********************************************************************
154 
155  // Define the InputConverters. This must be called before the InputManager is initialized
156  ana().SetAnalysisPoint(AnalysisAlgorithm::kDefineInputConverters);
157  ana().DefineInputConverters();
158 
159  // Define Productions
160  ana().SetAnalysisPoint(AnalysisAlgorithm::kDefineProductions);
161  ana().DefineProductions();
162 
163  // Set the skim file name
164  anaUtils::skimFileName = _inputSkimFileName;
165 
166  // Initialize the InputManager by specifying the input type and the input file
167  if (!ana().input().Initialize(_inputFileName,_inputFileType, _cosmicMode)) return false;
168 
169  // Tell the AnalysisAlgorithm to perform version checking to make sure the sofware version and the input file match each other
171 
172  // Initialize the User Analysis Algorithm. It can overwride the production via parameters file in baseAnalysis
173  ana().SetAnalysisPoint(AnalysisAlgorithm::kInitialize);
174  if (!ana().Initialize()) return false;
175 
176  // This will take care of data/MC differences in detector volumes definitions
177  // Should be applied after the version has been defined
178  // TODO. Moved temporarily to baseAnalysis.cxx to avoid dependency on psycheND280Utils
179  // ND::hgman().InitializeGeometry(ana().input().GetIsMC());
180 
181  // Initialise the Output Manager.
182  ana().output().Initialize();
183 
184  // Open the output file
185  if (_fillTrees)
186  if (!ana().output().OpenOutputFile(_outputFileName)) return false;
187 
188  // if (ana().input().GetChain() == 0) return;
189 
190  // Define the Corrections
192 
193  // Define the selection (s)
194  ana().SetAnalysisPoint(AnalysisAlgorithm::kDefineSelections);
195  ana().DefineSelections();
196 
197  // Initialize the Selections (create the ToyBox)
198  ana().sel().CreateToyBoxArray(_entry_nmax);
199 
200  // Define the Systematics
201  ana().SetAnalysisPoint(AnalysisAlgorithm::kDefineSystematics);
202  ana().DefineSystematics();
203 
204  // Define the configurations
206 
207  // Define the micro tree variables
208  if (_fillTrees)
210 
211  // Define the "truth tree" variables
213  DefineTruthTree();
214 
215  // Create and fill the "config" tree with a single entry
216  if (_fillTrees)
217  FillConfigTree();
218 
219  // Fill allways the event summary even when the selection is not passed
220  ana().sel().SetForceFillEventSummary(true);
221 
222  return true;
223 }
224 
225 //********************************************************************
227 //********************************************************************
228 
229  // Initialize the OutputManager (TODO)
230  if (_fillTrees)
231  ana().output().InitializeEntry();
232 
233  // Initialize the truth tree (which does not belong to any configuration)
234  if (_fillTrees)
235  ana().output().InitializeTree(OutputManager::truth);
236 
237  // To compute the entry increment
238  Int_t entry0 = _entry;
239 
240  // Fill the spill structure for the current spill from the input tree
241  bool spillOK = ana().input().LoadSpill(_entry);
242 
243  // To compute the entry increment
244  Int_t entry1 = _entry;
245 
246  // Increment the number of entries run so far
247  _entry_count += entry1-entry0;
248 
249  // Dump info about number of entries run
250  if (_entry_count%1000==0 || _entry_count == _entry_nmax)
251  std::cout << "entry: " << _entry_count << " of " << _entry_nmax << " (" << (100*_entry_count/_entry_nmax) << "%) --> " << _entry << std::endl;
252 
253  // return if the read spill is not OK
254  if (!spillOK) return false;
255 
256  // Apply Corrections. This will affect all configurations
257  ana().corr().ApplyCorrections(ana().input().GetCorrectedSpill());
258 
259  // Create a clone of the Corrected Spill
260  ana().input().MakeFinalSpill();
261 
262  // Record the POT for this spill
263  ana().input().IncrementPOTBySpill();
264 
265  // initialize the spill in the User Analysis Algorithm
266  ana().SetAnalysisPoint(AnalysisAlgorithm::kInitializeSpill);
267  if (!ana().InitializeSpill()) return false;
268 
269  return true;
270 }
271 
272 //********************************************************************
274 //********************************************************************
275 
276  // Create the event from the spill and the current bunch (needed by psyche packages)
277  _event = ana().MakeEvent();
278  ana().SetEvent(_event);
279 
280  // Create and fill the EventBox for the current event
281  ana().sel().InitializeEvent(*_event);
282 
283  // Initialize the Bunch in the User Analysis Algorithm
284  ana().SetAnalysisPoint(AnalysisAlgorithm::kInitializeBunch);
285  ana().InitializeBunch();
286 }
287 
288 //********************************************************************
290 //********************************************************************
291 
292  // Initialize the tree associated to the current configuration (put all variables to the default value)
293  if (_fillTrees)
294  ana().output().InitializeTree(ana().output().GetCurrentTree(), ana().GetInitializeTrees());
295 
296  if (ana().evar().HasEventVariations()){
297  // Enable the appropriate EventVariations for this configuration
298  ana().evar().DisableAllEventVariations();
299  ana().evar().EnableEventVariations(ana().conf().GetEnabledEventVariations());
300 
301  // Create the SystBox array (only the first time it is called for each EventVariation)
302  ana().evar().Initialize(_entry_nmax);
303 
304  // Initialize The SystBox for EventVariations
305  ana().evar().InitializeEvent(ana().sel(),*_event);
306  }
307 
308  if (ana().eweight().HasEventWeights()){
309  // Enable the appropriate EventWeights for this configuration
310  ana().eweight().DisableAllEventWeights();
311  ana().eweight().EnableEventWeights(ana().conf().GetEnabledEventWeights());
312 
313  // Create an array to store the systematics weights. (TODO. Is it faster to just resize the existing array ?)
314  _nWeightSyst= ana().eweight().GetNEnabledEventWeights();
315  anaUtils::CreateArray(_weightSyst, _nWeightSyst);
316 
317  // Create the SystBox array (only the first time it is called for each EventWeight)
318  ana().eweight().Initialize(ana().sel(),_entry_nmax);
319 
320  // Initialize The SystBox for variation systematics
321  ana().eweight().InitializeEvent(ana().sel(),*_event);
322  }
323 
324  // Initialize the Configuration in the User Analysis Algorithm
325  ana().InitializeConfiguration();
326 }
327 
328 //********************************************************************
330 //********************************************************************
331 
332  // Apply variation systematics. Only for MC. TODO: now that this is not only a systematic it could be also used for data
333  if (_event->GetIsMC() && ana().evar().GetNEnabledEventVariations()>0){
334 
335  // Get the current Toy Experiment
336  ToyExperiment* toy = ana().conf().GetCurrentConfiguration()->GetToyMaker().GetToyExperiment(ana().conf().GetToyIndex());
337 
338  // Apply systematic variations for systematic error propagation
339  ana().evar().ApplyEventVariations(*toy, *_event);
340  }
341 
342  // Initialize this toy experiment for the user Analysis Algorithm
343  ana().SetAnalysisPoint(AnalysisAlgorithm::kInitializeToy);
344  ana().InitializeToy();
345 }
346 
347 //********************************************************************
348 void AnalysisLoop::InitializeSelection(const SelectionBase& selec){
349 //********************************************************************
350 
351  // initialize selection for the user analysis. TODO: currently not used by any analysis
352  ana().SetAnalysisPoint(AnalysisAlgorithm::kInitializeSelection);
353  ana().InitializeSelection(selec);
354 }
355 
356 //********************************************************************
358 //********************************************************************
359 
360  /// Compute the weight for this selection by applying the systematic weights. Only for MC when any of the weight systematics is enabled,
361  // and when the selection was passed. TODO: now that this is not only a systematic it could be also used for data
362  if (_toy_passed && _event->GetIsMC() && ana().eweight().GetNEnabledEventWeights()>0){
363  // Get the current Toy Experiment
364  ToyExperiment* toy = ana().conf().GetCurrentConfiguration()->GetToyMaker().GetToyExperiment(ana().conf().GetToyIndex());
365  // Apply the relevant weight systematics for the current selection. Internally loops over branches in the selection and compute the weights only
366  // for the succesfull branches
367  ana().eweight().ComputeEventWeights(selec,*toy, *_event, selec.GetPreviousToyBox(*_event), _weightSyst);
368  }
369 
370  // finalize selection for the user analysis. TODO: currently not used by any analysis.
371  ana().SetAnalysisPoint(AnalysisAlgorithm::kFinalizeSelection);
372  ana().FinalizeSelection(selec);
373 }
374 
375 //********************************************************************
377 //********************************************************************
378 
379  // Finalize the Toy Experiment for the AnalysisAlgorithm (mandatory)
380  ana().FinalizeToyBase();
381 
382  // Finalize the Toy Experiment for the User AnalysisAlgorithm (optional). TODO: currently not used by any analysis
383  // ana().FinalizeToy();
384 
385  // Save the toy experiment weight such that it can be properly normalized after all toys have been run
386  // ana().output().AddToyWeight(1.);
387 
388  // The toy experiment dependent micro-tree variables are filled here
389  // Conditions inside method
391 
392  // break the toy loop when the the first toy does not reach a minimum accum level for any of the selections
393  // TODO: when running several selections we should stop running a given selection when the minimum accum level for that selection
394  // is not reached
395  if (!ana().sel().PreSelectionPassed(*_event)) return false;
396 
397  // Undo all variationSystematics variations at the end of this toy experiment. TODO: we should reset undo all systematics in the same method to
398  // avoid looping several times over the same objects
399  if (_event->GetIsMC() && ana().evar().GetNEnabledEventVariations()>0){
400  if (ana().evar().UndoEventVariations(*_event))
401  ana().input().ResetSpillToCorrected();
402  }
403 
404  // When false is returned the loop over toys is broken
405  return true;
406 }
407 
408 //********************************************************************
410 //********************************************************************
411 
412  // Delete the array for systematics weights. Will create a new one in InitializeConfiguration (TODO)
413  if (_weightSyst) delete [] _weightSyst;
414  _weightSyst = NULL;
415 
416  // Delete the SystBox for the current event
417  if (_event->GetIsMC() && ana().evar().GetNEnabledEventVariations()>0)
418  ana().evar().FinalizeEvent(*_event);
419 
420  // Delete the SystBox for the current event
421  if (_event->GetIsMC() && ana().eweight().GetNEnabledEventWeights()>0)
422  ana().eweight().FinalizeEvent(*_event);
423 
424  // Finalize the configuration for the User AnalysisAlgorithm
425  ana().SetAnalysisPoint(AnalysisAlgorithm::kFinalizeConfiguration);
426  if (!ana().FinalizeConfiguration()) return false;
427 
428  // When requested fill the tree only for events that pass the selection at least for one of the toys
429  // conf_passed is true when at least one of the toys passes the selection
430  if (!_fillTrees || (!_conf_passed && ana().GetFillSuccessOnly())) return true;
431 
432  // Only fill the tree for events that pass a given cut
433  if (!ana().CheckAccumLevelToSave()) return false;
434 
435  // Reset the categories for the current track
436  ana().cat().ResetCurrentCategories();
437 
438  // Fill categories for color drawing for the current track
439  ana().SetAnalysisPoint(AnalysisAlgorithm::kFillCategories);
440  ana().FillCategories();
441 
442  // Fill all micro-trees (main trees for analysis)
443  FillMicroTrees();
444 
445  return true;
446 }
447 
448 //********************************************************************
450 //********************************************************************
451 
452  // The PreviousToyBox must be Reset after processing one event (all toys)
453  ana().sel().FinalizeEvent(*_event);
454 
455  // Derived classes
456  ana().SetAnalysisPoint(AnalysisAlgorithm::kFinalizeBunch);
457  ana().FinalizeBunch();
458 
459  // Delete the event
460  delete _event;
461 }
462 
463 //********************************************************************
465 //********************************************************************
466 
467  if (_fillTrees){
468 
469  // Fill only the truth tree
470  ana().output().SetFillSingleTree(OutputManager::truth);
471  ana().output().SetCurrentTree(OutputManager::truth);
472 
473  // call the derived class function
474  ana().SetAnalysisPoint(AnalysisAlgorithm::kFillTruthTree);
475  ana().FillTruthTree();
476 
477  // Fill all trees
478  ana().output().SetFillAllTrees();
479 
480  // Finalize the derived class
481  ana().SetAnalysisPoint(AnalysisAlgorithm::kFinalizeSpill);
482  ana().FinalizeSpill();
483 
484  _memory.LogMemory();
485 
486  // Save all trees every NENTRIES_TREESAVE
487  if (_entry%NENTRIES_TREESAVE == 0){
488  std::vector< TTree* >::iterator it;
489  for (it=ana().output().GetTrees().begin();it!=ana().output().GetTrees().end();it++){
490  (*it)->AutoSave("SaveSelf");
491  }
492  }
493  }
494  // delete Spill, CorrectedSpill and RawSpill
495  ana().input().DeleteSpill();
496 
497 }
498 
499 //********************************************************************
501 //********************************************************************
502 
503  // Finalize the derived class
504  ana().SetAnalysisPoint(AnalysisAlgorithm::kFinalize);
505  ana().Finalize();
506 
507  // Create and fill the header tree with a single entry
508  if (_fillTrees) {
509  FillHeaderTree();
510 
511  // Save all trees after looping over all events
512  std::vector< TTree* >::iterator it;
513  for (it=ana().output().GetTrees().begin();it!=ana().output().GetTrees().end();it++){
514  (*it)->AutoSave("SaveSelf");
515  }
516 
517  // Write out memory usage, if needed.
518  _memory.Write();
519 
520  // Close the output file
521  ana().output().CloseOutputFile();
522  }
523 }
524 
525 //********************************************************************
527 //********************************************************************
528 
529  /* Here we add all default variables */
530 
531 
532  //------------ Add a tree for each configuration -----------------
533  Int_t tree_index = NMAXSPECIALTREES;
534  for (std::vector<ConfigurationBase* >::iterator it3= ana().conf().GetConfigurations().begin();it3!=ana().conf().GetConfigurations().end();it3++, tree_index++){
535  if (!(*it3)->IsEnabled()) continue;
536 
537  // Set the tree index to this configuration
538  (*it3)->SetTreeIndex(tree_index);
539  // Add a tree with a given index and name
540  ana().output().AddTreeWithName(tree_index, (*it3)->Name());
541  // Set the number of toys for the tree
542  ana().output().SetNToys(tree_index, (*it3)->GetNToys());
543  }
544 
545  //------------ Add a common variables to all trees (non special trees) -----------------
546 
547  // add entry number in original tree
548  ana().output().AddVar(AnalysisAlgorithm::entry, "entry", "I", "entry number");
549 
550  // add reference toy index to the tree
551  ana().output().AddVar(AnalysisAlgorithm::toy_ref, "toy_ref", "I", "Reference toy index");
552 
553  //---- Add variables to the tree for the different track categories ------
554  Int_t categ_index = AnalysisAlgorithm::firstCategory;
555  Int_t counter_index = AnalysisAlgorithm::firstCategoryCounter;
556  for (std::map< std::string, TrackCategoryDefinition*>::iterator it=ana().cat().GetCategories().begin();it!=ana().cat().GetCategories().end();it++, categ_index++){
557  std::string categ_name = it->first;
558  TrackCategoryDefinition& categ = *(it->second);
559  if (categ.IsMultiType()){
560  ana().output().AddVectorVar(categ_index, categ_name, "I","This is a category variable that can be used to split up a MC histogram into a stack. Use the DumpCategory(\"...\") function for more.", counter_index, "N"+categ_name, categ.GetNTypes());
561  counter_index++;
562  }
563  else
564  ana().output().AddVar(categ_index, categ_name,"I","This is a category variable that can be used to split up a MC histogram into a stack. Use the DumpCategory(\"...\") function for more.");
565  }
566 
567  ana().output().AddToyVar(AnalysisAlgorithm::redo, "redo", "I", "If running multiple toys (for evaluating systematics), whether the selection was re-performed for this toy.");
568 
569  //--- add cut flags to the output tree ----------------------
570 
571  // accumulated cut level
572  if (ana().sel().GetNEnabledSelections()>1) {
573  if (ana().sel().GetNMaxBranches()>1) {
574  ana().output().AddToyMatrixVar(AnalysisAlgorithm::accum_level, "accum_level", "I",
575  "The number of the first cut that was failed.\n"
576  "highland supports running multiple toys (for evaluating systematics), so the first index in this matrix is the toy index. \n"
577  "the second index is the selection and the third index is the branch.\n"
578  "If you only have one toy (normal), then you can use accum_level[][0][0], etc., where 0 can be replaced with your selection/branch number.",
579  ana().sel().GetNEnabledSelections(), ana().sel().GetNMaxBranches());
580  }
581  else{
582  ana().output().AddToyVectorVar(AnalysisAlgorithm::accum_level, "accum_level", "I",
583  "The number of the first cut that was failed.\n"
584  "highland supports running multiple toys (for evaluating systematics), so the first index in this matrix is the toy index. \n"
585  "The second index is the selection.\n"
586  "If you only have one toy (normal), then you can use accum_level[][0], etc., where 0 can be replaced with your selection number.",
587  ana().sel().GetNEnabledSelections());
588  }
589  }
590  else{
591  if (ana().sel().GetNMaxBranches()>1) {
592  ana().output().AddToyVectorVar(AnalysisAlgorithm::accum_level, "accum_level", "I",
593  "The number of the first cut that was failed.\n"
594  "highland supports running multiple toys (for evaluating systematics), so the first index in this matrix is the toy index. The second index is the branch.\n"
595  "If you only have one toy (normal), then you can use accum_level[][0], etc., where 0 can be replaced with your branch number.",
596  ana().sel().GetNMaxBranches());
597  } else {
598  ana().output().AddToyVar(AnalysisAlgorithm::accum_level, "accum_level", "I",
599  "The number of the first cut that was failed.\n"
600  "highland supports running multiple toys (for evaluating systematics), so the index in this vector is the toy index.\n"
601  "If you only have one toy (normal), then you can use accum_level or accum_level[] to access the correct number.");
602  }
603  }
604  char cut[50];
605  Int_t indx=AnalysisAlgorithm::first_cut;
606  for (unsigned int i=0;i<ana().sel().GetNMaxCuts() ;i++, indx++){
607  sprintf(cut, "cut%d", i);
608  if (ana().sel().GetNEnabledSelections()>1) {
609  if (ana().sel().GetNMaxBranches()>1) {
610  ana().output().AddToyMatrixVar(indx, cut, "I","Whether this cut was passed or not.\n"
611  "highland supports running multiple toys (for evaluating systematics), so the first index in this matrix is the toy index. \n"
612  "The second index is the selection and third index is the branch in that selection. \n"
613  "If you only have one toy (normal), then you can use cutN[][0][0], etc., where the 0 can be replaced with your selection/branch number \n"
614  "and N is the cut number.",
615  ana().sel().GetNEnabledSelections(), ana().sel().GetNMaxBranches());
616  }
617  else{
618  ana().output().AddToyVectorVar(indx, cut, "I","Whether this cut was passed or not.\n"
619  "highland supports running multiple toys (for evaluating systematics), so the index in this vector is the toy index.\n"
620  "The second index is the selection. \n"
621  "If you only have one toy (normal), then you can use cutN or cutN[][0] to access the correct number, \n"
622  "where the 0 can be replaced with your selection number and N is the cut number.",
623  ana().sel().GetNEnabledSelections());
624  }
625  }
626  else{
627  if (ana().sel().GetNMaxBranches()>1) {
628  ana().output().AddToyVectorVar(indx, cut, "I","Whether this cut was passed or not.\n"
629  "highland supports running multiple toys (for evaluating systematics), so the first index in this matrix is the toy index. The second index is the branch.\n"
630  "If you only have one toy (normal), then you can use cutN[][0], etc., where 0 can be replaced with your branch number and N is the cut number.",
631  ana().sel().GetNMaxBranches());
632  } else {
633  ana().output().AddToyVar(indx, cut, "I","Whether this cut was passed or not.\n"
634  "highland supports running multiple toys (for evaluating systematics), so the index in this vector is the toy index.\n"
635  "If you only have one toy (normal), then you can use cutN or cutN[] to access the correct number, where N is the cut number.");
636  }
637  }
638  }
639 
640  //------------ Add systematics related variables -----------------
641 
642  /*
643  //! [AnalysisLoop_syst]
644  There are several variables in the microtree related with systematic error propagation. The correspondence with variables used to compute the covariance matrix
645  is indicated inside the paretheses:
646 
647  - \b NTOYS (\(N_{toys}\)): this the the number of toy experiments. The same for all events.
648  - \b toy_index (t): the toy experiment index (from 0 to NTOYS-1). It has 1 index: toy_index[NTOYS];
649  - \b toy_weight (\(w^t\)): This is the toy experiment weight. It has 1 index: toy_weight[NTOYS].
650  - \b NWEIGHSYST (\(N_s\)): the number of weight systematics.
651  - \b weight_syst (\((W^t)_e^s\)): this is the event weights for each toy and each weight systematic enabled.
652  It has 2 indexes: weight_syst[NTOYS][NWEIGHTSYST].
653  - \b weight_syst_total (\((W^t)_e\)): the product of all weight systematics. It has one index weight_syst_total[NTOYS]
654 
655  //! [AnalysisLoop_syst]
656  */
657 
658  for (std::vector<ConfigurationBase* >::iterator it3= ana().conf().GetConfigurations().begin();it3!=ana().conf().GetConfigurations().end();it3++){
659  if (!(*it3)->IsEnabled()) continue;
660 
661  // Enable the appropriate Variations and Weights for this configuration
662  ana().evar().DisableAllEventVariations();
663  ana().evar().EnableEventVariations((*it3)->GetEnabledEventVariations());
664 
665  ana().eweight().DisableAllEventWeights();
666  ana().eweight().EnableEventWeights((*it3)->GetEnabledEventWeights());
667 
668 
669  if (ana().eweight().GetNEnabledEventWeights() == 0) continue;
670 
671  Int_t tree_index = (*it3)->GetTreeIndex();
672 
673  // add the vector of systematic weights and the total systematic weight. TODO
674  // ToyVars except for default_conf
675  if ((*it3)->GetIndex() == ConfigurationManager::default_conf){
676  ana().output().AddVectorVar(tree_index,AnalysisAlgorithm::weight_syst, "weight_syst", "F", "Weight parameters (corr+syst)", ana().eweight().GetNEnabledEventWeights());
677  ana().output().AddVar(tree_index,AnalysisAlgorithm::weight_syst_total, "weight_syst_total", "F", "Total weight (corr+syst)");
678 
679  ana().output().AddVectorVar(tree_index,AnalysisAlgorithm::weight_corr, "weight_corr", "F", "Weight parameters (corr only)", ana().eweight().GetNEnabledEventWeights());
680  ana().output().AddVar(tree_index,AnalysisAlgorithm::weight_corr_total, "weight_corr_total", "F", "Total weight (corr only)");
681 
682  }
683  else{
684  ana().output().AddToyVectorVar(tree_index,AnalysisAlgorithm::weight_syst, "weight_syst", "F", "Weight parameters (corr+syst)", ana().eweight().GetNEnabledEventWeights());
685  ana().output().AddToyVar(tree_index,AnalysisAlgorithm::weight_syst_total, "weight_syst_total", "F", "Total weight (corr+syst)");
686 
687  ana().output().AddToyVectorVar(tree_index,AnalysisAlgorithm::weight_corr, "weight_corr", "F", "Weight parameters (corr only)", ana().eweight().GetNEnabledEventWeights());
688  ana().output().AddToyVar(tree_index,AnalysisAlgorithm::weight_corr_total, "weight_corr_total", "F", "Total weight (corr only)");
689  }
690 
691  // add the number of systematic weights
692  ana().output().AddVar(tree_index,AnalysisAlgorithm::NWEIGHTSYST, "NWEIGHTSYST", "I", "Number of systematic weight parameters");
693  }
694 
695  // Define analysis specific variables
696  ana().DefineMicroTrees();
697 }
698 
699 //********************************************************************
701 //********************************************************************
702 
703  // Add a tree
704  ana().output().AddTreeWithName(OutputManager::truth, "truth");
705 
706  if (ana().sel().GetNEnabledSelections()>1) {
707  if (ana().sel().GetNMaxBranches()>1) {
708  ana().output().AddMatrixVar(OutputManager::truth, AnalysisAlgorithm::accum_level, "accum_level", "I",
709  "The number of the first cut that was failed for each branch. Unlike the variable with the same name in the standard micro-trees, \n"
710  "this one has a single toy running multiple toys \n"
711  "The first index is the selection and the second index is the branch.\n"
712  "Then you can use accum_level[0][0], etc., where 0 can be replaced with your selection/branch number.",
713  ana().sel().GetNEnabledSelections(), ana().sel().GetNMaxBranches());
714  }
715  else{
716  ana().output().AddVectorVar(OutputManager::truth, AnalysisAlgorithm::accum_level, "accum_level", "I",
717  "The number of the first cut that was failed for each branch. Unlike the variable with the same name in the standard micro-trees, \n"
718  "this one has a single toy running multiple toys \n"
719  "The first index is the selection and the second index is the branch.\n"
720  "Then you can use accum_level[0], etc., where 0 can be replaced with your selection number.",
721  ana().sel().GetNEnabledSelections());
722  }
723  }
724  else{
725  if (ana().sel().GetNMaxBranches()>1) {
726  ana().output().AddVectorVar(OutputManager::truth, AnalysisAlgorithm::accum_level, "accum_level", "I",
727  "The number of the first cut that was failed for each branch. Unlike the variable with the same name in the standard micro-trees, \n"
728  "this one has a single toy running multiple toys \n"
729  "The first index is the branch.\n"
730  "Then you can use accum_level[0], etc., where 0 can be replaced with your branch number.",
731  ana().sel().GetNMaxBranches());
732  }
733  else {
734  ana().output().AddVar(OutputManager::truth, AnalysisAlgorithm::accum_level, "accum_level", "I",
735  "The number of the first cut that was failed for each branch. Unlike the variable with the same name in the standard micro-trees, \n"
736  "this one has a single toy running multiple toys \n"
737  "Then you can use accum_level to access the correct number.");
738  }
739  }
740 
741  // Add variables only to the truth tree
742  ana().output().SetFillSingleTree(OutputManager::truth);
743 
744  //---- Add variables to the tree for the different track categories ------
745  Int_t categ_index = AnalysisAlgorithm::firstCategory;
746  Int_t counter_index = AnalysisAlgorithm::firstCategoryCounter;
747  for (std::map< std::string, TrackCategoryDefinition*>::iterator it=ana().cat().GetCategories().begin();it!=ana().cat().GetCategories().end();it++, categ_index++){
748  std::string categ_name = it->first;
749  TrackCategoryDefinition& categ = *(it->second);
750  if (categ.IsMultiType()){
751  ana().output().AddVectorVar(categ_index, categ_name, "I","This is a category variable that can be used to split up a MC histogram into a stack. Use the DumpCategory(\"...\") function for more.", counter_index, "N"+categ_name, categ.GetNTypes());
752  counter_index++;
753  }
754  else
755  ana().output().AddVar(categ_index, categ_name,"I","This is a category variable that can be used to split up a MC histogram into a stack. Use the DumpCategory(\"...\") function for more.");
756  }
757 
758  // Define analysis specific variables
759  ana().SetAnalysisPoint(AnalysisAlgorithm::kDefineTruthTree);
760  ana().DefineTruthTree();
761 
762  // Unset this field
763  ana().output().SetFillAllTrees();
764 }
765 
766 //********************************************************************
768 //********************************************************************
769 
770  // Add a tree
771  ana().output().AddTreeWithName(OutputManager::config, "config");
772 
773  ana().output().SetFillSingleTree(OutputManager::config);
774 
775  // The $CMTPATH
776  ana().output().AddVar(OutputManager::config, AnalysisAlgorithm::CMTPATH, "CMTPATH", "C", "the CMTPATH used to produce the output file");
777  ana().output().FillVar(AnalysisAlgorithm::CMTPATH, (std::string)getenv("CMTPATH") );
778 
779  // The Machine name
780  ana().output().AddVar(OutputManager::config, AnalysisAlgorithm::HOSTNAME, "HOSTNAME", "C", "the machine used to produce the output file");
781  if (getenv("HOSTNAME"))
782  ana().output().FillVar(AnalysisAlgorithm::HOSTNAME, (std::string)getenv("HOSTNAME") );
783  else
784  ana().output().FillVar(AnalysisAlgorithm::HOSTNAME, "unknown" );
785 
786  // The input file name
787  ana().output().AddVar(OutputManager::config, AnalysisAlgorithm::INPUTFILE, "InputFile", "C", "the input file used to produce the output file");
788  ana().output().FillVar(AnalysisAlgorithm::INPUTFILE, _inputFileName );
789 
790  // The original file (i.e. the recon output file)
791  ana().output().AddVar(OutputManager::config, AnalysisAlgorithm::OriginalFile, "OriginalFile", "C", "the original file used to produce the input file");
792 
793 
794  if (!ana().input().InputIsOriginalTree()){
795  TChain* chain = new TChain("config");
796  chain->AddFile(_inputFileName.c_str());
797  char OriginalFile[200]="unknown";
798  if (chain->FindLeaf("OriginalFile")){
799  chain->SetBranchAddress("OriginalFile", OriginalFile);
800  Long64_t centry = chain->LoadTree(0);
801  Int_t nb = chain->GetEntry(0);
802  (void) centry;
803  (void) nb;
804  }
805  ana().output().FillVar(AnalysisAlgorithm::OriginalFile, OriginalFile );
806  }
807  else
808  ana().output().FillVar(AnalysisAlgorithm::OriginalFile, _inputFileName );
809 
810 
811  ana().output().AddVar(OutputManager::config, AnalysisAlgorithm::MinAccumLevelToSave, "MinAccumLevelToSave", "I", "the minimum accut level to save the event");
812  ana().output().FillVar(AnalysisAlgorithm::MinAccumLevelToSave, ana().GetMinAccumCutLevelToSave());
813 
814 
815  // The software versions
816  ND::versioning().WriteClonesArray(*ana().output().GetTree(OutputManager::config));
817 
818  // TrackCategories
819  ana().cat().WriteClonesArray(*ana().output().GetTree(OutputManager::config));
820 
821  // CategoryManager* cat= &(ana().cat());
822  // ana().output().GetTree(OutputManager::config)->Branch("CatMan","CategoryManager",&cat,64000,0);
823 
824 
825  // selections
826  ana().sel().WriteClonesArray(*ana().output().GetTree(OutputManager::config));
827 
828  // SelectionManager* sel= &(ana().sel());
829  // ana().output().GetTree(OutputManager::config)->Branch("SelMan","SelectionManager",&sel,64000,0);
830 
831  // docstrings
832  ana().doc().WriteClonesArray(*ana().output().GetTree(OutputManager::config));
833 
834  // DocStringManager* doc= &(ana().doc());
835  // ana().output().GetTree(OutputManager::config)->Branch("DocMan","DocStringManager",&doc,64000,0);
836 
837 
838  // Configurations
839  ana().conf().WriteClonesArray(*ana().output().GetTree(OutputManager::config));
840 
841  // ConfigurationManager* conf= &(ana().conf());
842  // ana().output().GetTree(OutputManager::config)->Branch("ConfMan","ConfigurationManager",&conf,64000,0);
843 
844 
845  // Systematic
846  ana().syst().WriteClonesArray(*ana().output().GetTree(OutputManager::config));
847 
848  // SystematicManager* syst= &(ana().syst());
849  // ana().output().GetTree(OutputManager::config)->Branch("SystMan","SystematicManager",&syst,64000,0);
850 
851  // EventWeightManager* eweight= &(ana().eweight());
852  // ana().output().GetTree(OutputManager::config)->Branch("WeightMan","EventWeightManager", &eweight,64000,0);
853 
854  // EventVariationManager* evar= &(ana().evar());
855  // ana().output().GetTree(OutputManager::config)->Branch("VarMan", "EventVariationManager",&evar,64000,0);
856 
857 
858  // Corrections
859  ana().corr().WriteClonesArray(*ana().output().GetTree(OutputManager::config));
860 
861  // CorrectionManager* corr= &(ana().corr());
862  // ana().output().GetTree(OutputManager::config)->Branch("CorrMan","CorrectionManager",&corr,64000,0);
863 
864  // Fill user defined variables
865  ana().SetAnalysisPoint(AnalysisAlgorithm::kFillConfigTree);
866  ana().FillConfigTree();
867 
868  // Put back set fill all trees
869  ana().output().SetFillAllTrees();
870 
871  // Fill the tree
872  ana().output().GetTree(OutputManager::config)->Fill();
873 }
874 
875 //********************************************************************
877 //********************************************************************
878 
879  // Add a tree
880  ana().output().AddTreeWithName(OutputManager::header,"header");
881 
882  Header* headerp = &ana().input().header();
883  ana().output().GetTree(OutputManager::header)->Branch("POTInfo","Header",&headerp,32000,0);
884 
885  ana().output().GetTree(OutputManager::header)->Fill();
886 }
887 
888 //********************************************************************
890 //********************************************************************
891 
892  // Read corrections from the input file
893 
894  // When running over a FlatTree corrections may already exist in it.
895  // It that case corrections are read from the input file (config tree) and added to the CorrectionManager.
896  // In this case each correction is stored as
897  // "appliedInInput" and "disabled", such that it is not applied twice.
898 
899  if (!ana().input().InputIsOriginalTree()){
900  bool isROOTFile = ana().input().IsROOTFile(_inputFileName);
901  std::string firstFile = ana().input().FindFirstFile(_inputFileName, isROOTFile);
902  if (!isROOTFile)
903  std::cout << "ReadCorrections from first file in list: " << firstFile << std::endl;
904  ana().corr().ReadCorrections(firstFile, true);
905  }
906  // Add other corrections
907  ana().SetAnalysisPoint(AnalysisAlgorithm::kDefineCorrections);
908  ana().DefineCorrections();
909 
910  // Print on the screen the corrections
911  ana().corr().DumpCorrections();
912 }
913 
914 //********************************************************************
916 //********************************************************************
917 
918  // Add a default configuration with a single toy experiment
919  ana().conf().AddConfiguration(ConfigurationManager::default_conf, "default",1,1,new ZeroToyMaker());
920 
921  // Set "default" as the initial configuration, so that corrections can be applied.
922  ana().conf().SetCurrentConfigurationIndex(ConfigurationManager::default_conf);
923 
924  // Add other configurations
925  ana().SetAnalysisPoint(AnalysisAlgorithm::kDefineConfigurations);
926  ana().DefineConfigurations();
927 
928  // Create the Toy experiment with the appropriate format (number of systematics and number of parameters for each systematic)
929  // This must be done after defining the configurations
930  // The number of toys created is the one corresponding to the configuration with more toys
931 
932  for (UInt_t i=0;i<ana().eweight().GetNEventWeights();i++){
933  EventWeightBase* it = ana().eweight().GetEventWeights()[i];
934  ana().syst().AddWeightSystematic(it->GetIndex(), it->GetName(), it);
935  // ana().syst().AddSystematic(it->GetIndex(), it);
936  }
937  for (UInt_t i=0;i<ana().evar().GetNEventVariations();i++){
938  EventVariationBase* it = ana().evar().GetEventVariations()[i];
939  ana().syst().AddVariationSystematic(it->GetIndex(), it->GetName(), it);
940  // ana().syst().AddSystematic(it->GetIndex(), it);
941  }
942 
943 
944  for (std::vector<ConfigurationBase*>::iterator it= ana().conf().GetConfigurations().begin();it!=ana().conf().GetConfigurations().end();it++){
945  ConfigurationBase* conf = *it;
948  }
949 
950  ana().conf().CreateToyExperiments(ana().syst());
951 
952  // Dump all configurations
953  ana().conf().DumpConfigurations(&ana().syst());
954 }
955 
956 //********************************************************************
957 void AnalysisLoop::Loop(int nmax,int imin){
958 //********************************************************************
959 
960  if (!Initialize()) return;
961 
962  // Get the number of entries in the tree
963  Long64_t nentries = ana().input().GetEntries();
964 
965  if (imin>nentries){
966  std::cout << "AnalysisLoop::Loop(). input tree has " << nentries << " entries. You cannot start from entry " << imin << std::endl;
967  return;
968  }
969 
970  // Compute the number of entries to be run
971  if (nmax==0 || imin+nmax>nentries) _entry_nmax = nentries-imin;
972  else _entry_nmax = nmax;
973 
974  // Compute the number of the last entry to be run
975  _entry_imax = _entry_imin+_entry_nmax;
976 
977  if (ana().input().InputIsFlatTree())
978  std::cout << "AnalysisLoop::Loop(). input tree has " << nentries << " entries for " << ana().input().header().GetPOT() << " good POT" << std::endl;
979  else
980  std::cout << "AnalysisLoop::Loop(). input tree has " << nentries << " entries (POT counted on the fly)" << std::endl;
981  std::cout << "AnalysisLoop::Loop(). loop over " << _entry_nmax << " entries from entry number "<< _entry_imin << std::endl;
982 
983  double delta_t[20]={0};
984 
985  //--------- Loop over entries in the tree ----------------------------------
986  _entry=_entry_imin;
987  while (_entry<_entry_imax) {
988 
989  // Initialize clock
990  timeval tim;
991  gettimeofday(&tim, NULL);
992  double t0=tim.tv_sec+(tim.tv_usec/1000000.0);
993 
994  // Fills the full Spill structure (it could imply reading several entries in input tree)
995  bool spillOK = InitializeSpill();
996 
997  // Break the loop (at the moment only for skimmed events, when the last interesting event is processed)
998  if (anaUtils::breakLoop) break;
999 
1000  // go to the next spill if this one is not OK
1001  if (!spillOK) continue;
1002 
1003  gettimeofday(&tim, NULL);
1004  double t1=tim.tv_sec+(tim.tv_usec/1000000.0);
1005 
1006  delta_t[0] += t1-t0;
1007 
1008  //---- For each Spill loop over Bunches ----
1009  for (unsigned int ibunch=0;ibunch<ana().input().GetSpill().Bunches.size();ibunch++){
1010  gettimeofday(&tim, NULL);
1011  double t2=tim.tv_sec+(tim.tv_usec/1000000.0);
1012 
1013  ana().input().SetCurrentBunch(ibunch);
1014  InitializeBunch();
1015 
1016  gettimeofday(&tim, NULL);
1017  double t3=tim.tv_sec+(tim.tv_usec/1000000.0);
1018 
1019 
1020  delta_t[1] += t3-t2;
1021 
1022 
1023  //---- For each bunch loop over configurations ----
1024  for (std::vector<ConfigurationBase*>::iterator it= ana().conf().GetConfigurations().begin();it!=ana().conf().GetConfigurations().end();it++){
1025  ConfigurationBase* conf = *it;
1026 
1027  gettimeofday(&tim, NULL);
1028  double t4=tim.tv_sec+(tim.tv_usec/1000000.0);
1029 
1030  if (!conf->IsEnabled()) continue;
1031  ana().conf().SetCurrentConfigurationIndex(conf->GetIndex());
1032  ana().output().SetCurrentTree(conf->GetTreeIndex());
1034 
1035  gettimeofday(&tim, NULL);
1036  double t5=tim.tv_sec+(tim.tv_usec/1000000.0);
1037 
1038  delta_t[2] += t5-t4;
1039 
1040  _conf_passed=false;
1041 
1042  //---- For each configuration loop over toys --------
1043  for (int n=0;n<conf->GetNToys();n++){
1044 
1045  gettimeofday(&tim, NULL);
1046  double t6=tim.tv_sec+(tim.tv_usec/1000000.0);
1047 
1048  ana().conf().SetToyIndex(n);
1049  ana().output().SetToyIndex(n);
1050  InitializeToy();
1051 
1052  gettimeofday(&tim, NULL);
1053  double t7=tim.tv_sec+(tim.tv_usec/1000000.0);
1054 
1055  delta_t[3] += t7-t6;
1056 
1057  //---- For each toy loop over selections --------
1058  for (std::vector<SelectionBase*>::iterator sit= ana().sel().GetSelections().begin();sit!=ana().sel().GetSelections().end();sit++){
1059  SelectionBase& selec = **sit;
1060  if (!selec.IsEnabled()) continue;
1061  gettimeofday(&tim, NULL);
1062  double t8=tim.tv_sec+(tim.tv_usec/1000000.0);
1063 
1064  InitializeSelection(selec);
1065 
1066  gettimeofday(&tim, NULL);
1067  double t9=tim.tv_sec+(tim.tv_usec/1000000.0);
1068 
1069  delta_t[4] += t9-t8;
1070 
1071  _toy_passed = Process(selec);
1072 
1073  gettimeofday(&tim, NULL);
1074  double t10=tim.tv_sec+(tim.tv_usec/1000000.0);
1075 
1076  delta_t[5] += t10-t9;
1077 
1078  FinalizeSelection(selec);
1079 
1080  gettimeofday(&tim, NULL);
1081  double t11=tim.tv_sec+(tim.tv_usec/1000000.0);
1082 
1083 
1084  delta_t[6] += t11-t10;
1085  if (_toy_passed) _conf_passed=true;
1086  }
1087 
1088  gettimeofday(&tim, NULL);
1089  double t12=tim.tv_sec+(tim.tv_usec/1000000.0);
1090 
1091  if (!FinalizeToy()) break;
1092 
1093  gettimeofday(&tim, NULL);
1094  double t13=tim.tv_sec+(tim.tv_usec/1000000.0);
1095 
1096  delta_t[7] += t13-t12;
1097 
1098  }
1099 
1100  gettimeofday(&tim, NULL);
1101  double t14=tim.tv_sec+(tim.tv_usec/1000000.0);
1102 
1104 
1105  gettimeofday(&tim, NULL);
1106  double t15=tim.tv_sec+(tim.tv_usec/1000000.0);
1107 
1108  delta_t[8] += t15-t14;
1109  }
1110  gettimeofday(&tim, NULL);
1111  double t16=tim.tv_sec+(tim.tv_usec/1000000.0);
1112 
1113  FinalizeBunch();
1114 
1115  gettimeofday(&tim, NULL);
1116  double t17=tim.tv_sec+(tim.tv_usec/1000000.0);
1117 
1118  delta_t[9] += t17-t16;
1119  }
1120  gettimeofday(&tim, NULL);
1121  double t18=tim.tv_sec+(tim.tv_usec/1000000.0);
1122  FinalizeSpill();
1123  gettimeofday(&tim, NULL);
1124  double t19=tim.tv_sec+(tim.tv_usec/1000000.0);
1125 
1126  delta_t[10] += t19-t18;
1127 
1128  delta_t[11] += t19-t0;
1129  }
1130 
1131  for (Int_t i=0;i<11;i++)
1132  delta_t[12] += delta_t[i];
1133 
1134 
1135  std::cout << "time profile --------------" << std::endl;
1136  std::cout << "Ini Spill: " << delta_t[0] << std::endl;
1137  std::cout << "Ini Bunch: " << delta_t[1] << std::endl;
1138  std::cout << "Ini Conf: " << delta_t[2] << std::endl;
1139  std::cout << "Ini Toy (v syst): " << delta_t[3] << std::endl;
1140  std::cout << "Ini Sel: " << delta_t[4] << std::endl;
1141  std::cout << "Selection: " << delta_t[5] << std::endl;
1142  std::cout << "End Sel (w syst): " << delta_t[6] << std::endl;
1143  std::cout << "End Toy: " << delta_t[7] << std::endl;
1144  std::cout << "End Conf: " << delta_t[8] << std::endl;
1145  std::cout << "End Bunch: " << delta_t[9] << std::endl;
1146  std::cout << "End Spill: " << delta_t[10] << std::endl;
1147  std::cout << "Total: " << delta_t[11] << std::endl;
1148  std::cout << "Total wo t: " << delta_t[12] << std::endl;
1149 
1150 
1151 
1152  Finalize();
1153 }
1154 
1155 //********************************************************************
1157 //********************************************************************
1158 
1159  // Returns true when any of the branches is passed
1160  // Internaly the CheckRedoSelection is called. The returned boolean is returned as argument
1161  // by the Apply method of the selection such that we can save the redo value in the micro-tree
1162  bool redo = false;
1163  bool ToyPassed = selec.Apply(*_event, redo);
1164 
1165  // fill a variable saying if selection was redone for this toy experiment
1166  if (_fillTrees)
1167  ana().output().FillToyVar(AnalysisAlgorithm::redo, (int)redo);
1168 
1169  return ToyPassed;
1170 }
1171 
1172 //********************************************************************
1174 //********************************************************************
1175 
1176  // Fill the entry number in the input tree
1177  ana().output().FillVar(AnalysisAlgorithm::entry, (int) _entry);
1178 
1179  // Fill the tree for the current configuration provided the true codes for color drawing
1180  std::map< std::string, TrackCategoryDefinition* >::iterator it;
1181  Int_t categ_index = AnalysisAlgorithm::firstCategory;
1182  for (it=ana().cat().GetCategories().begin();it!=ana().cat().GetCategories().end();it++, categ_index++ ){
1183  std::string categ_name = it->first;
1184  TrackCategoryDefinition& categ = *(it->second);
1185  if (categ.IsMultiType()){
1186  for (unsigned int i=0;i<categ.GetNTypes();i++)
1187  ana().output().FillVectorVar(categ_index, (int)ana().cat().CheckCategoryType(categ_name,i),i);
1188  }
1189  else ana().output().FillVar(categ_index, ana().cat().GetCode(categ_name));
1190  }
1191 
1192  // reference toy
1193  ana().output().FillVar(AnalysisAlgorithm::toy_ref, ana().conf().GetCurrentConfiguration()->GetRefToyIndex());
1194 
1195  // Call the derive classes functions
1196  ana().SetAnalysisPoint(AnalysisAlgorithm::kFillMicroTrees);
1197  ana().FillMicroTrees();
1198 
1199  // Call the base class function and actually fills the tree
1200  // (fill the toy configuration variables: toy_index, toy_weight)
1201  ana().output().FillMicroTrees();
1202 }
1203 
1204 //********************************************************************
1206 //********************************************************************
1207 
1208  //Fill the Toy Experiment Index. Should be filled always !!!!
1209  ana().output().FillToyVar(OutputManager::toy_index, ana().conf().GetToyIndex());
1210 
1211  if (!_toy_passed && ana().GetFillSuccessOnly()) return;
1212  if (!ana().CheckAccumLevelToSave()) return;
1213 
1214 
1215  // ---------------- Fill cut level variables ------------------------
1216 
1217  Int_t isel=0;
1218  for (std::vector<SelectionBase*>::iterator it=ana().sel().GetSelections().begin();it!=ana().sel().GetSelections().end();it++){
1219  if (!(*it)->IsEnabled()) continue;
1220  for (UInt_t ibranch=0;ibranch<(*it)->GetNBranches();ibranch++){
1221  Int_t indx=AnalysisAlgorithm::first_cut;
1222  if (ana().sel().GetNEnabledSelections()>1){
1223  if (ana().sel().GetNMaxBranches()>1){
1224  ana().output().FillToyMatrixVar(AnalysisAlgorithm::accum_level, (*it)->GetAccumCutLevel(ibranch), isel, ibranch);
1225  for (unsigned int i=0;i<(*it)->GetNCuts(ibranch);i++, indx++){
1226  ana().output().FillToyMatrixVar(indx, (*it)->GetCutPassed(i, ibranch), isel, ibranch);
1227  }
1228  }
1229  else{
1230  ana().output().FillToyVectorVar(AnalysisAlgorithm::accum_level, (*it)->GetAccumCutLevel(ibranch), isel);
1231  for (unsigned int i=0;i<(*it)->GetNCuts(ibranch);i++, indx++){
1232  ana().output().FillToyVectorVar(indx, (*it)->GetCutPassed(i, ibranch), isel);
1233  }
1234  }
1235  }
1236  else{
1237  if (ana().sel().GetNMaxBranches()>1){
1238  ana().output().FillToyVectorVar(AnalysisAlgorithm::accum_level, (*it)->GetAccumCutLevel(ibranch), ibranch);
1239  for (unsigned int i=0;i<(*it)->GetNCuts(ibranch);i++, indx++){
1240  ana().output().FillToyVectorVar(indx, (*it)->GetCutPassed(i, ibranch), ibranch);
1241  }
1242  }
1243  else{
1244  ana().output().FillToyVar(AnalysisAlgorithm::accum_level, (*it)->GetAccumCutLevel(ibranch));
1245  for (unsigned int i=0;i<(*it)->GetNCuts(ibranch);i++, indx++){
1246  ana().output().FillToyVar(indx, (*it)->GetCutPassed(i, ibranch));
1247  }
1248  }
1249  }
1250  }
1251  isel++;
1252  }
1253 
1254  //------ Fill the event weights for each toy experiment ----
1255  Int_t nWeightSyst = (Int_t)ana().eweight().GetNEnabledEventWeights();
1256 
1257  if (nWeightSyst>0){
1258 
1259  Int_t w = 0;
1260  Float_t weight_syst_total = 1.;
1261  Float_t weight_corr_total = 1.;
1262 
1263  for (int j = 0; j < nWeightSyst; ++j){
1264  Float_t weight_syst = 1.;
1265  Float_t weight_corr = 1.;
1266  if (w < nWeightSyst){
1267  weight_syst = _weightSyst[w].Systematic;
1268  weight_corr = _weightSyst[w].Correction;
1269  }
1270  if (ana().conf().GetCurrentConfigurationIndex() == ConfigurationManager::default_conf){
1271  ana().output().FillVectorVar(AnalysisAlgorithm::weight_syst, weight_syst, w);
1272  ana().output().FillVectorVar(AnalysisAlgorithm::weight_corr, weight_corr, w);
1273  w++;
1274  }
1275  else{
1276  ana().output().FillToyVectorVar(AnalysisAlgorithm::weight_syst, weight_syst, w);
1277  ana().output().FillToyVectorVar(AnalysisAlgorithm::weight_corr, weight_corr, w);
1278  w++;
1279  }
1280  if(weight_syst < 0.) weight_syst = 0.;
1281  if(weight_syst > 100.) weight_syst = 100.;
1282  if(weight_syst != weight_syst) {
1283  std::cerr << "Warning: systematic weight_syst is NaN, setting to 0!" << std::endl;
1284  weight_syst = 0.;
1285  }
1286  if(weight_corr < 0.) weight_corr = 0.;
1287  if(weight_corr > 100.) weight_corr = 100.;
1288  if(weight_corr != weight_corr) {
1289  std::cerr << "Warning: systematic weight_corr is NaN, setting to 0!" << std::endl;
1290  weight_corr = 0.;
1291  }
1292 
1293  weight_syst_total *= weight_syst;
1294  weight_corr_total *= weight_corr;
1295  }
1296 
1297  // -------- Fill the total weight systematic -------------------
1298  if (ana().conf().GetCurrentConfigurationIndex() == ConfigurationManager::default_conf){
1299  ana().output().FillVar(AnalysisAlgorithm::weight_syst_total, weight_syst_total);
1300  ana().output().FillVar(AnalysisAlgorithm::weight_corr_total, weight_corr_total);
1301  }
1302  else{
1303  ana().output().FillToyVar(AnalysisAlgorithm::weight_syst_total, weight_syst_total);
1304  ana().output().FillToyVar(AnalysisAlgorithm::weight_corr_total, weight_corr_total);
1305  }
1306  ana().output().FillVar(AnalysisAlgorithm::NWEIGHTSYST, nWeightSyst);
1307  }
1308 
1309  // Fill the user toy experiment variables
1310  ana().SetAnalysisPoint(AnalysisAlgorithm::kFillToyVarsInMicroTrees);
1311  ana().FillToyVarsInMicroTrees();
1312 }
1313 
1314 //********************************************************************
1315 void AnalysisLoop::PrintUsage(const std::string& programName){
1316 //********************************************************************
1317  std::cout << "usage: " << programName << " [options] [input-file]" << std::endl;
1318  std::cout << std::endl;
1319  std::cout << "Options:" << std::endl;
1320  std::cout << " -c Run in cosmics mode, putting all tracks in one 'bunch'" << std::endl;
1321  std::cout << " -o <file> Set the name of an output file (mandatory)" << std::endl;
1322  std::cout << " -n <cnt> Only read <cnt> events" << std::endl;
1323  std::cout << " -s <cnt> Skip <cnt> events" << std::endl;
1324  std::cout << " -e <file> Set the name of file containing events to skim (format: run subrun event)" << std::endl;
1325  std::cout << " -p <file> Set the name of a parameter override file" << std::endl;
1326  std::cout << " -v Don't Check version compatibility between nd280AnalysisTools and oaAnalysis file" << std::endl;
1327  std::cout << " -r Don't fill any trees and don't create an output file (mainly for speed tests)" << std::endl;
1328  std::cout << " -m Dumps on the screen the memory usage" << std::endl;
1329  std::exit(1);
1330 }
1331 
1332 //********************************************************************
1334 //********************************************************************
1335  Loop(_entry_nmax, _entry_imin);
1336 }
1337 
1338 
void DefineCorrections()
Define the corrections to be applied.
void DumpConfigurations(SystematicManager *syst=NULL)
Dump summary info about all configurations.
void AddVar(Int_t index, const std::string &name, const std::string &type, const std::string &doc, double ini=-9999)
Add a single variable to all trees.
void AddWeightSystematic(Int_t index, EventWeightBase *sys)
Register an SystematicBase as a weight systematic.
MemoryUsage _memory
Tools for tracking memory usage.
Int_t GetIndex() const
Return the index of this systematic.
void AddConfiguration(Int_t index, const std::string &conf, UInt_t ntoys=1, Int_t randomSeed=-1, ToyMaker *toyMaker=NULL)
Add a new configuration.
bool IsMultiType()
Is this a multi-type category ? (Can several types coexist?)
UInt_t GetNEnabledEventWeights()
Returns the number of enabled EventWeights.
virtual AnaEventC * MakeEvent()=0
[AnalysisAlgorithm_optional]
TTree * GetTree(Int_t index)
Returns the a tree with a given index.
Definition: TreeManager.hxx:28
void Loop(int nmax=0, int imin=0)
void CreateToyBoxArray(Int_t nevents)
Create the array of PreviousToyBox for all enabled selections.
void LogMemory()
Definition: MemoryUsage.cxx:18
AnalysisLoop(AnalysisAlgorithm *ana, int argc, char *argv[])
Constructor which parses and sanity checks the command line options.
ConfigurationBase * GetCurrentConfiguration() const
return the current configuration
void FillHeaderTree()
Fill the "header" tree, which includes POT information etc.
UInt_t GetNEventVariations() const
Returns the number of EventVariations.
bool Process(SelectionBase &selec)
void SetCurrentConfigurationIndex(Int_t conf)
Set the index of the current configuration.
void FinalizeSelection(const SelectionBase &sel)
UInt_t GetNMaxCuts()
Returns the maximum number of cuts in all selections.
void AddTreeWithName(Int_t tree_index, const std::string &tree_name, TTree *tree=NULL)
Add a tree provided its index and name.
std::vector< EventVariationBase * > & GetEventVariations()
Get the vector of EventVariations.
void AddToyVar(Int_t index, const std::string &name, const std::string &type, const std::string &docstring)
Add a single analysis variable to all trees.
Int_t GetNToys() const
Get and sets the number of toys.
void FillVectorVar(Int_t index, Float_t var, Int_t indx=-1)
Fill a vector variable.
void DefineMicroTrees()
Define the variables that should be stored in the output micro-trees.
std::vector< AnaBunchC * > Bunches
The reconstructed objects, split into timing bunches.
void FillToyVectorVar(Int_t index, Int_t var, Int_t comp)
Fill a vector analysis variable.
UInt_t GetNEnabledSelections()
Returns the number of enabled selections.
UInt_t GetNEventWeights() const
Returns the number of EventWeights.
const std::vector< Int_t > & GetEnabledEventVariations()
Get the variations enabled for this configuration.
void InitializeEvent(SelectionManager &sel, AnaEventC &event)
Fill the SystBox for the enabled EventWeights.
ToyMaker & GetToyMaker()
Returns the ToyMaker.
void SetCurrentBunch(int ibunch)
Set the current bunch index.
const ToyBoxB & GetPreviousToyBox(const AnaEventC &event) const
Get the ToyBox of the last processed toy for a particular event.
std::string _inputFileType
void FinalizeEvent(AnaEventC &event)
Delete the SystBox for all EventWeights.
UInt_t GetNEnabledEventVariations()
Returns the number of enabled EventVariations.
void InitializeConfiguration()
void DeleteSpill()
clean up the remaining pointers to the spills.
void SetEvent(AnaEventC *event)
Set the current event into the algorithm and all used algorithms.
std::vector< SelectionBase * > & GetSelections()
Return the map of selections.
This class handles POT info, SoftwareVersion and IsMC.
Definition: Header.hxx:10
bool _versionCheck
Check version compatibility between nd280AnalysisTools compilation and oaAnalysis file...
void DisableAllEventVariations()
Disable all eventVariations.
void InitializeEvent(SelectionManager &sel, AnaEventC &event)
Fill the SystBox for the enabled EventVariations.
void FinalizeSpill()
void IncrementPOTBySpill()
const std::vector< Int_t > & GetEnabledEventWeights()
Get the weights enabled for this configuration.
void SetToyIndex(int index)
Set and gets the index of the current toy.
Int_t GetTreeIndex() const
Returns the index of the tree associated to this configuration in the TreeManager.
Double_t GetPOT()
This is the method used externaly. It corresponds to POT that passed beam and ND280 quality cuts...
Definition: Header.hxx:36
void SetCurrentTree(Int_t index)
Sets the current tree provided the index.
Definition: TreeManager.hxx:58
void FillToyVarsInMicroTrees()
Fill the standard configurations only toy-dependent variables.
void FillToyMatrixVar(Int_t index, Int_t var, Int_t comp1, Int_t comp2)
Fill a matrix analysis variable.
std::map< std::string, TrackCategoryDefinition * > & GetCategories()
Get the map of track categories.
void SetAnalysisPoint(enumAnalysisPoint point)
Set the point of the analysis at which AnalysisLoop is.
void SetNToys(Int_t tree_index, int ntoys)
Sets and gets the number of toy experiments for a given configuration.
void ApplyCorrections(AnaSpillC &spill)
Apply all corrections.
AnaSpillC & GetSpill()
Get the current spill (to have corrections and systematics applied to it).
std::string _inputFileName
Path to the input file, as defined by the user.
bool UndoEventVariations(AnaEventC &event)
Undo the event variation (Undo the variation, that is, go back to the previous values of modified obs...
void DisableAllEventWeights()
Disable all eventWeights.
std::string FindFirstFile(const std::string &infile_name, bool isROOTFile)
void ResetCurrentCategories()
Reset the properties of the current track.
virtual void Finalize()
[AnalysisAlgorithm_optional]
bool Apply(AnaEventC &event, bool &redo)
Apply all steps in the selection.
void PrintUsage(const std::string &programName)
void ReadParamOverrideFile(TString filename)
Definition: Parameters.cxx:192
void FillToyVar(Int_t index, Int_t var)
Fill a single analysis variable.
void DefineTruthTree()
Define the "truth" tree. See FillTruthTree().
void SetForceFillEventSummary(bool force)
std::string _inputSkimFileName
Path to the file with the list of events to skim, as defined by the user.
std::vector< ConfigurationBase * > & GetConfigurations()
return the vector of configurations
void DefineConfigurations()
Define the configurations (micro-trees) and which systematics should be applied in each "configuratio...
bool IsROOTFile(const std::string &infile_name)
Is this a ROOT file ?
Long64_t GetEntries()
Return the number of entries in the input file tree(s).
void FillVar(Int_t index, Float_t var)
Fill a single variable.
std::string _outputFileName
What to call the output file, as defined by the user.
void FillConfigTree()
Fill the "config" tree, which includes details of the analysis cuts etc.
bool _fillTrees
Whether to fill the trees and create an output file or not.
unsigned int GetNTypes()
Number of types defined for this category.
void ApplyEventVariations(const ToyExperiment &toy, AnaEventC &event)
Apply all EventVariations.
void FinalizeEvent(AnaEventC &event)
Delete the SystBox for all EventVariations.
void SetToyIndex(Int_t index)
Set and gets the index of the current toy experiment.
void EnableEventVariations(const std::vector< Int_t > &systs)
Enable the EventVariations registered with the given indices.
void FillMicroTrees()
Fill the standard configurations trees:
void SetVersionCheck(bool check)
Set version checking.
ToyExperiment * GetToyExperiment(UInt_t index)
Returns the Toy experiment with a given index.
Definition: ToyMaker.hxx:35
void DumpCorrections()
Dump all corrections.
std::vector< TTree *> & GetTrees()
Returns the map of trees.
Definition: TreeManager.hxx:25
bool FinalizeConfiguration()
std::vector< EventWeightBase * > & GetEventWeights()
Get the vector of EventWeights.
void AddMatrixVar(Int_t index, const std::string &name, const std::string &type, const std::string &doc, Int_t counter_index, const std::string &counter_name, int size1=-MAXVECTORSIZE, int size2=-1)
Add a matrix variable to all trees.
void CloseOutputFile()
close the output file
void InitializeToy()
void AddToyMatrixVar(Int_t index, const std::string &name, const std::string &type, const std::string &docstring, int ncomp1, int ncomp2)
Add a matrix analysis variable to all trees.
Int_t GetIndex() const
Returns the configuration index (should match the one in the Configuration Manager) ...
void EnableEventWeights(const std::vector< Int_t > &systs)
Enable the EventWeights registered with the given indices.
void MakeFinalSpill()
Creates a clone of the corrected Spill. This must be done after applying corrections.
UInt_t GetNMaxBranches()
Returns the maximum number of branches in all selections.
bool _enableTruthTree
Whether the "truth" tree should be filled. See FillTruthTree().
void Enable(bool enable=true)
Definition: MemoryUsage.cxx:14
virtual bool GetIsMC() const =0
Return whether this event is from Monte Carlo or not.
void FinalizeBunch()
void InitializeBunch()
void FinalizeEvent(const AnaEventC &event)
Delete the PreviousToyBox pointer for the last toy of the event for all enabled selections.
void EnableSystematics(const std::vector< Int_t > &indices)
Enable the systematic registered with the given name.
void AddVectorVar(Int_t index, const std::string &name, const std::string &type, const std::string &doc, Int_t counter_index, const std::string &counter_name, Int_t size=-MAXVECTORSIZE)
Add a vector variable to all trees.
void AddToyVectorVar(Int_t index, const std::string &name, const std::string &type, const std::string &docstring, int ncomp)
Add a vector analysis variable to all trees.
Weight_h ComputeEventWeights(const ToyExperiment &toy, const AnaEventC &event, const ToyBoxB &ToyBox)
Compute all eventWeights. Returns the total event normalization weight.
void FinalizeToyBase()
[AnalysisAlgorithm_mandatory]
void AddVariationSystematic(Int_t index, EventVariationBase *sys)
Register an EventVariationBase as a variation systematic.
void Write()
Write histograms of the memory usage to the output file.
Definition: MemoryUsage.cxx:27
bool LoadSpill(Long64_t &entry)
void SetReadParamOverrideFilePointPassed()
Set whether the point in which the overwride parameters file is read is passed or not...
Definition: Parameters.hxx:110
void ReadCorrections(const std::string &file, bool input=false)
Readthe corrections from a file.
Long64_t _entry
Fill the "truth" tree.
virtual const char * GetName() const
Return the name of this systematic. This overrides the TObject::GetName() interface.
bool InitializeSpill()
void CreateToyExperiments(const SystematicManager &syst)
Create the ToyExperiments using the ToyMaker and the SystematicManager.
bool FinalizeToy()
Called after each toy experiment is complete.
void ResetSpillToCorrected()
void InitializeEvent(AnaEventC &event)
Initialize the EventBox for all enabled selections.