85 for (
unsigned int i = 0; i < collection.
size(); ++i) {
93void convertArobaseReferences(std::string &formula)
96 for (std::size_t i = 0; i < formula.size(); ++i) {
97 if (match && !isdigit(formula[i])) {
98 formula.insert(formula.begin() + i,
']');
101 }
else if (!match && formula[i] ==
'@') {
103 formula.insert(formula.begin() + i + 1,
'[');
113void replaceAll(std::string &inout, std::string_view
what, std::string_view with)
115 for (std::string::size_type pos{}; inout.npos != (pos = inout.find(
what.data(), pos,
what.length()));
116 pos += with.length()) {
117 inout.replace(pos,
what.length(), with.data(), with.length());
124std::vector<bool> getWordBoundaryFlags(std::string
const &s)
126 static const std::regex
r{
"\\b"};
127 std::vector<bool> out(s.size() + 1);
129 for (
auto i = std::sregex_iterator(s.begin(), s.end(),
r); i != std::sregex_iterator(); ++i) {
131 out[
m.position()] =
true;
135 out[s.size()] =
true;
141void replaceVarNamesWithIndexStyle(std::string &formula,
RooArgList const &varList)
143 std::vector<bool> isWordBoundary = getWordBoundaryFlags(formula);
144 for (
unsigned int i = 0; i < varList.
size(); ++i) {
145 std::string_view varName = varList[i].
GetName();
147 std::stringstream replacementStream;
148 replacementStream <<
"x[" << i <<
"]";
149 std::string replacement = replacementStream.str();
151 for (std::string::size_type pos{}; formula.npos != (pos = formula.find(varName.data(), pos, varName.length()));
152 pos += replacement.size()) {
154 std::string::size_type next = pos + varName.length();
158 if (!isWordBoundary[pos] || !isWordBoundary[next])
163 if (next < formula.size() && (formula[next] ==
'[' || formula[next] ==
']')) {
171 std::size_t nOld = varName.length();
172 std::size_t nNew = replacement.size();
173 auto wbIter = isWordBoundary.begin() + pos;
175 isWordBoundary.insert(wbIter + nOld, nNew - nOld,
false);
176 else if (nNew < nOld)
177 isWordBoundary.erase(wbIter + nNew, wbIter + nOld);
180 formula.replace(pos, varName.length(), replacement);
184 <<
"Preprocessing formula: replace named references: " << varName <<
" --> " << replacement <<
"\n\t"
209 bool checkVariables) :
220 <<
" but only " << useList <<
" seem to be in use."
221 <<
"\n inputs: " << formula << std::endl;
235 std::unique_ptr<TFormula> newTF;
237 newTF = std::make_unique<TFormula>(*other.
_tFormula);
246#if !defined(__GNUC__) || defined(__clang__) || (__GNUC__ > 4) || ( __GNUC__ == 4 && __GNUC_MINOR__ > 8)
247#define ROOFORMULA_HAVE_STD_REGEX
251#ifdef ROOFORMULA_HAVE_STD_REGEX
264 cxcoutD(InputArguments) <<
"Preprocessing formula step 1: find category tags (catName::catState) in "
268 static const std::regex categoryReg(
"(\\w+)::(\\w+)");
269 std::map<std::string, int> categoryStates;
270 for (sregex_iterator matchIt = sregex_iterator(formula.begin(), formula.end(), categoryReg);
271 matchIt != sregex_iterator(); ++matchIt) {
272 assert(matchIt->size() == 3);
273 const std::string fullMatch = (*matchIt)[0];
274 const std::string catName = (*matchIt)[1];
275 const std::string catState = (*matchIt)[2];
279 cxcoutD(InputArguments) <<
"Formula " <<
GetName() <<
" uses '::' to reference a category state as '" << fullMatch
280 <<
"' but a category '" << catName <<
"' cannot be found in the input variables." << endl;
284 if (!catVariable->hasLabel(catState)) {
285 coutE(InputArguments) <<
"Formula " <<
GetName() <<
" uses '::' to reference a category state as '" << fullMatch
286 <<
"' but the category '" << catName <<
"' does not seem to have the state '" << catState <<
"'." << endl;
287 throw std::invalid_argument(formula);
289 const int catNum = catVariable->lookupIndex(catState);
291 categoryStates[fullMatch] = catNum;
292 cxcoutD(InputArguments) <<
"\n\t" << fullMatch <<
"\tname=" << catName <<
"\tstate=" << catState <<
"=" << catNum;
294 cxcoutD(InputArguments) <<
"-- End of category tags --"<< endl;
297 for (
const auto& catState : categoryStates) {
298 replaceAll(formula, catState.first, std::to_string(catState.second));
301 cxcoutD(InputArguments) <<
"Preprocessing formula step 2: replace category tags\n\t" << formula << endl;
304 convertArobaseReferences(formula);
306 cxcoutD(InputArguments) <<
"Preprocessing formula step 3: replace '@'-references\n\t" << formula << endl;
309 replaceVarNamesWithIndexStyle(formula,
_origList);
311 cxcoutD(InputArguments) <<
"Final formula:\n\t" << formula << endl;
324 const std::string formula(
_tFormula->GetTitle());
326 std::set<unsigned int> matchedOrdinals;
327 static const std::regex newOrdinalRegex(
"\\bx\\[([0-9]+)\\]");
328 for (sregex_iterator matchIt = sregex_iterator(formula.begin(), formula.end(), newOrdinalRegex);
329 matchIt != sregex_iterator(); ++matchIt) {
330 assert(matchIt->size() == 2);
331 std::stringstream matchString((*matchIt)[1]);
335 matchedOrdinals.insert(i);
338 for (
unsigned int i : matchedOrdinals) {
352 std::stringstream regexStr;
353 regexStr <<
"x\\[" << i <<
"\\]|@" << i;
354 std::regex regex(regexStr.str());
356 std::string replacement = std::string(
"[") + var.GetName() +
"]";
357 internalRepr = std::regex_replace(internalRepr, regex, replacement);
374 }
catch (std::runtime_error&
e) {
375 coutE(InputArguments) << __func__ <<
": new equation doesn't compile, formula unchanged."
376 <<
"\n" <<
e.what() << endl;
398 bool errorStat =
false;
405 if (arg->getStringAttribute(
"origName")) {
411 }
else if (mustReplaceAll) {
412 coutE(LinkStateMgmt) << __func__ <<
": cannot find replacement for " << arg->GetName() << endl;
434 coutF(Eval) << __func__ <<
" (" <<
GetName() <<
"): Formula didn't compile: " <<
GetTitle() << endl;
435 std::string
what =
"Formula ";
437 what +=
" didn't compile.";
438 throw std::runtime_error(
what);
441 std::vector<double> pars;
446 pars.push_back(cat.getCurrentIndex());
449 pars.push_back(real.getVal(nset));
459 coutF(Eval) << __func__ <<
" (" <<
GetName() <<
"): Formula didn't compile: " <<
GetTitle() << endl;
460 std::string
what =
"Formula ";
462 what +=
" didn't compile.";
463 throw std::runtime_error(
what);
466 std::vector<RooBatchCompute::BracketAdapterWithMask> valueAdapters;
467 std::vector<RooSpan<const double>> inputSpans;
470 auto realArg =
static_cast<const RooAbsReal*
>(arg);
471 auto batch = realArg->
getValues(inputData, nset);
472 assert(!batch.empty());
473 nData = std::max(nData, batch.size());
474 valueAdapters.emplace_back(batch[0], batch);
475 inputSpans.push_back(std::move(batch));
482 for (std::size_t i=0; i < nData; ++i) {
490 pars[j] = valueAdapters[j][i];
503 std::vector<RooSpan<const double>> inputSpans(nPars);
504 for (
int i=0; i<nPars; i++)
507 std::vector<double> pars(nPars);
508 for (
size_t i=0; i<nEvents; i++)
510 for (
int j=0; j<nPars; j++) pars[j] = inputSpans[j].
size()>1 ? inputSpans[j][i] : inputSpans[j][0];
520 os <<
indent <<
"--- RooFormula ---" << endl;
534 os << const_cast<RooFormula*>(
this)->eval(0) ;
570 os <<
"[ actualVars=";
572 os <<
" " << arg->GetName();
584 cxcoutD(InputArguments) <<
"RooFormula '" <<
GetName() <<
"' will be compiled as "
585 <<
"\n\t" << processedFormula
588 <<
"\n with the parameters " <<
_origList << endl;
590 auto theFormula = std::make_unique<TFormula>(
GetName(), processedFormula.c_str(),
false);
592 if (!theFormula || !theFormula->IsValid()) {
593 std::stringstream msg;
594 msg <<
"RooFormula '" <<
GetName() <<
"' did not compile or is invalid."
595 <<
"\nInput:\n\t" << formula
596 <<
"\nPassed over to TFormula:\n\t" << processedFormula << std::endl;
597 coutF(InputArguments) << msg.str();
598 throw std::runtime_error(msg.str());
601 if (theFormula && theFormula->GetNdim() != 1) {
604 bool haveProblem =
false;
605 std::stringstream msg;
606 msg <<
"TFormula interprets the formula " << formula <<
" as " << theFormula->GetNdim() <<
"-dimensional with the variable(s) {";
607 for (
int i=1; i < theFormula->GetNdim(); ++i) {
608 const TString varName = theFormula->GetVarName(i);
613 msg << theFormula->GetVarName(i) <<
",";
616 msg <<
"}, which could not be supplied by RooFit."
617 <<
"\nThe formula must be modified, or those variables must be supplied in the list of variables." << std::endl;
618 coutF(InputArguments) << msg.str();
619 throw std::invalid_argument(msg.str());
627#ifndef ROOFORMULA_HAVE_STD_REGEX
641 TString formulaTString = formula.c_str();
643 cxcoutD(InputArguments) <<
"Preprocessing formula step 1: find category tags (catName::catState) in "
644 << formulaTString.
Data() << endl;
647 TPRegexp categoryReg(
"(\\w+)::(\\w+)");
648 std::map<std::string, int> categoryStates;
651 std::unique_ptr<TObjArray> matches(categoryReg.MatchS(formulaTString,
"",
offset, 3));
652 if (matches->GetEntries() == 0)
655 std::string fullMatch =
static_cast<TObjString*
>(matches->At(0))->GetString().Data();
656 std::string catName =
static_cast<TObjString*
>(matches->At(1))->GetString().Data();
657 std::string catState =
static_cast<TObjString*
>(matches->At(2))->GetString().Data();
662 cxcoutD(InputArguments) <<
"Formula " <<
GetName() <<
" uses '::' to reference a category state as '" << fullMatch
663 <<
"' but a category '" << catName <<
"' cannot be found in the input variables." << endl;
667 const RooCatType* catType = catVariable->lookupType(catState.c_str(),
false);
669 coutE(InputArguments) <<
"Formula " <<
GetName() <<
" uses '::' to reference a category state as '" << fullMatch
670 <<
"' but the category '" << catName <<
"' does not seem to have the state '" << catState <<
"'." << endl;
671 throw std::invalid_argument(formula);
673 const int catNum = catType->
getVal();
675 categoryStates[fullMatch] = catNum;
676 cxcoutD(InputArguments) <<
"\n\t" << fullMatch <<
"\tname=" << catName <<
"\tstate=" << catState <<
"=" << catNum;
678 cxcoutD(InputArguments) <<
"-- End of category tags --"<< endl;
681 for (
const auto& catState : categoryStates) {
682 std::stringstream replacement;
683 replacement << catState.second;
684 formulaTString.
ReplaceAll(catState.first.c_str(), replacement.str().c_str());
687 cxcoutD(InputArguments) <<
"Preprocessing formula step 2: replace category tags\n\t" << formulaTString.
Data() << endl;
693 nsub = ordinalRegex.Substitute(formulaTString,
"x[$1]");
696 cxcoutD(InputArguments) <<
"Preprocessing formula step 3: replace '@'-references\n\t" << formulaTString.
Data() << endl;
702 regex += var.GetName();
703 regex +=
"\\b([^\\[\\]]|$)";
706 std::stringstream replacement;
707 replacement <<
"x[" << i <<
"]$1";
710 nsub2 = findParameterRegex.Substitute(formulaTString, replacement.str().c_str());
713 cxcoutD(InputArguments) <<
"Preprocessing formula step 4: replace named references: "
714 << var.GetName() <<
" --> " << replacement.str()
715 <<
"\n\t" << formulaTString.
Data() << endl;
718 cxcoutD(InputArguments) <<
"Final formula:\n\t" << formulaTString << endl;
720 return formulaTString.
Data();
734 std::set<unsigned int> matchedOrdinals;
735 TPRegexp newOrdinalRegex(
"\\bx\\[([0-9]+)\\]");
738 std::unique_ptr<TObjArray> matches(newOrdinalRegex.MatchS(formulaTString,
"",
offset, 2));
739 if (matches->GetEntries() == 0)
742 std::string fullMatch =
static_cast<TObjString*
>(matches->At(0))->GetString().Data();
743 std::string ordinal =
static_cast<TObjString*
>(matches->At(1))->GetString().Data();
746 std::stringstream matchString(ordinal.c_str());
750 matchedOrdinals.insert(i);
753 for (
unsigned int i : matchedOrdinals) {
765 TString internalReprT = internalRepr.c_str();
769 std::stringstream regexStr;
770 regexStr <<
"x\\[" << i <<
"\\]|@" << i;
771 TPRegexp regex(regexStr.str().c_str());
773 std::string replacement = std::string(
"[") + var.GetName() +
"]";
774 regex.Substitute(internalReprT, replacement.c_str());
777 return internalReprT.
Data();
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
static void indent(ostringstream &buf, int indent_level)
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h offset
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t r
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 nameChange) const
Find the new server in the specified set that matches the old server.
A space to attach TBranches.
virtual value_type getCurrentIndex() const
Return index number of current state.
RooAbsCollection is an abstract container object that can hold multiple RooAbsArg objects.
const char * GetName() const override
Returns name of object.
virtual bool add(const RooAbsArg &var, bool silent=false)
Add the specified argument to list.
Storage_t::size_type size() const
virtual bool replace(const RooAbsArg &var1, const RooAbsArg &var2)
Replace var1 with var2 and return true for success.
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.
RooSpan< const double > at(RooAbsArg const *arg, RooAbsArg const *caller=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.
const char * GetName() const override
Returns name of object.
const char * GetTitle() const override
Returns title of object.
Collectable string class.
Mother of all ROOT objects.
virtual const char * ClassName() const
Returns name of class to which the object belongs.
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.