ATLAS Offline Software
MdtSegmentT0Fitter.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3 */
4 
6 
10 
14 
17 
18 #include "Minuit2/Minuit2Minimizer.h"
19 #include "Math/Functor.h"
20 #include "TMath.h"
21 #include <functional>
22 
23 #include <iostream>
24 #include <fstream>
25 #include <atomic>
26 #include <mutex>
27 
28 namespace {
29  // number of fit parameters
30  constexpr unsigned int NUMPAR=3;
31 
32  // time corresponding to r=15 mm for internal rt
33  //constexpr double TUBE_TIME = 757.22;
34 
35  //constexpr double MAX_DRIFT= 855;
36 
37  // garbage time value to return when radius isn't wihin rt range
38  constexpr double R2TSPURIOUS = 50000;
39 
40  constexpr int WEAK_TOPO_T0ERROR = 10;
41 
42  constexpr int STRONG_TOPO_T0ERROR = 50;
43 
44  struct HitCoords {
45  public:
46  HitCoords(const double z_coord, const double t_coord,
47  const double y_coord, const double w_coord,
48  const double r_coord, const MuonCalib::IRtRelation * rt_rel):
49  z(z_coord),
50  t(t_coord),
51  y(y_coord),
52  w(w_coord),
53  r(r_coord),
54  rt(rt_rel){}
56  double z{0.};
58  double t{0.};
60  double y{0.};
62  double w{0.};
64  double r{0.};
66  double dr{0.};
68  const MuonCalib::IRtRelation *rt{nullptr};
70  bool rejected{false};
71  };
72  template <typename T> constexpr T sq(const T a) {return a * a;}
73 
74  class FunctionToMinimize : public ROOT::Math::IMultiGenFunction {
75  public:
76  explicit FunctionToMinimize(const int used) :m_used{used} {}
77 
78  double DoEval(const double* xx) const override {
79  const double ang = xx[0];
80  const double b = xx[1];
81  const double t0 = xx[2];
82 
83  const double cosin = std::cos(ang);
84  const double sinus = std::sin(ang);
85 
86  double fval = 0.;
87  // Add t0 constraint
88  if (m_t0Error == WEAK_TOPO_T0ERROR ) {
89  fval += xx[2]*xx[2]/(1.0 *m_t0Error*m_t0Error);
90  }
91  for(int i=0;i<m_used;++i) {
92  const double t = m_data[i].t - t0;
93  const double z = m_data[i].z;
94  const double y = m_data[i].y;
95  const double w = m_data[i].w;
96  const double dist = std::abs(b*cosin + z*sinus - y*cosin); // same thing as fabs(a*z - y + b)/sqrt(1. + a*a);
97  const double uppercut = m_data[i].rt->tUpper();
98  const double lowercut = m_data[i].rt->tLower();
99 
100  // Penalty for t<lowercut and t >uppercut
101  if (t> uppercut ) { // too large
102  fval += sq(t-uppercut)*0.1;
103  } else if (t < lowercut) {// too small
104  fval += sq(t-lowercut)*0.1;
105  }
106  const double r = t< lowercut ? m_data[i].rt->radius(lowercut) : t > uppercut ? m_data[i].rt->radius(uppercut) : m_data[i].rt->radius(t);
107  fval += sq(dist - r)*w;
108  }
109 
110  return fval;
111  }
112  ROOT::Math::IBaseFunctionMultiDim* Clone() const override {return new FunctionToMinimize(m_used);}
113  unsigned int NDim() const override {return 3;}
114  void setT0Error(const int t0Error){m_t0Error=t0Error;}
115  void addCoords(HitCoords coord){
116  m_data.emplace_back(coord);
117  }
118  private:
119  std::vector<HitCoords> m_data{};
120  int m_used{0};
121  int m_t0Error{-1};
122  };
123 
124  /***********************************************************************************/
127 
128  //constexpr double T2R_A[] = {1.184169e-1, 3.32382e-2, 4.179808e-4, -5.012896e-6, 2.61497e-8, -7.800677e-11, 1.407393e-13, -1.516193e-16, 8.967997e-20, -2.238627e-23};
129  //constexpr double RCORR_A[] = {234.3413, -5.803375, 5.061677e-2, -1.994959e-4, 4.017433e-7, -3.975037e-10, 1.522393e-13};
130 
131 
132 
133  double r2t_ext(const MuonCalib::IRtRelation* rtrel, double r) {
134  double ta = rtrel->tLower();
135  double tb = rtrel->tUpper();
136  if(r<rtrel->radius(ta) ) {
137  return -1*R2TSPURIOUS;
138  } else if(r>rtrel->radius(tb)) {
139  return R2TSPURIOUS;
140  }
141 
142  int itr = 0;
143  while (ta <= tb) {
144  double tm = (ta + tb) / 2; // compute mid point.
145  double rtm = rtrel->radius(tm);
146  if(std::abs(rtm - r) < 0.001 ) {
147  return tm;
148  }
149  else if (r > rtm) {
150  ta = tm; // repeat search in top half.
151  }
152  else if (r < rtm ) {
153  tb = tm; // repeat search in bottom half.
154  }
155 
156  itr++;
157  if(itr>50) return -1;
158  }
159  return -1; // failed to find key
160  }
161  int sign(double a) {
162  return a > 0 ? 1 : a < 0 ? -1 : 0;
163  }
164 }
165 
166 namespace TrkDriftCircleMath {
167 
168  MdtSegmentT0Fitter::MdtSegmentT0Fitter(const std::string& ty,const std::string& na,const IInterface* pa)
169  : AthAlgTool(ty,na,pa),
170  DCSLFitter() {
171  declareInterface <IDCSLFitProvider> (this);
172  }
173 
176  return StatusCode::SUCCESS;
177  }
178 
180 
181  double scaleFactor = m_ntotalCalls != 0 ? 1./(double)m_ntotalCalls : 1.;
182 
183  ATH_MSG_INFO( "Summarizing fitter statistics " << "\n"
184  << " Total fits " << std::setw(10) << m_ntotalCalls << " " << scaleFactor*m_ntotalCalls << "\n"
185  << " hits > 2 " << std::setw(10) << m_npassedNHits << " " << scaleFactor*m_npassedNHits << "\n"
186  << " hit consis. " << std::setw(10) << m_npassedSelectionConsistency << " " << scaleFactor*m_npassedSelectionConsistency << "\n"
187  << " sel. hits > 2 " << std::setw(10) << m_npassedNSelectedHits << " " << scaleFactor*m_npassedNSelectedHits << "\n"
188  << " Hits > min hits " << std::setw(10) << m_npassedMinHits << " " << scaleFactor*m_npassedMinHits << "\n"
189  << " Passed Fit " << std::setw(10) << m_npassedMinuitFit << " " << scaleFactor*m_npassedMinuitFit );
190  return StatusCode::SUCCESS;
191  }
192 
193  bool MdtSegmentT0Fitter::fit( Segment& result, const Line& line, const DCOnTrackVec& dcs, const HitSelection& selection, double t0Seed ) const {
194  ++m_ntotalCalls;
195  const MdtIdHelper& id_helper{m_idHelperSvc->mdtIdHelper()};
196  ATH_MSG_DEBUG("New seg: ");
197  const EventContext& ctx{Gaudi::Hive::currentContext()};
199  if (!calibData.isValid()) {
200  ATH_MSG_FATAL("Failed to retrieve Mdt calibration object "<<m_calibDbKey.fullKey());
201  return false;
202  }
203  std::array<const MuonCalib::MdtRtRelation*, 2> rtRelations{};
204  {
205  unsigned int nRel{0};
206  for (unsigned int i = 0; i < dcs.size() ; ++i) {
207  const Identifier id = dcs[i].rot()->identify();
208  const int mlIdx = id_helper.multilayer(id) -1;
209  if (rtRelations[mlIdx]) continue;
210  rtRelations[mlIdx] = calibData->getCalibData(id, msgStream())->rtRelation.get();
211  ++nRel;
212  if (nRel == 2) break;
213  }
214  }
215  const DCOnTrackVec& dcs_keep = dcs;
216 
217  unsigned int N = dcs_keep.size();
218 
219  result.setT0Shift(-99999,-99999);
220 
221  if(N<2) {
222  return false;
223  }
224  ++m_npassedNHits;
225  if( selection.size() != N ) {
226  ATH_MSG_ERROR("MdtSegmentT0Fitter.cxx:fit with t0 <bad HitSelection>");
227  return false;
228  }
230  int used=0;
231  for(unsigned int i=0;i<N;++i){
232  if( selection[i] == 0 ) ++used;
233  }
234  if(used < 2){
235  ATH_MSG_DEBUG("TOO FEW HITS SELECTED");
236  return false;
237  }
239 
240  if(used < m_minHits) {
241  ATH_MSG_DEBUG("FEWER THAN Minimum HITS N " << m_minHits << " total hits " <<N<<" used " << used);
242 
243  //
244  // Copy driftcircles and reset the drift radii as they might have been overwritten
245  // after a succesfull t0 fit
246  //
247 
248  DCOnTrackVec dcs_new;
249  dcs_new.reserve(dcs.size());
250 
251  double chi2p = 0.;
252  int n_elements = dcs.size();
253  for(int i=0; i< n_elements; ++i ){
254  const DriftCircle* ds = & dcs[i];
255  if(std::abs(ds->r()-ds->rot()->driftRadius())>m_dRTol) ATH_MSG_DEBUG("Different radii on dc " << ds->r() << " rot " << ds->rot()->driftRadius());
256 
257  DriftCircle dc_keep(ds->position(), ds->rot()->driftRadius(), ds->dr(), ds->drPrecise(), ds->driftState(), ds->id(), ds->rot(), ds->index());
258  DCOnTrack dc_new(dc_keep, 0., 0.);
259 
260  dc_new.state(dcs[i].state());
261  dcs_new.push_back( dc_new );
262  if( selection[i] == 0 ){
263  double t = ds->rot()->driftTime();
264  const unsigned int mlIdx = id_helper.multilayer(ds->rot()->identify()) - 1;
265  const MuonCalib::MdtRtRelation *rtInfo = rtRelations[mlIdx];
266 
267  double tUp = rtInfo->rt()->tUpper();
268  double tLow = rtInfo->rt()->tLower();
269 
270  if(t<tLow) chi2p += sq(t-tLow)*0.1;
271  else if(t>tUp) chi2p += sq(t-tUp)*0.1;
272  }
273  }
274 
275  if(chi2p>0) ATH_MSG_DEBUG("NO Minuit Fit TOO few hits Chi2 penalty " << chi2p);
276 
277  bool oldrefit = DCSLFitter::fit( result, line, dcs_new, selection );
278 
279  chi2p += result.chi2();
280  // add chi2 penalty for too large or too small driftTimes t < 0 or t> t upper
281  result.set(chi2p, result.ndof(), result.dtheta(), result.dy0());
282  int iok = 0;
283  if(oldrefit) iok = 1;
284  ATH_MSG_DEBUG(" chi2 total " << result.chi2() << " angle " << result.line().phi() << " y0 " << result.line().y0() << " nhits "<< selection.size() << " refit ok " << iok);
285  return oldrefit;
286 
287  }
288 
289  ATH_MSG_DEBUG("FITTING FOR T0 N "<<N<<" used " << used);
290 
291 
293 
294 
295  ATH_MSG_DEBUG(" in MdtSegmentT0Fitter::fit with N dcs "<< N << " hit selection size " << selection.size());
296  ATH_MSG_DEBUG("in fit "<<result.hasT0Shift()<< " " <<result.t0Shift());
297 
298 
299  double Zc{0.}, Yc{0.}, S{0.}, Sz{0.}, Sy{0};
300 
301  std::vector<HitCoords> hits{};
302  hits.reserve(N);
303  FunctionToMinimize minFunct(used);
304 
305  {
306  unsigned int ii{0};
307  for(const DCOnTrack& keep_me : dcs_keep ){
308  const Muon::MdtDriftCircleOnTrack *roto = keep_me.rot();
309  const unsigned int mlIdx = id_helper.multilayer(roto->identify()) - 1;
310  const MuonCalib::MdtRtRelation *rtInfo = rtRelations[mlIdx];
311 
312  const double newerror = m_scaleErrors ? keep_me.drPrecise() : keep_me.dr();
313  const double w = newerror >0. ? sq(1./newerror) : 0.;
314  hits.emplace_back(keep_me.x(), roto->driftTime(), keep_me.y(), w, std::abs(roto->driftRadius()), rtInfo->rt());
315  HitCoords& coords = hits.back();
316  coords.dr = keep_me.dr();
317  coords.rejected = selection[ii];
318  ATH_MSG_DEBUG("DC: (" << coords.y << "," << coords.z << ") R = " << coords.r << " W " << coords.w
319  <<" t " <<coords.t<< " id: "<<keep_me.id()<<" sel " <<coords.rejected);
320  if (!coords.rejected) {
321  S += coords.w;
322  Sz+= coords.z* coords.w;
323  Sy+= coords.y * coords.w;
324  }
325  ++ii;
326  }
327  }
328 
330  const double inv_S = 1. / S;
331  Zc = Sz*inv_S;
332  Yc = Sy*inv_S;
333 
334  ATH_MSG_DEBUG("Yc " << Yc << " Zc " << Zc);
335 
337  for(HitCoords& coords : hits) {
338  coords.y -= Yc;
339  coords.z -= Zc;
340  }
341 
342  int selcount{0};
343 
344  // replicate for the case where the external rt is used...
345  // each hit has an rt function with some range...we want to fit such that
346  // tlower_i < ti - t0 < tupper_i
347  double min_tlower{std::numeric_limits<float>::max()}, max_tupper{-std::numeric_limits<float>::max()};
348 
349  double t0seed=0; // the average t0 of the hit
350  double st0 = 0; // the std deviation of the hit t0s
351  double min_t0 = 1e10; // the smallest t0 seen
352 
353  for(HitCoords& coords : hits) {
354  if(coords.rejected) continue;
355 
356  double r2tval = r2t_ext(coords.rt, coords.r) ;
357  const double tl = coords.rt->tLower();
358  const double th = coords.rt->tUpper();
359  const double tee0 = coords.t - r2tval;
360 
361  min_tlower = std::min(min_tlower, coords.t - tl);
362  max_tupper = std::max(max_tupper, coords.t - th);
363 
364 
365  ATH_MSG_DEBUG(" z "<<coords.z <<" y "<<coords.y<<" r "<<coords.r
366  <<" t "<<coords.t<<" t0 "<<tee0<<" tLower "<<tl<<" tUpper "<<th);
367  t0seed += tee0;
368  st0 += sq(tee0);
369  if(tee0 < min_t0 && std::abs(r2tval) < R2TSPURIOUS) min_t0 = tee0;
370 
371  minFunct.addCoords(coords);
372 
373  selcount++;
374 
375  }
376  t0seed /= selcount;
377  st0 = st0/selcount - t0seed*t0seed;
378  st0 = st0 > 0. ? std::sqrt(st0) : 0.;
379 
380  ATH_MSG_DEBUG(" t0seed "<<t0seed<<" sigma "<<st0<< " min_t0 "<<min_t0);
381 
382  // ************************* seed the parameters
383  const double theta = line.phi();
384  double cosin = std::cos(theta);
385  double sinus = std::sin(theta);
386 
387  if ( sinus < 0.0 ) {
388  sinus = -sinus;
389  cosin = -cosin;
390  } else if ( sinus == 0.0 && cosin < 0.0 ) {
391  cosin = -cosin;
392  }
393 
394  ATH_MSG_DEBUG("before fit theta "<<theta<<" sinus "<<sinus<< " cosin "<< cosin);
395 
396  double d = line.y0() + Zc*sinus-Yc*cosin;
397 
398 
399  ATH_MSG_DEBUG(" line x y "<<line.position().x()<<" "<<line.position().y());
400  ATH_MSG_DEBUG(" Zc Yc "<< Zc <<" "<<Yc);
401  ATH_MSG_DEBUG(" line x0 y0 "<<line.x0()<<" "<<line.y0());
402  ATH_MSG_DEBUG(" hit shift " << -Zc*sinus+Yc*cosin);
403 
404 // Calculate signed radii
405 
406  int nml1p{0}, nml2p{0}, nml1n{0}, nml2n{0};
407  int ii{-1};
408  for(const DCOnTrack& keep_me : dcs_keep){
409  ++ii;
410  const HitCoords& coords = hits[ii];
411  if(coords.rejected) continue;
412  const double sdist = d*cosin + coords.z*sinus - coords.y*cosin; // same thing as |a*z - y + b|/sqrt(1. + a*a);
413  nml1p+=(keep_me.id().ml()==0&&sdist > 0);
414  nml1n+=(keep_me.id().ml()==0&&sdist < 0);
415  nml2p+=(keep_me.id().ml()==1&&sdist > 0);
416  nml2n+=(keep_me.id().ml()==1&&sdist < 0);
417  }
418 
419 // Define t0 constraint in Minuit
420  int t0Error = STRONG_TOPO_T0ERROR;
421  if (nml1p+nml2p < 2 || nml1n+nml2n < 2) t0Error = WEAK_TOPO_T0ERROR;
422 
423  minFunct.setT0Error(t0Error);
424 
425 // Reject topologies where in one of the Multilayers no +- combination is present
426  if((nml1p<1||nml1n<1)&&(nml2p<1||nml2n<1)&&m_rejectWeakTopologies) {
427  ATH_MSG_DEBUG("Combination rejected for positive radii ML1 " << nml1p << " ML2 " << nml2p << " negative radii ML1 " << nml1n << " ML " << nml2n << " used hits " << used << " t0 Error " << t0Error);
428  DCOnTrackVec::const_iterator it = dcs.begin();
429  DCOnTrackVec::const_iterator it_end = dcs.end();
430  double chi2p = 0.;
431  DCOnTrackVec dcs_new;
432  dcs_new.reserve(dcs.size());
433  for(int i=0; it!=it_end; ++it, ++i ){
434  const DriftCircle* ds = & dcs[i];
435  if(std::abs(ds->r()-ds->rot()->driftRadius())>m_dRTol) ATH_MSG_DEBUG("Different radii on dc " << ds->r() << " rot " << ds->rot()->driftRadius());
436  DriftCircle dc_keep(ds->position(), ds->rot()->driftRadius(), ds->dr(), ds->drPrecise(), ds->driftState(), ds->id(), ds->rot(), ds->index() );
437  DCOnTrack dc_new(dc_keep, 0., 0.);
438  dc_new.state(dcs[i].state());
439  dcs_new.push_back( std::move(dc_new) );
440  if( selection[i] == 0 ){
441  double t = ds->rot()->driftTime();
442  const unsigned int mlIdx = id_helper.multilayer(ds->rot()->identify()) - 1;
443  const MuonCalib::MdtRtRelation *rtInfo = rtRelations[mlIdx];
444  double tUp = rtInfo->rt()->tUpper();
445  double tLow = rtInfo->rt()->tLower();
446  if(t<tLow) chi2p += sq(t-tLow)*0.1;
447  if(t>tUp) chi2p += sq(t-tUp)*0.1;
448  }
449  }
450  if(chi2p>0) ATH_MSG_DEBUG(" Rejected weak topology Chi2 penalty " << chi2p);
451  bool oldrefit = DCSLFitter::fit( result, line, dcs_new, selection );
452  chi2p += result.chi2();
453 // add chi2 penalty for too large or too small driftTimes t < 0 or t> t upper
454  result.set( chi2p, result.ndof(), result.dtheta(), result.dy0() );
455  return oldrefit;
456  } // end rejection of weak topologies
457 
458  ATH_MSG_DEBUG("positive radii ML1 " << nml1p << " ML2 " << nml2p << " negative radii ML1 " << nml1n << " ML " << nml2n << " used hits " << used << " t0 Error " << t0Error);
459 
460  constexpr std::array<Double_t,3> step{0.01 , 0.01 , 0.1 };
461  // starting point
462  std::array<Double_t,3> variable{theta,d,0};
463  // if t0Seed value from outside use this
464  if(t0Seed > -999.) variable[2] = t0Seed;
465 
466  ROOT::Minuit2::Minuit2Minimizer minimum("algoName");
467  minimum.SetMaxFunctionCalls(10000);
468  minimum.SetTolerance(0.001);
469  minimum.SetPrintLevel(-1);
470  if(msgLvl(MSG::VERBOSE)) minimum.SetPrintLevel(1);
471 
472  if (m_floatDir){
473  minimum.SetVariable(0,"a",variable[0], step[0]);
474  minimum.SetVariable(1,"b",variable[1], step[1]);
475  } else {
476  minimum.SetFixedVariable(0,"a", variable[0]);
477  minimum.SetFixedVariable(1,"b", variable[1]);
478  }
479 
480  minimum.SetVariable(2,"t0",variable[2], step[2]);
481 
482  minimum.SetFunction(minFunct);
483 
484  // do the minimization
485  minimum.Minimize();
486 
487  const double *results = minimum.X();
488  const double *errors = minimum.Errors();
489  ATH_MSG_DEBUG("Minimum: f(" << results[0] << "+-" << errors[0] << "," << results[1]<< "+-" << errors[1]<< "," << results[2] << "+-" << errors[2]<< "): " << minimum.MinValue());
490 
492 
493  // Get the fit values
494  double aret=results[0];
495  double aErr=errors[0];
496  double dtheta = aErr;
497  double tana = std::tan(aret); // tangent of angle
498  double ang = aret; // between zero and pi
499  cosin = std::cos(ang);
500  sinus = std::sin(ang);
501  if ( sinus < 0.0 ) {
502  sinus = -sinus;
503  cosin = -cosin;
504  } else if ( sinus == 0.0 && cosin < 0.0 ) {
505  cosin = -cosin;
506  }
507  ang = std::atan2(sinus, cosin);
508  double b=results[1];
509  double bErr=errors[1];
510  double t0=results[2];
511  double t0Err=errors[2];
512  double dy0 = cosin * bErr - b * sinus * aErr;
513 
514  const double del_t = std::abs(hits[0].rt->radius((t0+t0Err)) - hits[0].rt->radius(t0)) ;
515 
516 
517  ATH_MSG_DEBUG("____________FINAL VALUES________________" );
518  ATH_MSG_DEBUG("Values: a "<<tana<<" d "<<b * cosin <<" t0 "<<t0);
519  ATH_MSG_DEBUG("Errors: a "<<aErr<<" b "<<dy0 <<" t0 "<<t0Err);
520 
521  d = b * cosin;
522  if(msg().level() <=MSG::DEBUG) {
523  msg() << MSG::DEBUG <<"COVAR ";
524  for(int it1=0; it1<3; it1++) {
525  for(int it2=0; it2<3; it2++) {
526  msg() << MSG::DEBUG <<minimum.CovMatrix(it1,it2)<<" ";
527  }
528  msg() << MSG::DEBUG << endmsg;
529  }
530  }
531 
532  result.dcs().clear();
533  result.clusters().clear();
534  result.emptyTubes().clear();
535 
536  ATH_MSG_DEBUG("after fit theta "<<ang<<" sinus "<<sinus<< " cosin "<< cosin);
537 
538  double chi2 = 0;
539  unsigned int nhits(0);
540 
541  // calculate predicted hit positions from track parameters
542 
543  ATH_MSG_DEBUG("------NEW HITS------");
544  int i{-1};
545  for(const HitCoords& coords : hits){
546  ++i;
547  const DCOnTrack& keep_me{dcs_keep[i]};
548  const double uppercut = coords.rt->tUpper();
549  const double lowercut = coords.rt->tLower();
550 
551  double rad = coords.rt->radius(coords.t-t0);
552  if(coords.t-t0<lowercut) rad = coords.rt->radius(lowercut);
553  if(coords.t-t0>uppercut) rad = coords.rt->radius(uppercut);
554  if (coords.w==0) {
555  ATH_MSG_WARNING("coords.w==0, continuing");
556  continue;
557  }
558  double drad = 1.0/std::sqrt(coords.w) ;
559 
560  double yl = (coords.y - tana*coords.z - b);
561 
562  ATH_MSG_DEBUG("i "<<i<<" ");
563 
564 
565  double dth = -(sinus*coords.y + cosin*coords.z)*dtheta;
566  double residuals = std::abs(yl)/std::sqrt(1+tana*tana) - rad;
567 
568  ATH_MSG_DEBUG(" dth "<<dth<<" dy0 "<<dy0<<" del_t "<<del_t);
569 
570 
571  double errorResiduals = std::hypot(dth, dy0, del_t);
572 
573  // derivatives of the residual 'R'
574  std::array<double,3> deriv{};
575  // del R/del theta
576  double dd = coords.z * sinus + b *cosin - coords.y * cosin;
577  deriv[0] = sign(dd) * (coords.z * cosin - b * sinus + coords.y * sinus);
578  // del R / del b
579  deriv[1] = sign(dd) * cosin ;
580  // del R / del t0
581 
582  deriv[2] = -1* coords.rt->driftVelocity(coords.t-t0);
583 
584  double covsq=0;
585  for(int rr=0; rr<3; rr++) {
586  for(int cc=0; cc<3; cc++) {
587  covsq += deriv[rr]*minimum.CovMatrix(rr,cc)* deriv[cc];
588  }
589  }
590  ATH_MSG_DEBUG(" covsquared " << covsq);
591  if( covsq < 0. && msgLvl(MSG::DEBUG)){
592  for(int rr=0; rr<3; rr++) {
593  for(int cc=0; cc<3; cc++) {
594  double dot = deriv[rr]*minimum.CovMatrix(rr,cc)* deriv[cc];
595  ATH_MSG_DEBUG(" adding term " << dot << " dev1 " << deriv[rr] << " cov " << minimum.CovMatrix(rr,cc) << " dev2 " << deriv[cc]);
596  }
597  }
598  }
599 
600  covsq = covsq > 0. ? std::sqrt(covsq) : 0.;
601  const DriftCircle* ds = & keep_me;
602  if (m_propagateErrors) drad = coords.dr;
603 
604  DriftCircle dc_newrad(keep_me.position(), rad, drad, ds->driftState(), keep_me.id(), ds->rot(), keep_me.index() );
605  DCOnTrack dc_new(dc_newrad, residuals, covsq);
606  dc_new.state(keep_me.state());
607 
608  ATH_MSG_DEBUG("T0 Segment hit res "<<residuals<<" eres "<<errorResiduals<<" covsq "<<covsq<<" ri " << coords.r<<" ro "<<rad<<" drad "<<drad << " sel "<<selection[i]<< " inv error " << coords.w);
609 
610  if(!coords.rejected) {
611  ++nhits;
612  if (!m_propagateErrors) {
613  chi2 += sq(residuals)*coords.w;
614  } else {
615  chi2 += sq(residuals)/sq(drad);
616  }
617  ATH_MSG_DEBUG("T0 Segment hit res "<<residuals<<" eres "<<errorResiduals<<" covsq "<<covsq<<" ri " << coords.r<<" radius after t0 "<<rad<<" radius error "<< drad << " original error " << coords.dr);
618 // Put chi2 penalty for drift times outside window
619  if (coords.t-t0> uppercut ) { // too large
620  chi2 += sq(coords.t-t0-uppercut)*0.1;
621  }else if (coords.t-t0 < lowercut ) {// too small
622  chi2 += sq(coords.t-t0-lowercut)*0.1;
623  }
624  }
625  result.dcs().push_back( dc_new );
626  }
627 
628  double oldshift = result.t0Shift();
629  ATH_MSG_DEBUG("end fit old "<<oldshift<< " new " <<t0);
630  // Final Minuit Fit result
631  if(nhits==NUMPAR) {
632  nhits++;
633  chi2 += 1.;
634  }
635  result.set( chi2, nhits-NUMPAR, dtheta, -1.*dy0 );
636  result.line().set( LocVec2D( Zc - sinus*d, Yc + cosin*d ), ang );
637  if(t0==0.) t0=0.00001;
638  result.setT0Shift(t0,t0Err);
639 
640  ATH_MSG_DEBUG("Minuit Fit complete: Chi2 " << chi2 << " angle " << result.line().phi() << " nhits "<< nhits << " t0result " << t0);
641  ATH_MSG_DEBUG("Minuit Fit complete: Chi2 " << chi2 << " angle " << result.line().phi() << " nhits "<<nhits<<" numpar "<<NUMPAR << " per dof " << chi2/(nhits-NUMPAR));
642  ATH_MSG_DEBUG("Fit complete: Chi2 " << chi2 <<" nhits "<<nhits<<" numpar "<<NUMPAR << " per dof " << chi2/(nhits-NUMPAR)<<(chi2/(nhits-NUMPAR) > 5 ? " NOT ":" ")<< "GOOD");
643  ATH_MSG_DEBUG("chi2 "<<chi2<<" per dof "<<chi2/(nhits-NUMPAR));
644 
645  return true;
646  }
647 
648 }
used
beamspotman.r
def r
Definition: beamspotman.py:676
MdtReadoutElement.h
TrkDriftCircleMath::MdtSegmentT0Fitter::m_ntotalCalls
std::atomic_uint m_ntotalCalls
Definition: MdtSegmentT0Fitter.h:54
checkxAOD.ds
ds
Definition: Tools/PyUtils/bin/checkxAOD.py:258
verify_menu_config.results
results
Definition: verify_menu_config.py:67
ATH_MSG_FATAL
#define ATH_MSG_FATAL(x)
Definition: AthMsgStreamMacros.h:34
checkFileSG.line
line
Definition: checkFileSG.py:75
TRTCalib_Extractor.hits
hits
Definition: TRTCalib_Extractor.py:35
get_generator_info.result
result
Definition: get_generator_info.py:21
TrkDriftCircleMath::DCOnTrackVec
std::vector< DCOnTrack > DCOnTrackVec
Definition: DCOnTrack.h:59
max
#define max(a, b)
Definition: cfImp.cxx:41
TrkDriftCircleMath::MdtSegmentT0Fitter::m_npassedNSelectedHits
std::atomic_uint m_npassedNSelectedHits
Definition: MdtSegmentT0Fitter.h:57
SG::ReadCondHandle
Definition: ReadCondHandle.h:44
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
TrkDriftCircleMath::DCSLFitter::fit
virtual bool fit(Segment &result, const Line &line, const DCOnTrackVec &dcs, double t0Seed=-99999.) const
Definition: Tracking/TrkUtilityPackages/TrkDriftCircleMath/TrkDriftCircleMath/DCSLFitter.h:38
TrkDriftCircleMath::MdtSegmentT0Fitter::m_npassedMinuitFit
std::atomic_uint m_npassedMinuitFit
Definition: MdtSegmentT0Fitter.h:59
hist_file_dump.d
d
Definition: hist_file_dump.py:137
m_data
std::vector< T > m_data
Definition: TrackTruthMatchingBaseAlg.cxx:660
TrkDriftCircleMath::MdtSegmentT0Fitter::m_dRTol
Gaudi::Property< float > m_dRTol
Definition: MdtSegmentT0Fitter.h:49
TrkDriftCircleMath::HitSelection
std::vector< bool > HitSelection
Definition: HitSelection.h:9
TrkDriftCircleMath::MdtSegmentT0Fitter::finalize
virtual StatusCode finalize() override
Definition: MdtSegmentT0Fitter.cxx:179
ALFA_EventTPCnv_Dict::t0
std::vector< ALFA_RawData_p1 > t0
Definition: ALFA_EventTPCnvDict.h:42
TrkDriftCircleMath::MdtSegmentT0Fitter::m_scaleErrors
Gaudi::Property< bool > m_scaleErrors
Definition: MdtSegmentT0Fitter.h:46
skel.it
it
Definition: skel.GENtoEVGEN.py:396
TrkDriftCircleMath::DCSLFitter
Definition: Tracking/TrkUtilityPackages/TrkDriftCircleMath/TrkDriftCircleMath/DCSLFitter.h:17
TrkDriftCircleMath
Function object to check whether two Segments are sub/super sets or different.
Definition: IMdtSegmentFinder.h:13
TrkDriftCircleMath::MdtSegmentT0Fitter::m_rejectWeakTopologies
Gaudi::Property< bool > m_rejectWeakTopologies
Definition: MdtSegmentT0Fitter.h:45
AthCommonMsg< AlgTool >::msgLvl
bool msgLvl(const MSG::Level lvl) const
Definition: AthCommonMsg.h:30
JetTiledMap::N
@ N
Definition: TiledEtaPhiMap.h:44
TrkDriftCircleMath::MdtSegmentT0Fitter::MdtSegmentT0Fitter
MdtSegmentT0Fitter(const std::string &, const std::string &, const IInterface *)
Definition: MdtSegmentT0Fitter.cxx:168
MdtPrepData.h
python.TurnDataReader.dr
dr
Definition: TurnDataReader.py:112
TrkDriftCircleMath::DriftCircle
This class represents a drift time measurement.
Definition: DriftCircle.h:22
TrkDriftCircleMath::DCOnTrack::state
void state(DCOnTrackState st)
set DCOnTrack state
Definition: DCOnTrack.h:47
read_hist_ntuple.t
t
Definition: read_hist_ntuple.py:5
drawFromPickle.cos
cos
Definition: drawFromPickle.py:36
MdtDriftCircleOnTrack.h
JetTiledMap::S
@ S
Definition: TiledEtaPhiMap.h:44
MuonCalib::MdtRtRelation
class which holds calibration constants per rt-region
Definition: MdtRtRelation.h:19
TrkDriftCircleMath::MdtSegmentT0Fitter::initialize
virtual StatusCode initialize() override
Definition: MdtSegmentT0Fitter.cxx:174
ReadCondHandle.h
Muon::MdtDriftCircleOnTrack::driftTime
double driftTime() const
Returns the value of the drift time used to obtain the drift radius.
Definition: MdtDriftCircleOnTrack.h:280
TrkDriftCircleMath::Segment
Definition: Tracking/TrkUtilityPackages/TrkDriftCircleMath/TrkDriftCircleMath/Segment.h:18
TrkDriftCircleMath::LocVec2D
Implementation of 2 dimensional vector class.
Definition: LocVec2D.h:16
python.iconfTool.models.loaders.level
level
Definition: loaders.py:20
TrkDriftCircleMath::Line
Definition: Line.h:17
Execution.tb
tb
Definition: Execution.py:15
TrkDriftCircleMath::MdtSegmentT0Fitter::m_npassedNHits
std::atomic_uint m_npassedNHits
Definition: MdtSegmentT0Fitter.h:55
TrkDriftCircleMath::MdtSegmentT0Fitter::m_minHits
Gaudi::Property< int > m_minHits
Definition: MdtSegmentT0Fitter.h:48
python.TriggerHandler.th
th
Definition: TriggerHandler.py:296
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
lumiFormat.i
int i
Definition: lumiFormat.py:85
z
#define z
MdtRtRelation.h
DetDescrDictionaryDict::it1
std::vector< HWIdentifier >::iterator it1
Definition: DetDescrDictionaryDict.h:17
endmsg
#define endmsg
Definition: AnalysisConfig_Ntuple.cxx:63
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
sq
#define sq(x)
Definition: CurvedSegmentFinder.cxx:6
TrkDriftCircleMath::MdtSegmentT0Fitter::m_npassedMinHits
std::atomic_uint m_npassedMinHits
Definition: MdtSegmentT0Fitter.h:58
chi2
double chi2(TH1 *h0, TH1 *h1)
Definition: comparitor.cxx:522
MdtIdHelper
Definition: MdtIdHelper.h:61
sign
int sign(int a)
Definition: TRT_StrawNeighbourSvc.h:107
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
python.selection.variable
variable
Definition: selection.py:33
drawFromPickle.tan
tan
Definition: drawFromPickle.py:36
MuonCalib::IRtRelation::tUpper
virtual double tUpper() const =0
Returns the upper time covered by the r-t.
Muon::MdtDriftCircleOnTrack::driftRadius
double driftRadius() const
Returns the value of the drift radius.
Definition: MdtDriftCircleOnTrack.h:277
xAOD::double
double
Definition: CompositeParticle_v1.cxx:159
IRtResolution.h
selection
std::string selection
Definition: fbtTestBasics.cxx:75
min
#define min(a, b)
Definition: cfImp.cxx:40
mergePhysValFiles.errors
list errors
Definition: DataQuality/DataQualityUtils/scripts/mergePhysValFiles.py:43
MdtSegmentT0Fitter.h
MuonCalib::IRtRelation::radius
virtual double radius(double t) const =0
returns drift radius for a given time
plotBeamSpotMon.b
b
Definition: plotBeamSpotMon.py:77
Muon::MdtDriftCircleOnTrack
This class represents the corrected MDT measurements, where the corrections include the effects of wi...
Definition: MdtDriftCircleOnTrack.h:37
SG::CondHandleKey::initialize
StatusCode initialize(bool used=true)
TrkDriftCircleMath::MdtSegmentT0Fitter::m_propagateErrors
Gaudi::Property< bool > m_propagateErrors
Definition: MdtSegmentT0Fitter.h:47
ParticleGun_SamplingFraction.radius
radius
Definition: ParticleGun_SamplingFraction.py:96
MuonDetectorManager.h
library_scraper.dd
list dd
Definition: library_scraper.py:46
JetVoronoiDiagramHelpers::coord
double coord
Definition: JetVoronoiDiagramHelpers.h:45
MuonCalib::IRtRelation::tLower
virtual double tLower() const =0
Returns the lower time covered by the r-t.
MuonCalib::MdtRtRelation::rt
const IRtRelation * rt() const
rt relation
Definition: MdtRtRelation.h:27
a
TList * a
Definition: liststreamerinfos.cxx:10
y
#define y
TrkDriftCircleMath::MdtSegmentT0Fitter::m_floatDir
Gaudi::Property< bool > m_floatDir
Definition: MdtSegmentT0Fitter.h:51
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
IRtRelation.h
Trk::RIO_OnTrack::identify
Identifier identify() const
return the identifier -extends MeasurementBase
Definition: RIO_OnTrack.h:152
DEBUG
#define DEBUG
Definition: page_access.h:11
AthCommonMsg< AlgTool >::msg
MsgStream & msg() const
Definition: AthCommonMsg.h:24
TrkDriftCircleMath::DCOnTrack
class representing a drift circle meaurement on segment
Definition: DCOnTrack.h:16
LArCellBinning.step
step
Definition: LArCellBinning.py:158
dot
Definition: dot.py:1
TrkDriftCircleMath::MdtSegmentT0Fitter::m_idHelperSvc
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
Definition: MdtSegmentT0Fitter.h:43
dqt_zlumi_alleff_HIST.tl
tl
Definition: dqt_zlumi_alleff_HIST.py:73
rr
const boost::regex rr(r_r)
python.Constants.VERBOSE
int VERBOSE
Definition: Control/AthenaCommon/python/Constants.py:14
drawFromPickle.sin
sin
Definition: drawFromPickle.py:36
TrkDriftCircleMath::MdtSegmentT0Fitter::m_npassedSelectionConsistency
std::atomic_uint m_npassedSelectionConsistency
Definition: MdtSegmentT0Fitter.h:56
AthAlgTool
Definition: AthAlgTool.h:26
python.IoTestsLib.w
def w
Definition: IoTestsLib.py:200
TrkDriftCircleMath::MdtSegmentT0Fitter::m_calibDbKey
SG::ReadCondHandleKey< MuonCalib::MdtCalibDataContainer > m_calibDbKey
Definition: MdtSegmentT0Fitter.h:40
TrkDriftCircleMath::MdtSegmentT0Fitter::fit
virtual bool fit(Segment &result, const Line &line, const DCOnTrackVec &dcs, double t0Seed) const override
Definition: MdtSegmentT0Fitter.h:63
MuonCalib::IRtRelation
generic interface for a rt-relation
Definition: IRtRelation.h:15
TSU::T
unsigned long long T
Definition: L1TopoDataTypes.h:35
python.SystemOfUnits.rad
int rad
Definition: SystemOfUnits.py:111
python.handimod.cc
int cc
Definition: handimod.py:523
Identifier
Definition: IdentifierFieldParser.cxx:14