Program Listing for File MinixAOD.cxx¶
↰ Return to documentation for file (Root/MinixAOD.cxx
)
// c++ include(s):
#include <iostream>
#include <typeinfo>
#include <sstream>
// EL include(s):
#include <EventLoop/Job.h>
#include <EventLoop/StatusCode.h>
#include <EventLoop/Worker.h>
// output stream
#include "EventLoop/OutputStream.h"
// EDM include(s):
#include "xAODCore/AuxContainerBase.h"
#include "xAODBase/IParticleContainer.h"
#include "xAODCore/ShallowCopy.h"
#include "xAODEgamma/ElectronContainer.h"
#include "xAODEgamma/ElectronAuxContainer.h"
#include "xAODJet/JetContainer.h"
#include "xAODJet/JetAuxContainer.h"
#include "xAODJet/Jet.h"
#include "xAODMissingET/MissingETContainer.h"
#include "xAODMissingET/MissingETAuxContainer.h"
#include "xAODMissingET/MissingET.h"
#include "xAODMuon/MuonContainer.h"
#include "xAODMuon/MuonAuxContainer.h"
#include "xAODMuon/Muon.h"
#include "xAODEgamma/PhotonContainer.h"
#include "xAODEgamma/PhotonAuxContainer.h"
#include "xAODEgamma/Photon.h"
#include "xAODTau/TauJetContainer.h"
#include "xAODTau/TauJetAuxContainer.h"
#include "xAODTau/TauJet.h"
// package include(s):
#include "xAODAnaHelpers/MinixAOD.h"
#include "xAODAnaHelpers/HelperClasses.h"
#include "xAODAnaHelpers/HelperFunctions.h"
// this is needed to distribute the algorithm to the workers
ClassImp(MinixAOD)
MinixAOD :: MinixAOD () :
Algorithm("MinixAOD")
{
}
EL::StatusCode MinixAOD :: setupJob (EL::Job& job)
{
ANA_MSG_DEBUG("Calling setupJob");
job.useXAOD ();
xAOD::Init( "MinixAOD" ).ignore(); // call before opening first file
// only create the output xaod if requested
if(m_createOutputFile){
EL::OutputStream out_xAOD (m_outputFileName, "xAOD");
job.outputAdd (out_xAOD);
}
return EL::StatusCode::SUCCESS;
}
EL::StatusCode MinixAOD :: histInitialize ()
{
ANA_CHECK( xAH::Algorithm::algInitialize());
return EL::StatusCode::SUCCESS;
}
EL::StatusCode MinixAOD :: changeInput (bool firstFile)
{
//
// Update CutBookkeeper
if(m_copyCutBookkeeper)
{
// Retrieve the input container:
const xAOD::CutBookkeeperContainer* inputCBKContainer(nullptr);
ANA_CHECK( wk()->xaodEvent()->retrieveMetaInput(inputCBKContainer, "CutBookkeepers"));
if(firstFile)
{
// Create an output container
m_outputCBKContainer = new xAOD::CutBookkeeperContainer();
m_outputCBKContainer_aux = new xAOD::CutBookkeeperAuxContainer();
m_outputCBKContainer->setStore( m_outputCBKContainer_aux );
// Create an empty incomplete output container
m_outputInCBKContainer = new xAOD::CutBookkeeperContainer();
m_outputInCBKContainer_aux = new xAOD::CutBookkeeperAuxContainer();
m_outputInCBKContainer->setStore( m_outputInCBKContainer_aux );
// Create our cutbookkeeper
m_outputCBK=new xAOD::CutBookkeeper();
m_outputCBK->setName("MinixAODKernel");
m_outputCBK->setCycle(inputCBKContainer->maxCycle()+1);
}
// Merge
m_outputCBKContainer->merge(inputCBKContainer);
}
return EL::StatusCode::SUCCESS;
}
EL::StatusCode MinixAOD :: fileExecute () { return EL::StatusCode::SUCCESS; }
EL::StatusCode MinixAOD :: initialize ()
{
ANA_MSG_DEBUG("Calling initialize");
m_event = wk()->xaodEvent();
m_store = wk()->xaodStore();
// always do this, obviously
TFile *file_xAOD = wk()->getOutputFile(m_outputFileName);
ANA_CHECK( m_event->writeTo(file_xAOD));
if(m_copyFileMetaData){
m_fileMetaDataTool = new xAODMaker::FileMetaDataTool();
ANA_CHECK( m_fileMetaDataTool->setProperty("OutputLevel", msg().level() ));
ANA_CHECK( m_fileMetaDataTool->initialize());
ANA_MSG_DEBUG("FileMetaDataTool initialized...");
}
if(m_copyTriggerInfo){
// m_trigMetaDataTool = new xAODMaker::TriggerMenuMetaDataTool();
// ANA_CHECK( m_trigMetaDataTool->setProperty("OutputLevel", msg().level() ));
// ANA_CHECK( m_trigMetaDataTool->initialize());
// ANA_MSG_DEBUG("TriggerMenuMetaDataTool initialized...");
ANA_MSG_DEBUG("Adding xTrigDecision and TrigConfKeys to the list of keys copied from the input file.");
m_simpleCopyKeys_vec.push_back("xTrigDecision");
m_simpleCopyKeys_vec.push_back("TrigConfKeys");
}
// parse and split by comma
std::string token;
std::istringstream ss("");
// A B C D ... Z -> {A, B, C, D, ..., Z}
ss.clear(); ss.str(m_simpleCopyKeys);
while(std::getline(ss, token, ' '))
m_simpleCopyKeys_vec.push_back(token);
// A B C D ... Z -> {A, B, C, D, ..., Z}
ss.clear(); ss.str(m_storeCopyKeys);
while(std::getline(ss, token, ' '))
m_copyFromStoreToEventKeys_vec.push_back(token);
// A1|A2 B1|B2 C1|C2 ... Z1|Z2 -> {(A1, A2), (B1, B2), ..., (Z1, Z2)}
ss.clear(); ss.str(m_shallowCopyKeys);
while(std::getline(ss, token, ' ')){
int pos = token.find_first_of('|');
m_shallowCopyKeys_vec.push_back(std::pair<std::string, std::string>(token.substr(0, pos), token.substr(pos+1)));
}
// A1|A2 B1|B2 C1|C2 ... Z1|Z2 -> {(A1, A2), (B1, B2), ..., (Z1, Z2)}
ss.clear(); ss.str(m_deepCopyKeys);
while(std::getline(ss, token, ' ')){
int pos = token.find_first_of('|');
m_deepCopyKeys_vec.push_back(std::pair<std::string, std::string>(token.substr(0, pos), token.substr(pos+1)));
}
// A1|A2 B1|B2 C1|C2 ... Z1|Z2 -> {(A1, A2), (B1, B2), ..., (Z1, Z2)}
ss.clear(); ss.str(m_vectorCopyKeys);
while(std::getline(ss, token, ' ')){
int pos = token.find_first_of('|');
m_vectorCopyKeys_vec.push_back(std::pair<std::string, std::string>(token.substr(0, pos), token.substr(pos+1)));
}
ANA_MSG_DEBUG("MinixAOD Interface succesfully initialized!" );
return EL::StatusCode::SUCCESS;
}
EL::StatusCode MinixAOD :: execute ()
{
ANA_MSG_VERBOSE( "Dumping objects...");
const xAOD::EventInfo* eventInfo(nullptr);
ANA_CHECK( HelperFunctions::retrieve(eventInfo, "EventInfo", m_event, m_store, msg()) );
//
// Fill cutbookkeeper
if(m_copyCutBookkeeper)
{
float eventWeight(1);
if ( eventInfo->eventType(xAOD::EventInfo::IS_SIMULATION) )
eventWeight = eventInfo->mcEventWeight();
m_outputCBK->addNAcceptedEvents(1);
m_outputCBK->addSumOfEventWeights(eventWeight);
m_outputCBK->addSumOfEventWeightsSquared(eventWeight*eventWeight);
}
//
// Copy code
// simple copy is easiest - it's in the input, copy over, no need for types
for(const auto& key: m_simpleCopyKeys_vec){
ANA_CHECK( m_event->copy(key));
ANA_MSG_DEBUG("Copying " << key << " from input file");
}
// we need to make deep copies
for(const auto& keypair: m_deepCopyKeys_vec){
auto in_key = keypair.first;
auto out_key = keypair.second;
const xAOD::IParticleContainer* cont(nullptr);
ANA_CHECK( HelperFunctions::retrieve(cont, in_key, nullptr, m_store, msg()));
if(const xAOD::ElectronContainer* t_cont = dynamic_cast<const xAOD::ElectronContainer*>(cont)){
ANA_CHECK( (HelperFunctions::makeDeepCopy<xAOD::ElectronContainer, xAOD::ElectronAuxContainer, xAOD::Electron>(m_store, out_key.c_str(), t_cont)));
} else if(const xAOD::JetContainer* t_cont = dynamic_cast<const xAOD::JetContainer*>(cont)){
ANA_CHECK( (HelperFunctions::makeDeepCopy<xAOD::JetContainer, xAOD::JetAuxContainer, xAOD::Jet>(m_store, out_key.c_str(), t_cont)));
} else if(const xAOD::MissingETContainer* t_cont = dynamic_cast<const xAOD::MissingETContainer*>(cont)){
ANA_CHECK( (HelperFunctions::makeDeepCopy<xAOD::MissingETContainer, xAOD::MissingETAuxContainer, xAOD::MissingET>(m_store, out_key.c_str(), t_cont)));
} else if(const xAOD::MuonContainer* t_cont = dynamic_cast<const xAOD::MuonContainer*>(cont)){
ANA_CHECK( (HelperFunctions::makeDeepCopy<xAOD::MuonContainer, xAOD::MuonAuxContainer, xAOD::Muon>(m_store, out_key.c_str(), t_cont)));
} else if(const xAOD::PhotonContainer* t_cont = dynamic_cast<const xAOD::PhotonContainer*>(cont)){
ANA_CHECK( (HelperFunctions::makeDeepCopy<xAOD::PhotonContainer, xAOD::PhotonAuxContainer, xAOD::Photon>(m_store, out_key.c_str(), t_cont)));
} else if(const xAOD::TauJetContainer* t_cont = dynamic_cast<const xAOD::TauJetContainer*>(cont)){
ANA_CHECK( (HelperFunctions::makeDeepCopy<xAOD::TauJetContainer, xAOD::TauJetAuxContainer, xAOD::TauJet>(m_store, out_key.c_str(), t_cont)));
} else {
ANA_MSG_ERROR("Could not identify what container " << in_key << " corresponds to for deep-copying.");
return EL::StatusCode::FAILURE;
}
m_copyFromStoreToEventKeys_vec.push_back(out_key);
ANA_MSG_DEBUG("Deep-Copied " << in_key << " to " << out_key << " to record to output file");
}
// shallow IO handling (if no parent, assume deep copy)
for(const auto& keypair: m_shallowCopyKeys_vec){
auto key = keypair.first;
auto parent = keypair.second;
// only add the parent if it doesn't exist
if(!parent.empty()) m_copyFromStoreToEventKeys_vec.push_back(parent);
ANA_MSG_DEBUG("Copying " << key);
if(!parent.empty()) ANA_MSG_DEBUG(" as well as it's parent " << parent);
m_copyFromStoreToEventKeys_vec.push_back(key);
}
// vector handling (if no parent, assume deep copy)
for(const auto& keypair: m_vectorCopyKeys_vec){
auto vectorName = keypair.first;
auto parent = keypair.second;
std::vector<std::string>* vector(nullptr);
ANA_CHECK( HelperFunctions::retrieve(vector, vectorName, nullptr, m_store, msg()));
// only add the parent if it doesn't exist
if(!parent.empty()) m_copyFromStoreToEventKeys_vec.push_back(parent);
ANA_MSG_INFO("The following containers are being copied over:");
for(const auto& key: *vector){
ANA_MSG_DEBUG("\t" << key);
m_copyFromStoreToEventKeys_vec.push_back(key);
}
if(!parent.empty()) ANA_MSG_DEBUG("... along with their parent " << parent);
}
// remove duplicates from m_copyFromStoreToEventKeys_vec
// - see http://stackoverflow.com/a/1041939/1532974
std::set<std::string> s;
unsigned size = m_copyFromStoreToEventKeys_vec.size();
for( unsigned i = 0; i < size; ++i ) s.insert( m_copyFromStoreToEventKeys_vec[i] );
m_copyFromStoreToEventKeys_vec.assign( s.begin(), s.end() );
// all we need to do is retrieve it and figure out what type it is to record it and we're done
for(const auto& key: m_copyFromStoreToEventKeys_vec){
const xAOD::IParticleContainer* cont(nullptr);
ANA_CHECK( HelperFunctions::retrieve(cont, key, nullptr, m_store, msg()));
if(dynamic_cast<const xAOD::ElectronContainer*>(cont)){
ANA_CHECK( (HelperFunctions::recordOutput<xAOD::ElectronContainer, xAOD::ElectronAuxContainer>(m_event, m_store, key)));
} else if(dynamic_cast<const xAOD::JetContainer*>(cont)){
ANA_CHECK( (HelperFunctions::recordOutput<xAOD::JetContainer, xAOD::JetAuxContainer>(m_event, m_store, key)));
} else if(dynamic_cast<const xAOD::MissingETContainer*>(cont)){
ANA_CHECK( (HelperFunctions::recordOutput<xAOD::MissingETContainer, xAOD::MissingETAuxContainer>(m_event, m_store, key)));
} else if(dynamic_cast<const xAOD::MuonContainer*>(cont)){
ANA_CHECK( (HelperFunctions::recordOutput<xAOD::MuonContainer, xAOD::MuonAuxContainer>(m_event, m_store, key)));
} else if(dynamic_cast<const xAOD::PhotonContainer*>(cont)){
ANA_CHECK( (HelperFunctions::recordOutput<xAOD::PhotonContainer, xAOD::PhotonAuxContainer>(m_event, m_store, key)));
} else if(dynamic_cast<const xAOD::TauJetContainer*>(cont)){
ANA_CHECK( (HelperFunctions::recordOutput<xAOD::TauJetContainer, xAOD::TauJetAuxContainer>(m_event, m_store, key)));
} else {
ANA_MSG_ERROR("Could not identify what container " << key << " corresponds to for copying from TStore to TEvent.");
return EL::StatusCode::FAILURE;
}
ANA_MSG_DEBUG("Copied " << key << " and it's auxiliary container from TStore to TEvent");
}
m_event->fill();
ANA_MSG_DEBUG("Finished dumping objects...");
return EL::StatusCode::SUCCESS;
}
EL::StatusCode MinixAOD :: postExecute () { return EL::StatusCode::SUCCESS; }
EL::StatusCode MinixAOD :: finalize () {
//
// Save cutbookkeeper
if(m_copyCutBookkeeper)
{
ANA_CHECK( wk()->xaodEvent()->recordMeta(m_outputCBKContainer ,"CutBookkeepers") );
ANA_CHECK( wk()->xaodEvent()->recordMeta(m_outputCBKContainer_aux ,"CutBookkeepersAux.") );
ANA_CHECK( wk()->xaodEvent()->recordMeta(m_outputInCBKContainer ,"IncompleteCutBookkeepers") );
ANA_CHECK( wk()->xaodEvent()->recordMeta(m_outputInCBKContainer_aux,"IncompleteCutBookkeepersAux."));
m_outputCBKContainer->push_back(m_outputCBK);
}
//
// Close file
TFile *file_xAOD = wk()->getOutputFile(m_outputFileName);
ANA_CHECK( m_event->finishWritingTo(file_xAOD));
if(m_fileMetaDataTool) delete m_fileMetaDataTool;
// if(m_trigMetaDataTool) delete m_trigMetaDataTool;
return EL::StatusCode::SUCCESS;
}
EL::StatusCode MinixAOD :: histFinalize ()
{
ANA_CHECK( xAH::Algorithm::algFinalize());
return EL::StatusCode::SUCCESS;
}