HighLAND
gammaFGD2Selection.cxx
1 #include "gammaFGD2Selection.hxx"
2 #include "gammaSelection.hxx"
3 
4 #include "baseSelection.hxx"
5 #include "CutUtils.hxx"
6 #include "EventBoxUtils.hxx"
7 #include "VersioningUtils.hxx"
8 #include "SystematicUtils.hxx"
9 #include "trackerSelectionUtils.hxx"
10 #include "SystematicTuning.hxx"
11 
12 #include "nueCCUtils.hxx"
13 #include "nueCutUtils.hxx"
14 
15 //********************************************************************
16 gammaFGD2Selection::gammaFGD2Selection(bool forceBreak): SelectionBase(forceBreak, EventBoxId::kEventBoxTracker) {
17 //********************************************************************
18 
19  _nueCCSelection.Initialize();
20 
21  //_elepullpri_min = (Float_t)ND::params().GetParameterD("gammaAnalysis.Cuts.PID.PullElecMin");
22  //_elepullpri_max = (Float_t)ND::params().GetParameterD("gammaAnalysis.Cuts.PID.PullElecMax");
23 }
24 
25 //********************************************************************
27 //********************************************************************
28 
29  // last "true" means the step sequence is broken if cut is not passed (default is "false")
30  AddStep(StepBase::kCut, "Event quality", new EventQualityCut(), true); // 0
31  AddStep(StepBase::kCut, "> 0 tracks ", new MultiplicityCut(), true); // 1
32  AddStep(StepBase::kAction, "Find leading tracks", new FindLeadingTracksAction_gamma() );
33  AddStep(StepBase::kAction, "Find vertex", new FillVertex() );
34  AddStep(StepBase::kAction, "Fill summary", new FillSummaryActionGamma() );
35 
36  AddStep(StepBase::kCut, "# TPC nodes 1ary track", new PrimaryTrackQualityCut_gamma() ); // 2
37 
38  AddStep(StepBase::kCut, "Highest Momentum Track Momentum cut", new HighestMomentumCut() ); // 3
39  AddStep(StepBase::kCut, "Electron PID", new PIDCut_gamma() ); // 4
40  AddStep(StepBase::kAction, "Find secondary tracks", new FindPairsAction() );
41  AddStep(StepBase::kCut, "Secondary Track", new PairTrackCut_gamma() ); // 5
42  AddStep(StepBase::kCut, "Invariant Mass Cut", new MinvCut_gamma() ); // 6
43 
44  AddStep(StepBase::kAction, "find best FGD1 e+e- pair", new FindFGD1PairsAction_gamma() );
45  AddStep(StepBase::kCut, "Pair Veto", new FGD1PairCut_gamma() ); // 7
46  SetBranchAlias(0, "Gamma Selection");
47 
48  _FindLeadingTracksStepIndex = GetStepNumber("Find leading tracks");
49  _TotalMultiplicityCutIndex = GetCutNumber("> 0 tracks ");
50 
51  _ElecPIDCutIndex = GetCutNumber("Electron PID");
52  _ElecPIDStepIndex = GetStepNumber("Electron PID");
53 
54  // By default the preselection correspond to cuts 0-3
55  // It means that if any of the four first cuts (0,1,2,3) is not passed
56  // the loop over toys will be broken ===> A single toy will be run
57  SetPreSelectionAccumLevel(3);
58 
59 }
60 
61 //**************************************************
63 //**************************************************
64 
65  AnaEventB& event = *static_cast<AnaEventB*>(&eventC);
66  ToyBoxNueCC& nuebox = *static_cast<ToyBoxNueCC*>(&boxB);
67 
68  AnaTrackB* MainTrackFGD1 = nueCCUtils::FindLeadingTrackInDet(event, SubDetId::kFGD1);
69 
70  if(!MainTrackFGD1){
71  nuebox.VetoTrack = NULL;
72  return true;
73  }
74 
75  if(nuebox.VetoTrack)
76  std::cout << "nuebox.VetoTrack already used!" << std::endl;
77 
78  nuebox.VetoTrack = nueCCUtils::FindPairTrack(event, *MainTrackFGD1, _delta_pos_max, _pullel_min, _pullel_max);
79 
80  return true;
81 
82 }
83 
84 //**************************************************
85 bool FGD1PairCut_gamma::Apply(AnaEventC& event, ToyBoxB& boxB) const {
86 //**************************************************
87 
88  (void) event;
89 
90  ToyBoxNueCC& nuebox = *static_cast<ToyBoxNueCC*>(&boxB);
91 
92  if(nuebox.VetoTrack) return false;
93 
94  return true;
95 
96 }
97 
98 //********************************************************************
100 //********************************************************************
101 
102  // The detector in which the selection is applied
103  SetDetectorFV(SubDetId::kFGD2);
104 
105  // Set the detector field into the selection being used
106  _nueCCSelection.SetDetectorFV(SubDetId::kFGD2);
107 }
108 
109 //********************************************************************
110 bool gammaFGD2Selection::FillEventSummary(AnaEventC& event, Int_t allCutsPassed[]){
111 //********************************************************************
112 
113  // The event sample corresponding to this selection
114  if(allCutsPassed[0])
115  static_cast<AnaEventSummaryB*>(event.Summary)->EventSample = SampleId::kFGD2Gamma;
116 
117  return (static_cast<AnaEventSummaryB*>(event.Summary)->EventSample != SampleId::kUnassigned);
118 
119 }
120 
121 //*********************************************************************
123 //*********************************************************************
124 
125  _nueCCSelection.InitializeEvent(eventC);
126 
127 }
128 
129 //*********************************************************************
130 bool gammaFGD2Selection::IsRelevantRecObjectForSystematic(const AnaEventC& event, AnaRecObjectC* recObj, SystId_h systId, Int_t branch) const{
131 //*********************************************************************
132 
133  (void)event;
134  (void)branch;
135 
136  AnaTrackB* track = static_cast<AnaTrackB*>(recObj);
137 
138  // True track should always exist
139  if(!track->TrueObject) return false;
140 
141  if(systId == SystId::kTpcClusterEff){
142  if(track->nTPCSegments == 0) return false;
143  // AnaTPCParticleB* tpcTrack = static_cast<AnaTPCParticleB*>(track->TPCSegments[0]);
145  if(!tpcTrack) return false;
146 
147  if(tpcTrack->NNodes == 17 || tpcTrack->NNodes == 18)
148  return true;
149 
150  return false;
151  }
152 
153  return true;
154 
155 }
156 
157 //*********************************************************************
158 bool gammaFGD2Selection::IsRelevantTrueObjectForSystematic(const AnaEventC& eventC, AnaTrueObjectC* trueObj, SystId_h systId, Int_t branch) const{
159 //*********************************************************************
160 
161  return _nueCCSelection.IsRelevantTrueObjectForSystematic(eventC, trueObj, systId, branch);
162 
163 }
164 
165 //**************************************************
166 bool gammaFGD2Selection::IsRelevantRecObjectForSystematicInToy(const AnaEventC& event, const ToyBoxB& boxB, AnaRecObjectC* recObj, SystId_h systId, Int_t branch) const{
167 //**************************************************
168 
169  (void)event;
170  (void)branch;
171 
172  const ToyBoxNueCC &nuebox = *static_cast<const ToyBoxNueCC*>(&boxB);
173 
174  AnaTrackB* track = static_cast<AnaTrackB*>(recObj);
175 
176  // cast the box to the appropriate type
177 
178  if(systId == SystId::kChargeIDEff){
179  if (track != nuebox.MainTrack && track != nuebox.PairTrack) return false;
180  }
181 
182  return true;
183 
184 }
185 
186 //**************************************************
187 bool gammaFGD2Selection::IsRelevantTrueObjectForSystematicInToy(const AnaEventC& event, const ToyBoxB& boxB, AnaTrueObjectC* trueObj, SystId_h systId, Int_t branch) const{
188 //**************************************************
189 
190  (void)event;
191  (void)branch;
192 
193  // cast the box to the appropriate type
194  const ToyBoxNueCC &box = *static_cast<const ToyBoxNueCC*>(&boxB);
195 
196  AnaTrueParticleB* truePart = static_cast<AnaTrueParticleB*>(trueObj);
197 
198  if(systId == SystId::kTpcTrackEff){
199  if(box.MainTrack->TrueObject){
200  // At first order the inclusive selection only depends on the tracking efficiency of the electron candidate.
201  if(truePart->ID == box.MainTrack->GetTrueParticle()->ID) return true;
202  // Consider also the case in which the electron candidate is not a true electron but this track it is
203  if(abs(truePart->PDG) == 11 && abs(box.MainTrack->GetTrueParticle()->PDG) != 11) return true;
204 
205  // Otherwise don't consider this TrueObject
206  return false;
207  }
208 
209  // Now check the paired track
210  if(box.PairTrack->TrueObject){
211  // At first order the inclusive selection only depends on the tracking efficiency of the electron candidate.
212  if(truePart->ID == box.PairTrack->GetTrueParticle()->ID) return true;
213 
214  // Consider also the case in which the electron candidate is not a true electron but this track it is
215  if(abs(truePart->PDG) == 11 && abs(box.PairTrack->GetTrueParticle()->PDG) != 11) return true;
216 
217  // Otherwise don't consider this TrueObject
218  return false;
219  }
220  }
221  else if(systId == SystId::kSIPion){
222  if(box.MainTrack->TrueObject && truePart->ID == box.MainTrack->GetTrueParticle()->ID){
223  if(abs(box.MainTrack->GetTrueParticle()->PDG) == 211) return true;
224  if(abs(box.MainTrack->GetTrueParticle()->ParentPDG) == 211) return true;
225  if(abs(box.MainTrack->GetTrueParticle()->GParentPDG) == 211) return true;
226  return false;
227  }
228  // If this truePart is NOT associated to the MainTrack, consider the posibility of this truePart to become the MainTrack and be identified as electron
229  // For the moment assume a negative pion may become the MainTrack if its momentum its above 90% of the current MainTrack momentum.
230  // Ideally we should check that this true pion is not associated to any reconstructed track, but this is not possible now without looping.
231  // Multiply by the charge of the MainTrack such that it can be use for antiNumu selection
232  if (truePart->PDG == 211*((Int_t)box.MainTrack->Charge) && truePart->Momentum > 0.9*box.MainTrack->Momentum) return true;
233 
234  // Now check the paired track - it doesn't have to be the most energetic track
235  if(box.PairTrack->TrueObject && truePart->ID == box.PairTrack->GetTrueParticle()->ID){
236  if(abs(box.PairTrack->GetTrueParticle()->PDG) == 211) return true;
237  if(abs(box.PairTrack->GetTrueParticle()->ParentPDG) == 211) return true;
238  if(abs(box.PairTrack->GetTrueParticle()->GParentPDG) == 211) return true;
239 
240  return false;
241  }
242  }
243  else if(systId == SystId::kSIProton){
244  // If this truePart is associated to the MainTrack
245  if(box.MainTrack->GetTrueParticle() && truePart->ID == box.MainTrack->GetTrueParticle()->ID){
246  if(box.MainTrack->GetTrueParticle()->PDG == 2212) return true;
247  if(box.MainTrack->GetTrueParticle()->ParentPDG == 2212) return true;
248  if(box.MainTrack->GetTrueParticle()->GParentPDG == 2212) return true;
249  return false;
250  }
251  // If this truePart is NOT associated to the MainTrack, consider the posibility of this truePart to become the MainTrack
252  if(truePart->PDG == 2212 && truePart->Momentum > 0.9*box.MainTrack->Momentum) return true;
253 
254  // Now check the paired track - it doesn't have to be the most energetic track
255  if(box.PairTrack->GetTrueParticle() && truePart->ID == box.PairTrack->GetTrueParticle()->ID){
256  if(box.PairTrack->GetTrueParticle()->PDG == 2212) return true;
257  if(box.PairTrack->GetTrueParticle()->ParentPDG == 2212) return true;
258  if(box.PairTrack->GetTrueParticle()->GParentPDG == 2212) return true;
259  return false;
260  }
261 
262  return false;
263  }
264 
265  return true;
266 
267 }
268 
269 //*********************************************************************
270 bool gammaFGD2Selection::IsRelevantSystematic(const AnaEventC& event, const ToyBoxB& boxB, SystId_h systId, Int_t branch) const{
271 //*********************************************************************
272 
273  (void)event;
274  (void)branch;
275  (void)boxB;
276 
277  if (systId == SystId::kFgdTrackEff) // No FGD track eff
278  return false;
279  else if(systId == SystId::kFgdHybridTrackEff) // No FGD hybrid track eff
280  return false;
281  else if(systId == SystId::kMichelEleEff) // No michel electron Systematic
282  return false;
283  else if(systId == SystId::kSIPion){
284  // check whether should be applied what the main track is a true pion or its product
285  if (!systTuning::APPLY_SYST_FINE_TUNING) return false;
286  }
287  else if(systId == SystId::kSIProton){
288  //check whether should be still applied when the main track is a true proton or its product: TESTING PURPOSES
289  if(!systTuning::APPLY_SYST_FINE_TUNING) return false;
290  }
291  else if(systId == SystId::kECalTrackEff) // No ecal related syst
292  return false;
293  else if(systId == SystId::kTpcECalMatchEff) // No ecal related syst
294  return false;
295  else if(systId == SystId::kECalEmHipPID) // No ecal related syst
296  return false;
297  else if(systId == SystId::kFGD2Shower) // No fgd2 shower syst
298  return false;
299  else if(systId == SystId::kECalPID) // No ecal related syst
300  return false;
301  else if(systId == SystId::kNuETPCPileUp) // No pile-up syst
302  return true; ///Changed that because I added the TPC2 veto (PL 21/07)
303  else if(systId == SystId::kNuEP0DPileUp) // No pile-up syst
304  return false;
305  else if(systId == SystId::kNuEECalPileUp) // No pile-up syst
306  return false;
307  else if(systId == SystId::kPileUp) // No pile-up syst
308  return false;
309  else if(systId == SystId::kOOFV) // Different oofv syst for gamma
310  return false;
311 
312  return true;
313 
314 }
315 
316 //*********************************************************************
317 bool gammaFGD2Selection::CheckRedoSelection(const AnaEventC& eventC, const ToyBoxB& PreviousToyBoxB, Int_t& redoFromStep){
318 //*********************************************************************
319 
320  const AnaEventB& event = *static_cast<const AnaEventB*>(&eventC);
321 
322  // cast the box to the appropriate type
323  const ToyBoxNueCC& PreviousToyBox = *static_cast<const ToyBoxNueCC*>(&PreviousToyBoxB);
324 
325  if(!PreviousToyBox.HMtrack) return false;
326 
327  // TODO: The code below implies calling cutUtils::FindLeadingTracks(event, box) twice. Can we avoid that ?
328  if(PreviousToyBox.MaxAccumLevel > _TotalMultiplicityCutIndex){
329  ToyBoxNueCC box;
330  trackerSelUtils::FindLeadingTracks(event, box);
331 
332  // Redo the selection if any of the leading tracks changes identity
333  if(PreviousToyBox.SHMNtrack != box.SHMNtrack ||
334  PreviousToyBox.SHMPtrack != box.SHMPtrack ||
335  PreviousToyBox.HMNtrack != box.HMNtrack ||
336  PreviousToyBox.HMPtrack != box.HMPtrack ||
337  PreviousToyBox.SHMtrack != box.SHMtrack ||
338  PreviousToyBox.HMtrack != box.HMtrack){
339 
340  redoFromStep = _FindLeadingTracksStepIndex;
341  return true;
342  }
343  }
344 
345  if(PreviousToyBox.MaxAccumLevel >= _ElecPIDCutIndex){
346  //bool pidCut = nueCutUtils::TPCElectronPull(PreviousToyBox.HMtrack, _elepullpri_min, _elepullpri_max, _elepullpri_min, _elepullpri_max, 0.0);
347  //if(( pidCut && (PreviousToyBox.AccumLevel[0] == _ElecPIDCutIndex)) ||
348  // (!pidCut && (PreviousToyBox.AccumLevel[0] > _ElecPIDCutIndex))){
349  // We should redo the selection starting from the PIDCut step
350  redoFromStep = _ElecPIDStepIndex;
351  return true;
352  //}
353  }
354 
355  return false;
356 }
AnaTrackB * SHMtrack
For storing the second highest momentum track.
bool Apply(AnaEventC &event, ToyBoxB &boxB) const
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) ...
bool CheckRedoSelection(const AnaEventC &eventC, const ToyBoxB &PreviousToyBox, Int_t &redoFromStep)
Int_t MaxAccumLevel
Definition: ToyBoxB.hxx:39
void InitializeEvent(AnaEventC &event)
Fill the EventBox with the objects needed by this selection.
Int_t NNodes
The number of nodes in the reconstructed object.
Int_t GParentPDG
The PDG code of this particle&#39;s grandparent, or 0 if there is no grandparent.
AnaTrackB * MainTrack
For storing the Main Track (The lepton candidate in geranal: HMN or HMP track)
AnaTrueObjectC * TrueObject
The link to the true oject that most likely generated this reconstructed object.
Float_t Momentum
The initial momentum of the true particle.
AnaTrackB * HMPtrack
For storing the highest momentum positive 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) ...
Float_t Charge
The reconstructed charge of the particle.
Int_t ID
The ID of the trueObj, which corresponds to the ID of the TTruthParticle that created it...
Float_t Momentum
The reconstructed momentum of the particle, at the start position.
int nTPCSegments
How many TPC tracks are associated with this track.
Representation of a true Monte Carlo trajectory/particle.
AnaTrackB * VetoTrack
The TPC veto track.
Int_t PDG
The PDG code of this particle.
AnaTrackB * HMNtrack
For storing the highest momentum negative track.
Int_t ParentPDG
The PDG code of this particle&#39;s immediate parent, or 0 if there is no parent.
bool IsRelevantSystematic(const AnaEventC &event, const ToyBoxB &box, SystId_h systId, Int_t branch) const
Is this systematic relevant for this selection.
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.
bool IsRelevantRecObjectForSystematic(const AnaEventC &event, AnaRecObjectC *track, SystId_h systId, Int_t branch) const
Is this track relevant for a given systematic (prior to selection, call when initializing the event...
void DefineSteps()
Define all steps in the selection.
Representation of a TPC segment of a global track.
bool APPLY_SYST_FINE_TUNING
General tuning, the concept of apply the systematic for only the "relevant" objects.
AnaEventSummaryC * Summary
A summary of the event with high level quantities.
AnaTrackB * SHMNtrack
For storing the second highest momentum negative track.
AnaTrackB * PairTrack
The particle that isn&#39;t HMTrackSelected that forms the e+e- pair with the lowest invariant mass...
AnaParticleB * GetSegmentWithMostNodesInClosestTpc(const AnaTrackB &track)
Combined function to address NuMu selection needs as efficiently as possible - gets the TPC segment w...
AnaTrueParticleB * GetTrueParticle() const
Return a casted version of the AnaTrueObject associated.
void DefineDetectorFV()
Define the detector Fiducial Volume in which this selection is applied.
bool IsRelevantTrueObjectForSystematic(const AnaEventC &event, AnaTrueObjectC *trueTrack, SystId_h systId, Int_t branch) const
Is this true track relevant for a given systematic (prior to selection, call when initializing the ev...
A cut on event quality. Requires good beam and ND280 data quality flags.
void Initialize()
Initialize this selection: defines the steps and the detectorFV.