HighLAND
ToFSenseCorrector.cxx
1 #include "ToFSenseCorrector.hxx"
2 #include "Parameters.hxx"
3 #include "BasicUtils.hxx"
4 #include "DetectorDefinition.hxx"
5 #include "ND280AnalysisUtils.hxx"
6 #include "CutUtils.hxx"
7 //#define DEBUG
8 
9 
10 //********************************************************************
11 ToFSenseCorrector::ToFSenseCorrector(){
12  //********************************************************************
13 
14  // Read various parameters
15  ToFCutValues[ToFSenseCorrector::kToFTopo_FGD1FGD2] = (Float_t)ND::params().GetParameterD("psycheND280Utils.ToF.FGD1FGD2" );
16  ToFCutValues[ToFSenseCorrector::kToFTopo_FGD1P0D_Track] = (Float_t)ND::params().GetParameterD("psycheND280Utils.ToF.FGD1P0D_Track" );
17  ToFCutValues[ToFSenseCorrector::kToFTopo_FGD1ECAL_LAStartFgd_Track] = (Float_t)ND::params().GetParameterD("psycheND280Utils.ToF.FGD1ECAL_LAStartFgd_Track" );
18  ToFCutValues[ToFSenseCorrector::kToFTopo_FGD1ECAL_LAStartFgd_Shower] = (Float_t)ND::params().GetParameterD("psycheND280Utils.ToF.FGD1ECAL_LAStartFgd_Shower" );
19  ToFCutValues[ToFSenseCorrector::kToFTopo_FGD1ECAL_LAEndFgd_Track] = (Float_t)ND::params().GetParameterD("psycheND280Utils.ToF.FGD1ECAL_LAEndFgd_Track" );
20  ToFCutValues[ToFSenseCorrector::kToFTopo_FGD1ECAL_LAEndFgd_Shower] = (Float_t)ND::params().GetParameterD("psycheND280Utils.ToF.FGD1ECAL_LAEndFgd_Shower" );
21  ToFCutValues[ToFSenseCorrector::kToFTopo_FGD1ECAL_HAStartFgd_Track] = (Float_t)ND::params().GetParameterD("psycheND280Utils.ToF.FGD1ECAL_HAStartFgd_Track" );
22  ToFCutValues[ToFSenseCorrector::kToFTopo_FGD1ECAL_HAStartFgd_Shower] = (Float_t)ND::params().GetParameterD("psycheND280Utils.ToF.FGD1ECAL_HAStartFgd_Shower" );
23  ToFCutValues[ToFSenseCorrector::kToFTopo_FGD1ECAL_HAEndFgd_Track] = (Float_t)ND::params().GetParameterD("psycheND280Utils.ToF.FGD1ECAL_HAEndFgd_Track" );
24  ToFCutValues[ToFSenseCorrector::kToFTopo_FGD1ECAL_HAEndFgd_Shower] = (Float_t)ND::params().GetParameterD("psycheND280Utils.ToF.FGD1ECAL_HAEndFgd_Shower" );
25 
26 }
27 
28 //********************************************************************
30  //********************************************************************
31 
32  //Flip the charge
33  track.Charge = -1.*track.Charge;
34 
35  // Position
36  Float_t pos_tmp[4];
37  anaUtils::CopyArray(track.PositionStart, pos_tmp, 4);
38  anaUtils::CopyArray(track.PositionEnd, track.PositionStart, 4);
39  anaUtils::CopyArray(pos_tmp, track.PositionEnd, 4);
40 
41  // DirectionEnd is proved to provide more stable results than reverse refit: (acceptably) worse resolution but
42  // not fit failures
43  Float_t dir_tmp_start[3] = {-1.*track.DirectionStart[0], -1.*track.DirectionStart[1], -1.*track.DirectionStart[2]};
44  Float_t dir_tmp_end[3] = {-1.*track.DirectionEnd[0], -1.*track.DirectionEnd[1], -1.*track.DirectionEnd[2] };
45  anaUtils::CopyArray(dir_tmp_end, track.DirectionStart, 3);
46  anaUtils::CopyArray(dir_tmp_start, track.DirectionEnd, 3);
47 
48  // Check whether a track uses TPC
49  if (SubDetId::GetDetectorUsed(track.Detector, SubDetId::kTPC))
50  //Momentum
51  std::swap(track.Momentum, track.MomentumFlip);
52 
53 }
54 
55 //********************************************************************
57  //********************************************************************
58 
59  // check if a track is forward (in Z) going
60  // need something fancier?
61 
62  return track.PositionStart[2] < track.PositionEnd[2];
63 }
64 
65 
66 //********************************************************************
68  //********************************************************************
69 
70  // check if a track is forward (in Z) going
71  // need something fancier?
72 
73  return track.Position[2] < track.PositionEnd[2];
74 }
75 
76 
77 
78 //********************************************************************
80  //********************************************************************
81 
82  if (!IsForward(track)) FlipTrack(track);
83 }
84 
85 
86 //********************************************************************
87 void ToFSenseCorrector::ForceForward(AnaTrackB* Tracks[], int nTracks){
88  //********************************************************************
89  for (int i=0; i<nTracks; i++){
90  if (!Tracks[i]) continue;
91  ForceForward(*Tracks[i]);
92  }
93 }
94 
95 
96 //********************************************************************
98  //********************************************************************
99 
100  /* The ToF cuts were studied to select Bwd going tracks in case of FGD-FGD/P0D ToF(1) and
101  * those that start from FGD for FGD-ECal (ToF2) cases. So here the following checks are done:
102  * track should be reverese in case:
103  * isForward but ToF1 > cut
104  * isBackward but ToF1 < cut
105  * if not valid ToF --> do not reverse
106  */
107 
108  bool isForward = IsForward(track);
109 
110  //FGD1-FGD2
111  if (topo == kToFTopo_FGD1FGD2) {
112  if ((track.ToF.FGD1_FGD2 <= ToFCutValues[ToFSenseCorrector::kToFTopo_FGD1FGD2] && !isForward) ||
113  (track.ToF.FGD1_FGD2 > ToFCutValues[ToFSenseCorrector::kToFTopo_FGD1FGD2] && isForward)) return true;
114  }
115 
116  // P0D-FGD1 -> We apply the flip only for track like cases
117  if (topo == ToFSenseCorrector::kToFTopo_FGD1P0D_Track) {
118  if ((track.ToF.P0D_FGD1 <= ToFCutValues[ToFSenseCorrector::kToFTopo_FGD1P0D_Track] && !isForward) ||
119  (track.ToF.P0D_FGD1 > ToFCutValues[ToFSenseCorrector::kToFTopo_FGD1P0D_Track] && isForward)) return true;
120  }
121 
122  // ECal-FGD1 -> We apply the flip for both track&shower like cases
123  if (topo == ToFSenseCorrector::kToFTopo_FGD1ECAL_LAStartFgd_Track) {
124  if ((track.ToF.ECal_FGD1 > ToFCutValues[ToFSenseCorrector::kToFTopo_FGD1ECAL_LAStartFgd_Track] && !isForward) ||
125  (track.ToF.ECal_FGD1 <= ToFCutValues[ToFSenseCorrector::kToFTopo_FGD1ECAL_LAStartFgd_Track] && isForward)) return true;
126  }
127  if (topo == ToFSenseCorrector::kToFTopo_FGD1ECAL_LAStartFgd_Shower) {
128  if ((track.ToF.ECal_FGD1 > ToFCutValues[ToFSenseCorrector::kToFTopo_FGD1ECAL_LAStartFgd_Shower] && !isForward) ||
129  (track.ToF.ECal_FGD1 <= ToFCutValues[ToFSenseCorrector::kToFTopo_FGD1ECAL_LAStartFgd_Shower] && isForward)) return true;
130  }
131 
132  if (topo == ToFSenseCorrector::kToFTopo_FGD1ECAL_LAEndFgd_Track) {
133  if ((track.ToF.ECal_FGD1 <= ToFCutValues[ToFSenseCorrector::kToFTopo_FGD1ECAL_LAEndFgd_Track] && !isForward) ||
134  (track.ToF.ECal_FGD1 > ToFCutValues[ToFSenseCorrector::kToFTopo_FGD1ECAL_LAEndFgd_Track] && isForward)) return true;
135  }
136  if (topo == ToFSenseCorrector::kToFTopo_FGD1ECAL_LAEndFgd_Shower) {
137  if ((track.ToF.ECal_FGD1 <= ToFCutValues[ToFSenseCorrector::kToFTopo_FGD1ECAL_LAEndFgd_Shower] && !isForward) ||
138  (track.ToF.ECal_FGD1 > ToFCutValues[ToFSenseCorrector::kToFTopo_FGD1ECAL_LAEndFgd_Shower] && isForward)) return true;
139  }
140 
141  if (topo == ToFSenseCorrector::kToFTopo_FGD1ECAL_HAStartFgd_Track) {
142  if ((track.ToF.ECal_FGD1 > ToFCutValues[ToFSenseCorrector::kToFTopo_FGD1ECAL_HAStartFgd_Track] && !isForward) ||
143  (track.ToF.ECal_FGD1 <= ToFCutValues[ToFSenseCorrector::kToFTopo_FGD1ECAL_HAStartFgd_Track] && isForward)) return true;
144  }
145  if (topo == ToFSenseCorrector::kToFTopo_FGD1ECAL_HAStartFgd_Shower) {
146  if ((track.ToF.ECal_FGD1 > ToFCutValues[ToFSenseCorrector::kToFTopo_FGD1ECAL_HAStartFgd_Shower] && !isForward) ||
147  (track.ToF.ECal_FGD1 <= ToFCutValues[ToFSenseCorrector::kToFTopo_FGD1ECAL_HAStartFgd_Shower] && isForward)) return true;
148  }
149 
150  if (topo == ToFSenseCorrector::kToFTopo_FGD1ECAL_HAEndFgd_Track) {
151  if ((track.ToF.ECal_FGD1 <= ToFCutValues[ToFSenseCorrector::kToFTopo_FGD1ECAL_HAEndFgd_Track] && !isForward) ||
152  (track.ToF.ECal_FGD1 > ToFCutValues[ToFSenseCorrector::kToFTopo_FGD1ECAL_HAEndFgd_Track] && isForward)) return true;
153  }
154  if (topo == ToFSenseCorrector::kToFTopo_FGD1ECAL_HAEndFgd_Shower) {
155  if ((track.ToF.ECal_FGD1 <= ToFCutValues[ToFSenseCorrector::kToFTopo_FGD1ECAL_HAEndFgd_Shower] && !isForward) ||
156  (track.ToF.ECal_FGD1 > ToFCutValues[ToFSenseCorrector::kToFTopo_FGD1ECAL_HAEndFgd_Shower] && isForward)) return true;
157  }
158 
159  // Everything is fine or cannot say that any flipping is needed
160  return false;
161 
162 }
163 
164 //********************************************************************
166  //********************************************************************
167 
168  // This function returns which type of ToF check/cut (there may be several involved since a
169  // track can cross several sub-detectors and the check/cut can also depend on the type of track,
170  // e.g. track/shower for the same topology)
171 
172 
173  // The current values (Sept 2016, details in TN-) used were retrieved using the track being forced to be forward going in Z
174  // hence the relevant type should be checked based on the position of the upstream/downstream (in Z) ends, no matter there correspondence
175  // to an actual start/end point
176 
177  const Float_t* pos_upstream;
178  const Float_t* pos_downstream;
179  bool forward = IsForward(track);
180  pos_upstream = forward ? track.PositionStart : track.PositionEnd;
181  pos_downstream = forward ? track.PositionEnd : track.PositionStart;
182 
183  // Four different topologies -> Fwd, HAFwd, Bwd, HABwd
184  if (anaUtils::InDetVolume(SubDetId::kFGD1, pos_upstream)) {
185  if (cutUtils::TrackQualityCut(track)) {
186  if (track.ToF.Flag_FGD1_FGD2) return kToFTopo_FGD1FGD2;
187  else if (track.ToF.Flag_ECal_FGD1) {
188  if (ToFSenseCorrector::IsBarrelECAL(track)) {
189  if (track.ECALSegments[0]->NNodes == 1) return kToFTopo_FGD1ECAL_LAStartFgd_Shower;
190  if (track.ECALSegments[0]->NNodes > 1) return kToFTopo_FGD1ECAL_LAStartFgd_Track;
191  }
192  }
193  }
194  else {
195  if (cutUtils::StoppingBrECALorSMRDCut(pos_downstream)!=-1) {
196  if (track.ToF.Flag_ECal_FGD1) {
197  if (ToFSenseCorrector::IsBarrelECAL(track)) {
198  if (track.ECALSegments[0]->NNodes == 1) return kToFTopo_FGD1ECAL_HAStartFgd_Shower;
199  if (track.ECALSegments[0]->NNodes > 1) return kToFTopo_FGD1ECAL_HAStartFgd_Track;
200  }
201  }
202  }
203  }
204  }
205  else if (anaUtils::InDetVolume(SubDetId::kFGD1, pos_downstream)) {
206  if (cutUtils::TrackQualityCut(track)) {
207  if (track.ToF.Flag_P0D_FGD1) {
208  if (track.nP0DSegments > 0) {
209  if (track.P0DSegments[0]) {
210  if (track.P0DSegments[0]->NNodes > 1) return kToFTopo_FGD1P0D_Track;
211  }
212  }
213  }
214  else if (track.ToF.Flag_ECal_FGD1) {
215  if (ToFSenseCorrector::IsBarrelECAL(track)) {
216  if (track.ECALSegments[0]->NNodes == 1) return kToFTopo_FGD1ECAL_LAEndFgd_Shower;
217  if (track.ECALSegments[0]->NNodes > 1) return kToFTopo_FGD1ECAL_LAEndFgd_Track;
218  }
219  }
220  }
221  else {
222  if (cutUtils::StoppingBrECALorSMRDCut(pos_upstream)!=-1) {
223  if (track.ToF.Flag_ECal_FGD1) {
224  if (ToFSenseCorrector::IsBarrelECAL(track)) {
225  if (track.ECALSegments[0]->NNodes == 1) return kToFTopo_FGD1ECAL_HAEndFgd_Shower;
226  if (track.ECALSegments[0]->NNodes > 1) return kToFTopo_FGD1ECAL_HAEndFgd_Track;
227  }
228  }
229  }
230  }
231  }
232 
233  return kToFInvalid;
234 
235 }
236 
237 //********************************************************************
239  //********************************************************************
240 
241  if (track.nECALSegments < 1) return false;
242 
243  int count = (int)(anaUtils::TrackUsesDet(track, SubDetId::kTopTECAL)) +
244  (int)(anaUtils::TrackUsesDet(track, SubDetId::kBottomTECAL)) +
245  (int)(anaUtils::TrackUsesDet(track, SubDetId::kLeftTECAL)) +
246  (int)(anaUtils::TrackUsesDet(track, SubDetId::kRightTECAL));
247  if (count != 1) return false;
248 
249  return track.ECALSegments[0];
250 
251 }
int nP0DSegments
How many P0D tracks are associated with this track.
Float_t PositionStart[4]
The reconstructed start position of the particle.
AnaP0DParticleB * P0DSegments[NMAXP0DS]
The P0D segments that contributed to this global track.
unsigned long Detector
static void ForceForward(AnaTrackB &track)
Force a track to be forward going (if needed)
AnaECALParticleB * ECALSegments[NMAXECALS]
The ECAL segments that contributed to this global track.
int nECALSegments
How many ECAL tracks are associated with this track.
static bool IsForward(const AnaTrackB &track)
Check whether a track is forward going.
Float_t DirectionEnd[3]
The reconstructed end direction of the particle.
Int_t NNodes
The number of nodes in the reconstructed object.
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
bool TrackUsesDet(const AnaTrackB &track, SubDetId::SubDetEnum det)
Float_t Charge
The reconstructed charge of the particle.
static void FlipTrack(AnaTrackB &track)
Flip a track.
Float_t MomentumFlip
Momentum for the main PID hypothesis and reverse sense.
Float_t Momentum
The reconstructed momentum of the particle, at the start position.
Representation of a true Monte Carlo trajectory/particle.
static ToFTopology GetToFTopology(const AnaTrackB &track)
bool CheckNeedApplyToFBasedFlip(const AnaTrackB &track, ToFTopology topo) const
Check whether a direction(sense) matches ToF.
Representation of a global track.
bool InDetVolume(SubDetId::SubDetEnum det, const Float_t *pos)
Float_t DirectionStart[3]
The reconstructed start direction of the particle.
Float_t PositionEnd[4]
The end position of the true particle.
Float_t Position[4]
The initial position of the true particle.
static bool IsBarrelECAL(const AnaTrackB &track)
Check whether a given track has ECAL segment, if so only BarrelECAL.
Float_t PositionEnd[4]
The reconstructed end position of the particle.