Project

General

Profile

Exercise 1

Prerequisites (suggested by Anne)

  • FHiCL (fickle) is a configuration language (used like python in CMS). Files end in .fcl (There's a ref somewhere)
  • introduce the 'art' command
  • 'art' doesn't produce log files automatically, you need to ask for them
  • Run exercises in your build window
  • what is RootInput file reader
  • constructor:
  • analyze method: may view information the event but it may not add information to or otherwise modify the event (or is that just because of const?)
  • accessor

To run exercise 1, checkout and build the art-workbook code. Then cd to your build directory:

art -c Ex01/ex01.fcl

Or, if you prefer, you can send the printed output to a file:
art -c Ex01/ex01.fcl >& output/ex01.log

This should produce output that looks like /ds50/data/user/kutschke/workbook-blessed-outputs/ex01.log . In particular, the last line of the file should be:
Art has completed and will exit with status 0.

If this line is absent, or if the status code is non-zero, contact the art team. (Anne: should give an email)

What did the art command do? It ran a main program named art, which is found in $ART_FQ_DIR/bin; this directory was added to your path when you sourced the setup_for_development script. The art main program looked for a file with the name Ex01/ex01.fcl, relative to the path defined by the environment variable FHICL_FILE_PATH. art found the file in the code checked out in your source window. From your build window, you can see this file as:

../art-workbook/artwb/Ex01/ex01.fcl

(Anne: why not say this up front?) The file ex01.fcl is written in a language named FHiCL , pronounced "fickle", which is an acronym for Fermilab Heirarhical Configuration Language. This file tells art what to do on this particular run. Once you have sent in your box tops and received the decoder ring, you will see that it says:

(Anne: might be nice to show the contents and match it with the explanations)

  1. Open the file named "inputFiles/input01_data.root" ( relative to the current working directory ).
  2. Expect the file to be in the format required by file reader named RootInput.
  3. Find a shared library named "*Ex01_module.so", somewhere in the path defined by LD_LIBRARY_PATH; here "*" is a normal text wildcard. If there are zero matches, or more than one match stop.
  4. Read three events from the input file and let the module do whatever it does to them.
  5. Oh yeah, and before you start, put the message logger in the recommended configuration.

ex01.fcl is a fairly verbose way of saying the above; but as you encounter more complex art jobs, the reasons for the structure of the language will become clear.

Now look at the source code for the module that you just ran. In your source window it is ../artwb/Ex01/Ex01_module.cc . This file

  • Declares a class named Ex01, in the namespace artwb.
    • This class has a constructor and one method, named analyze.
  • Provides the implementation for the constructor and the analyze method.
  • Invokes a cpp macro: DEFINE_ART_MODULE(artwb::Ex01)

The constructor and the analyze method just print out some information:

artwb::Ex01::Ex01(fhicl::ParameterSet const& ){
  std::cout << "Hello from Ex01::constructor." << std::endl;
}

void artwb::Ex01::analyze(art::Event const& event){
  std::cout << "Hello from Ex01::analyze. Event id: " 
            << event.id()
            << std::endl;
}

The constructor is called by art, once at the start of the job. The analyze method is called by art for every event; the analyze method has access to all of the information in the event because the event is passed to it as an argument. The event is passed by reference, to avoid wasteful copies. The event is passed by const reference, which means that the analyze method may view information the event but it may not add information to or otherwise modify the event. A later exercise will show how to add information to an event. If you are not familiar with the meaning of passing an argument by const reference you should consult a C++ reference; this is an important idea that is used frequently.

Now look at the log file made by art and find the four lines that start with "Hello":

Hello from Ex01::constructor.
Hello from Ex01::analyze. Event id: run: 1 subRun: 0 event: 1
Hello from Ex01::analyze. Event id: run: 1 subRun: 0 event: 2
Hello from Ex01::analyze. Event id: run: 1 subRun: 0 event: 3

The rest of the printout is made by art.

In art, events are identified by a three part identifier. The parts are named "Run", "SubRun" and "event"; each part has an integral value; run numbers and event numbers start at 1 while SubRun numbers start at 0. The intention is that this three part identifier allows a lot of flexibility in the tedious bookkeeping that accompanies any experiment. art, itself, does not define the meaning of a run or a sub run; that is left to the experiment. art allows both runs and subruns to be spread across more than one data file and it allows a single data file to contain many runs and subruns.

Activities for Exercise 1

Activity 1

Make a local copy of this file:

cp ../art-workbook/artwb/Ex01/ex01.fcl my01.fcl

Edit my01.fcl and, in the source block, change maxEvents to 5. Run art using your modified .fcl file:
art -c my01.fcl

This works because the leading element of FHICL_FILE_PATH is the current working directory. Notice the change in the printout.

Next change the value of maxEvents to -1. This tells art to run to the end of file, which will be 10 events. Notice the change in the printout.

Next change the name of the input file to inputFiles/input02_data.root. Remember that the filename needs to be quoted. Rerun art. This file also contains 10 events, but from run 2, not run 1. Notice the change in the printout.

Activity 2

 art --help

This shows you that you could have done the Activity 1 using the command line arguments, -n and -s. Try these out.

Experiment with reading multiple input files. You can do this inside the .fcl file like:

 source : {
  module_type : RootInput
  fileNames   : [ "inputFiles/input01_data.root", "inputFiles/input02_data.root", "inputFiles/input03_data.root"  ]
  maxEvents   : -1
}

Or you can do it from the command line with the -S option; remember the -n -1 on the command line if maxEvents inside the source block is small.

If a parameter is specified both in the .fcl file and on the command line, the command line wins.

Activity 3

Go to your source window and

  • cd artwb/Ex01
  • cp Ex01_module.cc Ex01a_module.cc
  • cp ex01.fcl ex01a.fcl
  • Edit Ex01a_module. cc.
    • Everywhere that there is an Ex01, change it to Ex01a. * Edit the two printout lines so that they contain an additional "Ex01a".
  • Edit ex01a.fcl * In the analyzers.hello block, change the value of module_type to Ex01a.

Go to your build window and

  • buildtool
  • art -c Ex01/ex01a.fcl

You should see the change that you added to the printout.

Activity 4

In Ex01_module.cc there is a fragment that prints the event ID.

void artwb::Ex01::analyze(art::Event const& event){
  std::cout << "Hello from Ex01::analyze. Event id: " 
            << event.id()
            << std::endl;
}

In this fragment, the code calls a method named id() on an object of type art::Event. To see what this does, look at the header file that defines art::Event, $ART_INC/art/Framework/Principal/Event.h. In this file you will find the definition of the method id():
class art::Event : private art::DataViewImpl {
public:

  // Lines deleted

  EventID
  id() const {return aux_.id();}

  // Lines deleted.

}

that is, it returns an object whose type is EventID. In C++, outside of quoted strings, all forms of whitespace are equivalent; whitespace includes spaces, tabs and newline characters.
So the previous line could have been written:
  EventID id() const {return aux_.id();}

Splitting it this line of code over two lines in the file is a style choice that you will encounter when you look at other people's code.

Next look at the headers included in Event.h to see that the definition of EventID is found in the file $ART_INC/art/Persistency/Provenance/EventID.h. In this file you can see that there are methods of the EventID class to return the run, subrun and event numbers separately,

class art::EventID {
public:

   // ...

   RunNumber_t run() const { return subRun_.run(); }
   SubRunNumber_t subRun() const { return subRun_.subRun(); }
   EventNumber_t event() const { return event_; }

   // ...

}

If you keep digging into the code you will discover that EventNumber_t, SubRunNumber_t and RunNumber_t are all just typedefs to an unsigned 32 bit integer. Another common convention that you will encounter is that the names of user defined types often end in _t or _type.

Using this information, rewrite Ex01a so that it prints out:

Hello from Ex01Activity01::analyze.  run number: 1 sub run number: 0 event number: 1

instead of
Hello from Ex01::analyze. Event id: run: 1 subRun: 0 event: 1

If after 5 minutes you are still stuck on this, the answer is in Ex01/Ex01Activity01_module.cc. It was built when you built the workbook and you can run it with:

 art -c Ex01/Activity01.fcl

Why is this in a file named Activity01 when the heading says Activity 4? It's still a prototype; wait until you see Exercise 2.