86 for (
unsigned int i = 0; i < collection.
size(); ++i) {
87 output.push_back(collection[i]->InheritsFrom(RooAbsCategory::Class()));
113 bool checkVariables) :
124 <<
" but only " << useList <<
" seem to be in use."
125 <<
"\n inputs: " << formula << std::endl;
149#if !defined(__GNUC__) || defined(__clang__) || (__GNUC__ > 4) || ( __GNUC__ == 4 && __GNUC_MINOR__ > 8)
150#define ROOFORMULA_HAVE_STD_REGEX
154#ifdef ROOFORMULA_HAVE_STD_REGEX
162 cxcoutD(InputArguments) <<
"Preprocessing formula step 1: find category tags (catName::catState) in "
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];
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;
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);
187 const int catNum = catVariable->lookupIndex(catState);
189 categoryStates[fullMatch] = catNum;
190 cxcoutD(InputArguments) <<
"\n\t" << fullMatch <<
"\tname=" << catName <<
"\tstate=" << catState <<
"=" << catNum;
192 cxcoutD(InputArguments) <<
"-- End of category tags --"<< endl;
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());
201 cxcoutD(InputArguments) <<
"Preprocessing formula step 2: replace category tags\n\t" << formula << endl;
204 std::regex ordinalRegex(
"@([0-9]+)");
205 formula = std::regex_replace(formula, ordinalRegex,
"x[$1]");
207 cxcoutD(InputArguments) <<
"Preprocessing formula step 3: replace '@'-references\n\t" << formula << endl;
212 auto regex = std::string{
"\\b"} + var.
GetName();
213 regex = std::regex_replace(regex, std::regex(
"([\\[\\]\\{\\}])"),
"\\$1");
214 regex +=
"\\b(?!\\[)";
215 regex +=
"\\b(?!\\])";
216 std::regex findParameterRegex(regex);
218 std::stringstream replacement;
219 replacement <<
"x[" << i <<
"]";
220 formula = std::regex_replace(formula, findParameterRegex, replacement.str());
222 cxcoutD(InputArguments) <<
"Preprocessing formula step 4: replace named references: "
223 << var.GetName() <<
" --> " << replacement.str()
224 <<
"\n\t" << formula << endl;
227 cxcoutD(InputArguments) <<
"Final formula:\n\t" << formula << endl;
240 const std::string formula(
_tFormula->GetTitle());
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]);
251 matchedOrdinals.insert(i);
254 for (
unsigned int i : matchedOrdinals) {
268 std::stringstream regexStr;
269 regexStr <<
"x\\[" << i <<
"\\]|@" << i;
270 std::regex regex(regexStr.str());
272 std::string replacement = std::string(
"[") + var.GetName() +
"]";
273 internalRepr = std::regex_replace(internalRepr, regex, replacement);
290 }
catch (std::runtime_error&
e) {
291 coutE(InputArguments) << __func__ <<
": new equation doesn't compile, formula unchanged."
292 <<
"\n" <<
e.what() << endl;
314 bool errorStat =
false;
321 if (arg->getStringAttribute(
"origName")) {
327 }
else if (mustReplaceAll) {
328 coutE(LinkStateMgmt) << __func__ <<
": cannot find replacement for " << arg->GetName() << endl;
350 coutF(Eval) << __func__ <<
" (" <<
GetName() <<
"): Formula didn't compile: " <<
GetTitle() << endl;
351 std::string
what =
"Formula ";
353 what +=
" didn't compile.";
354 throw std::runtime_error(
what);
357 std::vector<double> pars;
362 pars.push_back(cat.getCurrentIndex());
365 pars.push_back(real.getVal(nset));
375 coutF(Eval) << __func__ <<
" (" <<
GetName() <<
"): Formula didn't compile: " <<
GetTitle() << endl;
376 std::string
what =
"Formula ";
378 what +=
" didn't compile.";
379 throw std::runtime_error(
what);
382 std::vector<RooBatchCompute::BracketAdapterWithMask> valueAdapters;
383 std::vector<RooSpan<const double>> inputSpans;
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));
398 for (std::size_t i=0; i < nData; ++i) {
406 pars[j] = valueAdapters[j][i];
419 std::vector<RooSpan<const double>> inputSpans(nPars);
420 for (
int i=0; i<nPars; i++)
423 std::vector<double> pars(nPars);
424 for (
size_t i=0; i<nEvents; i++)
426 for (
int j=0; j<nPars; j++) pars[j] = inputSpans[j].
size()>1 ? inputSpans[j][i] : inputSpans[j][0];
436 os <<
indent <<
"--- RooFormula ---" << endl;
450 os << const_cast<RooFormula*>(
this)->eval(0) ;
477 os << IsA()->GetName() ;
486 os <<
"[ actualVars=";
488 os <<
" " << arg->GetName();
500 cxcoutD(InputArguments) <<
"RooFormula '" <<
GetName() <<
"' will be compiled as "
501 <<
"\n\t" << processedFormula
504 <<
"\n with the parameters " <<
_origList << endl;
506 auto theFormula = std::make_unique<TFormula>(
GetName(), processedFormula.c_str(),
false);
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());
517 if (theFormula && theFormula->GetNdim() != 1) {
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);
529 msg << theFormula->GetVarName(i) <<
",";
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());
543#ifndef ROOFORMULA_HAVE_STD_REGEX
557 TString formulaTString = formula.c_str();
559 cxcoutD(InputArguments) <<
"Preprocessing formula step 1: find category tags (catName::catState) in "
560 << formulaTString.
Data() << endl;
563 TPRegexp categoryReg(
"(\\w+)::(\\w+)");
564 std::map<std::string, int> categoryStates;
567 std::unique_ptr<TObjArray> matches(categoryReg.MatchS(formulaTString,
"", offset, 3));
568 if (matches->GetEntries() == 0)
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();
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;
583 const RooCatType* catType = catVariable->lookupType(catState.c_str(),
false);
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);
589 const int catNum = catType->
getVal();
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;
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());
603 cxcoutD(InputArguments) <<
"Preprocessing formula step 2: replace category tags\n\t" << formulaTString.
Data() << endl;
609 nsub = ordinalRegex.Substitute(formulaTString,
"x[$1]");
612 cxcoutD(InputArguments) <<
"Preprocessing formula step 3: replace '@'-references\n\t" << formulaTString.
Data() << endl;
618 regex += var.GetName();
619 regex +=
"\\b([^\\[\\]]|$)";
622 std::stringstream replacement;
623 replacement <<
"x[" << i <<
"]$1";
626 nsub2 = findParameterRegex.Substitute(formulaTString, replacement.str().c_str());
629 cxcoutD(InputArguments) <<
"Preprocessing formula step 4: replace named references: "
630 << var.GetName() <<
" --> " << replacement.str()
631 <<
"\n\t" << formulaTString.
Data() << endl;
634 cxcoutD(InputArguments) <<
"Final formula:\n\t" << formulaTString << endl;
636 return formulaTString.
Data();
649 std::set<unsigned int> matchedOrdinals;
650 TPRegexp newOrdinalRegex(
"\\bx\\[([0-9]+)\\]");
653 std::unique_ptr<TObjArray> matches(newOrdinalRegex.MatchS(formulaTString,
"", offset, 2));
654 if (matches->GetEntries() == 0)
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();
661 std::stringstream matchString(ordinal.c_str());
665 matchedOrdinals.insert(i);
666 }
while (offset != -1);
668 for (
unsigned int i : matchedOrdinals) {
680 TString internalReprT = internalRepr.c_str();
684 std::stringstream regexStr;
685 regexStr <<
"x\\[" << i <<
"\\]|@" << i;
686 TPRegexp regex(regexStr.str().c_str());
688 std::string replacement = std::string(
"[") + var.GetName() +
"]";
689 regex.Substitute(internalReprT, replacement.c_str());
692 return internalReprT.
Data();
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
static void indent(ostringstream &buf, int indent_level)
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...
virtual RooSpan< const double > getValues(RooBatchCompute::RunContext &evalData, const RooArgSet *normSet=nullptr) const
RooArgList is a container object that can hold multiple RooAbsArg objects.
RooArgSet is a container object that can hold multiple RooAbsArg objects.
RooCatType is an auxilary class for RooAbsCategory and defines a a single category state.
auto & at(RooAbsArg const *arg, RooAbsArg const *=nullptr)
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.
The TNamed class is the base class for all named ROOT classes.
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
virtual const char * GetTitle() const
Returns title of object.
virtual const char * GetName() const
Returns name of object.
Collectable string class.
const char * Data() const
TString & ReplaceAll(const TString &s1, const TString &s2)
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
This struct enables passing computation data around between elements of a computation graph.
RooSpan< double > makeBatch(const RooAbsArg *owner, std::size_t size)
Create a writable batch.
static void output(int code)