ATLAS Offline Software
Loading...
Searching...
No Matches
Muon::NSWCalibTool Class Reference

#include <NSWCalibTool.h>

Inheritance diagram for Muon::NSWCalibTool:
Collaboration diagram for Muon::NSWCalibTool:

Public Types

using TimeCalibType = NswCalibDbTimeChargeData::CalibDataType
using TimeCalibConst = NswCalibDbTimeChargeData::CalibConstants

Public Member Functions

virtual ~NSWCalibTool ()=default
StatusCode calibrateClus (const EventContext &ctx, const MMPrepData *prepData, const Amg::Vector3D &globalPos, std::vector< NSWCalib::CalibratedStrip > &calibClus) const override
StatusCode distToTime (const EventContext &ctx, const MMPrepData *prepData, const Amg::Vector3D &globalPos, const std::vector< double > &driftDistances, std::vector< double > &driftTimes) const override
StatusCode calibrateClus (const EventContext &ctx, const ActsTrk::GeometryContext &gctx, const xAOD::MMCluster &prepData, const Amg::Vector3D &globalPos, std::vector< NSWCalib::CalibratedStrip > &calibClus) const override
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
StatusCode calibrateStrip (const EventContext &ctx, const MM_RawData *mmRawData, NSWCalib::CalibratedStrip &calibStrip) const override
StatusCode calibrateStrip (const EventContext &ctx, const STGC_RawData *sTGCRawData, NSWCalib::CalibratedStrip &calibStrip) const override
bool tdoToTime (const EventContext &ctx, const bool inCounts, const int tdo, const Identifier &chnlId, float &time, const int relBCID) const override
bool timeToTdo (const EventContext &ctx, const float time, const Identifier &chnlId, int &tdo, int &relBCID) const override
bool chargeToPdo (const EventContext &ctx, const float charge, const Identifier &chnlId, int &pdo) const override
bool pdoToCharge (const EventContext &ctx, const bool inCounts, const int pdo, const Identifier &chnlId, float &charge) const override
virtual StatusCode initialize () override
NSWCalib::MicroMegaGas mmGasProperties () const override
float mmPeakTime () const override
float stgcPeakTime () const override

Private Types

using angleFunction = NSWCalib::MicroMegaGas::angleFunction

Private Member Functions

StatusCode loadMagneticField (const EventContext &ctx, MagField::AtlasFieldCache &fieldCache) const
bool timeToTdoMM (const NswCalibDbTimeChargeData *tdoPdoData, const float time, const Identifier &chnlId, int &tdo, int &relBCID) const
bool timeToTdoSTGC (const NswCalibDbTimeChargeData *tdoPdoData, const float time, const Identifier &chnlId, int &tdo, int &relBCID) const
float applyT0Calibration (const EventContext &ctx, const Identifier &id, float time) const
StatusCode initializeGasProperties ()
std::optional< Amg::Vector2DlocalStripPosition (const EventContext &ctx, const Identifier &id) const

Private Attributes

ServiceHandle< IMuonIdHelperSvcm_idHelperSvc {this, "MuonIdHelperSvc", "MuonIdHelperSvc/MuonIdHelperSvc"}
SG::ReadCondHandleKey< AtlasFieldCacheCondObjm_fieldCondObjInputKey {this, "AtlasFieldCacheCondObj", "fieldCondObj"}
SG::ReadCondHandleKey< MuonGM::MuonDetectorManagerm_muDetMgrKey {this, "DetectorManagerKey", "MuonDetectorManager", "Key of input MuonDetectorManager condition data"}
SG::ReadCondHandleKey< NswCalibDbTimeChargeDatam_condTdoPdoKey {this, "condTdoPdoKey", "NswCalibDbTimeChargeData", "Key of NswCalibDbTimeChargeData object containing calibration data (TDO and PDO)"}
SG::ReadCondHandleKey< NswT0Datam_condT0Key {this, "condT0Key", "NswT0Data", "Key of NswT0Data containing the t0 calibration data"}
Gaudi::Property< bool > m_isData {this, "isData", false, "Processing data"}
Gaudi::Property< bool > m_CalibDriftVelocityFromData {this, "calibrateDriftVelocityFromData", false, "calibrateDriftVelocityFromData"}
SG::ReadCondHandleKey< MmCTPClusterCalibDatam_ctpClusterCalibKey {this, "CTPClusterCalibKey", "MmCTPClusterCalibData", "Key of the CTP cluster calibration corrections"}
Gaudi::Property< double > m_vDrift {this, "DriftVelocity",0.047, "Drift velocity"}
Gaudi::Property< double > m_timeRes {this, "TimeResolution", 25., "Time resolution"}
Gaudi::Property< double > m_longDiff {this, "longDiff", 0.019}
Gaudi::Property< double > m_transDiff {this, "transDiff", 0.036}
Gaudi::Property< double > m_ionUncertainty {this,"ionUncertainty", 4.0}
Gaudi::Property< float > m_mmPeakTime {this, "mmPeakTime", 200.}
Gaudi::Property< float > m_stgcPeakTime {this, "sTgcPeakTime", 0.}
Gaudi::Property< std::string > m_gasMixture {this, "GasMixture", "ArCo2_937"}
Gaudi::Property< float > m_mmLatencyMC {this,"mmLatencyMC",25}
Gaudi::Property< float > m_mmLatencyData {this,"mmLatencyData",0}
Gaudi::Property< float > m_stgcLatencyMC {this,"stgcLatencyMC",-50}
Gaudi::Property< float > m_stgcLatencyData {this,"stgcLatencyData",-50}
Gaudi::Property< bool > m_applyMmT0Calib {this, "applyMmT0Calib", false, "apply the MM t0 calibration"}
Gaudi::Property< bool > m_applysTgcT0Calib {this, "applysTgcT0Calib", false, "apply the sTGC t0 calibration"}
Gaudi::Property< bool > m_applyMmBFieldCalib {this, "applyMmBFieldCalib", true, "apply the MM BField correction in reconstruction"}
Gaudi::Property< float > m_mmT0TargetValue {this, "mmT0TargetValue", 50.0, "target mean value for the MM t0 calibration"}
Gaudi::Property< float > m_stgcT0TargetValue {this,"stgcT0TargetValue", 0.0 ,"target mean value for the sTGC t0 calibration"}
double m_interactionDensitySigma {0.0F}
double m_interactionDensityMean {0.0F}
angleFunction m_lorentzAngleFunction {NSWCalib::MicroMegaGas::dummy_func()}

Detailed Description

Definition at line 26 of file NSWCalibTool.h.

Member Typedef Documentation

◆ angleFunction

◆ TimeCalibConst

◆ TimeCalibType

Constructor & Destructor Documentation

◆ ~NSWCalibTool()

virtual Muon::NSWCalibTool::~NSWCalibTool ( )
virtualdefault

Member Function Documentation

◆ applyT0Calibration()

float Muon::NSWCalibTool::applyT0Calibration ( const EventContext & ctx,
const Identifier & id,
float time ) const
private

Definition at line 458 of file NSWCalibTool.cxx.

458 {
459 const NswT0Data* readT0{nullptr};
460 if(!SG::get(readT0, m_condT0Key, ctx).isSuccess()){
461 ATH_MSG_ERROR("Cannot find conditions data container for T0s!");
462 }
463 std::optional<float> t0 = readT0->getT0(id);
464 if(!t0){
465 ATH_MSG_DEBUG("failed to retrieve good t0 from database, skipping t0 calibration");
466 return time;
467 }
468 const auto& targetT0 = (m_idHelperSvc->isMM(id) ? m_mmT0TargetValue : m_stgcT0TargetValue);
469 float newTime = time + (targetT0 - (*t0));
470 ATH_MSG_DEBUG("doing T0 calibration for RDO " << m_idHelperSvc->toString(id) << " time " << time
471 <<" t0 from database " << (*t0) << " t0 target " << targetT0 << " new time " << newTime);
472 return newTime;
473
474}
#define ATH_MSG_ERROR(x)
#define ATH_MSG_DEBUG(x)
static Double_t t0
Gaudi::Property< float > m_mmT0TargetValue
SG::ReadCondHandleKey< NswT0Data > m_condT0Key
Gaudi::Property< float > m_stgcT0TargetValue
ServiceHandle< IMuonIdHelperSvc > m_idHelperSvc
std::optional< float > getT0(const Identifier &channelId) const
Retrieve the t0 calibration constant for a given NSW channel.
Definition NswT0Data.cxx:62
time(flags, cells_name, *args, **kw)
const T * get(const ReadCondHandleKey< T > &key, const EventContext &ctx)
Convenience function to retrieve an object given a ReadCondHandleKey.

◆ calibrateClus() [1/2]

StatusCode Muon::NSWCalibTool::calibrateClus ( const EventContext & ctx,
const ActsTrk::GeometryContext & gctx,
const xAOD::MMCluster & prepData,
const Amg::Vector3D & globalPos,
std::vector< NSWCalib::CalibratedStrip > & calibClus ) const
override

magnetic field

get the component parallel to to the eta strips (same used in digitization)

swap sign depending on the readout side

loop over prepData strips

Definition at line 116 of file NSWCalibTool.cxx.

120 {
121
122 double lorentzAngle {0.};
125 MagField::AtlasFieldCache fieldCache;
126 ATH_CHECK(loadMagneticField(ctx, fieldCache));
127 Amg::Vector3D magneticField{Amg::Vector3D::Zero()};
128 fieldCache.getField(globalPos.data(), magneticField.data());
129
131 double phi = globalPos.phi();
132 double bfield = (magneticField.x()*std::sin(phi)-magneticField.y()*std::cos(phi))*1000.;
133
135 int gasGap = m_idHelperSvc->mmIdHelper().gasGap(prepData.identify());
136 bool changeSign = ( globalPos.z() < 0. ? (gasGap==1 || gasGap==3) : (gasGap==2 || gasGap==4) );
137 if (changeSign) bfield = -bfield;
138
140 lorentzAngle = (bfield>0. ? 1. : -1.)*m_lorentzAngleFunction(std::abs(bfield)) * toRad;
141 }
142
144 for (unsigned int i = 0; i < prepData.stripNumbers().size(); ++i){
145 Identifier id = m_idHelperSvc->mmIdHelper().channelID(prepData.identify(), m_idHelperSvc->mmIdHelper().multilayer(prepData.identify()), m_idHelperSvc->mmIdHelper().gasGap(prepData.identify()),prepData.stripNumbers().at(i));
146 double time = prepData.stripTimes().at(i);
147 double charge = prepData.stripCharges().at(i);
148 //Retrieve pointing constraint
149 const Amg::Vector3D& globPos{prepData.readoutElement()->localToGlobalTransform(gctx, prepData.layerHash()) * (prepData.localPosition<1>()[0]*Amg::Vector3D::UnitX())};
150 NSWCalib::CalibratedStrip calibStrip;
151 ATH_CHECK(calibrateStrip(ctx, id, time, charge, (globPos.theta() / toRad) , lorentzAngle, calibStrip));
152
153 calibClus.push_back(std::move(calibStrip));
154 }
155 return StatusCode::SUCCESS;
156}
Scalar phi() const
phi method
#define ATH_CHECK
Evaluate an expression and check for errors.
double charge(const T &p)
Definition AtlasPID.h:997
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 & localToGlobalTransform(const ActsTrk::GeometryContext &ctx) const
Returns the transformation from the local coordinate system of the readout element into the global AT...
angleFunction m_lorentzAngleFunction
Gaudi::Property< bool > m_applyMmBFieldCalib
StatusCode loadMagneticField(const EventContext &ctx, MagField::AtlasFieldCache &fieldCache) 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
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, 3, 1 > Vector3D

◆ calibrateClus() [2/2]

StatusCode Muon::NSWCalibTool::calibrateClus ( const EventContext & ctx,
const MMPrepData * prepData,
const Amg::Vector3D & globalPos,
std::vector< NSWCalib::CalibratedStrip > & calibClus ) const
override

magnetic field

get the component parallel to to the eta strips (same used in digitization)

swap sign depending on the readout side

loop over prepData strips

Definition at line 77 of file NSWCalibTool.cxx.

77 {
78
79 double lorentzAngle {0.};
82 MagField::AtlasFieldCache fieldCache;
83 ATH_CHECK(loadMagneticField(ctx, fieldCache));
84 Amg::Vector3D magneticField{Amg::Vector3D::Zero()};
85 fieldCache.getField(globalPos.data(), magneticField.data());
86
88 double phi = globalPos.phi();
89 double bfield = (magneticField.x()*std::sin(phi)-magneticField.y()*std::cos(phi))*1000.;
90
92 int gasGap = m_idHelperSvc->mmIdHelper().gasGap(prepData->identify());
93 bool changeSign = ( globalPos.z() < 0. ? (gasGap==1 || gasGap==3) : (gasGap==2 || gasGap==4) );
94 if (changeSign) bfield = -bfield;
95
97 lorentzAngle = (bfield>0. ? 1. : -1.)*m_lorentzAngleFunction(std::abs(bfield)) * toRad;
98 }
99
101 for (unsigned int i = 0; i < prepData->stripNumbers().size(); ++i){
102 Identifier id = prepData->rdoList().at(i);
103 double time = prepData->stripTimes().at(i);
104 double charge = prepData->stripCharges().at(i);
105 //Retrieve pointing constraint
106 const Amg::Vector3D& globPos{prepData->globalPosition()};
107 NSWCalib::CalibratedStrip calibStrip;
108 ATH_CHECK(calibrateStrip(ctx, id, time, charge, (globPos.theta() / toRad) , lorentzAngle, calibStrip));
109
110 calibClus.push_back(std::move(calibStrip));
111 }
112 return StatusCode::SUCCESS;
113}

◆ calibrateStrip() [1/3]

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
override

transversal and longitudinal components of the resolution

Definition at line 160 of file NSWCalibTool.cxx.

166 {
167 //get local positon
168 auto locPos = localStripPosition(ctx, id);
169 if(!locPos) {
170 ATH_MSG_WARNING(__FILE__<<":"<<__LINE__<<" Failed to retrieve local strip position "<<m_idHelperSvc->toString(id));
171 return StatusCode::FAILURE;
172 }
173
174 calibStrip.identifier = id;
175 calibStrip.charge = charge;
176 calibStrip.time = time;
177
178 const MmIdHelper& idHelper{m_idHelperSvc->mmIdHelper()};
179
180 //retrieve identifier for the gas gap, not necessarily for the channel
181 //There is no pcb segmentation for these corrections, stored with pcb = 1 as default
182 Identifier gasGapId = idHelper.channelID(id,
183 idHelper.multilayer(id),
184 idHelper.gasGap(id), 1);
185
186 double vDrift = m_vDrift; //nominal value from Garfield simulation
187
189 const MmCTPClusterCalibData* ctpCalibData{nullptr};
190 ATH_CHECK(SG::get(ctpCalibData, m_ctpClusterCalibKey, ctx));
191 vDrift = ctpCalibData->getCTPCorrectedDriftVelocity(gasGapId, theta);
192
193 //Calculate the new half max possible time based on the new drift velocity
194 float max_half_drifttime = (vDrift != 0 ) ? 2.5/vDrift : 50.;
195
196 //Shift the mean of the time to account for different values of drift velocities
197 calibStrip.time = time + (max_half_drifttime - m_mmT0TargetValue);
198 ATH_MSG_VERBOSE( "Original drift time: " << time << " new max half drift time: " << max_half_drifttime
199 << " new time: " << calibStrip.time << " targett0 " << m_mmT0TargetValue );
200 }
201
202
203 double vDriftCorrected = vDrift * std::cos(lorentzAngle);
204
205 calibStrip.distDrift = vDriftCorrected * calibStrip.time;
206
208 calibStrip.resTransDistDrift = pitchErr + std::pow(m_transDiff * calibStrip.distDrift, 2);
209 calibStrip.resLongDistDrift = std::pow(m_ionUncertainty * vDriftCorrected, 2)
210 + std::pow(m_longDiff * calibStrip.distDrift, 2);
211 calibStrip.dx = std::sin(lorentzAngle) * calibStrip.time * vDrift;
212 calibStrip.locPos = Amg::Vector2D{locPos->x() + calibStrip.dx, locPos->y()};
213 return StatusCode::SUCCESS;
214}
Scalar theta() const
theta method
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
Identifier channelID(int stationName, int stationEta, int stationPhi, int multilayer, int gasGap, int channel) const
int gasGap(const Identifier &id) const override
get the hashes
int multilayer(const Identifier &id) const
Gaudi::Property< bool > m_CalibDriftVelocityFromData
Gaudi::Property< double > m_ionUncertainty
SG::ReadCondHandleKey< MmCTPClusterCalibData > m_ctpClusterCalibKey
Gaudi::Property< double > m_transDiff
Gaudi::Property< double > m_longDiff
Gaudi::Property< double > m_vDrift
std::optional< Amg::Vector2D > localStripPosition(const EventContext &ctx, const Identifier &id) const
Eigen::Matrix< double, 2, 1 > Vector2D

◆ calibrateStrip() [2/3]

StatusCode Muon::NSWCalibTool::calibrateStrip ( const EventContext & ctx,
const MM_RawData * mmRawData,
NSWCalib::CalibratedStrip & calibStrip ) const
override

Hopefully this does not trigger the T0 reference test....

Definition at line 217 of file NSWCalibTool.cxx.

219 {
220
221 const Identifier& rdoId = mmRawData->identify();
222
223 const MuonGM::MuonDetectorManager* muDetMgr{nullptr};
224 ATH_CHECK(SG::get(muDetMgr, m_muDetMgrKey, ctx));
225
226 //get globalPos
227 Amg::Vector3D globalPos{Amg::Vector3D::Zero()};
228 const MuonGM::MMReadoutElement* detEl = muDetMgr->getMMReadoutElement(rdoId);
229 if (!detEl->stripGlobalPosition(rdoId, globalPos)) {
230 ATH_MSG_WARNING(__func__<<"() "<<__LINE__<<" - Failed to fetch global position for "
231 <<m_idHelperSvc->toString(rdoId));
232 return StatusCode::FAILURE;
233 }
234
235 // RDO has values in counts for both simulation and data
236 float time{-std::numeric_limits<float>::max()},
237 charge{-std::numeric_limits<float>::max()};
238 tdoToTime (ctx, mmRawData->timeAndChargeInCounts(), mmRawData->time(), rdoId, time, mmRawData->relBcid());
239 pdoToCharge(ctx, mmRawData->timeAndChargeInCounts(), mmRawData->charge(), rdoId, charge);
240
241 calibStrip.charge = charge;
242 // historically the peak time is included in the time determined by the MM digitization and therefore added back in the tdoToTime function
243 // in order to not break the RDO to digit conversion needed for the trigger and the overlay
244 calibStrip.time = time - globalPos.norm() * reciprocalSpeedOfLight - mmPeakTime();
245 // applying T0 calibration, cannot be done inside the the tdo to time function since the tof correction was included when deriving the calibration constants
247 calibStrip.time = applyT0Calibration(ctx, rdoId, calibStrip.time);
248 }
249
250 calibStrip.identifier = rdoId;
251
252 ATH_MSG_DEBUG(__func__<<"() "<<__LINE__<<" - Calibrating RDO " << m_idHelperSvc->toString(rdoId)
253 << " with pdo: " << mmRawData->charge() << ", tdo: "<< mmRawData->time()
254 << ", relBCID "<< mmRawData->relBcid() << ", charge and time in counts: "
255 << mmRawData->timeAndChargeInCounts() <<", "<< m_isData << " to charge: "
256 << calibStrip.charge << " electrons time after corrections " << calibStrip.time
257 << " ns time before corrections "<< time << "ns");
258 //get stripWidth
259 detEl->getDesign(rdoId)->channelWidth(); // positon is not used for strip width
260
261 calibStrip.distDrift = m_vDrift * calibStrip.time;
262 calibStrip.resTransDistDrift = pitchErr + std::pow(m_transDiff * calibStrip.distDrift, 2);
263 calibStrip.resLongDistDrift = std::pow(m_ionUncertainty * m_vDrift, 2)
264 + std::pow(m_longDiff * calibStrip.distDrift, 2);
265
267 detEl->surface(rdoId).globalToLocal(globalPos, Amg::Vector3D::Zero(), calibStrip.locPos);
268
269 return StatusCode::SUCCESS;
270}
const MuonChannelDesign * getDesign(const Identifier &id) const
returns the MuonChannelDesign class for the given identifier
bool stripGlobalPosition(const Identifier &id, Amg::Vector3D &gpos) const
virtual const Trk::PlaneSurface & surface() const override
access to chamber surface (phi orientation), uses the first gas gap
const MMReadoutElement * getMMReadoutElement(const Identifier &id) const
access via extended identifier (requires unpacking)
bool tdoToTime(const EventContext &ctx, const bool inCounts, const int tdo, const Identifier &chnlId, float &time, const int relBCID) const override
Gaudi::Property< bool > m_applyMmT0Calib
SG::ReadCondHandleKey< MuonGM::MuonDetectorManager > m_muDetMgrKey
float applyT0Calibration(const EventContext &ctx, const Identifier &id, float time) const
float mmPeakTime() const override
bool pdoToCharge(const EventContext &ctx, const bool inCounts, const int pdo, const Identifier &chnlId, float &charge) const override
Gaudi::Property< bool > m_isData
virtual bool globalToLocal(const Amg::Vector3D &glob, const Amg::Vector3D &mom, Amg::Vector2D &loc) const override final
Specified for PlaneSurface: GlobalToLocal method without dynamic memory allocation - boolean checks i...
double channelWidth() const
calculate local channel width

◆ calibrateStrip() [3/3]

StatusCode Muon::NSWCalibTool::calibrateStrip ( const EventContext & ctx,
const STGC_RawData * sTGCRawData,
NSWCalib::CalibratedStrip & calibStrip ) const
override

Hopefully this does not trigger the T0 reference test....

Definition at line 272 of file NSWCalibTool.cxx.

274 {
275
276 const Identifier& rdoId = sTGCRawData->identify();
277 const MuonGM::MuonDetectorManager* muDetMgr{nullptr};
278 ATH_CHECK(SG::get(muDetMgr, m_muDetMgrKey, ctx));
279
280 //get globalPos
281 Amg::Vector3D globalPos{Amg::Vector3D::Zero()};
282 const MuonGM::sTgcReadoutElement* detEl = muDetMgr->getsTgcReadoutElement(rdoId);
283 if (!detEl->stripGlobalPosition(rdoId,globalPos)) {
284 ATH_MSG_WARNING(__func__<<"() "<<__LINE__<<" - Failed to retrieve a valid global position for "
285 <<m_idHelperSvc->toString(rdoId));
286 return StatusCode::FAILURE;
287 }
288 // RDO has values in counts for both simulation and data
289 float time{-std::numeric_limits<float>::max()}, charge{-std::numeric_limits<float>::max()};
290 tdoToTime(ctx, sTGCRawData->timeAndChargeInCounts(), sTGCRawData->time(), rdoId, time, sTGCRawData->bcTag());
291 pdoToCharge(ctx, sTGCRawData->timeAndChargeInCounts(), sTGCRawData->charge(), rdoId, charge);
292 if(sTGCRawData->timeAndChargeInCounts()){
293 calibStrip.charge = charge * sTGC_pCPerfC;
294 } else {
295 calibStrip.charge = charge;
296 }
297 calibStrip.time = time - stgcPeakTime();
298
300 calibStrip.time = applyT0Calibration(ctx, rdoId, calibStrip.time);
301 }
302
303 calibStrip.identifier = rdoId;
305 detEl->surface(rdoId).globalToLocal(globalPos, Amg::Vector3D::Zero(), calibStrip.locPos);
306
307 return StatusCode::SUCCESS;
308
309}
const sTgcReadoutElement * getsTgcReadoutElement(const Identifier &id) const
access via extended identifier (requires unpacking)
bool stripGlobalPosition(const Identifier &id, Amg::Vector3D &gpos) const
float stgcPeakTime() const override
Gaudi::Property< bool > m_applysTgcT0Calib

◆ chargeToPdo()

bool Muon::NSWCalibTool::chargeToPdo ( const EventContext & ctx,
const float charge,
const Identifier & chnlId,
int & pdo ) const
override

Definition at line 346 of file NSWCalibTool.cxx.

346 {
347 const NswCalibDbTimeChargeData* tdoPdoData{nullptr};
348 if (!SG::get(tdoPdoData, m_condTdoPdoKey, ctx)) {
349 pdo = 0;
350 return false;
351 }
352 const TimeCalibConst* calib_ptr = tdoPdoData->getCalibForChannel(TimeCalibType::PDO, chnlId);
353 if (!calib_ptr) {
354 pdo = 0;
355 return false;
356 }
357 const TimeCalibConst& calib{*calib_ptr};
358 float c = charge;
359 if (m_idHelperSvc->isMM (chnlId)) c /= MM_electronsPerfC;
360 else if(m_idHelperSvc->issTgc(chnlId)) c *= sTGC_pCPerfC;
361 else {
362 pdo = 0;
363 return false;
364 }
365 pdo = c * calib.slope + calib.intercept;
366 return true;
367}
SG::ReadCondHandleKey< NswCalibDbTimeChargeData > m_condTdoPdoKey
NswCalibDbTimeChargeData::CalibConstants TimeCalibConst
const CalibConstants * getCalibForChannel(const CalibDataType type, const Identifier &channelId) const
Retrieves the calibration constant for a particular readout channel.

◆ distToTime()

StatusCode Muon::NSWCalibTool::distToTime ( const EventContext & ctx,
const MMPrepData * prepData,
const Amg::Vector3D & globalPos,
const std::vector< double > & driftDistances,
std::vector< double > & driftTimes ) const
override

retrieve the magnetic field

get the component parallel to to the eta strips (same used in digitization)

swap sign depending on the readout side

loop over drift distances

Definition at line 316 of file NSWCalibTool.cxx.

320 {
322 MagField::AtlasFieldCache fieldCache;
323 ATH_CHECK(loadMagneticField(ctx, fieldCache));
324 Amg::Vector3D magneticField{Amg::Vector3D::Zero()};
325 fieldCache.getField(globalPos.data(), magneticField.data());
326
328 const double phi = globalPos.phi();
329 double bfield = (magneticField.x()*std::sin(phi)-magneticField.y()*std::cos(phi))*1000.;
330
332 int gasGap = m_idHelperSvc->mmIdHelper().gasGap(prepData->identify());
333 bool changeSign = ( globalPos.z() < 0. ? (gasGap==1 || gasGap==3) : (gasGap==2 || gasGap==4) );
334 if (changeSign) bfield = -bfield;
335 double cos2_lorentzAngle = std::pow(std::cos ( (bfield>0. ? 1. : -1.)*m_lorentzAngleFunction(std::abs(bfield)) * toRad), 2);
337 for (const double dist : driftDistances){
338 double time = dist / (m_vDrift*cos2_lorentzAngle);
339 driftTimes.push_back(time);
340 }
341 return StatusCode::SUCCESS;
342
343}

◆ initialize()

StatusCode Muon::NSWCalibTool::initialize ( )
overridevirtual

Definition at line 49 of file NSWCalibTool.cxx.

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}
SG::ReadCondHandleKey< AtlasFieldCacheCondObj > m_fieldCondObjInputKey
StatusCode initializeGasProperties()

◆ initializeGasProperties()

StatusCode Muon::NSWCalibTool::initializeGasProperties ( )
private

Definition at line 63 of file NSWCalibTool.cxx.

63 {
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}
#define ATH_MSG_FATAL(x)
double m_interactionDensityMean
double m_interactionDensitySigma
Gaudi::Property< std::string > m_gasMixture

◆ loadMagneticField()

StatusCode Muon::NSWCalibTool::loadMagneticField ( const EventContext & ctx,
MagField::AtlasFieldCache & fieldCache ) const
private

Definition at line 310 of file NSWCalibTool.cxx.

310 {
311 const AtlasFieldCacheCondObj* condObj{};
313 condObj->getInitializedCache(fieldCache);
314 return StatusCode::SUCCESS;
315}
void getInitializedCache(MagField::AtlasFieldCache &cache) const
get B field cache for evaluation as a function of 2-d or 3-d position.

◆ localStripPosition()

std::optional< Amg::Vector2D > Muon::NSWCalibTool::localStripPosition ( const EventContext & ctx,
const Identifier & id ) const
private

Definition at line 518 of file NSWCalibTool.cxx.

519 {
520
521 const MuonGM::MuonDetectorManager* muDetMgr{nullptr};
522 if (!SG::get(muDetMgr, m_muDetMgrKey, ctx)) {
523 THROW_EXCEPTION("Failed to retrieve the detector manager");
524 }
525 Amg::Vector2D locPos{Amg::Vector2D::Zero()};
526 if(m_idHelperSvc->isMM(id)){
527 if (!muDetMgr->getMMReadoutElement(id)->stripPosition(id,locPos)) {
528 return std::nullopt;
529 }
530 } else if(m_idHelperSvc->issTgc(id)){
531 if (!muDetMgr->getsTgcReadoutElement(id)->stripPosition(id,locPos)) {
532 return std::nullopt;
533 }
534 } else {
535 ATH_MSG_WARNING("Non NSW identifier "<<m_idHelperSvc->toString(id));
536 return std::nullopt;
537 }
538 return locPos;
539}
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,...
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...
#define THROW_EXCEPTION(MESSAGE)
Definition throwExcept.h:10

◆ mmGasProperties()

NSWCalib::MicroMegaGas Muon::NSWCalibTool::mmGasProperties ( ) const
override

Definition at line 506 of file NSWCalibTool.cxx.

506 {
507 NSWCalib::MicroMegaGas properties{};
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}

◆ mmPeakTime()

float Muon::NSWCalibTool::mmPeakTime ( ) const
inlineoverride

Definition at line 59 of file NSWCalibTool.h.

59{return m_mmPeakTime; }
Gaudi::Property< float > m_mmPeakTime

◆ pdoToCharge()

bool Muon::NSWCalibTool::pdoToCharge ( const EventContext & ctx,
const bool inCounts,
const int pdo,
const Identifier & chnlId,
float & charge ) const
override

Definition at line 370 of file NSWCalibTool.cxx.

374 {
375 if(!inCounts){
376 charge = pdo;
377 return true;
378 }
379 const NswCalibDbTimeChargeData* tdoPdoData{nullptr};
380 if (!SG::get(tdoPdoData, m_condTdoPdoKey, ctx)) {
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}

◆ stgcPeakTime()

float Muon::NSWCalibTool::stgcPeakTime ( ) const
inlineoverride

Definition at line 60 of file NSWCalibTool.h.

60{return m_stgcPeakTime;}
Gaudi::Property< float > m_stgcPeakTime

◆ tdoToTime()

bool Muon::NSWCalibTool::tdoToTime ( const EventContext & ctx,
const bool inCounts,
const int tdo,
const Identifier & chnlId,
float & time,
const int relBCID ) const
override

Definition at line 478 of file NSWCalibTool.cxx.

478 {
479 if(!inCounts){
480 time = tdo;
481 return true;
482 }
483 const NswCalibDbTimeChargeData* tdoPdoData{nullptr};
484 if (!SG::get(tdoPdoData, m_condTdoPdoKey, ctx)){
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}
Gaudi::Property< float > m_mmLatencyData
Gaudi::Property< float > m_mmLatencyMC
Gaudi::Property< float > m_stgcLatencyMC
Gaudi::Property< float > m_stgcLatencyData

◆ timeToTdo()

bool Muon::NSWCalibTool::timeToTdo ( const EventContext & ctx,
const float time,
const Identifier & chnlId,
int & tdo,
int & relBCID ) const
override

Definition at line 398 of file NSWCalibTool.cxx.

398 {
399 const NswCalibDbTimeChargeData* tdoPdoData{nullptr};
400 if (!SG::get(tdoPdoData, m_condTdoPdoKey, ctx)) 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}
bool timeToTdoMM(const NswCalibDbTimeChargeData *tdoPdoData, const float time, const Identifier &chnlId, int &tdo, int &relBCID) const
bool timeToTdoSTGC(const NswCalibDbTimeChargeData *tdoPdoData, const float time, const Identifier &chnlId, int &tdo, int &relBCID) const

◆ timeToTdoMM()

bool Muon::NSWCalibTool::timeToTdoMM ( const NswCalibDbTimeChargeData * tdoPdoData,
const float time,
const Identifier & chnlId,
int & tdo,
int & relBCID ) const
private

Definition at line 407 of file NSWCalibTool.cxx.

407 {
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}
static constexpr int s_BCWindow
Definition MM_RawData.h:75
static constexpr double s_lowerTimeBound
Definition MM_RawData.h:72

◆ timeToTdoSTGC()

bool Muon::NSWCalibTool::timeToTdoSTGC ( const NswCalibDbTimeChargeData * tdoPdoData,
const float time,
const Identifier & chnlId,
int & tdo,
int & relBCID ) const
private

Definition at line 433 of file NSWCalibTool.cxx.

433 {
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}
static constexpr int s_BCWindow
static constexpr double s_lowerTimeBound

Member Data Documentation

◆ m_applyMmBFieldCalib

Gaudi::Property<bool> Muon::NSWCalibTool::m_applyMmBFieldCalib {this, "applyMmBFieldCalib", true, "apply the MM BField correction in reconstruction"}
private

Definition at line 104 of file NSWCalibTool.h.

104{this, "applyMmBFieldCalib", true, "apply the MM BField correction in reconstruction"};

◆ m_applyMmT0Calib

Gaudi::Property<bool> Muon::NSWCalibTool::m_applyMmT0Calib {this, "applyMmT0Calib", false, "apply the MM t0 calibration"}
private

Definition at line 101 of file NSWCalibTool.h.

101{this, "applyMmT0Calib", false, "apply the MM t0 calibration"};

◆ m_applysTgcT0Calib

Gaudi::Property<bool> Muon::NSWCalibTool::m_applysTgcT0Calib {this, "applysTgcT0Calib", false, "apply the sTGC t0 calibration"}
private

Definition at line 102 of file NSWCalibTool.h.

102{this, "applysTgcT0Calib", false, "apply the sTGC t0 calibration"};

◆ m_CalibDriftVelocityFromData

Gaudi::Property<bool> Muon::NSWCalibTool::m_CalibDriftVelocityFromData {this, "calibrateDriftVelocityFromData", false, "calibrateDriftVelocityFromData"}
private

Definition at line 78 of file NSWCalibTool.h.

78{this, "calibrateDriftVelocityFromData", false, "calibrateDriftVelocityFromData"};

◆ m_condT0Key

SG::ReadCondHandleKey<NswT0Data> Muon::NSWCalibTool::m_condT0Key {this, "condT0Key", "NswT0Data", "Key of NswT0Data containing the t0 calibration data"}
private

Definition at line 74 of file NSWCalibTool.h.

74{this, "condT0Key", "NswT0Data", "Key of NswT0Data containing the t0 calibration data"};

◆ m_condTdoPdoKey

SG::ReadCondHandleKey<NswCalibDbTimeChargeData> Muon::NSWCalibTool::m_condTdoPdoKey {this, "condTdoPdoKey", "NswCalibDbTimeChargeData", "Key of NswCalibDbTimeChargeData object containing calibration data (TDO and PDO)"}
private

Definition at line 73 of file NSWCalibTool.h.

73{this, "condTdoPdoKey", "NswCalibDbTimeChargeData", "Key of NswCalibDbTimeChargeData object containing calibration data (TDO and PDO)"};

◆ m_ctpClusterCalibKey

SG::ReadCondHandleKey<MmCTPClusterCalibData> Muon::NSWCalibTool::m_ctpClusterCalibKey {this, "CTPClusterCalibKey", "MmCTPClusterCalibData", "Key of the CTP cluster calibration corrections"}
private

Definition at line 79 of file NSWCalibTool.h.

79{this, "CTPClusterCalibKey", "MmCTPClusterCalibData", "Key of the CTP cluster calibration corrections"};

◆ m_fieldCondObjInputKey

SG::ReadCondHandleKey<AtlasFieldCacheCondObj> Muon::NSWCalibTool::m_fieldCondObjInputKey {this, "AtlasFieldCacheCondObj", "fieldCondObj"}
private

Definition at line 71 of file NSWCalibTool.h.

71{this, "AtlasFieldCacheCondObj", "fieldCondObj"};

◆ m_gasMixture

Gaudi::Property<std::string> Muon::NSWCalibTool::m_gasMixture {this, "GasMixture", "ArCo2_937"}
private

Definition at line 90 of file NSWCalibTool.h.

90{this, "GasMixture", "ArCo2_937"};

◆ m_idHelperSvc

ServiceHandle<IMuonIdHelperSvc> Muon::NSWCalibTool::m_idHelperSvc {this, "MuonIdHelperSvc", "MuonIdHelperSvc/MuonIdHelperSvc"}
private

Definition at line 70 of file NSWCalibTool.h.

70{this, "MuonIdHelperSvc", "MuonIdHelperSvc/MuonIdHelperSvc"};

◆ m_interactionDensityMean

double Muon::NSWCalibTool::m_interactionDensityMean {0.0F}
private

Definition at line 112 of file NSWCalibTool.h.

112{0.0F};

◆ m_interactionDensitySigma

double Muon::NSWCalibTool::m_interactionDensitySigma {0.0F}
private

Definition at line 111 of file NSWCalibTool.h.

111{0.0F};

◆ m_ionUncertainty

Gaudi::Property<double> Muon::NSWCalibTool::m_ionUncertainty {this,"ionUncertainty", 4.0}
private

Definition at line 87 of file NSWCalibTool.h.

87{this,"ionUncertainty", 4.0}; //ns

◆ m_isData

Gaudi::Property<bool> Muon::NSWCalibTool::m_isData {this, "isData", false, "Processing data"}
private

Definition at line 76 of file NSWCalibTool.h.

76{this, "isData", false, "Processing data"};

◆ m_longDiff

Gaudi::Property<double> Muon::NSWCalibTool::m_longDiff {this, "longDiff", 0.019}
private

Definition at line 85 of file NSWCalibTool.h.

85{this, "longDiff", 0.019}; // mm/ mm

◆ m_lorentzAngleFunction

angleFunction Muon::NSWCalibTool::m_lorentzAngleFunction {NSWCalib::MicroMegaGas::dummy_func()}
private

Definition at line 115 of file NSWCalibTool.h.

static angleFunction dummy_func()
Dummy function to be used for the initialization.

◆ m_mmLatencyData

Gaudi::Property<float> Muon::NSWCalibTool::m_mmLatencyData {this,"mmLatencyData",0}
private

Definition at line 95 of file NSWCalibTool.h.

95{this,"mmLatencyData",0}; //tuned with 2023 data, should not change anymore.

◆ m_mmLatencyMC

Gaudi::Property<float> Muon::NSWCalibTool::m_mmLatencyMC {this,"mmLatencyMC",25}
private

Definition at line 94 of file NSWCalibTool.h.

94{this,"mmLatencyMC",25};

◆ m_mmPeakTime

Gaudi::Property<float> Muon::NSWCalibTool::m_mmPeakTime {this, "mmPeakTime", 200.}
private

Definition at line 88 of file NSWCalibTool.h.

88{this, "mmPeakTime", 200.}; //ns

◆ m_mmT0TargetValue

Gaudi::Property<float> Muon::NSWCalibTool::m_mmT0TargetValue {this, "mmT0TargetValue", 50.0, "target mean value for the MM t0 calibration"}
private

Definition at line 107 of file NSWCalibTool.h.

107{this, "mmT0TargetValue", 50.0, "target mean value for the MM t0 calibration"};

◆ m_muDetMgrKey

SG::ReadCondHandleKey<MuonGM::MuonDetectorManager> Muon::NSWCalibTool::m_muDetMgrKey {this, "DetectorManagerKey", "MuonDetectorManager", "Key of input MuonDetectorManager condition data"}
private

Definition at line 72 of file NSWCalibTool.h.

72{this, "DetectorManagerKey", "MuonDetectorManager", "Key of input MuonDetectorManager condition data"};

◆ m_stgcLatencyData

Gaudi::Property<float> Muon::NSWCalibTool::m_stgcLatencyData {this,"stgcLatencyData",-50}
private

Definition at line 98 of file NSWCalibTool.h.

98{this,"stgcLatencyData",-50}; //this is temporary, need to align with what we find in data

◆ m_stgcLatencyMC

Gaudi::Property<float> Muon::NSWCalibTool::m_stgcLatencyMC {this,"stgcLatencyMC",-50}
private

Definition at line 97 of file NSWCalibTool.h.

97{this,"stgcLatencyMC",-50};

◆ m_stgcPeakTime

Gaudi::Property<float> Muon::NSWCalibTool::m_stgcPeakTime {this, "sTgcPeakTime", 0.}
private

Definition at line 89 of file NSWCalibTool.h.

89{this, "sTgcPeakTime", 0.}; // ns

◆ m_stgcT0TargetValue

Gaudi::Property<float> Muon::NSWCalibTool::m_stgcT0TargetValue {this,"stgcT0TargetValue", 0.0 ,"target mean value for the sTGC t0 calibration"}
private

Definition at line 108 of file NSWCalibTool.h.

108{this,"stgcT0TargetValue", 0.0 ,"target mean value for the sTGC t0 calibration"};

◆ m_timeRes

Gaudi::Property<double> Muon::NSWCalibTool::m_timeRes {this, "TimeResolution", 25., "Time resolution"}
private

Definition at line 84 of file NSWCalibTool.h.

84{this, "TimeResolution", 25., "Time resolution"};

◆ m_transDiff

Gaudi::Property<double> Muon::NSWCalibTool::m_transDiff {this, "transDiff", 0.036}
private

Definition at line 86 of file NSWCalibTool.h.

86{this, "transDiff", 0.036};

◆ m_vDrift

Gaudi::Property<double> Muon::NSWCalibTool::m_vDrift {this, "DriftVelocity",0.047, "Drift velocity"}
private

Definition at line 83 of file NSWCalibTool.h.

83{this, "DriftVelocity",0.047, "Drift velocity"};

The documentation for this class was generated from the following files: