193 {
197 const EventContext& ctx{Gaudi::Hive::currentContext()};
198 SG::ReadCondHandle<MuonCalib::MdtCalibDataContainer> calibData{
m_calibDbKey, ctx};
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 }
216
217 unsigned int N = dcs_keep.size();
218
219 result.setT0Shift(-99999,-99999);
220
221 if(N<2) {
222 return false;
223 }
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){
233 }
234 if(used < 2){
236 return false;
237 }
239
242
243
244
245
246
247
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 );
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
278
280
282 int iok = 0;
283 if(oldrefit) iok = 1;
285 return oldrefit;
286
287 }
288
290
291
293
294
295 ATH_MSG_DEBUG(
" in MdtSegmentT0Fitter::fit with N dcs "<< N <<
" hit selection size " <<
selection.size());
297
298
299 double Zc{0.}, Yc{0.},
S{0.}, Sz{0.}, Sy{0};
300
301 std::vector<HitCoords>
hits{};
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();
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.;
315 HitCoords& coords =
hits.back();
316 coords.dr = keep_me.dr();
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) {
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;
332 Yc = Sy*inv_S;
333
335
337 for(HitCoords& coords : hits) {
338 coords.y -= Yc;
340 }
341
342 int selcount{0};
343
344
345
346
347 double min_tlower{std::numeric_limits<float>::max()}, max_tupper{-std::numeric_limits<float>::max()};
348
349 double t0seed=0;
350 double st0 = 0;
351 double min_t0 = 1e10;
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;
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
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
395
396 double d =
line.y0() +
Zc*sinus-Yc*cosin;
397
398
403
404
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;
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
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
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.;
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) );
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);
453
455 return oldrefit;
456 }
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 , 2.0 };
461
463
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
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
485 const bool minuit_succedded = minimum.Minimize();
486 const int minuitStatus = minimum.Status();
487 if (!minuit_succedded || minuitStatus != 0) {
488 ATH_MSG_DEBUG(
"Minuit fit failed with status " << minuitStatus);
489 return false;
490 }
491
492 const double *
results = minimum.X();
493 const double *
errors = minimum.Errors();
494 ATH_MSG_DEBUG(
"Minimum: f(" << results[0] <<
"+-" << errors[0] <<
"," << results[1]<<
"+-" << errors[1]<<
"," << results[2] <<
"+-" << errors[2]<<
"): " << minimum.MinValue());
495
497
498
501 double dtheta = aErr;
502 double tana = std::tan(aret);
503 double ang = aret;
504 cosin = std::cos(ang);
505 sinus = std::sin(ang);
506 if ( sinus < 0.0 ) {
507 sinus = -sinus;
508 cosin = -cosin;
509 } else if ( sinus == 0.0 && cosin < 0.0 ) {
510 cosin = -cosin;
511 }
512 ang = std::atan2(sinus, cosin);
517 double dy0 = cosin * bErr -
b * sinus * aErr;
518
519 const double del_t = std::abs(hits[0].rt->radius((
t0+t0Err)) - hits[0].rt->radius(
t0)) ;
520
521
524 ATH_MSG_DEBUG(
"Errors: a "<<aErr<<
" b "<<dy0 <<
" t0 "<<t0Err);
525
528 msg() << MSG::DEBUG <<
"COVAR ";
529 for(int it1=0; it1<3; it1++) {
530 for(int it2=0; it2<3; it2++) {
531 msg() << MSG::DEBUG <<minimum.CovMatrix(it1,it2)<<
" ";
532 }
534 }
535 }
536
538 result.clusters().clear();
539 result.emptyTubes().clear();
540
541 ATH_MSG_DEBUG(
"after fit theta "<<ang<<
" sinus "<<sinus<<
" cosin "<< cosin);
542
544 unsigned int nhits(0);
545
546
547
550 for(const HitCoords& coords : hits){
552 const DCOnTrack& keep_me{dcs_keep[
i]};
553 const double uppercut = coords.rt->
tUpper();
554 const double lowercut = coords.rt->
tLower();
555
557 if(coords.t-
t0<lowercut)
rad = coords.rt->
radius(lowercut);
558 if(coords.t-
t0>uppercut)
rad = coords.rt->
radius(uppercut);
559 if (coords.w==0) {
561 continue;
562 }
563 double drad = 1.0/std::sqrt(coords.w) ;
564
565 double yl = (coords.y - tana*coords.z -
b);
566
568
569
570 double dth = -(sinus*coords.y + cosin*coords.z)*dtheta;
571 double residuals = std::abs(yl)/std::sqrt(1+tana*tana) -
rad;
572
574
575
576 double errorResiduals = std::hypot(dth, dy0, del_t);
577
578
579 std::array<double,3> deriv{};
580
581 double dd = coords.z * sinus +
b *cosin - coords.y * cosin;
582 deriv[0] =
sign(dd) * (coords.z * cosin -
b * sinus + coords.y * sinus);
583
584 deriv[1] =
sign(dd) * cosin ;
585
586
588
589 double covsq=0;
590 for(
int rr=0;
rr<3;
rr++) {
591 for(
int cc=0;
cc<3;
cc++) {
592 covsq += deriv[
rr]*minimum.CovMatrix(
rr,cc)* deriv[
cc];
593 }
594 }
596 if( covsq < 0. &&
msgLvl(MSG::DEBUG)){
597 for(
int rr=0;
rr<3;
rr++) {
598 for(
int cc=0;
cc<3;
cc++) {
599 double dot = deriv[
rr]*minimum.CovMatrix(
rr,cc)* deriv[
cc];
600 ATH_MSG_DEBUG(
" adding term " << dot <<
" dev1 " << deriv[
rr] <<
" cov " << minimum.CovMatrix(
rr,cc) <<
" dev2 " << deriv[cc]);
601 }
602 }
603 }
604
605 covsq = covsq > 0. ? std::sqrt(covsq) : 0.;
606 const DriftCircle*
ds = & keep_me;
608
609 DriftCircle dc_newrad(keep_me.position(), rad, drad,
ds->driftState(), keep_me.id(),
ds->rot(), keep_me.index() );
610 DCOnTrack dc_new(dc_newrad, residuals, covsq);
611 dc_new.state(keep_me.state());
612
613 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);
614
615 if(!coords.rejected) {
616 ++nhits;
618 chi2 +=
sq(residuals)*coords.w;
619 } else {
621 }
622 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);
623
624 if (coords.t-
t0> uppercut ) {
625 chi2 +=
sq(coords.t-
t0-uppercut)*0.1;
626 }
else if (coords.t-
t0 < lowercut ) {
627 chi2 +=
sq(coords.t-
t0-lowercut)*0.1;
628 }
629 }
630 result.dcs().push_back( dc_new );
631 }
632
633 double oldshift =
result.t0Shift();
635
636 if(nhits==NUMPAR) {
637 nhits++;
639 }
640 result.set(
chi2, nhits-NUMPAR, dtheta, -1.*dy0 );
641 result.line().set( LocVec2D( Zc - sinus*d, Yc + cosin*d ), ang );
642 if(
t0==0.)
t0=0.00001;
644
645 ATH_MSG_DEBUG(
"Minuit Fit complete: Chi2 " <<
chi2 <<
" angle " <<
result.line().phi() <<
" nhits "<< nhits <<
" t0result " <<
t0);
646 ATH_MSG_DEBUG(
"Minuit Fit complete: Chi2 " <<
chi2 <<
" angle " <<
result.line().phi() <<
" nhits "<<nhits<<
" numpar "<<NUMPAR <<
" per dof " <<
chi2/(nhits-NUMPAR));
647 ATH_MSG_DEBUG(
"Fit complete: Chi2 " <<
chi2 <<
" nhits "<<nhits<<
" numpar "<<NUMPAR <<
" per dof " <<
chi2/(nhits-NUMPAR)<<(
chi2/(nhits-NUMPAR) > 5 ?
" NOT ":
" ")<<
"GOOD");
649
650 return true;
651 }
const boost::regex rr(r_r)
Scalar theta() const
theta method
#define ATH_MSG_WARNING(x)
bool msgLvl(const MSG::Level lvl) const
int multilayer(const Identifier &id) const
Access to components of the ID.
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.
virtual double driftVelocity(double t) const =0
Returns the drift velocity for a given time.
const IRtRelation * rt() const
rt relation
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.
virtual bool fit(Segment &result, const Line &line, const DCOnTrackVec &dcs, double t0Seed=-99999.) const
Gaudi::Property< bool > m_rejectWeakTopologies
Gaudi::Property< bool > m_floatDir
Gaudi::Property< int > m_minHits
Gaudi::Property< bool > m_scaleErrors
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
Gaudi::Property< bool > m_propagateErrors
Gaudi::Property< float > m_dRTol
SG::ReadCondHandleKey< MuonCalib::MdtCalibDataContainer > m_calibDbKey
Identifier identify() const
return the identifier -extends MeasurementBase
double chi2(TH1 *h0, TH1 *h1)
const std::string selection
@ Zc
Z -> cc, nC = 1 (partial containment).
std::vector< DCOnTrack > DCOnTrackVec
dot(G, fn, nodesToHighlight=[])