Modules: Difference between revisions
Jump to navigation
Jump to search
No edit summary |
|||
(2 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
==Module Names== | ==Module Names== | ||
This page describes the skeleton of a minimal module that does some work on every event but nothing else. The class name of the module is <font color=red>MyClass</font>; the focus is on some rules defined by art and some conventions adopted by the Mu2e build system. These rules are case sensitive and are listed below: | |||
rules | |||
<ol> | <ol> | ||
<li> | <li> Your class must inherit from one of the module base classes, <font color=red>EDAnalyzer</font>, <font color=red>EDProducer</font> or <font color=red>EDFilter</font>; these base classes are defined by ''art''. There are other base classes available when using art in multi-threaded mode but those details are beyond the scope of this page. (FIXME: Link to MT section when we make it) | ||
<li> The build system will | <li> This class must be found in a file with a name that matches the class name, <font color=red>MyClass_module.cc</font>; typically this file will be found in a directory named like: <font color=red>MyDirectory/src/MyClass_module.cc</font>, relative to the top of Mu2e Offline. | ||
<li> The module source file must | <li> The Mu2e build system will compile this file into an object file named <font color=red>MyDirectory/src/MyClass_module.os</font> | ||
<li> The Mu2e build system will link this object file into a dynamic library named <font color=red>lib/libmu2e_MyDirectory_MyClass_module.so</font>; dynamic libraries are also called shared libraries. | |||
<li> This .so file is a plugin that ''art'' can load and run. You tell ''art'' to load and run the file using the fcl language; some basic elements of fcl are described below. | |||
<li> The module source file must have the structure:</li> | |||
namespace mu2e { | |||
class <font color=red>MyClass</font> : public art::EDAnalyzer { | |||
public: | |||
explicit <font color=red>MyClass</font>(fhicl::ParameterSet const& pset); | |||
void analyze( art::Event const& event ) override; | |||
}; | |||
<font color=red>MyClass</font>::<font color=red>MyClass</font>(fhicl::ParameterSet const& pset) | |||
: art::EDAnalyzer(pset){ | |||
// Body of the constructor. | |||
} | |||
void <font color=red>MyClass</font>::analyze(art::Event const& event){ | |||
// Body of the analyze member function: this is where you do per event work. | |||
// You can inspect information already in the event by using the art::Event argument. | |||
} | } | ||
} // end namespace mu2e | } // end namespace mu2e | ||
DEFINE_ART_MODULE(<font color=red>mu2e::MyClass</font>); | |||
DEFINE_ART_MODULE(<font color=red>MyClass</font>); | |||
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 | This example is for an analyzer module. 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 inserts code that runs at .so load time to register the factory method with art's module registry ). This example uses the variant in which the argument of the constructor is a ParameterSet object; there is a newer variant in which the argument is a smarter type of ParameterSet that knows how to check it's input for validity. (FIXME: Update the example with the validated pset technology) | ||
<li> To declare this module to the framework you need to have a fragment like the following in your .fcl file:</li> | <li> To declare this module to the framework you need to have a fragment like the following in your .fcl file:</li> | ||
physics : | physics : { | ||
<font color=green>analyzers</font>: { | |||
<font color=green>analyzers</font>: | <font color=blue>set1</font> : { module_type : <font color=red>MyClass</font> } | ||
# Any other analyzer modules listed here ... | |||
<font color=blue> | |||
# | |||
} | } | ||
} | } | ||
The string <font color=blue> | The identifiers '''physics''', '''analyzers''' and '''module_type''' are defined by ''art''. The name | ||
<font color=red>MyClass</font> tells '''art''' to look in CET_PLUGIN_PATH and find a file that matches the name <font color=red>lib*MyClass_module.so</font>; that's how it finds your module. | |||
The string <font color=blue>set1</font> is called a module label; if you are the author of a module then you can choose almost any name you want for a module label. If you are using a standard Mu2e module, you normally must use one of the module labels that Mu2e has defined for you. There is more information about module labels below. | |||
<li> The previous item was for the case that your module is an <font color=green>analyzer</font>. If it is a producer or filter, then the text in green needs to be either <font color=green>producers</font> or <font color=green>filters</font>. | <li> The previous item was for the case that your module is an <font color=green>analyzer</font>. If it is a producer or filter, then the text in green needs to be either <font color=green>producers</font> or <font color=green>filters</font>. | ||
<li> When | <li> When a module puts a data product into an event, the ''art'' data provenance system records the module label of the module that created the data product. | ||
</ol> | </ol> | ||
==Module Labels == | ==Module Labels == | ||
Most modules have run-time configurable parameters. So the full description of "what a module does" needs two things, it's source code and it's run-time configuration. The purpose of a module label is to uniquely identify a unit of work, a module plus it's runtime configuration. The example below illustrates this. | |||
Consider the following fragment from a .fcl file, | Consider the following fragment from a .fcl file, | ||
physics: { | physics: { | ||
producers: { | producers: { | ||
<font color=blue> | <font color=blue>set1</font>: { module_type : MyClass } | ||
} | } | ||
} | } | ||
<ol> | <ol> | ||
<li> The string <font color=blue> | <li> The string <font color=blue>set1</font> is refered to as the module | ||
module label; | module label; you will sometimes hear this called "a module instance name". | ||
<li> The above fragment may be expanded to include additional parameters, for example,</li> | |||
<li> The above fragment may be | physics : { | ||
<font color=green>analyzers</font>: { | |||
<font color=blue>set1</font> : { | |||
physics : | |||
<font color=green>analyzers</font>: | |||
<font color=blue> | |||
module_type : <font color=red>MyClass</font> | module_type : <font color=red>MyClass</font> | ||
cutSet : 1 | |||
} | } | ||
<font color=blue> | <font color=blue>set2</font> : { | ||
module_type : <font color=red>MyClass</font> | module_type : <font color=red>MyClass</font> | ||
cutSet : 2 | |||
} | } | ||
} | } | ||
} | } | ||
This example presumes the module MyClass has code in it's constructor that reads the parameter '''cutSet''' and changes the behaviour of the module depending on the value of the parameter. If you look back at the code fragment for <font color=red>MyClass</font> you will see that the constructor has an argument of type fhicl::ParameterSet - the module uses the parameter set object to look up the value of '''cutSet'''. You can find the details of how to do this an another tutorial (FIXME: add a link). | |||
<li> In this example two | |||
<li> In this example ''art'' will make two instances of the class <font color=red>MyClass</font>, one class will see a '''cutSet''' parameter of 1 and the other '''cutSet''' parameter of 2. For every event that it processes ''art'' will call the analyze member function of both instances. | |||
<li> In this sense the unique identifiers of units of work are '''set1''' and '''set2''', the two module labels. | |||
<li> Within a single ''art'' job, all module labels must be unique. | |||
</ol> | |||
[[Category:Computing]] | [[Category:Computing]] | ||
[[Category: | [[Category:Code]] |
Latest revision as of 14:14, 20 August 2020
Module Names
This page describes the skeleton of a minimal module that does some work on every event but nothing else. The class name of the module is MyClass; the focus is on some rules defined by art and some conventions adopted by the Mu2e build system. These rules are case sensitive and are listed below:
- Your class must inherit from one of the module base classes, EDAnalyzer, EDProducer or EDFilter; these base classes are defined by art. There are other base classes available when using art in multi-threaded mode but those details are beyond the scope of this page. (FIXME: Link to MT section when we make it)
- This class must be found in a file with a name that matches the class name, MyClass_module.cc; typically this file will be found in a directory named like: MyDirectory/src/MyClass_module.cc, relative to the top of Mu2e Offline.
- The Mu2e build system will compile this file into an object file named MyDirectory/src/MyClass_module.os
- The Mu2e build system will link this object file into a dynamic library named lib/libmu2e_MyDirectory_MyClass_module.so; dynamic libraries are also called shared libraries.
- This .so file is a plugin that art can load and run. You tell art to load and run the file using the fcl language; some basic elements of fcl are described below.
- The module source file must have the structure: namespace mu2e { class MyClass : public art::EDAnalyzer { public: explicit MyClass(fhicl::ParameterSet const& pset); void analyze( art::Event const& event ) override; }; MyClass::MyClass(fhicl::ParameterSet const& pset) : art::EDAnalyzer(pset){ // Body of the constructor. } void MyClass::analyze(art::Event const& event){ // Body of the analyze member function: this is where you do per event work. // You can inspect information already in the event by using the art::Event argument. } } // end namespace mu2e DEFINE_ART_MODULE(mu2e::MyClass); This example is for an analyzer module. 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 inserts code that runs at .so load time to register the factory method with art's module registry ). This example uses the variant in which the argument of the constructor is a ParameterSet object; there is a newer variant in which the argument is a smarter type of ParameterSet that knows how to check it's input for validity. (FIXME: Update the example with the validated pset technology)
- To declare this module to the framework you need to have a fragment like the following in your .fcl file: physics : { analyzers: { set1 : { module_type : MyClass } # Any other analyzer modules listed here ... } } The identifiers physics, analyzers and module_type are defined by art. The name MyClass tells art to look in CET_PLUGIN_PATH and find a file that matches the name lib*MyClass_module.so; that's how it finds your module. The string set1 is called a module label; if you are the author of a module then you can choose almost any name you want for a module label. If you are using a standard Mu2e module, you normally must use one of the module labels that Mu2e has defined for you. There is more information about module labels 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 a module puts a data product into an event, the art data provenance system records the module label of the module that created the data product.
Module Labels
Most modules have run-time configurable parameters. So the full description of "what a module does" needs two things, it's source code and it's run-time configuration. The purpose of a module label is to uniquely identify a unit of work, a module plus it's runtime configuration. The example below illustrates this.
Consider the following fragment from a .fcl file,
physics: { producers: { set1: { module_type : MyClass } } }
- The string set1 is refered to as the module module label; you will sometimes hear this called "a module instance name".
- The above fragment may be expanded to include additional parameters, for example, physics : { analyzers: { set1 : { module_type : MyClass cutSet : 1 } set2 : { module_type : MyClass cutSet : 2 } } } This example presumes the module MyClass has code in it's constructor that reads the parameter cutSet and changes the behaviour of the module depending on the value of the parameter. If you look back at the code fragment for MyClass you will see that the constructor has an argument of type fhicl::ParameterSet - the module uses the parameter set object to look up the value of cutSet. You can find the details of how to do this an another tutorial (FIXME: add a link).
- In this example art will make two instances of the class MyClass, one class will see a cutSet parameter of 1 and the other cutSet parameter of 2. For every event that it processes art will call the analyze member function of both instances.
- In this sense the unique identifiers of units of work are set1 and set2, the two module labels.
- Within a single art job, all module labels must be unique.