From 74559966f45f4721cfc40da0dba0b534632f49cc Mon Sep 17 00:00:00 2001 From: Jack Cranshaw <cranshaw@anl.gov> Date: Tue, 30 Aug 2016 15:16:57 +0200 Subject: [PATCH] Fix issue with athfile use in CutFlowHelpers.py (EventBookkeeperTools-00-00-92) * Fix issue with athfile use in CutFlowHelpers.py * Tagging EventBookkeeperTools-00-00-92 2016-05-04 Jack Cranshaw <cranshaw@anl.gov> * Add in factorized cutflowsvc FileCutFlowSvc and BookkeeperTool * No changes to existing behavior * Modified: BookkeeperTool.cxx, EventBookkeeperTools_entries.cxx, BookkeeperTool.h * Added: FileCutFlowSvc.h, src/FileCutFlowSvc.cxx * Tagging EventBookkeeperTools-00-00-91 2015-07-28 Karsten Koeneke <karsten.koeneke@cern.ch> * Fix configuration to extract the input stream name. * Fix EventCounterAlg for otherMCWeights. * Tagging EventBookkeeperTools-00-00-90 * Tagging EventBookkeeperTools-00-00-89. * Fix coverity warnings. * Tagging EventBookkeeperTools-00-00-88. ... (Long ChangeLog diff - truncated) Former-commit-id: f85724246d9ac4fff4740c4aebc099424da0206a --- .../EventBookkeeperTools/BookkeeperTool.h | 21 +- .../Root/BookkeeperTool.cxx | 366 +++++++++--- .../python/CutFlowHelpers.py | 83 ++- .../src/EventCounterAlg.cxx | 5 +- .../src/FileCutFlowSvc.cxx | 549 ++++++++++++++++++ .../EventBookkeeperTools/src/FileCutFlowSvc.h | 204 +++++++ .../EventBookkeeperTools_entries.cxx | 3 + 7 files changed, 1132 insertions(+), 99 deletions(-) create mode 100644 Event/EventBookkeeperTools/src/FileCutFlowSvc.cxx create mode 100644 Event/EventBookkeeperTools/src/FileCutFlowSvc.h diff --git a/Event/EventBookkeeperTools/EventBookkeeperTools/BookkeeperTool.h b/Event/EventBookkeeperTools/EventBookkeeperTools/BookkeeperTool.h index 40436dfb823..3982b9a0e77 100644 --- a/Event/EventBookkeeperTools/EventBookkeeperTools/BookkeeperTool.h +++ b/Event/EventBookkeeperTools/EventBookkeeperTools/BookkeeperTool.h @@ -53,23 +53,28 @@ public: virtual StatusCode finalize(); private: - /// Update an existing (possibly empty) xAOD::CutBookkeeperContainer with - /// all the information from the container(s) form the input file - StatusCode updateCollFromInputStore( xAOD::CutBookkeeperContainer* coll, - const std::string &collName ); /// Helper class to update a container with information from another one StatusCode updateContainer( xAOD::CutBookkeeperContainer* contToUpdate, const xAOD::CutBookkeeperContainer* otherCont ); + + /// Fill Cutflow information + StatusCode addCutFlow(); /// Pointer to cut flow svc //ServiceHandle<ICutFlowSvc> m_cutflowsvc; - /// The name of the completed, i.e., fully processed, CutBookkeeperContainer - std::string m_completeCollName; + /// The name of the output CutBookkeeperContainer + std::string m_outputCollName; - /// The name of the incomplete, i.e., not fully processed (e.g. failed job), CutBookkeeperContainer - std::string m_incompleteCollName; + /// The name of the input CutBookkeeperContainer + std::string m_inputCollName; + + /// The name of the CutFlowSvc CutBookkeeperContainer + std::string m_cutflowCollName; + + bool m_cutflowTaken; + }; #endif diff --git a/Event/EventBookkeeperTools/Root/BookkeeperTool.cxx b/Event/EventBookkeeperTools/Root/BookkeeperTool.cxx index b36770f9c1a..b9c3a2e3f51 100644 --- a/Event/EventBookkeeperTools/Root/BookkeeperTool.cxx +++ b/Event/EventBookkeeperTools/Root/BookkeeperTool.cxx @@ -23,12 +23,15 @@ BookkeeperTool::BookkeeperTool(const std::string& name) - : asg::AsgMetadataTool(name) + : asg::AsgMetadataTool(name), + m_cutflowTaken(false) { - declareProperty("OutputCollName", m_completeCollName="CutBookkeepers", - "The default name of the xAOD::CutBookkeeperContainer for fully processed files"); - declareProperty("OutputIncompleteCollName", m_incompleteCollName = "IncompleteCutBookkeepers", - "The default name of the xAOD::CutBookkeeperContainer for partially processed files"); + declareProperty("OutputCollName", m_outputCollName="CutBookkeepers", + "The default name of the xAOD::CutBookkeeperContainer for output files"); + declareProperty("InputCollName", m_inputCollName = "CutBookkeepers", + "The default name of the xAOD::CutBookkeeperContainer for input files"); + declareProperty("CutFlowCollName", m_cutflowCollName = "CutBookkeepersFile", + "The default name of the xAOD::CutBookkeeperContainer for CutFlowSvc"); #ifdef ASGTOOL_ATHENA declareInterface< ::IMetaDataTool >( this ); #endif // ASGTOOL_ATHENA @@ -46,8 +49,10 @@ StatusCode BookkeeperTool::initialize() { ATH_MSG_DEBUG( "Initializing " << name() << " - package version " << PACKAGE_VERSION ); - ATH_MSG_DEBUG("OutputCollName = " << m_completeCollName); - ATH_MSG_DEBUG("OutputIncompleteCollName = " << m_incompleteCollName); + + ATH_MSG_DEBUG("InputCollName = " << m_inputCollName); + ATH_MSG_DEBUG("OutputCollName = " << m_outputCollName); + ATH_MSG_DEBUG("CutFlowCollName = " << m_cutflowCollName); return StatusCode::SUCCESS; } @@ -63,43 +68,50 @@ StatusCode BookkeeperTool::beginInputFile() // 2a) if incomplete from input, directly propagate to output // 2b) if complete from input, wait for EndInputFile to decide what to do in output + // reset cutflow taken marker + m_cutflowTaken = false; + // Get the incomplete bookkeeper collection of the input metadata store const xAOD::CutBookkeeperContainer* input_inc = 0; - StatusCode ssc = inputMetaStore()->retrieve( input_inc, m_incompleteCollName ); + // Construct input and output incomplete names + std::string inCollName = "Incomplete" + m_inputCollName; + std::string outCollName = "Incomplete" + m_outputCollName; + StatusCode ssc = inputMetaStore()->retrieve( input_inc, inCollName ); if (ssc.isSuccess()) { - //if ( (inputMetaStore()->retrieve( input_inc, m_incompleteCollName )).isSuccess() ) { // First make sure there is an incomplete container in the output store - if( !(outputMetaStore()->contains<xAOD::CutBookkeeperContainer>(m_incompleteCollName)) ) { + if( !(outputMetaStore()->contains<xAOD::CutBookkeeperContainer>(outCollName)) ) { xAOD::CutBookkeeperContainer* inc = new xAOD::CutBookkeeperContainer(); xAOD::CutBookkeeperAuxContainer* auxinc = new xAOD::CutBookkeeperAuxContainer(); inc->setStore(auxinc); - ATH_CHECK(outputMetaStore()->record(inc,m_incompleteCollName)); - ATH_CHECK(outputMetaStore()->record(auxinc,m_incompleteCollName+"Aux.")); + ATH_CHECK(outputMetaStore()->record(inc,outCollName)); + ATH_CHECK(outputMetaStore()->record(auxinc,outCollName+"Aux.")); } // retrieve the incomplete output container xAOD::CutBookkeeperContainer* incompleteBook(NULL); - ATH_CHECK(outputMetaStore()->retrieve( incompleteBook, m_incompleteCollName)); + ATH_CHECK(outputMetaStore()->retrieve( incompleteBook, outCollName)); // update incomplete output with any incomplete input ATH_CHECK(this->updateContainer(incompleteBook,input_inc)); ATH_MSG_DEBUG("Successfully merged input incomplete bookkeepers with output"); } else { - ATH_MSG_INFO("No incomplete bookkeepers in this file " << m_incompleteCollName); + ATH_MSG_INFO("No incomplete bookkeepers in this file " << inCollName); } // Get the complete bookkeeper collection of the input metadata store const xAOD::CutBookkeeperContainer* input_com = 0; - if ( (inputMetaStore()->retrieve( input_com, m_completeCollName )).isSuccess() ) { + inCollName = m_inputCollName; + outCollName = m_outputCollName; + if ( (inputMetaStore()->retrieve( input_com, inCollName )).isSuccess() ) { // Check if a tmp is there. IT SHOULD NOT BE //xAOD::CutBookkeeperContainer* incompleteBook(NULL); - if( !(outputMetaStore()->contains<xAOD::CutBookkeeperContainer>(m_completeCollName+"tmp")) ) { + if( !(outputMetaStore()->contains<xAOD::CutBookkeeperContainer>(outCollName+"tmp")) ) { // Now create the tmp container xAOD::CutBookkeeperContainer* tmp = new xAOD::CutBookkeeperContainer(); xAOD::CutBookkeeperAuxContainer* auxtmp = new xAOD::CutBookkeeperAuxContainer(); tmp->setStore(auxtmp); if (updateContainer(tmp,input_com).isSuccess()) { - ATH_CHECK(outputMetaStore()->record(tmp,m_completeCollName+"tmp")); - ATH_CHECK(outputMetaStore()->record(auxtmp,m_completeCollName+"tmpAux.")); + ATH_CHECK(outputMetaStore()->record(tmp,outCollName+"tmp")); + ATH_CHECK(outputMetaStore()->record(auxtmp,outCollName+"tmpAux.")); } else { ATH_MSG_WARNING("Could not update tmp container from input complete conatiner"); @@ -111,39 +123,53 @@ StatusCode BookkeeperTool::beginInputFile() } ATH_MSG_DEBUG("Successfully copied complete bookkeepers to temp container"); } - - return StatusCode::SUCCESS; -} - -StatusCode BookkeeperTool::endInputFile() -{ - //CLOSING INPUT FILE - //Things to do: + // Now make sure the output containers are in the output store + // // Make sure complete container exists in output - if( !(outputMetaStore()->contains<xAOD::CutBookkeeperContainer>(m_completeCollName)) ) { + if( !(outputMetaStore()->contains<xAOD::CutBookkeeperContainer>(m_outputCollName)) ) { // Now create the complete container xAOD::CutBookkeeperContainer* inc = new xAOD::CutBookkeeperContainer(); xAOD::CutBookkeeperAuxContainer* auxinc = new xAOD::CutBookkeeperAuxContainer(); inc->setStore(auxinc); - ATH_CHECK(outputMetaStore()->record(inc,m_completeCollName)); - ATH_CHECK(outputMetaStore()->record(auxinc,m_completeCollName+"Aux.")); + ATH_CHECK(outputMetaStore()->record(inc,m_outputCollName)); + ATH_CHECK(outputMetaStore()->record(auxinc,m_outputCollName+"Aux.")); } else { ATH_MSG_WARNING("complete collection already exists"); //return StatusCode::SUCCESS; } + // Make sure incomplete container exists in output + std::string inc_name = "Incomplete"+m_outputCollName; + if( !(outputMetaStore()->contains<xAOD::CutBookkeeperContainer>(inc_name)) ) { + // Now create the complete container + xAOD::CutBookkeeperContainer* coll = new xAOD::CutBookkeeperContainer(); + xAOD::CutBookkeeperAuxContainer* auxcoll = new xAOD::CutBookkeeperAuxContainer(); + coll->setStore(auxcoll); + ATH_CHECK(outputMetaStore()->record(coll,inc_name)); + ATH_CHECK(outputMetaStore()->record(auxcoll,inc_name+"Aux.")); + } + else { + ATH_MSG_WARNING("incomplete collection already exists"); + } + + return StatusCode::SUCCESS; +} + + +StatusCode BookkeeperTool::endInputFile() +{ // Get the complete bookkeeper collection of the output meta-data store xAOD::CutBookkeeperContainer* completeBook(NULL); - if( !(outputMetaStore()->retrieve( completeBook, m_completeCollName) ).isSuccess() ) { + if( !(outputMetaStore()->retrieve( completeBook, m_outputCollName) ).isSuccess() ) { ATH_MSG_ERROR( "Could not get complete CutBookkeepers from output MetaDataStore" ); return StatusCode::FAILURE; } // Get the tmp bookkeeper from the input const xAOD::CutBookkeeperContainer* tmpCompleteBook(NULL); - if( !(outputMetaStore()->retrieve( tmpCompleteBook, m_completeCollName+"tmp") ).isSuccess() ) { + if( !(outputMetaStore()->retrieve( tmpCompleteBook, m_outputCollName+"tmp") ).isSuccess() ) { ATH_MSG_WARNING( "Could not get tmp CutBookkeepers from output MetaDataStore" ); } else { @@ -154,7 +180,36 @@ StatusCode BookkeeperTool::endInputFile() ATH_CHECK(outputMetaStore()->removeDataAndProxy(tmpCompleteBook)); ATH_CHECK(outputMetaStore()->removeDataAndProxy(tmpCompleteBookAux)); } - + +/* + if (!m_cutflowTaken) { + // Get the bookkeeper from the current processing + const xAOD::CutBookkeeperContainer* fileCompleteBook(NULL); + if( !(outputMetaStore()->retrieve( fileCompleteBook, m_cutflowCollName) ).isSuccess() ) { + ATH_MSG_WARNING( "Could not get CutFlowSvc CutBookkeepers from output MetaDataStore" ); + } + else { + // update the complete output with the complete input + ATH_CHECK(this->updateContainer(completeBook,fileCompleteBook)); + // Set flag for cutflow container to false + m_cutflowTaken = true; + } + } + else { + ATH_MSG_DEBUG("Cutflow information written into container before endInputFile"); + } + +*/ + if (!m_cutflowTaken) { + if (addCutFlow().isFailure()) { + ATH_MSG_ERROR("Could not add CutFlow information"); + } + m_cutflowTaken = true; + } + else { + ATH_MSG_DEBUG("Cutflow information written into container before endInputFile"); + } + return StatusCode::SUCCESS; } @@ -165,29 +220,19 @@ StatusCode BookkeeperTool::metaDataStop() // 1) Create new incomplete CutBookkeepers if relevant // 2) Print cut flow summary // 3) Write root file if requested - // Make sure complete container exists in output - if( !(outputMetaStore()->contains<xAOD::CutBookkeeperContainer>(m_incompleteCollName)) ) { - // Now create the complete container - xAOD::CutBookkeeperContainer* coll = new xAOD::CutBookkeeperContainer(); - xAOD::CutBookkeeperAuxContainer* auxcoll = new xAOD::CutBookkeeperAuxContainer(); - coll->setStore(auxcoll); - ATH_CHECK(outputMetaStore()->record(coll,m_incompleteCollName)); - ATH_CHECK(outputMetaStore()->record(auxcoll,m_incompleteCollName+"Aux.")); - } - else { - ATH_MSG_WARNING("incomplete collection already exists"); - } + // Make sure incomplete container exists in output + std::string inc_name = "Incomplete"+m_outputCollName; // Get the complete bookkeeper collection of the output meta-data store xAOD::CutBookkeeperContainer* incompleteBook(NULL); - if( !(outputMetaStore()->retrieve( incompleteBook, m_incompleteCollName) ).isSuccess() ) { + if( !(outputMetaStore()->retrieve( incompleteBook, inc_name) ).isSuccess() ) { ATH_MSG_WARNING( "Could not get incomplete CutBookkeepers from output MetaDataStore" ); } // Get the tmp bookkeeper from the input const xAOD::CutBookkeeperContainer* tmpCompleteBook(NULL); - if( !(outputMetaStore()->retrieve( tmpCompleteBook, m_completeCollName+"tmp") ).isSuccess() ) { - ATH_MSG_WARNING( "Could not get tmp CutBookkeepers from output MetaDataStore for " << m_completeCollName+"tmp"); + if( !(outputMetaStore()->retrieve( tmpCompleteBook, m_outputCollName+"tmp") ).isSuccess() ) { + ATH_MSG_WARNING( "Could not get tmp CutBookkeepers from output MetaDataStore for " << m_outputCollName+"tmp"); } else { // update the complete output with the complete input @@ -198,6 +243,36 @@ StatusCode BookkeeperTool::metaDataStop() ATH_CHECK(outputMetaStore()->removeDataAndProxy(tmpCompleteBookAux)); } +/* + if (!m_cutflowTaken) { + // Get the bookkeeper from the current processing + const xAOD::CutBookkeeperContainer* fileCompleteBook(NULL); + if( !(outputMetaStore()->retrieve( fileCompleteBook, m_cutflowCollName) ).isSuccess() ) { + ATH_MSG_WARNING( "Could not get CutFlowSvc CutBookkeepers from output MetaDataStore" ); + } + else { + // update the complete output with the complete input + ATH_CHECK(this->updateContainer(incompleteBook,fileCompleteBook)); + // Set flag for cutflow container to false + m_cutflowTaken = true; + } + } + else { + ATH_MSG_DEBUG("Cutflow information written into container before metaDataStop"); + } +*/ + if (!m_cutflowTaken) { + if (addCutFlow().isFailure()) { + ATH_MSG_ERROR("Could not add CutFlow information"); + } + } + else { + ATH_MSG_DEBUG("Cutflow information written into container before metaDataStop"); + } + + // Reset after metadata stop + m_cutflowTaken = false; + return StatusCode::SUCCESS; } @@ -209,40 +284,7 @@ BookkeeperTool::finalize() return StatusCode::SUCCESS; } - - -StatusCode -BookkeeperTool::updateCollFromInputStore(xAOD::CutBookkeeperContainer* coll, - const std::string &collName) -{ - ATH_MSG_DEBUG("calling updateCollFromInputStore(" << collName << ") with coll-size=" << coll->size() ); - - if ( inputMetaStore()->contains<xAOD::CutBookkeeperContainer>(collName) ) { - ATH_MSG_VERBOSE("Input MetaData contains type xAOD::CutBookkeeperContainer with name" << collName); - - // There can always only be a single object in the input store. As the store - // is connected to just a single input file. - const xAOD::CutBookkeeperContainer* tmpColl = 0; - ATH_CHECK( inputMetaStore()->retrieve( tmpColl, collName ) ); - - // Check that we succeeded: - if( ! tmpColl->hasStore() ) { - ATH_MSG_FATAL( "Object doesn't have an auxiliary store" ); - return StatusCode::FAILURE; - } - - //...and update coll with each list. - ATH_CHECK( this->updateContainer(coll, tmpColl) ); - } - else { - ATH_MSG_INFO( "Cannot find xAOD::CutBookkeeperContainer " - << "with name " << collName << " in the input file."); - } - return StatusCode::SUCCESS; -} - - - +/* StatusCode BookkeeperTool::updateContainer( xAOD::CutBookkeeperContainer* contToUpdate, const xAOD::CutBookkeeperContainer* otherCont ) { @@ -379,5 +421,167 @@ BookkeeperTool::updateContainer( xAOD::CutBookkeeperContainer* contToUpdate, } // Done fixing all cross references return StatusCode::SUCCESS; } +*/ + + +StatusCode BookkeeperTool::addCutFlow() +{ + // Add the information from the current processing to the complete output + // --> same paradigm as original CutFlowSvc + // Get the complete bookkeeper collection of the output meta-data store + xAOD::CutBookkeeperContainer* completeBook(NULL); + if( !(outputMetaStore()->retrieve( completeBook, m_outputCollName) ).isSuccess() ) { + ATH_MSG_ERROR( "Could not get complete CutBookkeepers from output MetaDataStore" ); + return StatusCode::FAILURE; + } + + // Get the bookkeeper from the current processing + const xAOD::CutBookkeeperContainer* fileCompleteBook(NULL); + if( !(outputMetaStore()->retrieve( fileCompleteBook, m_cutflowCollName) ).isSuccess() ) { + ATH_MSG_WARNING( "Could not get CutFlowSvc CutBookkeepers from output MetaDataStore" ); + } + else { + // update the complete output with the complete input + ATH_CHECK(this->updateContainer(completeBook,fileCompleteBook)); + } + + return StatusCode::SUCCESS; +} + + +namespace { + + +xAOD::CutBookkeeper* +resolveLink (const xAOD::CutBookkeeper* old, + xAOD::CutBookkeeperContainer& contToUpdate, + const xAOD::CutBookkeeperContainer& otherCont, + const std::vector<size_t>& otherIndices) +{ + { + xAOD::CutBookkeeperContainer::iterator matchIter = + std::find( contToUpdate.begin(), + contToUpdate.end(), + old ); + if (matchIter != contToUpdate.end()) + return *matchIter; + } + + { + xAOD::CutBookkeeperContainer::const_iterator matchIter = + std::find( otherCont.begin(), + otherCont.end(), + old ); + if (matchIter != contToUpdate.end()) { + size_t pos = matchIter - otherCont.begin(); + return contToUpdate[otherIndices[pos]]; + } + } + + // If we didn't find it, we need to add it + xAOD::CutBookkeeper* newEBK = new xAOD::CutBookkeeper(); + if ( newEBK->usingPrivateStore() ) { newEBK->releasePrivateStore(); } + newEBK->makePrivateStore(old); + contToUpdate.push_back( newEBK ); + return newEBK; +} + + +} // anonymous namespace + + +StatusCode +BookkeeperTool::updateContainer( xAOD::CutBookkeeperContainer* contToUpdate, + const xAOD::CutBookkeeperContainer* otherCont ) +{ + ATH_MSG_DEBUG("calling updateContainer(...)" ); + ATH_MSG_VERBOSE("Have container to update with size=" << contToUpdate->size() + << ", and other container with size=" << otherCont->size() ); + + size_t origSize = contToUpdate->size(); + + // Vector of indices in contToUpdate of elements in otherCont. + std::vector< std::size_t > otherIndices (otherCont->size()); + // Loop through otherCont. + // If element already in contToUpdate, update event counts, otherwise create new element + for ( std::size_t i=0; i<otherCont->size(); ++i ) { + const xAOD::CutBookkeeper* otherEBK = otherCont->at(i); + ATH_MSG_VERBOSE("Looping through otherCont at index " << i); + ATH_MSG_VERBOSE("Have otherEBK with: name=" << otherEBK->name() + << ", cycle=" << otherEBK->cycle() + << ", nAcceptedEvents=" << otherEBK->nAcceptedEvents() + << ", inputStream=" << otherEBK->inputStream() ); + + + // Loop through the container to be updated (contToUpdate) and see if we find a match + bool foundEBKToUpdate(false); + for ( std::size_t j=0; j<contToUpdate->size(); ++j ) { + xAOD::CutBookkeeper* ebkToUpdate = contToUpdate->at(j); + // Check if they are identical, if so, update; else add otherEBK + if ( otherEBK->isEqualTo(ebkToUpdate) ) { + ebkToUpdate->setPayload( ebkToUpdate->payload() + otherEBK->payload() ); + otherIndices[i] = j; + foundEBKToUpdate = true; + break; + } + } // End: Inner loop over contToUpdate + if (!foundEBKToUpdate) { + xAOD::CutBookkeeper* newEBK = new xAOD::CutBookkeeper(); + if ( newEBK->usingPrivateStore() ) { newEBK->releasePrivateStore(); } + newEBK->makePrivateStore(otherEBK); + contToUpdate->push_back( newEBK ); + std::size_t ebIdx = newEBK->index(); + otherIndices[i] = ebIdx; + } + } // End: Outer loop over contToUpdate + // Now, we still need to fix the cross-referencing of the newly added CutBookkkeepers + for ( std::size_t i=origSize; i<contToUpdate->size(); ++i ) { + xAOD::CutBookkeeper* ebkToModify = contToUpdate->at(i); + + // Parent check + if ( ebkToModify->hasParent() ) { + const xAOD::CutBookkeeper* oldParent = ebkToModify->parent(); + const xAOD::CutBookkeeper* newParent = resolveLink (oldParent, + *contToUpdate, + *otherCont, + otherIndices); + ebkToModify->setParent (newParent); + } // Done fixing parent + + // Children check + std::vector< xAOD::CutBookkeeper* > newChildren; + for ( std::size_t oldIdx=0; oldIdx<ebkToModify->nChildren(); ++oldIdx ) { + const xAOD::CutBookkeeper* oldEBK = ebkToModify->child(oldIdx); + newChildren.push_back (resolveLink (oldEBK, + *contToUpdate, + *otherCont, + otherIndices)); + } // Done fixing children + ebkToModify->setChildren (newChildren); + + // Used others check + std::vector< xAOD::CutBookkeeper* > newOthers; + for ( std::size_t oldIdx=0; oldIdx<ebkToModify->nUsedOthers(); ++oldIdx ) { + const xAOD::CutBookkeeper* oldEBK = ebkToModify->usedOther(oldIdx); + newOthers.push_back (resolveLink (oldEBK, + *contToUpdate, + *otherCont, + otherIndices)); + } // Done fixing used others + ebkToModify->setUsedOthers (newOthers); + + // Siblings check + std::vector< xAOD::CutBookkeeper* > newSiblings; + for ( std::size_t oldIdx=0; oldIdx<ebkToModify->nSiblings(); ++oldIdx ) { + const xAOD::CutBookkeeper* oldEBK = ebkToModify->sibling(oldIdx); + newSiblings.push_back (resolveLink (oldEBK, + *contToUpdate, + *otherCont, + otherIndices)); + } // Done fixing siblings + ebkToModify->setSiblings (newSiblings); + } // Done fixing all cross references + return StatusCode::SUCCESS; +} diff --git a/Event/EventBookkeeperTools/python/CutFlowHelpers.py b/Event/EventBookkeeperTools/python/CutFlowHelpers.py index c71361fa188..5282feb88df 100644 --- a/Event/EventBookkeeperTools/python/CutFlowHelpers.py +++ b/Event/EventBookkeeperTools/python/CutFlowHelpers.py @@ -43,9 +43,7 @@ def GetCurrentStreamName( msg, athFile=None ): - - -def CreateCutFlowSvc( svcName="CutFlowSvc", athFile=None, seq=None, addAlgInPlace=False, addMetaDataToAllOutputFiles=True ): +def CreateCutFlowSvc( svcName="CutFlowSvc", athFile=None, seq=None, addAlgInPlace=False, addMetaDataToAllOutputFiles=True, SGkey="CutBookkeepers" ): """ Helper to create the CutFlowSvc, extract the needed information from the input file, and also schedule all the needed stuff. @@ -61,11 +59,50 @@ def CreateCutFlowSvc( svcName="CutFlowSvc", athFile=None, seq=None, addAlgInPlac inputStreamName = GetCurrentStreamName( msg=msg, athFile=athFile ) msg.debug("CreateCutFlowSvc: Have inputStreamName = %s" % (inputStreamName) ) - # Create the CutFlowSvc instance + # Create the CutFlowSvc instance(s) import AthenaCommon.CfgMgr as CfgMgr if not hasattr(svcMgr,"CutFlowSvc"): svcMgr += CfgMgr.CutFlowSvc() svcMgr.CutFlowSvc.InputStream = inputStreamName - # svcMgr.CutFlowSvc.OutputLevel = 1 #=VERBOSE + #if not hasattr(svcMgr,"FileCutFlowSvc"): svcMgr += CfgMgr.FileCutFlowSvc() + #svcMgr.FileCutFlowSvc.InputStream = inputStreamName + + # Make sure MetaDataSvc is ready + if not hasattr(svcMgr,'MetaDataSvc'): + from EventSelectorAthenaPool.EventSelectorAthenaPoolConf import MetaDataSvc + svcMgr += MetaDataSvc( "MetaDataSvc" ) + + # Add BookkeeperTools + from EventBookkeeperTools.EventBookkeeperToolsConf import BookkeeperTool + + # Standard event bookkeepers + inname = "CutBookkeepers" + outname = "FileBookkeepers" + cutflowtool = BookkeeperTool(outname, + OutputLevel = 2, + InputCollName = inname, + OutputCollName= outname) + svcMgr.ToolSvc += cutflowtool + + # Add tool to MetaDataSvc + svcMgr.MetaDataSvc.MetaDataTools += [cutflowtool] + + # Add pdf sum of weights counts if appropriate + from AthenaCommon.GlobalFlags import globalflags + if globalflags.DataSource() == 'geant4': + #from PyUtils import AthFile + #afc = AthFile.fopen( svcMgr.EventSelector.InputCollections[0] ) + + # PDF + name = "PDFSumOfWeights" + pdfweighttool = BookkeeperTool(name, + OutputLevel = 2, + OutputCollName= name, + InputCollName = name) + svcMgr.ToolSvc += pdfweighttool + + # Add tool to MetaDataSvc + svcMgr.MetaDataSvc.MetaDataTools += [pdfweighttool] + # Check if we have a sequence given if not seq : @@ -104,10 +141,38 @@ def CreateCutFlowSvc( svcName="CutFlowSvc", athFile=None, seq=None, addAlgInPlac from OutputStreamAthenaPool.MultipleStreamManager import MSMgr # Explicitely add file metadata from input and from transient store, # but only the ones that we always create. - MSMgr.AddMetaDataItemToAllStreams( "xAOD::CutBookkeeperContainer#CutBookkeepers" ) - MSMgr.AddMetaDataItemToAllStreams( "xAOD::CutBookkeeperAuxContainer#CutBookkeepersAux.*" ) - MSMgr.AddMetaDataItemToAllStreams( "xAOD::CutBookkeeperContainer#IncompleteCutBookkeepers" ) - MSMgr.AddMetaDataItemToAllStreams( "xAOD::CutBookkeeperAuxContainer#IncompleteCutBookkeepersAux.*" ) + MSMgr.AddMetaDataItemToAllStreams( "xAOD::CutBookkeeperContainer#"+SGkey ) + MSMgr.AddMetaDataItemToAllStreams( "xAOD::CutBookkeeperAuxContainer#"+SGkey+"Aux.*" ) + MSMgr.AddMetaDataItemToAllStreams( "xAOD::CutBookkeeperContainer#Incomplete"+SGkey ) + MSMgr.AddMetaDataItemToAllStreams( "xAOD::CutBookkeeperAuxContainer#Incomplete"+SGkey+"Aux.*" ) + SGkey = "FileBookkeepers" + MSMgr.AddMetaDataItemToAllStreams( "xAOD::CutBookkeeperContainer#"+SGkey ) + MSMgr.AddMetaDataItemToAllStreams( "xAOD::CutBookkeeperAuxContainer#"+SGkey+"Aux.*" ) + MSMgr.AddMetaDataItemToAllStreams( "xAOD::CutBookkeeperContainer#Incomplete"+SGkey ) + MSMgr.AddMetaDataItemToAllStreams( "xAOD::CutBookkeeperAuxContainer#Incomplete"+SGkey+"Aux.*" ) pass return + +def CreateBookkeeperTool( name="CutBookkeepers" ): + + from AthenaCommon.AppMgr import ServiceMgr as svcMgr + + # Make sure MetaDataSvc is ready + if not hasattr(svcMgr,'MetaDataSvc'): + from EventSelectorAthenaPool.EventSelectorAthenaPoolConf import MetaDataSvc + svcMgr += MetaDataSvc( "MetaDataSvc" ) + + # Add BookkeeperTools + from EventBookkeeperTools.EventBookkeeperToolsConf import BookkeeperTool + + # Standard event bookkeepers + cutflowtool = BookkeeperTool(name, + InputCollName=name, + OutputCollName = name) + svcMgr.ToolSvc += cutflowtool + + # Add tool to MetaDataSvc + svcMgr.MetaDataSvc.MetaDataTools += [cutflowtool] + + return diff --git a/Event/EventBookkeeperTools/src/EventCounterAlg.cxx b/Event/EventBookkeeperTools/src/EventCounterAlg.cxx index 21f3e991ede..6483fbc951e 100644 --- a/Event/EventBookkeeperTools/src/EventCounterAlg.cxx +++ b/Event/EventBookkeeperTools/src/EventCounterAlg.cxx @@ -109,7 +109,10 @@ StatusCode EventCounterAlg::execute() std::stringstream sstm2; sstm2 << "non-nominal MC event weight number " << i; const std::string& cutDescription = sstm2.str(); - CutIdentifier cutID = cutFlowSvc()->registerCut( cutName, cutDescription, this->cutID() ); + CutIdentifier cutID = cutFlowSvc()->registerTopFilter( cutName, + cutDescription, + xAOD::CutBookkeeper::CutLogic::ALLEVENTSPROCESSED, + "AllStreams" ); m_mcCutIDs.push_back(cutID); } } diff --git a/Event/EventBookkeeperTools/src/FileCutFlowSvc.cxx b/Event/EventBookkeeperTools/src/FileCutFlowSvc.cxx new file mode 100644 index 00000000000..ef0957997f8 --- /dev/null +++ b/Event/EventBookkeeperTools/src/FileCutFlowSvc.cxx @@ -0,0 +1,549 @@ +///////////////////////// -*- C++ -*- ///////////////////////////// + +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +// Implementation file for class FileCutFlowSvc +// Authors: Joao Firmino da Costa <joao.costa@cern.ch> and David Cote <david.cote@cern.ch> +/////////////////////////////////////////////////////////////////// + +#include "FileCutFlowSvc.h" + +// STL include +#include <algorithm> + +// #include "FillEBCFromFlat.h" + +#include "GaudiKernel/Incident.h" +#include "GaudiKernel/FileIncident.h" +#include "StoreGate/StoreClearedIncident.h" +#include "GaudiKernel/IIncidentSvc.h" +#include <TTree.h> +#include <TFile.h> + +// EDM includes +#include "xAODCutFlow/CutBookkeeper.h" +#include "xAODCutFlow/CutBookkeeperContainer.h" +#include "xAODCutFlow/CutBookkeeperAuxContainer.h" +#include "EventBookkeeperMetaData/EventBookkeeperCollection.h" +#include "EventBookkeeperMetaData/EventBookkeeper.h" +#include "xAODEventInfo/EventInfo.h" +#include "EventInfo/EventStreamInfo.h" + + +FileCutFlowSvc::FileCutFlowSvc(const std::string& name, + ISvcLocator* pSvcLocator ) : + AthService(name, pSvcLocator), + m_outMetaDataStore("StoreGateSvc/MetaDataStore", name), + m_inMetaDataStore("StoreGateSvc/InputMetaDataStore", name), + m_eventStore("StoreGateSvc", name), + m_completeCollName(""), + m_incompleteCollName(""), + m_skimmingCycle(0), + m_fileCollName("CutBookkeepersFile"), + m_inputStream(""), + m_alreadyDeterminedCycleNumber(false) +{ + declareProperty("OutputCollName", m_completeCollName="CutBookkeepers", + "DEFUNCT - handled by tool now"); + declareProperty("OutputIncompleteCollName", m_incompleteCollName = "IncompleteCutBookkeepers", + "DEFUNCT - handled by tool now"); + declareProperty("SkimmingCycle", m_skimmingCycle = 0, "DEFUNCT - handled automatically"); + declareProperty("InputStream", m_inputStream = "N/A", "The name of the input file stream"); + assert( pSvcLocator ); +} + + + +FileCutFlowSvc::~FileCutFlowSvc() +{ +} + + + +StatusCode +FileCutFlowSvc::initialize() +{ + ATH_MSG_DEBUG( "Initializing " << name() << " - package version " << PACKAGE_VERSION ); + + //Get output MetaData StoreGate + ATH_CHECK( m_outMetaDataStore.retrieve() ); + //Get input MetaData StoreGate + ATH_CHECK( m_inMetaDataStore.retrieve() ); + //Get Event StoreGate + ATH_CHECK( m_eventStore.retrieve() ); + + // Align File name with complete name + m_fileCollName = m_completeCollName + "File"; + + //Get IncidentSvc + ServiceHandle<IIncidentSvc> incSvc("IncidentSvc", this->name()); + ATH_CHECK( incSvc.retrieve() ); + incSvc->addListener(this, IncidentType::BeginInputFile, 60); // pri has to be < 100 to be after MetaDataSvc. + incSvc->addListener(this, IncidentType::EndInputFile, 50); // pri has to be > 10 to be before MetaDataSvc. + incSvc->addListener(this, "MetaDataStop", 50); + + xAOD::CutBookkeeperContainer* fileBook(NULL); + fileBook = new xAOD::CutBookkeeperContainer(); + ATH_CHECK( recordCollection( fileBook, m_fileCollName) ); + if (m_outMetaDataStore->retrieve(m_completeBook,m_fileCollName).isFailure()) { + ATH_MSG_ERROR("Could not retrieve handle to cutflowsvc bookkeeper"); + //return StatusCode::RECOVERABLE; + } + + // Determine the skimming cycle number that we should use now from the input file + ATH_MSG_VERBOSE("Have currently the cycle number = " << m_skimmingCycle ); + ATH_CHECK( this->determineCycleNumberFromInput(m_completeCollName) ); + ATH_MSG_VERBOSE("Will use cycle number = " << m_skimmingCycle ); + + return StatusCode::SUCCESS; +} + + +StatusCode +FileCutFlowSvc::stop() +{ + return StatusCode::SUCCESS; +} + + +StatusCode +FileCutFlowSvc::finalize() +{ + ATH_MSG_DEBUG( "Finalizing " << name() << " - package version " << PACKAGE_VERSION ); + return StatusCode::SUCCESS; +} + + + +StatusCode +FileCutFlowSvc::queryInterface( const InterfaceID& riid, void** ppvi ) +{ + // valid placeholder? + if ( 0 == ppvi ) { return StatusCode::FAILURE ; } // RETURN + if ( ICutFlowSvc::interfaceID() == riid ) { + *ppvi = static_cast<ICutFlowSvc*>(this); + addRef(); // NB! : inrement the reference count! + return StatusCode::SUCCESS; // RETURN + } + // Interface is not directly availible: try out a base class + return AthService::queryInterface( riid, ppvi ); +} + + +CutIdentifier FileCutFlowSvc::registerFilter( const std::string& name, + const std::string& description ) +{ + ATH_MSG_DEBUG("calling registerFilter(" << name << ", " << description << ")" ); + + xAOD::CutBookkeeper* tmpEBK = new xAOD::CutBookkeeper(); + tmpEBK->setName(name); + tmpEBK->setDescription(description); + tmpEBK->setInputStream(m_inputStream); + tmpEBK->setCycle(m_skimmingCycle); + CutIdentifier cutID = tmpEBK->uniqueIdentifier(); + + // Let's see if an CutBookkeeper of this name already exists + ATH_MSG_VERBOSE("in registerFilter(" << name << ", " << description << "): " + << "Going to search if this CutBookkeeper already exists" ); + bool existsAlready=false; + for ( std::size_t i=0; i<m_completeBook->size(); ++i ) { + xAOD::CutBookkeeper* ebk = m_completeBook->at(i); + if( tmpEBK->isEqualTo( ebk) ) { + ATH_MSG_DEBUG("The CutBookkeeper with name " << name + << " and cutID " << cutID << " already exists... not adding!" ); + existsAlready = true; + cutID = ebk->uniqueIdentifier(); + break; + } + } + + ATH_MSG_VERBOSE("in registerFilter(" << name << ", " << description << "): " + << "Found it: " << existsAlready ); + + // If this CutBookkeeper already exists, delete the temporary + // and return the existing cutID + if ( existsAlready ) { + delete tmpEBK; + return cutID; + } + + // If it is a new CutBookkeeper, add it to the container + ATH_MSG_DEBUG( "You are DECLARING a new filter of name " << name + << " and cutID " << cutID ); + m_completeBook->push_back(tmpEBK); + + ATH_MSG_VERBOSE("done calling registerFilter(" << name << ", " << description << ")" ); + return cutID; +} + + + + +CutIdentifier FileCutFlowSvc::registerCut( const std::string& name, + const std::string& description, + CutIdentifier originCutID ) +{ + ATH_MSG_DEBUG("calling registerCut(" << name << ", " << description + << ", " << originCutID << ")" ); + + // Get the CutBookkeeper of the origin Filter Algorithm/Tool + xAOD::CutBookkeeper *originEBK = this->getCutBookkeeper(originCutID); + if ( !originEBK ) { + ATH_MSG_ERROR( "(file: " __FILE__ << ", line: " << __LINE__ << ") " + << "Couldn't find CutBookkeeper with cutID " << originCutID ); + return 0; + } + + // Call the registerFilter method and get the correct CutBookkeeper + // from the returned cutID + CutIdentifier cutID = this->registerFilter( name, description ); + xAOD::CutBookkeeper* ebk = this->getCutBookkeeper(cutID); + if ( !ebk ) { + ATH_MSG_ERROR( "(file: " __FILE__ << ", line: " << __LINE__ << ") " + << "Couldn't find CutBookkeeper with cutID " << cutID ); + return 0; + } + originEBK->addUsedOther( ebk ); + + return cutID; +} + + + + +// This method is probably only called by the DecionsSvc +CutIdentifier FileCutFlowSvc::registerTopFilter( const std::string& name, + const std::string& description, + unsigned int logic, + const std::string& outputStream ) +{ + ATH_MSG_DEBUG("calling registerTopFilter(" << name << ", " << description + << ", " << logic << ", " << outputStream << ")" ); + // Call the registerFilter method and get the correct CutBookkeeper + // from the returned cutID + CutIdentifier cutID = this->registerFilter( name, description ); + xAOD::CutBookkeeper* ebk = this->getCutBookkeeper(cutID); + if ( !ebk ) { + ATH_MSG_ERROR( "(file: " __FILE__ << ", line: " << __LINE__ << ") " + << "Couldn't find CutBookkeeper with cutID " << cutID ); + return 0; + } + + //Then set the logic and outputStream of the relevant CutBookkeeper + // toFind->setDescription(description); + ebk->setCutLogic(xAOD::CutBookkeeper::CutLogic(logic)); + ebk->setTopFilter(true); + ebk->addOutputStreamForAllUsed(outputStream); + + return cutID; +} + + + +CutIdentifier FileCutFlowSvc::declareUsedOtherFilter( const std::string& name, + CutIdentifier originCutID ) +{ + ATH_MSG_DEBUG("calling declareUsedOtherFilter(" << name << ", " << originCutID << ")" ); + + // Get the CutBookkeeper of the origin cut + xAOD::CutBookkeeper *originEBK = this->getCutBookkeeper(originCutID); + if ( !originEBK ) { + ATH_MSG_ERROR( "(file: " << __FILE__ << ", line: " << __LINE__ << ") " + << "Couldn't find CutBookkeeper with cutID " << originCutID ); + return 0; + } + + // Create a temporary CutBookkeeper object + xAOD::CutBookkeeper* tmpEBK = new xAOD::CutBookkeeper(); + // tmpEBK->makePrivateStore(); + tmpEBK->setName(name); + tmpEBK->setInputStream(m_inputStream); + tmpEBK->setCycle(m_skimmingCycle); + CutIdentifier cutID = tmpEBK->uniqueIdentifier(); + + // See if the CutBookkeeper already exists or not + bool existsAlready = false; + for ( std::size_t i=0; i<m_completeBook->size(); ++i ) { + xAOD::CutBookkeeper* ebk = m_completeBook->at(i); + if( tmpEBK->isEqualTo( ebk ) ) { + originEBK->addUsedOther( ebk ); + cutID = ebk->uniqueIdentifier(); + existsAlready = true; + } + } + + // If this CutBookkeeper already exists, delete the temporary + // and return the existing cutID + if ( existsAlready ) { + delete tmpEBK; + return cutID; + } + + // Otherwise, add the new one to the collection + tmpEBK->setDescription( "Registered by origin filter" ); + originEBK->addUsedOther( tmpEBK ); + m_completeBook->push_back( tmpEBK ); + + return cutID; +} + + + +void +FileCutFlowSvc::setFilterDescription( CutIdentifier cutID, + const std::string& descr ) +{ + ATH_MSG_DEBUG("calling setFilterDescription(" << cutID << ", " << descr << ")" ); + + xAOD::CutBookkeeper* ebk = this->getCutBookkeeper(cutID); + ebk->setDescription(descr); + return; +} + + + + +void +FileCutFlowSvc::addEvent( CutIdentifier cutID ) +{ + ATH_MSG_INFO("calling addEvent(" << cutID << ")" ); + + double evtWeight=1.0; + + const xAOD::EventInfo* evtInfo = 0; + StatusCode sc = m_eventStore->retrieve(evtInfo); + if ( sc.isFailure() || NULL == evtInfo ) { + ATH_MSG_WARNING("Could not retrieve EventInfo from StoreGate "); + evtWeight=-1000.; + } else { + // Only try to access the mcEventWeight is we are running on Monte Carlo, duhhh! + if ( evtInfo->eventType(xAOD::EventInfo::IS_SIMULATION) ) { + evtWeight = evtInfo->mcEventWeight(); + } + } + + addEvent(cutID,evtWeight); + + return; +} + + + +void +FileCutFlowSvc::addEvent( CutIdentifier cutID, double weight) +{ + ATH_MSG_INFO("calling addEvent(" << cutID << ", " << weight << ")" ); + + xAOD::CutBookkeeper* eb = this->getCutBookkeeper(cutID); + if ( !eb ) { + ATH_MSG_INFO("Could not find eb"); + + // Iterate over the complete bookkeepers and update the cutID-to-bookkeeper map + ATH_MSG_DEBUG( "addEvent: Going to re-populate the map. Have " + << m_completeBook->size() << " CutBookkeepers" + << " and skimming cycle " << m_skimmingCycle + << " and input Stream name " << m_inputStream ); + xAOD::CutBookkeeperContainer::iterator iter = m_completeBook->begin(); + xAOD::CutBookkeeperContainer::iterator iterEnd = m_completeBook->end(); + for ( ; iter != iterEnd; ++iter ) { + xAOD::CutBookkeeper* ebk = *iter; + CutIdentifier cutID = ebk->uniqueIdentifier(); + ATH_MSG_VERBOSE( "addEvent: Have CutBookkeeper with" + << " skimming cycle " << ebk->cycle() + << " and input Stream name " << ebk->inputStream() + << " and logic " << ebk->cutLogic() + << " isTopFilter " << ebk->isTopFilter() + << " and cutID " << cutID + << " and name " << ebk->name() ); + if ( m_skimmingCycle == ebk->cycle() ) { + if ( m_inputStream == ebk->inputStream() ) { + CutIDMap_t::iterator mapIter = m_ebkMap.find(cutID); + ATH_MSG_DEBUG( "BeginInputFile: Have CutBookkeeper with" + << " cutID " << cutID + << " and name " << ebk->name() ); + if ( mapIter != m_ebkMap.end() ) { // we found this CutBookkeeper in the existing map + (*mapIter).second = ebk; + } + } + } + } // End: Loop over all complete CutBookkeepers + eb = this->getCutBookkeeper(cutID); + } + if ( !eb ) { + ATH_MSG_ERROR ( "Got a zero pointer to an CutBookkeeper with cutID=" + << cutID << "! This should never happen..." ); + return; + } + ATH_MSG_VERBOSE( "addEvent: have cutID " << cutID + << " and CutBookkeeper name " << eb->name() ); + eb->addNAcceptedEvents(1); + eb->addSumOfEventWeights(weight); + eb->addSumOfEventWeightsSquared(weight*weight); + return; +} + + + +//__________________________________________________________________________ +void FileCutFlowSvc::handle( const Incident& inc ) +{ + ATH_MSG_VERBOSE( "Start incident " << inc.type() ); + + //OPENING NEW INPUT FILE + //Things to do: + // 1) note that a file is currently opened + // 2) Load CutBookkeepers from input file + // 2a) if incomplete from input, directly propagate to output + // 2b) if complete from input, wait for EndInputFile to decide what to do in output + + if ( inc.type() == IncidentType::BeginInputFile ) { + // Check the stream name + const EventStreamInfo* esi; + if (m_inMetaDataStore->retrieve(esi).isFailure()) { + ATH_MSG_WARNING("No EventStreamInfo taking stream from property InputStream"); + } + else { + std::string inputstream = *(esi->getProcessingTags().begin()); + if (m_inputStream.empty()) {m_inputStream=inputstream;} + else if (m_inputStream!=inputstream) { + const FileIncident* finc = dynamic_cast<const FileIncident*>(&inc); + ATH_MSG_FATAL("File " << finc->fileName() + << " stream " << inputstream + << " does not match previous file " + << m_inputStream); + return; + } + } + + // Clear the file bookkeeper + if (m_completeBook.isValid()) { + // Reset existing container + for (xAOD::CutBookkeeperContainer::iterator it = m_completeBook->begin(); + it != m_completeBook->end(); ++it) { + (*it)->setNAcceptedEvents(0); + (*it)->setSumOfEventWeights(0); + (*it)->setSumOfEventWeightsSquared(0); + } + } + } + + // Clean up the bookkeeper before output + //if ( inc.type() == "MetaDataStop" || inc.type() == "EndInputFile") { + if ( inc.type() == "MetaDataStop" ) { + if (m_completeBook.isValid()) { + // Reset existing container + for (xAOD::CutBookkeeperContainer::iterator it = m_completeBook->begin(); + it != m_completeBook->end(); ++it) { + } + } + const xAOD::CutBookkeeperContainer* fileBook(NULL); + if( !(m_outMetaDataStore->retrieve(fileBook, m_fileCollName) ).isSuccess() ) { + ATH_MSG_WARNING( "Could not get " << m_fileCollName + << " CutBookkeepers from output MetaDataStore" ); + } + else { + const SG::IConstAuxStore* fileBookAux = fileBook->getConstStore(); + if (m_outMetaDataStore->removeDataAndProxy(fileBook).isFailure()) { + ATH_MSG_ERROR("Unable to remove " << m_fileCollName); + } + if (m_outMetaDataStore->removeDataAndProxy(fileBookAux).isFailure()) { + ATH_MSG_ERROR("Unable to remove " << m_fileCollName); + } + } + } + + ATH_MSG_DEBUG( "End incident " << inc.type() ); + return; +} + + +void +FileCutFlowSvc::print() +{ + return; +} + + +StatusCode FileCutFlowSvc::determineCycleNumberFromInput( const std::string& collName ) +{ + ATH_MSG_DEBUG("calling determineCycleNumberFromInput('" << collName + << "')... have currently cycle number = " << m_skimmingCycle ); + + // Try to get CutBookkeepers from the input file + if ( m_inMetaDataStore->contains<xAOD::CutBookkeeperContainer>(collName) ) { + ATH_MSG_VERBOSE("Found xAOD::CutBookkeeperContainer in input MetaStore with name: " << collName); + + // There can always only be a single object in the input store. As the store + // is connected to just a single input file. + const xAOD::CutBookkeeperContainer* constColl = 0; + ATH_CHECK( m_inMetaDataStore->retrieve( constColl, collName ) ); + xAOD::CutBookkeeperContainer* tmpColl = const_cast<xAOD::CutBookkeeperContainer*>(constColl); + if ( !(tmpColl->hasStore()) ) { + ATH_MSG_VERBOSE("Setting store of xAOD::CutBookkeeperContainer"); + // Get also the auxilliary store + // const SG::IConstAuxStore* auxColl = 0; + const xAOD::CutBookkeeperAuxContainer* auxColl = 0; + ATH_CHECK( m_inMetaDataStore->retrieve(auxColl, collName+"Aux.") ); + tmpColl->setConstStore( auxColl ); + } + // Now, iterate over all CutBookkeepers and search for the highest cycle number + int maxCycle=0; + for ( std::size_t i=0; i<tmpColl->size(); ++i ) { + // Get the current old EBK + const xAOD::CutBookkeeper* cbk = tmpColl->at(i); + int inCycle = cbk->cycle(); + if (inCycle > maxCycle) maxCycle = inCycle; + } + m_skimmingCycle = std::max(m_skimmingCycle,maxCycle+1); + } + + ATH_MSG_DEBUG("done calling determineCycleNumberFromInput('" << collName + << "')... have now cycle number = " << m_skimmingCycle ); + return StatusCode::SUCCESS; +} + + + +StatusCode +FileCutFlowSvc::recordCollection( xAOD::CutBookkeeperContainer * coll, + const std::string &collName) { + ATH_MSG_VERBOSE("calling recordCollection(..., " << collName << ")" ); + + //Expected that FileCutFlowSvc is the only one allowed to record *coll + if( m_outMetaDataStore->contains<xAOD::CutBookkeeperContainer>(collName) ) { + ATH_MSG_ERROR( "xAOD::CutBookkeeperContainer " << collName + << " already exists in output MetaData store. This is unexpected." ); + return StatusCode::FAILURE; + } + + // Record the container + ATH_CHECK( m_outMetaDataStore->record(coll, collName) ); + ATH_MSG_VERBOSE("Recorded xAOD::CutBookkeeperContainer " << collName); + + + // Take care of the peculiarities of the new xAOD EDM, i.e., create the needed AuxStore + xAOD::CutBookkeeperAuxContainer* auxCont = new xAOD::CutBookkeeperAuxContainer; + coll->setStore( auxCont ); //gives it a new associated aux container + + // Record the aux container + ATH_CHECK( m_outMetaDataStore->record( auxCont, collName+"Aux." ) ); + ATH_MSG_VERBOSE( "Recorded xAOD::CutBookkeeperContainer " << collName << "Aux." ); + + return StatusCode::SUCCESS; +} + + + +xAOD::CutBookkeeper* +FileCutFlowSvc::getCutBookkeeper( const CutIdentifier cutID ) { + xAOD::CutBookkeeperContainer::iterator it = m_completeBook->begin(); + xAOD::CutBookkeeperContainer::iterator ite = m_completeBook->end(); + while (it != ite) { + if ((*it)->uniqueIdentifier()==cutID) return (*it); + ++it; + } + return 0; +} + diff --git a/Event/EventBookkeeperTools/src/FileCutFlowSvc.h b/Event/EventBookkeeperTools/src/FileCutFlowSvc.h new file mode 100644 index 00000000000..4060db8fbe1 --- /dev/null +++ b/Event/EventBookkeeperTools/src/FileCutFlowSvc.h @@ -0,0 +1,204 @@ +///////////////////////// -*- C++ -*- ///////////////////////////// + +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +// Header file for class FileCutFlowSvc +// Authors: Joao Firmino da Costa <joao.costa@cern.ch> and David Cote <david.cote@cern.ch> + +/////////////////////////////////////////////////////////////////// +#ifndef FILECUTFLOWSVC_H +#define FILECUTFLOWSVC_H + +/** + * @class FileCutFlowSvc + * @brief This implementes the methods for ICutFlowSvc + */ + +// for size_t +#include <cassert> + +// STL includes +#include <string> +#include <vector> + +// FrameWork includes +#include "GaudiKernel/ISvcLocator.h" +#include "GaudiKernel/IIncidentListener.h" +#include "GaudiKernel/ServiceHandle.h" +#include "StoreGate/DataHandle.h" + +// Athena includes +#include "AthenaBaseComps/AthService.h" +#include "AthenaKernel/ICutFlowSvc.h" +#include "StoreGate/StoreGateSvc.h" + +// EDM includes +#include "xAODCutFlow/CutBookkeeper.h" +#include "xAODCutFlow/CutBookkeeperContainer.h" +#include "xAODCutFlow/CutBookkeeperAuxContainer.h" + +// STL include(s): +#if __cplusplus < 201100 +# include <tr1/unordered_map> +namespace MAP_NS = std::tr1; +#else +# include <unordered_map> +namespace MAP_NS = std; +#endif // C++ + +// forward declarations +class EventBookkeeperCollection; +class EventBookkeeper; + + + +class FileCutFlowSvc : + virtual public ICutFlowSvc, + virtual public IIncidentListener, + public AthService +{ + +public: + +/// Constructor + FileCutFlowSvc(const std::string& name, ISvcLocator* pSvcLocator ); + + /// Destructor + virtual ~FileCutFlowSvc(); + + /// Gaudi Service Implementation + //@{ + StatusCode initialize(); + StatusCode stop(); + StatusCode finalize(); + StatusCode queryInterface( const InterfaceID& riid, void** ppvi ); + //@} + + + /// Incident service handle listening for BeginFile and EndFile. + void handle(const Incident& incident); + + /////////////////////////////////////////////////////////////////// + // Non-const methods: + /////////////////////////////////////////////////////////////////// + +public: + + /// Register filter in the FileCutFlowSvc and returns the CutID of the + /// corresponding CutBookkeeper. + /// This method should be used by filters that register themselves. + CutIdentifier registerFilter( const std::string& name, + const std::string& description ) override final; + + /// Register cut as child of a filter in the FileCutFlowSvc and returns the CutID + /// of the corresponding CutBookkeeper. This method should be used by + /// filters to register their internal cuts that are not the Algs themselves. + CutIdentifier registerCut( const std::string& name, + const std::string& description, + CutIdentifier originCutID ) override final; + + /// Tells FileCutFlowSvc that a filter is used directly by an outputStream with + /// a given logical context. The only foreseen client should the DecisionSvc, + /// with its Accept/Require/Veto. + CutIdentifier registerTopFilter( const std::string& name, + const std::string& description, + unsigned int logic, + const std::string& outputStream ) override final; + + /// Tells FileCutFlowSvc that a filter should not be treated as as being used by + /// another filter. This should be used by filters that use other filter Algs + /// internally, e.g., like the LogicalFilterCombiner + CutIdentifier declareUsedOtherFilter( const std::string& name, + CutIdentifier originCutID ) override final; + + /// Set the description of an existing CutBookkeeper + void setFilterDescription( CutIdentifier cutID, + const std::string& descr ) override final; + + /// Tells FileCutFlowSvc to update the event counter of a CutIdentifier cutID, + /// using the CutIdentifier returned by selfRegisterFilter or registerCut + /// Internally, the Monte Carlo event weight will be retrieved from the + /// xAOD::EventInfo object as evtWeight = evtInfo->mcEventWeight(); + void addEvent( CutIdentifier cutID ) override final; + + /// Tells FileCutFlowSvc to update the weighted event counter of a CutIdentifier cutID, + /// using CutIdentifier returned by selfRegisterFilter or registerCut + void addEvent( CutIdentifier cutID, double weight ) override final; + + /// Get a CutBookkeeper given a CutID + xAOD::CutBookkeeper* getCutBookkeeper( const CutIdentifier cutID ); + + void print(); + +private: + /// Helper function to determine the processing cycle number from the + /// input meta-data store + StatusCode determineCycleNumberFromInput( const std::string& collName ); + + /// Helper function to record the collection (and its aux store) to the + /// output MetaData store + StatusCode recordCollection( xAOD::CutBookkeeperContainer* coll, + const std::string &collName ); + + /// Create a typedef + typedef ServiceHandle<StoreGateSvc> StoreGateSvc_t; + + /// The output meta-data store + StoreGateSvc_t m_outMetaDataStore; + + /// The input meta-data store + StoreGateSvc_t m_inMetaDataStore; + + /// The event store + StoreGateSvc_t m_eventStore; + + DataHandle<xAOD::CutBookkeeperContainer> m_completeBook; + + /// The name of the completed, i.e., fully processed, CutBookkeeperContainer + std::string m_completeCollName; + + /// The name of the incomplete, i.e., not fully processed (e.g. failed job), CutBookkeeperContainer + std::string m_incompleteCollName; + + /// The current skimming cycle, i.e., how many processing stages we already had + int m_skimmingCycle; + + /// The name of the container in storegate with cutflow values for a file. + std::string m_fileCollName; + + /// The name of the currently used input file stream + std::string m_inputStream; + + /// A flag to say if the input file is currently open or not + //bool m_fileCurrentlyOpened; + + /// Declare a simple typedef for the internal map + typedef MAP_NS::unordered_map<CutIdentifier, xAOD::CutBookkeeper*> CutIDMap_t; + + /// This internal map keeps the association between the instance identifier of each algorithm + /// to the pointer of associated CutBookkeeper + CutIDMap_t m_ebkMap; + + /// Internal flag to track if we have already determined the cycle number from the first input file + bool m_alreadyDeterminedCycleNumber; + +public: + + /// Publish the interface for this service + static const InterfaceID& interfaceID(); + +}; + + + +/////////////////////////////////////////////////////////////////// +// Inline methods: +/////////////////////////////////////////////////////////////////// + +inline const InterfaceID& FileCutFlowSvc::interfaceID() { + return ICutFlowSvc::interfaceID(); +} + +#endif //> !FILECUTFLOWSVC_H diff --git a/Event/EventBookkeeperTools/src/components/EventBookkeeperTools_entries.cxx b/Event/EventBookkeeperTools/src/components/EventBookkeeperTools_entries.cxx index 383b2149695..d02d62cf31e 100644 --- a/Event/EventBookkeeperTools/src/components/EventBookkeeperTools_entries.cxx +++ b/Event/EventBookkeeperTools/src/components/EventBookkeeperTools_entries.cxx @@ -2,6 +2,7 @@ #include "EventBookkeeperTools/myCppFilterTest.h" #include "../SkimDecisionMultiFilter.h" +#include "../FileCutFlowSvc.h" #include "../CutFlowSvc.h" #include "EventBookkeeperTools/BookkeeperTool.h" #include "../EventSelectorCounterTool.h" @@ -13,6 +14,7 @@ DECLARE_ALGORITHM_FACTORY( EventCounterAlg ) DECLARE_TOOL_FACTORY( EventSelectorCounterTool ) DECLARE_TOOL_FACTORY( BookkeeperTool ) DECLARE_SERVICE_FACTORY( CutFlowSvc ) +DECLARE_SERVICE_FACTORY( FileCutFlowSvc ) DECLARE_FACTORY_ENTRIES(EventBookkeeperTools) { DECLARE_ALGORITHM( myCppFilterTest ); @@ -21,4 +23,5 @@ DECLARE_FACTORY_ENTRIES(EventBookkeeperTools) { DECLARE_ALGTOOL( EventSelectorCounterTool ); DECLARE_ALGTOOL( BookkeeperTool ); DECLARE_SERVICE( CutFlowSvc ); + DECLARE_SERVICE( FileCutFlowSvc ); } -- GitLab