81 for (
unsigned int i = 0; i < collection.
size(); ++i) {
89void convertArobaseReferences(std::string &formula)
92 for (std::size_t i = 0; i < formula.size(); ++i) {
93 if (match && !isdigit(formula[i])) {
94 formula.insert(formula.begin() + i,
']');
97 }
else if (!match && formula[i] ==
'@') {
99 formula.insert(formula.begin() + i + 1,
'[');
109void replaceAll(std::string &inOut, std::string_view
what, std::string_view with)
111 for (std::string::size_type pos{}; inOut.npos != (pos = inOut.find(
what.data(), pos,
what.length()));
112 pos += with.length()) {
113 inOut.replace(pos,
what.length(), with.data(), with.length());
120std::vector<bool> getWordBoundaryFlags(std::string
const &s)
122 static const std::regex
r{
"\b"};
123 std::vector<bool>
out(s.size() + 1);
125 for (
auto i = std::sregex_iterator(s.begin(), s.end(),
r); i != std::sregex_iterator(); ++i) {
127 out[
m.position()] =
true;
131 out[s.size()] =
true;
137void replaceVarNamesWithIndexStyle(std::string &formula,
RooArgList const &varList)
139 std::vector<bool> isWordBoundary = getWordBoundaryFlags(formula);
140 for (
unsigned int i = 0; i < varList.
size(); ++i) {
141 std::string_view varName = varList[i].
GetName();
143 std::stringstream replacementStream;
144 replacementStream <<
"x[" << i <<
"]";
145 std::string replacement = replacementStream.str();
147 for (std::string::size_type pos{}; formula.npos != (pos = formula.find(varName.data(), pos, varName.length()));
148 pos += replacement.size()) {
150 std::string::size_type next = pos + varName.length();
154 if (!isWordBoundary[pos] || !isWordBoundary[next])
159 if (next < formula.size() && (formula[next] ==
'[' || formula[next] ==
']')) {
167 std::size_t nOld = varName.length();
168 std::size_t nNew = replacement.size();
169 auto wbIter = isWordBoundary.begin() + pos;
171 isWordBoundary.insert(wbIter + nOld, nNew - nOld,
false);
172 else if (nNew < nOld)
173 isWordBoundary.erase(wbIter + nNew, wbIter + nOld);
176 formula.replace(pos, varName.length(), replacement);
180 <<
"Preprocessing formula: replace named references: " << varName <<
" --> " << replacement <<
"\n\t"
181 << formula << std::endl;
197 bool checkVariables) :
208 <<
" but only " << useList <<
" seem to be in use."
209 <<
"\n inputs: " << formula << std::endl;
223 std::unique_ptr<TFormula> newTF;
225 newTF = std::make_unique<TFormula>(*other.
_tFormula);
245 cxcoutD(InputArguments) <<
"Preprocessing formula step 1: find category tags (catName::catState) in "
246 << formula << std::endl;
249 static const std::regex categoryReg(
"(\w+)::(\w+)");
250 std::map<std::string, int> categoryStates;
251 for (sregex_iterator matchIt = sregex_iterator(formula.begin(), formula.end(), categoryReg);
252 matchIt != sregex_iterator(); ++matchIt) {
253 assert(matchIt->size() == 3);
254 const std::string fullMatch = (*matchIt)[0];
255 const std::string catName = (*matchIt)[1];
256 const std::string catState = (*matchIt)[2];
260 cxcoutD(InputArguments) <<
"Formula " <<
GetName() <<
" uses '::' to reference a category state as '" << fullMatch
261 <<
"' but a category '" << catName <<
"' cannot be found in the input variables." << std::endl;
265 if (!catVariable->hasLabel(catState)) {
266 coutE(InputArguments) <<
"Formula " <<
GetName() <<
" uses '::' to reference a category state as '" << fullMatch
267 <<
"' but the category '" << catName <<
"' does not seem to have the state '" << catState <<
"'." << std::endl;
268 throw std::invalid_argument(formula);
270 const int catNum = catVariable->lookupIndex(catState);
272 categoryStates[fullMatch] = catNum;
273 cxcoutD(InputArguments) <<
"\n\t" << fullMatch <<
"\tname=" << catName <<
"\tstate=" << catState <<
"=" << catNum;
275 cxcoutD(InputArguments) <<
"-- End of category tags --"<< std::endl;
278 for (
const auto& catState : categoryStates) {
279 replaceAll(formula, catState.first, std::to_string(catState.second));
282 cxcoutD(InputArguments) <<
"Preprocessing formula step 2: replace category tags\n\t" << formula << std::endl;
285 convertArobaseReferences(formula);
287 cxcoutD(InputArguments) <<
"Preprocessing formula step 3: replace '@'-references\n\t" << formula << std::endl;
290 replaceVarNamesWithIndexStyle(formula,
_origList);
292 cxcoutD(InputArguments) <<
"Final formula:\n\t" << formula << std::endl;
305 const std::string formula(
_tFormula->GetTitle());
307 std::set<unsigned int> matchedOrdinals;
308 static const std::regex newOrdinalRegex(
"\bx\[([0-9]+)\]");
309 for (sregex_iterator matchIt = sregex_iterator(formula.begin(), formula.end(), newOrdinalRegex);
310 matchIt != sregex_iterator(); ++matchIt) {
311 assert(matchIt->size() == 2);
312 std::stringstream matchString((*matchIt)[1]);
316 matchedOrdinals.insert(i);
319 for (
unsigned int i : matchedOrdinals) {
333 std::stringstream regexStr;
334 regexStr <<
"x\[" << i <<
"\]|@" << i;
335 std::regex regex(regexStr.str());
337 std::string replacement = std::string(
"[") + var.GetName() +
"]";
338 internalRepr = std::regex_replace(internalRepr, regex, replacement);
359 bool errorStat =
false;
368 if (arg->getStringAttribute(
"origName")) {
374 }
else if (mustReplaceAll) {
375 coutE(LinkStateMgmt) << __func__ <<
": cannot find replacement for " << arg->GetName() << std::endl;
397 coutF(Eval) << __func__ <<
" (" <<
GetName() <<
"): Formula didn't compile: " <<
GetTitle() << std::endl;
398 std::string
what =
"Formula ";
400 what +=
" didn't compile.";
401 throw std::runtime_error(
what);
404 std::vector<double> pars;
409 pars.push_back(cat.getCurrentIndex());
412 pars.push_back(real.getVal(nset));
422 std::vector<std::span<const double>> inputSpans(nPars);
423 for (
int i=0; i<nPars; i++) {
428 std::vector<double> pars(nPars);
429 for (
size_t i=0; i<nEvents; i++)
431 for (
int j=0; j<nPars; j++) pars[j] = inputSpans[j].
size()>1 ? inputSpans[j][i] : inputSpans[j][0];
441 os <<
indent <<
"--- RooFormula ---" << std::endl;
455 os << const_cast<RooFormula*>(
this)->eval(
nullptr) ;
491 os <<
"[ actualVars=";
493 os <<
" " << arg->GetName();
505 cxcoutD(InputArguments) <<
"RooFormula '" <<
GetName() <<
"' will be compiled as "
506 <<
"\n\t" << processedFormula
509 <<
"\n with the parameters " <<
_origList << std::endl;
511 auto theFormula = std::make_unique<TFormula>(
GetName(), processedFormula.c_str(),
false);
513 if (!theFormula || !theFormula->IsValid()) {
514 std::stringstream msg;
515 msg <<
"RooFormula '" <<
GetName() <<
"' did not compile or is invalid."
516 <<
"\nInput:\n\t" << formula
517 <<
"\nPassed over to TFormula:\n\t" << processedFormula << std::endl;
518 coutF(InputArguments) << msg.str();
519 throw std::runtime_error(msg.str());
522 if (theFormula && theFormula->GetNdim() != 1) {
525 bool haveProblem =
false;
526 std::stringstream msg;
527 msg <<
"TFormula interprets the formula " << formula <<
" as " << theFormula->GetNdim() <<
"-dimensional with the variable(s) {";
528 for (
int i=1; i < theFormula->GetNdim(); ++i) {
529 const TString varName = theFormula->GetVarName(i);
534 msg << theFormula->GetVarName(i) <<
",";
537 msg <<
"}, which could not be supplied by RooFit."
538 <<
"\nThe formula must be modified, or those variables must be supplied in the list of variables." << std::endl;
539 coutF(InputArguments) << msg.str();
540 throw std::invalid_argument(msg.str());
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 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.
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.
Abstract base class for objects that represent a real value and implements functionality common to al...
RooArgList is a container object that can hold multiple RooAbsArg objects.
RooArgSet is a container object that can hold multiple RooAbsArg objects.
std::span< 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.
The TNamed class is the base class for all named ROOT classes.
const char * GetName() const override
Returns name of object.
const char * GetTitle() const override
Returns title of object.
Mother of all ROOT objects.
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const