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