HighLAND
numuCCMultiPiSelection.cxx
1 #include "numuCCMultiPiSelection.hxx"
2 #include "numuCCSelection.hxx"
3 #include "baseSelection.hxx"
4 #include "SystematicTuning.hxx"
5 #include "CutUtils.hxx"
6 #include "EventBoxUtils.hxx"
7 #include "Parameters.hxx"
8 #include "SubDetId.hxx"
9 #include "SystId.hxx"
10 #include "SystematicUtils.hxx"
11 #include <DetectorDefinition.hxx>
12 
13 
14 /**
15  \\! [numuCCMultiPiSelection_info]
16  This selection adds tree branches on top of the numuCCSelection. As descrived in numuCCMultiPiSelection::DefineSteps "numuCCMultiPiSelection::DefineSteps "the cuts of the numuCCSelection are copied to this selection.
17  Then new cuts for each branch are added:
18 
19  Cuts for Branch 0: This is the branch requiring no pions
20  <table>
21  <tr><th> #cut <th> cut class <th> from source file <th> Cut description
22  <tr><td> 6 <td> ExternalVetoCut::Apply <td> numuCCSelection.cxx <td> External veto cut
23  <tr><td> 7 <td> ExternalFGD1lastlayersCut::Apply <td> numuCCSelection.cxx <td> External FGD1 last layers cut
24  </table>
25 
26  Cuts for Branch 1: This is the branch requiring 1 and only 1 pion
27  <table>
28  <tr><th> #cut <th> cut class <th> from source file <th> Cut description
29  <tr><td> 6 <td> ExternalVetoCut::Apply <td> numuCCSelection.cxx <td> External veto cut
30  <tr><td> 7 <td> ExternalFGD1lastlayersCut::Apply <td> numuCCSelection.cxx <td> External FGD1 last layers cut
31  </table>
32 
33  Cuts for Branch 2: This is the branch requiring more than 1 pion
34  <table>
35  <tr><th> #cut <th> cut class <th> from source file <th> Cut description
36  <tr><td> 6 <td> ExternalVetoCut::Apply <td> numuCCSelection.cxx <td> External veto cut
37  <tr><td> 7 <td> ExternalFGD1lastlayersCut::Apply <td> numuCCSelection.cxx <td> External FGD1 last layers cut
38  </table>
39 
40 
41  \\! [numuCCMultiPiSelection_info]
42 */
43 
44 //*******************************************************************************
45 numuCCMultiPiSelection::numuCCMultiPiSelection(bool forceBreak): SelectionBase(forceBreak,EventBoxId::kEventBoxTracker){
46 //*******************************************************************************
47 
48  // Initialize systematic tuning parameters
49  systTuning::Initialize();
50 }
51 
52 /// This is the method where the actual steps are added to the selection
53 /// \anchor numuCCMultiPiSelection_DefineSteps
54 //*******************************************************************************
56 //*******************************************************************************
57 
58  // Copy all steps from the numuCCSelection
59  CopySteps(_numuCCSelection);
60 
61  //Additional actions for the multi-pi selection.
62  AddStep(StepBase::kAction, "fill_summary_multiPi", new FillSummaryAction_numuCCMultiPi());
63  AddStep(StepBase::kAction, "find_pions", new FindPionsAction());
64  AddStep(StepBase::kAction, "find ECal photons", new FindEcalPhotonsAction());
65 
66  //Add a split to the trunk with 3 branches.
67  AddSplit(3);
68 
69  //First branch is for CC-0pi
70  AddStep(0, StepBase::kCut, "CC-0pi", new NoPionCut());
71  AddStep(0, StepBase::kCut, "ECal Pi0 veto", new EcalPi0VetoCut());
72 
73  //Second branch is for CC-1pi
74  AddStep(1, StepBase::kCut, "CC-1pi", new OnePionCut());
75  AddStep(1, StepBase::kCut, "ECal Pi0 veto", new EcalPi0VetoCut());
76 
77  //Third branch is for CC-Other
78  AddStep(2, StepBase::kCut, "CC-Other", new OthersCut());
79 
80  // Set the branch aliases to the three branches
81  SetBranchAlias(0,"CC-0pi", 0);
82  SetBranchAlias(1,"CC-1pi", 1);
83  SetBranchAlias(2,"CC-Other",2);
84 
85  // By default the preselection correspond to cuts 0-2
87 
88  // Step and Cut numbers needed by CheckRedoSelection
89  _MuonPIDCutIndex = GetCutNumber("muon PID");
90  _FindPionsStepIndex = GetStepNumber("find_pions");
91 }
92 
93 
94 //*******************************************************************************
96 //*******************************************************************************
97 
98  // The detector in which the selection is applied
99  SetDetectorFV(SubDetId::kFGD1);
100 }
101 
102 //********************************************************************
103 bool numuCCMultiPiSelection::FillEventSummary(AnaEventC& event, Int_t allCutsPassed[]){
104 //********************************************************************
105 
106  //CC0pi
107  if(allCutsPassed[0]){
108  static_cast<AnaEventSummaryB*>(event.Summary)->EventSample = SampleId::kFGD1NuMuCC0Pi;
109  }
110  //CC1pi
111  else if (allCutsPassed[1]){
112  static_cast<AnaEventSummaryB*>(event.Summary)->EventSample = SampleId::kFGD1NuMuCC1Pi;
113  }
114  //CCOther
115  else if (allCutsPassed[2]){
116  static_cast<AnaEventSummaryB*>(event.Summary)->EventSample = SampleId::kFGD1NuMuCCOther;
117  }
118 
119  // otherwise kUnassigned is used from the EventSummary constructor
120  return (static_cast<AnaEventSummaryB*>(event.Summary)->EventSample != SampleId::kUnassigned);
121 }
122 
123 
124 //*********************************************************************
126 //*********************************************************************
127 
128  // Cast the ToyBox to the appropriate type
129  ToyBoxTracker& box = *static_cast<ToyBoxTracker*>(&boxB);
130 
131 
132  if(!box.HMNtrack) return 1;
133 
134  static_cast<AnaEventSummaryB*>(event.Summary)->LeptonCandidate[SampleId::kFGD1NuMuCC0Pi] = box.HMNtrack;
135  static_cast<AnaEventSummaryB*>(event.Summary)->LeptonCandidate[SampleId::kFGD1NuMuCC1Pi] = box.HMNtrack;
136  static_cast<AnaEventSummaryB*>(event.Summary)->LeptonCandidate[SampleId::kFGD1NuMuCCOther] = box.HMNtrack;
137 
138  for(int i = 0; i < 4; ++i){
139  static_cast<AnaEventSummaryB*>(event.Summary)->VertexPosition[SampleId::kFGD1NuMuCC0Pi][i] = box.HMNtrack->PositionStart[i];
140  static_cast<AnaEventSummaryB*>(event.Summary)->VertexPosition[SampleId::kFGD1NuMuCC1Pi][i] = box.HMNtrack->PositionStart[i];
141  static_cast<AnaEventSummaryB*>(event.Summary)->VertexPosition[SampleId::kFGD1NuMuCCOther][i] = box.HMNtrack->PositionStart[i];
142  }
143  if(box.HMNtrack->GetTrueParticle()){
144  static_cast<AnaEventSummaryB*>(event.Summary)->TrueVertex[SampleId::kFGD1NuMuCC0Pi] = box.HMNtrack->GetTrueParticle()->TrueVertex;
145  static_cast<AnaEventSummaryB*>(event.Summary)->TrueVertex[SampleId::kFGD1NuMuCC1Pi] = box.HMNtrack->GetTrueParticle()->TrueVertex;
146  static_cast<AnaEventSummaryB*>(event.Summary)->TrueVertex[SampleId::kFGD1NuMuCCOther] = box.HMNtrack->GetTrueParticle()->TrueVertex;
147  }
148  return 1;
149 }
150 
151 //*********************************************************************
152 bool FindPionsAction::Apply(AnaEventC& event, ToyBoxB& box) const{
153 //*********************************************************************
154 
155  SubDetId::SubDetEnum det = static_cast<SubDetId::SubDetEnum>(box.DetectorFV);
156 
157  ToyBoxCCMultiPi * ccmultipibox = static_cast<ToyBoxCCMultiPi*>(&box);
158  EventBoxTracker* EventBox = static_cast<EventBoxTracker*>(event.EventBoxes[EventBoxId::kEventBoxTracker]);
159 
160  if (useTPCPions) numuCCMultiPiUtils::FindTPCPions(event, box, det, useOldSecondaryPID);
161  if (useME) numuCCMultiPiUtils::FindMEPions(event,det, prod5Cut);
162  if (useFGDPions) numuCCMultiPiUtils::FindIsoFGDPions(event, box, det);
163 
164  int nnegpions = ccmultipibox->nNegativePionTPCtracks;
165  int npospions = ccmultipibox->nPositivePionTPCtracks;
166  int nisofgdpions = ccmultipibox->nIsoFGDPiontracks;
167  int nmichelelectrons = EventBox->nFGDMichelElectrons[det];
168  int npi0 = ccmultipibox->nPosPi0TPCtracks+ ccmultipibox->nElPi0TPCtracks;
169 
170  int pionFGD = nmichelelectrons;
171  if (!nmichelelectrons && nisofgdpions>0) pionFGD = 1;
172 
173  ccmultipibox->nPosPions = npospions+pionFGD;
174  ccmultipibox->nOtherPions = nnegpions+npi0;
175 
176  return true;
177 }
178 
179 //*********************************************************************
180 bool NoPionCut::Apply(AnaEventC& event, ToyBoxB& box) const{
181 //*********************************************************************
182 
183  (void)event;
184 
185  ToyBoxCCMultiPi * ccmultipibox = static_cast<ToyBoxCCMultiPi*>(&box);
186 
187  // no positive and no other pions
188  if( ccmultipibox->nPosPions + ccmultipibox->nOtherPions == 0 ) return true;
189  return false;
190 }
191 
192 
193 //*********************************************************************
194 bool OnePionCut::Apply(AnaEventC& event, ToyBoxB& box) const{
195 //*********************************************************************
196 
197  (void)event;
198 
199  ToyBoxCCMultiPi * ccmultipibox = static_cast<ToyBoxCCMultiPi*>(&box);
200 
201  // one Positive pion and no other pions
202  if( ccmultipibox->nOtherPions != 0 ) return false;
203  if( ccmultipibox->nPosPions == 1 ) return true;
204  return false;
205 }
206 
207 
208 //*********************************************************************
209 bool OthersCut::Apply(AnaEventC& event, ToyBoxB& box) const{
210 //*********************************************************************
211 
212  (void)event;
213 
214  ToyBoxCCMultiPi * ccmultipibox = static_cast<ToyBoxCCMultiPi*>(&box);
215 
216  // More than one positive pion or more than zero other pions or event doesn't pass the pi0 veto
217  if( ccmultipibox->nOtherPions != 0 ) return true;
218  if( ccmultipibox->nPosPions > 1 ) return true;
219  if( ccmultipibox->nPi0Ecaltracks > 0) return true;
220 
221  return false;
222 }
223 
224 //*********************************************************************
225 void numuCCMultiPiUtils::FindTPCPions(AnaEventC& event, ToyBoxB& box, SubDetId::SubDetEnum det, bool useOldSecondaryPID){
226 //*********************************************************************
227 
228  ToyBoxCCMultiPi * ccmultipibox = static_cast<ToyBoxCCMultiPi*>(&box);
229 
230  ccmultipibox->nPositivePionTPCtracks = 0;
231  ccmultipibox->nPosPi0TPCtracks = 0;
232  ccmultipibox->nNegativePionTPCtracks = 0;
233  ccmultipibox->nElPi0TPCtracks = 0;
234 
235  EventBoxTracker::RecObjectGroupEnum groupID;
236  if (det==SubDetId::kFGD1) groupID = EventBoxTracker::kTracksWithGoodQualityTPCInFGD1FV;
237  else if (det==SubDetId::kFGD2) groupID = EventBoxTracker::kTracksWithGoodQualityTPCInFGD2FV;
238  else return;
239 
240  EventBoxB* EventBox = event.EventBoxes[EventBoxId::kEventBoxTracker];
241 
242  // Look for pions in positive tracks
243  for(int i = 0; i < EventBox->nRecObjectsInGroup[groupID]; i++ ) {
244  AnaTrackB *ptrack = static_cast<AnaTrackB*>(EventBox->RecObjectsInGroup[groupID][i]);
245 
246  if (ptrack->Charge>0){
247  if(useOldSecondaryPID){
248  if ( numuCCMultiPiUtils::TPCpionSelection(ptrack) ) {
249  ccmultipibox->PositivePionTPCtracks[ccmultipibox->nPositivePionTPCtracks] = ptrack;
250  ccmultipibox->nPositivePionTPCtracks++;
251  }
252  else if ( numuCCMultiPiUtils::TPCElPi0Selection(ptrack) ) {
253  ccmultipibox->PosPi0TPCtracks[ccmultipibox->nPosPi0TPCtracks] = ptrack;
254  ccmultipibox->nPosPi0TPCtracks++;
255  }
256  }
257  else {
258  Float_t PIDLikelihood[4];
259  anaUtils::GetPIDLikelihood(*ptrack, PIDLikelihood);
260 
261  // For Positive tracks we distinguish pions, electrons and protons.
262  double ElLklh = PIDLikelihood[1];
263  double ProtonLklh = PIDLikelihood[2];
264  double PionLklh = PIDLikelihood[3];
265  double norm = ElLklh+ProtonLklh+PionLklh;
266  ProtonLklh /= norm;
267  ElLklh /= norm;
268  PionLklh /= norm;
269 
270  if( ProtonLklh > ElLklh && ProtonLklh > PionLklh ) continue; // If the highest probability is a proton continue.
271 
272  // Id associated to the largest of the two probabilities.
273  if( PionLklh > ElLklh ){
274  ccmultipibox->PositivePionTPCtracks[ccmultipibox->nPositivePionTPCtracks] = ptrack;
275  ccmultipibox->nPositivePionTPCtracks++;
276  }
277  else {
278  if( ptrack->Momentum > 900. ) continue; // This is mainly protons.
279  ccmultipibox->PosPi0TPCtracks[ccmultipibox->nPosPi0TPCtracks] = ptrack;
280  ccmultipibox->nPosPi0TPCtracks++;
281  }
282  }
283  }
284  else{
285  if( ccmultipibox->HMNtrack == ptrack ) continue; // Same as the leading track.
286 
287  if(useOldSecondaryPID) {
288  if ( numuCCMultiPiUtils::TPCpionSelection(ptrack) ) {
289  ccmultipibox->NegativePionTPCtracks[ccmultipibox->nNegativePionTPCtracks] = ptrack;
290  ccmultipibox->nNegativePionTPCtracks++;
291  }
292  else if ( numuCCMultiPiUtils::TPCElPi0Selection(ptrack) ) {
293  ccmultipibox->ElPi0TPCtracks[ccmultipibox->nElPi0TPCtracks] = ptrack;
294  ccmultipibox->nElPi0TPCtracks++;
295  }
296  }
297  else {
298  // For Negative tracks we distinguish pions, electrons and protons.
299  Float_t PIDLikelihood[4];
300  anaUtils::GetPIDLikelihood(*ptrack, PIDLikelihood);
301 
302  // For Positive tracks we distinguish pions, electrons and protons.
303  double ElLklh = PIDLikelihood[1];
304  double PionLklh = PIDLikelihood[3];
305  double norm = ElLklh+PionLklh;
306  ElLklh /= norm;
307  PionLklh /= norm;
308 
309  if( PionLklh > 0.8 ){ // Id associated to the largest of the two probabilities.
310  ccmultipibox->NegativePionTPCtracks[ccmultipibox->nNegativePionTPCtracks] = ptrack;
311  ccmultipibox->nNegativePionTPCtracks++;
312  }
313  else{
314  ccmultipibox->ElPi0TPCtracks[ccmultipibox->nElPi0TPCtracks] = ptrack;
315  ccmultipibox->nElPi0TPCtracks++;
316  }
317  }
318  }
319  }
320 }
321 
322 
323 //*********************************************************************
324 void numuCCMultiPiUtils::FindIsoFGDPions(AnaEventC& event, ToyBoxB& box, SubDetId::SubDetEnum det){
325 //*********************************************************************
326 
327  ToyBoxCCMultiPi * ccmultipibox = static_cast<ToyBoxCCMultiPi*>(&box);
328  ccmultipibox->nIsoFGDPiontracks = 0;
329  ccmultipibox->nIsoFGDElPi0tracks = 0;
330 
331  EventBoxTracker::RecObjectGroupEnum groupID;
332  if (det==SubDetId::kFGD1) groupID = EventBoxTracker::kTracksWithFGD1AndNoTPC;
333  else if (det==SubDetId::kFGD2) groupID = EventBoxTracker::kTracksWithFGD2AndNoTPC;
334  else return;
335 
336  EventBoxB* EventBox = event.EventBoxes[EventBoxId::kEventBoxTracker];
337 
338  //loop over tracks
339  for (int i=0;i<EventBox->nRecObjectsInGroup[groupID]; i++ ){
340  AnaTrackB* track = static_cast<AnaTrackB*>(EventBox->RecObjectsInGroup[groupID][i]);
341  // Apply the fiducial cut and PID
342  if( numuCCMultiPiUtils::FGDpionSelection(track,det) ){
343  ccmultipibox->IsoFGDPiontracks[ccmultipibox->nIsoFGDPiontracks] = track;
344  ccmultipibox->nIsoFGDPiontracks++;
345  }
346  else if( numuCCMultiPiUtils::FGDElPi0Selection(event,box,track,det) ){
347  ccmultipibox->IsoFGDElPi0tracks[ccmultipibox->nIsoFGDElPi0tracks] = track;
348  ccmultipibox->nIsoFGDElPi0tracks++;
349  }
350  }
351 }
352 
353 //*********************************************************************
354 void numuCCMultiPiUtils::FindMEPions(AnaEventC& eventBB, SubDetId::SubDetEnum det, bool prod5Cut){
355 //*********************************************************************
356 
357  AnaEventB& event = *static_cast<AnaEventB*>(&eventBB);
358 
359  EventBoxTracker* EventBox = static_cast<EventBoxTracker*>(event.EventBoxes[EventBoxId::kEventBoxTracker]);
360 
361  // Fill the box only the first time this is used
362  if (EventBox->FGDMichelElectrons[det]) return;
363 
364  anaUtils::CreateArray(EventBox->FGDMichelElectrons[det], NMAXFGDTIMEBINS);
365  EventBox->nFGDMichelElectrons[det] = anaUtils::GetFGDMichelElectrons(event, det, EventBox->FGDMichelElectrons[det], prod5Cut);
366  anaUtils::ResizeArray(EventBox->FGDMichelElectrons[det], EventBox->nFGDMichelElectrons[det]);
367 
368 }
369 
370 //*********************************************************************
371 bool numuCCMultiPiUtils::TPCpionSelection(AnaTrackB *track){
372 //*********************************************************************
373 
374  Float_t PIDLikelihood[4];
375  anaUtils::GetPIDLikelihood(*track, PIDLikelihood);
376 
377  if ( PIDLikelihood[3] < 0.3 ) return false;
378 
379  double cut1 = (PIDLikelihood[0]+PIDLikelihood[3])/(1.-PIDLikelihood[2]);
380 
381  if( track->Momentum < 500. && cut1 < 0.8 ) return false;
382 
383  return true;
384 
385 
386 }
387 //*********************************************************************
388 bool numuCCMultiPiUtils::TPCElPi0Selection(AnaTrackB *track){
389 //*********************************************************************
390 
391  if( track->nTPCSegments == 0 ) return false; // There is no TPC segment
392 
393  bool seltrack = false;
394 
395  // if (!cutUtils::TrackQualityCut(*track)) return seltrack;
396 
397  if( track->Momentum < 50. ) return seltrack;
398 
399  // if( track->Charge > 0. && track->Momentum > 800.) return seltrack;
400 
401  Float_t pulls[4];
402 
403  for(int i = 0; i < track->nTPCSegments ; i++ ){
404 
405  AnaTPCParticleB *tpcTrack = track->TPCSegments[i];
406 
407  if( !tpcTrack ) continue; // Extra protection.
408 
409  // Pulls are: Muon, Electron, Proton, Pion
410  anaUtils::ComputeTPCPull(*tpcTrack,pulls);
411 
412  if (TMath::Abs(pulls[0]) > 1.e+6 // muon pull
413  || TMath::Abs(pulls[1]) > 1.e+6 // electron pull
414  || TMath::Abs(pulls[2]) > 1.e+6 // proton pull
415  || TMath::Abs(pulls[3]) > 1.e+6) continue; // pion pull
416 
417  if( pulls[1] < -2.0 || pulls[1] > 2.0 ) break;
418 
419  if( track->Charge > 0. && ( pulls[2] > -4.0 && pulls[2] < 8.0 ) ) break;
420 
421  seltrack = true;
422 
423  }
424  return seltrack;
425 }
426 
427 //*********************************************************************
428 bool numuCCMultiPiUtils::FGDpionSelection(AnaTrackB *track, SubDetId::SubDetEnum det){
429 //*********************************************************************
430  if( track->nFGDSegments != 1 ) return false; // There is no FGD segment or it has more than one FGD
431 
432  AnaFGDParticleB *fgdTrack = track->FGDSegments[0];
433 
434  if( !fgdTrack ) return false; // Extra protection.
435 
436  if( TMath::Abs(fgdTrack->Pullp) > 1.e+6 || TMath::Abs(fgdTrack->Pullmu) > 1.e+6 || TMath::Abs(fgdTrack->Pullpi) > 1.e+6 ) return false;
437 
438  // Check the pullnotset variable.
439  // This tells us if the pull was calculated by the algorithm.
440  // If it was not calculated this variable will be 1, so for calculated pulls fgdpulls!=1.
441  if( fgdTrack->Pullno == 1 ) return false;
442 
443  // This tell us something about the geometry.
444  // If the algorithm says the particle started and stopped in 1st/ 2nd fgd this is equal 1 or 2.
445  // If the particle stopped in 1st/2nd fgd, this is equal -1/-2. Other cases: 0.
446  if( fgdTrack->Containment == 0 ) return false;
447  if ( det == SubDetId::kFGD1 && fgdTrack->Containment != 1 ) return false;
448  else if( det == SubDetId::kFGD2 && fgdTrack->Containment != 2 ) return false;
449  else if( det == SubDetId::kFGD && fgdTrack->Containment != 1 && fgdTrack->Containment != 2) return false;
450 
451  double cosFGDpion = fgdTrack->DirectionStart[2];
452 
453  if(cosFGDpion > -0.3 && cosFGDpion < 0.3) return false;/// only for systematics issues. Must be remove in the future!!
454 
455  if( fgdTrack->Pullpi < 2.5 && fgdTrack->Pullpi > -2.0 ) return true;
456 
457  return false;
458 
459 
460 }
461 
462 //*********************************************************************
463 bool numuCCMultiPiUtils::FGDElPi0Selection(AnaEventC& event, ToyBoxB& box, AnaTrackB *track, SubDetId::SubDetEnum det){
464 //*********************************************************************
465 
466  (void)box;
467 
468  if( track->nFGDSegments != 1 ) return false; // There is no FGD segment or it has more than one FGD
469 
470  // ToyBoxCCMultiPi * ccmultipibox = static_cast<ToyBoxCCMultiPi*>(&box);
471 
472  AnaFGDParticleB *fgdTrack = track->FGDSegments[0];
473 
474  if( !fgdTrack ) return false; // Extra protection.
475 
476  if( TMath::Abs(fgdTrack->Pullp) > 1.e+6 || TMath::Abs(fgdTrack->Pullmu) > 1.e+6 || TMath::Abs(fgdTrack->Pullpi) > 1.e+6 ) return false;
477 
478  // Check the pullnotset variable.
479  // This tells us if the pull was calculated by the algorithm.
480  // If it was not calculated this variable will be 1, so for calculated pulls fgdpulls!=1.
481  if( fgdTrack->Pullno == 1 ) return false;
482 
483  // This tell us something about the geometry.
484  // If the algorithm says the particle started and stopped in 1st/ 2nd fgd this is equal 1 or 2.
485  // If the particle stopped in 1st/2nd fgd, this is equal -1/-2. Other cases: 0.
486  if( fgdTrack->Containment == 0 ) return false;
487  if ( det == SubDetId::kFGD1 && fgdTrack->Containment != 1 ) return false;
488  else if( det == SubDetId::kFGD2 && fgdTrack->Containment != 2 ) return false;
489  else if( det == SubDetId::kFGD && fgdTrack->Containment != 1 && fgdTrack->Containment != 2) return false;
490 
491  EventBoxTracker* EventBox = static_cast<EventBoxTracker*>(event.EventBoxes[EventBoxId::kEventBoxTracker]);
492 
493  if(EventBox->nFGDMichelElectrons[det] > 0 && fgdTrack->Pullpi < -3.0 ) return true;
494  if(EventBox->nFGDMichelElectrons[det] == 0 && fgdTrack->Pullpi < -1.5 ) return true;
495 
496 
497  return false;
498 }
499 
500 //**************************************************
501 bool numuCCMultiPiSelection::IsRelevantRecObjectForSystematic(const AnaEventC& event, AnaRecObjectC* track, SystId_h systId, Int_t branch) const{
502 //**************************************************
503 
504  return _numuCCSelection.IsRelevantRecObjectForSystematic(event,track,systId,branch);
505 }
506 
507 //**************************************************
508 bool numuCCMultiPiSelection::IsRelevantTrueObjectForSystematic(const AnaEventC& event, AnaTrueObjectC* trueTrack, SystId_h systId, Int_t branch) const{
509 //**************************************************
510 
511  return _numuCCSelection.IsRelevantTrueObjectForSystematic(event,trueTrack,systId,branch);
512 }
513 
514 //**************************************************
515 bool numuCCMultiPiSelection::IsRelevantRecObjectForSystematicInToy(const AnaEventC& event, const ToyBoxB& box, AnaRecObjectC* track, SystId_h systId, Int_t branch) const{
516 //**************************************************
517 
518  (void)event;
519 
520  // all CC inclusive cases
521  // APPLY_SYST_FINE_TUNING is taken into account as well (will return true if not used), hence in what follows assume
522  // APPLY_SYST_FINE_TUNING case ON
523  if (_numuCCSelection.IsRelevantRecObjectForSystematicInToy(event,box,track,systId,branch)) return true;
524 
525  const ToyBoxCCMultiPi* ccmultipibox = static_cast<const ToyBoxCCMultiPi*>(&box);
526 
527  switch (systId){
528  // Fall back through the relevant ones
529  // TPC reco
530  case SystId::kChargeIDEff:
531  // TPC matching
532  case SystId::kTpcFgdMatchEff:
533 
534  // Use the APPLY_SYST_FINE_TUNING concept as well, since we worry about the "main" track that defines the topology
535  if (branch == 1){
536  // For CC-1pi also the positive Pion in the TPC matters
537  if (ccmultipibox->nPositivePionTPCtracks==1 && track==ccmultipibox->PositivePionTPCtracks[0]) return true;
538  }
539  else if (branch == 2){
540  // For CC-Other consider the negative pion when there are no other pions
541  if (ccmultipibox->nNegativePionTPCtracks==1 && track==ccmultipibox->NegativePionTPCtracks[0] &&
542  ccmultipibox->nOtherPions==1 && ccmultipibox->nPosPions == 0) return true;
543 
544  }
545  // Failed above +
546  // CC0pi explicit false (should have been covered by numuCC if tuning is ON)
547  return false;
548  break;
549 
550  // TPC cluster, consider a potential HMN track, can affect the selection
551  case SystId::kTpcClusterEff:
552  // Rare case it can affect, need to consider PID as well, apply for the moment...
553  return true;
554  break;
555 
556  // The rest of the systematics go here, tuning to come
557  default:
558  return true;
559  break;
560  }
561 
562  return true;
563 
564 }
565 
566 
567 //**************************************************
568 bool numuCCMultiPiSelection::IsRelevantTrueObjectForSystematicInToy(const AnaEventC& event, const ToyBoxB& box, AnaTrueObjectC* trueObj, SystId_h systId, Int_t branch) const{
569 //**************************************************
570 
571  (void)event;
572 
573  AnaTrueParticleB* trueTrack = static_cast<AnaTrueParticleB*>(trueObj);
574 
575  // all CC inclusive cases
576  // MAIN track mode is taken into account there
577  if (_numuCCSelection.IsRelevantTrueObjectForSystematicInToy(event,box,trueTrack,systId,branch)) return true;
578 
579  if(systId == SystId::kTpcTrackEff){
580  const ToyBoxCCMultiPi* ccmultipibox = static_cast<const ToyBoxCCMultiPi*>(&box);
581 
582  if (branch==0 || branch==1){
583  // For CC-0pi and CC-1pi all true pions and muons matter
584  if (abs(trueTrack->PDG)==211 || abs(trueTrack->PDG)==13) return true;
585  }
586  else if (branch==2){
587  // Don't consider pions when there are many
588 
589  // cases in which we must loose two or more pions are excluded (0.01*0.01 probability)
590  if (ccmultipibox->nNegativePionTPCtracks+ccmultipibox->nPositivePionTPCtracks>2 || ccmultipibox->nNegativePionTPCtracks>1) return false;
591 
592  // If the are few pions consider them. Also true muons
593  if (abs(trueTrack->PDG)==211 || abs(trueTrack->PDG)==13) return true;
594  }
595  return false;
596  }
597 
598  // For the rest of the systematic return true, tuning to come
599  return true;
600 }
601 
602 //**************************************************
603 bool numuCCMultiPiSelection::IsRelevantSystematic(const AnaEventC& event, const ToyBoxB& box, SystId_h systId, Int_t branch) const{
604 //**************************************************
605 
606  (void)event;
607  (void)box;
608  (void)systId;
609  (void)branch;
610 
611  /* THIS IS JUST AN EXAMPLE. DO NOT TAKE SERIOUSLY !!!! */
612 
613  // CC-Other branch
614  /* if (branch==2){
615  if (systId==SystId::kFgdTrackEff) // No FGD track eff
616  return false;
617  else if (systId==SystId::kFgdHybridTrackEff) // No FGD hybrid track eff
618  return false;
619  else if (systId==SystId::kMichelEleEff) // No michel electron Systematic
620  return false;
621  else if (systId==SystId::kSIPion){ // No Pion SI systematic when there are many pions
622  const ToyBoxCCMultiPi* box2 = static_cast<const ToyBoxCCMultiPi*>(&box);
623  if (box2->nOtherPions >4 ) return false;
624  if (box2->nPosPions > 4 ) return false;
625  }
626  }
627  */
628 
629  if (branch==2){
630  if (systId==SystId::kSIPion){
631  // No Pion SI systematic when there are many pions
632  if (!systTuning::APPLY_SYST_FINE_TUNING) return true;
633  const ToyBoxCCMultiPi* box2 = static_cast<const ToyBoxCCMultiPi*>(&box);
634  if (box2->nOtherPions >1 || box2->nPosPions > 2 ) return false;
635  }
636  }
637 
638  return true;
639 }
640 
641 //**************************************************
643 //**************************************************
644 
645  AnaEventB& event = *static_cast<AnaEventB*>(&eventBB);
646 
647  _numuCCSelection.InitializeEvent(event);
648  boxUtils::FillTracksWithECal(event);
649 }
650 
651 //********************************************************************
652 bool numuCCMultiPiSelection::CheckRedoSelection(const AnaEventC& event, const ToyBoxB& PreviousToyBox, Int_t& redoFromStep){
653 //********************************************************************
654 
655  // Must redo selection if numuCCSelection decides so
656  if( _numuCCSelection.CheckRedoSelection(event,PreviousToyBox,redoFromStep)) return true;
657 
658  // Otherwise selection must be redone From the FindPionsAction, but only when the Muon PID cut is passed in the previous toy
659  if (PreviousToyBox.MaxAccumLevel>_MuonPIDCutIndex){
660  redoFromStep=_FindPionsStepIndex;
661  return true;
662  }
663  return false;
664 }
665 
666 //*********************************************************************
668 //*********************************************************************
669  // Find whether there is a pi0 track in the ECal or not
670  // In order to apply a pi0 veto cut later
671  ToyBoxCCMultiPi * ccmultipibox = static_cast<ToyBoxCCMultiPi*>(&box);
672  SubDetId::SubDetEnum det = static_cast<SubDetId::SubDetEnum>(box.DetectorFV);
673 
674  // Get all Ecal objects
675  EventBoxTracker::RecObjectGroupEnum groupID;
676  groupID = EventBoxTracker::kTracksWithECal;
677  EventBoxB* EventBox = event.EventBoxes[EventBoxId::kEventBoxTracker];
678 
679  AnaTrackB *highestObject = NULL;
680  double higherEnergyObject = 0;
681 
682  //loop over all ECal objects
683  for(int i = 0; i < EventBox->nRecObjectsInGroup[groupID]; i++ ) {
684  AnaTrackB *allECALObjects = static_cast<AnaTrackB*>(EventBox->RecObjectsInGroup[groupID][i]);
685  if(!(allECALObjects->nECALSegments)) continue;
686  // Check for isolated ecal object
687  if(!(anaUtils::TrackUsesOnlyDet(*allECALObjects,SubDetId::kDSECAL) ||
688  anaUtils::TrackUsesOnlyDet(*allECALObjects,SubDetId::kTopTECAL) ||
689  anaUtils::TrackUsesOnlyDet(*allECALObjects,SubDetId::kBottomTECAL) ||
690  anaUtils::TrackUsesOnlyDet(*allECALObjects,SubDetId::kLeftTECAL) ||
691  anaUtils::TrackUsesOnlyDet(*allECALObjects,SubDetId::kRightTECAL))
692  ) continue;
693 
694  AnaECALParticleB* ecalBase = allECALObjects->ECALSegments[0];
695  AnaTrackB* object = allECALObjects;
696  ccmultipibox->ISOEcal.push_back(object);
697 
698  // Find the most energetic object in ECal
699  if(ecalBase->EMEnergy > higherEnergyObject){
700  higherEnergyObject = ecalBase->EMEnergy;
701  highestObject = object;
702  }
703  }// end of loop on allECALTracks
704 
705  // Save the highest energetic ecal object in the box and the pi0 track
706  if (highestObject){
707  ccmultipibox->HObject = highestObject;
708  // Check if the highest energetic ecal object is shower-like
709  if( numuCCMultiPiUtils::ECALPi0Selection(event, box, highestObject, MostUpstreamLayerHitCut, det) ) {
710  ccmultipibox->Pi0Ecaltrack = highestObject;
711  ccmultipibox->nPi0Ecaltracks = ccmultipibox->nPi0Ecaltracks+1;
712  }
713  }
714  return true;
715 }
716 
717 
718 //***********************************************************************
719 bool numuCCMultiPiUtils::ECALPi0Selection(AnaEventC& event, ToyBoxB& box, AnaTrackB *HO, int MostUpstreamLayerHitCut, SubDetId::SubDetEnum det){
720 //***********************************************************************
721 
722  (void)event;
723  (void)box;
724  (void)det;
725 
726  // Identify if the highest ECal object comes from a TPC positive track
727  // or the muon candidate.
728  // If not, then the ecal object might comes from a pi0 (if the object is shower like)
729 
730  bool Ecalpi0 = false;
731 
732  double EMENERGY = -9999.;
733  double MIPEM = -9999.;
734  double EM_UPSTREAM = -9999;
735  AnaECALParticleB* EcalSegment = HO->ECALSegments[0];
736  if( !EcalSegment ) return false;
737 
738  // Check that the Highest energetic ecal obj is actually shower-like (MIPEM>0)
739  // Cut on EMEnergy because of big spike around 26 MeV (feature of the reconstruction)
740  MIPEM = EcalSegment->PIDMipEm;
741  EMENERGY = EcalSegment->EMEnergy;
742  if (EMENERGY > 30. && MIPEM > 0.) Ecalpi0 = true;
743 
744  // This is the cut on MostUpstreamLayerHit variable.
745  // The cut threshold has to be set in the parameter file
746  // For more information on this variable, see slide 10: http://www.t2k.org/nd280/physics/convener/2015/November2/ECal_pi0_veto
747  EM_UPSTREAM = EcalSegment->MostUpStreamLayerHit;
748  if(EM_UPSTREAM > MostUpstreamLayerHitCut ) Ecalpi0 = false;
749 
750  return Ecalpi0;
751 }
752 
753 //*********************************************************************
754 bool EcalPi0VetoCut::Apply( AnaEventC& event, ToyBoxB& box) const{
755 //*********************************************************************
756 
757  (void)event;
758 
759  // Select event without pi0 track (see FindEcalPhotonsAction)
760  ToyBoxCCMultiPi * ccmultipibox = static_cast<ToyBoxCCMultiPi*>(&box);
761  if(ccmultipibox->nPi0Ecaltracks > 0) return false;
762  else return true;
763 }
bool IsRelevantRecObjectForSystematic(const AnaEventC &event, AnaRecObjectC *recObj, SystId_h systId, Int_t branch) const
Is this track relevant for a given systematic (prior to selection, call when initializing the event...
AnaTrueVertexB * TrueVertex
Pointer to the AnaTrueVertexB of the interaction that created this AnaTrueParticleB.
Float_t PositionStart[4]
The reconstructed start position of the particle.
void DefineDetectorFV()
Define the detector Fiducial Volume in which this selection is applied.
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.
bool Apply(AnaEventC &event, ToyBoxB &box) const
Int_t MaxAccumLevel
Definition: ToyBoxB.hxx:39
bool IsRelevantRecObjectForSystematicInToy(const AnaEventC &event, const ToyBoxB &box, AnaRecObjectC *recObj, SystId_h systId, Int_t branch) const
Is this track relevant for a given systematic (after selection, called for each toy) ...
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 ...
void SetPreSelectionAccumLevel(Int_t presel)
Set the pre-selection accum level.
int GetFGDMichelElectrons(const AnaEventB &event, const SubDetId::SubDetEnum det, AnaFgdTimeBinB **arr, bool prod5Cut=0)
Get all delayed time bins as Michel Electron candidates.
AnaECALParticleB * ECALSegments[NMAXECALS]
The ECAL segments that contributed to this global track.
int nECALSegments
How many ECAL tracks are associated with this track.
bool Apply(AnaEventC &event, ToyBoxB &box) const
Float_t Pullp
Proton pull, according to FGD information.
bool Apply(AnaEventC &event, ToyBoxB &box) const
bool Apply(AnaEventC &event, ToyBoxB &box) const
Float_t Pullno
Dummy pull. If the FGD pulls weren&#39;t set, this is set to 1.
SubDetId_h DetectorFV
Indicate the FV we are interested in.
Definition: ToyBoxB.hxx:52
Representation of an ECAL segment of a global track.
Float_t Pullpi
Pion pull, according to FGD information.
AnaTPCParticleB * TPCSegments[NMAXTPCS]
The TPC segments that contributed to this global track.
bool Apply(AnaEventC &event, ToyBoxB &box) const
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...
Float_t Pullmu
Muon pull, according to FGD information.
Float_t Charge
The reconstructed charge of the particle.
bool CheckRedoSelection(const AnaEventC &event, const ToyBoxB &PreviousToyBox, Int_t &redoFromStep)
Float_t GetPIDLikelihood(const AnaTrackB &track, Int_t hypo, bool prod5Cut=0)
Definition: PIDUtils.cxx:180
Int_t nRecObjectsInGroup[NMAXRECOBJECTGROUPS]
----—— RecObjects and TrueRecObjects used in the selection and systematics ------------—— ...
Float_t Momentum
The reconstructed momentum of the particle, at the start position.
bool IsRelevantRecObjectForSystematic(const AnaEventC &event, AnaRecObjectC *recObj, SystId_h systId, Int_t branch) const
Is this track relevant for a given systematic (prior to selection, call when initializing the event...
int nTPCSegments
How many TPC tracks are associated with this track.
Representation of a true Monte Carlo trajectory/particle.
void InitializeEvent(AnaEventC &event)
Fill the EventBox with the objects needed by this selection.
bool IsRelevantTrueObjectForSystematic(const AnaEventC &event, AnaTrueObjectC *trueObj, SystId_h systId, Int_t branch) const
Is this true track relevant for a given systematic (prior to selection, call when initializing the ev...
bool IsRelevantTrueObjectForSystematicInToy(const AnaEventC &event, const ToyBoxB &box, AnaTrueObjectC *trueTrack, SystId_h systId, Int_t branch) const
Is this true track relevant for a given systematic (after selection, called for each toy) ...
SubDetEnum
Enumeration of all detector systems and subdetectors.
Definition: SubDetId.hxx:25
Int_t PDG
The PDG code of this particle.
AnaTrackB * HMNtrack
For storing the highest momentum negative track.
AnaFgdTimeBinB ** FGDMichelElectrons[2]
----------— Michel Electron candidates -------------------------------—
Representation of a global track.
Float_t ComputeTPCPull(const AnaTPCParticleB &track, const std::string &particle)
Function to recompute the pull for a TPC track segment.
bool IsRelevantRecObjectForSystematicInToy(const AnaEventC &, const ToyBoxB &, AnaRecObjectC *, SystId_h systId, Int_t branch=0) const
Is this track relevant for a given systematic (after selection, called for each toy) ...
Representation of a TPC segment of a global track.
bool Apply(AnaEventC &event, ToyBoxB &box) const
bool APPLY_SYST_FINE_TUNING
General tuning, the concept of apply the systematic for only the "relevant" objects.
bool IsRelevantTrueObjectForSystematic(const AnaEventC &event, AnaTrueObjectC *trueObj, SystId_h systId, Int_t branch) const
Is this true track relevant for a given systematic (prior to selection, call when initializing the ev...
Float_t DirectionStart[3]
The reconstructed start direction of the particle.
AnaEventSummaryC * Summary
A summary of the event with high level quantities.
Representation of a FGD segment of a global track.
bool IsRelevantSystematic(const AnaEventC &event, const ToyBoxB &box, SystId_h systId, Int_t branch) const
Is this systematic relevant for this selection.
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.
int nFGDSegments
How many FGD tracks are associated with this track.
Int_t Containment
Containment flag required for proper PID analysis.
void SetDetectorFV(SubDetId_h det, Int_t ibranch=-1)
Set the detector in which the Fiducial Volume is defined.
Int_t MostUpStreamLayerHit
Innermost layer hit of the ecal object (used in ecal pi0 veto)
AnaTrueParticleB * GetTrueParticle() const
Return a casted version of the AnaTrueObject associated.
ToyBoxB ** PreviousToyBox
Array of pointers to the PreviousToyBox (for each event)
bool TrackUsesOnlyDet(const AnaTrackB &track, SubDetId::SubDetEnum det)
AnaFGDParticleB * FGDSegments[NMAXFGDS]
The FGD segments that contributed to this global track.
bool IsRelevantTrueObjectForSystematicInToy(const AnaEventC &, const ToyBoxB &, AnaTrueObjectC *, SystId_h systId, Int_t branch=0) const
Is this true track relevant for a given systematic (after selection, called for each toy) ...
numuCCMultiPiSelection(bool forceBreak=true)
void InitializeEvent(AnaEventC &event)
Fill the EventBox with the objects needed by this selection.
void AddStep(StepBase::TypeEnum type, const std::string &title, StepBase *step, bool cut_break=false)
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.
bool Apply(AnaEventC &event, ToyBoxB &box) const
bool CheckRedoSelection(const AnaEventC &event, const ToyBoxB &PreviousToyBox, Int_t &redoFromStep)