Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RooFormulaVar.cxx
Go to the documentation of this file.
1/*****************************************************************************
2 * Project: RooFit *
3 * Package: RooFitCore *
4 * @(#)root/roofitcore:$Id$
5 * Authors: *
6 * WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu *
7 * DK, David Kirkby, UC Irvine, dkirkby@uci.edu *
8 * *
9 * Copyright (c) 2000-2005, Regents of the University of California *
10 * and Stanford University. All rights reserved. *
11 * *
12 * Redistribution and use in source and binary forms, *
13 * with or without modification, are permitted according to the terms *
14 * listed in LICENSE (http://roofit.sourceforge.net/license.txt) *
15 *****************************************************************************/
16
17//////////////////////////////////////////////////////////////////////////////
18/// \class RooFormulaVar
19///
20/// A RooFormulaVar is a generic implementation of a real-valued object,
21/// which takes a RooArgList of servers and a C++ expression string defining how
22/// its value should be calculated from the given list of servers.
23/// RooFormulaVar uses a RooFormula object to perform the expression evaluation.
24///
25/// If RooAbsPdf objects are supplied to RooFormulaVar as servers, their
26/// raw (unnormalized) values will be evaluated. Use RooGenericPdf, which
27/// constructs generic PDF functions, to access their properly normalized
28/// values.
29///
30/// The string expression can be any valid TFormula expression referring to the
31/// listed servers either by name or by their ordinal list position. These three are
32/// equivalent:
33/// ```
34/// RooFormulaVar("gen", "x*y", RooArgList(x,y)) // reference by name
35/// RooFormulaVar("gen", "@0*@1", RooArgList(x,y)) // reference by ordinal with @
36/// RooFormulaVar("gen", "x[0]*x[1]", RooArgList(x,y)) // TFormula-builtin reference by ordinal
37/// ```
38/// Note that `x[i]` is an expression reserved for TFormula. All variable references
39/// are automatically converted to the TFormula-native format. If a variable with
40/// the name `x` is given, the RooFormula interprets `x[i]` as a list position,
41/// but `x` without brackets as the name of a RooFit object.
42///
43/// The last two versions, while slightly less readable, are more versatile because
44/// the names of the arguments are not hard coded.
45///
46
47
48#include "Riostream.h"
49
50#include "RooFormulaVar.h"
51#include "RooStreamParser.h"
52#include "RooMsgService.h"
53#include "RooTrace.h"
54#include "RooFormula.h"
55
56#ifdef ROOFIT_LEGACY_EVAL_BACKEND
57#include "RooNLLVar.h"
58#include "RooChi2Var.h"
59#endif
60
61using std::cout,std::endl, std::ostream, std::istream, std::list;
62
64
66
68{
69 if(_formula) delete _formula;
70}
71
72////////////////////////////////////////////////////////////////////////////////
73/// Constructor with formula expression and list of input variables.
74/// \param[in] name Name of the formula.
75/// \param[in] title Title of the formula.
76/// \param[in] inFormula Expression to be evaluated.
77/// \param[in] dependents Variables that should be passed to the formula.
78/// \param[in] checkVariables Check that all variables from `dependents` are used in the expression.
79RooFormulaVar::RooFormulaVar(const char *name, const char *title, const char* inFormula, const RooArgList& dependents,
80 bool checkVariables) :
81 RooAbsReal(name,title),
82 _actualVars("actualVars","Variables used by formula expression",this),
83 _formExpr(inFormula)
84{
85 if (dependents.empty()) {
86 _value = traceEval(nullptr);
87 } else {
88 _formula = new RooFormula(GetName(), _formExpr, dependents, checkVariables);
89 _formExpr = _formula->formulaString().c_str();
91 }
92}
93
94
95
96////////////////////////////////////////////////////////////////////////////////
97/// Constructor with formula expression, title and list of input variables.
98/// \param[in] name Name of the formula.
99/// \param[in] title Formula expression. Will also be used as the title.
100/// \param[in] dependents Variables that should be passed to the formula.
101/// \param[in] checkVariables Check that all variables from `dependents` are used in the expression.
102RooFormulaVar::RooFormulaVar(const char *name, const char *title, const RooArgList& dependents,
103 bool checkVariables) :
104 RooAbsReal(name,title),
105 _actualVars("actualVars","Variables used by formula expression",this),
106 _formExpr(title)
107{
108 if (dependents.empty()) {
109 _value = traceEval(nullptr);
110 } else {
111 _formula = new RooFormula(GetName(), _formExpr, dependents, checkVariables);
112 _formExpr = _formula->formulaString().c_str();
114 }
115}
116
117
118
119////////////////////////////////////////////////////////////////////////////////
120/// Copy constructor
121
123 RooAbsReal(other, name),
124 _actualVars("actualVars",this,other._actualVars),
125 _formExpr(other._formExpr)
126{
127 if (other._formula && other._formula->ok()) {
128 _formula = new RooFormula(*other._formula);
129 _formExpr = _formula->formulaString().c_str();
130 }
131}
132
133
134////////////////////////////////////////////////////////////////////////////////
135/// Return reference to internal RooFormula object.
136/// If it doesn't exist, create it on the fly.
138{
139 if (!_formula) {
140 // After being read from file, the formula object might not exist, yet:
142 const_cast<TString&>(_formExpr) = _formula->formulaString().c_str();
143 }
144
145 return *_formula;
146}
147
148
149bool RooFormulaVar::ok() const { return getFormula().ok() ; }
150
151
153
154
155////////////////////////////////////////////////////////////////////////////////
156/// Calculate current value of object from internal formula
157
159{
160 return getFormula().eval(_actualVars.nset());
161}
162
163
165{
166 getFormula().doEval(ctx);
167}
168
169
170////////////////////////////////////////////////////////////////////////////////
171/// Propagate server change information to embedded RooFormula object
172
173bool RooFormulaVar::redirectServersHook(const RooAbsCollection& newServerList, bool mustReplaceAll, bool nameChange, bool isRecursive)
174{
175 bool error = getFormula().changeDependents(newServerList,mustReplaceAll,nameChange);
176
178 return error || RooAbsReal::redirectServersHook(newServerList, mustReplaceAll, nameChange, isRecursive);
179}
180
181
182
183////////////////////////////////////////////////////////////////////////////////
184/// Print info about this object to the specified stream.
185
186void RooFormulaVar::printMultiline(ostream& os, Int_t contents, bool verbose, TString indent) const
187{
188 RooAbsReal::printMultiline(os,contents,verbose,indent);
189 if(verbose) {
190 indent.Append(" ");
191 os << indent;
192 getFormula().printMultiline(os,contents,verbose,indent);
193 }
194}
195
196
197
198////////////////////////////////////////////////////////////////////////////////
199/// Add formula expression as meta argument in printing interface
200
201void RooFormulaVar::printMetaArgs(ostream& os) const
202{
203 os << "formula=\"" << _formExpr << "\" " ;
204}
205
206
207
208
209////////////////////////////////////////////////////////////////////////////////
210/// Read object contents from given stream
211
212bool RooFormulaVar::readFromStream(istream& /*is*/, bool /*compact*/, bool /*verbose*/)
213{
214 coutE(InputArguments) << "RooFormulaVar::readFromStream(" << GetName() << "): can't read" << endl ;
215 return true ;
216}
217
218
219
220////////////////////////////////////////////////////////////////////////////////
221/// Write object contents to given stream
222
223void RooFormulaVar::writeToStream(ostream& os, bool compact) const
224{
225 if (compact) {
226 cout << getVal() << endl ;
227 } else {
228 os << GetTitle() ;
229 }
230}
231
232
233
234////////////////////////////////////////////////////////////////////////////////
235/// Forward the plot sampling hint from the p.d.f. that defines the observable obs
236
237std::list<double>* RooFormulaVar::binBoundaries(RooAbsRealLValue& obs, double xlo, double xhi) const
238{
239 for (const auto par : _actualVars) {
240 auto func = static_cast<const RooAbsReal*>(par);
241 list<double>* binb = nullptr;
242
243 if (func && (binb = func->binBoundaries(obs,xlo,xhi)) ) {
244 return binb;
245 }
246 }
247
248 return nullptr;
249}
250
251
252
253////////////////////////////////////////////////////////////////////////////////
254/// Forward the plot sampling hint from the p.d.f. that defines the observable obs
255
256std::list<double>* RooFormulaVar::plotSamplingHint(RooAbsRealLValue& obs, double xlo, double xhi) const
257{
258 for (const auto par : _actualVars) {
259 auto func = dynamic_cast<const RooAbsReal*>(par);
260 list<double>* hint = nullptr;
261
262 if (func && (hint = func->plotSamplingHint(obs,xlo,xhi)) ) {
263 return hint;
264 }
265 }
266
267 return nullptr;
268}
269
270
271
272////////////////////////////////////////////////////////////////////////////////
273/// Return the default error level for MINUIT error analysis
274/// If the formula contains one or more RooNLLVars and
275/// no RooChi2Vars, return the defaultErrorLevel() of
276/// RooNLLVar. If the addition contains one ore more RooChi2Vars
277/// and no RooNLLVars, return the defaultErrorLevel() of
278/// RooChi2Var. If the addition contains neither or both
279/// issue a warning message and return a value of 1
280
282{
283 RooAbsReal* nllArg(nullptr) ;
284 RooAbsReal* chi2Arg(nullptr) ;
285
286#ifdef ROOFIT_LEGACY_EVAL_BACKEND
287 for (const auto arg : _actualVars) {
288 if (dynamic_cast<RooNLLVar*>(arg)) {
289 nllArg = static_cast<RooAbsReal*>(arg) ;
290 }
291 if (dynamic_cast<RooChi2Var*>(arg)) {
292 chi2Arg = static_cast<RooAbsReal*>(arg) ;
293 }
294 }
295#endif
296
297 if (nllArg && !chi2Arg) {
298 coutI(Minimization) << "RooFormulaVar::defaultErrorLevel(" << GetName()
299 << ") Formula contains a RooNLLVar, using its error level" << endl ;
300 return nllArg->defaultErrorLevel() ;
301 } else if (chi2Arg && !nllArg) {
302 coutI(Minimization) << "RooFormulaVar::defaultErrorLevel(" << GetName()
303 << ") Formula contains a RooChi2Var, using its error level" << endl ;
304 return chi2Arg->defaultErrorLevel() ;
305 } else if (!nllArg && !chi2Arg) {
306 coutI(Minimization) << "RooFormulaVar::defaultErrorLevel(" << GetName() << ") WARNING: "
307 << "Formula contains neither RooNLLVar nor RooChi2Var server, using default level of 1.0" << endl ;
308 } else {
309 coutI(Minimization) << "RooFormulaVar::defaultErrorLevel(" << GetName() << ") WARNING: "
310 << "Formula contains BOTH RooNLLVar and RooChi2Var server, using default level of 1.0" << endl ;
311 }
312
313 return 1.0 ;
314}
315
317{
318 // If the number of elements to sum is less than 3, just build a sum expression.
319 // Otherwise build a loop to sum over the values.
320 unsigned int eleSize = _actualVars.size();
321 std::string className = GetName();
322 std::string varName = "elements" + className;
323 std::string sumName = "sum" + className;
324 std::string code;
325 std::string decl = "double " + varName + "[" + std::to_string(eleSize) + "]{";
326 int idx = 0;
327 for (RooAbsArg *it : _actualVars) {
328 decl += ctx.getResult(*it) + ",";
329 ctx.addResult(it, varName + "[" + std::to_string(idx) + "]");
330 idx++;
331 }
332 decl.back() = '}';
333 code += decl + ";\n";
334
335 ctx.addResult(this, (_formula->getTFormula()->GetUniqueFuncName() + "(" + varName + ")").Data());
336
337 ctx.addToCodeBody(this, code);
338}
339
340
341
#define coutI(a)
#define coutE(a)
#define ClassImp(name)
Definition Rtypes.h:377
static void indent(ostringstream &buf, int indent_level)
char name[80]
Definition TGX11.cxx:110
Common abstract base class for objects that represent a value and a "shape" in RooFit.
Definition RooAbsArg.h:77
Abstract container object that can hold multiple RooAbsArg objects.
Storage_t::size_type size() const
const RooArgSet * nset() const
Definition RooAbsProxy.h:52
Abstract base class for objects that represent a real value that may appear on the left hand side of ...
Abstract base class for objects that represent a real value and implements functionality common to al...
Definition RooAbsReal.h:59
double getVal(const RooArgSet *normalisationSet=nullptr) const
Evaluate object.
Definition RooAbsReal.h:103
virtual double defaultErrorLevel() const
Definition RooAbsReal.h:248
void printMultiline(std::ostream &os, Int_t contents, bool verbose=false, TString indent="") const override
Structure printing.
bool redirectServersHook(const RooAbsCollection &newServerList, bool mustReplaceAll, bool nameChange, bool isRecursiveStep) override
Function that is called at the end of redirectServers().
double _value
Cache for current value of object.
Definition RooAbsReal.h:543
double traceEval(const RooArgSet *set) const
Calculate current value of object, with error tracing wrapper.
RooArgList is a container object that can hold multiple RooAbsArg objects.
Definition RooArgList.h:22
Simple calculation from a binned dataset and a PDF.
Definition RooChi2Var.h:50
bool add(const RooAbsArg &var, bool valueServer, bool shapeServer, bool silent)
Overloaded RooCollection_t::add() method insert object into set and registers object as server to own...
A class to maintain the context for squashing of RooFit models into code.
void addResult(RooAbsArg const *key, std::string const &value)
A function to save an expression that includes/depends on the result of the input node.
void addToCodeBody(RooAbsArg const *klass, std::string const &in)
Adds the input string to the squashed code body.
std::string const & getResult(RooAbsArg const &arg)
Gets the result for the given node using the node name.
A RooFormulaVar is a generic implementation of a real-valued object, which takes a RooArgList of serv...
~RooFormulaVar() override
RooListProxy _actualVars
Actual parameters used by formula engine.
RooFormula & getFormula() const
Return reference to internal RooFormula object.
RooFormula * _formula
! Formula engine
void doEval(RooFit::EvalContext &ctx) const override
Base function for computing multiple values of a RooAbsReal.
void dumpFormula()
Dump the formula to stdout.
void translate(RooFit::Detail::CodeSquashContext &ctx) const override
This function defines a translation for each RooAbsReal based object that can be used to express the ...
double defaultErrorLevel() const override
Return the default error level for MINUIT error analysis If the formula contains one or more RooNLLVa...
bool redirectServersHook(const RooAbsCollection &newServerList, bool mustReplaceAll, bool nameChange, bool isRecursive) override
Propagate server change information to embedded RooFormula object.
bool ok() const
const RooArgList & dependents() const
std::list< double > * binBoundaries(RooAbsRealLValue &, double, double) const override
Forward the plot sampling hint from the p.d.f. that defines the observable obs.
bool readFromStream(std::istream &is, bool compact, bool verbose=false) override
Read object contents from given stream.
TString _formExpr
Formula expression string.
void printMultiline(std::ostream &os, Int_t contents, bool verbose=false, TString indent="") const override
Print info about this object to the specified stream.
double evaluate() const override
Calculate current value of object from internal formula.
void writeToStream(std::ostream &os, bool compact) const override
Write object contents to given stream.
void printMetaArgs(std::ostream &os) const override
Add formula expression as meta argument in printing interface.
std::list< double > * plotSamplingHint(RooAbsRealLValue &, double, double) const override
Forward the plot sampling hint from the p.d.f. that defines the observable obs.
Internally uses ROOT's TFormula to compute user-defined expressions of RooAbsArgs.
Definition RooFormula.h:27
TFormula * getTFormula() const
Definition RooFormula.h:72
std::string formulaString() const
Definition RooFormula.h:71
void printMultiline(std::ostream &os, Int_t contents, bool verbose=false, TString indent="") const override
Printing interface.
RooArgSet actualDependents() const
Return list of arguments which are used in the formula.
Definition RooFormula.h:39
bool ok() const
Definition RooFormula.h:50
void dump() const
DEBUG: Dump state information.
double eval(const RooArgSet *nset=nullptr) const
Evaluate all parameters/observables, and then evaluate formula.
bool changeDependents(const RooAbsCollection &newDeps, bool mustReplaceAll, bool nameChange)
Change used variables to those with the same name in given list.
void doEval(RooFit::EvalContext &) const
Implements a -log(likelihood) calculation from a dataset and a PDF.
Definition RooNLLVar.h:50
TString GetUniqueFuncName() const
Definition TFormula.h:253
const char * GetName() const override
Returns name of object.
Definition TNamed.h:47
const char * GetTitle() const override
Returns title of object.
Definition TNamed.h:48
Basic string class.
Definition TString.h:139