ATLAS Offline Software
Loading...
Searching...
No Matches
TRT_ToT_dEdx.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
5#include "TRT_ToT_dEdx.h"
7
8#include "GaudiKernel/MsgStream.h"
9#include "GaudiKernel/IToolSvc.h"
10
13
14#include "TrkSurfaces/Surface.h"
15
16#include "GaudiKernel/IChronoStatSvc.h"
17
18#include "TF1.h"
19
23#include <cmath>
24#include <limits>
25
26namespace{
27 bool
28 inRange(const double val, const double lo, const double hi){
29 return (val>lo) and (val<hi);
30 }
31}
32
33// constructor
34TRT_ToT_dEdx::TRT_ToT_dEdx(const std::string& t, const std::string& n, const IInterface* p) : AthAlgTool(t,n,p)
35{
36 declareInterface<ITRT_ToT_dEdx>(this);
37}
38
39
40// destructor
42
43
44
45// initialize
47{
48
49 MsgStream log(msgSvc(), name());
50
51 // retrieve TRT-ID helper
52
53 StatusCode sc = detStore()->retrieve(m_trtId, "TRT_ID");
54 if (sc.isFailure()){
55 ATH_MSG_ERROR ( "Could not get TRT_ID helper !" );
56 return StatusCode::FAILURE;
57 }
58
59 // Initialize ReadHandleKey and ReadCondHandleKey
60 ATH_CHECK(m_rdhkEvtInfo.initialize());
61 ATH_CHECK(m_ReadKey.initialize());
62 ATH_CHECK(m_assoTool.retrieve());
63 ATH_CHECK( m_localOccTool.retrieve() );
65
68 ATH_MSG_ERROR("Property TRT_dEdx_useTrackPartWithGasType has an invalid "
69 << "value: " << m_useTrackPartWithGasType);
70 return StatusCode::FAILURE;
71 }
72
73 return StatusCode::SUCCESS;
74}
75
76bool
77TRT_ToT_dEdx::isGoodHit(const EventContext& ctx,
78 const Trk::TrackStateOnSurface* trackState,
79 bool useHitsHT,
80 double& length) const
81{
82 const Trk::MeasurementBase* trkM = trackState->measurementOnTrack();
83 if (!trkM) {
84 return false;
85 }
86
87 // Check if this is RIO on track
88 // and if yes check if is TRT Drift Circle
89 // then set the ptr
90 const InDet::TRT_DriftCircleOnTrack* driftcircle = nullptr;
92 const Trk::RIO_OnTrack* tmpRio = static_cast<const Trk::RIO_OnTrack*>(trkM);
94 driftcircle = static_cast<const InDet::TRT_DriftCircleOnTrack*>(tmpRio);
95 }
96 }
97
98 if (!driftcircle) {
99 return false;
100 }
101
102 const Trk::TrackParameters* trkP = trackState->trackParameters();
103 if(trkP==nullptr)return false;
104
105 double Trt_Rtrack = std::abs(trkP->parameters()[Trk::locR]);
106 double Trt_RHit = std::abs(driftcircle->localParameters()[Trk::driftRadius]);
107 double error = std::sqrt(driftcircle->localCovariance()(Trk::driftRadius,Trk::driftRadius));
108
109 if (trackState->type(Trk::TrackStateOnSurface::Outlier)) return false; //Outliers
110 if (m_useZeroRHitCut && Trt_RHit==0 && error>1.) return false; //Select precision hits only
111 if ((Trt_Rtrack >= m_trackConfig_maxRtrack) || (Trt_Rtrack <= m_trackConfig_minRtrack)) return false; // drift radius close to wire or wall
112
114
115 if (m_divideByL and length < 1.7) return false; // Length in the straw
116
117 if (!useHitsHT) {
118 int TrtHl = driftcircle->highLevel();
119 if (TrtHl==1) return false;
120 }
121
122 if (m_useTrackPartWithGasType != kUnset) { // don't preselect hits
123 if(m_useTrackPartWithGasType != gasTypeInStraw(ctx,trackState)) return false;
124 }
125
126 if (driftcircle->prepRawData()->timeOverThreshold()==0.) return false; // If ToT for this hit equal 0, skip it.
127
128 return true;
129}
130
131double
132TRT_ToT_dEdx::dEdx(const EventContext& ctx,
133 const Trk::Track* track,
134 bool useHitsHT,
135 std::optional<float> localOccupancy) const
136{
137 ATH_MSG_DEBUG("dEdx()");
138
139 double nVtx=-1.;
140 // Event information
142 if(!eventInfoDecor.isPresent()) {
143 REPORT_MESSAGE(MSG::FATAL) << "EventInfo decoration not available!";
144 return 0;
145 }
146
147 // Average interactions per crossing for the current BCID
148 // TODO: we should really not hard-code a mu to nVtx conversion
149 double mu = eventInfoDecor(0);
150 if(m_isData) {
151 nVtx = 1.3129 + 0.716194*mu + (-0.00475074)*mu*mu;
152 }
153 else {
154 nVtx = 1.0897 + 0.748287*mu + (-0.00421788)*mu*mu;
155 }
156
157 if (!track) {
158 return 0;
159 }
160 const Trk::TrackStates* vtsos = track->trackStateOnSurfaces();
161 if (!vtsos) {
162 return 0;
163 }
164
165 EGasType gasType;
168 size_t vtos_size = vtsos->size();
169 double correctionFactor = 1.;
170
172 std::vector<double> vecToT;
173 vecToT.reserve(vtos_size);
174 double ToTsum = 0;
175
176 for ( ; itr!=itre ; ++itr) {
177 double length = 0;
178 if ( isGoodHit(ctx,(*itr), useHitsHT, length)) {
179 double ToT_correct = correctToT_corrRZ(ctx,*itr, length);
181 correctionFactor = hitOccupancyCorrection(ctx,*itr);
182 ToT_correct*=correctionFactor;
183 }
184 vecToT.push_back(ToT_correct);
185 }
186 }
187
188 sort(vecToT.begin(), vecToT.end());
189 size_t nhits = vecToT.size();
190
191 if (m_divideByL) {
192 nhits-=m_nTrunkateHits;
193 }
194
195 // Boost speed
196 if (nhits<1) return 0.0;
197
198 ToTsum = std::accumulate(vecToT.begin(), vecToT.end(), 0);
200 correctionFactor=trackOccupancyCorrection(ctx,track, useHitsHT,localOccupancy);
201 } else {
202 correctionFactor=correctNormalization(ctx,nVtx);
203 }
204 ToTsum*=correctionFactor;
205 return ToTsum/nhits;
206 }
207
209 std::vector<double> vecToT_Xe;
210 vecToT_Xe.reserve(vtos_size/2);
211 std::vector<double> vecToT_Ar;
212 vecToT_Ar.reserve(vtos_size/2);
213 std::vector<double> vecToT_Kr;
214
217 "dEdX_Estimator():: Using m_toolScenario="
218 << m_toolScenario << " scenario m_useTrackPartWithGasType is set to"
220 << ", but kUnset is requiered. Check you tool configuration.");
221 }
222
223 for ( ; itr!=itre ; ++itr) {
224 double length=0;
225 if (isGoodHit(ctx,(*itr), useHitsHT, length)) {
226 gasType=gasTypeInStraw(ctx,*itr);
227 double ToT_correct = correctToT_corrRZ(ctx,*itr, length);
229 correctionFactor = hitOccupancyCorrection(ctx,*itr);
230 }
231 ToT_correct*=correctionFactor;
232 if(gasType==kXenon) {
233 vecToT_Xe.push_back(ToT_correct);
234 } else if (gasType==kArgon) {
235 vecToT_Ar.push_back(ToT_correct);
236 } else if (gasType==kKrypton) {
237 vecToT_Kr.push_back(ToT_correct);
238 } else {
239 ATH_MSG_ERROR("dEdX_Estimator():: During scenario kAlgReweight variable gasTypeInStraw got value kUnset.");
240 }
241 }
242 }
243
244 sort(vecToT_Xe.begin(), vecToT_Xe.end());
245 sort(vecToT_Ar.begin(), vecToT_Ar.end());
246 sort(vecToT_Kr.begin(), vecToT_Kr.end());
247
248 size_t nhitsXe = vecToT_Xe.size();
249 size_t nhitsAr = vecToT_Ar.size();
250 size_t nhitsKr = vecToT_Kr.size();
251
252 if (m_divideByL) {
254 if (nhitsXe>=m_nTrunkateHits) nhitsXe-=m_nTrunkateHits;
255 if (nhitsAr>=m_nTrunkateHits) nhitsAr-=m_nTrunkateHits;
256 if (nhitsKr>=m_nTrunkateHits) nhitsKr-=m_nTrunkateHits;
257 } else {// kAlgReweightTrunkOne
258 int trunkGas = kUnset;
259 double maxToT = 0.;
260 if (nhitsXe>0 && vecToT_Xe.at(nhitsXe-1)>maxToT) {
261 trunkGas = kXenon;
262 maxToT = vecToT_Xe.at(nhitsXe-1);
263 }
264 if(nhitsAr>0 && vecToT_Ar.at(nhitsAr-1)>maxToT){
265 trunkGas = kArgon;
266 maxToT = vecToT_Ar.at(nhitsAr-1);
267 }
268 if (nhitsKr>0 && vecToT_Kr.at(nhitsKr-1)>maxToT) {
269 trunkGas = kKrypton;
270 }
271
272 if (trunkGas==kXenon) {
273 nhitsXe-=m_nTrunkateHits;
274 } else if (trunkGas==kArgon) {
275 nhitsAr-=m_nTrunkateHits;
276 } else if (trunkGas==kKrypton) {
277 nhitsKr-=m_nTrunkateHits;
278 }
279 }
280 }
281
282 size_t nhits = nhitsXe + nhitsAr + nhitsKr;
283 if(nhits<1) return 0.0;
284
285 double ToTsumXe = 0;
286 double ToTsumAr = 0;
287 double ToTsumKr = 0;
288 for (size_t i = 0; i < nhitsXe;i++) {
289 ToTsumXe+=vecToT_Xe[i];
290 }
291 for (size_t i = 0; i < nhitsAr;i++) {
292 ToTsumAr+=vecToT_Ar[i];
293 }
294 for (size_t i = 0; i < nhitsKr;i++) {
295 ToTsumKr+=vecToT_Kr[i];
296 }
297
298 ToTsumXe = (nhitsXe>0) ? ToTsumXe/nhitsXe : 0;
299 ToTsumAr = (nhitsAr>0) ? ToTsumAr/nhitsAr : 0;
300 ToTsumKr = (nhitsKr>0) ? ToTsumKr/nhitsKr : 0;
301 double ToTsum = ToTsumXe*nhitsXe + ToTsumAr*nhitsAr + ToTsumKr*nhitsKr;
302
304 correctionFactor =
305 trackOccupancyCorrection(ctx, track, true, localOccupancy);
306 } else {
307 correctionFactor = correctNormalization(ctx, nVtx);
308 }
309 ToTsum *= correctionFactor;
310
311 return ToTsum/nhits;
312 }
313
314 ATH_MSG_ERROR("dEdX_Estimator():: m_toolScenario has wrong value "<<m_toolScenario<<"");
315 return 0.;
316}
317
318double
319TRT_ToT_dEdx::usedHits(const EventContext& ctx,
320 const Trk::Track* track,
321 bool useHitsHT) const
322{
323 ATH_MSG_DEBUG("usedHits()");
324 EGasType gasType = kUnset;
325
326 if (!track) {
327 return 0;
328 }
329 const Trk::TrackStates* vtsos = track->trackStateOnSurfaces();
330 if (!vtsos) {
331 return 0;
332 }
333
336
338 int nhits =0;
339
340 for ( ; itr!=itre ; ++itr) {
341 double length=0;
342 if (isGoodHit(ctx,(*itr), useHitsHT, length)) {
343 nhits++;
344 }
345 }
346 if (m_divideByL) nhits -= m_nTrunkateHits;
347 return nhits;
349 int nhits = 0;
350 int nhitsXe = 0;
351 int nhitsAr = 0;
352 int nhitsKr = 0;
353
356 "usedHits_Estimator():: Using m_toolScenario="
357 << m_toolScenario << " scenario m_useTrackPartWithGasType is set to "
359 << ", but kUnset is required. Check you tool configuration.");
360 }
361
362 for ( ; itr!=itre ; ++itr) {
363 double length=0;
364 if ( isGoodHit(ctx,(*itr), useHitsHT, length)) {
365 gasType=gasTypeInStraw(ctx,*itr);
366 if (gasType==kXenon) {
367 nhitsXe++;
368 } else if (gasType==kArgon) {
369 nhitsAr++;
370 } else if (gasType==kKrypton) {
371 nhitsKr++;
372 } else {
373 ATH_MSG_ERROR("usedHits_Estimator():: During scenario kAlgReweight variable gasTypeInStraw got value kUnset.");
374 }
375 }
376 }
377
378 if (m_divideByL) {
380 if(nhitsXe>0) nhitsXe -= m_nTrunkateHits;
381 if(nhitsAr>0) nhitsAr -= m_nTrunkateHits;
382 if(nhitsKr>0) nhitsKr -= m_nTrunkateHits;
383 } else { // kAlgReweightTrunkOne
384 if(nhitsXe>0 || nhitsAr>0 || nhitsKr>0)
385 nhitsXe -= m_nTrunkateHits;
386 }
387 }
388
389 nhits = nhitsXe + nhitsAr + nhitsKr;
390 return nhits;
391 }
392
393 ATH_MSG_ERROR("usedHits_Estimator():: m_toolScenario has wrong value "<<m_toolScenario<<"");
394 return 0;
395}
396
397double
398TRT_ToT_dEdx::getProb(const EventContext& ctx,
399 const Trk::TrackStateOnSurface* itr,
400 const double dEdx_obs,
401 const double pTrk,
402 Trk::ParticleHypothesis hypothesis,
403 int nUsedHits) const
404{
405 EGasType gasType = gasTypeInStraw(ctx, itr);
406 return getProb(ctx,gasType, dEdx_obs, pTrk, hypothesis, nUsedHits);
407}
408
409double
410TRT_ToT_dEdx::getProb(const EventContext& ctx,
411 EGasType gasType,
412 const double dEdx_obs,
413 const double pTrk,
414 Trk::ParticleHypothesis hypothesis,
415 int nUsedHits) const
416{
417 ATH_MSG_DEBUG("getProb():: gasTypeInStraw = "<<gasType<<"");
418
420 const TRTDedxcorrection* dEdxCorrection{*readHandle};
421 if (dEdxCorrection==nullptr) {
422 ATH_MSG_ERROR(" getProb: Could not find any dEdxCorrection in CondStore. Return zero.");
423 return 0;
424 }
425
426 if(gasType==kUnset) {
427 ATH_MSG_DEBUG("getProb():: gasTypeInStraw set kUnset that is not allowed! Use gasTypeInStraw(*itr) to get gas type info for that hit first!");
428 ATH_MSG_DEBUG("getProb():: Now gasTypeInStraw sets to kXenon.");
429 gasType = kXenon;
430 }
431
432 double dEdx_pred = predictdEdx(ctx,gasType, pTrk, hypothesis);
433 if (dEdx_pred==0) return 0.0;
434 if (hypothesis==Trk::electron) {
435 // correction for pTrk in [MeV]
436 double factor = 1;
437 double correct = 1+factor*(0.045*log10(pTrk)+0.885-1);
438 dEdx_pred= dEdx_pred/correct;
439 }
440
441 double Resolution =
442 dEdxCorrection->resolution[gasType][0] +
443 dEdxCorrection->resolution[gasType][1] * (nUsedHits + 0.5) +
444 dEdxCorrection->resolution[gasType][2] * (nUsedHits + 0.5) *
445 (nUsedHits + 0.5) +
446 dEdxCorrection->resolution[gasType][3] * (nUsedHits + 0.5) *
447 (nUsedHits + 0.5) * (nUsedHits + 0.5);
448 if (hypothesis == Trk::electron) {
449 Resolution =
450 dEdxCorrection->resolutionElectron[gasType][0] +
451 dEdxCorrection->resolutionElectron[gasType][1] * (nUsedHits + 0.5) +
452 dEdxCorrection->resolutionElectron[gasType][2] * (nUsedHits + 0.5) *
453 (nUsedHits + 0.5) +
454 dEdxCorrection->resolutionElectron[gasType][3] * (nUsedHits + 0.5) *
455 (nUsedHits + 0.5) * (nUsedHits + 0.5);
456 }
457
458 double prob = std::exp( -0.5 * ( ( ( dEdx_obs - dEdx_pred ) / (Resolution*dEdx_pred) ) *
459 ( ( dEdx_obs - dEdx_pred ) / (Resolution*dEdx_pred) ) )) ;
460
461 ATH_MSG_DEBUG("getProb():: return "<<prob<<"");
462 return prob;
463}
464
465double
466TRT_ToT_dEdx::getTest(const EventContext& ctx,
467 const double dEdx_obs,
468 const double pTrk,
469 Trk::ParticleHypothesis hypothesis,
470 Trk::ParticleHypothesis antihypothesis,
471 int nUsedHits) const
472{
473 ATH_MSG_DEBUG("getTest()");
474
475 EGasType gasType = kUnset;
476 if ( dEdx_obs<=0. || pTrk<=0. || nUsedHits<=0 ) return 0.5;
477
478 double Pone = getProb(ctx,gasType, dEdx_obs,pTrk,hypothesis,nUsedHits);
479 double Ptwo = getProb(ctx,gasType, dEdx_obs,pTrk,antihypothesis,nUsedHits);
480 if ((Pone+Ptwo) != 0) {
481 ATH_MSG_DEBUG("getTest():: return "<<Pone/(Pone+Ptwo)<<"");
482 return Pone/(Pone+Ptwo);
483 } else {
484 return 0.5;
485 }
486}
487
488double
489TRT_ToT_dEdx::predictdEdx(const EventContext& ctx,
490 const Trk::TrackStateOnSurface* itr,
491 const double pTrk,
492 Trk::ParticleHypothesis hypothesis) const
493{
494 EGasType gasType = gasTypeInStraw(ctx, itr);
495 return predictdEdx(ctx,gasType, pTrk, hypothesis);
496}
497
498double
499TRT_ToT_dEdx::predictdEdx(const EventContext& ctx,
500 EGasType gasType,
501 const double pTrk,
502 Trk::ParticleHypothesis hypothesis) const
503{
504 ATH_MSG_DEBUG("predictdEdx(): gasTypeInStraw = " << gasType << "");
505
507 const TRTDedxcorrection* dEdxCorrection{ *readHandle };
508 if (dEdxCorrection == nullptr) {
509 ATH_MSG_ERROR(" predictdEdx: Could not find any dEdxCorrection in "
510 "CondStore. Return zero.");
511 return 0;
512 }
513
514 if (gasType == kUnset) {
516 "predictdEdx():: gasTypeInStraw set kUnset that is not allowed! Use "
517 "gasTypeInStraw(*itr) to get gas type info for that hit first!");
518 ATH_MSG_DEBUG("predictdEdx():: Now gasTypeInStraw sets to kXenon.");
519 gasType = kXenon;
520 }
521
522 double mass = Trk::ParticleMasses::mass[hypothesis];
523
524 double betaGamma = pTrk/mass;
526 // low momentum particle can create floating point error
527 // do we need the check in the log parameter in addition? will create CPU increase
528 // do we want to throw an assertion here?
529 if (pTrk < 100)
530 return 0;
531 if (m_divideByL) {
532 if (dEdxCorrection->paraDivideByLengthDedxP3[gasType] +
533 1. / (std::pow(betaGamma,
534 dEdxCorrection->paraDivideByLengthDedxP5[gasType])) <=
535 0)
536 return 0;
537 return dEdxCorrection->paraDivideByLengthDedxP1[gasType] /
538 std::pow(std::sqrt((betaGamma * betaGamma) /
539 (1. + (betaGamma * betaGamma))),
540 dEdxCorrection->paraDivideByLengthDedxP4[gasType]) *
541 (dEdxCorrection->paraDivideByLengthDedxP2[gasType] -
542 std::pow(std::sqrt((betaGamma * betaGamma) /
543 (1. + (betaGamma * betaGamma))),
544 dEdxCorrection->paraDivideByLengthDedxP4[gasType]) -
545 log(dEdxCorrection->paraDivideByLengthDedxP3[gasType] +
546 1. / (std::pow(
547 betaGamma,
548 dEdxCorrection->paraDivideByLengthDedxP5[gasType]))));
549 }
550 if (dEdxCorrection->paraDedxP3[gasType] +
551 1. / (std::pow(betaGamma, dEdxCorrection->paraDedxP5[gasType])) <=
552 0)
553 return 0;
554 return dEdxCorrection->paraDedxP1[gasType] /
555 std::pow(
556 std::sqrt((betaGamma * betaGamma) / (1. + (betaGamma * betaGamma))),
557 dEdxCorrection->paraDedxP4[gasType]) *
558 (dEdxCorrection->paraDedxP2[gasType] -
559 std::pow(
560 std::sqrt((betaGamma * betaGamma) / (1. + (betaGamma * betaGamma))),
561 dEdxCorrection->paraDedxP4[gasType]) -
562 log(dEdxCorrection->paraDedxP3[gasType] +
563 1. / (std::pow(betaGamma, dEdxCorrection->paraDedxP5[gasType]))));
564
565 //return 0;
566}
567
568double
569TRT_ToT_dEdx::mass(const EventContext& ctx,
570 const Trk::TrackStateOnSurface* itr,
571 const double pTrk,
572 double dEdx) const
573{
574 EGasType gasType = gasTypeInStraw(ctx,itr);
575
576 ATH_MSG_DEBUG("mass(): gasTypeInStraw = "<<gasType<<"");
577
579 const TRTDedxcorrection* dEdxCorrection{*readHandle};
580 if(dEdxCorrection==nullptr)
581 {
582 ATH_MSG_ERROR(" mass: Could not find any dEdxCorrection in CondStore. Return zero.");
583 return 0;
584 }
585
586 if(gasType==kUnset)
587 {
588 ATH_MSG_WARNING("mass():: gasTypeInStraw set kUnset that is not allowed! Use gasTypeInStraw(*itr) to get gas type info for that hit first!");
589 ATH_MSG_WARNING("mass():: Now gasTypeInStraw sets to kXenon.");
590 gasType = kXenon;
591 }
592 // only for testing purposes!!!!
593 // note that dE/dx has to be corrected on track level first before value can be transferred to mass
594 // this has to be tuned on user level
596 static const double bg_min = 0.001;
597 static const double bg_max = 3; // maximal allowed bg
598
599 static const std::string blumRolandiFunction =
600 "( [0]/sqrt( (x*x/([5]*[5]))/(1.+(x*x/([5]*[5]))) )^[3] ) * ([1] - sqrt( "
601 "(x*x/([5]*[5]))/(1.+(x*x/([5]*[5]))) )^[3] - log([2]+1./((x/[5])^[4]) ) )";
602
603 TF1 blumRolandi( "BR", blumRolandiFunction.c_str(), 0.7, 100000);
604
605 blumRolandi.SetParameters(dEdxCorrection->paraDedxP1[gasType],
606 dEdxCorrection->paraDedxP2[gasType],
607 dEdxCorrection->paraDedxP3[gasType],
608 dEdxCorrection->paraDedxP4[gasType],
609 dEdxCorrection->paraDedxP5[gasType],
610 1.);
611 //blumRolandi.SetParameters(&dEdxCorrection->para_dEdx_BB);
612 double betaGamma = blumRolandi.GetX(dEdx, bg_min, bg_max);
613
614 ATH_MSG_DEBUG("mass():: return "<<pTrk/betaGamma<<"");
615
616 return pTrk/betaGamma;
617}
618
619/* returns gas type for given straw */
620// TODO: move this functionality to TRT_StrawStatusSummaryTool.
622 const Trk::TrackStateOnSurface *itr) const
623{
624 const Trk::MeasurementBase* trkM = itr->measurementOnTrack();
625 if (!trkM) {
626 return kUnset;
627 }
628
629 // Check if this is RIO on track
630 //annd if yes check if is TRT Drift Circle
631 //then set the ptr
632 const InDet::TRT_DriftCircleOnTrack* driftcircle = nullptr;
634 const Trk::RIO_OnTrack* tmpRio = static_cast<const Trk::RIO_OnTrack*>(trkM);
636 driftcircle = static_cast<const InDet::TRT_DriftCircleOnTrack*>(tmpRio);
637 }
638 }
639
640 if (!driftcircle) {
641 return kUnset;
642 }
643
644 return gasTypeInStraw(ctx,driftcircle);
645}
646
649 const EventContext& ctx,
650 const InDet::TRT_DriftCircleOnTrack* driftcircle) const
651{
652 Identifier DCid = driftcircle->identify();
653
654 // getStatusHT returns enum {Undefined, Dead, Good, Xenon, Argon, Krypton, EmulatedArgon, EmulatedKrypton}.
655 // Our representation of 'GasType' is 0:Xenon, 1:Argon, 2:Krypton
656 EGasType GasType=kUnset; // kUnset is default
657 if (!m_TRTStrawSummaryTool.empty()) {
658 int stat = m_TRTStrawSummaryTool->getStatusHT(DCid,ctx);
659 if ( stat==2 || stat==3 ) { GasType = kXenon; } // Xe
660 else if ( stat==1 || stat==4 ) { GasType = kArgon; } // Ar
661 else if ( stat==5 ) { GasType = kKrypton; } // Kr
662 else if ( stat==6 ) { GasType = kArgon; } // Emulated Ar
663 else if ( stat==7 ) { GasType = kKrypton;
664 } // Emulated Kr
665 else {
667 "getStatusHT = "
668 << stat
669 << ", must be 'Good(2)||Xenon(3)' or 'Dead(1)||Argon(4)' or "
670 "'Krypton(5)' or 'EmulatedArgon(6)' or 'EmulatedKr(7)'!");
671 throw std::exception();
672 }
673 }
674
675 return GasType;
676}
677
679// Corrections
681
682double
683TRT_ToT_dEdx::correctNormalization(const EventContext& ctx, double nVtx) const
684{
686 const TRTDedxcorrection* dEdxCorrection{*readHandle};
687 if(dEdxCorrection==nullptr) {
688 ATH_MSG_ERROR(" correctNormalization: Could not find any dEdxCorrection in CondStore. Return zero.");
689 return 0;
690 }
691
692 EGasType gasType = static_cast<EGasType> (m_useTrackPartWithGasType.value());
694 if (nVtx<=0) nVtx=dEdxCorrection->normNzero[gasType];
695 double slope = dEdxCorrection->normSlopeTot[gasType];
696 double offset = dEdxCorrection->normOffsetTot[gasType];
697 if (m_divideByL){
698 slope = dEdxCorrection->normSlopeTotDivideByLength[gasType];
699 offset = dEdxCorrection->normOffsetTotDivideByLength[gasType];
700 }
701 double shift = dEdxCorrection->normOffsetData[gasType];
702 if(!m_isData)shift = 0;
703 return (slope*dEdxCorrection->normNzero[gasType]+offset)/(slope*nVtx+offset+shift);
704}
705
706double
707TRT_ToT_dEdx::correctToT_corrRZ(const EventContext& ctx,
708 const Trk::TrackStateOnSurface* itr,
709 double length) const
710{
711 const Trk::MeasurementBase* trkM = itr->measurementOnTrack();
712 const Trk::TrackParameters* trkP = itr->trackParameters();
713
714 // Check if this is RIO on track
715 // annd if yes check if is TRT Drift Circle
716 // then set the ptr
717 const InDet::TRT_DriftCircleOnTrack* driftcircle = nullptr;
718 if (trkM && trkM->type(Trk::MeasurementBaseType::RIO_OnTrack)) {
719 const Trk::RIO_OnTrack* tmpRio = static_cast<const Trk::RIO_OnTrack*>(trkM);
721 driftcircle = static_cast<const InDet::TRT_DriftCircleOnTrack*>(tmpRio);
722 }
723 }
724
725 if (!driftcircle) {
726 return 0;
727 }
728 if (driftcircle->prepRawData()==nullptr) {
729 return 0;
730 }
731
732 Identifier DCId = driftcircle->identify();
733 double timeOverThreshold = driftcircle->prepRawData()->timeOverThreshold();
734 if(timeOverThreshold==0) {
735 ATH_MSG_WARNING("correctToT_corrRZ(const Trk::TrackStateOnSurface *itr):: ToT="<<timeOverThreshold<<". We must cut that hit in isGoodHit() !");
736 return 0;
737 }
738 int hitPart = m_trtId->barrel_ec(DCId);
739 int StrawLayer = m_trtId->straw_layer(DCId);
740 int Layer = m_trtId->layer_or_wheel(DCId);
741 double hitRtrack = std::abs(trkP->parameters()[Trk::locR]);
742 EGasType gasType = gasTypeInStraw(ctx,itr);
743 if(gasType==kUnset) {
744 ATH_MSG_ERROR("correctToT_corrRZ(const Trk::TrackStateOnSurface *itr):: Gas type in straw is kUnset! Return ToT = 0");
745 return 0;
746 }
747
749 if(!m_corrected) return timeOverThreshold;
750 /* else correct */
751
752 double hitZ = driftcircle->globalPosition().z();
753 double trackx = driftcircle->globalPosition().x();
754 double tracky = driftcircle->globalPosition().y();
755 double hitPosR = std::sqrt(trackx*trackx+tracky*tracky);
756
759 double ToTmip = 1;
760 double valToT = 0;
761 if(m_divideByL){
762 if (abs(hitPart)==1) // Barrel
763 valToT = fitFuncBarrel_corrRZL(ctx,gasType, hitRtrack, hitZ, Layer, StrawLayer);
764 else // End-cap
765 valToT = fitFuncEndcap_corrRZL(ctx,gasType, hitRtrack, hitPosR, Layer, hitZ>0?1:(hitZ<0?-1:0));
766 }else{
767 if (abs(hitPart)==1) // Barrel
768 valToT = fitFuncBarrel_corrRZ(ctx,gasType, hitRtrack, hitZ, Layer, StrawLayer);
769 else // End-cap
770 valToT = fitFuncEndcap_corrRZ(ctx,gasType, hitRtrack, hitPosR, Layer, hitZ>0?1:(hitZ<0?-1:0));
771 }
772 if (std::isinf(valToT)) return 0.;
773 if (valToT!=0) return ToTmip*timeOverThreshold/valToT;
774 return 0.;
775}
776
777double
779 EGasType gasType,
780 double driftRadius,
781 double zPosition,
782 int Layer,
783 int StrawLayer) const
784{
785 if (Layer == 0 && StrawLayer < 9) {
786 return fitFuncBarrelShort_corrRZ(ctx,gasType, driftRadius, zPosition, StrawLayer);
787 }
788 return fitFuncBarrelLong_corrRZ(ctx,gasType, driftRadius, zPosition, Layer, StrawLayer);
789}
790
791double
793 EGasType gasType,
794 double driftRadius,
795 double radialPosition,
796 int Layer,
797 int sign) const
798{
802 double T0 = fitFuncPol_corrRZ(ctx,gasType, 0,driftRadius,Layer,0,sign,2);
803 double a = fitFuncPol_corrRZ(ctx,gasType, 1,driftRadius,Layer,0,sign,2);
804 return T0+a*radialPosition;
805}
806
807double
809 EGasType gasType,
810 double driftRadius,
811 double zPosition,
812 int Layer,
813 int StrawLayer) const
814{
820 double z = std::abs(zPosition);
821 int sign=1;
822 if(zPosition<0)sign=-1;
823 double l = 704.6;
824 // define set of parameters for negative and positive z positions
825 double T0 = fitFuncPol_corrRZ(ctx,gasType, 0,driftRadius,Layer,StrawLayer,sign,0);
826 double v = fitFuncPol_corrRZ(ctx,gasType, 1,driftRadius,Layer,StrawLayer,sign,0);
827 double s = fitFuncPol_corrRZ(ctx,gasType, 2,driftRadius,Layer,StrawLayer,sign,0);
828 //_in theory_ For IEEE-compatible type double, argument causes exp to overflow if outside [-708.4, 709.8]
829 //however, overflow still seen when argument is 702; so I restrict these to -600, 600
830 const double expArg=(z-l)/s;
831 if (not inRange(expArg, -600.0,600.0)){
832 return expArg>0 ? std::numeric_limits<double>::infinity():0.;
833 }
834 return T0+(z/v)*std::exp(expArg);
835}
836
837double
839 EGasType gasType,
840 double driftRadius,
841 double zPosition,
842 int StrawLayer) const
843{
847 double z = std::abs(zPosition);
848 int sign=1;
849 if(zPosition<0)sign=-1;
850 double T0 = fitFuncPol_corrRZ(ctx,gasType, 0,driftRadius,0,StrawLayer,sign,1);
851 double b = fitFuncPol_corrRZ(ctx,gasType, 1,driftRadius,0,StrawLayer,sign,1);
852 return T0+b*z;
853}
854
855double
856TRT_ToT_dEdx::fitFuncPol_corrRZ(const EventContext& ctx,
857 EGasType gasType,
858 int parameter,
859 double driftRadius,
860 int Layer,
861 int Strawlayer,
862 int sign,
863 int set) const
864{
866 const TRTDedxcorrection* dEdxCorrection{*readHandle};
867 if(dEdxCorrection==nullptr)
868 {
869 ATH_MSG_ERROR(" fitFuncPol_corrRZ: Could not find any dEdxCorrection in CondStore. Return zero.");
870 return 0;
871 }
872
873 double a = 0;
874 double b = 0;
875 double c = 0;
876 double d = 0;
877 double e = 0;
878 double f = 0;
879 double r = driftRadius;
880 int offset = 0;
881 if(m_isData){
882 if(set==0){ // long straws in barrel
883 a = dEdxCorrection->paraLongCorrRZ[gasType][(6*parameter+0)*30*3+Layer*30+Strawlayer+offset];
884 b = dEdxCorrection->paraLongCorrRZ[gasType][(6*parameter+1)*30*3+Layer*30+Strawlayer+offset];
885 c = dEdxCorrection->paraLongCorrRZ[gasType][(6*parameter+2)*30*3+Layer*30+Strawlayer+offset];
886 d = dEdxCorrection->paraLongCorrRZ[gasType][(6*parameter+3)*30*3+Layer*30+Strawlayer+offset];
887 e = dEdxCorrection->paraLongCorrRZ[gasType][(6*parameter+4)*30*3+Layer*30+Strawlayer+offset];
888 f = dEdxCorrection->paraLongCorrRZ[gasType][(6*parameter+5)*30*3+Layer*30+Strawlayer+offset];
889
890 }else if (set ==1) { // short straws in barrel
891 if(sign > 0) offset+=108;
892 a = dEdxCorrection->paraShortCorrRZ[gasType][(6*parameter+0)*9+Layer+offset];
893 b = dEdxCorrection->paraShortCorrRZ[gasType][(6*parameter+1)*9+Layer+offset];
894 c = dEdxCorrection->paraShortCorrRZ[gasType][(6*parameter+2)*9+Layer+offset];
895 d = dEdxCorrection->paraShortCorrRZ[gasType][(6*parameter+3)*9+Layer+offset];
896 e = dEdxCorrection->paraShortCorrRZ[gasType][(6*parameter+4)*9+Layer+offset];
897 f = dEdxCorrection->paraShortCorrRZ[gasType][(6*parameter+5)*9+Layer+offset];
898 }else{ // straws in endcap
899 if(sign >0) Layer+=14;
900 a = dEdxCorrection->paraEndCorrRZ[gasType][(6*parameter+0)*28+Layer];
901 b = dEdxCorrection->paraEndCorrRZ[gasType][(6*parameter+1)*28+Layer];
902 c = dEdxCorrection->paraEndCorrRZ[gasType][(6*parameter+2)*28+Layer];
903 d = dEdxCorrection->paraEndCorrRZ[gasType][(6*parameter+3)*28+Layer];
904 e = dEdxCorrection->paraEndCorrRZ[gasType][(6*parameter+4)*28+Layer];
905 f = dEdxCorrection->paraEndCorrRZ[gasType][(6*parameter+5)*28+Layer];
906 }
907 }else{
908 if(set==0){ // long straws in barrel
909 if(sign > 0) offset=1620;
910 a = dEdxCorrection->paraLongCorrRZMC[gasType][(6*parameter+0)*30*3+Layer*30+Strawlayer+offset];
911 b = dEdxCorrection->paraLongCorrRZMC[gasType][(6*parameter+1)*30*3+Layer*30+Strawlayer+offset];
912 c = dEdxCorrection->paraLongCorrRZMC[gasType][(6*parameter+2)*30*3+Layer*30+Strawlayer+offset];
913 d = dEdxCorrection->paraLongCorrRZMC[gasType][(6*parameter+3)*30*3+Layer*30+Strawlayer+offset];
914 e = dEdxCorrection->paraLongCorrRZMC[gasType][(6*parameter+4)*30*3+Layer*30+Strawlayer+offset];
915 f = dEdxCorrection->paraLongCorrRZMC[gasType][(6*parameter+5)*30*3+Layer*30+Strawlayer+offset];
916 }else if (set ==1) { // short straws in barrel
917 if(sign > 0) offset+=108;
918 a = dEdxCorrection->paraShortCorrRZMC[gasType][(6*parameter+0)*9+Layer+offset];
919 b = dEdxCorrection->paraShortCorrRZMC[gasType][(6*parameter+1)*9+Layer+offset];
920 c = dEdxCorrection->paraShortCorrRZMC[gasType][(6*parameter+2)*9+Layer+offset];
921 d = dEdxCorrection->paraShortCorrRZMC[gasType][(6*parameter+3)*9+Layer+offset];
922 e = dEdxCorrection->paraShortCorrRZMC[gasType][(6*parameter+4)*9+Layer+offset];
923 f = dEdxCorrection->paraShortCorrRZMC[gasType][(6*parameter+5)*9+Layer+offset];
924 }else{ // straws in endcap
925 if(sign >0) Layer+=14;
926 a = dEdxCorrection->paraEndCorrRZMC[gasType][(6*parameter+0)*28+Layer];
927 b = dEdxCorrection->paraEndCorrRZMC[gasType][(6*parameter+1)*28+Layer];
928 c = dEdxCorrection->paraEndCorrRZMC[gasType][(6*parameter+2)*28+Layer];
929 d = dEdxCorrection->paraEndCorrRZMC[gasType][(6*parameter+3)*28+Layer];
930 e = dEdxCorrection->paraEndCorrRZMC[gasType][(6*parameter+4)*28+Layer];
931 f = dEdxCorrection->paraEndCorrRZMC[gasType][(6*parameter+5)*28+Layer];
932 }
933 }
934 return a+b*r+c*r*r+d*r*r*r+e*r*r*r*r+f*r*r*r*r*r;
935}
936
937double
939 EGasType gasType,
940 double driftRadius,
941 double radialPosition,
942 int Layer,
943 int sign) const
944{
945 /*
946 * T(r,R) = T0(r)+ a(r)*R
947 */
948
950 const TRTDedxcorrection* dEdxCorrection{*readHandle};
951 if(dEdxCorrection==nullptr) {
952 ATH_MSG_ERROR(" fitFuncEndcap_corrRZL: Could not find any dEdxCorrection in CondStore. Return zero.");
953 return 0;
954 }
955
956 double r = std::abs(driftRadius);
957 double a,b,c,d,e,f,g,h,i;
958 if(sign >0) Layer+=14;
959 if(m_isData){
960 a = dEdxCorrection->paraEndCorrRZDivideByLengthDATA[gasType][(0)*28+Layer];
961 b = dEdxCorrection->paraEndCorrRZDivideByLengthDATA[gasType][(1)*28+Layer];
962 c = dEdxCorrection->paraEndCorrRZDivideByLengthDATA[gasType][(2)*28+Layer];
963 d = dEdxCorrection->paraEndCorrRZDivideByLengthDATA[gasType][(3)*28+Layer];
964 e = dEdxCorrection->paraEndCorrRZDivideByLengthDATA[gasType][(4)*28+Layer];
965 f = dEdxCorrection->paraEndCorrRZDivideByLengthDATA[gasType][(5)*28+Layer];
966 g = dEdxCorrection->paraEndCorrRZDivideByLengthDATA[gasType][(6)*28+Layer];
967 h = dEdxCorrection->paraEndCorrRZDivideByLengthDATA[gasType][(7)*28+Layer];
968 i = dEdxCorrection->paraEndCorrRZDivideByLengthDATA[gasType][(8)*28+Layer];
969 }else{
970 a = dEdxCorrection->paraEndCorrRZDivideByLengthMC[gasType][(0)*28+Layer];
971 b = dEdxCorrection->paraEndCorrRZDivideByLengthMC[gasType][(1)*28+Layer];
972 c = dEdxCorrection->paraEndCorrRZDivideByLengthMC[gasType][(2)*28+Layer];
973 d = dEdxCorrection->paraEndCorrRZDivideByLengthMC[gasType][(3)*28+Layer];
974 e = dEdxCorrection->paraEndCorrRZDivideByLengthMC[gasType][(4)*28+Layer];
975 f = dEdxCorrection->paraEndCorrRZDivideByLengthMC[gasType][(5)*28+Layer];
976 g = dEdxCorrection->paraEndCorrRZDivideByLengthMC[gasType][(6)*28+Layer];
977 h = dEdxCorrection->paraEndCorrRZDivideByLengthMC[gasType][(7)*28+Layer];
978 i = dEdxCorrection->paraEndCorrRZDivideByLengthMC[gasType][(8)*28+Layer];
979 }
980
981 double T1 = b*r+c*r*r+d*r*r*r+e*r*r*r*r+f*r*r*r*r*r;
982 double slope = g+h*r+i*r*r;
983 double T0 = a;
984
985 return T0+T1+slope*radialPosition;
986}
987
988double
990 EGasType gasType,
991 double driftRadius,
992 double zPosition,
993 int Layer,
994 int Strawlayer) const
995{
996 /*
997 * T(r,z) = T0(r)+ b(r)*z*z
998 */
1000 const TRTDedxcorrection* dEdxCorrection{*readHandle};
1001 if(dEdxCorrection==nullptr) {
1002 ATH_MSG_ERROR(" fitFuncBarrel_corrRZL: Could not find any dEdxCorrection in CondStore. Return zero.");
1003 return 0;
1004 }
1005
1006 double a,b,c,d,e,f,g;
1007 if (Layer==0 && Strawlayer<9) { // short straws
1008 if (m_isData){
1009 a = dEdxCorrection->paraShortCorrRZDivideByLengthDATA[gasType][(0)*9+Strawlayer];
1010 b = dEdxCorrection->paraShortCorrRZDivideByLengthDATA[gasType][(1)*9+Strawlayer];
1011 c = dEdxCorrection->paraShortCorrRZDivideByLengthDATA[gasType][(2)*9+Strawlayer];
1012 d = dEdxCorrection->paraShortCorrRZDivideByLengthDATA[gasType][(3)*9+Strawlayer];
1013 e = dEdxCorrection->paraShortCorrRZDivideByLengthDATA[gasType][(4)*9+Strawlayer];
1014 f = dEdxCorrection->paraShortCorrRZDivideByLengthDATA[gasType][(5)*9+Strawlayer];
1015 g = dEdxCorrection->paraShortCorrRZDivideByLengthDATA[gasType][(6)*9+Strawlayer];
1016 } else {
1017 a = dEdxCorrection->paraShortCorrRZDivideByLengthMC[gasType][(0)*9+Strawlayer];
1018 b = dEdxCorrection->paraShortCorrRZDivideByLengthMC[gasType][(1)*9+Strawlayer];
1019 c = dEdxCorrection->paraShortCorrRZDivideByLengthMC[gasType][(2)*9+Strawlayer];
1020 d = dEdxCorrection->paraShortCorrRZDivideByLengthMC[gasType][(3)*9+Strawlayer];
1021 e = dEdxCorrection->paraShortCorrRZDivideByLengthMC[gasType][(4)*9+Strawlayer];
1022 f = dEdxCorrection->paraShortCorrRZDivideByLengthMC[gasType][(5)*9+Strawlayer];
1023 g = dEdxCorrection->paraShortCorrRZDivideByLengthMC[gasType][(6)*9+Strawlayer];
1024 }
1025 } else {
1026 if (m_isData) {
1027 a = dEdxCorrection->paraLongCorrRZDivideByLengthDATA[gasType][(0)*30*3+Layer*30+Strawlayer];
1028 b = dEdxCorrection->paraLongCorrRZDivideByLengthDATA[gasType][(1)*30*3+Layer*30+Strawlayer];
1029 c = dEdxCorrection->paraLongCorrRZDivideByLengthDATA[gasType][(2)*30*3+Layer*30+Strawlayer];
1030 d = dEdxCorrection->paraLongCorrRZDivideByLengthDATA[gasType][(3)*30*3+Layer*30+Strawlayer];
1031 e = dEdxCorrection->paraLongCorrRZDivideByLengthDATA[gasType][(4)*30*3+Layer*30+Strawlayer];
1032 f = dEdxCorrection->paraLongCorrRZDivideByLengthDATA[gasType][(5)*30*3+Layer*30+Strawlayer];
1033 g = dEdxCorrection->paraLongCorrRZDivideByLengthDATA[gasType][(6)*30*3+Layer*30+Strawlayer];
1034 } else {
1035 a = dEdxCorrection->paraLongCorrRZDivideByLengthMC[gasType][(0)*30*3+Layer*30+Strawlayer];
1036 b = dEdxCorrection->paraLongCorrRZDivideByLengthMC[gasType][(1)*30*3+Layer*30+Strawlayer];
1037 c = dEdxCorrection->paraLongCorrRZDivideByLengthMC[gasType][(2)*30*3+Layer*30+Strawlayer];
1038 d = dEdxCorrection->paraLongCorrRZDivideByLengthMC[gasType][(3)*30*3+Layer*30+Strawlayer];
1039 e = dEdxCorrection->paraLongCorrRZDivideByLengthMC[gasType][(4)*30*3+Layer*30+Strawlayer];
1040 f = dEdxCorrection->paraLongCorrRZDivideByLengthMC[gasType][(5)*30*3+Layer*30+Strawlayer];
1041 g = dEdxCorrection->paraLongCorrRZDivideByLengthMC[gasType][(6)*30*3+Layer*30+Strawlayer];
1042 }
1043 }
1044 double z = std::abs(zPosition);
1045 double r = std::abs(driftRadius);
1046 double T0neg=a;
1047 double T0pos=b;
1048 double T1 = std::exp(-c*r*r)+d*r;
1049 double slope = e*r+f*r*r+g*r*r*r;
1050 double result;
1051 result = T0neg+T1+slope*z;
1052 if (zPosition>0) result = T0pos+T1+slope*z;
1053
1054 return result;
1055}
1056
1057double
1059 const Trk::TrackStateOnSurface* itr) const
1060{
1062 const TRTDedxcorrection* dEdxCorrection{*readHandle};
1063
1064 const Trk::MeasurementBase* trkM = itr->measurementOnTrack();
1065
1066 // Check if this is RIO on track
1067 // and if yes check if is TRT Drift Circle
1068 // then set the ptr
1069 const InDet::TRT_DriftCircleOnTrack* driftcircle = nullptr;
1070 if (trkM && trkM->type(Trk::MeasurementBaseType::RIO_OnTrack)) {
1071 const Trk::RIO_OnTrack* tmpRio = static_cast<const Trk::RIO_OnTrack*>(trkM);
1073 driftcircle = static_cast<const InDet::TRT_DriftCircleOnTrack*>(tmpRio);
1074 }
1075 }
1076
1077 if (!driftcircle) {
1078 return 0.;
1079 }
1080
1081 const Trk::TrackParameters* trkP = itr->trackParameters();
1082 Identifier DCId = driftcircle->identify();
1083 int isHT = driftcircle->highLevel();
1084 int isShared=0;
1085
1086 const Trk::RIO_OnTrack* hit_trt = nullptr;
1087 if (trkM && trkM->type(Trk::MeasurementBaseType::RIO_OnTrack)) {
1088 hit_trt = static_cast<const Trk::RIO_OnTrack*>(trkM);
1089 }
1090
1091 if (hit_trt) {
1092 if ( m_assoTool->isShared(*(hit_trt->prepRawData())) ) isShared=1;
1093 }
1094 int layer = m_trtId->layer_or_wheel(DCId);
1095 int phimodule = m_trtId->phi_module(DCId);
1096 int HitPart = m_trtId->barrel_ec(DCId);
1097 double Trt_HitTheta = trkP->parameters()[Trk::theta];
1098 double trackEta = -log(tan(Trt_HitTheta/2.0));
1099
1100 double localOccupancy = m_localOccTool->LocalOccupancy(ctx, trackEta, phimodule);
1101 double ToTmip = 1;
1102 double valToT = 1.;
1103
1104 double p0=0., p1=0., p2=0., p0_flat=0.;
1105
1106 //the calibration array is structured as follows (hence the non intuitive numbers)
1107 //the first 36 parameters are for barrel, the last 168 for the endcap
1108 //each of these subarrays is divided into smaller subarrays of length 12 (barrel has 3 and endcap 14 layers)
1109 int nBarrelLayers = 3, nEndcapLayers = 14;
1110 //each layer has 3 parameters (function 2nd order), so a subarray for each layer has 3 parameters
1111 int nParametersPerLayer = 3;
1112 //this subarray for every layer exits for HT/LT hits, so 6 parameters
1113 int nHTConfigurations = 2;
1114 //this subarray exists for shared/non-shared hits, so 12 parameters
1115 int nSharedConfigurations = 2;
1116 int num =
1117 layer * nParametersPerLayer +
1118 isHT * ((abs(HitPart) - 1) * (nEndcapLayers - nBarrelLayers) *
1119 nParametersPerLayer +
1120 nBarrelLayers * nParametersPerLayer) +
1121 isShared * ((abs(HitPart) - 1) * (nEndcapLayers - nBarrelLayers) *
1122 nParametersPerLayer * nHTConfigurations +
1123 nBarrelLayers * nParametersPerLayer * nHTConfigurations) +
1124 (abs(HitPart) - 1) * nParametersPerLayer * nBarrelLayers *
1125 nHTConfigurations * nSharedConfigurations;
1126 //number for that given hit for non-shared conditions
1127 int num_flat = layer * 3 +
1128 isHT * ((abs(HitPart) - 1) * (nEndcapLayers - nBarrelLayers) *
1129 nParametersPerLayer +
1130 nBarrelLayers * nParametersPerLayer) +
1131 (abs(HitPart) - 1) * nParametersPerLayer * nBarrelLayers *
1132 nHTConfigurations * nSharedConfigurations;
1133
1134 p0 = dEdxCorrection->hitOccPar[num];
1135 p1 = dEdxCorrection->hitOccPar[num+1];
1136 p2 = dEdxCorrection->hitOccPar[num+2];
1137 p0_flat = dEdxCorrection->hitOccPar[num_flat];
1138
1139 //fitting function is a polynomial 2nd order f(x)=a+b*x+x^2
1140 //Hence the tot value is divided by the value of the function
1141 //multiplied to the non-shared intercept
1142 valToT = p0_flat/(p0+p1*localOccupancy+p2*localOccupancy*localOccupancy);
1143
1144 return ToTmip*valToT;
1145}
1146
1147double
1149 const Trk::Track* track,
1150 bool useHitsHT,
1151 std::optional<float> localOccupancy) const
1152{
1154 const TRTDedxcorrection* dEdxCorrection{*readHandle};
1155
1156 double corr=-999.;
1157
1158 double trackOcc = localOccupancy != std::nullopt
1159 ? *localOccupancy
1160 : m_localOccTool->LocalOccupancy(ctx, *track);
1161 const Trk::TrackParameters* perigee = track->perigeeParameters();
1162 const AmgVector(Trk::TrackParameters::dim)& parameterVector = perigee->parameters();
1163 double theta = parameterVector[Trk::theta];
1164 double trackEta = -log(tan(theta/2.0));
1165
1166 // the correction constants were determined in 100 bins of 0.04 in the eta range between -2 and 2
1167 int index = int(25*(trackEta+2.)); // determine the bin of the corrections
1168 if (index < 0) index = 0; // lower bound corresponding to eta = -2
1169 else if (index > 99) index = 99; // upper bound corresponding to eta = +2
1170
1171 //Function of the from f(x)=a+b*x+c*x^2 was used as a fitting function, separately for tracks with and without excluding HT hits
1172 if (useHitsHT) {
1173 corr=dEdxCorrection->trackOccPar0[index]+dEdxCorrection->trackOccPar1[index]*trackOcc+dEdxCorrection->trackOccPar2[index]*pow(trackOcc,2);
1174 } else {
1175 corr=dEdxCorrection->trackOccPar0NoHt[index]+dEdxCorrection->trackOccPar1NoHt[index]*trackOcc+dEdxCorrection->trackOccPar2NoHt[index]*pow(trackOcc,2);
1176 }
1177
1178 if (corr != 0) {
1179 return 1./corr;
1180 }
1181 return 0.;
1182}
1183
1185 if (trackState->type(Trk::TrackStateOnSurface::Outlier)) return 0.; //Outliers
1186
1187 const Trk::MeasurementBase* trkM = trackState->measurementOnTrack();
1188 if (!trkM) {
1189 return 0.;
1190 }
1191
1192 // Check if this is RIO on track
1193 // and if yes check if is TRT Drift Circle
1194 // then set the ptr
1195 const InDet::TRT_DriftCircleOnTrack* driftcircle = nullptr;
1197 const Trk::RIO_OnTrack* tmpRio = static_cast<const Trk::RIO_OnTrack*>(trkM);
1199 driftcircle = static_cast<const InDet::TRT_DriftCircleOnTrack*>(tmpRio);
1200 }
1201 }
1202
1203 if (!driftcircle) {
1204 return 0.;
1205 }
1206
1207 const Trk::TrackParameters* trkP = trackState->trackParameters();
1208 if(trkP==nullptr) return 0.;
1209
1210 double Trt_Rtrack = std::abs(trkP->parameters()[Trk::locR]);
1211 double Trt_HitTheta = trkP->parameters()[Trk::theta];
1212 double Trt_HitPhi = trkP->parameters()[Trk::phi];
1213 Identifier DCId = driftcircle->identify();
1214 int HitPart = std::abs(identifier->barrel_ec(DCId));
1215 const InDetDD::TRT_BaseElement* element = driftcircle->detectorElement();
1216 double strawphi = element->center(DCId).phi();
1217
1218 // check if track is an outlier
1219 if (Trt_Rtrack >= 2.0) {
1220 return 0.;
1221 }
1222
1223 double length=0;
1224 if (HitPart == 1) { //Barrel
1225 length = 2*std::sqrt(4-Trt_Rtrack*Trt_Rtrack)*1./std::abs(std::sin(Trt_HitTheta));
1226 } else if (HitPart == 2) { //EndCap
1227 length = 2*std::sqrt(4-Trt_Rtrack*Trt_Rtrack)*1./std::sqrt(1-std::sin(Trt_HitTheta)*std::sin(Trt_HitTheta)*std::cos(Trt_HitPhi-strawphi)*std::cos(Trt_HitPhi-strawphi));
1228 } else {
1229 // This should never happen
1230 throw std::runtime_error("Unknown barrel/endcap identifier: " + std::to_string(HitPart) + ". Must be 1(Barrel) or 2(Endcap)");
1231 }
1232
1233 return length;
1234}
Scalar theta() const
theta method
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_FATAL(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
#define REPORT_MESSAGE(LVL)
Report a message.
#define AmgVector(rows)
double length(const pvec &v)
static Double_t a
static Double_t sc
bool inRange(const double *boundaries, const double value, const double tolerance=0.02)
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
Handle class for reading a decoration on an object.
Handle class for reading from StoreGate.
This is an Identifier helper class for the TRT subdetector.
int sign(int a)
#define z
AthAlgTool(const std::string &type, const std::string &name, const IInterface *parent)
Constructor with parameters:
const ServiceHandle< StoreGateSvc > & detStore() const
Header file for AthHistogramAlgorithm.
DataModel_detail::const_iterator< DataVector > const_iterator
Definition DataVector.h:838
const_iterator end() const noexcept
Return a const_iterator pointing past the end of the collection.
const_iterator begin() const noexcept
Return a const_iterator pointing at the beginning of the collection.
size_type size() const noexcept
Returns the number of elements in the collection.
Virtual base class of TRT readout elements.
virtual const Amg::Vector3D & center() const override final
Element Surface: center of a straw layer.
Represents 'corrected' measurements from the TRT (for example, corrected for wire sag).
bool highLevel() const
returns true if the high level threshold was passed
virtual const InDetDD::TRT_BaseElement * detectorElement() const override final
returns the detector element, assoicated with the PRD of this class
virtual const TRT_DriftCircle * prepRawData() const override final
returns the PrepRawData - is a TRT_DriftCircle in this scope
virtual const Amg::Vector3D & globalPosition() const override final
return the global position of this RIO_OnTrack
double timeOverThreshold() const
returns Time over threshold in ns
Handle class for reading a decoration on an object.
bool isPresent() const
Is the referenced container present in SG?
This is an Identifier helper class for the TRT subdetector.
Definition TRT_ID.h:84
double fitFuncEndcap_corrRZL(const EventContext &ctx, EGasType gasType, double driftRadius, double radialPosition, int Layer, int sign) const
function to compute correction factor in endcap region
virtual StatusCode initialize() override
AlgTool initailize method.
double fitFuncBarrel_corrRZ(const EventContext &ctx, EGasType gas, double driftRadius, double zPosition, int Layer, int StrawLayer) const
function to compute correction factor in barrel region
const TRT_ID * m_trtId
BooleanProperty m_corrected
virtual double dEdx(const EventContext &ctx, const Trk::Track *track, bool useHThits, std::optional< float > localOccupancy=std::nullopt) const override final
function to calculate sum ToT normalised to number of used hits
EGasType gasTypeInStraw(const EventContext &ctx, const Trk::TrackStateOnSurface *itr) const
return gas type for that hit
IntegerProperty m_correctionType
TRT_ToT_dEdx(const std::string &, const std::string &, const IInterface *)
AlgTool like constructor.
IntegerProperty m_useTrackPartWithGasType
SG::ReadCondHandleKey< TRTDedxcorrection > m_ReadKey
BooleanProperty m_useZeroRHitCut
double trackOccupancyCorrection(const EventContext &ctx, const Trk::Track *track, bool useHThits, std::optional< float > localOccupancy) const
double fitFuncBarrelShort_corrRZ(const EventContext &ctx, EGasType gasType, double driftRadius, double zPosition, int StrawLayer) const
function called by fitFuncBarrel_corrRZ for short straws
virtual ~TRT_ToT_dEdx()
Virtual destructor.
double mass(const EventContext &ctx, const Trk::TrackStateOnSurface *itr, const double pTrk, double dEdx) const
function to extract most likely mass in bg [0,3]
virtual double getTest(const EventContext &ctx, const double dEdx_obs, const double pTrk, Trk::ParticleHypothesis hypothesis, Trk::ParticleHypothesis antihypothesis, int nUsedHits) const override final
function to calculate likelihood ratio test
bool isGoodHit(const EventContext &ctx, const Trk::TrackStateOnSurface *trackState, bool useHitsHT, double &length) const
function to define what is a good hit to be used for dEdx calculation cuts on track level can be made...
virtual double usedHits(const EventContext &ctx, const Trk::Track *track, bool useHThits=true) const override final
function to calculate number of used hits
double fitFuncPol_corrRZ(const EventContext &ctx, EGasType gasType, int parameter, double driftRadius, int Layer, int Strawlayer, int sign, int set) const
function called by fitFuncBarrel_corrRZ and fitFuncEndcap_corrRZ
unsigned int m_nTrunkateHits
double predictdEdx(const EventContext &ctx, const Trk::TrackStateOnSurface *itr, const double pTrk, Trk::ParticleHypothesis hypothesis) const
function to calculate expectation value for dEdx using BB fit
BooleanProperty m_isData
ToolHandle< Trk::IPRD_AssociationTool > m_assoTool
double fitFuncBarrel_corrRZL(const EventContext &ctx, EGasType gasType, double driftRadius, double zPosition, int Layer, int StrawLayer) const
function to compute correction factor in barrel region
FloatProperty m_trackConfig_maxRtrack
double fitFuncEndcap_corrRZ(const EventContext &ctx, EGasType gas, double driftRadius, double rPosition, int Layer, int sign) const
function to compute correction factor in endcap region
double correctToT_corrRZ(const EventContext &ctx, const Trk::TrackStateOnSurface *itr, double length) const
main function to correct ToT values on hit level as a function of track radius and z-position
ToolHandle< ITRT_StrawStatusSummaryTool > m_TRTStrawSummaryTool
SG::ReadDecorHandleKey< xAOD::EventInfo > m_rdhkEvtInfo
FloatProperty m_trackConfig_minRtrack
double hitOccupancyCorrection(const EventContext &ctx, const Trk::TrackStateOnSurface *itr) const
static double calculateTrackLengthInStraw(const Trk::TrackStateOnSurface *trackState, const TRT_ID *identifier)
double getProb(const EventContext &ctx, const Trk::TrackStateOnSurface *itr, const double dEdx_obs, const double pTrk, Trk::ParticleHypothesis hypothesis, int nUsedHits) const
function to calculate likelihood from prediction and resolution
double fitFuncBarrelLong_corrRZ(const EventContext &ctx, EGasType gasType, double driftRadius, double zPosition, int Layer, int StrawLayer) const
function called by fitFuncBarrel_corrRZ for long straws
BooleanProperty m_divideByL
IntegerProperty m_toolScenario
double correctNormalization(const EventContext &ctx, double nVtx=-1) const
correct overall dEdx normalization on track level
ToolHandle< InDet::ITRT_LocalOccupancy > m_localOccTool
This class is the pure abstract base class for all fittable tracking measurements.
const LocalParameters & localParameters() const
Interface method to get the LocalParameters.
virtual bool type(MeasurementBaseType::Type type) const =0
Interface method checking the type.
const Amg::MatrixX & localCovariance() const
Interface method to get the localError.
Class to handle RIO On Tracks ROT) for InDet and Muons, it inherits from the common MeasurementBase.
Definition RIO_OnTrack.h:70
virtual const Trk::PrepRawData * prepRawData() const =0
returns the PrepRawData (also known as RIO) object to which this RIO_OnTrack is associated.
Identifier identify() const
return the identifier -extends MeasurementBase
virtual bool rioType(RIO_OnTrackType::Type type) const =0
Method checking the Rio On Track type.
represents the track state (measurement, material, fit parameters and quality) at a surface.
const MeasurementBase * measurementOnTrack() const
returns MeasurementBase const overload
const TrackParameters * trackParameters() const
return ptr to trackparameters const overload
bool type(const TrackStateOnSurfaceType type) const
Use this method to find out if the TSoS is of a certain type: i.e.
@ Outlier
This TSoS contains an outlier, that is, it contains a MeasurementBase/RIO_OnTrack which was not used ...
STL class.
double timeOverThreshold(unsigned int m_word)
int r
Definition globals.cxx:22
constexpr double mass[PARTICLEHYPOTHESES]
the array of masses
DataVector< const Trk::TrackStateOnSurface > TrackStates
@ driftRadius
trt, straws
Definition ParamDefs.h:53
@ locR
Definition ParamDefs.h:44
@ theta
Definition ParamDefs.h:66
@ phi
Definition ParamDefs.h:75
ParticleHypothesis
Enumeration for Particle hypothesis respecting the interaction with material.
ParametersBase< TrackParametersDim, Charged > TrackParameters
Definition index.py:1
double normOffsetData[nGasTypes]
double hitOccPar[nParametersHitBaseddEdx]
double paraShortCorrRZDivideByLengthMC[nGasTypes][nParametersShortStrawsRZDivideByLength]
double paraEndCorrRZMC[nGasTypes][nParametersEndcapRZ]
double paraDivideByLengthDedxP4[nGasTypes]
double trackOccPar0NoHt[nParametersTrackBaseddEdx]
double resolution[nGasTypes][nParametersResolution]
double paraDedxP5[nGasTypes]
double paraDedxP4[nGasTypes]
double paraShortCorrRZMC[nGasTypes][nParametersShortStrawsRZ]
double paraLongCorrRZDivideByLengthMC[nGasTypes][nParametersLongStrawsRZDivideByLength]
double trackOccPar2[nParametersTrackBaseddEdx]
double normSlopeTot[nGasTypes]
double paraDedxP3[nGasTypes]
double paraDivideByLengthDedxP1[nGasTypes]
double paraDedxP2[nGasTypes]
double trackOccPar1NoHt[nParametersTrackBaseddEdx]
double paraLongCorrRZ[nGasTypes][nParametersLongStrawsRZ]
double normSlopeTotDivideByLength[nGasTypes]
int normNzero[nGasTypes]
double paraEndCorrRZDivideByLengthDATA[nGasTypes][nParametersEndcapRZDivideByLength]
double paraDivideByLengthDedxP2[nGasTypes]
double paraShortCorrRZ[nGasTypes][nParametersShortStrawsRZ]
double trackOccPar2NoHt[nParametersTrackBaseddEdx]
double paraShortCorrRZDivideByLengthDATA[nGasTypes][nParametersShortStrawsRZDivideByLength]
double paraLongCorrRZDivideByLengthDATA[nGasTypes][nParametersLongStrawsRZDivideByLength]
double normOffsetTot[nGasTypes]
double paraEndCorrRZDivideByLengthMC[nGasTypes][nParametersEndcapRZDivideByLength]
double trackOccPar0[nParametersTrackBaseddEdx]
double trackOccPar1[nParametersTrackBaseddEdx]
double paraLongCorrRZMC[nGasTypes][nParametersLongStrawsRZ]
double paraDivideByLengthDedxP3[nGasTypes]
double paraDedxP1[nGasTypes]
double paraDivideByLengthDedxP5[nGasTypes]
double paraEndCorrRZ[nGasTypes][nParametersEndcapRZ]
double normOffsetTotDivideByLength[nGasTypes]
double resolutionElectron[nGasTypes][nParametersResolution]