SetBranchAddress TLorentzVector

Hello,
I have a tree containing a TLorentzVector branch named “lv1”.
I would like to access : “lv1.M()” in a dynamic way such as.

fTree->SetBranchAddress("lv1.M()", &mass)

Is there a way to do that ? I am basically passing a string to my code.
I don’t really want to hardcode such cases (I have many other objects types) :

TLorentzVector lv1;
 fTree->SetBranchAddress("lv1.", &lv1);
if(str.EqualTo("lv1.M()")) mass = lv1.M();

I assume it should be possible to do it, as we can do the following to get an histogram:
fTree->Draw("lv1.M()");

Hello,
I tried to write a simple script to illustrate. The reason why I don’t want to hardcode is because I have an already written function defined as following :
myfct(vector<TString> varname, vector<double*> varaddr)

varname is referring to variable name used later on in the library I use {“M”, “X”, “Y”, “Z”}
The varaddr is referring to double pointers which are initialized calling Three::SetBranchAddress and set to the correct value with Three::GetEntry.
So I would like to do the same for the mass.

I tried to address different variables such as Px. I have done that in a different way. But I think I am missing something simple…

#include "TROOT.h"
#include "TFile.h"
#include "TTree.h"
#include "TBrowser.h"
#include "TH2.h"
#include "TRandom.h"

void tree1w()
{
   TFile f("tree1.root","recreate");
   TTree t1("t1","a simple Tree with simple variables");
   TLorentzVector lv1;
  
   t1.Branch("lv1.", "TLorentzVector", &lv1);

   //fill the tree
   for (Int_t i=0;i<10;i++) {
     lv1.SetPx(i);
     t1.Fill();
  }

  t1.Write();
}

void tree1r()
{
   TFile *f = new TFile("tree1.root");
   TTree *t1 = (TTree*)f->Get("t1");
   TLorentzVector* lv1 = NULL;
   double X;

   t1->SetMakeClass(1);
   t1->SetBranchAddress("lv1.",&lv1);
   t1->SetBranchStatus("lv1.*", 1 );

   t1->SetBranchAddress("lv1.fP.fX",&X);

   Long64_t nentries = t1->GetEntries();
   for (Long64_t i=0;i<nentries;i++) {
     t1->GetEntry(i);
     lv1->Print();
     cout << lv1->Px() << " " << X << endl;
  }
}

void tree1() {
   tree1w();
   tree1r();
}
(x,y,z,t)=(0.000000,0.000000,0.000000,0.000000) (P,eta,phi,E)=(0.000000,0.000000,0.000000,0.000000)
0 0
(x,y,z,t)=(1.000000,0.000000,0.000000,0.000000) (P,eta,phi,E)=(1.000000,-0.000000,0.000000,0.000000)
1 0
(x,y,z,t)=(2.000000,0.000000,0.000000,0.000000) (P,eta,phi,E)=(2.000000,-0.000000,0.000000,0.000000)
2 0
(x,y,z,t)=(3.000000,0.000000,0.000000,0.000000) (P,eta,phi,E)=(3.000000,-0.000000,0.000000,0.000000)
3 0
(x,y,z,t)=(4.000000,0.000000,0.000000,0.000000) (P,eta,phi,E)=(4.000000,-0.000000,0.000000,0.000000)
4 0
(x,y,z,t)=(5.000000,0.000000,0.000000,0.000000) (P,eta,phi,E)=(5.000000,-0.000000,0.000000,0.000000)
5 0
(x,y,z,t)=(6.000000,0.000000,0.000000,0.000000) (P,eta,phi,E)=(6.000000,-0.000000,0.000000,0.000000)
6 0
(x,y,z,t)=(7.000000,0.000000,0.000000,0.000000) (P,eta,phi,E)=(7.000000,-0.000000,0.000000,0.000000)
7 0
(x,y,z,t)=(8.000000,0.000000,0.000000,0.000000) (P,eta,phi,E)=(8.000000,-0.000000,0.000000,0.000000)
8 0
(x,y,z,t)=(9.000000,0.000000,0.000000,0.000000) (P,eta,phi,E)=(9.000000,-0.000000,0.000000,0.000000)
9 0

SetMakeClass explicitly request to not read the data as object (but rather as individual int, floats, double and array there of).

I do not see what you mean here. By using SetMakeClass(1), then I should be able to access individual array. This is exactly what I want.

However fP.fX is still not accessible.
If I print the tree, it is still showing TLorentzVector.

******************************************************************************
*Tree    :t1        : a simple Tree with simple variables                    *
*Entries :       10 : Total =            1697 bytes  File  Size =        638 *
*        :          : Tree compression factor =   4.03                       *
******************************************************************************
*Br    0 :lv1.      : TLorentzVector                                         *
*Entries :       10 : Total  Size=       1242 bytes  File Size  =        188 *
*Baskets :        1 : Basket Size=      32000 bytes  Compression=   4.03     *
*............................................................................*

I would have expected to see a different print of the tree by enabling SetMakeClass(1) or (0).

NB: With or without the SetMakeClass function, the tree is showing the same structure.

The structure that is shown by Print is the structure defined as write time.
In your case the LorentzVector was not “split” and thus the individual member were stored together and can only be retrieve together and thus, in this case, retrieve the whole object is the only way (TTreeReader, the newer MakeSelector and TDataFrame will give you a syntax to access the member but it will still retrieve the whole object).

Cheers,
Philippe.

1 Like

Thank you pcanal.

I finally used the following method (perhaps a “non-efficient” one), but it does what I want in a very simple way.

fTree->Draw("lv1.M()", "", "goff", 1, ientry);
cout << fTree->GetV1()[0] << endl;

Marco

Don’t forget to call

fTree->SetEstimate(fTree->GetEntries());

to make sure GetV1() has all the value.

Also you original code was close:

TFile *f = new TFile("tree1.root");
   TTree *t1 = (TTree*)f->Get("t1");
   TLorentzVector* lv1 = NULL;

  TBranch *br = nullptr;
   t1->SetBranchAddress("lv1.",&lv1, &br);


   Long64_t nentries = t1->GetEntries();
   for (Long64_t i=0;i<nentries;i++) {
     br->GetEntry(i);
     lv1->Print();
     auto X = lv1->Px();
  }
}

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.