Tutorial - Kanga++ Interactive Access to CM2 Data
This tutorial has been updated for release 16.0.2 and later. Earlier tutorials are here and here.
Running Kanga
First you need to check out a release >= 16.0.2 and set up the workdir:
prompt> newrel -t 16.0.2 my16.0.2
prompt> cd my16.0.2
prompt> srtpath <ret> <ret>
prompt> addpkg workdir
prompt> gmake workdir.setup
prompt> cd workdir
Then you just run Kanga:
prompt> Kanga
You will see the ROOT logo and startup message.
Reading data with Kanga
First you make an object to read the data for you
root[0] KanEventSource* mc = KanEventSource::microMC();
There are 4 standard configurations you can choose from for your event source. Each one has
a different set of components enabled:
- micro() -> hdr usr tag cnd aod
- microMC() -> hdr usr tag cnd aod tru
- mini() -> hdr usr tag cnd aod esd
- miniMC() -> hdr usr tag cnd aod tru esd
The various components are:
- hdr: Event Header
- usr: User Data
- tag: Event Tag
- cnd: Beta Candidates
- aod: "Micro" level reconstruction data {tracks, clusters, PID}
- tru: Monte Carlo Truth
- esd: "Mini" level reconstruction data {hits,digis}
It isn't that big a deal if you pick the wrong type of event source. You may get a message saying that a particular component is being disabled (if you try and read a collection where that component is missing) or you simple will not be able to read the unconfigured components.
Then you can start adding collections:
root[1] mc->Add("/store/users/echarles/prod_14.5.3/SP-B0B0bar/BSemiExcl_001237_0315_merged");
After this command you should get some messages about opening files and adding collections.
If certain components are borrowed or missing you may also get messages about that.
If you mistyped the name of the collection you will get a message about not being able to find the
file. If you need a collection to run over, go to this page.
Then you can get access to the various components and browse the data structures. For example
to see all the branches that make up the "cnd" (aka "Beta Candidates") component:
root[2] mc->getCnd()->Print();
Which would generate a pretty normal looking printout of the TTree for the "cnd" component.
You can get a list of the components that are on in your collection:
root[3] mc->listComponents();
hdr usr tag cnd aod tru
You can do some simple things with your input source. For example:
root[4] mc->nEvt()
(const unsigned int)131564
Note that you must leave off the trailing semicolon for ROOT to print out the return value of
a function.
Since KanEventSource is a kind of TTree object, you can do any of the functions
that you are used to doing with TTree. Of course, some of them might not really make much sense.
You can have more that one input source.
root[5] KanEventSource* input = KanEventSource::microMC();
root[6] input->Add("/work/users/echarles/prod_14.5.3a/Run1-OnPeak/BSemiExcl_0041_merged");
root[7] KanEventSource::list();
------------------------------------------------------------
Name
# Events Components
------------------------------------------------------------
_microMC0
131564 hdr usr tag cnd aod tru
_microMC1
313896 hdr usr tag cnd aod
The event sources are defined by their names.
The names is the configuration ("_microMC") and whatever argument you pass to the function (default is "0").
You can make some nice plots:
root[8] input->getCnd()->Draw("Cnd_B0__n","","",5000);
root[9] input->getCnd()->Draw("Cnd_B0.lundID()","","",5000);
root[10] input->getCnd()->Draw("Cnd_B0.p4().Theta():Cnd_B0.p4().Phi()","","",5000);
root[11] input->getCnd()->Draw("Cnd_B0.p4().Theta():Cnd_B0.p4().Phi()","Cnd_B0.lundID()==511","",5000);
If you want to access data from more that one component, you need to link the trees
root[12] input->setupFriends();
root[13] input->Draw("Cnd_Pions.trk()->nSvt()","","",5000);
The point here is that the Track data live in the "aod" component, so you have to loop over the top
level object, not just the cnd component.
You can project data into histograms:
root[14] TH2F hist("MyHist","A hist of Theta v. Phi",100,0.,3.15,100,-3.15,3.15);
root[15] input->getCnd()->Project("MyHist","Cnd_B0.p4().Theta():Cnd_B0.p4().Phi()","Cnd_B0.lundID()==511","",5000);
You can load and run macros
root[16] .L PARENT/KanExamples/nCand.C
root[17] TH1* nC = nCand(*input,"ChargedTracks",5000);
root[18] nC->Draw();
There are a few very basic steps you need to be able to write you own macros
First, you have to decide which data you will access
root[19] BtaCandHandleBranch B0(KanCompMap::cnd ,"Cnd_B0");
root[20] BtaCandHandleList Trk(KanCompMap::cnd ,"Cnd_ChargedTracks");
There are two types of "handles" you can use to read BtaCandidate data.
The first, BtaCandHandleBranch, is for candidates that are all stored on the same branch.
This is usually all the particles of the same type (B0 and B0-bar in this example).
The second, BtaCandHandleList, is for named lists of BtaCandidates (for example ChargedTracks);
Second, you have to attach the handles to the data
root[21] input->setBranchToRead(B0);
root[22] input->setBranchToRead(Trk);
Third, you load an event
root[23] input->LoadTree(12);
This will load the first event.
Fourth, you read the data for that event
root[24] Bool_t readOk = B0(*input) && Trk(*input);
A return value of kTRUE means the data were succesfully read, kFALSE indicates problems occurred.
Then you can access the data
root[25] UInt_t nB0 = B0.size();
root[26] BtaCandIdI* aCand = B0.cand(0);
root[27] aCand != 0 ? aCand->nDau() : 0
(const unsigned int)6
The macros KanExamples/nCand.C and KanExample/nDau.C uses these functions and very little else.
It is very easy to access User Data in Kanga
You can use TTree::Draw() like normal
root[28] input->getUsr()->Draw("mES","","",5000);
root[29] input->Draw("mES:BSemiExclCandData_Cands.obj()->lundID()","","",5000);
You can make handles to access the user data
root[30] UsrCandHandle usrCand(KanCompMap::usr,"BSemiExclCandData");
root[31] UsrEventHandle usrEvt(KanCompMap::usr,"BSemiExclEventData");
You have to add the branches you car about to the handle
root[32] UsrVectorK mES;usrCand.addVect("mES",mES);
root[33] UsrDatumK mult;usrEvt.addDatum("multiplicity",mult);
Then you attach the handles, load events and read the data as before
root[32] input->setBranchToRead(usrCand);
root[33] input->setBranchToRead(usrEvt);
root[34] input->LoadTree(0);
root[35] Bool_t readOk = usrCand(*input) && usrEvt(*input);
root[36] usrCand.readIndex(); mult.readBranch(); mES.readBranch();
Note that you have to read each of the user data seperately.
Although this is a bit of a pain, it is intentional, to allow you to avoid reading any branches
you don't have to in a macro subject to any preselection cuts you might have.
And finally, you can use the handles to access the data
root[37] mult()
(const int)11
root[38] usrCand.nCands()
(const unsigned int)16
root[39] usrCand.cand(0)->lundID()
(const int)(-511)
root[40] mES[0]
(const float)5.25386857986450195e+00
Eric Charles
Last modified: Wed Nov 24 11:48:55 PST 2004