37 m_effTool (
"BTaggingEfficiencyTool/effTool", this),
38 m_selTool (
"BTaggingSelectionTool/selTool", this)
45 declareProperty(
"UsePermutations",
m_usePerm=
true,
"if the chosen permutation is used, a reweighting is applied to the TRF weight for systematics");
46 declareProperty(
"UseQuantile",
m_useQuntile=
true,
"if the chosen quantile is used, a reweighting is applied to the TRF weight for systematics");
47 declareProperty(
"UseSystematics",
m_useSys=
false,
"will the results contain all systematic variations, or just the nominal");
57 declareProperty(
"OperatingPoint",
m_OP=
"FixedCutBEff_77",
"operating point as specified in CDI file");
59 declareProperty(
"ScaleFactorFileName",
m_SFFile =
"xAODBTaggingEfficiency/13TeV/2016-20_7-13TeV-MC15-CDI-July12_v1.root",
"name of the official scale factor calibration CDI file (uses PathResolver)");
60 declareProperty(
"UseDevelopmentFile",
m_useDevFile =
false,
"specify whether or not to use the (PathResolver) area for temporary scale factor calibration CDI files");
64 declareProperty(
"ScaleFactorTCalibration",
m_SFTName =
"default",
"name of tau-jet scale factor calibration object");
66 declareProperty(
"EigenvectorReductionB",
m_EVReductionB =
"Loose",
"b-jet scale factor Eigenvector reduction strategy; choose between 'Loose', 'Medium', 'Tight'");
67 declareProperty(
"EigenvectorReductionC",
m_EVReductionC =
"Loose",
"c-jet scale factor Eigenvector reduction strategy; choose between 'Loose', 'Medium', 'Tight'");
68 declareProperty(
"EigenvectorReductionLight",
m_EVReductionLight =
"Loose",
"light-flavour jet scale factor Eigenvector reduction strategy; choose between 'Loose', 'Medium', 'Tight'");
69 declareProperty(
"EfficiencyBCalibrations",
m_EffBName =
"default",
"(semicolon-separated) name(s) of b-jet efficiency object(s)");
70 declareProperty(
"EfficiencyCCalibrations",
m_EffCName =
"default",
"(semicolon-separated) name(s) of c-jet efficiency object(s)");
71 declareProperty(
"EfficiencyTCalibrations",
m_EffTName =
"default",
"(semicolon-separated) name(s) of tau-jet efficiency object(s)");
72 declareProperty(
"EfficiencyLightCalibrations",
m_EffLightName =
"default",
"(semicolon-separated) name(s) of light-flavour-jet efficiency object(s)");
73 declareProperty(
"ExcludeFromEigenVectorTreatment",
m_excludeFromEV =
"",
"(semicolon-separated) names of uncertainties to be excluded from eigenvector decomposition (if used)");
74 declareProperty(
"SystematicsStrategy",
m_systStrategy =
"SFEigen",
"name of systematics model; presently choose between 'SFEigen' and 'Envelope'");
75 declareProperty(
"ConeFlavourLabel",
m_coneFlavourLabel =
true,
"specify whether or not to use the cone-based flavour labelling instead of the default ghost association based labelling");
76 declareProperty(
"OldConeFlavourLabel",
m_oldConeFlavourLabel =
false,
"when using cone-based flavour labelling, specify whether or not to use the (deprecated) Run-1 legacy labelling");
77 declareProperty(
"CutBenchmark",
m_cutBenchmark =
"1,2",
"if you want to run in continuous you need to fix a benchmark - it does something only if running in Continuous OP");
78 declareProperty(
"ExcludeSpecificEigens",
m_excludeEV =
"" ,
"(semicolon-separated) names of Eigens you want to exclude. in case of continuous some eigenvectors can be ignored to make the computation faster");
79 declareProperty(
"StoreOnlyUpVariations",
m_doOnlyUpVariations =
false ,
"If set to true it processes only the __1up b-tagging variations. It speeds up the computation in case of symmetric variations.");
80 declareProperty(
"doDirectTagging",
m_doDirectTag =
false ,
"If set to true it also computes and stores the direct tagging choice and the related SFs for each jet");
83 declareProperty(
"TaggingStrategy",
m_taggingStrategy =
"AllJets",
"tagging strategy in the Analysis (eg. 'leading2SignalJets' in boosted VHbb). Required to do TT with GNN");
88 return StatusCode::SUCCESS;
92 ATH_MSG_DEBUG(
"setting the use of systematics to: " <<useSystematics);
103 for (
auto syst : systConfig) {
105 ATH_MSG_WARNING(
"applySystematicVariation was called for " << syst.name() <<
" but BTaggingTruthTaggingTool does not apply Systematic Variations");
108 return StatusCode::SUCCESS;
114 return sys.find( systematic) !=
sys.end();
163 if(
m_OP.find(
"Continuous") != std::string::npos){
166 if(
m_OP.find(
"Continuous2D") != std::string::npos)
171 for (
const auto & tag_bin : tag_benchmarks ){
184 ATH_MSG_ERROR(
"UseQuantile is available only in Continuous WP. Please consider switching the Operating Point.");
185 return StatusCode::FAILURE;
200 std::vector<std::string> excludeEV_vector;
204 for (
const auto & syst : systs) {
206 string s = syst.name();
208 if(std::any_of(excludeEV_vector.begin(), excludeEV_vector.end(), [&
s](
const std::string&
str) { return str.find(s) != std::string::npos; }))
continue;
211 ATH_MSG_INFO(
"Adding systematic " << syst.name() <<
"to the list ");
213 ATH_MSG_DEBUG(
"Adding systematic " << syst.name() <<
"to the list ");
223 m_inf = TFile::Open(pathtofile,
"read");
225 float min_cut_low = (
m_taggerName ==
"MV2c10") ? -1 : -20;
226 float max_cut_hig = (
m_taggerName ==
"MV2c10") ? +1 : +20;
228 if(
m_OP ==
"Continuous"){
229 std::vector<float> bin_edges;
230 bin_edges.push_back(min_cut_low);
233 float cutval = ((TVector*)
m_inf->Get(cutname))[0](0);
234 bin_edges.push_back(cutval);
236 bin_edges.push_back(max_cut_hig);
237 for (
unsigned int be = 0 ;
be < bin_edges.size()-1 ;
be++){
242 m_cuts.push_back(one_cut);
245 else if (
m_OP.find(
"Continuous2D") != std::string::npos){
246 ATH_MSG_INFO(
"TruthTagging initialization: Working with Continuous2D WP.");
248 TMatrixD* cuts2D = (TMatrixD*)
m_inf->Get(cutname);
251 for (
int bin = 0;
bin < cuts2D->GetNrows();
bin++){
253 <<(*cuts2D)(
bin,1) <<
" b-cuts : "
254 <<(*cuts2D)(
bin,2) <<
" "
262 float c_tagcut_low = ((*cuts2D)(
bin,0) < min_cut_low) ? min_cut_low : (*cuts2D)(
bin,0);
263 float c_tagcut_hig = ((*cuts2D)(
bin,1) > max_cut_hig) ? max_cut_hig : (*cuts2D)(
bin,1);
264 float b_tagcut_low = ((*cuts2D)(
bin,2) < min_cut_low) ? min_cut_low : (*cuts2D)(
bin,2);
265 float b_tagcut_hig = ((*cuts2D)(
bin,3) > max_cut_hig) ? max_cut_hig : (*cuts2D)(
bin,3);
267 TagBin one_cut =
TagBin(is_tagbin, b_tagcut_low, b_tagcut_hig, c_tagcut_low, c_tagcut_hig);
268 m_cuts.push_back(one_cut);
273 float cutval = ((TVector*)
m_inf->Get(cutname))[0](0);
278 m_cuts.push_back(untag_bin);
279 m_cuts.push_back(tag_bin);
284 ATH_MSG_INFO(
"b-tag low: " <<
c.bcut_low <<
" b-tag hig: " <<
c.bcut_hig <<
" c-tag low: " <<
c.ccut_low <<
" c-tag hig: " <<
c.ccut_hig <<
" Added to tag bins: " <<
c.is_tagbin);
301 return StatusCode::FAILURE;
304 return StatusCode::SUCCESS;
310 if(
pt.size()!=
eta.size() ||
pt.size()!=flav.size() ||
pt.size()!=tagw.size()){
311 ATH_MSG_ERROR(
"Vectors of pt, eta, flav and tagw should have same size" );
312 return StatusCode::FAILURE;
315 std::vector<Analysis::CalibrationDataVariables>* vars =
new std::vector<Analysis::CalibrationDataVariables>(0);
316 for(
unsigned int i =0;
i<
pt.size();
i++){
319 vars->push_back(vars_appo);
324 return StatusCode::SUCCESS;
329 std::vector<int> flav;
330 std::vector<Analysis::CalibrationDataVariables>* vars =
new std::vector<Analysis::CalibrationDataVariables>(0);
334 vars->push_back(vars_appo);
341 return StatusCode::SUCCESS;
345 if(flav.size()!=vars->size()){
346 ATH_MSG_ERROR(
"Vector of CalibrationDataVariables and flavour should have same size" );
347 return StatusCode::FAILURE;
350 for(
unsigned int i =0;
i<vars->size();
i++){
352 jetVar_appo.
flav=flav.at(
i);
353 jetVar_appo.
vars=vars->at(
i);
354 trfinf.
jets.push_back(jetVar_appo);
358 return StatusCode::SUCCESS;
364 if(node_feat.size()!=tagw.size()){
365 ATH_MSG_ERROR(
"Vectors of node_feat (outer axis) and tagw should have same size" );
366 return StatusCode::FAILURE;
369 std::vector<int> flav;
370 std::vector<Analysis::CalibrationDataVariables>* vars =
new std::vector<Analysis::CalibrationDataVariables>(0);
371 for(
unsigned int i =0;
i<tagw.size();
i++){
375 float pt = node_feat.at(
i)[1];
376 float eta = node_feat.at(
i)[2];
379 vars->push_back(vars_appo);
380 flav.push_back(node_feat.at(
i)[0]);
384 return StatusCode::SUCCESS;
390 std::vector<int> flav;
391 std::vector<Analysis::CalibrationDataVariables>* vars =
new std::vector<Analysis::CalibrationDataVariables>(0);
395 vars->push_back(vars_appo);
401 return StatusCode::SUCCESS;
408 if(flav.size()!=vars->size()){
409 ATH_MSG_ERROR(
"Vector of CalibrationDataVariables and flavour should have same size" );
410 return StatusCode::FAILURE;
415 trfinf.
njets = vars->size();
420 for(
unsigned int i =0;
i<trfinf.
njets;
i++){
422 jetVar_appo.
flav=flav.at(
i);
423 jetVar_appo.
vars=vars->at(
i);
424 trfinf.
jets.push_back(jetVar_appo);
427 return StatusCode::SUCCESS;
433 x.jetEta =
jet.eta();
437 if (!tagInfo)
return StatusCode::FAILURE;
440 if(!(
code==CorrectionCode::Ok ||
code==CorrectionCode::OutOfValidityRange)){
441 ATH_MSG_ERROR(
"BTaggingSelectionTool::getTaggerWeight returned CorrectionCode::Error");
442 return StatusCode::FAILURE;
445 return StatusCode::SUCCESS;
451 x.jetTagWeight = jetTagWeight;
453 return StatusCode::SUCCESS;
469 trf_weight_ex = trfinf.
trfw_ex;
470 trf_weight_in = trfinf.
trfw_in;
471 return StatusCode::SUCCESS;
480 trfinf.
rand.SetSeed(rand_seed);
483 std::vector<float> trf_weight_ex, trf_weight_in;
485 trf_weight_ex.clear();
486 trf_weight_in.clear();
507 for(
unsigned int sys = 0;
sys < n_systs; ++
sys){
522 std::vector<int> is_tagged;
524 is_tagged.push_back(
static_cast<int>(
t));
531 for(
unsigned int ntj=0; ntj< trfinf.
trfw_ex.size(); ntj++){
532 if(ntj > trfinf.
njets) {
535 ATH_MSG_DEBUG(
"number of jets: " <<trfinf.
njets <<
" less than max btag: " <<
m_nbtag <<
". Return BTag SF = 1. Consider applying an event pre-selection if this happens too often.");
552 return StatusCode::SUCCESS;
617 std::vector<std::vector<float>> tmp_effMC_allBins;
620 if(!(
code==CorrectionCode::Ok ||
code==CorrectionCode::OutOfValidityRange)){
621 ATH_MSG_ERROR(
"BTaggingEfficiencyTool::getMCEfficiencyONNX returned CorrectionCode::Error");
622 return StatusCode::FAILURE;
628 std::vector<float> tmp_effMC_oneBin;
629 for (
unsigned int jet_index=0; jet_index<trfinf.
njets; jet_index++){
630 tmp_effMC_oneBin.push_back(tmp_effMC_allBins[jet_index][
bin]);
636 for (
unsigned int jet_index=0; jet_index<trfinf.
njets; jet_index++){
643 return StatusCode::SUCCESS;
658 trfinf.
jets.at(
jet).vars.jetTagWeight =
bin+0.5;
665 if(!(
code==CorrectionCode::Ok ||
code==CorrectionCode::OutOfValidityRange)){
666 ATH_MSG_ERROR(
"BTaggingEfficiencyTool::getMCEfficiency returned CorrectionCode::Error");
667 return StatusCode::FAILURE;
671 ATH_MSG_DEBUG(
"effMC_allBins: tag bin: " <<
bin <<
" tagw: " << trfinf.
jets.at(
jet).vars.jetTagWeight <<
" eff: " <<eff_all);
675 return StatusCode::SUCCESS;
679 std::vector<std::vector<bool> > perm;
680 std::vector<std::vector<bool> > temp_perm;
682 std::vector<bool>
tags(njets,
false);
683 perm.push_back(
tags);
685 else if(
tags == njets) {
686 std::vector<bool>
tags(njets,
true);
687 perm.push_back(
tags);
692 for(
unsigned int j=0; j<temp_perm.size(); j++){
693 temp_perm.at(j).at(
i)=
true;
694 perm.push_back(temp_perm.at(j));
705 for (
unsigned int t=0;
t<
tags.size();
t++) {
715 ATH_MSG_WARNING(
"Truth Tagging weight > 1. --> setting it to 1. check maps!");
728 unsigned int njets = trfinf.
njets;
730 unsigned int limit = (njets > 7) ? 8 : njets+1;
733 auto& perm = trfinf.
perms[njets];
743 unsigned int max = nbtag+1;
754 for(
unsigned int i=0;
i<
limit;
i++) {
755 std::vector<float> weights;
764 for(
unsigned int p=0;
p<trfinf.
perms[njets].at(
i).
size();
p++) {
776 if(
i == 0) trfinf.
trfw_in.at(0) = 1.;
781 ATH_MSG_DEBUG(
"before return, nbtag = " << nbtag <<
" size de trfinf.trfw_in = " << trfinf.
trfw_in.size());
782 return StatusCode::SUCCESS;
785 std::vector<float> weights;
786 float sum = 0.,
w = 0.;
787 size_t size = trfinf.
perms[njets].at(nbtag).size();
793 for(
unsigned int p=0;
p<trfinf.
perms[njets].at(nbtag).
size();
p++) {
800 return StatusCode::SUCCESS;
802 return StatusCode::SUCCESS;
807 trf_chosen_perm_ex.resize(
m_nbtag+1);
808 trf_chosen_perm_in.resize(
m_nbtag+1);
809 trf_chosen_perm_ex = trfinf.
perm_ex;
810 trf_chosen_perm_in = trfinf.
perm_in;
811 std::string print_perm =
"Permutation: ";
812 for(
auto perm: trfinf.
perm_ex){
820 return StatusCode::SUCCESS;
828 return StatusCode::FAILURE;
831 unsigned int njets = trfinf.
njets;
832 unsigned int limit = (njets > 7) ? 8 : njets+1;
833 unsigned int max = (njets < nbtag+1) ?
limit : nbtag+1;
841 for(
unsigned int i=0;
i<
max;
i++) {
846 return StatusCode::SUCCESS;
850 std::vector<float> incl;
851 std::vector<std::pair<unsigned int, unsigned int> > trackPerm;
854 for(
unsigned int itag=nbtag; itag < trfinf.
permsWeight.size(); itag++) {
858 trackPerm.push_back(std::make_pair(itag,
ip));
867 float theX = trfinf.
rand.Uniform(
sum);
868 for(
unsigned int ip=0;
ip < incl.size();
ip++) {
870 if(incl.at(
ip) >= theX) {
872 trfinf.
perm_in.at(nbtag) = trfinf.
perms[trfinf.
njets].at(trackPerm.at(
ip).first).at(trackPerm.at(
ip).second);
876 trfinf.
perm_ex.at(nbtag) = trfinf.
perms[trfinf.
njets].at(trackPerm.at(
ip).first).at(trackPerm.at(
ip).second);
879 return StatusCode::SUCCESS;
882 return StatusCode::SUCCESS;
899 trf_bin_ex.resize(trfinf.
tbins_ex.size());
900 for(
unsigned int i =0;
i<trfinf.
tbins_ex.size();
i++)
901 trf_bin_ex.at(
i).resize(trfinf.
tbins_ex.at(
i).size());
903 trf_bin_in.resize(trfinf.
tbins_in.size());
904 for(
unsigned int i =0;
i<trfinf.
tbins_in.size();
i++)
905 trf_bin_in.at(
i).resize(trfinf.
tbins_in.at(
i).size());
907 for(
unsigned int i =0;
i<trfinf.
tbins_ex.size();
i++)
911 for(
unsigned int i =0;
i<trfinf.
tbins_in.size();
i++)
912 for(
unsigned int j=0; j<trfinf.
tbins_in.at(
i).size(); j++)
915 return StatusCode::SUCCESS;
936 return StatusCode::SUCCESS;
941 std::vector<int> btagops;
945 std::vector<float> incl;
946 std::vector<float> untagged_bins;
952 untagged_bins.push_back(
bin);
958 for(
unsigned int j=0; j<tagconf.size(); j++) {
970 float theX = trfinf.
rand.Uniform(
sum);
971 auto tag_index = std::lower_bound(incl.begin(), incl.end(), theX) - incl.begin();
973 btagops.push_back(tbin_choice);
978 float untag_sum = 0. ;
981 for(
auto bin : untagged_bins){
983 incl.push_back(untag_sum);
986 float theX = trfinf.
rand.Uniform(untag_sum);
987 auto untag_index = std::lower_bound(incl.begin(), incl.end(), theX) - incl.begin();
988 float utbin_choice = untagged_bins[untag_index];
989 btagops.push_back(utbin_choice);
995 if(btagops.size() != tagconf.size()) {
996 ATH_MSG_ERROR(
"You should not be here -> wrong size of tag bins vector. btagops: " <<btagops.size() <<
" tagconf: " <<tagconf.size());
997 return StatusCode::FAILURE;
1000 trfinf.
tbins_in.at(nbtag) = btagops;
1005 trfinf.
tbins_ex.at(nbtag) = btagops;
1009 return StatusCode::SUCCESS;
1014 for(
unsigned int j=0; j<tagws.size(); j++) {
1035 std::vector<int> appo;
1036 auto is_jettag =
false;
1037 for(
const auto &
jet : trfinf.
jets) {
1038 ATH_MSG_DEBUG(
"pt " <<
jet.vars.jetPt <<
" eta " <<
jet.vars.jetEta <<
" wei " <<
jet.vars.jetTagWeight);
1042 if(is_jettag) is_tagged.push_back(1);
1043 else is_tagged.push_back(0);
1046 return StatusCode::SUCCESS;
1057 for(
unsigned int i =0;
i< trfinf.
njets;
i++) {
1062 bool is_btagged = quantiles.at(
i);
1065 if(!(
code==CorrectionCode::Ok ||
code==CorrectionCode::OutOfValidityRange)){
1066 ATH_MSG_ERROR(
"BTaggingEfficiencyTool::getScaleFactor returned CorrectionCode::Error");
1071 int bin = quantiles.at(
i);
1077 if(!(
code==CorrectionCode::Ok ||
code==CorrectionCode::OutOfValidityRange)){
1078 ATH_MSG_ERROR(
"BTaggingEfficiencyTool::getScaleFactor returned CorrectionCode::Error");
1081 ATH_MSG_DEBUG(
"BIN " <<
bin <<
"SF: pt " <<trfinf.
jets.at(
i).vars.jetPt <<
" " <<trfinf.
jets.at(
i).vars.jetEta <<
" " <<trfinf.
jets.at(
i).vars.jetTagWeight <<
" jetSF " <<jetSF);
1094 return StatusCode::FAILURE;
1115 const std::string labelB =
"GhostBHadronsFinal";
1116 const std::string labelC =
"GhostCHadronsFinal";
1117 const std::string labelTau =
"GhostTausFinal";
1119 std::vector<const IParticle*> ghostB;
1120 if (
jet.getAssociatedObjects<
IParticle>(labelB, ghostB) && ghostB.size() > 0)
return 5;
1121 std::vector<const IParticle*> ghostC;
1122 if (
jet.getAssociatedObjects<
IParticle>(labelC, ghostC) && ghostC.size() > 0)
return 4;
1123 std::vector<const IParticle*> ghostTau;
1124 if (
jet.getAssociatedObjects<
IParticle>(labelTau, ghostTau) && ghostTau.size() > 0)
return 15;
1134 if (
jet.getAttribute(
"ConeTruthLabelID",
label))
return label;
1136 jet.getAttribute(
"TruthLabelID",
label);
1144 jet.getAttribute(
"HadronConeExclTruthLabelID",
label);
1150 const std::string& whitespace =
" \t") {
1151 const auto strBegin =
str.find_first_not_of(whitespace);
1152 if (strBegin == std::string::npos)
1155 const auto strEnd =
str.find_last_not_of(whitespace);
1156 const auto strRange = strEnd - strBegin + 1;
1158 return str.substr(strBegin, strRange);
1163 std::vector<std::string>
result;
1164 if (
str.size() > 0) {
1165 std::string::size_type
end;
1172 }
while (
end != std::string::npos);
1181 btag_scores.clear();
1182 btag_scores.resize(quantiles.size());
1185 ctag_scores.clear();
1186 ctag_scores.resize(quantiles.size());
1189 for(
unsigned int i=0;
i <quantiles.size();
i++ ){
1191 btag_scores.at(
i).resize(quantiles.at(
i).size());
1193 ctag_scores.at(
i).resize(quantiles.at(
i).size());
1195 unsigned int njets = quantiles.at(
i).size();
1196 for(
unsigned int j=0; j < njets; j++ ){
1198 int temp_quantile = (
m_continuous2D) ? quantiles.at(
i).at(j) : quantiles.at(
i).at(j) -1;
1200 float btag_low =
m_cuts[temp_quantile].bcut_low;
1201 float btag_hig =
m_cuts[temp_quantile].bcut_hig;
1203 float ctag_low =
m_cuts[temp_quantile].ccut_low;
1204 float ctag_hig =
m_cuts[temp_quantile].ccut_hig;
1206 btag_scores.at(
i).at(j) = btag_low + random.Uniform()*(btag_hig - btag_low );
1208 ctag_scores.at(
i).at(j) = ctag_low + random.Uniform()*(ctag_hig - ctag_low );
1211 return StatusCode::SUCCESS;