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 
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.};
145  if(m_applyMmBFieldCalib){
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 
182 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 {
183 
184 
185  //get local positon
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),
199 m_idHelperSvc->mmIdHelper().gasGap(id), 1);
200 
201  double vDrift = m_vDrift; //nominal value from Garfield simulation
202 
203  if(m_CalibDriftVelocityFromData){
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 
229 StatusCode 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
240  SG::ReadCondHandle<MuonGM::MuonDetectorManager> muDetMgrHandle{m_muDetMgrKey, ctx};
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
258  if(m_applyMmT0Calib){
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 
281 StatusCode Muon::NSWCalibTool::calibrateStrip(const EventContext& ctx, const Muon::STGC_RawData* sTGCRawData, NSWCalib::CalibratedStrip& calibStrip) const {
282 
283  Identifier rdoId = sTGCRawData->identify();
284  SG::ReadCondHandle<MuonGM::MuonDetectorManager> muDetMgrHandle{m_muDetMgrKey, ctx};
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
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 
310  if(m_applysTgcT0Calib){
311  calibStrip.time = applyT0Calibration(ctx, rdoId, calibStrip.time);
312  }
313 
314  calibStrip.identifier = rdoId;
315  calibStrip.locPos = locPos;
316  return StatusCode::SUCCESS;
317 
318 }
319 bool Muon::NSWCalibTool::loadMagneticField(const EventContext& ctx, MagField::AtlasFieldCache& fieldCache) const {
320  SG::ReadCondHandle<AtlasFieldCacheCondObj> readHandle{m_fieldCondObjInputKey, ctx};
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 }
328 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 {
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 
353 bool
354 Muon::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 
377 bool
378 Muon::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 
401 bool
402 Muon::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 
410 bool
411 Muon::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 
436 bool
437 Muon::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 
462 float Muon::NSWCalibTool::applyT0Calibration(const EventContext& ctx, const Identifier& id, float time) const {
463  SG::ReadCondHandle<NswT0Data> readT0{m_condT0Key, ctx};
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 
481 bool
482 Muon::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 
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
524  SG::ReadCondHandle<MuonGM::MuonDetectorManager> muDetMgrHandle{m_muDetMgrKey};
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 }
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:34
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
phi
Scalar phi() const
phi method
Definition: AmgMatrixBasePlugin.h:67
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:378
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
theta
Scalar theta() const
theta method
Definition: AmgMatrixBasePlugin.h:75
MuonGM::MMReadoutElement::getDesign
const MuonChannelDesign * getDesign(const Identifier &id) const
returns the MuonChannelDesign class for the given identifier
Definition: MMReadoutElement.h:190
ALFA_EventTPCnv_Dict::t0
std::vector< ALFA_RawData_p1 > t0
Definition: ALFA_EventTPCnvDict.h:42
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:402
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:482
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:319
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:510
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:328
Muon::NSWCalibTool::timeToTdoSTGC
bool timeToTdoSTGC(const NswCalibDbTimeChargeData *tdoPdoData, const float time, const Identifier &chnlId, int &tdo, int &relBCID) const
Definition: NSWCalibTool.cxx:437
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:462
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
MuonGMR4::MuonReadoutElement::localToGlobalTrans
const Amg::Transform3D & localToGlobalTrans(const ActsTrk::GeometryContext &ctx) const
Returns the local to global transformation into the ATLAS coordinate system.
Definition: MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/src/MuonReadoutElement.cxx:81
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
ActsTrk::GeometryContext
Definition: GeometryContext.h:28
NSWCalib::CalibratedStrip
Definition: INSWCalibTool.h:24
xAOD::UncalibratedMeasurement_v1::localPosition
ConstVectorMap< N > localPosition() const
Returns the local position of the measurement.
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:182
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:997
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:522
Muon::NSWCalibTool::timeToTdoMM
bool timeToTdoMM(const NswCalibDbTimeChargeData *tdoPdoData, const float time, const Identifier &chnlId, int &tdo, int &relBCID) const
Definition: NSWCalibTool.cxx:411
CaloSwCorrections.time
def time(flags, cells_name, *args, **kw)
Definition: CaloSwCorrections.py:242
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:268
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
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:25
MuonGM::MuonDetectorManager::getsTgcReadoutElement
const sTgcReadoutElement * getsTgcReadoutElement(const Identifier &id) const
access via extended identifier (requires unpacking)
Definition: MuonDetDescr/MuonReadoutGeometry/src/MuonDetectorManager.cxx:272
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:354
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:122
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