Wanted: Event structure example

Hi,

I have been trying to adapt Event.cxx to create an event structure as follows:

For each event, I would like to have a list of tracks, like in Event.cxx. I would also like to have objects for reconstructed particles with links from the reconstructed particle object to the daughter tracks in the track list. I have succeeded in making these reconstructed particle TCLonesArrays and reading them back, however I have never gotten the links to work. It is these links that have been giving me an endless headache for the past two weeks.

I was successful in adding the reconstructed particle objects (these are TCloneArrays) but cannot get the TRefArray links to work (Root 4.03/04). More succintly, I cannot get code to work to READ the thing, so I do not know if my structure is OK or not. I do not know what syntax to use to access the objects pointed to – everything I tried has failed.
Maybe the TClonesArrays are not what I should be using for the reconstructed particles?

Can someone point me to a working example with such a structure? The reading part is what I am most unsure of. Someone must have built some such thing for an experiment or Monte Carlo.

Thanks,

Alex

Hello Axel,

I’m using TRefs and TRefArrays since quite some time now. It works perfect.
Have a look at eg.
www-zeus.desy.de/~kind/zplusplus … Event.html
www-zeus.desy.de/~kind/zplusplus … Decay.html
www-zeus.desy.de/~kind/zplusplus … Track.html
The full index is at
www-zeus.desy.de/~kind/zplusplus … Index.html

Hope this helps. Cheers,
Oliver

PS. I’m not using MakeClass or TTree:Draw() for analyzing. So I can’t tell you if this works properly.

Thanks Oliver,

That looks very useful. Do you have an example of a script the reads this tree? In particular, something that accesses a TRefArray (or TObjArray).

Thanks,
Alex

Hello Alex,

well, let’s look at tracks coming from the primary vertex in an interactive Root session.
The vertex holds a list of all daughter tracks in a TRefArray.

[code]
root [0] TFile *f = new TFile(“beautydir_ZEUSMC.A7KP717.F8307.PYT62C.EP820PET.BBDIR.11.Z00.root”)
root [1] TTree t = (TTree)f->Get(“beautydir_mc”)
root [2] ZEvent *evt = new ZEvent
root [3] t->SetBranchAddress(“Event”, &evt)
root [4] t->GetEntry(0)
(Int_t)69340
root [5] ZVertex primary_vtx = (ZVertex)evt->GetPrimaryVertex()
root [6] TRefArray vtx_tracks = primary_vtx->GetDaughters()
root [7] .p ((ZVctrhl
)vtx_tracks->At(0))->Print()

Id P Pt Theta Phi Q/R Q*Dh Zh chi2/DoF dE/dx vertex

1 2.987 1.595 0.563 2.320 0.003 -0.040 -43.211 26.280 / 73 52.000 1 (prim)

root [8] .p ((ZVctrhl*)vtx_tracks->At(1))->Print()

Id P Pt Theta Phi Q/R Q*Dh Zh chi2/DoF dE/dx vertex

2 1.155 0.575 0.521 2.528 -0.007 0.216 -43.317 60.160 / 64 38.000 1 (prim)
-------------------------------------------------------------------------------------------------------------------------------------[/code]
Here I’ve printed the first 2 vertex tracks only. In real code in most cases you might loop over the array. This is done by using its iterator:

TIterator next(vtx_tracks); while ( ZVctrhl *trk = (ZVctrhl*)next() ) { trk->DoSomething(); ... }
Best regards,
Oliver

Hi Oliver,

I notice that you do not declare your TClonesArrays as static in your nice ZEvent example, as was done in the Event.cxx example. Is this because you saw memory leaks when using static? This appears to be what I am seeing in my code. The number of objects keeps increasing until I run out of memory. Has anyone else come across this problem?

Thanks,

Alex Smith

Hi,

It is also possible to have the TClonesArray being non-static.
If you send us a concise example of what you do you may be able to spot where the leaks comes from (maybe you continually add to the TClonesArray instead of re-using it? etc.)

Cheers,
Philippe.

Hi Philip,

My code is too large to pare down to a small example you can run. I will include what I believe are the most relevant pieces in the attach tar/gzip file.

This is patterned after Event.cxx. I find that the static declaration I mentioned earlier does not matter-- I seem to get the same behavior with or without it. What I observe by using gObjectTable->Print() is that the number of any of the My* objects (MyDPhiRho0, for example) that I create always increases as the job procedes, as if it is resizing to some maximum and never getting shrunk back down when I call MyAnalysisEvent::Clear(), which callls the Clear method of TClonesArray.

eg.,

fMyDPhiRho0s->Clear(“C”);
NDPhiRho0 = 0;

I do use TRefs and TRefArrays in my jobs which point between different objects within a given event (only). I don’t know if this matters. I do delete the TRef’/TRefArrays when I Clear() and set their pointers to zero.
MyEvent.tar.gz (9.33 KB)

[quote]I create always increases as the job procedes, as if it is resizing to some maximum and never getting shrunk back down when I call MyAnalysisEvent::Clear(), which callls the Clear method of TClonesArray.
[/quote]This is the intent of the TClonesArray. The goal is to minimize the number of memory allocation/deallocation. So the size should grow up to the maximum number of element in any of the events.

Cheers.
Philippe.

Yes, I can confirm this. The memory consumption increases at the beginning of a job and after a short time stays the same for the whole job (in my case less than 200MB with ~20 clone arrays in the event tree running over millions of events). I do not have any memory leaks. The important thing is to write proper Clear() functions for all objects inside the clone deleting all dynamic sub-objects, arrays etc. (including TRefs!. IMHO this is a weak point in the $ROOTSYS/test/Event.* example, that the TRefs there are not instantiated on the heap via the new operator. Because a TRef object internally occupies memory on the heap this leads to memory leaks.)

Regarding your original question on the staticness of the clone arrays: I simply didn’t feel the need of making them static. Maybe René can comment on this for he is the author of the event class example.

Cheers,
Oliver