As a first step for writing your analysis code you need to create an algorithm class. An algorithm is the basic unit of code EventLoop or Athena knows about. At least as a beginner you will typically just have a single algorithm in your job that will hold your analysis code. (As an advanced user you may want to create multiple algorithms, and maybe also tools and services.)
We will create an empty algorithm now and call it MyxAODAnalysis
.
You can really name it anything you want, but if you give it a
different name you will have to update any paths and code referring to
it in the rest of the tutorial accordingly (so for the first time it
is probably best to stick with this name).
Going into your source/
directory, create the file
MyAnalysis/MyAnalysis/MyxAODAnalysis.h
with this content:
#ifndef MyAnalysis_MyxAODAnalysis_H
#define MyAnalysis_MyxAODAnalysis_H
#include <AnaAlgorithm/AnaAlgorithm.h>
class MyxAODAnalysis : public EL::AnaAlgorithm
{
public:
// this is a standard algorithm constructor
MyxAODAnalysis (const std::string& name, ISvcLocator* pSvcLocator);
// these are the functions inherited from Algorithm
virtual StatusCode initialize () override;
virtual StatusCode execute () override;
virtual StatusCode finalize () override;
private:
// Configuration, and any other types of variables go here.
//float m_cutValue;
//TTree *m_myTree;
//TH1 *m_myHist;
};
#endif
Create the file MyAnalysis/Root/MyxAODAnalysis.cxx
with this content:
#include <AsgMessaging/MessageCheck.h>
#include <MyAnalysis/MyxAODAnalysis.h>
MyxAODAnalysis :: MyxAODAnalysis (const std::string& name,
ISvcLocator *pSvcLocator)
: EL::AnaAlgorithm (name, pSvcLocator)
{
// Here you put any code for the base initialization of variables,
// e.g. initialize all pointers to 0. This is also where you
// declare all properties for your algorithm. Note that things like
// resetting statistics variables or booking histograms should
// rather go into the initialize() function.
}
StatusCode MyxAODAnalysis :: initialize ()
{
// Here you do everything that needs to be done at the very
// beginning on each worker node, e.g. create histograms and output
// trees. This method gets called before any input files are
// connected.
return StatusCode::SUCCESS;
}
StatusCode MyxAODAnalysis :: execute ()
{
// Here you do everything that needs to be done on every single
// events, e.g. read input variables, apply cuts, and fill
// histograms and trees. This is where most of your actual analysis
// code will go.
return StatusCode::SUCCESS;
}
StatusCode MyxAODAnalysis :: finalize ()
{
// This method is the mirror image of initialize(), meaning it gets
// called after the last event has been processed on the worker node
// and allows you to finish up any objects you created in
// initialize() before they are written to disk. This is actually
// fairly rare, since this happens separately for each worker node.
// Most of the time you want to do your post-processing on the
// submission node after all your histogram outputs have been
// merged.
return StatusCode::SUCCESS;
}
This section describes the setup required specifically for working with AnalysisBase or AthAnalysis. The tutorial can be run using either but when running with AnalysisBase (working with EventLoop) you need to set up a dictionary for the algorithm, whereas when working with AthAnalysis (Athena) you are required to set up a factory for the algorithm.
Both methods are described below but please take care to implement the relevant section depending on which release you setup.
This is strictly speaking only needed when working in EventLoop (AnalysisBase). You can create it when working with Athena (AthAnalysis), if you want, but it will give you compilation overhead, so you can skip this if you want.
Create the file MyAnalysis/MyAnalysis/MyAnalysisDict.h
with this
content:
#ifndef MYANALYSIS_MYANALYSIS_DICT_H
#define MYANALYSIS_MYANALYSIS_DICT_H
// This file includes all the header files that you need to create
// dictionaries for.
#include <MyAnalysis/MyxAODAnalysis.h>
#endif
Create the file MyAnalysis/MyAnalysis/selection.xml
with this
content:
<lcgdict>
<!-- This file contains a list of all classes for which a dictionary
should be created. -->
<class name="MyxAODAnalysis" />
</lcgdict>
This is only needed when working with Athena (AthAnalysis), inside EventLoop (AnalysisBase) this will not be used. As such if you know that you will never work in Athena you can leave this out (or add it later).
Create the file MyAnalysis/src/components/MyAnalysis_entries.cxx
with this content:
#include <MyAnalysis/MyxAODAnalysis.h>
DECLARE_COMPONENT (MyxAODAnalysis)
CMakeLists.txt
fileNow you need to add the compilation of these files to your
MyAnalysis/CMakeLists.txt
file. Note that you only have to do this
once per package, and not for subsequent algorithms in the same
package. The first two lines should already be there, the remainder
of lines ought to be new:
# The name of the package:
atlas_subdir (MyAnalysis)
# Add the shared library:
atlas_add_library (MyAnalysisLib
MyAnalysis/*.h Root/*.cxx
PUBLIC_HEADERS MyAnalysis
LINK_LIBRARIES AnaAlgorithmLib)
if (XAOD_STANDALONE)
# Add the dictionary (for AnalysisBase only):
atlas_add_dictionary (MyAnalysisDict
MyAnalysis/MyAnalysisDict.h
MyAnalysis/selection.xml
LINK_LIBRARIES MyAnalysisLib)
endif ()
if (NOT XAOD_STANDALONE)
# Add a component library for AthAnalysis only:
atlas_add_component (MyAnalysis
src/components/*.cxx
LINK_LIBRARIES MyAnalysisLib)
endif ()
Note that the if (XAOD_STANDALONE)
and if (NOT XAOD_STANDALONE)
blocks are
ways for you to control what is actually built
Now we should be able to build our package with our empty algorithm:
cd ../build/
cmake ../source/
make
Don’t forget to run source x86_64-*/setup.sh
Note that strictly speaking we didn’t need to call cmake
ourselves
this time, as make will realize that we modified CMakeLists.txt
and
call cmake
for us, but I prefer calling cmake
manually whenever I
add or remove a file, just to make sure that the new file gets picked
up.
Basic notes about algorithms:
MyAnalysis/Root/MyxAODAnalysis.cxx
and a header file
MyAnalysis/MyAnalysis/MyxAODAnalysis.h
initialize()
: called once, before the first event is executedexecute()
: called once per eventfinalize()
: called once, after the final event has completed