10namespace ADD_CMODE(CP) {
11 const unsigned int EfficiencyScaleFactor::m_warningLimit = 10;
12 EfficiencyScaleFactor::EfficiencyScaleFactor(std::shared_ptr<EfficiencyScaleFactor> nominal,
13 const MuonEfficiencyScaleFactors& ref_tool,
14 const std::string&
file,
15 const std::string& time_unit,
16 const std::string& syst_name,
17 int syst_type_bitmap):
18 m_measurement(ref_tool.measurement()),
19 m_syst_name(syst_name),
20 m_is_up(syst_type_bitmap & EffiCollection::UpVariation),
21 m_is_lowpt(syst_type_bitmap & EffiCollection::JPsiAnalysis),
22 m_respond_to_kineDepSyst(syst_type_bitmap & EffiCollection::PtDependent),
23 m_separateBinSyst(syst_type_bitmap & EffiCollection::UnCorrelated),
28 m_sf_decor(std::make_unique<FloatDecorator>(ref_tool.sf_decoration()+ (m_syst_name.empty()?
"" :
"_"+ m_syst_name + (m_is_up?
"_1UP":
"_1DN")))),
29 m_eff_decor(std::make_unique<FloatDecorator>(ref_tool.data_effi_decoration()+ (m_syst_name.empty()?
"" :
"_"+ m_syst_name + (m_is_up?
"_1UP":
"_1DN")))),
30 m_mc_eff_decor(std::make_unique<FloatDecorator>(ref_tool.mc_effi_decoration()+ (m_syst_name.empty()?
"" :
"_"+ m_syst_name + (m_is_up?
"_1UP":
"_1DN")))),
31 m_sf_rep_decor(std::make_unique<FloatVectorDecorator>(ref_tool.sf_replica_decoration()+ (m_syst_name.empty()?
"" :
"_"+ m_syst_name + (m_is_up?
"_1UP":
"_1DN")))),
32 m_eff_rep_decor(std::make_unique<FloatVectorDecorator>(ref_tool.data_effi_replica_decoration()+ (m_syst_name.empty()?
"" :
"_"+ m_syst_name + (m_is_up?
"_1UP":
"_1DN")))),
33 m_mc_eff_rep_decor(std::make_unique<FloatVectorDecorator>(ref_tool.mc_effi_replica_deocration()+ (m_syst_name.empty()?
"" :
"_"+ m_syst_name + (m_is_up?
"_1UP":
"_1DN")))),
39 m_NominalFallBack(nominal),
42 m_default_eff_ttva(1.),
47 if (ref_tool.measurement() == MuonEfficiencyType::Iso){
48 dRJetAxisHandler::set_close_jet_decorator(ref_tool.close_by_jet_decoration());
49 dRJetAxisHandler::set_use_2D_sf(ref_tool.use_2D_iso_corrections());
52 std::unique_ptr<TFile> f (TFile::Open(
file.c_str(),
"READ"));
53 if (!f || !f->IsOpen()) {
54 Error(
"EfficiencyScaleFactor",
"Unable to open file %s",
file.c_str());
58 m_eff = ReadHistFromFile(
this,
"Eff", f.get(), time_unit);
59 m_mc_eff = ReadHistFromFile(
this,
"MC_Eff", f.get(), time_unit);
60 m_sf = ReadHistFromFile(
this,
"SF", f.get(), time_unit);
62 if (syst_name.empty())
return;
67 m_default_eff_ttva = 1. + 1.e-9;
70 m_default_eff_ttva = 1. - 1.e-9;
72 std::function<void(std::unique_ptr<HistHandler>&,
const std::string& )> syst_loader = [
this, &f, &time_unit, &syst_type_bitmap] (std::unique_ptr<HistHandler>& nominal,
const std::string& hist_type) {
74 std::unique_ptr<HistHandler> sys = ReadHistFromFile(
this, Form(
"%s_%s_%s", hist_type.c_str() ,
76 (syst_type_bitmap & EffiCollection::Symmetric ?
"SYM" : (m_is_up ?
"1UP" :
"1DN")) ),
79 for (
int i = 1; i <= nominal->nBins(); ++i) {
80 double content = nominal->GetBinContent(i);
81 double variation = (IsUpVariation() ? 1. : -1.)*sys->GetBinContent(i);
82 nominal->SetBinContent(i,content + variation);
89 if (m_syst_name ==
"SYS"){
90 std::unique_ptr<HistHandler> old_sys = ReadHistFromFile(
this, hist_type +
"_sys", f.get(), time_unit);
97 for (
int i = 1; i<= nominal->nBins(); ++i) {
98 nominal->SetBinContent(i, nominal->GetBinContent(i) + (IsUpVariation() ? 1. : -1.)*old_sys->GetBinContent(i));
102 else if (m_syst_name ==
"STAT") {
103 for (
int i = 1; i<= nominal->nBins(); ++i) {
104 nominal->SetBinContent(i, nominal->GetBinContent(i) + (IsUpVariation() ? 1. : -1.)*nominal->GetBinError(i));
108 else if (m_syst_name ==
"PTDEPENDENCY"){
113 Error(
"EfficiencyScaleFactor()",
"Failed to load sytstematic variation %s for measurement %s and histo-type %s", sysname(
true).c_str(),
114 EfficiencyTypeName(m_measurement).c_str(),
120 syst_loader(m_sf,
"SF");
121 syst_loader(m_eff,
"Eff");
122 syst_loader(m_mc_eff,
"MC_Eff");
125 if (m_is_lowpt || (
file == ref_tool.filename_HighEta() && ref_tool.filename_HighEta() != ref_tool.filename_Central()) ||
126 (
file == ref_tool.filename_Calo() && ref_tool.filename_Calo() != ref_tool.filename_Central())) m_respond_to_kineDepSyst =
false;
130 if (!m_respond_to_kineDepSyst){
134 if (m_measurement == MuonEfficiencyType::BadMuonVeto) {
135 TDirectory* SystDir =
nullptr;
136 f->GetObject((
"KinematicSystHandler_" + time_unit).c_str(), SystDir);
139 m_sf_KineDepsys = std::make_unique<BadMuonVetoSystHandler>(SystDir);
142 f->GetObject(
"BadMuonVetoSyst_3Stations", SystDir);
143 TDirectory* SystDir_2Stat =
nullptr;
144 f->GetObject(
"BadMuonVetoSyst_2Stations", SystDir_2Stat);
145 m_sf_KineDepsys = std::make_unique<BadMuonVetoSystHandler>(SystDir, SystDir_2Stat);
147 m_sf_KineDepsys->SetSystematicWeight( IsUpVariation() ? 1 : -1);
148 if (!m_sf_KineDepsys->initialize()){
149 Error(
"EfficiencyScaleFactor()",
"Pt dependent systematic could not be loaded");
150 m_sf_KineDepsys.reset();
153 addSubtool (*m_sf_KineDepsys);
155 }
else if (m_measurement == MuonEfficiencyType::TTVA){
156 m_sf_KineDepsys = std::make_unique<TTVAClosureSysHandler>(ReadHistFromFile(
this,
"SF_NonClosure_sys",f.get(),time_unit));
157 if (!m_sf_KineDepsys->initialize()){
158 Error(
"EfficiencyScaleFactor()",
"TTVA non closure systematic could not be loaded.");
159 m_sf_KineDepsys.reset();
162 m_sf_KineDepsys->SetSystematicWeight( IsUpVariation() ? 1 : -1);
164 addSubtool (*m_sf_KineDepsys);
169 m_sf_KineDepsys = std::make_unique<PtKinematicSystHandler>(ReadHistFromFile(
this, Form(
"SF_PtFlatness_1%s", m_is_up?
"UP" :
"DN"), f.get(), time_unit), ReadHistFromFile(
this,
"SF_PtDep_sys", f.get(), time_unit));
172 if(!m_sf_KineDepsys->initialize()){
173 m_sf_KineDepsys = std::make_unique<PrimodialPtSystematic>(ReadHistFromFile(
this,
"SF_PtDep_sys", f.get(), time_unit));
175 m_sf_KineDepsys->SetSystematicWeight( IsUpVariation() ? 1 : -1);
176 addSubtool (*m_sf_KineDepsys);
178 EfficiencyScaleFactor::EfficiencyScaleFactor(
const MuonEfficiencyScaleFactors& ref_tool,
179 const std::string &
file,
180 const std::string &time_unit):
182 ref_tool,
file, time_unit,
"",0){}
184 std::string EfficiencyScaleFactor::sysname(
bool with_direction)
const {
185 return m_syst_name.empty() ?
"" : EfficiencyTypeName(m_measurement) +
"_" + m_syst_name +(m_is_lowpt ?
"_LOWPT" :
"") + (with_direction ? (m_is_up ?
"__1UP" :
"__1DN") :
"");
187 bool EfficiencyScaleFactor::separateBinSyst()
const {
188 return m_separateBinSyst;
190 bool EfficiencyScaleFactor::IsUpVariation()
const{
193 unsigned int EfficiencyScaleFactor::firstRun()
const{
196 unsigned int EfficiencyScaleFactor::lastRun()
const{
199 bool EfficiencyScaleFactor::coversRunNumber(
unsigned int run)
const{
200 return m_firstRun <=
run &&
run <= m_lastRun;
202 void EfficiencyScaleFactor::setFirstLastRun(
unsigned int first,
unsigned int last){
206 bool EfficiencyScaleFactor::CheckConsistency() {
209 Error(
"EfficiencyScaleFactor()",
"Could not load the SF for measurement %s and systematic %s",EfficiencyTypeName(m_measurement).c_str(), sysname().c_str());
212 if (m_respond_to_kineDepSyst && !m_sf_KineDepsys->initialize()) {
213 Error(
"EfficiencyScaleFactor()",
"Could not load the SF pt-dependent systematic for %s and systematic %s", EfficiencyTypeName(m_measurement).c_str(), sysname().c_str() );
216 if (m_NominalFallBack.get() ==
this) {
217 Error(
"EfficiencyScaleFactor()",
"The EfficiencyScaleFactor %s has itself as Nominal Fall back.", EfficiencyTypeName(m_measurement).c_str());
218 m_NominalFallBack.reset();
221 if (m_NominalFallBack) {
222 if (!m_NominalFallBack->sysname().empty() || sysname().
empty()){
223 Error(
"EfficiencyScaleFactor()",
"Either nominal is assigned with a fall back (%s) or the nominal fall back is invald(%s).", sysname().c_str(), m_NominalFallBack->sysname().c_str() );
227 if (firstRun() > lastRun()){
228 Error(
"EfficiencyScaleFactor()",
"Invalid run number range. Since the map is ranging from %u to %u.", firstRun(), lastRun());
231 std::function<bool(
const std::unique_ptr<HistHandler>&)> consistent_histo = [](
const std::unique_ptr<HistHandler>& histo)->
bool{
234 if (!histo)
return true;
235 for (
int i = 1; i <= histo->nBins(); ++i){
236 if (std::isnan(histo->GetBinContent(i)) || std::isinf(histo->GetBinContent(i))){
237 Error(
"EfficiencyScaleFactor()",
"The %d-th bin %s has not a number (%f)",i, histo->GetBinName(i).c_str(), histo->GetBinContent(i));
243 if (!consistent_histo(m_sf)){
244 Error(
"EfficiencyScaleFactor()",
"Invalid scalefactor in %s", sysname().c_str());
247 if (!consistent_histo(m_eff)){
248 Error(
"EfficiencyScaleFactor()",
"Invalid data-efficiency in %s", sysname().c_str());
251 if (!consistent_histo(m_mc_eff)){
252 Error(
"EfficiencyScaleFactor()",
"Invalid MC-efficiency in %s", sysname().c_str());
257 std::unique_ptr<HistHandler> EfficiencyScaleFactor::ReadHistFromFile(
columnar::ColumnarTool<>* parent,
const std::string& name, TFile* f,
const std::string& time_unit) {
259 TH1* hist_from_file =
nullptr;
261 f->GetObject((name + std::string(
"_") + time_unit).c_str(), hist_from_file);
264 if (!hist_from_file && time_unit ==
"All") {
265 f->GetObject(name.c_str(), hist_from_file);
267 if (!hist_from_file) {
268 return std::unique_ptr<HistHandler>();
270 return package_histo(parent, hist_from_file);
275 if (!
h)
return std::unique_ptr<HistHandler>();
276 if (
dynamic_cast<TH2Poly*
>(
h)) {
277 return std::make_unique<HistHandler_TH2Poly>(parent,
dynamic_cast<TH2Poly*
>(
h));
278 }
else if (
h->GetDimension() == 3) {
279 return std::make_unique<HistHandler_TH3>(parent,
h);
280 }
else if (
h->GetDimension() == 2) {
281 return std::make_unique<HistHandler_TH2>(parent,
h);
282 }
else if (
h->GetDimension() == 1) {
283 return std::make_unique<HistHandler_TH1>(parent,
h);
285 Error(
"EfficiencyScaleFactor",
"Unable to package histo %s (%s) in a known HistHandler",
h->GetName(),
h->IsA()->GetName());
286 return std::unique_ptr<HistHandler>();
288 int EfficiencyScaleFactor::nBins()
const {
289 return m_sf ? m_sf->nBins() : -1;
291 int EfficiencyScaleFactor::nOverFlowBins()
const{
292 return m_sf ? m_sf->nOverFlowBins() : -1;
294 bool EfficiencyScaleFactor::isOverFlowBin(
int b)
const{
295 return m_sf ? m_sf->isOverFlowBin(b) :
true;
301 if (m_separateBinSyst && m_NominalFallBack) {
307 if (
bin != m_SystematicBin) {
308 return m_NominalFallBack->ScaleFactor(mu, SF);
317 if (m_separateBinSyst && m_NominalFallBack && m_eff) {
323 if (
bin != m_SystematicBin) {
324 return m_NominalFallBack->DataEfficiency(mu, Eff);
332 if (m_separateBinSyst && m_NominalFallBack && m_mc_eff) {
338 if (
bin != m_SystematicBin) {
339 return m_NominalFallBack->MCEfficiency(mu, Eff);
348 return GetContentFromHist (Hist,
columnar::MuonId (mu), Eff, add_kine_syst);
353 if (m_warnsPrinted < m_warningLimit){
354 Warning(
"EfficiencyScaleFactor",
"Could not find histogram for variation %s and muon with pt=%.4f, eta=%.2f and phi=%.2f, returning %.1f", sysname().c_str(), ptAcc(mu), etaAcc(mu), phiAcc(mu), m_default_eff);
359 if (m_measurement == MuonEfficiencyType::TTVA && std::abs(etaAcc(mu)) > 2.5 && std::abs(etaAcc(mu)) <= 2.7 && muonTypeAcc(mu) == xAOD::Muon::MuonType::MuonStandAlone) {
360 if (m_warnsPrinted < m_warningLimit){
361 Info(
"EfficiencyScaleFactor",
"No TTVA sf/efficiency provided for standalone muons with 2.5<|eta|<2.7 for variation %s and muon with pt=%.4f, eta=%.2f and phi=%.2f, returning %.1f", sysname().c_str(), ptAcc(mu), etaAcc(mu), phiAcc(mu), m_default_eff_ttva);
364 Eff = m_default_eff_ttva;
370 else Eff = Hist->GetBinContent(
bin);
372 if (add_kine_syst && m_respond_to_kineDepSyst) {
373 return m_sf_KineDepsys->GetKineDependent(mu, Eff);
380 (*m_sf_decor)(mu) = sf;
384 std::vector<float> replicas(n_replicas);
386 (*m_sf_rep_decor)(mu)= replicas;
393 (*m_eff_decor)(mu) = effi;
397 std::vector<float> replicas(n_replicas);
399 (*m_eff_rep_decor)(mu) = replicas;
405 (*m_mc_eff_decor)(mu) = effi;
409 std::vector<float> replicas(n_replicas);
411 (*m_mc_eff_rep_decor)(mu) = replicas;
415 return GetContentReplicasFromHist(m_sf_replicas, mu, SF,
true);
418 return GetContentReplicasFromHist(m_eff_replicas, mu, eff,
true);
421 return GetContentReplicasFromHist(m_mc_eff_replicas, mu, eff,
false);
423 CP::CorrectionCode EfficiencyScaleFactor::GetContentReplicasFromHist(EfficiencyScaleFactor::SFReplicaVec &replicas,
const xAOD::Muon& mu, std::vector<float> & SF,
bool add_kine_syst) {
424 if (replicas.size() != SF.size()) GenerateReplicas(SF.size(), 1000. * mu.phi() + mu.eta());
426 if (m_measurement == MuonEfficiencyType::TTVA && std::abs(mu.eta()) > 2.5 && std::abs(mu.eta()) <= 2.7 && mu.muonType() == xAOD::Muon::MuonType::MuonStandAlone) {
427 if (m_warnsPrinted < m_warningLimit){
428 Info(
"EfficiencyScaleFactor",
"No TTVA sf/efficiency provided for standalone muons with 2.5<|eta|<2.7 for variation %s and muon with pt=%.4f, eta=%.2f and phi=%.2f, returning %.1f", sysname().c_str(), mu.pt(), mu.eta(), mu.phi(), m_default_eff_ttva);
432 r = m_default_eff_ttva;
437 if (add_kine_syst && m_respond_to_kineDepSyst) {
445 for (
size_t k = 0; k < SF.size(); k++) {
446 SF[k] = replicas.at(k)->GetBinContent(
bin) * extra_sys;
451 void EfficiencyScaleFactor::GenerateReplicas(
int nrep,
int seed) {
452 GenerateReplicasFromHist(m_eff.get(), nrep, seed, m_eff_replicas);
453 GenerateReplicasFromHist(m_sf.get(), nrep, seed, m_sf_replicas);
454 GenerateReplicasFromHist(m_mc_eff.get(), nrep, seed, m_mc_eff_replicas);
456 void EfficiencyScaleFactor::GenerateReplicasFromHist(
HistHandler*
h,
int nrep,
int seed, EfficiencyScaleFactor::SFReplicaVec &replicas) {
460 replicas.reserve(nrep);
461 int nBins =
h->nBins();
462 for (
int t = 0; t < nrep; t++) {
463 replicas.push_back(package_histo(
this,
h->GetHist()));
466 replica->SetBinContent(
bin, Rndm.Gaus(
h->GetBinContent(
bin),
h->GetBinError(
bin)));
471 bool EfficiencyScaleFactor::SetSystematicBin(
int bin) {
472 if (m_syst_name.empty())
return true;
473 if (!m_NominalFallBack) {
474 Error(
"EfficiencyScaleFactor::SetSystematicBin()",
"No fallback has been given for %s", sysname().c_str());
477 if (!m_separateBinSyst || bin < 1 || bin > nBins()) {
478 Error(
"EfficiencyScaleFactor::SetSystematicBin()",
"The current bin %i is out of the maximum range %u ",
bin, nBins());
481 m_SystematicBin =
bin;
484 std::string EfficiencyScaleFactor::GetBinName(
int bin)
const {
485 if (bin < 1 || bin > nBins()) {
486 Error(
"EfficiencyScaleFactor::GetBinName()",
"The current bin %i is out of the maximum range %u ",
bin, nBins());
487 return "Out of range";
489 return m_sf->GetBinName(
bin);
492 int EfficiencyScaleFactor::FindBinSF(
const xAOD::Muon & mu)
const {