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: The various components are: 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