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