NAIA  1.1.1
TrTrackFill.cpp
Go to the documentation of this file.
1 #include "Containers/TrTrack.h"
3 
4 #include "NtpMaker/NtpTools.h"
5 
6 #include "bcorr.h"
7 
8 #include <cmath>
9 #include <iostream>
10 
11 namespace NAIA {
12 using namespace TrTrack;
13 
14 static std::array<unsigned long int, numSpans> patterns = {3, 5, 6, 7, 0, 0};
15 std::array<int, numFits> fitAlgoCode{1, 6, 7, 6, 11, 17};
16 static bool TrackHasExtHits(TrTrackR *trackPtr, Span span) {
17  switch (span) {
18  case Span::InnerOnly:
19  return true;
20  case Span::InnerL1:
21  return trackPtr->TestHitLayerJHasXY(1);
22  case Span::InnerL9:
23  return trackPtr->TestHitLayerJHasXY(9);
24  case Span::FullSpan:
25  return (trackPtr->TestHitLayerJHasXY(1) && trackPtr->TestHitLayerJHasXY(9));
28  return true;
29  default:
30  throw std::runtime_error("Span not supported");
31  }
32 }
33 
34 static constexpr std::array<double, 9> powersOfTen = {1, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8};
35 
36 void ComputePatterns(TrTrackR *trackPtr) {
38 
39  for (int il = 2; il < 9; il++) {
40  if (!trackPtr->TestHitLayerJ(il))
41  continue;
42 
43  if (il < 7) {
44  patterns[Span::UpperHalfInner] += std::lround(9 * powersOfTen[il - 1]);
45  }
46 
47  if (il > 2) {
48  patterns[Span::LowerHalfInner] += std::lround(9 * powersOfTen[il - 1]);
49  }
50  }
51 }
52 
53 bool TrTrackBaseData::_FitIDExists(Fit fit, Span span) const {
54  auto itr = _fit_ID.find(fit);
55  if (itr == end(_fit_ID)) {
56  return false;
57  }
58 
59  auto fit_ID_itr = itr->second.find(span);
60  if (fit_ID_itr == end(itr->second)) {
61  return false;
62  }
63 
64  return (fit_ID_itr->second > 0);
65 }
66 
67 Span TrTrackBaseData::_GetBestSpan(Fit fit) const {
68  Span bestspan = _FitIDExists(fit, Span::FullSpan)
70  : (_FitIDExists(fit, Span::InnerL1) > 0
72  : (_FitIDExists(fit, Span::InnerL9) > 0 ? Span::InnerL9 : Span::InnerOnly));
73  return bestspan;
74 }
75 
77  int refit;
78  float mass;
79  int charge;
80 };
81 
82 ReFitParameters InitTrkReFit(float inner_charge, bool _isMC, float production_charge) {
83  ReFitParameters pars{};
84 
85  pars.charge = static_cast<int>(inner_charge + 0.5f);
86  if (pars.charge < 1)
87  pars.charge = 1;
88  pars.mass = TrFit::Mproton; // Proton
89  if (pars.charge >= 2)
90  pars.mass = TrFit::Mhelium / 2.0f * pars.charge; // Helium+Ion
91 
92  if (!_isMC) { // Data
93  if (pars.charge == static_cast<int>(production_charge + 0.5f))
94  pars.refit = 1;
95  else
96  pars.refit = 3;
97  } else {
98  pars.refit = 3; // MC
99  }
100  return pars;
101 }
102 
103 namespace {
104 // these never change so let's make them static and cache them
105 AMSPlane pl_TOI_top(TVector3(0, 0, 195), TVector3(1, 0, 0), TVector3(0, 1, 0));
106 AMSPlane pl_TOI_bot(TVector3(0, 0, -195), TVector3(1, 0, 0), TVector3(0, 1, 0));
107 AMSPlane pl_RICH(TVector3(0, 0, -70), TVector3(1, 0, 0), TVector3(0, 1, 0));
108 
109 // FIXME: this is horrible. I know.
110 AMSPlane pl_TrCenter(TVector3(0, 0, 0), TVector3(1, 0, 0), TVector3(0, 1, 0));
111 std::array<AMSPlane, numFitPositionHeights> pl_TrPlanes{
112  AMSPlane(TVector3(0, 0, fitPositionHeightZ[0]), TVector3(1, 0, 0), TVector3(0, 1, 0)),
113  AMSPlane(TVector3(0, 0, fitPositionHeightZ[1]), TVector3(1, 0, 0), TVector3(0, 1, 0)),
114  AMSPlane(TVector3(0, 0, fitPositionHeightZ[2]), TVector3(1, 0, 0), TVector3(0, 1, 0)),
115  AMSPlane(TVector3(0, 0, fitPositionHeightZ[3]), TVector3(1, 0, 0), TVector3(0, 1, 0)),
116  AMSPlane(TVector3(0, 0, fitPositionHeightZ[4]), TVector3(1, 0, 0), TVector3(0, 1, 0)),
117  AMSPlane(TVector3(0, 0, fitPositionHeightZ[5]), TVector3(1, 0, 0), TVector3(0, 1, 0)),
118  AMSPlane(TVector3(0, 0, fitPositionHeightZ[6]), TVector3(1, 0, 0), TVector3(0, 1, 0)),
119  AMSPlane(TVector3(0, 0, fitPositionHeightZ[7]), TVector3(1, 0, 0), TVector3(0, 1, 0)),
120  AMSPlane(TVector3(0, 0, fitPositionHeightZ[8]), TVector3(1, 0, 0), TVector3(0, 1, 0)),
121  AMSPlane(TVector3(0, 0, fitPositionHeightZ[9]), TVector3(1, 0, 0), TVector3(0, 1, 0)),
122  AMSPlane(TVector3(0, 0, fitPositionHeightZ[10]), TVector3(1, 0, 0), TVector3(0, 1, 0)),
123  AMSPlane(TVector3(0, 0, fitPositionHeightZ[11]), TVector3(1, 0, 0), TVector3(0, 1, 0)),
124  AMSPlane(TVector3(0, 0, fitPositionHeightZ[12]), TVector3(1, 0, 0), TVector3(0, 1, 0)),
125  AMSPlane(TVector3(0, 0, fitPositionHeightZ[13]), TVector3(1, 0, 0), TVector3(0, 1, 0)),
126  AMSPlane(TVector3(0, 0, fitPositionHeightZ[14]), TVector3(1, 0, 0), TVector3(0, 1, 0)),
127  AMSPlane(TVector3(0, 0, fitPositionHeightZ[15]), TVector3(1, 0, 0), TVector3(0, 1, 0)),
128  AMSPlane(TVector3(0, 0, fitPositionHeightZ[16]), TVector3(1, 0, 0), TVector3(0, 1, 0)),
129 };
130 } // namespace
131 
132 bool TrTrackBaseData::Fill(TrTrackR *trackPtr, TrTrackFillType type) {
133 
134  // some helper default variables
135  int temp_fit_ID = 0;
136  if (type == TrTrackFillType::Standalone) {
137  _beta = 1.0f;
138  temp_fit_ID = -1;
139  }
140 
141  // New Charge-refit Logic from Qi
142  float tmp_inner_charge = trackPtr->GetQ_all(_beta, temp_fit_ID).Mean;
143 
144  // more accurate HighZ charge
145  if (tmp_inner_charge > 1.5) {
146  auto tmp_inner_charge_YJ = trackPtr->GetQYJ_all(2, _beta, temp_fit_ID).InnerQ;
147  if (tmp_inner_charge_YJ > 8.5)
148  tmp_inner_charge = tmp_inner_charge_YJ;
149  }
150 
151  FitCharge = tmp_inner_charge;
152 
153  auto fitPars = InitTrkReFit(tmp_inner_charge, _isMC, FitCharge);
154  _tmpCharge = fitPars.charge;
155 
156  ComputePatterns(trackPtr);
157 
158  // Rigidity
159  for (auto fit : fitTypes) {
160  if (type == TrTrackFillType::Standalone) {
161  switch (fit) {
162  case Fit::KalmanElectron:
163  case Fit::ChoutkoNoMS:
164  case Fit::GBLNoMS:
165  // for standalone we only consider Choutko, Kalman and GBL
166  continue;
167  default:
168  break;
169  }
170  }
171 
172  // Kalman with electron mass hyp. to be done in dedicated fill method
173  if (fit == Fit::KalmanElectron)
174  continue;
175 
176  for (auto span : spanTypes) {
177  // For NoMS fits we only care about InnerOnly
178  if ((fit == Fit::ChoutkoNoMS || fit == Fit::GBLNoMS) && span != Span::InnerOnly) {
179  continue;
180  }
181 
182  if (type == TrTrackFillType::Standalone) {
183  switch (span) {
186  case Span::InnerL9:
187  // for standalone we only consider InnerOnly, InnerL1 and FullSpan
188  continue;
189  default:
190  break;
191  }
192  }
193 
194  if (TrackHasExtHits(trackPtr, span)) {
195  Logging::MuteOutput(); // this can get quite verbose...
196  _fit_ID[fit][span] = trackPtr->iTrTrackPar(fitAlgoCode[fit], static_cast<int>(patterns[span]),
197  30 + fitPars.refit, fitPars.mass, _tmpCharge);
198  if (_fit_ID[fit][span] > 0) {
199  double rigidity{0};
200  trackPtr->Interpolate(pl_TrCenter, rigidity, _fit_ID[fit][span]);
201  Rigidity[fit][span] = static_cast<float>(rigidity);
202  TrChiSq[fit][span][Side::X] =
203  static_cast<float>(trackPtr->GetChisqX(_fit_ID[fit][span]) / trackPtr->GetNdofX(_fit_ID[fit][span]));
204  TrChiSq[fit][span][Side::Y] =
205  static_cast<float>(trackPtr->GetChisqY(_fit_ID[fit][span]) / trackPtr->GetNdofY(_fit_ID[fit][span]));
206  }
208  }
209  }
210  }
211  trackPtr->RecalcHitCoordinates(0, false, false, _tmpCharge); // using default fit and inner tracker charge to restore
212  // coordinate
213 
214  int base_fit_ID = FitIDExists(Fit::Choutko, Span::InnerOnly) ? _fit_ID[Fit::Choutko][Span::InnerOnly] : -1;
215  if (type == TrTrackFillType::Standalone) {
216  base_fit_ID = -1;
217  }
218 
219  // Charges
220  auto stdCharge = trackPtr->GetQ_all(_beta, base_fit_ID);
221  auto stdChargeInner = trackPtr->GetInnerQ_all(_beta, base_fit_ID);
222 
223  auto hlCharge = trackPtr->GetQH_all(2, _beta, base_fit_ID);
224  auto hlChargeInner = trackPtr->GetInnerQH_all(2, _beta, base_fit_ID);
225 
226  auto yj_opt = TrChargeYJ::DefaultCorOpt | TrChargeYJ::kPow;
227 
228  // FIXME: As soon as Yi Jia fixes charge reconstruction for Z=1 and Z=2, we can remove this option
229  if (_tmpCharge < 2.5) {
230  yj_opt |= TrChargeYJ::kSingle;
231  }
232 
233  auto yjCharge = trackPtr->GetQYJ_all(2, _beta, base_fit_ID);
234 
235  // - Inner tracker
236  Charge[ChargeRecoType::STD] = stdCharge.Mean;
237  Charge[ChargeRecoType::HL] = hlCharge.Mean;
238  // Charge[ChargeRecoType::YJ] does not support "global" charge;
239  ChargeRMS[ChargeRecoType::STD] = stdCharge.RMS;
240  ChargeRMS[ChargeRecoType::HL] = hlCharge.RMS;
241  // ChargeRMS[ChargeRecoType::YJ] does not support "global" charge;
242  InnerCharge[ChargeRecoType::STD] = stdChargeInner.Mean;
243  InnerCharge[ChargeRecoType::HL] = hlChargeInner.Mean;
244  InnerCharge[ChargeRecoType::YJ] = yjCharge.InnerQ;
245  InnerChargeRMS[ChargeRecoType::STD] = stdChargeInner.RMS;
246  InnerChargeRMS[ChargeRecoType::HL] = hlChargeInner.RMS;
247  InnerChargeRMS[ChargeRecoType::YJ] = yjCharge.InnerQRMS;
248 
249  // geometry and position
250  for (int ijl = 0; ijl < 9; ijl++) {
251 
252  if (!trackPtr->GetHitLJ(ijl + 1)) {
253  continue;
254  }
255 
256  if (trackPtr->GetHitLJ(ijl + 1)->OnlyY()) {
257  m_trackPattern |= (static_cast<uint32_t>(HitClusterAssociation::Y) << (2 * ijl));
258  } else {
259  // Only-X case does not exist, right?
260  m_trackPattern |= (static_cast<uint32_t>(HitClusterAssociation::XY) << (2 * ijl));
261  }
262 
263  AMSPlaneM plm = trackPtr->GetHitCooLJN(ijl + 1);
264  TVector3 mglob = plm.getMGlobal();
265  if (trackPtr->GetHitLJ(ijl + 1)->GetXCluster())
266  TrTrackHitPos[ijl][0] = static_cast<float>(mglob.x());
267  if (trackPtr->GetHitLJ(ijl + 1)->GetYCluster())
268  TrTrackHitPos[ijl][1] = static_cast<float>(mglob.y());
269  if (trackPtr->GetHitLJ(ijl + 1))
270  TrTrackHitPos[ijl][2] = static_cast<float>(mglob.z());
271  }
272 
273  if (type == TrTrackFillType::SecondTrack) {
274  return true;
275  }
276 
277  // - single layers
278  for (int ijl = 0; ijl < 9; ijl++) {
279  Fit fit = Fit::Choutko;
280  Span span = Span::InnerOnly;
281 
282  if (trackPtr->GetHitLJ(ijl + 1)) {
283  LayerChargeStatus[ijl] = trackPtr->GetHitLJ(ijl + 1)->GetQStatus();
284 
285  LayerChargeXY[ijl][ChargeRecoType::STD] = trackPtr->GetHitLJ(ijl + 1)->GetQ(2, _beta, Rigidity[fit][span]);
286  LayerChargeXY[ijl][ChargeRecoType::HL] = trackPtr->GetLayerJQH(ijl + 1, 2, _beta, _fit_ID[fit][span]);
287  LayerChargeXY[ijl][ChargeRecoType::YJ] = trackPtr->GetLayerQYJ(ijl + 1, 2, _beta, _fit_ID[fit][span]);
288  }
289  }
290 
291  for (const auto fitPos : fitPositionHeights) {
292  // Define a Plane from the Hits Coordinates
293  AMSPlaneM plm_res;
294  TVector3 mglob;
295  if (fitPos <= TrTrack::FitPositionHeight::Layer9) { // Just for the Layers
296  plm_res = trackPtr->GetHitCooLJN(fitPos + 1);
297  mglob = plm_res.getMGlobal();
298  }
299  for (auto fit : fitTypes) {
300  if (type == TrTrackFillType::Standalone) {
301  switch (fit) {
302  case Fit::KalmanElectron:
303  case Fit::ChoutkoNoMS:
304  case Fit::GBLNoMS:
305  // for standalone we only consider Choutko, Kalman and GBL
306  continue;
307  default:
308  break;
309  }
310  }
311 
312  for (auto span : spanTypes) {
313  // For NoMS fits we only care about InnerOnly
314  if ((fit == Fit::ChoutkoNoMS || fit == Fit::GBLNoMS) && span != Span::InnerOnly) {
315  continue;
316  }
317 
318  if (type == TrTrackFillType::Standalone) {
319  switch (span) {
322  case Span::InnerL9:
323  // for standalone we only consider InnerOnly, InnerL1 and FullSpan
324  continue;
325  break;
326  default:
327  break;
328  }
329  }
330 
331  if (FitIDExists(fit, span)) {
332  int fit_ID = _fit_ID.at(fit).at(span);
333  if (fit_ID < 0)
334  continue;
335 
336  double rigidity;
337 
338  // Define a Plane from a given Nominal HeightZ to store the FitPositions
339  trackPtr->Interpolate(pl_TrPlanes[fitPos], rigidity, fit_ID);
340  TVector3 pglob_fitpos = pl_TrPlanes[fitPos].getP();
341  TrTrackFitPos[fitPos][fit][span][Side::X] = static_cast<float>(pglob_fitpos.x());
342  TrTrackFitPos[fitPos][fit][span][Side::Y] = static_cast<float>(pglob_fitpos.y());
343  }
344  }
345  }
346  }
347 
348  return true;
349 }
350 
351 bool TrTrackPlusData::Fill(TrTrackR *trackPtr) {
352  const auto &_beta = trkBase->_beta;
353  const auto &_tmpCharge = trkBase->_tmpCharge;
354 
355  if (trkBase->InnerCharge.empty())
356  return false;
357 
358  auto *pev = AMSEventR::Head();
359 
360  int refit = ((trkBase->_isMC) || (_tmpCharge != trackPtr->GetAdvancedFitCharge())) ? 3 : 1;
361  float fitMass = (_tmpCharge >= 2) ? TrFit::Mhelium / 2 * _tmpCharge : TrFit::Mproton;
362 
363  auto getPartialPattern = [](TrTrackR *track, unsigned int jLayer) {
364  unsigned int pattern = 0;
365  for (unsigned int ijl = 1; ijl < 10; ijl++) {
366  if (track->TestHitLayerJ(ijl) && ijl != jLayer)
367  pattern += 9 * powersOfTen[ijl - 1];
368  }
369  return pattern;
370  };
371 
372  for (unsigned int ijl = 2; ijl < 9; ijl++) {
373  TrackFeetDistance[ijl - 1] = pev->GetTkFeetDist(ijl, trackPtr);
374  }
375 
376  // Rigidity
377  for (auto fit : fitTypes) {
378 
379  // Kalman with electron mass hyp. to be done in dedicated fill method
380  if (fit == Fit::KalmanElectron)
381  continue;
382 
384  for (auto span : spanTypes) {
385  // For NoMS fits we only care about InnerOnly
386  if ((fit == Fit::ChoutkoNoMS || fit == Fit::GBLNoMS) && span != Span::InnerOnly) {
387  continue;
388  }
389 
390  if (trkBase->FitIDExists(fit, span)) {
391  _fit_ID[fit][span] =
392  trackPtr->iTrTrackPar(fitAlgoCode[fit], static_cast<int>(patterns[span]), 30 + refit, fitMass, _tmpCharge);
393  if (_fit_ID[fit][span] < 0)
394  continue;
395 
396  AMSPlane &pl_TOI = _beta < 0 ? pl_TOI_bot : pl_TOI_top;
397  double rigidity;
398  if (fit == Fit::Kalman) {
399  // TOI rigidity for both downward and upward going particles.
400  trackPtr->Interpolate(pl_TOI, rigidity, _fit_ID[fit][span], fitMass, _tmpCharge, 1, (_beta > 0) ? 1 : -1);
401  // NOTE: To keep the same convention for all rigidities measured in AMS we invert the result for upgoing
402  // particles. We need to do this because Kalman keeps track of the propagation direction so an upgoing proton
403  // is reconstructed with a positive TOI rigidity while all the "other" rigidities are reconstructed negative.
404  RigidityTOI[fit][span] = static_cast<float>(rigidity * (_beta > 0 ? 1.0f : -1.0f));
405  // Rigidity at RICH
406  trackPtr->Interpolate(pl_RICH, rigidity, _fit_ID[fit][span], fitMass, _tmpCharge, 1);
407  RigidityRICH[fit][span] = static_cast<float>(rigidity);
408  }
409  const TrTrackPar &trackPar = trackPtr->gTrTrackPar(_fit_ID[fit][span]);
410  InvRigErr[fit][span] = static_cast<float>(trackPar.ErrRinv);
411 
412  // Theta and Phi
413  trackPtr->Interpolate(pl_TOI, rigidity, _fit_ID[fit][span], fitMass, _tmpCharge, 1, (_beta > 0) ? 1 : -1);
414  Theta[fit][span] = static_cast<float>(pl_TOI.getD().Theta());
415  Phi[fit][span] = static_cast<float>(pl_TOI.getD().Phi());
416  }
417  }
419 
420  // using default fit and inner tracker charge to restore coordinate
421  trackPtr->RecalcHitCoordinates(0, false, false, _tmpCharge);
422 
423  // doesn't make sense to try if inner only fit failed...
424  if (trkBase->FitIDExists(fit, Span::InnerOnly)) {
425  for (unsigned int ijl = 1; ijl < 10; ijl++) {
426  if (!trackPtr->TestHitLayerJ(ijl))
427  continue;
428  auto partialPattern = getPartialPattern(trackPtr, ijl);
429 
431  int pfit_ID = trackPtr->iTrTrackPar(fitAlgoCode[fit], partialPattern, 30 + refit, fitMass, _tmpCharge);
433  if (pfit_ID < 0)
434  continue;
435 
436  const TrTrackPar &partialTrackPar = trackPtr->gTrTrackPar(pfit_ID);
437  PartialRigidity[ijl - 1][fit] = partialTrackPar.Rigidity;
438  PartialInvRigErr[ijl - 1][fit] = partialTrackPar.ErrRinv;
439  PartialTrChiSq[ijl - 1][fit][Side::X] = static_cast<float>(partialTrackPar.ChisqX / partialTrackPar.NdofX);
440  PartialTrChiSq[ijl - 1][fit][Side::Y] = static_cast<float>(partialTrackPar.ChisqY / partialTrackPar.NdofY);
441 
442  // Define a Plane from a given Nominal HeightZ to store the Partial FitPositions
443  double rigidity;
444  trackPtr->Interpolate(pl_TrPlanes[ijl - 1], rigidity, pfit_ID);
445  TVector3 pglob_fitpos = pl_TrPlanes[ijl - 1].getP();
446  PartialTrTrackFitPos[ijl - 1][fit][Side::X] = static_cast<float>(pglob_fitpos.x());
447  PartialTrTrackFitPos[ijl - 1][fit][Side::Y] = static_cast<float>(pglob_fitpos.y());
448 
449  // Define a Plane from the Hits Coordinates to calculate the Partial Residuals
450  // by using the real Height of the event
451  AMSPlaneM plm_res = trackPtr->GetHitCooLJN(ijl + 1);
452  TVector3 mglob = plm_res.getMGlobal();
453  trackPtr->Interpolate(plm_res, rigidity, pfit_ID);
454  TVector3 pglob_res = plm_res.getP();
455  PartialTrTrackResidual[ijl - 1][fit][Side::X] = static_cast<float>(mglob.x() - pglob_res.x());
456  PartialTrTrackResidual[ijl - 1][fit][Side::Y] = static_cast<float>(mglob.y() - pglob_res.y());
457  }
458  }
459  }
460  trackPtr->RecalcHitCoordinates(0, 0, 0, _tmpCharge); // using default fit and inner tracker charge to restore
461  // coordinate
462 
463  auto dir_fit = TrTrack::Fit::Choutko;
464  auto dir_span = trkBase->GetBestSpan(dir_fit);
465  if (trkBase->FitIDExists(dir_fit, dir_span)) {
466  const AMSDir trk_dir{Theta[dir_fit][dir_span], Phi[dir_fit][dir_span]};
467  // Once again, I come to you to complain about the worst API ever designed: gbatch
468  // 5 LOC when 2 would have been enough
469  double tmp;
470  AMSEventR::Head()->GetStoermerCutoff(tmp, -1, trk_dir);
471  DirectionalStoermerCutoff[0] = tmp;
472  AMSEventR::Head()->GetStoermerCutoff(tmp, 1, trk_dir);
473  DirectionalStoermerCutoff[1] = tmp;
474  }
475 
476  // - single layers
477  constexpr Fit base_fit = Fit::Choutko;
478  constexpr Span base_span = Span::InnerOnly;
479  if (trkBase->FitIDExists(base_fit, base_span)) {
480  int base_fit_ID = _fit_ID.at(base_fit).at(base_span);
481 
482  for (int ijl = 0; ijl < 9; ijl++) {
483  if (trackPtr->GetHitLJ(ijl + 1)) {
484  float rigidity = (base_fit_ID > 0) ? trkBase->Rigidity.at(base_fit).at(base_span) : 0;
485 
486  if (!trackPtr->GetHitLJ(ijl + 1)->OnlyY()) {
487  LayerCharge[ijl][ChargeRecoType::STD][Side::X] = trackPtr->GetHitLJ(ijl + 1)->GetQ(0, _beta, rigidity);
488  LayerCharge[ijl][ChargeRecoType::HL][Side::X] = trackPtr->GetLayerJQH(ijl + 1, 0, _beta, base_fit_ID);
489  LayerCharge[ijl][ChargeRecoType::YJ][Side::X] = trackPtr->GetLayerQYJ(ijl + 1, 0, _beta, base_fit_ID);
490  }
491 
492  if (trackPtr->GetHitLJ(ijl + 1)->GetXCluster())
493  LayerEdep[ijl][Side::X] = trackPtr->GetHitLJ(ijl + 1)->GetXCluster()->GetEdep();
494  if (trackPtr->GetHitLJ(ijl + 1)->GetYCluster())
495  LayerEdep[ijl][Side::Y] = trackPtr->GetHitLJ(ijl + 1)->GetYCluster()->GetEdep();
496 
497  LayerCharge[ijl][ChargeRecoType::STD][Side::Y] = trackPtr->GetHitLJ(ijl + 1)->GetQ(1, _beta, rigidity);
498  LayerCharge[ijl][ChargeRecoType::HL][Side::Y] = trackPtr->GetLayerJQH(ijl + 1, 1, _beta, base_fit_ID);
499  LayerCharge[ijl][ChargeRecoType::YJ][Side::Y] = trackPtr->GetLayerQYJ(ijl + 1, 1, _beta, base_fit_ID);
500  }
501  }
502  }
503 
504  for (const auto fitPos : fitPositionHeights) {
505  // Define a Plane from the Hits Coordinates
506  AMSPlaneM plm_res;
507  TVector3 mglob;
508  if (fitPos <= TrTrack::FitPositionHeight::Layer9) { // Just for the Layers
509  plm_res = trackPtr->GetHitCooLJN(fitPos + 1);
510  mglob = plm_res.getMGlobal();
511  }
512  for (auto fit : fitTypes) {
513  for (auto span : spanTypes) {
514  if (trkBase->FitIDExists(fit, span)) {
515  int fit_ID = _fit_ID.at(fit).at(span);
516  if (fit_ID < 0)
517  continue;
518  double rigidity;
519 
520  // Define a Plane from a given Nominal HeightZ to store the FitPositions
521  trackPtr->Interpolate(pl_TrPlanes[fitPos], rigidity, fit_ID);
522  TVector3 pglob_fitpos = pl_TrPlanes[fitPos].getP();
523 
524  // From the Plane defined by the Hits Cooordinates, calculate the Residuals using the real Height associated
525  // with the event
526  if (fitPos <= TrTrack::FitPositionHeight::Layer9) { // Just for the Layers
527  if (!trackPtr->TestHitLayerJ(fitPos + 1))
528  continue;
529  trackPtr->Interpolate(plm_res, rigidity, fit_ID);
530  TVector3 pglob_res = plm_res.getP();
531  if (!trackPtr->GetHitLJ(fitPos + 1)->OnlyY()) {
532  TrTrackResidual[fitPos][fit][span][Side::X] = static_cast<float>(mglob.x() - pglob_res.x());
533  }
534  TrTrackResidual[fitPos][fit][span][Side::Y] = static_cast<float>(mglob.y() - pglob_res.y());
535  }
536  }
537  }
538  }
539  }
540 
541  static constexpr std::array<float, 5> window = {0.1, 1., 2., 5., 10.};
542 
543  // from dbar code
544  for (int jLayer = 1; jLayer <= 9; jLayer++) {
545 
546  ClusterSignalRatio[jLayer - 1] = pev->GetTrackerRawSignalRatio(jLayer, 10);
547 
548  // identify the clusters used in trtrack
549  TrClusterR *trackClusterPtrX = trackPtr->GetHitLJ(jLayer) ? trackPtr->GetHitLJ(jLayer)->GetXCluster() : nullptr;
550  TrClusterR *trackClusterPtrY = trackPtr->GetHitLJ(jLayer) ? trackPtr->GetHitLJ(jLayer)->GetYCluster() : nullptr;
551 
552  // Get track interpolation to jLayer
553  double rigidity;
554  trackPtr->Interpolate(pl_TrPlanes[jLayer - 1], rigidity, _fit_ID[Fit::Kalman][Span::InnerOnly]);
555  TVector3 pglob = pl_TrPlanes[jLayer - 1].getP();
556  AMSPoint fitcoo = AMSPoint(pglob.x(), pglob.y(), pglob.z());
557 
558  // TODO: Check if zero threshold is correct
559  static constexpr float noiseThreshold = 0;
560 
561  for (int icl = 0; icl < pev->nTrCluster(); icl++) {
562  auto *cluster = pev->pTrCluster(icl);
563 
564  if (!cluster || cluster->GetLayerJ() != jLayer)
565  continue;
566 
567  float edep = 1000 * cluster->GetEdep();
568  if (cluster == trackClusterPtrX) {
569  NClusters[jLayer - 1][DistanceFromTrack::OnTrack][Side::X]++;
570  ClustersEdep[jLayer - 1][DistanceFromTrack::OnTrack][Side::X] += edep;
571  continue;
572  }
573  if (cluster == trackClusterPtrY) {
574  NClusters[jLayer - 1][DistanceFromTrack::OnTrack][Side::Y]++;
575  ClustersEdep[jLayer - 1][DistanceFromTrack::OnTrack][Side::Y] += edep;
576  continue;
577  }
578 
579  if (edep < noiseThreshold)
580  continue; // apply a threshold to account for noise
581 
582  // Deal with multiplicities: Choose closest to track
583  float clusterDistanceToTrack = std::numeric_limits<float>::max();
584  for (int im = 0; im < cluster->GetMultiplicity(); im++) {
585  AMSPlaneM pl_mult = cluster->GetGCoordN(im);
586  TVector3 mglob_mult = pl_mult.getMGlobal();
587 
588  clusterDistanceToTrack =
589  std::min(clusterDistanceToTrack,
590  fabs(static_cast<float>(fitcoo[cluster->GetSide()] - mglob_mult[cluster->GetSide()])));
591  }
592 
593  Side side = cluster->GetSide() == 0 ? Side::X : Side::Y;
594 
595  NClusters[jLayer - 1][DistanceFromTrack::AllLayer][side]++;
596  ClustersEdep[jLayer - 1][DistanceFromTrack::AllLayer][side] += edep;
597  if (edep > MaxClusterEdep[jLayer - 1][side]) {
598  MaxClusterEdep[jLayer - 1][side] = edep;
599  MaxClusterDistance[jLayer - 1][side] = clusterDistanceToTrack;
600  }
601 
602  // FIXME: I don't really like using an int instead of the right enum
603  for (unsigned int iw = 0; iw < window.size(); iw++) {
604  if (std::fabs(clusterDistanceToTrack) < window[iw]) {
605  NClusters[jLayer - 1][static_cast<DistanceFromTrack>(iw + 1)][side]++;
606  ClustersEdep[jLayer - 1][static_cast<DistanceFromTrack>(iw + 1)][side] += edep;
607  }
608  }
609  }
610  }
611  return true;
612 }
613 
614 bool TrTrackBaseData::FillElectronVars(TrTrackR *trackPtr, float zEcalCOG, bool refitKalman) {
615  // Rigidity
616  auto fit = Fit::KalmanElectron;
617  auto span = _GetBestSpan(Fit::Kalman);
618 
619  if (TrackHasExtHits(trackPtr, span) && refitKalman) {
620  Logging::MuteOutput(); // this can get quite verbose...
621  _fit_ID[fit][span] = trackPtr->iTrTrackPar(fitAlgoCode[fit], static_cast<int>(patterns[span]), 32,
622  static_cast<float>(TrFit::Melectron), 1);
624  if (_fit_ID[fit][span] > 0) {
625  double rigidity;
626  trackPtr->Interpolate(pl_TrCenter, rigidity, _fit_ID[fit][span], TrFit::Melectron, 1);
627  Rigidity[fit][span] = static_cast<float>(rigidity);
628  TrChiSq[fit][span][Side::X] =
629  static_cast<float>(trackPtr->GetChisqX(_fit_ID[fit][span]) / trackPtr->GetNdofX(_fit_ID[fit][span]));
630  TrChiSq[fit][span][Side::Y] =
631  static_cast<float>(trackPtr->GetChisqY(_fit_ID[fit][span]) / trackPtr->GetNdofY(_fit_ID[fit][span]));
632  }
633  } else {
634  return false;
635  }
636 
637  if (zEcalCOG < std::numeric_limits<float>::max()) {
638  for (auto fit : fitTypes) {
639  for (auto span : spanTypes) {
640  if (FitIDExists(fit, span)) {
641  int fit_ID = _fit_ID.at(fit).at(span);
642  double rigidity;
643  AMSPlane plm(TVector3(0, 0, zEcalCOG), TVector3(1, 0, 0), TVector3(0, 1, 0));
644  trackPtr->Interpolate(plm, rigidity, fit_ID);
645  TVector3 pglob = plm.getP();
646  TrTrackFitPos[FitPositionHeight::EcalCOG][fit][span][Side::X] = static_cast<float>(pglob.x());
647  TrTrackFitPos[FitPositionHeight::EcalCOG][fit][span][Side::Y] = static_cast<float>(pglob.y());
648  }
649  }
650  }
651  }
652 
653  return true;
654 }
655 
656 bool TrTrackPlusData::FillElectronVars(TrTrackR *trackPtr, bool refitKalman) {
657  const auto &base_fit_ID = trkBase->_fit_ID;
658  const auto &_beta = trkBase->_beta;
659 
660  {
661  auto fit = Fit::KalmanElectron;
662  auto span = trkBase->GetBestSpan(Fit::Kalman);
663  if (trkBase->FitIDExists(fit, span) && refitKalman) {
664  AMSPlane &pl_TOI = _beta < 0 ? pl_TOI_bot : pl_TOI_top;
665  int fit_ID = base_fit_ID.at(fit).at(span);
666  // TOI rigidity for both downward and upward going particles.
667  double rigidity;
668  float zpl = (_beta > 0) ? 195 : -195;
669  trackPtr->Interpolate(pl_TOI, rigidity, fit_ID, TrFit::Melectron, 1, 1, (_beta > 0) ? 1 : -1);
670  RigidityTOI[fit][span] = static_cast<float>(rigidity);
671  // Rigidity at RICH
672  AMSPlane pl_RICH(TVector3(0, 0, -70), TVector3(1, 0, 0), TVector3(0, 1, 0));
673  trackPtr->Interpolate(pl_RICH, rigidity, fit_ID, TrFit::Melectron, 1, 1);
674  RigidityRICH[fit][span] = static_cast<float>(rigidity);
675  // Theta and Phi
676  Theta[fit][span] = static_cast<float>(pl_TOI.getD().Theta());
677  Phi[fit][span] = static_cast<float>(pl_TOI.getD().Phi());
678 
679  const TrTrackPar &trackPar = trackPtr->gTrTrackPar(fit_ID);
680  InvRigErr[fit][span] = static_cast<float>(trackPar.ErrRinv);
681  }
682  }
683 
684  return true;
685 }
686 } // namespace NAIA
NAIA::TrTrack::FullSpan
@ FullSpan
Track constructed with all available hits (inner tracker + layer 1 + layer 9)
Definition: Utils.h:162
NAIA::ComputePatterns
void ComputePatterns(TrTrackR *trackPtr)
Definition: TrTrackFill.cpp:36
NAIA::TrTrack::InnerL9
@ InnerL9
Track constructed with inner tracker + layer9 hits.
Definition: Utils.h:161
NAIA::TrTrack::EcalCOG
@ EcalCOG
Definition: Utils.h:118
NAIA::end
NAIAChain::EventItr end(NAIAChain &chain)
Definition: NAIAChain.h:298
NAIA::Logging::UnmuteOutput
void UnmuteOutput()
Definition: Logging.cpp:36
NAIA::TrackHasExtHits
static bool TrackHasExtHits(TrTrackR *trackPtr, Span span)
Definition: TrTrackFill.cpp:16
NAIA::TrTrack::Side
Side
Definition: Utils.h:207
NAIA::TrTrack::KalmanElectron
@ KalmanElectron
GenFit kalman filter track fit assuming electron mass.
Definition: Utils.h:182
NAIA::patterns
static std::array< unsigned long int, numSpans > patterns
Definition: TrTrackFill.cpp:14
NAIA::TrTrack::GBLNoMS
@ GBLNoMS
GBL fit without multiple scattering corrections.
Definition: Utils.h:184
NtpTools.h
NAIA::TrTrack::DistanceFromTrack
DistanceFromTrack
Definition: Utils.h:217
NAIA::TrTrack::X
@ X
Definition: Utils.h:207
NAIA::TrTrack::STD
@ STD
Standard tracker charge reconstruction.
Definition: Utils.h:91
NAIA::TrTrack::Choutko
@ Choutko
standard track fit
Definition: Utils.h:179
NAIA::TrTrack::OnTrack
@ OnTrack
Definition: Utils.h:217
NAIA::TrTrack::Span
Span
Definition: Utils.h:157
NAIA
Definition: Event.h:13
NAIA::ReFitParameters
Definition: TrTrackFill.cpp:76
NAIA::HitClusterAssociation::Y
@ Y
NAIA::TrTrack::InnerOnly
@ InnerOnly
Track constructed with only inner tracker hits.
Definition: Utils.h:159
NAIA::TrTrack::YJ
@ YJ
Yi Jia reconstruction.
Definition: Utils.h:93
NAIA::ReFitParameters::refit
int refit
Definition: TrTrackFill.cpp:77
NAIA::powersOfTen
static constexpr std::array< double, 9 > powersOfTen
Definition: TrTrackFill.cpp:34
NAIA::ReFitParameters::mass
float mass
Definition: TrTrackFill.cpp:78
NAIA::TrTrack::fitPositionHeights
constexpr std::array< FitPositionHeight, numFitPositionHeights > fitPositionHeights
Definition: Utils.h:124
NAIA::TrTrack::Kalman
@ Kalman
GenFit kalman filter track fit.
Definition: Utils.h:180
NAIA::TrTrack::HL
@ HL
Hu Liu reconstruction.
Definition: Utils.h:92
NAIA::TrTrack::UpperHalfInner
@ UpperHalfInner
Track constructed with the upper part of the inner tracker (layers 2 to 6)
Definition: Utils.h:163
NAIA::Logging::MuteOutput
void MuteOutput()
Definition: Logging.cpp:22
TrTrack.h
TrTrack container class description.
NAIA::TrTrack::AllLayer
@ AllLayer
Definition: Utils.h:217
NAIA::TrTrack::spanTypes
constexpr std::array< Span, numSpans > spanTypes
Definition: Utils.h:167
NAIA::TrTrack::LowerHalfInner
@ LowerHalfInner
Track constructed with the upper part of the inner tracker (layers 3 to 8)
Definition: Utils.h:164
NAIA::TrTrack::fitPositionHeightZ
constexpr std::array< float, numFitPositionHeights > fitPositionHeightZ
Definition: Utils.h:136
NAIA::TrTrack::Y
@ Y
Definition: Utils.h:207
NAIA::HitClusterAssociation::XY
@ XY
NAIA::TrTrack::InnerL1
@ InnerL1
Track constructed with inner tracker + layer 1 hits.
Definition: Utils.h:160
NAIA::TrTrack::Fit
Fit
Definition: Utils.h:177
Logging.h
NAIA::TrTrack::ChoutkoNoMS
@ ChoutkoNoMS
Choutko fit without multiple scattering corrections.
Definition: Utils.h:183
NAIA::TrTrack::Layer9
@ Layer9
Definition: Utils.h:112
NAIA::ReFitParameters::charge
int charge
Definition: TrTrackFill.cpp:79
NAIA::TrTrack::fitTypes
constexpr std::array< Fit, numFits > fitTypes
Definition: Utils.h:187
NAIA::fitAlgoCode
std::array< int, numFits > fitAlgoCode
Definition: TrTrackFill.cpp:15
NAIA::InitTrkReFit
ReFitParameters InitTrkReFit(float inner_charge, bool _isMC, float production_charge)
Definition: TrTrackFill.cpp:82