HighLAND
gammaSelection.cxx
1 #include "gammaSelection.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 #include "SystematicTuning.hxx"
10 
11 #include "nueCCUtils.hxx"
12 #include "nueCutUtils.hxx"
13 
14 //********************************************************************
15 gammaSelection::gammaSelection(bool forceBreak): SelectionBase(forceBreak, EventBoxId::kEventBoxTracker) {
16 //********************************************************************
17 
18  _nueCCSelection.Initialize();
19 
20  //_elepullpri_min = (Float_t)ND::params().GetParameterD("gammaAnalysis.Cuts.PID.PullElecMin");
21  //_elepullpri_max = (Float_t)ND::params().GetParameterD("gammaAnalysis.Cuts.PID.PullElecMax");
22 }
23 
24 //********************************************************************
26 //********************************************************************
27 
28  // last "true" means the step sequence is broken if cut is not passed (default is "false")
29  AddStep(StepBase::kCut, "Event quality", new EventQualityCut(), true); // 0
30  AddStep(StepBase::kCut, "> 0 tracks ", new MultiplicityCut(), true); // 1
31  AddStep(StepBase::kAction, "Find leading tracks", new FindLeadingTracksAction_gamma() );
32  AddStep(StepBase::kAction, "Find vertex", new FillVertex() );
33  AddStep(StepBase::kAction, "Fill summary", new FillSummaryActionGamma() );
34 
35  AddStep(StepBase::kCut, "# TPC nodes 1ary track", new PrimaryTrackQualityCut_gamma() ); // 2
36 
37  AddStep(StepBase::kCut, "Highest Momentum Track Momentum cut", new HighestMomentumCut() ); // 3
38  AddStep(StepBase::kCut, "Electron PID", new PIDCut_gamma() ); // 4
39  AddStep(StepBase::kAction, "Find secondary tracks", new FindPairsAction() );
40  AddStep(StepBase::kCut, "Secondary Track", new PairTrackCut_gamma() ); // 5
41  AddStep(StepBase::kCut, "Invariant Mass Cut", new MinvCut_gamma() ); // 6
42 
43  SetBranchAlias(0, "Gamma Selection");
44 
45  _FindLeadingTracksStepIndex = GetStepNumber("Find leading tracks");
46  _TotalMultiplicityCutIndex = GetCutNumber("> 0 tracks ");
47 
48  _ElecPIDCutIndex = GetCutNumber("Electron PID");
49  _ElecPIDStepIndex = GetStepNumber("Electron PID");
50 
51  // By default the preselection correspond to cuts 0-3
52  // It means that if any of the four first cuts (0,1,2,3) is not passed
53  // the loop over toys will be broken ===> A single toy will be run
54  SetPreSelectionAccumLevel(3);
55 
56 }
57 
58 //********************************************************************
60 //********************************************************************
61 
62  // The detector in which the selection is applied
63  SetDetectorFV(SubDetId::kFGD1);
64 
65  // Set the detector field into the selection being used
66  _nueCCSelection.SetDetectorFV(SubDetId::kFGD1);
67 
68 }
69 
70 //********************************************************************
71 bool FillSummaryActionGamma::Apply(AnaEventC& eventC, ToyBoxB& boxB) const{
72 //********************************************************************
73 
74  ToyBoxNueCC& box = *static_cast<ToyBoxNueCC*>(&boxB);
75 
76  if(!box.MainTrack) return false;
77 
78  static_cast<AnaEventSummaryB*>(eventC.Summary)->LeptonCandidate[SampleId::kFGD1Gamma] = box.MainTrack;
79 
80  for(int i = 0; i < 4; ++i){
81  static_cast<AnaEventSummaryB*>(eventC.Summary)->VertexPosition[SampleId::kFGD1Gamma][i] = box.MainTrack->PositionStart[i];
82  }
83 
84  if(box.MainTrack->GetTrueParticle()){
85  static_cast<AnaEventSummaryB*>(eventC.Summary)->TrueVertex[SampleId::kFGD1Gamma] = box.MainTrack->GetTrueParticle()->TrueVertex;
86  }
87 
88  return true;
89 
90 }
91 
92 //********************************************************************
93 bool gammaSelection::FillEventSummary(AnaEventC& eventC, Int_t allCutsPassed[]){
94 //********************************************************************
95 
96  // The event sample corresponding to this selection
97  if(allCutsPassed[0])
98  static_cast<AnaEventSummaryB*>(eventC.Summary)->EventSample = SampleId::kFGD1Gamma;
99 
100  return (static_cast<AnaEventSummaryB*>(eventC.Summary)->EventSample != SampleId::kUnassigned);
101 
102 }
103 
104 //*********************************************************************
106 //*********************************************************************
107 
108  ToyBoxNueCC& box = *static_cast<ToyBoxNueCC*>(&boxB);
109 
110  trackerSelUtils::FindLeadingTracks(eventC, boxB);
111 
112  if( box.HMtrack) box.MainTrack = box.HMtrack;
113  //if(!box.MainTrack) return false;
114 
115  return true;
116 
117 }
118 
119 //*********************************************************************
120 bool PairTrackCut_gamma::Apply(AnaEventC& eventC, ToyBoxB& boxB) const{
121 //*********************************************************************
122 
123  (void) eventC;
124 
125  ToyBoxNueCC& nuebox = *static_cast<ToyBoxNueCC*>(&boxB);
126  bool accept = (nuebox.PairTrack);
127 
128  return accept;
129 
130 }
131 
132 //*********************************************************************
134 //*********************************************************************
135 
136  (void) eventC;
137 
138  ToyBoxNueCC& box = *static_cast<ToyBoxNueCC*>(&boxB);
139 
140  // No vertex - reject
141  if(!box.Vertex) return false;
142 
143  AnaTrackB* track = box.MainTrack;
144  if(!track) return false;
145 
146  return nueCutUtils::TrackQuality(track, _num_tpc_nodes, _num_tpc_nodes);
147 
148 }
149 
150 
151 //*********************************************************************
152 bool MinvCut_gamma::Apply(AnaEventC& eventC, ToyBoxB& boxB) const{
153 //*********************************************************************
154 
155  (void) eventC;
156 
157  ToyBoxNueCC& nuebox = *static_cast<ToyBoxNueCC*>(&boxB);
158 
159  if (!nuebox.MainTrack)
160  return false;
161 
162  if (!nuebox.PairTrack)
163  return false;
164 
165  return (nueCCUtils::GetInvMass(*nuebox.MainTrack, *nuebox.PairTrack) < _inv_mass_min);
166 
167 }
168 
169 //*********************************************************************
170 bool PIDCut_gamma::Apply(AnaEventC& eventC, ToyBoxB& boxB) const{
171 //*********************************************************************
172 
173  (void) eventC;
174  ToyBoxNueCC& box = *static_cast<ToyBoxNueCC*>(&boxB);
175 
176  AnaTrackB* track_pri = box.MainTrack;
177  // AnaTrackB* track_sec = box.PairTrack;
178 
179  bool accept = nueCutUtils::TPCElectronPull(track_pri, _elepullpri_min, _elepullpri_max,
180  _elepullpri_min, _elepullpri_max, 0.0);
181 
182  return accept;
183 
184 }
185 
186 
187 
188 //*********************************************************************
190 //*********************************************************************
191 
192  _nueCCSelection.InitializeEvent(eventC);
193 }
194 
195 //*********************************************************************
196 bool gammaSelection::CheckRedoSelection(const AnaEventC& eventC, const ToyBoxB& PreviousToyBoxB, Int_t& redoFromStep){
197 //*********************************************************************
198 
199  const AnaEventB& event = *static_cast<const AnaEventB*>(&eventC);
200 
201  // cast the box to the appropriate type
202  const ToyBoxNueCC& PreviousToyBox = *static_cast<const ToyBoxNueCC*>(&PreviousToyBoxB);
203 
204  if(!PreviousToyBox.HMtrack) return false;
205 
206  // TODO: The code below implies calling cutUtils::FindLeadingTracks(event, box) twice. Can we avoid that ?
207  if(PreviousToyBox.MaxAccumLevel > _TotalMultiplicityCutIndex){
208  ToyBoxNueCC box;
209  trackerSelUtils::FindLeadingTracks(event, box);
210 
211  // Redo the selection if any of the leading tracks changes identity
212  if(PreviousToyBox.SHMNtrack != box.SHMNtrack ||
213  PreviousToyBox.SHMPtrack != box.SHMPtrack ||
214  PreviousToyBox.HMNtrack != box.HMNtrack ||
215  PreviousToyBox.HMPtrack != box.HMPtrack ||
216  PreviousToyBox.SHMtrack != box.SHMtrack ||
217  PreviousToyBox.HMtrack != box.HMtrack){
218 
219  redoFromStep = _FindLeadingTracksStepIndex;
220  return true;
221  }
222  }
223 
224  if(PreviousToyBox.MaxAccumLevel >= _ElecPIDCutIndex){
225  //bool pidCut = nueCutUtils::TPCElectronPull(PreviousToyBox.HMtrack, _elepullpri_min, _elepullpri_max, _elepullpri_min, _elepullpri_max, 0.0);
226  //if(( pidCut && (PreviousToyBox.AccumLevel[0] == _ElecPIDCutIndex)) ||
227  // (!pidCut && (PreviousToyBox.AccumLevel[0] > _ElecPIDCutIndex))){
228  // We should redo the selection starting from the PIDCut step
229  redoFromStep = _ElecPIDStepIndex;
230  return true;
231  //}
232  }
233 
234  /*
235  AnaTrackB* selTracks[NMAXPARTICLES];
236  int nTPC = anaUtils::GetAllTracksUsingTPC(event, selTracks);
237  double distance_min, distance;
238  for (int i = 0; i < nTPC; i++){
239  AnaTrackB* secondary = selTracks[i];
240 
241  if(secondary == box.SHMNtrack ||
242  secondary == box.SHMPtrack ||
243  secondary == box.HMNtrack ||
244  secondary == box.HMPtrack ||
245  secondary == box.SHMtrack ||
246  secondary == box.HMtrack)
247  continue;
248 
249  if(!cutUtils::FiducialCut(*secondary, static_cast<SubDetId::SubDetEnum>(box.DetectorFV)))
250  continue;
251 
252  if(box.MainTrack->Charge * secondary->Charge > 0)
253  continue;
254 
255  TVector3 PrimaryPos = anaUtils::ArrayToTVector3(box.MainTrack->PositionStart);
256  TVector3 SecondaryPos = anaUtils::ArrayToTVector3(secondary->PositionStart);
257 
258  //Calculate distance between tracks
259  distance = (PrimaryPos - SecondaryPos).Mag();
260  if(distance < distance_min) {
261  nuebox.PairTrack = secondary; //Fill secondary track box with closer track
262  distance_min = distance;
263  }
264  }
265  if(PreviousNuebox.PairTrack != nuebox.PairTrack){
266  redoFromStep = _FindPairTracksStepIndex;
267  return true;
268  }
269  }
270  */
271 
272  return false;
273 
274 }
275 
276 
277 //*********************************************************************
278 bool gammaSelection::IsRelevantRecObjectForSystematic(const AnaEventC& event, AnaRecObjectC* trackRecC, SystId_h systId, Int_t branch) const{
279 //*********************************************************************
280 
281  (void)event;
282  (void)branch;
283 
284  AnaTrackB* track = static_cast<AnaTrackB*>(trackRecC);
285 
286  // True track should always exist
287  if(!track->TrueObject) return false;
288 
289  if(systId == SystId::kTpcClusterEff){
290  if(track->nTPCSegments == 0) return false;
291  // AnaTPCParticleB* tpcTrack = static_cast<AnaTPCParticleB*>(track->TPCSegments[0]);
293  if(!tpcTrack) return false;
294 
295  if(tpcTrack->NNodes == 17 || tpcTrack->NNodes == 18)
296  return true;
297 
298  return false;
299  }
300 
301  return true;
302 
303 }
304 
305 
306 //*********************************************************************
307 bool gammaSelection::IsRelevantTrueObjectForSystematic(const AnaEventC& event, AnaTrueObjectC* trueTrack, SystId_h systId, Int_t branch) const{
308 //*********************************************************************
309 
310  return _nueCCSelection.IsRelevantTrueObjectForSystematic(event, trueTrack, systId, branch);
311 
312 }
313 
314 
315 //*********************************************************************
316 bool gammaSelection::IsRelevantRecObjectForSystematicInToy(const AnaEventC& event, const ToyBoxB& boxB, AnaRecObjectC* recObj, SystId_h systId, Int_t branch) const{
317 //*********************************************************************
318 
319  (void)event;
320  (void)branch;
321 
322  // cast the box to the appropriate type
323  const ToyBoxNueCC &nuebox = *static_cast<const ToyBoxNueCC*>(&boxB);
324 
325  AnaTrackB* track = static_cast<AnaTrackB*>(recObj);
326 
327  if(systId == SystId::kChargeIDEff){
328  if (track != nuebox.MainTrack && track != nuebox.PairTrack) return false;
329  }
330 
331  return true;
332 
333 }
334 
335 
336 //*********************************************************************
337 bool gammaSelection::IsRelevantTrueObjectForSystematicInToy(const AnaEventC& event, const ToyBoxB& boxB, AnaTrueObjectC* trueObj, SystId_h systId, Int_t branch) const{
338 //*********************************************************************
339 
340  (void)event;
341  (void)branch;
342 
343  // cast the box to the appropriate type
344  const ToyBoxNueCC &box = *static_cast<const ToyBoxNueCC*>(&boxB);
345 
346  AnaTrueParticleB* truePart = static_cast<AnaTrueParticleB*>(trueObj);
347 
348  if(systId == SystId::kTpcTrackEff){
349  if(box.MainTrack->GetTrueParticle()){
350  // At first order the inclusive selection only depends on the tracking efficiency of the electron candidate.
351  if(truePart->ID == box.MainTrack->GetTrueParticle()->ID) return true;
352  // Consider also the case in which the electron candidate is not a true electron but this track it is
353  if(abs(truePart->PDG) == 11 && abs(box.MainTrack->GetTrueParticle()->PDG) != 11) return true;
354 
355  // Now check the paired track
356  if(box.PairTrack && box.PairTrack->GetTrueParticle()){
357  if(truePart->ID == box.PairTrack->GetTrueParticle()->ID) return true;
358 
359  if(abs(truePart->PDG) == 11 && abs(box.PairTrack->GetTrueParticle()->PDG) != 11) return true;
360  }
361  }
362  // Apply for electrons(?)
363  else if (abs(truePart->PDG) == 11) return true;
364 
365  return false;
366  }
367  else if(systId == SystId::kSIPion){
368  if(box.MainTrack->GetTrueParticle() && truePart->ID == box.MainTrack->GetTrueParticle()->ID){
369  if(abs(box.MainTrack->GetTrueParticle()->PDG) == 211) return true;
370  if(abs(box.MainTrack->GetTrueParticle()->ParentPDG) == 211) return true;
371  if(abs(box.MainTrack->GetTrueParticle()->GParentPDG) == 211) return true;
372  return false;
373  }
374  // If this truePart is NOT associated to the MainTrack, consider the posibility of this truePart to become the MainTrack and be identified as electron
375  // For the moment assume a negative pion may become the MainTrack if its momentum its above 90% of the current MainTrack momentum.
376  // Ideally we should check that this true pion is not associated to any reconstructed track, but this is not possible now without looping.
377  // Multiply by the charge of the MainTrack such that it can be use for antiNumu selection
378  if (truePart->PDG == 211*((Int_t)box.MainTrack->Charge) && truePart->Momentum > 0.9*box.MainTrack->Momentum) return true;
379 
380  // Now check the paired track - it doesn't have to be the most energetic track
381  if(box.PairTrack && box.PairTrack->GetTrueParticle() && truePart->ID == box.PairTrack->GetTrueParticle()->ID){
382  if(abs(box.PairTrack->GetTrueParticle()->PDG) == 211) return true;
383  if(abs(box.PairTrack->GetTrueParticle()->ParentPDG) == 211) return true;
384  if(abs(box.PairTrack->GetTrueParticle()->GParentPDG) == 211) return true;
385 
386  return false;
387  }
388  }
389  else if(systId == SystId::kSIProton){
390  // If this truePart is associated to the MainTrack
391  if(box.MainTrack->GetTrueParticle() && truePart->ID == box.MainTrack->GetTrueParticle()->ID){
392  if(box.MainTrack->GetTrueParticle()->PDG == 2212) return true;
393  if(box.MainTrack->GetTrueParticle()->ParentPDG == 2212) return true;
394  if(box.MainTrack->GetTrueParticle()->GParentPDG == 2212) return true;
395  return false;
396  }
397  // If this truePart is NOT associated to the MainTrack, consider the posibility of this truePart to become the MainTrack
398  //if(truePart->PDG == 2212 && truePart->Momentum > 0.9*box.MainTrack->Momentum) return true;
399 
400  // Now check the paired track - it doesn't have to be the most energetic track
401  if(box.PairTrack && box.PairTrack->GetTrueParticle() && truePart->ID == box.PairTrack->GetTrueParticle()->ID){
402  if(box.PairTrack->GetTrueParticle()->PDG == 2212) return true;
403  if(box.PairTrack->GetTrueParticle()->ParentPDG == 2212) return true;
404  if(box.PairTrack->GetTrueParticle()->GParentPDG == 2212) return true;
405  return false;
406  }
407 
408  return false;
409  }
410 
411  return true;
412 
413 }
414 
415 
416 //*********************************************************************
417 bool gammaSelection::IsRelevantSystematic(const AnaEventC& event, const ToyBoxB& box, SystId_h systId, Int_t branch) const{
418 //*********************************************************************
419 
420  if (systId == SystId::kTpcECalMatchEff) // No ecal related syst
421  return false;
422  else if(systId == SystId::kECalPID) // No ecal related syst
423  return false;
424  else if(systId == SystId::kECalEMResol) // No ecal related syst
425  return false;
426  else if(systId == SystId::kECalEMScale) // No ecal related syst
427  return false;
428  else if(systId == SystId::kNuETPCPileUp) // No pile-up syst
429  return false;
430  else if(systId == SystId::kNuEP0DPileUp) // No pile-up syst
431  return false;
432  else if(systId == SystId::kNuEECalPileUp) // No pile-up syst
433  return false;
434 
435  // The rest are disabled here
436  return _nueCCSelection.IsRelevantSystematic(event, box, systId, branch);
437 }
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.
void DefineDetectorFV()
Define the detector Fiducial Volume in which this selection is applied.
Int_t MaxAccumLevel
Definition: ToyBoxB.hxx:39
bool IsRelevantRecObjectForSystematicInToy(const AnaEventC &event, const ToyBoxB &boxB, AnaRecObjectC *recObj, SystId_h systId, Int_t branch) const
Is this track relevant for a given systematic (after selection, called for each toy) ...
Int_t NNodes
The number of nodes in the reconstructed object.
bool IsRelevantSystematic(const AnaEventC &event, const ToyBoxB &box, SystId_h systId, Int_t branch) const
Is this systematic relevant for this selection.
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)
void DefineSteps()
Define all steps in the selection.
AnaTrueObjectC * TrueObject
The link to the true oject that most likely generated this reconstructed object.
bool CheckRedoSelection(const AnaEventC &eventC, const ToyBoxB &PreviousToyBox, Int_t &redoFromStep)
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
bool Apply(AnaEventC &eventC, ToyBoxB &boxB) const
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.
AnaVertexB * Vertex
For storing the reconstructed vertex.
int nTPCSegments
How many TPC tracks are associated with this track.
bool Apply(AnaEventC &eventC, ToyBoxB &boxB) const
Representation of a true Monte Carlo trajectory/particle.
bool Apply(AnaEventC &eventC, ToyBoxB &boxB) const
bool Apply(AnaEventC &eventC, ToyBoxB &boxB) const
Int_t PDG
The PDG code of this particle.
bool IsRelevantRecObjectForSystematic(const AnaEventC &event, AnaRecObjectC *trackRecC, SystId_h systId, Int_t branch) const
Is this track relevant for a given systematic (prior to selection, call when initializing the event...
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.
AnaTrackB * SHMPtrack
For storing the second highest momentum positive track.
Representation of a global track.
bool Apply(AnaEventC &eventC, ToyBoxB &boxB) const
AnaTrackB * HMtrack
For storing the highest momentum track.
Representation of a TPC segment of a global track.
void InitializeEvent(AnaEventC &event)
Fill the EventBox with the objects needed by this selection.
AnaEventSummaryC * Summary
A summary of the event with high level quantities.
bool IsRelevantTrueObjectForSystematicInToy(const AnaEventC &event, const ToyBoxB &boxB, AnaTrueObjectC *trueObj, SystId_h systId, Int_t branch) const
Is this true track relevant for a given systematic (after selection, called for each toy) ...
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.
A cut on event quality. Requires good beam and ND280 data quality flags.
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...
void Initialize()
Initialize this selection: defines the steps and the detectorFV.