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::ostream, std::istream, std::list;
62
63
65
70
71////////////////////////////////////////////////////////////////////////////////
72/// Constructor with formula expression and list of input variables.
73/// \param[in] name Name of the formula.
74/// \param[in] title Title of the formula.
75/// \param[in] inFormula Expression to be evaluated.
76/// \param[in] dependents Variables that should be passed to the formula.
77/// \param[in] checkVariables Check that all variables from `dependents` are used in the expression.
78RooFormulaVar::RooFormulaVar(const char *name, const char *title, const char* inFormula, const RooArgList& dependents,
79 bool checkVariables) :
80 RooAbsReal(name,title),
81 _actualVars("actualVars","Variables used by formula expression",this),
82 _formExpr(inFormula)
83{
84 if (dependents.empty()) {
85 _value = traceEval(nullptr);
86 } else {
88 _formExpr = _formula->formulaString().c_str();
89 _actualVars.add(_formula->actualDependents());
90 }
91}
92
93
94
95////////////////////////////////////////////////////////////////////////////////
96/// Constructor with formula expression, title and list of input variables.
97/// \param[in] name Name of the formula.
98/// \param[in] title Formula expression. Will also be used as the title.
99/// \param[in] dependents Variables that should be passed to the formula.
100/// \param[in] checkVariables Check that all variables from `dependents` are used in the expression.
101RooFormulaVar::RooFormulaVar(const char *name, const char *title, const RooArgList& dependents,
102 bool checkVariables) :
103 RooAbsReal(name,title),
104 _actualVars("actualVars","Variables used by formula expression",this),
105 _formExpr(title)
106{
107 if (dependents.empty()) {
108 _value = traceEval(nullptr);
109 } else {
111 _formExpr = _formula->formulaString().c_str();
112 _actualVars.add(_formula->actualDependents());
113 }
114}
115
116
117
118////////////////////////////////////////////////////////////////////////////////
119/// Copy constructor
120
123 _actualVars("actualVars",this,other._actualVars),
124 _formExpr(other._formExpr)
125{
126 if (other._formula && other._formula->ok()) {
127 _formula = new RooFormula(*other._formula);
128 _formExpr = _formula->formulaString().c_str();
129 }
130}
131
132
133////////////////////////////////////////////////////////////////////////////////
134/// Return reference to internal RooFormula object.
135/// If it doesn't exist, create it on the fly.
137{
138 if (!_formula) {
139 // After being read from file, the formula object might not exist, yet:
141 const_cast<TString&>(_formExpr) = _formula->formulaString().c_str();
142 }
143
144 return *_formula;
145}
146
147
148bool RooFormulaVar::ok() const { return getFormula().ok() ; }
149
150
151void RooFormulaVar::dumpFormula() { getFormula().printMultiline(std::cout, 0) ; }
152
153
154////////////////////////////////////////////////////////////////////////////////
155/// Calculate current value of object from internal formula
156
158{
159 return getFormula().eval(_actualVars.nset());
160}
161
162
164{
165 getFormula().doEval(_actualVars, ctx);
166}
167
168
169////////////////////////////////////////////////////////////////////////////////
170/// Propagate server change information to embedded RooFormula object
171
179
180
181
182////////////////////////////////////////////////////////////////////////////////
183/// Print info about this object to the specified stream.
184
185void RooFormulaVar::printMultiline(ostream& os, Int_t contents, bool verbose, TString indent) const
186{
187 RooAbsReal::printMultiline(os,contents,verbose,indent);
188 if(verbose) {
189 indent.Append(" ");
190 os << indent;
191 getFormula().printMultiline(os,contents,verbose,indent);
192 }
193}
194
195
196
197////////////////////////////////////////////////////////////////////////////////
198/// Add formula expression as meta argument in printing interface
199
200void RooFormulaVar::printMetaArgs(ostream& os) const
201{
202 os << "formula=\"" << _formExpr << "\" " ;
203}
204
205
206
207
208////////////////////////////////////////////////////////////////////////////////
209/// Read object contents from given stream
210
211bool RooFormulaVar::readFromStream(istream& /*is*/, bool /*compact*/, bool /*verbose*/)
212{
213 coutE(InputArguments) << "RooFormulaVar::readFromStream(" << GetName() << "): can't read" << std::endl ;
214 return true ;
215}
216
217
218
219////////////////////////////////////////////////////////////////////////////////
220/// Write object contents to given stream
221
222void RooFormulaVar::writeToStream(ostream& os, bool compact) const
223{
224 if (compact) {
225 std::cout << getVal() << std::endl ;
226 } else {
227 os << GetTitle() ;
228 }
229}
230
231
232
233////////////////////////////////////////////////////////////////////////////////
234/// Forward the plot sampling hint from the p.d.f. that defines the observable obs
235
236std::list<double>* RooFormulaVar::binBoundaries(RooAbsRealLValue& obs, double xlo, double xhi) const
237{
238 for (const auto par : _actualVars) {
239 auto func = static_cast<const RooAbsReal*>(par);
240 list<double>* binb = nullptr;
241
242 if (func && (binb = func->binBoundaries(obs,xlo,xhi)) ) {
243 return binb;
244 }
245 }
246
247 return nullptr;
248}
249
250
251
252////////////////////////////////////////////////////////////////////////////////
253/// Forward the plot sampling hint from the p.d.f. that defines the observable obs
254
255std::list<double>* RooFormulaVar::plotSamplingHint(RooAbsRealLValue& obs, double xlo, double xhi) const
256{
257 for (const auto par : _actualVars) {
258 auto func = dynamic_cast<const RooAbsReal*>(par);
259 list<double>* hint = nullptr;
260
261 if (func && (hint = func->plotSamplingHint(obs,xlo,xhi)) ) {
262 return hint;
263 }
264 }
265
266 return nullptr;
267}
268
269
270
271////////////////////////////////////////////////////////////////////////////////
272/// Return the default error level for MINUIT error analysis
273/// If the formula contains one or more RooNLLVars and
274/// no RooChi2Vars, return the defaultErrorLevel() of
275/// RooNLLVar. If the addition contains one ore more RooChi2Vars
276/// and no RooNLLVars, return the defaultErrorLevel() of
277/// RooChi2Var. If the addition contains neither or both
278/// issue a warning message and return a value of 1
279
281{
282 RooAbsReal* nllArg(nullptr) ;
283 RooAbsReal* chi2Arg(nullptr) ;
284
285#ifdef ROOFIT_LEGACY_EVAL_BACKEND
286 for (const auto arg : _actualVars) {
287 if (dynamic_cast<RooNLLVar*>(arg)) {
288 nllArg = static_cast<RooAbsReal*>(arg) ;
289 }
290 if (dynamic_cast<RooChi2Var*>(arg)) {
291 chi2Arg = static_cast<RooAbsReal*>(arg) ;
292 }
293 }
294#endif
295
296 if (nllArg && !chi2Arg) {
297 coutI(Minimization) << "RooFormulaVar::defaultErrorLevel(" << GetName()
298 << ") Formula contains a RooNLLVar, using its error level" << std::endl ;
299 return nllArg->defaultErrorLevel() ;
300 } else if (chi2Arg && !nllArg) {
301 coutI(Minimization) << "RooFormulaVar::defaultErrorLevel(" << GetName()
302 << ") Formula contains a RooChi2Var, using its error level" << std::endl ;
303 return chi2Arg->defaultErrorLevel() ;
304 } else if (!nllArg && !chi2Arg) {
305 coutI(Minimization) << "RooFormulaVar::defaultErrorLevel(" << GetName() << ") WARNING: "
306 << "Formula contains neither RooNLLVar nor RooChi2Var server, using default level of 1.0" << std::endl ;
307 } else {
308 coutI(Minimization) << "RooFormulaVar::defaultErrorLevel(" << GetName() << ") WARNING: "
309 << "Formula contains BOTH RooNLLVar and RooChi2Var server, using default level of 1.0" << std::endl ;
310 }
311
312 return 1.0 ;
313}
314
316{
317 return getFormula().getTFormula()->GetUniqueFuncName().Data();
318}
319
320std::unique_ptr<RooAbsArg>
322{
323 // Some users exploit unnormalized RooAbsPdfs as inputs for RooFormulaVars,
324 // relying on what the pdf returns from RooAbsPdf::evaluate(). This is in
325 // principle not allowed because every pdf needs to be evaluated with a
326 // normalization set, but it's so common in user code that we need to
327 // support it. To make this work, we need to make sure that the no
328 // normalization over non-dependents is happening at this point, reducing
329 // the normalization set to the subset of actual dependents.
330 // See also the "PdfAsFunctionInFormulaVar" test in testRooAbsPdf.
333 auto newArg = std::unique_ptr<RooAbsArg>{static_cast<RooAbsArg *>(Clone())};
336 return newArg;
337}
#define coutI(a)
#define coutE(a)
static void indent(ostringstream &buf, int indent_level)
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
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:76
RooFit::OwningPtr< RooArgSet > getObservables(const RooArgSet &set, bool valueOnly=true) const
Given a set of possible observables, return the observables that this PDF depends on.
TObject * Clone(const char *newname=nullptr) const override
Make a clone of an object using the Streamer facility.
Definition RooAbsArg.h:88
Abstract container object that can hold multiple RooAbsArg objects.
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:63
double getVal(const RooArgSet *normalisationSet=nullptr) const
Evaluate object.
Definition RooAbsReal.h:107
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:539
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
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Definition RooArgSet.h:24
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...
void markAsCompiled(RooAbsArg &arg) const
void compileServers(RooAbsArg &arg, RooArgSet const &normSet)
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.
double defaultErrorLevel() const override
Return the default error level for MINUIT error analysis If the formula contains one or more RooNLLVa...
std::unique_ptr< RooAbsArg > compileForNormSet(RooArgSet const &normSet, RooFit::Detail::CompileContext &ctx) const override
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.
std::string getUniqueFuncName() const
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.
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
const char * GetTitle() const override
Returns title of object.
Definition TNamed.h:50
Basic string class.
Definition TString.h:138