Program Listing for File JetCalibrator.cxx¶
↰ Return to documentation for file (Root/JetCalibrator.cxx
)
/******************************************
*
* Interface to Jet calibration tool(s).
*
* G.Facini (gabriel.facini@cern.ch), M. Milesi (marco.milesi@cern.ch), J. Dandoy (jeff.dandoy@cern.ch)
*
*
******************************************/
// c++ include(s):
#include <iostream>
// EL include(s):
#include <EventLoop/Job.h>
#include <EventLoop/StatusCode.h>
#include <EventLoop/Worker.h>
// EDM include(s):
#include "xAODMuon/MuonContainer.h"
#include "xAODJet/JetContainer.h"
#include "xAODJet/Jet.h"
#include "xAODBase/IParticleHelpers.h"
#include "xAODBase/IParticleContainer.h"
#include "xAODBase/IParticle.h"
#include "AthContainers/ConstDataVector.h"
#include "AthContainers/DataVector.h"
#include "xAODCore/ShallowCopy.h"
// package include(s):
#include "xAODAnaHelpers/HelperFunctions.h"
#include "xAODAnaHelpers/JetCalibrator.h"
// ROOT includes:
#include "TSystem.h"
// tools
#include "JetCalibTools/JetCalibrationTool.h"
#include "JetUncertainties/JetUncertaintiesTool.h"
#include "JetSelectorTools/JetCleaningTool.h"
// #include "JetTileCorrection/JetTileCorrectionTool.h"
#include "METUtilities/METHelpers.h"
// this is needed to distribute the algorithm to the workers
ClassImp(JetCalibrator)
JetCalibrator :: JetCalibrator () :
Algorithm("JetCalibrator")
{
}
EL::StatusCode JetCalibrator :: setupJob (EL::Job& job)
{
// Here you put code that sets up the job on the submission object
// so that it is ready to work with your algorithm, e.g. you can
// request the D3PDReader service or add output files. Any code you
// put here could instead also go into the submission script. The
// sole advantage of putting it here is that it gets automatically
// activated/deactivated when you add/remove the algorithm from your
// job, which may or may not be of value to you.
ANA_MSG_INFO( "Calling setupJob");
job.useXAOD ();
xAOD::Init( "JetCalibrator" ).ignore(); // call before opening first file
return EL::StatusCode::SUCCESS;
}
EL::StatusCode JetCalibrator :: histInitialize ()
{
// Here you do everything that needs to be done at the very
// beginning on each worker node, e.g. create histograms and output
// trees. This method gets called before any input files are
// connected.
ANA_CHECK( xAH::Algorithm::algInitialize());
return EL::StatusCode::SUCCESS;
}
EL::StatusCode JetCalibrator :: fileExecute ()
{
// Here you do everything that needs to be done exactly once for every
// single file, e.g. collect a list of all lumi-blocks processed
return EL::StatusCode::SUCCESS;
}
EL::StatusCode JetCalibrator :: changeInput (bool /*firstFile*/)
{
// Here you do everything you need to do when we change input files,
// e.g. resetting branch addresses on trees. If you are using
// D3PDReader or a similar service this method is not needed.
return EL::StatusCode::SUCCESS;
}
EL::StatusCode JetCalibrator :: initialize ()
{
// Here you do everything that you need to do after the first input
// file has been connected and before the first event is processed,
// e.g. create additional histograms based on which variables are
// available in the input files. You can also create all of your
// histograms and trees in here, but be aware that this method
// doesn't get called if no events are processed. So any objects
// you create here won't be available in the output if you have no
// input events.
ANA_MSG_INFO( "Initializing JetCalibrator Interface... ");
m_runSysts = false; //Ensure this starts false
m_event = wk()->xaodEvent();
m_store = wk()->xaodStore();
ANA_MSG_INFO( "Number of events in file: " << m_event->getEntries() );
// If there is no InputContainer we must stop
if ( m_inContainerName.empty() ) {
ANA_MSG_ERROR( "InputContainer is empty!");
return EL::StatusCode::FAILURE;
}
if ( m_jetAlgo.empty() ) {
m_jetAlgo = m_inContainerName;
std::string jets = "Jets";
std::string::size_type i = m_jetAlgo.find(jets);
if (i != std::string::npos) {
m_jetAlgo.erase(i, jets.length());
}
}
if ( m_outputAlgo.empty() ) {
m_outputAlgo = m_jetAlgo + "_Calib_Algo";
}
m_numEvent = 0;
m_numObject = 0;
if( isMC() && m_calibSequence.find("_Insitu") != std::string::npos){
ANA_MSG_ERROR( "Attempting to use an Insitu calibration sequence on MC. Exiting.");
return EL::StatusCode::FAILURE;
}
if( !isMC() && m_calibSequence.find("_Smear") != std::string::npos){
ANA_MSG_ERROR( "Attempting to use an Smear calibration sequence on data. Exiting.");
return EL::StatusCode::FAILURE;
}
if ( !isMC() ) {
// Insitu should not be applied to the trimmed jets, per Jet/Etmiss recommendation
if ( m_forceInsitu && m_calibSequence.find("Insitu") == std::string::npos) m_calibSequence += "_Insitu";
m_calibConfig = m_calibConfigData;
} else {
if ( isFastSim() ) {
m_calibConfig = m_calibConfigAFII;
} else {
m_calibConfig = m_calibConfigFullSim;
// Insitu should not be applied to the trimmed jets, per Jet/Etmiss recommendation
if ( m_forceSmear && m_calibSequence.find("Smear") == std::string::npos) m_calibSequence += "_Smear";
}
}
if(!isFastSim() && m_uncertMCType.empty() && !m_uncertConfig.empty()){
ANA_MSG_ERROR("MCType not provided, please set m_uncertMCType (MC20 or MC21) when running on FullSim samples. Exiting.");
return EL::StatusCode::FAILURE;
}
// Autoconfigure calibration sequence if the user didn't do it.
// Recommended strings taken from ApplyJetCalibrationR21 Twiki.
if(m_calibSequence.empty()){
// Standard R=0.4 jets
if(m_inContainerName.find("AntiKt4EM") != std::string::npos){
if( !isMC() ) m_calibSequence = "JetArea_Residual_EtaJES_GSC_Insitu";
else if( isFastSim() ) m_calibSequence = "JetArea_Residual_EtaJES_GSC";
else /*FullSim*/ m_calibSequence = "JetArea_Residual_EtaJES_GSC_Smear";
}
// R-scan jets
else if(m_inContainerName.find("AntiKt2LCTopo") != std::string::npos ||
m_inContainerName.find("AntiKt6LCTopo") != std::string::npos)
m_calibSequence = "JetArea_Residual_EtaJES_GSC";
// R=1.0 jets
else if(m_inContainerName.find("AntiKt10LCTopo") != std::string::npos ||
m_inContainerName.find("AntiKt10TrackCaloCluster") != std::string::npos)
m_calibSequence = "EtaJES_JMS";
// Anything else is unrecognized
else{
ANA_MSG_ERROR( "Cannot autoconfigure jet calibration sequence for collection " << m_systName);
ANA_MSG_ERROR( "JetCalibrator::m_calibSequence needs to be set manually in configuration.");
return EL::StatusCode::FAILURE;
}
}
// Warn user if they're running standard jets without in-situ in data or smearing in MC
if(m_inContainerName.find("AntiKt4EM") != std::string::npos){
if(!isMC()){
if(m_calibSequence.find("_Insitu") == std::string::npos){
ANA_MSG_WARNING("Calibrating AntiKt4EM jets in data without the in-situ step. This is not recommended, make sure it's really what you want!");
}
} else { // MC
if(!isFastSim() && m_calibSequence.find("_Smear") == std::string::npos){
ANA_MSG_WARNING("Calibrating AntiKt4EM jets in fullsim without the smearing step. This is not recommended, make sure it's really what you want!");
}
}
}
// initialize jet calibration tool
ANA_CHECK( ASG_MAKE_ANA_TOOL(m_JetCalibrationTool_handle, JetCalibrationTool));
ANA_CHECK( m_JetCalibrationTool_handle.setProperty("JetCollection",m_jetAlgo));
if(!m_calibConfigDir.empty()){
ANA_CHECK( m_JetCalibrationTool_handle.setProperty("ConfigDir",m_calibConfigDir));
}
ANA_CHECK( m_JetCalibrationTool_handle.setProperty("ConfigFile",m_calibConfig));
ANA_CHECK( m_JetCalibrationTool_handle.setProperty("CalibSequence",m_calibSequence));
if ( !m_overrideCalibArea.empty() ) {
ANA_MSG_WARNING("Overriding jet calibration area to " << m_overrideCalibArea);
ANA_CHECK( m_JetCalibrationTool_handle.setProperty("CalibArea", m_overrideCalibArea));
}
ANA_CHECK( m_JetCalibrationTool_handle.setProperty("IsData",!isMC()));
ANA_CHECK( m_JetCalibrationTool_handle.setProperty("OutputLevel", msg().level()));
if ( m_jetCalibToolsDEV ) {
ANA_CHECK( m_JetCalibrationTool_handle.setProperty("DEVmode", m_jetCalibToolsDEV));
}
if (!m_calibGSCDepth.empty() && m_calibSequence.find("GSC") != std::string::npos) {
ANA_MSG_WARNING("Using modified GSCDepth property for jet calibration '" << m_calibGSCDepth << "' which will override config file value");
ANA_CHECK( m_JetCalibrationTool_handle.setProperty("GSCDepth", m_calibGSCDepth));
}
// HLT jet re-calibration configuration
if (m_recalibrateHLTJets) {
ANA_CHECK( m_JetCalibrationTool_handle.setProperty("UseHLTEventShape", true) );
// Note: PrimaryVerticesContainerName is actually a private ReadHandleKey, but we can set its value via the setProperty method
ANA_CHECK( m_JetCalibrationTool_handle.setProperty("PrimaryVerticesContainerName", m_HLTVertexContainerName) );
ANA_CHECK( m_JetCalibrationTool_handle.setProperty("averageInteractionsPerCrossingKey", m_HLTAvgMuDecor) );
if (m_EvtInfoHLTNPVDecor != "") {
ANA_CHECK( m_JetCalibrationTool_handle.setProperty("UseNPVFromEventInfo", true) );
ANA_CHECK( m_JetCalibrationTool_handle.setProperty("NPVKey", m_EvtInfoHLTNPVDecor) );
}
}
ANA_CHECK( m_JetCalibrationTool_handle.retrieve());
ANA_MSG_DEBUG("Retrieved tool: " << m_JetCalibrationTool_handle);
// initialize jet tile correction tool
// if(m_doJetTileCorr && !isMC()){ // Jet Tile Correction should only be applied to data
// ANA_CHECK( ASG_MAKE_ANA_TOOL(m_JetTileCorrectionTool_handle, CP::JetTileCorrectionTool));
// ANA_CHECK( m_JetTileCorrectionTool_handle.setProperty("OutputLevel", msg().level()));
// ANA_CHECK( m_JetTileCorrectionTool_handle.retrieve());
// ANA_MSG_DEBUG("Retrieved tool: " << m_JetTileCorrectionTool_handle);
// }
if(m_doCleaning){
// initialize and configure the jet cleaning tool
//------------------------------------------------
ANA_CHECK( m_JetCleaningTool_handle.setProperty( "CutLevel", m_jetCleanCutLevel));
ANA_CHECK( m_JetCleaningTool_handle.setProperty( "DoUgly", m_jetCleanUgly));
ANA_CHECK( m_JetCleaningTool_handle.setProperty( "OutputLevel", msg().level() ));
ANA_CHECK( m_JetCleaningTool_handle.retrieve());
ANA_MSG_DEBUG("Retrieved tool: " << m_JetCleaningTool_handle);
if( m_saveAllCleanDecisions ){
m_decisionNames.push_back( "LooseBad" );
m_decisionNames.push_back( "LooseBadUgly" );
m_decisionNames.push_back( "LooseBadTrigger" );
m_decisionNames.push_back( "LooseBadLLP" );
m_decisionNames.push_back( "TightBad" );
m_decisionNames.push_back( "TightBadUgly" );
for(unsigned int iD=0; iD < m_decisionNames.size() ; ++iD){
asg::AnaToolHandle<IJetSelector> this_JetCleaningTool_handle("JetCleaningTool/JetCleaningTool_"+m_decisionNames.at(iD), this);
if( m_decisionNames.at(iD).find("Ugly") != std::string::npos ){
ANA_CHECK( this_JetCleaningTool_handle.setProperty( "CutLevel", m_decisionNames.at(iD).substr(0,m_decisionNames.at(iD).size()-4) ));
ANA_CHECK( this_JetCleaningTool_handle.setProperty( "DoUgly", true));
}else{
ANA_CHECK( this_JetCleaningTool_handle.setProperty( "CutLevel", m_decisionNames.at(iD) ));
}
ANA_CHECK( this_JetCleaningTool_handle.setProperty( "OutputLevel", msg().level() ));
ANA_CHECK( this_JetCleaningTool_handle.retrieve());
ANA_MSG_DEBUG("Retrieved tool: " << this_JetCleaningTool_handle);
m_AllJetCleaningTool_handles.push_back( this_JetCleaningTool_handle );
}// For each cleaning decision
}//If save all cleaning decisions
}// if m_doCleaning
// initialize largeR jet truth labelling tool
if(isMC() && m_useLargeRTruthLabelingTool && m_inContainerName.find("AntiKt10") != std::string::npos){
// Truth labelling is required for systematics on largeR jets.
// TruthLabelName typically should not be changed until new recommendations are available
// The other properties have default values but need to be configured by the user
// ANA_CHECK(m_JetTruthLabelingTool_handle.setProperty("TruthLabelName" , m_truthLabelName));
// ANA_CHECK(m_JetTruthLabelingTool_handle.setProperty("IsTruthJetCollection" , m_isTruthJetCol));
// ANA_CHECK(m_JetTruthLabelingTool_handle.setProperty("UseTRUTH3" , m_useTRUTH3));
// ANA_CHECK(m_JetTruthLabelingTool_handle.setProperty("TruthParticleContainerName" , m_truthParticleContainerName));
// ANA_CHECK(m_JetTruthLabelingTool_handle.setProperty("TruthBosonContainerName" , m_truthBosonContainerName));
// ANA_CHECK(m_JetTruthLabelingTool_handle.setProperty("TruthTopQuarkContainerName" , m_truthTopQuarkContainerName));
// ANA_CHECK(m_JetTruthLabelingTool_handle.setProperty("OutputLevel" , msg().level()));
// ANA_CHECK(m_JetTruthLabelingTool_handle.retrieve());
}// if MC && largeR
// Generate nominal systematic
const CP::SystematicSet recSyst = CP::SystematicSet();;
m_systList = HelperFunctions::getListofSystematics( recSyst, "", 0, msg() ); // Generate nominal
// initialize and configure the jet uncertainity tool
// only initialize if a config file has been given
//------------------------------------------------
if ( !m_uncertConfig.empty() && !m_systName.empty() && m_systName != "None" ) {
if(m_mcAndPseudoData){
ANA_MSG_INFO("Input treated as MC AND pseudo-data. JER uncertainties will be run twice.");
initializeUncertaintiesTool(m_JetUncertaintiesTool_handle, false);
// Need a second uncertainties tool to handle the pseudodata smearing
initializeUncertaintiesTool(m_pseudodataJERTool_handle, true);
}
else if(m_pseudoData) {
ANA_MSG_INFO("Input treated as pseudo-data");
initializeUncertaintiesTool(m_JetUncertaintiesTool_handle, true);
}
else {
initializeUncertaintiesTool(m_JetUncertaintiesTool_handle, !isMC());
}
//
// Get a list of recommended systematics for this tool
//
ANA_MSG_INFO(" Initializing Jet Systematics :");
const CP::SystematicSet recSysts = m_JetUncertaintiesTool_handle->recommendedSystematics();
//If just one systVal, then push it to the vector
ANA_CHECK( this->parseSystValVector());
if( m_systValVector.size() == 0) {
ANA_MSG_DEBUG("Pushing the following systVal to m_systValVector: " << m_systVal );
m_systValVector.push_back(m_systVal);
}
for(unsigned int iSyst=0; iSyst < m_systValVector.size(); ++iSyst){
std::vector<CP::SystematicSet> sysList = HelperFunctions::getListofSystematics( recSysts, m_systName, m_systValVector.at(iSyst), msg() );
for(unsigned int i=0; i < sysList.size(); ++i){
// do not add another nominal syst to the list!!
// CP::SystematicSet() creates an empty systematic set, compared to the set at index i
if (sysList.at(i).empty() || sysList.at(i) == CP::SystematicSet() ) { ANA_MSG_INFO("sysList Empty at index " << i); continue; }
m_systList.push_back( sysList.at(i) );
}
}
// Setup the tool for the 1st systematic on the list
// If running all, the tool will be setup for each syst on each event
if ( !m_systList.empty() ) {
m_runSysts = true;
// setup uncertainity tool for systematic evaluation
if ( m_JetUncertaintiesTool_handle->applySystematicVariation(m_systList.at(0)) != EL::StatusCode::SUCCESS ) {
ANA_MSG_ERROR( "Cannot configure JetUncertaintiesTool for systematic " << m_systName);
return EL::StatusCode::FAILURE;
}
}
} // running systematics
else {
ANA_MSG_INFO( "No Jet Uncertainities considered");
}
auto SystJetsNames = std::make_unique< std::vector< std::string > >();
for ( const auto& syst_it : m_systList ) {
if ( m_systName.empty() && m_systName.empty() ) {
ANA_MSG_INFO("\t Running w/ nominal configuration only!");
break;
}
SystJetsNames->push_back(syst_it.name());
ANA_MSG_INFO("\t " << syst_it.name());
}
ANA_CHECK(m_store->record(std::move(SystJetsNames), "jets_Syst"+m_name ));
// Write output sys names
if ( m_writeSystToMetadata ) {
TFile *fileMD = wk()->getOutputFile ("metadata");
HelperFunctions::writeSystematicsListHist(m_systList, m_name, fileMD);
}
ANA_MSG_INFO( "JetCalibrator Interface succesfully initialized!" );
return EL::StatusCode::SUCCESS;
}
EL::StatusCode JetCalibrator :: execute ()
{
// Here you do everything that needs to be done on every single
// events, e.g. read input variables, apply cuts, and fill
// histograms and trees. This is where most of your actual analysis
// code will go.
ANA_MSG_DEBUG("Applying Jet Calibration and Cleaning... ");
m_numEvent++;
// get the collection from TEvent or TStore
const xAOD::JetContainer* inJets(nullptr);
ANA_CHECK( HelperFunctions::retrieve(inJets, m_inContainerName, m_event, m_store, msg()) );
//
// Perform nominal calibration
std::pair< xAOD::JetContainer*, xAOD::ShallowAuxContainer* > calibJetsSC = xAOD::shallowCopyContainer( *inJets );
if ( m_addGhostMuonsToJets ) {
ANA_MSG_VERBOSE("Run muon-to-jet ghost association");
const xAOD::MuonContainer* muons(nullptr);
ANA_CHECK( HelperFunctions::retrieve(muons, "Muons", m_event, m_store, msg()) );
met::addGhostMuonsToJets( *muons, *calibJetsSC.first );
}
std::string outSCContainerName=m_outContainerName+"ShallowCopy";
std::string outSCAuxContainerName=m_outContainerName+"ShallowCopyAux.";
ANA_CHECK( m_store->record( calibJetsSC.first, outSCContainerName));
ANA_CHECK( m_store->record( calibJetsSC.second, outSCAuxContainerName));
for ( auto jet_itr : *(calibJetsSC.first) ) {
m_numObject++;
//
// truth labelling for systematics
if(isMC()){
if(m_runSysts){
// b-jet truth labelling
int this_TruthLabel = 0;
static SG::AuxElement::ConstAccessor<int> TruthLabelID ("TruthLabelID");
static SG::AuxElement::ConstAccessor<int> PartonTruthLabelID ("PartonTruthLabelID");
if ( TruthLabelID.isAvailable( *jet_itr) ) {
this_TruthLabel = TruthLabelID( *jet_itr );
if (this_TruthLabel == 21 || this_TruthLabel<4) this_TruthLabel = 0;
} else if(PartonTruthLabelID.isAvailable( *jet_itr) ) {
this_TruthLabel = PartonTruthLabelID( *jet_itr );
if (this_TruthLabel == 21 || this_TruthLabel<4) this_TruthLabel = 0;
}
bool isBjet = false; // decide whether or not the jet is a b-jet (truth-labelling + kinematic selections)
if (this_TruthLabel == 5) isBjet = true;
static SG::AuxElement::Decorator<char> accIsBjet("IsBjet"); // char due to limitations of ROOT I/O, still treat it as a bool
accIsBjet(*jet_itr) = isBjet;
}
if(m_useLargeRTruthLabelingTool){
static SG::AuxElement::ConstAccessor<int> JetTruthLabel (m_truthLabelName);
// largeR jet truth labelling
// if(m_JetTruthLabelingTool_handle.isInitialized() && !JetTruthLabel.isAvailable(*jet_itr)) {
// m_JetTruthLabelingTool_handle->modifyJet(*jet_itr);
// }
}
}
}//for jets
// Apply the calibration
if ( m_JetCalibrationTool_handle->applyCalibration( *(calibJetsSC.first) ) == EL::StatusCode::FAILURE ) {
ANA_MSG_ERROR( "JetCalibration tool reported a EL::StatusCode::FAILURE");
ANA_MSG_ERROR( m_name );
return StatusCode::FAILURE;
}
// Need to be adapted to use full jet container (once tool works in R22)
// if(m_doJetTileCorr && !isMC()){
// if( m_JetTileCorrectionTool_handle->applyCorrection(*jet_itr) == CP::CorrectionCode::Error ){
// ANA_MSG_ERROR( "JetTileCorrection tool reported a CP::CorrectionCode::Error");
// }
// }
// loop over available systematics - remember syst == "Nominal" --> baseline
auto vecOutContainerNames = std::make_unique< std::vector< std::string > >();
for ( const auto& syst_it : m_systList ) {
executeSystematic(syst_it, inJets, calibJetsSC, *vecOutContainerNames, false);
if(m_mcAndPseudoData && std::string(syst_it.name()).find("JER") != std::string::npos) {
// This is a JER uncertainty that also needs a pseudodata copy done.
executeSystematic(syst_it, inJets, calibJetsSC, *vecOutContainerNames, true);
}
}
// add vector of systematic names to TStore
ANA_CHECK( m_store->record( std::move(vecOutContainerNames), m_outputAlgo));
// look what do we have in TStore
if(msgLvl(MSG::VERBOSE)) m_store->print();
return EL::StatusCode::SUCCESS;
}
EL::StatusCode JetCalibrator :: postExecute ()
{
// Here you do everything that needs to be done after the main event
// processing. This is typically very rare, particularly in user
// code. It is mainly used in implementing the NTupleSvc.
ANA_MSG_DEBUG("Calling postExecute");
return EL::StatusCode::SUCCESS;
}
EL::StatusCode JetCalibrator :: finalize ()
{
// This method is the mirror image of initialize(), meaning it gets
// called after the last event has been processed on the worker node
// and allows you to finish up any objects you created in
// initialize() before they are written to disk. This is actually
// fairly rare, since this happens separately for each worker node.
// Most of the time you want to do your post-processing on the
// submission node after all your histogram outputs have been
// merged. This is different from histFinalize() in that it only
// gets called on worker nodes that processed input events.
return EL::StatusCode::SUCCESS;
}
EL::StatusCode JetCalibrator :: histFinalize ()
{
// This method is the mirror image of histInitialize(), meaning it
// gets called after the last event has been processed on the worker
// node and allows you to finish up any objects you created in
// histInitialize() before they are written to disk. This is
// actually fairly rare, since this happens separately for each
// worker node. Most of the time you want to do your
// post-processing on the submission node after all your histogram
// outputs have been merged. This is different from finalize() in
// that it gets called on all worker nodes regardless of whether
// they processed input events.
ANA_MSG_INFO( "Calling histFinalize");
ANA_CHECK( xAH::Algorithm::algFinalize());
return EL::StatusCode::SUCCESS;
}
EL::StatusCode JetCalibrator::executeSystematic(const CP::SystematicSet& thisSyst, const xAOD::JetContainer* inJets,
std::pair<xAOD::JetContainer*, xAOD::ShallowAuxContainer*>& calibJetsSC,
std::vector<std::string>& vecOutContainerNames, bool isPDCopy){
bool nominal = thisSyst.name().empty();
std::string outSCContainerName, outSCAuxContainerName, outContainerName;
asg::AnaToolHandle<ICPJetUncertaintiesTool>* jetUncTool(nullptr);
// always append the name of the variation, including nominal which is an empty string
if(isPDCopy){
outSCContainerName = m_outContainerName+thisSyst.name()+"_PDShallowCopy";
outSCAuxContainerName = m_outContainerName+thisSyst.name()+"_PDShallowCopyAux.";
outContainerName = m_outContainerName+thisSyst.name()+"_PD";
vecOutContainerNames.push_back(thisSyst.name()+"_PD");
jetUncTool = &m_pseudodataJERTool_handle;
}
else{
outSCContainerName = m_outContainerName+thisSyst.name()+"ShallowCopy";
outSCAuxContainerName = m_outContainerName+thisSyst.name()+"ShallowCopyAux.";
outContainerName = m_outContainerName+thisSyst.name();
vecOutContainerNames.push_back(thisSyst.name());
jetUncTool = &m_JetUncertaintiesTool_handle;
}
// create shallow copy;
std::pair< xAOD::JetContainer*, xAOD::ShallowAuxContainer* > uncertCalibJetsSC = nominal ? calibJetsSC : xAOD::shallowCopyContainer(*calibJetsSC.first);
ConstDataVector<xAOD::JetContainer>* uncertCalibJetsCDV = new ConstDataVector<xAOD::JetContainer>(SG::VIEW_ELEMENTS);
uncertCalibJetsCDV->reserve( uncertCalibJetsSC.first->size() );
//Apply Uncertainties
if ( m_runSysts ) {
// Jet Uncertainty Systematic
ANA_MSG_DEBUG("Configure for systematic variation : " << thisSyst.name());
if ( (*jetUncTool)->applySystematicVariation(thisSyst) != EL::StatusCode::SUCCESS ) {
ANA_MSG_ERROR( "Cannot configure JetUncertaintiesTool for systematic " << m_systName);
return EL::StatusCode::FAILURE;
}
for ( auto jet_itr : *(uncertCalibJetsSC.first) ) {
if (m_applyFatJetPreSel) {
bool validForJES = (jet_itr->pt() >= 150e3 && jet_itr->pt() < 3000e3);
validForJES &= (jet_itr->m()/jet_itr->pt() >= 0 && jet_itr->m()/jet_itr->pt() < 1);
validForJES &= (fabs(jet_itr->eta()) < 2);
if (!validForJES) continue;
}
if ( (*jetUncTool)->applyCorrection( *jet_itr ) == CP::CorrectionCode::Error ) {
ANA_MSG_ERROR( "JetUncertaintiesTool reported a CP::CorrectionCode::Error");
ANA_MSG_ERROR( m_name );
}
}
}// if m_runSysts
if(m_doCleaning){
// decorate with cleaning decision
for ( auto jet_itr : *(uncertCalibJetsSC.first) ) {
static SG::AuxElement::Decorator< int > isCleanDecor( "cleanJet" );
const xAOD::Jet* jetToClean = jet_itr;
if(m_cleanParent){
ElementLink<xAOD::JetContainer> el_parent = jet_itr->auxdata<ElementLink<xAOD::JetContainer> >("Parent") ;
if(!el_parent.isValid())
ANA_MSG_ERROR( "Could not make jet cleaning decision on the parent! It doesn't exist.");
else
jetToClean = *el_parent;
}
isCleanDecor(*jet_itr) = m_JetCleaningTool_handle->keep(*jetToClean);
if( m_saveAllCleanDecisions ){
for(unsigned int i=0; i < m_AllJetCleaningTool_handles.size() ; ++i){
jet_itr->auxdata< int >(("clean_pass"+m_decisionNames.at(i)).c_str()) = m_AllJetCleaningTool_handles.at(i)->keep(*jetToClean);
}
}
} //end cleaning decision
}
if ( !xAOD::setOriginalObjectLink(*inJets, *(uncertCalibJetsSC.first)) ) {
ANA_MSG_ERROR( "Failed to set original object links -- MET rebuilding cannot proceed.");
}
// save pointers in ConstDataVector with same order
for ( auto jet_itr : *(uncertCalibJetsSC.first) ) {
uncertCalibJetsCDV->push_back( jet_itr );
}
// can only sort the CDV - a bit no-no to sort the shallow copies
if ( m_sort ) {
std::sort( uncertCalibJetsCDV->begin(), uncertCalibJetsCDV->end(), HelperFunctions::sort_pt );
}
// add shallow copy to TStore
if(!nominal){ // nominal is always saved outside of systematics loop
ANA_CHECK( m_store->record( uncertCalibJetsSC.first, outSCContainerName));
ANA_CHECK( m_store->record( uncertCalibJetsSC.second, outSCAuxContainerName));
}
// add ConstDataVector to TStore
ANA_CHECK( m_store->record( uncertCalibJetsCDV, outContainerName));
return EL::StatusCode::SUCCESS;
}
EL::StatusCode JetCalibrator::initializeUncertaintiesTool(asg::AnaToolHandle<ICPJetUncertaintiesTool>& uncToolHandle, bool isData){
ANA_MSG_INFO("Initialize Jet Uncertainties Tool with " << m_uncertConfig);
ANA_CHECK( ASG_MAKE_ANA_TOOL(uncToolHandle, JetUncertaintiesTool));
ANA_CHECK( uncToolHandle.setProperty("JetDefinition",m_jetAlgo));
ANA_CHECK( uncToolHandle.setProperty("MCType",m_uncertMCType));
ANA_CHECK( uncToolHandle.setProperty("IsData",isData));
ANA_CHECK( uncToolHandle.setProperty("ConfigFile", m_uncertConfig));
if ( !m_overrideUncertCalibArea.empty() ) {
ANA_MSG_WARNING("Overriding jet uncertainties calibration area to " << m_overrideUncertCalibArea);
ANA_CHECK( uncToolHandle.setProperty("CalibArea", m_overrideUncertCalibArea));
}
if( !m_overrideAnalysisFile.empty() ) {
ANA_MSG_WARNING("Overriding jet uncertainties analysis file to " << m_overrideAnalysisFile);
ANA_CHECK( uncToolHandle.setProperty("AnalysisFile", m_overrideAnalysisFile));
}
if( !m_overrideUncertPath.empty() ){
std::string uncPath = PathResolverFindCalibDirectory(m_overrideUncertPath);
ANA_MSG_WARNING("Overriding jet uncertainties path to " << uncPath);
ANA_CHECK( uncToolHandle.setProperty("Path", uncPath));
}
ANA_CHECK( uncToolHandle.setProperty("OutputLevel", msg().level()));
ANA_CHECK( uncToolHandle.retrieve());
ANA_MSG_DEBUG("Retrieved JetUncertaintiesTool: " << uncToolHandle);
return EL::StatusCode::SUCCESS;
}