TRef example with objects in different files

Hi all.

I’d like to give TRef a try in order to link the “high-level” analysis results with the raw digitized waveform. Basically, a TRef in the high-level file should point to the waveform object in the “raw” file. However, I am struggling to figure out how this is done. Could somebody point to an example of this? The only TRef examples that I have found are the ones used to point between objects stored in TClonesArrays that are within the same event (a la $ROOTSYS/test/Events.h).

Thanks for your help,
Adam

If you have a TObject *objraw in memory and have
TRef myref = objraw;
the fUniqueID of objraw is set with a TProcessID and a unique ID within this process. myref contains the same info. You can write objraw to file1 and myref to file2. In a subsequent session when opening file1 and file2 again
and reading objraw from file 1 and myref from file2, myref will automatically point to objraw (via GetObject()).

NOTE that objraw must be written to file1 with its fUniqueID set. The system will not work if in a first session
you set myref=objraw but do not write objraw on file1.

Rene

Thanks Rene. It makes sense to me why it wasn’t working then because I wasn’t rewriting the file that contained the pulse.

My next question is, is there an example of how to know which file to open at run-time? From what I understand, the process of setting this up would be the following:

  1. Open file A containing events that contain the TRef object P, open the files B, C, D, E, etc… that contain events that contain the objects R to be referred to, set my TRef objects to point to the desired reference objects, P = R, then fill/write/close both files.

  2. To access the referred objects from events in file A, I open file A. Now, for each event in A, the object referred to in the TRef P, will exist on different files. How do I know which file to open?

Even in the case where there is just one file to be opened, B, how do I know which file it is exactly? Or would this be some sort of information that I would need to store in the events in file A?

A related question is this - what is the advantage of storing a TRef pointer if instead I could store a file name and entry number in file A to retrieve the object in file B?

Thanks for your help and sorry for so many questions at once.
Adam

Hi Rene - one more question.

What do you mean exactly by:
“NOTE that objraw must be written to file1 with its fUniqueID set”. How do I do this? Is this done automatically?

thanks again.
A

[quote]My next question is, is there an example of how to know which file to open
at run-time? From what I understand, the process of setting this up would be
the following:

  1. Open file A containing events that contain the TRef object P, open the files B, C, D, E, etc… that contain events that contain the objects R to be referred to, set my TRef objects to point to the desired reference objects, P = R, then fill/write/close both files.
    [/quote]
    You do not need to set the TRef again. Simply open files B,C,etc. Read the referenced objects
    from B,C in memory. If you have TRef myref
    in file A, you can directly call myref.GetObject() and this will point directly
    to the referenced object in file B (if the referenced object was in B).

[quote]2. To access the referred objects from events in file A, I open file A. Now, for each event in A, the object referred to in the TRef P, will exist on different files. How do I know which file to open?
[/quote]It is up to you to know in which file the referenced objects are (however see remark below).
A TRef can only point to one object in memory.
Even in the case where there is just one file to be opened, B, how do I know which file it is exactly? Or would this be some sort of information that I would need to store in the events in file A?
(see remark below)

[quote]A related question is this - what is the advantage of storing a TRef pointer if instead I could store a file name and entry number in file A to retrieve the object in file B?
[/quote]
of course you can store a string instead of a TRef. Some of the LHC experiments
have taken this bad option. A TRef consumes (in average) about 2.5 bytes on disk.
string references might be kilometers long. They will take far more space on the file
and even if the reference string is always more or less the same, you will spend a huge amount
of cpu time in the compression algorithm.

[quote]What do you mean exactly by:
“NOTE that objraw must be written to file1 with its fUniqueID set”. How do I do this? Is this done automatically?
[/quote]
Let me repeat what I said in my previous answer;
When you do TRef myref = objraw, the fUniqueID of objraw is modified to include
a uniqueid and a process id when this object was referenced. In this way,
you can write different objraws in different sessions in the same file.

REMARK:
If you read carefully the TRef documentation, you will see a section "Action on demand"
If you implement this feature, then you can dynamically open the file referenced
by the TRef by executing a script (or a TExec)

Rene

Hi again, Rene.

In the “Action on Demand” script, how does it know which file to open?

I’ll tell you the situation that I have and then perhaps you can tell me if what I want to do is possible.

I have one “high-level processed” file A that contains events with TRef P that were set to hold a pointer to an object in raw data files (B, C, D, E, etc… ZZZZZZZZ). If I want to access the object stored in P, do I need to open ALL of the files B, C, D, E, … ZZZZZ in order to “automatically” retrieve it? Or is there some way of knowing that my object is stored specifically in file Q.

I can see how it may be more ideal to have raw files B, C, D, E,… and then have the same number of high-level processed files, B_hlp, C_hlp, D_hlp, … ZZZZZZ_hlp. This way, I suppose the “Action on Demand” script can find out which file to open more easily.

Do TRefs work in a compiled program?

Thanks again for being patient with me. Dear ROOT users - please let me know if there’s an explicit example of this.

Adam

To answer more precisely your question, I need to know your storage model.
Probably your event data is inside a ROOT Tree.
The typical solution in this case is to add some bookeeping data in the form of one or several
objects in tree.GetUserInfo().
For example if you want to keep the information about the raw data file corresponding
to the AOD/ESD/DST of the current tree, you can create a TNamed object

TNamed *n1 = new TNamed("rawdata","file name containing the raw data"); mytree->GetUserInfo()->Add(n1); when executing mytree->Write at the end of your job, the list of objects in the UserInfo list
is written to the file together with the tree header.
When reading the Tree, you can access this information by doing

TNamed *n1 = (TNamed*)mytree->GetUserInfo()->FindObject("rawdata"); const char *filename = n1->GetTitle();
Now back to TRef, you must at least know something about what it references.
Suppose you have read in memory TRef myref. you can test if myref has a valid pointer
to its referenced object (may be the referenced object is not yet read in memory).
Example1: referenced object is a TKey in the rawdata file

MyClass *obj = (MyClass*)myref.GetObject(); if (!obj) { //referenced object is not yet in memory //open the raw data file and read the object in memory const char *filename = n1->GetTitle(); TFile *rawdata = TFile::Open(filename); MyClass *rawobject = (MyClass*)rawdata->Get("object name"); obj = (MyClass*)myref->GetObject(); }
Example2: the referenced object is in the raw data Tree at the same entry

//open the raw data file corresponding to mytree TNamed *n1 = (TNamed*)mytree->GetUserInfo()->FindObject("rawdata"); TFile *rawdata = TFile::Open(n1->GetTitle()); TTree *rawTree = (TTree*)rawdata->Get("rawTree"); //here SetBranchAddress for your Tree(s) //loop on entries of the AOD Tree Long64_t nentries = mytree->GetEntries(); for (Long64_t entry=0;entry<nentries;entry++) { mytree->GetEntry(entry); MyClass *obj = (MyClass*)myref->GetObject(); if (!obj) { //referenced object is not yet in memory //read the entry in the raw data containing the referenced object rawTree->GetEntry(entry); obj = (MyClass*)myref->GetObject(); } }

[quote] Do TRefs work in a compiled program?
[/quote] Yes, this is the typical use case.

Rene