Logo ROOT  
Reference Guide
RooFormula.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 \file RooFormula.cxx
19 \class RooFormula
20 \ingroup Roofitcore
21 
22 RooFormula internally uses ROOT's TFormula to compute user-defined expressions
23 of RooAbsArgs.
24 
25 The string expression can be any valid TFormula expression referring to the
26 listed servers either by name or by their ordinal list position. These three are
27 forms equivalent:
28 ```
29  RooFormula("formula", "x*y", RooArgList(x,y)) or
30  RooFormula("formula", "@0*@1", RooArgList(x,y))
31  RooFormula("formula", "x[0]*x[1]", RooArgList(x,y))
32 ```
33 Note that `x[i]` is an expression reserved for TFormula. If a variable with
34 the name `x` is given, the RooFormula interprets `x` as a variable name,
35 but `x[i]` as an index in the list of variables.
36 
37 ### Category expressions
38 State information of RooAbsCategories can be accessed using the '::' operator,
39 *i.e.*, `tagCat::Kaon` will resolve to the numerical value of
40 the `Kaon` state of the RooAbsCategory object named `tagCat`.
41 
42 A formula to switch between lepton categories could look like this:
43 ```
44  RooFormula("formulaWithCat",
45  "x * (leptonMulti == leptonMulti::one) + y * (leptonMulti == leptonMulti::two)",
46  RooArgList(x, y, leptonMulti));
47 ```
48 
49 ### Debugging a formula that won't compile
50 When the formula is preprocessed, RooFit can print information in the debug stream.
51 These can be retrieved by activating the RooFit::MsgLevel `RooFit::DEBUG`
52 and the RooFit::MsgTopic `RooFit::InputArguments`.
53 Check the tutorial rf506_msgservice.C for details.
54 **/
55 
56 #include "RooFormula.h"
57 
58 #include "RooFit.h"
59 #include "RooAbsReal.h"
60 #include "RooAbsCategory.h"
61 #include "RooArgList.h"
62 #include "RooMsgService.h"
63 #include "RooBatchCompute.h"
64 
65 #include "ROOT/RMakeUnique.hxx"
66 #include "TObjString.h"
67 #include "TClass.h"
68 
69 #include <sstream>
70 #include <regex>
71 
72 using namespace std;
73 
75 
76 namespace {
77 
78 ////////////////////////////////////////////////////////////////////////////////
79 /// Find all input arguments which are categories, and save this information in
80 /// with the names of the variables that are being used to evaluate it.
81 std::vector<bool> findCategoryServers(const RooAbsCollection& collection) {
82  std::vector<bool> output;
83  output.reserve(collection.size());
84 
85  for (unsigned int i = 0; i < collection.size(); ++i) {
86  output.push_back(collection[i]->InheritsFrom(RooAbsCategory::Class()));
87  }
88 
89  return output;
90 }
91 
92 }
93 
94 ////////////////////////////////////////////////////////////////////////////////
95 /// Default constructor
96 /// coverity[UNINIT_CTOR]
97 
99 {
100 }
101 
102 
103 ////////////////////////////////////////////////////////////////////////////////
104 /// Construct a new formula.
105 /// \param[in] name Name of the formula.
106 /// \param[in] formula Formula to be evaluated. Parameters/observables are identified by name
107 /// or ordinal position in `varList`.
108 /// \param[in] varList List of variables to be passed to the formula.
109 /// \param[in] checkVariables Check that the variables being passed in the `varList` are used in
110 /// the formula expression.
111 RooFormula::RooFormula(const char* name, const char* formula, const RooArgList& varList,
112  bool checkVariables) :
113  TNamed(name, formula), _tFormula{nullptr}
114 {
115  _origList.add(varList);
116  _isCategory = findCategoryServers(_origList);
117 
118  installFormulaOrThrow(formula);
119 
120  RooArgList useList = usedVariables();
121  if (checkVariables && _origList.size() != useList.size()) {
122  coutI(InputArguments) << "The formula " << GetName() << " claims to use the variables " << _origList
123  << " but only " << useList << " seem to be in use."
124  << "\n inputs: " << formula << std::endl;
125  }
126 }
127 
128 
129 
130 ////////////////////////////////////////////////////////////////////////////////
131 /// Copy constructor
132 RooFormula::RooFormula(const RooFormula& other, const char* name) :
133  TNamed(name ? name : other.GetName(), other.GetTitle()), RooPrintable(other)
134 {
135  _origList.add(other._origList);
136  _isCategory = findCategoryServers(_origList);
137 
138  TFormula* newTF = nullptr;
139  if (other._tFormula) {
140  newTF = new TFormula(*other._tFormula);
141  newTF->SetName(GetName());
142  }
143 
144  _tFormula.reset(newTF);
145 }
146 
147 #ifndef _MSC_VER
148 #if !defined(__GNUC__) || defined(__clang__) || (__GNUC__ > 4) || ( __GNUC__ == 4 && __GNUC_MINOR__ > 8)
149 #define ROOFORMULA_HAVE_STD_REGEX
150 ////////////////////////////////////////////////////////////////////////////////
151 /// Process given formula by replacing all ordinal and name references by
152 /// `x[i]`, where `i` matches the position of the argument in `_origList`.
153 /// Further, references to category states such as `leptonMulti:one` are replaced
154 /// by the category index.
155 std::string RooFormula::processFormula(std::string formula) const {
156 
157  cxcoutD(InputArguments) << "Preprocessing formula step 1: find category tags (catName::catState) in "
158  << formula << endl;
159 
160  // Step 1: Find all category tags and the corresponding index numbers
161  std::regex categoryReg("(\\w+)::(\\w+)");
162  std::map<std::string, int> categoryStates;
163  for (sregex_iterator matchIt = sregex_iterator(formula.begin(), formula.end(), categoryReg);
164  matchIt != sregex_iterator(); ++matchIt) {
165  assert(matchIt->size() == 3);
166  const std::string fullMatch = (*matchIt)[0];
167  const std::string catName = (*matchIt)[1];
168  const std::string catState = (*matchIt)[2];
169 
170  const auto catVariable = dynamic_cast<const RooAbsCategory*>(_origList.find(catName.c_str()));
171  if (!catVariable) {
172  cxcoutD(InputArguments) << "Formula " << GetName() << " uses '::' to reference a category state as '" << fullMatch
173  << "' but a category '" << catName << "' cannot be found in the input variables." << endl;
174  continue;
175  }
176 
177  if (!catVariable->hasLabel(catState)) {
178  coutE(InputArguments) << "Formula " << GetName() << " uses '::' to reference a category state as '" << fullMatch
179  << "' but the category '" << catName << "' does not seem to have the state '" << catState << "'." << endl;
180  throw std::invalid_argument(formula);
181  }
182  const int catNum = catVariable->lookupIndex(catState);
183 
184  categoryStates[fullMatch] = catNum;
185  cxcoutD(InputArguments) << "\n\t" << fullMatch << "\tname=" << catName << "\tstate=" << catState << "=" << catNum;
186  }
187  cxcoutD(InputArguments) << "-- End of category tags --"<< endl;
188 
189  // Step 2: Replace all category tags
190  for (const auto& catState : categoryStates) {
191  std::stringstream replacement;
192  replacement << catState.second;
193  formula = std::regex_replace(formula, std::regex(catState.first), replacement.str());
194  }
195 
196  cxcoutD(InputArguments) << "Preprocessing formula step 2: replace category tags\n\t" << formula << endl;
197 
198  // Step 3: Convert `@i`-style references to `x[i]`
199  std::regex ordinalRegex("@([0-9]+)");
200  formula = std::regex_replace(formula, ordinalRegex, "x[$1]");
201 
202  cxcoutD(InputArguments) << "Preprocessing formula step 3: replace '@'-references\n\t" << formula << endl;
203 
204  // Step 4: Replace all named references with "x[i]"-style
205  for (unsigned int i = 0; i < _origList.size(); ++i) {
206  const auto& var = _origList[i];
207  auto regex = std::string{"\\b"} + var.GetName();
208  regex = std::regex_replace(regex, std::regex("([\\[\\]\\{\\}])"), "\\$1"); // The name might contain [, ], {, or }.
209  regex += "\\b(?!\\[)"; // Veto '[' as next character. If the variable is called `x`, this might otherwise replace `x[0]`.
210  std::regex findParameterRegex(regex);
211 
212  std::stringstream replacement;
213  replacement << "x[" << i << "]";
214  formula = std::regex_replace(formula, findParameterRegex, replacement.str());
215 
216  cxcoutD(InputArguments) << "Preprocessing formula step 4: replace named references: "
217  << var.GetName() << " --> " << replacement.str()
218  << "\n\t" << formula << endl;
219  }
220 
221  cxcoutD(InputArguments) << "Final formula:\n\t" << formula << endl;
222 
223  return formula;
224 }
225 
226 
227 ////////////////////////////////////////////////////////////////////////////////
228 /// Analyse internal formula to find out which variables are actually in use.
230  RooArgList useList;
231  if (_tFormula == nullptr)
232  return useList;
233 
234  const std::string formula(_tFormula->GetTitle());
235 
236  std::set<unsigned int> matchedOrdinals;
237  std::regex newOrdinalRegex("\\bx\\[([0-9]+)\\]");
238  for (sregex_iterator matchIt = sregex_iterator(formula.begin(), formula.end(), newOrdinalRegex);
239  matchIt != sregex_iterator(); ++matchIt) {
240  assert(matchIt->size() == 2);
241  std::stringstream matchString((*matchIt)[1]);
242  unsigned int i;
243  matchString >> i;
244 
245  matchedOrdinals.insert(i);
246  }
247 
248  for (unsigned int i : matchedOrdinals) {
249  useList.add(_origList[i]);
250  }
251 
252  return useList;
253 }
254 
255 
256 ////////////////////////////////////////////////////////////////////////////////
257 /// From the internal representation, construct a formula by replacing all index place holders
258 /// with the names of the variables that are being used to evaluate it.
259 std::string RooFormula::reconstructFormula(std::string internalRepr) const {
260  for (unsigned int i = 0; i < _origList.size(); ++i) {
261  const auto& var = _origList[i];
262  std::stringstream regexStr;
263  regexStr << "x\\[" << i << "\\]|@" << i;
264  std::regex regex(regexStr.str());
265 
266  std::string replacement = std::string("[") + var.GetName() + "]";
267  internalRepr = std::regex_replace(internalRepr, regex, replacement);
268  }
269 
270  return internalRepr;
271 }
272 #endif //GCC < 4.9 Check
273 #endif //_MSC_VER
274 
275 
276 
277 
278 ////////////////////////////////////////////////////////////////////////////////
279 /// Recompile formula with new expression. In case of error, the old formula is
280 /// retained.
281 Bool_t RooFormula::reCompile(const char* newFormula)
282 {
283  try {
284  installFormulaOrThrow(newFormula);
285  } catch (std::runtime_error& e) {
286  coutE(InputArguments) << __func__ << ": new equation doesn't compile, formula unchanged."
287  << "\n" << e.what() << endl;
288  return true;
289  }
290 
291  SetTitle(newFormula);
292  return false;
293 }
294 
295 void RooFormula::dump() const
296 {
297  printMultiline(std::cout, 0);
298 }
299 
300 
301 ////////////////////////////////////////////////////////////////////////////////
302 /// Change used variables to those with the same name in given list.
303 /// \param[in] newDeps New dependents to replace the old ones.
304 /// \param[in] mustReplaceAll Will yield an error if one dependent does not have a replacement.
305 /// \param[in] nameChange Passed down to RooAbsArg::findNewServer(const RooAbsCollection&, Bool_t) const.
306 Bool_t RooFormula::changeDependents(const RooAbsCollection& newDeps, Bool_t mustReplaceAll, Bool_t nameChange)
307 {
308  //Change current servers to new servers with the same name given in list
309  bool errorStat = false;
310 
311  for (const auto arg : _origList) {
312  RooAbsReal* replace = (RooAbsReal*) arg->findNewServer(newDeps,nameChange) ;
313  if (replace) {
314  _origList.replace(*arg, *replace);
315 
316  if (arg->getStringAttribute("origName")) {
317  replace->setStringAttribute("origName",arg->getStringAttribute("origName")) ;
318  } else {
319  replace->setStringAttribute("origName",arg->GetName()) ;
320  }
321 
322  } else if (mustReplaceAll) {
323  coutE(LinkStateMgmt) << __func__ << ": cannot find replacement for " << arg->GetName() << endl;
324  errorStat = true;
325  }
326  }
327 
328  _isCategory = findCategoryServers(_origList);
329 
330  return errorStat;
331 }
332 
333 
334 
335 ////////////////////////////////////////////////////////////////////////////////
336 /// Evaluate the internal TFormula.
337 ///
338 /// First, all variables serving this instance are evaluated given the normalisation set,
339 /// and then the formula is evaluated.
340 /// \param[in] nset Normalisation set passed to evaluation of arguments serving values.
341 /// \return The result of the evaluation.
343 {
344  if (!_tFormula) {
345  coutF(Eval) << __func__ << " (" << GetName() << "): Formula didn't compile: " << GetTitle() << endl;
346  std::string what = "Formula ";
347  what += GetTitle();
348  what += " didn't compile.";
349  throw std::runtime_error(what);
350  }
351 
352  std::vector<double> pars;
353  pars.reserve(_origList.size());
354  for (unsigned int i = 0; i < _origList.size(); ++i) {
355  if (_isCategory[i]) {
356  const auto& cat = static_cast<RooAbsCategory&>(_origList[i]);
357  pars.push_back(cat.getCurrentIndex());
358  } else {
359  const auto& real = static_cast<RooAbsReal&>(_origList[i]);
360  pars.push_back(real.getVal(nset));
361  }
362  }
363 
364  return _tFormula->EvalPar(pars.data());
365 }
366 
367 
369  if (!_tFormula) {
370  coutF(Eval) << __func__ << " (" << GetName() << "): Formula didn't compile: " << GetTitle() << endl;
371  std::string what = "Formula ";
372  what += GetTitle();
373  what += " didn't compile.";
374  throw std::runtime_error(what);
375  }
376 
377  std::vector<RooBatchCompute::BracketAdapterWithMask> valueAdapters;
378  std::vector<RooSpan<const double>> inputSpans;
379  size_t nData=1;
380  for (const auto arg : _origList) {
381  auto realArg = static_cast<const RooAbsReal*>(arg);
382  auto batch = realArg->getValues(inputData, nset);
383  assert(!batch.empty());
384  nData = std::max(nData, batch.size());
385  valueAdapters.emplace_back(batch[0], batch);
386  inputSpans.push_back(std::move(batch));
387  }
388 
389  auto output = inputData.makeBatch(dataOwner, nData);
390  std::vector<double> pars(_origList.size());
391 
392 
393  for (std::size_t i=0; i < nData; ++i) {
394  for (unsigned int j=0; j < _origList.size(); ++j) {
395  if (_isCategory[j]) {
396  // TODO: As long as category states cannot be passed in the RunContext,
397  // the current state has to be used.
398  const auto& cat = static_cast<RooAbsCategory&>(_origList[j]);
399  pars[j] = cat.getCurrentIndex();
400  } else {
401  pars[j] = valueAdapters[j][i];
402  }
403  }
404 
405  output[i] = _tFormula->EvalPar(pars.data());
406  }
407 
408  return output;
409 }
410 
411 ////////////////////////////////////////////////////////////////////////////////
412 /// Printing interface
413 
414 void RooFormula::printMultiline(ostream& os, Int_t /*contents*/, Bool_t /*verbose*/, TString indent) const
415 {
416  os << indent << "--- RooFormula ---" << endl;
417  os << indent << " Formula: '" << GetTitle() << "'" << endl;
418  os << indent << " Interpretation: '" << reconstructFormula(GetTitle()) << "'" << endl;
419  indent.Append(" ");
420  os << indent << "Servers: " << _origList << "\n";
421  os << indent << "In use : " << actualDependents() << endl;
422 }
423 
424 
425 ////////////////////////////////////////////////////////////////////////////////
426 /// Print value of formula
427 
428 void RooFormula::printValue(ostream& os) const
429 {
430  os << const_cast<RooFormula*>(this)->eval(0) ;
431 }
432 
433 
434 ////////////////////////////////////////////////////////////////////////////////
435 /// Print name of formula
436 
437 void RooFormula::printName(ostream& os) const
438 {
439  os << GetName() ;
440 }
441 
442 
443 ////////////////////////////////////////////////////////////////////////////////
444 /// Print title of formula
445 
446 void RooFormula::printTitle(ostream& os) const
447 {
448  os << GetTitle() ;
449 }
450 
451 
452 ////////////////////////////////////////////////////////////////////////////////
453 /// Print class name of formula
454 
455 void RooFormula::printClassName(ostream& os) const
456 {
457  os << IsA()->GetName() ;
458 }
459 
460 
461 ////////////////////////////////////////////////////////////////////////////////
462 /// Print arguments of formula, i.e. dependents that are actually used
463 
464 void RooFormula::printArgs(ostream& os) const
465 {
466  os << "[ actualVars=";
467  for (const auto arg : usedVariables()) {
468  os << " " << arg->GetName();
469  }
470  os << " ]";
471 }
472 
473 
474 ////////////////////////////////////////////////////////////////////////////////
475 /// Check that the formula compiles, and also fulfills the assumptions.
476 ///
477 void RooFormula::installFormulaOrThrow(const std::string& formula) {
478  const std::string processedFormula = processFormula(formula);
479 
480  cxcoutD(InputArguments) << "RooFormula '" << GetName() << "' will be compiled as "
481  << "\n\t" << processedFormula
482  << "\n and used as"
483  << "\n\t" << reconstructFormula(processedFormula)
484  << "\n with the parameters " << _origList << endl;
485 
486  auto theFormula = std::make_unique<TFormula>(GetName(), processedFormula.c_str(), false);
487 
488  if (!theFormula || !theFormula->IsValid()) {
489  std::stringstream msg;
490  msg << "RooFormula '" << GetName() << "' did not compile or is invalid."
491  << "\nInput:\n\t" << formula
492  << "\nPassed over to TFormula:\n\t" << processedFormula << std::endl;
493  coutF(InputArguments) << msg.str();
494  throw std::runtime_error(msg.str());
495  }
496 
497  if (theFormula && theFormula->GetNdim() != 1) {
498  // TFormula thinks that we have a multi-dimensional formula, e.g. with variables x,y,z,t.
499  // We have to check now that this is not the case, as RooFit only uses the syntax x[0], x[1], x[2], ...
500  bool haveProblem = false;
501  std::stringstream msg;
502  msg << "TFormula interprets the formula " << formula << " as " << theFormula->GetNdim() << "-dimensional with the variable(s) {";
503  for (int i=1; i < theFormula->GetNdim(); ++i) {
504  const TString varName = theFormula->GetVarName(i);
505  if (varName.BeginsWith("x[") && varName[varName.Length()-1] == ']')
506  continue;
507 
508  haveProblem = true;
509  msg << theFormula->GetVarName(i) << ",";
510  }
511  if (haveProblem) {
512  msg << "}, which could not be supplied by RooFit."
513  << "\nThe formula must be modified, or those variables must be supplied in the list of variables." << std::endl;
514  coutF(InputArguments) << msg.str();
515  throw std::invalid_argument(msg.str());
516  }
517  }
518 
519  _tFormula = std::move(theFormula);
520 }
521 
522 
523 #ifndef ROOFORMULA_HAVE_STD_REGEX
524 /*
525  * g++ 4.8 doesn't support the std::regex. It has headers, but no implementations of the standard, leading to linker
526  * errors. As long as centos 7 needs to be supported, this forces us to have a legacy implementation.
527  */
528 
529 #include "TPRegexp.h"
530 
531 ////////////////////////////////////////////////////////////////////////////////
532 /// Process given formula by replacing all ordinal and name references by
533 /// `x[i]`, where `i` matches the position of the argument in `_origList`.
534 /// Further, references to category states such as `leptonMulti:one` are replaced
535 /// by the category index.
536 std::string RooFormula::processFormula(std::string formula) const {
537  TString formulaTString = formula.c_str();
538 
539  cxcoutD(InputArguments) << "Preprocessing formula step 1: find category tags (catName::catState) in "
540  << formulaTString.Data() << endl;
541 
542  // Step 1: Find all category tags and the corresponding index numbers
543  TPRegexp categoryReg("(\\w+)::(\\w+)");
544  std::map<std::string, int> categoryStates;
545  int offset = 0;
546  do {
547  std::unique_ptr<TObjArray> matches(categoryReg.MatchS(formulaTString, "", offset, 3));
548  if (matches->GetEntries() == 0)
549  break;
550 
551  std::string fullMatch = static_cast<TObjString*>(matches->At(0))->GetString().Data();
552  std::string catName = static_cast<TObjString*>(matches->At(1))->GetString().Data();
553  std::string catState = static_cast<TObjString*>(matches->At(2))->GetString().Data();
554  offset = formulaTString.Index(categoryReg, offset) + fullMatch.size();
555 
556  const auto catVariable = dynamic_cast<const RooAbsCategory*>(_origList.find(catName.c_str()));
557  if (!catVariable) {
558  cxcoutD(InputArguments) << "Formula " << GetName() << " uses '::' to reference a category state as '" << fullMatch
559  << "' but a category '" << catName << "' cannot be found in the input variables." << endl;
560  continue;
561  }
562 
563  const RooCatType* catType = catVariable->lookupType(catState.c_str(), false);
564  if (!catType) {
565  coutE(InputArguments) << "Formula " << GetName() << " uses '::' to reference a category state as '" << fullMatch
566  << "' but the category '" << catName << "' does not seem to have the state '" << catState << "'." << endl;
567  throw std::invalid_argument(formula);
568  }
569  const int catNum = catType->getVal();
570 
571  categoryStates[fullMatch] = catNum;
572  cxcoutD(InputArguments) << "\n\t" << fullMatch << "\tname=" << catName << "\tstate=" << catState << "=" << catNum;
573  } while (offset != -1);
574  cxcoutD(InputArguments) << "-- End of category tags --"<< endl;
575 
576  // Step 2: Replace all category tags
577  for (const auto& catState : categoryStates) {
578  std::stringstream replacement;
579  replacement << catState.second;
580  formulaTString.ReplaceAll(catState.first.c_str(), replacement.str().c_str());
581  }
582 
583  cxcoutD(InputArguments) << "Preprocessing formula step 2: replace category tags\n\t" << formulaTString.Data() << endl;
584 
585  // Step 3: Convert `@i`-style references to `x[i]`
586  TPRegexp ordinalRegex("@([0-9]+)");
587  int nsub = 0;
588  do {
589  nsub = ordinalRegex.Substitute(formulaTString, "x[$1]");
590  } while (nsub > 0);
591 
592  cxcoutD(InputArguments) << "Preprocessing formula step 3: replace '@'-references\n\t" << formulaTString.Data() << endl;
593 
594  // Step 4: Replace all named references with "x[i]"-style
595  for (unsigned int i = 0; i < _origList.size(); ++i) {
596  const auto& var = _origList[i];
597  TString regex = "\\b";
598  regex += var.GetName();
599  regex += "\\b([^[]|$)"; //Negative lookahead. If the variable is called `x`, this might otherwise replace `x[0]`.
600  TPRegexp findParameterRegex(regex);
601 
602  std::stringstream replacement;
603  replacement << "x[" << i << "]$1";
604  int nsub2 = 0;
605  do {
606  nsub2 = findParameterRegex.Substitute(formulaTString, replacement.str().c_str());
607  } while (nsub2 > 0);
608 
609  cxcoutD(InputArguments) << "Preprocessing formula step 4: replace named references: "
610  << var.GetName() << " --> " << replacement.str()
611  << "\n\t" << formulaTString.Data() << endl;
612  }
613 
614  cxcoutD(InputArguments) << "Final formula:\n\t" << formulaTString << endl;
615 
616  return formulaTString.Data();
617 }
618 
619 
620 ////////////////////////////////////////////////////////////////////////////////
621 /// Analyse internal formula to find out which variables are actually in use.
623  RooArgList useList;
624  if (_tFormula == nullptr)
625  return useList;
626 
627  const TString formulaTString = _tFormula->GetTitle();
628 
629  std::set<unsigned int> matchedOrdinals;
630  TPRegexp newOrdinalRegex("\\bx\\[([0-9]+)\\]");
631  int offset = 0;
632  do {
633  std::unique_ptr<TObjArray> matches(newOrdinalRegex.MatchS(formulaTString, "", offset, 2));
634  if (matches->GetEntries() == 0)
635  break;
636 
637  std::string fullMatch = static_cast<TObjString*>(matches->At(0))->GetString().Data();
638  std::string ordinal = static_cast<TObjString*>(matches->At(1))->GetString().Data();
639  offset = formulaTString.Index(newOrdinalRegex, offset) + fullMatch.size();
640 
641  std::stringstream matchString(ordinal.c_str());
642  unsigned int i;
643  matchString >> i;
644 
645  matchedOrdinals.insert(i);
646  } while (offset != -1);
647 
648  for (unsigned int i : matchedOrdinals) {
649  useList.add(_origList[i]);
650  }
651 
652  return useList;
653 }
654 
655 
656 ////////////////////////////////////////////////////////////////////////////////
657 /// From the internal representation, construct a formula by replacing all index place holders
658 /// with the names of the variables that are being used to evaluate it.
659 std::string RooFormula::reconstructFormula(std::string internalRepr) const {
660  TString internalReprT = internalRepr.c_str();
661 
662  for (unsigned int i = 0; i < _origList.size(); ++i) {
663  const auto& var = _origList[i];
664  std::stringstream regexStr;
665  regexStr << "x\\[" << i << "\\]|@" << i;
666  TPRegexp regex(regexStr.str().c_str());
667 
668  std::string replacement = std::string("[") + var.GetName() + "]";
669  regex.Substitute(internalReprT, replacement.c_str());
670  }
671 
672  return internalReprT.Data();
673 }
674 #endif //GCC < 4.9 Check
RooFormula::installFormulaOrThrow
void installFormulaOrThrow(const std::string &formulaa)
Check that the formula compiles, and also fulfills the assumptions.
Definition: RooFormula.cxx:477
RooBatchCompute.h
RooFormula
RooFormula internally uses ROOT's TFormula to compute user-defined expressions of RooAbsArgs.
Definition: RooFormula.h:34
e
#define e(i)
Definition: RSha256.hxx:103
RooAbsReal.h
RooBatchCompute::RunContext::makeBatch
RooSpan< double > makeBatch(const RooAbsReal *owner, std::size_t size)
Create a writable batch.
Definition: RunContext.cxx:87
RooMsgService.h
TFormula
The Formula class.
Definition: TFormula.h:87
RooFit.h
RooFit::InputArguments
@ InputArguments
Definition: RooGlobalFunc.h:61
TString::Data
const char * Data() const
Definition: TString.h:369
RooFormula::RooFormula
RooFormula()
Default constructor coverity[UNINIT_CTOR].
Definition: RooFormula.cxx:98
ClassImp
#define ClassImp(name)
Definition: Rtypes.h:364
TNamed::GetTitle
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:48
TObjString.h
coutE
#define coutE(a)
Definition: RooMsgService.h:33
output
static void output(int code)
Definition: gifencode.c:226
RooArgList
RooArgList is a container object that can hold multiple RooAbsArg objects.
Definition: RooArgList.h:21
RooCatType::getVal
Int_t getVal() const
Definition: RooCatTypeLegacy.h:80
RooFormula::_isCategory
std::vector< bool > _isCategory
Original list of dependents.
Definition: RooFormula.h:93
RooFormula::usedVariables
RooArgList usedVariables() const
Analyse internal formula to find out which variables are actually in use.
Definition: RooFormula.cxx:229
RooAbsCollection::find
RooAbsArg * find(const char *name) const
Find object with given name in list.
Definition: RooAbsCollection.cxx:810
RooFormula::dump
void dump() const
DEBUG: Dump state information.
Definition: RooFormula.cxx:295
TString::Length
Ssiz_t Length() const
Definition: TString.h:410
coutI
#define coutI(a)
Definition: RooMsgService.h:30
TClass.h
RooFormula::printTitle
virtual void printTitle(std::ostream &os) const
Print title of formula.
Definition: RooFormula.cxx:446
indent
static void indent(ostringstream &buf, int indent_level)
Definition: TClingCallFunc.cxx:87
RooFormula.h
RooAbsReal
RooAbsReal is the common abstract base class for objects that represent a real value and implements f...
Definition: RooAbsReal.h:61
TString
Basic string class.
Definition: TString.h:136
RooAbsCollection::GetName
const char * GetName() const
Returns name of object.
Definition: RooAbsCollection.h:286
RooPrintable
RooPlotable is a 'mix-in' base class that define the standard RooFit plotting and printing methods.
Definition: RooPrintable.h:25
bool
TString::ReplaceAll
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition: TString.h:692
RooFormula::_origList
RooArgList _origList
Definition: RooFormula.h:92
RooAbsArg::findNewServer
RooAbsArg * findNewServer(const RooAbsCollection &newSet, Bool_t nameChange) const
Find the new server in the specified set that matches the old server.
Definition: RooAbsArg.cxx:1114
RooAbsCategory
RooAbsCategory is the base class for objects that represent a discrete value with a finite number of ...
Definition: RooAbsCategory.h:37
RooFormula::_tFormula
std::unique_ptr< TFormula > _tFormula
Whether an element of the _origList is a category.
Definition: RooFormula.h:94
TObjString
Collectable string class.
Definition: TObjString.h:28
RooFit::LinkStateMgmt
@ LinkStateMgmt
Definition: RooGlobalFunc.h:60
RooFormula::changeDependents
Bool_t changeDependents(const RooAbsCollection &newDeps, Bool_t mustReplaceAll, Bool_t nameChange)
Change used variables to those with the same name in given list.
Definition: RooFormula.cxx:306
RooAbsArg::setStringAttribute
void setStringAttribute(const Text_t *key, const Text_t *value)
Associate string 'value' to this object under key 'key'.
Definition: RooAbsArg.cxx:323
TPRegexp.h
Double_t
TNamed
The TNamed class is the base class for all named ROOT classes.
Definition: TNamed.h:29
RooFormula::printValue
virtual void printValue(std::ostream &os) const
Print value of formula.
Definition: RooFormula.cxx:428
RooFormula::reCompile
Bool_t reCompile(const char *newFormula)
Recompile formula with new expression.
Definition: RooFormula.cxx:281
RooAbsCollection::replace
virtual Bool_t replace(const RooAbsArg &var1, const RooAbsArg &var2)
Replace var1 with var2 and return kTRUE for success.
Definition: RooAbsCollection.cxx:534
RooFormula::reconstructFormula
std::string reconstructFormula(std::string internalRepr) const
From the internal representation, construct a formula by replacing all index place holders with the n...
Definition: RooFormula.cxx:259
RooAbsCollection
RooAbsCollection is an abstract container object that can hold multiple RooAbsArg objects.
Definition: RooAbsCollection.h:33
what
static const char * what
Definition: stlLoader.cc:6
RooAbsCollection::add
virtual Bool_t add(const RooAbsArg &var, Bool_t silent=kFALSE)
Add the specified argument to list.
Definition: RooAbsCollection.cxx:455
TString::BeginsWith
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition: TString.h:615
RooAbsCollection::size
Storage_t::size_type size() const
Definition: RooAbsCollection.h:214
RooFormula::evaluateSpan
RooSpan< double > evaluateSpan(const RooAbsReal *dataOwner, RooBatchCompute::RunContext &inputData, const RooArgSet *nset=nullptr) const
Definition: RooFormula.cxx:368
RooFormula::printName
virtual void printName(std::ostream &os) const
Print name of formula.
Definition: RooFormula.cxx:437
TNamed::SetTitle
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition: TNamed.cxx:164
TPRegexp
Definition: TPRegexp.h:36
TString::Index
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:639
RooFormula::actualDependents
RooArgSet actualDependents() const
Return list of arguments which are used in the formula.
Definition: RooFormula.h:44
TFormula::SetName
void SetName(const char *name)
Set the name of the TNamed.
RooFormula::processFormula
std::string processFormula(std::string origFormula) const
Process given formula by replacing all ordinal and name references by x[i], where i matches the posit...
Definition: RooFormula.cxx:155
RooAbsCategory.h
coutF
#define coutF(a)
Definition: RooMsgService.h:34
name
char name[80]
Definition: TGX11.cxx:110
RooCatType
RooCatType is an auxilary class for RooAbsCategory and defines a a single category state.
Definition: RooCatTypeLegacy.h:23
RooFormula::printMultiline
void printMultiline(std::ostream &os, Int_t contents, Bool_t verbose=kFALSE, TString indent="") const
Printing interface.
Definition: RooFormula.cxx:414
RooAbsReal::getValues
virtual RooSpan< const double > getValues(RooBatchCompute::RunContext &evalData, const RooArgSet *normSet=nullptr) const
by this change, please consult the release notes for ROOT 6.24 for guidance on how to make this trans...
Definition: RooAbsReal.cxx:312
RMakeUnique.hxx
TNamed::GetName
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
RooFormula::printClassName
virtual void printClassName(std::ostream &os) const
Print class name of formula.
Definition: RooFormula.cxx:455
Class
void Class()
Definition: Class.C:29
RooFit::Eval
@ Eval
Definition: RooGlobalFunc.h:61
RooFormula::eval
Double_t eval(const RooArgSet *nset=0) const
Evalute all parameters/observables, and then evaluate formula.
Definition: RooFormula.cxx:342
RooArgList.h
RooBatchCompute::RunContext
This struct enables passing computation data around between elements of a computation graph.
Definition: RunContext.h:31
RooFormula::printArgs
virtual void printArgs(std::ostream &os) const
Print arguments of formula, i.e. dependents that are actually used.
Definition: RooFormula.cxx:464
RooSpan
A simple container to hold a batch of data values.
Definition: RooSpan.h:34
RooArgSet
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Definition: RooArgSet.h:33
cxcoutD
#define cxcoutD(a)
Definition: RooMsgService.h:81
int