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 "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
28namespace {
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
166namespace 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
175 ATH_CHECK(m_calibDbKey.initialize());
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 {
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 }
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}
const boost::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)
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