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());
63 return StatusCode::SUCCESS;
67 if (!map_vDrift.count(m_gasMixture)) {
68 ATH_MSG_FATAL(
"Configured Micromegas with unkown gas mixture: " << m_gasMixture);
69 return StatusCode::FAILURE;
72 m_vDrift = map_vDrift.find(m_gasMixture)->second;
73 m_transDiff = map_transDiff.find(m_gasMixture)->second;
74 m_longDiff = map_longDiff.find(m_gasMixture)->second;
75 m_interactionDensitySigma = map_interactionDensitySigma.find(m_gasMixture)->second;
76 m_interactionDensityMean = map_interactionDensityMean.find(m_gasMixture)->second;
77 m_lorentzAngleFunction = map_lorentzAngleFunctionPars.find(m_gasMixture)->second;
78 return StatusCode::SUCCESS;
84 if(!readTdoPdo.isValid()){
85 ATH_MSG_ERROR(
"Cannot find conditions data container for TDOs and PDOs!");
88 return readTdoPdo.cptr();
93 double lorentzAngle {0.};
94 if(m_applyMmBFieldCalib){
97 if (!loadMagneticField(ctx, fieldCache))
return StatusCode::FAILURE;
99 fieldCache.
getField(globalPos.data(), magneticField.data());
102 double phi = globalPos.phi();
103 double bfield = (magneticField.x()*
std::sin(phi)-magneticField.y()*
std::cos(phi))*1000.;
106 int gasGap = m_idHelperSvc->mmIdHelper().gasGap(prepData->
identify());
108 if (changeSign) bfield = -bfield;
111 lorentzAngle = (bfield>0. ? 1. : -1.)*m_lorentzAngleFunction(std::abs(bfield)) * toRad;
121 calibClus.push_back(std::move(calibStrip));
123 return StatusCode::SUCCESS;
130 if(!localStripPosition(
id,locPos)) {
131 ATH_MSG_WARNING(__FILE__<<
":"<<__LINE__<<
" Failed to retrieve local strip position "<<m_idHelperSvc->toString(
id));
132 return StatusCode::FAILURE;
137 calibStrip.
time = time;
139 double vDriftCorrected = m_vDrift *
std::cos(lorentzAngle);
146 calibStrip.
dx =
std::sin(lorentzAngle) * calibStrip.
time * m_vDrift;
148 return StatusCode::SUCCESS;
157 if(!localStripPosition(rdoId,locPos)) {
158 ATH_MSG_WARNING(__FILE__<<
":"<<__LINE__<<
" Failed to retrieve local strip position "<<m_idHelperSvc->toString(rdoId));
159 return StatusCode::FAILURE;
172 float time{-FLT_MAX},
charge{-FLT_MAX};
179 calibStrip.
time = time - globalPos.norm() * reciprocalSpeedOfLight - mmPeakTime();
181 if(m_applyMmT0Calib){
182 calibStrip.
time = applyT0Calibration(ctx, rdoId, calibStrip.
time);
187 ATH_MSG_DEBUG(
"Calibrating RDO " << m_idHelperSvc->toString(rdoId) <<
"with pdo: " << mmRawData->
charge() <<
" tdo: "<< mmRawData->
time() <<
" relBCID "<< mmRawData->
relBcid() <<
" charge and time in counts " <<
188 mmRawData->
timeAndChargeInCounts() <<
" isData "<< m_isData <<
" to charge: " << calibStrip.
charge <<
" electrons time after corrections " << calibStrip.
time <<
" ns time before corrections "<< time <<
"ns");
199 calibStrip.
locPos = locPos;
201 return StatusCode::SUCCESS;
217 if(!localStripPosition(rdoId,locPos)) {
218 ATH_MSG_WARNING(__FILE__<<
":"<<__LINE__<<
" Failed to retrieve local strip position "<<m_idHelperSvc->toString(rdoId));
219 return StatusCode::FAILURE;
223 float time{-FLT_MAX},
charge{-FLT_MAX};
231 calibStrip.
time = time - stgcPeakTime();
233 if(m_applysTgcT0Calib){
234 calibStrip.
time = applyT0Calibration(ctx, rdoId, calibStrip.
time);
238 calibStrip.
locPos = locPos;
239 return StatusCode::SUCCESS;
244 if (!readHandle.isValid()) {
245 ATH_MSG_ERROR(
"doDigitization: Failed to retrieve AtlasFieldCacheCondObj with key " << m_fieldCondObjInputKey.key());
248 readHandle.cptr()->getInitializedCache(fieldCache);
254 if (!loadMagneticField(ctx, fieldCache))
return StatusCode::FAILURE;
256 fieldCache.
getField(globalPos.data(), magneticField.data());
259 const double phi = globalPos.phi();
260 double bfield = (magneticField.x()*
std::sin(phi)-magneticField.y()*
std::cos(phi))*1000.;
263 int gasGap = m_idHelperSvc->mmIdHelper().gasGap(prepData->
identify());
265 if (changeSign) bfield = -bfield;
266 double cos2_lorentzAngle =
std::pow(
std::cos ( (bfield>0. ? 1. : -1.)*m_lorentzAngleFunction(std::abs(bfield)) * toRad), 2);
268 for (
const double dist : driftDistances){
269 double time = dist / (m_vDrift*cos2_lorentzAngle);
270 driftTimes.push_back(time);
272 return StatusCode::SUCCESS;
290 if (m_idHelperSvc->isMM (chnlId))
c /= MM_electronsPerfC;
291 else if(m_idHelperSvc->issTgc(chnlId))
c *= sTGC_pCPerfC;
318 if (m_idHelperSvc->isMM (chnlId))
charge *= MM_electronsPerfC;
319 else if(m_idHelperSvc->issTgc(chnlId))
charge /= sTGC_pCPerfC;
327 if (!tdoPdoData)
return false;
328 if (m_idHelperSvc->isMM (chnlId))
return timeToTdoMM (tdoPdoData, time, chnlId, tdo, relBCID);
329 else if(m_idHelperSvc->issTgc(chnlId))
return timeToTdoSTGC(tdoPdoData, time, chnlId, tdo, relBCID);
335 const float t = time - m_mmPeakTime - m_mmLatencyMC;
342 float tdoTime = -999.9;
345 if(
t >= lowerBound+i_relBCID*25 &&
t < (lowerBound+25)+i_relBCID*25){
346 tdoTime = i_relBCID*25 -
t;
351 if(tdoTime < lowerBound) {
361 const float t = time - m_stgcPeakTime - m_stgcLatencyMC;
368 float tdoTime = -999.9;
371 if(
t >= lowerBound+i_relBCID*25 &&
t < (lowerBound+25)+i_relBCID*25){
372 tdoTime = i_relBCID*25 -
t;
377 if(tdoTime < lowerBound) {
387 if(!readT0.isValid()){
388 ATH_MSG_ERROR(
"Cannot find conditions data container for T0s!");
391 bool isGood = readT0->getT0(
id, t0);
392 if(!isGood || t0==0){
393 ATH_MSG_DEBUG(
"failed to retrieve good t0 from database, skipping t0 calibration");
396 float targetT0 = (m_idHelperSvc->isMM(
id) ? m_mmT0TargetValue : m_stgcT0TargetValue);
397 float newTime = time + (targetT0 - t0);
398 ATH_MSG_DEBUG(
"doing T0 calibration for RDO " << m_idHelperSvc->toString(
id) <<
" time " << time <<
" t0 from database " << t0 <<
" t0 target " << targetT0 <<
" new time " << newTime);
425 float mmLatency = (m_isData? m_mmLatencyData : m_mmLatencyMC );
426 float stgcLatency = (m_isData? m_stgcLatencyData : m_stgcLatencyMC);
428 const float peakTime = m_idHelperSvc->isMM(chnlId) ? mmPeakTime() + mmLatency : stgcPeakTime() + stgcLatency;
429 time = relBCID*25. - (tdo-
calib.intercept)/
calib.slope + peakTime;
436 properties.longitudinalDiffusionSigma = m_longDiff;
437 properties.transverseDiffusionSigma = m_transDiff;
438 properties.interactionDensityMean = m_interactionDensityMean;
439 properties.interactionDensitySigma = m_interactionDensitySigma;
440 properties.lorentzAngleFunction = m_lorentzAngleFunction;
449 if(m_idHelperSvc->isMM(
id)){
453 }
else if(m_idHelperSvc->issTgc(
id)){