ATLAS Offline Software
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>
14 namespace {
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());
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 
78 const NswCalibDbTimeChargeData* Muon::NSWCalibTool::getCalibData(const EventContext& ctx) const {
79  // set up pointer to conditions object
80  SG::ReadCondHandle<NswCalibDbTimeChargeData> readTdoPdo{m_condTdoPdoKey, ctx};
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?
90  SG::ReadCondHandle<Muon::mmCTPClusterCalibData> ctpClusterCalibDB{m_ctpClusterCalibKey, ctx};
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 
99 StatusCode 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.};
102  if(m_applyMmBFieldCalib){
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 
138 StatusCode Muon::NSWCalibTool::calibrateClus(const EventContext& ctx, const ActsGeometryContext& gctx, const xAOD::MMCluster* prepData, const Amg::Vector3D& globalPos, std::vector<NSWCalib::CalibratedStrip>& calibClus) const {
139 
140  double lorentzAngle {0.};
141  if(m_applyMmBFieldCalib){
143  MagField::AtlasFieldCache fieldCache;
144  if (!loadMagneticField(ctx, fieldCache)) return StatusCode::FAILURE;
145  Amg::Vector3D magneticField{Amg::Vector3D::Zero()};
146  fieldCache.getField(globalPos.data(), magneticField.data());
147 
149  double phi = globalPos.phi();
150  double bfield = (magneticField.x()*std::sin(phi)-magneticField.y()*std::cos(phi))*1000.;
151 
153  int gasGap = m_idHelperSvc->mmIdHelper().gasGap(prepData->identify());
154  bool changeSign = ( globalPos.z() < 0. ? (gasGap==1 || gasGap==3) : (gasGap==2 || gasGap==4) );
155  if (changeSign) bfield = -bfield;
156 
158  lorentzAngle = (bfield>0. ? 1. : -1.)*m_lorentzAngleFunction(std::abs(bfield)) * toRad;
159  }
160 
162  for (unsigned int i = 0; i < prepData->stripNumbers().size(); ++i){
163  Identifier id = m_idHelperSvc->mmIdHelper().channelID(prepData->identify(), m_idHelperSvc->mmIdHelper().multilayer(prepData->identify()), m_idHelperSvc->mmIdHelper().gasGap(prepData->identify()),prepData->stripNumbers().at(i));
164  double time = prepData->stripTimes().at(i);
165  double charge = prepData->stripCharges().at(i);
166  //Retrieve pointing constraint
167  const Amg::Vector3D& globPos{prepData->readoutElement()->localToGlobalTrans(gctx, prepData->layerHash()) * (prepData->localPosition<1>()[0]*Amg::Vector3D::UnitX())};
168  NSWCalib::CalibratedStrip calibStrip;
169  ATH_CHECK(calibrateStrip(ctx, id, time, charge, (globPos.theta() / toRad) , lorentzAngle, calibStrip));
170 
171  calibClus.push_back(std::move(calibStrip));
172  }
173  return StatusCode::SUCCESS;
174 }
175 
176 
177 
178 StatusCode 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 {
179 
180 
181  //get local positon
183  if(!localStripPosition(id,locPos)) {
184  ATH_MSG_WARNING(__FILE__<<":"<<__LINE__<<" Failed to retrieve local strip position "<<m_idHelperSvc->toString(id));
185  return StatusCode::FAILURE;
186  }
187 
188  calibStrip.identifier = id;
189  calibStrip.charge = charge;
190  calibStrip.time = time;
191 
192  //retrieve identifier for the gas gap, not necessarily for the channel
193  //There is no pcb segmentation for these corrections, stored with pcb = 1 as default
194  Identifier gasGapId = m_idHelperSvc->mmIdHelper().channelID(id, m_idHelperSvc->mmIdHelper().multilayer(id),
195 m_idHelperSvc->mmIdHelper().gasGap(id), 1);
196 
197  double vDrift = m_vDrift; //nominal value from Garfield simulation
198 
199  if(m_CalibDriftVelocityFromData){
200  vDrift = getCTPClusterCalibData(ctx)->getCTPCorrectedDriftVelocity(gasGapId, theta);
201 
202  //Calculate the new half max possible time based on the new drift velocity
203  float max_half_drifttime = (vDrift != 0 ) ? 2.5/vDrift : 50.;
204 
205  //Shift the mean of the time to account for different values of drift velocities
206  calibStrip.time = time + (max_half_drifttime - m_mmT0TargetValue);
207  ATH_MSG_VERBOSE( "Original drift time: " << time << " new max half drift time: " << max_half_drifttime << " new time: " << calibStrip.time << " targett0 " << m_mmT0TargetValue );
208  }
209 
210 
211  double vDriftCorrected = vDrift * std::cos(lorentzAngle);
212 
213  calibStrip.distDrift = vDriftCorrected * calibStrip.time;
214 
216  calibStrip.resTransDistDrift = pitchErr + std::pow(m_transDiff * calibStrip.distDrift, 2);
217  calibStrip.resLongDistDrift = std::pow(m_ionUncertainty * vDriftCorrected, 2)
218  + std::pow(m_longDiff * calibStrip.distDrift, 2);
219  calibStrip.dx = std::sin(lorentzAngle) * calibStrip.time * vDrift;
220  calibStrip.locPos = Amg::Vector2D(locPos.x() + calibStrip.dx, locPos.y());
221  return StatusCode::SUCCESS;
222 }
223 
224 
225 StatusCode Muon::NSWCalibTool::calibrateStrip(const EventContext& ctx, const Muon::MM_RawData* mmRawData, NSWCalib::CalibratedStrip& calibStrip) const {
226 
227  const Identifier rdoId = mmRawData->identify();
228  //get local postion
229  Amg::Vector2D locPos{0,0};
230  if(!localStripPosition(rdoId,locPos)) {
231  ATH_MSG_WARNING(__FILE__<<":"<<__LINE__<<" Failed to retrieve local strip position "<<m_idHelperSvc->toString(rdoId));
232  return StatusCode::FAILURE;
233  }
234 
235  // MuonDetectorManager from the conditions store
236  SG::ReadCondHandle<MuonGM::MuonDetectorManager> muDetMgrHandle{m_muDetMgrKey, ctx};
237  const MuonGM::MuonDetectorManager* muDetMgr = muDetMgrHandle.cptr();
238 
239  //get globalPos
240  Amg::Vector3D globalPos{Amg::Vector3D::Zero()};
241  const MuonGM::MMReadoutElement* detEl = muDetMgr->getMMReadoutElement(rdoId);
242  detEl->stripGlobalPosition(rdoId,globalPos);
243 
244  // RDO has values in counts for both simulation and data
245  float time{-FLT_MAX}, charge{-FLT_MAX};
246  tdoToTime (ctx, mmRawData->timeAndChargeInCounts(), mmRawData->time (), rdoId, time , mmRawData->relBcid());
247  pdoToCharge(ctx, mmRawData->timeAndChargeInCounts(), mmRawData->charge(), rdoId, charge );
248 
249  calibStrip.charge = charge;
250  // historically the peak time is included in the time determined by the MM digitization and therefore added back in the tdoToTime function
251  // in order to not break the RDO to digit conversion needed for the trigger and the overlay
252  calibStrip.time = time - globalPos.norm() * reciprocalSpeedOfLight - mmPeakTime();
253  // applying T0 calibration, cannot be done inside the the tdo to time function since the tof correction was included when deriving the calibration constants
254  if(m_applyMmT0Calib){
255  calibStrip.time = applyT0Calibration(ctx, rdoId, calibStrip.time);
256  }
257 
258  calibStrip.identifier = rdoId;
259 
260  ATH_MSG_DEBUG("Calibrating RDO " << m_idHelperSvc->toString(rdoId) << "with pdo: " << mmRawData->charge() << " tdo: "<< mmRawData->time() << " relBCID "<< mmRawData->relBcid() << " charge and time in counts " <<
261  mmRawData->timeAndChargeInCounts() << " isData "<< m_isData << " to charge: " << calibStrip.charge << " electrons time after corrections " << calibStrip.time << " ns time before corrections "<< time << "ns");
262 
263 
264  //get stripWidth
265  detEl->getDesign(rdoId)->channelWidth(); // positon is not used for strip width
266 
267  calibStrip.distDrift = m_vDrift * calibStrip.time;
268  calibStrip.resTransDistDrift = pitchErr + std::pow(m_transDiff * calibStrip.distDrift, 2);
269  calibStrip.resLongDistDrift = std::pow(m_ionUncertainty * m_vDrift, 2)
270  + std::pow(m_longDiff * calibStrip.distDrift, 2);
271 
272  calibStrip.locPos = locPos;
273 
274  return StatusCode::SUCCESS;
275 }
276 
277 StatusCode Muon::NSWCalibTool::calibrateStrip(const EventContext& ctx, const Muon::STGC_RawData* sTGCRawData, NSWCalib::CalibratedStrip& calibStrip) const {
278 
279  Identifier rdoId = sTGCRawData->identify();
280  SG::ReadCondHandle<MuonGM::MuonDetectorManager> muDetMgrHandle{m_muDetMgrKey, ctx};
281  const MuonGM::MuonDetectorManager* muDetMgr = muDetMgrHandle.cptr();
282 
283  //get globalPos
284  Amg::Vector3D globalPos{Amg::Vector3D::Zero()};
285  const MuonGM::sTgcReadoutElement* detEl = muDetMgr->getsTgcReadoutElement(rdoId);
286  detEl->stripGlobalPosition(rdoId,globalPos);
287 
288  //get local postion
290  if(!localStripPosition(rdoId,locPos)) {
291  ATH_MSG_WARNING(__FILE__<<":"<<__LINE__<<" Failed to retrieve local strip position "<<m_idHelperSvc->toString(rdoId));
292  return StatusCode::FAILURE;
293  }
294 
295  // RDO has values in counts for both simulation and data
296  float time{-FLT_MAX}, charge{-FLT_MAX};
297  tdoToTime (ctx, sTGCRawData->timeAndChargeInCounts(), sTGCRawData->time (), rdoId, time , sTGCRawData->bcTag());
298  pdoToCharge(ctx, sTGCRawData->timeAndChargeInCounts(), sTGCRawData->charge(), rdoId, charge );
299  if(sTGCRawData->timeAndChargeInCounts()){
300  calibStrip.charge = charge * sTGC_pCPerfC;
301  } else {
302  calibStrip.charge = charge;
303  }
304  calibStrip.time = time - stgcPeakTime();
305 
306  if(m_applysTgcT0Calib){
307  calibStrip.time = applyT0Calibration(ctx, rdoId, calibStrip.time);
308  }
309 
310  calibStrip.identifier = rdoId;
311  calibStrip.locPos = locPos;
312  return StatusCode::SUCCESS;
313 
314 }
315 bool Muon::NSWCalibTool::loadMagneticField(const EventContext& ctx, MagField::AtlasFieldCache& fieldCache) const {
316  SG::ReadCondHandle<AtlasFieldCacheCondObj> readHandle{m_fieldCondObjInputKey, ctx};
317  if (!readHandle.isValid()) {
318  ATH_MSG_ERROR("doDigitization: Failed to retrieve AtlasFieldCacheCondObj with key " << m_fieldCondObjInputKey.key());
319  return false;
320  }
321  readHandle.cptr()->getInitializedCache(fieldCache);
322  return true;
323 }
324 StatusCode Muon::NSWCalibTool::distToTime(const EventContext& ctx, const Muon::MMPrepData* prepData, const Amg::Vector3D& globalPos, const std::vector<double>& driftDistances, std::vector<double>& driftTimes) const {
326  MagField::AtlasFieldCache fieldCache;
327  if (!loadMagneticField(ctx, fieldCache)) return StatusCode::FAILURE;
328  Amg::Vector3D magneticField{Amg::Vector3D::Zero()};
329  fieldCache.getField(globalPos.data(), magneticField.data());
330 
332  const double phi = globalPos.phi();
333  double bfield = (magneticField.x()*std::sin(phi)-magneticField.y()*std::cos(phi))*1000.;
334 
336  int gasGap = m_idHelperSvc->mmIdHelper().gasGap(prepData->identify());
337  bool changeSign = ( globalPos.z() < 0. ? (gasGap==1 || gasGap==3) : (gasGap==2 || gasGap==4) );
338  if (changeSign) bfield = -bfield;
339  double cos2_lorentzAngle = std::pow(std::cos ( (bfield>0. ? 1. : -1.)*m_lorentzAngleFunction(std::abs(bfield)) * toRad), 2);
341  for (const double dist : driftDistances){
342  double time = dist / (m_vDrift*cos2_lorentzAngle);
343  driftTimes.push_back(time);
344  }
345  return StatusCode::SUCCESS;
346 
347 }
348 
349 bool
350 Muon::NSWCalibTool::chargeToPdo(const EventContext& ctx, const float charge, const Identifier& chnlId, int& pdo) const {
351  const NswCalibDbTimeChargeData* tdoPdoData = getCalibData(ctx);
352  if (!tdoPdoData) {
353  pdo = 0;
354  return false;
355  }
356  const TimeCalibConst* calib_ptr = tdoPdoData->getCalibForChannel(TimeCalibType::PDO, chnlId);
357  if (!calib_ptr) {
358  pdo = 0;
359  return false;
360  }
361  const TimeCalibConst& calib{*calib_ptr};
362  float c = charge;
363  if (m_idHelperSvc->isMM (chnlId)) c /= MM_electronsPerfC;
364  else if(m_idHelperSvc->issTgc(chnlId)) c *= sTGC_pCPerfC;
365  else {
366  pdo = 0;
367  return false;
368  }
369  pdo = c * calib.slope + calib.intercept;
370  return true;
371 }
372 
373 bool
374 Muon::NSWCalibTool::pdoToCharge(const EventContext& ctx, const bool inCounts, const int pdo, const Identifier& chnlId, float& charge) const {
375  if(!inCounts){
376  charge = pdo;
377  return true;
378  }
379  const NswCalibDbTimeChargeData* tdoPdoData = getCalibData(ctx);
380  if (!tdoPdoData) {
381  charge =0.;
382  return false;
383  }
384  const TimeCalibConst* calib_ptr = tdoPdoData->getCalibForChannel(TimeCalibType::PDO, chnlId);
385  if (!calib_ptr) {
386  charge = 0.;
387  return false;
388  }
389  const TimeCalibConst& calib{*calib_ptr};
390  charge = (pdo-calib.intercept)/calib.slope;
391  if (m_idHelperSvc->isMM (chnlId)) charge *= MM_electronsPerfC;
392  else if(m_idHelperSvc->issTgc(chnlId)) charge /= sTGC_pCPerfC;
393  else return false;
394  return true;
395 }
396 
397 bool
398 Muon::NSWCalibTool::timeToTdo(const EventContext& ctx, const float time, const Identifier& chnlId, int& tdo, int& relBCID) const {
399  const NswCalibDbTimeChargeData* tdoPdoData = getCalibData(ctx);
400  if (!tdoPdoData) return false;
401  if (m_idHelperSvc->isMM (chnlId)) return timeToTdoMM (tdoPdoData, time, chnlId, tdo, relBCID);
402  else if(m_idHelperSvc->issTgc(chnlId)) return timeToTdoSTGC(tdoPdoData, time, chnlId, tdo, relBCID);
403  return false;
404 }
405 
406 bool
407 Muon::NSWCalibTool::timeToTdoMM(const NswCalibDbTimeChargeData* tdoPdoData, const float time, const Identifier& chnlId, int& tdo, int& relBCID) const {
408  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
409  const TimeCalibConst* calib_ptr = tdoPdoData->getCalibForChannel(TimeCalibType::TDO, chnlId);
410  if (!calib_ptr) {
411  tdo = relBCID = 0;
412  return false;
413  }
414  const TimeCalibConst& calib{*calib_ptr};
415  float tdoTime = -999.9;
416  constexpr float lowerBound = Muon::MM_RawData::s_lowerTimeBound;
417  for(int i_relBCID=0; i_relBCID<Muon::MM_RawData::s_BCWindow; i_relBCID++){
418  if(t >= lowerBound+i_relBCID*25 && t < (lowerBound+25)+i_relBCID*25){
419  tdoTime = i_relBCID*25 - t;
420  relBCID = i_relBCID;
421  break;
422  }
423  }
424  if(tdoTime < lowerBound) {
425  tdo = relBCID = 0;
426  return false;
427  }
428  tdo = tdoTime*calib.slope + calib.intercept;
429  return true;
430 }
431 
432 bool
433 Muon::NSWCalibTool::timeToTdoSTGC(const NswCalibDbTimeChargeData* tdoPdoData, const float time, const Identifier& chnlId, int& tdo, int& relBCID) const {
434  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
435  const TimeCalibConst* calib_ptr = tdoPdoData->getCalibForChannel(TimeCalibType::TDO, chnlId);
436  if (!calib_ptr){
437  tdo = relBCID = 0;
438  return false;
439  }
440  const TimeCalibConst& calib = {*calib_ptr};
441  float tdoTime = -999.9;
442  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
443  for(int i_relBCID=0; i_relBCID<Muon::STGC_RawData::s_BCWindow; ++i_relBCID){
444  if(t >= lowerBound+i_relBCID*25 && t < (lowerBound+25)+i_relBCID*25){
445  tdoTime = i_relBCID*25 - t;
446  relBCID = i_relBCID;
447  break;
448  }
449  }
450  if(tdoTime < lowerBound) {
451  tdo = relBCID = 0;
452  return false;
453  }
454  tdo = tdoTime*calib.slope + calib.intercept;
455  return true;
456 }
457 
458 float Muon::NSWCalibTool::applyT0Calibration(const EventContext& ctx, const Identifier& id, float time) const {
459  SG::ReadCondHandle<NswT0Data> readT0{m_condT0Key, ctx};
460  if(!readT0.isValid()){
461  ATH_MSG_ERROR("Cannot find conditions data container for T0s!");
462  }
463  float t0 {0};
464  bool isGood = readT0->getT0(id, t0);
465  if(!isGood || t0==0){
466  ATH_MSG_DEBUG("failed to retrieve good t0 from database, skipping t0 calibration");
467  return time;
468  } else {
469  float targetT0 = (m_idHelperSvc->isMM(id) ? m_mmT0TargetValue : m_stgcT0TargetValue);
470  float newTime = time + (targetT0 - t0);
471  ATH_MSG_DEBUG("doing T0 calibration for RDO " << m_idHelperSvc->toString(id) << " time " << time <<" t0 from database " << t0 << " t0 target " << targetT0 << " new time " << newTime);
472  return newTime;
473  }
474 }
475 
476 
477 bool
478 Muon::NSWCalibTool::tdoToTime(const EventContext& ctx, const bool inCounts, const int tdo, const Identifier& chnlId, float& time, const int relBCID) const {
479  if(!inCounts){
480  time = tdo;
481  return true;
482  }
483  const NswCalibDbTimeChargeData* tdoPdoData = getCalibData(ctx);
484  if (!tdoPdoData) {
485  time = 0.;
486  return false;
487  }
488  const TimeCalibConst* calib_ptr = tdoPdoData->getCalibForChannel(TimeCalibType::TDO, chnlId);
489  if (!calib_ptr){
490  time = 0.;
491  return false;
492  }
493  const TimeCalibConst& calib {*calib_ptr};
494  //this shift of 25ns is necessary to align the time of the signal with the way the VMM determines the time
495  //(relBCID 0 corresponds to -37.5 ns to - 12.5 ns)
496  //Eventually it should go into the conditions db since it is probably not the same for MC and Data
497  //but for now it is kept like it is. pscholer 8th of June 2022
498  float mmLatency = (m_isData? m_mmLatencyData : m_mmLatencyMC );
499  float stgcLatency = (m_isData? m_stgcLatencyData : m_stgcLatencyMC);
500 
501  const float peakTime = m_idHelperSvc->isMM(chnlId) ? mmPeakTime() + mmLatency : stgcPeakTime() + stgcLatency;
502  time = relBCID*25. - (tdo-calib.intercept)/calib.slope + peakTime;
503  return true;
504 }
505 
508  properties.driftVelocity = m_vDrift;
509  properties.longitudinalDiffusionSigma = m_longDiff;
510  properties.transverseDiffusionSigma = m_transDiff;
511  properties.interactionDensityMean = m_interactionDensityMean;
512  properties.interactionDensitySigma = m_interactionDensitySigma;
513  properties.lorentzAngleFunction = m_lorentzAngleFunction;
514  return properties;
515 }
516 
517 
519  // MuonDetectorManager from the conditions store
520  SG::ReadCondHandle<MuonGM::MuonDetectorManager> muDetMgrHandle{m_muDetMgrKey};
521  const MuonGM::MuonDetectorManager* muDetMgr = muDetMgrHandle.cptr();
522  if(m_idHelperSvc->isMM(id)){
523  const MuonGM::MMReadoutElement* detEl = muDetMgr->getMMReadoutElement(id);
524  return detEl->stripPosition(id,locPos);
525 
526  } else if(m_idHelperSvc->issTgc(id)){
527  const MuonGM::sTgcReadoutElement* detEl = muDetMgr->getsTgcReadoutElement(id);
528  return detEl->stripPosition(id,locPos);
529 
530  } else {
531  return false;
532  }
533 }
MuonGM::MMReadoutElement::stripPosition
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,...
Definition: MMReadoutElement.h:206
Muon::STGC_RawData::identify
const Identifier identify() const
Definition: STGC_RawData.h:52
Muon::NSWCalibTool::m_applyMmT0Calib
Gaudi::Property< bool > m_applyMmT0Calib
Definition: NSWCalibTool.h:103
dumpTgcDigiDeadChambers.gasGap
list gasGap
Definition: dumpTgcDigiDeadChambers.py:33
NSWCalib::CalibratedStrip::time
double time
Definition: INSWCalibTool.h:26
ATH_MSG_FATAL
#define ATH_MSG_FATAL(x)
Definition: AthMsgStreamMacros.h:34
Muon::MMPrepData
Class to represent MM measurements.
Definition: MMPrepData.h:22
Muon::MM_RawData::relBcid
uint16_t relBcid() const
Definition: MM_RawData.h:63
Muon::NSWCalibTool::m_idHelperSvc
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
Definition: NSWCalibTool.h:72
Muon::MM_RawData::s_lowerTimeBound
static constexpr double s_lowerTimeBound
Definition: MM_RawData.h:72
NswCalibDbTimeChargeData::CalibConstants
Helper struct to cache all calibration constants in a common place of the memory.
Definition: NswCalibDbTimeChargeData.h:28
Muon::MMPrepData::globalPosition
virtual const Amg::Vector3D & globalPosition() const override final
Returns the global position.
Definition: MMPrepData.h:211
NSWCalib::CalibratedStrip::charge
double charge
Definition: INSWCalibTool.h:25
SG::ReadCondHandle
Definition: ReadCondHandle.h:44
Muon::NSWCalibTool::initializeGasProperties
StatusCode initializeGasProperties()
Definition: NSWCalibTool.cxx:63
python.TestDriveDummies.properties
dictionary properties
Definition: TestDriveDummies.py:14
xAOD::MMCluster_v1
Definition: MMCluster_v1.h:20
NSWCalib::CalibratedStrip::distDrift
double distDrift
Definition: INSWCalibTool.h:28
Muon::NSWCalibTool::pdoToCharge
bool pdoToCharge(const EventContext &ctx, const bool inCounts, const int pdo, const Identifier &chnlId, float &charge) const override
Definition: NSWCalibTool.cxx:374
NSWCalib::CalibratedStrip::dx
double dx
Definition: INSWCalibTool.h:31
sTgcReadoutElement.h
Amg::Vector2D
Eigen::Matrix< double, 2, 1 > Vector2D
Definition: GeoPrimitives.h:48
Muon::MM_RawData::timeAndChargeInCounts
bool timeAndChargeInCounts() const
Definition: MM_RawData.h:65
Muon::MM_RawData::identify
const Identifier & identify() const
Definition: MM_RawData.h:58
MuonGM::MMReadoutElement::getDesign
const MuonChannelDesign * getDesign(const Identifier &id) const
returns the MuonChannelDesign class for the given identifier
Definition: MMReadoutElement.h:190
Muon::MM_RawData::time
int time() const
Definition: MM_RawData.h:62
Muon::NSWCalibTool::timeToTdo
bool timeToTdo(const EventContext &ctx, const float time, const Identifier &chnlId, int &tdo, int &relBCID) const override
Definition: NSWCalibTool.cxx:398
NSWCalib::CalibratedStrip::resTransDistDrift
double resTransDistDrift
Definition: INSWCalibTool.h:29
M_PI
#define M_PI
Definition: ActiveFraction.h:11
xAOD::MMCluster_v1::readoutElement
const MuonGMR4::MmReadoutElement * readoutElement() const
Retrieve the associated MmReadoutElement.
Muon::NSWCalibTool::m_muDetMgrKey
SG::ReadCondHandleKey< MuonGM::MuonDetectorManager > m_muDetMgrKey
Definition: NSWCalibTool.h:74
Trk::PrepRawData::rdoList
const std::vector< Identifier > & rdoList() const
return the List of rdo identifiers (pointers)
Muon::NSWCalibTool::tdoToTime
bool tdoToTime(const EventContext &ctx, const bool inCounts, const int tdo, const Identifier &chnlId, float &time, const int relBCID) const override
Definition: NSWCalibTool.cxx:478
read_hist_ntuple.t
t
Definition: read_hist_ntuple.py:5
drawFromPickle.cos
cos
Definition: drawFromPickle.py:36
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
Muon::MM_RawData::s_BCWindow
static constexpr int s_BCWindow
Definition: MM_RawData.h:75
NSWCalib::CalibratedStrip::resLongDistDrift
double resLongDistDrift
Definition: INSWCalibTool.h:30
x
#define x
Muon::NSWCalibTool::m_CalibDriftVelocityFromData
Gaudi::Property< bool > m_CalibDriftVelocityFromData
Definition: NSWCalibTool.h:80
Muon::NSWCalibTool::loadMagneticField
bool loadMagneticField(const EventContext &ctx, MagField::AtlasFieldCache &fieldCache) const
Definition: NSWCalibTool.cxx:315
Muon::STGC_RawData::s_lowerTimeBound
static constexpr double s_lowerTimeBound
Definition: STGC_RawData.h:67
MuonGM::sTgcReadoutElement::stripPosition
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...
Definition: MuonDetDescr/MuonReadoutGeometry/MuonReadoutGeometry/sTgcReadoutElement.h:321
Muon::NSWCalibTool::mmGasProperties
NSWCalib::MicroMegaGas mmGasProperties() const override
Definition: NSWCalibTool.cxx:506
python.setupRTTAlg.size
int size
Definition: setupRTTAlg.py:39
xAOD::MMCluster_v1::layerHash
IdentifierHash layerHash() const
Returns the hash of the associated layer (Needed for surface retrieval)
Definition: MMCluster_v1.cxx:23
MMReadoutElement.h
Muon::MMPrepData::stripCharges
const std::vector< int > & stripCharges() const
returns the list of charges
Definition: MMPrepData.h:257
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
NSWCalib::MicroMegaGas::angleFunction
std::function< double(double)> angleFunction
Definition: INSWCalibTool.h:44
Muon::NSWCalibTool::distToTime
StatusCode distToTime(const EventContext &ctx, const Muon::MMPrepData *prepData, const Amg::Vector3D &globalPos, const std::vector< double > &driftDistances, std::vector< double > &driftTimes) const override
Definition: NSWCalibTool.cxx:324
Muon::NSWCalibTool::timeToTdoSTGC
bool timeToTdoSTGC(const NswCalibDbTimeChargeData *tdoPdoData, const float time, const Identifier &chnlId, int &tdo, int &relBCID) const
Definition: NSWCalibTool.cxx:433
Muon::STGC_RawData
Definition: STGC_RawData.h:14
lumiFormat.i
int i
Definition: lumiFormat.py:85
Muon::MM_RawData
Temporary class to hold the MM RDO.
Definition: MM_RawData.h:20
Muon::NSWCalibTool::applyT0Calibration
float applyT0Calibration(const EventContext &ctx, const Identifier &id, float time) const
Definition: NSWCalibTool.cxx:458
xAOD::MMCluster_v1::identify
const Identifier & identify() const
: Returns the Athena identifier of the micro mega cluster It's constructed from the measurementHash &...
Definition: MMCluster_v1.cxx:26
xAOD::MMCluster_v1::stripNumbers
const std::vector< uint16_t > & stripNumbers() const
returns the list of strip numbers
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
Muon::NSWCalibTool::m_ctpClusterCalibKey
SG::ReadCondHandleKey< Muon::mmCTPClusterCalibData > m_ctpClusterCalibKey
Definition: NSWCalibTool.h:81
MuonGM::MMReadoutElement::stripGlobalPosition
bool stripGlobalPosition(const Identifier &id, Amg::Vector3D &gpos) const
Definition: MMReadoutElement.h:277
NSWCalib::CalibratedStrip::locPos
Amg::Vector2D locPos
Definition: INSWCalibTool.h:32
MuonGM::sTgcReadoutElement
An sTgcReadoutElement corresponds to a single STGC module; therefore typicaly a barrel muon station c...
Definition: MuonDetDescr/MuonReadoutGeometry/MuonReadoutGeometry/sTgcReadoutElement.h:30
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
Muon::MMPrepData::stripNumbers
const std::vector< uint16_t > & stripNumbers() const
returns the list of strip numbers
Definition: MMPrepData.h:247
NSWCalib::CalibratedStrip
Definition: INSWCalibTool.h:24
xAOD::UncalibratedMeasurement_v1::localPosition
ConstVectorMap< N > localPosition() const
Returns the local position of the measurement.
ActsGeometryContext
Include the GeoPrimitives which need to be put first.
Definition: ActsGeometryContext.h:27
Muon::MMPrepData::stripTimes
const std::vector< short int > & stripTimes() const
returns the list of times
Definition: MMPrepData.h:252
Trk::PrepRawData::identify
Identifier identify() const
return the identifier
Muon::MM_RawData::charge
int charge() const
Definition: MM_RawData.h:64
Muon::NSWCalibTool::getCTPClusterCalibData
const Muon::mmCTPClusterCalibData * getCTPClusterCalibData(const EventContext &ctx) const
Definition: NSWCalibTool.cxx:88
Muon::NSWCalibTool::m_condT0Key
SG::ReadCondHandleKey< NswT0Data > m_condT0Key
Definition: NSWCalibTool.h:76
Muon::NSWCalibTool::calibrateStrip
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
Definition: NSWCalibTool.cxx:178
id
SG::auxid_t id
Definition: Control/AthContainers/Root/debug.cxx:239
Muon::NSWCalibTool::getCalibData
const NswCalibDbTimeChargeData * getCalibData(const EventContext &ctx) const
Definition: NSWCalibTool.cxx:78
xAOD::MMCluster_v1::stripTimes
const std::vector< int16_t > & stripTimes() const
returns the list of times
MuonGM::sTgcReadoutElement::stripGlobalPosition
bool stripGlobalPosition(const Identifier &id, Amg::Vector3D &gpos) const
Definition: MuonDetDescr/MuonReadoutGeometry/MuonReadoutGeometry/sTgcReadoutElement.h:332
Muon::STGC_RawData::time
float time() const
Definition: STGC_RawData.h:55
charge
double charge(const T &p)
Definition: AtlasPID.h:986
Muon::NSWCalibTool::calibrateClus
StatusCode calibrateClus(const EventContext &ctx, const Muon::MMPrepData *prepData, const Amg::Vector3D &globalPos, std::vector< NSWCalib::CalibratedStrip > &calibClus) const override
Definition: NSWCalibTool.cxx:99
SG::CondHandleKey::initialize
StatusCode initialize(bool used=true)
python.PhysicalConstants.c_light
float c_light
Definition: PhysicalConstants.py:73
Amg::Vector3D
Eigen::Matrix< double, 3, 1 > Vector3D
Definition: GeoPrimitives.h:47
NSWCalibTool.h
Muon::NSWCalibTool::m_applysTgcT0Calib
Gaudi::Property< bool > m_applysTgcT0Calib
Definition: NSWCalibTool.h:104
PlotSFuncertainty.calib
calib
Definition: PlotSFuncertainty.py:110
Muon::NSWCalibTool::localStripPosition
bool localStripPosition(const Identifier &id, Amg::Vector2D &locPos) const
Definition: NSWCalibTool.cxx:518
Muon::NSWCalibTool::timeToTdoMM
bool timeToTdoMM(const NswCalibDbTimeChargeData *tdoPdoData, const float time, const Identifier &chnlId, int &tdo, int &relBCID) const
Definition: NSWCalibTool.cxx:407
MuonGM::MuonDetectorManager
The MuonDetectorManager stores the transient representation of the Muon Spectrometer geometry and pro...
Definition: MuonDetDescr/MuonReadoutGeometry/MuonReadoutGeometry/MuonDetectorManager.h:51
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
MuonGM::MuonDetectorManager::getMMReadoutElement
const MMReadoutElement * getMMReadoutElement(const Identifier &id) const
access via extended identifier (requires unpacking)
Definition: MuonDetDescr/MuonReadoutGeometry/src/MuonDetectorManager.cxx:257
MagField::AtlasFieldCache
Local cache for magnetic field (based on MagFieldServices/AtlasFieldSvcTLS.h)
Definition: AtlasFieldCache.h:43
if
if(febId1==febId2)
Definition: LArRodBlockPhysicsV0.cxx:567
MuonGM::MMReadoutElement
An MMReadoutElement corresponds to a single STGC module; therefore typicaly a barrel muon station con...
Definition: MMReadoutElement.h:25
MuonGMR4::MuonReadoutElement::localToGlobalTrans
const Amg::Transform3D & localToGlobalTrans(const ActsGeometryContext &ctx) const
Returns the local to global transformation into the ATLAS coordinate system.
Definition: MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/src/MuonReadoutElement.cxx:81
MagField::AtlasFieldCache::getField
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,...
Definition: AtlasFieldCache.cxx:42
MMCluster.h
Muon::NSWCalibTool::initialize
virtual StatusCode initialize() override
Definition: NSWCalibTool.cxx:49
Muon::NSWCalibTool::m_condTdoPdoKey
SG::ReadCondHandleKey< NswCalibDbTimeChargeData > m_condTdoPdoKey
Definition: NSWCalibTool.h:75
NswCalibDbTimeChargeData
Definition: NswCalibDbTimeChargeData.h:19
MuonGM::MuonDetectorManager::getsTgcReadoutElement
const sTgcReadoutElement * getsTgcReadoutElement(const Identifier &id) const
access via extended identifier (requires unpacking)
Definition: MuonDetDescr/MuonReadoutGeometry/src/MuonDetectorManager.cxx:261
drawFromPickle.sin
sin
Definition: drawFromPickle.py:36
Muon::STGC_RawData::charge
unsigned int charge() const
Definition: STGC_RawData.h:57
Muon::mmCTPClusterCalibData
Definition: mmCTPClusterCalibData.h:18
Muon::STGC_RawData::bcTag
uint16_t bcTag() const
Definition: STGC_RawData.h:58
pow
constexpr int pow(int base, int exp) noexcept
Definition: ap_fixedTest.cxx:15
MuonGM::MuonChannelDesign::channelWidth
double channelWidth() const
calculate local channel width
Definition: MuonChannelDesign.h:394
Muon::NSWCalibTool::chargeToPdo
bool chargeToPdo(const EventContext &ctx, const float charge, const Identifier &chnlId, int &pdo) const override
Definition: NSWCalibTool.cxx:350
python.compressB64.c
def c
Definition: compressB64.py:93
Muon::STGC_RawData::timeAndChargeInCounts
bool timeAndChargeInCounts() const
Definition: STGC_RawData.h:61
NswCalibDbTimeChargeData::getCalibForChannel
const CalibConstants * getCalibForChannel(const CalibDataType type, const Identifier &channelId) const
Retrieves the calibration constant for a particular readout channel.
Definition: NswCalibDbTimeChargeData.cxx:121
NSWCalib::MicroMegaGas
Definition: INSWCalibTool.h:36
Muon::STGC_RawData::s_BCWindow
static constexpr int s_BCWindow
Definition: STGC_RawData.h:70
MmReadoutElement.h
generate::Zero
void Zero(TH1D *hin)
Definition: generate.cxx:32
xAOD::MMCluster_v1::stripCharges
const std::vector< int > & stripCharges() const
returns the list of charges
NSWCalib::CalibratedStrip::identifier
Identifier identifier
Definition: INSWCalibTool.h:33
Muon::NSWCalibTool::m_fieldCondObjInputKey
SG::ReadCondHandleKey< AtlasFieldCacheCondObj > m_fieldCondObjInputKey
Definition: NSWCalibTool.h:73
Identifier
Definition: IdentifierFieldParser.cxx:14