Introduction
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:
setupATLAS
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/MyPackageAlgJobOptions.py
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
MyPackageAlgJobOptions.py
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:
acmSetup
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}
LINK_LIBRARIES ${ROOT_LIBRARIES}
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;
selectedMuons.push_back(muon);
}
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
MyPackageAlgJobOptions.py
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;
selectedMuons.push_back(muon);
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.
AAH::setProperty("myWriter","TreeName","/MYSTREAM/MyTree");
std::vector<std::string> branches = {"mu_tlv_pt/vector<double>","mu_tlv_eta/vector<double>","mu_ptcone30/vector<float>"};
AAH::setProperty("myWriter","Branches",branches);
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.
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;
selectedMuons.push_back(muon);
m_myHist->Fill(muon->Pt()*1e-3);
}
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;
muons->at(0)->get<int>("myProperty");
muons->at(0)->print();
}
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