Modules: Difference between revisions

From Mu2eWiki
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==


Consider a class named <font color=red>MyClass</font> that you wish to
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:
make into a module that can be manipulated by the
framework. First, 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>.
Second it must follow the following
rules, all of which are case sensitive.


<ol>
<ol>
  <li> It must be in a file named  <font color=red>MyClass_module.cc</font>.
  <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 make this into a file named  <font color=red>lib/libMyClass_module.so</font>.
<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 look like:</li>
  <li> The Mu2e build system will compile this file into an object file named <font color=red>MyDirectory/src/MyClass_module.os</font>
  namespace mu2e {
<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.
  class <font color=red>MyClass</font> : public art::EDAnalyzer {
<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.
  public:
  <li> The module source file must have the structure:</li>
    explicit <font color=red>MyClass</font>(fhicl::ParameterSet const& pset);
namespace mu2e {
    // Compiler generated d'tor is OK.
  class <font color=red>MyClass</font> : public art::EDAnalyzer {
    void analyze( art::Event const& event );
    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){
  <font color=red>MyClass</font>::<font color=red>MyClass</font>(fhicl::ParameterSet const& pset)
  // Body of the constructor. You can access information in the parameter set here.
    : art::EDAnalyzer(pset){
  }
    // Body of the constructor.
  }
   
   
  void <font color=red>MyClass</font>::analyze(art::Event const& event){
  void <font color=red>MyClass</font>::analyze(art::Event const& event){
    mf::LogVerbatim("test")
    // Body of the analyze member function: this is where you do per event work.
      << "Hello, world. From analyze. "
    // You can inspect information already in the event by using the art::Event argument.
      << event.id();
   }
   }
  } // end namespace mu2e
  } // end namespace mu2e
  DEFINE_ART_MODULE(<font color=red>mu2e::MyClass</font>);
using mu2e::<font color=red>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 it inserts and auto-registration object that registers the factory method with art's module registry ).
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>looseCuts</font> : { module_type  : <font color=red>MyClass</font> }
           # Other analyzer modules listed here ...
         }
         }
     }
     }


The string <font color=blue>looseCuts</font> is called a module label and is defined below .
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 you put a data product into an event, the data provenance system records the module label of the module that did the put.
<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>looseCuts</font>: { module_type  : MyClass }
     <font color=blue>set1</font>: { module_type  : MyClass }
   }
   }
  }
  }


  <ol>
  <ol>
   <li> The string <font color=blue>looseCuts</font> is refered to as the module
   <li> The string <font color=blue>set1</font> is refered to as the module
         module label; I have sometimes called this module "instance name" but
         module label; you will sometimes hear this called "a module instance name".
        the code refers to it as ModuleLabel.
     <li> The above fragment may be expanded to include additional parameters, for example,</li>
     <li> The above fragment may be expaned to include additional
  physics : {
          arguments, that will be treated as the definition
     <font color=green>analyzers</font>: {
          of a parameter set to be given to the object.  For example,</li>
       <font color=blue>set1</font> : {
  physics :
{
     <font color=green>analyzers</font>:
    {
       <font color=blue>looseCuts</font> :
      {
           module_type  : <font color=red>MyClass</font>
           module_type  : <font color=red>MyClass</font>
           cutLevel : 1
           cutSet : 1
       }
       }
       <font color=blue>tightCuts</font> :
       <font color=blue>set2</font> : {
      {
           module_type  : <font color=red>MyClass</font>
           module_type  : <font color=red>MyClass</font>
           cutLevel : 2
           cutSet : 2
       }
       }
     }
     }
  }
  }


The parameter cutLevel is available to the contructor of MyClass via the fhicl::ParameterSet argument.
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 modules are defined, both are of type EDAnalzer and both are instances of the class <font color=red>MyClass</font>. They are distinguished by having different values in the parameter sets and by having different module labelsThe name <font color=green>cutLevel</font> has no meaning to the framework: presumably it has meaning within <font color=red>MyClass</font>.
 
</ol>
<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 2For 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:Computing/Code]]
[[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:

  1. 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)
  2. 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.
  3. The Mu2e build system will compile this file into an object file named MyDirectory/src/MyClass_module.os
  4. 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.
  5. 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.
  6. The module source file must have the structure:
  7. 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)
  8. To declare this module to the framework you need to have a fragment like the following in your .fcl file:
  9. 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.
  10. 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.
  11. 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 }
  }
}
  1. The string set1 is refered to as the module module label; you will sometimes hear this called "a module instance name".
  2. The above fragment may be expanded to include additional parameters, for example,
  3. 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).
  4. 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.
  5. In this sense the unique identifiers of units of work are set1 and set2, the two module labels.
  6. Within a single art job, all module labels must be unique.