Project

General

Profile

Using the Framework » History » Version 70

Gavin Davies, 03/11/2017 01:10 PM
add a link to the art Filtering Events wiki page

1 1 Brian Rebel
{{toc}}
2 1 Brian Rebel
3 1 Brian Rebel
h1. Using the Framework
4 1 Brian Rebel
5 64 Brian Rebel
The ART framework interface makes use of these basic ideas - all the algorithms are stored in modules and the event information is accessed using objects living in the art namespace.  The I/O uses ROOT, but it is not based on TObjects.  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 read back those data members may or may not contain sensible information.
6 1 Brian Rebel
7 1 Brian Rebel
h2. Basic Concepts
8 1 Brian Rebel
9 10 Brian Rebel
The art namespace contains the handles to information stored in an event.  Objects that are stored in an event are collectively known as data products.  They can either be added to an event using an art::EDProducer derived module or they can be retrieved and operated on using an art::EDAnalyzer module.  Once an object has been stored in the event, its data cannot be altered.  
10 1 Brian Rebel
11 7 Brian Rebel
Other namespaces to be aware of are 
12 7 Brian Rebel
13 9 Jonathan Paley
* fhicl - the namespace corresponding to the ParameterSet information described below 
14 9 Jonathan Paley
* cet - the namespace where the exceptions and some other utilities live.
15 9 Jonathan Paley
* mf - the namespace of the message logger facility
16 7 Brian Rebel
17 64 Brian Rebel
There is a link to the interface for each concept in the heading for that concept. The first three sections below, art::EDProducer, art::EDAnalyzer, art::Filter are the three main classes from which probably _all_ of your classes will derive. You will become intimate with these when you want to, (1) add a data product to the event record, or (2) read a data product from the event record and do analysis but not write to the event record and (3) use the event record to determine if you want to keep this event at all to write to an output stream.
18 1 Brian Rebel
19 64 Brian Rebel
h3. "art::EDProducer":https://cdcvs.fnal.gov/redmine/projects/art/repository/revisions/master/entry/art/Framework/Core/EDProducer.h
20 1 Brian Rebel
21 11 Brian Rebel
This is a type of module that makes data products and stores them in the art::Event. The module takes a fhicl::ParameterSet in the constructor and uses that to configure that module. 
22 1 Brian Rebel
23 11 Brian Rebel
The module can also implement a reconfigure method to allow for run time reconfiguration, for example while running the event display.  Reconfiguration during a batch job would not make sense.
24 11 Brian Rebel
25 21 Enrique Arrieta Diaz
The user must supply the implementation for the art::EDProducer::produce() method to create and store data products and the art::EDProducer::reconfigure() method to allow for reconfiguration from the event display.
26 11 Brian Rebel
27 64 Brian Rebel
h3. "art::EDAnalyzer":https://cdcvs.fnal.gov/redmine/projects/art/repository/revisions/master/entry/art/Framework/Core/EDAnalyzer.h
28 1 Brian Rebel
29 11 Brian Rebel
This is a type of module that analyzes data products but cannot write them in an art::Event. The module takes a fhicl::ParameterSet in the constructor and uses that to configure that module.  
30 1 Brian Rebel
31 1 Brian Rebel
The module can also implement a reconfigure method to allow for run time reconfiguration, for example while running the event display.  Reconfiguration during a batch job would not make sense.
32 1 Brian Rebel
33 64 Brian Rebel
The user must supply the implementation for the art::EDAnalyzer::analyze() method to analyze data products and the art::EDAnalyzer::reconfigure() method to allow for reconfiguration from the event display.
34 1 Brian Rebel
35 1 Brian Rebel
36 64 Brian Rebel
h3. "art::Filter":https://cdcvs.fnal.gov/redmine/projects/art/repository/revisions/master/entry/art/Framework/Core/EDFilter.h 
37 1 Brian Rebel
38 70 Gavin Davies
The object allows one to filter records based on information obtained about the record.
39 70 Gavin Davies
For more detailed description of how to correctly configure jobs to filter events see the art wiki page: "Filtering Events":https://cdcvs.fnal.gov/redmine/projects/art/wiki/Filtering_events
40 1 Brian Rebel
41 64 Brian Rebel
h3. art::EDProducer,Analyzer,Filter::beginJob, endJob, etc
42 64 Brian Rebel
43 64 Brian Rebel
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. A beginRun method could contain definitions of properties that can change from run to run (e.g. electron lifetime, temperature etc... ).
44 64 Brian Rebel
45 64 Brian Rebel
h3. "art::Event":https://cdcvs.fnal.gov/redmine/projects/art/repository/revisions/master/entry/art/Framework/Principal/Event.h
46 64 Brian Rebel
47 1 Brian Rebel
The art::Event is the primary way to access products made by EDProducer type modules.  
48 1 Brian Rebel
49 64 Brian Rebel
It also provides the user with information about an event such as the run, event number, etc through methods like
50 7 Brian Rebel
51 1 Brian Rebel
<pre><code class="c">
52 7 Brian Rebel
53 1 Brian Rebel
// assume we have an art::Event &evt
54 1 Brian Rebel
55 64 Brian Rebel
// get the run number. RunNumber_t is a typedef to unsigned int
56 7 Brian Rebel
art::RunNumber_t run = evt.run();
57 1 Brian Rebel
58 64 Brian Rebel
// get the subrun number. SubRunNumber_t is a typedef to unsigned int
59 1 Brian Rebel
art::SubRunNumber_t subRun = evt.subRun();
60 10 Brian Rebel
61 7 Brian Rebel
// get the time stamp.  art::Timestamp::value() returns a TimeValue_t which is a typedef to unsigned long long.
62 3 Brian Rebel
// The conventional use is for the upper 32 bits to have the seconds since 1970 epoch and the lower 32 bits to be
63 64 Brian Rebel
// the number of nanoseconds within the current second.
64 23 Brian Rebel
art::Timestamp ts = evt.time();
65 23 Brian Rebel
66 1 Brian Rebel
// make it into a TTimeStamp
67 64 Brian Rebel
TTimeStamp tts(ts.timeHigh(), ts.timeLow());
68 1 Brian Rebel
69 7 Brian Rebel
// get the event number - this calls a reference to art::EventID().  EventNumber_t is a typedef to unsigned int
70 7 Brian Rebel
art::EventNumber_t event = evt.id().event();
71 1 Brian Rebel
</code></pre>
72 1 Brian Rebel
73 1 Brian Rebel
The header files for the classes mentioned above are at 
74 1 Brian Rebel
75 1 Brian Rebel
"art::EventID.h":https://cdcvs.fnal.gov/redmine/projects/art/repository/revisions/master/entry/art/Persistency/Provenance/EventID.h
76 1 Brian Rebel
"art::Timestamp.h":https://cdcvs.fnal.gov/redmine/projects/art/repository/revisions/master/entry/art/Persistency/Provenance/Timestamp.h
77 1 Brian Rebel
78 7 Brian Rebel
The art::Event can also be used to access products by asking it to return an art::Handle.
79 1 Brian Rebel
80 64 Brian Rebel
h3. "art::Handle":https://cdcvs.fnal.gov/redmine/projects/art/repository/revisions/master/changes/art/Framework/Principal/Handle.h
81 1 Brian Rebel
82 7 Brian Rebel
An art::Handle is what is returned to a Module when a data product is requested.  The request can either be from a art::EDProducer that is attempting to get objects stored in a previous reconstruction or analysis step, or it can be from a art::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
83 1 Brian Rebel
84 1 Brian Rebel
<pre><code class="c">
85 7 Brian Rebel
  art::Handle< std::vector<mp::MyProd> > mplistHandle;
86 1 Brian Rebel
  evt.getByLabel("moduleprocesslabel",mplistHandle);
87 1 Brian Rebel
</code></pre>
88 1 Brian Rebel
89 7 Brian Rebel
where evt is an object of type art::Event discussed below.  The art::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 art::Handle that is to be associated to the list.
90 1 Brian Rebel
91 13 Brian Rebel
You can also get all objects of a given type out of the event using the art::Event::getByType method:
92 13 Brian Rebel
93 13 Brian Rebel
<pre><code class="c">
94 64 Brian Rebel
  art::Handle< std::vector<mp::MyProd> > mplistHandle;
95 64 Brian Rebel
  evt.getByType(mplistHandle);
96 13 Brian Rebel
</code></pre>
97 13 Brian Rebel
98 13 Brian Rebel
Notice that no module label is used because we are getting all objects of the specified type out of the event.
99 13 Brian Rebel
100 7 Brian Rebel
art::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
101 1 Brian Rebel
102 1 Brian Rebel
<pre><code class="c">
103 1 Brian Rebel
  mplistHandle->size();
104 1 Brian Rebel
</code></pre>
105 1 Brian Rebel
106 55 Brian Rebel
To use the objects in the handle collection, you can 
107 1 Brian Rebel
108 55 Brian Rebel
* Use the art::Handle directly, 
109 1 Brian Rebel
<pre><code class="c">
110 16 Brian Rebel
// in the code below, ev is an art::Event...
111 16 Brian Rebel
art::Handle<std::vector<mp::MyProd> > hnd;
112 16 Brian Rebel
ev.getByLabel("...", hnd); // use the appropriate label, not "..." 
113 1 Brian Rebel
114 55 Brian Rebel
for(size_t i = 0; i < hnd->size(); ++i){
115 55 Brian Rebel
    const mp::MyProd& mp = hnd->at(i);
116 55 Brian Rebel
}
117 55 Brian Rebel
</code></pre>
118 55 Brian Rebel
119 55 Brian Rebel
* Get the collection from the art::Handle,
120 55 Brian Rebel
<pre><code class="c">
121 55 Brian Rebel
// in the code below, ev is an art::Event...
122 55 Brian Rebel
art::Handle<std::vector<mp::MyProd> > hnd;
123 55 Brian Rebel
ev.getByLabel("...", hnd); // use the appropriate label, not "..." 
124 55 Brian Rebel
125 55 Brian Rebel
std::vector<mp::MyProd>& mpvec(*hnd);
126 55 Brian Rebel
}
127 55 Brian Rebel
</code></pre>
128 55 Brian Rebel
129 55 Brian Rebel
* Make a std::list of art::Ptr<mp::MyProd>,
130 55 Brian Rebel
<pre><code class="c">
131 55 Brian Rebel
// in the code below, ev is an art::Event...
132 55 Brian Rebel
art::Handle<std::vector<mp::MyProd> > hnd;
133 55 Brian Rebel
ev.getByLabel("...", hnd); // use the appropriate label, not "..." 
134 55 Brian Rebel
135 66 Brian Rebel
std::list<art::Ptr<mp::MyProd> > ptrs;
136 16 Brian Rebel
art::fill_ptr_list(ptrs, hnd);
137 16 Brian Rebel
// now ptrs contains Ptr<mp::MyProd> instances, each pointing
138 16 Brian Rebel
// to one of the rb::Tracks in the collection to which hnd
139 1 Brian Rebel
// refers.
140 19 Brian Rebel
</code></pre>
141 1 Brian Rebel
142 55 Brian Rebel
* Make a std::vector of art::Ptr<mp::MyProd>,
143 19 Brian Rebel
<pre><code class="c">
144 19 Brian Rebel
// in the code below, ev is an art::Event...
145 19 Brian Rebel
art::Handle<std::vector<mp::MyProd> > hnd;
146 19 Brian Rebel
ev.getByLabel("...", hnd); // use the appropriate label, not "..." 
147 19 Brian Rebel
148 66 Brian Rebel
std::vector<art::Ptr<mp::MyProd> > ptrs;
149 19 Brian Rebel
art::fill_ptr_vector(ptrs, hnd);
150 66 Brian Rebel
// now ptrs contains art::Ptr<mp::MyProd> instances, each pointing
151 1 Brian Rebel
// to one of the rb::Tracks in the collection to which hnd
152 19 Brian Rebel
// refers.
153 1 Brian Rebel
</code></pre>
154 55 Brian Rebel
155 1 Brian Rebel
Use the const std::vector<mp::MyProd>, std::list< art::Ptr<mp::MyProd> >, or std::vector< art::Ptr<mp::MyProd> > if you want to be able to modify the collection of objects. 
156 16 Brian Rebel
157 16 Brian Rebel
* Make a art::PtrVector (discussed below).  
158 1 Brian Rebel
<pre><code class="c">
159 1 Brian Rebel
// make an art::PtrVector of the objects
160 7 Brian Rebel
art::PtrVector<mp::MyProd> prodvec;
161 1 Brian Rebel
for(unsigned int i = 0; i < mplistHandle->size(); ++i){
162 1 Brian Rebel
  art::Ptr<mp::MyProd> prod(mplistHandle, i);
163 1 Brian Rebel
  prodvec.push_back(prod);
164 7 Brian Rebel
}
165 1 Brian Rebel
</code></pre>
166 55 Brian Rebel
167 1 Brian Rebel
The reason for using std::list or std::vector rather than art::PtrVector<T> for this use case is that we expected people to want to modify the collection, e.g. to re-order it, or to remove elements. This is more efficient if done with the list or vector rather than the art::PtrVector.
168 1 Brian Rebel
169 1 Brian Rebel
Most code in the modules should probably use the std::list to establish the final set of art::Ptrs to mp::MyProd data objects stored in the event.  The final set of art::Ptrs can then be saved in a new data product as an art::PtrVector if that is needed.
170 19 Brian Rebel
171 19 Brian Rebel
*NB* Only art::PtrVectors correctly save the references to objects made in other modules, so if you want to save the collection, it must be done as an art::PtrVector.
172 1 Brian Rebel
173 47 Brian Rebel
h3. Upcast on read
174 1 Brian Rebel
175 64 Brian Rebel
The upcast on read functionality can be 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, recob::Tracks which inherit from recob::Prongs.  The objects are retrieved from the art::Event by passing a std::vector<const myprod::MyObject*> to the art::Event::getView() method. An example of using this functionality is
176 1 Brian Rebel
177 1 Brian Rebel
<pre><code class="c">
178 7 Brian Rebel
    // declare the std::vector
179 64 Brian Rebel
    std::vector<const recob::Prong*> prongs;
180 7 Brian Rebel
181 64 Brian Rebel
    // Read in the list of recob::Tracks we made in fTrackModuleLabel as recob::Prongs.
182 7 Brian Rebel
    evt.getView(fTrackModuleLabel,prongs);
183 1 Brian Rebel
184 1 Brian Rebel
</code></pre>
185 1 Brian Rebel
186 7 Brian Rebel
Notice that the vector is of const pointers of the requested type.  You shouldn't save these vectors anywhere (ie as collections in other data objects).  Instead they are should only be used for information, ie in the event display.
187 2 Brian Rebel
188 7 Brian Rebel
h3. "cet::search_path":https://cdcvs.fnal.gov/redmine/projects/cetlib/repository/revisions/master/entry/cetlib/search_path.h
189 2 Brian Rebel
190 64 Brian Rebel
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 a detector, mydet.gdml, as the input for the Geometry service, you would pass the geometry service the value "Geometry/gdml/mydet.gdml" as an std::string.  The cet::search_path 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
191 2 Brian Rebel
192 2 Brian Rebel
@$srt_setup -a@ 
193 2 Brian Rebel
194 2 Brian Rebel
from within that test release.
195 1 Brian Rebel
196 2 Brian Rebel
An example of using cet::search_path is
197 7 Brian Rebel
198 1 Brian Rebel
<pre><code class="c">
199 7 Brian Rebel
    
200 7 Brian Rebel
    // constructor decides if initialized value is a path or an environment variable
201 7 Brian Rebel
    // FW_SEARCH_PATH is set to be a cascade with SRT_PRIVATE_CONTEXT, SRT_PUBLIC_CONTEXT and
202 7 Brian Rebel
    // directory where perhaps auxiliary root files are stored 
203 7 Brian Rebel
    cet::search_path sp("FW_SEARCH_PATH");
204 7 Brian Rebel
205 7 Brian Rebel
    // taking a parameter from the parameter set passed into the geometry as the first argument,
206 7 Brian Rebel
    // the second argument is the local variable storing the full path - both are std::string objects
207 7 Brian Rebel
    sp.find_file(pset.get< std::string >("GDML"), fGDMLFile); //fGDMLFile is the relative path to a file
208 7 Brian Rebel
209 1 Brian Rebel
    // Open the GDML file and test if it is there
210 1 Brian Rebel
    struct stat sb;
211 1 Brian Rebel
    if (fGDMLFile.empty() || stat(fGDMLFile.c_str(), &sb)!=0)
212 7 Brian Rebel
      // failed to resolve the file name
213 1 Brian Rebel
      throw cet::exception("NoGDMLGeometry") 
214 1 Brian Rebel
	<< "geometry gdml file " << fGDMLFile << " not found!";
215 7 Brian Rebel
216 7 Brian Rebel
</code></pre>
217 7 Brian Rebel
218 64 Brian Rebel
219 7 Brian Rebel
h3. "fhicl::ParameterSet":https://cdcvs.fnal.gov/redmine/projects/fhicl-cpp/repository/revisions/master/entry/fhiclcpp/ParameterSet.h
220 7 Brian Rebel
221 48 Brian Rebel
This object keeps track of which parameters are to be set by the user at run time for a module or art::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.
222 7 Brian Rebel
223 10 Brian Rebel
* bool:                      fMyBool      (pset.get< bool >("MyBool"))
224 1 Brian Rebel
* int:                       fMyInt       (pset.get< int >("MyInt"))
225 7 Brian Rebel
* unsigned int:              fMyUInt      (pset.get< unsigned int >("MyUInt"))
226 7 Brian Rebel
* std::vector<int>:          fMyVInt      (pset.get< std::vector<int> >("MyVInt"))
227 7 Brian Rebel
* std::vector<unsigned int>: fMyVUInt     (pset.get< std::vector<unsigned int> >("MyVUInt"))
228 7 Brian Rebel
* std::string:               fMyString    (pset.get< std::string >("MyString"))
229 7 Brian Rebel
* std::vector<std::string>:  fMyVString   (pset.get< std::vector<std::string> >("MyVString"))
230 7 Brian Rebel
* double:                    fMyDouble    (pset.get< double >("MyDouble"))
231 7 Brian Rebel
* std::vector<double>:       fMyVDouble   (pset.get< std::vector<double> >("MyDouble"))
232 7 Brian Rebel
233 64 Brian Rebel
Other types are available, but the above list should serve almost all a user's needs.  It is also possible to pass entire parameter sets in as a single variable.  Please see this "quick start guide":https://cdcvs.fnal.gov/redmine/attachments/5348/quick_start.pdf for more details.
234 1 Brian Rebel
235 64 Brian Rebel
h3. "art::ServiceHandle":https://cdcvs.fnal.gov/redmine/projects/art/repository/revisions/master/changes/art/Framework/Services/Registry/ServiceHandle.h
236 1 Brian Rebel
237 64 Brian Rebel
The art::ServiceHandle 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.
238 1 Brian Rebel
239 64 Brian Rebel
It is possible to store a service handle as a data member of a module or other object.  One should do this if the handle is expected to be called many times during the processing of a single event as that is the most efficient way to access the handle.
240 64 Brian Rebel
241 1 Brian Rebel
h3. "art::TFileService":https://cdcvs.fnal.gov/redmine/projects/art/repository/revisions/master/entry/art/Framework/Services/Optional/TFileService.h
242 1 Brian Rebel
243 1 Brian Rebel
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
244 1 Brian Rebel
245 1 Brian Rebel
<pre><code class="c">
246 1 Brian Rebel
    // get the geometry to figure out something for the histogram
247 1 Brian Rebel
    art::ServiceHandle<geo::Geometry> geo;
248 1 Brian Rebel
249 1 Brian Rebel
    // get access to the TFile service
250 1 Brian Rebel
    art::ServiceHandle<art::TFileService> tfs;
251 1 Brian Rebel
252 1 Brian Rebel
    // make the histogram - fHist is assumed to have been declared in the .h file
253 1 Brian Rebel
    fHist    = tfs->make<TH1D>("channels",  ";channel;# PE",  geo->Nchannels(), 0, geo->Nchannels());
254 1 Brian Rebel
255 1 Brian Rebel
    // note that for some reason ROOT does not automatically connect TGraphs to the output directory when created 
256 1 Brian Rebel
    // like it does for histograms.  So we have to do that ourselves using the ROOT global directory variable gDirectory
257 1 Brian Rebel
    fGraph   = tfs->make<TGraph>(); //default constructor, set number of points and values later
258 1 Brian Rebel
    gDirectory->Append(fGraph);
259 1 Brian Rebel
260 1 Brian Rebel
</code></pre>
261 1 Brian Rebel
262 64 Brian Rebel
h3. "Message Facility":https://cdcvs.fnal.gov/redmine/projects/messagefacility/wiki/Tutorial_for_MessageFacility_v12_Configuration and "MessageLogger":https://cdcvs.fnal.gov/redmine/projects/messagefacility/repository/revisions/master/entry/messagefacility/MessageLogger/MessageLogger.h
263 1 Brian Rebel
264 64 Brian Rebel
*The Message Levels*
265 1 Brian Rebel
266 64 Brian Rebel
The MessageLogger provides several levels of messages that can be used to print information to an output log.  The decision of which level to use is your first way to determine how frequently your message will be printed.  If you choose the INFO level, then typically all such messages are printed; if instead you choose the DEBUG level, then typically those messages are not printed unless a specific environmental flag is set or the message service is configured properly.  
267 1 Brian Rebel
268 64 Brian Rebel
The levels most likely to be useful are LOG_DEBUG, mf::LogInfo, mf::LogVerbatim, mf::LogWarning and mf::LogError.  Note there is no mf:: in front of LOG_DEBUG because it is a macro that will include the file and line numbers of the code producing the output.  These are listed in order of severity and have the following behaviors:
269 64 Brian Rebel
270 64 Brian Rebel
    * LogInfo, LogWarning, and LogError represent three levels of "severity" of the message. It is possible (see MessageLogger Parameters ) to configure the job to ignore all LogInfo messages, or all messages of severity less than LogError.
271 64 Brian Rebel
    * LogVerbatim is identical in all ways to LogInfo, except that absolutely no message formatting is performed, and no context, module, or other information is appended to the message. This is appropriate, for example, if the program has prepared a nicely-formatted table for output.
272 64 Brian Rebel
    * The category should specify what this message is about. The category will generally appear as the first part of the message, but it also plays two other roles:
273 64 Brian Rebel
         1. It is possible to set limits on how many times some specific type of message will be sent to the outputs of the logger. By "type" we mean any messages with some specific category. See MessageLogger Parameters for details.
274 64 Brian Rebel
         2. When message statistics are provided, the counts of how many times messages of a given type were issued are keyed to category, module label, and (if provided) subroutine. 
275 64 Brian Rebel
      Normally a category name should be up to 20 characters long, without special characters other than underscore.
276 64 Brian Rebel
    * It is unnecessary to explicitly specify the module label or the run/event number; these are automatically provided by the logger.
277 64 Brian Rebel
    * An arbitrary number of additional objects << a << b << ... << z can be appended to the message. These can be strings, ints, doubles, or any object that has an operator<< to an ostream. (Or the message can be issued with no additional objects at all.)
278 64 Brian Rebel
    * There is no need to add spaces at the beginning or end of text items sent to the message, or to add text separators between numerical items. This spacing is taken care of by the logger. However, if any item appended to a message ends in a space, then it is assumed that the user is handling spacing explicitly, and no further automatic spaces are inserted for that message.
279 64 Brian Rebel
    * There is no need to affix any sort of endl; when the statement ends the message will be dispatched.
280 64 Brian Rebel
    * Newline characters can be included in the objects appended to the message. These will be used in formatting the message. But they are generally not necessary: Line breaks are automatically inserted if the next appended object would cause the line to exceed 80 characters. 
281 64 Brian Rebel
    * LOG_DEBUG is identical to the others, except:
282 64 Brian Rebel
283 64 Brian Rebel
       * LOG_DEBUG affixes the __FILE__ and __LINE__ number to the message.
284 64 Brian Rebel
       * LOG_DEBUG messages are considered to be lower in severity than LogInfo messages.
285 64 Brian Rebel
       * By default, LOG_DEBUG messages will be rapidly discarded with a minimum of overhead. The user must specify in the .fcl file LOG_DEBUG messages from various modules that are to be enabled
286 64 Brian Rebel
       * Because it must get __FILE__ and __LINE__ from the spot issuing the message, LOG_DEBUG is implemented as a macro rather than a free function.
287 64 Brian Rebel
       * Because LOG_DEBUG is a macro, it is not prepended with the mf:: namespace designation. 
288 64 Brian Rebel
289 64 Brian Rebel
*Using the Message Service in Code*
290 64 Brian Rebel
291 1 Brian Rebel
In order to issue messages, the module must include the MessageLogger header:
292 1 Brian Rebel
293 1 Brian Rebel
<pre><code class="c">
294 1 Brian Rebel
  #include "messagefacility/MessageLogger/MessageLogger.h"
295 1 Brian Rebel
</code></pre>
296 6 Brian Rebel
297 64 Brian Rebel
Having included the necessary MessageLogger header, when code wishes to issue a message, one of these functions can be used:
298 1 Brian Rebel
299 1 Brian Rebel
<pre><code class="c">
300 1 Brian Rebel
  mf::LogError    ("category") << a << b << ... << z;
301 1 Brian Rebel
  mf::LogWarning  ("category") << a << b << ... << z;
302 1 Brian Rebel
  mf::LogInfo     ("category") << a << b << ... << z;
303 1 Brian Rebel
  mf::LogVerbatim ("category") << a << b << ... << z;
304 64 Brian Rebel
  LOG_DEBUG       ("category") << a << b << ... << z;
305 1 Brian Rebel
</code></pre>
306 1 Brian Rebel
307 64 Brian Rebel
The easiest way to produce output that is formatted to your specifications is to emply the mf::LogVerbatim level.  This level has absolutely no extra formatting from the message service tacked on to it and most closely resembles what one would expect from std::cout.  
308 1 Brian Rebel
309 64 Brian Rebel
You can use std formatting functions in all message service levels.  For example
310 1 Brian Rebel
311 64 Brian Rebel
<pre>
312 64 Brian Rebel
mf::LogVerbatim("MyMessageStream") << "define the width of the following field to be 5, " 
313 64 Brian Rebel
                                   << std::setw(5) << 999 
314 64 Brian Rebel
                                   << " and now define the precision of the following field to be 1, " 
315 64 Brian Rebel
                                   << std::setprecision(2) << 1.00012;
316 64 Brian Rebel
</pre>
317 1 Brian Rebel
318 64 Brian Rebel
The above example uses mf::LogVerbatim, but the same would work in LOG_DEBUG, mf::LogInfo, mf::LogWarning, and mf::LogError.
319 1 Brian Rebel
320 64 Brian Rebel
*Configuring the Message Service*
321 6 Brian Rebel
322 64 Brian Rebel
Here is a "tutorial":https://cdcvs.fnal.gov/redmine/projects/messagefacility/wiki/Tutorial_for_MessageFacility_v12_Configuration for configuring the message facility.  Below are some helpful tips for configuring message output.
323 6 Brian Rebel
324 64 Brian Rebel
The .fcl file controlling the job should contain the line
325 6 Brian Rebel
326 64 Brian Rebel
<pre>
327 64 Brian Rebel
  message:      @local::standard_xxx
328 64 Brian Rebel
</pre>
329 28 Brian Rebel
330 64 Brian Rebel
in the services block of the file, where xxx indicates the message level severity. The various predefined configurations are defined in the source:trunk/Utilities/messageservice.fcl file.  Those options are
331 1 Brian Rebel
332 64 Brian Rebel
<pre>
333 64 Brian Rebel
standard_debug
334 64 Brian Rebel
standard_info
335 64 Brian Rebel
standard_warning
336 64 Brian Rebel
standard_error
337 64 Brian Rebel
</pre>
338 28 Brian Rebel
339 64 Brian Rebel
*NB* you can only use one of the above in a job .fcl file.
340 1 Brian Rebel
341 64 Brian Rebel
The MessageLogger can be configured to set the number of messages printed and to send each class of message to a different output stream. For example, see the standard_warning configuration of the source:trunk/Utilities/messageservice.fcl file, which is repeated here
342 27 Brian Rebel
343 64 Brian Rebel
<pre>
344 64 Brian Rebel
standard_warning:
345 64 Brian Rebel
{ 
346 63 Jonathan Paley
347 64 Brian Rebel
 destinations:  #defines the behavior of the configuration
348 64 Brian Rebel
 {  
349 64 Brian Rebel
  warningmsg:   #conveniently defined name for a destination, this is not a FHICL key word
350 64 Brian Rebel
  {
351 64 Brian Rebel
   type:      "cout"	  #tells the message service to output this destination to cout
352 64 Brian Rebel
   threshold: "WARNING"   #tells the message service that this destination applies to WARNING and higher level messages
353 64 Brian Rebel
   append:    true        #says to append all messages to the output
354 64 Brian Rebel
   categories:            #these correspond to the strings in the mf::LogWarning("") calls in the code
355 64 Brian Rebel
   {
356 64 Brian Rebel
     default:             #defines a default behavior, this is a FHICL key word
357 64 Brian Rebel
     {
358 64 Brian Rebel
      limit:       1000   #limits the total number of messages in this category to 1000
359 64 Brian Rebel
      timespan:    60     #in seconds, tells the message service it can output 1000 messages from this category every minute
360 64 Brian Rebel
     }
361 1 Brian Rebel
362 64 Brian Rebel
     RecoBaseDefaultCtor: #an example of a loud category in LArSoft mf::LogWarning messages
363 64 Brian Rebel
     {
364 64 Brian Rebel
      limit: 10           #limit the total number printed to 10
365 64 Brian Rebel
      timespan: 600       #only print this category every 5 minutes
366 64 Brian Rebel
     }
367 1 Brian Rebel
368 64 Brian Rebel
   } # end categories
369 64 Brian Rebel
  } # end warningmsg
370 64 Brian Rebel
 } # end destinations
371 64 Brian Rebel
} # end standard_warning
372 64 Brian Rebel
</pre>
373 12 Christopher Green
374 64 Brian Rebel
If one wanted to add another category in the job control .fcl file, it can be done with these lines after the services block:
375 12 Christopher Green
376 64 Brian Rebel
<pre>
377 64 Brian Rebel
services.message.destinations.warningmsg.categories.YourStringHere: { limit: 100 timespan: 60 }
378 64 Brian Rebel
</pre>
379 64 Brian Rebel
380 64 Brian Rebel
If instead, you want to add some message printing for info level messages you can add the following to the fcl file after the services block:
381 64 Brian Rebel
382 64 Brian Rebel
<pre>
383 64 Brian Rebel
services.message.destinations.infomsg: {
384 64 Brian Rebel
   type:      "cout"	  #tells the message service to output this destination to cout
385 64 Brian Rebel
   threshold: "INFO"      #tells the message service that this destination applies to INFO and higher level messages
386 64 Brian Rebel
   append:    true        #says to append all messages to the output
387 64 Brian Rebel
   categories{
388 64 Brian Rebel
     default:        {limit: 0}  #don't print anything at the infomsg level except the explicitly named categories
389 64 Brian Rebel
     YourStringHere: {limit: 100 timespan: 60 }
390 64 Brian Rebel
     YourOtherString:{limit: 1   timespan: 1000} 
391 64 Brian Rebel
  }
392 64 Brian Rebel
}
393 64 Brian Rebel
</pre>
394 64 Brian Rebel
395 64 Brian Rebel
h3. "cet::exception":https://cdcvs.fnal.gov/redmine/projects/cetlib/repository/revisions/master/entry/cetlib/exception.h 
396 64 Brian Rebel
397 1 Brian Rebel
The cet::exception can be used to cause the framework to end a job gracefully if some predetermined bad thing happens.  The use of the art::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.
398 1 Brian Rebel
399 64 Brian Rebel
cet::exception can be used as follows:
400 1 Brian Rebel
401 1 Brian Rebel
<pre><code class="c">
402 63 Jonathan Paley
if(x > 2) throw cet::exception("SomeUsefulDescription") << "x = " << x << " is too big";
403 1 Brian Rebel
</code></pre>
404 34 Brian Rebel
405 35 Brian Rebel
Detailed instructions for using exceptions under the former incarnation of ART are attached to this page, attachment:CMS_SWGuideEdmExceptionUse.pdf.  These instructions may no longer be accurate.
406 1 Brian Rebel
407 54 Brian Rebel
In short however, the default behavior of the framework upon catching an exception is to rethrow (except for some system exceptions, which skip the event). However, one can specify the behavior for exceptions with the following configuration fragment:
408 54 Brian Rebel
409 1 Brian Rebel
<pre>
410 54 Brian Rebel
services.scheduler.XXXX: [ "SomeUsefulDescription", "SomeOtherUsefulDescription", ... ]
411 34 Brian Rebel
</pre> 
412 34 Brian Rebel
413 34 Brian Rebel
where @XXX@ can be:
414 35 Brian Rebel
* @Rethrow@;
415 34 Brian Rebel
* @IgnoreCompletely@;
416 1 Brian Rebel
* @SkipEevent@;
417 1 Brian Rebel
* @FailModule@ (behave as if the module returned a failure value for this event);
418 1 Brian Rebel
* @FailPath@ (behave as if the path rejected this event).
419 1 Brian Rebel
420 1 Brian Rebel
Note that the @FailModule@ setting does not imply a path rejection if the module throwing the exception so configured is a filter set to "VETO" or "IGNORE."
421 1 Brian Rebel
422 1 Brian Rebel
A NOvA specific discussion of using cet::exceptions can be found here: [[NOVA exceptions]]
423 1 Brian Rebel
424 1 Brian Rebel
h3. "art::Ptr<T>":https://cdcvs.fnal.gov/redmine/projects/art/repository/revisions/master/entry/art/Persistency/Common/Ptr.h and "art::PtrVector<T>":https://cdcvs.fnal.gov/redmine/projects/art/repository/revisions/master/entry/art/Persistency/Common/PtrVector.h
425 1 Brian Rebel
426 64 Brian Rebel
The art::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 art::PtrVector<recob::Hit> pointing to the hits contained in the recob::Cluster.  The art::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 art::Ptr<T>::get() or to check if the art::Ptr<T> is pointing to a legitimate object using art::Ptr<T>::isNull().
427 1 Brian Rebel
428 1 Brian Rebel
An art::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 art::Ptr<T> if you have an art::Handle to a collection of objects of type T.  art::Ptr<T> cannot be instantiated like an object of type T, 
429 1 Brian Rebel
430 1 Brian Rebel
<pre><code class="c">
431 1 Brian Rebel
// The following line will NOT work
432 1 Brian Rebel
art::Ptr<T> myt = new T(); 
433 1 Brian Rebel
</code></pre>
434 1 Brian Rebel
435 34 Brian Rebel
or similar will not work because the object you are interested in for that code has not been first stored in the event record.
436 1 Brian Rebel
437 64 Brian Rebel
Please see this "note":https://cdcvs.fnal.gov/redmine/projects/art/wiki/A_note_on_the_behavior_of_Ptr about art::Ptrs as well.
438 1 Brian Rebel
439 64 Brian Rebel
An art::PtrVector<T> is a vector of art::Ptr<T> objects.  It provides the basic functionality you would expect from a std::vector, including iterators, size(), begin() and end() methods.  
440 64 Brian Rebel
441 64 Brian Rebel
This is a code snippet that iterates on a PtrVector of Hits.
442 64 Brian Rebel
443 67 Justin Vasel
<pre><code class="c">
444 64 Brian Rebel
    for(art::PtrVector<recob::Hit>::const_iterator ihit = hits.begin();
445 64 Brian Rebel
	ihit != hits.end(); ++ihit) {
446 64 Brian Rebel
      const art::Ptr<recob::Hit>& phit = *ihit;
447 64 Brian Rebel
      geo::View_t view = phit->View();
448 64 Brian Rebel
      //...
449 64 Brian Rebel
    }
450 67 Justin Vasel
</code></pre>
451 64 Brian Rebel
452 64 Brian Rebel
453 64 Brian Rebel
An art::PtrVector<T> can also be sorted, viz.
454 64 Brian Rebel
455 58 Ruth Toner
<pre><code class="c">
456 1 Brian Rebel
art::PtrVector< mp::MyProd > mpcol;
457 1 Brian Rebel
mpcol.sort();
458 1 Brian Rebel
</code></pre>
459 1 Brian Rebel
460 1 Brian Rebel
This example makes use of the predefined "<" operator of the mp::MyProd.  If you want to sort using a function, first define a predicate in the namespace of your module
461 1 Brian Rebel
462 1 Brian Rebel
<pre><code class="c">
463 1 Brian Rebel
namespace mymodule {
464 1 Brian Rebel
465 1 Brian Rebel
  struct SortByTime {
466 1 Brian Rebel
    bool operator()(mp::MyProd const& a, mp::MyProd const& b) const { return a.Time() < b.Time(); }
467 1 Brian Rebel
  };
468 1 Brian Rebel
469 1 Brian Rebel
  //////--------- intervening code calling constructors, destructors, etc, now we are in the produce method ---/////////
470 1 Brian Rebel
471 1 Brian Rebel
  
472 1 Brian Rebel
  art::PtrVector< mp::MyProd > mpcol;
473 1 Brian Rebel
  // fill the PtrVector as in the examples in the art::Handle section above
474 1 Brian Rebel
475 1 Brian Rebel
  mpcol.sort(mymodule::SortByTime());
476 1 Brian Rebel
477 1 Brian Rebel
</code></pre>
478 1 Brian Rebel
479 1 Brian Rebel
h3. "art::Assns":https://cdcvs.fnal.gov/redmine/projects/art/repository/revisions/master/changes/art/Persistency/Common/Assns.h
480 1 Brian Rebel
481 64 Brian Rebel
art::Assns are a way to associate (Assns is a contraction for associations) objects of one type with another.  For example, you may want to associate a recob::Cluster with the recob::Hit objects comprising the recob::Cluster.  The art:Assns object allows you to navigate these associations bidirectionally, that is you can ask a recob::Cluster which recob::Hits it contains, as well as as a recob::Hit to which recob::Cluster it belongs.  The art::Assns also allow us to avoid storing these connections in the higher level object that is being associated.  Instead the associations are stored in the event record.
482 1 Brian Rebel
483 69 Matthew Strait
A set of utility functions to perform the necessary steps to associate objects for storage in the art::Event are found in source:trunk/Utilities/AssociationUtil.h  There are also methods to retrieve a collection of objects of one type that are not associated with objects of another type.  Those methods allow one to retrieve, for example, all recob::Hits from an event that are not associated with recob::Tracks.  The comments in that file describe how to use the functions.  
484 1 Brian Rebel
485 1 Brian Rebel
To make use of the associations and retrieve objects from the file, one would do
486 1 Brian Rebel
487 64 Brian Rebel
<pre><code class="C">
488 1 Brian Rebel
489 64 Brian Rebel
// below trackListHandle is of type art::Handle< std::vector<recob::Track> >, 
490 64 Brian Rebel
// evt is an art::Event, and trackCreatorModule is an std::string holding the 
491 64 Brian Rebel
// label of the module making the tracks and the associations of hits to tracks
492 64 Brian Rebel
art::FindMany<recob::Hit> fmh(trackListHandle, evt, trackCreatorModule);
493 1 Brian Rebel
494 1 Brian Rebel
// loop over all tracks in the handle and get their hits
495 1 Brian Rebel
for(size_t t = 0; t < trackListHandle->size(); ++t){
496 64 Brian Rebel
   std::vector<const recob::Hit*> hits = fmh.at(t);
497 1 Brian Rebel
}
498 1 Brian Rebel
499 1 Brian Rebel
// can also get a collection of art::Ptrs instead of const pointers
500 64 Brian Rebel
art::FindManyP<recob::Hit> fmh(trackListHandle, evt, trackCreatorModule);
501 1 Brian Rebel
502 1 Brian Rebel
// loop over all tracks in the handle and get their hits
503 1 Brian Rebel
for(size_t t = 0; t < trackListHandle->size(); ++t){
504 64 Brian Rebel
   std::vector<art::Ptr<recob::Hit> > hits = fmh.at(t);
505 1 Brian Rebel
}
506 1 Brian Rebel
507 67 Justin Vasel
</code></pre>
508 1 Brian Rebel
509 1 Brian Rebel
One can also use the art::FindOne and art::FindOneP, see the detailed description on how to use art::Assns is "here.":https://cdcvs.fnal.gov/redmine/projects/art/wiki/Inter-Product_References  The art::FindOne returns a cet::maybe_ref, whose interface is defined "here.":http://cdcvs.fnal.gov/lxr/cetlib/source/cetlib/maybe_ref.h#044  The cet::maybe_ref can be tested for validity, allowing a user to be sure a valid association was created.
510 1 Brian Rebel
511 1 Brian Rebel
*NB* The art::FindMany(P) and art::FindOne(P) are smart query objects and should only be instantiated once for a given collection.  If they are instantiated once for each item in a art::Handle, art::PtrVector, art::View or std::vector< art::Ptr<T> > then a heavy performance price will be paid as a lookup table is made multiple times.
512 1 Brian Rebel
513 65 Brian Rebel
If the Assn being retrieved has an instance name associated with it, in addition to a module label, the std::string label (above, trackCreatorModule) can be replaced with an art::InputTag. In this example, assnCreatorModule would be replaced with art::InputTag(trackCreatorModule, trackCreatorInstance), where trackCreatorInstance is a string with the name of the instance.
514 65 Brian Rebel
515 65 Brian Rebel
516 64 Brian Rebel
h3. art::RandomNumberGenerator Service
517 64 Brian Rebel
518 64 Brian Rebel
A nice description of how to use this service can be found "here":http://mu2e.fnal.gov/public/hep/computing/Random.shtml.  Note that this write up is for the older fw implementation of art, but there are only minor differences.
519 64 Brian Rebel
520 64 Brian Rebel
To store the "state":https://cdcvs.fnal.gov/redmine/projects/art/repository/revisions/master/entry/art/Persistency/Common/RNGsnapshot.h of the random number engines for each event one must add the RandomNumberSaver module to the list of physics producers to be run by the job.  The necessary line to add to the fcl file is
521 64 Brian Rebel
522 64 Brian Rebel
<pre>
523 64 Brian Rebel
physics{
524 64 Brian Rebel
 producers{
525 64 Brian Rebel
   ...
526 64 Brian Rebel
   rns: { module_type: "RandomNumberSaver" }
527 64 Brian Rebel
 }
528 64 Brian Rebel
 
529 64 Brian Rebel
 ...
530 64 Brian Rebel
}
531 64 Brian Rebel
</pre>
532 64 Brian Rebel
533 64 Brian Rebel
A more detailed description of how to use the service in your code and store the state of the generator in the event record and retrieve it later is located [[Saving_and_recovering_random_number_generator_states_|here]].
534 64 Brian Rebel
535 1 Brian Rebel
h2. Making Objects to Store in the Output
536 1 Brian Rebel
537 1 Brian Rebel
Making objects to store in the art::Event is a straightforward operation.  The first step is to declare a container for the objects, 
538 1 Brian Rebel
539 67 Justin Vasel
<pre><code class="c">
540 64 Brian Rebel
std::unique_ptr<std::vector<mp::MyProd> > mpCollection(new std::vector<mp::MyProd>);
541 67 Justin Vasel
</code></pre>
542 1 Brian Rebel
543 1 Brian Rebel
Here we used the std::auto_ptr because it handles the cleanup of the memory for the collection for us.  
544 1 Brian Rebel
545 64 Brian Rebel
The mpCollection now behaves just like a std::vector, except one accesses the std::vector methods using the "->" operator.  Once the collection has been filled (and it can be a collection of just one object), it is written to the event by doing
546 1 Brian Rebel
547 67 Justin Vasel
<pre><code class="c">
548 64 Brian Rebel
event.put(std::move(mpCollection));
549 67 Justin Vasel
</code></pre>
550 63 Jonathan Paley
551 64 Brian Rebel
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.
552 1 Brian Rebel
553 1 Brian Rebel
h2. Schema Evolution for Data Products
554 1 Brian Rebel
555 1 Brian Rebel
Data products may change over time and we will want to do everything we can to ensure backwards compatibility between old and new versions.  Please see "this page":https://cdcvs.fnal.gov/redmine/projects/art/wiki/Facilitating_Schema_Evolution_for_Data_Products on the ART wiki for information on how to evolve a data product while still maintaining backwards compatibility.
556 1 Brian Rebel
557 1 Brian Rebel
h2. Making a Module
558 1 Brian Rebel
559 64 Brian Rebel
Below are examples of how to make both an EDProducer module and an EDAnalyzer module.  The examples show a basic .cc file for each.  
560 1 Brian Rebel
561 64 Brian Rebel
*Important* Module names may not contain underscores. Underscores are special characters used by the ART system for storing data products in an event to label the products according to what module, instance and process created them.  Using underscores in module names will result in your job not running.
562 1 Brian Rebel
563 64 Brian Rebel
The artmod command is useful for generating these files required for plugging a new module (Analyzer, Producer, or Filter) into the framework. The command documents itself:
564 7 Brian Rebel
565 64 Brian Rebel
@% artmod --help@
566 7 Brian Rebel
567 64 Brian Rebel
Suppose I'm working in a package called "MyPackage" which uses the namespace "mp" and I want to create a producer module called "MyProducer".  Moreover, assume that I want to include certain methods from the art::EDProducer base class, like art::EDProducer::beginJob() and art::EDProducer::reconfigure():
568 1 Brian Rebel
569 64 Brian Rebel
@% artmod --header-loc MyPackage -e beginJob -e reconfigure producer mp::MyProducer@
570 1 Brian Rebel
571 64 Brian Rebel
I can also pass it methods specific to my module using the -e tag as long as the interface is completely defined, ie
572 1 Brian Rebel
573 64 Brian Rebel
@% artmod --header-loc MyPackage -e beginJob -e reconfigure -e "bool CheckSomethingOut(double d)" producer mp::MyProducer@
574 1 Brian Rebel
575 64 Brian Rebel
Similarly I could pass data members like
576 64 Brian Rebel
577 64 Brian Rebel
@% artmod --header-loc MyPackage -e beginJob -e reconfigure -e "bool CheckSomethingOut(double d)" -e "double fMyDouble" producer mp::MyProducer@
578 64 Brian Rebel
579 64 Brian Rebel
Read the help screen for more details.
580 64 Brian Rebel
581 64 Brian Rebel
*NB Objects are stored in the art::Event as collections of references, not pointers.  You need to get them out of the event as collections of references, not pointers.*
582 64 Brian Rebel
583 64 Brian Rebel
h3. A word about Algorithm objects
584 64 Brian Rebel
585 64 Brian Rebel
Before describing how to use the ART module objects, it is worth discussing a complementary concept used in NOvASoft.
586 64 Brian Rebel
587 64 Brian Rebel
In NOvASoft we have the concept of an Algorithm object.  Its basic purpose is to take data products in and return either new or modified data products back to the user.  In almost all cases, the user will be a EDProducer or EDFilter type module.  The reason to have this additional type of object, which is not defined in the ART framework, is to facilitate use of algorithms in multiple modules.  That is, a user may write a module that makes use of both Algorithm objects A&B while another may only want to use Algorithm object A. If the algorithm code is written outside of the modules, then the code can be reused in many modules.
588 64 Brian Rebel
589 64 Brian Rebel
The Algorithm objects that are used in modules should have constructors that take a fhicl::ParameterSet const& p as an argument, and they must also define reconfigure(fhicl::ParameterSet const& p) methods.  The constructor should call the reconfigure method in order to configure any parameters needed by the Algorithm.  The modules owning the Algorithm object should call the Algorithm's reconfigure method from within the module reconfigure method. 
590 64 Brian Rebel
591 64 Brian Rebel
h3. EDProducer
592 64 Brian Rebel
593 64 Brian Rebel
<pre><code class="c">
594 1 Brian Rebel
#ifndef MYPRODUCER_H
595 1 Brian Rebel
#define MYPRODUCER_H
596 1 Brian Rebel
597 64 Brian Rebel
#include <iostream>
598 1 Brian Rebel
599 64 Brian Rebel
// Framework includes
600 64 Brian Rebel
#include "art/Framework/Core/ModuleMacros.h" 
601 64 Brian Rebel
#include "art/Framework/Core/EDProducer.h"
602 64 Brian Rebel
#include "art/Framework/Principal/Event.h" 
603 64 Brian Rebel
#include "art/Framework/Principal/Handle.h" 
604 64 Brian Rebel
#include "art/Persistency/Common/Ptr.h" 
605 64 Brian Rebel
#include "art/Persistency/Common/PtrVector.h" 
606 64 Brian Rebel
#include "art/Framework/Services/Registry/ServiceHandle.h" 
607 64 Brian Rebel
#include "art/Framework/Services/Optional/TFileService.h" 
608 64 Brian Rebel
#include "art/Framework/Services/Optional/TFileDirectory.h" 
609 64 Brian Rebel
#include "fhiclcpp/ParameterSet.h" 
610 64 Brian Rebel
#include "messagefacility/MessageLogger/MessageLogger.h" 
611 64 Brian Rebel
#include "cetlib/exception.h"
612 64 Brian Rebel
#include "cetlib/search_path.h"
613 64 Brian Rebel
614 64 Brian Rebel
#include "Geometry/Geometry.h"
615 64 Brian Rebel
#include "Utilities/LArProperties.h"
616 64 Brian Rebel
#include "MyProducts/MyProduct.h"
617 64 Brian Rebel
#include "MyProducts/MyOtherProduct.h"
618 64 Brian Rebel
619 64 Brian Rebel
#include "TH1.h"
620 64 Brian Rebel
621 64 Brian Rebel
namespace mp {
622 1 Brian Rebel
  
623 1 Brian Rebel
  ///class to produce a data product
624 1 Brian Rebel
  class MyProducer : public art::EDProducer {
625 1 Brian Rebel
    
626 7 Brian Rebel
  public:
627 1 Brian Rebel
    
628 1 Brian Rebel
    explicit MyProducer(fhicl::ParameterSet const& pset);  // the explicit tag tells the compiler that MyProducer is different from fhicl::ParameterSet
629 1 Brian Rebel
    virtual ~MyProducer();
630 1 Brian Rebel
    void produce(art::Event& evt);                         // makes the objects I want made
631 64 Brian Rebel
    void beginJob();                                      // does things like make histograms at the beginning of the job
632 64 Brian Rebel
    void beginRun(art::Run& run);                         // Happens before each run, so this is a good place to pick up run dependent variables like Lifetime etc. 
633 64 Brian Rebel
    void reconfigure(fhicl::ParameterSet const& pset);    // every module should have one of these to allow the event display to alter configurations
634 1 Brian Rebel
    
635 1 Brian Rebel
  private:
636 1 Brian Rebel
        
637 1 Brian Rebel
    double      fDouble;          ///< some data member
638 64 Brian Rebel
    double      fRunProperty;     ///< a property that changes from run to run
639 1 Brian Rebel
    std::string fPrevModuleLabel; ///< label of the module making objects that i need for this step
640 1 Brian Rebel
    TH1D*       fHist;            ///< a histogram data member
641 1 Brian Rebel
    
642 1 Brian Rebel
  }; // class MyProducer
643 1 Brian Rebel
644 1 Brian Rebel
  //-----------------------------------------------------
645 64 Brian Rebel
  MyProducer::MyProducer(fhicl::ParameterSet const& pset)
646 1 Brian Rebel
  {
647 64 Brian Rebel
    this->reconfigure(pset);
648 1 Brian Rebel
    produces< std::vector<mp::MyOtherProduct> >(); // this line tells the module what it is going to make, you must have one line
649 1 Brian Rebel
                                                   // for each type of collection to be made
650 1 Brian Rebel
651 7 Brian Rebel
  }
652 7 Brian Rebel
653 1 Brian Rebel
  //-----------------------------------------------------
654 1 Brian Rebel
  MyProducer::~MyProducer()
655 1 Brian Rebel
  {
656 1 Brian Rebel
  }
657 1 Brian Rebel
658 1 Brian Rebel
  //-----------------------------------------------------
659 64 Brian Rebel
  void MyProducer::reconfigure(fhicl::ParameterSet const& pset)
660 64 Brian Rebel
  {
661 64 Brian Rebel
    fDouble          = pset.get< double >     ("TheDouble");
662 64 Brian Rebel
    fPrevModuleLabel = pset.get< std::string >("PreviousModuleLabel");
663 64 Brian Rebel
    return;
664 64 Brian Rebel
  }
665 64 Brian Rebel
666 64 Brian Rebel
  //-----------------------------------------------------
667 1 Brian Rebel
  void MyProducer::beginJob()
668 1 Brian Rebel
  {
669 1 Brian Rebel
    // get access to the TFile service
670 63 Jonathan Paley
    art::ServiceHandle<art::TFileService> tfs;
671 1 Brian Rebel
672 1 Brian Rebel
    // get the geometry to figure out something for the histogram
673 1 Brian Rebel
    art::ServiceHandle<geo::Geometry> geo;
674 1 Brian Rebel
675 64 Brian Rebel
    fHist    = tfs->make<TH1D>("channels",  ";channels;",  geo->NPlanes()*geo->Plane(0)->Nwires(), 0, geo->NPlanes()*geo->Plane(0)->Ncells());
676 1 Brian Rebel
677 1 Brian Rebel
    return;
678 1 Brian Rebel
  }
679 1 Brian Rebel
680 1 Brian Rebel
  //-----------------------------------------------------
681 64 Brian Rebel
  void MyProducer::beginRun(art::Run& run)
682 64 Brian Rebel
  {
683 64 Brian Rebel
   //get Access to the LArProperties service:
684 64 Brian Rebel
   art::ServiceHandle<util::LArProperties> larp;
685 64 Brian Rebel
   //get temperature from LArProperties - it will have been updated from the DB by now.
686 64 Brian Rebel
   fRunProperty = larp->Temperature();
687 64 Brian Rebel
  }
688 64 Brian Rebel
689 64 Brian Rebel
  //-----------------------------------------------------
690 1 Brian Rebel
  void MyProducer::produce(art::Event& evt)
691 63 Jonathan Paley
  {
692 1 Brian Rebel
    
693 1 Brian Rebel
    //get a collection of electrons
694 64 Brian Rebel
    std::unique_ptr<std::vector<mp::MyOtherProduct> > mopcol(new std::vector<mp::MyOtherProduct>);
695 1 Brian Rebel
696 1 Brian Rebel
    // maybe I will need the geometry service here too
697 1 Brian Rebel
    art::ServiceHandle<geo::Geometry> geom;
698 1 Brian Rebel
  
699 1 Brian Rebel
    double xyz[3] = {0.};
700 7 Brian Rebel
    double xyz1[3] = {0.};
701 64 Brian Rebel
    int planes = geom->Nplanes();
702 1 Brian Rebel
  
703 1 Brian Rebel
    ///plane 0 is the first induction plane, every plane has a wire 0
704 1 Brian Rebel
    geom->Plane(0)->GetCenter(xyz);
705 10 Brian Rebel
706 1 Brian Rebel
    // grab the mp::MyProducts made in the last module
707 1 Brian Rebel
    art::Handle< std::vector<mp::MyProduct> > mplistHandle;
708 10 Brian Rebel
    evt.getByLabel(fPrevModuleLabel,mplistHandle);
709 7 Brian Rebel
710 1 Brian Rebel
    // loop over the list of MyProducts
711 1 Brian Rebel
    for(unsigned int i = 0; i < mplistHandle->size(); ++i){
712 7 Brian Rebel
713 64 Brian Rebel
      //get a art::Ptr to the MyProducts
714 7 Brian Rebel
      art::Ptr<mp::MyProduct> mpMyProd(mplistHandle, i);
715 10 Brian Rebel
716 10 Brian Rebel
      // do something to turn out MyOtherProducts - not shown here
717 1 Brian Rebel
718 1 Brian Rebel
      // add the new MyOtherProduct to the collection
719 1 Brian Rebel
      mopcol->push_back(myOtherProd)
720 1 Brian Rebel
    }
721 1 Brian Rebel
722 64 Brian Rebel
    evt.put(std::move(mopcol));
723 1 Brian Rebel
724 1 Brian Rebel
    // mopcol is no longer a valid pointer - don't use it any more!
725 1 Brian Rebel
    // if for some reason you still want access to the products in mopcol, then use 
726 1 Brian Rebel
    // this syntax where the return value is a "read only pointer" to the data product 
727 1 Brian Rebel
    // art::OrphanHandle< std::vector<mp::MyOtherProd> > q = event.put(mopcol);
728 1 Brian Rebel
    // mf::LogInfo("NumMyProds") << "Number of products: " << q->size();
729 1 Brian Rebel
730 1 Brian Rebel
    return;
731 1 Brian Rebel
732 63 Jonathan Paley
  }
733 1 Brian Rebel
734 1 Brian Rebel
  // A macro required for a JobControl module.
735 7 Brian Rebel
  DEFINE_ART_MODULE(MyProducer);
736 30 Joseph Sobek
737 64 Brian Rebel
} // namespace mp
738 64 Brian Rebel
739 64 Brian Rebel
#endif //MYPRODUCER_H
740 64 Brian Rebel
741 7 Brian Rebel
</code></pre>
742 7 Brian Rebel
743 1 Brian Rebel
h3. EDAnalyzer
744 1 Brian Rebel
745 64 Brian Rebel
<pre><code class="c">
746 1 Brian Rebel
#ifndef MYANALYZERER_H
747 1 Brian Rebel
#define MYANALYZER_H
748 1 Brian Rebel
749 64 Brian Rebel
#include <iostream>
750 64 Brian Rebel
751 64 Brian Rebel
// Framework includes
752 1 Brian Rebel
#include "art/Framework/Core/EDAnalyzer.h"
753 64 Brian Rebel
#include "art/Framework/Core/Event.h"
754 64 Brian Rebel
#include "fhiclcpp/ParameterSet.h"
755 64 Brian Rebel
#include "art/Persistency/Common/Handle.h"
756 64 Brian Rebel
#include "art/Framework/Services/Registry/ServiceHandle.h"
757 64 Brian Rebel
#include "art/Framework/Services/Optional/TFileService.h"
758 64 Brian Rebel
#include "art/Framework/Core/TFileDirectory.h"
759 64 Brian Rebel
#include "messagefacility/MessageLogger/MessageLogger.h"
760 64 Brian Rebel
#include "art/Framework/Core/ModuleMacros.h"
761 1 Brian Rebel
762 64 Brian Rebel
763 64 Brian Rebel
#include "Geometry/Geometry.h"
764 64 Brian Rebel
#include "Utilities/LArProperties.h"
765 64 Brian Rebel
#include "MyProducts/MyProduct.h"
766 64 Brian Rebel
#include "MyProducts/MyOtherProduct.h"
767 64 Brian Rebel
768 64 Brian Rebel
#include "TH1.h"
769 7 Brian Rebel
  
770 1 Brian Rebel
771 1 Brian Rebel
// My Module
772 64 Brian Rebel
namespace mp {
773 1 Brian Rebel
  
774 1 Brian Rebel
  // class to produce a data product
775 1 Brian Rebel
  class MyAnalyzer : public art::EDAnalyzer {
776 1 Brian Rebel
    
777 1 Brian Rebel
  public:
778 1 Brian Rebel
    
779 1 Brian Rebel
    explicit MyAnalyzer(fhicl::ParameterSet const& pset);  // the explicit tag tells the compiler that MyProducer is different from fhicl::ParameterSet
780 7 Brian Rebel
    virtual ~MyAnalyzer();
781 1 Brian Rebel
    void analyze(const art::Event& evt);                   // makes the objects I want made
782 64 Brian Rebel
    void beginJob();                                       // does things like make histograms at the beginning of the job
783 64 Brian Rebel
    void beginRun(art::Run const& run);                    // Happens before each run, so this is a good place to pick up run dependent variables like Lifetime etc. 
784 64 Brian Rebel
    void reconfigure(fhicl::ParameterSet const&pset);      // every module should have one of these
785 1 Brian Rebel
    
786 1 Brian Rebel
  private:
787 1 Brian Rebel
        
788 1 Brian Rebel
    double      fDouble;          ///< some data member
789 64 Brian Rebel
    double      fRunProperty;     ///< a property that changes from run to run
790 1 Brian Rebel
    std::string fPrevModuleLabel; ///< label of the module making objects that i now want to look at
791 1 Brian Rebel
    TH1D*       fHist;            ///< a histogram data member
792 1 Brian Rebel
    
793 64 Brian Rebel
  }; // class MyAnalyzer
794 7 Brian Rebel
795 1 Brian Rebel
  //-----------------------------------------------------
796 64 Brian Rebel
  MyAnalyzer::MyAnalyzer(fhicl::ParameterSet const& pset)
797 1 Brian Rebel
  {
798 1 Brian Rebel
  }
799 1 Brian Rebel
800 1 Brian Rebel
  //-----------------------------------------------------
801 7 Brian Rebel
  MyAnalyzer::~MyAnalyzer()
802 1 Brian Rebel
  {
803 1 Brian Rebel
  }
804 1 Brian Rebel
805 1 Brian Rebel
  //-----------------------------------------------------
806 64 Brian Rebel
  void MyAnalyzer::reconfigure(fhicl::ParameterSet const& pset)
807 64 Brian Rebel
  {
808 64 Brian Rebel
   fDouble          = pset.get< double >     ("TheDouble");
809 64 Brian Rebel
   fPrevModuleLabel = pset.get< std::string >("PreviousModuleLabel");
810 64 Brian Rebel
811 64 Brian Rebel
   return;
812 64 Brian Rebel
  }
813 64 Brian Rebel
814 64 Brian Rebel
  //-----------------------------------------------------
815 1 Brian Rebel
  void MyAnalyzer::beginJob()
816 7 Brian Rebel
  {
817 1 Brian Rebel
    // get access to the TFile service
818 63 Jonathan Paley
    art::ServiceHandle<art::TFileService> tfs;
819 7 Brian Rebel
820 7 Brian Rebel
    // get the geometry to figure out something for the histogram
821 1 Brian Rebel
    art::ServiceHandle<geo::Geometry> geo;
822 7 Brian Rebel
823 64 Brian Rebel
    fHist    = tfs->make<TH1D>("channels",  ";channels;",  geo->NPlanes()*geo->Plane(0)->Nwires(), 0, geo->NPlanes()*geo->Plane(0)->Ncells());
824 1 Brian Rebel
825 1 Brian Rebel
    return;
826 1 Brian Rebel
  }
827 1 Brian Rebel
828 7 Brian Rebel
  //-----------------------------------------------------
829 64 Brian Rebel
  void MyAnalyzer::beginRun(art::Run const& run)
830 64 Brian Rebel
  {
831 64 Brian Rebel
   //get Access to the LArProperties service:
832 64 Brian Rebel
   art::ServiceHandle<util::LArProperties> larp;
833 64 Brian Rebel
   //get temperature from LArProperties - it will have been updated from the DB by now.
834 64 Brian Rebel
   fRunProperty = larp->Temperature();
835 64 Brian Rebel
  }
836 64 Brian Rebel
837 64 Brian Rebel
  //-----------------------------------------------------
838 63 Jonathan Paley
  void MyAnalyzer::analyze(const art::Event& evt)
839 1 Brian Rebel
  {
840 7 Brian Rebel
    
841 1 Brian Rebel
    // maybe I will need the geometry service here too
842 1 Brian Rebel
    art::ServiceHandle<geo::Geometry> geom;
843 1 Brian Rebel
  
844 7 Brian Rebel
    double xyz[3] = {0.};
845 1 Brian Rebel
    double xyz1[3] = {0.};
846 10 Brian Rebel
    int planes = geom->NPlanes();
847 1 Brian Rebel
  
848 10 Brian Rebel
    ///plane 0 is the first induction plane, every plane has a wire 0
849 1 Brian Rebel
    geom->Plane(0)->GetCenter(xyz);
850 1 Brian Rebel
851 1 Brian Rebel
    // grab the mp::MyProducts made in a previous module
852 1 Brian Rebel
    art::Handle< std::vector<mp::MyProduct> > mplistHandle;
853 1 Brian Rebel
    evt.getByLabel(fPrevModuleLabel,mplistHandle);
854 1 Brian Rebel
855 1 Brian Rebel
    // loop over the list of MyProducts
856 1 Brian Rebel
    for(unsigned int i = 0; i < mplistHandle->size(); ++i){
857 1 Brian Rebel
858 1 Brian Rebel
      //get a edm::Ptr to the MyProducts
859 1 Brian Rebel
      art::Ptr<mp::MyProduct> mpMyProd(mplistHandle, i);
860 1 Brian Rebel
861 1 Brian Rebel
      // do something to analyze them
862 63 Jonathan Paley
863 1 Brian Rebel
    }
864 1 Brian Rebel
865 1 Brian Rebel
    return;
866 1 Brian Rebel
867 10 Brian Rebel
  }
868 7 Brian Rebel
869 1 Brian Rebel
  // A macro required for a JobControl module.
870 1 Brian Rebel
  DEFINE_ART_MODULE(MyAnalyzer);
871 1 Brian Rebel
872 64 Brian Rebel
} // namespace mp
873 64 Brian Rebel
874 64 Brian Rebel
#endif // MYANALYZER_H
875 64 Brian Rebel
876 1 Brian Rebel
</code></pre>
877 1 Brian Rebel
878 1 Brian Rebel
h3. EDFilter
879 1 Brian Rebel
880 1 Brian Rebel
A simple example of filtering on even or odd event numbers is below.
881 1 Brian Rebel
882 1 Brian Rebel
First the header file:
883 64 Brian Rebel
<pre><code class="c">
884 1 Brian Rebel
// Framework includes
885 1 Brian Rebel
#include "art/Framework/Core/EDFilter.h"
886 64 Brian Rebel
#include "art/Framework/Core/ModuleMacros.h"
887 64 Brian Rebel
#include "art/Framework/Principal/Event.h" 
888 1 Brian Rebel
889 64 Brian Rebel
890 1 Brian Rebel
namespace filt{
891 1 Brian Rebel
892 1 Brian Rebel
 class SelectEvents : public art::EDFilter {
893 1 Brian Rebel
   public:
894 1 Brian Rebel
     explicit SelectEvents(fhicl::ParameterSet const& pset);
895 1 Brian Rebel
    virtual ~SelectEvents() { }
896 1 Brian Rebel
    virtual bool filter(art::Event& e);
897 64 Brian Rebel
    void    reconfigure(fhicl::ParameterSet const& pset);
898 1 Brian Rebel
    
899 1 Brian Rebel
  private:
900 1 Brian Rebel
901 7 Brian Rebel
    // Control parameter: 1 to select odd numbered events; 
902 1 Brian Rebel
    //                    else select even numbered event.
903 64 Brian Rebel
    int fkeepOddOrEven;
904 7 Brian Rebel
905 7 Brian Rebel
  };
906 1 Brian Rebel
907 7 Brian Rebel
908 64 Brian Rebel
   SelectEvents::SelectEvents(fhicl::ParameterSet const& pset)
909 64 Brian Rebel
  {
910 64 Brian Rebel
  }
911 1 Brian Rebel
912 64 Brian Rebel
  void SelectEvents::reconfigure(fhicl::ParameterSet const& pset)
913 7 Brian Rebel
  {
914 64 Brian Rebel
    fkeepOddOrEven = pset.get<int>("keepOddOrEven");
915 1 Brian Rebel
  }
916 1 Brian Rebel
917 64 Brian Rebel
918 1 Brian Rebel
  bool SelectEvents::filter(art::Event& e)
919 1 Brian Rebel
  {
920 1 Brian Rebel
921 1 Brian Rebel
    // EventSetup is a cms leftover that we do not use.
922 1 Brian Rebel
    
923 1 Brian Rebel
    // Get event number from the event.
924 1 Brian Rebel
    int event = e.id().event();
925 1 Brian Rebel
    
926 1 Brian Rebel
    // Always keep event 3.
927 1 Brian Rebel
    if ( event == 3 ) return true;
928 1 Brian Rebel
929 1 Brian Rebel
    // Always discard event 4.
930 1 Brian Rebel
    if ( event == 4 ) return false;
931 1 Brian Rebel
932 1 Brian Rebel
    // Is this an odd numbered event?
933 1 Brian Rebel
    bool isOdd = ((event % 2) != 0);
934 1 Brian Rebel
  
935 1 Brian Rebel
    // Keep only events with odd or even event numbers, as 
936 1 Brian Rebel
    // controled by the parameter from the ParameterSet.
937 64 Brian Rebel
    if ( fkeepOddOrEven == 1){
938 1 Brian Rebel
      return isOdd;
939 1 Brian Rebel
    } else{
940 1 Brian Rebel
      return !isOdd;
941 1 Brian Rebel
    }
942 1 Brian Rebel
  
943 1 Brian Rebel
  }
944 1 Brian Rebel
945 1 Brian Rebel
  // A macro required for a JobControl module.
946 1 Brian Rebel
  DEFINE_ART_MODULE(SelectEvents);
947 1 Brian Rebel
948 1 Brian Rebel
} // namespace filt
949 1 Brian Rebel
</code></pre>
950 64 Brian Rebel
951 64 Brian Rebel
h2. Checking the Configuration of a ROOT file
952 64 Brian Rebel
953 64 Brian Rebel
To dump the information regarding all the ParameterSets stored in a given art data file, then the program config_dumper is useful.
954 64 Brian Rebel
@% config_dumper file_name.root@
955 1 Brian Rebel
956 1 Brian Rebel
h2. Configuring a Job
957 1 Brian Rebel
958 1 Brian Rebel
See the [[Running Jobs]] page.
959 68 Justin Vasel
960 68 Justin Vasel
h2. ART exit codes
961 68 Justin Vasel
962 68 Justin Vasel
More information on the exit status codes for art can be found in the "ART workbook":http://art.fnal.gov/art-workbook-versions/ circa page C-433 (at the time of this writing).
963 68 Justin Vasel
964 68 Justin Vasel
The exit status codes are:
965 68 Justin Vasel
966 68 Justin Vasel
* 0  -- ART completed successfully
967 68 Justin Vasel
* 65 -- A cet::exception was caught and processed in main
968 68 Justin Vasel
* 66 -- An std::exception was caught and processed in main
969 68 Justin Vasel
* 67 -- An unknown exception was caught and processed in main
970 68 Justin Vasel
* 68 -- An std::bad_alloc was caught in main
971 68 Justin Vasel
* 88 -- Exception from command line processing
972 68 Justin Vasel
* 89 -- Check command line options failed
973 68 Justin Vasel
* 90 -- Process command line options failed
974 68 Justin Vasel
* 91 -- Failed to create a parameter set from parsed configuration with exception