Using TBranch::Fill

Hi,

In my code, I write some variables and I fill some branches but I need to treat them separately, do you know a method of TTree to make the link between the branches and the tree like I cannot use the TTree::Fill method ?
I really need help because I’m a new PhD student and I learn to use root.
Thank you in advance,

Jérôme

Hi,

Use TTree::SetEntries(Long64_t n = -1):

[quote] Change number of entries in the tree.

If n >= 0, set number of entries in the tree = n.

If n < 0, set number of entries in the tree to match the
number of entries in each branch. (default for n is -1)

This function should be called only when one fills each branch
independently via TBranch::Fill without calling TTree::Fill.
Calling TTree::SetEntries() make sense only if the number of entries
in each branch is identical, a warning is issued otherwise.
The function returns the number of entries.[/quote]

Cheers,
Philippe.

Hello,

Thank you for your answer. This method works very well if each branch has the same number of entries, but, in my case, they have different number of entries. To illustrate, I’m using Muon objects and LooseMuon objects, which are muons but after a given selection.

Jérôme

Hi Jerome,

The branches of the same TTree must have the same number of entries. If you need branches with different number of entries, you will need to create 2 TTree, associate them together with TTree::AddFriend and link the entries together by creating an index (via TTree::BuildIndex).

Alternatively, you could tweak your data model. If I guessing your use case correctly, the typical use case is to use 2 collections, one for the Muon and one for the LooseMuon and to have only one TTree entry for each “event”. i.e. each TTree entry will containing many Muons. FurtherMore If LooseMuon is a subset of Muon, you could have one collection of Muons and then the looseMuon can be a collection of references (for example a TRefArray) to the Muons.

Cheers,
Philippe.

Thank you again. As the branches I use (two for the moment) have not the same number of entries, I created 2 trees, each containing one branch.
If I choose the first option you’ve explained, I don’t really understand in the root examples whether I must create a new tree for every tree I use in my code with TTree::AddFriend, if I must link them together with this method, or if I must create just one “Friend” tree, so I ask myself some questions about the nature of a “Friend” Tree. Moreover, must the trees created in my code have the same names of branches in order to use correctly the BuildIndex method ?
What I would like in the end is working on a simple tree containing all my branches, with different number of entries for each. I ever tried to use the TBranch::Fill method but the tree isn’t filled and I see no possibility to access the branch variables in the browser, I also tried to use the TTree::MergeTrees method with the TList::Add method to add my trees to a list, but it was not a success too.
Thanks,

Jérôme

[quote]What I would like in the end is working on a simple tree containing all my branches, with different number of entries for each. I ever tried to use the TBranch::Fill method but the tree isn’t filled and I see no possibility to access the branch variables in the browser, I also tried to use the TTree::MergeTrees method with the TList::Add method to add my trees to a list, but it was not a success too.[/quote]All the TTree tools assume(rely on) the fact that ALL branches have the same number of entries. So if indeed you can create an unbalanced TTree, you then are deciding not to use the TTree tools (Browse, MergeTTree, Draws, etc …).

[quote]What I would like in the end is working on a simple tree containing all my branches, with different number of entries for each.[/quote]Why? Are you really sure you are not actually wanting the 2nd option I described (I.e branches with the same number of entries but with more than one object per entry (and in that case the number of object per entry can be unbalanced within each entry?

[quote]If I choose the first option you’ve explained, I don’t really understand in the root examples whether I must create a new tree for every tree I use in my code with TTree::AddFriend, if I must link them together with this method, or if I must create just one “Friend” tree, so I ask myself some questions about the nature of a “Friend” Tree. [/quote]You would typically create one master TTree to which you can attach many friend TTree. You would call BuildIndex on each friend TTree. You create as many TTree as you have varying number of entries.[quote]Moreover, must the trees created in my code have the same names of branches in order to use correctly the BuildIndex method ?[/quote]Yes for the index branches …

Cheers,
Philippe.

Hi Jerome,

I may be missing what you are trying to do, but I think it’s quite easy in a single tree. You can easily have two branches, one an STL vector of Muon objects, the other a vector of LooseMuon objects. At this point, in each event, you can have different numbers of Muon and LooseMuon objects without any problem.

Is this what you are trying to do?

Cheers,
Charles

Hello,

Yes, I should try to use two vectors, one of them containing Muons, and the other one containing LooseMuons, but I don’t understand how to use them (using the class TMBMuon). This central part of my code is :

[code] if (nentries!=0)
{
TClonesArray* p20Muon = new TClonesArray(“TMBMuon”,10);
TClonesArray* p20LooseMuon = new TClonesArray(“TMBMuon”,10);

ch->SetBranchAddress(“Muon”, &p20Muon);
ch->SetBranchAddress(“LooseMuon”, &p20LooseMuon);

  for (Long64_t evtc=0;evtc<nentries;++evtc)
    {

      ch->GetBranch("Muon")->GetEntry(evtc);
     ch->GetBranch("LooseMuon")->GetEntry(evtc);
               
        Int_t nmuons=p20Muon->GetLast()+1;
      
             if (nmuons>=1)
       {
         for (int muonc=0;muonc<nmuons;++muonc)
           {
             TMBMuon* Muonc=static_cast<TMBMuon*>(p20Muon->At(muonc));

                  Muon_Pt=(*Muonc).Pt();
                 Muon_Eta=(*Muonc).Eta();
                 Muon_calEta=(*Muonc).calEta();

                   tree_Muon->Fill();
                  }
                       }


         Int_t nloosemuons=p20LooseMuon->GetLast()+1;

      if (nloosemuons>=1)
             {
                for (int loosemuonc=0;loosemuonc<nloosemuons;++loosemuonc)
                  {

              TMBMuon* LooseMuonc=static_cast<TMBMuon*>(p20LooseMuon->At(loosemuonc));

              LooseMuon_Pt=(*LooseMuonc).Pt();
              LooseMuon_Eta=(*LooseMuonc).Eta();

LooseMuon_calEta(*LooseMuonc).calEta();

               tree_LooseMuon->Fill();
            }
           }
                                                                                                                        
   }

}
[/code]

As you can see, I used two trees, but I don’t really know how to do to fill one single tree and more precisely how to catch the information of LooseMuons.

Thanks,

Jérôme

[quote]As you can see, I used two trees, [/quote]Why? In addition, it seems from the code that you are simply copying the 2 array from an existing TTree where both are in the same TTree. Is there any reason you can not do the same?

It looks like the following is ALL you need:

[code]
if (nentries != 0) {
TClonesArray* p20Muon = new TClonesArray(“TMBMuon”,10);
TClonesArray* p20LooseMuon = new TClonesArray(“TMBMuon”,10);
TBranch *b_muon;
TBranch *b_loosemuon;
ch->SetBranchAddress(“Muon”, &p20Muon, &b_muon);
ch->SetBranchAddress(“LooseMuon”, &p20LooseMuon, &b_loosemuon);

  TTree *outputTree = new TTree("mycopy","copy from TMBTree");
  outputTree->Branch("Muon",&p20Muon);
  outputTree->Branch("LooseMuon", &p20LooseMuon);

  for (Long64_t evtc=0;evtc<nentries;++evtc) 
  { 
      Long64_t localentry = chain->LoadTree(evtc);
      b_muon->GetEntry(localentry);
      b_loosemuon->GetEntry(localentry);
      outputTree->Fill();
  }
  outputTree->GetCurrentFile()->Write();

}[/code]

In the above example, this conserve the structure of TMBTree extracting just the Muons. Is there a specific reason why you have been trying to move away from the structure of the TMBTree? Keeping with it with insure that you will stay compatible with the rest of your collaboration (and give straightforward answer to your question) …

Cheers,
Philippe.

Hi,

Thank you for your answer.
The reason why I don’t get the branches of the original tree only is that I want to have some new variables (like Pt, Eta of the particles) that were not present in the first tree.
That’s why I use loops to get the information (Pt, Eta …) of each object (Muon, LooseMuon …) selected in my analysis.
In your code, I understand the principle, but I have a doubt about the TChain “chain” that you used, and, in particular, what it should contain.
Thanks,

Jérôme

[quote]but I have a doubt about the TChain “chain” that you used, and, in particular, what it should contain. [/quote]This is a typo :slight_smile: I meant ‘ch’.

Cheers,
Philippe.

Oh ok, I’m sorry.
Cheers,

Jérôme

I think there is a problem of type, that’s what I get when I try to compile my code :

no matching function for call to `TTree::SetBranchAddress(const char[5],
TClonesArray**, TBranch**)’

for this statement in the code :
ch->SetBranchAddress(“Muon”, &p20Muon, &b_muon)

When I try to write :
ch->SetBranchAddress(“Muon”, &p20Muon)

it’s ok at the compilation, but at the execution, I get a seg fault (problem with b_muon).
Cheers,

Jérôme

Hi,

You must be using an older version of ROOT :slight_smile:.
You need to use: for (Long64_t evtc=0;evtc<nentries;++evtc) { Long64_t localentry = chain->LoadTree(evtc); b_muon = ch->GetBranch("Muon"); b_loosemuon = ch->GetBranch("LooseMuon"); ...

Cheers,
Philippe.

It must be that ! Your code runs perfectly now :slight_smile:
Thank you very much,

Jérôme

The two last questions that I have are the following :

  • If you just want to work on one or several leaves of a branch of the original tree, must you use the GetLeaf method ?
  • If you want to create one or several leaves, for exemple with the Pt and the Eta of particles, how do you do to avoid using a loop on objects (for example muons and loosemuons) ?

Cheers,

Jérôme

[quote]- If you just want to work on one or several leaves of a branch of the original tree, must you use the GetLeaf method ? [/quote]No. Always use branches (but possibly sub-branches).

I don’t think you can (i.e. I would not know how to express the transformation otherwise …).

Cheers,
Philippe.

Thank you very much.

Jérôme