Services

In my notes on Writing Your Own Athena Algorithms, the example code shows the use of the Message Service to print to the terminal and the THistSvc to make a TTree saved in a ROOT file. In the next sections, I explain how to use of these services in more detail.

The Message Service

You can use the Message Service to print text in the terminal. In the C++ code for your algorithm, you must #include "GaudiKernel/MsgStream.h". Then define an instance of the MsgStream by
MsgStream mLog( msgSvc(), name() );
Now you can use it to print to the terminal by
mLog << MSG::INFO << "Hello World!" << endreq;
where INFO specifies the Output Level of the message. It can be one of the following 2=DEBUG, 3=INFO, 4=WARNING, 5=ERROR, or 6=FATAL. If the message's Output Level is not above the Output Level specified in the job options, then the message will be suppressed.

Now in your job options, you must have the line

from AthenaCommon.AppMgr import ServiceMgr
To specify the global Output Level in job options, do
ServiceMgr.MessageSvc.OutputLevel = WARNING
This will suppress output of all message with output level INFO or lower. (Note the difference in syntax between msgSvc() in the C++ code and MessageSvc in the Python job options.) One can specify that a specific algorithm have an Output Level differing from the global Output Level by setting the OutputLevel member variable of that algorithm.
someAlg.OutputLevel = INFO
Alternatively, one can set the Output Level when declaring an instance of the algorithm, as is done in the job options in my notes on Writing Your Own Athena Algorithms.
theJob += MyAlg(OutputLevel = INFO)

If the names of your algorithms get long and descriptive, or if you have several algorithms with nested tools, then the default settings for the Message Service may not leave enough space for the source of the message to be printed. In order to lengthen the space for the source of the message to be printed add the following line to your job options.

ServiceMgr.MessageSvc.Format = "% F%50W%S%7W%R%T %0W%M"
where 50 is the print length for the name of the tool/algorithm. This is an increase from the default of 30.

Back to top

The StoreGate Service

StoreGate is a service that handles data storage for Athena algorithms. You can think of StoreGate as a "blackboard" on which algorithms take turns reading and writing. The data in an AOD file is stored in different collections. For example, the ElectronAODCollection holds the electron candidates. Event by event, the collections are written to StoreGate so that algorithms can get the data.

To be able to access StoreGate in the C++ code of an algorithm, you should add a pointer to StoreGate in the algorithms class (in the header file).

#include "StoreGate/StoreGateSvc.h"
...
class MyAlg : public Algorithm
{
    ...
    private:
        StoreGateSvc* m_storeGate;
    ...
}
In the initialize() function in MyAlg.cxx, you should assign the StoreGate pointer.
#include "StoreGate/StoreGateSvc.h"
...
StatusCode MyAlg::initialize()
{
    MsgStream mLog( messageService(), name() );
    mLog << MSG::DEBUG << "Initializing MyAlg" << endreq;

    // Get handle StoreGate
    StatusCode sc = service("StoreGateSvc", m_storeGate);
    if(sc.isFailure())
    {
        mLog << MSG::ERROR
             << "Unable to retrieve pointer to StoreGate service."
             << endreq;
        return sc;
    }
    ....
}

Now in the execute method, you can retrieve data from StoreGate with the retrieve function.

StatusCode MyAlg::execute()
{
    MsgStream mLog( messageService(), name() );
    const ElectronContainer*  eCont = 0;
    StatusCode sc=m_storeGate->retrieve(eCont, "ElectronAODCollection");

    if( sc.isFailure()  ||  !eCont )
    {
        mLog << MSG::ERROR
             << "No ElectronAODCollection found."
             << endreq;
        return sc;
    }
    ...
}
The first argument of retrieve is a pointer that will point to the retrieved data. The second argument is a string that is the Store Gate Key for that container.

The easiest way to find out what the Store Gate Keys are for the data in an AOD, is to do a Store Gate Dump. The following job option will print the contents of the AOD to the terminal with the keys.

# Event selector
include( "AthenaPoolCnvSvc/ReadAthenaPool_jobOptions.py" )
EventSelector = Service( "EventSelector" )
#EventSelector.BackNavigation = True

# Particle Properties
#include( "PartPropSvc/PartPropSvc.py" )

# the POOL converters
#include( "ParticleBuilderOptions/ESD_PoolCnv_jobOptions.py" )
include( "ParticleBuilderOptions/AOD_PoolCnv_jobOptions.py")
include( "ParticleBuilderOptions/McAOD_PoolCnv_jobOptions.py")
include( "EventAthenaPool/EventAthenaPool_joboptions.py" )

include("PyAnalysisCore/InitPyAnalysisCore.py")

# The AOD input file
EventSelector.InputCollections = ["AOD"]

theApp.initialize()
theApp.nextEvent()
dumpSG()
theApp.finalize()
theApp.exit()

Back to top

The THistSvc Service

The THistSvc allows you to create ROOT TTree's and save them to ROOT files in your athena algorithms. The first thing to do is to add pointers to the THistSvc and to your TTree in the class for your algorithm. In MyAlg.h include the THistSvc andTTree headers.

#include "GaudiKernel/ITHistSvc.h"
#include "TTree.h"
And add the pointers as private member variables. Also add variables that you want to put in the tree.
class MyAlg : public Algorithm
{
    ...
    private:
        ITHistSvc * m_histSvc;
        TTree* m_tree;
        float m_someVariable;
}

Then, in the initialize() function in MyAlg.cxx, get the ThistSvc, create a TTree, register it to the THistSvc, and add branches to the TTree.

StatusCode MyAlg::initialize()
{
    ...
    // Get a handle on the NTuple and histogramming service
    sc = service("THistSvc", m_histSvc);
    if(sc.isFailure())
    {
        mLog << MSG::ERROR
             << "Unable to retrieve pointer to THistSvc"
             << endreq;
        return sc;
    }

    // Create TTree and register it to THistSvc
    m_tree = new TTree("MyTree" , "MyTree");
    std::string fullTreeName =  "/AANT/MyTree" ;
    sc = m_histSvc->regTree(fullTreeName, m_tree);
    if(sc.isFailure())
    {
        mLog << MSG::ERROR << "Unable to register TTree : " << fullTreeName << endreq;
        return sc;
    }

    // Create TTree branches.
    m_tree->Branch("someVariable", &m_someVariable, "someVariable/F");
    ...
}

Where AANT is the output file stream specified in your job options. This will be explained below.

Now you need to calculate your variables for each event in the execute() function and then call Fill() for the TTree.

StatusCode MyAlg::execute()
{
    ...
    m_someVariable = something;
    m_tree->Fill();
    ...
}

Now you can compile your code. Lastly, you need to setup your job options to use the THistSvc by adding the following lines

THistSvc = Service ( "THistSvc" )
THistSvc.Output = ["AANT DATAFILE='filename.root' OPT='RECREATE'"]
THistSvc.OutputLevel = INFO
where filename.root specifies the name of the ROOT file to which the TTree will be saved.

Back to top


-- RyanReece - 11 Jan 2008
Edit | Attach | Watch | Print version | History: r5 < r4 < r3 < r2 < r1 | Backlinks | Raw View | WYSIWYG | More topic actions
Topic revision: r5 - 2008-03-10 - RyanReece
 
    • Cern Search Icon Cern Search
    • TWiki Search Icon TWiki Search
    • Google Search Icon Google Search

    Sandbox All webs login

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