diff --git a/Generators/HepMCWeightSvc/CMakeLists.txt b/Generators/HepMCWeightSvc/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..3443c1b77c30971fd58e66fd65bb7e887201953d --- /dev/null +++ b/Generators/HepMCWeightSvc/CMakeLists.txt @@ -0,0 +1,26 @@ +################################################################################ +# Package: HepMCWeightSvc +################################################################################ + +# Declare the package name: +atlas_subdir( HepMCWeightSvc ) + +# Declare the package's dependencies: +atlas_depends_on_subdirs( PUBLIC + GaudiKernel + PRIVATE + Control/AthenaBaseComps + Database/AthenaPOOL/AthenaPoolUtilities + Database/IOVDbDataModel + Database/IOVDbMetaDataTools + Event/EventInfo ) + +# Component(s) in the package: +atlas_add_component( HepMCWeightSvc + src/*.cxx + src/components/*.cxx + LINK_LIBRARIES GaudiKernel AthenaBaseComps AthenaPoolUtilities IOVDbDataModel EventInfo ) + +# Install files from the package: +atlas_install_headers( HepMCWeightSvc ) + diff --git a/Generators/HepMCWeightSvc/HepMCWeightSvc/IHepMCWeightSvc.h b/Generators/HepMCWeightSvc/HepMCWeightSvc/IHepMCWeightSvc.h new file mode 100644 index 0000000000000000000000000000000000000000..b2958657a0eb7307504810bc526479ed449ccdf8 --- /dev/null +++ b/Generators/HepMCWeightSvc/HepMCWeightSvc/IHepMCWeightSvc.h @@ -0,0 +1,33 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef EVGENPRODTOOLS_IHEPMCWEIGHTSVC_H +#define EVGENPRODTOOLS_IHEPMCWEIGHTSVC_H + +#include "GaudiKernel/IInterface.h" +#include <string> + +/// @brief IService to read/write HepMC's WeightContainer key names from/to IOVMetaDataContainers +/// author: will buttinger , NLAA +/// +/// + +static const InterfaceID IID_IHepMCWeightSvc("IHepMCWeightSvc", 1 , 0); + +class IHepMCWeightSvc : virtual public IInterface { +public: + + + ///checks for any changes to weightnames ... none are allowed. Then records to metadata + virtual StatusCode setWeightNames(const std::map<std::string, std::size_t>& weightNames)= 0; + + ///returns the current weight names ... will only change at file boudaries, it is assumed all events in a given file will have same weights in SAME ORDER + virtual const std::map<std::string, std::size_t>& weightNames() = 0; + + static const InterfaceID& interfaceID() { return IID_IHepMCWeightSvc; } + + +}; + +#endif diff --git a/Generators/HepMCWeightSvc/cmt/requirements b/Generators/HepMCWeightSvc/cmt/requirements new file mode 100644 index 0000000000000000000000000000000000000000..76f08de47a351bd6464eba111939ea9af9bb5dfc --- /dev/null +++ b/Generators/HepMCWeightSvc/cmt/requirements @@ -0,0 +1,35 @@ +## automatically generated CMT requirements file +package HepMCWeightSvc +author will + +## for athena policies: this has to be the first use statement +use AtlasPolicy AtlasPolicy-* + +## for gaudi tools, services and objects +use GaudiInterface GaudiInterface-* External + +private +use EventInfo EventInfo-* Event +use AthenaBaseComps AthenaBaseComps-* Control +use IOVDbMetaDataTools IOVDbMetaDataTools-* Database +use AthenaPoolUtilities AthenaPoolUtilities-* Database/AthenaPOOL +use IOVDbDataModel IOVDbDataModel-* Database +end_private + +## put here your package dependencies... + +## + +branches src src/components doc python share + +private +## default is to make component library +library HepMCWeightSvc *.cxx components/*.cxx + +apply_pattern component_library +apply_pattern declare_joboptions files="*.py" +apply_pattern declare_python_modules files="*.py" + +end_private + + diff --git a/Generators/HepMCWeightSvc/src/HepMCWeightSvc.cxx b/Generators/HepMCWeightSvc/src/HepMCWeightSvc.cxx new file mode 100644 index 0000000000000000000000000000000000000000..192fc330cb454e076eb55e42253b06965cd679bf --- /dev/null +++ b/Generators/HepMCWeightSvc/src/HepMCWeightSvc.cxx @@ -0,0 +1,169 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +#include "HepMCWeightSvc.h" + +#include "AthenaPoolUtilities/CondAttrListCollection.h" + +#include "EventInfo/EventInfo.h" +#include "EventInfo/EventType.h" +#include "EventInfo/EventID.h" +#include "EventInfo/EventStreamInfo.h" + +#include "IOVDbDataModel/IOVMetaDataContainer.h" + +HepMCWeightSvc::HepMCWeightSvc(const std::string& name, ISvcLocator* pSvcLocator) + : AthService(name, pSvcLocator), + m_metaDataTool("IOVDbMetaDataTool"),m_weightNamesLoaded(false) +{ + +} + + +bool HepMCWeightSvc::weightNamesChanged(const std::map<std::string, std::size_t>& weightNames) { + + //check all weights are the same + if(m_currentWeightNames.size() != weightNames.size()) { + return true; + } + auto itr1 = m_currentWeightNames.begin(); + auto itr2 = weightNames.begin(); + + for(;itr1!=m_currentWeightNames.end();++itr1,++itr2) { + if( itr1->first != itr2->first ) return true; + if( itr1->second != itr2->second ) return true; + } + return false; +} + +StatusCode HepMCWeightSvc::initialize() { + ServiceHandle<IIncidentSvc> incsvc("IncidentSvc",name()); + int priority = 100; + incsvc->addListener( this, IncidentType::BeginInputFile, priority); + return StatusCode::SUCCESS; +} + +void HepMCWeightSvc::handle(const Incident& inc) { + if(inc.type()==IncidentType::BeginInputFile) { //resets the weight names + m_weightNamesLoaded = false; + m_currentWeightNames.clear(); + } +} + +StatusCode HepMCWeightSvc::loadWeights() { + //clear the currentWeightNames + m_currentWeightNames.clear(); + m_weightNamesLoaded = true; //regardless of success or failure, we will say the weights are loaded! + + //read the weight map from the metadata, it will be std::map<std::string,int> so we need to convert to our internal type + ServiceHandle<StoreGateSvc> inputMetaStore("StoreGateSvc/InputMetaDataStore",name()); + CHECK( inputMetaStore.retrieve() ); + + const IOVMetaDataContainer* cont = 0; + if(inputMetaStore->retrieve(cont,"/Generation/Parameters").isFailure()) { + //exit quietly... + return StatusCode::SUCCESS; + } + //payload is a collection of condattrlistcollections + //only look a the first one, assuming it exists, and within that only look at the first channel; + if(! (cont->payloadContainer()->size()>0 && cont->payloadContainer()->at(0)->size()>0) ) return StatusCode::FAILURE; + + //need to retrieve the EventStreamInfo to get at the channel number + const EventStreamInfo* esi = 0; + CHECK( inputMetaStore->retrieve(esi) ); + if(esi->getEventTypes().size() == 0) return StatusCode::FAILURE; + int chanNum = esi->getEventTypes().begin()->mc_channel_number(); + if(chanNum==0) { + //perhaps channel number not set yet, use the first run number instead + if(esi->getRunNumbers().size()==0) return StatusCode::FAILURE; + chanNum = *esi->getRunNumbers().begin(); + } + const coral::Attribute& attr = cont->payloadContainer()->at(0)->attributeList(chanNum)["HepMCWeightNames"]; + + std::map<std::string, int> in; + + CHECK( Gaudi::Parsers::parse(in,attr.data<std::string>()) ); + + ATH_MSG_DEBUG("Loaded weightnames: " << attr.data<std::string>()); + + + for(auto& i : in) m_currentWeightNames[i.first] = i.second; + + + + return StatusCode::SUCCESS; + + +} + +StatusCode HepMCWeightSvc::setWeightNames(const std::map<std::string, std::size_t>& weightNames) { + + //ignore any attempt to set 'nothing' for the weight names + if(weightNames.size()==0 || (weightNames.size()==1 && weightNames.begin()->first=="0") ) return StatusCode::SUCCESS; + + if(m_weightNamesLoaded) return StatusCode::SUCCESS; //we only allow setting of weightNames ONCE! ... if the weights have ever been loaded, we will not allow them to be set again! + //effectively means the weights are only set in evgen jobs. + + //check that the weight names correspond to what we have currently. + //if( weightNamesChanged(weightNames) ) { + m_currentWeightNames = weightNames; + + //create and register the metadata containter with these weight names + //use the MetaDataTool to do this + CHECK( m_metaDataTool->registerFolder("/Generation/Parameters","Metadata created during Event Generation") ); + + //create a new attributelist collection for it ... + CondAttrListCollection* cont = new CondAttrListCollection(true /* use regular timestamps, not run-lumiblock timestamps */); + //create a single attribute list + CondAttrListCollection::AttributeList myAttributes; + + //store as strings ... when read back in we use a gaudi parser to parse the list + myAttributes.extend("HepMCWeightNames","string"); + + std::string stringToStore = "{"; + for(auto& name : weightNames) { + if(stringToStore != "{") stringToStore += ", "; + std::stringstream ss; + ss << "'" << name.first << "':" << name.second; stringToStore += ss.str(); + } + stringToStore += "}"; + myAttributes["HepMCWeightNames"].data<std::string>() = stringToStore; + + //use the run-number as the 'channel' ... all weightnames should be the same for the same channel + + //set the start time ... do we set the stop time? + const EventInfo* evt = 0; + ServiceHandle<StoreGateSvc> evtStore("StoreGateSvc/StoreGateSvc",name()); + CHECK( evtStore->retrieve(evt) ); + //IOVTime evtTime; + //evtTime.setRunEvent(evt->event_ID()->run_number(), evt->event_ID()->lumi_block()); + //uint64_t nsTime=evt->event_ID()->time_stamp()*1000000000LL; + //nsTime += evt->event_ID()->time_stamp_ns_offset(); + //evtTime.setTimestamp(nsTime); + //cont->addNewStart(evtTime); + cont->add(evt->event_ID()->run_number(),myAttributes); + + + + ATH_MSG_INFO("Storing /Generation/Parameters :: WeightNames = " << stringToStore); + + //and assign it to 'channel 0' .. consistent with other metadata + + CHECK( m_metaDataTool->addPayload("/Generation/Parameters",cont) ); + + m_weightNamesLoaded=true; + + //} + + return StatusCode::SUCCESS; +} + + +const std::map<std::string,std::size_t>& HepMCWeightSvc::weightNames() { + if(!m_weightNamesLoaded) { + if(loadWeights().isFailure()) { ATH_MSG_WARNING("Unable to load weightnames from metadata ... do not trust the weightnames!"); } + } + return m_currentWeightNames; +} diff --git a/Generators/HepMCWeightSvc/src/HepMCWeightSvc.h b/Generators/HepMCWeightSvc/src/HepMCWeightSvc.h new file mode 100644 index 0000000000000000000000000000000000000000..c4a6da6013248739f87543c4cc81d015d3145146 --- /dev/null +++ b/Generators/HepMCWeightSvc/src/HepMCWeightSvc.h @@ -0,0 +1,65 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef EVGENPRODTOOLS_HEPMCWEIGHTSVC_H +#define EVGENPRODTOOLS_HEPMCWEIGHTSVC_H + +#include "AthenaBaseComps/AthService.h" +#include "HepMCWeightSvc/IHepMCWeightSvc.h" +#include <string> + +#include "IOVDbMetaDataTools/IIOVDbMetaDataTool.h" + +#include "GaudiKernel/IIncidentListener.h" +#include "GaudiKernel/IIncidentSvc.h" + +#include "GaudiKernel/ToolHandle.h" + +/// @brief Service to read/write HepMC's WeightContainer key names from/to IOVMetaDataContainers +/// author: will buttinger , NLAA +/// +/// +class HepMCWeightSvc : public AthService , public IHepMCWeightSvc, virtual public IIncidentListener { +public: + + + + // Constructor and destructor + HepMCWeightSvc(const std::string& name, ISvcLocator* pSvcLocator); + + ~HepMCWeightSvc() {;} + + ///checks for any changes to weightnames ... none are allowed. Then records to metadata + virtual StatusCode setWeightNames(const std::map<std::string, std::size_t>& weightNames); + + ///returns the current weight names ... will only change at file boudaries, it is assumed all events in a given file will have same weights in SAME ORDER + virtual const std::map<std::string, std::size_t>& weightNames(); + + + virtual StatusCode initialize(); + + virtual void handle(const Incident& inc); //listen for beginInputFile and load the weights at that point + + StatusCode queryInterface(const InterfaceID& riid, void** ppvInterface) { + if(IID_IHepMCWeightSvc == riid) { + *ppvInterface = dynamic_cast<IHepMCWeightSvc*>(this); + return StatusCode::SUCCESS; + } + return AthService::queryInterface(riid,ppvInterface); + } + +private: + bool weightNamesChanged(const std::map<std::string, std::size_t>& weightNames); + + StatusCode loadWeights(); //reads from the IOVMetaData + + std::map<std::string, std::size_t> m_currentWeightNames; + + ToolHandle<IIOVDbMetaDataTool> m_metaDataTool; + + bool m_weightNamesLoaded; + +}; + +#endif diff --git a/Generators/HepMCWeightSvc/src/components/HepMCWeightSvc_entries.cxx b/Generators/HepMCWeightSvc/src/components/HepMCWeightSvc_entries.cxx new file mode 100644 index 0000000000000000000000000000000000000000..18dfea8a06c2e59c454fc87e7b71361e256d3ed3 --- /dev/null +++ b/Generators/HepMCWeightSvc/src/components/HepMCWeightSvc_entries.cxx @@ -0,0 +1,8 @@ +#include "GaudiKernel/DeclareFactoryEntries.h" + +#include "../HepMCWeightSvc.h" +DECLARE_SERVICE_FACTORY(HepMCWeightSvc) + +DECLARE_FACTORY_ENTRIES( HepMCWeightSvc ) { + DECLARE_SERVICE(HepMCWeightSvc) +} diff --git a/Generators/HepMCWeightSvc/src/components/HepMCWeightSvc_load.cxx b/Generators/HepMCWeightSvc/src/components/HepMCWeightSvc_load.cxx new file mode 100644 index 0000000000000000000000000000000000000000..573c3c5a41d8531f40697f2d820d2be8dcbbe19e --- /dev/null +++ b/Generators/HepMCWeightSvc/src/components/HepMCWeightSvc_load.cxx @@ -0,0 +1,3 @@ +#include "GaudiKernel/LoadFactoryEntries.h" + +LOAD_FACTORY_ENTRIES(HepMCWeightSvc)