New branch as function of existing branches

Is there a way to make a new branch (either in a new tree/file or in the existing one) as a function of old branches? That is, I want “sqrt(pow(J_psi_1S_TRUEP_E+Lambda0_TRUEP_E,2)-pow(J_psi_1S_TRUEP_X+Lambda0_TRUEP_X,2)-pow(J_psi_1S_TRUEP_Y+Lambda0_TRUEP_Y,2)-pow(J_psi_1S_TRUEP_Z+Lambda0_TRUEP_Z,2))” to exist as its own branch.

Details of my motivation:

I’m working with an invariant mass. I can do MCDecayTree->Draw("sqrt(pow(J_psi_1S_TRUEP_E+Lambda0_TRUEP_E,2)-pow(J_psi_1S_TRUEP_X+Lambda0_TRUEP_X,2)-pow(J_psi_1S_TRUEP_Y+Lambda0_TRUEP_Y,2)-pow(J_psi_1S_TRUEP_Z+Lambda0_TRUEP_Z,2))"); just fine.
I want to do an unbinned fit to this distribution. Normally, I would do this by making a RooDataSet from the tree with a RooRealVar whose name is same as the branch’s: TFile *hastree = new TFile("[path to file]/file.root", "READ"); TTree * h100 = (TTree*)hastree->Get("MCDecayTreeTuple/MCDecayTree"); RooRealVar *mass = new RooRealVar("Bs_LOKI_MASS_JpsiConstr","m(J/#psi #Lambda)",4100,6100,"MeV"); RooDataSet *data = new RooDataSet("data","1D",h100,*mass); I tried doing this by using the above string as the name of the RooRealVar, but I end up with a distribution = 0 except at one point. One resolution seems to be creating a branch with the same values as the function so I can just use the branch name instead of the function as the name of RooRealVar.

Hi,

I wonder if a simpler approach would consist in creating a dataset and adding* to it the values of the invariant mass while looping on the ttree.

Cheers,
Danilo
*
root.cern.ch/doc/master/classRo … 890da8bf1f

RooDataSet::add, nor apparently any other member function, takes a double as an argument, and there does not seem to be a convenient way to put these doubles into a RooArgSet (which RooDataSet::add would take).

Hi,

I don’t think the signature with a double precision floating point is provided too.
What can be done is to inject the information in form of a RooArgSet.

Cheers,
Danilo

Yes, but (forgive my ignorance) I don’t see how to put the double into an acceptable RooArgSet. The flow seems to be RooDataSet(RooArgSet(RooAbsArg(double))), and I don’t know how to make a double into a RooAbsArg, and I’m a little unclear on if the RooArgSet is supposed to just contain the value for a given event or if it needs more than that (the description of RooDataSet::add says something about coordinates…).

This will get you started:

RooRealVar x("myVar", "myVar", 0)
RooArgSet as(x)
RooDataSet ds("name","title",as)
for (auto i : ROOT::TSeqI(10)) {
   x.setVal(i);
   ds.add(as);
}
for (auto i : ROOT::TSeqI(ds.numEntries())) {
   ds.get(i)->Print("v");
}

Unfortunately, this gives me the same result as before: a dataset at 0 except for one point (apparently the same point, actually). I think I may really have to build a new tree. Details of the failure:

I did a makeclass on the tuple where the data is stored, then cut down the .h file to only the branches I needed. I then edited the loop in the .C file to populate a dataset:[code]void Lst_1405::Loop(RooDataSet& set)
{
if (fChain == 0) return;

Long64_t nentries = fChain->GetEntriesFast();

Long64_t nbytes = 0, nb = 0;
for (Long64_t jentry=0; jentry<nentries;jentry++) {
Long64_t ientry = LoadTree(jentry);
if (ientry < 0) break;
nb = fChain->GetEntry(jentry); nbytes += nb;
// if (Cut(ientry) < 0) continue;
RooRealVar x(“x”,“x”,sqrt(pow(J_psi_1S_TRUEP_E+Lambda0_TRUEP_E,2)-pow(J_psi_1S_TRUEP_X+Lambda0_TRUEP_X,2)-
pow(J_psi_1S_TRUEP_Y+Lambda0_TRUEP_Y,2)-pow(J_psi_1S_TRUEP_Z+Lambda0_TRUEP_Z,2)),
“MeV”);
RooArgSet inv_mass(x);
set.add(inv_mass);
}
}
[/code]Then in my fit code I include the .C file and do RooDataSet *LstMC = new RooDataSet("LstMC","1D",RooArgList(*mass)); Lst_1405 t; t.Loop(*LstMC); This results in the following distribution (generated by doing [code]root [0] RooRealVar *mass = new RooRealVar(“Bs_LOKI_MASS_JpsiConstr”,“m(J/#psi #Lambda)”,4100,6100,“MeV”);

RooFit v3.60 – Developed by Wouter Verkerke and David Kirkby
Copyright © 2000-2013 NIKHEF, University of California & Stanford University
All rights reserved, please read http://roofit.sourceforge.net/license.txt

root [1] #include “Lst_1405.C”
root [2] RooDataSet *LstMC = new RooDataSet(“LstMC”,“1D”,RooArgList(*mass));
root [3] Lst_1405 t;
root [4] t.Loop(*LstMC);
root [5] RooPlot *framex = mass->frame();
root [6] framex->GetYaxis()->SetTitle(“Events/(5 MeV)”);
root [8] LstMC->plotOn(framex)
(RooPlot *) 0x8ebb820
root [9] framex->Draw()
[/code]):


I think I must fill a tree.

Okay, it turns out filling a new tree is pretty easy. I just did the makeclass as I described above, but used the following in the definition of Loop() instead:[code]void Lst_1405::Loop()
{
if (fChain == 0) return;

Long64_t nentries = fChain->GetEntriesFast();

Long64_t nbytes = 0, nb = 0;

//create tree
TFile f("[path to file]/file.root",“RECREATE”);
TTree t(“mytree”,“mytree”);
double val;
t.Branch(“m(J/#psi #Lambda)”, &val, “mass/D”);

//fill tree
for (Long64_t jentry=0; jentry<nentries;jentry++) {
Long64_t ientry = LoadTree(jentry);
if (ientry < 0) break;
nb = fChain->GetEntry(jentry); nbytes += nb;
// if (Cut(ientry) < 0) continue;
val = sqrt(pow(J_psi_1S_TRUEP_E+Lambda0_TRUEP_E,2)-pow(J_psi_1S_TRUEP_X+Lambda0_TRUEP_X,2)-pow(J_psi_1S_TRUEP_Y+Lambda0_TRUEP_Y,2)-pow(J_psi_1S_TRUEP_Z+Lambda0_TRUEP_Z,2));
t.Fill();
}
t.Write();
}
[/code]

Hi,

the problem with your previous snippets is that you are plotting a variable different from the one you are filling. This simplified macro shows the behaviour you reported. The solution is to use the same RooRealVar instance representing the invariant mass.

Cheers,
D

void plot() {

RooRealVar *mass = new RooRealVar("Bs_LOKI_MASS_JpsiConstr","m(J/#psi #Lambda)",4100,6100,"MeV");
RooArgSet row(*mass);
RooRealVar *mass2 = new RooRealVar("Bs_LOKI_MASS_JpsiConstr2","m(J/#psi #Lambda)",4100,6100,"MeV");
RooArgSet row2(*mass2);

RooDataSet *LstMC = new RooDataSet("LstMC","1D",RooArgList(*mass));
TRandom3 rndm(1);
for (auto i : ROOT::TSeqI(1000)) {
// Uncomment to make work
//   mass->setVal(rndm.Gaus(5000,100));
//   LstMC->add(row);
// Comment to make work
   mass2->setVal(rndm.Gaus(5000,100));
   LstMC->add(row2);

}
RooPlot *framex = mass->frame();
framex->GetYaxis()->SetTitle("Events/(5 MeV)");
LstMC->plotOn(framex);
framex->Draw();

}