How to add a branch contains more than one objects in a exit tree?

HI all,
I want to use “particles” in the root file to reconstruct “jet”. So I want to read the root file and create a new branch to contain my result, jet. The reason that I want to store them in the old file is that I want to keep the relationship of jet and event. So I write a code:

  Jet *new_jet = new Jet();
  TBranch *njt = tree->Branch("new_jet","Jet",&new_jet);

  for(Int_t entry=0; entry<allEntries; ++entry)
  {
    
    for(Int_t i=0;i<branchParticle->GetEntriesFast();++i)
    {
      particle=(GenParticle*) branchParticle->At(i);
      if(particle->Status==1)
      {
        particles.push_back(fastjet::PseudoJet(particle->Px,particle->Py,particle->Pz,particle->E));
      }
    }
        
    fastjet::ClusterSequence cs(particles, jet_def);
    std::vector<fastjet::PseudoJet> jets=fastjet::sorted_by_pt(cs.inclusive_jets(20));
  
    for (Int_t i=0; i<jets.size(); ++i)
    {
      new_jet->PT = jets[i].pt();
      new_jet->Eta = jets[i].eta();
      new_jet->Phi = jets[i].phi();
      new_jet->Mass = jets[i].m();
    }
    njt->Fill();
  }
  tree->Write();
  

I just pick the core of the code because I don’t want to confuse you with Delphes and fastjet classes.

And my question is that:

Since I don’t know how many jets I will get in each event, I write a loop. And I fill the branch in the loop. I thought all the jets can stored after tree->Write(). But in fact it’s not. It just store one jet per event ( even there are more than one jet ). Why and how can I solve it?

Hi,

a good solution is to store a vector of jets.

Cheers,
Danilo

[quote=“dpiparo”]Hi,

a good solution is to store a vector of jets.

Cheers,
Danilo[/quote]

HI Danilo,

I use,

  TClonesArray jets_array("Jet",10);
  TBranch *njt = chain->Branch("new_jet",&jets_array,64000);

  for(Int_t entry=0; entry<allEntries; ++entry)
  {
    for (Int_t i=0; i<jets.size(); ++i)
    {
      Jet *new_jet1 = new Jet();
      new_jet1->PT = jets[i].pt();
      new_jet1->Eta = jets[i].eta();
      new_jet1->Phi = jets[i].phi();
      new_jet1->Mass = jets[i].m();

      jets_array[i]=new_jet1;
    }
    njt->Fill();
    jets_array.Delete();
  }
  chain->Write()

to store the objects. But this no so good because I have to declare the “TCloneArray” length before I know the jet number. And I was extremely wired , for example , when I have 10000 events but I break the loop after run 1 events and in this events I get 2 jets, I thought in my result I should get 2 jets in the branch but in fact the code repeat the 2 jets for 10000 times.

Best,
Li

Hi Li,

why not giving a look to root.cern.ch/doc/master/hvector_8C.html ?
It is very very common to persist collections of jets in stl vectors.

Cheers,
Danilo

[quote=“dpiparo”]Hi Li,

why not giving a look to root.cern.ch/doc/master/hvector_8C.html ?
It is very very common to persist collections of jets in stl vectors.

Cheers,
Danilo[/quote]

Hi Danilo,

Thanks a lot !

Best,
Li

[quote=“dpiparo”]Hi Li,

why not giving a look to root.cern.ch/doc/master/hvector_8C.html ?
It is very very common to persist collections of jets in stl vectors.

Cheers,
Danilo[/quote]

Hi Danilo,

Trying your example, I changed it to a general c++ code, with:

#include <vector>
#include "TFile.h"
#include "TTree.h"
#include "TCanvas.h"
#include "TFrame.h"
#include "TH1F.h"
#include "TBenchmark.h"
#include "TRandom.h"
#include "TSystem.h"
#include "TROOT.h"
#include "TLorentzVector.h"

int main()
{
   gROOT->ProcessLine("#include <vector>");
   TFile *f = TFile::Open("hvector.root","RECREATE");
   if (!f) { return 0; }
   // Create one histograms
   TH1F *hpx = new TH1F("hpx","This is the px distribution",100,-4,4);
   hpx->SetFillColor(48);
   std::vector<float> vpx;
   std::vector<float> vpy;
   std::vector<float> vpz;
   std::vector<float> vrand;
   std::vector<TLorentzVector> vec;
   // Create a TTree
   TTree *t = new TTree("tvec","Tree with vectors");
   t->Branch("vpx",&vpx);
   t->Branch("vpy",&vpy);
   t->Branch("vpz",&vpz);
   t->Branch("vrand",&vrand);
   t->Branch("vec",&vec);

   // Create a new canvas.
   TCanvas *c1 = new TCanvas("c1","Dynamic Filling Example",200,10,700,500);
   gRandom->SetSeed();
   const Int_t kUPDATE = 1000;
   for (Int_t i = 0; i < 25000; i++) {
      Int_t npx = (Int_t)(gRandom->Rndm(1)*15);
      vpx.clear();
      vpy.clear();
      vpz.clear();
      vrand.clear();
      for (Int_t j = 0; j < npx; ++j) {
         Float_t px,py,pz;
         gRandom->Rannor(px,py);
         pz = px*px + py*py;
         Float_t random = gRandom->Rndm(1);
         hpx->Fill(px);
         vpx.emplace_back(px);
         vpy.emplace_back(py);
         vpz.emplace_back(pz);
         vrand.emplace_back(random);
      }
      if (i && (i%kUPDATE) == 0) {
         if (i == kUPDATE) hpx->Draw();
         c1->Modified();
         c1->Update();
         if (gSystem->ProcessEvents())
            break;
      }
      t->Fill();
   }
   f->Write();
   delete f;
  
   return 0;
}

And I use commands to compile it, successfully,

g++ write.cxx -std=c++11 `root-config --cflags --libs`

But when running it, there is errors,


Error in <TTree::Branch>: The pointer specified for vec is not of a class or type known to ROOT

You can see it works for

vector < float >

But for

\vector <TLorentzVector> 

it doesn’t work.

Do you know why? I use ROOT 5 and I use mac.
Can you help me solve this error?

Best,
Li

Hi Li,

there are several ways of tackling this.
Probably the simplest is to generate the dictionary on the fly. Add at the beginning of your code the line:

 gInterpreter->GenerateDictionary("vector<TLorentzVector>","TLorentzVector.h;vector");

the include file providing gInterpreter is TInterpreter.h.

Note that this technique works for a single class. If you want to scale to a full datamodel it’s probably much better to create the dictionary separately with rootcling/genreflex and then link it together with the rest of the code.

Cheers,
D

[quote=“dpiparo”]Hi Li,

there are several ways of tackling this.
Probably the simplest is to generate the dictionary on the fly. Add at the beginning of your code the line:

 gInterpreter->GenerateDictionary("vector<TLorentzVector>","TLorentzVector.h;vector");

the include file providing gInterpreter is TInterpreter.h.

Note that this technique works for a single class. If you want to scale to a full datamodel it’s probably much better to create the dictionary separately with rootcling/genreflex and then link it together with the rest of the code.

Cheers,
D[/quote]

Hi, Danilo
Tring adding this code, there is a error,

lis-MacBook-Pro:test_folder li$ g++ write.cxx -std=c++11 `root-config --cflags --libs`
lis-MacBook-Pro:test_folder li$ ./a.out 
In file included from /Users/li/work/test_folder/AutoDict_vector_TLorentzVector__cxx_ACLiC_dict.cxx:17:
In file included from /Users/li/work/test_folder/AutoDict_vector_TLorentzVector__cxx_ACLiC_dict.h:34:
/Users/li/work/test_folder/AutoDict_vector_TLorentzVector_.cxx:1:10: fatal error: 
      'vector.h' file not found
#include "vector.h"
         ^
1 error generated.
clang: error: no such file or directory: '/Users/li/work/test_folder/AutoDict_vector_TLorentzVector__cxx_ACLiC_dict.o'
Error in <ACLiC>: Compilation failed!
Error in <TTree::Branch>: The pointer specified for vec is not of a class or type known to ROOT

Best,
Li

Hi,

I tried it on ROOT6 and also 5.34/36 on linux and it works. What version do you have on mac?
D

[quote=“dpiparo”]Hi,

I tried it on ROOT6 and also 5.34/36 on linux and it works. What version do you have on mac?
D[/quote]

Hi, Danilo,

I use version 10.11.4 (15E65) and

lis-MacBook-Pro:test_folder li$ g++ --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 7.3.0 (clang-703.0.31)
Target: x86_64-apple-darwin15.4.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

Best,
Li

Hi Li,

sorry I meant what root version :slight_smile:

D

[quote=“dpiparo”]Hi Li,

sorry I meant what root version :slight_smile:

D[/quote]

Hi Danilo,

Haha, the same version with you… ROOT 5.34/36 .

Best,
Li

I am not sure then we ran the same thing.
What happens if you open a prompt and you type:

 gInterpreter->GenerateDictionary("vector<TLorentzVector>","TLorentzVector.h;vector");

[quote=“dpiparo”]I am not sure then we ran the same thing.
What happens if you open a prompt and you type:

gInterpreter->GenerateDictionary("vector<TLorentzVector>","TLorentzVector.h;vector"); [/quote]

Hi Danilo,

The result is:

lis-MacBook-Pro:~ li$ root -l
root [0]  gInterpreter->GenerateDictionary("vector<TLorentzVector>","TLorentzVector.h;vector")
(Int_t)0
root [1] 

And as my last error information said

lis-MacBook-Pro:test_folder li$ g++ write.cxx -std=c++11 `root-config --cflags --libs`
lis-MacBook-Pro:test_folder li$ ./a.out 
In file included from /Users/li/work/test_folder/AutoDict_vector_TLorentzVector__cxx_ACLiC_dict.cxx:17:
In file included from /Users/li/work/test_folder/AutoDict_vector_TLorentzVector__cxx_ACLiC_dict.h:34:
/Users/li/work/test_folder/AutoDict_vector_TLorentzVector_.cxx:1:10: fatal error: 
      'vector.h' file not found
#include "vector.h"
         ^
1 error generated.
clang: error: no such file or directory: '/Users/li/work/test_folder/AutoDict_vector_TLorentzVector__cxx_ACLiC_dict.o'
Error in <ACLiC>: Compilation failed!
Error in <TTree::Branch>: The pointer specified for vec is not of a class or type known to ROOT

I find the file “AutoDict_vector_TLorentzVector__cxx_ACLiC_dict.cxx” and changed

to

Then it works well.
So the problem should be there. I guess that include “xxx.h” and include is different when finding head files (In my previous experience, I never find a case that they are different…).

Best,
Li

Hi Li,

so in your case the line in the interpreter works but if you compile an executable containing only that line it does not work?

Cheers,
D

[quote=“dpiparo”]Hi Li,

so in your case the line in the interpreter works but if you compile an executable containing only that line it does not work?

Cheers,
D[/quote]

Hi Danilo,
Yes, and I guess the reason is that it generate files like “AutoDict_random_access_iterator_TLorentzVector_long_.cxx” contains include “vector.h” but, in fact except for standard library of C++, many compiles can’t recognize this. It can only recognize include .

Best,
Li

Hi,

so what you are experiencing is a different behaviour of the interpreted and compiled code, right? Just tried both on standard Scientific Linux and had no problem.
If the answer to the above after trying is yes, another question: can you move to ROOT6?

Cheers,
Danilo

[quote=“dpiparo”]Hi,

so what you are experiencing is a different behaviour of the interpreted and compiled code, right? Just tried both on standard Scientific Linux and had no problem.
If the answer to the above after trying is yes, another question: can you move to ROOT6?

Cheers,
Danilo[/quote]

Hi Danilo,
yes, I guess the problem is some compiles cant read “vector.h” since it’s a old style and the standard way is but some compiles are nicer.

Since I don’t have Linux with me, so I can’t try it. But I find that even I delete all the compilation files and recompile it again. In this file : AutoDict_vector_TLorentzVector_.cxx is produced automatically but now it can produce a good version now. It seems ROOT have “memory”…It use:

#include "vector"

instead of

#include "vector.h"

But I don’t know why.

Then I tried ROOT 6 and of course it works.

Best,
Li

Hi Li,

so also for ROOT5, can we consider the issue closed? I understand you had some remnants around which prevented you to pick up the latest changes.
As for ROOT6: it’s not an obligation to move but ROOT5 is in bugfixmode. The new 6 series is actively developed and provides tons of new features which may really boost your productivity.

Cheers,
Danilo

[quote=“dpiparo”]Hi Li,

so also for ROOT5, can we consider the issue closed? I understand you had some remnants around which prevented you to pick up the latest changes.
As for ROOT6: it’s not an obligation to move but ROOT5 is in bugfixmode. The new 6 series is actively developed and provides tons of new features which may really boost your productivity.

Cheers,
Danilo[/quote]

Hi Danilo,
It’s closed and thanks for suggestions. I find the point may be that I don’t know basic compile knowledge so I can’t understand some errors. I will try it!

Best,
Li