15 #include "TGraphErrors.h"
31 if (m_saveDiagnostic) {
33 m_clientToken.canvasLimit = -1;
34 m_clientToken.preFixName =
"AnalyticMdtCalib";
35 ATH_CHECK(m_visualSvc->registerClient(m_clientToken));
37 return StatusCode::SUCCESS;
41 if(writeHandle.isValid()) {
42 ATH_MSG_DEBUG(
"CondHandle " << writeHandle.fullKey() <<
" is already valid.");
43 return StatusCode::SUCCESS;
48 writeHandle.addDependency(readHandle);
50 auto writeCdo = std::make_unique<MdtCalibDataContainer>(m_idHelperSvc.get(), readHandle->granularity());
52 const MdtIdHelper& idHelper{m_idHelperSvc->mdtIdHelper()};
53 std::map<RtRelationPtr, RtRelationPtr, CalibParamSorter> translatedRts{
CalibParamSorter{
std::pow(0.1, m_precCutOff)}};
57 std::unordered_set<Identifier> missedElements{};
58 for (
auto itr = idHelper.detectorElement_begin(); itr != idHelper.detectorElement_end(); ++itr){
60 if (!readHandle->hasDataForChannel(detId, msgStream())){
61 ATH_MSG_VERBOSE(
"There's no calibration data available for "<<m_idHelperSvc->toStringDetEl(detId));
62 missedElements.insert(detId);
65 const MdtFullCalibData* copyMe = readHandle->getCalibData(detId, msgStream());
68 return StatusCode::FAILURE;
71 const std::vector<Identifier> tubes = tubeIds(detId);
72 if (std::ranges::none_of(tubes, [copyMe](
const Identifier& tubeId){
76 if (!writeCdo->storeData(detId, copyMe->
tubeCalib, msgStream())) {
77 return StatusCode::FAILURE;
80 ATH_MSG_VERBOSE(
"Tube calibration constants invalid for: "<<m_idHelperSvc->toStringDetEl(detId));
81 missedElements.insert(detId);
86 translated = translateRt(ctx, detId, *copyMe->
rtRelation);
89 dummyFillerRt = translated;
92 if (!writeCdo->storeData(detId, translated, msgStream())) {
93 ATH_MSG_FATAL(
"Failed to store rt relation for "<<m_idHelperSvc->toStringDetEl(detId));
94 return StatusCode::FAILURE;
97 if (!m_fillMissingCh) {
98 missedElements.clear();
100 for (
const Identifier& detId: missedElements) {
101 ATH_MSG_WARNING(
"Initial container did not contain any constants for "<<m_idHelperSvc->toString(detId)
102 <<
". Insert instead the first translated rt-relation for those channels");
103 const bool fillRt = !writeCdo->hasDataForChannel(detId, msgStream()) ||
104 !writeCdo->getCalibData(detId, msgStream())->rtRelation;
106 if (!writeCdo->storeData(detId, dummyFillerRt, msgStream())) {
107 ATH_MSG_FATAL(
"Failed to store rt relation for "<<m_idHelperSvc->toStringDetEl(detId));
108 return StatusCode::FAILURE;
110 if (dummyFillerCorr && !writeCdo->storeData(detId, dummyFillerCorr, msgStream())) {
111 return StatusCode::FAILURE;
114 if (writeCdo->getCalibData(detId, msgStream())->tubeCalib) {
119 dummyT0Calib.
t0 = m_missingT0;
120 for (
const Identifier& tubeId : tubeIds(detId)) {
121 if (!dummyT0cont->
setCalib(dummyT0Calib, tubeId, msgStream())) {
122 return StatusCode::FAILURE;
125 if (!writeCdo->storeData(detId, std::move(dummyT0cont), msgStream())) {
126 return StatusCode::FAILURE;
129 ATH_CHECK(writeHandle.record(std::move(writeCdo)));
130 return StatusCode::SUCCESS;
132 std::vector<Identifier> MdtAnalyticRtCalibAlg::tubeIds(
const Identifier& chId)
const {
133 std::vector<Identifier> tubes{};
134 const MdtIdHelper& idHelper{m_idHelperSvc->mdtIdHelper()};
135 for (
int ml = 1; ml <= idHelper.multilayerMax(chId); ++ml) {
136 const Identifier detId = idHelper.multilayerID(chId, ml);
138 for (
int tube = 1;
tube <= idHelper.tubeMax(detId); ++
tube) {
139 tubes.emplace_back(idHelper.channelID(detId, ml,
layer,
tube));
147 MdtAnalyticRtCalibAlg::translateRt(
const EventContext& ctx,
154 unsigned int order{0};
155 while (
order++ <= m_maxOrder && !rt) {
156 ATH_MSG_DEBUG(
"Attempt to fit rt relation for "<<m_idHelperSvc->toStringDetEl(detId)
157 <<
" using a polynomial of order "<<
order);
158 switch(m_polyTypeRt) {
159 case toUnderlying(PolyType::ChebyChev):
162 case toUnderlying(PolyType::Legendre):
165 case toUnderlying(PolyType::Simple):
171 const unsigned rtNdoF = rtPoints.size() - rt->nDoF();
173 ATH_MSG_VERBOSE(
"Fit has a chi2 of "<<rtChi2<<
". Cut off at "<<m_chiCutOff);
174 if (rtChi2 > m_chiCutOff) {
179 ATH_MSG_ERROR(
"Failed to fit rt relation for "<<m_idHelperSvc->toStringDetEl(detId));
182 const std::vector<SamplePoint> trPoints =
swapCoordinates(rtPoints, *rt);
184 while (
order++ <= m_maxOrder && !tr) {
185 ATH_MSG_DEBUG(
"Now continue with tr fit for "<<m_idHelperSvc->toStringDetEl(detId)
186 <<
" using a polynomial of order "<<
order);
187 switch(m_polyTypeTr) {
188 case toUnderlying(PolyType::Legendre):
191 case toUnderlying(PolyType::ChebyChev):
194 case toUnderlying(PolyType::Simple):
200 const unsigned trNdoF = rtPoints.size() - tr->nDoF();
203 ATH_MSG_VERBOSE(
"T-R fit resulted in a chi2/nDoF for tr: "<<trChi2<<
" ("<<trNdoF<<
")");
204 if (trChi2 > m_chiCutOff) {
209 ATH_MSG_FATAL(
"Failed to fit tr relation for "<<m_idHelperSvc->toStringDetEl(detId));
214 std::unique_ptr<IRtResolution> fittedReso{};
215 std::vector<SamplePoint> rtResoPoints =
fetchResolution(rtPoints, m_relUncReso);
217 while (
order++ <= m_maxOrderReso && !fittedReso) {
218 ATH_MSG_VERBOSE(
"Finally fit the resolution function "<<m_idHelperSvc->toStringDetEl(detId)
219 <<
" using a polynomial of order "<<
order);
221 const unsigned nDoF = rtResoPoints.size() - fittedReso->nDoF();
224 if (
chi2 > m_chiCutOff) {
225 if (
order == m_maxOrderReso) {
226 drawResoFunc(ctx, detId, rtResoPoints, *fittedReso);
233 drawResoFunc(ctx, detId, rtResoPoints, *fittedReso);
234 rtReso = std::move(fittedReso);
237 <<
" no rt resolution function could be fitted for "<<m_idHelperSvc->toStringDetEl(detId));
240 auto finalRt = std::make_unique<MdtRtRelation>(std::move(rt), rtReso, std::move(tr));
241 drawRt(ctx, detId, rtPoints, *finalRt);
244 void MdtAnalyticRtCalibAlg::drawRt(
const EventContext& ctx,
246 const std::vector<SamplePoint>& rtPoints,
248 if (!m_saveDiagnostic) {
252 m_idHelperSvc->stationNameString(detId),
253 std::abs(m_idHelperSvc->stationEta(detId)),
254 m_idHelperSvc->stationEta(detId)> 0?
'A' :
'C',
255 m_idHelperSvc->stationPhi(detId),
256 m_idHelperSvc->mdtIdHelper().multilayer(detId));
258 canvas->setAxisTitles(
"drift time [ns]",
"drift radius [mm]");
259 auto dataGraph = std::make_unique<TGraphErrors>();
261 dataGraph->SetPoint(dataGraph->GetN(), dataPoint.x1(), dataPoint.x2());
262 dataGraph->SetPointError(dataGraph->GetN()-1, 0., dataPoint.error());
263 canvas->expandPad(dataPoint.x1(), dataPoint.x2());
267 auto rtGraph = std::make_unique<TGraph>();
268 auto trGraph = std::make_unique<TGraph>();
274 const double backTime = inRel.
tr()->
driftTime(backRadius).value_or(-666.);
276 trGraph->SetPoint(trGraph->GetN(), backTime,
radius);
282 const unsigned rtNDoF= rtPoints.size() - inRel.
rt()->
nDoF();
283 const unsigned trNDoF= rtPoints.size() - inRel.
tr()->
nDoF();
287 auto legend = std::make_unique<TLegend>(0.2,0.7,0.6, 0.9,
chName.c_str());
290 legend->AddEntry(rtGraph.get(),
std::format(
"{:}, order: {:d}, #chi^{{2}}: {:.3f}({:d})",
291 inRel.
rt()->
name(), inRel.
rt()->
nDoF(), rtChi2, rtNDoF).c_str(),
"L");
293 legend->AddEntry(trGraph.get(),
std::format(
"{:}, order: {:d}, #chi^{{2}}: {:.3f}({:d})",
294 inRel.
tr()->
name(), inRel.
tr()->
nDoF(), trChi2, trNDoF).c_str(),
"L");
296 dataGraph->SetMarkerSize(0);
297 rtGraph->SetLineColor(kRed);
298 trGraph->SetLineColor(kBlue);
300 canvas->add(std::move(dataGraph),
"P");
301 canvas->add(std::move(rtGraph),
"C");
302 canvas->add(std::move(trGraph),
"C");
306 void MdtAnalyticRtCalibAlg::drawResoFunc(
const EventContext& ctx,
308 const std::vector<SamplePoint>& resoPoints,
312 m_idHelperSvc->stationNameString(detId),
313 std::abs(m_idHelperSvc->stationEta(detId)),
314 m_idHelperSvc->stationEta(detId)> 0?
'A' :
'C',
315 m_idHelperSvc->stationPhi(detId),
316 m_idHelperSvc->mdtIdHelper().multilayer(detId));
319 canvas->setAxisTitles(
"drift time [ns]",
"#sigma(r_{drift}) [mm]");
320 auto dataGraph = std::make_unique<TGraphErrors>();
322 dataGraph->SetPoint(dataGraph->GetN(), dataPoint.x1(), dataPoint.x2());
323 dataGraph->SetPointError(dataGraph->GetN()-1, 0., dataPoint.error());
324 canvas->expandPad(dataPoint.x1(), dataPoint.x2());
326 auto resoGraph = std::make_unique<TGraph>();
327 const auto [tLow, tHigh] =
interval(resoPoints);
328 const auto [resoLow, resoHigh] =
minMax(resoPoints);
329 canvas->expandPad(tLow, resoLow);
330 canvas->expandPad(tHigh, resoHigh);
334 resoGraph->SetPoint(resoGraph->GetN(),
driftTime, evalReso);
337 canvas->add(std::move(dataGraph),
"P");
338 canvas->add(std::move(resoGraph),
"C");