6 #include "GaudiKernel/SystemOfUnits.h"
7 #include "GaudiKernel/PhysicalConstants.h"
12 constexpr
double toRad =
M_PI/180;
13 constexpr
double pitchErr = 0.425 * 0.425 / 12;
17 static const std::map<std::string, float> map_transDiff {{
"ArCo2_937", 0.036},
18 {
"ArCo2_8020", 0.019}, {
"ArCo2iC4H10_9352", 0.035}};
19 static const std::map<std::string, float> map_longDiff {{
"ArCo2_937", 0.019},
20 {
"ArCo2_8020", 0.022 }, {
"ArCo2iC4H10_9352", 0.0195}};
21 static const std::map<std::string, float> map_vDrift {{
"ArCo2_937", 0.047},
22 {
"ArCo2_8020", 0.040}, {
"ArCo2iC4H10_9352", 0.045}};
26 constexpr
double const MM_electronsPerfC = 6241.;
27 constexpr
double const sTGC_pCPerfC = 1000.;
33 static const std::map<std::string, angleFunction> map_lorentzAngleFunctionPars {
34 {
"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;}},
35 {
"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;}},
36 {
"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;}}};
39 static const std::map<std::string, float> map_interactionDensitySigma {{
"ArCo2_937", 4.04 / 5.},
40 {
"ArCo2_8020", 4.04 / 5.}, {
"ArCo2iC4H10_9352", 4.04 / 5.}};
41 static const std::map<std::string, float> map_interactionDensityMean {{
"ArCo2_937", 16.15 / 5.},
42 {
"ArCo2_8020", 16.15 / 5.}, {
"ArCo2iC4H10_9352", 16.15 / 5.}};
48 declareInterface<INSWCalibTool>(
this);
57 ATH_CHECK(m_condT0Key.initialize(m_applyMmT0Calib || m_applysTgcT0Calib));
58 ATH_CHECK(m_fieldCondObjInputKey.initialize( m_idHelperSvc->hasMM() && m_idHelperSvc->hasSTGC() ));
59 ATH_CHECK(m_muDetMgrKey.initialize( m_idHelperSvc->hasMM() && m_idHelperSvc->hasSTGC() ));
61 if ( m_idHelperSvc->hasMM() && m_idHelperSvc->hasSTGC() ) {
64 ATH_MSG_INFO(
"MM or STGC not part of initialized detector layout, skipping initialization");
67 return StatusCode::SUCCESS;
71 if (!map_vDrift.count(m_gasMixture)) {
72 ATH_MSG_FATAL(
"Configured Micromegas with unkown gas mixture: " << m_gasMixture);
73 return StatusCode::FAILURE;
76 m_vDrift = map_vDrift.find(m_gasMixture)->second;
77 m_transDiff = map_transDiff.find(m_gasMixture)->second;
78 m_longDiff = map_longDiff.find(m_gasMixture)->second;
79 m_interactionDensitySigma = map_interactionDensitySigma.find(m_gasMixture)->second;
80 m_interactionDensityMean = map_interactionDensityMean.find(m_gasMixture)->second;
81 m_lorentzAngleFunction = map_lorentzAngleFunctionPars.find(m_gasMixture)->second;
82 return StatusCode::SUCCESS;
88 if(!readTdoPdo.isValid()){
89 ATH_MSG_ERROR(
"Cannot find conditions data container for TDOs and PDOs!");
92 return readTdoPdo.cptr();
97 double lorentzAngle {0.};
98 if(m_applyMmBFieldCalib){
101 if (!loadMagneticField(ctx, fieldCache))
return StatusCode::FAILURE;
103 fieldCache.
getField(globalPos.data(), magneticField.data());
106 double phi = globalPos.phi();
110 int gasGap = m_idHelperSvc->mmIdHelper().gasGap(prepData->
identify());
112 if (changeSign) bfield = -bfield;
115 lorentzAngle = (bfield>0. ? 1. : -1.)*m_lorentzAngleFunction(std::abs(bfield)) * toRad;
125 calibClus.push_back(std::move(calibStrip));
127 return StatusCode::SUCCESS;
134 if(!localStripPosition(
id,locPos)) {
135 ATH_MSG_WARNING(__FILE__<<
":"<<__LINE__<<
" Failed to retrieve local strip position "<<m_idHelperSvc->toString(
id));
136 return StatusCode::FAILURE;
143 double vDriftCorrected = m_vDrift *
std::cos(lorentzAngle);
150 calibStrip.
dx =
std::sin(lorentzAngle) * calibStrip.
time * m_vDrift;
152 return StatusCode::SUCCESS;
161 if(!localStripPosition(rdoId,locPos)) {
162 ATH_MSG_WARNING(__FILE__<<
":"<<__LINE__<<
" Failed to retrieve local strip position "<<m_idHelperSvc->toString(rdoId));
163 return StatusCode::FAILURE;
183 calibStrip.
time =
time - globalPos.norm() * reciprocalSpeedOfLight - mmPeakTime();
185 if(m_applyMmT0Calib){
186 calibStrip.
time = applyT0Calibration(ctx, rdoId, calibStrip.
time);
191 ATH_MSG_DEBUG(
"Calibrating RDO " << m_idHelperSvc->toString(rdoId) <<
"with pdo: " << mmRawData->
charge() <<
" tdo: "<< mmRawData->
time() <<
" relBCID "<< mmRawData->
relBcid() <<
" charge and time in counts " <<
192 mmRawData->
timeAndChargeInCounts() <<
" isData "<< m_isData <<
" to charge: " << calibStrip.
charge <<
" electrons time after corrections " << calibStrip.
time <<
" ns time before corrections "<<
time <<
"ns");
203 calibStrip.
locPos = locPos;
205 return StatusCode::SUCCESS;
221 if(!localStripPosition(rdoId,locPos)) {
222 ATH_MSG_WARNING(__FILE__<<
":"<<__LINE__<<
" Failed to retrieve local strip position "<<m_idHelperSvc->toString(rdoId));
223 return StatusCode::FAILURE;
235 calibStrip.
time =
time - stgcPeakTime();
237 if(m_applysTgcT0Calib){
238 calibStrip.
time = applyT0Calibration(ctx, rdoId, calibStrip.
time);
242 calibStrip.
locPos = locPos;
243 return StatusCode::SUCCESS;
248 if (!readHandle.isValid()) {
249 ATH_MSG_ERROR(
"doDigitization: Failed to retrieve AtlasFieldCacheCondObj with key " << m_fieldCondObjInputKey.key());
252 readHandle.cptr()->getInitializedCache(fieldCache);
258 if (!loadMagneticField(ctx, fieldCache))
return StatusCode::FAILURE;
260 fieldCache.
getField(globalPos.data(), magneticField.data());
263 const double phi = globalPos.phi();
267 int gasGap = m_idHelperSvc->mmIdHelper().gasGap(prepData->
identify());
269 if (changeSign) bfield = -bfield;
270 double cos2_lorentzAngle =
std::pow(
std::cos ( (bfield>0. ? 1. : -1.)*m_lorentzAngleFunction(std::abs(bfield)) * toRad), 2);
272 for (
const double dist : driftDistances){
273 double time = dist / (m_vDrift*cos2_lorentzAngle);
274 driftTimes.push_back(
time);
276 return StatusCode::SUCCESS;
294 if (m_idHelperSvc->isMM (chnlId))
c /= MM_electronsPerfC;
295 else if(m_idHelperSvc->issTgc(chnlId))
c *= sTGC_pCPerfC;
322 if (m_idHelperSvc->isMM (chnlId))
charge *= MM_electronsPerfC;
323 else if(m_idHelperSvc->issTgc(chnlId))
charge /= sTGC_pCPerfC;
331 if (!tdoPdoData)
return false;
332 if (m_idHelperSvc->isMM (chnlId))
return timeToTdoMM (tdoPdoData,
time, chnlId, tdo, relBCID);
333 else if(m_idHelperSvc->issTgc(chnlId))
return timeToTdoSTGC(tdoPdoData,
time, chnlId, tdo, relBCID);
339 const float t =
time - m_mmPeakTime - m_mmLatencyMC;
346 float tdoTime = -999.9;
349 if(
t >= lowerBound+i_relBCID*25 &&
t < (lowerBound+25)+i_relBCID*25){
350 tdoTime = i_relBCID*25 -
t;
355 if(tdoTime < lowerBound) {
365 const float t =
time - m_stgcPeakTime - m_stgcLatencyMC;
372 float tdoTime = -999.9;
375 if(
t >= lowerBound+i_relBCID*25 &&
t < (lowerBound+25)+i_relBCID*25){
376 tdoTime = i_relBCID*25 -
t;
381 if(tdoTime < lowerBound) {
391 if(!readT0.isValid()){
392 ATH_MSG_ERROR(
"Cannot find conditions data container for T0s!");
395 bool isGood = readT0->getT0(
id,
t0);
396 if(!isGood ||
t0==0){
397 ATH_MSG_DEBUG(
"failed to retrieve good t0 from database, skipping t0 calibration");
400 float targetT0 = (m_idHelperSvc->isMM(
id) ? m_mmT0TargetValue : m_stgcT0TargetValue);
401 float newTime =
time + (targetT0 -
t0);
402 ATH_MSG_DEBUG(
"doing T0 calibration for RDO " << m_idHelperSvc->toString(
id) <<
" time " <<
time <<
" t0 from database " <<
t0 <<
" t0 target " << targetT0 <<
" new time " << newTime);
429 float mmLatency = (m_isData? m_mmLatencyData : m_mmLatencyMC );
430 float stgcLatency = (m_isData? m_stgcLatencyData : m_stgcLatencyMC);
432 const float peakTime = m_idHelperSvc->isMM(chnlId) ? mmPeakTime() + mmLatency : stgcPeakTime() + stgcLatency;
433 time = relBCID*25. - (tdo-
calib.intercept)/
calib.slope + peakTime;
440 properties.longitudinalDiffusionSigma = m_longDiff;
441 properties.transverseDiffusionSigma = m_transDiff;
442 properties.interactionDensityMean = m_interactionDensityMean;
443 properties.interactionDensitySigma = m_interactionDensitySigma;
444 properties.lorentzAngleFunction = m_lorentzAngleFunction;
453 if(m_idHelperSvc->isMM(
id)){
457 }
else if(m_idHelperSvc->issTgc(
id)){