Within the Mu2e software there are some cases in which
names of files, classes, libraries etc must follow certain
rules. There are other cases in which conventions are
just conventions. This page is concerned with those cases
in which they are actual rules.
Module Names
Consider a class named MyClass that you wish to
make into a module that can be manipulated by the
framework. First, your class must
inherit from one of the modulle base classes,
EDAnalyzer,
EDProducer or EDFilter.
Second it must follow the following
rules, all of which are case sensitive.
- It must be in a file named MyClass_module.cc.
- The build system will make this into a file
named lib/libMyClass_module.so.
- The module source file must look like:
namespace mu2e {
class MyClass : public art::EDAnalyzer {
public:
explicit MyClass(fhicl::ParameterSet const& pset);
// Compiler generated d'tor is OK.
void analyze( art::Event const& event );
};
MyClass::MyClass(fhicl::ParameterSet const& pset){
// Body of the constructor. You can access information in the parameter set here.
}
void MyClass::analyze(art::Event const& event){
mf::LogVerbatim("test")
<< "Hello, world. From analyze. "
<< event.id();
}
} // end namespace mu2e
using mu2e::MyClass;
DEFINE_ART_MODULE(MyClass);
This example is for an analyzer. To create a producer or a filter module, you must inherit from either
art::EDProducer or art::EDFilter. The last line invokes a macro that inserts additional code into the
.so file ( for the experts: it inserts a factory method to produce an instance of the class and it
inserts and auto-registration object that registers the factory method with art's module registry ).
- To declare this module to the framework you need to have a
fragment like the following in your .fcl file:
physics :
{
analyzers:
{
looseCuts : { module_type : MyClass }
# Other analyzer modules listed here ...
}
}
The string looseCuts is called a module label and
is is defined below.
- The previous item was for the case that your module is an analyzer.
If it is a producer or filter, then the text in green needs to be either
producers or filters.
- When you put a data product into an event, the data provenance system records the module label
of the module that did the put.
Consider the following fragment from a .fcl file,
physics: {
producers: {
looseCuts: { module_type : MyClass }
}
}
- The string looseCuts is refered to as the module
module label; I have sometimes called this module "instance name" but
the code refers to it as ModuleLabel.
- The above fragment may be expaned to include additional
arguments, that will be treated as the definition
of a parameter set to be given to the object. For example,
physics :
{
analyzers:
{
looseCuts :
{
module_type : MyClass
cutLevel : 1
}
tightCuts :
{
module_type : MyClass
cutLevel : 2
}
}
}
The parameter cutLevel is available to the contructor of MyClass via the fhicl::ParameterSet argument.
-
In this example two modules are defined, both are of type EDAnalzer and both are instances of the
class MyClass. They are distinguished by having different values in the
parameter sets and by having different module labels. The name cutLevel
has no meaning to the
framework: presumably it has meaning within MyClass.
Getting Information by Module Label
There are several ways to
get a data product out from an event.
The recommended way is to ask for it by specifying the module label of the module
that created it.
#include "RecoDataProducts/inc/StrawHitCollection.hh"
art::Handle<StrawHitCollection> hitsHandle;
event.getByLabel("strawHitMaker",hitsHandle);
StrawHitCollection const& hits = *hitsHandle;
In this example, it is presumed that the hits that we want were created by a module with the
label "strawHitMaker".
After a successful call to getByLabel the variable hitsHandle will hold
a valid handle to a collection of StrawHits.
You can read more about handles.
If getByLabel cannot successfully
and uniquely do its job, it will return a handle that points to nothing. If a
user attempts to use such a handle, the handle will throw.
It will throw if any of the following is true:
- the event contains no collection of StrawHits.
- the event contains one or more collections of StrawHits but none
were created by the module with the label
strawHitMaker.
- the event contains more than 1 collections of StrawHits made by the
module with the label
strawHitMaker.
- the event contains data products made by the module with the
label strawHitMaker but none of those data
products are of type StrawHitCollection.
The last line in the example strips away the handle-ness and leaves a const reference to the
a StrawHitCollection; check the header file to see that StrawHitCollection is just a typedef for
std::vector<StrawHit>.
This line is not strictly necessary; you can use hitsHandle as if it
were a pointer to the StrawHitsCollection. This is OK if you only want to use it a few times.
But, everytime that you dereference a handle it does the safety check to see that the product
really exists. If you want to write a multiply nested loop over the StrawHitCollection, perhaps
finding all triplets of hits, you do not want to do this safety check every time that you access
a hit. By construction of the framework, if the hits are there the first time you dereference
the handle, they will always be there for the rest of the event. So you need only do the check once.
For beginners: the & in the following:
StrawHitCollection const & hits = *hitsHandle;
makes the variable hits a reference; this means that hits is a compile time alias which imposes
no additional run time cost in either memory or CPU. If you forget the &
the code will compile but the variable hits will be a copy of the hits that are found in the
event; this may create a significant CPU and memory penalty.
There are
other ways to get data products from an event.
This file last modified Tuesday, 29-Jan-2013 11:26:36 CST