This guide will illustrate first steps to perform basic operations using the AnalysisCam physics analysis software. AnalysisCam is a modular environment, mainly handling TLorentzVectors for which properties can be easily set and get. It runs with athena and allows to plug desidered reconstructed and calibrated objects - eventually retrieved from other frameworks, like SUSYTools - and perform basic selection or more complex analyses. Please refer also to the tutorial: xAOD Analysis in CMake.

Disclaimer: this is a very first attempt of putting information together. Your edits are welcome to improve the quality of this page.

Setup and configure

In your favorite directory run the following, using the acm command suite for checking out and compiling:

mkdir build source
cd build
acmSetup AthAnalysis,21.2.20
acm clone_project will/AnalysisCam
acm add_pkg AnalysisCam/AnalysisCamEvent
acm compile

The main AnalysisCamEvent package is the only package needed to get started. The first attempt on compiling on lxplus was failing, but probably due to a glitch, so better not giving up on that. Continuing with the following however went fine:

acm new_skeleton MyPackage
acm compile

This time it also compiled without problems. Before starting any new implementation it is worth trying if things work out-of-the-box.

mkdir $TestArea/run
cd $TestArea/run
athena --filesInput=$ASG_TEST_FILE_MC --evtMax=100 MyPackage/

Note that the input file and the number of events to run on (as well as the number of events to eventually skip) can be set in the jobOption, using the jps.AthenaCommonFlags. If they are set on the submitting command line, they take precedence.

If the outcome is satisfying, this setup can be recovered in a clean shell next time, by going into the build/ directory and running:


In the following, changes will be applied into $SourceArea/MyPackage/src/MyPackageAlg.cxx. If a new dependence is added, it is needed to include it in the file CMakeLists.txt (see below).

Retrieve an xAOD container

As a first example, it will be shown how to retrieve a muon collection. First it is needed to include the header specific for the container that will be retrieved at the top of the MyPackageAlg.cxx.

#include "xAODMuon/MuonContainer.h"

The container is then retrieved via the evtStore (available from athena), in the execute() section.

const xAOD::MuonContainer* xaod_muons =0;
CHECK( evtStore()->retrieve(xaod_muons, "Muons") );

Before compiling, it is important to handle correctly dependencies in CMakeLists.txt file. It is possible to fully remove the section on public and private dependencies (atlas_depends_on_subdirs) since they are not actually needed. While it must be added xAODMuon to atlas_add_library (see also below).

Make use of AnalysisCam features

Now let us open the possibility to use the classes already implemented in AnalysisCam, adding the following at the beginning of MyPackageAlg.cxx:

#include "AnalysisCamEvent/CamEvent.h"

After adding all dependencies in CMakeLists.txt file, atlas_add_library function will look like this:

atlas_add_library( MyPackageLib src/*.cxx
                   PUBLIC_HEADERS MyPackage
                   INCLUDE_DIRS ${ROOT_INCLUDE_DIRS}
                                    AthAnalysisBaseCompsLib AnalysisCamEventLib xAODMuon

Let us convert the muon container in the CamDeque format to access all its features, and create a new collection of muons passing the cuts. A CamDeque is a deque (which is very similar to a vector) of CamObjects. A CamObject is a TLorentzVector with set and get method for setting and getting arbitrary properties of. When you construct a CamDeque from an xAOD collection it will automatically create one CamObject for each object in the xAOD collection. The TLorentzVector properties of the CamObject will be automatically set from the 4-vector properties of the xAOD objects:

CamDeque muons(*xaod_muons);
CamDeque selectedMuons;

Then it is possible to apply a cut on their properties, e.g. pT:

for(auto muon : muons){
    if(muon->Pt() < 28000) continue;

When debugging things, you can print some variables in this event, after the loop on them:

selectedMuons.all_print("tlv_pt,tlv_eta,ptcone30"); // leaving it blank will print all the possible "aux" variables

The tlv_ prefix is needed only to access TLV variables (pT, eta, phi, m).

Adding histograms

The muons pT can be stored in a histogram. To do this, it is possible to uncomment the following lines in the initialize() section:

m_myHist = new TH1D("myHist","myHist",100,0,100);
CHECK( histSvc()->regHist("/MYSTREAM/myHist", m_myHist) ); //registers histogram to output stream

and the declaration of m_myHist in the MyPackageAlg.h header file. The MYSTREAM is defined and registered in the jobOption file:

jps.AthenaCommonFlags.HistOutputs = ["MYSTREAM:myfile.root"]  #register output files like this. MYSTREAM is used in the code.

then the I/O for histograms is entirely taken care by the CamWriter (see below). Finally, fill the histogram with the selected muons:

for(auto muon : muons){
    if(muon->Pt() < 28000) continue;
    m_myHist->Fill(muon->Pt()*1e-3); // to get pT in GeV

The registered histogram will be automatically closed and written in the output file.

Adding branches to a TTree

Similarly as it is done before, branches can be added to the MYSTREAM. As an example:

// The setProperty syntax is the same normally used in athena jobOptions.
// To access the properties of the algorithms in the source code, AAH is used. 
std::vector<std::string> branches = {"mu_tlv_pt/vector<double>","mu_tlv_eta/vector<double>","mu_ptcone30/vector<float>"};

Selected muons will populate the branches with:

selectedMuons.applyService("CamWriter/myWriter","mu_"); // type of the service / name of the service

This last line makes use of the CamWriter that takes care of all I/O related to the root file. Only the branches with the given prefix mu_ will be written out.

Smarter use of CamEvent

The retrieval of the muon container can be done through the use of CamEvent, instead of the evtStore(), making even more transparent the use of xAOD collections:

CamEvent e;
CamDeque* muons = e.getDeque("Muons");

In this case the loop has to be done using the pointer:

for(auto muon : *muons){
    if(muon->Pt() < 28000) continue;

Addition of new properties

As was said in the introduction, properties can be created just by setting them, e.g.:

if(muons->size()>0) {
   muons->at(0)->set("myProperty") = 5;

Here a new property "myProperty" is created and attributed to the first muon in the event. Any subsequent muon will also have this property defined. This feature can be used to attach an analysis specific variable to a given collection, that can be used as any other property of the collection itself.

-- SergioGrancagnolo - 2018-03-05

Edit | Attach | Watch | Print version | History: r4 < r3 < r2 < r1 | Backlinks | Raw View | WYSIWYG | More topic actions
Topic revision: r4 - 2018-03-06 - WillButtinger
    • Cern Search Icon Cern Search
    • TWiki Search Icon TWiki Search
    • Google Search Icon Google Search

    Main 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