Program Listing for File BJetEfficiencyCorrector.cxx¶
↰ Return to documentation for file (Root/BJetEfficiencyCorrector.cxx
)
/**************************************************
*
* Interface to CP BJet Efficiency Correction Tool.
*
* John Alison (john.alison@cern.ch)
* Gabriel Facini (gabriel.facini@cern.ch)
*
*
**************************************************/
// c++ include(s):
#include <iostream>
// EL include(s):
#include <EventLoop/Job.h>
#include <EventLoop/StatusCode.h>
#include <EventLoop/Worker.h>
#include <SampleHandler/MetaFields.h>
#include "PathResolver/PathResolver.h"
//EDM
#include "xAODJet/JetAuxContainer.h"
// package include(s):
#include "xAODAnaHelpers/HelperFunctions.h"
#include "xAODAnaHelpers/HelperClasses.h"
#include "xAODAnaHelpers/BJetEfficiencyCorrector.h"
#include <AsgMessaging/MessageCheck.h>
// tools
#include "xAODBTaggingEfficiency/BTaggingSelectionTool.h"
#include "xAODBTaggingEfficiency/BTaggingEfficiencyTool.h"
using HelperClasses::ToolName;
// this is needed to distribute the algorithm to the workers
ClassImp(BJetEfficiencyCorrector)
BJetEfficiencyCorrector :: BJetEfficiencyCorrector () :
Algorithm("BJetEfficiencyCorrector")
{
}
EL::StatusCode BJetEfficiencyCorrector :: setupJob (EL::Job& job)
{
ANA_MSG_INFO( "Calling setupJob");
job.useXAOD ();
xAOD::Init( "BJetEfficiencyCorrector" ).ignore(); // call before opening first file
return EL::StatusCode::SUCCESS;
}
EL::StatusCode BJetEfficiencyCorrector :: histInitialize ()
{
ANA_CHECK( xAH::Algorithm::algInitialize());
m_corrFileName = PathResolverFindCalibFile(m_corrFileName);
return EL::StatusCode::SUCCESS;
}
EL::StatusCode BJetEfficiencyCorrector :: fileExecute ()
{
return EL::StatusCode::SUCCESS;
}
EL::StatusCode BJetEfficiencyCorrector :: changeInput (bool /*firstFile*/)
{
return EL::StatusCode::SUCCESS;
}
EL::StatusCode BJetEfficiencyCorrector :: initialize ()
{
ANA_MSG_INFO( "Initializing BJetEfficiencyCorrector Interface... ");
m_event = wk()->xaodEvent();
m_store = wk()->xaodStore();
ANA_MSG_INFO( "Number of events in file: " << m_event->getEntries() );
// several lists of systematics could be configured
// this is the case when MET sys should be added
// to the OR ones
// parse and split by comma
std::string token;
std::istringstream ss(m_inputAlgo);
while (std::getline(ss, token, ',')) {
m_inputAlgoList.push_back(token);
}
m_decorSF = m_decor + "_SF";
m_decorWeight = m_decor + "_Weight";
m_decorQuantile = m_decor + "_Quantile";
bool opOK(false),taggerOK(false);
m_getScaleFactors = false;
m_useContinuous = false;
// not calibrated yet
// https://twiki.cern.ch/twiki/bin/view/AtlasProtected/BTagCalib2017
// https://twiki.cern.ch/twiki/bin/viewauth/AtlasProtected/BTaggingBenchmarksRelease21
// All working points are calibrated (but not all taggers, see next check)
if (m_operatingPt == "FixedCutBEff_60" and (m_taggerName != "GN2v01")) { opOK = true; m_getScaleFactors = true; }
if (m_operatingPt == "FixedCutBEff_65") {
if(m_taggerName == "GN2v01"){
opOK = true; m_getScaleFactors = true;
}
}
if (m_operatingPt == "FixedCutBEff_70") { opOK = true; m_getScaleFactors = true; }
if (m_operatingPt == "FixedCutBEff_77") { opOK = true; m_getScaleFactors = true; }
if (m_operatingPt == "FixedCutBEff_85") { opOK = true; m_getScaleFactors = true; }
if (m_operatingPt == "FixedCutBEff_90" and (m_taggerName == "GN2v01")) { opOK = true; m_getScaleFactors = true; }
if (m_operatingPt == "Continuous" ) { opOK = true; m_getScaleFactors = true;
m_useContinuous = true;
ANA_MSG_DEBUG(" Using continuous b-tagging"); }
// No official calibrations in rel22 yet
if (m_taggerName == "DL1r") { taggerOK = true; m_getScaleFactors = false; }
if (m_taggerName == "DL1dv00") { taggerOK = true; m_getScaleFactors = false; }
if (m_taggerName == "DL1dv01") { taggerOK = true; m_getScaleFactors = true; }
if (m_taggerName == "GN120220509") { taggerOK = true; m_getScaleFactors = false; }
if (m_taggerName == "GN2v00LegacyWP") { taggerOK = true; m_getScaleFactors = false; }
if (m_taggerName == "GN2v00NewAliasWP") { taggerOK = true; m_getScaleFactors = false; }
if (m_taggerName == "GN2v01") { taggerOK = true; m_getScaleFactors = true; }
if( !opOK || !taggerOK ) {
ANA_MSG_ERROR( "Requested tagger/operating point is not known to xAH. Arrow v Indian? " << m_taggerName << "/" << m_operatingPt);
return EL::StatusCode::FAILURE;
}
// make unique name
m_decor += "_" + m_taggerName + "_" + m_operatingPt;
m_decorSF += "_" + m_taggerName + "_" + m_operatingPt;
m_outputSystName += "_" + m_taggerName + "_" + m_operatingPt;
m_decorWeight += "_" + m_taggerName + "_" + m_operatingPt;
m_decorQuantile += "_" + m_taggerName + "_" + m_operatingPt;
if(!m_useContinuous){
ANA_MSG_INFO( "Decision Decoration Name : " << m_decor);
ANA_MSG_INFO( "Scale Factor Decoration Name : " << m_decorSF);
} else {
ANA_MSG_INFO( "Weight Decoration Name: " << m_decorWeight);
ANA_MSG_INFO( "Quantile Decoration Name: " << m_decorQuantile);
ANA_MSG_INFO( "Scale Factor Decoration Name : " << m_decorSF);
}
// now take this name and convert it to the cut value for the CDI file
// if using the fixed efficiency points
if(m_operatingPtCDI.empty()) m_operatingPtCDI = m_operatingPt;
ANA_MSG_INFO("Using Standard OperatingPoint for CDI BTag Efficiency of " << m_operatingPtCDI);
m_runAllSyst = (m_systName.find("All") != std::string::npos);
if( m_inContainerName.empty() ) {
ANA_MSG_ERROR( "InputContainer is empty!");
return EL::StatusCode::FAILURE;
}
if ( !isMC() && m_getScaleFactors ) {
ANA_MSG_WARNING( "Attempting to run BTagging Jet Scale Factors on data. Turning off scale factors." );
m_getScaleFactors = false;
}
if ( m_tagDecisionOnly && m_getScaleFactors ) {
ANA_MSG_WARNING( "BTagging scale factors have been manually disabled. This is not recommended!" );
m_getScaleFactors = false;
}
// initialize the BJetSelectionTool
// A few which are not configurable as of yet....
// is there a reason to have this configurable here??...I think no (GF to self)
ANA_CHECK( m_BJetSelectTool_handle.setProperty("FlvTagCutDefinitionsFileName",m_corrFileName.c_str()));
// configurable parameters
ANA_CHECK( m_BJetSelectTool_handle.setProperty("TaggerName", m_taggerName));
ANA_CHECK( m_BJetSelectTool_handle.setProperty("OperatingPoint", m_operatingPt));
ANA_CHECK( m_BJetSelectTool_handle.setProperty("JetAuthor", m_jetAuthor));
ANA_CHECK( m_BJetSelectTool_handle.setProperty("MinPt", m_minPt));
ANA_CHECK( m_BJetSelectTool_handle.setProperty("ErrorOnTagWeightFailure", m_errorOnTagWeightFailure));
ANA_CHECK( m_BJetSelectTool_handle.setProperty("OutputLevel", msg().level() ));
ANA_CHECK( m_BJetSelectTool_handle.retrieve());
ANA_MSG_DEBUG("Retrieved tool: " << m_BJetSelectTool_handle);
// Configure the BJetEfficiencyCorrectionTool
if( m_getScaleFactors ) {
// initialize the BJetEfficiencyCorrectionTool
ANA_CHECK( m_BJetEffSFTool_handle.setProperty("TaggerName", m_taggerName ));
ANA_CHECK( m_BJetEffSFTool_handle.setProperty("SystematicsStrategy", m_systematicsStrategy));
ANA_CHECK( m_BJetEffSFTool_handle.setProperty("OperatingPoint", m_operatingPtCDI ));
ANA_CHECK( m_BJetEffSFTool_handle.setProperty("JetAuthor", m_jetAuthor ));
ANA_CHECK( m_BJetEffSFTool_handle.setProperty("MinPt", m_minPt ));
ANA_CHECK( m_BJetEffSFTool_handle.setProperty("ScaleFactorFileName", m_corrFileName ));
ANA_CHECK( m_BJetEffSFTool_handle.setProperty("UseDevelopmentFile", m_useDevelopmentFile ));
ANA_CHECK( m_BJetEffSFTool_handle.setProperty("ConeFlavourLabel", m_coneFlavourLabel ));
ANA_CHECK( m_BJetEffSFTool_handle.setProperty("OutputLevel", msg().level() ));
if(!m_EfficiencyCalibration.empty()){
std::string calibration=m_EfficiencyCalibration;
if(m_EfficiencyCalibration=="auto")
{
std::string gridName=wk()->metaData()->castString(SH::MetaFields::gridName);
HelperFunctions::ShowerType sampleShowerType=HelperFunctions::Unknown;
if(!gridName.empty())
{ // Do not trust sample name on the grid, in case there are multiple samples per job
std::stringstream ss(gridName);
std::string sampleName;
while(std::getline(ss,sampleName,','))
{
HelperFunctions::ShowerType mySampleShowerType=HelperFunctions::getMCShowerType(sampleName,m_taggerName);
if(mySampleShowerType!=sampleShowerType && sampleShowerType!=HelperFunctions::Unknown)
ANA_MSG_ERROR("Cannot have different shower types per grid task.");
sampleShowerType=mySampleShowerType;
}
}
else // Use sample name when running locally
{
gridName=wk()->metaData()->castString(SH::MetaFields::sampleName);
sampleShowerType=HelperFunctions::getMCShowerType(gridName,m_taggerName);
}
if(m_taggerName=="DL1dv01"){
if(m_isRun3){
switch(sampleShowerType)
{
case HelperFunctions::Pythia8:
calibration="601229";
break;
case HelperFunctions::Herwig7p2:
calibration="601414";
break;
case HelperFunctions::Sherpa2212:
calibration="700660";
break;
default:
if (m_allowCalibrationFallback) {
ANA_MSG_WARNING("Cannot determine MC shower type for sample " << gridName << ", falling back to 'default'.");
ANA_MSG_WARNING("Please double-check if this is appropriate for your sample, otherwise you have specify the MC-to-MC calibration manually!");
calibration="default";
break;
}
else {
ANA_MSG_ERROR("Cannot determine MC shower type for sample " << gridName << ".");
return EL::StatusCode::FAILURE;
break;
}
}
} else {
switch(sampleShowerType)
{
case HelperFunctions::Pythia8:
calibration="410470";
break;
case HelperFunctions::Herwig7p1:
calibration="411233";
break;
case HelperFunctions::Herwig7p2:
calibration="600666";
break;
case HelperFunctions::Sherpa221:
calibration="410250";
break;
case HelperFunctions::Sherpa2210:
calibration="700122";
break;
case HelperFunctions::Sherpa2212:
calibration="700660";
break;
case HelperFunctions::AmcPy8:
calibration="410464";
break;
case HelperFunctions::AmcH7:
calibration="412116";
break;
default:
if (m_allowCalibrationFallback) {
ANA_MSG_WARNING("Cannot determine MC shower type for sample " << gridName << ", falling back to 'default'.");
ANA_MSG_WARNING("Please double-check if this is appropriate for your sample, otherwise you have specify the MC-to-MC calibration manually!");
calibration="default";
break;
}
else {
ANA_MSG_ERROR("Cannot determine MC shower type for sample " << gridName << ".");
return EL::StatusCode::FAILURE;
break;
}
}
}
} else if(m_taggerName=="GN2v01"){
if(m_isRun3){
switch(sampleShowerType)
{
case HelperFunctions::Pythia8_517:
calibration="601398";
break;
case HelperFunctions::Pythia8:
calibration="601229";
break;
case HelperFunctions::Herwig7p2:
calibration="601414";
break;
case HelperFunctions::Sherpa2214:
calibration="700808";
break;
case HelperFunctions::Sherpa_Unknown:
ANA_MSG_WARNING("Unknown Sherpa version MC shower type for sample " << gridName << ", falling back to MC-MC SFs for Sherpa 2.2.11-2.2.16.");
ANA_MSG_WARNING("Please double-check if this is appropriate for your sample, otherwise you have specify the MC-to-MC calibration manually!");
calibration="700808";
break;
default:
if (m_allowCalibrationFallback) {
ANA_MSG_WARNING("Cannot determine MC shower type for sample " << gridName << ", falling back to 'default'.");
ANA_MSG_WARNING("Please double-check if this is appropriate for your sample, otherwise you have specify the MC-to-MC calibration manually!");
calibration="default";
break;
}
else {
ANA_MSG_ERROR("Cannot determine MC shower type for sample " << gridName << ".");
return EL::StatusCode::FAILURE;
break;
}
}
} else {
switch(sampleShowerType)
{
case HelperFunctions::Pythia8_517:
calibration="410480";
break;
case HelperFunctions::Pythia8:
calibration="410470";
break;
case HelperFunctions::Herwig7p1:
calibration="411233";
break;
case HelperFunctions::Herwig7p2:
calibration="600666";
break;
case HelperFunctions::Sherpa2214:
calibration="700660";
break;
case HelperFunctions::Sherpa_Unknown:
ANA_MSG_WARNING("Unknown Sherpa version MC shower type for sample " << gridName << ", falling back to MC-MC SFs for Sherpa 2.2.11-2.2.16.");
ANA_MSG_WARNING("Please double-check if this is appropriate for your sample, otherwise you have specify the MC-to-MC calibration manually!");
calibration="700660";
break;
default:
if (m_allowCalibrationFallback) {
ANA_MSG_WARNING("Cannot determine MC shower type for sample " << gridName << ", falling back to 'default'.");
ANA_MSG_WARNING("Please double-check if this is appropriate for your sample, otherwise you have specify the MC-to-MC calibration manually!");
calibration="default";
break;
}
else {
ANA_MSG_ERROR("Cannot determine MC shower type for sample " << gridName << ".");
return EL::StatusCode::FAILURE;
break;
}
}
}
} else {
if (m_allowCalibrationFallback) {
ANA_MSG_WARNING("Cannot determine MC shower type for tagger " << m_taggerName << ", only GN2v01 and DL1dv01 are supported. Falling back to 'default'.");
ANA_MSG_WARNING("Please double-check if this is appropriate for your sample and tagger, otherwise you have specify the MC-to-MC calibration manually!");
calibration="default";
} else {
ANA_MSG_ERROR("Cannot determine MC shower type for tagger " << m_taggerName << ".");
return EL::StatusCode::FAILURE;
}
}
} else { makeMCIndexMap(m_EfficiencyCalibration); }
ANA_CHECK( m_BJetEffSFTool_handle.setProperty("EfficiencyBCalibrations" , calibration));
ANA_CHECK( m_BJetEffSFTool_handle.setProperty("EfficiencyCCalibrations" , calibration));
ANA_CHECK( m_BJetEffSFTool_handle.setProperty("EfficiencyTCalibrations" , calibration));
ANA_CHECK( m_BJetEffSFTool_handle.setProperty("EfficiencyLightCalibrations", calibration));
}
ANA_CHECK( m_BJetEffSFTool_handle.setProperty("EigenvectorReductionB" , m_EigenvectorReductionB) );
ANA_CHECK( m_BJetEffSFTool_handle.setProperty("EigenvectorReductionC" , m_EigenvectorReductionC) );
ANA_CHECK( m_BJetEffSFTool_handle.setProperty("EigenvectorReductionLight" , m_EigenvectorReductionLight) );
ANA_CHECK( m_BJetEffSFTool_handle.retrieve());
ANA_MSG_DEBUG("Retrieved tool: " << m_BJetEffSFTool_handle);
} else {
ANA_MSG_WARNING( "Input operating point is not calibrated - no SFs will be obtained");
}
//
// Print out
//
if( !m_systName.empty() && m_getScaleFactors ) {
ANA_MSG_DEBUG("-----------------------------------------------------");
const std::map<CP::SystematicVariation, std::vector<std::string> > allowed_variations = m_BJetEffSFTool_handle->listSystematics();
ANA_MSG_DEBUG("Allowed systematics variations for tool " << m_BJetEffSFTool_handle.typeAndName() << ":");
for (auto var : allowed_variations) {
ANA_MSG_DEBUG(std::setw(40) << std::left << var.first.name() << ":");
for (auto flv : var.second) ANA_MSG_DEBUG("\t" << flv);
}
ANA_MSG_DEBUG("-----------------------------------------------------");
}
// Get a list of affecting systematics
if( m_getScaleFactors ) {
CP::SystematicSet affectSysts = m_BJetEffSFTool_handle->affectingSystematics();
// Convert into a simple list
std::vector<CP::SystematicSet> affectSystList = CP::make_systematics_vector(affectSysts);
if( !m_systName.empty() ) {
for ( const auto& syst_it : affectSystList ){
ANA_MSG_DEBUG(" tool can be affected by systematic: " << syst_it.name());
}
}
if( m_systName.empty() )
ANA_MSG_INFO(" Running w/ nominal configuration!");
// Get a list of recommended systematics
CP::SystematicSet recSyst = m_BJetEffSFTool_handle->recommendedSystematics();
m_systList = HelperFunctions::getListofSystematics( recSyst, m_systName, m_systVal, msg() );
}
if( m_runAllSyst ){
ANA_MSG_INFO(" Running w/ All systematics");
}
// Write output sys names
if ( m_writeSystToMetadata ) {
TFile *fileMD = wk()->getOutputFile ("metadata");
HelperFunctions::writeSystematicsListHist(m_systList, m_outputSystName, fileMD);
}
// Get DSID to Generator map (if needed)
if (m_setMapIndex){
ANA_MSG_DEBUG("Fill DSID->Generator map");
// open input file
std::ifstream file;
std::string fn = PathResolverFindCalibFile(m_DSIDtoGenerator_filename);
//file.open(gSystem->ExpandPathName(m_DSIDtoGenerator_filename.c_str()));
file.open(fn.c_str());
if (!file.good()) {
ANA_MSG_ERROR("Can't open file " << m_DSIDtoGenerator_filename.c_str());
return EL::StatusCode::FAILURE;
}
// process file
while (!file.eof()) {
// read line
std::string lineString;
getline(file, lineString);
// store in map
std::stringstream line(lineString);
int dsid;
std::string gen;
line >> dsid >> gen;
if (m_DSIDtoGenerator.count(dsid) != 0) {
ANA_MSG_WARNING("Skipping duplicated DSID for line " << lineString.c_str());
continue;
}
m_DSIDtoGenerator[dsid] = gen;
}
file.close();
}
ANA_MSG_INFO( "BJetEfficiencyCorrector Interface succesfully initialized!" );
return EL::StatusCode::SUCCESS;
}
EL::StatusCode BJetEfficiencyCorrector :: execute ()
{
ANA_MSG_DEBUG( "Applying BJetEfficiencyCorrector for " << m_taggerName << " tagger... ");
//
// retrieve event
//
const xAOD::EventInfo* eventInfo(nullptr);
ANA_CHECK( HelperFunctions::retrieve(eventInfo, m_eventInfoContainerName, m_event, m_store, msg()) );
ANA_MSG_DEBUG("\n\n eventNumber: " << eventInfo->eventNumber() << std::endl );
// if m_inputAlgo == "" --> input comes from xAOD, or just running one collection,
// then get the one collection and be done with it
std::vector<std::string>* systNames_ptr(nullptr);
if ( !m_inputAlgo.empty() ) ANA_CHECK( HelperFunctions::retrieve(systNames_ptr, m_inputAlgo, 0, m_store, msg()) );
std::vector<std::string> systNames{""};
if (systNames_ptr) systNames = *systNames_ptr;
// loop over systematic sets available
for ( const std::string& systName : systNames ) {
bool doNominal = (systName == "");
// input jets
const xAOD::JetContainer* inJets(nullptr);
// some systematics might have rejected the event
if ( m_store->contains<xAOD::JetContainer>( m_inContainerName+systName ) ) {
// Check the existence of the container
ANA_CHECK( HelperFunctions::retrieve(inJets, m_inContainerName+systName, m_event, m_store, msg()) );
ANA_CHECK( executeEfficiencyCorrection( inJets, eventInfo, doNominal ) );
}
}
ANA_MSG_DEBUG( "Leave Efficency Selection... ");
return EL::StatusCode::SUCCESS;
}
EL::StatusCode BJetEfficiencyCorrector :: executeEfficiencyCorrection(const xAOD::JetContainer* inJets,
const xAOD::EventInfo* eventInfo,
bool doNominal)
{
ANA_MSG_DEBUG("Applying BJet Cuts and Efficiency Correction (when applicable...) ");
SG::AuxElement::Decorator< char > dec_isBTag( m_decor );
SG::AuxElement::Decorator< std::vector<float> > dec_sfBTag( m_decorSF );
SG::AuxElement::Decorator< char > dec_isBTagOR( m_decor+"OR" );
// for continuous b-tagging only
SG::AuxElement::Decorator< float > dec_Weight( m_decorWeight );
SG::AuxElement::Decorator< int > dec_Quantile( m_decorQuantile );
//
// run the btagging decision or get weight and quantile if running continuous
//
for( const xAOD::Jet* jet_itr : *(inJets)){
if(abs(jet_itr->eta()) > 2.5){
if(!m_useContinuous){
dec_isBTag( *jet_itr ) = 0;
dec_isBTagOR( *jet_itr ) = 0;
}else{
dec_Quantile( *jet_itr ) = -1;
}
if(m_useContinuous || m_alwaysGetTagWeight) dec_Weight( *jet_itr) = 1;
continue;
}
if(!m_useContinuous){
// get tagging decision
ANA_MSG_DEBUG(" Getting tagging decision ");
// Add decorator for decision
if( m_BJetSelectTool_handle->accept( *jet_itr ) )
dec_isBTag( *jet_itr ) = 1;
else
dec_isBTag( *jet_itr ) = 0;
// Add pT-dependent b-tag decision decorator (intended for use in OR)
if ((m_orBJetPtUpperThres < 0 || m_orBJetPtUpperThres > (*jet_itr).pt()/1000.) // passes pT criteria
&& m_BJetSelectTool_handle->accept( *jet_itr ) )
dec_isBTagOR( *jet_itr ) = 1;
else
dec_isBTagOR( *jet_itr ) = 0;
}
else{
ANA_MSG_DEBUG(" Getting Quantile");
int quantile = m_BJetSelectTool_handle->getQuantile(*jet_itr);
ANA_MSG_DEBUG( "quantile: " << quantile );
dec_Quantile( *jet_itr ) = quantile;
}
if(m_useContinuous || m_alwaysGetTagWeight){
ANA_MSG_DEBUG(" Getting TaggerWeight");
double tagWeight;
if( m_BJetSelectTool_handle->getTaggerWeight( *jet_itr, tagWeight)!=CP::CorrectionCode::Ok ){
ANA_MSG_ERROR(" Error retrieving b-tagger weight ");
return EL::StatusCode::FAILURE;
}
ANA_MSG_DEBUG( "tagWeight: " << tagWeight );
dec_Weight( *jet_itr) = tagWeight;
}
}
//
// get the scale factors for all jets
//
if(m_getScaleFactors)
{ // loop over available systematics
for(const CP::SystematicSet& syst_it : m_systList)
{
// If not nominal input jet collection, dont calculate systematics
if ( !doNominal )
{
if( syst_it.name() != "" )
{ // if not nominal btag decision
ANA_MSG_DEBUG("Not running B-tag systematics when doing JES systematics");
continue;
}
}
// configure tool with syst variation
if (m_BJetEffSFTool_handle->applySystematicVariation(syst_it) != EL::StatusCode::SUCCESS)
{
ANA_MSG_ERROR( "Failed to configure BJetEfficiencyCorrections for systematic " << syst_it.name());
return EL::StatusCode::FAILURE;
}
ANA_MSG_DEBUG("Successfully configured BJetEfficiencyCorrections for systematic: " << syst_it.name());
for( const xAOD::Jet* jet_itr : *(inJets))
{
if(abs(jet_itr->eta()) > 2.5){
if(!dec_sfBTag.isAvailable( *jet_itr ))
dec_sfBTag ( *jet_itr ) = std::vector<float>({1.});
continue;
}
if(m_setMapIndex){ // select an efficiency map for use in MC/MC and inefficiency scale factors, based on user specified selection of efficiency maps
auto FlavLabel = getFlavorLabel(*jet_itr);
auto DSID = eventInfo->mcChannelNumber();
auto MCindex = getMCIndex(DSID);
ANA_CHECK( m_BJetEffSFTool_handle->setMapIndex(FlavLabel,MCindex));
}
// get the scale factor
float SF(-1.0);
CP::CorrectionCode BJetEffCode;
// if passes cut take the efficiency scale factor
// if failed cut take the inefficiency scale factor
// for continuous take efficiency, as inefficiency should not be used
if(m_useContinuous)
{
BJetEffCode = m_BJetEffSFTool_handle->getScaleFactor( *jet_itr, SF );
}
else
{
if( dec_isBTag( *jet_itr ) )
BJetEffCode = m_BJetEffSFTool_handle->getScaleFactor( *jet_itr, SF );
else
BJetEffCode = m_BJetEffSFTool_handle->getInefficiencyScaleFactor( *jet_itr, SF );
}
if (BJetEffCode == CP::CorrectionCode::Error)
{
ANA_MSG_ERROR( "Error in getEfficiencyScaleFactor");
return EL::StatusCode::FAILURE;
}
else if (BJetEffCode == CP::CorrectionCode::OutOfValidityRange)
{
ANA_MSG_DEBUG( "Jet is out of validity range");
}
// Save it to the vector
if( !dec_sfBTag .isAvailable( *jet_itr ))
dec_sfBTag ( *jet_itr ) = std::vector<float>();
dec_sfBTag( *jet_itr ).push_back(SF);
}
}
}
else
{
for( const xAOD::Jet* jet_itr : *(inJets))
{
if( !dec_sfBTag .isAvailable( *jet_itr ))
dec_sfBTag ( *jet_itr ) = std::vector<float>({1.});
}
}
//
// Store list of available systematics
//
if(doNominal){
auto sysVariationNames = std::make_unique< std::vector< std::string > >();
if(m_getScaleFactors) {
for(const auto& syst_it : m_systList)
sysVariationNames->push_back(syst_it.name());
}
else {
sysVariationNames->push_back("");
}
ANA_MSG_DEBUG("Size is " << sysVariationNames->size());
for(auto sysName : *sysVariationNames) ANA_MSG_DEBUG(sysName);
ANA_CHECK( m_store->record( std::move(sysVariationNames), m_outputSystName));
}
return EL::StatusCode::SUCCESS;
}
EL::StatusCode BJetEfficiencyCorrector :: postExecute ()
{
ANA_MSG_DEBUG("Calling postExecute");
return EL::StatusCode::SUCCESS;
}
EL::StatusCode BJetEfficiencyCorrector :: finalize ()
{
return EL::StatusCode::SUCCESS;
}
EL::StatusCode BJetEfficiencyCorrector :: histFinalize ()
{
ANA_MSG_INFO( "Calling histFinalize");
ANA_CHECK( xAH::Algorithm::algFinalize());
return EL::StatusCode::SUCCESS;
}
void BJetEfficiencyCorrector :: makeMCIndexMap (std::string effCalib)
{
ANA_MSG_DEBUG( "Calling makeMCIndexMap()");
// Interprete m_EfficiencyCalibration string to identify the corresponding indexes
char delim = ';';
std::vector<std::string> samples;
std::stringstream ss(effCalib);
std::string item;
while (std::getline(ss, item, delim)) {
samples.push_back(item);
}
// Find index for Pythia8, Sherpa 2.2, Herwig7 and aMC@NLO+Pythia8
for (unsigned int i = 0; i < samples.size(); ++i){
if (samples.at(i) == "410470") m_MCIndexes["Pythia8"] = i;
if (samples.at(i) == "700122") m_MCIndexes["Sherpa2210"] = i;
if (samples.at(i) == "410250") m_MCIndexes["Sherpa22"] = i;
if (samples.at(i) == "600666") m_MCIndexes["Herwig721"] = i;
if (samples.at(i) == "410558") m_MCIndexes["Herwig7"] = i;
if (samples.at(i) == "410464") m_MCIndexes["aMC@NLO"] = i;
}
}
unsigned int BJetEfficiencyCorrector :: getMCIndex (int dsid)
{
ANA_MSG_DEBUG( "Calling getMCIndex");
auto name = m_DSIDtoGenerator[dsid];
if(m_EfficiencyCalibration=="auto") {
return 0; // there is only one index when m_EfficiencyCalibration == 'auto'
} else {
// Pythia 8
if ((name.find("Pythia8_") != std::string::npos) ||
(name.find("Pythia8B_") != std::string::npos) ||
(name.find("MGPy8EG_") != std::string::npos) ||
(name.find("MadGraphPythia8_") != std::string::npos) ||
(name.find("MadGraphPythia8EvtGen_") != std::string::npos) ||
(name.find("PowhegPythia8EvtGen_CT10_") != std::string::npos) ||
(name.find("PowhegPythia8EvtGen_") != std::string::npos) ||
(name.find("Pythia8EvtGen_") != std::string::npos) ||
(name.find("Pythia8EG_") != std::string::npos) ||
(name.find("PwPy8EG_CT10_") != std::string::npos) ||
(name.find("PowhegPythia8_") != std::string::npos) ||
(name.find("PowhegPythia8EG_") != std::string::npos) ||
(name.find("PhPy8EG_CT10_") != std::string::npos) ||
(name.find("Py8EG_") != std::string::npos) ||
(name.find("Py8") != std::string::npos)) { return m_MCIndexes["Pythia8"]; }
// Sherpa 2.2.10
if ((name.find("Sh_2210") != std::string::npos)){ return m_MCIndexes["Sherpa2210"]; }
// Sherpa 2.2.11
if ((name.find("Sh_2211") != std::string::npos)){ return m_MCIndexes["Sherpa2210"]; } // MC-MC SFs from Sherpa 2.2.10 is the best we can use for Sherpa 2.2.11 (for now)
// Sherpa 2.2
if ((name.find("Sh_22") != std::string::npos) ||
(name.find("Sherpa_NNPDF30NNLO") != std::string::npos) ||
(name.find("Sherpa_221_NNPDF30NNLO") != std::string::npos)){ return m_MCIndexes["Sherpa22"]; }
// Herwig 7.2.1
if ( (name.find("Herwig721") != std::string::npos) ){ return m_MCIndexes["Herwig721"]; }
// Herwig 7
if ( (name.find("Herwig") != std::string::npos) ){ return m_MCIndexes["Herwig"]; }
// aMC@NLO+Pythia8
if ( (name.find("aMC@NLO+Pythia8") != std::string::npos) ){ return m_MCIndexes["aMC@NLO"]; }
// for all other samples, use the default map (pythia8).
ANA_MSG_WARNING( "MC index not recognized, using default (0)." );
return 0;
}
}
std::string BJetEfficiencyCorrector :: getFlavorLabel (const xAOD::Jet &jet) const
{
int label;
bool status = jet.getAttribute<int>( "HadronConeExclTruthLabelID", label );
if(status){
if ((label == 5) || (label == -5)){ return "B";
} else if ((label == 4) || (label == -4)){ return "C";
} else if ((label == 15) || (label == -15)){ return "T";
} else { return "Light";}
} else {
ANA_MSG_WARNING( "HadronConeExclTruthLabelID was not found, using Light as jet flavour for retrieving b-tagging SF." );
return "Light";
}
}