ATLAS Offline Software
Loading...
Searching...
No Matches
MuonCalibTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3*/
4
5// Framework include(s):
9
10// Local include(s):
11#include <cmath>
12#include "TRandom3.h"
13
15
17
18namespace CP
19{
20
22
24 m_MuonSelectionTool.declarePropertyFor(this,"MuonSelectionTool", "Instance of the MuonSelectionTool needed for the HighPt categorization");
25 m_MuonIntSagittaTool.declarePropertyFor(this, "SagittaTool", "Instance of the Sagitta bias corrections sub tool");
26 m_MuonIntScaleSmearTool.declarePropertyFor(this, "ScaleAndSmearTool", "Instance of the tool that applies the smearing & scale corrections");
27 m_MuonIntHighTSmearTool.declarePropertyFor(this, "HighPtSmearingTool", "Extra smearing of the high pt working point");
28 }
29
31 {
32 // Greet the user:
33 ATH_MSG_INFO("Initialising...");
34
35 // Get the m_eventinfo container
36 ATH_CHECK(m_eventInfo.initialize());
37
38 // Set the options
39 if (m_calibMode == MuonCalibTool::correctData_CB) {
40 ATH_MSG_INFO("Data will be corrected for sagitta bias with CB calibration");
41 m_doDirectCBCalib = true;
43
44 } else if (m_calibMode == MuonCalibTool::correctData_IDMS) {
45 ATH_MSG_INFO("Data will be corrected for sagitta bias with ID+MS calibration");
46 if (m_isRun3.value()) ATH_MSG_WARNING("You are using the ID+MS calibration which is currenlty not recommended from the MCP group in Run3. Please refer to the MCP documentation page");
47 m_doDirectCBCalib = false;
49
50 } else if (m_calibMode == MuonCalibTool::notCorrectData_IDMS) {
51 ATH_MSG_INFO("Data will be untouched. Instead an additional systematic will be added with ID+MS calibration");
52 if (m_isRun3.value()) ATH_MSG_WARNING("You are using the ID+MS calibration which is currenlty not recommended from the MCP group in Run3. Please refer to the MCP documentation page");
53 m_doDirectCBCalib = false;
55 }
56 else if (m_calibMode == MuonCalibTool::notCorrectData_CB) {
57 ATH_MSG_INFO("Data will be untouched. Instead an additional systematic will be added with CB calibration");
58 m_doDirectCBCalib = true;
60 }
61 else if (m_calibMode == MuonCalibTool::userDefined) {
62 ATH_MSG_INFO("Using options as provided by the user");
63 }
64 else {
65 ATH_MSG_FATAL("Invalid calibration mode: " << m_calibMode << " Allowed modes are correctData_CB("
66 << MuonCalibTool::correctData_CB << ") correctData_IDMS ("
67 << MuonCalibTool::correctData_IDMS << ") or notCorrectData_IDMS ("
68 << MuonCalibTool::notCorrectData_IDMS << ") or notCorrectData_CB ("
69 << MuonCalibTool::notCorrectData_CB << ")");
70 return StatusCode::FAILURE;
71 }
72
73 if (!m_skipResolutionCategory.value())
74 {
75 // Get the muon selection tool
76 if (m_MuonSelectionTool.empty()) {
77 m_MuonSelectionTool.setTypeAndName("CP::MuonSelectionTool/MCaST_Own_MST");
78 ATH_CHECK(m_MuonSelectionTool.setProperty("MaxEta", 2.7));
79 ATH_CHECK(m_MuonSelectionTool.setProperty("MuQuality", 1));
80 ATH_CHECK(m_MuonSelectionTool.setProperty("TurnOffMomCorr", true));
81 ATH_CHECK(m_MuonSelectionTool.setProperty("IsRun3Geo", m_isRun3.value()));
82 ATH_CHECK(m_MuonSelectionTool.setProperty("OutputLevel", msg().level()));
83 ATH_CHECK(m_MuonSelectionTool.setProperty("ExcludeNSWFromPrecisionLayers", m_excludeNSWFromPrecisionLayers.value()));
84 }
86 if (auto *selectionTool = dynamic_cast<columnar::ColumnarTool<>*>(m_MuonSelectionTool.get()))
87 addSubtool (*selectionTool);
88 }
89
90 // Create the Sagitta tool
91 if (m_MuonIntSagittaTool.empty()) {
92 m_MuonIntSagittaTool.setTypeAndName("CP::MuonCalibIntSagittaTool/MCaST_Sagitta");
93 ATH_CHECK(m_MuonIntSagittaTool.setProperty("release", m_release.value()));
94 ATH_CHECK(m_MuonIntSagittaTool.setProperty("systematicScheme", m_sysScheme.value()));
95 ATH_CHECK(m_MuonIntSagittaTool.setProperty("applyCorrectionOnData", m_applyCorrectionOnData.value()));
96 ATH_CHECK(m_MuonIntSagittaTool.setProperty("doDirectCBCalib", m_doDirectCBCalib.value()));
97 ATH_CHECK(m_MuonIntSagittaTool.setProperty("doEtaSagittaSys", m_doEtaSagittaSys.value()));
98 ATH_CHECK(m_MuonIntSagittaTool.setProperty("OutputLevel", msg().level()));
99 }
101
102 // Create the scale smear tool
103 if (m_MuonIntScaleSmearTool.empty()) {
104 m_MuonIntScaleSmearTool.setTypeAndName("CP::MuonCalibIntScaleSmearTool/MCaST_ScaleSmear");
105 ATH_CHECK(m_MuonIntScaleSmearTool.setProperty("release", m_release.value()));
106 ATH_CHECK(m_MuonIntScaleSmearTool.setProperty("systematicScheme", m_sysScheme.value()));
107 ATH_CHECK(m_MuonIntScaleSmearTool.setProperty("doDirectCBCalib", m_doDirectCBCalib.value()));
108 ATH_CHECK(m_MuonIntScaleSmearTool.setProperty("OutputLevel", msg().level()));
110 }
113 if (m_MuonIntHighTSmearTool.empty()) {
114 m_MuonIntHighTSmearTool.setTypeAndName("CP::MuonCalibIntHighpTSmearTool/MCaST_highPtScaleSmear");
115 ATH_CHECK(m_MuonIntHighTSmearTool.setProperty("release", m_release.value()));
116 ATH_CHECK(m_MuonIntHighTSmearTool.setProperty("OutputLevel", msg().level()));
117 }
120 }
122 {
123 ATH_MSG_ERROR("Unable to run with no systematic");
124 return StatusCode::FAILURE;
125 }
127 if (registry.registerSystematics(*this) != StatusCode::SUCCESS)
128 {
129 ATH_MSG_ERROR("Unkown systematic list");
130 return StatusCode::FAILURE;
131 }
132 ATH_CHECK (initializeColumns());
133 // Return gracefully:
134 return StatusCode::SUCCESS;
135 }
136
138 {
139 // Retrieve the event information:
142 }
143
145 {
146 auto& acc = *m_acc;
147 ATH_MSG_VERBOSE("Muon Type = " << mu(acc.muonTypeAcc) << " ( 0: Combined, 1: StandAlone, 2: SegmentTagged, 3: CaloTagged, 4: SiliconAssociatedForwardMuon)");
148 ATH_MSG_VERBOSE("Muon Author = " << mu(acc.authorAcc));
149
150 // Convert to the internal object
151 MCP::MuonObj muonObj = convertToMuonObj(mu, evtInfo);
152
153 ATH_MSG_VERBOSE("input ID pT "<<muonObj.ID.calib_pt);
154 ATH_MSG_VERBOSE("input ME pT "<<muonObj.ME.calib_pt);
155 ATH_MSG_VERBOSE("input CB pT "<<muonObj.CB.calib_pt);
156 ATH_MSG_VERBOSE("input eta "<<muonObj.CB.eta);
157 ATH_MSG_VERBOSE("input phi "<<muonObj.CB.phi);
158
159 if (muonObj.CB.isData)
160 {
161 ATH_MSG_VERBOSE("Doing data corrections");
162
163 // Sagitta Correction specifics
165 {
166 CorrectionCode sgCode = m_MuonIntSagittaTool->applyCorrection(muonObj);
167 if (sgCode != CorrectionCode::Ok) return sgCode;
168 }
169
170 // Override combined momentum for special cases
171 if (std::abs(muonObj.ME.calib_pt) == 0) muonObj.CB.calib_pt = muonObj.ID.calib_pt;
172 if (std::abs(muonObj.ID.calib_pt) == 0) muonObj.CB.calib_pt = muonObj.ME.calib_pt;
173
174 // Only for combined set it
175 if (mu(acc.muonTypeAcc) == xAOD::Muon::Combined)
176 {
177 acc.ptOutDec (mu) = muonObj.CB.calib_pt * GeVtoMeV;
178 }
179
180
181 acc.dec_idPt(mu) = muonObj.ID.calib_pt * GeVtoMeV;
182 acc.dec_mePt(mu) = muonObj.ME.calib_pt * GeVtoMeV;
183 acc.dec_idCharge(mu) = muonObj.ID.calib_charge;
184 acc.dec_meCharge(mu) = muonObj.ME.calib_charge;
185
186 ATH_MSG_DEBUG("Checking Output Muon Info for data - Pt_ID: " << acc.dec_idPt(mu));
187 ATH_MSG_DEBUG("Checking Output Muon Info for data - Pt_MS: " << acc.dec_mePt(mu));
188 ATH_MSG_DEBUG("Checking Output Muon Info for data - Pt_CB: " << mu(acc.ptAcc));
189
190 return CorrectionCode::Ok;
191 }
192
193 // Do Scale and Smearing corrections
194 CorrectionCode sgCode = m_MuonIntScaleSmearTool->applyCorrection(muonObj);
195 if (sgCode != CorrectionCode::Ok) return sgCode;
196
197 // Systematics for sagitta correction
198 if ((mu(acc.muonTypeAcc) != xAOD::Muon::SiliconAssociatedForwardMuon))
199 {
200 ATH_MSG_VERBOSE("Systematic uncertainties for sagitta bias ");
201 // TODO:: something specific for calo tags
202 CorrectionCode sgCode = m_MuonIntSagittaTool->applyCorrection(muonObj);
203 if (sgCode != CorrectionCode::Ok) return sgCode;
204 }
205
206 // Override combined momentum for special cases
207 if (std::abs(muonObj.ME.calib_pt) == 0) muonObj.CB.calib_pt = muonObj.ID.calib_pt;
208 if (std::abs(muonObj.ID.calib_pt) == 0) muonObj.CB.calib_pt = muonObj.ME.calib_pt;
209
210 // Setting the output object properties right now, so the resolution category get the corrected info
211 acc.ptOutDec(mu) = muonObj.CB.calib_pt * GeVtoMeV;
212 acc.chargeOutDec(mu) = muonObj.CB.calib_charge;
213 acc.dec_idPt(mu) = muonObj.ID.calib_pt * GeVtoMeV;
214 acc.dec_mePt(mu) = muonObj.ME.calib_pt * GeVtoMeV;
215 acc.dec_idCharge(mu) = muonObj.ID.calib_charge;
216 acc.dec_meCharge(mu) = muonObj.ME.calib_charge;
217
219 {
220 muonObj.raw_mst_category = (CP::IMuonSelectionTool::ResolutionCategory) m_MuonSelectionTool->getResolutionCategory(mu.getXAODObject());
221 }
222
223 // Special case: if the proper flags are selected (m_extra_highpt_smearing or m_2stations_highpt_smearing)
224 // an ad-hoc smearing of the combined momentum has to be applied
225 bool extra_smearing = (m_extra_highpt_smearing && (muonObj.raw_mst_category.value() >= 0) && !( muonObj.raw_mst_category.value() & IMuonSelectionTool::CategoryFour)); // Extra smearing, if selected, gets anyway only applied to non-3-station muons!
226 bool highpt_smearing = (m_2stations_highpt_smearing && (muonObj.raw_mst_category.value() >= 0) && ( muonObj.raw_mst_category.value() & IMuonSelectionTool::CategoryThree)); // Special highpt smearing, if selected, gets anyway only applied to missing-inner, 2-station muons only!
227
228 if (((extra_smearing || highpt_smearing)) && (mu(acc.ptAcc) > m_HighPtSystThreshold * GeVtoMeV))
229 {
230 sgCode = m_MuonIntHighTSmearTool->applyCorrection(muonObj);
231 if (sgCode != CorrectionCode::Ok) return sgCode;
232 }
233
234 // Final info to be written to the muon object
235 acc.ptOutDec(mu) = muonObj.CB.calib_pt * GeVtoMeV;
236 acc.dec_idPt(mu) = muonObj.ID.calib_pt * GeVtoMeV;
237 acc.dec_mePt(mu) = muonObj.ME.calib_pt * GeVtoMeV;
238
239
240 ATH_MSG_DEBUG("Checking Output Muon Info - Pt_ID: " << acc.dec_idPt(mu));
241 ATH_MSG_DEBUG("Checking Output Muon Info - Pt_MS: " << acc.dec_mePt(mu));
242 ATH_MSG_DEBUG("Checking Output Muon Info - Pt_CB: " << acc.ptOutDec(mu));
243
244 // If saggita was out of validity, return it here
245 if (sgCode == CorrectionCode::OutOfValidityRange) return sgCode;
246
247 // Return gracefully:
248 return CorrectionCode::Ok;
249 }
250
252 {
253 // Convert to the internal object
254 MCP::MuonObj muonObj = convertToMuonObj(inTrk, DetType);
255
256 // Do Scale and Smearing corrections
257 CorrectionCode sgCode = m_MuonIntScaleSmearTool->applyCorrection(muonObj);
258 if (sgCode != CorrectionCode::Ok) return sgCode;
259
260 double res_pt = (DetType == MCP::DetectorType::MS) ? muonObj.ME.calib_pt*GeVtoMeV : muonObj.ID.calib_pt*GeVtoMeV;
261
262 inTrk.setDefiningParameters(inTrk.d0(), inTrk.z0(), inTrk.phi0(), inTrk.theta(),
263 inTrk.charge() / (res_pt * std::cosh(inTrk.eta())));
264
265 // Return gracefully:
266 return CorrectionCode::Ok;
267 }
268
270 {
271 // A sanity check:
272 if (output)
274 "Non-null pointer received. "
275 "There's a possible memory leak!");
276
277 // Create a new object:
278 ATH_MSG_VERBOSE("Going to create new xAOD::Muon...");
279 output = new xAOD::Muon();
280 ATH_MSG_VERBOSE("Calling makePrivateStore...");
281 output->makePrivateStore(input);
282
283 // Use the other function to modify this object:
284 ATH_MSG_VERBOSE("Calling applyCorrection...");
285
286 CP::CorrectionCode retCode = applyCorrection(*output);
287
288 return retCode;
289 }
290
292 {
294 return sys.find(systematic) != sys.end();
295 }
296
298 {
299 SystematicSet result = m_MuonIntSagittaTool->affectingSystematics();
300 result.insert(m_MuonIntScaleSmearTool->affectingSystematics());
301 if (m_MuonIntHighTSmearToolInitialized) result.insert(m_MuonIntHighTSmearTool->affectingSystematics());
302 return result;
303 }
304
306
308 {
309 // Apply to the underlying tool
310 StatusCode code = m_MuonIntSagittaTool->applySystematicVariation(systConfig);
311 if(code != StatusCode::SUCCESS) return code;
312
313 code = m_MuonIntScaleSmearTool->applySystematicVariation(systConfig);
314 if(code != StatusCode::SUCCESS) return code;
315
317 code = m_MuonIntHighTSmearTool->applySystematicVariation(systConfig);
318 if(code != StatusCode::SUCCESS) return code;
319 }
320 return code;
321 }
322
323 double MuonCalibTool::expectedResolution(const std::string &DetType, const xAOD::Muon &mu, const bool addMCCorrectionSmearing) const
324 {
325 // Expected resolution in data (or unsmeared MC if second argument is true)
326 if (DetType == "MS") {
327 return expectedResolution(MCP::DetectorType::MS, mu, addMCCorrectionSmearing);
328 } else if (DetType == "ID") {
329 return expectedResolution(MCP::DetectorType::ID, mu, addMCCorrectionSmearing);
330 } else if (DetType == "CB") {
331 return expectedResolution(MCP::DetectorType::CB, mu, addMCCorrectionSmearing);
332 } else {
333 ATH_MSG_ERROR("The DetType that you entered is not allows - DetType = " << DetType);
334 return 0.;
335 }
336 }
337
338 double MuonCalibTool::expectedResolution(const int &DetType, const xAOD::Muon &mu, const bool addMCCorrectionSmearing) const
339 {
341 return expectedResolution(DetType, columnar::MuonId(mu), columnar::EventInfoId(*evtInfo), addMCCorrectionSmearing);
342 }
343
344 double MuonCalibTool::expectedResolution(const int &DetType, columnar::MuonId mu, columnar::EventInfoId evtInfo, const bool addMCCorrectionSmearing) const
345 {
346 auto& acc = *m_acc;
347 // Get information about data
348 bool isData = false;
350 else
351 {
352 // Retrieve the event information:
353 isData = !evtInfo(acc.eventTypeAcc, xAOD::EventInfo::IS_SIMULATION);
354 }
355
356 // Get information about which year it is here
357 MCP::DataYear dataYear = MuonCalibTool::getPeriod(isData, evtInfo);
358
359 // get the pt measurements from the xAOD::Muon object
360 double loc_ptid = 0;
361 double loc_ptms = 0;
362 double loc_ptcb = 0;
363
364 double Primary_eta = mu(acc.etaAcc);
365 double Primary_phi = mu(acc.phiAcc);
366
367 if (m_validationMode)
368 {
369 static const SG::AuxElement::Accessor<float> id_pt("expert_ptid");
370 static const SG::AuxElement::Accessor<float> ms_pt("expert_ptms");
371 static const SG::AuxElement::Accessor<float> cb_pt("expert_ptcb");
372
373 loc_ptid = id_pt(mu.getXAODObject()) * MeVtoGeV;
374 loc_ptms = ms_pt(mu.getXAODObject()) * MeVtoGeV;
375 loc_ptcb = cb_pt(mu.getXAODObject()) * MeVtoGeV;
376
377 } else {
378
379 // Retrieve all the trans
380 auto CB_track = mu(acc.combinedTrackParticleLinkAcc);
381 auto ID_track = mu(acc.inDetTrackParticleLinkAcc).opt_value();
382 auto ME_track = mu(acc.extrapolatedMuonSpectrometerTrackParticleLinkAcc);
383
384 if(CB_track) loc_ptcb = acc.trkMomentumAcc.pt(CB_track.value(), ParticleConstants::muonMassInMeV) * MeVtoGeV;
385 if(ID_track) loc_ptid = acc.trkMomentumAcc.pt(ID_track.value(), ParticleConstants::muonMassInMeV) * MeVtoGeV;
386 if(ME_track) loc_ptms = acc.trkMomentumAcc.pt(ME_track.value(), ParticleConstants::muonMassInMeV) * MeVtoGeV;
387 }
388
390 {
391 return m_MuonIntScaleSmearTool->getExpectedResolution(DetType, loc_ptms, Primary_eta, Primary_phi, dataYear, addMCCorrectionSmearing);
392 }
393 else if (DetType == MCP::DetectorType::ID)
394 {
395 return m_MuonIntScaleSmearTool->getExpectedResolution(DetType, loc_ptid, Primary_eta, Primary_phi, dataYear, addMCCorrectionSmearing);
396 }
397 else if (DetType == MCP::DetectorType::CB)
398 {
399 // Due to complicated maths, the expected combined resolution
400 // is given by this equation (note: all sigmas are fractional uncertainties):
401 // sigma_CB = std::sqrt(2) * sigma_ID * sigma_MS * pTMS * pTID / {pTCB * std::sqrt({sigma_ID*pTID}^2 + {sigma_MS*pTMS}^2)}
402 // Do a little recursive calling to make things easier to read
403 // Turn these into *absolute* uncertainties to make life easier
404 double sigmaID = expectedResolution(MCP::DetectorType::ID, mu, evtInfo, addMCCorrectionSmearing) * loc_ptid;
405 double sigmaMS = expectedResolution(MCP::DetectorType::MS, mu, evtInfo, addMCCorrectionSmearing) * loc_ptms;
406 double denominator = (loc_ptcb)*std::sqrt(sigmaID * sigmaID + sigmaMS * sigmaMS);
407 return denominator ? sigmaID * sigmaMS / denominator : 0.;
408 }
409 else
410 {
411 ATH_MSG_ERROR("wrong DetType in input " << DetType);
412 }
413 return 0.;
414
415 }
416
417 // Internal tool function
419 {
420 auto& acc = *m_acc;
421 // Get information about data
422 bool isData = false;
424 else
425 {
426 // Retrieve the event information:
427 isData = !evtInfo(acc.eventTypeAcc, xAOD::EventInfo::IS_SIMULATION);
428 }
429 ATH_MSG_VERBOSE("Checking Simulation flag: " << !isData);
430
431 // Get information about which year it is here
432 auto year = MuonCalibTool::getPeriod(isData, evtInfo);
433
434
435 double Primary_eta = mu(acc.etaAcc);
436 double Primary_phi = mu(acc.phiAcc);
437 int charge = mu(acc.chargeAcc);
439
441 {
442 static const SG::AuxElement::Accessor<float> cb_pt("expert_ptcb");
443 static const SG::AuxElement::Accessor<float> id_pt("expert_ptid");
444 static const SG::AuxElement::Accessor<float> ms_pt("expert_ptms");
445 static const SG::AuxElement::Accessor<AmgVector(5)> CBParam("CBParam");
446 static const SG::AuxElement::Accessor<AmgSymMatrix(5)> CBCov("CBCov");
447 static const SG::AuxElement::Accessor<AmgVector(5)> IDParam("IDParam");
448 static const SG::AuxElement::Accessor<AmgSymMatrix(5)> IDCov("IDCov");
449 static const SG::AuxElement::Accessor<AmgVector(5)> MEParam("MEParam");
450 static const SG::AuxElement::Accessor<AmgSymMatrix(5)> MECov("MECov");
451
452 // Use the constructor where the eta/phi are overwritten to keep it inma line with current recommendations. To be changed in the future
453 auto CB = MCP::TrackCalibObj(MCP::TrackType::CB, charge, cb_pt(mu.getXAODObject()), Primary_eta, Primary_phi, mass, CBParam(mu.getXAODObject()), CBCov(mu.getXAODObject()), year, isData);
454 auto ID = MCP::TrackCalibObj(MCP::TrackType::ID, charge, id_pt(mu.getXAODObject()), Primary_eta, Primary_phi, mass, IDParam(mu.getXAODObject()), IDCov(mu.getXAODObject()), year, isData);
455 auto ME = MCP::TrackCalibObj(MCP::TrackType::ME, charge, ms_pt(mu.getXAODObject()), Primary_eta, Primary_phi, mass, MEParam(mu.getXAODObject()), MECov(mu.getXAODObject()), year, isData);
456
457 MCP::MuonObj muonObj{CB,ID,ME};
458 initializeRandNumbers(muonObj, evtInfo);
459
462 muonObj.expectedResID = expectedResolution(MCP::DetectorType::ID, mu, evtInfo, true) * muonObj.CB.calib_pt;
463 muonObj.expectedResME = expectedResolution(MCP::DetectorType::MS, mu, evtInfo, true) * muonObj.CB.calib_pt;
464
465 return muonObj;
466 }
467
468
469 // Retrieve all the trans
470 auto CB_track = mu(acc.combinedTrackParticleLinkAcc);
471 auto ID_track = mu(acc.inDetTrackParticleLinkAcc).opt_value();
472 auto ME_track = mu(acc.extrapolatedMuonSpectrometerTrackParticleLinkAcc);
473
474 // For SI muons, overwrite the charge from the CB track
475 if (mu(acc.muonTypeAcc) == xAOD::Muon::SiliconAssociatedForwardMuon)
476 {
477 if (CB_track) charge = CB_track.value()(acc.trkChargeAcc);
478 }
479
480 // Use the constructor where the eta/phi are overwritten to keep it inma line with current recommendations. To be changed in the future
481 auto CB = MCP::TrackCalibObj(acc, columnar::OptObjectId<columnar::MuonTrackDef>(CB_track), MCP::TrackType::CB, charge, Primary_eta, Primary_phi, year, isData);
482 auto ID = MCP::TrackCalibObj(acc, columnar::OptObjectId<columnar::MuonTrackDef>(ID_track), MCP::TrackType::ID, charge, Primary_eta, Primary_phi, year, isData);
483 auto ME = MCP::TrackCalibObj(acc, columnar::OptObjectId<columnar::MuonTrackDef>(ME_track), MCP::TrackType::ME, charge, Primary_eta, Primary_phi, year, isData);
484
485 MCP::MuonObj muonObj{CB,ID,ME};
486 initializeRandNumbers(muonObj, evtInfo);
489
490 muonObj.expectedResID = expectedResolution(MCP::DetectorType::ID, mu, evtInfo, true) * muonObj.CB.calib_pt;
491 muonObj.expectedResME = expectedResolution(MCP::DetectorType::MS, mu, evtInfo, true) * muonObj.CB.calib_pt;
492 return muonObj;
493 }
495 {
496 auto& acc = *m_acc;
497 // Get information about data
498 bool isData = false;
499
500 // Retrieve the event information:
502 isData = !evtInfo->eventType(xAOD::EventInfo::IS_SIMULATION);
503
504 ATH_MSG_VERBOSE("Checking Simulation flag: " << !isData);
505
506 // Get information about which year it is here
507 auto year = MuonCalibTool::getPeriod(isData, *evtInfo);
508 int charge = inTrk.charge();
510 {
511 auto CB = MCP::TrackCalibObj(acc, &inTrk, MCP::TrackType::CB, charge, year, isData);
512 auto ID = MCP::TrackCalibObj(acc, &inTrk, MCP::TrackType::ID, charge, year, isData);
513 auto ME = MCP::TrackCalibObj(acc, &inTrk, MCP::TrackType::ME, charge, year, isData);
514
515 MCP::MuonObj muonObj{CB,ID,ME};
516 return muonObj;
517 }
518
519 auto CB = MCP::TrackCalibObj(acc, &inTrk, MCP::TrackType::CB, charge, year, isData);
520 auto ID = MCP::TrackCalibObj(acc, nullptr, MCP::TrackType::ID, charge, year, isData);
521 auto ME = MCP::TrackCalibObj(acc, &inTrk, MCP::TrackType::ME, charge, year, isData);
522
523 MCP::MuonObj muonObj{CB,ID,ME};
524 return muonObj;
525 }
526
527
529 {
530 auto& acc = *m_acc;
531 // Random number generation for smearing
532 TRandom3 loc_random3;
533 // Get Event Number, Retrieve the event information:
534 unsigned long long eventNumber = 0;
536 else eventNumber = evtInfo(acc.eventNumberAcc);
537 // Construct a seed for the random number generator:
538 const UInt_t seed = 1 + std::abs(muonObj.CB.phi) * 1E6 + std::abs(muonObj.CB.eta) * 1E3 + eventNumber;
539 loc_random3.SetSeed(seed);
540
541 muonObj.rnd_g0 = loc_random3.Gaus(0, 1);
542 muonObj.rnd_g1 = loc_random3.Gaus(0, 1);
543 muonObj.rnd_g2 = loc_random3.Gaus(0, 1);
544 muonObj.rnd_g3 = loc_random3.Gaus(0, 1);
545 muonObj.rnd_g4 = loc_random3.Gaus(0, 1);
546 muonObj.rnd_g_highPt = loc_random3.Gaus(0, 1);
547
548
549 }
550
552 {
553 // I've copied the run number ranges from SUSYTools (Run2) - Haider
554 // https://gitlab.cern.ch/atlas/athena/blob/21.2/PhysicsAnalysis/SUSYPhys/SUSYTools/Root/SUSYObjDef_xAOD.cxx#L2438
555 // Range for Run3 taken from COMA - Luca
556 // https://atlas-tagservices.cern.ch/tagservices/RunBrowser/runBrowserReport/rBR_Period_Report.php?fnt=data22_13p6TeV
557 // https://atlas-tagservices.cern.ch/tagservices/RunBrowser/runBrowserReport/rBR_Period_Report.php?fnt=data23_13p6TeV
558 // https://atlas-tagservices.cern.ch/tagservices/RunBrowser/runBrowserReport/rBR_Period_Report.php?fnt=data24_13p6TeV
559 constexpr unsigned int last_run_16 = 320000;
560 constexpr unsigned int last_run_17 = 342000;
561 constexpr unsigned int last_run_18 = 370000;
562 constexpr unsigned int last_run_22 = 440614;
563 constexpr unsigned int last_run_23 = 456750;
564 constexpr unsigned int last_run_24 = 999999;
565
566 static const std::set<int> MCperiods1516{284500};
567 static const std::set<int> MCperiods17{300000, 304000, 305000};
568 static const std::set<int> MCperiods18{310000};
569 static const std::set<int> MCperiods22{330000, 410000};
570 static const std::set<int> MCperiods23{450000};
571 static const std::set<int> MCperiods24{470000};
572
573 static const std::set<int> MCperiodsRun4{350000, 350060, 350140, 350200};
574
575 auto& acc = *m_acc;
576 unsigned int run = 0;
578 else run = evtInfo(acc.runNumberAcc);
579 // retrieve the random run number
580 if (!isData && m_useRndRun) {
581 if (acc.acc_rnd.isAvailable(evtInfo))
582 run = acc.acc_rnd(evtInfo);
583 else {
585 "No random runnumber could be found although the tool is configured to assign the years based on it. Please make sure "
586 "to apply the prwTool before-hand or consider to set the property 'useRandomRunNumber' to false.");
588 }
589 }
590 // Check the Monte carlo
591 if (!isData && (!m_useRndRun || !acc.acc_rnd.isAvailable(evtInfo))) {
592 if (MCperiods1516.count(run)) {
593 ATH_MSG_DEBUG("The current run " << run << " corresponds to data mc20a / data15-16");
595 } else if (MCperiods17.count(run)) {
596 ATH_MSG_DEBUG("The current run " << run << " corresponds to data mc20d / data17");
598 } else if (MCperiods18.count(run)) {
599 ATH_MSG_DEBUG("The current run " << run << " corresponds to data mc20e / data18");
601 } else if (MCperiods22.count(run)) {
602 ATH_MSG_DEBUG("The current run " << run << " corresponds to data mc21 / mc23a / data22");
604 } else if (MCperiods23.count(run)) {
605 ATH_MSG_DEBUG("The current run " << run << " corresponds to data mc23c / mc23d / data23");
607 } else if (MCperiods24.count(run)) {
608 ATH_MSG_DEBUG("The current run " << run << " corresponds to data mc23e / data24");
610 } else if (MCperiodsRun4.count(run)) {
611 ATH_MSG_DEBUG("The current run " << run << " corresponds to data Run4");
612 return MCP::DataYear::Run4;
613 }
614
615 }
616 // Check data itself or the random run number is used
617 else if (isData || m_useRndRun) {
618 if (run < last_run_16) {
619 ATH_MSG_DEBUG("The current run " << run << " is taken in data 15-16");
621 } else if (run <= last_run_17) {
622 ATH_MSG_DEBUG("The current run " << run << " is taken in data 17");
624 } else if (run <= last_run_18) {
625 ATH_MSG_DEBUG("The current run " << run << " is taken in data 18");
627 } else if (run <= last_run_22) {
628 ATH_MSG_DEBUG("The current run " << run << " is taken in data 22");
630 } else if (run < last_run_23) {
631 ATH_MSG_DEBUG("The current run " << run << " is taken in data 23");
633 } else if (run < last_run_24) {
634 ATH_MSG_DEBUG("The current run " << run << " is taken in data 24");
636 }
637 }
638 static std::atomic<bool> warningPrinted {false};
639 if (!warningPrinted) {
640 ATH_MSG_WARNING("Could not assign run-number " << run << " to a specific year of data-taking, using default year 24");
641 warningPrinted = true;
642 }
644 }
645
646
648 {
649 for (columnar::MuonId muon : muons)
650 {
651 switch (applyCorrection(muon, event).code())
652 {
654 break;
656 throw std::runtime_error("OutOfValidityRange in applyCorrection");
657 break;
659 throw std::runtime_error("Error in applyCorrection");
660 }
661 }
662 }
663
665 auto& acc = *m_acc;
666 for (columnar::EventContextId event : events)
667 {
668 auto eventInfo = acc.m_eventInfoCol(event);
669 callSingleEvent (acc.m_muons(event), eventInfo);
670 }
671 }
672
673} // namespace CP
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_FATAL(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
Handle class for reading from StoreGate.
std::vector< Identifier > ID
#define AmgSymMatrix(dim)
#define AmgVector(rows)
Return value from object correction CP tools.
@ Error
Some error happened during the object correction.
@ OutOfValidityRange
Input object is out of validity range.
@ Ok
The correction was done successfully.
ResolutionCategory
Declare the interface that the class provides.
Gaudi::Property< std::string > m_sysScheme
asg::AnaToolHandle< CP::IMuonCalibIntScaleSmearTool > m_MuonIntScaleSmearTool
Gaudi::Property< unsigned long long > m_expertMode_EvtNumber
virtual StatusCode initialize() override
Dummy implementation of the initialisation function.
Gaudi::Property< std::string > m_release
Gaudi::Property< bool > m_validationMode
Gaudi::Property< bool > m_excludeNSWFromPrecisionLayers
virtual ASG_TOOL_CLASS3(MuonCalibTool, CP::IMuonCalibrationAndSmearingTool, CP::ISystematicsTool, CP::IReentrantSystematicsTool) public CorrectionCode applyCorrection(xAOD::Muon &mu) const override
Declare the interface that the class provides.
MuonCalibTool(const std::string &name)
Gaudi::Property< bool > m_useRndRun
void initializeRandNumbers(MCP::MuonObj &obj, columnar::EventInfoId evtInfo) const
Decorate all information that's needed to ensure reproducibility of the smearing.
Gaudi::Property< bool > m_extra_highpt_smearing
virtual CorrectionCode applyCorrectionTrkOnly(xAOD::TrackParticle &inTrk, const int DetType) const override
Gaudi::Property< bool > m_skipResolutionCategory
MCP::DataYear getPeriod(bool isData, columnar::EventInfoId evtInfo) const
virtual CorrectionCode correctedCopy(const xAOD::Muon &input, xAOD::Muon *&output) const override
Create a corrected copy from a constant muon.
bool m_MuonIntHighTSmearToolInitialized
asg::AnaToolHandle< CP::IMuonCalibIntTool > m_MuonIntHighTSmearTool
Gaudi::Property< bool > m_doEtaSagittaSys
void callEvents(columnar::EventContextRange events) const override
Gaudi::Property< bool > m_applyCorrectionOnData
Gaudi::Property< float > m_HighPtSystThreshold
void callSingleEvent(columnar::MuonRange muons, columnar::EventInfoId event) const
asg::AnaToolHandle< CP::IMuonSelectionTool > m_MuonSelectionTool
MCP::MuonObj convertToMuonObj(columnar::MuonId mu, columnar::EventInfoId evtInfo) const
Gaudi::Property< bool > m_isRun3
virtual double expectedResolution(const std::string &DetType, const xAOD::Muon &mu, const bool addMCCorrectionSmearing) const override
Get the expected pT resolution.
asg::AnaToolHandle< CP::IMuonCalibIntTool > m_MuonIntSagittaTool
Gaudi::Property< bool > m_2stations_highpt_smearing
SG::ReadHandleKey< xAOD::EventInfo > m_eventInfo
virtual StatusCode applySystematicVariation(const SystematicSet &systConfig) override
effects: configure this tool for the given list of systematic variations.
Gaudi::Property< int > m_expertMode_RunNumber
virtual bool isAffectedBySystematic(const SystematicVariation &systematic) const override
Declare the interface that this class provides.
virtual SystematicSet affectingSystematics() const override
the list of all systematics this tool can be affected by
Gaudi::Property< int > m_calibMode
std::unique_ptr< MCP::MuonCalibToolAccessors > m_acc
Gaudi::Property< bool > m_doDirectCBCalib
virtual SystematicSet recommendedSystematics() const override
the list of all systematics this tool recommends to use
Gaudi::Property< bool > m_expertMode_isData
This module implements the central registry for handling systematic uncertainties with CP tools.
static SystematicRegistry & getInstance()
Get the singleton instance of the registry for the curren thread.
StatusCode registerSystematics(const IReentrantSystematicsTool &tool)
effects: register all the systematics from the tool
Class to wrap a set of SystematicVariations.
SG::Accessor< T, ALLOC > Accessor
Definition AuxElement.h:572
AsgTool(const std::string &name)
Constructor specifying the tool instance's name.
Definition AsgTool.cxx:58
a class representing a single optional object (electron, muons, etc.)
@ IS_SIMULATION
true: simulation, false: data
float z0() const
Returns the parameter.
float theta() const
Returns the parameter, which has range 0 to .
float d0() const
Returns the parameter.
void setDefiningParameters(float d0, float z0, float phi0, float theta, float qOverP)
Set the defining parameters.
virtual double eta() const override final
The pseudorapidity ( ) of the particle.
float charge() const
Returns the charge.
float phi0() const
Returns the parameter, which has range to .
Select isolated Photons, Electrons and Muons.
constexpr float MeVtoGeV
DataYear
Definition EnumDef.h:28
constexpr double muonMassInMeV
the mass of the muon (in MeV)
ObjectId< ContainerId::muon > MuonId
Definition MuonDef.h:25
ObjectRange< ContainerId::eventContext > EventContextRange
ObjectId< ContainerId::eventContext > EventContextId
ObjectRange< ContainerId::muon > MuonRange
Definition MuonDef.h:24
ObjectId< ContainerId::eventInfo > EventInfoId
Definition run.py:1
TrackParticle_v1 TrackParticle
Reference the current persistent version:
Muon_v1 Muon
Reference the current persistent version:
static const SG::AuxElement::Accessor< ElementLink< IParticleContainer > > acc("originalObjectLink")
Object used for setting/getting the dynamic decoration in question.
double rnd_g1
Definition MuonObj.h:188
double rnd_g3
Definition MuonObj.h:190
double expectedResID
Definition MuonObj.h:201
double expectedPercentResME
Definition MuonObj.h:205
double rnd_g0
Random numbers helping for the calibration.
Definition MuonObj.h:187
double expectedResME
Definition MuonObj.h:202
double rnd_g2
Definition MuonObj.h:189
TrackCalibObj ID
Definition MuonObj.h:182
std::optional< ResolutionCategory > raw_mst_category
Definition MuonObj.h:198
double rnd_g_highPt
Definition MuonObj.h:192
double expectedPercentResID
Definition MuonObj.h:204
TrackCalibObj CB
Definition MuonObj.h:184
TrackCalibObj ME
Definition MuonObj.h:183
double rnd_g4
Definition MuonObj.h:191
Basic object to cache all relevant information from the track.
Definition MuonObj.h:74
int calib_charge
Value of the track-charge (after calibration)
Definition MuonObj.h:165
const double eta
Value of the track-eta.
Definition MuonObj.h:157
const double phi
Value of the track-phi.
Definition MuonObj.h:159
const bool isData
Definition MuonObj.h:169
double calib_pt
Smeared track pt.
Definition MuonObj.h:155
MsgStream & msg
Definition testRead.cxx:32