HighLAND
SelectionBase.cxx
1 #include "SelectionBase.hxx"
2 #include "CoreUtils.hxx"
3 #include "MultiThread.hxx"
4 
5 ClassImp(SelectionBase)
6 
7 //********************************************************************
8 SelectionBase::SelectionBase(bool forceBreak, EventBoxId_h eventBoxId){
9 //********************************************************************
10 
11  _initialized=false;
12  _name="";
13  _enabled=true;
14 
15  _branchSequence.clear();
16  _branchAlias.clear();
17  _nEventsPassed.clear();
18 
19 #ifndef MULTITHREAD
20  for(unsigned int branch = 0; branch < NMAXBRANCHES; ++branch){
21  for(unsigned int cut = 0; cut < NMAXSTEPS; ++cut){
22  _cut_passed_stats[branch][cut] = 0;
23  }
24  }
25 #endif
26 
27  _nCutsInBranch.clear();
28 
29  // AddBranch(0, ConvertBranch(),"trunk");
30 
31  // whether to break or not the cut sequence when a cut is not passed
32  _forceBreak = forceBreak;
33 
34  /// By default EventSummary class is created and filled when the selection is passed. But this might be necessary also for events not passing the selection
35  /// The user can force the EventSummary to be filled always.
36  _forceFillEventSummary = false;
37 
38  // Initialised all run periods to be true - the selection will be applied to all run periods by default
39  // TODO: Really should use enumeration for run periods!!
40  for(int i = 0; i < 10; ++i){
41  _validRunPeriods[i] = true;
42  }
43 
44  // Initialze default pre-selection accum cut level to zero
45  _presel_accum_cut_level = 0;
46 
47  // The index of the selection in the selection manager (for enabled selections)
48  _selEnabledIndex=0;
49 
50  // detector in which the Fiducial Volume is defined, By default no detector is set
51  for (UInt_t b=0;b<NMAXBRANCHES;b++)
52  _detectorFV[b] = UNASSIGNEDID;
53 
54  // Set the EventBox to be used by this selection (kUnassigned by default)
55  _eventBoxId = eventBoxId;
56 }
57 
58 //********************************************************************
59 bool SelectionBase::HasBranch(Int_t ibranch, const std::string& fromMethod) const{
60 //********************************************************************
61 
62  if (ibranch<0 || ibranch>=(Int_t)GetNBranches()){
63  std::cout << "ERROR. SelectionBase::" << fromMethod << "() Unknown branch " << ibranch
64  << ". There are " << GetNBranches() << " branches in selection of type " << typeid(*this).name() << std::endl;
65  return false;
66  }
67  return true;
68 }
69 
70 //********************************************************************
71 void SelectionBase::SetDetectorFV(SubDetId_h det, Int_t ibranch) {
72 //********************************************************************
73 
74  if (ibranch==-1){
75  for (UInt_t b = 0; b<GetNBranches();b++)
76  _detectorFV[b]=det;
77  }
78  else if (!HasBranch(ibranch,"SetDetectorFV"))
79  exit(1);
80  else
81  _detectorFV[ibranch]=det;
82 }
83 
84 //********************************************************************
85 SubDetId_h SelectionBase::GetDetectorFV(Int_t ibranch) const {
86 //********************************************************************
87 
88  if (!HasBranch(ibranch,"GetDetectorFV")) exit(1);
89  return _detectorFV[ibranch];
90 }
91 
92 //********************************************************************
94 //********************************************************************
95 
96  // Don't do anything when the selection is already initialized
97  if (_initialized) return;
98 
99  // Define the selection steps
100  DefineSteps();
101 
102  // Define the detector Fiducial Volume in which the selection is applied
104 
105  // validate the selection. The program will exit if the selection is not correct
106  Validate();
107 
108  // Mark this selection as initialized
109  _initialized=true;
110 }
111 
112 //********************************************************************
114 //********************************************************************
115 
116  std::cout << "SelectionBase::Validate(). Validating selection '" << _name << "' of type " << typeid(*this).name() << " .....";
117 
118  // Validate all steps recursively
119  for (std::vector<StepBase*>::const_iterator it=_firstSteps.begin();it!=_firstSteps.end();it++){
120  (*it)->ValidateStepRecursive();
121  }
122 
123  if (_eventBoxId == UNASSIGNEDID){
124  std::cout << "ERROR. SelectionBase::Validate(). _eventBoxId is not set in this selection. Please use the constructor to specify the EventBox to be used. "
125  << "The standard way is to write something like 'numuCCSelection::numuCCSelection(bool forceBreak): SelectionBase(forceBreak,EventBoxId::kEventBoxTracker)'. "
126  << "_eventBoxId is a integer (not an enum) and therefor values in the EventBoxId.hxx file (in psycheEventModel) can be extended using a different enum" << std::endl;
127  exit(1);
128  }
129 
130  std::cout << " OK " << std::endl;
131 }
132 
133 //********************************************************************
135 //********************************************************************
136 
137 #ifndef MULTITHREAD
138  nevents=1;
139 #endif
140 
141  // Create the array of PreviousToyBox for a given number of events
142  PreviousToyBox = new ToyBoxB*[nevents];
143  for (Int_t k= 0;k<nevents;k++){
145 
146  // Calling the Reset method we check that it is implemented in the derived class (if the class is derived)
147  PreviousToyBox[k]->Reset();
148 
149  anaUtils::CreateArray(PreviousToyBox[k]->AccumLevel, GetNBranches(), 0);
150  anaUtils::CreateArray(PreviousToyBox[k]->BranchPassed, GetNBranches(), true);
152 
154 
155  // Set the DetectorFV into the ToyBox. By default the DetectorFV for a particular Toy is the one of the first branch in the selection.
156  // For selections in which the FV may change depending on the event and toy, this variable will be overwritten when applying the selection.
157  PreviousToyBox[k]->DetectorFV = _detectorFV[0];
158  }
159 }
160 
161 //********************************************************************
163 //********************************************************************
164 
165  Int_t uniqueID = 0;
166 
167 #ifdef MULTITHREAD
168  uniqueID = event.UniqueID;
169 #else
170  (void)event;
171 #endif
172 
173  // Reset the PreviousToyBox for the input event. This should be called after processing all toys for a given event
174  PreviousToyBox[uniqueID]->ResetBase(); // first the base class
175  PreviousToyBox[uniqueID]->Reset(); // then the derived class (if any)
176  PreviousToyBox[uniqueID]->MaxAccumLevel=-1;
177 
178 }
179 
180 //********************************************************************
182 //********************************************************************
183 
184  Int_t uniqueID = 0;
185 
186 #ifdef MULTITHREAD
187  uniqueID = event.UniqueID;
188 #else
189  (void)event;
190 #endif
191 
192  return *PreviousToyBox[uniqueID];
193 }
194 
195 //********************************************************************
197 //********************************************************************
198 
199 #ifdef MULTITHREAD
200  std::cout << "ERROR. SelectionBase::GetPreviousToyBox() with no Event provided cannot be called in MULTITHREAD mode " << std::endl;
201  exit(1);
202 #endif
203 
204  return *PreviousToyBox[0];
205 }
206 
207 //********************************************************************
208 bool SelectionBase::Apply(AnaEventC& event, bool& redo){
209 //********************************************************************
210 
211  //------ This function is called for each event and toy experiment ----------
212 
213  Int_t uniqueID = 0;
214 
215 #ifdef MULTITHREAD
216  uniqueID = event.UniqueID;
217 #endif
218 
219  // Retrieve the ToyBoxB to store intermediate objects
220  ToyBoxB* ToyBox = PreviousToyBox[uniqueID];
221 
222  // by default start from the first step
223  Int_t firstStepToApply=0;
224  // Check whether the selection has to be redone or not. To do that the ToyBox of the previous toy for this event should not have default values
225  // That means that this is not the first toy
226  if (ToyBox->MaxAccumLevel>-1){
227  // This method computes also the step from which the selection should be reapplied
228  redo = CheckRedoSelection(event, *ToyBox, firstStepToApply);
229  // if the selection does not have to be reapplied just return the success boolean of the previous toy: any of the branches succesfull
230  if (!redo) return (ToyBox->SuccessfulBranch!=-1);
231  }
232  else
234 
235 
236  // If we are here that means that the selection must be reapplied
237  redo=true;
238 
239  // Reset the ToyBox
240  if (firstStepToApply==0){
241  ToyBox->ResetBase(); // first the base class
242  ToyBox->Reset(); // then the derived class (if any)
243  }
244  else
245  ToyBox->SoftReset();
246  // Apply all steps from firstStepToApply. Returns true when all cuts are passed
247  bool ok = ApplySteps(event, *ToyBox, firstStepToApply);
248 
249  // Save the accum level of this toy
250  Int_t all_cuts_passed[NMAXBRANCHES];
251  for (UInt_t i=0;i<GetNBranches();i++){
252  if (ToyBox->BranchPassed[i]) ToyBox->SuccessfulBranch = i;
253  all_cuts_passed[i] = ToyBox->BranchPassed[i];
254  // If we pass one branch then say that the event passed the selection
255  if(all_cuts_passed[i]) ok = true;
256  }
257 
258  // By default EventSummary class is created and filled when the selection is passed. But this might be necessary also for events not passing the selection
259  // The user can force the EventSummary to be filled always by setting _forceFillEventSummary to true.
260  // TODO: return value of FillEventSummary ignored for the moment to solve bug 1160. Must check if there are side effects (bug 1164)
261  if (ok || _forceFillEventSummary){
262  // Tell the FillEventSummary which cuts were passed
263  FillEventSummary(event, all_cuts_passed);
264  }
265 
266  return ok;
267 }
268 
269 //********************************************************************
270 void SelectionBase::PrintStatistics() const{
271 //********************************************************************
272 
273  std::cout << "----------- Statistics for selection '" << _name << "'" << std::endl;
274 
275  UInt_t ID=0;
276  for (std::vector<std::string>::const_iterator it = _branchAlias.begin();it!=_branchAlias.end();it++, ID++){
277  PrintStatistics(ID);
278  }
279 }
280 
281 //********************************************************************
282 void SelectionBase::PrintStatistics(UInt_t ID) const{
283 //********************************************************************
284 
285 #ifndef MULTITHREAD
286  std::cout << "branch '" << GetBranchAlias(ID) << "' --> # events = " << _nEventsPassed[ID] << std::endl;
287  for(unsigned int cut = 0; cut < GetNCuts(ID); ++cut){
288  std::cout << "cut " << cut << " = " << _cut_passed_stats[ID][cut] << std::endl;
289  }
290 #else
291  std::cout << "SelectionBase::PrintStatistics(). No statistics can be printed in MULTITHREAD mode !!!" << std::endl;
292 #endif
293 }
294 
295 //********************************************************************
296 void SelectionBase::PrintStatistics(const std::string& name) const{
297 //********************************************************************
298 
299  UInt_t ID = GetBranchUniqueID(name);
300  PrintStatistics(ID);
301 }
302 
303 //********************************************************************
305 //********************************************************************
306 
307  int nBranches = GetNBranches();
308 
309  memset(&_current_cut[0], 0, nBranches *sizeof(_current_cut[0]));
310  memset(&_cut_passed[0][0], 0, nBranches*NMAXSTEPS*sizeof(_cut_passed[0][0]));
311 }
312 
313 //********************************************************************
314 bool SelectionBase::ApplyStep(AnaEventC& event, ToyBoxB& ToyBox, const StepBase& step, Int_t branch) {
315 //********************************************************************
316 
317  bool passed = step.Apply(event, ToyBox);
318  // If the step is not a cut it should return always true
319  if (step.Type() != StepBase::kCut){
320  CutPassed(passed, branch, ToyBox);
321  return true;
322  }
323 
324  return passed;
325 }
326 
327 //********************************************************************
328 bool SelectionBase::ApplyStepRecursive(AnaEventC& event, ToyBoxB& ToyBox, const StepBase& step, Int_t firstStepToApply) {
329 //********************************************************************
330 
331  // This function applies all steps recursively provided the first step
332 
333  // Apply the current step
334  // If the step is not a cut it should return always true
335 
336  // Steps below firstStepToApply are assumed to be already applied and passed
337  bool passed = true;
338  if (step.Index() >= firstStepToApply){
339  // Disabled actions (in all branches) are not applied
340  if (step.Type() == StepBase::kCut || !step.IsDisabledInBranch(0))
341  passed = step.Apply(event, ToyBox);
342  }
343 
344  // Deal with accum_level and individual steps passed
345  if (step.Type() == StepBase::kCut){
346  CutPassed(passed, step, ToyBox);
347 
348  // Stop applying steps when there is a break point.
349  // Or when _forceBreak == true (we are not interested about intermediate steps)
350  if (!passed && (step.Break() || _forceBreak)){
351  return false;
352  }
353  }
354 
355  for (UInt_t i = 0; i < step.GetNextSteps().size(); ++i){
356  StepBase* step2=step.GetNextSteps()[i];
357  bool passed2 = true;
358  if (step2) passed2 = ApplyStepRecursive(event,ToyBox,*step2, firstStepToApply);
359  // When a cut is not passed the final return must be false
360  if (passed) passed=passed2;
361  }
362 
363  return passed;
364 }
365 
366 //********************************************************************
367 bool SelectionBase::ApplySteps(AnaEventC& event, ToyBoxB& ToyBox, const std::string& branch, Int_t ifirst, Int_t ilast) {
368 //********************************************************************
369 
370  // This function applies steps in a given branch from step ifirst to step ilast
371 
372  // initialize the cut levels
374 
375  bool all_passed=true;
376 
377  // Get all steps in a given branch
378  std::vector<StepBase*> steps = GetStepsInBranch(branch);
379 
380  // Get the branch unique ID for a given branch name
381  UInt_t ID = GetBranchUniqueID(branch);
382 
383  // Loop over steps
384  Int_t ilast2 = std::min(ilast,(Int_t)steps.size());
385  for (Int_t i=ifirst;i<ilast2;i++ ){
386  bool passed = ApplyStep(event, ToyBox, *steps[i], ID);
387  if (!passed) all_passed=false;
388  // Don't continue when a given step(cut) has a break point
389  // Or when _forceBreak == true (we are not interested about intermediate steps)
390  if ((steps[i]->Break() || _forceBreak) && !passed) break;
391  }
392 
393  if (all_passed)
394  _nEventsPassed[ID]++;
395 
396  // TODO. This return value is not really used (yet !!!!)
397  return all_passed;
398 }
399 
400 //********************************************************************
401 bool SelectionBase::ApplySteps(AnaEventC& event, ToyBoxB& ToyBox, Int_t firstStepToApply) {
402 //********************************************************************
403 
404  // This function applies all steps in all branches
405 
406  // There should be at least one step
407  if ( _firstSteps.size() == 0) return false;
408 
409 #ifndef MULTITHREAD
410  // initialize the cut levels
412 #endif
413 
414  // Apply all steps recursively
415  bool ok = ApplyStepRecursive(event, ToyBox, **_firstSteps.begin(), firstStepToApply);
416 
417 #ifndef MULTITHREAD
418  // update the event selection statistics
419  for (UInt_t i=0; i<_nEventsPassed.size();i++){
420  if (ToyBox.BranchPassed[i]) _nEventsPassed[i]++;
421  }
422 #endif
423 
424  return ok;
425 }
426 
427 //********************************************************************
428 bool SelectionBase::CutPassed(bool ok, const StepBase& step, ToyBoxB& box) {
429 //********************************************************************
430 
431  // if the step is not a cut it's allways passed
432  if (step.Type() != StepBase::kCut) return true;
433 
434  // Get the list of branches unique IDs associated to this cut
435  const std::vector<UInt_t>& branches = step.GetBranchUniqueIDs();
436 
437  // Process each of the branches
438  for (UInt_t i = 0;i<branches.size();i++){
439  bool ok2=ok;
440  // If a cut is disabled in a given branch we assume it returns true for that branch
441  if (step.IsDisabledInBranch(branches[i])) ok2=true;
442  CutPassed(ok2, branches[i], box);
443  }
444 
445  return ok;
446 }
447 
448 //********************************************************************
449 bool SelectionBase::CutPassed(bool ok, Int_t branch, ToyBoxB& box) {
450 //********************************************************************
451 
452  if (ok){
453  // The event has passed all previous cuts and this one
454  if(box.BranchPassed[branch]){
455  box.AccumLevel[branch]++;
456 
457  // compute the max accum cut level from all branches
458  if (box.AccumLevel[branch]> box.MaxAccumLevel)
459  box.MaxAccumLevel = box.AccumLevel[branch];
460 
461 #ifndef MULTITHREAD
462  if (box.AccumLevel[branch]> _maxAccumLevelForAllToys)
463  _maxAccumLevelForAllToys = box.AccumLevel[branch];
464 #endif
465 
466  }
467 #ifndef MULTITHREAD
468  // the event has passed cut number "icut"
469  _cut_passed[branch][_current_cut[branch] ]=true;
470  _cut_passed_stats[branch][ _current_cut[branch] ]++;
471 #endif
472  }
473  else
474  box.BranchPassed[branch] = false;
475 
476  // increment the current cut in each branch
477  #ifndef MULTITHREAD
478  _current_cut[branch]++;
479 #endif
480 
481  return ok;
482 }
483 
484 //********************************************************************
486 //********************************************************************
487 
488  return (GetPreviousToyBox(event).MaxAccumLevel >= _presel_accum_cut_level);
489 }
490 
491 //********************************************************************
493 //********************************************************************
494 
495  /// Return the number of cuts of the branch with more cuts
496 
497  UInt_t nmaxcuts=0;
498  for (UInt_t i=0;i<GetNBranches();i++ )
499  if ( GetNCuts(i) > nmaxcuts) nmaxcuts=GetNCuts(i);
500 
501  return nmaxcuts;
502 }
503 
504 //********************************************************************
505 UInt_t SelectionBase::GetNCuts(Int_t ibranch) const{
506 //********************************************************************
507 
508  /// Return the number of cuts that have been added for a given branch
509  if (!HasBranch(ibranch,"GetNCuts")) return 0;
510  return _nCutsInBranch[ibranch];
511 }
512 
513 //********************************************************************
514 void SelectionBase::DumpSteps(const std::string& name, bool onlycuts) const{
515 //********************************************************************
516 
517  if (_branchAlias.size() ==0){
518  std::cout << "ERROR. SelectionBase::DumpSteps(). Cannot dump steps before setting the branch aliases" << std::endl;
519  exit(1);
520  }
521 
522  if (name==""){
523  std::vector<std::string>::const_iterator it;
524  for (it=_branchAlias.begin();it!=_branchAlias.end();it++)
525  DumpSteps(*it,onlycuts);
526  }
527  else{
528  Int_t ID = GetBranchUniqueID(name);
529  DumpSteps(ID,onlycuts);
530  }
531 }
532 
533 //********************************************************************
534 void SelectionBase::DumpSteps(Int_t ID, bool onlycuts) const{
535 //********************************************************************
536 
537  if (ID==-1){
538  std::vector<std::string>::const_iterator it;
539  for (it=_branchAlias.begin();it!=_branchAlias.end();it++)
540  DumpSteps(*it,onlycuts);
541  }
542  else{
543  if (ID >= (Int_t)GetNBranches() || ID<0){
544  std::cout << "SelectionBase::DumpSteps(). Branch with index " << ID << " does not exist in selection '"<< _name <<"' !!!" << std::endl;
545  return;
546  }
547 
548  std::vector<UInt_t> branch = GetBranchSequence(ID);
549  std::string alias = GetBranchAlias(ID);
550  std::string steps_cuts = "Steps";
551  std::stringstream sID;
552  sID << ID;
553 
554  std::string sbranch = "branch " + sID.str() + " --> " + ConvertBranchToString(branch) + " '" + alias + "'";
555 
556  if (onlycuts) steps_cuts = "Cuts";
557  if (_branchAlias.size()==1) sbranch = " with no branches";
558 
559  std::cout << "-------------------------------------------------------------------" << std::endl;
560  std::cout << " " << steps_cuts << " for selection '" << _name << "' " << sbranch << std::endl;
561  std::cout << "-------------------------------------------------------------------" << std::endl;
562 
563  char out[256];
564  sprintf(out,"%3s: %-10s %-25s %-6s %-10s", "#", "type", "title", "break", "branches");
565  std::cout << out << "\n" << std::endl;
566 
567  std::vector<StepBase*> steps = GetStepsInBranchWithDummy(branch);
568  UInt_t step=0;
569  for (UInt_t i=0;i<steps.size();i++ ){
570  if ((!onlycuts || steps[i]->Type() == StepBase::kCut) && steps[i]->Title()!="dummy"){
571  if (steps[i]->IsDisabledInBranch(ID))
572  sprintf(out,"%3d: %-10s %-25s %-6d ", step, (steps[i]->ConvertType()+" (D)").c_str(), steps[i]->Title().c_str(), (int)steps[i]->Break());
573  else
574  sprintf(out,"%3d: %-10s %-25s %-6d ", step, steps[i]->ConvertType().c_str(), steps[i]->Title().c_str(), (int)steps[i]->Break());
575  std::cout << out;
576  const std::vector<UInt_t>& IDs = steps[i]->GetBranchUniqueIDs();
577  for (UInt_t j=0;j<IDs.size();j++){
578  if (steps[i]->IsDisabledInBranch(IDs[j]))
579  std::cout << "("<<IDs[j] << ") ";
580  else
581  std::cout << IDs[j] << " ";
582  }
583  std::cout << std::endl;
584  step++;
585  }
586 
587  if (steps[i]->GetNextSteps().size()>1)
588  std::cout << "--- split with " << steps[i]->GetNextSteps().size() << " branches" << std::endl;
589  }
590  std::cout << "-------------------------------------------------------------------" << std::endl;
591 
592  }
593 }
594 
595 //********************************************************************
597 //********************************************************************
598 
599  std::cout << "-------------------------------------------------------------------" << std::endl;
600  std::cout << " Branches for selection '" << _name << "' " << std::endl;
601  std::cout << "-------------------------------------------------------------------" << std::endl;
602 
603  char out[256];
604  sprintf(out,"%3s: %-25s %-10s %-10s %-10s", "ID", "name", "Sequence", "#steps", "#cuts");
605  std::cout << out << "\n" << std::endl;
606 
607  for (Int_t ID=0;ID<(Int_t)GetNBranches();ID++){
608 
609  std::vector<UInt_t> branch = GetBranchSequence(ID);
610  std::string alias = GetBranchAlias(ID);
611  std::vector<StepBase*> steps = GetStepsInBranch(branch);
612 
613  sprintf(out,"%3d: %-25s %-10s %-10d %-10d", ID, alias.c_str(), ConvertBranchToString(branch).c_str(),(Int_t)steps.size(),GetNCuts(ID));
614  std::cout << out << std::endl;
615  }
616  std::cout << "-------------------------------------------------------------------" << std::endl;
617 
618 }
619 
620 
621 //********************************************************************
622 void SelectionBase::DisableStep(const std::string& title, Int_t ID) {
623 //********************************************************************
624 
625  Int_t ID2 = ID;
626  if (ID==-1) ID2=0;
627  StepBase* step = GetStep(title,ID2);
628  if (!step){
629  std::cout << "ERROR. SelectionBase::DisableStep(). Step with title '" << title << "' does not exist in branch "<< ID2 << std::endl;
630  exit(1);
631  }
632 
633  if (step->Type() == StepBase::kAction && ID!=-1){
634  std::cout << "ERROR. SelectionBase::DisableStep(). Action '" << title << "' cannot be disabled in a single branch. "
635  << "Actions should be disabled in all branches. Don't specify branch ID" << std::endl;
636  exit(1);
637  }
638 
639  if (ID==-1){
640  const std::vector<UInt_t> branches = step->GetBranchUniqueIDs();
641  for (UInt_t i=0;i<branches.size();i++)
642  step->DisableInBranch(i);
643  }
644  else
645  step->DisableInBranch(ID);
646 
647 }
648 
649 
650 //********************************************************************
651 void SelectionBase::RemoveStep(const std::string& title, Int_t ID) {
652 //********************************************************************
653 
654  Int_t ID2 = ID;
655  if (ID==-1) ID2=0;
656  StepBase* step = GetStep(title,ID2);
657  if (!step){
658  std::cout << "ERROR. SelectionBase::DisableStep(). Step with title '" << title << "' does not exist in branch "<< ID2 << std::endl;
659  exit(1);
660  }
661 
662  // Get the vector of next steps
663  const std::vector<StepBase*> nextSteps = step->GetNextSteps();
664 
665  if (nextSteps.size() > 1){
666  std::cout << "ERROR. SelectionBase::DisableStep(). Step with title '" << title << "' in branch "<< ID2
667  << " cannot be removed because it contains an split (with " << nextSteps.size() << " branches)" << std::endl;
668  exit(1);
669  }
670 
671  // If this is a first step
672  if (step->Index() == 0){
673 
674  if (ID2<0 || ID2 >= (Int_t)_firstSteps.size()){
675  std::cout << "ERROR. SelectionBase::RemoveStep(). branch " << ID2 << " not defined in first steps in selection '" << _name << "'" << std::endl;
676  exit(1);
677  }
678 
679  // This method removes a step with a given title (and branch ID) from the vector of next steps
680  if (_firstSteps[ID2]->Title() != title){
681  std::cout << "ERROR. SelectionBase::RemoveStep(). Selection '" << _name << "' does not have a first step '" << title << "' in branch " << ID2 << std::endl;
682  exit(1);
683  }
684 
685  // if there is step in firstSteps, the vector is emptied, otherwise the corresponding entry in the vector is set to NULL
686  // in order to keep the number of branches in the split
687  if (_firstSteps.size()==1)
688  _firstSteps.clear();
689  else
690  _firstSteps[ID2]=NULL;
691 
692  if (nextSteps.size()>0)
693  _firstSteps.push_back(nextSteps[0]);
694  }
695  else{
696  // Remove the step from the vector of next steps of the previous step
697  StepBase* previousStep = GetStepInBranch(ID2, step->Index()-1);
698  previousStep->RemoveNextStep(title,ID2);
699 
700  // Add the next step of the removed step to the vector of next steps of the previous step
701  if (nextSteps.size()>0)
702  previousStep->AddNextStep(nextSteps[0]);
703  }
704 
705  // get all steps with index above the one we removed and decrement the index by one unit
706  std::vector<StepBase*> nextSteps2;
707  step->GetNextSteps(nextSteps2,true);
708  for (std::vector<StepBase*>::iterator it=nextSteps2.begin();it!=nextSteps2.end();it++){
709  (*it)->SetIndex((*it)->Index()-1);
710  }
711 
712 }
713 
714 //********************************************************************
715 void SelectionBase::InsertStep(const std::string& previous_title, Int_t ID, StepBase::TypeEnum type, const std::string& title, StepBase* step, bool cut_break){
716 //********************************************************************
717 
718  (void) previous_title;
719  (void) ID;
720  (void) type;
721  (void) title;
722  (void) step;
723  (void) cut_break;
724 
725 /*
726  // get all steps with index above the one we removed and decrement the index by one unit
727  std::vector<StepBase*> nextSteps2;
728  step->GetNextSteps(nextSteps2,true);
729  for (std::vector<StepBase*>::iterator it=nextSteps2.begin();it!=nextSteps2.end();it++){
730  (*it)->SetIndex((*it)->Index()+1);
731  }
732 */
733 
734 }
735 
736 
737 //********************************************************************
738 void SelectionBase::ReplaceStep(const std::string& old_title, Int_t ID, StepBase::TypeEnum type, const std::string& title, StepBase* step, bool cut_break){
739 //********************************************************************
740 
741  // Remove the step old_title in branch ID
742  RemoveStep(old_title,ID);
743 
744  (void) type;
745  (void) title;
746  (void) step;
747  (void) cut_break;
748 
749 
750  // Insert a new step after step previous_title in branch ID
751  // InsertStep(previous_title,ID,type,title,step,cut_break);
752 }
753 
754 //********************************************************************
755 void SelectionBase::AddStep(Int_t b0, Int_t b1, Int_t b2, Int_t b3, Int_t b4, Int_t b5, Int_t b6, Int_t b7, StepBase::TypeEnum type, const std::string& title, StepBase* step, bool cut_break){
756 //********************************************************************
757  std::vector<UInt_t> branch = ConvertBranch(b0,b1,b2,b3,b4,b5,b6,b7);
758  AddStep(branch, type, title, step, cut_break);
759 }
760 
761 //********************************************************************
762 void SelectionBase::AddStep(Int_t b0, Int_t b1, Int_t b2, Int_t b3, Int_t b4, Int_t b5, Int_t b6, StepBase::TypeEnum type, const std::string& title, StepBase* step, bool cut_break){
763 //********************************************************************
764  std::vector<UInt_t> branch = ConvertBranch(b0,b1,b2,b3,b4,b5,b6);
765  AddStep(branch, type, title, step, cut_break);
766 }
767 
768 //********************************************************************
769 void SelectionBase::AddStep(Int_t b0, Int_t b1, Int_t b2, Int_t b3, Int_t b4, Int_t b5, StepBase::TypeEnum type, const std::string& title, StepBase* step, bool cut_break){
770 //********************************************************************
771  std::vector<UInt_t> branch = ConvertBranch(b0,b1,b2,b3,b4,b5);
772  AddStep(branch, type, title, step, cut_break);
773 }
774 
775 //********************************************************************
776 void SelectionBase::AddStep(Int_t b0, Int_t b1, Int_t b2, Int_t b3, Int_t b4, StepBase::TypeEnum type, const std::string& title, StepBase* step, bool cut_break){
777 //********************************************************************
778  std::vector<UInt_t> branch = ConvertBranch(b0,b1,b2,b3,b4);
779  AddStep(branch, type, title, step, cut_break);
780 }
781 
782 //********************************************************************
783 void SelectionBase::AddStep(Int_t b0, Int_t b1, Int_t b2, Int_t b3, StepBase::TypeEnum type, const std::string& title, StepBase* step, bool cut_break){
784 //********************************************************************
785  std::vector<UInt_t> branch = ConvertBranch(b0,b1,b2,b3);
786  AddStep(branch, type, title, step, cut_break);
787 }
788 
789 //********************************************************************
790 void SelectionBase::AddStep(Int_t b0, Int_t b1, Int_t b2, StepBase::TypeEnum type, const std::string& title, StepBase* step, bool cut_break){
791 //********************************************************************
792  std::vector<UInt_t> branch = ConvertBranch(b0,b1,b2);
793  AddStep(branch, type, title, step, cut_break);
794 }
795 
796 //********************************************************************
797 void SelectionBase::AddStep(Int_t b0, Int_t b1, StepBase::TypeEnum type, const std::string& title, StepBase* step, bool cut_break){
798 //********************************************************************
799  std::vector<UInt_t> branch = ConvertBranch(b0,b1);
800  AddStep(branch, type, title, step, cut_break);
801 }
802 
803 //********************************************************************
804 void SelectionBase::AddStep(Int_t b0, StepBase::TypeEnum type, const std::string& title, StepBase* step, bool cut_break){
805 //********************************************************************
806  std::vector<UInt_t> branch = ConvertBranch(b0);
807  AddStep(branch, type, title, step, cut_break);
808 }
809 
810 //********************************************************************
811 void SelectionBase::AddStep(StepBase::TypeEnum type, const std::string& title, StepBase* step, bool cut_break){
812 //********************************************************************
813  std::vector<UInt_t> branch = ConvertBranch();
814  AddStep(branch, type, title, step, cut_break);
815 }
816 
817 //********************************************************************
818 void SelectionBase::AddStep(const std::vector<UInt_t>& branch, StepBase::TypeEnum type, const std::string& title, StepBase* step, bool cut_break){
819 //********************************************************************
820 
821  // Check that no step exist in the same branch with this title
822  std::vector<StepBase*> steps = GetStepsInBranchWithDummy(branch);
823  for (UInt_t i=0;i<steps.size();i++){
824  if (steps[i]->Title() == title){
825  std::cout << "ERROR. SelectionBase::AddStep(). An step with title '" << title << "' already exists in this branch " << ConvertBranchToString(branch)
826  << " at position " << i << " in selection of type " << typeid(*this).name() << std::endl;
827  exit(1);
828  }
829  }
830 
831  // Set the type (cut or action)
832  step->SetType(type);
833 
834  // Set the title (a nice name to be displayed in plots)
835  step->SetTitle(title);
836 
837  // Set the cut break (only for cuts)
838  if (step->Type() == StepBase::kCut)
839  step->SetBreak(cut_break);
840 
841  // Add the step
842  AddStep(branch, step);
843 }
844 
845 //********************************************************************
846 void SelectionBase::AddStep(const std::vector<UInt_t>& branch, StepBase* step){
847 //********************************************************************
848 
849  Int_t index=0;
850 
851  if (_firstSteps.size() ==0){
852  // Add the first step
853  _firstSteps.push_back(step);
854  if (step->Title()=="dummy") index=-1;
855  }
856  else if (_firstSteps.size() >1 && !_firstSteps[branch[0]]){
857  _firstSteps[branch[0]] = step;
858  }
859  else{
860  // Get the last step added to this branch sequence
861  StepBase* laststep = GetLastStepInBranch(branch);
862 
863  if (!laststep) return;
864  if (branch.size()==0)
865  // Add the step to trunk
866  laststep->AddNextStep(step);
867  else {
868  // Add the step to branch
869  laststep->AddNextStep(step, branch[branch.size()-1]);
870  }
871  index = laststep->Index()+1;
872  }
873 
874  // Set the step index
875  step->SetIndex(index);
876 }
877 
878 //********************************************************************
879 void SelectionBase::AddSteps(const std::vector<UInt_t>& branch, const std::vector<StepBase*>& steps){
880 //********************************************************************
881 
882  for (std::vector<StepBase*>::const_iterator it= steps.begin(); it!=steps.end();it++){
883  AddStep(branch, *it);
884  }
885 }
886 
887 //********************************************************************
888 void SelectionBase::AddSplit(UInt_t nbranches, Int_t b0, Int_t b1, Int_t b2, Int_t b3, Int_t b4, Int_t b5, Int_t b6, Int_t b7){
889 //********************************************************************
890 
891  std::vector<UInt_t> branch = ConvertBranch(b0,b1,b2,b3,b4,b5,b6,b7);
892  AddSplit(nbranches,branch);
893 }
894 
895 //********************************************************************
896 void SelectionBase::AddSplit(UInt_t nbranches, const std::vector<UInt_t>& branch_seq){
897 //********************************************************************
898 
899  // When there are no steps yet we should add a dummy one such that NULL steps can be added to this when doing AddSplit
900  if (_firstSteps.size() ==0){
901  AddStep(StepBase::kAction, "dummy", new StepBase(), false);
902  }
903 
904  std::cout << "SelectionBase::AddSplit(). Add split with " << nbranches << " branches to branch "<< ConvertBranchToString(branch_seq) << std::endl;
905 
906  // Get the last step in the branch sequence
907  StepBase* laststep = GetLastStepInBranch(branch_seq);
908  if (!laststep) return;
909 
910  if (laststep->GetNextSteps().size() !=0){
911  std::cout << "SelectionBase::AddSplit(). Last step in branch " << ConvertBranchToString(branch_seq) << " with title '" << laststep->Title() << "'"
912  << " already has an split with " << laststep->GetNextSteps().size() << " branches !!!!" << std::endl;
913  return;
914  }
915 
916  // Add "nbranches" NULL steps to the last step
917  for (UInt_t i=0;i<nbranches;i++){
918  laststep->AddNextStep(NULL);
919  // Add a branch, but only when this is a first level split
920  // AddBranch(i, branch_seq);
921  }
922 }
923 
924 //********************************************************************
925 std::vector<StepBase*> SelectionBase::GetStepsInBranch(const std::vector<UInt_t>& branch, UInt_t first, UInt_t last) const{
926 //********************************************************************
927 
928  std::vector<StepBase*> steps = GetStepsInBranchWithDummy(branch, first, last);
929  if ((*steps.begin())->Title()=="dummy")
930  steps.erase(steps.begin());
931  return steps;
932 }
933 
934 //********************************************************************
935 std::vector<StepBase*> SelectionBase::GetStepsInBranchWithDummy(const std::vector<UInt_t>& branch, UInt_t first, UInt_t last) const{
936 //********************************************************************
937 
938  std::vector<StepBase*> steps;
939 
940  // three different cases
941 
942  // 1. No steps were added yet, return an empty vector
943  if ( _firstSteps.size() ==0) return steps;
944 
945  // Get all steps from trunk (up to first split)
946  if ( _firstSteps.size() == 1){
947  steps.push_back(*_firstSteps.begin());
948  if (*steps.rbegin())
949  (*steps.rbegin())->GetNextSteps(steps);
950  }
951 
952  StepBase::BranchStatus status= StepBase::BranchOK;
953  for (UInt_t i=0;i<branch.size();i++){
954  // 2. There is one split at the beginning of the step sequence
955  if (i==0 && _firstSteps.size() > 1){
956  steps.push_back(_firstSteps[branch[0]]);
957  if (*steps.rbegin()) status = (*steps.rbegin())->GetNextStepsInBranch(steps,branch[i]); // Get all steps up to (i+1)th split
958  status=StepBase::BranchOK;
959  }
960  // 3. If there is no split at the beginning of the step sequence just go through all the branches collecting steps recursively
961  else {
962  if (status==StepBase::BranchOK && *steps.rbegin()){
963  status = (*steps.rbegin())->GetNextStepsInBranch(steps,branch[i]); // Get all steps up to (i+1)th split
964  if ((status == StepBase::NoBranches && i>0)||
965  (status == StepBase::BranchEmpty && i<branch.size()-1) ||
966  (status == StepBase::BranchOutOfRange)){
967  std::cout << "ERROR. SelectionBase::GetStepsInBranchWithDummy(). Branch " << ConvertBranchToString(branch)
968  << " does not exist in selection of type " << typeid(*this).name() << ". ";
969  if (status==StepBase::NoBranches && i>0){
970  std::cout << "Branch " << ConvertBranchToString(branch,i-1) << " has no split" << std::endl;
971  }
972  else if (status == StepBase::BranchEmpty && i<branch.size()-1){
973  std::cout << "Branch " << ConvertBranchToString(branch,i) << " has no split" << std::endl;
974  }
975  else if (status == StepBase::BranchOutOfRange){
976  std::cout << "Last number in " << ConvertBranchToString(branch,i) << " is out of range" << std::endl;
977  }
978  exit(1);
979  }
980  }
981  }
982  }
983 
984 
985  if (first==0 && last==NMAXSTEPS-1){
986  // Return all steps in this branch
987  return steps;
988  }
989  else{
990  UInt_t first2 = first;
991  UInt_t last2 = last;
992  UInt_t size2 = steps.size();
993 
994  if (_firstSteps[0]->Title()=="dummy"){
995  first2++;
996  last2++;
997  size2--;
998  }
999  // Return only from step "first" to step "last"
1000  std::vector<StepBase*> steps2;
1001  if (first>=size2){
1002  std::cout << "SelectionBase::GetStepsInBranchWithDummy(). Invalid first step " << first << ", there are " << size2 << " steps !!!" << std::endl;
1003  return steps2;
1004  }
1005  if (last>=size2){
1006  std::cout << "SelectionBase::GetStepsInBranchWithDummy(). Invalid last step " << last << ", there are " << size2 << " steps !!!" << std::endl;
1007  return steps2;
1008  }
1009  if (last<first){
1010  std::cout << "SelectionBase::GetStepsInBranchWithDummy(). Last step " << last << " smaller than first step " << size2 << " !!!" << std::endl;
1011  return steps2;
1012  }
1013 
1014  for (UInt_t i=first2;i<=last2;i++)
1015  steps2.push_back(steps[i]);
1016  return steps2;
1017  }
1018 }
1019 
1020 //********************************************************************
1021 std::vector<StepBase*> SelectionBase::GetStepsInBranch(const std::string& name, UInt_t first, UInt_t last) const{
1022 //********************************************************************
1023 
1024  std::vector<UInt_t> branch = GetBranchSequence(name);
1025  return GetStepsInBranch(branch,first,last);
1026 }
1027 
1028 //********************************************************************
1029 std::vector<StepBase*> SelectionBase::GetStepsInBranch(UInt_t ID, UInt_t first, UInt_t last) const{
1030 //********************************************************************
1031 
1032  std::vector<UInt_t> branch = GetBranchSequence(ID);
1033  return GetStepsInBranch(branch,first,last);
1034 }
1035 
1036 //********************************************************************
1037 std::vector<StepBase*> SelectionBase::GetCutsInBranch(UInt_t ID) const{
1038 //********************************************************************
1039 
1040  std::vector<StepBase*> cuts;
1041  std::vector<StepBase*> steps = GetStepsInBranch(ID);
1042  for (std::vector<StepBase*>::iterator it=steps.begin();it!=steps.end();it++){
1043  if ((*it)->Type() == StepBase::kCut) cuts.push_back(*it);
1044  }
1045 
1046  return cuts;
1047 }
1048 
1049 //********************************************************************
1050 std::vector<StepBase*> SelectionBase::GetCutsInBranch(const std::string& name) const{
1051 //********************************************************************
1052 
1053  UInt_t ID = GetBranchUniqueID(name);
1054  return GetCutsInBranch(ID);
1055 }
1056 
1057 //********************************************************************
1058 StepBase* SelectionBase::GetLastStepInBranch(const std::vector<UInt_t>& branch) const{
1059 //********************************************************************
1060 
1061  // get the vector of steps in this branch sequence
1062  std::vector<StepBase*> steps = GetStepsInBranchWithDummy(branch);
1063 
1064  // returns the last step if exists
1065  if (steps.size()!=0)
1066  return *(steps.rbegin());
1067  else{
1068  return NULL;
1069  }
1070 }
1071 
1072 //********************************************************************
1073 StepBase* SelectionBase::GetLastStepInBranch(Int_t b0, Int_t b1, Int_t b2, Int_t b3, Int_t b4, Int_t b5, Int_t b6, Int_t b7) const{
1074 //********************************************************************
1075 
1076  std::vector<UInt_t> branch = ConvertBranch(b0,b1,b2,b3,b4,b5,b6,b7);
1077  return GetLastStepInBranch(branch);
1078 }
1079 
1080 //********************************************************************
1081 StepBase* SelectionBase::GetLastStepInBranch(const std::string& name) const{
1082 //********************************************************************
1083 
1084  std::vector<UInt_t> branch = GetBranchSequence(name);
1085  return GetLastStepInBranch(branch);
1086 }
1087 
1088 
1089 //********************************************************************
1090 StepBase* SelectionBase::GetStepInBranch(const std::vector<UInt_t>& branch, UInt_t index) const{
1091 //********************************************************************
1092 
1093  std::vector<StepBase*> steps = GetStepsInBranch(branch, index, index);
1094  if (steps.size()!=0)
1095  return *(steps.begin());
1096  else{
1097  return NULL;
1098  }
1099 }
1100 
1101 //********************************************************************
1102 StepBase* SelectionBase::GetStepInBranch(const std::string& name, UInt_t index) const{
1103 //********************************************************************
1104 
1105  std::vector<StepBase*> steps = GetStepsInBranch(name, index, index);
1106  if (steps.size()!=0)
1107  return *(steps.begin());
1108  else{
1109  return NULL;
1110  }
1111 }
1112 
1113 //********************************************************************
1114 StepBase* SelectionBase::GetStepInBranch(UInt_t ID, UInt_t index) const{
1115 //********************************************************************
1116 
1117  std::vector<StepBase*> steps = GetStepsInBranch(ID, index, index);
1118  if (steps.size()!=0)
1119  return *(steps.begin());
1120  else{
1121  return NULL;
1122  }
1123 }
1124 
1125 //********************************************************************
1126 std::vector<UInt_t> SelectionBase::ConvertBranch(Int_t b0, Int_t b1, Int_t b2, Int_t b3, Int_t b4, Int_t b5, Int_t b6, Int_t b7) const{
1127 //********************************************************************
1128 
1129  std::vector<UInt_t> branch;
1130  if (b0>=0) branch.push_back(b0);
1131  if (b1>=0) branch.push_back(b1);
1132  if (b2>=0) branch.push_back(b2);
1133  if (b3>=0) branch.push_back(b3);
1134  if (b4>=0) branch.push_back(b4);
1135  if (b5>=0) branch.push_back(b5);
1136  if (b6>=0) branch.push_back(b6);
1137  if (b7>=0) branch.push_back(b7);
1138 
1139  return branch;
1140 }
1141 
1142 //********************************************************************
1143 std::string SelectionBase::ConvertBranchToString(const std::vector<UInt_t>& branch, Int_t upToSplit) const{
1144 //********************************************************************
1145 
1146  if (branch.size()==0) return "'trunk'";
1147 
1148  std::stringstream os;
1149 
1150  UInt_t nsplits = branch.size();
1151  if (upToSplit>=0 && (UInt_t)upToSplit<branch.size())
1152  nsplits=(UInt_t)upToSplit+1;
1153  else if (upToSplit!=-1){
1154  std::cout << "ERROR. SelectionBase::ConvertBranchToString(). Branch sequence " << ConvertBranchToString(branch) << " has less than " << upToSplit+1 << " splits !!!" << std::endl;
1155  exit(1);
1156  }
1157 
1158 
1159  os << "(";
1160  for (UInt_t i=0;i<nsplits;i++){
1161  if (i>0) os<< ",";
1162  os << branch[i];
1163  }
1164  os << ")";
1165 
1166  return os.str();
1167 
1168 }
1169 
1170 //********************************************************************
1171 void SelectionBase::AddBranch(Int_t ibranch, const std::vector<UInt_t>& branch_seq, const std::string& alias){
1172 //********************************************************************
1173 
1174  // associate the branch unique ID with the branch alias (branch1, branch2, ...)
1175  // This is just a default name, that can be changed later
1176  if (alias==""){
1177  char branch[50];
1178  sprintf(branch, "branch%d", ibranch);
1179  _branchAlias.push_back(branch);
1180  }
1181  else
1182  _branchAlias.push_back(alias);
1183 
1184  // associate the branch unique ID with the branch sequence
1185  _branchSequence.push_back(branch_seq);
1186 
1187  // Initialize the event counter for this branch
1188  _nEventsPassed.push_back(0);
1189 
1190  // get the vector of steps in this branch sequence
1191  std::vector<StepBase*> steps = GetStepsInBranchWithDummy(branch_seq);
1192  if (steps.size()==0) return;
1193 
1194  // Add the branch uniqueID to all steps in this branch
1195  AddBranchUniqueID(steps, ibranch);
1196 
1197  //Store the number of cuts in each branch such that we don't have to recomput it everytime
1198  _nCutsInBranch.push_back(GetCutsInBranch(ibranch).size());
1199 }
1200 
1201 //********************************************************************
1202 void SelectionBase::SetBranchAlias(Int_t ID, const std::string& name, Int_t b0, Int_t b1, Int_t b2, Int_t b3, Int_t b4, Int_t b5, Int_t b6, Int_t b7){
1203 //********************************************************************
1204 
1205  /*
1206  A full branch is defined by a branching sequence, that is the branch to be taken in each split.
1207  But we can set a unique ID for the full branch and a name. In that way we can for example apply all steps
1208  in a given branch by specifying the ID or the name.
1209  */
1210 
1211  // Check that this branch has the correct ID
1212  if (ID != (Int_t)(_branchSequence.size())){
1213  std::cout << "ERROR. SelectionBase::SetBranchAlias(). Invalid branch unique ID " << ID << " for branch with alias '"<< name << "' . It should be " << _branchSequence.size() << std::endl;
1214  exit(1);
1215  }
1216 
1217  // Check that the branch has not an alias already in use
1218  for (UInt_t i=0;i<_branchAlias.size();i++){
1219  if (_branchAlias[i] == name ){
1220  std::cout << "ERROR. SelectionBase::SetBranchAlias(). Alias '" << name << "' cannot be used for branch " << ID << " since is already used for branch " << i << std::endl;
1221  exit(1);
1222  }
1223  }
1224 
1225 
1226  // Convert the branch sequence with individual integers into a vector of integers
1227  std::vector<UInt_t> branch_seq = ConvertBranch(b0, b1, b2, b3, b4, b5, b6, b7);
1228 
1229  // get the vector of steps in this branch sequence
1230  // std::vector<StepBase*> steps = GetStepsInBranch(branch_seq);
1231  // if (steps.size()==0) return;
1232 
1233  // Add the branch uniqueID to all steps in this branch
1234  // AddBranchUniqueID(steps, ID);
1235 
1236  AddBranch(ID,branch_seq,name);
1237 
1238  // associate the branch unique ID with the branch alias
1239  _branchAlias[ID] = name;
1240 
1241  // associate the branch unique ID with the branch sequence
1242  _branchSequence[ID] = branch_seq;
1243 
1244 
1245 }
1246 
1247 //********************************************************************
1248 void SelectionBase::AddBranchUniqueID(std::vector<StepBase*>& steps, UInt_t ID){
1249 //********************************************************************
1250 
1251  std::vector<StepBase*>::iterator it;
1252  for (it=steps.begin();it!=steps.end();it++){
1253  if (*it) (*it)->AddBranchUniqueID(ID);
1254  }
1255 }
1256 
1257 //********************************************************************
1258 std::vector<UInt_t> SelectionBase::GetBranchSequence(Int_t ID) const{
1259 //********************************************************************
1260 
1261  if (ID<0 || ID >= (Int_t)_branchSequence.size()){
1262  std::cout << "ERROR. SelectionBase::GetBranchSequence(). Branch with index " << ID << " does not exist in selection '"<< _name <<"' !!!" << std::endl;
1263  exit(1);
1264  }
1265  return _branchSequence[ID];
1266 }
1267 
1268 //********************************************************************
1269 std::vector<UInt_t> SelectionBase::GetBranchSequence(const std::string& name) const{
1270 //********************************************************************
1271 
1272  Int_t ID = GetBranchUniqueID(name);
1273  return GetBranchSequence(ID);
1274 }
1275 
1276 //********************************************************************
1277 Int_t SelectionBase::GetBranchUniqueID(const std::string& name) const{
1278 //********************************************************************
1279 
1280  Int_t ID = 0;
1281  for (std::vector<std::string>::const_iterator it=_branchAlias.begin();it!=_branchAlias.end();it++, ID++){
1282  if (*it == name) return ID;
1283  }
1284 
1285  std::cout << "ERROR. SelectionBase::GetBranchUniqueID(). Branch with alias '" << name << "' does not exist in selection '"<< _name <<"' of type " << typeid(*this).name() << std::endl;
1286  exit(1);
1287 
1288  return -1;
1289 }
1290 
1291 //********************************************************************
1292 std::string SelectionBase::GetBranchAlias(Int_t ID) const{
1293 //********************************************************************
1294 
1295  if (ID<0 || ID >= (Int_t)_branchAlias.size()) return "";
1296  return _branchAlias[ID];
1297 }
1298 
1299 //********************************************************************
1300 std::vector<std::string> SelectionBase::GetCutNames(Int_t ID) const{
1301 //********************************************************************
1302 
1303  std::vector<std::string> cut_names;
1304  std::vector<StepBase*> steps = GetStepsInBranch(ID);
1305  for (std::vector<StepBase*>::iterator it=steps.begin();it!=steps.end();it++){
1306  if ((*it)->Type() == StepBase::kCut) cut_names.push_back((*it)->Title());
1307  }
1308  return cut_names;
1309 }
1310 
1311 //********************************************************************
1312 std::vector<std::string> SelectionBase::GetStepNames(Int_t ID) const{
1313 //********************************************************************
1314 
1315  std::vector<std::string> step_names;
1316  std::vector<StepBase*> steps = GetStepsInBranch(ID);
1317  for (std::vector<StepBase*>::iterator it=steps.begin();it!=steps.end();it++){
1318  step_names.push_back((*it)->Title());
1319  }
1320  return step_names;
1321 }
1322 
1323 
1324 //********************************************************************
1325 Int_t SelectionBase::GetCutNumber(const std::string& title, Int_t ID) const{
1326 //********************************************************************
1327 
1328  Int_t icut=-1;
1329  std::vector<StepBase*> steps = GetStepsInBranch(ID);
1330  for (std::vector<StepBase*>::iterator it=steps.begin();it!=steps.end();it++){
1331  if ((*it)->Type() == StepBase::kCut) icut ++;
1332  if ((*it)->Title() == title) break;
1333  }
1334  return icut;
1335 }
1336 
1337 //********************************************************************
1338 Int_t SelectionBase::GetStepNumber(const std::string& title, Int_t ID) const{
1339 //********************************************************************
1340 
1341  StepBase* step = GetStep(title,ID);
1342  if (step) return step->Index();
1343  else{
1344  std::cout << "ERROR. SelectionBase::GetStepNumber(). Step with title '" << title << "' does not exist in branch "<< ID << std::endl;
1345  exit(1);
1346  }
1347 }
1348 
1349 //********************************************************************
1350 StepBase* SelectionBase::GetStep(const std::string& title, Int_t ID) const{
1351 //********************************************************************
1352 
1353  std::vector<StepBase*> steps = GetStepsInBranch(ID);
1354  for (std::vector<StepBase*>::iterator it=steps.begin();it!=steps.end();it++){
1355  if ((*it)->Title() == title) return *it;
1356  }
1357  return NULL;
1358 }
1359 
1360 //********************************************************************
1361 void SelectionBase::CopySteps(SelectionBase& sel1, UInt_t branchID1, UInt_t first, UInt_t last, const std::vector<UInt_t>& branch2){
1362 //********************************************************************
1363 
1364  // Initialize the input selection
1365  sel1.Initialize();
1366 
1367  // Get the steps from the first selection
1368  std::vector<StepBase*> steps1 = sel1.GetStepsInBranch(branchID1, first, last);
1369 
1370  // Add a clone of the steps of the first selection to the second selection
1371  for (UInt_t i=0;i<steps1.size();i++){
1372  StepBase* step = steps1[i];
1373  StepBase* stepC = step->MakeClone();
1374  if (typeid(*stepC) != typeid(*step)){
1375  std::cout << "ERROR. SelectionBase::CopySteps(). Error when cloning step '" << step->Title() <<"' in selection of type '" << typeid(*this).name() << "'" << std::endl;
1376  std::cout << " ---> Incompatiple types " << typeid(*stepC).name() << " and " << typeid(*step).name() << std::endl;
1377  std::cout << " ---> Please correct the MakeClone() method of this step" << std::endl;
1378  exit(1);
1379  }
1380  AddStep(branch2,step->Type(), step->Title(), stepC, step->Break());
1381  }
1382 
1383 }
1384 
1385 //********************************************************************
1386 void SelectionBase::CopySteps(SelectionBase& sel1, UInt_t branchID1, UInt_t first, UInt_t last, Int_t b0, Int_t b1, Int_t b2, Int_t b3, Int_t b4, Int_t b5, Int_t b6, Int_t b7){
1387 //********************************************************************
1388 
1389  CopySteps(sel1, branchID1, first, last, ConvertBranch(b0,b1,b2,b3,b4,b5,b6,b7));
1390 
1391 }
1392 
1393 //********************************************************************
1394 void SelectionBase::CopySteps(SelectionBase& sel1, const std::string& sbranch1, UInt_t first, UInt_t last, Int_t b0, Int_t b1, Int_t b2, Int_t b3, Int_t b4, Int_t b5, Int_t b6, Int_t b7){
1395 //********************************************************************
1396 
1397  // Initialize the input selection
1398  sel1.Initialize();
1399 
1400  CopySteps(sel1, sel1.GetBranchUniqueID(sbranch1), first, last, ConvertBranch(b0,b1,b2,b3,b4,b5,b6,b7));
1401 }
1402 
1403 //********************************************************************
1404 void SelectionBase::CopySteps(SelectionBase& sel1, const std::string& sbranch1){
1405 //********************************************************************
1406 
1407  // Initialize the input selection
1408  sel1.Initialize();
1409 
1410  if (sbranch1=="trunk" && sel1.GetNBranches() != 1){
1411  std::cout << "ERROR. SelectionBase::CopySteps(). Selection of type " << typeid(sel1).name() << " has " << sel1.GetNBranches()
1412  << " branches. Branch ID or name must be specified: CopySteps(SelectionBase& sel1, const std::string& sbranch1 ...) " << std::endl;
1413  exit(1);
1414  }
1415 
1416  // Copy all steps
1417  std::vector<StepBase*> steps1 = sel1.GetStepsInBranch(sbranch1);
1418  CopySteps(sel1,sbranch1,0,steps1.size()-1,0);
1419 }
1420 
1421 //********************************************************************
1422 void SelectionBase::CopyStep(SelectionBase& sel1, const std::string& sbranch1, UInt_t istep, Int_t b0, Int_t b1, Int_t b2, Int_t b3, Int_t b4, Int_t b5, Int_t b6, Int_t b7){
1423 //********************************************************************
1424 
1425  // Copy only one step
1426  CopySteps(sel1,sbranch1,istep,istep,b0,b1,b2,b3,b4,b5,b6,b7);
1427 }
1428 
1429 //********************************************************************
1430 void SelectionBase::SetValidRunPeriods(std::string runPeriods){
1431 //********************************************************************
1432 
1433  // First, set them all to false, since they are initialised to true
1434  for(int i = 0; i < 10; ++i){
1435  _validRunPeriods[i] = false;
1436  }
1437 
1438  // Now, parse the runPeriods string
1439  std::stringstream ss(runPeriods);
1440  int i;
1441 
1442  while (ss >> i){
1443  // If the selection is valid for this run period then set the corresponding array entry to be true
1444  _validRunPeriods[i] = true;
1445  // If the next character in the string is a comma, ignore it
1446  if (ss.peek() == ',') ss.ignore();
1447  }
1448 }
1449 
1450 
1451 
1452 
1453 
1454 
1455 
bool _validRunPeriods[10]
bool _cut_passed[NMAXBRANCHES][NMAXSTEPS]
The cuts that were passed.
std::string _name
The name of the selection.
std::vector< StepBase * > _firstSteps
The top level steps in the trunk.
Int_t Index() const
Return the index of this step.
Definition: StepBase.hxx:72
void DumpBranches() const
Dumps the list of branches.
Int_t GetStepNumber(const std::string &title, Int_t ID=0) const
Return the step number (starting at 0) corresponding to an step with a given title.
StepBase * GetLastStepInBranch(Int_t b0=-1, Int_t b1=-1, Int_t b2=-1, Int_t b3=-1, Int_t b4=-1, Int_t b5=-1, Int_t b6=-1, Int_t b7=-1) const
Get the last step in a given branch provided the branch sequence (individual integers) ...
void AddBranchUniqueID(std::vector< StepBase *> &steps, UInt_t ibranch)
Add a branch unique ID to all steps in that branch.
Int_t _selEnabledIndex
The index of the selection in the selection manager (for enabled selections)
bool ApplyStep(AnaEventC &event, ToyBoxB &box, const StepBase &step, Int_t branch=-1)
std::string GetBranchAlias(Int_t ID) const
Gets the branch alias for a given branch unique ID.
Int_t MaxAccumLevel
Definition: ToyBoxB.hxx:39
void DumpSteps(const std::string &branch="", bool onlycuts=false) const
Print out the index, name and title of each step for a given branch (no argument for all branches) ...
void CopyStep(SelectionBase &sel1, const std::string &sbranch1, UInt_t istep, Int_t b0=-1, Int_t b1=-1, Int_t b2=-1, Int_t b3=-1, Int_t b4=-1, Int_t b5=-1, Int_t b6=-1, Int_t b7=-1)
Copy a clone of the steps with number istep from branch sbranch1 in selection ssel1 to sbranch2 in se...
void CopySteps(SelectionBase &sel1, UInt_t branchID1, UInt_t first, UInt_t last, Int_t b0=-1, Int_t b1=-1, Int_t b2=-1, Int_t b3=-1, Int_t b4=-1, Int_t b5=-1, Int_t b6=-1, Int_t b7=-1)
Copy a clone of the steps in range first-last from branch sbranch1 in selection ssel1 to sbranch2 in ...
UInt_t GetNMaxCuts() const
Return the number of steps in a given branch.
const std::vector< StepBase * > & GetNextSteps() const
Returns the vector of next steps.
Definition: StepBase.hxx:87
std::vector< std::string > GetStepNames(Int_t ibranch=0) const
Return all the names of the steps, in the order they were added.
EventBoxId_h _eventBoxId
The ID of the EventBox to be used.
Int_t SelectionEnabledIndex
The enabled index of this selection this ToyBox belongs to.
Definition: ToyBoxB.hxx:49
const std::vector< UInt_t > & GetBranchUniqueIDs() const
Returns the vector of branche unique IDs associated to this step.
Definition: StepBase.hxx:101
SubDetId_h DetectorFV
Indicate the FV we are interested in.
Definition: ToyBoxB.hxx:52
void SetValidRunPeriods(std::string runPeriods)
const std::string & Title() const
Return the title of this step.
Definition: StepBase.hxx:63
StepBase * GetStepInBranch(const std::vector< UInt_t > &branch_seq, UInt_t index) const
Get step in a given branch provided the branch sequence (vector of integers) and the step index...
void InitializeCutLevels()
Reset all cuts to "not passed", and set the accumulated cut level to 0.
bool PreSelectionPassed(const AnaEventC &event)
Is the preselection passed in any of the branches.
bool ApplySteps(AnaEventC &event, ToyBoxB &box, const std::string &branch, Int_t ifirst=0, Int_t ilast=NMAXSTEPS)
Apply a range of steps in a branch.
void SetType(TypeEnum type)
Set the type of this step.
Definition: StepBase.hxx:54
void AddSplit(UInt_t nbranches, Int_t b0=-1, Int_t b1=-1, Int_t b2=-1, Int_t b3=-1, Int_t b4=-1, Int_t b5=-1, Int_t b6=-1, Int_t b7=-1)
Add a split in the step sequence. The user should specify the number of branches in this split and th...
Int_t GetBranchUniqueID(const std::string &name) const
Gets the branch unique ID with a given alias.
UInt_t nBranches
The number of branches in the selection this ToyBox belongs to.
Definition: ToyBoxB.hxx:32
bool ApplyStepRecursive(AnaEventC &event, ToyBoxB &box, const StepBase &step, Int_t firstStepToApply)
Apply all steps recursively provided the first step in a threadsafe way.
void CreateToyBoxArray(Int_t nevents)
Create the array of PreviousToyBox.
virtual ToyBoxB * MakeToyBox()
Create the appropriate type of box.
std::vector< std::string > _branchAlias
Association between a branch unique ID (entry in vector) and branch alias.
Int_t SuccessfulBranch
The branch that is successful for this toy in the selection this ToyBox belongs to.
Definition: ToyBoxB.hxx:46
virtual bool Apply(AnaEventC &event, ToyBoxB &box) const
Definition: StepBase.hxx:46
bool Break() const
Return true if the cut sequence should be stopped when a cut fails.
Definition: StepBase.hxx:69
std::vector< UInt_t > _nCutsInBranch
Number of cuts in each branch.
std::vector< StepBase * > GetCutsInBranch(const std::string &branch) const
Get all cuts in a given branch provided the branch alias.
void AddNextStep(StepBase *step, Int_t branch=-1)
Definition: StepBase.cxx:71
const ToyBoxB & GetPreviousToyBox() const
Get the ToyBox of the last processed toy (only for no MULTITHREAD)
bool Apply(AnaEventC &event, bool &redo)
Apply all steps in the selection.
std::vector< StepBase * > GetStepsInBranch(const std::vector< UInt_t > &branch_seq, UInt_t first=0, UInt_t last=NMAXSTEPS-1) const
Get all steps in a given branch provided the branch sequence (vector of integers) ...
void SoftReset()
Reset the ToyBoxB.
Definition: ToyBoxB.cxx:55
void SetBreak(bool b)
Set whether the cut sequence should be stopped when this cut fails.
Definition: StepBase.hxx:57
std::vector< UInt_t > GetBranchSequence(const std::string &name) const
Get the branch sequence for a specific branch alias.
const std::string & Title() const
Return the title of this selection. A nice version of the name.
virtual bool FillEventSummary(AnaEventC &, Int_t *)
Fill the Event Summary, needed by fitters.
UInt_t GetNCuts(Int_t branch) const
Return the number of cuts in a given branch.
void RemoveStep(const std::string &title, Int_t ID=-1)
Disable step provided title and branch ID.
std::vector< UInt_t > ConvertBranch(Int_t b0=-1, Int_t b1=-1, Int_t b2=-1, Int_t b3=-1, Int_t b4=-1, Int_t b5=-1, Int_t b6=-1, Int_t b7=-1) const
Convert the branch sequence of individual integers into a vector of integers.
void Validate() const
Validates this selection.
void FinalizeEvent(const AnaEventC &event)
Delete the PreviousToyBox pointer for the last toy of the event.
void SetIndex(Int_t index)
Set the index of this step.
Definition: StepBase.hxx:60
virtual void DefineSteps()
Define all steps in the selection.
void SetTitle(const std::string &title)
Definition: StepBase.hxx:51
bool CutPassed(bool passed, Int_t branch, ToyBoxB &box)
void SetBranchAlias(Int_t ID, const std::string &name, Int_t b0=-1, Int_t b1=-1, Int_t b2=-1, Int_t b3=-1, Int_t b4=-1, Int_t b5=-1, Int_t b6=-1, Int_t b7=-1)
Set the branch alias and unique ID provided the branch sequence.
UInt_t GetNBranches() const
Return the number of branches.
std::vector< UInt_t > _nEventsPassed
Used for statistics.
void DisableStep(const std::string &title, Int_t ID=-1)
Replace a step (same structure of AddStep, but for only one step at once)
Int_t * AccumLevel
Accum level for each branch in this toy in the selection this ToyBox belongs to.
Definition: ToyBoxB.hxx:35
void RemoveNextStep(const std::string &title, Int_t ID=0)
Remove step with a given title (and branch ID) from next steps.
Definition: StepBase.cxx:86
void SetDetectorFV(SubDetId_h det, Int_t ibranch=-1)
Set the detector in which the Fiducial Volume is defined.
virtual void Reset()=0
Mandatory method to be implemented by the derived class. Reset the top level derived box...
Definition: ToyBoxB.cxx:29
std::vector< std::string > GetCutNames(Int_t ibranch=0) const
Return all the names of the cuts, in the order they were added.
void ReplaceStep(const std::string &old_title, Int_t ID, StepBase::TypeEnum type, const std::string &title, StepBase *step, bool cut_break=false)
Replace step provided title and branch ID of the step to replace.
virtual StepBase * MakeClone()
MANDATORY FUNCTIONS !!!
Definition: StepBase.hxx:42
std::string ConvertBranchToString(const std::vector< UInt_t > &branch, Int_t upToSplit=-1) const
Convert the branch sequence into a string.
StepBase * GetStep(const std::string &title, Int_t ID=0) const
Return an step provided the title and the Branch ID.
Int_t _maxAccumLevelForAllToys
This is the maximum accum level of any of the branches in all toys.
bool HasBranch(Int_t ibranch, const std::string &fromMethod="HasBranch") const
Check the existence of branch.
std::vector< StepBase * > GetStepsInBranchWithDummy(const std::vector< UInt_t > &branch_seq, UInt_t first=0, UInt_t last=NMAXSTEPS-1) const
Get all steps in a given branch provided the branch sequence (vector of integers) ...
bool _initialized
Is this selection initialized ?
virtual void ResetBase()=0
Mandatory method to be implemented by the derived class. Reset the base class for the top level box...
Definition: ToyBoxB.cxx:47
Int_t _presel_accum_cut_level
The preselection accum level.
virtual bool CheckRedoSelection(const AnaEventC &, const ToyBoxB &PreviousToyBox, Int_t &redoFromStep)
ToyBoxB ** PreviousToyBox
Array of pointers to the PreviousToyBox (for each event)
SubDetId_h GetDetectorFV(Int_t ibranch=0) const
Get the detector in which the Fiducial Volume is defined.
TypeEnum Type() const
Return the type of this step.
Definition: StepBase.hxx:66
virtual void DefineDetectorFV()
Define the detector Fiducial Volume in which this selection is applied.
bool _forceFillEventSummary
Int_t _current_cut[NMAXBRANCHES]
The current cut level.
bool IsDisabledInBranch(Int_t branch) const
Returns true if the step is disabled in the specified branch.
Definition: StepBase.hxx:84
bool * BranchPassed
Definition: ToyBoxB.hxx:43
std::vector< std::vector< UInt_t > > _branchSequence
Association between a branch unique ID (entry in vector) and branch sequence.
void AddStep(StepBase::TypeEnum type, const std::string &title, StepBase *step, bool cut_break=false)
void Initialize()
Initialize this selection: defines the steps and the detectorFV.
void DisableInBranch(Int_t branch)
Disable step in a given branch.
Definition: StepBase.hxx:78
Int_t GetCutNumber(const std::string &title, Int_t ID=0) const
Return the cut number (starting at 0) corresponding to an step with a given title.
TypeEnum
Enumerator describing the values that _type member can take.
Definition: StepBase.hxx:22