Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
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 "RooFit.h"
49 #include "Riostream.h"
50 
51 #include "RooFormulaVar.h"
52 #include "RooFormulaVar.h"
53 #include "RooStreamParser.h"
54 #include "RooNLLVar.h"
55 #include "RooChi2Var.h"
56 #include "RooMsgService.h"
57 #include "RooTrace.h"
58 
59 
60 using namespace std;
61 
62 ClassImp(RooFormulaVar);
63 
64 
65 
66 ////////////////////////////////////////////////////////////////////////////////
67 /// Constructor with formula expression and list of input variables.
68 /// \param[in] name Name of the formula.
69 /// \param[in] title Title of the formula.
70 /// \param[in] formula Expression to be evaluated.
71 /// \param[in] dependents Variables that should be passed to the formula.
72 /// \param[in] checkVariables Check that all variables from `dependents` are used in the expression.
73 RooFormulaVar::RooFormulaVar(const char *name, const char *title, const char* inFormula, const RooArgList& dependents,
74  bool checkVariables) :
75  RooAbsReal(name,title),
76  _actualVars("actualVars","Variables used by formula expression",this),
77  _formExpr(inFormula)
78 {
79  _actualVars.add(dependents) ;
80 
81  if (_actualVars.getSize()==0) {
82  _value = traceEval(0);
83  } else {
84  _formula.reset(new RooFormula(GetName(), _formExpr, _actualVars, checkVariables));
85  _formExpr = _formula->formulaString().c_str();
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.
97 RooFormulaVar::RooFormulaVar(const char *name, const char *title, const RooArgList& dependents,
98  bool checkVariables) :
99  RooAbsReal(name,title),
100  _actualVars("actualVars","Variables used by formula expression",this),
101  _formExpr(title)
102 {
103  _actualVars.add(dependents) ;
104 
105  if (_actualVars.getSize()==0) {
106  _value = traceEval(0);
107  } else {
108  _formula.reset(new RooFormula(GetName(), _formExpr, _actualVars, checkVariables));
109  _formExpr = _formula->formulaString().c_str();
110  }
111 }
112 
113 
114 
115 ////////////////////////////////////////////////////////////////////////////////
116 /// Copy constructor
117 
118 RooFormulaVar::RooFormulaVar(const RooFormulaVar& other, const char* name) :
119  RooAbsReal(other, name),
120  _actualVars("actualVars",this,other._actualVars),
121  _formExpr(other._formExpr)
122 {
123  if (other._formula && other._formula->ok()) {
124  _formula.reset(new RooFormula(GetName(), _formExpr, _actualVars));
125  _formExpr = _formula->formulaString().c_str();
126  }
127 }
128 
129 
130 ////////////////////////////////////////////////////////////////////////////////
131 /// Return reference to internal RooFormula object.
132 RooFormula& RooFormulaVar::formula() const
133 {
134  if (!_formula) {
135  // After being read from file, the formula object might not exist, yet:
136  auto theFormula = new RooFormula(GetName(), _formExpr, _actualVars);
137  const_cast<std::unique_ptr<RooFormula>&>(this->_formula).reset(theFormula);
138  const_cast<TString&>(_formExpr) = _formula->formulaString().c_str();
139  }
140 
141  return *_formula;
142 }
143 
144 
145 
146 ////////////////////////////////////////////////////////////////////////////////
147 /// Calculate current value of object from internal formula
148 
149 Double_t RooFormulaVar::evaluate() const
150 {
151  return formula().eval(_lastNSet);
152 }
153 
154 
155 ////////////////////////////////////////////////////////////////////////////////
156 /// Propagate server change information to embedded RooFormula object
157 
158 Bool_t RooFormulaVar::redirectServersHook(const RooAbsCollection& newServerList, Bool_t mustReplaceAll, Bool_t nameChange, Bool_t /*isRecursive*/)
159 {
160  bool success = formula().changeDependents(newServerList,mustReplaceAll,nameChange);
161 
162  _formExpr = formula().GetTitle();
163  return success;
164 }
165 
166 
167 
168 ////////////////////////////////////////////////////////////////////////////////
169 /// Print info about this object to the specified stream.
170 
171 void RooFormulaVar::printMultiline(ostream& os, Int_t contents, Bool_t verbose, TString indent) const
172 {
173  RooAbsReal::printMultiline(os,contents,verbose,indent);
174  if(verbose) {
175  indent.Append(" ");
176  os << indent;
177  formula().printMultiline(os,contents,verbose,indent);
178  }
179 }
180 
181 
182 
183 ////////////////////////////////////////////////////////////////////////////////
184 /// Add formula expression as meta argument in printing interface
185 
186 void RooFormulaVar::printMetaArgs(ostream& os) const
187 {
188  os << "formula=\"" << _formExpr << "\" " ;
189 }
190 
191 
192 
193 
194 ////////////////////////////////////////////////////////////////////////////////
195 /// Read object contents from given stream
196 
197 Bool_t RooFormulaVar::readFromStream(istream& /*is*/, Bool_t /*compact*/, Bool_t /*verbose*/)
198 {
199  coutE(InputArguments) << "RooFormulaVar::readFromStream(" << GetName() << "): can't read" << endl ;
200  return kTRUE ;
201 }
202 
203 
204 
205 ////////////////////////////////////////////////////////////////////////////////
206 /// Write object contents to given stream
207 
208 void RooFormulaVar::writeToStream(ostream& os, Bool_t compact) const
209 {
210  if (compact) {
211  cout << getVal() << endl ;
212  } else {
213  os << GetTitle() ;
214  }
215 }
216 
217 
218 
219 ////////////////////////////////////////////////////////////////////////////////
220 /// Forward the plot sampling hint from the p.d.f. that defines the observable obs
221 
222 std::list<Double_t>* RooFormulaVar::binBoundaries(RooAbsRealLValue& obs, Double_t xlo, Double_t xhi) const
223 {
224  for (const auto par : _actualVars) {
225  auto func = static_cast<const RooAbsReal*>(par);
226  list<Double_t>* binb = nullptr;
227 
228  if (func && (binb = func->binBoundaries(obs,xlo,xhi)) ) {
229  return binb;
230  }
231  }
232 
233  return nullptr;
234 }
235 
236 
237 
238 ////////////////////////////////////////////////////////////////////////////////
239 /// Forward the plot sampling hint from the p.d.f. that defines the observable obs
240 
241 std::list<Double_t>* RooFormulaVar::plotSamplingHint(RooAbsRealLValue& obs, Double_t xlo, Double_t xhi) const
242 {
243  for (const auto par : _actualVars) {
244  auto func = dynamic_cast<const RooAbsReal*>(par);
245  list<Double_t>* hint = nullptr;
246 
247  if (func && (hint = func->plotSamplingHint(obs,xlo,xhi)) ) {
248  return hint;
249  }
250  }
251 
252  return nullptr;
253 }
254 
255 
256 
257 ////////////////////////////////////////////////////////////////////////////////
258 /// Return the default error level for MINUIT error analysis
259 /// If the formula contains one or more RooNLLVars and
260 /// no RooChi2Vars, return the defaultErrorLevel() of
261 /// RooNLLVar. If the addition contains one ore more RooChi2Vars
262 /// and no RooNLLVars, return the defaultErrorLevel() of
263 /// RooChi2Var. If the addition contains neither or both
264 /// issue a warning message and return a value of 1
265 
266 Double_t RooFormulaVar::defaultErrorLevel() const
267 {
268  RooAbsReal* nllArg(0) ;
269  RooAbsReal* chi2Arg(0) ;
270 
271  for (const auto arg : _actualVars) {
272  if (dynamic_cast<RooNLLVar*>(arg)) {
273  nllArg = (RooAbsReal*)arg ;
274  }
275  if (dynamic_cast<RooChi2Var*>(arg)) {
276  chi2Arg = (RooAbsReal*)arg ;
277  }
278  }
279 
280  if (nllArg && !chi2Arg) {
281  coutI(Minimization) << "RooFormulaVar::defaultErrorLevel(" << GetName()
282  << ") Formula contains a RooNLLVar, using its error level" << endl ;
283  return nllArg->defaultErrorLevel() ;
284  } else if (chi2Arg && !nllArg) {
285  coutI(Minimization) << "RooFormulaVar::defaultErrorLevel(" << GetName()
286  << ") Formula contains a RooChi2Var, using its error level" << endl ;
287  return chi2Arg->defaultErrorLevel() ;
288  } else if (!nllArg && !chi2Arg) {
289  coutI(Minimization) << "RooFormulaVar::defaultErrorLevel(" << GetName() << ") WARNING: "
290  << "Formula contains neither RooNLLVar nor RooChi2Var server, using default level of 1.0" << endl ;
291  } else {
292  coutI(Minimization) << "RooFormulaVar::defaultErrorLevel(" << GetName() << ") WARNING: "
293  << "Formula contains BOTH RooNLLVar and RooChi2Var server, using default level of 1.0" << endl ;
294  }
295 
296  return 1.0 ;
297 }
298 
299 
300 
301