.. _program_listing_file_Root_JetCalibrator.cxx: Program Listing for File JetCalibrator.cxx ========================================== |exhale_lsh| :ref:`Return to documentation for file ` (``Root/JetCalibrator.cxx``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp /****************************************** * * 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 // EL include(s): #include #include #include // 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 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 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 TruthLabelID ("TruthLabelID"); static SG::AuxElement::ConstAccessor 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 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 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& calibJetsSC, std::vector& vecOutContainerNames, bool isPDCopy){ bool nominal = thisSyst.name().empty(); std::string outSCContainerName, outSCAuxContainerName, outContainerName; asg::AnaToolHandle* 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* uncertCalibJetsCDV = new ConstDataVector(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 el_parent = jet_itr->auxdata >("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& 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; }