15 #include "TGraphErrors.h"
30 if (m_saveDiagnostic) {
31 gROOT->SetStyle(
"ATLAS");
33 return StatusCode::SUCCESS;
36 const EventContext& ctx{Gaudi::Hive::currentContext()};
38 if(writeHandle.isValid()) {
39 ATH_MSG_DEBUG(
"CondHandle " << writeHandle.fullKey() <<
" is already valid.");
40 return StatusCode::SUCCESS;
45 writeHandle.addDependency(readHandle);
47 auto writeCdo = std::make_unique<MdtCalibDataContainer>(m_idHelperSvc.get(), readHandle->granularity());
49 const MdtIdHelper& idHelper{m_idHelperSvc->mdtIdHelper()};
50 std::map<RtRelationPtr, RtRelationPtr, CalibParamSorter> translatedRts{
CalibParamSorter{
std::pow(0.1, m_precCutOff)}};
54 std::unordered_set<Identifier> missedElements{};
55 for (
auto itr = idHelper.detectorElement_begin(); itr != idHelper.detectorElement_end(); ++itr){
57 if (!readHandle->hasDataForChannel(detId, msgStream())){
58 ATH_MSG_VERBOSE(
"There's no calibration data available for "<<m_idHelperSvc->toStringDetEl(detId));
59 missedElements.insert(detId);
62 const MdtFullCalibData* copyMe = readHandle->getCalibData(detId, msgStream());
65 return StatusCode::FAILURE;
68 const std::vector<Identifier> tubes = tubeIds(detId);
69 if (std::ranges::find_if(tubes, [copyMe](
const Identifier& tubeId){
73 if (!writeCdo->storeData(detId, copyMe->
tubeCalib, msgStream())) {
74 return StatusCode::FAILURE;
77 ATH_MSG_VERBOSE(
"Tube calibration constants invalid for: "<<m_idHelperSvc->toStringDetEl(detId));
78 missedElements.insert(detId);
83 translated = translateRt(ctx, detId, *copyMe->
rtRelation);
86 dummyFillerRt = translated;
89 if (!writeCdo->storeData(detId, translated, msgStream())) {
90 ATH_MSG_FATAL(
"Failed to store rt relation for "<<m_idHelperSvc->toStringDetEl(detId));
91 return StatusCode::FAILURE;
94 if (!m_fillMissingCh) {
95 missedElements.clear();
97 for (
const Identifier& detId: missedElements) {
98 ATH_MSG_WARNING(
"Initial container did not contain any constants for "<<m_idHelperSvc->toString(detId)
99 <<
". Insert instead the first translated rt-relation for those channels");
100 const bool fillRt = !writeCdo->hasDataForChannel(detId, msgStream()) ||
101 !writeCdo->getCalibData(detId, msgStream())->rtRelation;
104 if (!writeCdo->storeData(detId, dummyFillerRt, msgStream())) {
105 ATH_MSG_FATAL(
"Failed to store rt relation for "<<m_idHelperSvc->toStringDetEl(detId));
106 return StatusCode::FAILURE;
108 if (dummyFillerCorr && !writeCdo->storeData(detId, dummyFillerCorr, msgStream())) {
109 return StatusCode::FAILURE;
112 if (writeCdo->getCalibData(detId, msgStream())->tubeCalib) {
117 dummyT0Calib.
t0 = m_missingT0;
118 for (
const Identifier& tubeId : tubeIds(detId)) {
119 if (!dummyT0cont->
setCalib(dummyT0Calib, tubeId, msgStream())) {
120 return StatusCode::FAILURE;
123 if (!writeCdo->storeData(detId, std::move(dummyT0cont), msgStream())) {
124 return StatusCode::FAILURE;
127 ATH_CHECK(writeHandle.record(std::move(writeCdo)));
128 return StatusCode::SUCCESS;
130 std::vector<Identifier> MdtAnalyticRtCalibAlg::tubeIds(
const Identifier& chId)
const {
131 std::vector<Identifier> tubes{};
132 const MdtIdHelper& idHelper{m_idHelperSvc->mdtIdHelper()};
133 for (
int ml = 1; ml <= idHelper.multilayerMax(chId); ++ml) {
134 const Identifier detId = idHelper.multilayerID(chId, ml);
136 for (
int tube = 1;
tube <= idHelper.tubeMax(detId); ++
tube) {
137 tubes.emplace_back(idHelper.channelID(detId, ml,
layer,
tube));
145 MdtAnalyticRtCalibAlg::translateRt(
const EventContext& ctx,
153 unsigned int order{0};
154 while (
order++ <= m_maxOrder && !rt) {
155 ATH_MSG_DEBUG(
"Attempt to fit rt relation for "<<m_idHelperSvc->toStringDetEl(detId)
156 <<
" using a polynomial of order "<<
order);
157 switch(m_polyTypeRt) {
158 case static_cast<int>(PolyType::ChebyChev):
161 case static_cast<int>(PolyType::Legendre):
164 case static_cast<int>(PolyType::Simple):
170 const unsigned rtNdoF = rtPoints.size() - rt->nDoF();
172 ATH_MSG_VERBOSE(
"Fit has a chi2 of "<<rtChi2<<
". Cut off at "<<m_chiCutOff);
173 if (rtChi2 > m_chiCutOff) {
178 ATH_MSG_ERROR(
"Failed to fit rt relation for "<<m_idHelperSvc->toStringDetEl(detId));
181 const std::vector<SamplePoint> trPoints =
swapCoordinates(rtPoints, *rt);
183 while (
order++ <= m_maxOrder && !tr) {
184 ATH_MSG_DEBUG(
"Now continue with tr fit for "<<m_idHelperSvc->toStringDetEl(detId)
185 <<
" using a polynomial of order "<<
order);
186 switch(m_polyTypeTr) {
187 case static_cast<int>(PolyType::Legendre):
190 case static_cast<int>(PolyType::ChebyChev):
193 case static_cast<int>(PolyType::Simple):
199 const unsigned trNdoF = rtPoints.size() - tr->nDoF();
202 ATH_MSG_VERBOSE(
"T-R fit resulted in a chi2/nDoF for tr: "<<trChi2<<
" ("<<trNdoF<<
")");
203 if (trChi2 > m_chiCutOff) {
208 ATH_MSG_FATAL(
"Failed to fit tr relation for "<<m_idHelperSvc->toStringDetEl(detId));
213 std::unique_ptr<IRtResolution> fittedReso{};
214 std::vector<SamplePoint> rtResoPoints =
fetchResolution(rtPoints, m_relUncReso);
216 while (
order++ <= m_maxOrderReso && !fittedReso) {
217 ATH_MSG_VERBOSE(
"Finally fit the resolution function "<<m_idHelperSvc->toStringDetEl(detId)
218 <<
" using a polynomial of order "<<
order);
220 const unsigned nDoF = rtResoPoints.size() - fittedReso->nDoF();
223 if (
chi2 > m_chiCutOff) {
224 if (
order == m_maxOrderReso) {
225 drawResoFunc(ctx, detId, rtResoPoints, *fittedReso);
232 drawResoFunc(ctx, detId, rtResoPoints, *fittedReso);
233 rtReso = std::move(fittedReso);
236 <<
" no rt resolution function could be fitted for "<<m_idHelperSvc->toStringDetEl(detId));
239 auto finalRt = std::make_unique<MdtRtRelation>(std::move(rt), rtReso, std::move(tr));
240 drawRt(ctx, detId, rtPoints, *finalRt);
243 void MdtAnalyticRtCalibAlg::drawRt(
const EventContext& ctx,
245 const std::vector<SamplePoint>& rtPoints,
247 if (!m_saveDiagnostic) {
250 auto dataGraph = std::make_unique<TGraphErrors>();
252 dataGraph->SetPoint(dataGraph->GetN(), dataPoint.x1(), dataPoint.x2());
253 dataGraph->SetPointError(dataGraph->GetN()-1, 0., dataPoint.error());
257 auto rtGraph = std::make_unique<TGraph>();
258 auto trGraph = std::make_unique<TGraph>();
264 const double backTime = inRel.
tr()->
driftTime(backRadius).value_or(-666.);
266 trGraph->SetPoint(trGraph->GetN(), backTime,
radius);
269 auto canvas = std::make_unique<TCanvas>(
"can",
"can", 800, 600);
271 auto refHisto = std::make_unique<TH1F>(
"canvasHisto",
"canvasHisto;drift time [ns]; drift radius [mm]", 1,
274 refHisto->SetMinimum(0.);
275 refHisto->SetMaximum(inRel.
rt()->
radius(refHisto->GetXaxis()->GetBinUpEdge(1))*1.3);
276 refHisto->Draw(
"AXIS");
278 m_idHelperSvc->stationNameString(detId),
279 std::abs(m_idHelperSvc->stationEta(detId)),
280 m_idHelperSvc->stationEta(detId)> 0?
'A' :
'C',
281 m_idHelperSvc->stationPhi(detId),
282 m_idHelperSvc->mdtIdHelper().multilayer(detId));
284 dataGraph->SetMarkerSize(0);
285 dataGraph->Draw(
"P");
286 rtGraph->SetLineColor(kRed);
288 trGraph->SetLineColor(kBlue);
291 const unsigned rtNDoF= rtPoints.size() - inRel.
rt()->
nDoF();
292 const unsigned trNDoF= rtPoints.size() - inRel.
tr()->
nDoF();
296 auto legend = std::make_unique<TLegend>(0.2,0.7,0.6, 0.9,
chName.c_str());
299 legend->AddEntry(rtGraph.get(),
std::format(
"{:}, order: {:d}, #chi^{{2}}: {:.3f}({:d})",
300 inRel.
rt()->
name(), inRel.
rt()->
nDoF(), rtChi2, rtNDoF).c_str(),
"L");
302 legend->AddEntry(trGraph.get(),
std::format(
"{:}, order: {:d}, #chi^{{2}}: {:.3f}({:d})",
303 inRel.
tr()->
name(), inRel.
tr()->
nDoF(), trChi2, trNDoF).c_str(),
"L");
309 saveGraph(
std::format(
"/{:}/Evt{:d}/Data_{:}", m_outStream.value(), ctx.evt(),
chName ), std::move(dataGraph));
310 saveGraph(
std::format(
"/{:}/Evt{:d}/Rt_{:}", m_outStream.value(), ctx.evt(),
chName ), std::move(rtGraph));
311 saveGraph(
std::format(
"/{:}/Evt{:d}/Tr_{:}", m_outStream.value(), ctx.evt(),
chName ), std::move(trGraph));
313 void MdtAnalyticRtCalibAlg::saveGraph(
const std::string&
path, std::unique_ptr<TGraph>&& graph)
const {
314 graph->SetName(
path.substr(
path.rfind(
"/")+1).c_str());
315 histSvc()->regGraph(
path, std::move(graph)).ignore();
317 void MdtAnalyticRtCalibAlg::drawResoFunc(
const EventContext& ctx,
319 const std::vector<SamplePoint>& resoPoints,
321 auto dataGraph = std::make_unique<TGraphErrors>();
323 dataGraph->SetPoint(dataGraph->GetN(), dataPoint.x1(), dataPoint.x2());
324 dataGraph->SetPointError(dataGraph->GetN()-1, 0., dataPoint.error());
326 auto resoGraph = std::make_unique<TGraph>();
327 const auto [tLow, tHigh] =
interval(resoPoints);
328 const auto [resoLow, resoHigh] =
minMax(resoPoints);
332 resoGraph->SetPoint(resoGraph->GetN(),
driftTime, evalReso);
335 auto canvas = std::make_unique<TCanvas>(
"can",
"can", 800, 600);
337 auto refHisto = std::make_unique<TH1F>(
"canvasHisto",
"canvasHisto;drift time [ns]; #sigma(r_{drift}) [mm]", 1,
338 tLow - 2, tHigh + 2);
340 refHisto->SetMinimum(resoLow*0.7);
341 refHisto->SetMaximum(resoHigh*1.3);
342 refHisto->Draw(
"AXIS");
344 dataGraph->Draw(
"P");
345 resoGraph->SetLineColor(kRed);
346 resoGraph->Draw(
"C");
349 m_idHelperSvc->stationNameString(detId),
350 std::abs(m_idHelperSvc->stationEta(detId)),
351 m_idHelperSvc->stationEta(detId)> 0?
'A' :
'C',
352 m_idHelperSvc->stationPhi(detId),
353 m_idHelperSvc->mdtIdHelper().multilayer(detId));