ATLAS Offline Software
Loading...
Searching...
No Matches
NSWCalibTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
5#include "NSWCalibTool.h"
6#include "GaudiKernel/SystemOfUnits.h"
7#include "GaudiKernel/PhysicalConstants.h"
10
13#include <cfloat>
14namespace {
15 constexpr double toRad = M_PI/180;
16 constexpr double pitchErr = 0.425 * 0.425 / 12;
17 constexpr double reciprocalSpeedOfLight = 1. / Gaudi::Units::c_light; // mm/ns
18
19 // since the final operation gas is not yet fixed different, different mixtures are added for studies
20 static const std::map<std::string, float> map_transDiff {{"ArCo2_937", 0.036},
21 {"ArCo2_8020", 0.019}, {"ArCo2iC4H10_9352", 0.035}};
22 static const std::map<std::string, float> map_longDiff {{"ArCo2_937", 0.019},
23 {"ArCo2_8020", 0.022 }, {"ArCo2iC4H10_9352", 0.0195}};
24 static const std::map<std::string, float> map_vDrift {{"ArCo2_937", 0.047},
25 {"ArCo2_8020", 0.040}, {"ArCo2iC4H10_9352", 0.045}};
26
27
28 // unit correction factors
29 constexpr double const MM_electronsPerfC = 6241.;
30 constexpr double const sTGC_pCPerfC = 1000.;
31
32
33 //Functional form fit to agree with Garfield simulations. Fit and parameters from G. Iakovidis
34 // For now only the parametrisation for 93:7 is available
35 using angleFunction = NSWCalib::MicroMegaGas::angleFunction;
36 static const std::map<std::string, angleFunction> map_lorentzAngleFunctionPars {
37 {"ArCo2_937", [](double x) {return 0.f + 58.87f*x -2.983f*x*x -10.62f*x*x*x + 2.818f*x*x*x*x;}},
38 {"ArCo2_8020", [](double x) {return 0.f + 58.87f*x -2.983f*x*x -10.62f*x*x*x + 2.818f*x*x*x*x;}},
39 {"ArCo2iC4H10_9352", [](double x) {return 0.f + 58.87f*x -2.983f*x*x -10.62f*x*x*x + 2.818f*x*x*x*x;}}};
40
41 // For now only the parametrisation for 93:7 is available
42 static const std::map<std::string, float> map_interactionDensitySigma {{"ArCo2_937", 4.04 / 5.},
43 {"ArCo2_8020", 4.04 / 5.}, {"ArCo2iC4H10_9352", 4.04 / 5.}};
44 static const std::map<std::string, float> map_interactionDensityMean {{"ArCo2_937", 16.15 / 5.},
45 {"ArCo2_8020", 16.15 / 5.}, {"ArCo2iC4H10_9352", 16.15 / 5.}};
46
47}
48
50{
51 ATH_MSG_DEBUG("In initialize()");
52 ATH_CHECK(m_idHelperSvc.retrieve());
53 ATH_CHECK(m_condTdoPdoKey.initialize());
56 ATH_CHECK(m_muDetMgrKey.initialize());
60 return StatusCode::SUCCESS;
61}
62
64 if (!map_vDrift.count(m_gasMixture)) {
65 ATH_MSG_FATAL("Configured Micromegas with unkown gas mixture: " << m_gasMixture);
66 return StatusCode::FAILURE;
67 }
68
69 m_vDrift = map_vDrift.find(m_gasMixture)->second;
70 m_transDiff = map_transDiff.find(m_gasMixture)->second;
71 m_longDiff = map_longDiff.find(m_gasMixture)->second;
72 m_interactionDensitySigma = map_interactionDensitySigma.find(m_gasMixture)->second;
73 m_interactionDensityMean = map_interactionDensityMean.find(m_gasMixture)->second;
74 m_lorentzAngleFunction = map_lorentzAngleFunctionPars.find(m_gasMixture)->second;
75 return StatusCode::SUCCESS;
76}
77
78const NswCalibDbTimeChargeData* Muon::NSWCalibTool::getCalibData(const EventContext& ctx) const {
79 // set up pointer to conditions object
81 if(!readTdoPdo.isValid()){
82 ATH_MSG_ERROR("Cannot find conditions data container for TDOs and PDOs!");
83 return nullptr;
84 }
85 return readTdoPdo.cptr();
86}
87
89 //Can we not get this somewhere above? Can this not be read just once? per run?
91 if (!ctpClusterCalibDB.isValid()) {
92 ATH_MSG_FATAL("Failed to retrieve the parameterized errors "<<ctpClusterCalibDB.fullKey());
93 return nullptr;
94 }
95 return ctpClusterCalibDB.cptr();
96}
97
98
99StatusCode Muon::NSWCalibTool::calibrateClus(const EventContext& ctx, const Muon::MMPrepData* prepData, const Amg::Vector3D& globalPos, std::vector<NSWCalib::CalibratedStrip>& calibClus) const {
100
101 double lorentzAngle {0.};
104 MagField::AtlasFieldCache fieldCache;
105 if (!loadMagneticField(ctx, fieldCache)) return StatusCode::FAILURE;
106 Amg::Vector3D magneticField{Amg::Vector3D::Zero()};
107 fieldCache.getField(globalPos.data(), magneticField.data());
108
110 double phi = globalPos.phi();
111 double bfield = (magneticField.x()*std::sin(phi)-magneticField.y()*std::cos(phi))*1000.;
112
114 int gasGap = m_idHelperSvc->mmIdHelper().gasGap(prepData->identify());
115 bool changeSign = ( globalPos.z() < 0. ? (gasGap==1 || gasGap==3) : (gasGap==2 || gasGap==4) );
116 if (changeSign) bfield = -bfield;
117
119 lorentzAngle = (bfield>0. ? 1. : -1.)*m_lorentzAngleFunction(std::abs(bfield)) * toRad;
120 }
121
123 for (unsigned int i = 0; i < prepData->stripNumbers().size(); ++i){
124 Identifier id = prepData->rdoList().at(i);
125 double time = prepData->stripTimes().at(i);
126 double charge = prepData->stripCharges().at(i);
127 //Retrieve pointing constraint
128 const Amg::Vector3D& globPos{prepData->globalPosition()};
129 NSWCalib::CalibratedStrip calibStrip;
130 ATH_CHECK(calibrateStrip(ctx, id, time, charge, (globPos.theta() / toRad) , lorentzAngle, calibStrip));
131
132 calibClus.push_back(std::move(calibStrip));
133 }
134 return StatusCode::SUCCESS;
135}
136
137
138StatusCode Muon::NSWCalibTool::calibrateClus(const EventContext& ctx,
139 const ActsTrk::GeometryContext& gctx,
140 const xAOD::MMCluster& prepData,
141 const Amg::Vector3D& globalPos,
142 std::vector<NSWCalib::CalibratedStrip>& calibClus) const {
143
144 double lorentzAngle {0.};
147 MagField::AtlasFieldCache fieldCache;
148 if (!loadMagneticField(ctx, fieldCache)) return StatusCode::FAILURE;
149 Amg::Vector3D magneticField{Amg::Vector3D::Zero()};
150 fieldCache.getField(globalPos.data(), magneticField.data());
151
153 double phi = globalPos.phi();
154 double bfield = (magneticField.x()*std::sin(phi)-magneticField.y()*std::cos(phi))*1000.;
155
157 int gasGap = m_idHelperSvc->mmIdHelper().gasGap(prepData.identify());
158 bool changeSign = ( globalPos.z() < 0. ? (gasGap==1 || gasGap==3) : (gasGap==2 || gasGap==4) );
159 if (changeSign) bfield = -bfield;
160
162 lorentzAngle = (bfield>0. ? 1. : -1.)*m_lorentzAngleFunction(std::abs(bfield)) * toRad;
163 }
164
166 for (unsigned int i = 0; i < prepData.stripNumbers().size(); ++i){
167 Identifier id = m_idHelperSvc->mmIdHelper().channelID(prepData.identify(), m_idHelperSvc->mmIdHelper().multilayer(prepData.identify()), m_idHelperSvc->mmIdHelper().gasGap(prepData.identify()),prepData.stripNumbers().at(i));
168 double time = prepData.stripTimes().at(i);
169 double charge = prepData.stripCharges().at(i);
170 //Retrieve pointing constraint
171 const Amg::Vector3D& globPos{prepData.readoutElement()->localToGlobalTrans(gctx, prepData.layerHash()) * (prepData.localPosition<1>()[0]*Amg::Vector3D::UnitX())};
172 NSWCalib::CalibratedStrip calibStrip;
173 ATH_CHECK(calibrateStrip(ctx, id, time, charge, (globPos.theta() / toRad) , lorentzAngle, calibStrip));
174
175 calibClus.push_back(std::move(calibStrip));
176 }
177 return StatusCode::SUCCESS;
178}
179
180
181
182StatusCode Muon::NSWCalibTool::calibrateStrip(const EventContext& ctx, const Identifier& id, const double time, const double charge, const double theta, const double lorentzAngle, NSWCalib::CalibratedStrip& calibStrip) const {
183
184
185 //get local positon
186 Amg::Vector2D locPos{Amg::Vector2D::Zero()};
187 if(!localStripPosition(id,locPos)) {
188 ATH_MSG_WARNING(__FILE__<<":"<<__LINE__<<" Failed to retrieve local strip position "<<m_idHelperSvc->toString(id));
189 return StatusCode::FAILURE;
190 }
191
192 calibStrip.identifier = id;
193 calibStrip.charge = charge;
194 calibStrip.time = time;
195
196 //retrieve identifier for the gas gap, not necessarily for the channel
197 //There is no pcb segmentation for these corrections, stored with pcb = 1 as default
198 Identifier gasGapId = m_idHelperSvc->mmIdHelper().channelID(id, m_idHelperSvc->mmIdHelper().multilayer(id),
199m_idHelperSvc->mmIdHelper().gasGap(id), 1);
200
201 double vDrift = m_vDrift; //nominal value from Garfield simulation
202
204 vDrift = getCTPClusterCalibData(ctx)->getCTPCorrectedDriftVelocity(gasGapId, theta);
205
206 //Calculate the new half max possible time based on the new drift velocity
207 float max_half_drifttime = (vDrift != 0 ) ? 2.5/vDrift : 50.;
208
209 //Shift the mean of the time to account for different values of drift velocities
210 calibStrip.time = time + (max_half_drifttime - m_mmT0TargetValue);
211 ATH_MSG_VERBOSE( "Original drift time: " << time << " new max half drift time: " << max_half_drifttime << " new time: " << calibStrip.time << " targett0 " << m_mmT0TargetValue );
212 }
213
214
215 double vDriftCorrected = vDrift * std::cos(lorentzAngle);
216
217 calibStrip.distDrift = vDriftCorrected * calibStrip.time;
218
220 calibStrip.resTransDistDrift = pitchErr + std::pow(m_transDiff * calibStrip.distDrift, 2);
221 calibStrip.resLongDistDrift = std::pow(m_ionUncertainty * vDriftCorrected, 2)
222 + std::pow(m_longDiff * calibStrip.distDrift, 2);
223 calibStrip.dx = std::sin(lorentzAngle) * calibStrip.time * vDrift;
224 calibStrip.locPos = Amg::Vector2D(locPos.x() + calibStrip.dx, locPos.y());
225 return StatusCode::SUCCESS;
226}
227
228
229StatusCode Muon::NSWCalibTool::calibrateStrip(const EventContext& ctx, const Muon::MM_RawData* mmRawData, NSWCalib::CalibratedStrip& calibStrip) const {
230
231 const Identifier rdoId = mmRawData->identify();
232 //get local postion
233 Amg::Vector2D locPos{0,0};
234 if(!localStripPosition(rdoId,locPos)) {
235 ATH_MSG_WARNING(__FILE__<<":"<<__LINE__<<" Failed to retrieve local strip position "<<m_idHelperSvc->toString(rdoId));
236 return StatusCode::FAILURE;
237 }
238
239 // MuonDetectorManager from the conditions store
241 const MuonGM::MuonDetectorManager* muDetMgr = muDetMgrHandle.cptr();
242
243 //get globalPos
244 Amg::Vector3D globalPos{Amg::Vector3D::Zero()};
245 const MuonGM::MMReadoutElement* detEl = muDetMgr->getMMReadoutElement(rdoId);
246 detEl->stripGlobalPosition(rdoId,globalPos);
247
248 // RDO has values in counts for both simulation and data
249 float time{-FLT_MAX}, charge{-FLT_MAX};
250 tdoToTime (ctx, mmRawData->timeAndChargeInCounts(), mmRawData->time (), rdoId, time , mmRawData->relBcid());
251 pdoToCharge(ctx, mmRawData->timeAndChargeInCounts(), mmRawData->charge(), rdoId, charge );
252
253 calibStrip.charge = charge;
254 // historically the peak time is included in the time determined by the MM digitization and therefore added back in the tdoToTime function
255 // in order to not break the RDO to digit conversion needed for the trigger and the overlay
256 calibStrip.time = time - globalPos.norm() * reciprocalSpeedOfLight - mmPeakTime();
257 // applying T0 calibration, cannot be done inside the the tdo to time function since the tof correction was included when deriving the calibration constants
259 calibStrip.time = applyT0Calibration(ctx, rdoId, calibStrip.time);
260 }
261
262 calibStrip.identifier = rdoId;
263
264 ATH_MSG_DEBUG("Calibrating RDO " << m_idHelperSvc->toString(rdoId) << "with pdo: " << mmRawData->charge() << " tdo: "<< mmRawData->time() << " relBCID "<< mmRawData->relBcid() << " charge and time in counts " <<
265 mmRawData->timeAndChargeInCounts() << " isData "<< m_isData << " to charge: " << calibStrip.charge << " electrons time after corrections " << calibStrip.time << " ns time before corrections "<< time << "ns");
266
267
268 //get stripWidth
269 detEl->getDesign(rdoId)->channelWidth(); // positon is not used for strip width
270
271 calibStrip.distDrift = m_vDrift * calibStrip.time;
272 calibStrip.resTransDistDrift = pitchErr + std::pow(m_transDiff * calibStrip.distDrift, 2);
273 calibStrip.resLongDistDrift = std::pow(m_ionUncertainty * m_vDrift, 2)
274 + std::pow(m_longDiff * calibStrip.distDrift, 2);
275
276 calibStrip.locPos = locPos;
277
278 return StatusCode::SUCCESS;
279}
280
281StatusCode Muon::NSWCalibTool::calibrateStrip(const EventContext& ctx, const Muon::STGC_RawData* sTGCRawData, NSWCalib::CalibratedStrip& calibStrip) const {
282
283 Identifier rdoId = sTGCRawData->identify();
285 const MuonGM::MuonDetectorManager* muDetMgr = muDetMgrHandle.cptr();
286
287 //get globalPos
288 Amg::Vector3D globalPos{Amg::Vector3D::Zero()};
289 const MuonGM::sTgcReadoutElement* detEl = muDetMgr->getsTgcReadoutElement(rdoId);
290 detEl->stripGlobalPosition(rdoId,globalPos);
291
292 //get local postion
293 Amg::Vector2D locPos{Amg::Vector2D::Zero()};
294 if(!localStripPosition(rdoId,locPos)) {
295 ATH_MSG_WARNING(__FILE__<<":"<<__LINE__<<" Failed to retrieve local strip position "<<m_idHelperSvc->toString(rdoId));
296 return StatusCode::FAILURE;
297 }
298
299 // RDO has values in counts for both simulation and data
300 float time{-FLT_MAX}, charge{-FLT_MAX};
301 tdoToTime (ctx, sTGCRawData->timeAndChargeInCounts(), sTGCRawData->time (), rdoId, time , sTGCRawData->bcTag());
302 pdoToCharge(ctx, sTGCRawData->timeAndChargeInCounts(), sTGCRawData->charge(), rdoId, charge );
303 if(sTGCRawData->timeAndChargeInCounts()){
304 calibStrip.charge = charge * sTGC_pCPerfC;
305 } else {
306 calibStrip.charge = charge;
307 }
308 calibStrip.time = time - stgcPeakTime();
309
311 calibStrip.time = applyT0Calibration(ctx, rdoId, calibStrip.time);
312 }
313
314 calibStrip.identifier = rdoId;
315 calibStrip.locPos = locPos;
316 return StatusCode::SUCCESS;
317
318}
319bool Muon::NSWCalibTool::loadMagneticField(const EventContext& ctx, MagField::AtlasFieldCache& fieldCache) const {
321 if (!readHandle.isValid()) {
322 ATH_MSG_ERROR("doDigitization: Failed to retrieve AtlasFieldCacheCondObj with key " << m_fieldCondObjInputKey.key());
323 return false;
324 }
325 readHandle.cptr()->getInitializedCache(fieldCache);
326 return true;
327}
328StatusCode Muon::NSWCalibTool::distToTime(const EventContext& ctx, const Muon::MMPrepData* prepData, const Amg::Vector3D& globalPos, const std::vector<double>& driftDistances, std::vector<double>& driftTimes) const {
330 MagField::AtlasFieldCache fieldCache;
331 if (!loadMagneticField(ctx, fieldCache)) return StatusCode::FAILURE;
332 Amg::Vector3D magneticField{Amg::Vector3D::Zero()};
333 fieldCache.getField(globalPos.data(), magneticField.data());
334
336 const double phi = globalPos.phi();
337 double bfield = (magneticField.x()*std::sin(phi)-magneticField.y()*std::cos(phi))*1000.;
338
340 int gasGap = m_idHelperSvc->mmIdHelper().gasGap(prepData->identify());
341 bool changeSign = ( globalPos.z() < 0. ? (gasGap==1 || gasGap==3) : (gasGap==2 || gasGap==4) );
342 if (changeSign) bfield = -bfield;
343 double cos2_lorentzAngle = std::pow(std::cos ( (bfield>0. ? 1. : -1.)*m_lorentzAngleFunction(std::abs(bfield)) * toRad), 2);
345 for (const double dist : driftDistances){
346 double time = dist / (m_vDrift*cos2_lorentzAngle);
347 driftTimes.push_back(time);
348 }
349 return StatusCode::SUCCESS;
350
351}
352
353bool
354Muon::NSWCalibTool::chargeToPdo(const EventContext& ctx, const float charge, const Identifier& chnlId, int& pdo) const {
355 const NswCalibDbTimeChargeData* tdoPdoData = getCalibData(ctx);
356 if (!tdoPdoData) {
357 pdo = 0;
358 return false;
359 }
360 const TimeCalibConst* calib_ptr = tdoPdoData->getCalibForChannel(TimeCalibType::PDO, chnlId);
361 if (!calib_ptr) {
362 pdo = 0;
363 return false;
364 }
365 const TimeCalibConst& calib{*calib_ptr};
366 float c = charge;
367 if (m_idHelperSvc->isMM (chnlId)) c /= MM_electronsPerfC;
368 else if(m_idHelperSvc->issTgc(chnlId)) c *= sTGC_pCPerfC;
369 else {
370 pdo = 0;
371 return false;
372 }
373 pdo = c * calib.slope + calib.intercept;
374 return true;
375}
376
377bool
378Muon::NSWCalibTool::pdoToCharge(const EventContext& ctx, const bool inCounts, const int pdo, const Identifier& chnlId, float& charge) const {
379 if(!inCounts){
380 charge = pdo;
381 return true;
382 }
383 const NswCalibDbTimeChargeData* tdoPdoData = getCalibData(ctx);
384 if (!tdoPdoData) {
385 charge =0.;
386 return false;
387 }
388 const TimeCalibConst* calib_ptr = tdoPdoData->getCalibForChannel(TimeCalibType::PDO, chnlId);
389 if (!calib_ptr) {
390 charge = 0.;
391 return false;
392 }
393 const TimeCalibConst& calib{*calib_ptr};
394 charge = (pdo-calib.intercept)/calib.slope;
395 if (m_idHelperSvc->isMM (chnlId)) charge *= MM_electronsPerfC;
396 else if(m_idHelperSvc->issTgc(chnlId)) charge /= sTGC_pCPerfC;
397 else return false;
398 return true;
399}
400
401bool
402Muon::NSWCalibTool::timeToTdo(const EventContext& ctx, const float time, const Identifier& chnlId, int& tdo, int& relBCID) const {
403 const NswCalibDbTimeChargeData* tdoPdoData = getCalibData(ctx);
404 if (!tdoPdoData) return false;
405 if (m_idHelperSvc->isMM (chnlId)) return timeToTdoMM (tdoPdoData, time, chnlId, tdo, relBCID);
406 else if(m_idHelperSvc->issTgc(chnlId)) return timeToTdoSTGC(tdoPdoData, time, chnlId, tdo, relBCID);
407 return false;
408}
409
410bool
411Muon::NSWCalibTool::timeToTdoMM(const NswCalibDbTimeChargeData* tdoPdoData, const float time, const Identifier& chnlId, int& tdo, int& relBCID) const {
412 const float t = time - m_mmPeakTime - m_mmLatencyMC; // subtract peaking time first! This is not supossed to run on data ever only needed for the RDO->Digit step
413 const TimeCalibConst* calib_ptr = tdoPdoData->getCalibForChannel(TimeCalibType::TDO, chnlId);
414 if (!calib_ptr) {
415 tdo = relBCID = 0;
416 return false;
417 }
418 const TimeCalibConst& calib{*calib_ptr};
419 float tdoTime = -999.9;
420 constexpr float lowerBound = Muon::MM_RawData::s_lowerTimeBound;
421 for(int i_relBCID=0; i_relBCID<Muon::MM_RawData::s_BCWindow; i_relBCID++){
422 if(t >= lowerBound+i_relBCID*25 && t < (lowerBound+25)+i_relBCID*25){
423 tdoTime = i_relBCID*25 - t;
424 relBCID = i_relBCID;
425 break;
426 }
427 }
428 if(tdoTime < lowerBound) {
429 tdo = relBCID = 0;
430 return false;
431 }
432 tdo = tdoTime*calib.slope + calib.intercept;
433 return true;
434}
435
436bool
437Muon::NSWCalibTool::timeToTdoSTGC(const NswCalibDbTimeChargeData* tdoPdoData, const float time, const Identifier& chnlId, int& tdo, int& relBCID) const {
438 const float t = time - m_stgcPeakTime - m_stgcLatencyMC; // subtract peaking time and latency first! This is not supossed to run on data ever only needed for the RDO->Digit step
439 const TimeCalibConst* calib_ptr = tdoPdoData->getCalibForChannel(TimeCalibType::TDO, chnlId);
440 if (!calib_ptr){
441 tdo = relBCID = 0;
442 return false;
443 }
444 const TimeCalibConst& calib = {*calib_ptr};
445 float tdoTime = -999.9;
446 const float lowerBound = Muon::STGC_RawData::s_lowerTimeBound - m_stgcLatencyMC; // this is not supossed to run on data ever, only needed for the RDO->Digit step
447 for(int i_relBCID=0; i_relBCID<Muon::STGC_RawData::s_BCWindow; ++i_relBCID){
448 if(t >= lowerBound+i_relBCID*25 && t < (lowerBound+25)+i_relBCID*25){
449 tdoTime = i_relBCID*25 - t;
450 relBCID = i_relBCID;
451 break;
452 }
453 }
454 if(tdoTime < lowerBound) {
455 tdo = relBCID = 0;
456 return false;
457 }
458 tdo = tdoTime*calib.slope + calib.intercept;
459 return true;
460}
461
462float Muon::NSWCalibTool::applyT0Calibration(const EventContext& ctx, const Identifier& id, float time) const {
464 if(!readT0.isValid()){
465 ATH_MSG_ERROR("Cannot find conditions data container for T0s!");
466 }
467 float t0 {0};
468 bool isGood = readT0->getT0(id, t0);
469 if(!isGood || t0==0){
470 ATH_MSG_DEBUG("failed to retrieve good t0 from database, skipping t0 calibration");
471 return time;
472 } else {
473 float targetT0 = (m_idHelperSvc->isMM(id) ? m_mmT0TargetValue : m_stgcT0TargetValue);
474 float newTime = time + (targetT0 - t0);
475 ATH_MSG_DEBUG("doing T0 calibration for RDO " << m_idHelperSvc->toString(id) << " time " << time <<" t0 from database " << t0 << " t0 target " << targetT0 << " new time " << newTime);
476 return newTime;
477 }
478}
479
480
481bool
482Muon::NSWCalibTool::tdoToTime(const EventContext& ctx, const bool inCounts, const int tdo, const Identifier& chnlId, float& time, const int relBCID) const {
483 if(!inCounts){
484 time = tdo;
485 return true;
486 }
487 const NswCalibDbTimeChargeData* tdoPdoData = getCalibData(ctx);
488 if (!tdoPdoData) {
489 time = 0.;
490 return false;
491 }
492 const TimeCalibConst* calib_ptr = tdoPdoData->getCalibForChannel(TimeCalibType::TDO, chnlId);
493 if (!calib_ptr){
494 time = 0.;
495 return false;
496 }
497 const TimeCalibConst& calib {*calib_ptr};
498 //this shift of 25ns is necessary to align the time of the signal with the way the VMM determines the time
499 //(relBCID 0 corresponds to -37.5 ns to - 12.5 ns)
500 //Eventually it should go into the conditions db since it is probably not the same for MC and Data
501 //but for now it is kept like it is. pscholer 8th of June 2022
502 float mmLatency = (m_isData? m_mmLatencyData : m_mmLatencyMC );
503 float stgcLatency = (m_isData? m_stgcLatencyData : m_stgcLatencyMC);
504
505 const float peakTime = m_idHelperSvc->isMM(chnlId) ? mmPeakTime() + mmLatency : stgcPeakTime() + stgcLatency;
506 time = relBCID*25. - (tdo-calib.intercept)/calib.slope + peakTime;
507 return true;
508}
509
511 NSWCalib::MicroMegaGas properties{};
512 properties.driftVelocity = m_vDrift;
513 properties.longitudinalDiffusionSigma = m_longDiff;
514 properties.transverseDiffusionSigma = m_transDiff;
515 properties.interactionDensityMean = m_interactionDensityMean;
516 properties.interactionDensitySigma = m_interactionDensitySigma;
517 properties.lorentzAngleFunction = m_lorentzAngleFunction;
518 return properties;
519}
520
521
523 // MuonDetectorManager from the conditions store
525 const MuonGM::MuonDetectorManager* muDetMgr = muDetMgrHandle.cptr();
526 if(m_idHelperSvc->isMM(id)){
527 const MuonGM::MMReadoutElement* detEl = muDetMgr->getMMReadoutElement(id);
528 return detEl->stripPosition(id,locPos);
529
530 } else if(m_idHelperSvc->issTgc(id)){
531 const MuonGM::sTgcReadoutElement* detEl = muDetMgr->getsTgcReadoutElement(id);
532 return detEl->stripPosition(id,locPos);
533
534 } else {
535 return false;
536 }
537}
#define M_PI
Scalar phi() const
phi method
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_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
double charge(const T &p)
Definition AtlasPID.h:997
static Double_t t0
#define x
Local cache for magnetic field (based on MagFieldServices/AtlasFieldSvcTLS.h)
void getField(const double *ATH_RESTRICT xyz, double *ATH_RESTRICT bxyz, double *ATH_RESTRICT deriv=nullptr)
get B field value at given position xyz[3] is in mm, bxyz[3] is in kT if deriv[9] is given,...
const Amg::Transform3D & localToGlobalTrans(const ActsTrk::GeometryContext &ctx) const
Returns the local to global transformation into the ATLAS coordinate system.
An MMReadoutElement corresponds to a single STGC module; therefore typicaly a barrel muon station con...
virtual bool stripPosition(const Identifier &id, Amg::Vector2D &pos) const override final
strip position – local or global If the strip number is outside the range of valid strips,...
const MuonChannelDesign * getDesign(const Identifier &id) const
returns the MuonChannelDesign class for the given identifier
bool stripGlobalPosition(const Identifier &id, Amg::Vector3D &gpos) const
The MuonDetectorManager stores the transient representation of the Muon Spectrometer geometry and pro...
const MMReadoutElement * getMMReadoutElement(const Identifier &id) const
access via extended identifier (requires unpacking)
const sTgcReadoutElement * getsTgcReadoutElement(const Identifier &id) const
access via extended identifier (requires unpacking)
An sTgcReadoutElement corresponds to a single STGC module; therefore typicaly a barrel muon station c...
virtual bool stripPosition(const Identifier &id, Amg::Vector2D &pos) const override final
strip position - should be renamed to channel position If the strip number is outside the range of va...
bool stripGlobalPosition(const Identifier &id, Amg::Vector3D &gpos) const
Class to represent MM measurements.
Definition MMPrepData.h:22
const std::vector< uint16_t > & stripNumbers() const
returns the list of strip numbers
Definition MMPrepData.h:247
const std::vector< short int > & stripTimes() const
returns the list of times
Definition MMPrepData.h:252
virtual const Amg::Vector3D & globalPosition() const override final
Returns the global position.
Definition MMPrepData.h:211
const std::vector< int > & stripCharges() const
returns the list of charges
Definition MMPrepData.h:257
Temporary class to hold the MM RDO.
Definition MM_RawData.h:20
static constexpr int s_BCWindow
Definition MM_RawData.h:75
int time() const
Definition MM_RawData.h:62
static constexpr double s_lowerTimeBound
Definition MM_RawData.h:72
const Identifier & identify() const
Definition MM_RawData.h:58
uint16_t relBcid() const
Definition MM_RawData.h:63
bool timeAndChargeInCounts() const
Definition MM_RawData.h:65
int charge() const
Definition MM_RawData.h:64
StatusCode calibrateClus(const EventContext &ctx, const Muon::MMPrepData *prepData, const Amg::Vector3D &globalPos, std::vector< NSWCalib::CalibratedStrip > &calibClus) const override
Gaudi::Property< bool > m_CalibDriftVelocityFromData
Gaudi::Property< float > m_mmT0TargetValue
bool timeToTdoMM(const NswCalibDbTimeChargeData *tdoPdoData, const float time, const Identifier &chnlId, int &tdo, int &relBCID) const
double m_interactionDensityMean
bool tdoToTime(const EventContext &ctx, const bool inCounts, const int tdo, const Identifier &chnlId, float &time, const int relBCID) const override
angleFunction m_lorentzAngleFunction
Gaudi::Property< double > m_ionUncertainty
double m_interactionDensitySigma
SG::ReadCondHandleKey< Muon::mmCTPClusterCalibData > m_ctpClusterCalibKey
const Muon::mmCTPClusterCalibData * getCTPClusterCalibData(const EventContext &ctx) const
virtual StatusCode initialize() override
SG::ReadCondHandleKey< NswT0Data > m_condT0Key
Gaudi::Property< bool > m_applyMmT0Calib
Gaudi::Property< float > m_stgcT0TargetValue
Gaudi::Property< bool > m_applyMmBFieldCalib
bool chargeToPdo(const EventContext &ctx, const float charge, const Identifier &chnlId, int &pdo) const override
SG::ReadCondHandleKey< MuonGM::MuonDetectorManager > m_muDetMgrKey
bool timeToTdoSTGC(const NswCalibDbTimeChargeData *tdoPdoData, const float time, const Identifier &chnlId, int &tdo, int &relBCID) const
Gaudi::Property< float > m_mmLatencyData
bool loadMagneticField(const EventContext &ctx, MagField::AtlasFieldCache &fieldCache) const
Gaudi::Property< std::string > m_gasMixture
float applyT0Calibration(const EventContext &ctx, const Identifier &id, float time) const
Gaudi::Property< float > m_stgcPeakTime
bool localStripPosition(const Identifier &id, Amg::Vector2D &locPos) const
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
SG::ReadCondHandleKey< AtlasFieldCacheCondObj > m_fieldCondObjInputKey
bool timeToTdo(const EventContext &ctx, const float time, const Identifier &chnlId, int &tdo, int &relBCID) const override
Gaudi::Property< double > m_transDiff
StatusCode initializeGasProperties()
Gaudi::Property< double > m_longDiff
float stgcPeakTime() const override
Gaudi::Property< float > m_mmLatencyMC
Gaudi::Property< double > m_vDrift
Gaudi::Property< bool > m_applysTgcT0Calib
Gaudi::Property< float > m_stgcLatencyMC
SG::ReadCondHandleKey< NswCalibDbTimeChargeData > m_condTdoPdoKey
float mmPeakTime() const override
StatusCode distToTime(const EventContext &ctx, const Muon::MMPrepData *prepData, const Amg::Vector3D &globalPos, const std::vector< double > &driftDistances, std::vector< double > &driftTimes) const override
bool pdoToCharge(const EventContext &ctx, const bool inCounts, const int pdo, const Identifier &chnlId, float &charge) const override
Gaudi::Property< float > m_stgcLatencyData
NswCalibDbTimeChargeData::CalibConstants TimeCalibConst
const NswCalibDbTimeChargeData * getCalibData(const EventContext &ctx) const
StatusCode calibrateStrip(const EventContext &ctx, const Identifier &id, const double time, const double charge, const double theta, const double lorentzAngle, NSWCalib::CalibratedStrip &calibStrip) const override
Gaudi::Property< bool > m_isData
NSWCalib::MicroMegaGas mmGasProperties() const override
Gaudi::Property< float > m_mmPeakTime
bool timeAndChargeInCounts() const
static constexpr int s_BCWindow
static constexpr double s_lowerTimeBound
unsigned int charge() const
uint16_t bcTag() const
const Identifier identify() const
float time() const
const CalibConstants * getCalibForChannel(const CalibDataType type, const Identifier &channelId) const
Retrieves the calibration constant for a particular readout channel.
const DataObjID & fullKey() const
const_pointer_type cptr()
Identifier identify() const
return the identifier
const std::vector< Identifier > & rdoList() const
return the List of rdo identifiers (pointers)
const std::vector< uint16_t > & stripNumbers() const
returns the list of strip numbers
const Identifier & identify() const
: Returns the Athena identifier of the micro mega cluster It's constructed from the measurementHash &...
IdentifierHash layerHash() const
Returns the hash of the associated layer (Needed for surface retrieval)
const std::vector< int > & stripCharges() const
returns the list of charges
const std::vector< int16_t > & stripTimes() const
returns the list of times
const MuonGMR4::MmReadoutElement * readoutElement() const
Retrieve the associated MmReadoutElement.
ConstVectorMap< N > localPosition() const
Returns the local position of the measurement.
Eigen::Matrix< double, 2, 1 > Vector2D
Eigen::Matrix< double, 3, 1 > Vector3D
MMCluster_v1 MMCluster
double channelWidth() const
calculate local channel width
std::function< double(double)> angleFunction