Project

General

Profile

Using the Framework » History » Version 3

Version 2 (Brian Rebel, 10/14/2010 12:43 PM) → Version 3/70 (Brian Rebel, 10/14/2010 01:41 PM)

{{toc}}

h1. Using the Framework

The ART framework has a very similar interface to the previously used FMWK framework. The same basic ideas apply - all the algorithms are stored in modules, the event information is accessed using objects living in the EventDataModel namespace, etc. The main difference between the two is that I/O is not based on TObjects in the CD framework. The objects that are stored in a file do not derive from TObject and it is likely that TObject derived objects will also not play nicely with the I/O. The reason for this is ROOT's way of handling pointer data members - ROOT does not store the fields for the data members of pointers, which means on readback those data members may or may not contain sensible information.

h2. Basic Concepts

The namespace edm is short for "Event Data Model". It is the namespace that contains the handles to both information stored in an event and configurations for jobs. Objects that are stored in an event are collectively known as data products. They can either be added to an event using an edm::EDProducer derived module or they can be retrieved and operated on using an edm::EDAnalyzer module. Once an object has been stored in the event, its data cannot be altered. The FMWK equivalents are given "()" in the topic heading.

There is a link to interface for each concept in the heading for that concept.

h3. "edm::EDProducer":https://cdcvs.fnal.gov/redmine/projects/art/repository/revisions/master/changes/art/Framework/Core/EDProducer.h (jobc::Module::Reco)

This is a type of module that makes data products and stores them in the edm::Event. The module takes an edm::ParameterSet in the constructor and uses that to configure that module. The user must supply the implementation for the edm::EDProducer::produce() method to create and store data products.

h3. "edm::EDAnalyzer":https://cdcvs.fnal.gov/redmine/projects/art/repository/revisions/master/changes/art/Framework/Core/EDAnalyzer.h (jobc::Module::Ana)

This is a type of module that analyzes data products but cannot write them in an edm::Event. The module takes an edm::ParameterSet in the constructor and uses that to configure that module. The user must supply the implementation for the edm::EDAnalyzer::analyze() method to analyze data products.

h3. edm::EDProducer(Analyzer)::beginJob, endJob, etc (jobc::Module::beginJob, endJob, etc)

These are methods that do tasks that are needed only once a job starts, ends, or a run starts or ends, etc. For example, a beginJob method would likely contain definitions of histograms that might need to be filled during the operation of the module.

h3. "edm::Event.h":https://cdcvs.fnal.gov/redmine/projects/art/repository/revisions/master/entry/art/Framework/Core/Event.h (edm::EventHandle)

The edm::Event is the primary way to access products made by EDProducer type modules.

It also provide the user with information about an event such as the run, event number, etc through methods like

<pre><code class="c">

// assume we have an edm::Event &evt

// get the run number RunNumber_t is a typedef to unsigned int
edm::RunNumber_t run = evt.run();

// get the subrun number SubRunNumber_t is a typedef to unsigned int
edm::SubRunNumber_t subRun = evt.subRun();

// get the time stamp. edm::Timestamp::value() returns a TimeValue_t which is a typedef to unsigned long long.
// The conventional use is for the upper 32 bits to have the seconds since 1970 epoch and the lower 32 bits to be
// the number of microseconds with the current second.
edm::Timestamp ts = evt.time();


// make it into a TTimeStamp
unsigned long long int tsval = ts.value();

// taking it apart
// the masking isn't strictly necessary *if* "long" is truly 32bits
// but this can vary w/ compiler/platform
const unsigned long int mask32 = 0xFFFFFFFFUL;
unsigned long int lup = ( ul64 >> 32 ) & mask32;
unsigned long int llo = ul64 & mask32;
TTimeStamp tts(lup, llo); tts(ts.value());

// get the event number - this calls a reference to edm::EventID(). EventNumber_t is a typedef to unsigned int
edm::EventNumber_t event = evt.id().event();
</code></pre>

The header files for the classes mentioned above are at

"edm::EventID.h":https://cdcvs.fnal.gov/redmine/projects/art/repository/revisions/master/entry/art/Persistency/Provenance/EventID.h
"edm::Timestamp.h":https://cdcvs.fnal.gov/redmine/projects/art/repository/revisions/master/changes/art/Persistency/Provenance/Timestamp.h

The edm::Event can also be used to access products by asking it to return an edm::Handle.

h3. "edm::Handle":https://cdcvs.fnal.gov/redmine/projects/art/repository/revisions/master/changes/art/Persistency/Common/Handle.h (no FMWK equivalent)

An edm::Handle is what is returned to a Module when a data product is requested. The request can either be from a edm::EDProducer that is attempting to get objects stored in a previous reconstruction or analysis step, or it can be from a edm::EDAnalyzer that is attempting to do some analysis task using the information in the object. For example, to get the data product mp::MyProd from the event, one should do

<pre><code class="c">
edm::Handle< std::vector<mp::MyProd> > mplistHandle;
evt.getByLabel("moduleprocesslabel",mplistHandle);
</code></pre>

where evt is an object of type edm::Event discussed below. The edm::Event::getByLabel method takes two arguments, the first is the name of the process associated with the module that produced the list of mp::MyProd objects, and the second is the edm::Handle that is to be associated to the list.

edm::Handles look like a pointer in the code in that the data members of the object being handled are accessed using the "->". For example, to get the size of the list one can do

<pre><code class="c">
mplistHandle->size();
</code></pre>

To use the objects in the list, it is easiest to make a edm::PtrVector (discussed below).
<pre><code class="c">
// make an edm::PtrVector of the objects
edm::PtrVector<mp::MyProd> prodvec;
for(unsigned int i = 0; i < mplistHandle->size(); ++i){
edm::Ptr<mp::MyProd> prod(mplistHandle, i);
prodvec.push_back(prod);
}
</code></pre>

h3. edm::View (Upcast on read)

The edm::View is a templated collection of objects. It is used to read back objects written into a file that follow a simple inheritance scheme, ie reading in objects of a derived type using the base class type. For instance, rb::Tracks which inherit from rb::Prongs. An example of using the edm::View is

<pre><code class="c">
// Read in the list of rb::Tracks we made in fTrackModuleLabel as rb::Prongs.
edm::Handle< edm::View<rb::Prong> > prongVecHandle;
evt.getByLabel(fTrackModuleLabel,prongVecHandle);

// Use the handle to get a particular (0th) element of collection.
edm::Ptr<rb::Prong> prong = prongVecHandle->ptrAt(0);

// this does the same thing as the previous line
edm::Ptr<rb::Prong> prong(prongVecHandle,0);

</code></pre>

Notice that the edm::View behaves similarly to a std collection like std::vector. You can ask the view for an iterator over the collection with edm::View::begin() or edm::View::end() methods, an edm::Ptr<T> using edm::View::ptrAt(i), or a edm::PtrVector<T> using edm::View::ptrVector().

h3. "edm::FileInPath":https://cdcvs.fnal.gov/redmine/projects/art/repository/revisions/master/changes/art/ParameterSet/FileInPath.h

This is a utility that will search a list of predefined directories for a relative location of a file. For instance, if you want to use the geometry definition for ArgoNeuT, argoneut.gdml, as the input for the Geometry service, you would pass the job Module the value "Geometry/gdml/argoneut.gdml" as type FileInPath. The edm::FileInPath object then searches through the previously defined @$FW_SEARCH_PATH@ variable to see if it can locate the specified file. It will then allow access to information about the file, including its full path. This is helpful when writing code that should search for a given file in several locations such as private and public contexts in the SRT build system. The necessary variables are set when a user sets up the environment. If a user wants the search path to include a test release, the the user should do

@$srt_setup -a@

from within that test release.

h3. "edm::ParameterSet":https://cdcvs.fnal.gov/redmine/projects/art/repository/revisions/master/changes/art/ParameterSet/ParameterSet.h (cfg::Config)

This object keeps track of which parameters are to be set by the user at run time for a module or edm::Service. It can interpret several data types, including those listed below. An example for how to read the parameter types from the module constructor is listed for each type. See [[Running Jobs]] for examples of the job configuration file syntax for each type.

* bool: fMyBool (pset.getParameter< bool >("MyBool"))
* int: fMyInt (pset.getParameter< int >("MyInt"))
* unsigned int: fMyUInt (pset.getParameter< unsigned int >("MyUInt"))
* std::vector<int>: fMyVInt (pset.getParameter< std::vector<int> >("MyVInt"))
* std::vector<unsigned int>: fMyVUInt (pset.getParameter< std::vector<unsigned int> >("MyVUInt"))
* std::string: fMyString (pset.getParameter< std::string >("MyString"))
* std::vector<std::string>: fMyVString (pset.getParameter< std::vector<std::string> >("MyVString"))
* double: fMyDouble (pset.getParameter< double >("MyDouble"))
* std::vector<double>: fMyVDouble (pset.getParameter< std::vector<double> >("MyDouble"))
* edm::FileInPath: fMyFileInPath(pset.getParameter< edm::FileInPath >("My/File/In/Path/file.root"))

Other types are available, but the above list should serve almost all a user's needs.

h3. "edm::Service":https://cdcvs.fnal.gov/redmine/projects/art/repository/revisions/master/changes/art/Framework/Services/Registry/Service.h (no real FMWK equivalent)

The edm::Service is a templated object that behaves like a singleton, except that it is owned and managed by the framework. A service can be used within any module. Services can be configured using the job configuration file. A typical example of the use of a service is the detector Geometry. The Geometry is needed in just about every module, but you don't want to keep making instances of the Geometry. Additionally, the different detectors may have to set different parameter values that should be handled in the job configuration.

h3. "edm::TFileService":https://cdcvs.fnal.gov/redmine/projects/art/repository/revisions/master/changes/art/Framework/Services/Basic/TFileService.h

This is a specialized service that connects up to the file where histograms made by modules are to be stored. It provides a mechanism for making TObjects to be stored in that file and managing the memory for those objects. For example

<pre><code class="c">
// get the geometry to figure out something for the histogram
edm::Service<geo::Geometry> geo;

// get access to the TFile service
edm::Service<edm::TFileService> tfs;

// make the histogram
fHist = tfs->make<TH1D>("channels", ";channel;# electrons", geo->Nchannels(), 0, geo->Nchannels());

// note that for some reason ROOT does not automatically connect TGraphs to the output directory when created
// like it does for histograms. So we have to do that ourselves using the ROOT global directory variable gDirectory
fGraph = tfs->make<TGraph>(); //default constructor, set number of points and values later
gDirectory->Append(fGraph);

</code></pre>

h3. MessageLogger and MessageService

The MessageLogger provides several levels of messages that can be used to print information to an output log. The levels most likely to be useful are edm::LogDebug, edm::LogInfo, edm::LogWarning and edm::LogError. These are listed in order of severity. The MessageService can be configured to set the number of messages printed and to send each class of message to a different output stream.

It can be used as follows:

<pre><code class="c">
if(x > 2) edm::LogWarning("XTooBig") << "x = " << x << " is too big";
</code></pre>

Details on how to set message levels and verbosity, etc, can be found "here":http://www.uscms.org/LPC/lpc_offl/MessageLogger/MessageLogger.html

h3. "edm::Exception":https://cdcvs.fnal.gov/redmine/projects/art/repository/revisions/master/changes/art/Utilities/Exception.h (edm::Exception in FMWK)

The edm::Exception can be used to cause the framework to end a job gracefully if some predetermined bad thing happens. The use of the edm::Exception can be configured to skip a module, or skip to the next event, run, etc. Different exception classes can be set to do different things.

edm::Exception can be used as follows:

<pre><code class="c">
if(x > 2) throw edm::Exception("XTooBig") << "x = " << x << " is too big";
</code></pre>

Detailed instructions for using edm::Exceptions are attached to this page, attachment:CMS_SWGuideEdmExceptionUse.pdf

Caveat: Currently the exception lives in the cms namespace, so change edm::Exception to cms::Exception in the above.

h3. "edm::Ptr<T>":https://cdcvs.fnal.gov/redmine/projects/art/repository/revisions/master/changes/art/Persistency/Common/Ptr.h and "edm::PtrVector<T>":https://cdcvs.fnal.gov/redmine/projects/art/repository/revisions/master/changes/art/Persistency/Common/PtrVector.h

The edm::Ptr<T> is a template class that acts like a ROOT TRef. It provides a linkage between objects written into different areas of the event (and output file). For example, the rb::Cluster object holds an edm::PtrVector<rb::CellHit> pointing to the hits contained in the rb::Cluster. The edm::Ptr<T> behaves like a pointer (ie you access the methods of the T using the "->"). It also has functionality to return the actual pointer to the object in question using edm::Ptr<T>::get() or to check if the edm::Ptr<T> is pointing to a legitimate object using edm::Ptr<T>::isNull().

An edm::Ptr<T> can only be made from an object that has been stored in the event record and is being fetched from the event record. Put another way, you can only make an edm::Ptr<T> if you have an edm::Handle to a collection of objects of type T. edm::Ptr<T> cannot be instantiated like an object of type T,

<pre><code class="c">
edm::Ptr<T> myt = new T();
</code></pre>

or similar will not work because the object you are interested in for that code has not been first stored in the event record.

An edm::PtrVector<T> is a vector of edm::Ptr<T> objects. It provides the basic functionality you would expect from a std::vector, including iterators, size(), begin() and end() methods. It is useful when storing the connections of many objects of the same type in an object, for example rb::CellHits in a rb::Cluster.

h3. "edm::Filter":https://cdcvs.fnal.gov/redmine/projects/art/repository/revisions/master/changes/art/Framework/Core/EDFilter.h (io::Filter)

The object allows one to filter spills based on information obtained about the event.

h2. Making Objects to Store in the Output

Making objects to store in the edm::Event is a straightforward operation. The first step is to declare a container for the objects,

<pre><code class="c">
std::auto_ptr<std::vector<mp::MyProd> > mpCollection(new std::vector<mp::MyProd>);
</code></pre>

Here we used the std::auto_ptr because it handles the cleanup of the memory for the collection for us.

The mpCollection now behaves just like a std::vector, except one accesses the std::vector methods using a "->". Once the collection has been filled (and it can be a collection of just one object), it is written to the event by doing

<pre><code class="c">
event.put(mpCollection);
</code></pre>

Now the ownership of the collection belongs to the event and the user cannot modify the collection or the objects in the collection any more. If a user wants access to the collection after the put method is invoked, then the following syntax should be used instead:
<pre><code class="c">
// Return value is a "read only pointer" to the data product when putting the product into the event.
edm::OrphanHandle< std::vector<mp::MyProd> > q = event.put(mpCollection);
edm::LogInfo("NumMyProds") << "Number of products: " << q->size();
</code></pre>

h2. Making a Module

Below are examples of how to make both an EDProducer module and an EDAnalyzer module. The examples show basic .h and .cxx files for each. One other file needs to be made for the module to be recognized by the framework at run time and that is called the _plugin.cc file. An example of the plugin file is also included.

To recap, you need three files to make a module and they should be named as follows:

*MyModule.h - the file defining the interface
*MyModule.cxx - the implementation file
*MyModule_plugin.cc - the file defining the connection to the framework.

h3. EDProducer

<pre><code class="c">
#ifndef MYPRODUCER_H
#define MYPRODUCER_H

#include "FWCore/Framework/interface/EDProducer.h"

class TH1D;

namespace edm {
class Event;
class EventSetup;
class ParameterSet;
}

///My Module
namespace mm {

///class to produce a data product
class MyProducer : public edm::EDProducer {

public:

explicit MyProducer(edm::ParameterSet const& pset); // the explicit tag tells the compiler that MyProducer is different from edm::ParameterSet
virtual ~MyProducer();
void produce(edm::Event& evt, edm::EventSetup const&); // makes the objects I want made
void beginJob(edm::EventSetup const&); // does things like make histograms at the beginning of the job, also beginRun and beginSpill methods available.

private:

double fDouble; ///< some data member
std::string fPrevModuleLabel; ///< label of the module making objects that i need for this step
TH1D* fHist; ///< a histogram data member

}; // class MyProducer
}

#endif // MYPRODUCER_H
</code></pre>

The implementation file is then

<pre><code class="c">

#include <iostream>

// Framework includes
#include "FWCore/Framework/interface/Event.h"
#include "FWCore/ParameterSet/interface/ParameterSet.h"
#include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
#include "DataFormats/Common/interface/Handle.h"
#include "DataFormats/Common/interface/Ptr.h"
#include "DataFormats/Common/interface/PtrVector.h"
#include "FWCore/Framework/interface/MakerMacros.h"
#include "FWCore/ServiceRegistry/interface/Service.h"
#include "FWCore/Services/interface/TFileService.h"
#include "FWCore/Framework/interface/TFileDirectory.h"
#include "FWCore/MessageLogger/interface/MessageLogger.h"

#include "MyModule/MyProducer.h"
#include "Geometry/geo.h"
#include "MyProducts/MyProduct.h"
#include "MyProducts/MyOtherProduct.h"

#include "TH1.h"

namespace mm{

//-----------------------------------------------------
MyProducer::MyProducer(edm::ParameterSet const& pset) :
fDouble (pset.getParameter< double > ("TheDouble")),
fPrevModuleLabel(pset.getParameter< std::string >("PreviousModuleLabel"))
{
produces< std::vector<mp::MyOtherProduct> >(); // this line tells the module what it is going to make, you must have one line
// for each type of collection to be made

}

//-----------------------------------------------------
MyProducer::~MyProducer()
{
}

//-----------------------------------------------------
void MyProducer::beginJob(edm::EventSetup const&)
{
// get access to the TFile service
edm::Service<edm::TFileService> tfs;

// get the geometry to figure out something for the histogram
edm::Service<geo::Geometry> geo;

fHist = tfs->make<TH1D>("channels", ";channels;", geo->NPlanes()*geo->Plane(0)->Ncells(), 0, geo->NPlanes()*geo->Plane(0)->Ncells());

return;
}

//-----------------------------------------------------
void MyProducer::produce(edm::Event& evt, edm::EventSetup const&)
{

//get a collection of electrons
std::auto_ptr<std::vector<mp::MyOtherProduct> > mopcol(new std::vector<mp::MyOtherProduct>);

// maybe I will need the geometry service here too
edm::Service<geo::Geometry> geom;

double xyz[3] = {0.};
double xyz1[3] = {0.};
int planes = geom->NPlanes();

///plane 0 is the first induction plane, every plane has a wire 0
geom->Plane(0)->GetCenter(xyz);

// grab the mp::MyProducts made in the last module
edm::Handle< std::vector<mp::MyProduct> > mplistHandle;
evt.getByLabel(fPrevModuleLabel,mplistHandle);

// loop over the list of MyProducts
for(unsigned int i = 0; i < mplistHandle->size(); ++i){

//get a edm::Ptr to the MyProducts
edm::Ptr<mp::MyProduct> mpMyProd(mplistHandle, i);

// do something to turn out MyOtherProducts - not shown here

// add the new MyOtherProduct to the collection
mopcol->push_back(myOtherProd)
}

evt.put(mopcol);

// mopcol is no longer a valid pointer - don't use it any more!
// if for some reason you still want access to the products in mopcol, then use
// this syntax where the return value is a "read only pointer" to the data product
// edm::OrphanHandle< std::vector<mp::MyOtherProd> > q = event.put(mopcol);
// edm::LogInfo("NumMyProds") << "Number of products: " << q->size();

return;

}

}
</code></pre>

And now the _plugin.cc file. The need for separate files for the implementation and the plugin was not obvious to me to begin with. Having separate files allows you to produce .so libraries for both the plugin and the rest of the objects in the package. SRT also likes to have .cxx targets to build, so that is another reason to have separate .cxx and _plugin.cc files.

For this example, the plugin file is named MyProducer_plugin.cc.

<pre><code class="c">
/// Framework includes
#include "FWCore/Framework/interface/MakerMacros.h"
#include "FWCore/MessageLogger/interface/MessageLogger.h"
#include "FWCore/ServiceRegistry/interface/ServiceMaker.h"

// NOvASoft includes
#include "MyModule/MyProducer.h"

namespace mm {

// A macro required for a JobControl module.
DEFINE_FWK_MODULE(MyProducer);

} // namespace mm
</code></pre>

h3. EDAnalyzer

<pre><code class="c">
#ifndef MYANALYZERER_H
#define MYANALYZER_H

#include "FWCore/Framework/interface/EDAnalyzer.h"

class TH1D;


///My Module
namespace mm {

///class to produce a data product
class MyAnalyzer : public edm::EDAnalyzer {

public:

explicit MyAnalyzer(edm::ParameterSet const& pset); // the explicit tag tells the compiler that MyProducer is different from edm::ParameterSet
virtual ~MyAnalyzer();
void analyze(const edm::Event& evt, edm::EventSetup const&); // makes the objects I want made
void beginJob(edm::EventSetup const&); // does things like make histograms at the beginning of the job, also beginRun and beginSpill methods available.

private:

double fDouble; ///< some data member
std::string fPrevModuleLabel; ///< label of the module making objects that i now want to look at
TH1D* fHist; ///< a histogram data member

}; // class MyProducer
}

#endif // MYPRODUCER_H
</code></pre>

The implementation file is then

<pre><code class="c">
#include <iostream>

// Framework includes
#include "FWCore/Framework/interface/Event.h"
#include "FWCore/ParameterSet/interface/ParameterSet.h"
#include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
#include "DataFormats/Common/interface/Handle.h"
#include "DataFormats/Common/interface/Ptr.h"
#include "DataFormats/Common/interface/PtrVector.h"
#include "FWCore/Framework/interface/MakerMacros.h"
#include "FWCore/ServiceRegistry/interface/Service.h"
#include "FWCore/Services/interface/TFileService.h"
#include "FWCore/Framework/interface/TFileDirectory.h"
#include "FWCore/MessageLogger/interface/MessageLogger.h"

#include "MyModule/MyAnalyzer.h"
#include "Geometry/geo.h"
#include "MyProducts/MyProduct.h"
#include "MyProducts/MyOtherProduct.h"

#include "TH1.h"

namespace mm{

//-----------------------------------------------------
MyAnalyzer::MyAnalyzer(edm::ParameterSet const& pset) :
fDouble (pset.getParameter< double > ("TheDouble")),
fPrevModuleLabel(pset.getParameter< std::string >("PreviousModuleLabel"))
{
}

//-----------------------------------------------------
MyAnalyzer::~MyAnalyzer()
{
}

//-----------------------------------------------------
void MyAnalyzer::beginJob(edm::EventSetup const&)
{
// get access to the TFile service
edm::Service<edm::TFileService> tfs;

// get the geometry to figure out something for the histogram
edm::Service<geo::Geometry> geo;

fHist = tfs->make<TH1D>("channels", ";channels;", geo->NPlanes()*geo->Plane(0)->Ncells(), 0, geo->NPlanes()*geo->Plane(0)->Ncells());

return;
}

//-----------------------------------------------------
void MyAnalyzer::analyze(const edm::Event& evt, edm::EventSetup const&)
{

// maybe I will need the geometry service here too
edm::Service<geo::Geometry> geom;

double xyz[3] = {0.};
double xyz1[3] = {0.};
int planes = geom->NPlanes();

///plane 0 is the first induction plane, every plane has a wire 0
geom->Plane(0)->GetCenter(xyz);

// grab the mp::MyProducts made in a previous module
edm::Handle< std::vector<mp::MyProduct> > mplistHandle;
evt.getByLabel(fPrevModuleLabel,mplistHandle);

// loop over the list of MyProducts
for(unsigned int i = 0; i < mplistHandle->size(); ++i){

//get a edm::Ptr to the MyProducts
edm::Ptr<mp::MyProduct> mpMyProd(mplistHandle, i);

// do something to analyze them

}

return;

}

}
</code></pre>

And now the _plugin.cc file. The need for separate files for the implementation and the plugin was not obvious to me to begin with. Having separate files allows you to produce .so libraries for both the plugin and the rest of the objects in the package. SRT also likes to have .cxx targets to build, so that is another reason to have separate .cxx and _plugin.cc files.

For this example, the plugin file is named MyAnalyzer_plugin.cc.

<pre><code class="c">
/// Framework includes
#include "FWCore/Framework/interface/MakerMacros.h"
#include "FWCore/MessageLogger/interface/MessageLogger.h"
#include "FWCore/ServiceRegistry/interface/ServiceMaker.h"

// LArSoft includes
#include "MyModule/MyAnalyzer.h"

namespace mm {

// A macro required for a JobControl module.
DEFINE_FWK_MODULE(MyAnalyzer);

} // namespace mm
</code></pre>

h3. EDFilter

A simple example of filtering on even or odd event numbers is below.

First the header file:
<pre><code class="c">
// Framework includes
#include "FWCore/Framework/interface/Event.h"
#include "DataFormats/Common/interface/Handle.h"
#include "FWCore/Framework/interface/EDFilter.h"
#include "FWCore/ParameterSet/interface/ParameterSet.h"
#include "FWCore/ParameterSet/interface/ParameterSetDescription.h"

namespace filt{

class SelectEvents : public edm::EDFilter {
public:
explicit SelectEvents(edm::ParameterSet const& pset);
virtual ~SelectEvents() { }
virtual bool filter(edm::Event& e, edm::EventSetup const& c);

private:

// Control parameter: 1 to select odd numbered events;
// else select even numbered event.
int _keepOddOrEven;

};

</code></pre>

Now the implementation:

<pre><code class="c">
#include "SelectEvents.h"

namespace filt{

SelectEvents::SelectEvents(edm::ParameterSet const& pset):
_keepOddOrEven(pset.getUntrackedParameter<int>("keepOddOrEven",1))
{
}

bool SelectEvents::filter(edm::Event& e, edm::EventSetup const&)
{

// EventSetup is a cms leftover that we do not use.

// Get event number from the event.
int event = e.id().event();

// Always keep event 3.
if ( event == 3 ) return true;

// Always discard event 4.
if ( event == 4 ) return false;

// Is this an odd numbered event?
bool isOdd = ((event % 2) != 0);

// Keep only events with odd or even event numbers, as
// controled by the parameter from the ParameterSet.
if ( _keepOddOrEven == 1){
return isOdd;
} else{
return !isOdd;
}

}
}//end namespace
</code></pre>

And now the plugin.cc:

<pre><code class="c">
/// Framework includes
#include "FWCore/Framework/interface/MakerMacros.h"
#include "FWCore/MessageLogger/interface/MessageLogger.h"
#include "FWCore/ServiceRegistry/interface/ServiceMaker.h"

// LArSoft includes
#include "SelectEvents.h"

namespace filt {

// A macro required for a JobControl module.
DEFINE_FWK_MODULE(SelectEvents);

} // namespace filt
</code></pre>

h2. Configuring a Job

See the [[Running Jobs]] page.