From 1e64c49e27cd00b0cf88d3413235e1b182857cdb Mon Sep 17 00:00:00 2001 From: jvoss Date: Tue, 28 Oct 2025 14:46:39 +0100 Subject: [PATCH 01/10] Use self measured SF for pt corrections with up to date correctionlib. --- include/taus.hxx | 23 ++++ src/taus.cxx | 300 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 323 insertions(+) diff --git a/include/taus.hxx b/include/taus.hxx index 32bb0a64..9c0f1e3e 100644 --- a/include/taus.hxx +++ b/include/taus.hxx @@ -70,6 +70,29 @@ ROOT::RDF::RNode PtCorrectionMC_genuineTau( const std::string &variation_dm0, const std::string &variation_dm1, const std::string &variation_dm10, const std::string &variation_dm11); +ROOT::RDF::RNode PtCorrectionMC_genuineTau( + ROOT::RDF::RNode df, + correctionManager::CorrectionManager &correction_manager, + const std::string &outputname, const std::string &pt, + const std::string &eta, const std::string &decay_mode, + const std::string &gen_match, const std::string &es_file, + const std::string &correction_name, const std::string &id_algorithm, + const std::string &wp, const std::string &vsele_wp, + const std::string &variation_dm0, const std::string &variation_dm1, + const std::string &variation_dm10, const std::string &variation_dm11); + +ROOT::RDF::RNode PtCorrectionMC_genuineTau( + ROOT::RDF::RNode df, + correctionManager::CorrectionManager &correction_manager, + const std::string &outputname, const std::string &pt, + const std::string &eta, const std::string &decay_mode, + const std::string &gen_match, const std::string &es_file, + const std::string &correction_name, const std::string &id_algorithm, + const std::string &wp, const std::string &vsele_wp, + const std::string &variation_dm0_20to40, const std::string &variation_dm1_20to40, + const std::string &variation_dm10_20to40, const std::string &variation_dm11_20to40, + const std::string &variation_dm0_40toInf, const std::string &variation_dm1_40toInf, + const std::string &variation_dm10_40toInf, const std::string &variation_dm11_40toInf); namespace quantity { ROOT::RDF::RNode IDFlag_v9(ROOT::RDF::RNode df, const std::string &outputname, const std::string &ID, const std::string &index_vector, diff --git a/src/taus.cxx b/src/taus.cxx index a1720bc5..157fce6c 100644 --- a/src/taus.cxx +++ b/src/taus.cxx @@ -688,6 +688,306 @@ ROOT::RDF::RNode PtCorrectionMC_genuineTau( return df2; } +/** + * @brief This function corrects the transverse momentum (\f$p_T\f$) in MC + * simulations of genuine hadronic taus. The energy scale correction for these + * objects is measured for four tau decay modes (dm0, dm1, dm10 and dm11) and + * depends on the transverse momentum of the hadronic tau. + * + * The correction procedure is taken from the officially recommendation of the + * TauPOG: + * + * Run2 (UL): + * https://twiki.cern.ch/twiki/bin/viewauth/CMS/TauIDRecommendationForRun2 + * - + * https://cms-nanoaod-integration.web.cern.ch/commonJSONSFs/summaries/TAU_2018_UL_tau.html + * - + * https://cms-nanoaod-integration.web.cern.ch/commonJSONSFs/summaries/TAU_2017_UL_tau.html + * - + * https://cms-nanoaod-integration.web.cern.ch/commonJSONSFs/summaries/TAU_2016postVFP_UL_tau.html + * - + * https://cms-nanoaod-integration.web.cern.ch/commonJSONSFs/summaries/TAU_2016preVFP_UL_tau.html + * + * Run3: https://twiki.cern.ch/twiki/bin/view/CMS/TauIDRecommendationForRun3 + * (not added yet) + * + * @param df input dataframe + * @param correction_manager correction manager responsible for loading the + * correction file + * @param outputname name of the output column storing the corrected hadronic + * tau \f$p_T\f$ values + * @param pt name of the input column containing hadronic tau \f$p_T\f$ values + * @param eta name of the column containing hadronic tau eta values + * @param decay_mode name of the column containing hadronic tau decay modes + * @param gen_match name of the column with the matching information of the + * hadronic tau to generator-level particles (matches are: 1=prompt e, 2=prompt mu, + * 3=tau->e, 4=tau->mu, 5=had. tau, 0=unmatched) + * @param es_file path to the correction file for the energy scale correction + * @param correction_name name of the correction in `es_file` + * @param id_algorithm identification algorithm used for hadronic tau ID + * @param wp working point of the vsJet ID + * @param vsele_wp working point of the vsEle ID + * @param variation_dm0 variation for decay mode 0, options are "nom", "up", + * "down" + * @param variation_dm1 variation for decay mode 1, options are "nom", "up", + * "down" + * @param variation_dm10 variation for decay mode 10, options are "nom", "up", + * "down" + * @param variation_dm11 variation for decay mode 11, options are "nom", "up", + * "down" + * + * @return a dataframe containing the corrected transverse momenta + * + * @note This correction is only applied to genuine hadronic taus + * (`gen_match=5`). + */ +ROOT::RDF::RNode PtCorrectionMC_genuineTau( + ROOT::RDF::RNode df, + correctionManager::CorrectionManager &correction_manager, + const std::string &outputname, const std::string &pt, + const std::string &eta, const std::string &decay_mode, + const std::string &gen_match, const std::string &es_file, + const std::string &correction_name, const std::string &id_algorithm, + const std::string &wp, const std::string &vsele_wp, + const std::string &variation_dm0, const std::string &variation_dm1, + const std::string &variation_dm10, const std::string &variation_dm11) { + // In nanoAODv12 the type of tau decay mode was changed to UChar_t + // For v9 compatibility a type casting is applied + auto [df1, decay_mode_column] = utility::Cast, ROOT::RVec>( + df, decay_mode+"_v12", "ROOT::VecOps::RVec", decay_mode); + + auto evaluator = + correction_manager.loadCorrection(es_file, correction_name); + auto correction_lambda = + [evaluator, id_algorithm, wp, vsele_wp, variation_dm0, variation_dm1, variation_dm10, + variation_dm11](const ROOT::RVec &pts, + const ROOT::RVec &etas, + const ROOT::RVec &decay_modes_v12, + const ROOT::RVec &gen_matches_char) { + auto decay_modes = static_cast>(decay_modes_v12); + auto gen_matches = static_cast>(gen_matches_char); + ROOT::RVec corrected_pts(pts.size()); + for (int i = 0; i < pts.size(); i++) { + if (gen_matches.at(i) == 5) { + if (decay_modes.at(i) == 0) { + auto correction_factor = evaluator->evaluate( + {pts.at(i), std::abs(etas.at(i)), decay_modes.at(i), + gen_matches.at(i), id_algorithm, wp, vsele_wp, + variation_dm0}); + corrected_pts[i] = pts.at(i) * correction_factor; + } else if (decay_modes.at(i) == 1) { + auto correction_factor = evaluator->evaluate( + {pts.at(i), std::abs(etas.at(i)), decay_modes.at(i), + gen_matches.at(i), id_algorithm, wp, vsele_wp, + variation_dm1}); + corrected_pts[i] = pts.at(i) * correction_factor; + } else if (decay_modes.at(i) == 10) { + auto correction_factor = evaluator->evaluate( + {pts.at(i), std::abs(etas.at(i)), decay_modes.at(i), + gen_matches.at(i), id_algorithm, wp, vsele_wp, + variation_dm10}); + corrected_pts[i] = pts.at(i) * correction_factor; + } else if (decay_modes.at(i) == 11) { + auto correction_factor = evaluator->evaluate( + {pts.at(i), std::abs(etas.at(i)), decay_modes.at(i), + gen_matches.at(i), id_algorithm, wp, vsele_wp, + variation_dm11}); + corrected_pts[i] = pts.at(i) * correction_factor; + } + } else { + corrected_pts[i] = pts.at(i); + } + Logger::get("physicsobject::tau::PtCorrection_genuineTau") + ->debug("tau pt before {}, tau pt after {}, decaymode {}", + pts.at(i), corrected_pts.at(i), decay_modes.at(i)); + } + return corrected_pts; + }; + auto df2 = df1.Define(outputname, correction_lambda, + {pt, eta, decay_mode_column, gen_match}); + return df2; +} + + +/** + * @brief This function corrects the transverse momentum (\f$p_T\f$) in MC + * simulations of genuine hadronic taus. The energy scale correction for these + * objects is measured for four tau decay modes (dm0, dm1, dm10 and dm11) and + * depends on the transverse momentum of the hadronic tau. + * + * The correction procedure is taken from the officially recommendation of the + * TauPOG: + * + * Run2 (UL): + * https://twiki.cern.ch/twiki/bin/viewauth/CMS/TauIDRecommendationForRun2 + * - + * https://cms-nanoaod-integration.web.cern.ch/commonJSONSFs/summaries/TAU_2018_UL_tau.html + * - + * https://cms-nanoaod-integration.web.cern.ch/commonJSONSFs/summaries/TAU_2017_UL_tau.html + * - + * https://cms-nanoaod-integration.web.cern.ch/commonJSONSFs/summaries/TAU_2016postVFP_UL_tau.html + * - + * https://cms-nanoaod-integration.web.cern.ch/commonJSONSFs/summaries/TAU_2016preVFP_UL_tau.html + * + * Run3: https://twiki.cern.ch/twiki/bin/view/CMS/TauIDRecommendationForRun3 + * (not added yet) + * + * @param df input dataframe + * @param correction_manager correction manager responsible for loading the + * correction file + * @param outputname name of the output column storing the corrected hadronic + * tau \f$p_T\f$ values + * @param pt name of the input column containing hadronic tau \f$p_T\f$ values + * @param eta name of the column containing hadronic tau eta values + * @param decay_mode name of the column containing hadronic tau decay modes + * @param gen_match name of the column with the matching information of the + * hadronic tau to generator-level particles (matches are: 1=prompt e, 2=prompt mu, + * 3=tau->e, 4=tau->mu, 5=had. tau, 0=unmatched) + * @param es_file path to the correction file for the energy scale correction + * @param correction_name name of the correction in `es_file` + * @param id_algorithm identification algorithm used for hadronic tau ID + * @param wp working point of the vsJet ID + * @param vsele_wp working point of the vsEle ID + * @param variation_dm0_20to40 variation for decay mode 0, options are "nom", "up", + * "down" + * @param variation_dm1_20to40 variation for decay mode 1, options are "nom", "up", + * "down" + * @param variation_dm10_20to40 variation for decay mode 10, options are "nom", "up", + * "down" + * @param variation_dm11_20to40 variation for decay mode 11, options are "nom", "up", + * "down" + * @param variation_dm0_40toInf variation for decay mode 0, options are "nom", "up", + * "down" + * @param variation_dm1_40toInf variation for decay mode 1, options are "nom", "up", + * "down" + * @param variation_dm10_40toInf variation for decay mode 10, options are "nom", "up", + * "down" + * @param variation_dm11_40toInf variation for decay mode 11, options are "nom", "up", + * "down" + * + * @return a dataframe containing the corrected transverse momenta + * + * @note This correction is only applied to genuine hadronic taus + * (`gen_match=5`). + */ +ROOT::RDF::RNode PtCorrectionMC_genuineTau( + ROOT::RDF::RNode df, + correctionManager::CorrectionManager &correction_manager, + const std::string &outputname, const std::string &pt, + const std::string &eta, const std::string &decay_mode, + const std::string &gen_match, const std::string &es_file, + const std::string &correction_name, const std::string &id_algorithm, + const std::string &wp, const std::string &vsele_wp, + const std::string &variation_dm0_20to40, const std::string &variation_dm1_20to40, + const std::string &variation_dm10_20to40, const std::string &variation_dm11_20to40, + const std::string &variation_dm0_40toInf, const std::string &variation_dm1_40toInf, + const std::string &variation_dm10_40toInf, const std::string &variation_dm11_40toInf) { + // In nanoAODv12 the type of tau decay mode was changed to UChar_t + // For v9 compatibility a type casting is applied + const std::map variations_dm0 = { + {20.0f, variation_dm0_20to40}, + {40.0f, variation_dm0_40toInf}, + {100000.0f, variation_dm0_40toInf}, + }; + const std::map variations_dm1 = { + {20.0f, variation_dm1_20to40}, + {40.0f, variation_dm1_40toInf}, + {100000.0f, variation_dm1_40toInf}, + }; + const std::map variations_dm10 = { + {20.0f, variation_dm10_20to40}, + {40.0f, variation_dm10_40toInf}, + {100000.0f, variation_dm10_40toInf}, + }; + const std::map variations_dm11 = { + {20.0f, variation_dm11_20to40}, + {40.0f, variation_dm11_40toInf}, + {100000.0f, variation_dm11_40toInf}, + }; + + auto [df1, decay_mode_column] = utility::Cast, ROOT::RVec>( + df, decay_mode+"_v12", "ROOT::VecOps::RVec", decay_mode); + + auto evaluator = + correction_manager.loadCorrection(es_file, correction_name); + auto correction_lambda = + [evaluator, id_algorithm, wp, vsele_wp, variations_dm0, variations_dm1, variations_dm10, variations_dm11](const ROOT::RVec &pts, + const ROOT::RVec &etas, + const ROOT::RVec &decay_modes_v12, + const ROOT::RVec &gen_matches_char) { + auto decay_modes = static_cast>(decay_modes_v12); + auto gen_matches = static_cast>(gen_matches_char); + ROOT::RVec corrected_pts(pts.size()); + for (int i = 0; i < pts.size(); i++) { + if (gen_matches.at(i) == 5) { + if (decay_modes.at(i) == 0) { + auto it = variations_dm0.upper_bound(pts.at(i)); + if (it != variations_dm0.begin()){ + it = std::prev(it); + std::string variation_dm0 = it->second; + auto correction_factor = evaluator->evaluate( + {pts.at(i), std::abs(etas.at(i)), decay_modes.at(i), + gen_matches.at(i), id_algorithm, wp, vsele_wp, + variation_dm0}); + corrected_pts[i] = pts.at(i) * correction_factor; + } else { + corrected_pts[i] = pts.at(i); + } + } else if (decay_modes.at(i) == 1) { + auto it = variations_dm1.upper_bound(pts.at(i)); + if (it != variations_dm1.begin()){ + it = std::prev(it); + std::string variation_dm1 = it->second; + auto correction_factor = evaluator->evaluate( + {pts.at(i), std::abs(etas.at(i)), decay_modes.at(i), + gen_matches.at(i), id_algorithm, wp, vsele_wp, + variation_dm1}); + corrected_pts[i] = pts.at(i) * correction_factor; + } else { + corrected_pts[i] = pts.at(i); + } + } else if (decay_modes.at(i) == 10) { + auto it = variations_dm10.upper_bound(pts.at(i)); + if (it != variations_dm10.begin()){ + it = std::prev(it); + std::string variation_dm10 = it->second; + auto correction_factor = evaluator->evaluate( + {pts.at(i), std::abs(etas.at(i)), decay_modes.at(i), + gen_matches.at(i), id_algorithm, wp, vsele_wp, + variation_dm10}); + corrected_pts[i] = pts.at(i) * correction_factor; + } else { + corrected_pts[i] = pts.at(i); + } + } else if (decay_modes.at(i) == 11) { + auto it = variations_dm11.upper_bound(pts.at(i)); + if (it != variations_dm11.begin()){ + it = std::prev(it); + std::string variation_dm11 = it->second; + auto correction_factor = evaluator->evaluate( + {pts.at(i), std::abs(etas.at(i)), decay_modes.at(i), + gen_matches.at(i), id_algorithm, wp, vsele_wp, + variation_dm11}); + corrected_pts[i] = pts.at(i) * correction_factor; + } else { + corrected_pts[i] = pts.at(i); + } + } else { + corrected_pts[i] = pts.at(i); + } + } else { + corrected_pts[i] = pts.at(i); + } + Logger::get("physicsobject::tau::PtCorrection_genuineTau") + ->debug("tau pt before {}, tau pt after {}, decaymode {}", + pts.at(i), corrected_pts.at(i), decay_modes.at(i)); + } + return corrected_pts; + }; + auto df2 = df1.Define(outputname, correction_lambda, + {pt, eta, decay_mode_column, gen_match}); + return df2; +} namespace quantity { /** From e75f995efecfece962ae8d64bca8ffff1d3c6518 Mon Sep 17 00:00:00 2001 From: jvoss Date: Wed, 5 Nov 2025 19:07:29 +0100 Subject: [PATCH 02/10] dm and dm_pt binned corrections for ES and ID --- include/taus.hxx | 41 ++++++++---- src/taus.cxx | 169 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 196 insertions(+), 14 deletions(-) diff --git a/include/taus.hxx b/include/taus.hxx index 9c0f1e3e..5ad2e31c 100644 --- a/include/taus.hxx +++ b/include/taus.hxx @@ -129,20 +129,33 @@ ROOT::RDF::RNode Id_vsJet_tt( const std::string &sf_file, const std::string &sf_name, const std::string &wp, const std::string &vsele_wp, const std::string &sf_dependence, - const std::string &sf_vsjet_tauDM0, - const std::string &sf_vsjet_tauDM1, - const std::string &sf_vsjet_tauDM10, - const std::string &sf_vsjet_tauDM11); -ROOT::RDF::RNode -Id_vsEle(ROOT::RDF::RNode df, - correctionManager::CorrectionManager &correction_manager, - const std::string &outputname, - const std::string &eta, - const std::string &gen_match, - const std::string &sf_file, const std::string &sf_name, - const std::string &wp, - const std::string &sf_vsele_barrel, - const std::string &sf_vsele_endcap); + const std::string &variation_dm0, + const std::string &variation_dm1, + const std::string &variation_dm10, + const std::string &variation_dm11); +ROOT::RDF::RNode Id_vsJet_tt( + ROOT::RDF::RNode df, + correctionManager::CorrectionManager &correction_manager, + const std::string &outputname, + const std::string &pt, const std::string &decay_mode, + const std::string &gen_match, + const std::string &sf_file, const std::string &sf_name, + const std::string &wp, const std::string &vsele_wp, + const std::string &sf_dependence, + const std::string &variation_dm0_20to40, const std::string &variation_dm1_20to40, + const std::string &variation_dm10_20to40, const std::string &variation_dm11_20to40, + const std::string &variation_dm0_40toInf, const std::string &variation_dm1_40toInf, + const std::string &variation_dm10_40toInf, const std::string &variation_dm11_40toInf); +ROOT::RDF::RNode Id_vsEle( + ROOT::RDF::RNode df, + correctionManager::CorrectionManager &correction_manager, + const std::string &outputname, + const std::string &eta, + const std::string &gen_match, + const std::string &sf_file, const std::string &sf_name, + const std::string &wp, + const std::string &sf_vsele_barrel, + const std::string &sf_vsele_endcap); ROOT::RDF::RNode Id_vsEle(ROOT::RDF::RNode df, correctionManager::CorrectionManager &correction_manager, diff --git a/src/taus.cxx b/src/taus.cxx index 157fce6c..a20fb87e 100644 --- a/src/taus.cxx +++ b/src/taus.cxx @@ -1283,6 +1283,175 @@ ROOT::RDF::RNode Id_vsJet_tt( return df1; } +/** + * @brief This function calculates scale factors (SFs) for tau identification (ID) + * against jets (`vsJet`). The scale factors are loaded from a correctionlib file + * using a specified scale factor name and variation. The variation and the scale + * factor itself is binned in decay modes of hadronic taus for this function. This + * dependence is usually used in the fully hadronic channel (\f$\tau_h\tau_h\f$). + * + * Description of the bit map used to define the tau ID against jets working points of the + * DeepTau v2.1 tagger. + * vsJets | Value | Bit (value used in the config) + * ------------------------------------|-------|------- + * no ID selection (takes every tau) | 0 | - + * VVVLoose | 1 | 1 + * VVLoose | 2 | 2 + * VLoose | 4 | 3 + * Loose | 8 | 4 + * Medium | 16 | 5 + * Tight | 32 | 6 + * VTight | 64 | 7 + * VVTight | 128 | 8 + * + * @param df input dataframe + * @param correction_manager correction manager responsible for loading the + * tau scale factor file + * @param outputname name of the output column containing the vsJets ID scale factor + * @param pt name of the column containing the transverse momentum of a tau + * @param decay_mode name of the column containing the decay mode of the tau + * @param gen_match name of the column with the matching information of the + * hadronic tau to generator-level particles (matches are: 1=prompt e, 2=prompt mu, + * 3=tau->e, 4=tau->mu, 5=had. tau, 0=unmatched) + * @param sf_file path to the file with the tau scale factors + * @param sf_name name of the tau scale factor for the vsJet ID correction + * @param wp working point of the vsJet ID + * @param vsele_wp working point of the vsEle ID + * @param sf_dependence variable dependence of the scale factor, opions are "pt" or "dm" + * @param variation_dm0 name of the scale factor variation for decay mode 0, "nom" for nominal + * and "up"/"down" the up/down variation + * @param variation_dm1 name of the scale factor variation for decay mode 1, "nom" for nominal + * and "up"/"down" the up/down variation + * @param variation_dm10 name of the scale factor variation for decay mode 10, "nom" for nominal + * and "up"/"down" the up/down variation + * @param variation_dm11 name of the scale factor variation for decay mode 11, "nom" for nominal + * and "up"/"down" the up/down variation + * + * @return a new dataframe containing the new column + */ +ROOT::RDF::RNode Id_vsJet_tt( + ROOT::RDF::RNode df, + correctionManager::CorrectionManager &correction_manager, + const std::string &outputname, + const std::string &pt, const std::string &decay_mode, + const std::string &gen_match, + const std::string &sf_file, const std::string &sf_name, + const std::string &wp, const std::string &vsele_wp, + const std::string &sf_dependence, + const std::string &variation_dm0_20to40, const std::string &variation_dm1_20to40, + const std::string &variation_dm10_20to40, const std::string &variation_dm11_20to40, + const std::string &variation_dm0_40toInf, const std::string &variation_dm1_40toInf, + const std::string &variation_dm10_40toInf, const std::string &variation_dm11_40toInf) { + + // const std::unordered_map variations = { + const std::map variations_dm0 = { + {20.0f, variation_dm0_20to40}, + {40.0f, variation_dm0_40toInf}, + {100000.0f, variation_dm0_40toInf}, + }; + const std::map variations_dm1 = { + {20.0f, variation_dm1_20to40}, + {40.0f, variation_dm1_40toInf}, + {100000.0f, variation_dm1_40toInf}, + }; + const std::map variations_dm10 = { + {20.0f, variation_dm10_20to40}, + {40.0f, variation_dm10_40toInf}, + {100000.0f, variation_dm10_40toInf}, + }; + const std::map variations_dm11 = { + {20.0f, variation_dm11_20to40}, + {40.0f, variation_dm11_40toInf}, + {100000.0f, variation_dm11_40toInf}, + }; + Logger::get("physicsobject::tau::scalefactor::Id_vsJet_tt") + ->debug("Setting up function for tau id vsJet sf"); + Logger::get("physicsobject::tau::scalefactor::Id_vsJet_tt")->debug("ID - Name {}", sf_name); + auto evaluator = correction_manager.loadCorrection(sf_file, sf_name); + auto sf_calculator = [evaluator, wp, vsele_wp, variations_dm0, variations_dm1, variations_dm10, variations_dm11, + sf_dependence, sf_name](const float &pt, const int &decay_mode, + const int &gen_match) { + Logger::get("physicsobject::tau::scalefactor::Id_vsJet_tt")->debug("ID - decayMode {}", decay_mode); + // only calculate SFs for allowed tau decay modes (also excludes default + // values due to tau energy correction shifts below good tau pt + // selection) + double sf = 1.; + if (decay_mode == 0) { + auto it = variations_dm0.upper_bound(pt); + if (it != variations_dm0.begin()){ + it = std::prev(it); + std::string variation_dm0 = it->second; + Logger::get("physicsobject::tau::scalefactor::Id_vsJet_tt") + ->debug("ID {} - pt {}, decay_mode {}, gen_match {}, wp {}, " + "vsele_wp {}, variation {}, sf_dependence {}", + sf_name, pt, decay_mode, gen_match, wp, vsele_wp, + variation_dm0, sf_dependence); + sf = evaluator->evaluate( + {pt, decay_mode, gen_match, wp, vsele_wp, + variation_dm0, sf_dependence}); + } + } else if (decay_mode == 1) { + auto it = variations_dm1.upper_bound(pt); + if (it != variations_dm1.begin()){ + it = std::prev(it); + std::string variation_dm1 = it->second; + Logger::get("physicsobject::tau::scalefactor::Id_vsJet_tt") + ->debug("ID {} - pt {}, decay_mode {}, gen_match {}, wp {}, " + "vsele_wp {}, variation {}, sf_dependence {}", + sf_name, pt, decay_mode, gen_match, wp, vsele_wp, + variation_dm1, sf_dependence); + sf = evaluator->evaluate( + {pt, decay_mode, gen_match, wp, vsele_wp, + variation_dm1, sf_dependence}); + } + } else if (decay_mode == 10) { + auto it = variations_dm10.upper_bound(pt); + if (it != variations_dm10.begin()){ + it = std::prev(it); + std::string variation_dm10 = it->second; + Logger::get("physicsobject::tau::scalefactor::Id_vsJet_tt") + ->debug("ID {} - pt {}, decay_mode {}, gen_match {}, wp {}, " + "vsele_wp {}, variation {}, sf_dependence {}", + sf_name, pt, decay_mode, gen_match, wp, vsele_wp, + variation_dm10, sf_dependence); + sf = evaluator->evaluate( + {pt, decay_mode, gen_match, wp, vsele_wp, + variation_dm10, sf_dependence}); + } + } else if (decay_mode == 11) { + auto it = variations_dm11.upper_bound(pt); + if (it != variations_dm11.begin()){ + it = std::prev(it); + std::string variation_dm11 = it->second; + Logger::get("physicsobject::tau::scalefactor::Id_vsJet_tt") + ->debug("ID {} - pt {}, decay_mode {}, gen_match {}, wp {}, " + "vsele_wp {}, variation {}, sf_dependence {}", + sf_name, pt, decay_mode, gen_match, wp, vsele_wp, + variation_dm11, sf_dependence); + sf = evaluator->evaluate( + {pt, decay_mode, gen_match, wp, vsele_wp, + variation_dm11, sf_dependence}); + } + } + // if (auto it = variations.find(decay_mode); it != variations.end()) { + // std::string variation = it->second; + // Logger::get("physicsobject::tau::scalefactor::Id_vsJet_tt") + // ->debug("ID {} - pt {}, decay_mode {}, gen_match {}, wp {}, " + // "vsele_wp {}, variation {}, sf_dependence {}", + // sf_name, pt, decay_mode, gen_match, wp, vsele_wp, + // variation, sf_dependence); + // sf = evaluator->evaluate( + // {pt, decay_mode, gen_match, wp, vsele_wp, + // variation, sf_dependence}); + // } + Logger::get("physicsobject::tau::scalefactor::Id_vsJet_tt")->debug("Scale Factor {}", sf); + return sf; + }; + auto df1 = df.Define(outputname, sf_calculator, {pt, decay_mode, gen_match}); + return df1; +} + + /** * @brief This function calculates scale factors (SFs) for tau identification (ID) * against electrons (`vsEle`). The scale factors are loaded from a correctionlib file From 12caa1c426ab5e212fb55c12f05200ae0adf237e Mon Sep 17 00:00:00 2001 From: Artur Monsch <60860160+a-monsch@users.noreply.github.com> Date: Mon, 24 Nov 2025 12:29:13 +0100 Subject: [PATCH 03/10] dm and dm_pt binned corrections for ES and ID implementing same scheme between MC/EMB --- include/taus.hxx | 38 +++++++++- src/taus.cxx | 188 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 225 insertions(+), 1 deletion(-) diff --git a/include/taus.hxx b/include/taus.hxx index 5ad2e31c..dea9840e 100644 --- a/include/taus.hxx +++ b/include/taus.hxx @@ -93,6 +93,22 @@ ROOT::RDF::RNode PtCorrectionMC_genuineTau( const std::string &variation_dm10_20to40, const std::string &variation_dm11_20to40, const std::string &variation_dm0_40toInf, const std::string &variation_dm1_40toInf, const std::string &variation_dm10_40toInf, const std::string &variation_dm11_40toInf); +ROOT::RDF::RNode PtCorrectionMC_genuineTau( + ROOT::RDF::RNode df, + correctionManager::CorrectionManager &correction_manager, + const std::string &outputname, const std::string &pt, + const std::string &eta, const std::string &decay_mode, + const std::string &gen_match, const std::string &es_file, + const std::string &correction_name, const std::string &id_algorithm, + // New: 8 arguments for DM/Pt splitting + const std::string &variation_dm0_pt20to40, + const std::string &variation_dm0_pt40toInf, + const std::string &variation_dm1_pt20to40, + const std::string &variation_dm1_pt40toInf, + const std::string &variation_dm10_pt20to40, + const std::string &variation_dm10_pt40toInf, + const std::string &variation_dm11_pt20to40, + const std::string &variation_dm11_pt40toInf); namespace quantity { ROOT::RDF::RNode IDFlag_v9(ROOT::RDF::RNode df, const std::string &outputname, const std::string &ID, const std::string &index_vector, @@ -120,6 +136,26 @@ Id_vsJet_lt(ROOT::RDF::RNode df, const std::string &sf_vsjet_tau40to500, const std::string &sf_vsjet_tau500to1000, const std::string &sf_vsjet_tau1000toinf); +ROOT::RDF::RNode +Id_vsJet_lt(ROOT::RDF::RNode df, + correctionManager::CorrectionManager &correction_manager, + const std::string &outputname, + const std::string &pt, const std::string &decay_mode, + const std::string &gen_match, + const std::string &sf_file, + const std::string &sf_name, + const std::vector &selected_dms, + const std::string &wp, const std::string &vsele_wp, + const std::string &sf_dependence, + // DM + pT split + const std::string &variation_dm0_pt20to40, + const std::string &variation_dm0_pt40toInf, + const std::string &variation_dm1_pt20to40, + const std::string &variation_dm1_pt40toInf, + const std::string &variation_dm10_pt20to40, + const std::string &variation_dm10_pt40toInf, + const std::string &variation_dm11_pt20to40, + const std::string &variation_dm11_pt40toInf); ROOT::RDF::RNode Id_vsJet_tt( ROOT::RDF::RNode df, correctionManager::CorrectionManager &correction_manager, @@ -203,4 +239,4 @@ Trigger(ROOT::RDF::RNode df, } // end namespace scalefactor } // end namespace tau } // end namespace physicsobject -#endif /* GUARD_TAUS_H */ \ No newline at end of file +#endif /* GUARD_TAUS_H */ diff --git a/src/taus.cxx b/src/taus.cxx index a20fb87e..49c162f8 100644 --- a/src/taus.cxx +++ b/src/taus.cxx @@ -688,6 +688,99 @@ ROOT::RDF::RNode PtCorrectionMC_genuineTau( return df2; } + +ROOT::RDF::RNode PtCorrectionMC_genuineTau( + ROOT::RDF::RNode df, + correctionManager::CorrectionManager &correction_manager, + const std::string &outputname, const std::string &pt, + const std::string &eta, const std::string &decay_mode, + const std::string &gen_match, const std::string &es_file, + const std::string &correction_name, const std::string &id_algorithm, + // New: 8 arguments for DM/Pt splitting + const std::string &variation_dm0_pt20to40, + const std::string &variation_dm0_pt40toInf, + const std::string &variation_dm1_pt20to40, + const std::string &variation_dm1_pt40toInf, + const std::string &variation_dm10_pt20to40, + const std::string &variation_dm10_pt40toInf, + const std::string &variation_dm11_pt20to40, + const std::string &variation_dm11_pt40toInf) { + + // 1. Define the variation map structure + // This map acts as both the variation lookup AND the "Allowed Decay Modes" list + const std::unordered_map> variations = { + {0, {{20.0f, variation_dm0_pt20to40}, {40.0f, variation_dm0_pt40toInf}}}, + {1, {{20.0f, variation_dm1_pt20to40}, {40.0f, variation_dm1_pt40toInf}}}, + {10, {{20.0f, variation_dm10_pt20to40}, {40.0f, variation_dm10_pt40toInf}}}, + {11, {{20.0f, variation_dm11_pt20to40}, {40.0f, variation_dm11_pt40toInf}}}, + }; + + // 2. Setup + auto [df1, decay_mode_column] = utility::Cast, ROOT::RVec>( + df, decay_mode+"_v12", "ROOT::VecOps::RVec", decay_mode); + + auto evaluator = correction_manager.loadCorrection(es_file, correction_name); + + // 3. Calculation Lambda + auto correction_lambda = + [evaluator, id_algorithm, variations](const ROOT::RVec &pts, + const ROOT::RVec &etas, + const ROOT::RVec &decay_modes_v12, + const ROOT::RVec &gen_matches_char) { + + auto decay_modes = static_cast>(decay_modes_v12); + auto gen_matches = static_cast>(gen_matches_char); + ROOT::RVec corrected_pts(pts.size()); + + for (size_t i = 0; i < pts.size(); i++) { + float current_pt = pts.at(i); + int current_dm = decay_modes.at(i); + int current_gen = gen_matches.at(i); + + // Default: No correction + corrected_pts[i] = current_pt; + std::string variation_to_use = "nom"; + + // Only correct if GenMatch is 5 (Genuine Tau) + if (current_gen == 5) { + // Look for DM in our allowed map + auto dm_it = variations.find(current_dm); + + // CRITICAL FIX: Only call evaluate if DM is supported (0, 1, 10, 11) + if (dm_it != variations.end()) { + const auto &pt_map = dm_it->second; + + // Determine variation based on Pt + auto pt_it = pt_map.upper_bound(current_pt); + if (pt_it != pt_map.begin()) { + variation_to_use = std::prev(pt_it)->second; + } + + // Evaluate now safe because current_dm is guaranteed valid + auto correction_factor = evaluator->evaluate( + {current_pt, std::abs(etas.at(i)), current_dm, + current_gen, id_algorithm, + variation_to_use}); + + corrected_pts[i] = current_pt * correction_factor; + } + } + + // Logging + Logger::get("physicsobject::tau::PtCorrection_genuineTau") + ->debug("tau pt before {}, tau pt after {}, decaymode {}, var {}", + current_pt, corrected_pts.at(i), current_dm, variation_to_use); + } + return corrected_pts; + }; + + auto df2 = df1.Define(outputname, correction_lambda, + {pt, eta, decay_mode_column, gen_match}); + return df2; +} + + + /** * @brief This function corrects the transverse momentum (\f$p_T\f$) in MC * simulations of genuine hadronic taus. The energy scale correction for these @@ -1187,6 +1280,101 @@ Id_vsJet_lt(ROOT::RDF::RNode df, return df1; } + + +ROOT::RDF::RNode +Id_vsJet_lt(ROOT::RDF::RNode df, + correctionManager::CorrectionManager &correction_manager, + const std::string &outputname, + const std::string &pt, const std::string &decay_mode, + const std::string &gen_match, + const std::string &sf_file, + const std::string &sf_name, + const std::vector &selected_dms, + const std::string &wp, const std::string &vsele_wp, + const std::string &sf_dependence, + // DM + pT split + const std::string &variation_dm0_pt20to40, + const std::string &variation_dm0_pt40toInf, + const std::string &variation_dm1_pt20to40, + const std::string &variation_dm1_pt40toInf, + const std::string &variation_dm10_pt20to40, + const std::string &variation_dm10_pt40toInf, + const std::string &variation_dm11_pt20to40, + const std::string &variation_dm11_pt40toInf) { + + const std::unordered_map> variations = { + {0, {{20.0f, variation_dm0_pt20to40}, {40.0f, variation_dm0_pt40toInf}}}, + {1, {{20.0f, variation_dm1_pt20to40}, {40.0f, variation_dm1_pt40toInf}}}, + {10, {{20.0f, variation_dm10_pt20to40}, {40.0f, variation_dm10_pt40toInf}}}, + {11, {{20.0f, variation_dm11_pt20to40}, {40.0f, variation_dm11_pt40toInf}}}, + }; + + Logger::get("physicsobject::tau::scalefactor::Id_vsJet_lt") + ->debug("Setting up function for tau id vsJet sf (DM & Pt binned)"); + Logger::get("physicsobject::tau::scalefactor::Id_vsJet_lt")->debug("ID - Name {}", sf_name); + + auto evaluator = correction_manager.loadCorrection(sf_file, sf_name); + + auto sf_calculator = [evaluator, wp, vsele_wp, variations, + sf_dependence, selected_dms, + sf_name](const float &pt, const int &decay_mode, + const int &gen_match) { + Logger::get("physicsobject::tau::scalefactor::Id_vsJet_lt")->debug("ID - decayMode {}", decay_mode); + + double sf = 1.; + + if (std::find(selected_dms.begin(), selected_dms.end(), decay_mode) != selected_dms.end()) { + auto dm_it = variations.find(decay_mode); // specific map for this Decay Mode + if (dm_it != variations.end()) { + const auto &pt_map = dm_it->second; + + auto pt_it = pt_map.upper_bound(pt); + + if (pt_it != pt_map.begin()){ + pt_it = std::prev(pt_it); // Move back to the lower bound key + std::string variation = pt_it->second; + + Logger::get("physicsobject::tau::scalefactor::Id_vsJet_lt") + ->debug("ID {} - pt {}, decay_mode {}, gen_match {}, wp {}, " + "vsele_wp {}, variation {}, sf_dependence {}", + sf_name, pt, decay_mode, gen_match, wp, vsele_wp, + variation, sf_dependence); + + sf = evaluator->evaluate({pt, decay_mode, gen_match, wp, vsele_wp, variation, sf_dependence}); + } + // If pt_it == pt_map.begin(), it means pt < 20.0f (the first key), so sf remains 1. + } + } + + Logger::get("physicsobject::tau::scalefactor::Id_vsJet_lt")->debug("Scale Factor {}", sf); + return sf; + }; + + bool all_nominal = true; + for (const auto& [dm, pt_map] : variations) { + for (const auto& [pt_val, var_name] : pt_map) { + if (var_name != "nom") { + all_nominal = false; + break; + } + } + if (!all_nominal) break; + } + + if (all_nominal) { + Logger::get("physicsobject::tau::scalefactor::Id_vsJet_lt") + ->debug("All variations are 'nom'. Skipping definition of {} to avoid collision.", outputname); + return df; + } + + auto df1 = df.Define(outputname, sf_calculator, {pt, decay_mode, gen_match}); + return df1; +} + + + + /** * @brief This function calculates scale factors (SFs) for tau identification (ID) * against jets (`vsJet`). The scale factors are loaded from a correctionlib file From cedb1202f66e465171c9bc702c2e98f1a1e67568 Mon Sep 17 00:00:00 2001 From: Artur Monsch <60860160+a-monsch@users.noreply.github.com> Date: Tue, 25 Nov 2025 17:24:25 +0100 Subject: [PATCH 04/10] Adjusting mc/embedding ID/ES naming finalization --- include/taus.hxx | 19 ++++++++++++- src/taus.cxx | 72 ++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 75 insertions(+), 16 deletions(-) diff --git a/include/taus.hxx b/include/taus.hxx index dea9840e..0549d915 100644 --- a/include/taus.hxx +++ b/include/taus.hxx @@ -93,6 +93,7 @@ ROOT::RDF::RNode PtCorrectionMC_genuineTau( const std::string &variation_dm10_20to40, const std::string &variation_dm11_20to40, const std::string &variation_dm0_40toInf, const std::string &variation_dm1_40toInf, const std::string &variation_dm10_40toInf, const std::string &variation_dm11_40toInf); + ROOT::RDF::RNode PtCorrectionMC_genuineTau( ROOT::RDF::RNode df, correctionManager::CorrectionManager &correction_manager, @@ -100,7 +101,7 @@ ROOT::RDF::RNode PtCorrectionMC_genuineTau( const std::string &eta, const std::string &decay_mode, const std::string &gen_match, const std::string &es_file, const std::string &correction_name, const std::string &id_algorithm, - // New: 8 arguments for DM/Pt splitting + // note: no id_algorithm and wp/vsele_wp here const std::string &variation_dm0_pt20to40, const std::string &variation_dm0_pt40toInf, const std::string &variation_dm1_pt20to40, @@ -156,6 +157,22 @@ Id_vsJet_lt(ROOT::RDF::RNode df, const std::string &variation_dm10_pt40toInf, const std::string &variation_dm11_pt20to40, const std::string &variation_dm11_pt40toInf); +ROOT::RDF::RNode +Id_vsJet_lt(ROOT::RDF::RNode df, + correctionManager::CorrectionManager &correction_manager, + const std::string &outputname, + const std::string &pt, const std::string &decay_mode, + const std::string &gen_match, + const std::string &sf_file, + const std::string &sf_name, + const std::vector &selected_dms, + const std::string &wp, const std::string &vsele_wp, + const std::string &sf_dependence, + // DM split + const std::string &variation_dm0, + const std::string &variation_dm1, + const std::string &variation_dm10, + const std::string &variation_dm11); ROOT::RDF::RNode Id_vsJet_tt( ROOT::RDF::RNode df, correctionManager::CorrectionManager &correction_manager, diff --git a/src/taus.cxx b/src/taus.cxx index 49c162f8..af61388f 100644 --- a/src/taus.cxx +++ b/src/taus.cxx @@ -1343,7 +1343,6 @@ Id_vsJet_lt(ROOT::RDF::RNode df, sf = evaluator->evaluate({pt, decay_mode, gen_match, wp, vsele_wp, variation, sf_dependence}); } - // If pt_it == pt_map.begin(), it means pt < 20.0f (the first key), so sf remains 1. } } @@ -1351,22 +1350,65 @@ Id_vsJet_lt(ROOT::RDF::RNode df, return sf; }; - bool all_nominal = true; - for (const auto& [dm, pt_map] : variations) { - for (const auto& [pt_val, var_name] : pt_map) { - if (var_name != "nom") { - all_nominal = false; - break; + auto df1 = df.Define(outputname, sf_calculator, {pt, decay_mode, gen_match}); + return df1; +} + +ROOT::RDF::RNode +Id_vsJet_lt(ROOT::RDF::RNode df, + correctionManager::CorrectionManager &correction_manager, + const std::string &outputname, + const std::string &pt, const std::string &decay_mode, + const std::string &gen_match, + const std::string &sf_file, + const std::string &sf_name, + const std::vector &selected_dms, + const std::string &wp, const std::string &vsele_wp, + const std::string &sf_dependence, + // DM split + const std::string &variation_dm0, + const std::string &variation_dm1, + const std::string &variation_dm10, + const std::string &variation_dm11) { + const std::unordered_map variations = { + {0, variation_dm0}, + {1, variation_dm1}, + {10, variation_dm10}, + {11, variation_dm11}, + }; + Logger::get("physicsobject::tau::scalefactor::Id_vsJet_lt") + ->debug("Setting up function for tau id vsJet sf (DM binned only)"); + Logger::get("physicsobject::tau::scalefactor::Id_vsJet_lt")->debug("ID - Name {}", sf_name); + + auto evaluator = correction_manager.loadCorrection(sf_file, sf_name); + + auto sf_calculator = [evaluator, wp, vsele_wp, variations, + sf_dependence, selected_dms, + sf_name](const float &pt, const int &decay_mode, + const int &gen_match) { + Logger::get("physicsobject::tau::scalefactor::Id_vsJet_lt")->debug("ID - decayMode {}", decay_mode); + + double sf = 1.; + + if (std::find(selected_dms.begin(), selected_dms.end(), decay_mode) != selected_dms.end()) { + + auto it = variations.find(decay_mode); + if (it != variations.end()) { + std::string variation = it->second; + + Logger::get("physicsobject::tau::scalefactor::Id_vsJet_lt") + ->debug("ID {} - pt {}, decay_mode {}, gen_match {}, wp {}, " + "vsele_wp {}, variation {}, sf_dependence {}", + sf_name, pt, decay_mode, gen_match, wp, vsele_wp, + variation, sf_dependence); + + sf = evaluator->evaluate({pt, decay_mode, gen_match, wp, vsele_wp, variation, sf_dependence}); } } - if (!all_nominal) break; - } - - if (all_nominal) { - Logger::get("physicsobject::tau::scalefactor::Id_vsJet_lt") - ->debug("All variations are 'nom'. Skipping definition of {} to avoid collision.", outputname); - return df; - } + + Logger::get("physicsobject::tau::scalefactor::Id_vsJet_lt")->debug("Scale Factor {}", sf); + return sf; + }; auto df1 = df.Define(outputname, sf_calculator, {pt, decay_mode, gen_match}); return df1; From d55e8100563fe5e96d9605d79ec0f3e8cf0e4a0b Mon Sep 17 00:00:00 2001 From: nshadskiy Date: Thu, 8 Jan 2026 15:20:48 +0100 Subject: [PATCH 05/10] fix variation order inconsistency in TES --- include/taus.hxx | 30 ++++---- src/taus.cxx | 176 +++++++++++++++++++++++++---------------------- 2 files changed, 106 insertions(+), 100 deletions(-) diff --git a/include/taus.hxx b/include/taus.hxx index 0549d915..c84d6228 100644 --- a/include/taus.hxx +++ b/include/taus.hxx @@ -69,7 +69,6 @@ ROOT::RDF::RNode PtCorrectionMC_genuineTau( const std::string &correction_name, const std::string &id_algorithm, const std::string &variation_dm0, const std::string &variation_dm1, const std::string &variation_dm10, const std::string &variation_dm11); - ROOT::RDF::RNode PtCorrectionMC_genuineTau( ROOT::RDF::RNode df, correctionManager::CorrectionManager &correction_manager, @@ -77,10 +76,10 @@ ROOT::RDF::RNode PtCorrectionMC_genuineTau( const std::string &eta, const std::string &decay_mode, const std::string &gen_match, const std::string &es_file, const std::string &correction_name, const std::string &id_algorithm, - const std::string &wp, const std::string &vsele_wp, - const std::string &variation_dm0, const std::string &variation_dm1, - const std::string &variation_dm10, const std::string &variation_dm11); - + const std::string &variation_dm0_pt20to40, const std::string &variation_dm0_pt40toInf, + const std::string &variation_dm1_pt20to40, const std::string &variation_dm1_pt40toInf, + const std::string &variation_dm10_pt20to40, const std::string &variation_dm10_pt40toInf, + const std::string &variation_dm11_pt20to40, const std::string &variation_dm11_pt40toInf); ROOT::RDF::RNode PtCorrectionMC_genuineTau( ROOT::RDF::RNode df, correctionManager::CorrectionManager &correction_manager, @@ -89,10 +88,8 @@ ROOT::RDF::RNode PtCorrectionMC_genuineTau( const std::string &gen_match, const std::string &es_file, const std::string &correction_name, const std::string &id_algorithm, const std::string &wp, const std::string &vsele_wp, - const std::string &variation_dm0_20to40, const std::string &variation_dm1_20to40, - const std::string &variation_dm10_20to40, const std::string &variation_dm11_20to40, - const std::string &variation_dm0_40toInf, const std::string &variation_dm1_40toInf, - const std::string &variation_dm10_40toInf, const std::string &variation_dm11_40toInf); + const std::string &variation_dm0, const std::string &variation_dm1, + const std::string &variation_dm10, const std::string &variation_dm11); ROOT::RDF::RNode PtCorrectionMC_genuineTau( ROOT::RDF::RNode df, @@ -101,15 +98,12 @@ ROOT::RDF::RNode PtCorrectionMC_genuineTau( const std::string &eta, const std::string &decay_mode, const std::string &gen_match, const std::string &es_file, const std::string &correction_name, const std::string &id_algorithm, - // note: no id_algorithm and wp/vsele_wp here - const std::string &variation_dm0_pt20to40, - const std::string &variation_dm0_pt40toInf, - const std::string &variation_dm1_pt20to40, - const std::string &variation_dm1_pt40toInf, - const std::string &variation_dm10_pt20to40, - const std::string &variation_dm10_pt40toInf, - const std::string &variation_dm11_pt20to40, - const std::string &variation_dm11_pt40toInf); + const std::string &wp, const std::string &vsele_wp, + const std::string &variation_dm0_pt20to40, const std::string &variation_dm0_pt40toInf, + const std::string &variation_dm1_pt20to40, const std::string &variation_dm1_pt40toInf, + const std::string &variation_dm10_pt20to40, const std::string &variation_dm10_pt40toInf, + const std::string &variation_dm11_pt20to40, const std::string &variation_dm11_pt40toInf); + namespace quantity { ROOT::RDF::RNode IDFlag_v9(ROOT::RDF::RNode df, const std::string &outputname, const std::string &ID, const std::string &index_vector, diff --git a/src/taus.cxx b/src/taus.cxx index af61388f..38bf7933 100644 --- a/src/taus.cxx +++ b/src/taus.cxx @@ -574,25 +574,14 @@ PtCorrectionMC_muFake(ROOT::RDF::RNode df, /** * @brief This function corrects the transverse momentum (\f$p_T\f$) in MC * simulations of genuine hadronic taus. The energy scale correction for these - * objects is measured for four tau decay modes (dm0, dm1, dm10 and dm11) and - * depends on the transverse momentum of the hadronic tau. + * objects is measured for four tau decay modes (dm0, dm1, dm10 and dm11) of + * the hadronic tau. This correction is only applied to genuine hadronic taus + * (`gen_match=5`). * * The correction procedure is taken from the officially recommendation of the * TauPOG: * - * Run2 (UL): - * https://twiki.cern.ch/twiki/bin/viewauth/CMS/TauIDRecommendationForRun2 - * - - * https://cms-nanoaod-integration.web.cern.ch/commonJSONSFs/summaries/TAU_2018_UL_tau.html - * - - * https://cms-nanoaod-integration.web.cern.ch/commonJSONSFs/summaries/TAU_2017_UL_tau.html - * - - * https://cms-nanoaod-integration.web.cern.ch/commonJSONSFs/summaries/TAU_2016postVFP_UL_tau.html - * - - * https://cms-nanoaod-integration.web.cern.ch/commonJSONSFs/summaries/TAU_2016preVFP_UL_tau.html - * - * Run3: https://twiki.cern.ch/twiki/bin/view/CMS/TauIDRecommendationForRun3 - * (not added yet) + * Run2 (UL): https://twiki.cern.ch/twiki/bin/viewauth/CMS/TauIDRecommendationForRun2 * * @param df input dataframe * @param correction_manager correction manager responsible for loading the @@ -619,8 +608,9 @@ PtCorrectionMC_muFake(ROOT::RDF::RNode df, * * @return a dataframe containing the corrected transverse momenta * - * @note This correction is only applied to genuine hadronic taus - * (`gen_match=5`). + * @note This function is intended to be used for Run 2 analyses working with + * NanoAOD versions below v15 because it is not using the tau ID vsJet and vsEle + * working points as input. */ ROOT::RDF::RNode PtCorrectionMC_genuineTau( ROOT::RDF::RNode df, @@ -688,7 +678,55 @@ ROOT::RDF::RNode PtCorrectionMC_genuineTau( return df2; } - +/** + * @brief This function corrects the transverse momentum (\f$p_T\f$) in MC + * simulations of genuine hadronic taus. The energy scale correction for these + * objects is measured for four tau decay modes (dm0, dm1, dm10 and dm11) and + * in two (\f$p_T\f$) bins of the hadronic tau. This correction is only applied + * to genuine hadronic taus (`gen_match=5`). + * + * The correction procedure is taken from the officially recommendation of the + * TauPOG: + * + * Run2 (UL): https://twiki.cern.ch/twiki/bin/viewauth/CMS/TauIDRecommendationForRun2 + * + * @param df input dataframe + * @param correction_manager correction manager responsible for loading the + * correction file + * @param outputname name of the output column storing the corrected hadronic + * tau \f$p_T\f$ values + * @param pt name of the input column containing hadronic tau \f$p_T\f$ values + * @param eta name of the column containing hadronic tau eta values + * @param decay_mode name of the column containing hadronic tau decay modes + * @param gen_match name of the column with the matching information of the + * hadronic tau to generator-level particles (matches are: 1=prompt e, 2=prompt mu, + * 3=tau->e, 4=tau->mu, 5=had. tau, 0=unmatched) + * @param es_file path to the correction file for the energy scale correction + * @param correction_name name of the correction in `es_file` + * @param id_algorithm identification algorithm used for hadronic tau ID + * @param variation_dm0_20to40 variation for decay mode 0 and + * 20 GeV \f$<= p_{T,\tau} <\f$ 40 GeV, options are "nom", "up", "down" + * @param variation_dm0_40toInf variation for decay mode 0 and + * 40 GeV \f$<= p_{T,\tau}\f$, options are "nom", "up", "down" + * @param variation_dm1_20to40 variation for decay mode 1 and + * 20 GeV \f$<= p_{T,\tau} <\f$ 40 GeV, options are "nom", "up", "down" + * @param variation_dm1_40toInf variation for decay mode 1 and + * 40 GeV \f$<= p_{T,\tau}\f$, options are "nom", "up", "down" + * @param variation_dm10_20to40 variation for decay mode 10 and + * 20 GeV \f$<= p_{T,\tau} <\f$ 40 GeV, options are "nom", "up", "down" + * @param variation_dm10_40toInf variation for decay mode 10 and + * 40 GeV \f$<= p_{T,\tau}\f$, options are "nom", "up", "down" + * @param variation_dm11_20to40 variation for decay mode 11 and + * 20 GeV \f$<= p_{T,\tau} <\f$ 40 GeV, options are "nom", "up", "down" + * @param variation_dm11_40toInf variation for decay mode 11 and + * 40 GeV \f$<= p_{T,\tau}\f$, options are "nom", "up", "down" + * + * @return a dataframe containing the corrected transverse momenta + * + * @note This function is intended to be used for Run 2 analyses working with + * NanoAOD versions below v15 because it is not using the tau ID vsJet and vsEle + * working points as input. + */ ROOT::RDF::RNode PtCorrectionMC_genuineTau( ROOT::RDF::RNode df, correctionManager::CorrectionManager &correction_manager, @@ -696,15 +734,10 @@ ROOT::RDF::RNode PtCorrectionMC_genuineTau( const std::string &eta, const std::string &decay_mode, const std::string &gen_match, const std::string &es_file, const std::string &correction_name, const std::string &id_algorithm, - // New: 8 arguments for DM/Pt splitting - const std::string &variation_dm0_pt20to40, - const std::string &variation_dm0_pt40toInf, - const std::string &variation_dm1_pt20to40, - const std::string &variation_dm1_pt40toInf, - const std::string &variation_dm10_pt20to40, - const std::string &variation_dm10_pt40toInf, - const std::string &variation_dm11_pt20to40, - const std::string &variation_dm11_pt40toInf) { + const std::string &variation_dm0_pt20to40, const std::string &variation_dm0_pt40toInf, + const std::string &variation_dm1_pt20to40, const std::string &variation_dm1_pt40toInf, + const std::string &variation_dm10_20to40, const std::string &variation_dm10_40toInf, + const std::string &variation_dm11_20to40, const std::string &variation_dm11_40toInf) { // 1. Define the variation map structure // This map acts as both the variation lookup AND the "Allowed Decay Modes" list @@ -779,30 +812,19 @@ ROOT::RDF::RNode PtCorrectionMC_genuineTau( return df2; } - - /** * @brief This function corrects the transverse momentum (\f$p_T\f$) in MC * simulations of genuine hadronic taus. The energy scale correction for these - * objects is measured for four tau decay modes (dm0, dm1, dm10 and dm11) and - * depends on the transverse momentum of the hadronic tau. + * objects is measured for four tau decay modes (dm0, dm1, dm10 and dm11) of + * the hadronic tau. This correction is only applied to genuine hadronic taus + * (`gen_match=5`). * * The correction procedure is taken from the officially recommendation of the * TauPOG: * - * Run2 (UL): - * https://twiki.cern.ch/twiki/bin/viewauth/CMS/TauIDRecommendationForRun2 - * - - * https://cms-nanoaod-integration.web.cern.ch/commonJSONSFs/summaries/TAU_2018_UL_tau.html - * - - * https://cms-nanoaod-integration.web.cern.ch/commonJSONSFs/summaries/TAU_2017_UL_tau.html - * - - * https://cms-nanoaod-integration.web.cern.ch/commonJSONSFs/summaries/TAU_2016postVFP_UL_tau.html - * - - * https://cms-nanoaod-integration.web.cern.ch/commonJSONSFs/summaries/TAU_2016preVFP_UL_tau.html + * Run2 (UL): https://twiki.cern.ch/twiki/bin/viewauth/CMS/TauIDRecommendationForRun2 * * Run3: https://twiki.cern.ch/twiki/bin/view/CMS/TauIDRecommendationForRun3 - * (not added yet) * * @param df input dataframe * @param correction_manager correction manager responsible for loading the @@ -818,8 +840,6 @@ ROOT::RDF::RNode PtCorrectionMC_genuineTau( * @param es_file path to the correction file for the energy scale correction * @param correction_name name of the correction in `es_file` * @param id_algorithm identification algorithm used for hadronic tau ID - * @param wp working point of the vsJet ID - * @param vsele_wp working point of the vsEle ID * @param variation_dm0 variation for decay mode 0, options are "nom", "up", * "down" * @param variation_dm1 variation for decay mode 1, options are "nom", "up", @@ -831,8 +851,9 @@ ROOT::RDF::RNode PtCorrectionMC_genuineTau( * * @return a dataframe containing the corrected transverse momenta * - * @note This correction is only applied to genuine hadronic taus - * (`gen_match=5`). + * @note This function is intended to be used for Run 3 analyses or Run 2 + * analyses working with NanoAODv15. The reason is the newly introduced + * dependence of the tau ID vsJet and vsEle working points. */ ROOT::RDF::RNode PtCorrectionMC_genuineTau( ROOT::RDF::RNode df, @@ -901,29 +922,19 @@ ROOT::RDF::RNode PtCorrectionMC_genuineTau( return df2; } - /** * @brief This function corrects the transverse momentum (\f$p_T\f$) in MC * simulations of genuine hadronic taus. The energy scale correction for these - * objects is measured for four tau decay modes (dm0, dm1, dm10 and dm11) and - * depends on the transverse momentum of the hadronic tau. + * objects is measured for four tau decay modes (dm0, dm1, dm10 and dm11) and + * in two (\f$p_T\f$) bins of the hadronic tau. This correction is only applied + * to genuine hadronic taus (`gen_match=5`). * * The correction procedure is taken from the officially recommendation of the * TauPOG: * - * Run2 (UL): - * https://twiki.cern.ch/twiki/bin/viewauth/CMS/TauIDRecommendationForRun2 - * - - * https://cms-nanoaod-integration.web.cern.ch/commonJSONSFs/summaries/TAU_2018_UL_tau.html - * - - * https://cms-nanoaod-integration.web.cern.ch/commonJSONSFs/summaries/TAU_2017_UL_tau.html - * - - * https://cms-nanoaod-integration.web.cern.ch/commonJSONSFs/summaries/TAU_2016postVFP_UL_tau.html - * - - * https://cms-nanoaod-integration.web.cern.ch/commonJSONSFs/summaries/TAU_2016preVFP_UL_tau.html + * Run2 (UL): https://twiki.cern.ch/twiki/bin/viewauth/CMS/TauIDRecommendationForRun2 * * Run3: https://twiki.cern.ch/twiki/bin/view/CMS/TauIDRecommendationForRun3 - * (not added yet) * * @param df input dataframe * @param correction_manager correction manager responsible for loading the @@ -941,27 +952,28 @@ ROOT::RDF::RNode PtCorrectionMC_genuineTau( * @param id_algorithm identification algorithm used for hadronic tau ID * @param wp working point of the vsJet ID * @param vsele_wp working point of the vsEle ID - * @param variation_dm0_20to40 variation for decay mode 0, options are "nom", "up", - * "down" - * @param variation_dm1_20to40 variation for decay mode 1, options are "nom", "up", - * "down" - * @param variation_dm10_20to40 variation for decay mode 10, options are "nom", "up", - * "down" - * @param variation_dm11_20to40 variation for decay mode 11, options are "nom", "up", - * "down" - * @param variation_dm0_40toInf variation for decay mode 0, options are "nom", "up", - * "down" - * @param variation_dm1_40toInf variation for decay mode 1, options are "nom", "up", - * "down" - * @param variation_dm10_40toInf variation for decay mode 10, options are "nom", "up", - * "down" - * @param variation_dm11_40toInf variation for decay mode 11, options are "nom", "up", - * "down" + * @param variation_dm0_20to40 variation for decay mode 0 and + * 20 GeV \f$<= p_{T,\tau} <\f$ 40 GeV, options are "nom", "up", "down" + * @param variation_dm0_40toInf variation for decay mode 0 and + * 40 GeV \f$<= p_{T,\tau}\f$, options are "nom", "up", "down" + * @param variation_dm1_20to40 variation for decay mode 1 and + * 20 GeV \f$<= p_{T,\tau} <\f$ 40 GeV, options are "nom", "up", "down" + * @param variation_dm1_40toInf variation for decay mode 1 and + * 40 GeV \f$<= p_{T,\tau}\f$, options are "nom", "up", "down" + * @param variation_dm10_20to40 variation for decay mode 10 and + * 20 GeV \f$<= p_{T,\tau} <\f$ 40 GeV, options are "nom", "up", "down" + * @param variation_dm10_40toInf variation for decay mode 10 and + * 40 GeV \f$<= p_{T,\tau}\f$, options are "nom", "up", "down" + * @param variation_dm11_20to40 variation for decay mode 11 and + * 20 GeV \f$<= p_{T,\tau} <\f$ 40 GeV, options are "nom", "up", "down" + * @param variation_dm11_40toInf variation for decay mode 11 and + * 40 GeV \f$<= p_{T,\tau}\f$, options are "nom", "up", "down" * * @return a dataframe containing the corrected transverse momenta * - * @note This correction is only applied to genuine hadronic taus - * (`gen_match=5`). + * @note This function is intended to be used for Run 3 analyses or Run 2 + * analyses working with NanoAODv15. The reason is the newly introduced + * dependence of the tau ID vsJet and vsEle working points. */ ROOT::RDF::RNode PtCorrectionMC_genuineTau( ROOT::RDF::RNode df, @@ -971,10 +983,10 @@ ROOT::RDF::RNode PtCorrectionMC_genuineTau( const std::string &gen_match, const std::string &es_file, const std::string &correction_name, const std::string &id_algorithm, const std::string &wp, const std::string &vsele_wp, - const std::string &variation_dm0_20to40, const std::string &variation_dm1_20to40, - const std::string &variation_dm10_20to40, const std::string &variation_dm11_20to40, - const std::string &variation_dm0_40toInf, const std::string &variation_dm1_40toInf, - const std::string &variation_dm10_40toInf, const std::string &variation_dm11_40toInf) { + const std::string &variation_dm0_pt20to40, const std::string &variation_dm0_pt40toInf, + const std::string &variation_dm1_pt20to40, const std::string &variation_dm1_pt40toInf, + const std::string &variation_dm10_20to40, const std::string &variation_dm10_40toInf, + const std::string &variation_dm11_20to40, const std::string &variation_dm11_40toInf) { // In nanoAODv12 the type of tau decay mode was changed to UChar_t // For v9 compatibility a type casting is applied const std::map variations_dm0 = { From 7d745632b06e71f1d8c0f840a6f4874265544a22 Mon Sep 17 00:00:00 2001 From: nshadskiy Date: Thu, 8 Jan 2026 18:43:04 +0100 Subject: [PATCH 06/10] remove redundant tau ID vs jet functions and add new tau embedding SF file --- .../unittest/producers/scalefactors.py | 4 +- data/embedding/tau_emb_2018UL.json.gz | Bin 0 -> 4406 bytes include/taus.hxx | 48 +- src/taus.cxx | 550 +++++------------- 4 files changed, 165 insertions(+), 437 deletions(-) create mode 100644 data/embedding/tau_emb_2018UL.json.gz diff --git a/analysis_configurations/unittest/producers/scalefactors.py b/analysis_configurations/unittest/producers/scalefactors.py index 2b4fbbe6..6c535148 100644 --- a/analysis_configurations/unittest/producers/scalefactors.py +++ b/analysis_configurations/unittest/producers/scalefactors.py @@ -130,7 +130,7 @@ ############################ Tau_1_VsJetTauID_SF = ExtendedVectorProducer( name="Tau_1_VsJetTauID_SF", - call="""physicsobject::tau::scalefactor::Id_vsJet_tt( + call="""physicsobject::tau::scalefactor::Id_vsJet( {df}, correctionManager, {output}, @@ -215,7 +215,7 @@ ) Tau_2_VsJetTauID_tt_SF = ExtendedVectorProducer( name="Tau_2_VsJetTauID_tt_SF", - call="""physicsobject::tau::scalefactor::Id_vsJet_tt( + call="""physicsobject::tau::scalefactor::Id_vsJet( {df}, correctionManager, {output}, diff --git a/data/embedding/tau_emb_2018UL.json.gz b/data/embedding/tau_emb_2018UL.json.gz new file mode 100644 index 0000000000000000000000000000000000000000..b15ae28d605e1b5b4917856fcdbe439ebdebafc9 GIT binary patch literal 4406 zcmZWs2T+q+(?$dZQK~eNCZR|TMLLEqfzaCxAQ1^5y?5!tMFfG+J3=5_Ls5!|5)hCQ zN>F;25(pg$y?^?t_y1=8*_n6FzB^~1-RI1l=Pc(73JPa~YmTHBYFZj>& zreO?|0E)}POd&8=ADEAg?~i|OCcYjncHS^u6PTYLYIRxCb-V^!~ZSRn|jR zL|g_YE-UKf?e0dhp4a0x*+n075PD6Ot)E2u%fX9?TvOmD68@a$$$cu1fR87?sxwCx zt&3j?JTMj+Pgln>-8EczyLMu^s4>NRt;bU67;PNi1~1%9SP#_6{Y{0 z(2nsmd}a;SU=TdvWaPzu13RQrUp|{TVo?pv(j#BkH^ZOy5I}0$dG9nj3(xKL}H z{}?uAi%5LPLR!BrL|-^o0d$I>M|OmN&igk@JF4fF zI*yC0Z7iY7B?nlK+~|NZN>uYUsHrb92Y9R0ZtKL&Pti@+mCr{6LgdcE>2wJT7E(bp zKkFl!u3cWe-5xNct1fJ0B9+?#yB88ikm0~eM{N=NN(aW56Wy$9{fsYkHapsBCV<#Z zpEt}{RMH-*ZPV^zDY#)e6)jev7QFQAwK%Nl)L$|GSO~FvN2|G$;cm8W`T+tQ$&K zj{eIWxbIx+aA@FKqUSX#*32JxR6r9c!g}(3Wi5q`MPG+_d1&>Uei{>j7=-O5SSb%5 zGTLUG4HYwjn43gJ2DN*92>0I&>hyR>if(31X3JIFAY?q#Hn4TOQBoW>0&@=5=A?j{mE>$MPHe`BZHT#P1-m$-!6_PLG zbx@07Wz7;f+OMqP@2B?q_gvgV$<{jGF8TY*7Oi?J$xbr+Tb_LPQ|elMW#1-0yvDIU z!TwjVU-9J`kFjsZ#fHNhqYC@?`uAEjxj#}$B6Y}u_476QLJ@jj`VQ*$t+Vqwqjxv_ z(q!0ovST?vFAcxczx54DG+)O!#7PR3(6+Kw;`t6t-A4x-s~uKS@iX$=wRUa?>Y?fP{B;VkzLNR zBI|p#hIwIQ?GzZ5AR`z=WO^8JU=+NV>m@xwlP0U)pM-4FgZ5|c_Qo=OjLC=-9|)*Q z9jG8)PNv?Y+R9>hyLC5KohMmY_)^-KdOR+u7?WZ}wbJM&nNEv$0Bo2E8C@TA19Ioh z-7HKx1?s-N2A`*upi7<#w9N!oKg>$XHbmZOnAHT^TMkpAOS~+uZDIyzl=*M1kQGrb zllhR!U&@ocmnS=UPzal8OV_D?Z?e9nuq(RQ)c~s&yI^V0>&HbkdMhUOlhf@DD}jhE#ZXEJ(%8eht&3D@;3`OA%3 zz4$OPt+&42Q3d`JaFgppJZ>$We;8WC(e@0e=RuS83CIE`mAI4@4pHXYFN<=>n`o>7 zc3p01=c3v5W5%>|^{=$s8BmsyT?s6t-!mnRQbeKXDfoU-nuLjhG;%S-{&15hyU5`4 zpW*YaN~=C*{-CvcXkN6XNZ7}L$@Jp^+AXf&ccL>YW~2S{>~Muo08JOzi~K;V*R;!x z4Du)M1z8C4h)P%Q_h!y>@pO@Q(a#VYMK!$pLRi0!f}m z687xw-i8z#35?d>3wdy(S^~vmT20S9=?PDV;+hDaPw%M|Tk^HI621(uEC^qU5Er=< z!3*PR9FAct@%>1ZEWzFIHJ8=7q?RQ@!-+kgRKhmpOM{2=#sy=Tmkw8jGogg81EU}`*4pOYMy zI48);xoV=iz>e(FYN1=tN~U+&m)7U2BTk{EnU{eQOCNJHmGpQfLN5O!jeo~7M`)YW zouf!fj^rPsqI|y_4;8CTtlD$+PSS>cfbtFwcs`CwPyXalk_WdEibjBI zNaR^Z8w$8>R`Fqc-el$tVq1~syF1k&jy_45KMJ=j4SCXrKS;#76yxPL(iZMCl!m=k zyxtrwOa+yAC8WgVuva@cX#iPLczUO%K|iy6YE>&4AK`lifbYs55Y4Nh0D zA@*ogS$^QmxJ6|*Vd3lvv&=@r+wv{e61!s(>|SNe@T(E~Yf72}OvsNr>!EKv)80<} zmbn$(KQebHnF?1w1+1Wf6qst3#1GG7HR9r81`pAt`rBlkJmdBrph*|OyoA?8vx>9- zQSu_<$-8u+wcw4f#EgEQ$B2)f+fmXGqIllY3wYCabN~FBX{YXq(?(1$rKv4P>FRKe zy>55T7%@wlddTkhzoO?TTwnztAcqOl_@~*O1%{XVGkRswTKW!(A_S|qpWa3PZAk?6 zfBWi8SRVX%T0OtH6za7}V^f8IlLj@8N1ZzpQVVa_7GdDv-ch%(sZF+E+I(3;dt?` zW{2JY5fPbI`6Y|1V0(BjGqM~}9`Z6C&HTjZOiQfyT3<_Y)kreH7VJAF~@_8feLOj}+7o}vb8QjOhTy&O-e2b&4uu!=eS3?3SYI+5$%8|>+ zx$G`wERPx(4~Rf0g9`x$^a7NrWZI;>5s1CDN0-v2L$2EAl6GHO4EItFSgv#Qx8>@(!i$~ z1wOs+IO?=ej0dWLB55{DT*h7{261=p2*uBm8up+yL?kqYdfP{p9SJl*{tQy)K9LvR zch^WKkSi^$sb0Yzh*R+8PH@O0(xSr?! z%RpLKF9Qkq9YgA)d=f2UfY$%DKnDJe2j7stc&+iMe|6IVV_ygNMK8KD7jUli>TqmU zEY}arWV66tm0UJsbco`5V529bfXIbp7s>YpuF`2Z%``{!Na%I$W(X?MGg!zg)bJ?8vd2I0$D`l~!q3;h z#teGW2H+fYY|^?PT@GURBh-x6XIH=bYsdQM>_M|8Jz8Ub!z%mV8yL`*-|zC*+Pzwtc-}atHp2rKeT_-Km@V z!%MKGHu8gt-DQU-ZYpxadLIQx`%6_;=T=+G5<+c++(ea9-lzuUd~tIefu4ORQh7LD zSm|UiDpiJ-`8t$tWt!6UIPh$r@Y*Gjh6&@m`Rom~QvNm7nVW&ec-;%Tz(HB?b?{(R zZys$O&bb8J8RtbtW;0pjhnGUb(FEDTvoE1fK()%Akv@PenM99 zoU?!;4mp$mU&f0`3-S6t5hn*$fLO2HO%ih zlkiH1KN`TX10YJYO^ z_rBUmy(5TEU-=|a=Y;MLmths3I2ZV7FBa&+)PHgN>s*=xx5F%TymN=A`-A$Nu&ZW0 h-$d_&MzS(K7r^>M&pAm*E-o&Uu$|Rt3SS~6`43DTn^*t< literal 0 HcmV?d00001 diff --git a/include/taus.hxx b/include/taus.hxx index c84d6228..2b4d0720 100644 --- a/include/taus.hxx +++ b/include/taus.hxx @@ -131,43 +131,7 @@ Id_vsJet_lt(ROOT::RDF::RNode df, const std::string &sf_vsjet_tau40to500, const std::string &sf_vsjet_tau500to1000, const std::string &sf_vsjet_tau1000toinf); -ROOT::RDF::RNode -Id_vsJet_lt(ROOT::RDF::RNode df, - correctionManager::CorrectionManager &correction_manager, - const std::string &outputname, - const std::string &pt, const std::string &decay_mode, - const std::string &gen_match, - const std::string &sf_file, - const std::string &sf_name, - const std::vector &selected_dms, - const std::string &wp, const std::string &vsele_wp, - const std::string &sf_dependence, - // DM + pT split - const std::string &variation_dm0_pt20to40, - const std::string &variation_dm0_pt40toInf, - const std::string &variation_dm1_pt20to40, - const std::string &variation_dm1_pt40toInf, - const std::string &variation_dm10_pt20to40, - const std::string &variation_dm10_pt40toInf, - const std::string &variation_dm11_pt20to40, - const std::string &variation_dm11_pt40toInf); -ROOT::RDF::RNode -Id_vsJet_lt(ROOT::RDF::RNode df, - correctionManager::CorrectionManager &correction_manager, - const std::string &outputname, - const std::string &pt, const std::string &decay_mode, - const std::string &gen_match, - const std::string &sf_file, - const std::string &sf_name, - const std::vector &selected_dms, - const std::string &wp, const std::string &vsele_wp, - const std::string &sf_dependence, - // DM split - const std::string &variation_dm0, - const std::string &variation_dm1, - const std::string &variation_dm10, - const std::string &variation_dm11); -ROOT::RDF::RNode Id_vsJet_tt( +ROOT::RDF::RNode Id_vsJet( ROOT::RDF::RNode df, correctionManager::CorrectionManager &correction_manager, const std::string &outputname, @@ -180,7 +144,7 @@ ROOT::RDF::RNode Id_vsJet_tt( const std::string &variation_dm1, const std::string &variation_dm10, const std::string &variation_dm11); -ROOT::RDF::RNode Id_vsJet_tt( +ROOT::RDF::RNode Id_vsJet( ROOT::RDF::RNode df, correctionManager::CorrectionManager &correction_manager, const std::string &outputname, @@ -189,10 +153,10 @@ ROOT::RDF::RNode Id_vsJet_tt( const std::string &sf_file, const std::string &sf_name, const std::string &wp, const std::string &vsele_wp, const std::string &sf_dependence, - const std::string &variation_dm0_20to40, const std::string &variation_dm1_20to40, - const std::string &variation_dm10_20to40, const std::string &variation_dm11_20to40, - const std::string &variation_dm0_40toInf, const std::string &variation_dm1_40toInf, - const std::string &variation_dm10_40toInf, const std::string &variation_dm11_40toInf); + const std::string &variation_dm0_pt20to40, const std::string &variation_dm0_pt40toInf, + const std::string &variation_dm1_pt20to40, const std::string &variation_dm1_pt40toInf, + const std::string &variation_dm10_pt20to40, const std::string &variation_dm10_pt40toInf, + const std::string &variation_dm11_pt20to40, const std::string &variation_dm11_pt40toInf); ROOT::RDF::RNode Id_vsEle( ROOT::RDF::RNode df, correctionManager::CorrectionManager &correction_manager, diff --git a/src/taus.cxx b/src/taus.cxx index 38bf7933..4c94c8b0 100644 --- a/src/taus.cxx +++ b/src/taus.cxx @@ -704,22 +704,22 @@ ROOT::RDF::RNode PtCorrectionMC_genuineTau( * @param es_file path to the correction file for the energy scale correction * @param correction_name name of the correction in `es_file` * @param id_algorithm identification algorithm used for hadronic tau ID - * @param variation_dm0_20to40 variation for decay mode 0 and - * 20 GeV \f$<= p_{T,\tau} <\f$ 40 GeV, options are "nom", "up", "down" - * @param variation_dm0_40toInf variation for decay mode 0 and - * 40 GeV \f$<= p_{T,\tau}\f$, options are "nom", "up", "down" - * @param variation_dm1_20to40 variation for decay mode 1 and - * 20 GeV \f$<= p_{T,\tau} <\f$ 40 GeV, options are "nom", "up", "down" - * @param variation_dm1_40toInf variation for decay mode 1 and - * 40 GeV \f$<= p_{T,\tau}\f$, options are "nom", "up", "down" - * @param variation_dm10_20to40 variation for decay mode 10 and - * 20 GeV \f$<= p_{T,\tau} <\f$ 40 GeV, options are "nom", "up", "down" - * @param variation_dm10_40toInf variation for decay mode 10 and - * 40 GeV \f$<= p_{T,\tau}\f$, options are "nom", "up", "down" - * @param variation_dm11_20to40 variation for decay mode 11 and - * 20 GeV \f$<= p_{T,\tau} <\f$ 40 GeV, options are "nom", "up", "down" - * @param variation_dm11_40toInf variation for decay mode 11 and - * 40 GeV \f$<= p_{T,\tau}\f$, options are "nom", "up", "down" + * @param variation_dm0_pt20to40 variation for decay mode 0 and + * \f$20 \leq p_T <40\f$ GeV, options are "nom", "up", "down" + * @param variation_dm0_pt40toInf variation for decay mode 0 and + * 40 GeV \f$\leq p_{T,\tau}\f$, options are "nom", "up", "down" + * @param variation_dm1_pt20to40 variation for decay mode 1 and + * \f$20 \leq p_T <40\f$ GeV, options are "nom", "up", "down" + * @param variation_dm1_pt40toInf variation for decay mode 1 and + * 40 GeV \f$\leq p_{T,\tau}\f$, options are "nom", "up", "down" + * @param variation_dm10_pt20to40 variation for decay mode 10 and + * \f$20 \leq p_T <40\f$ GeV, options are "nom", "up", "down" + * @param variation_dm10_pt40toInf variation for decay mode 10 and + * 40 GeV \f$\leq p_{T,\tau}\f$, options are "nom", "up", "down" + * @param variation_dm11_pt20to40 variation for decay mode 11 and + * \f$20 \leq p_T <40\f$ GeV, options are "nom", "up", "down" + * @param variation_dm11_pt40toInf variation for decay mode 11 and + * 40 GeV \f$\leq p_{T,\tau}\f$, options are "nom", "up", "down" * * @return a dataframe containing the corrected transverse momenta * @@ -736,11 +736,9 @@ ROOT::RDF::RNode PtCorrectionMC_genuineTau( const std::string &correction_name, const std::string &id_algorithm, const std::string &variation_dm0_pt20to40, const std::string &variation_dm0_pt40toInf, const std::string &variation_dm1_pt20to40, const std::string &variation_dm1_pt40toInf, - const std::string &variation_dm10_20to40, const std::string &variation_dm10_40toInf, - const std::string &variation_dm11_20to40, const std::string &variation_dm11_40toInf) { + const std::string &variation_dm10_pt20to40, const std::string &variation_dm10_pt40toInf, + const std::string &variation_dm11_pt20to40, const std::string &variation_dm11_pt40toInf) { - // 1. Define the variation map structure - // This map acts as both the variation lookup AND the "Allowed Decay Modes" list const std::unordered_map> variations = { {0, {{20.0f, variation_dm0_pt20to40}, {40.0f, variation_dm0_pt40toInf}}}, {1, {{20.0f, variation_dm1_pt20to40}, {40.0f, variation_dm1_pt40toInf}}}, @@ -748,13 +746,13 @@ ROOT::RDF::RNode PtCorrectionMC_genuineTau( {11, {{20.0f, variation_dm11_pt20to40}, {40.0f, variation_dm11_pt40toInf}}}, }; - // 2. Setup + // In nanoAODv12 the type of tau decay mode was changed to UChar_t + // For v9 compatibility a type casting is applied auto [df1, decay_mode_column] = utility::Cast, ROOT::RVec>( df, decay_mode+"_v12", "ROOT::VecOps::RVec", decay_mode); auto evaluator = correction_manager.loadCorrection(es_file, correction_name); - // 3. Calculation Lambda auto correction_lambda = [evaluator, id_algorithm, variations](const ROOT::RVec &pts, const ROOT::RVec &etas, @@ -768,41 +766,38 @@ ROOT::RDF::RNode PtCorrectionMC_genuineTau( for (size_t i = 0; i < pts.size(); i++) { float current_pt = pts.at(i); int current_dm = decay_modes.at(i); - int current_gen = gen_matches.at(i); + int current_gen_match = gen_matches.at(i); // Default: No correction corrected_pts[i] = current_pt; - std::string variation_to_use = "nom"; + std::string variation = "nom"; // Only correct if GenMatch is 5 (Genuine Tau) - if (current_gen == 5) { + if (current_gen_match == 5) { // Look for DM in our allowed map auto dm_it = variations.find(current_dm); - // CRITICAL FIX: Only call evaluate if DM is supported (0, 1, 10, 11) + // Only call evaluate if DM is supported (0, 1, 10, 11) if (dm_it != variations.end()) { const auto &pt_map = dm_it->second; - // Determine variation based on Pt + // Determine variation based on pT auto pt_it = pt_map.upper_bound(current_pt); if (pt_it != pt_map.begin()) { - variation_to_use = std::prev(pt_it)->second; + variation = std::prev(pt_it)->second; } - // Evaluate now safe because current_dm is guaranteed valid auto correction_factor = evaluator->evaluate( {current_pt, std::abs(etas.at(i)), current_dm, - current_gen, id_algorithm, - variation_to_use}); + current_gen_match, id_algorithm, variation}); corrected_pts[i] = current_pt * correction_factor; } } - // Logging - Logger::get("physicsobject::tau::PtCorrection_genuineTau") - ->debug("tau pt before {}, tau pt after {}, decaymode {}, var {}", - current_pt, corrected_pts.at(i), current_dm, variation_to_use); + Logger::get("physicsobject::tau::PtCorrectionMC_genuineTau") + ->debug("tau pt before {}, tau pt after {}, decay mode {}, variation {}", + current_pt, corrected_pts.at(i), current_dm, variation); } return corrected_pts; }; @@ -840,6 +835,8 @@ ROOT::RDF::RNode PtCorrectionMC_genuineTau( * @param es_file path to the correction file for the energy scale correction * @param correction_name name of the correction in `es_file` * @param id_algorithm identification algorithm used for hadronic tau ID + * @param wp working point of the vsJet ID + * @param vsele_wp working point of the vsEle ID * @param variation_dm0 variation for decay mode 0, options are "nom", "up", * "down" * @param variation_dm1 variation for decay mode 1, options are "nom", "up", @@ -952,22 +949,22 @@ ROOT::RDF::RNode PtCorrectionMC_genuineTau( * @param id_algorithm identification algorithm used for hadronic tau ID * @param wp working point of the vsJet ID * @param vsele_wp working point of the vsEle ID - * @param variation_dm0_20to40 variation for decay mode 0 and - * 20 GeV \f$<= p_{T,\tau} <\f$ 40 GeV, options are "nom", "up", "down" - * @param variation_dm0_40toInf variation for decay mode 0 and - * 40 GeV \f$<= p_{T,\tau}\f$, options are "nom", "up", "down" - * @param variation_dm1_20to40 variation for decay mode 1 and - * 20 GeV \f$<= p_{T,\tau} <\f$ 40 GeV, options are "nom", "up", "down" - * @param variation_dm1_40toInf variation for decay mode 1 and - * 40 GeV \f$<= p_{T,\tau}\f$, options are "nom", "up", "down" - * @param variation_dm10_20to40 variation for decay mode 10 and - * 20 GeV \f$<= p_{T,\tau} <\f$ 40 GeV, options are "nom", "up", "down" + * @param variation_dm0_20to40 variation for decay mode 0 and + * \f$20 \leq p_T <40\f$ GeV, options are "nom", "up", "down" + * @param variation_dm0_40toInf variation for decay mode 0 and + * 40 GeV \f$\leq p_{T,\tau}\f$, options are "nom", "up", "down" + * @param variation_dm1_20to40 variation for decay mode 1 and + * \f$20 \leq p_T <40\f$ GeV, options are "nom", "up", "down" + * @param variation_dm1_40toInf variation for decay mode 1 and + * 40 GeV \f$\leq p_{T,\tau}\f$, options are "nom", "up", "down" + * @param variation_dm10_20to40 variation for decay mode 10 and + * \f$20 \leq p_T <40\f$ GeV, options are "nom", "up", "down" * @param variation_dm10_40toInf variation for decay mode 10 and - * 40 GeV \f$<= p_{T,\tau}\f$, options are "nom", "up", "down" - * @param variation_dm11_20to40 variation for decay mode 11 and - * 20 GeV \f$<= p_{T,\tau} <\f$ 40 GeV, options are "nom", "up", "down" - * @param variation_dm11_40toInf variation for decay mode 11 and - * 40 GeV \f$<= p_{T,\tau}\f$, options are "nom", "up", "down" + * 40 GeV \f$\leq p_{T,\tau}\f$, options are "nom", "up", "down" + * @param variation_dm11_20to40 variation for decay mode 11 and + * \f$20 \leq p_T <40\f$ GeV, options are "nom", "up", "down" + * @param variation_dm11_40toInf variation for decay mode 11 and + * 40 GeV \f$\leq p_{T,\tau}\f$, options are "nom", "up", "down" * * @return a dataframe containing the corrected transverse momenta * @@ -985,38 +982,25 @@ ROOT::RDF::RNode PtCorrectionMC_genuineTau( const std::string &wp, const std::string &vsele_wp, const std::string &variation_dm0_pt20to40, const std::string &variation_dm0_pt40toInf, const std::string &variation_dm1_pt20to40, const std::string &variation_dm1_pt40toInf, - const std::string &variation_dm10_20to40, const std::string &variation_dm10_40toInf, - const std::string &variation_dm11_20to40, const std::string &variation_dm11_40toInf) { - // In nanoAODv12 the type of tau decay mode was changed to UChar_t - // For v9 compatibility a type casting is applied - const std::map variations_dm0 = { - {20.0f, variation_dm0_20to40}, - {40.0f, variation_dm0_40toInf}, - {100000.0f, variation_dm0_40toInf}, - }; - const std::map variations_dm1 = { - {20.0f, variation_dm1_20to40}, - {40.0f, variation_dm1_40toInf}, - {100000.0f, variation_dm1_40toInf}, - }; - const std::map variations_dm10 = { - {20.0f, variation_dm10_20to40}, - {40.0f, variation_dm10_40toInf}, - {100000.0f, variation_dm10_40toInf}, - }; - const std::map variations_dm11 = { - {20.0f, variation_dm11_20to40}, - {40.0f, variation_dm11_40toInf}, - {100000.0f, variation_dm11_40toInf}, + const std::string &variation_dm10_pt20to40, const std::string &variation_dm10_pt40toInf, + const std::string &variation_dm11_pt20to40, const std::string &variation_dm11_pt40toInf) { + + const std::unordered_map> variations = { + {0, {{20.0f, variation_dm0_pt20to40}, {40.0f, variation_dm0_pt40toInf}}}, + {1, {{20.0f, variation_dm1_pt20to40}, {40.0f, variation_dm1_pt40toInf}}}, + {10, {{20.0f, variation_dm10_pt20to40}, {40.0f, variation_dm10_pt40toInf}}}, + {11, {{20.0f, variation_dm11_pt20to40}, {40.0f, variation_dm11_pt40toInf}}}, }; + // In nanoAODv12 the type of tau decay mode was changed to UChar_t + // For v9 compatibility a type casting is applied auto [df1, decay_mode_column] = utility::Cast, ROOT::RVec>( df, decay_mode+"_v12", "ROOT::VecOps::RVec", decay_mode); auto evaluator = correction_manager.loadCorrection(es_file, correction_name); auto correction_lambda = - [evaluator, id_algorithm, wp, vsele_wp, variations_dm0, variations_dm1, variations_dm10, variations_dm11](const ROOT::RVec &pts, + [evaluator, id_algorithm, wp, vsele_wp, variations](const ROOT::RVec &pts, const ROOT::RVec &etas, const ROOT::RVec &decay_modes_v12, const ROOT::RVec &gen_matches_char) { @@ -1024,68 +1008,40 @@ ROOT::RDF::RNode PtCorrectionMC_genuineTau( auto gen_matches = static_cast>(gen_matches_char); ROOT::RVec corrected_pts(pts.size()); for (int i = 0; i < pts.size(); i++) { - if (gen_matches.at(i) == 5) { - if (decay_modes.at(i) == 0) { - auto it = variations_dm0.upper_bound(pts.at(i)); - if (it != variations_dm0.begin()){ - it = std::prev(it); - std::string variation_dm0 = it->second; - auto correction_factor = evaluator->evaluate( - {pts.at(i), std::abs(etas.at(i)), decay_modes.at(i), - gen_matches.at(i), id_algorithm, wp, vsele_wp, - variation_dm0}); - corrected_pts[i] = pts.at(i) * correction_factor; - } else { - corrected_pts[i] = pts.at(i); - } - } else if (decay_modes.at(i) == 1) { - auto it = variations_dm1.upper_bound(pts.at(i)); - if (it != variations_dm1.begin()){ - it = std::prev(it); - std::string variation_dm1 = it->second; - auto correction_factor = evaluator->evaluate( - {pts.at(i), std::abs(etas.at(i)), decay_modes.at(i), - gen_matches.at(i), id_algorithm, wp, vsele_wp, - variation_dm1}); - corrected_pts[i] = pts.at(i) * correction_factor; - } else { - corrected_pts[i] = pts.at(i); - } - } else if (decay_modes.at(i) == 10) { - auto it = variations_dm10.upper_bound(pts.at(i)); - if (it != variations_dm10.begin()){ - it = std::prev(it); - std::string variation_dm10 = it->second; - auto correction_factor = evaluator->evaluate( - {pts.at(i), std::abs(etas.at(i)), decay_modes.at(i), - gen_matches.at(i), id_algorithm, wp, vsele_wp, - variation_dm10}); - corrected_pts[i] = pts.at(i) * correction_factor; - } else { - corrected_pts[i] = pts.at(i); - } - } else if (decay_modes.at(i) == 11) { - auto it = variations_dm11.upper_bound(pts.at(i)); - if (it != variations_dm11.begin()){ - it = std::prev(it); - std::string variation_dm11 = it->second; - auto correction_factor = evaluator->evaluate( - {pts.at(i), std::abs(etas.at(i)), decay_modes.at(i), - gen_matches.at(i), id_algorithm, wp, vsele_wp, - variation_dm11}); - corrected_pts[i] = pts.at(i) * correction_factor; - } else { - corrected_pts[i] = pts.at(i); + float current_pt = pts.at(i); + int current_dm = decay_modes.at(i); + int current_gen_match = gen_matches.at(i); + + // Default: No correction + corrected_pts[i] = current_pt; + std::string variation = "nom"; + + // Only correct if GenMatch is 5 (Genuine Tau) + if (current_gen_match == 5) { + // Look for DM in our allowed map + auto dm_it = variations.find(current_dm); + + // Only call evaluate if DM is supported (0, 1, 10, 11) + if (dm_it != variations.end()) { + const auto &pt_map = dm_it->second; + + // Determine variation based on pT + auto pt_it = pt_map.upper_bound(current_pt); + if (pt_it != pt_map.begin()) { + variation = std::prev(pt_it)->second; } - } else { - corrected_pts[i] = pts.at(i); + + auto correction_factor = evaluator->evaluate( + {current_pt, std::abs(etas.at(i)), current_dm, + current_gen_match, id_algorithm, wp, vsele_wp, + variation}); + + corrected_pts[i] = current_pt * correction_factor; } - } else { - corrected_pts[i] = pts.at(i); } - Logger::get("physicsobject::tau::PtCorrection_genuineTau") - ->debug("tau pt before {}, tau pt after {}, decaymode {}", - pts.at(i), corrected_pts.at(i), decay_modes.at(i)); + Logger::get("physicsobject::tau::PtCorrectionMC_genuineTau") + ->debug("tau pt before {}, tau pt after {}, decay mode {}, variation {}", + current_pt, corrected_pts.at(i), current_dm, variation); } return corrected_pts; }; @@ -1185,8 +1141,7 @@ namespace scalefactor { * against jets (`vsJet`). The scale factors are loaded from a correctionlib file * using a specified scale factor name and variation. The variation and the scale * factor itself is binned in transverse momenta (\f$p_T\f$) of hadronic taus - * for this function. This dependence is usually used in semi-leptonic channels - * (\f$e\tau_h\f$, \f$\mu\tau_h\f$). + * for this function. * * Description of the bit map used to define the tau ID against jets working points of the * DeepTau v2.1 tagger. @@ -1230,6 +1185,9 @@ namespace scalefactor { * and "up"/"down" the up/down variation * * @return a new dataframe containing the new column + * + * @warning This function uses an outdated \f$p_T\f$ splitting for the + * uncertainty variations from legacy H(tautau). */ ROOT::RDF::RNode Id_vsJet_lt(ROOT::RDF::RNode df, @@ -1292,152 +1250,14 @@ Id_vsJet_lt(ROOT::RDF::RNode df, return df1; } - - -ROOT::RDF::RNode -Id_vsJet_lt(ROOT::RDF::RNode df, - correctionManager::CorrectionManager &correction_manager, - const std::string &outputname, - const std::string &pt, const std::string &decay_mode, - const std::string &gen_match, - const std::string &sf_file, - const std::string &sf_name, - const std::vector &selected_dms, - const std::string &wp, const std::string &vsele_wp, - const std::string &sf_dependence, - // DM + pT split - const std::string &variation_dm0_pt20to40, - const std::string &variation_dm0_pt40toInf, - const std::string &variation_dm1_pt20to40, - const std::string &variation_dm1_pt40toInf, - const std::string &variation_dm10_pt20to40, - const std::string &variation_dm10_pt40toInf, - const std::string &variation_dm11_pt20to40, - const std::string &variation_dm11_pt40toInf) { - - const std::unordered_map> variations = { - {0, {{20.0f, variation_dm0_pt20to40}, {40.0f, variation_dm0_pt40toInf}}}, - {1, {{20.0f, variation_dm1_pt20to40}, {40.0f, variation_dm1_pt40toInf}}}, - {10, {{20.0f, variation_dm10_pt20to40}, {40.0f, variation_dm10_pt40toInf}}}, - {11, {{20.0f, variation_dm11_pt20to40}, {40.0f, variation_dm11_pt40toInf}}}, - }; - - Logger::get("physicsobject::tau::scalefactor::Id_vsJet_lt") - ->debug("Setting up function for tau id vsJet sf (DM & Pt binned)"); - Logger::get("physicsobject::tau::scalefactor::Id_vsJet_lt")->debug("ID - Name {}", sf_name); - - auto evaluator = correction_manager.loadCorrection(sf_file, sf_name); - - auto sf_calculator = [evaluator, wp, vsele_wp, variations, - sf_dependence, selected_dms, - sf_name](const float &pt, const int &decay_mode, - const int &gen_match) { - Logger::get("physicsobject::tau::scalefactor::Id_vsJet_lt")->debug("ID - decayMode {}", decay_mode); - - double sf = 1.; - - if (std::find(selected_dms.begin(), selected_dms.end(), decay_mode) != selected_dms.end()) { - auto dm_it = variations.find(decay_mode); // specific map for this Decay Mode - if (dm_it != variations.end()) { - const auto &pt_map = dm_it->second; - - auto pt_it = pt_map.upper_bound(pt); - - if (pt_it != pt_map.begin()){ - pt_it = std::prev(pt_it); // Move back to the lower bound key - std::string variation = pt_it->second; - - Logger::get("physicsobject::tau::scalefactor::Id_vsJet_lt") - ->debug("ID {} - pt {}, decay_mode {}, gen_match {}, wp {}, " - "vsele_wp {}, variation {}, sf_dependence {}", - sf_name, pt, decay_mode, gen_match, wp, vsele_wp, - variation, sf_dependence); - - sf = evaluator->evaluate({pt, decay_mode, gen_match, wp, vsele_wp, variation, sf_dependence}); - } - } - } - - Logger::get("physicsobject::tau::scalefactor::Id_vsJet_lt")->debug("Scale Factor {}", sf); - return sf; - }; - - auto df1 = df.Define(outputname, sf_calculator, {pt, decay_mode, gen_match}); - return df1; -} - -ROOT::RDF::RNode -Id_vsJet_lt(ROOT::RDF::RNode df, - correctionManager::CorrectionManager &correction_manager, - const std::string &outputname, - const std::string &pt, const std::string &decay_mode, - const std::string &gen_match, - const std::string &sf_file, - const std::string &sf_name, - const std::vector &selected_dms, - const std::string &wp, const std::string &vsele_wp, - const std::string &sf_dependence, - // DM split - const std::string &variation_dm0, - const std::string &variation_dm1, - const std::string &variation_dm10, - const std::string &variation_dm11) { - const std::unordered_map variations = { - {0, variation_dm0}, - {1, variation_dm1}, - {10, variation_dm10}, - {11, variation_dm11}, - }; - Logger::get("physicsobject::tau::scalefactor::Id_vsJet_lt") - ->debug("Setting up function for tau id vsJet sf (DM binned only)"); - Logger::get("physicsobject::tau::scalefactor::Id_vsJet_lt")->debug("ID - Name {}", sf_name); - - auto evaluator = correction_manager.loadCorrection(sf_file, sf_name); - - auto sf_calculator = [evaluator, wp, vsele_wp, variations, - sf_dependence, selected_dms, - sf_name](const float &pt, const int &decay_mode, - const int &gen_match) { - Logger::get("physicsobject::tau::scalefactor::Id_vsJet_lt")->debug("ID - decayMode {}", decay_mode); - - double sf = 1.; - - if (std::find(selected_dms.begin(), selected_dms.end(), decay_mode) != selected_dms.end()) { - - auto it = variations.find(decay_mode); - if (it != variations.end()) { - std::string variation = it->second; - - Logger::get("physicsobject::tau::scalefactor::Id_vsJet_lt") - ->debug("ID {} - pt {}, decay_mode {}, gen_match {}, wp {}, " - "vsele_wp {}, variation {}, sf_dependence {}", - sf_name, pt, decay_mode, gen_match, wp, vsele_wp, - variation, sf_dependence); - - sf = evaluator->evaluate({pt, decay_mode, gen_match, wp, vsele_wp, variation, sf_dependence}); - } - } - - Logger::get("physicsobject::tau::scalefactor::Id_vsJet_lt")->debug("Scale Factor {}", sf); - return sf; - }; - - auto df1 = df.Define(outputname, sf_calculator, {pt, decay_mode, gen_match}); - return df1; -} - - - - /** * @brief This function calculates scale factors (SFs) for tau identification (ID) * against jets (`vsJet`). The scale factors are loaded from a correctionlib file * using a specified scale factor name and variation. The variation and the scale - * factor itself is binned in decay modes of hadronic taus for this function. This - * dependence is usually used in the fully hadronic channel (\f$\tau_h\tau_h\f$). + * factor itself is binned in decay modes of hadronic taus for this function. * * Description of the bit map used to define the tau ID against jets working points of the - * DeepTau v2.1 tagger. + * DeepTau v2.1 or v2.5 tagger. * vsJets | Value | Bit (value used in the config) * ------------------------------------|-------|------- * no ID selection (takes every tau) | 0 | - @@ -1475,7 +1295,7 @@ Id_vsJet_lt(ROOT::RDF::RNode df, * * @return a new dataframe containing the new column */ -ROOT::RDF::RNode Id_vsJet_tt( +ROOT::RDF::RNode Id_vsJet( ROOT::RDF::RNode df, correctionManager::CorrectionManager &correction_manager, const std::string &outputname, @@ -1495,22 +1315,21 @@ ROOT::RDF::RNode Id_vsJet_tt( {10, variation_dm10}, {11, variation_dm11}, }; - Logger::get("physicsobject::tau::scalefactor::Id_vsJet_tt") - ->debug("Setting up function for tau id vsJet sf"); - Logger::get("physicsobject::tau::scalefactor::Id_vsJet_tt")->debug("ID - Name {}", sf_name); + Logger::get("physicsobject::tau::scalefactor::Id_vsJet") + ->debug("Setting up function for tau ID vsJet SF (DM binned only)"); + Logger::get("physicsobject::tau::scalefactor::Id_vsJet")->debug("SF - Name {}", sf_name); auto evaluator = correction_manager.loadCorrection(sf_file, sf_name); auto sf_calculator = [evaluator, wp, vsele_wp, variations, sf_dependence, sf_name](const float &pt, const int &decay_mode, const int &gen_match) { - Logger::get("physicsobject::tau::scalefactor::Id_vsJet_tt")->debug("ID - decayMode {}", decay_mode); + Logger::get("physicsobject::tau::scalefactor::Id_vsJet")->debug("SF - decayMode {}", decay_mode); // only calculate SFs for allowed tau decay modes (also excludes default - // values due to tau energy correction shifts below good tau pt - // selection) + // values due to tau energy correction shifts below good tau pt selection) double sf = 1.; if (auto it = variations.find(decay_mode); it != variations.end()) { std::string variation = it->second; - Logger::get("physicsobject::tau::scalefactor::Id_vsJet_tt") - ->debug("ID {} - pt {}, decay_mode {}, gen_match {}, wp {}, " + Logger::get("physicsobject::tau::scalefactor::Id_vsJet") + ->debug("SF {} - pt {}, decay_mode {}, gen_match {}, wp {}, " "vsele_wp {}, variation {}, sf_dependence {}", sf_name, pt, decay_mode, gen_match, wp, vsele_wp, variation, sf_dependence); @@ -1518,7 +1337,7 @@ ROOT::RDF::RNode Id_vsJet_tt( {pt, decay_mode, gen_match, wp, vsele_wp, variation, sf_dependence}); } - Logger::get("physicsobject::tau::scalefactor::Id_vsJet_tt")->debug("Scale Factor {}", sf); + Logger::get("physicsobject::tau::scalefactor::Id_vsJet")->debug("Scale Factor {}", sf); return sf; }; auto df1 = df.Define(outputname, sf_calculator, {pt, decay_mode, gen_match}); @@ -1529,11 +1348,11 @@ ROOT::RDF::RNode Id_vsJet_tt( * @brief This function calculates scale factors (SFs) for tau identification (ID) * against jets (`vsJet`). The scale factors are loaded from a correctionlib file * using a specified scale factor name and variation. The variation and the scale - * factor itself is binned in decay modes of hadronic taus for this function. This - * dependence is usually used in the fully hadronic channel (\f$\tau_h\tau_h\f$). + * factor itself is binned in decay modes and transverse momentum of hadronic taus + * for this function. * * Description of the bit map used to define the tau ID against jets working points of the - * DeepTau v2.1 tagger. + * DeepTau v2.1 and v2.5 tagger. * vsJets | Value | Bit (value used in the config) * ------------------------------------|-------|------- * no ID selection (takes every tau) | 0 | - @@ -1560,18 +1379,26 @@ ROOT::RDF::RNode Id_vsJet_tt( * @param wp working point of the vsJet ID * @param vsele_wp working point of the vsEle ID * @param sf_dependence variable dependence of the scale factor, opions are "pt" or "dm" - * @param variation_dm0 name of the scale factor variation for decay mode 0, "nom" for nominal - * and "up"/"down" the up/down variation - * @param variation_dm1 name of the scale factor variation for decay mode 1, "nom" for nominal - * and "up"/"down" the up/down variation - * @param variation_dm10 name of the scale factor variation for decay mode 10, "nom" for nominal - * and "up"/"down" the up/down variation - * @param variation_dm11 name of the scale factor variation for decay mode 11, "nom" for nominal - * and "up"/"down" the up/down variation + * @param variation_dm0_pt20to40 variation for decay mode 0 and + * \f$20 \leq p_T <40\f$ GeV, options are "nom", "up", "down" + * @param variation_dm0_pt40toInf variation for decay mode 0 and + * 40 GeV \f$\leq p_{T,\tau}\f$, options are "nom", "up", "down" + * @param variation_dm1_pt20to40 variation for decay mode 1 and + * \f$20 \leq p_T <40\f$ GeV, options are "nom", "up", "down" + * @param variation_dm1_pt40toInf variation for decay mode 1 and + * 40 GeV \f$\leq p_{T,\tau}\f$, options are "nom", "up", "down" + * @param variation_dm10_pt20to40 variation for decay mode 10 and + * \f$20 \leq p_T <40\f$ GeV, options are "nom", "up", "down" + * @param variation_dm10_pt40toInf variation for decay mode 10 and + * 40 GeV \f$\leq p_{T,\tau}\f$, options are "nom", "up", "down" + * @param variation_dm11_pt20to40 variation for decay mode 11 and + * \f$20 \leq p_T <40\f$ GeV, options are "nom", "up", "down" + * @param variation_dm11_pt40toInf variation for decay mode 11 and + * 40 GeV \f$\leq p_{T,\tau}\f$, options are "nom", "up", "down" * * @return a new dataframe containing the new column */ -ROOT::RDF::RNode Id_vsJet_tt( +ROOT::RDF::RNode Id_vsJet( ROOT::RDF::RNode df, correctionManager::CorrectionManager &correction_manager, const std::string &outputname, @@ -1580,113 +1407,50 @@ ROOT::RDF::RNode Id_vsJet_tt( const std::string &sf_file, const std::string &sf_name, const std::string &wp, const std::string &vsele_wp, const std::string &sf_dependence, - const std::string &variation_dm0_20to40, const std::string &variation_dm1_20to40, - const std::string &variation_dm10_20to40, const std::string &variation_dm11_20to40, - const std::string &variation_dm0_40toInf, const std::string &variation_dm1_40toInf, - const std::string &variation_dm10_40toInf, const std::string &variation_dm11_40toInf) { + const std::string &variation_dm0_pt20to40, const std::string &variation_dm0_pt40toInf, + const std::string &variation_dm1_pt20to40, const std::string &variation_dm1_pt40toInf, + const std::string &variation_dm10_pt20to40, const std::string &variation_dm10_pt40toInf, + const std::string &variation_dm11_pt20to40, const std::string &variation_dm11_pt40toInf) { - // const std::unordered_map variations = { - const std::map variations_dm0 = { - {20.0f, variation_dm0_20to40}, - {40.0f, variation_dm0_40toInf}, - {100000.0f, variation_dm0_40toInf}, - }; - const std::map variations_dm1 = { - {20.0f, variation_dm1_20to40}, - {40.0f, variation_dm1_40toInf}, - {100000.0f, variation_dm1_40toInf}, - }; - const std::map variations_dm10 = { - {20.0f, variation_dm10_20to40}, - {40.0f, variation_dm10_40toInf}, - {100000.0f, variation_dm10_40toInf}, - }; - const std::map variations_dm11 = { - {20.0f, variation_dm11_20to40}, - {40.0f, variation_dm11_40toInf}, - {100000.0f, variation_dm11_40toInf}, + const std::unordered_map> variations = { + {0, {{20.0f, variation_dm0_pt20to40}, {40.0f, variation_dm0_pt40toInf}}}, + {1, {{20.0f, variation_dm1_pt20to40}, {40.0f, variation_dm1_pt40toInf}}}, + {10, {{20.0f, variation_dm10_pt20to40}, {40.0f, variation_dm10_pt40toInf}}}, + {11, {{20.0f, variation_dm11_pt20to40}, {40.0f, variation_dm11_pt40toInf}}}, }; - Logger::get("physicsobject::tau::scalefactor::Id_vsJet_tt") - ->debug("Setting up function for tau id vsJet sf"); - Logger::get("physicsobject::tau::scalefactor::Id_vsJet_tt")->debug("ID - Name {}", sf_name); + + Logger::get("physicsobject::tau::scalefactor::Id_vsJet") + ->debug("Setting up function for tau ID vsJet SF (DM & pT binned)"); + Logger::get("physicsobject::tau::scalefactor::Id_vsJet")->debug("SF - Name {}", sf_name); auto evaluator = correction_manager.loadCorrection(sf_file, sf_name); - auto sf_calculator = [evaluator, wp, vsele_wp, variations_dm0, variations_dm1, variations_dm10, variations_dm11, + auto sf_calculator = [evaluator, wp, vsele_wp, variations, sf_dependence, sf_name](const float &pt, const int &decay_mode, const int &gen_match) { - Logger::get("physicsobject::tau::scalefactor::Id_vsJet_tt")->debug("ID - decayMode {}", decay_mode); + Logger::get("physicsobject::tau::scalefactor::Id_vsJet")->debug("SF - decayMode {}", decay_mode); // only calculate SFs for allowed tau decay modes (also excludes default - // values due to tau energy correction shifts below good tau pt - // selection) + // values due to tau energy correction shifts below good tau pt selection) double sf = 1.; - if (decay_mode == 0) { - auto it = variations_dm0.upper_bound(pt); - if (it != variations_dm0.begin()){ - it = std::prev(it); - std::string variation_dm0 = it->second; - Logger::get("physicsobject::tau::scalefactor::Id_vsJet_tt") - ->debug("ID {} - pt {}, decay_mode {}, gen_match {}, wp {}, " - "vsele_wp {}, variation {}, sf_dependence {}", - sf_name, pt, decay_mode, gen_match, wp, vsele_wp, - variation_dm0, sf_dependence); - sf = evaluator->evaluate( - {pt, decay_mode, gen_match, wp, vsele_wp, - variation_dm0, sf_dependence}); - } - } else if (decay_mode == 1) { - auto it = variations_dm1.upper_bound(pt); - if (it != variations_dm1.begin()){ - it = std::prev(it); - std::string variation_dm1 = it->second; - Logger::get("physicsobject::tau::scalefactor::Id_vsJet_tt") - ->debug("ID {} - pt {}, decay_mode {}, gen_match {}, wp {}, " - "vsele_wp {}, variation {}, sf_dependence {}", - sf_name, pt, decay_mode, gen_match, wp, vsele_wp, - variation_dm1, sf_dependence); - sf = evaluator->evaluate( - {pt, decay_mode, gen_match, wp, vsele_wp, - variation_dm1, sf_dependence}); - } - } else if (decay_mode == 10) { - auto it = variations_dm10.upper_bound(pt); - if (it != variations_dm10.begin()){ - it = std::prev(it); - std::string variation_dm10 = it->second; - Logger::get("physicsobject::tau::scalefactor::Id_vsJet_tt") - ->debug("ID {} - pt {}, decay_mode {}, gen_match {}, wp {}, " - "vsele_wp {}, variation {}, sf_dependence {}", - sf_name, pt, decay_mode, gen_match, wp, vsele_wp, - variation_dm10, sf_dependence); - sf = evaluator->evaluate( - {pt, decay_mode, gen_match, wp, vsele_wp, - variation_dm10, sf_dependence}); - } - } else if (decay_mode == 11) { - auto it = variations_dm11.upper_bound(pt); - if (it != variations_dm11.begin()){ - it = std::prev(it); - std::string variation_dm11 = it->second; - Logger::get("physicsobject::tau::scalefactor::Id_vsJet_tt") - ->debug("ID {} - pt {}, decay_mode {}, gen_match {}, wp {}, " + + if (auto dm_it = variations.find(decay_mode); dm_it != variations.end()) { + const auto &pt_map = dm_it->second; + + auto pt_it = pt_map.upper_bound(pt); + + if (pt_it != pt_map.begin()){ + pt_it = std::prev(pt_it); // Move back to the lower bound key + std::string variation = pt_it->second; + + Logger::get("physicsobject::tau::scalefactor::Id_vsJet") + ->debug("SF {} - pt {}, decay_mode {}, gen_match {}, wp {}, " "vsele_wp {}, variation {}, sf_dependence {}", sf_name, pt, decay_mode, gen_match, wp, vsele_wp, - variation_dm11, sf_dependence); - sf = evaluator->evaluate( - {pt, decay_mode, gen_match, wp, vsele_wp, - variation_dm11, sf_dependence}); + variation, sf_dependence); + + sf = evaluator->evaluate({pt, decay_mode, gen_match, wp, vsele_wp, variation, sf_dependence}); } } - // if (auto it = variations.find(decay_mode); it != variations.end()) { - // std::string variation = it->second; - // Logger::get("physicsobject::tau::scalefactor::Id_vsJet_tt") - // ->debug("ID {} - pt {}, decay_mode {}, gen_match {}, wp {}, " - // "vsele_wp {}, variation {}, sf_dependence {}", - // sf_name, pt, decay_mode, gen_match, wp, vsele_wp, - // variation, sf_dependence); - // sf = evaluator->evaluate( - // {pt, decay_mode, gen_match, wp, vsele_wp, - // variation, sf_dependence}); - // } - Logger::get("physicsobject::tau::scalefactor::Id_vsJet_tt")->debug("Scale Factor {}", sf); + + Logger::get("physicsobject::tau::scalefactor::Id_vsJet")->debug("Scale Factor {}", sf); return sf; }; auto df1 = df.Define(outputname, sf_calculator, {pt, decay_mode, gen_match}); From 0871e0d1f3aaee5d7a0252c6293c1212de0d8bb1 Mon Sep 17 00:00:00 2001 From: nshadskiy Date: Mon, 12 Jan 2026 14:10:13 +0100 Subject: [PATCH 07/10] fix doc string --- src/taus.cxx | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/taus.cxx b/src/taus.cxx index 4c94c8b0..2d1057c8 100644 --- a/src/taus.cxx +++ b/src/taus.cxx @@ -707,14 +707,14 @@ ROOT::RDF::RNode PtCorrectionMC_genuineTau( * @param variation_dm0_pt20to40 variation for decay mode 0 and * \f$20 \leq p_T <40\f$ GeV, options are "nom", "up", "down" * @param variation_dm0_pt40toInf variation for decay mode 0 and - * 40 GeV \f$\leq p_{T,\tau}\f$, options are "nom", "up", "down" + * \f$40 \leq p_{T,\tau} <\infty\f$ GeV, options are "nom", "up", "down" * @param variation_dm1_pt20to40 variation for decay mode 1 and * \f$20 \leq p_T <40\f$ GeV, options are "nom", "up", "down" * @param variation_dm1_pt40toInf variation for decay mode 1 and * 40 GeV \f$\leq p_{T,\tau}\f$, options are "nom", "up", "down" * @param variation_dm10_pt20to40 variation for decay mode 10 and * \f$20 \leq p_T <40\f$ GeV, options are "nom", "up", "down" - * @param variation_dm10_pt40toInf variation for decay mode 10 and + * @param variation_dm10_pt40toInf variation for decay mode 10 and * 40 GeV \f$\leq p_{T,\tau}\f$, options are "nom", "up", "down" * @param variation_dm11_pt20to40 variation for decay mode 11 and * \f$20 \leq p_T <40\f$ GeV, options are "nom", "up", "down" @@ -949,21 +949,21 @@ ROOT::RDF::RNode PtCorrectionMC_genuineTau( * @param id_algorithm identification algorithm used for hadronic tau ID * @param wp working point of the vsJet ID * @param vsele_wp working point of the vsEle ID - * @param variation_dm0_20to40 variation for decay mode 0 and + * @param variation_dm0_pt20to40 variation for decay mode 0 and * \f$20 \leq p_T <40\f$ GeV, options are "nom", "up", "down" - * @param variation_dm0_40toInf variation for decay mode 0 and + * @param variation_dm0_pt40toInf variation for decay mode 0 and * 40 GeV \f$\leq p_{T,\tau}\f$, options are "nom", "up", "down" - * @param variation_dm1_20to40 variation for decay mode 1 and + * @param variation_dm1_pt20to40 variation for decay mode 1 and * \f$20 \leq p_T <40\f$ GeV, options are "nom", "up", "down" - * @param variation_dm1_40toInf variation for decay mode 1 and + * @param variation_dm1_pt40toInf variation for decay mode 1 and * 40 GeV \f$\leq p_{T,\tau}\f$, options are "nom", "up", "down" - * @param variation_dm10_20to40 variation for decay mode 10 and + * @param variation_dm10_pt20to40 variation for decay mode 10 and * \f$20 \leq p_T <40\f$ GeV, options are "nom", "up", "down" - * @param variation_dm10_40toInf variation for decay mode 10 and + * @param variation_dm10_pt40toInf variation for decay mode 10 and * 40 GeV \f$\leq p_{T,\tau}\f$, options are "nom", "up", "down" - * @param variation_dm11_20to40 variation for decay mode 11 and + * @param variation_dm11_pt20to40 variation for decay mode 11 and * \f$20 \leq p_T <40\f$ GeV, options are "nom", "up", "down" - * @param variation_dm11_40toInf variation for decay mode 11 and + * @param variation_dm11_pt40toInf variation for decay mode 11 and * 40 GeV \f$\leq p_{T,\tau}\f$, options are "nom", "up", "down" * * @return a dataframe containing the corrected transverse momenta @@ -1173,16 +1173,16 @@ namespace scalefactor { * @param wp working point of the vsJet ID * @param vsele_wp working point of the vsEle ID * @param sf_dependence variable dependence of the scale factor, opions are "pt" or "dm" - * @param variation_pt30to35 name of the scale factor variation for \f$30 \leq p_T <35\f$ GeV, "nom" for nominal - * and "up"/"down" the up/down variation - * @param variation_pt35to40 name of the scale factor variation for \f$35 \leq p_T <40\f$ GeV, "nom" for nominal - * and "up"/"down" the up/down variation - * @param variation_pt40to500 name of the scale factor variation for \f$40 \leq p_T <500\f$ GeV, "nom" for nominal - * and "up"/"down" the up/down variation - * @param variation_pt500to1000 name of the scale factor variation for \f$500 \leq p_T <1000\f$ GeV, "nom" for nominal - * and "up"/"down" the up/down variation - * @param variation_pt1000toInf name of the scale factor variation for \f$1000 \leq p_T < \infty \f$ GeV, "nom" for nominal - * and "up"/"down" the up/down variation + * @param variation_pt30to35 name of the scale factor variation for \f$30 \leq p_T <35\f$ GeV, + * "nom" for nominal and "up"/"down" the up/down variation + * @param variation_pt35to40 name of the scale factor variation for \f$35 \leq p_T <40\f$ GeV, + * "nom" for nominal and "up"/"down" the up/down variation + * @param variation_pt40to500 name of the scale factor variation for \f$40 \leq p_T <500\f$ GeV, + * "nom" for nominal and "up"/"down" the up/down variation + * @param variation_pt500to1000 name of the scale factor variation for \f$500 \leq p_T <1000\f$ GeV, + * "nom" for nominal and "up"/"down" the up/down variation + * @param variation_pt1000toInf name of the scale factor variation for \f$1000 \leq p_T < \infty \f$ GeV, + * "nom" for nominal and "up"/"down" the up/down variation * * @return a new dataframe containing the new column * From a9da340d8cfe24904b3a9a4d0133b1953db65fde Mon Sep 17 00:00:00 2001 From: nshadskiy Date: Mon, 12 Jan 2026 16:38:42 +0100 Subject: [PATCH 08/10] update doc strings --- src/taus.cxx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/taus.cxx b/src/taus.cxx index 2d1057c8..34f13db5 100644 --- a/src/taus.cxx +++ b/src/taus.cxx @@ -1172,7 +1172,7 @@ namespace scalefactor { * should be calculated * @param wp working point of the vsJet ID * @param vsele_wp working point of the vsEle ID - * @param sf_dependence variable dependence of the scale factor, opions are "pt" or "dm" + * @param sf_dependence variable dependence of the scale factor, options are "pt" or "dm" * @param variation_pt30to35 name of the scale factor variation for \f$30 \leq p_T <35\f$ GeV, * "nom" for nominal and "up"/"down" the up/down variation * @param variation_pt35to40 name of the scale factor variation for \f$35 \leq p_T <40\f$ GeV, @@ -1283,7 +1283,8 @@ Id_vsJet_lt(ROOT::RDF::RNode df, * @param sf_name name of the tau scale factor for the vsJet ID correction * @param wp working point of the vsJet ID * @param vsele_wp working point of the vsEle ID - * @param sf_dependence variable dependence of the scale factor, opions are "pt" or "dm" + * @param sf_dependence variable dependence of the scale factor, options are "pt" + * (which is dm+pt) or "dm" (which is dm only) * @param variation_dm0 name of the scale factor variation for decay mode 0, "nom" for nominal * and "up"/"down" the up/down variation * @param variation_dm1 name of the scale factor variation for decay mode 1, "nom" for nominal @@ -1378,7 +1379,8 @@ ROOT::RDF::RNode Id_vsJet( * @param sf_name name of the tau scale factor for the vsJet ID correction * @param wp working point of the vsJet ID * @param vsele_wp working point of the vsEle ID - * @param sf_dependence variable dependence of the scale factor, opions are "pt" or "dm" + * @param sf_dependence variable dependence of the scale factor, options are "pt" + * (which is dm+pt) or "dm" (which is dm only) * @param variation_dm0_pt20to40 variation for decay mode 0 and * \f$20 \leq p_T <40\f$ GeV, options are "nom", "up", "down" * @param variation_dm0_pt40toInf variation for decay mode 0 and From 4975329f2cbd219aa2834cf288cc9c644ab3a99e Mon Sep 17 00:00:00 2001 From: nshadskiy Date: Mon, 12 Jan 2026 18:29:44 +0100 Subject: [PATCH 09/10] remove outdated tau ID embedding function --- include/embedding.hxx | 20 ------- src/embedding.cxx | 118 ------------------------------------------ 2 files changed, 138 deletions(-) diff --git a/include/embedding.hxx b/include/embedding.hxx index c1a926b2..a595ddb4 100644 --- a/include/embedding.hxx +++ b/include/embedding.hxx @@ -65,26 +65,6 @@ PtCorrection_byValue(ROOT::RDF::RNode df, const std::string &outputname, const std::string &pt, const std::string &decay_mode, const float &sf_dm0, const float &sf_dm1, const float &sf_dm10, const float &sf_dm11); - -namespace scalefactor { - -ROOT::RDF::RNode -Id_vsJet_lt(ROOT::RDF::RNode df, - correctionManager::CorrectionManager &correction_manager, - const std::string &outputname, - const std::string &pt, const std::string &decay_mode, - const std::string &gen_match, - const std::string &sf_file, - const std::string &sf_name, - const std::vector &selected_dms, - const std::string &wp, const std::string &vsele_wp, - const std::string &sf_dependence, - const std::string &sf_vsjet_tau20to25, - const std::string &sf_vsjet_tau25to30, - const std::string &sf_vsjet_tau30to35, - const std::string &sf_vsjet_tau35to40, - const std::string &sf_vsjet_tau40toInf); -} // end namespace scalefactor } // end namespace tau } // end namespace embedding #endif /* GUARD_EMBEDDING_H */ \ No newline at end of file diff --git a/src/embedding.cxx b/src/embedding.cxx index bef87907..bcdd8c7c 100644 --- a/src/embedding.cxx +++ b/src/embedding.cxx @@ -408,124 +408,6 @@ PtCorrection_byValue(ROOT::RDF::RNode df, const std::string &outputname, auto df2 = df1.Define(outputname, correction_lambda, {pt, decay_mode_column}); return df2; } - -namespace scalefactor { - -/** - * @brief This function calculates scale factors (SFs) for tau identification (ID) - * against jets (`vsJet`) for embedding samples. The scale factors are loaded from - * a correctionlib file using a specified scale factor name and variation. The - * variation and the scale factor itself is binned in transverse momenta (\f$p_T\f$) - * of hadronic taus for this function. This dependence is usually used in semi-leptonic - * channels (\f$e\tau_h\f$, \f$\mu\tau_h\f$). - * - * Description of the bit map used to define the tau ID against jets working points of the - * DeepTau v2.1 tagger. - * vsJets | Value | Bit (value used in the config) - * ------------------------------------|-------|------- - * no ID selection (takes every tau) | 0 | - - * VVVLoose | 1 | 1 - * VVLoose | 2 | 2 - * VLoose | 4 | 3 - * Loose | 8 | 4 - * Medium | 16 | 5 - * Tight | 32 | 6 - * VTight | 64 | 7 - * VVTight | 128 | 8 - * - * @param df input dataframe - * @param correction_manager correction manager responsible for loading the - * tau scale factor file - * @param outputname name of the output column containing the vsJets ID scale factor - * @param pt name of the column containing the transverse momentum of a tau - * @param decay_mode name of the column containing the decay mode of the tau - * @param gen_match name of the column with the matching information of the - * hadronic tau to generator-level particles (matches are: 1=prompt e, 2=prompt mu, - * 3=tau->e, 4=tau->mu, 5=had. tau, 0=unmatched) - * @param sf_file path to the file with the tau scale factors - * @param sf_name name of the tau scale factor for the vsJet ID correction - * @param selected_dms list of allowed decay modes for which a scale factor - * should be calculated - * @param wp working point of the vsJet ID - * @param vsele_wp working point of the vsEle ID - * @param sf_dependence variable dependence of the scale factor, opions are "pt" or "dm" - * @param variation_pt20to25 name of the scale factor variation for \f$20 \leq p_T <25\f$ GeV, "nom" for nominal - * and "up"/"down" the up/down variation - * @param variation_pt25to30 name of the scale factor variation for \f$25 \leq p_T <30\f$ GeV, "nom" for nominal - * and "up"/"down" the up/down variation - * @param variation_pt30to35 name of the scale factor variation for \f$30 \leq p_T <35\f$ GeV, "nom" for nominal - * and "up"/"down" the up/down variation - * @param variation_pt35to40 name of the scale factor variation for \f$35 \leq p_T <40\f$ GeV, "nom" for nominal - * and "up"/"down" the up/down variation - * @param variation_pt40toInf name of the scale factor variation for \f$40 \leq p_T < \infty \f$ GeV, "nom" for nominal - * and "up"/"down" the up/down variation - * - * @return a new dataframe containing the new column - * - * @note The only differnce to the `physicsobject::tau::scalefactor::Id_vsJet_lt` function, - * which is used for simulated samples, is the \f$p_T\f$ binning of the variations. - */ -ROOT::RDF::RNode -Id_vsJet_lt(ROOT::RDF::RNode df, - correctionManager::CorrectionManager &correction_manager, - const std::string &outputname, - const std::string &pt, const std::string &decay_mode, - const std::string &gen_match, - const std::string &sf_file, - const std::string &sf_name, - const std::vector &selected_dms, - const std::string &wp, const std::string &vsele_wp, - const std::string &sf_dependence, - const std::string &variation_pt20to25, - const std::string &variation_pt25to30, - const std::string &variation_pt30to35, - const std::string &variation_pt35to40, - const std::string &variation_pt40toInf) { - - const std::map variations = { - {20.0f, variation_pt20to25}, - {25.0f, variation_pt25to30}, - {30.0f, variation_pt30to35}, - {35.0f, variation_pt35to40}, - {40.0f, variation_pt40toInf}, - {100000.0f, variation_pt40toInf}, - }; - Logger::get("embedding::tau::scalefactor::Id_vsJet_lt") - ->debug("Setting up function for tau id vsJet sf"); - Logger::get("embedding::tau::scalefactor::Id_vsJet_lt")->debug("ID - Name {}", sf_name); - auto evaluator = correction_manager.loadCorrection(sf_file, sf_name); - auto sf_calculator = [evaluator, wp, vsele_wp, variations, - sf_dependence, selected_dms, - sf_name](const float &pt, const int &decay_mode, - const int &gen_match) { - Logger::get("embedding::tau::scalefactor::Id_vsJet_lt")->debug("ID - decayMode {}", decay_mode); - // only calculate SFs for allowed tau decay modes (also excludes default - // values due to tau energy correction shifts below good tau pt - // selection) - double sf = 1.; - if (std::find(selected_dms.begin(), selected_dms.end(), decay_mode) != - selected_dms.end()) { - auto it = variations.upper_bound(pt); - if (it != variations.begin()){ - it = std::prev(it); - std::string variation = it->second; - Logger::get("embedding::tau::scalefactor::Id_vsJet_lt") - ->debug("ID {} - pt {}, decay_mode {}, gen_match {}, wp {}, " - "vsele_wp {}, variation {}, sf_dependence {}", - sf_name, pt, decay_mode, gen_match, wp, vsele_wp, - variation, sf_dependence); - sf = evaluator->evaluate({pt, decay_mode, gen_match, wp, vsele_wp, variation, sf_dependence}); - } else { - sf = 1.; - } - } - Logger::get("embedding::tau::scalefactor::Id_vsJet_lt")->debug("Scale Factor {}", sf); - return sf; - }; - auto df1 = df.Define(outputname, sf_calculator, {pt, decay_mode, gen_match}); - return df1; -} -} // end namespace scalefactor } // end namespace tau } // end namespace embedding From 1cfa0d051feb1983d14b9361a68de55f20cf7e23 Mon Sep 17 00:00:00 2001 From: nshadskiy Date: Mon, 12 Jan 2026 18:45:47 +0100 Subject: [PATCH 10/10] adding tau ID SF function for embedding back for legacy reasons --- include/embedding.hxx | 20 +++++++ src/embedding.cxx | 118 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 138 insertions(+) diff --git a/include/embedding.hxx b/include/embedding.hxx index a595ddb4..c1a926b2 100644 --- a/include/embedding.hxx +++ b/include/embedding.hxx @@ -65,6 +65,26 @@ PtCorrection_byValue(ROOT::RDF::RNode df, const std::string &outputname, const std::string &pt, const std::string &decay_mode, const float &sf_dm0, const float &sf_dm1, const float &sf_dm10, const float &sf_dm11); + +namespace scalefactor { + +ROOT::RDF::RNode +Id_vsJet_lt(ROOT::RDF::RNode df, + correctionManager::CorrectionManager &correction_manager, + const std::string &outputname, + const std::string &pt, const std::string &decay_mode, + const std::string &gen_match, + const std::string &sf_file, + const std::string &sf_name, + const std::vector &selected_dms, + const std::string &wp, const std::string &vsele_wp, + const std::string &sf_dependence, + const std::string &sf_vsjet_tau20to25, + const std::string &sf_vsjet_tau25to30, + const std::string &sf_vsjet_tau30to35, + const std::string &sf_vsjet_tau35to40, + const std::string &sf_vsjet_tau40toInf); +} // end namespace scalefactor } // end namespace tau } // end namespace embedding #endif /* GUARD_EMBEDDING_H */ \ No newline at end of file diff --git a/src/embedding.cxx b/src/embedding.cxx index bcdd8c7c..e55596aa 100644 --- a/src/embedding.cxx +++ b/src/embedding.cxx @@ -408,6 +408,124 @@ PtCorrection_byValue(ROOT::RDF::RNode df, const std::string &outputname, auto df2 = df1.Define(outputname, correction_lambda, {pt, decay_mode_column}); return df2; } + +namespace scalefactor { + +/** + * @brief This function calculates scale factors (SFs) for tau identification (ID) + * against jets (`vsJet`) for embedding samples. The scale factors are loaded from + * a correctionlib file using a specified scale factor name and variation. The + * variation and the scale factor itself is binned in transverse momenta (\f$p_T\f$) + * of hadronic taus for this function. This dependence is usually used in semi-leptonic + * channels (\f$e\tau_h\f$, \f$\mu\tau_h\f$). + * + * Description of the bit map used to define the tau ID against jets working points of the + * DeepTau v2.1 tagger. + * vsJets | Value | Bit (value used in the config) + * ------------------------------------|-------|------- + * no ID selection (takes every tau) | 0 | - + * VVVLoose | 1 | 1 + * VVLoose | 2 | 2 + * VLoose | 4 | 3 + * Loose | 8 | 4 + * Medium | 16 | 5 + * Tight | 32 | 6 + * VTight | 64 | 7 + * VVTight | 128 | 8 + * + * @param df input dataframe + * @param correction_manager correction manager responsible for loading the + * tau scale factor file + * @param outputname name of the output column containing the vsJets ID scale factor + * @param pt name of the column containing the transverse momentum of a tau + * @param decay_mode name of the column containing the decay mode of the tau + * @param gen_match name of the column with the matching information of the + * hadronic tau to generator-level particles (matches are: 1=prompt e, 2=prompt mu, + * 3=tau->e, 4=tau->mu, 5=had. tau, 0=unmatched) + * @param sf_file path to the file with the tau scale factors + * @param sf_name name of the tau scale factor for the vsJet ID correction + * @param selected_dms list of allowed decay modes for which a scale factor + * should be calculated + * @param wp working point of the vsJet ID + * @param vsele_wp working point of the vsEle ID + * @param sf_dependence variable dependence of the scale factor, options are "pt" or "dm" + * @param variation_pt20to25 name of the scale factor variation for \f$20 \leq p_T <25\f$ GeV, "nom" for nominal + * and "up"/"down" the up/down variation + * @param variation_pt25to30 name of the scale factor variation for \f$25 \leq p_T <30\f$ GeV, "nom" for nominal + * and "up"/"down" the up/down variation + * @param variation_pt30to35 name of the scale factor variation for \f$30 \leq p_T <35\f$ GeV, "nom" for nominal + * and "up"/"down" the up/down variation + * @param variation_pt35to40 name of the scale factor variation for \f$35 \leq p_T <40\f$ GeV, "nom" for nominal + * and "up"/"down" the up/down variation + * @param variation_pt40toInf name of the scale factor variation for \f$40 \leq p_T < \infty \f$ GeV, "nom" for nominal + * and "up"/"down" the up/down variation + * + * @return a new dataframe containing the new column + * + * @warning This function is depricated (used for legacy H(tt) analysis). It is + * recommended to use `physicsobject::tau::scalefactor::Id_vsJet` instead. + */ +ROOT::RDF::RNode +Id_vsJet_lt(ROOT::RDF::RNode df, + correctionManager::CorrectionManager &correction_manager, + const std::string &outputname, + const std::string &pt, const std::string &decay_mode, + const std::string &gen_match, + const std::string &sf_file, + const std::string &sf_name, + const std::vector &selected_dms, + const std::string &wp, const std::string &vsele_wp, + const std::string &sf_dependence, + const std::string &variation_pt20to25, + const std::string &variation_pt25to30, + const std::string &variation_pt30to35, + const std::string &variation_pt35to40, + const std::string &variation_pt40toInf) { + + const std::map variations = { + {20.0f, variation_pt20to25}, + {25.0f, variation_pt25to30}, + {30.0f, variation_pt30to35}, + {35.0f, variation_pt35to40}, + {40.0f, variation_pt40toInf}, + {100000.0f, variation_pt40toInf}, + }; + Logger::get("embedding::tau::scalefactor::Id_vsJet_lt") + ->debug("Setting up function for tau id vsJet sf"); + Logger::get("embedding::tau::scalefactor::Id_vsJet_lt")->debug("ID - Name {}", sf_name); + auto evaluator = correction_manager.loadCorrection(sf_file, sf_name); + auto sf_calculator = [evaluator, wp, vsele_wp, variations, + sf_dependence, selected_dms, + sf_name](const float &pt, const int &decay_mode, + const int &gen_match) { + Logger::get("embedding::tau::scalefactor::Id_vsJet_lt")->debug("ID - decayMode {}", decay_mode); + // only calculate SFs for allowed tau decay modes (also excludes default + // values due to tau energy correction shifts below good tau pt + // selection) + double sf = 1.; + if (std::find(selected_dms.begin(), selected_dms.end(), decay_mode) != + selected_dms.end()) { + auto it = variations.upper_bound(pt); + if (it != variations.begin()){ + it = std::prev(it); + std::string variation = it->second; + Logger::get("embedding::tau::scalefactor::Id_vsJet_lt") + ->debug("ID {} - pt {}, decay_mode {}, gen_match {}, wp {}, " + "vsele_wp {}, variation {}, sf_dependence {}", + sf_name, pt, decay_mode, gen_match, wp, vsele_wp, + variation, sf_dependence); + sf = evaluator->evaluate({pt, decay_mode, gen_match, wp, vsele_wp, variation, sf_dependence}); + } else { + sf = 1.; + } + } + Logger::get("embedding::tau::scalefactor::Id_vsJet_lt")->debug("Scale Factor {}", sf); + return sf; + }; + auto df1 = df.Define(outputname, sf_calculator, {pt, decay_mode, gen_match}); + return df1; +} +} // end namespace scalefactor } // end namespace tau } // end namespace embedding