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///
24/// If RooAbsPdf objects are supplied to RooFormulaVar as servers, their
25/// raw (unnormalized) values will be evaluated. Use RooGenericPdf, which
26/// constructs generic PDF functions, to access their properly normalized
27/// values.
28///
29/// The string expression can be any valid TFormula expression referring to the
30/// listed servers either by name or by their ordinal list position. These three are
31/// equivalent:
32/// ```
33/// RooFormulaVar("gen", "x*y", RooArgList(x,y)) // reference by name
34/// RooFormulaVar("gen", "@0*@1", RooArgList(x,y)) // reference by ordinal with @
35/// RooFormulaVar("gen", "x[0]*x[1]", RooArgList(x,y)) // TFormula-builtin reference by ordinal
36/// ```
37/// Note that `x[i]` is an expression reserved for TFormula. All variable references
38/// are automatically converted to the TFormula-native format. If a variable with
39/// the name `x` is given, `x[i]` is interpreted as a list position,
40/// but `x` without brackets as the name of a RooFit object.
41///
42/// The last two versions, while slightly less readable, are more versatile because
43/// the names of the arguments are not hard coded.
44///
45
46#include "RooFormulaVar.h"
47#include "RooStreamParser.h"
48#include "RooMsgService.h"
49#include "RooFormulaUtils.h"
50#include "RooAbsRealLValue.h"
51
52#include "TFormula.h"
53
54#ifdef ROOFIT_LEGACY_EVAL_BACKEND
55#include "RooNLLVar.h"
56#include "RooChi2Var.h"
57#endif
58
59#include <iostream>
60#include <list>
61
62using std::ostream, std::istream, std::list;
63
64
66
68
69////////////////////////////////////////////////////////////////////////////////
70/// Constructor with formula expression and list of input variables.
71/// \param[in] name Name of the formula.
72/// \param[in] title Title of the formula.
73/// \param[in] inFormula Expression to be evaluated.
74/// \param[in] dependents Variables that should be passed to the formula.
75/// \param[in] checkVariables Unused parameter.
76RooFormulaVar::RooFormulaVar(const char *name, const char *title, const char* inFormula, const RooArgList& dependents,
77 bool /*checkVariables*/) :
78 RooAbsReal(name,title),
79 _actualVars("actualVars","Variables used by formula expression",this),
80 _formExpr(inFormula)
81{
82 if (dependents.empty()) {
83 _value = traceEval(nullptr);
84 } else {
85 RooFormulaUtils::initFormula(_evaluator, _formExpr, _actualVars, dependents, GetName());
86 }
87}
88
89
90
91////////////////////////////////////////////////////////////////////////////////
92/// Constructor with formula expression, title and list of input variables.
93/// \param[in] name Name of the formula.
94/// \param[in] title Formula expression. Will also be used as the title.
95/// \param[in] dependents Variables that should be passed to the formula.
96/// \param[in] checkVariables Check that all variables from `dependents` are used in the expression.
97RooFormulaVar::RooFormulaVar(const char *name, const char *title, const RooArgList &dependents, bool checkVariables)
98 : RooFormulaVar(name, title, title, dependents, checkVariables)
99{
100}
101
102////////////////////////////////////////////////////////////////////////////////
103/// Copy constructor
104
107 _actualVars("actualVars",this,other._actualVars),
108 _formExpr(other._formExpr)
109{
110 _binnings = RooFormulaUtils::cloneBinnings(other._binnings);
111 if (other._evaluator) {
112 _evaluator = RooFormulaUtils::cloneEvaluator(*other._evaluator, GetName());
113 }
114}
115
116////////////////////////////////////////////////////////////////////////////////
117/// Return reference to the formula evaluation engine.
118/// If it doesn't exist, create it on the fly. Throws if the formula is invalid.
120{
121 return RooFormulaUtils::ensureEvaluator(_evaluator, const_cast<TString &>(_formExpr), _actualVars, GetName());
122}
123
125{
126 evaluator();
127 return true;
128}
129
131{
132 RooFormulaUtils::printFormula(std::cout, "", _formExpr.Data(), _actualVars);
133}
134
135////////////////////////////////////////////////////////////////////////////////
136/// Calculate current value of object from internal formula
137
139{
140 return RooFormulaUtils::evalFormula(evaluator(), _actualVars, _actualVars.nset());
141}
142
143
145{
146 RooFormulaUtils::doEvalFormula(evaluator(), _actualVars, ctx);
147}
148
149////////////////////////////////////////////////////////////////////////////////
150/// Print info about this object to the specified stream.
151
152void RooFormulaVar::printMultiline(ostream& os, Int_t contents, bool verbose, TString indent) const
153{
154 RooAbsReal::printMultiline(os,contents,verbose,indent);
155 if(verbose) {
156 indent.Append(" ");
157 os << indent;
158 RooFormulaUtils::printFormula(os, indent, _formExpr.Data(), _actualVars);
159 }
160}
161
162
163
164////////////////////////////////////////////////////////////////////////////////
165/// Add formula expression as meta argument in printing interface
166
167void RooFormulaVar::printMetaArgs(ostream& os) const
168{
169 os << "formula=\"" << _formExpr << "\" " ;
170}
171
172
173
174
175////////////////////////////////////////////////////////////////////////////////
176/// Read object contents from given stream
177
178bool RooFormulaVar::readFromStream(istream& /*is*/, bool /*compact*/, bool /*verbose*/)
179{
180 coutE(InputArguments) << "RooFormulaVar::readFromStream(" << GetName() << "): can't read" << std::endl ;
181 return true ;
182}
183
184
185
186////////////////////////////////////////////////////////////////////////////////
187/// Write object contents to given stream
188
189void RooFormulaVar::writeToStream(ostream& os, bool compact) const
190{
191 if (compact) {
192 std::cout << getVal() << std::endl ;
193 } else {
194 os << GetTitle() ;
195 }
196}
197
198////////////////////////////////////////////////////////////////////////////////
199/// Declare that this function is piecewise constant (flat) within the bins of
200/// the given `binning` of the observable `obs`, which must be one of the formula
201/// variables. The method can be called several times to set a binning for more
202/// than one observable. See RooGenericPdf::setBinning() for details.
203
205{
206 RooFormulaUtils::setBinning(_binnings, *this, _actualVars, _formExpr.Data(), obs, binning, checkFlatness);
207}
208
209////////////////////////////////////////////////////////////////////////////////
210/// Return the binning previously declared with setBinning() for observable
211/// `obs`, or nullptr if no binning was declared. This reports only binnings
212/// owned by this formula, not binning hints forwarded by its servers.
213
215{
216 return RooFormulaUtils::getBinning(_binnings, _actualVars, obs);
217}
218
219////////////////////////////////////////////////////////////////////////////////
220/// Remove a binning previously declared with setBinning() for observable `obs`,
221/// reverting to the generic numeric integrator for it. Returns true if a binning
222/// was removed, false if none was set for `obs`.
223
225{
226 return _binnings.erase(_actualVars.index(obs.GetName())) > 0;
227}
228
229////////////////////////////////////////////////////////////////////////////////
230/// Return true if a binning was set with setBinning() for every
231/// observable in the integration set `obs`.
232
234{
235 return RooFormulaUtils::isBinnedDistribution(_binnings, _actualVars, obs);
236}
237
238////////////////////////////////////////////////////////////////////////////////
239/// Return the boundaries of the binning set with setBinning() that fall
240/// within [xlo, xhi]. If no binning was set for this observable, forward the bin
241/// boundaries from the server that defines the observable obs.
242
243std::list<double>* RooFormulaVar::binBoundaries(RooAbsRealLValue& obs, double xlo, double xhi) const
244{
245 if (auto *hint = RooFormulaUtils::binBoundaries(_binnings, _actualVars, obs, xlo, xhi)) {
246 return hint;
247 }
248
249 for (const auto par : _actualVars) {
250 auto func = static_cast<const RooAbsReal*>(par);
251 list<double>* binb = nullptr;
252
253 if (func && (binb = func->binBoundaries(obs,xlo,xhi)) ) {
254 return binb;
255 }
256 }
257
258 return nullptr;
259}
260
261////////////////////////////////////////////////////////////////////////////////
262/// Return sampling hints that draw the piecewise-flat shape exactly if a binning
263/// was set for this observable. Otherwise, forward the plot sampling hint from
264/// the server that defines the observable obs.
265
266std::list<double>* RooFormulaVar::plotSamplingHint(RooAbsRealLValue& obs, double xlo, double xhi) const
267{
268 if (auto *hint = RooFormulaUtils::plotSamplingHint(_binnings, _actualVars, obs, xlo, xhi)) {
269 return hint;
270 }
271
272 for (const auto par : _actualVars) {
273 auto func = dynamic_cast<const RooAbsReal*>(par);
274 list<double>* hint = nullptr;
275
276 if (func && (hint = func->plotSamplingHint(obs,xlo,xhi)) ) {
277 return hint;
278 }
279 }
280
281 return nullptr;
282}
283
284
285
286////////////////////////////////////////////////////////////////////////////////
287/// Return the default error level for MINUIT error analysis
288/// If the formula contains one or more RooNLLVars and
289/// no RooChi2Vars, return the defaultErrorLevel() of
290/// RooNLLVar. If the addition contains one ore more RooChi2Vars
291/// and no RooNLLVars, return the defaultErrorLevel() of
292/// RooChi2Var. If the addition contains neither or both
293/// issue a warning message and return a value of 1
294
296{
297 RooAbsReal* nllArg(nullptr) ;
298 RooAbsReal* chi2Arg(nullptr) ;
299
300#ifdef ROOFIT_LEGACY_EVAL_BACKEND
301 for (const auto arg : _actualVars) {
302 if (dynamic_cast<RooNLLVar*>(arg)) {
303 nllArg = static_cast<RooAbsReal*>(arg) ;
304 }
305 if (dynamic_cast<RooChi2Var*>(arg)) {
306 chi2Arg = static_cast<RooAbsReal*>(arg) ;
307 }
308 }
309#endif
310
311 if (nllArg && !chi2Arg) {
312 coutI(Minimization) << "RooFormulaVar::defaultErrorLevel(" << GetName()
313 << ") Formula contains a RooNLLVar, using its error level" << std::endl ;
314 return nllArg->defaultErrorLevel() ;
315 } else if (chi2Arg && !nllArg) {
316 coutI(Minimization) << "RooFormulaVar::defaultErrorLevel(" << GetName()
317 << ") Formula contains a RooChi2Var, using its error level" << std::endl ;
318 return chi2Arg->defaultErrorLevel() ;
319 } else if (!nllArg && !chi2Arg) {
320 coutI(Minimization) << "RooFormulaVar::defaultErrorLevel(" << GetName() << ") WARNING: "
321 << "Formula contains neither RooNLLVar nor RooChi2Var server, using default level of 1.0" << std::endl ;
322 } else {
323 coutI(Minimization) << "RooFormulaVar::defaultErrorLevel(" << GetName() << ") WARNING: "
324 << "Formula contains BOTH RooNLLVar and RooChi2Var server, using default level of 1.0" << std::endl ;
325 }
326
327 return 1.0 ;
328}
329
331{
332 return evaluator().getTFormula()->GetUniqueFuncName().Data();
333}
334
335std::unique_ptr<RooAbsArg>
337{
338 // Some users exploit unnormalized RooAbsPdfs as inputs for RooFormulaVars,
339 // relying on what the pdf returns from RooAbsPdf::evaluate(). This is in
340 // principle not allowed because every pdf needs to be evaluated with a
341 // normalization set, but it's so common in user code that we need to
342 // support it. To make this work, we need to make sure that the no
343 // normalization over non-dependents is happening at this point, reducing
344 // the normalization set to the subset of actual dependents.
345 // See also the "PdfAsFunctionInFormulaVar" test in testRooAbsPdf.
348 auto newArg = std::unique_ptr<RooAbsArg>{static_cast<RooAbsArg *>(Clone())};
349 ctx.markAsCompiled(*newArg);
350 ctx.compileServers(*newArg, depList);
351 return newArg;
352}
#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:142
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 base class for RooRealVar binning definitions.
Int_t index(const RooAbsArg *arg) const
Returns index of given arg, or -1 if arg is not in the collection.
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.
double _value
Cache for current value of object.
Definition RooAbsReal.h:541
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
A RooFormulaVar is a generic implementation of a real-valued object, which takes a RooArgList of serv...
~RooFormulaVar() override
std::map< int, std::unique_ptr< RooAbsBinning > > _binnings
User-defined binnings, keyed by the observable's index in _actualVars, for a piecewise-flat distribut...
RooListProxy _actualVars
Actual parameters used by formula engine.
std::list< double > * binBoundaries(RooAbsRealLValue &obs, double xlo, double xhi) const override
Return the boundaries of the binning set with setBinning() that fall within [xlo, xhi].
bool isBinnedDistribution(const RooArgSet &obs) const override
Return true if a binning was set with setBinning() for every observable in the integration set obs.
void doEval(RooFit::EvalContext &ctx) const override
Base function for computing multiple values of a RooAbsReal.
void dumpFormula()
Dump the formula to stdout.
RooFormulaEvaluator & evaluator() const
Return reference to the formula evaluation engine.
double defaultErrorLevel() const override
Return the default error level for MINUIT error analysis If the formula contains one or more RooNLLVa...
std::unique_ptr< RooFormulaEvaluator > _evaluator
! Formula evaluation engine
std::unique_ptr< RooAbsArg > compileForNormSet(RooArgSet const &normSet, RooFit::Detail::CompileContext &ctx) const override
std::list< double > * plotSamplingHint(RooAbsRealLValue &obs, double xlo, double xhi) const override
Return sampling hints that draw the piecewise-flat shape exactly if a binning was set for this observ...
void setBinning(const RooAbsRealLValue &obs, const RooAbsBinning &binning, bool checkFlatness=true)
Declare that this function is piecewise constant (flat) within the bins of the given binning of the o...
bool ok() const
const RooArgList & dependents() const
bool removeBinning(const RooAbsRealLValue &obs)
Remove a binning previously declared with setBinning() for observable obs, reverting to the generic n...
bool readFromStream(std::istream &is, bool compact, bool verbose=false) override
Read object contents from given stream.
const RooAbsBinning * getBinning(const RooAbsRealLValue &obs) const
Return the binning previously declared with setBinning() for observable obs, or nullptr if no binning...
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.
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:137
const char * Data() const
Definition TString.h:385