39namespace ADD_CMODE(CP)
45AsgPhotonEfficiencyCorrectionTool::AsgPhotonEfficiencyCorrectionTool(
const std::string& myname ) :
47 m_rootTool_unc(
nullptr),
48 m_rootTool_con(
nullptr),
49 m_appliedSystematics(
nullptr),
58 declareProperty(
"CorrectionFileNameConv", m_corrFileNameConv=
"",
59 "File that stores the correction factors for simulation for converted photons");
61 declareProperty(
"CorrectionFileNameUnconv", m_corrFileNameUnconv=
"",
62 "File that stores the correction factors for simulation for unconverted photons");
64 declareProperty(
"MapFilePath", m_mapFile =
"PhotonEfficiencyCorrection/2015_2025/rel22.2/2026_Run3Consolidated_Recommendation_v1/map0.txt",
65 "Full path to the map file");
67 declareProperty(
"ForceDataType", m_dataTypeOverwrite=-1,
68 "Force the DataType of the Photon to specified value");
70 declareProperty(
"ResultPrefix", m_resultPrefix=
"",
"The prefix string for the result");
71 declareProperty(
"ResultName", m_resultName=
"",
"The string for the result");
74 declareProperty(
"IsoKey", m_isoWP=
"",
"Set isolation WP, if this string is empty the tool will return ID SF");
77 declareProperty(
"TriggerKey", m_trigger=
"",
"Set trigger, if this string is empty the tool will return ID SF");
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 ");
93AsgPhotonEfficiencyCorrectionTool::~AsgPhotonEfficiencyCorrectionTool()
95 if ( m_rootTool_unc )
delete m_rootTool_unc;
96 if ( m_rootTool_con )
delete m_rootTool_con;
102StatusCode AsgPhotonEfficiencyCorrectionTool::initialize()
105 std::vector < std::string > corrFileNameList;
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));
112 else if(!m_corrFileNameConv.empty() && !m_corrFileNameUnconv.empty()){
113 corrFileNameList.push_back(m_corrFileNameConv);
114 corrFileNameList.push_back(m_corrFileNameUnconv);
117 ATH_MSG_ERROR (
"Fail to resolve input file name, check if you set MapFilePath or CorrectionFileName properly" );
118 return StatusCode::FAILURE ;
122 for (
auto & i : corrFileNameList){
127 if (filename.empty()){
129 return StatusCode::FAILURE ;
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;}
146 m_rootTool_con->addFileName( corrFileNameList[0] );
147 m_rootTool_unc->addFileName( corrFileNameList[1] );
150 m_rootTool_con->msg().setLevel(this->
msg().level());
151 m_rootTool_unc->msg().setLevel(this->
msg().level());
154 if ( (0 == m_rootTool_con->initialize()) || (0 == m_rootTool_unc->initialize()) )
156 ATH_MSG_ERROR(
"Could not initialize the TElectronEfficiencyCorrectionTool!");
157 return StatusCode::FAILURE;
162 m_rootTool_con->getNbins(m_pteta_bins);
163 std::map<float, std::vector<float>> pteta_bins_unc;
165 m_rootTool_unc->getNbins(pteta_bins_unc);
168 for (
const auto& [pt_unc, eta_unc]: pteta_bins_unc) {
169 m_pteta_bins[pt_unc] = eta_unc;
173 if ( registerSystematics() != StatusCode::SUCCESS) {
174 return StatusCode::FAILURE;
177 return StatusCode::SUCCESS ;
186 const auto& acc = *m_accessors;
189 auto clusters = egam(acc.caloClusterAcc);
190 if (clusters.size()<1||!clusters[0].has_value()){
194 auto cluster = clusters[0].value();
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.;
205 double eta2 = cluster(acc.clusterEtaBEAcc,2);
211 if (itr_pt!=m_pteta_bins.end() &&
et<itr_pt->first) {
216 if (std::abs(eta2) >
MAXETA) {
220 << eta2 <<
" Returning SF = 1 + / - 1");
227 <<
et <<
" Returning SF = 1 + / - 1");
234 <<
et / 1e3 <<
"GeV Returning SF = 1 + / - 1");
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");
247 runnumber = acc.randomRunNumberAcc(eventInfo);
254 PATCore::ParticleDataType::DataType::Data;
255 if (m_dataTypeOverwrite >= 0)
260 bool excludeTRT =
false;
261 if(
runnumber >= 410000 && m_removeTRTConversion) excludeTRT =
true;
263 const auto [isConv, missingLinks] = acc.isConvertedPhotonAcc(egam, excludeTRT);
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);
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.");
275 ATH_MSG_DEBUG(
"Missing vertex or track links when trying to calculate the conversion type. missingLinks=" << std::hex << missingLinks);
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);
299CP::CorrectionCode AsgPhotonEfficiencyCorrectionTool::getEfficiencyScaleFactor(
const xAOD::Egamma& inputObject,
double& efficiencyScaleFactor)
const{
321 if(m_appliedSystematics==
nullptr){
322 efficiencyScaleFactor=sfresult.SF;
328 sigma=appliedSystematics().getParameterByBaseName(
"PH_EFF_"+m_sysSubstring+
"Uncertainty");
329 efficiencyScaleFactor=sfresult.SF+sigma*sfresult.Total;
333CP::CorrectionCode AsgPhotonEfficiencyCorrectionTool::getEfficiencyScaleFactorError(
const xAOD::Egamma& inputObject,
double& efficiencyScaleFactorError)
const{
355 efficiencyScaleFactorError=sfresult.Total;
361 double efficiencyScaleFactor = 1.0;
362 CP::CorrectionCode result = getEfficiencyScaleFactor(inputObject, efficiencyScaleFactor);
364 dec(inputObject) = efficiencyScaleFactor;
371bool AsgPhotonEfficiencyCorrectionTool::isAffectedBySystematic(
const CP::SystematicVariation& systematic )
const {
372 if(!systematic.
empty()){
374 return sys.find(systematic) != sys.end();
381CP::SystematicSet AsgPhotonEfficiencyCorrectionTool::affectingSystematics()
const {
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;
398 return StatusCode::SUCCESS;
402CP::SystematicSet AsgPhotonEfficiencyCorrectionTool::recommendedSystematics()
const {
411StatusCode AsgPhotonEfficiencyCorrectionTool::
415 auto itr = m_systFilter.find(systConfig);
418 if( itr == m_systFilter.end() ){
423 ATH_MSG_ERROR(
"Unsupported combination of systematics passed to the tool!");
424 return StatusCode::FAILURE;
427 itr = m_systFilter.
insert(std::make_pair(systConfig, filteredSys)).first;
431 m_appliedSystematics = &mySysConf;
432 return StatusCode::SUCCESS;
439std::string AsgPhotonEfficiencyCorrectionTool::getFileName(
const std::string& isoWP,
const std::string& trigWP,
bool isConv) {
443 if(mapFileName.empty()){
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;
454 if(trigWP.empty()) {correction_type += isConv ?
"_Converted" :
"_Unconverted";}
459 std::ifstream is(mapFileName);
468 int nPos = strLine.find(
'=');
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);
475 if(0==correction_type.compare(strKey)) {value=strVal;
break;}
484 const Accessors& acc = *m_accessors;
485 for (
auto photon : photons)
488 switch (getEfficiencyScaleFactor(photon, event, sf).code())
492 acc.sfDec(photon) = sf;
493 acc.validDec(photon) =
true;
495 case OutOfValidityRange:
496 acc.sfDec(photon) = sf;
497 acc.validDec(photon) =
false;
500 throw std::runtime_error(
"Error in getEfficiencyScaleFactor");
507 const Accessors& acc = *m_accessors;
510 auto eventInfo = acc.eventInfoAcc(event);
511 callSingleEvent (acc.photonsAcc(event), eventInfo);