3.5.2 Event Loop in FWLite

Complete: 5

Contents


Detailed Review status

The goals of this page:

In this page you will learn how to

  • write ROOT macros that analyze CMS data directly
  • compile these ROOT macros to make them faster and safer

Those users who like command line options, can have a look at SWGuideCommandLineParsing for command line parsing instructions.

The structure of a FWLite macro

Let us illustrate the access to EDM collections in FWLite with an example. But before we begin, the following lines need to be executed from within ROOT

{
   gSystem->Load("libFWCoreFWLite.so"); 
   FWLiteEnabler::enable();
   gSystem->Load("libDataFormatsFWLite.so");
   gSystem->Load("libDataFormatsPatCandidates.so");
}

as discussed in the previous section, it is best to place these lines inside the rootlogon.C file, so that they are executed automatically and you don't need to worry about them.

Here's a sketch of a macro that loops over events, and in each event retrieves an ED object:

void print_data()
{
   #include "DataFormats/FWLite/interface/Handle.h"
   TFile file("MYCOPY.root");

   fwlite::Event ev(&file);

   for( ev.toBegin(); ! ev.atEnd(); ++ev) {
       fwlite::Handle<std::vector<...> > objs;
       objs.getByLabel(ev,"....");
       // now can access data
       std::cout <<" size "<<objs.ptr()->size()<<std::endl;
       ...
   }
}

ALERT! Note: When building a macro, there is a particular order of calls to ROOT methods which are required in order for ROOT to function properly:

  1. Start the autoloader
  2. Create the TFile
  3. Load in the helper library gSystem->Load("libDataFormatsFWLite")
  4. Include "DataFormats/FWLite/interface/Handle.h" to get the fwlite::Handle
  5. Create an fwlite::Event by passing to the constructor a pointer to the TFile. The fwlite::Event allows you to use the same information you use when accessing data in cmsRun using the edm::Event.
  6. Create a for loop over events
    1. Start loop by calling toBegin() on the fwlite::Event
    2. For each iteration of the loop call atEnd on the fwlite::Event
    3. At the end of each iteration, increment the fwlite::Event by using the operator++ method
  7. When looping over the events
    1. Create an fwlite::Handle< ... > where the template argument is the C++ class you want to get from the event
    2. Call the getByLabel method of the fwlite::Handle passing the event and the strings or edm::InputTag used to specify the object
    3. The object retrieved from the handle is either a single number, or a collection of CMS objects (e.g. Tracks). In the latter case, you can loop the vector of objects using the standard iterator notation (same as in the FullFramework).

If you save the above macro in a file called print_data.C, you can load it and execute it from the interactive ROOT session with

root[] .L print_data.C
print_data()

or simply

.x print_data.C

However, note that in the above case the macro print_data.C is interpreted by CINT. This is okay for rapid prototyping, however, for real data processing one should always compile it with ACliC for several reasons:

  • The macro will be significantly faster, as ACliC invokes the native compiler (so on Linux it's the same version of GCC used to build ROOT)
  • CINT is good, but ii is not 100% reliable in its computations, and it is better not to risk running into one of the rare cases which are not correctly handled by CINT
  • Compiled code can be debugged, profiled, or processed with valgrind (especially when linked into a standalone executable)

Compling the macro with ACliC

Compiling the macro on the fly (while it's being loaded) is trivial. One simply adds a "+" at the end of the macro name:

   TFile f("....root");
   .x print_data.C+

ROOT then first invokes GCC from the release, makes a shared library, and loads it. Note that "++" would always cause compilation, while "+" would recompile an already existing macro only if the source code is newer than the compiled code, just like make.

ALERT! Note: There are several pieces of information you need to know about how ROOT compiles a macro:

  1. ROOT runs the CINT interpreter over the macro before compiling it in order to determine if it needs to generate dictionaries for some of the classes/functions mentioned in the macro. Unfortunately many of CMS's header files contain code that CINT can not parse. This means we must hide those headers from CINT but make sure they are visible to the compiler.
  2. After compiling the code, ROOT links the compiled macro against all libraries which have been loaded. If the macro uses a function or variable from a library which has not yet been loaded, then ROOT will issue a 'missing symbol' error.

With the above in mind, here are the steps needed to arrive at a compiled ROOT macro:

  1. Protect all headers using a
    #if !defined(__CINT__) && !defined(__MAKECINT__) #endif
    block
  2. Introduce the macro block as a function with the same name as the file (this keeps CINT from trying to fully parse the internals of the routine)
  3. In ROOT
    1. Load and start the autoloader
    2. Load libDataFormatsFWLite
    3. Create a TFile from one of the files you want to read. This will cause all the libraries for every class in the file to be loaded.
    4. Compile/link/execute the macro by doing .x <filename>++

An example macro template is shown below. The example assumes that the file is named print_data.C

#if !defined(__CINT__) && !defined(__MAKECINT__)
#include "DataFormats/FWLite/interface/Handle.h"
#include "DataFormats/FWLite/interface/Event.h"
//Headers for the data items
...
#endif
void print_data() {
  TFile file("....root");

   fwlite::Event ev(&file);

   for( ev.toBegin(); ! ev.atEnd(); ++ev) {
       fwlite::Handle<std::vector<...> > objs;
       objs.getByLabel(ev,"....");
       //now can access data
       std::cout <<" size "<<objs.ptr()->size()<<std::endl;
       ...
   }
}

ALERT! Note: A note on the preprocessor switches (testing on CINT and MAKECINT): The first step that ROOT takes when compiling a macro is to run the CINT interpreter over the macro in order to determine what class or function 'dictionaries' it must create. After that step, the regular C++ compiler is used to build the code. Unfortunately, CINT is incapable of properly parsing many of our header files. However, it turns out the headers are not needed by CINT but only by the compiler, therefore adding

#if !defined(__CINT__) && !defined(__MAKECINT__)
...
#endif

around the header files avoids the problem with CINT.

However, the compiler still needs to know where to find our header files. FWLite pre-configures ROOT to find CMS headers from the environment variables CMSSW_BASE and CMSSW_RELEASE_BASE. FWLite pre-configures ROOT to find standard externals header files (e.g. boost and CLHEP).

Running over a list of files

The fwlite::ChainEvent allows you to use the same information you use when accessing data in cmsRun using edm::Event:

  1. Start the autoloader
  2. Load in the helper library gSystem->Load("libDataFormatsFWLite")
  3. Create a std::vector<std::string> to hold the list of file names
  4. Include "DataFormats/FWLite/interface/Handle.h" to get the fwlite::Handle
  5. push_back each file name into the std::vector<std::string>
  6. Create an fwlite::ChainEvent by passing to the constructor the vector
  7. Create a for loop
    1. Start loop by calling toBegin() on the fwlite::ChainEvent
    2. For each iteration of the loop call atEnd on the fwlite::ChainEvent
    3. At the end of each iteration, increment the fwlite::Event by using the operator++ method
  8. When looping over the events
    1. Create an fwlite::Handle< ... > where the template argument is the C++ class you want to get from the event
    2. Call the getByLabel method of the fwlite::Handle passing it the event and the strings used to denote the object

An example macro template is shown below:

{
   gSystem->Load("libFWCoreFWLite.so"); 
   AutoLibraryLoader::enable();
   gSystem->Load("libDataFormatsFWLite.so");

   #include "DataFormats/FWLite/interface/Handle.h"
   vector<string> fileNames;
   fileNames.push_back("....root");

   fwlite::ChainEvent ev(fileNames);

   for( ev.toBegin(); ! ev.atEnd(); ++ev) {
       fwlite::Handle<std::vector<...> > objs;
       objs.getByLabel(ev,"....");
       //now can access data
       std::cout <<" size "<<objs.ptr()->size()<<std::endl;
       ...
   }
}

The compilation is identical to what is done for the case of a single file above, except in the macro you replace the use of fwlite::Event with fwlite::ChainEvent. ALERT! Note: You must still pick one of the files to be used in the fwlite::ChainEvent and open it with a TFile on the ROOT command line in order to force the proper dictionaries to be opened.

3.5.2.4 Using edm::EventBase

It is now possible to use the edm::EventBase such that the user does not need to use the fwlite::Handle any more. This allows the user to write functions that can be used directly in FWLite or in the full framework and use the same "get" methods. Note that this does not function if one uses CINT to interprete the macros. A snippet of how to do this is given below:

for (ev.toBegin(); ! ev.atEnd(); ++ev) {
    edm::EventBase const & event = ev;

    // This snippet can be used in EITHER FWLite or the Full Framework
    edm::Handle<vector<reco::Vertex> > vertices;
    event.getByLabel( edm::InputTag("offlinePrimaryVertices"), vertices);

    // ...

  }

In the meantime FWLite and full framework can indeed be used in parallel on tha bases of truely compiled executables! If you want to know more about this have a look for a bunch of examples of compiled executables with FWLite on WorkBookFWLiteExamples.

Review status

Reviewer/Editor and Date (copy from screen) Comments
RogerWolf - 22 Mar 2011 Update for CMSSW_4_1_3

Responsible: RogerWolf

Topic attachments
I Attachment History Action Size Date Who Comment
Cascading Style Sheet filecss tutorial.css r1 manage 0.2 K 2011-03-22 - 16:44 RogerWolf  
Edit | Attach | Watch | Print version | History: r15 < r14 < r13 < r12 < r11 | Backlinks | Raw View | WYSIWYG | More topic actions
Topic revision: r15 - 2018-12-16 - ElizaMelo


ESSENTIALS

ADVANCED TOPICS


 
    • Cern Search Icon Cern Search
    • TWiki Search Icon TWiki Search
    • Google Search Icon Google Search

    CMSPublic All webs login

This site is powered by the TWiki collaboration platform Powered by PerlCopyright & 2008-2019 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback