HighLAND
numuCCBwdSelection.cxx
1 #include "numuCCBwdSelection.hxx"
2 
3 #include "baseSelection.hxx"
4 #include "EventBoxUtils.hxx"
5 #include "VersioningUtils.hxx"
6 #include "SystematicUtils.hxx"
7 
8 
9 //********************************************************************
10 numuCCBwdSelection::numuCCBwdSelection(bool forceBreak, SubDetId::SubDetEnum aFV): SelectionBase(forceBreak,EventBoxId::kEventBoxTracker) {
11 //********************************************************************
12 
13  _aFV=aFV;
14 }
15 
16 //********************************************************************
18 //********************************************************************
19 
20  // Muon Cand
21  AddStep(StepBase::kCut, "Event quality", new EventQualityCut(), true );
22 
23  AddStep(StepBase::kCut, "Find muon candidate", new numuCCBwd::FindMuonCandidateAction(), true );
24  AddStep(StepBase::kAction, "Find vertex", new numuCCBwd::FindVertexAction() );
25  AddStep(StepBase::kCut, "Muon PID", new numuCCBwd::MuonPIDCut() );
26  AddStep(StepBase::kCut, "ToF is available", new numuCCBwd::AvailableToF() );
27  AddStep(StepBase::kCut, "More than one node in second detector", new numuCCBwd::NoShower() );
28  AddStep(StepBase::kCut, "Positive time of flight", new numuCCBwd::ToF() );
29  AddStep(StepBase::kCut, "Exclusive", new numuCCBwd::Exclusive() );
30 
31  //Available ToF branch
32  SetBranchAlias(0, "Bwd muon");
33 }
34 
35 //********************************************************************
37 //********************************************************************
38 
39  // The detector in which the selection is applied
40  SetDetectorFV(_aFV);
41 }
42 
43 //**************************************************
44 bool numuCCBwd::Exclusive::Apply(AnaEventC& event, ToyBoxB& box ) const{
45 //**************************************************
46 
47  return !( static_cast<AnaEventSummaryB*>(event.Summary)->EventSample == SampleId::kFGD1NuMuCCBwd && box.DetectorFV == SubDetId::kFGD2 );
48 
49 }
50 
51 
52 //********************************************************************
53 bool numuCCBwdSelection::FillEventSummary(AnaEventC& event, Int_t allCutsPassed[]){
54 //********************************************************************
55 
56  if(allCutsPassed[0]){
57  static_cast<AnaEventSummaryB*>(event.Summary)->EventSample = GetSampleEnum();
58  }
59  return (static_cast<AnaEventSummaryB*>(event.Summary)->EventSample != SampleId::kUnassigned);
60 
61 }
62 
63 //**************************************************
65 //**************************************************
66 
67  AnaEventB& event = *static_cast<AnaEventB*>(&eventBB);
68 
69  // Create the appropriate EventBox if it does not exist yet
70  if (!event.EventBoxes[EventBoxId::kEventBoxTracker])
71  event.EventBoxes[EventBoxId::kEventBoxTracker] = new EventBoxTracker();
72 
73  boxUtils::FillTracksWithTPC( event );
74  boxUtils::FillTrajsChargedInTPC( event );
75 }
76 
77 //********************************************************************
78 SubDetId::SubDetEnum numuCCBwd::InFGDFV( const Float_t pos[4] ) {
79 //********************************************************************
80  if( anaUtils::InFiducialVolume( SubDetId::kFGD1, pos, numuCCBwd::FVdefminFGD1, numuCCBwd::FVdefmaxFGD1 ) ){
81  return SubDetId::kFGD1;
82  }else if( anaUtils::InFiducialVolume( SubDetId::kFGD2, pos, numuCCBwd::FVdefminFGD2, numuCCBwd::FVdefmaxFGD2 ) ){
83  return SubDetId::kFGD2;
84  }
85  return SubDetId::kInvalid;
86 }
87 
88 //********************************************************************
89 SubDetId::SubDetEnum numuCCBwd::EndsInFGDFV(const AnaTrackB& track) {
90 //********************************************************************
91  return numuCCBwd::InFGDFV( track.PositionEnd );
92 }
93 
94 
95 //**************************************************
96 bool numuCCBwd::ToF::Apply(AnaEventC& event, ToyBoxB& boxB ) const{
97 //**************************************************
98 
99  (void) event;
100 
101  // Cast the ToyBox to the appropriate type
102  ToyBoxTracker& box = *static_cast<ToyBoxTracker*>(&boxB);
103 
104  AnaTrackB* track = box.MainTrack;
105  if(!track){ return false; }
106 
107  if(box.DetectorFV == SubDetId::kFGD1){
108  if( track->ToF.Flag_P0D_FGD1 ){
109  return track->ToF.P0D_FGD1 > _P0D_FGD1;
110  }else if(track->ToF.Flag_ECal_FGD1){
111  return track->ToF.ECal_FGD1 > _ECal_FGD1;
112  }
113  }else if(box.DetectorFV == SubDetId::kFGD2){
114  if( track->ToF.Flag_FGD1_FGD2 ){
115  return track->ToF.FGD1_FGD2 > _FGD1_FGD2;
116  }else if(track->ToF.Flag_ECal_FGD2){
117  return track->ToF.ECal_FGD2 > _ECal_FGD2;
118  }
119  }
120 
121  return false;
122 
123 
124 }
125 
126 
127 //**************************************************
128 bool numuCCBwd::NoShower::Apply(AnaEventC& event, ToyBoxB& boxB ) const{
129 //**************************************************
130 
131  (void) event;
132 
133  // Cast the ToyBox to the appropriate type
134  ToyBoxTracker& box = *static_cast<ToyBoxTracker*>(&boxB);
135 
136 
137  AnaTrackB* track = box.MainTrack;
138  if(!track){ return false; }
139 
140  if(box.DetectorFV == SubDetId::kFGD1){
141  if( track->ToF.Flag_P0D_FGD1 && anaUtils::TrackUsesDet(*track, SubDetId::kP0D) ){
142  if( track->nP0DSegments>0 ){
143  return track->P0DSegments[0]->NNodes > 1 ;
144  }
145  std::cout<<"Flag but no segment in P0D"<<std::endl;
146  }else if(track->ToF.Flag_ECal_FGD1 && anaUtils::TrackUsesDet(*track, SubDetId::kTECAL) ){
147  if( track->nECALSegments>0 ){
148  return track->ECALSegments[0]->NNodes > 1 ;
149  }
150  std::cout<<"Flag but no segment in ECal"<<std::endl;
151  }
152  }else if(box.DetectorFV == SubDetId::kFGD2){
153  if( track->ToF.Flag_FGD1_FGD2 && anaUtils::TrackUsesDet(*track, SubDetId::kFGD1) ){
154  for(int i = 0; i<track->nFGDSegments; i++){
155  if( SubDetId::GetDetectorUsed( track->FGDSegments[i]->Detector , SubDetId::kFGD1 ) ){return track->FGDSegments[i]->NNodes > 1 ;}
156  }
157  std::cout<<"Flag but no segment in FGD1"<<std::endl;
158  }else if( track->ToF.Flag_ECal_FGD2 && anaUtils::TrackUsesDet(*track, SubDetId::kTECAL) ){
159  if( track->nECALSegments>0 ){
160  return track->ECALSegments[0]->NNodes > 1 ;
161  }
162  std::cout<<"Flag but no segment in ECal"<<std::endl;
163  }
164  }
165 
166  return false;
167 
168 }
169 
170 /// CUTS
171 
172 //**************************************************
174 //**************************************************
175 
176  (void) event;
177 
178  // Cast the ToyBox to the appropriate type
179  ToyBoxTracker& box = *static_cast<ToyBoxTracker*>(&boxB);
180 
181  AnaTrackB* track = box.MainTrack;
182  if(!track){ return false; }
183 
184  bool available = false;
185  if( box.DetectorFV == SubDetId::kFGD1 ){
186  available = track->ToF.Flag_P0D_FGD1 || track->ToF.Flag_ECal_FGD1;
187  }else if( box.DetectorFV == SubDetId::kFGD2 ){
188  available = track->ToF.Flag_FGD1_FGD2 || track->ToF.Flag_ECal_FGD2;
189  }
190 
191  return available;
192 }
193 
194 
195 //**************************************************
196 bool numuCCBwd::MuonPIDCut::Apply(AnaEventC& event, ToyBoxB& boxB ) const{
197 //**************************************************
198 
199  (void) event;
200 
201  // Cast the ToyBox to the appropriate type
202  ToyBoxTracker& box = *static_cast<ToyBoxTracker*>(&boxB);
203 
204 
205  AnaTrackB* track = box.MainTrack;
206 
207  if(!track){ return false; }
208 
209  Float_t PIDLikelihood[4];
210  anaUtils::GetPIDLikelihood(*track, PIDLikelihood, false);
211 
212  if ( PIDLikelihood[0] > _muon_pid ){
213  return true;
214  }
215 
216  return false;
217 }
218 
219 //Define vertex
220 //**************************************************
222 //**************************************************
223 
224  (void)event;
225 
226  // Cast the ToyBox to the appropriate type
227  ToyBoxTracker& box = *static_cast<ToyBoxTracker*>(&boxB);
228 
229  // reset the vertex
230  if (box.Vertex) delete box.Vertex;
231  box.Vertex = NULL;
232 
233  if (! box.MainTrack) return false;
234 
235  box.Vertex = new AnaVertexB();
236  anaUtils::CreateArray(box.Vertex->Particles, 1);
237 
238  box.Vertex->nParticles = 0;
239  box.Vertex->Particles[box.Vertex->nParticles++] = box.MainTrack;
240 
241  anaUtils::CopyArray( box.MainTrack->PositionEnd , box.Vertex->Position , 4);
242 
243  if( box.MainTrack->GetTrueParticle() ){
245  }
246 
247  return true;
248 }
249 
250 
251 //Modified track quality cut
252 //**************************************************
253 bool numuCCBwd::TrackQualityCut(const AnaTrackB& track, SubDetId::SubDetEnum tpc){
254 //**************************************************
255 
256  for(int i = 0; i < track.nTPCSegments; ++i){
257  AnaTPCParticleB* tpc_track = track.TPCSegments[i];
258  if( SubDetId::GetDetectorUsed( tpc_track->Detector , tpc ) ){
259  if( tpc_track->NNodes > 18 ){return true;}
260  }
261  }
262 
263  return false;
264 }
265 
266 
267 bool HMFirst(AnaTrackB* a, AnaTrackB* b){//Is "a" before "b" ?
268 
269  AnaTPCParticleB* aTPC = NULL;
270  if( numuCCBwd::EndsInFGDFV(*a) == SubDetId::kFGD1 ){
271  aTPC = static_cast<AnaTPCParticleB*>( anaUtils::GetSegmentInDet( *a, SubDetId::kTPC1) );
272  }else if( numuCCBwd::EndsInFGDFV(*a) == SubDetId::kFGD2 ){
273  aTPC = static_cast<AnaTPCParticleB*>( anaUtils::GetSegmentInDet( *a, SubDetId::kTPC2) );
274  }
275 
276  AnaTPCParticleB* bTPC = NULL;
277  if( numuCCBwd::EndsInFGDFV(*b) == SubDetId::kFGD1 ){
278  bTPC = static_cast<AnaTPCParticleB*>( anaUtils::GetSegmentInDet( *b, SubDetId::kTPC1) );
279  }else if( numuCCBwd::EndsInFGDFV(*b) == SubDetId::kFGD2 ){
280  bTPC = static_cast<AnaTPCParticleB*>( anaUtils::GetSegmentInDet( *b, SubDetId::kTPC2) );
281  }
282 
283  if(!aTPC) return false;
284  if(!bTPC) return true;
285 
286  return aTPC->Momentum > bTPC->Momentum;
287 
288 }
289 
290 //Find muon candidate
291 //**************************************************
293 //**************************************************
294 
295  /*
296  Can't use the usual find leading track action since it requires the upstream and not the downstream end to be inside the FGD FV
297  Muon candidate is taken as the highest mom "positive" track whose downstream end is inside the FGD FV, >18 TPC hits needed
298  <=> HMPT FGD FV end <=> HMNT FGD FV start
299  */
300 
301  // Cast the ToyBox to the appropriate type
302  ToyBoxTracker& box = *static_cast<ToyBoxTracker*>(&boxB);
303 
304  box.MainTrack = NULL;
305 
306  EventBoxB* EventBox = event.EventBoxes[EventBoxId::kEventBoxTracker];
307  AnaRecObjectC** selTracksNS = EventBox->RecObjectsInGroup[EventBoxTracker::kTracksWithTPC];
308  int nTPC = EventBox->nRecObjectsInGroup[EventBoxTracker::kTracksWithTPC];
309 
310  //Sort according to TPC mom TODO : put it in a correction
311  std::vector<AnaTrackB*> selTracksV;
312  for (Int_t i=0;i<nTPC; ++i){
313  selTracksV.push_back( static_cast<AnaTrackB*>(selTracksNS[i]) );
314  }
315  std::sort(selTracksV.begin(), selTracksV.end(), HMFirst);
316 
317 
318  //Copy vector in an array
319  AnaTrackB** selTracks = new AnaTrackB*[nTPC];
320  std::copy(selTracksV.begin(), selTracksV.end(), selTracks);
321 
322 
323 
324  //loop over tpc tracks
325  for (Int_t i=0;i<nTPC; ++i){
326  AnaTrackB* track = selTracks[i];
327 
328  if( numuCCBwd::EndsInFGDFV(*track) != box.DetectorFV ) continue;
329 
330  //apply the quality cut (>18 hits in TPC)
331  if ( ( box.DetectorFV == SubDetId::kFGD1 && !numuCCBwd::TrackQualityCut(*track, SubDetId::kTPC1 ) )
332  || ( box.DetectorFV == SubDetId::kFGD2 && !numuCCBwd::TrackQualityCut(*track, SubDetId::kTPC2 ) ) ){
333  continue;
334  }
335 
336 
337  //Require a "positive" charge (implies a negative one in the backward hypothesis)
338  if( track->Charge == 1 ){
339  //Take the first (HM) track which satifsies the previous requirements
340  box.MainTrack = track;
341 
342  delete[] selTracks;
343  return true;
344  }
345  }
346 
347  delete[] selTracks;
348  return false;
349 
350 }
351 
352 //IsRelevantRecObjectForSystematic
353 //**************************************************
354 bool numuCCBwdSelection::IsRelevantRecObjectForSystematic(const AnaEventC& event, AnaRecObjectC* track, SystId_h systId, Int_t branch) const{
355 //**************************************************
356 
357  (void) event;
358  (void) track;
359  (void) systId;
360  (void) branch;
361 
362  return true;
363 }
364 
365 //**************************************************
366 bool numuCCBwdSelection::IsRelevantSystematic(const AnaEventC& event, const ToyBoxB& box, SystId_h systId, Int_t branch) const{
367 //**************************************************
368 
369  (void) event;
370  (void) box;
371  (void) systId;
372  (void) branch;
373 
374  return true;
375 }
376 
377 //Redo selection ?
378 //********************************************************************
379 bool numuCCBwdSelection::CheckRedoSelection(const AnaEventC& event, const ToyBoxB& PreviousToyBox, Int_t& redoFromStep){
380 //********************************************************************
381 
382  (void)event;
383  (void)PreviousToyBox;
384  (void)redoFromStep;
385 
386  return true;
387 
388 }
bool Apply(AnaEventC &event, ToyBoxB &box) const
AnaTrueVertexB * TrueVertex
Pointer to the AnaTrueVertexB of the interaction that created this AnaTrueParticleB.
int nP0DSegments
How many P0D tracks are associated with this track.
bool Apply(AnaEventC &event, ToyBoxB &box) const
AnaTrueVertexB * TrueVertex
AnaP0DParticleB * P0DSegments[NMAXP0DS]
The P0D segments that contributed to this global track.
unsigned long Detector
bool Apply(AnaEventC &event, ToyBoxB &box) const
void DefineSteps()
Define all steps in the selection.
AnaECALParticleB * ECALSegments[NMAXECALS]
The ECAL segments that contributed to this global track.
int nECALSegments
How many ECAL tracks are associated with this track.
bool CheckRedoSelection(const AnaEventC &event, const ToyBoxB &PreviousToyBox, Int_t &redoFromStep)
Event failed FGD1 selection when running FGD2 selection in a FGD1 + FGD2 analysis.
Float_t Position[4]
The identified position of the global vertex.
Int_t NNodes
The number of nodes in the reconstructed object.
SubDetId_h DetectorFV
Indicate the FV we are interested in.
Definition: ToyBoxB.hxx:52
bool Apply(AnaEventC &event, ToyBoxB &box) const
CUTS.
AnaTrackB * MainTrack
For storing the Main Track (The lepton candidate in geranal: HMN or HMP track)
AnaTPCParticleB * TPCSegments[NMAXTPCS]
The TPC segments that contributed to this global track.
AnaToF ToF
Times of flight between pairs of detectors.
static bool GetDetectorUsed(unsigned long BitField, SubDetId::SubDetEnum det)
Method to see if a certain subdetector or subdetector system is used.
Definition: SubDetId.cxx:40
AnaTrueVertexB * TrueVertex
For storing the true vertex, for analyses with no reconstructed primary vertex.
Definition: ToyBoxND280.hxx:22
Track has more than one node in ecal or p0d.
AnaParticleB * GetSegmentInDet(const AnaTrackB &track, SubDetId::SubDetEnum det)
bool TrackUsesDet(const AnaTrackB &track, SubDetId::SubDetEnum det)
Float_t Charge
The reconstructed charge of the particle.
bool Apply(AnaEventC &event, ToyBoxB &box) const
Float_t GetPIDLikelihood(const AnaTrackB &track, Int_t hypo, bool prod5Cut=0)
Definition: PIDUtils.cxx:180
bool Apply(AnaEventC &event, ToyBoxB &box) const
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.
AnaVertexB * Vertex
For storing the reconstructed vertex.
int nTPCSegments
How many TPC tracks are associated with this track.
bool IsRelevantSystematic(const AnaEventC &event, const ToyBoxB &box, SystId_h systId, Int_t branch) const
Is this systematic relevant for this selection.
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...
SubDetEnum
Enumeration of all detector systems and subdetectors.
Definition: SubDetId.hxx:25
void InitializeEvent(AnaEventC &event)
Fill the EventBox with the objects needed by this selection.
Representation of a global track.
Representation of a TPC segment of a global track.
AnaParticleB ** Particles
Representation of a global vertex.
void DefineDetectorFV()
Define the detector Fiducial Volume in which this selection is applied.
AnaEventSummaryC * Summary
A summary of the event with high level quantities.
bool Apply(AnaEventC &event, ToyBoxB &box) const
int nFGDSegments
How many FGD tracks are associated with this track.
Muon candidate has a positive time of flight.
AnaTrueParticleB * GetTrueParticle() const
Return a casted version of the AnaTrueObject associated.
bool InFiducialVolume(SubDetId::SubDetEnum det, const Float_t *pos, const Float_t *FVdefmin, const Float_t *FVdefmax)
AnaFGDParticleB * FGDSegments[NMAXFGDS]
The FGD segments that contributed to this global track.
A cut on event quality. Requires good beam and ND280 data quality flags.
Float_t PositionEnd[4]
The reconstructed end position of the particle.