Re: [ROOT] Evaluating complicated expressions from the Tree

From: Rene Brun (Rene.Brun@cern.ch)
Date: Mon Nov 03 2003 - 16:04:02 MET


Miro,

Use TTreeFormula if you insist using strings.
You can create as many TTreeFormula as you want (see example in TTree::Scan)
Then in the loop on entries
 TTreeFormula *form1 = new TTreeFormula("form1",formula1, tree);
..
 TTreeFormula *formn = new TTreeFormula("formn",formulan, tree);
 for (int i=-;i<nentries;i++) {
  tree.GetEntry(i);
  double result1 = form1->EvalInstance();
  double result2 = form2->EvalInstance();
  ..
  double resultn = formn->EvalInstance();
 }

delete form1, form2,  formn;

Rene Brun

helbich@mail.desy.de wrote:
> 
>  Hi Rene,
> 
>   this is not what I want. I use SetBranchAddress etc. a lot.
> 
>  The exact application I need now is for the cross-section making class.
> This class allows user to set the Trees containing processed data and
> Monte Carlo information. User can set the data selection, kinematical
> range, variable according to which the cross-section is made
> (e.g. dsigma/d cos(Thetah) in the example below. The class contains a
> customized Fitter to get the number of signal events as well as
> Reweighting class that takes care of MC reweighting etc.
> 
>  The usage could be like:
> 
> TChain* tdat = new TChain("OutputTree_");
> tdat->AddFile("data9899rec.root",-1);
> 
> TChain* tmc = new TChain("OutputTree_");
> tmc->AddFile("mc00rec.root",-1);
> xm = new XsecMaker();
> xm->SetDataTree(tdat)
> xm->SetDataTree(tmc);
> 
> xm->SetVariable("cos(Thetah)");
> xm->SetDataSelection("(goodevent&&EIslesmax<0.2&&dis05&&HBoxCut2&&EmPz>45&&EmPz<65&&abs(vz)<50.&&sqrt(vx^2+vy^2)<0.4&&!elErr)&&KPosPt>0.2&&KNegPt>0.2");
> xm->SetKinematicRange("Q2>2&&Q2<3&&t<1");
> double bins1[] = {32,40,60,80,100};
> xm->SetBins(4,bins1);
> xm->MakeXsec();
> xm->Save("xsec.dat");
> 
>  At the end the cross-sections + info on Acceptances, purities,
> #events + other related quantities will be calculated and saved to
> ascii file.
> 
>  What I want is to avoid the parsing of the strings and evaluating it.
> For example the reweighting formula finalizes to:
> root [3] cout << rw->GetReweightFormula()
> (1)*(pow((0.593+mc_Q2)/(1.04+mc_Q2),2.3)*1e4*(1+0.84*mc_Q2/(1.0+0.123*mc_Q2))/(1+mc_Q2/0.8938)^2.779)/(1e4*(1+0.84*mc_Q2/(1.0+0.123*mc_Q2))/(1+mc_Q2/0.8938)^2.779)*(1.5/(1+mc_eps*0.462963*(mc_Q2)^0.750000 )*(sin(mc_Thetah)^2*(1+mc_eps*cos(2*mc_Psi)) + 2*mc_eps*0.462963*(mc_Q2)^0.750000*cos(mc_Thetah)^2 - sqrt(2*mc_eps*(1+mc_eps)*0.462963*(mc_Q2)^0.750000)*cos(mc_Psi)*sin(2*mc_Thetah))-3*mc_eps*cos(2*mc_Phi)*0.2*mc_t/(2.500000)*(0.500000*sin(mc_Thetah)^2+cos(mc_Thetah)^2))/(1.)
> 
>  and I can get the value for each event easily by
> tmc->Draw(rw->GetReweightFormula);
> tmc->GetV1();
> 
>  So the parsing and evaluating even such a complicated monster must
> be already implemented and used by the TTree::Draw().
> 
> What I want is to know wheter this feature is available for the users
> so that not just 3 (tmc->GetV1-3()) but any number of expression could
> be obtained for a given event.
> 
> Note that all the cuts, variables, reweighting should be able to be
> modified at will by the user - e.g cannot be hard coded.
> 
> Of course I could program it myself and evaluate this expression by
> parsing the string and replacing all the operands by the <cmath>
> functions and all the variables by the ones I obtain from the tree.
> However this would lead to a monster code and I think the repetition
> of the already written and tested code.
> 
>  I had to deal with other applications for which such a functionality
> would be useful.
> 
>   I hope this explanation would work much better.
> 
>                                 Cheers,
>                                                 Miro
> 
> Simple example:
>  Assume a class AA containing TTree fTree would have a method for calulating
> average of some expression after a given cut. The implementation would
> be simple:
> 
> double AA::GetMean(const char* expression,const char* selection) {
>   int nevents = fTree->Draw(expression,selection);
>   double sum = 0.;
>   for (int i=0;i<nevents;i++) {
>     sum += fTree->GetV1()[i];
>   }
>   return sum/ntot;
> }
> 
>  instead of getting single branches for the variables and trying to
> figure out what the value of the expression would be.
> 
>  Now imagine you want to calculate mean of 10 such expressions for
> different cuts at one pass through the Tree. How could this be done?
> 
> On Mon, 3 Nov 2003, Rene Brun wrote:
> 
> > Hi Miro,
> >
> > You should use TTree::MakeClass (or better MakeSelector) to generate a skeleton
> > code for your analysis.
> > In the Loop function (if using MakeClass), you are free to use directly
> > the class members directly in C++ with as many expressions as you like. In this
> > way you read the entries only once and for each entry you can
> > select what to read (via TBranch::SetBranchStatus) or calling TBranch::GetEntry
> > directly.
> > I suggest to have a look at $ROOTSYS/tutorials/h1analysis.C tutorial
> > with the corresponding explanations in the Users Guide.
> >
> > Rene Brun
> >
> > @mail.desy.de wrote:
> > >
> > >  Hi all,
> > >
> > >  I have the following problem:
> > >
> > >  For the purpose of my analysis I have root trees with Branches containing
> > > many leafs (all are simple floats/integers).
> > >
> > >  In order to get the cross-sections a number of (combinations of
> > > ) variables have to be extracted for different selections. These variables
> > > and cuts are passed to the class as character strings.
> > >
> > >  e.g. I need to evaluate
> > >
> > >  cos(Thetah), cos(mc_Thetah),(Q2+0.59)^2.2/(Q2+1.02)^0.2,
> > > goodevent&&BoxCut, Q2>2&&Q2<5&&t<1 etc...
> > >
> > >  There is a way to get it
> > > tree->Draw("cos(Thetah):cos(mc_Thetah)",cut1)
> > > double* var1 = tree->GetV1() // contains cos(Thetah)
> > > double* var2 = tree->GetV2() // contains cos(mc_Thetah)
> > >
> > >  However for more than 3 variables and few cuts one has to loop MANY times
> > > over the tree to get it. The I/O is the slowest operation and this is the
> > > main limit on the speed of my calculations. For this reason I would like
> > > to know if there is other way to do this
> > >
> > >  if there would be a method like  double TTree::Eval(const char*
> > > variable) or something more efficient so that one doesn't have to parse
> > > the string by every call.
> > >
> > > This would mean that after
> > > tree->GetEntry(10)
> > > var = tree->Eval("cos(Thetah)")
> > > the var would contain the value of cos(Thetah) for entry 10
> > >
> > >  This way I could do all my calculation in one loop through the data.
> > >
> > > Well, there is a way to do it if the variable is just a simple Leaf but is
> > > there anything I could use to evaluate more complicated strings?
> > >
> > > I think it must be already implemented somehow since the TTree::Draw()
> > > uses it extensively but I couldn't find it anywhere and many people around
> > > would be interested in this feature.
> > >
> > >                                 Best regards,
> > >
> > >                                         Miro
> > >
> > > Version   3.05/05       5 June 2003 for linuxsuse6
> >



This archive was generated by hypermail 2b29 : Thu Jan 01 2004 - 17:50:16 MET