Mu2e Home
What Names Must Match
Search
Mu2e@Work

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.
  1. It must be in a file named MyClass_module.cc.
  2. The build system will make this into a file named lib/libMyClass_module.so.
  3. 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 ).
  4. 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.
  5. 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.
  6. When you put a data product into an event, the data provenance system records the module label of the module that did the put.

Module Labels

Consider the following fragment from a .fcl file,
physics: {
  producers: {
    looseCuts: { module_type   : MyClass }
  }
}
  1. 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.
  2. 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.
  3. 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:
  1. the event contains no collection of StrawHits.
  2. the event contains one or more collections of StrawHits but none were created by the module with the label strawHitMaker.
  3. the event contains more than 1 collections of StrawHits made by the module with the label strawHitMaker.
  4. 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.


Fermilab at Work ]  [ Mu2e Home ]  [ Mu2e @ Work ]  [ Mu2e DocDB ]  [ Mu2e Search ]

For web related questions: Mu2eWebMaster@fnal.gov.
For content related questions: kutschke@fnal.gov
This file last modified Tuesday, 29-Jan-2013 11:26:36 CST
Security, Privacy, Legal Fermi National Accelerator Laboratory