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.
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).
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.
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…).
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”);
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]
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();
}