Writing linked TH2F and TVector3 into root file and reading them afterwards

I am a bit lost in the documentation about read/write into root files.

I have:

  1. TObjArray of TH2F … histList
  2. TObjArray of TVector3 … vecList

Each TVector3 belongs to one TH2F.

Now suppose I somehow wrote them into root file.

Suppose I read the TObjArray of TH2F.
Now when reading any TVector3 I want to know to which TH2F it belongs.
Is it possible to somehow mark each TVector3 (say vecList(3) belongs to hisList(1)) when writing it into root file?

Can you explain a bit what you mean? some code example?

Maybe a: TMap

Tried to simplify it

// writing into .root file
TFile f("histvec.root", "recreate");
TRandom2 rng = new TRandom2();

int histNumber=100;
TObjArray histList(histNumber);
int vecNumber=250;
TObjArray vecList(vecNumber);

int vecCountInHist[histNumber]; // sum of all array elements = vecNumber

for (int iHist=0; iHist<histNumber; ++iHist)
{
 TString histName = "HistName " + std::to_string(iHist);
 TString histTitle = "HistTitle " + std::to_string(iHist);
 TH2F *hist = newTH2F(histName, histTitle, ...numerical hist parameters...);
 histList.Add(hist);
 
 for (int k=0; k<vecCountInHist[iHist]; ++k)
 {
  TVector3 *vec = new TVector3(rng->Rndm(),rng->Rndm(),rng->Rndm());
  vecList.Add(vec);
 }
}

histList.Write();
vecList.Write();
f.Close();

Now when I read this file somewhere else I get histList & vecList,
but the linking between which “vec” belongs to which “hist” is lost.

Is there a way to label “vec” when adding to vecList, so that later when reading “vec” I know to which “hist” it belongs? Or structure the .root file in a way so that when reading particular “hist” I am automatically reading all “vec” that belong to it?

TMap might be actually the simpliest solution to what I need…, without explicitly structuring the .root file in the code by myself.

Edit: unfortunately TMap does not take integers as key… Even declaring RooInt object (which is integer that inherits from TObject) in code leads to segfault (I have v6.26/10).

Maybe a: TExMap

I am missing something. The documentation states:

Blockquote
This class stores a (key,value) pair using an external hash.
The (key,value) are Long64_t’s and therefore can contain object pointers or any longs. The map uses an open addressing hashing method (linear probing).

TExMap has values as Long64_t, how do I convert TList* to Long64_t? It should be possible, but I have no idea how

value = (Long64_t)pointer
pointer = (TList*)value

An example: montecarlo/eg/inc/TDatabasePDG.h + montecarlo/eg/src/TDatabasePDG.cxx

BTW. Maybe you should also have a look at the TRef and the TRefArray classes (plus “${ROOTSYS}/tutorials/tree/[jJ]et*” files).

Tried TExMap, when executing this before writing the file

std::cout << "List size " << i << ": " << ((TList *)exMap->GetValue(i))->GetSize() << std::endl;

this gives 1 (and size of the map is 14)

When executing the same after reading the file

Error in <HandleInterpreterException>: Trying to access a pointer that points to an invalid memory address..
Execution of your code was aborted.
ROOT_prompt_7:1:7: warning: invalid memory pointer passed to a callee:
cout<<((TList *)exMap->GetValue(0))->GetSize()<<endl;
      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

the size of the map after reading is correct though (14)

Is the “i” your “key”?
I have the impression that you actually try to access the “slot” number.

I guess you maybe want to play with the “built-in” iterator: TExMapIter

I’m not very much familiar with these classes.
@Axel It seems @rdm is the original author, so maybe someone who maintains it now could provide more help.

sorry, I forgot to write - it is a cycle so “i” is any index of TExMap. That line of code works, i.e. accessing the data from TExMap before they are written into root file.

I’m not sure what you mean by the “index”.
In the most complex case, you may need to deal with four variables: UInt_t slot”, “ULong64_t hash”, “Long64_t key”, “Long64_t value

yes, “i” is key.

Actually, when I think of it, I could solve my problem, if I can make sure that

  • TObjArray of TH2F, i.e. TObjArray plotList(100)
  • TObjArray of TVector3, i.e. TObjArray vecList(250)

(or any other than TObjArray container that can store them) gets written in the order they are stored in TObjArray.
Then I can simply write into root file a list of integers that will just do the mapping. (I really do not want to make a big programmatic deal out of this one)

Because now when I called

plotList.Write();
vecList.Write();

the TH2F histograms were stored in ascending order from 0 to 99, while the TVector3 vectors were stored in descending order from 249 to 0.

@pcanal Is there a way to guarantee the order of writing of the elements of these containers into file?