C++ Interface Description for One Modules

Complete: 4

Contacts

Base Class

Each of the three fundamental types of modules, EDProducer, EDFilter and EDAnalyzer, all have their own base class which reside in the edm::one namespace. The base classes are names
  • edm::one::EDProducer<>
  • edm::one::EDFilter<>
  • edm::one::EDAnalyzer<>
All the base classes are templatized and take optional template arguments. The optional template arguments are used to extend the interface and therefore abilities of the base classes. Each of the allowed template arguments are described later in this page.

The interface available to all modules inheriting from the base classes (with or without giving additional template arguments) is described below.

void beginJob()
Called once each job just before processing the data.
void produce(edm::Event&, edm::EventSetup const&)
This is called each Event. This is only available to edm::one::EDProducer<>
bool filter(edm::Event&, edm::EventSetup const&)
This is called each Event. The return value decides whether the modules following the filter on its Paths will be processed this Event. This is only available to edm::one::EDFilter<>
void analyze(edm::Event& const, edm::EventSetup const&)
This is called each Event. This is only available to edm::one::EDAnalyzer<>
void endJob()
Called once each job just after processing has ended.

All methods are non-const and the framework guarantees that only one method will ever be called at a time. Since only one thread at a time will ever be communicating with a module instance the system maintains its thread safety. Member data of a module therefore does not have to be inherently thread safe. However, this constraint causes major performance penalties.

example usage: Writing to a file

We need to see all events in the job and write info about them to a file. This could be accomplished using a edm::global::EDAnalyzer<> but that would require the developer to manual handle the thread safety of the file interaction. This way the system handles it.

//use an anonymous namespace since there is no need for any other file to see these class names
namespace {

class EventBreadcrumbsDropper : public edm::one::EDAnalyzer<> {
public:
   EventBreadcrumbsDropper(edm::ParameterSet const& iPSet):
   m_file(iPSet.getUntrackedParameter<std::string>("fileName"))
   {}
   
   void analyze(edm::Event const& iEvent, edm::EventSetup const&) override {
      //record which event the job saw
      m_file <<iEvent.runNumber()<<" "<<iEvent.id().number()<<std::endl;
   }
private:
   std::ofstream m_file;
};
} //ends namespace

Template Arguments

Each of the base classes can take multiple template arguments. These template arguments allow one to extend the interface in order to get additional information about the state of the system. If multiple template arguments are used, the order of the arguments does not matter.

edm::one::SharedResources

This extension tells the system that this module is using a thread-unsafe resource, e.g. a FORTRAN common block, which some other module type in the system may also try to use. The exact resources being used are obtained from the string passed to the usesResource function calls. The system makes sure that only one module which has declared a usage of a specific resource will ever be run at a time. That is, the system will serialize all calls to all modules which declare that resource.

This extension leads to extreme performance penalties, e.g. if all modules in a job declare usage of the same resource the system will only ever run one module at a time no matter how many threads are available. In addition, if multiple modules in a configuration have declared edm::one::SharedResources only one of them will be constructed at a time, regardless of whether they have overlapping usesResource specifications. The reason is the framework does not know until after the constructor call has completed which resources a module has declared and we can not guarantee that the resource was not accessed during the constructor call. Therefore the safest behavior is to serialize construction of all modules which declare this template argument.

The extended interface is as follows:

void usesResource(std::string const& aNameOfAResource)

void usesResource()

This method must be called in the constructor. The argument names the shared resource to which the module is dependent. Multiple usesResource calls can be made and the framework will guarantee that unique access to all those resources have been obtained before calling a member function of that module instance. If no usesResource call is made in the constructor, the system will throw an exception. When the no argument function is used the system will ensure the module is not run concurrently with any module that declares any shared resource including all other modules that called the no argument function. Performance will better with no shared resources, but if they exist it is much better to call usesResource with a resource name than with no argument.

Classic (or Legacy modules) always behave as if they had a shared resource declared with the no argument form of the usesResource function. This is automatic and the module does not have to call usesResource or modify the inheritance. They will not be run concurrently with each other or with "One" type modules that declare any shared resources.

example usage: Drawing ROOT histograms

ROOT's graphing engine uses global state and is therefore inherently thread unsafe. This particular user isn't sure what resource to use so went with the safest option which is no argument to the usesResource function

//use an anonymous namespace since there is no need for any other file to see these class names
namespace {

class SeedPlotter : public edm::one::EDAnalyzer<edm::one::SharedResources> {
public:
   SeedPlotter(edm::ParameterSet const& iPSet) {
      //record the parameters needed to configure the SeedPlotter
      m_seedTag = iPSet.getParameter<edm::InputTag>("seedTag");

      //state that we use a resource but are not sure which one
      usesResource();
   }
   
   void analyze(edm::Event const& iEvent, edm::EventSetup const&) override {
      edm::Handle<TrackSeeds> hSeeds;
      iEvent.getByLabel(m_seedTag, hSeeds);
 
      //Fill a histogram with the hit distribution
      TH1F h("HitDist", "Distribution of Hits on Seeds",50,0.,50.);
      for(auto const& seed: *hSeeds) {
         h.Fill(seed.numberOfHits());
      }
 
      //Write histogram to a file
      TCanvas c("hit_dist","hit_dist",800,800);
      h->Draw("HIST");
      c.Update();
      c.SaveAs( Form("hist_dist_run_%i_ev_%i",iEvent.runNumber(),iEvent.eventNumber()) );
      
   }
private:
   edm::InputTag m_seedTag;
};
} //ends namespace

example usage: calling FORTRAN

FORTRANs common blocks are inherently thread unsafe since they are globally accessible.

//use an anonymous namespace since there is no need for any other file to see these class names
namespace {

class PythiaProducer : public edm::one::EDProducer<edm::one::SharedResources> {
public:
   PythiaProducer(edm::ParameterSet const& iPSet) {
      //get data from parameters and fill PYTHIA's common blocks
      ...
      pyinit_(...);
      ...
      usesResource("Pythia6");
   }
   
   void produce(edm::Event const& iEvent, edm::EventSetup const&) override {
      //Tell pythia to make a new event
      pyevnt_();

      //call routine which reads from common block and writes to event
      writeEvent(iEvent);            
   }
private:
};
} //ends namespace

edm::one::WatchRuns

This extension allows the module to watch Run transitions. The framework guarantees that the module will not see a new beginRun call until the endRun has been called for the last Run. If a module which extends edm::one::WatchRuns is added to a configuration, the system will only be able to process LuminosityBlocks from one Run at a time (the global begin Run for the next Run can be started before the global end Run for the previous Run has finished).

The extended interface is as follows:

void beginRun(edm::Run const&, edm::EventSetup const&)
This method is called each time the Source sees a new Run, i.e. during the global begin Run transition.
void endRun(edm::Run const&, edm::EventSetup const&)
This method is called after the system has finished processing a given Run, i.e. the global end Run transition. This method is also when data created by edm::EndRunProducers are accessible as well as Run products which are mergeable.

edm::one::WatchLuminosityBlocks

This extension allows the module to watch LuminosityBlock transitions. The framework guarantees that the module will not see a new beginLuminosityBlock call until the endLuminosityBlock has been called for the last LuminosityBlock. If a module which extends edm::one::WatchLuminosityBlocks is added to a configuration, the system will only be able to process Events from one LuminosityBlock at a time (the global begin LuminosityBlock for the next LuminosityBlock can be started before the global end LuminosityBlock for the previous LuminosityBlock has finished).

The extended interface is as follows:

void beginLuminosityBlock(edm::LuminosityBlock const&, edm::EventSetup const&)
This method is called each time the Source sees a new LuminosityBlock.
void endLuminosityBlock(edm::LuminosityBlock const&, edm::EventSetup const&)
This method is called after the system has finished processing a given LuminosityBlock. This method is also when data created by edm::EndLuminosityBlockProducers are accessible as well as LuminosityBlock products which are mergeable.

edm::RunCache<T>

This extension manages information pertaining to Runs and properly handles the case where multiple Runs are occuring in the job at the same time. The actual information stored is up to the developer and is specified to the system based on the template parameter of the edm::RunCache<T> class. Note that the template argument void is an allowed value and can be used in the case where you just want to be informed about the globalEndRun but do not need to store per Run information.

The main reason to use this extension is if the item (or items) requires a lot of memory or a lot of CPU time to construct. Another reason to use this extension is if you must accumulate simple information for a Run.

The extended interface is as follows:

std::shared_ptr<T> globalBeginRun(edm::Run const&, edm::EventSetup const&) const
This method is called each time the Source sees a new Run. The return value is a std::shared_ptr<T> rather than a T* in order to facilitate the possibility of reusing the created object. (See example below.)
T* runCache(edm::RunIndex)
Returns the approriate run cache object created from globalBeginRun. The Run is identified by a edm::RunIndex which can be obtained through the edm::Run (and indirectly through edm::LuminosityBlock and edm::Event.)
void globalEndRun(edm::Run const&, edm::EventSetup const&)
This method is called after all Streams have finished processing a given Run. This method is also when data created by edm::EndRunProducers are accessible as well as Run products which are mergeable.

example usage: counting events in a run

The following example counts the number of events in a Run.

#include <atomic>

//use an anonymous namespace since there is no need for any other file to see these class names
namespace {
struct Count { 
   Count():value(0) {}
   unsigned int value;
};

class MyAnalyzer : public edm::one::EDAnalyzer<edm::RunCache<Count>> {
public:
   MyAnalyzer(edm::ParameterSet const&) {}
   
   std::shared_ptr<Count> globalBeginRun(edm::Run const&, edm::EventSetup const&) const {
       return std::make_shared<Count>();
   }

   void analyze(edm::Event const& iEvent, edm::EventSetup const&){
      ++(runCache(iEvent.getRun().index())->value);
   }

   void globalEndRun(edm::Run const& iRun, edm::EventSetup const&) {
      std::cout <<"Number of events seen in Run "<<iRun.runNumber()<<" = "<<runCache(iRun.index())->value<<std::endl;
   }
};
} //ends namespace

example usage: reusing a heavy weight object that gets updated each run

The following example guarantees that we have a unique instance of a heavy weight object (TrackFitter) for each Run. By using a edm::ReusableObjectHolder<> the system only creates new instances of the TrackFitter if an unused older instance is not available. This guarantees the minimum number of TrackFitters in the job needed without causing the system to wait on Run boundaries. The edm::ReusuableObjectHolder<> is maintained as member data since that allows one to re-use a TrackFitter across Run boundaries.

#include "FWCore/Utilities/interface/ReusableObjectHolder.h"

//use an anonymous namespace since there is no need for any other file to see these class names
namespace {
class ATrackFitter : public edm::one::EDProducer<edm::RunCache<TrackFitter> > {
public:

   ATrackFitter(edm::ParameterSet const& iPSet) {
     //save parameter information needed to createa a TrackFitter
     ...
   }
   
   std::shared_ptr<TrackFitter> globalBeginRun(edm::Run const& iRun, edm::EventSetup const& iES) const {
      //use a lambda to generate a new TrackFitter only if there isn't an old one available
      auto trackFitter = m_holder->makeOrGet( [this](){ return this->makeNewTrackFitter();} );
      trackFitter->update(iRun,iES);
      return trackFitter;
   }

   void producer(edm::Event& iEvent, edm::EventSetup const&) {
      //Get the track you are interested in
      ...
      //Refit the track using the Run specific TrackFitter
      runCache(iEvent.getRun().index())->fit(track);

      //Do what ever else is needed
      ...
   }

private:
  TrackFitter* makeNewTrackFitter() const; //helper function that creates a new TrackFitter based on the saved parameters

  mutable edm::ReusuableObjectHolder<TrackFitter> m_holder;

  //This is where all the data is pulled from the PSet
  ...

};
} //ends namespace

edm::LuminosityBlockCache<T>

This extension manages information pertaining to LuminosityBlocks and properly handles the case where multiple LuminosityBlocks are occuring in the job at the same time. The actual information is up to the developer and is specified to the system based on the template parameter of the edm::LuminosityBlockCache<T> class. Note that the template argument void is an allowed value and can be used in the case where you just want to be informed about the globalEndLuminosityBlock.

The main reason to use this extension is if the item (or items) either requires a lot of memory or a lot of CPU time to construct. Another reason to use this extension is if you must accumulate simple information for a LuminosityBlock.

The extended interface is as follows:

std::shared_ptr<T> globalBeginLuminosityBlock(edm::LuminosityBlock const&, edm::EventSetup const&) const
This method is called each time the Source sees a new LuminosityBlock. The return value is a std::shared_ptr<T> rather than a T* in order to facilitate the possibility of reusing the created object.
T* luminosityBlockCache(edm::LuminosityBlockIndex)
Returns the approriate luminosity block cache object created from globalBeginLuminosityBlock.
void globalEndLuminosityBlock(edm::LuminosityBlock const&, edm::EventSetup const&)
This method is called after all Streams have finished processing a given LuminosityBlock. This method is also when data created by edm::EndLuminosityBlockProducers are accessible as well as LuminosityBlock products which are mergeable.

example usage: updating a helper object only if a condition actually changed

The following example updates a helper class, PositionFinder, only if a particular condition has changed. This code assumes that the condition in question is only allowed to change on LuminosityBlock boundaries (which is the common case). Like the Run example, we will use an edm::ReusableObjectHolder<> object to allow us to reuse old instances of the PositionFinder.

NOTE: The design presented in this example should only be used if all of the following apply

  1. The change of conditions requires a length recalculation and/or the creation of a large memory structure.
  2. The structure created is only useful to this module.
If you just need to have access to an object in the edm::EventSetup it is better just to ask for that item once each Event. Fetching data from the edm::EventSetup is very fast. If the data structure is not modified each Event, consider moving it into the EventSetup directly and let the framework manage the proper updating of the structure.

#include "FWCore/Utilities/interface/ReusableObjectHolder.h"

//use an anonymous namespace since there is no need for any other file to see these class names
namespace {

class MovedItemProducer : public edm::one::EDProducer<edm::LuminosityBlockCache<PositionFinder> > {
public:

   MovedItemProducer(edm::ParameterSet const& iPSet) {
      //store parameters needed to create the PositionFinder
      ...
   }
   
   std::shared_ptr<PositionFinder> globalBeginLuminosityBlock(edm::LuminosityBlock const&, 
                                                              edm::EventSetup const& iES) const {
      std::shared_ptr<PositionFinder> returnValue;
      if(!this->m_watcher.check(iES)) {
         //the condition hasn't changed so we can just use our old value
         returnValue = m_mostRecentPositionFinder;
      } else {
         //the condition has changed so we need to update
         //use a lambda to generate a new PositionFinder only if there isn't an old one available
         returnValue = m_holder->makeOrGet( [this] (){ return this->makeNewPositionFinder();} );
         returnValue->update(iES.get<AlignmentRcd>());
         m_mostRecentPositionFinder = returnValue;
      }
      return returnValue;
   }

   void producer(edm::StreamID, edm::Event& iEvent, edm::EventSetup const&) {
      //Get the item you need to move
      ...
      //Apply the move
      luminosityBlockCache(iEvent.luminosityBlock().luminosityBlockIndex())->move(item);

      //Do what ever else is needed
      ...
   }

private:
  PositionFinder* makeNewPositionFinder() const;

  edm::ReusuableObjectHolder<PositionFinder> m_holder;
  mutable edm::ESWatcher<AlignmentRcd> m_watcher; 
  mutable std::shared_ptr<PositionFinder> m_mostRecentPostionFinder;

  //This is where all the data is pulled from the PSet
  ...
};
} //ends namespace

edm::BeginRunProducer

This extension allows an EDProducer to put data into the Run at the begin of Run transition. Items placed during the begin of Run transition are available to get for any method that directly or indirectly provides a edm::Run.

The extended interface is as follows:

void beginRunProduce(edm::Run&, edm::EventSetup const&)
This method is called each time the Source sees a new Run. The routine is called as part of the global begin run transition.

example usage: pull data from a database and put it into the run

This example will use a fictitious thread-unsafe database interface to retrieve data and then place it into the Run.

//use an anonymous namespace since there is no need for any other file to see these class names
namespace {

class LHCStatusProducer : public edm::one::EDProducer<edm::BeginRunProducer, edm::one::SharedResources> {
public:
   LHCStatusProducer(edm::ParameterSet const& iPSet): m_dbConnection(iPSet.getParameter<std::string>("dbURL")){
      //we need to register the fact that we will make the LHCStatus object
      produces<LHCStatus, edm::Transition::BeginRun>();

      //say we use the database
      usesResource("Database");
   }
   
   void produce(edm::Event const& iEvent, edm::EventSetup const&) override{
      //Do nothing
   }

   void beginRunProduce(edm::Run& iRun, edm::EventSetup const&) override {
      std::auto_ptr<LHCStatus> status(new LHCStatus);
      m_dbConnection.fill(*status);
 
      iRun.put(status);
   }

   void endJob() override {
      m_dbConnection.closeConnection();
   }

private:
   DBConnection m_dbConnection;
};
} //ends namespace

edm::BeginLuminosityBlockProducer

This extension allows an EDProducer to put data into the LuminosityBlock at the begin of LuminosityBlock transition. Items placed during the begin of LuminosityBlock transition are available to get for any method that directly or indirectly provides a edm::LuminosityBlock.

The extended interface is as follows:

void beginLuminosityBlockProduce(edm::LuminosityBlock&, edm::EventSetup const&)
This method is called each time the Source sees a new LuminosityBlock. The routine is called as part of the global begin LuminosityBlock transition.

example usage: pull data from a database and put it into the luminosity block

This example will use a fictitious thread-unsafe database interface to retrieve data and then place it into the LuminosityBlock.

//use an anonymous namespace since there is no need for any other file to see these class names
namespace {

class LumiSummaryProducer : public edm::one::EDProducer<edm::BeginLuminosityBlockProducer, edm::one::SharedResources> {
public:

   LumiSummaryProducer(edm::ParameterSet const& iPSet): m_dbConnection(iPSet.getParameter<std::string>("dbURL")) {
      //we need to register the fact that we will make the LumiSummary object
      produces<LumiSummary, edm::Transition::BeginLuminosityBlock>();
  
      //say we use the database
      usesResource("Database");
   }
   
   void produce(edm::Event const& iEvent, edm::EventSetup const&) override {
      //Do nothing
   }

   static void beginLuminosityBlockProduce(edm::LuminosityBlock& iLumi, edm::EventSetup const&) override {
      std::auto_ptr<LumiSummary> summary(new LumiSummary);
      m_dbConnection.fill(iLumi.runNumber(), iLumi.luminosityBlockNumber(),*summary);
 
      iLumi.put(summary);
   }

   void endJob() override {
      m_dbConnection.closeConnection();
   }
private:
   DBConnection m_dbConnection;
};
} //ends namespace

edm::EndRunProducer

This extension allows an EDProducer to put data into the Run at the end of Run transition. Items placed during the end of Run transition are only available during globalEndRun calls and are not available to the standard Stream method streamEndRun. The reason for this restriction is the need to make all Run products invariant for the entire processing of the Run.

The extended interface is as follows:

void endRunProduce(edm::Run&, edm::EventSetup const&)
This method is called once all Streams processing a Run are done with the Run. This method is called as part of the global end Run transition.

edm::EndLuminosityBlockProducer

This extension allows an EDProducer to put data into the LuminosityBlock at the end of a LuminosityBlock transition. Items placed during the end of LuminosityBlock transition are only available during globalEndLuminosityBlock calls and are not available to the standard Stream method streamEndLuminosityBlock. The reason for this restriction is the final product cannot be determined until all the Streams have completed their processing of that LuminosityBlock.

The extended interface is as follows:

void endLuminosityBlockProduce(edm::LuminosityBlock&, edm::EventSetup const&)
This method is called once all Streams processing a LuminosityBlock are done with the LuminosityBlock. This method is called as part of the global end LuminosityBlock transition.

edm::Accumulator

This extension is usually used with EDProducers that put products in the Run or LuminosityBlock but do not put products in the Event. Although they do not put products in the Event, these EDProducers need data from Events for the products they put in the Run or LuminosityBlock. Without this extension and if the EDProducer is configured to run unscheduled, its event method will never run because nothing ever requests a product it produces. With this extension, these modules will run their event method on every event and accumulate the data they need.

The declaration of an EDProducer with the Accumulator feature looks like this:

class MyProducer : public edm::one::EDProducer<edm::Accumulator>

This only works with the EDProducer base class. It does not work with EDAnalyzers, EDFilters, or OutputModules.

When you use this feature you must replace the produce function with the accumulate function. It will not compile if you do not define the accumulate function. It will not compile if you define the produce function. The accumulate function will not allow products to be put into the Event because the Event argument is declared const.

void accumulate(edm::Event const&, edm::EventSetup const&) override

You can put modules with this feature on a Path or EndPath. The special behavior does not occur then. In that case, they run on the Path or EndPath the same as if they did not have the Accumulate extension. If the module is on a Path after an EDFilter that does not pass the event, then the module will not run.

Usually this feature extension will be used with other feature extensions. For example, it might be used with EndLuminosityBlockProducer.

This extension was first added in release 10_1_0 (in 2018), it cannot be used in earlier releases.

Review status

Reviewer/Editor and Date Comments
Last reviewed by: ChrisDJones - 14-Nov-2012 Created the page

Responsible: ChrisDJones
Last reviewed by:

Edit | Attach | Watch | Print version | History: r11 < r10 < r9 < r8 < r7 | Backlinks | Raw View | WYSIWYG | More topic actions
Topic revision: r11 - 2018-10-31 - ChrisDJones
 
    • Cern Search Icon Cern Search
    • TWiki Search Icon TWiki Search
    • Google Search Icon Google Search

    CMSPublic All webs login

This site is powered by the TWiki collaboration platform Powered by PerlCopyright & 2008-2019 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback