9#include <nlohmann/json.hpp>
13using json = nlohmann::json;
22 ANA_MSG_WARNING(
"The Run3 SSV calibration has not been performed yet -> the scale factors are not usable yet");
49 return StatusCode::FAILURE;
79 std::ifstream jsonFile_SSVWeightsAlg(json_file_SSVWeightsAlg);
80 if (!jsonFile_SSVWeightsAlg.is_open()) {
82 return StatusCode::FAILURE;
86 jsonFile_SSVWeightsAlg.close();
91 return StatusCode::FAILURE;
112 return StatusCode::FAILURE;
120 else if (
m_nFMethod ==
"pileup_based_linearfit") {
124 else if (
m_nFMethod ==
"pileup_based_binned") {
129 ATH_MSG_ERROR(
"Unknown nF method: " <<
m_nFMethod <<
" , accepted nF methods are: 'pileup_bjet_based', 'pileup_based_linearfit', 'pileup_based_binned'");
130 return StatusCode::FAILURE;
154 return StatusCode::SUCCESS;
161 return StatusCode::SUCCESS;
165 std::vector<const xAOD::TruthParticle*> truthBhs;
172 truthBhs.push_back(part);
187 std::vector<const xAOD::Jet*> jets_Selected;
193 jets_Selected.push_back(
jet);
197 b_jet_count = b_jet_count+1;
206 std::vector<const xAOD::Electron*> electrons_Selected;
211 electrons_Selected.push_back (
electron);
218 std::vector<const xAOD::Muon*> muons_Selected;
223 muons_Selected.push_back(
muon );
228 std::vector<const xAOD::Vertex*> good_SSVs =
create_good_SSVs(jets_Selected, electrons_Selected, muons_Selected, *SSVs);
237 int N_matched = std::count(truthBh_to_SSV_matched.begin(), truthBh_to_SSV_matched.end(),
true);
238 int N_missed = truthBh_to_SSV_matched.size() - N_matched;
245 double P_eff = std::pow(
m_SF_eff, N_matched);
269 double SSV_weight = P_eff * P_ineff * P_fake;
304 return StatusCode::SUCCESS;
309 const std::vector<const xAOD::Jet*> &jets,
310 const std::vector<const xAOD::Electron*> &electrons,
311 const std::vector<const xAOD::Muon*> &muons,
314 static const SG::AuxElement::ConstAccessor<float> ssv_pt_accessor((
"bvrtPt"));
315 static const SG::AuxElement::ConstAccessor<float> ssv_m_accessor(
"bvrtM");
316 static const SG::AuxElement::ConstAccessor<float> ssv_eta_accessor(
"bvrtEta");
318 std::vector<const xAOD::Vertex*> good_SSVs;
321 bool overlaps =
false;
324 if ( (ssv_pt_accessor(*SSV) < 3000) || (ssv_m_accessor(*SSV) < 600) || (std::abs(ssv_eta_accessor(*SSV)) > 2.5) ){
331 if (DeltaR_jet < 0.6){
337 if (overlaps ==
true){
343 if (DeltaR_el < 0.2){
349 if (overlaps ==
true){
356 if (DeltaR_mu < 0.2){
362 if (overlaps ==
true){
365 good_SSVs.push_back(SSV);
372 const std::vector<const xAOD::TruthParticle*> &truthBhs,
373 const std::vector<const xAOD::Jet*> &jets)
const {
375 std::vector<const xAOD::TruthParticle*> accepted_truthBhs;
379 if (truthBh->pt() < 2000 || (std::abs(truthBh->eta()) > 2.8)){
384 bool overlaps =
false;
386 double DeltaR = truthBh->p4().DeltaR(
jet->p4());
393 if (overlaps ==
true){
397 accepted_truthBhs.push_back(truthBh);
399 return accepted_truthBhs;
403 const std::vector<const xAOD::TruthParticle*> &truthBhs,
404 const std::vector<const xAOD::Vertex*> &SSVs)
const {
408 bool foundMatch =
false;
420 N_fake_SSV = N_fake_SSV + 1;
431 const std::vector<const xAOD::TruthParticle*> &truthBhs,
432 const std::vector<const xAOD::Vertex*> &SSVs)
const {
434 std::vector<bool> matched_vector(truthBhs.size(),
false);
435 for (
size_t i = 0; i < truthBhs.size(); ++i){
437 for (
size_t j = 0; j < SSVs.size(); ++j){
441 matched_vector[i] =
true;
446 return matched_vector;
454 static const SG::AuxElement::ConstAccessor<float> ssv_eta_accessor(
"bvrtEta");
455 static const SG::AuxElement::ConstAccessor<float> ssv_phi_accessor(
"bvrtPhi");
457 double eta_diff = ssv_eta_accessor(*vtx) - part->eta() ;
461 double phi_diff = TVector2::Phi_mpi_pi(ssv_phi_accessor(*vtx) - part->phi() );
464 return std::sqrt( eta_diff*eta_diff + phi_diff*phi_diff );
469 const std::vector<const xAOD::TruthParticle*> &truthBhs,
470 const std::vector<bool> &matched_vector) {
472 std::vector<const xAOD::TruthParticle*> missed_vector;
473 for (
size_t i = 0; i < truthBhs.size(); ++i){
474 if (matched_vector[i] ==
false){
475 missed_vector.push_back(truthBhs[i]);
478 return missed_vector;
484 const int type)
const {
486 for (
unsigned int i = 0; i < part->nChildren(); ++i){
518 const double lambda){
519 if (lambda == 0.0 )
return k == 0 ? 1.0 : 0.0;
520 if (lambda < 0 || k < 0)
return 0.0;
521 return std::exp(-lambda + k * std::log(lambda) - std::lgamma(k + 1));
528 for (
size_t i = 0; i <
m_ptbins.size() - 1; ++i) {
529 std::string pT_bin_key =
"pt_bin_" + std::to_string((
int)
m_ptbins[i]) +
"_" + std::to_string((
int)
m_ptbins[i+1]);
542 const std::vector<const xAOD::TruthParticle*> &accepted_truthBhs,
543 const std::vector<bool> &truthBh_to_SSV_matched,
544 double SF_eff)
const{
549 const std::vector<double> &ptbins =
m_ptbins;
552 const std::string etaStr{
"eta"};
553 const std::string effStr{
"efficiency"};
554 for (
size_t i = 0; i < missed_truthBhs.size(); ++i) {
556 double pt = missed_truthBhs[i]->pt();
557 double eta = std::abs(missed_truthBhs[i]->
eta());
558 std::string pt_bin_of_truthBh =
"";
561 throw std::runtime_error(
"EfficiencyMethodBhadronPtEtaBasedClass::getPIneff: B-hadron pT above the last pT bin edge, but no '" +
m_overflowPtBinKey +
"' entry in the calibration JSON file");
567 for (
size_t j = 0; j < ptbins.size() - 1; ++j) {
568 if (
pt >= ptbins[j] &&
pt < ptbins[j+1]) {
570 pt_bin_of_truthBh =
"pt_bin_" + std::to_string((
int)ptbins[j]) +
"_" + std::to_string((
int)ptbins[j+1]);
574 if (pt_bin_of_truthBh ==
""){
585 for (
size_t k = 0; k < eta_bins.size() - 1; ++k) {
586 double eta_low = eta_bins[k];
587 double eta_up = eta_bins[k+1];
588 if (
eta >= eta_low &&
eta < eta_up) {
598 P_ineff = P_ineff*(1-SF_eff*(*efficiency))/(1-(*
efficiency));
608 std::string lastItemKey = lastItem->first;
615 const int b_jet_count,
617 const double SF_eff)
const{
627 std::string bjets_key = std::to_string(b_jet_count) +
"_bjets";
635 P_ineff = std::pow((1-SF_eff*epsilon)/(1-epsilon), N_missed);
644 std::map<std::string, double>::iterator lastItem = std::prev(
m_nFPileupBJetMap.at(
"high_muactual").end());
645 std::string lastItemKey = lastItem->first;
652 const double muactual,
653 const int b_jet_count,
655 const double SF_fake_low,
656 const double SF_fake_high)
const{
663 double n_F_value = 0;
667 std::string bjets_key = std::to_string(b_jet_count) +
"_bjets";
677 throw std::runtime_error(
"nFMethodPileupBJetBasedClass::getPFake: divide-by-zero");
680 P_fake = (
poisson_pmf(N_fake, SF_fake_high*n_F_value))/denom;
683 P_fake = (
poisson_pmf(N_fake, SF_fake_low*n_F_value))/denom;
691 m_slopeUnscaled = jsonConfig[
"nF_pileup_based_linearfit"][
"unscaled"][
"slope"];
693 m_slopeScaled = jsonConfig[
"nF_pileup_based_linearfit"][
"scaled"][
"slope"];
694 m_interceptScaled = jsonConfig[
"nF_pileup_based_linearfit"][
"scaled"][
"intercept"];
699 const double muactual,
700 const int N_fake)
const{
706 throw std::runtime_error(
"nFMethodPileupBasedLinearFitClass::getPFake: divide-by-zero.");
725 const double muactual,
727 const double SF_fake_low,
728 const double SF_fake_high)
const{
742 P_fake =
poisson_pmf(N_fake, SF_fake_low * nF) / denom;
744 P_fake =
poisson_pmf(N_fake, SF_fake_high * nF) / denom;
Scalar eta() const
pseudorapidity method
#define ATH_MSG_ERROR(x,...)
static const std::vector< std::string > systematics
std::string PathResolverFindCalibFile(const std::string &logical_file_name)
TEfficiency * efficiency(std::string_view effName, std::string_view tDir="", std::string_view stream="")
Simplify the retrieval of registered TEfficiency.
EfficiencyMethodBJetBasedClass(const nlohmann::json &jsonConfig)
double getPIneff(const int b_jet_count, const int N_missed, const double SF_eff) const
std::map< std::string, double > m_bjetEfficiencyMap
std::string m_overflowPtBinKey
EfficiencyMethodBhadronPtEtaBasedClass(const nlohmann::json &jsonConfig)
std::map< std::string, std::map< std::string, std::vector< double > > > m_BhadronPtEtaEfficiencyMap
double getPIneff(const std::vector< const xAOD::TruthParticle * > &accepted_truthBh, const std::vector< bool > &truthBh_to_SSV_matched, double SF_eff) const
std::vector< double > m_ptbins
double getPFake(const double muactual, const int b_jet_count, const int N_fake, const double SF_fake_low, const double SF_fake_high) const
double m_lowMuHighMuThreshold
nFMethodPileupBJetBasedClass(const nlohmann::json &jsonConfig)
std::map< std::string, std::map< std::string, double > > m_nFPileupBJetMap
std::vector< double > m_muactualBins
double getPFake(const double muactual, const int N_fake, const double SF_fake_low, const double SF_fake_high) const
nFMethodPileupBasedBinnedClass(const nlohmann::json &jsonConfig)
std::vector< double > m_nFBins
double m_lowMuHighMuThreshold
double getPFake(const double muactual, const int N_fake) const
nFMethodPileupBasedLinearFitClass(const nlohmann::json &jsonConfig)
double m_interceptUnscaled
std::optional< SG::AuxElement::ConstAccessor< char > > m_jetBTagAccessor
CP::SysReadSelectionHandle m_muonSelection
std::vector< bool > truthBh_to_SSV_matching(const std::vector< const xAOD::TruthParticle * > &truthBhs, const std::vector< const xAOD::Vertex * > &SSVs) const
CP::SysWriteDecorHandle< int > m_N_fake_decor
CP::SysReadHandle< xAOD::JetContainer > m_jetsHandle
OutputVariableSizeType m_OutputVariableSizeType
CP::SysReadHandle< xAOD::VertexContainer > m_ssvHandle
std::unique_ptr< nFMethodPileupBasedLinearFitClass > m_nFPileupBasedLinearFitPtr
CP::SysWriteDecorHandle< float > m_SSV_weight_decor
CP::SysWriteDecorHandle< int > m_number_of_accepted_Bhadrons_decor
std::unique_ptr< EfficiencyMethodBJetBasedClass > m_EfficiencyMethodBJetBasedPtr
CP::SysReadHandle< xAOD::MuonContainer > m_muonsHandle
virtual StatusCode initialize() override
CP::SysWriteDecorHandle< int > m_N_matched_decor
double compute_DeltaR_between_SSV_and_particle(const xAOD::Vertex *vtx, const xAOD::IParticle *part) const
CP::SysWriteDecorHandle< float > m_P_fake_pileup_based_linearfit_decor
std::unique_ptr< EfficiencyMethodBhadronPtEtaBasedClass > m_EfficiencyMethodBhadronPtEtaBasedPtr
nlohmann::json m_jsonConfig_SSVWeightsAlg
CP::SysWriteDecorHandle< int > m_number_of_good_SSVs_decor
bool isHFHadronFinalState(const xAOD::TruthParticle *part, const int type) const
std::vector< const xAOD::TruthParticle * > create_accepted_truthBhs(const std::vector< const xAOD::TruthParticle * > &truthBhs, const std::vector< const xAOD::Jet * > &jets) const
CP::SysReadSelectionHandle m_electronSelection
static double poisson_pmf(const int k, const double lambda)
Gaudi::Property< std::string > m_jsonConfigPath_SSVWeightsAlg
nFMethodType m_nFMethodType
CP::SysWriteDecorHandle< float > m_P_fake_pileup_bjet_based_decor
Gaudi::Property< std::string > m_nFMethod
Gaudi::Property< std::string > m_EfficiencyMethod
CP::SysReadHandle< xAOD::TruthParticleContainer > m_truthParticlesHandle
std::unique_ptr< nFMethodPileupBJetBasedClass > m_nFPileupBJetBasedPtr
CP::SysWriteDecorHandle< float > m_P_ineff_bjet_based_decor
CP::SysWriteDecorHandle< float > m_P_ineff_decor
SSVWeightsAlg(const std::string &name, ISvcLocator *pSvcLocator)
CP::SysReadSelectionHandle m_jetSelection
int count_number_of_fake_SSVs(const std::vector< const xAOD::TruthParticle * > &truthBhs, const std::vector< const xAOD::Vertex * > &SSVs) const
CP::SysReadHandle< xAOD::EventInfo > m_eventInfoHandle
CP::SysListHandle m_systematicsList
Gaudi::Property< std::string > m_OutputVariableSize
std::vector< const xAOD::Vertex * > create_good_SSVs(const std::vector< const xAOD::Jet * > &jets, const std::vector< const xAOD::Electron * > &electrons, const std::vector< const xAOD::Muon * > &muons, const xAOD::VertexContainer &SSVs) const
CP::SysWriteDecorHandle< int > m_number_of_bjets_decor
CP::SysWriteDecorHandle< int > m_N_missed_decor
Gaudi::Property< std::string > m_BTaggingWP
CP::SysWriteDecorHandle< float > m_P_ineff_pt_eta_based_decor
CP::SysWriteDecorHandle< float > m_P_fake_pileup_based_binned_decor
static std::vector< const xAOD::TruthParticle * > construct_not_matched_vectors(const std::vector< const xAOD::TruthParticle * > &truthBhs, const std::vector< bool > &matched_vector)
CP::SysWriteDecorHandle< float > m_P_fake_decor
CP::SysReadHandle< xAOD::ElectronContainer > m_electronsHandle
CP::SysWriteDecorHandle< float > m_P_eff_decor
EfficiencyMethodType m_EfficiencyMethodType
std::unique_ptr< nFMethodPileupBasedBinnedClass > m_nFPileupBasedBinnedPtr
AnaAlgorithm(const std::string &name, ISvcLocator *pSvcLocator)
constructor with parameters
virtual::StatusCode execute()
execute this algorithm
float actualInteractionsPerCrossing() const
Average interactions per crossing for the current BCID - for in-time pile-up.
Class providing the definition of the 4-vector interface.
bool isBottomHadron() const
Determine if the PID is that of a b-hadron.
bool isGenStable() const
Check if this is generator stable particle.
bool isCharmHadron() const
Determine if the PID is that of a c-hadron.
T * get(TKey *tobj)
get a TObject* from a TKey* (why can't a TObject be a TKey?)
bool contains(const std::string &s, const std::string ®x)
does a string contain the substring
Select isolated Photons, Electrons and Muons.
This module defines the arguments passed from the BATCH driver to the BATCH worker.
Jet_v1 Jet
Definition of the current "jet version".
setRcore setEtHad setFside pt
ElectronContainer_v1 ElectronContainer
Definition of the current "electron container version".
EventInfo_v1 EventInfo
Definition of the latest event info version.
VertexContainer_v1 VertexContainer
Definition of the current "Vertex container version".
Vertex_v1 Vertex
Define the latest version of the vertex class.
TruthParticle_v1 TruthParticle
Typedef to implementation.
Muon_v1 Muon
Reference the current persistent version:
JetContainer_v1 JetContainer
Definition of the current "jet container version".
MuonContainer_v1 MuonContainer
Definition of the current "Muon container version".
TruthParticleContainer_v1 TruthParticleContainer
Declare the latest version of the truth particle container.
Electron_v1 Electron
Definition of the current "egamma version".