10namespace ADD_CMODE(CP) {
12 static const std::vector<std::string> ToRemove {
"GeV",
"MeV",
"[",
"]",
"{",
"}",
"(",
")",
"#",
" " };
13 typedef std::pair<std::string,std::string> stringpair;
14 static const std::vector<stringpair> ToReplace { stringpair(
"-",
"minus"), stringpair(
".",
"p")};
17 EffiCollection::EffiCollection(MuonEfficiencyScaleFactors& ref_tool) :
22 m_lowpt_central_eff(),
25 m_lrt_lowpt_central_eff(),
26 m_syst_set(std::make_unique<CP::SystematicSet>()){
28 ref_tool.addSubtool (*
this);
30 m_central_eff = std::make_shared<CollectionContainer>(m_ref_tool, CollectionType::Central);
31 m_central_eff->addSubtoolsTo(*
this);
32 if (m_ref_tool.filename_Calo() != m_ref_tool.filename_Central()){
33 m_calo_eff = std::make_shared<CollectionContainer>(m_ref_tool,CollectionType::Calo);
34 m_calo_eff->addSubtoolsTo(*
this);
35 }
else m_calo_eff = m_central_eff;
37 if (m_ref_tool.filename_HighEta() != m_ref_tool.filename_Central()){
38 m_forward_eff = std::make_shared<CollectionContainer>(m_ref_tool,CollectionType::Forward);
39 m_forward_eff->addSubtoolsTo(*
this);
40 }
else m_forward_eff = m_central_eff;
42 if (m_ref_tool.lowPtTransition() > 0 && m_ref_tool.filename_LowPt() != m_ref_tool.filename_Central()){
43 m_lowpt_central_eff = std::make_shared<CollectionContainer>(m_ref_tool,CollectionType::CentralLowPt);
44 m_lowpt_central_eff->addSubtoolsTo(*
this);
45 }
else m_lowpt_central_eff = m_central_eff;
47 if (m_ref_tool.lowPtTransition() > 0 && m_ref_tool.filename_LowPtCalo() != m_ref_tool.filename_Central()){
48 m_lowpt_calo_eff = std::make_shared<CollectionContainer>(m_ref_tool, CollectionType::CaloLowPt);
49 m_lowpt_calo_eff->addSubtoolsTo(*
this);
50 }
else m_lowpt_calo_eff = m_central_eff;
52 if(m_ref_tool.use_lrt()) {
53 if (m_ref_tool.filename_LRTCentral() != m_ref_tool.filename_Central()) {
54 m_lrt_central_eff = std::make_shared<CollectionContainer>(m_ref_tool,CollectionType::LRTCentral);
55 m_lrt_central_eff->addSubtoolsTo(*
this);
58 m_lrt_central_eff = m_central_eff;
60 if (m_ref_tool.lowPtTransition() > 0 ) {
61 if (m_ref_tool.filename_LRTLowPt() != m_ref_tool.filename_LRTCentral()) {
62 m_lrt_lowpt_central_eff = m_lrt_central_eff;
64 else if (m_ref_tool.filename_LRTLowPt() == m_ref_tool.filename_LowPt()) {
65 m_lrt_lowpt_central_eff = m_lowpt_central_eff;
67 else if (m_ref_tool.filename_LRTLowPt() == m_ref_tool.filename_Central()) {
68 m_lrt_lowpt_central_eff = m_central_eff;
71 m_lrt_lowpt_central_eff = std::make_shared<CollectionContainer>(m_ref_tool,CollectionType::LRTCentralLowPt);
72 m_lrt_lowpt_central_eff->addSubtoolsTo(*
this);
76 m_lrt_lowpt_central_eff = m_lrt_central_eff;
81 EffiCollection::EffiCollection(
const EffiCollection* Nominal, MuonEfficiencyScaleFactors& ref_tool,
const std::string& syst,
int syst_bit_map,
bool is_up):
86 m_lowpt_central_eff(),
89 m_lrt_lowpt_central_eff(),
92 ref_tool.addSubtool (*
this);
94 if (is_up) syst_bit_map |= EffiCollection::UpVariation;
96 std::function< std::shared_ptr<CollectionContainer>(CollectionType)> make_variation = [
this,&ref_tool, Nominal, syst_bit_map, syst](CollectionType
type){
97 if (syst_bit_map &
type) {
98 return std::make_shared<CollectionContainer>(ref_tool,
99 Nominal->retrieveContainer(
type).get(),
100 syst, syst_bit_map); }
102 if (ref_tool.measurement() != MuonEfficiencyType::Reco)
return m_central_eff;
103 return Nominal->retrieveContainer(
type);
105 m_central_eff = make_variation(CollectionType::Central);
106 m_central_eff->addSubtoolsTo (*
this);
107 m_forward_eff = make_variation(CollectionType::Forward);
108 m_forward_eff->addSubtoolsTo (*
this);
109 m_calo_eff = make_variation(CollectionType::Calo);
110 m_calo_eff->addSubtoolsTo (*
this);
111 m_lowpt_central_eff = make_variation(CollectionType::CentralLowPt);
112 m_lowpt_central_eff->addSubtoolsTo (*
this);
113 m_lowpt_calo_eff = make_variation(CollectionType::CaloLowPt);
114 m_lowpt_calo_eff->addSubtoolsTo (*
this);
116 if (m_ref_tool.use_lrt()) {
117 if(Nominal->m_lrt_central_eff == Nominal->m_central_eff) {
118 m_lrt_central_eff = m_central_eff;
121 m_lrt_central_eff = make_variation(CollectionType::LRTCentral);
122 m_lrt_central_eff->addSubtoolsTo (*
this);
124 if (Nominal->m_lrt_lowpt_central_eff == Nominal->m_lrt_central_eff) {
125 m_lrt_lowpt_central_eff = m_lrt_central_eff;
126 }
else if (Nominal->m_lrt_lowpt_central_eff == Nominal->m_lowpt_central_eff) {
127 m_lrt_lowpt_central_eff = m_lowpt_central_eff;
128 }
else if (Nominal->m_lrt_lowpt_central_eff == Nominal->m_central_eff) {
129 m_lrt_lowpt_central_eff = m_central_eff;
131 m_lrt_lowpt_central_eff = make_variation(CollectionType::LRTCentralLowPt);
132 m_lrt_lowpt_central_eff->addSubtoolsTo (*
this);
137 std::shared_ptr<CollectionContainer> EffiCollection::retrieveContainer(CollectionType
Type)
const {
138 if (
Type == CollectionType::Central)
return m_central_eff;
139 if (
Type == CollectionType::Forward)
return m_forward_eff;
140 if (
Type == CollectionType::Calo)
return m_calo_eff;
141 if (
Type == CollectionType::CentralLowPt)
return m_lowpt_central_eff;
142 if (
Type == CollectionType::CaloLowPt)
return m_lowpt_calo_eff;
143 if (
Type == CollectionType::LRTCentral)
return m_lrt_central_eff;
144 if (
Type == CollectionType::LRTCentralLowPt)
return m_lrt_lowpt_central_eff;
145 return std::shared_ptr<CollectionContainer>();
147 bool EffiCollection::CheckConsistency() {
148 if (!m_central_eff || !m_central_eff->CheckConsistency()) {
149 Error(
"EffiCollection()",
"Consistency check for central file failed");
152 if (!m_calo_eff || !m_calo_eff->CheckConsistency()) {
153 Error(
"EffiCollection()",
"Consistency check for calo file failed");
156 if (!m_forward_eff || !m_forward_eff->CheckConsistency()) {
157 Error(
"EffiCollection()",
"Consistency check for forward file failed");
160 if (!m_lowpt_central_eff || !m_lowpt_central_eff->CheckConsistency()) {
161 Error(
"EffiCollection()",
"Consistency check for low-pt file failed");
164 if (!m_lowpt_calo_eff || !m_lowpt_calo_eff->CheckConsistency()) {
165 Error(
"EffiCollection()",
"Consistency check for low-pt calo file failed");
168 if (m_ref_tool.use_lrt()) {
169 if (!m_lrt_central_eff || !m_lrt_central_eff->CheckConsistency()) {
170 Error(
"EffiCollection()",
"Consistency check for LRT central file failed");
173 if (!m_lrt_lowpt_central_eff || !m_lrt_lowpt_central_eff->CheckConsistency()) {
174 Error(
"EffiCollection()",
"Consistency check for LRT low-pt file failed");
181 unsigned int n = m_central_eff->nBins();
182 std::function<void (CollectionContainer*)> assign_mapping = [
this, &n](CollectionContainer* container){
183 if (container != m_central_eff.get() && container->separateBinSyst()){
184 container->SetGlobalOffSet(n);
185 n += container->nBins();
188 assign_mapping(m_calo_eff.get());
189 assign_mapping(m_calo_eff.get());
190 assign_mapping(m_lowpt_central_eff.get());
191 assign_mapping(m_lowpt_calo_eff.get());
193 assign_mapping(m_forward_eff.get());
195 if (m_ref_tool.use_lrt()) {
196 assign_mapping(m_lrt_central_eff.get());
197 assign_mapping(m_lrt_lowpt_central_eff.get());
202 m_syst_set = std::make_unique<CP::SystematicSet>();
203 size_t glob_sys = m_ref_tool.getPosition(
this);
204 if (glob_sys > m_ref_tool.getNCollections()){
205 Error(
"EffiCollection()",
"Invalid position in the list of systematics. It seems that I'm not part of the referring ScaleFactorTool.");
209 std::vector<EffiCollection::CollectionType> collection_types{EffiCollection::Central, EffiCollection::Calo, EffiCollection::Forward,
210 EffiCollection::CentralLowPt, EffiCollection::CaloLowPt};
211 if (m_ref_tool.use_lrt()) {
212 collection_types.push_back(EffiCollection::LRTCentral);
213 collection_types.push_back(EffiCollection::LRTCentralLowPt);
215 for (
const EffiCollection::CollectionType& collection_type: collection_types){
217 std::shared_ptr<CollectionContainer> container = retrieveContainer(collection_type);
218 if (container->isNominal())
continue;
219 if (container->separateBinSyst()){
222 for (
unsigned int b = container->nBins() - 1; b > 0 ; --b){
223 unsigned int bin = b + container->globalOffSet();
224 if (container->isOverFlowBin(
bin))
continue;
228 m_syst_set->insert(
CP::SystematicVariation(
"MUON_EFF_" + container->sysname(), container->isUpVariation() ? 1 : -1));
235 CollectionContainer* EffiCollection::FindContainer(
columnar::MuonId mu)
const {
236 if (m_ref_tool.use_lrt()) {
237 if (isLRTmuon.isAvailable(mu)) {
238 if (isLRTmuon(mu))
return FindLRTContainer(mu);
242 const xAOD::TrackParticle* idtrack = mu.getXAODObject().trackParticle(xAOD::Muon::TrackParticleType::InnerDetectorTrackParticle);
245 Error(
"CollectionContainer",
"No information available to tell if the muon is LRT or standard. Either run MuonLRTMergingAlg to decorate with `isLRT` flag, or supply the patternRecoInfo for the original ID track.");
247 std::bitset<xAOD::NumberOfTrackRecoInfo> patternBitSet(patternAcc(*idtrack));
252 if (ptAcc(mu) < m_ref_tool.lowPtTransition()) {
253 if (std::abs(etaAcc(mu)) >= 2.5) {
254 return m_forward_eff.get();
256 if (muonTypeAcc(mu) == xAOD::Muon::MuonType::CaloTagged) {
257 return m_lowpt_calo_eff.get();
259 return m_lowpt_central_eff.get();
261 if (muonTypeAcc(mu) == xAOD::Muon::MuonType::CaloTagged) {
262 return m_calo_eff.get();
263 }
else if (std::abs(etaAcc(mu)) < 2.5) {
264 return m_central_eff.get();
266 return m_forward_eff.get();
269 CollectionContainer* EffiCollection::FindContainer(
unsigned int bin)
const{
270 if (m_central_eff->isBinInMap(
bin))
return m_central_eff.get();
271 if (m_forward_eff->isBinInMap(
bin))
return m_forward_eff.get();
272 if (m_calo_eff->isBinInMap(
bin))
return m_calo_eff.get();
273 if (m_lowpt_central_eff->isBinInMap(
bin))
return m_lowpt_central_eff.get();
274 if (m_lowpt_calo_eff->isBinInMap(
bin))
return m_lowpt_calo_eff.get();
275 if (m_ref_tool.use_lrt()) {
276 if (m_lrt_central_eff->isBinInMap(
bin))
return m_lrt_central_eff.get();
277 if (m_lrt_lowpt_central_eff->isBinInMap(
bin))
return m_lrt_lowpt_central_eff.get();
281 CollectionContainer* EffiCollection::FindLRTContainer(
columnar::MuonId mu)
const {
282 if (ptAcc(mu) < m_ref_tool.lowPtTransition())
return m_lrt_lowpt_central_eff.get();
283 else return m_lrt_central_eff.get();
289 CollectionContainer* Cont = FindContainer(mu);
290 if (Cont !=
nullptr)
return Cont->retrieve(RunNumber);
291 Warning(
"EffiCollection::retrieveSF()",
"Invalid muon");
294 unsigned int EffiCollection::nBins()
const {
295 unsigned int Nbins = 0;
297 Nbins += m_central_eff->nBins();
299 if (m_central_eff != m_calo_eff) {
300 Nbins += m_calo_eff->nBins();
302 if (m_forward_eff != m_central_eff) {
303 Nbins += m_forward_eff->nBins();
305 if (m_lowpt_central_eff != m_central_eff) {
306 Nbins += m_lowpt_central_eff->nBins();
308 if (m_lowpt_calo_eff != m_central_eff) {
309 Nbins += m_lowpt_calo_eff->nBins();
311 if (m_ref_tool.use_lrt()) {
312 if (m_lrt_central_eff) {
313 Nbins += m_lrt_central_eff->nBins();
315 if (m_lrt_lowpt_central_eff) {
316 Nbins += m_lrt_lowpt_central_eff->nBins();
321 bool EffiCollection::SetSystematicBin(
unsigned int Bin) {
322 CollectionContainer* Cont = FindContainer(Bin);
323 if (!Cont)
return false;
324 return Cont->SetSystematicBin(Bin);
326 bool EffiCollection::IsLowPtBin(
unsigned int Bin)
const {
327 return (m_central_eff != m_lowpt_central_eff && m_lowpt_central_eff->isBinInMap(Bin)) ||
328 (m_central_eff != m_lowpt_calo_eff && m_lowpt_calo_eff->isBinInMap(Bin));
330 bool EffiCollection::IsForwardBin(
unsigned int Bin)
const {
331 return m_forward_eff != m_central_eff && m_forward_eff->isBinInMap(Bin);
334 std::string EffiCollection::FileTypeName(EffiCollection::CollectionType T) {
335 if (T == CollectionType::Central)
return "Central";
336 if (T == CollectionType::Calo)
return "Calo";
337 if (T == CollectionType::Forward)
return "Forward";
338 if (T == CollectionType::CentralLowPt)
return "CentralLowPt";
339 if (T == CollectionType::CaloLowPt)
return "CaloLowPt";
340 if (T == CollectionType::LRTCentral)
return "LRTCentral";
341 if (T == CollectionType::LRTCentralLowPt)
return "LRTCentralLowPt";
342 return "EffiCollection::FileTypeName() - WARNING: Unknown EffiCollection::CollectionType!";
345 std::string EffiCollection::GetBinName(
unsigned int bin)
const {
346 CollectionContainer* Cont = FindContainer(
bin);
348 std::string BinName = FileTypeName(Cont->type()) +
"_"+ Cont->GetBinName(
bin);
349 for (
const std::string& R : ToRemove) {
350 BinName = ReplaceExpInString(BinName, R,
"");
352 for (
const stringpair& R : ToReplace) {
353 BinName = ReplaceExpInString(BinName, R.first, R.second);
357 Warning(
"EffiCollection::GetBinName()",
"Unknown bin %u",
bin);
359 return "UNKNOWN_BIN";
361 int EffiCollection::getUnCorrelatedSystBin(
const xAOD::Muon& mu)
const {
362 CollectionContainer* container = FindContainer(mu);
363 if (container)
return container->FindBinSF(mu);
367 return m_syst_set.get();
370 return m_syst_set->
find(variation) != m_syst_set->end();
373 if (
set.empty())
return m_syst_set->empty();
375 if (isAffectedBySystematic(variation))
return true;
384 CollectionContainer::CollectionContainer(
const MuonEfficiencyScaleFactors& ref_tool, EffiCollection::CollectionType FileType):
386 m_currentSF(
nullptr),
387 m_FileType(FileType),
390 std::map<std::string, std::pair<unsigned int, unsigned int>>
map = findPeriods(ref_tool);
391 for (
auto& period :
map) {
392 m_SF.push_back(std::make_shared<EfficiencyScaleFactor>(ref_tool, fileName(ref_tool), period.first));
393 m_SF.back()->setFirstLastRun(period.second.first, period.second.second);
396 CollectionContainer::CollectionContainer(
const MuonEfficiencyScaleFactors& ref_tool, CollectionContainer* Nominal,
const std::string& syst_name,
unsigned int syst_bit_map):
398 m_currentSF(
nullptr),
399 m_FileType(Nominal->type()),
401 std::map<std::string, std::pair<unsigned int, unsigned int>>
map = findPeriods(ref_tool);
402 for (
auto& period :
map) {
403 std::vector< std::shared_ptr<EfficiencyScaleFactor>>
::const_iterator itr = std::find_if( Nominal->m_SF.begin(),
405 [&period](
const std::shared_ptr<EfficiencyScaleFactor>&
a){
406 return a->coversRunNumber(period.second.first);
408 m_SF.push_back(std::make_shared<EfficiencyScaleFactor>(*itr, ref_tool, fileName(ref_tool), period.first, syst_name, syst_bit_map));
409 m_SF.back()->setFirstLastRun(period.second.first, period.second.second);
412 std::map<std::string, std::pair<unsigned int, unsigned int>> CollectionContainer::findPeriods(
const MuonEfficiencyScaleFactors& ref_tool)
const{
414 std::string file_name = fileName(ref_tool);
415 std::map<std::string, std::pair<unsigned int, unsigned int>>
map;
417 std::unique_ptr<TFile> fin (TFile::Open(file_name.c_str()));
418 if (!fin || !fin->IsOpen()) {
419 Error(
"CollectionContainer",
"Unable to open file %s", file_name.c_str());
423 fin->GetObject(
"LumiData", intree);
427 map[
"All"] = std::pair<unsigned int,unsigned int>(1, 999999);
429 std::string *period = 0;
430 unsigned int firstRun = 0;
431 unsigned int lastRun = 0;
432 intree->SetBranchAddress(
"Period", &period);
433 intree->SetBranchAddress(
"FirstRun", &firstRun);
434 intree->SetBranchAddress(
"LastRun", &lastRun);
435 for (
int t = 0; intree->GetEntry(t); t++) {
436 map[*period] = std::pair<unsigned int, unsigned int>(firstRun, lastRun);
441 std::string CollectionContainer::fileName(
const MuonEfficiencyScaleFactors& ref_tool)
const{
442 if (
type() == EffiCollection::CollectionType::Central)
return ref_tool.filename_Central();
443 if (
type() == EffiCollection::CollectionType::Calo)
return ref_tool.filename_Calo();
444 if (
type() == EffiCollection::CollectionType::CentralLowPt)
return ref_tool.filename_LowPt();
445 if (
type() == EffiCollection::CollectionType::CaloLowPt)
return ref_tool.filename_LowPtCalo();
446 if (
type() == EffiCollection::CollectionType::LRTCentral)
return ref_tool.filename_LRTCentral();
447 if (
type() == EffiCollection::CollectionType::LRTCentralLowPt)
return ref_tool.filename_LRTLowPt();
448 return ref_tool.filename_HighEta();
451 bool CollectionContainer::CheckConsistency() {
453 Error(
"CollectionContainer",
"Could not retrieve any SFs from the input file");
457 for (std::vector< std::shared_ptr<EfficiencyScaleFactor>>
::const_iterator first_sf = m_SF.
begin() ; first_sf != m_SF.end(); ++first_sf) {
458 if (!(*first_sf)->CheckConsistency())
return false;
459 for (std::vector< std::shared_ptr<EfficiencyScaleFactor>>
::const_iterator second_sf = m_SF.
begin(); second_sf != first_sf; ++second_sf) {
460 if ( (*first_sf)->coversRunNumber( (*second_sf)->firstRun()) || (*first_sf)->coversRunNumber((*second_sf)->lastRun()) ||
461 (*second_sf)->coversRunNumber( (*first_sf)->firstRun()) || (*second_sf)->coversRunNumber((*first_sf)->lastRun())){
462 Error(
"CollectionContainer",
"Overlapping periods observed in file type %s. As run %i is in period %i - %i. Please check your SF file!",
463 EffiCollection::FileTypeName(m_FileType).c_str(), (*first_sf)->firstRun(), (*second_sf)->firstRun(), (*second_sf)->lastRun());
469 std::sort(m_SF.begin(), m_SF.end(), [](
const std::shared_ptr<EfficiencyScaleFactor>&
a,
const std::shared_ptr<EfficiencyScaleFactor>& b){
470 return a->firstRun() < b->firstRun();});
473 bool CollectionContainer::LoadPeriod(
unsigned int RunNumber) {
474 if (!m_currentSF || !m_currentSF->coversRunNumber(RunNumber)) {
475 for (
auto& period : m_SF) {
476 if (period->coversRunNumber(RunNumber)) {
477 m_currentSF = period.get();
482 if (!m_warnedForRunNumber.contains(RunNumber)) {
483 Warning(
"CollectionContainer",
"Could not find any SF period in %s matching the run number %u", EffiCollection::FileTypeName(
type()).c_str(), RunNumber);
484 m_warnedForRunNumber.insert(RunNumber);
489 if (!LoadPeriod(RunNumber)) {
490 return (*m_SF.rbegin()).get();
494 bool CollectionContainer::SetSystematicBin(
unsigned int Bin) {
495 for ( std::shared_ptr<EfficiencyScaleFactor>& Period : m_SF) {
496 if (!Period->SetSystematicBin(Bin- m_binOffSet)) {
502 unsigned int CollectionContainer::nBins()
const {
503 return m_SF.empty() ? 0 : (*m_SF.begin())->nBins();
505 unsigned int CollectionContainer::nOverFlowBins()
const {
506 return m_SF.empty() ? 0 : (*m_SF.begin())->nOverFlowBins();
508 bool CollectionContainer::isOverFlowBin(
int b)
const {
509 return m_SF.empty() ? true : (*m_SF.begin())->isOverFlowBin(b-m_binOffSet);
511 bool CollectionContainer::isBinInMap(
unsigned int bin)
const{
512 return m_binOffSet <=
bin &&
bin < m_binOffSet + nBins();
514 EffiCollection::CollectionType CollectionContainer::type()
const {
517 std::string CollectionContainer::GetBinName(
unsigned int Bin)
const {
518 return (*m_SF.begin())->GetBinName(Bin- m_binOffSet);
520 int CollectionContainer::FindBinSF(
const xAOD::Muon &mu)
const {
521 if (m_SF.empty() )
return -1;
522 int bin = (*m_SF.begin())->FindBinSF(mu);
523 return bin > 0 ? m_binOffSet +
bin :
bin;
525 void CollectionContainer::SetGlobalOffSet(
unsigned int OffSet){
526 m_binOffSet = OffSet;
528 unsigned int CollectionContainer::globalOffSet()
const{
531 bool CollectionContainer::isNominal()
const {
532 if (m_SF.empty())
return false;
533 return (*m_SF.begin())->sysname(
false).empty();
535 bool CollectionContainer::isUpVariation()
const {
536 if (m_SF.empty())
return false;
537 return (*m_SF.begin())->IsUpVariation();
539 bool CollectionContainer::separateBinSyst()
const {
540 if (m_SF.empty())
return false;
541 return (*m_SF.begin())->separateBinSyst();
543 std::string CollectionContainer::sysname()
const{
544 if (m_SF.empty())
return "UNKNOWN SYST";
545 return (*m_SF.begin())->sysname(
false);
548 for (
auto& SF : m_SF)
549 parentTool.addSubtool(*SF);