HighLAND
antiNueCCSelection.cxx
1 #include "antiNueCCSelection.hxx"
2 
3 #include "baseSelection.hxx"
4 #include "CutUtils.hxx"
5 #include "EventBoxUtils.hxx"
6 #include "VersioningUtils.hxx"
7 #include "SystematicUtils.hxx"
8 #include "trackerSelectionUtils.hxx"
9 
10 #include "nueCCUtils.hxx"
11 #include "nueCutUtils.hxx"
12 #include "SystematicTuning.hxx"
13 
14 //********************************************************************
15 antiNueCCSelection::antiNueCCSelection(bool forceBreak): SelectionBase(forceBreak, EventBoxId::kEventBoxTracker) {
16 //********************************************************************
17 
18  // Initialize the nueCCSelection, which is used
19  _nueCCSelection.Initialize();
20 
21  _protonregion_low = (Float_t)ND::params().GetParameterD("psycheSelections.antiNueCCAnalysis.Analysis.ProtonMomentumRegion.Low");
22 
23  // Initialize systematic tuning parameters
24  systTuning::Initialize();
25 }
26 
27 //********************************************************************
29 //********************************************************************
30 
31  // The detector in which the selection is applied
32  SetDetectorFV(SubDetId::kFGD1);
33 
34  // Set the detector field into the selection being used
35  _nueCCSelection.SetDetectorFV(SubDetId::kFGD1);
36 }
37 
38 //********************************************************************
40 //********************************************************************
41 
42  // Last "true" means the step sequence is broken if cut is not passed (default is "false")
43  AddStep(StepBase::kCut, "event quality", new EventQualityCut(), true); // 0
44  AddStep(StepBase::kCut, "> 0 tracks ", new MultiplicityCut(), true); // 1
45  AddStep(StepBase::kAction, "find leading tracks", new FillLeadingTracksAction_antiNueCC());
46  AddStep(StepBase::kAction, "Fill vertex info", new FillVertex());
47  AddStep(StepBase::kAction, "fill summary", new FillSummaryAction_antiNueCC());
48 
49  AddStep(StepBase::kCut, "TPC Quality", new TrackQualityCut(), true); // 2
50  AddStep(StepBase::kCut, "Momentum", new HighestMomentumCut()); // 3
51 
52  // Here the most energetic track must be positive and it has to be the most energetic compared to all TPC tracks
53  AddStep(StepBase::kAction, "find second most energetic track", new FindSecondMostEnergeticTPCTrack_antiNueCC());
54  AddStep(StepBase::kCut, "Most energetic positive track", new MostEnergeticTrackCut_antiNueCC()); // 4
55 
56  // e- PID cuts.
57  AddStep(StepBase::kCut, "TPC Electron Pull", new TPCElectronPullCut()); // 5
58  AddStep(StepBase::kCut, "TPC Muon Pull", new TPCMuonPullCut()); // 6
59  AddStep(StepBase::kCut, "TPC Pion Pull", new TPCPionPullCut()); // 7
60  AddStep(StepBase::kCut, "Ecal EMEnergy", new EcalEMEnergyCut_antiNueCC()); // 8
61  AddStep(StepBase::kCut, "Ecal MIPEM PID", new EcalMIPEMPIDCut()); // 9
62  AddStep(StepBase::kCut, "TPC2 PID", new SecondTPCPIDCut_antiNueCC()); // 10
63 
64  // Upstream vetos. Reduce OOFV background.
65  AddStep(StepBase::kAction, "find TPC Veto track", new FillTPCVetoTrackAction());
66  AddStep(StepBase::kCut, "TPC Veto", new TPCVetoCut()); // 11
67  AddStep(StepBase::kCut, "Gamma Iso Veto", new GammaIsoVetoCut()); // 12
68  AddStep(StepBase::kCut, "External FGD1", new ExternalFGD1layersCut()); // 13
69 
70  AddStep(StepBase::kAction, "find best e+e- pair", new FindPairsAction());
71  AddStep(StepBase::kCut, "Pair Veto", new PairCut()); // 14
72 
73  AddStep(StepBase::kAction, "find P0D veto track", new FindP0DVetoTrackAction());
74  AddStep(StepBase::kCut, "P0D Veto", new P0DVetoCut()); // 15
75 
76  AddStep(StepBase::kAction, "find ecal veto track", new FindECalVetoTrackAction());
77  AddStep(StepBase::kCut, "Ecal Veto", new ECalVetoCut()); // 16
78 
79  // Proton rejection in nuebar selection
80  AddStep(StepBase::kCut, "E over P", new EoverPCut_antiNueCC()); // 17
81  AddStep(StepBase::kCut, "Ecal EMHIP PID", new EcalEMHIPPIDCut_antiNueCC()); // 18
82  AddStep(StepBase::kCut, "FGD Shower", new FGDShowerCut_antiNueCC()); // 19
83 
84  // ToF for antinue selection
85  AddStep(StepBase::kCut, "ToF", new ToFCut_antiNueCC()); // 20
86 
87  // Momentum quality cut
88  AddStep(StepBase::kCut, "Momentum quality", new MomentumQualityCut()); // 21
89 
90  SetBranchAlias(0,"trunk");
91 
92 
93  // By default the preselection correspond to cuts 0-3
94  // It means that if any of the four first cuts (0,1,2,3) is not passed
95  // the loop over toys will be broken ===> A single toy will be run
96  SetPreSelectionAccumLevel(3); //
97 
98  _FindLeadingTracksStepIndex = GetStepNumber("find leading tracks");
99  _TotalMultiplicityCutIndex = GetCutNumber("> 0 tracks ");
100 
101  _ElecPIDCutIndex = GetCutNumber("TPC Electron Pull");
102  _ElecPIDStepIndex = GetStepNumber("TPC Electron Pull");
103 }
104 
105 //********************************************************************
106 bool antiNueCCSelection::FillEventSummary(AnaEventC& event, Int_t allCutsPassed[]){
107 //********************************************************************
108 
109 // The event sample corresponding to this selection
110  if(allCutsPassed[0]) static_cast<AnaEventSummaryB*>(event.Summary)->EventSample = SampleId::kFGD1AntiNuECC;
111 
112  return (static_cast<AnaEventSummaryB*>(event.Summary)->EventSample != SampleId::kUnassigned);
113 }
114 
115 //********************************************************************
117 //********************************************************************
118 
119  //ToyBoxTracker& nuebox = *static_cast<ToyBoxTracker*>(&boxB);
120  ToyBoxNueCC& nuebox = *static_cast<ToyBoxNueCC*>(&boxB);
121 
122  if(!nuebox.MainTrack) return false;
123 
124  static_cast<AnaEventSummaryB*>(event.Summary)->LeptonCandidate[SampleId::kFGD1AntiNuECC] = nuebox.MainTrack;
125  for(int i = 0; i < 4; ++i)
126  static_cast<AnaEventSummaryB*>(event.Summary)->VertexPosition[SampleId::kFGD1AntiNuECC][i] = nuebox.MainTrack->PositionStart[i];
127 
128  if(nuebox.MainTrack->GetTrueParticle())
129  static_cast<AnaEventSummaryB*>(event.Summary)->TrueVertex[SampleId::kFGD1AntiNuECC] = nuebox.MainTrack->GetTrueParticle()->TrueVertex;
130 
131  return true;
132 }
133 
134 //*********************************************************************
135 bool antiNueCCSelection::IsRelevantRecObjectForSystematic(const AnaEventC& event, AnaRecObjectC* recObj, SystId_h systId, Int_t branch) const{
136 //*********************************************************************
137 
138  return _nueCCSelection.IsRelevantRecObjectForSystematic(event, recObj, systId, branch);
139 }
140 
141 //*********************************************************************
142 bool antiNueCCSelection::IsRelevantTrueObjectForSystematic(const AnaEventC& event, AnaTrueObjectC* trueObj, SystId_h systId, Int_t branch) const{
143 //*********************************************************************
144 
145  return _nueCCSelection.IsRelevantTrueObjectForSystematic(event, trueObj, systId, branch);
146 }
147 
148 //**************************************************
149 bool antiNueCCSelection::IsRelevantRecObjectForSystematicInToy(const AnaEventC& event, const ToyBoxB& boxB, AnaRecObjectC* recObj, SystId_h systId, Int_t branch) const{
150 //**************************************************
151 
152  AnaTrackB* track = static_cast<AnaTrackB*>(recObj);
153 
154  // cast the box to the appropriate type
155  const ToyBoxNueCC& box = *static_cast<const ToyBoxNueCC*>(&boxB);
156 
157  // Special nuebar systematics
158  if(systId == SystId::kECalEmHipPID){
159  // Only applied to main track
160  if (track != box.MainTrack) return false;
161 
162  if(!nueCCUtils::UseEcal(track)) return false;
163  // Only applied for tracks with p > 600 MeV/c
164  if(track->Momentum < _protonregion_low) return false;
165 
166  return true;
167  }
168  else if(systId == SystId::kFGD2Shower){
169  // Only applied to main track
170  if (track != box.MainTrack) return false;
171 
172  // Only applied for tracks with p > _protonregion_low
173  if(track->Momentum < _protonregion_low) return false;
174 
175  // Conditions to apply this systematic
176  if(nueCCUtils::UseEcal(track)){
177  if(nueCutUtils::FGD2ShowerActivityEcal(track, _protonregion_low, box.FGD2ShowerNFGD1TPC2Tracks, box.FGD2ShowerNFGD2TPC3Tracks))
178  return true;
179 
180  return false;
181  }
182 
183  return true;
184  }
185 
186  return _nueCCSelection.IsRelevantRecObjectForSystematicInToy(event, boxB, recObj, systId, branch);
187 }
188 
189 //**************************************************
190 bool antiNueCCSelection::IsRelevantTrueObjectForSystematicInToy(const AnaEventC&event, const ToyBoxB& boxB, AnaTrueObjectC* trueObj, SystId_h systId, Int_t branch) const{
191 //**************************************************
192 
193  if(systId == SystId::kSIProton){
194  const ToyBoxTracker& box = *static_cast<const ToyBoxTracker*>(&boxB);
195 
196  AnaTrueParticleB* trueTrack = static_cast<AnaTrueParticleB*>(trueObj);
197 
198  // If this trueTrack is NOT associated to the MainTrack, consider the posibility of this trueTrack to become the MainTrack
199  // This is to be tuned: e.g. may consider explicitely those not reconstructed in TPC
200  // also the ones that have the momentum ~closer to the Bethe-Bloch crossing point,
201  // i.e. when proton background starts to become non-negligible
202  if (trueTrack->PDG == 2212 && trueTrack->Momentum > box.MainTrack->Momentum
203  && trueTrack->Momentum > _protonregion_low) return true;
204  }
205 
206  return _nueCCSelection.IsRelevantTrueObjectForSystematicInToy(event, boxB, trueObj, systId, branch);
207 }
208 
209 //*********************************************************************
210 bool antiNueCCSelection::IsRelevantSystematic(const AnaEventC& event, const ToyBoxB& boxB, SystId_h systId, Int_t branch) const{
211 //*********************************************************************
212 
213  // Anti-nue FGD1 related
214  if(systId == SystId::kECalEmHipPID) return true;
215  if(systId == SystId::kFGD2Shower) return true;
216 
217  // Rest are the same as in the nue analysis
218  return _nueCCSelection.IsRelevantSystematic(event, boxB, systId, branch);
219 }
220 
221 //*********************************************************************
222 bool antiNueCCSelection::CheckRedoSelection(const AnaEventC& eventC, const ToyBoxB& PreviousToyBoxB, Int_t& redoFromStep){
223 //*********************************************************************
224 
225  const AnaEventB& event = *static_cast<const AnaEventB*>(&eventC);
226 
227  // cast the box to the appropriate type
228  const ToyBoxNueCC& PreviousToyBox = *static_cast<const ToyBoxNueCC*>(&PreviousToyBoxB);
229 
230  /// Nothing to do if there is no HM or HMP track
231  if(!PreviousToyBox.HMtrack || !PreviousToyBox.HMPtrack) return false;
232 
233  // TODO: The code below implies calling cutUtils::FindLeadingTracks(event, box) twice. Can we avoid that ?
234  if(PreviousToyBox.MaxAccumLevel > _TotalMultiplicityCutIndex){
235  ToyBoxNueCC box;
236  trackerSelUtils::FindLeadingTracks(event, box);
237 
238  // Redo the selection if any of the leading tracks changes identity
239  if(PreviousToyBox.SHMNtrack!=box.SHMNtrack ||
240  PreviousToyBox.SHMPtrack!=box.SHMPtrack ||
241  PreviousToyBox.HMNtrack !=box.HMNtrack ||
242  PreviousToyBox.HMPtrack !=box.HMPtrack ||
243  PreviousToyBox.SHMtrack !=box.SHMtrack ||
244  PreviousToyBox.HMtrack !=box.HMtrack){
245 
246  redoFromStep = _FindLeadingTracksStepIndex;
247  return true;
248  }
249  }
250 
251  // When the HMP track does not change identity, Redo the selection if the effect of the PID cut is different.
252  // We have previously saved in the EventBox the AccumLevel of the previous toy for each branch.
253  // PreviousToyBox->AccumLevel[0]>_ElecPIDCutIndex means that the PID cut was passed, so we check whether the cut
254  // was passed in the previous toy and not in the current one, or the opposit, it was not passed before
255  // and it is passed now.
256 
257  if(PreviousToyBox.MaxAccumLevel >= _ElecPIDCutIndex){
258  //bool pidCut = nueCutUtils::TPCElectronPull(PreviousToyBox.HMPtrack, _pullel_accept_min, _pullel_accept_max, _pullel_accept_tight_min, _pullel_accept_tight_max, _minMom_ecal);
259  //if(( pidCut && (PreviousToyBox.AccumLevel[0] == _ElecPIDCutIndex)) ||
260  // (!pidCut && (PreviousToyBox.AccumLevel[0] > _ElecPIDCutIndex))){
261  // We should redo the selection starting from the PIDCut step
262  redoFromStep = _ElecPIDStepIndex;
263  return true;
264  //}
265  }
266 
267  return false;
268 }
269 
270 //*********************************************************************
272 //*********************************************************************
273 
274  _nueCCSelection.InitializeEvent(eventC);
275 }
276 
277 //*********************************************************************
279 //*********************************************************************
280 
281  ToyBoxNueCC& nuebox = *static_cast<ToyBoxNueCC*>(&boxB);
282 
283  //trackerSelUtils::FindLeadingTracksOld(event, box, false, det_FGD, true);
284  trackerSelUtils::FindLeadingTracks(event,boxB);
285 
286  if(nuebox.HMPtrack) nuebox.MainTrack = nuebox.HMPtrack;
287  if(!nuebox.MainTrack) return false;
288 
289  return true;
290 }
291 
292 //*********************************************************************
294 //*********************************************************************
295 
296  AnaEventB& event = *static_cast<AnaEventB*>(&eventC);
297 
298  // cast the box to the appropriate type
299  ToyBoxNueCC& nuebox = *static_cast<ToyBoxNueCC*>(&boxB);
300 
301  nuebox.SecondMostEnergeticTPCTrack = nueCCUtils::FindSecondTPCTrack(event, *nuebox.MainTrack);
302 
303  return true;
304 }
305 
306 //*********************************************************************
308 //*********************************************************************
309 
310  (void) event;
311 
312  // cast the box to the appropriate type
313  ToyBoxNueCC& nuebox = *static_cast<ToyBoxNueCC*>(&boxB);
314 
315  AnaTrackB* track = nuebox.MainTrack;
316  if(!track) return false;
317 
318  // Most energetic track must be positive
319  if(track != nuebox.HMtrack) return false;
320 
321  if(!nuebox.SecondMostEnergeticTPCTrack) return true;
322 
323  if(nuebox.SecondMostEnergeticTPCTrack->Momentum > track->Momentum) return false;
324 
325  return true;
326 }
327 
328 //**************************************************
330 //**************************************************
331 
332  (void) event;
333 
334  // cast the box to the appropriate type
335  ToyBoxNueCC& nuebox = *static_cast<ToyBoxNueCC*>(&boxB);
336 
337  AnaTrackB* track = nuebox.MainTrack;
338  if(!track) return false;
339 
340  return nueCutUtils::AntiNuSecondTPCPID(track, _protonregion_low, _protonregion_high, _pullelec_reject_min, _pullelec_reject_max);
341 }
342 
343 //**************************************************
345 //**************************************************
346 
347  (void) event;
348 
349  // cast the box to the appropriate type
350  ToyBoxNueCC& nuebox = *static_cast<ToyBoxNueCC*>(&boxB);
351 
352  AnaTrackB* track = nuebox.MainTrack;
353  if(!track) return false;
354 
355  return nueCutUtils::EcalEMEnergy(track, _Ethreshold, _Emin_ecal, _EoverP, true);
356 }
357 
358 
359 //**************************************************
360 bool EoverPCut_antiNueCC::Apply(AnaEventC& event, ToyBoxB& boxB) const {
361 //**************************************************
362 
363  AnaEventB& eventB = *static_cast<AnaEventB*>(&event);
364 
365  // cast the box to the appropriate type
366  ToyBoxNueCC& box = *static_cast<ToyBoxNueCC*>(&boxB);
367 
368  AnaTrackB* track = box.MainTrack;
369  if(!track) return false;
370 
371  // For FGD1 events only: If produced FGD2 shower activity then keep the event
372  if(nueCutUtils::FGD2ShowerActivityEcal(track, _protonregion_low, box.FGD2ShowerNFGD1TPC2Tracks, box.FGD2ShowerNFGD2TPC3Tracks))
373  return true;
374 
375  Int_t realrun = eventB.EventInfo.Run;
376  Int_t realsubrun = eventB.EventInfo.SubRun;
377 
378  Int_t run = anaUtils::GetRunPeriod(realrun,realsubrun);
379 
380  if(run < 8 || run == 13)
381  return nueCutUtils::EOverP(track, _protonregion_low, _eoverpfhc);
382  else
383  return nueCutUtils::EOverP(track, _protonregion_low, _eoverp);
384 }
385 
386 //**************************************************
388 //**************************************************
389 
390  AnaEventB& eventB = *static_cast<AnaEventB*>(&event);
391 
392  // cast the box to the appropriate type
393  ToyBoxNueCC& box = *static_cast<ToyBoxNueCC*>(&boxB);
394 
395  AnaTrackB* track = box.MainTrack;
396  if(!track) return false;
397 
398  // For FGD1 events only: If produced FGD2 shower activity then keep the event
399  if(nueCutUtils::FGD2ShowerActivityEcal(track, _protonregion_low, box.FGD2ShowerNFGD1TPC2Tracks, box.FGD2ShowerNFGD2TPC3Tracks))
400  return true;
401 
402  Int_t realrun = eventB.EventInfo.Run;
403  Int_t realsubrun = eventB.EventInfo.SubRun;
404 
405  Int_t run = anaUtils::GetRunPeriod(realrun,realsubrun);
406 
407  if(run < 8 || run == 13)
408  return (nueCutUtils::EcalEMHIPPID(track, _protonregion_low, _emhipfhc));
409  else
410  return (nueCutUtils::EcalEMHIPPID(track, _protonregion_low, _emhip));
411 }
412 
413 //**************************************************
415 //**************************************************
416 
417  (void) event;
418 
419  // cast the box to the appropriate type
420  ToyBoxNueCC& box = *static_cast<ToyBoxNueCC*>(&boxB);
421 
422  AnaTrackB* track = box.MainTrack;
423  if(!track) return false;
424 
425  return (nueCutUtils::FGD2Shower(track, _protonregion_low, _protonregion_high, box.FGD2ShowerNFGD1TPC2Tracks, box.FGD2ShowerNFGD2TPC3Tracks));
426 }
427 
428 //**************************************************
429 bool ToFCut_antiNueCC::Apply(AnaEventC& eventC, ToyBoxB& boxB) const {
430 //**************************************************
431 
432  AnaEventB& eventB = *static_cast<AnaEventB*>(&eventC);
433 
434  // Cast the ToyBox to the appropriate type
435  ToyBoxNueCC& nuebox = *static_cast<ToyBoxNueCC*>(&boxB);
436 
437  AnaTrackB* track = nuebox.MainTrack;
438  if(!track) return false;
439 
440  Int_t realrun = eventB.EventInfo.Run;
441  Int_t realsubrun = eventB.EventInfo.SubRun;
442 
443  Int_t run = anaUtils::GetRunPeriod(realrun,realsubrun);
444 
445  return (nueCutUtils::AntiNuToF(*track, _fgdecaltof, _fgd1fgd2tof, _protonregion_low, run));
446 }
AnaTrackB * SHMtrack
For storing the second highest momentum track.
AnaTrueVertexB * TrueVertex
Pointer to the AnaTrueVertexB of the interaction that created this AnaTrueParticleB.
Float_t PositionStart[4]
The reconstructed start position of the particle.
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...
Int_t MaxAccumLevel
Definition: ToyBoxB.hxx:39
bool Apply(AnaEventC &event, ToyBoxB &boxB) const
bool CheckRedoSelection(const AnaEventC &eventC, const ToyBoxB &PreviousToyBoxB, Int_t &redoFromStep)
bool IsRelevantTrueObjectForSystematicInToy(const AnaEventC &, const ToyBoxB &, AnaTrueObjectC *, SystId_h systId, Int_t branch) const
Is this true track relevant for a given systematic (after selection, called for each toy) ...
AnaTrackB * MainTrack
For storing the Main Track (The lepton candidate in geranal: HMN or HMP track)
Int_t FGD2ShowerNFGD2TPC3Tracks
FGD2 shower.
bool Apply(AnaEventC &event, ToyBoxB &boxB) const
Float_t Momentum
The initial momentum of the true particle.
AnaTrackB * HMPtrack
For storing the highest momentum positive track.
bool Apply(AnaEventC &eventC, ToyBoxB &boxB) const
AnaEventInfoB EventInfo
Run, sunrun, event, time stamp, etc.
bool Apply(AnaEventC &event, ToyBoxB &boxB) const
Int_t SubRun
The subrun number.
Float_t Momentum
The reconstructed momentum of the particle, at the start position.
Representation of a true Monte Carlo trajectory/particle.
bool Apply(AnaEventC &event, ToyBoxB &boxB) const
int GetRunPeriod(int run, int subrun=-1)
Returns the run period (sequentially: 0,1,2,3,4,5 ...)
Int_t PDG
The PDG code of this particle.
bool Apply(AnaEventC &event, ToyBoxB &boxB) const
AnaTrackB * HMNtrack
For storing the highest momentum negative track.
bool Apply(AnaEventC &event, ToyBoxB &boxB) const
AnaTrackB * SHMPtrack
For storing the second highest momentum positive track.
Representation of a global track.
AnaTrackB * HMtrack
For storing the highest momentum track.
AnaTrackB * SecondMostEnergeticTPCTrack
The second most energetic TPC track.
bool Apply(AnaEventC &event, ToyBoxB &boxB) const
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...
AnaEventSummaryC * Summary
A summary of the event with high level quantities.
void DefineSteps()
Define all steps in the selection.
AnaTrackB * SHMNtrack
For storing the second highest momentum negative track.
bool Apply(AnaEventC &event, ToyBoxB &boxB) const
void InitializeEvent(AnaEventC &eventC)
Fill the EventBox with the objects needed by this selection.
bool Apply(AnaEventC &eventC, ToyBoxB &boxB) const
AnaTrueParticleB * GetTrueParticle() const
Return a casted version of the AnaTrueObject associated.
bool IsRelevantRecObjectForSystematicInToy(const AnaEventC &, const ToyBoxB &, AnaRecObjectC *, SystId_h systId, Int_t branch) const
Is this track relevant for a given systematic (after selection, called for each toy) ...
bool IsRelevantSystematic(const AnaEventC &event, const ToyBoxB &boxB, SystId_h systId, Int_t branch) const
Is this systematic relevant for this selection.
A cut on event quality. Requires good beam and ND280 data quality flags.
void DefineDetectorFV()
Define the detector Fiducial Volume in which this selection is applied.
void Initialize()
Initialize this selection: defines the steps and the detectorFV.
Int_t Run
The ND280 run number.