returns: the list of all systematics this tool can be affected by (for now keep +-1 sigma variation, but ignore it later in applySystematicVariation() )
40{
41
42
43
44
45AsgPhotonEfficiencyCorrectionTool::AsgPhotonEfficiencyCorrectionTool( const std::string& myname ) :
46 AsgTool(myname),
47 m_rootTool_unc(nullptr),
48 m_rootTool_con(nullptr),
49 m_appliedSystematics(nullptr),
50 m_sysSubstring("")
51{
52
53
56
57
58 declareProperty( "CorrectionFileNameConv", m_corrFileNameConv="",
59 "File that stores the correction factors for simulation for converted photons");
60
61 declareProperty( "CorrectionFileNameUnconv", m_corrFileNameUnconv="",
62 "File that stores the correction factors for simulation for unconverted photons");
63
64 declareProperty("MapFilePath", m_mapFile = "PhotonEfficiencyCorrection/2015_2025/rel22.2/2026_Run3Consolidated_Recommendation_v1/map0.txt",
65 "Full path to the map file");
66
67 declareProperty( "ForceDataType", m_dataTypeOverwrite=-1,
68 "Force the DataType of the Photon to specified value");
69
70 declareProperty( "ResultPrefix", m_resultPrefix="", "The prefix string for the result");
71 declareProperty( "ResultName", m_resultName="", "The string for the result");
72
73
74 declareProperty( "IsoKey", m_isoWP="", "Set isolation WP, if this string is empty the tool will return ID SF");
75
76
77 declareProperty( "TriggerKey", m_trigger="", "Set trigger, if this string is empty the tool will return ID SF");
78
79
80 declareProperty("UseRandomRunNumber", m_useRandomRunNumber = true,
81 "Set if use RandomRunNumber from eventinfo");
82 declareProperty("DefaultRandomRunNumber", m_defaultRandomRunNumber = 999999,
83 "Set default run number manually");
84 declareProperty("removeTRTConversion", m_removeTRTConversion = true,
85 "boolean to treat barrel standalone TRT conversion as unconverted for Run3 ");
86
87
88}
89
90
91
92
93AsgPhotonEfficiencyCorrectionTool::~AsgPhotonEfficiencyCorrectionTool()
94{
95 if ( m_rootTool_unc ) delete m_rootTool_unc;
96 if ( m_rootTool_con ) delete m_rootTool_con;
97}
98
99
100
101
102StatusCode AsgPhotonEfficiencyCorrectionTool::initialize()
103{
104
105 std::vector < std::string > corrFileNameList;
106
107
108 if(!m_mapFile.empty()){
109 corrFileNameList.push_back(
getFileName(m_isoWP,m_trigger,
true));
110 corrFileNameList.push_back(
getFileName(m_isoWP,m_trigger,
false));
111 }
112 else if(!m_corrFileNameConv.empty() && !m_corrFileNameUnconv.empty()){
113 corrFileNameList.push_back(m_corrFileNameConv);
114 corrFileNameList.push_back(m_corrFileNameUnconv);
115 }
116 else{
117 ATH_MSG_ERROR (
"Fail to resolve input file name, check if you set MapFilePath or CorrectionFileName properly" );
118 return StatusCode::FAILURE ;
119 }
120
121
122 for (auto & i : corrFileNameList){
123
124
126
129 return StatusCode::FAILURE ;
130 } else{
132 }
133
135
136 }
137
138
139 if( corrFileNameList[0].
find(m_file_prefix_Trig) != std::string::npos) m_sysSubstring=
"TRIGGER_";
140 if( corrFileNameList[0].
find(m_file_prefix_ID) != std::string::npos) m_sysSubstring=
"ID_";
141 if( corrFileNameList[0].
find(m_file_prefix_ISO) != std::string::npos) m_sysSubstring=
"ISO_";
142 if( corrFileNameList[0].
find(m_file_prefix_TrigEff) != std::string::npos) m_sysSubstring=
"TRIGGER_";
143 if(m_sysSubstring.empty()) {
ATH_MSG_ERROR (
"Invalid input file" );
return StatusCode::FAILURE;}
144
145
146 m_rootTool_con->addFileName( corrFileNameList[0] );
147 m_rootTool_unc->addFileName( corrFileNameList[1] );
148
149
150 m_rootTool_con->msg().setLevel(this->
msg().
level());
151 m_rootTool_unc->msg().setLevel(this->
msg().
level());
152
153
154 if ( (0 == m_rootTool_con->initialize()) || (0 == m_rootTool_unc->initialize()) )
155 {
156 ATH_MSG_ERROR(
"Could not initialize the TElectronEfficiencyCorrectionTool!");
157 return StatusCode::FAILURE;
158 }
159
160
161
162 m_rootTool_con->getNbins(m_pteta_bins);
163 std::map<float, std::vector<float>> pteta_bins_unc;
164
165 m_rootTool_unc->getNbins(pteta_bins_unc);
166
167
168 for (const auto& [pt_unc, eta_unc]: pteta_bins_unc) {
169 m_pteta_bins[pt_unc] = eta_unc;
170 }
171
172
173 if ( registerSystematics() != StatusCode::SUCCESS) {
174 return StatusCode::FAILURE;
175 }
176
177 return StatusCode::SUCCESS ;
178}
179
180
181
182
183
185{
186 const auto&
acc = *m_accessors;
187
188
190 if (
clusters.size()<1||!clusters[0].has_value()){
193 }
195
196
197 const double energy = cluster(
acc.clusterEAcc);
199 if ( std::abs(egam(
acc.etaAcc)) < 999.) {
200 const double cosheta = std::cosh(egam(
acc.etaAcc));
201 et = (cosheta != 0.) ? energy / cosheta : 0.;
202 }
203
204
205 double eta2 = cluster(
acc.clusterEtaBEAcc,2);
206
207
208
209
211 if (itr_pt!=m_pteta_bins.end() &&
et<itr_pt->first) {
213 }
214
215
216 if (std::abs(eta2) >
MAXETA) {
220 << eta2 << " Returning SF = 1 + / - 1");
222 }
227 <<
et <<
" Returning SF = 1 + / - 1");
229 }
234 <<
et / 1e3 <<
"GeV Returning SF = 1 + / - 1");
236 }
237
238
239 unsigned int runnumber = m_defaultRandomRunNumber;
240 if (m_useRandomRunNumber) {
241 if (!
acc.randomRunNumberAcc.isAvailable(eventInfo)) {
243 "Pileup tool not run before using PhotonEfficiencyTool! SFs do not "
244 "reflect PU distribution in data");
246 }
248 }
249
250
251
252
254 PATCore::ParticleDataType::DataType::Data;
255 if (m_dataTypeOverwrite >= 0)
257
258
259
260 bool excludeTRT = false;
261 if(
runnumber >= 410000 && m_removeTRTConversion) excludeTRT =
true;
262
263 const auto [isConv, missingLinks] =
acc.isConvertedPhotonAcc(egam, excludeTRT);
264 if (missingLinks) {
265 if (!m_allowMissingLinks.value()) {
266 ATH_MSG_ERROR(
"Missing vertex or track links when trying to calculate the conversion type. missingLinks=" << std::hex << missingLinks);
268 }
269 static std::atomic<bool> warned {false};
270 if (warned.exchange(true) == false) {
271 ATH_MSG_WARNING(
"Missing vertex or track links when trying to calculate the conversion type. missingLinks=" << std::hex << missingLinks);
272 ATH_MSG_WARNING(
"This may indicate that the DAOD is incorrectly missing some conversion vertices.");
273 ATH_MSG_WARNING(
"This is your only warning, repeat occurrences will be reported at the DEBUG level.");
274 } else {
275 ATH_MSG_DEBUG(
"Missing vertex or track links when trying to calculate the conversion type. missingLinks=" << std::hex << missingLinks);
276 }
280 }
281
282
283
284 const int status = isConv ? m_rootTool_con->calculate(dataType,
runnumber,
285 eta2,
et, result,
true)
286 : m_rootTool_unc->calculate(dataType,
runnumber,
287 eta2,
et, result,
true);
288
289
290 if (!status) {
294 }
295
297}
298
299CP::CorrectionCode AsgPhotonEfficiencyCorrectionTool::getEfficiencyScaleFactor(
const xAOD::Egamma& inputObject,
double& efficiencyScaleFactor)
const{
300
301
304 if (!eventInfo) {
307 }
308
310}
311
313
316
319 }
320
321 if(m_appliedSystematics==nullptr){
322 efficiencyScaleFactor=sfresult.SF;
324 }
325
326
328 sigma=appliedSystematics().getParameterByBaseName(
"PH_EFF_"+m_sysSubstring+
"Uncertainty");
329 efficiencyScaleFactor=sfresult.SF+
sigma*sfresult.Total;
331}
332
333CP::CorrectionCode AsgPhotonEfficiencyCorrectionTool::getEfficiencyScaleFactorError(
const xAOD::Egamma& inputObject,
double& efficiencyScaleFactorError)
const{
334
335
338 if (!eventInfo) {
341 }
342
344}
345
347
350
353 }
354
355 efficiencyScaleFactorError=sfresult.Total;
357}
358
360
361 double efficiencyScaleFactor = 1.0;
364 dec(inputObject) = efficiencyScaleFactor;
366}
367
368
369
370
371bool AsgPhotonEfficiencyCorrectionTool::isAffectedBySystematic(
const CP::SystematicVariation& systematic )
const {
372 if(!systematic.
empty()){
374 return sys.find(systematic) !=
sys.end();
375 }
376 return true;
377}
378
379
381CP::SystematicSet AsgPhotonEfficiencyCorrectionTool::affectingSystematics()
const {
383
387
388 return mySysSet;
389}
390
392StatusCode AsgPhotonEfficiencyCorrectionTool::registerSystematics() {
394 if (
registry.registerSystematics(*
this) != StatusCode::SUCCESS) {
395 ATH_MSG_ERROR(
"Failed to add systematic to list of recommended systematics.");
396 return StatusCode::FAILURE;
397 }
398 return StatusCode::SUCCESS;
399}
400
402CP::SystematicSet AsgPhotonEfficiencyCorrectionTool::recommendedSystematics()
const {
406
407 return mySysSet;
408}
409
410
413{
414
415 auto itr = m_systFilter.find(systConfig);
416
417
418 if( itr == m_systFilter.end() ){
419
423 ATH_MSG_ERROR(
"Unsupported combination of systematics passed to the tool!");
424 return StatusCode::FAILURE;
425 }
426
427 itr = m_systFilter.
insert(std::make_pair(systConfig, filteredSys)).first;
428 }
429
431 m_appliedSystematics = &mySysConf;
432 return StatusCode::SUCCESS;
433}
434
435
436
437
438
439std::string AsgPhotonEfficiencyCorrectionTool::getFileName(const std::string& isoWP, const std::string& trigWP, bool isConv) {
440
441
443 if(mapFileName.empty()){
445 return mapFileName;
446 }
447
448
449 std::string correction_type = "ID_Tight";
450 if(!trigWP.empty()) correction_type = "Trigger_"+trigWP+"_"+isoWP;
451 else if(!isoWP.empty()) correction_type = "ISO_"+isoWP;
452
453
454 if(trigWP.empty()) {correction_type += isConv ? "_Converted" : "_Unconverted";}
455
457
458
459 std::ifstream is(mapFileName);
460 if (!is.is_open()){
462 return "";
463 }
464 while (!is.eof()) {
465 std::string strLine;
466 getline(is,strLine);
467
468 int nPos = strLine.find('=');
469
470 if ((signed int)std::string::npos == nPos) continue;
471 std::string strKey = strLine.substr(0,nPos);
472 std::string strVal = strLine.substr(nPos + 1, strLine.length() - nPos + 1);
473
474
475 if(0==correction_type.compare(strKey)) {
value=strVal;
break;}
476 }
477
479
480}
481
483{
484 const Accessors&
acc = *m_accessors;
485 for (auto photon : photons)
486 {
488 switch (getEfficiencyScaleFactor(photon, event, sf).code())
489 {
491 case Ok:
492 acc.sfDec(photon) =
sf;
493 acc.validDec(photon) =
true;
494 break;
495 case OutOfValidityRange:
496 acc.sfDec(photon) =
sf;
497 acc.validDec(photon) =
false;
498 break;
499 default:
500 throw std::runtime_error("Error in getEfficiencyScaleFactor");
501 }
502 }
503}
504
506{
507 const Accessors&
acc = *m_accessors;
509 {
510 auto eventInfo =
acc.eventInfoAcc(event);
511 callSingleEvent (
acc.photonsAcc(event), eventInfo);
512 }
513}
514
515}
#define ATH_MSG_DEBUG(x,...)
#define ATH_MSG_ERROR(x,...)
#define ATH_MSG_WARNING(x,...)
#define ATH_MSG_INFO(x,...)
float et(const xAOD::jFexSRJetRoI *j)
std::string PathResolverFindCalibFile(const std::string &logical_file_name)
const_iterator begin() const
Return value from object correction CP tools.
ErrorCode
Possible values for the correction code.
@ Error
Some error happened during the object correction.
@ OutOfValidityRange
Input object is out of validity range.
@ Ok
The correction was done successfully.
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.
Class to wrap a set of SystematicVariations.
void insert(const SystematicVariation &systematic)
description: insert a systematic into the set
static StatusCode filterForAffectingSystematics(const SystematicSet &systConfig, const SystematicSet &affectingSystematics, SystematicSet &filteredSystematics)
description: filter the systematics for the affected systematics returns: success guarantee: strong f...
bool empty() const
returns: whether this is an empty systematic, i.e.
std::string find(const std::string &s)
return a remapped string
static std::vector< uint32_t > runnumber
::StatusCode StatusCode
StatusCode definition for legacy code.
void calculate(xAOD::Electron &electron)
SG::Decorator< T, ALLOC > Decorator
Helper class to provide type-safe access to aux data, specialized for JaggedVecElt.
ObjectRange< EgammaDef > EgammaRange
ObjectRange< EventContextDef > EventContextRange
ObjectId< EventContextDef > EventContextId
ObjectId< EgammaDef > EgammaId
ObjectId< EventInfoDef > EventInfoId
getFileName(name, sep='#')
EventInfo_v1 EventInfo
Definition of the latest event info version.
Egamma_v1 Egamma
Definition of the current "egamma version".
Extra patterns decribing particle interation process.