45void checkObservableSpanInRange(
RooRealVar const &var, std::string
const &obsName, std::string
const &datasetName,
46 std::span<const double> span)
48 for (
double val : span) {
49 if (!var.
inRange(val,
nullptr)) {
50 const double lo = var.
getMin();
52 std::stringstream errMsg;
53 errMsg <<
"RooAbsPdf::fitTo/createNLL: cannot evaluate the likelihood because dataset \"" << datasetName
54 <<
"\" has an entry for observable \"" << obsName <<
"\" with value " << val
55 <<
", which is outside of its range [" << lo <<
", " <<
hi <<
"]. The probability density is "
56 <<
"normalized over exactly that range, so events outside of it would silently bias the fit. If "
57 <<
"you want to fit only a subset of the data, define a named range and use it in the fit, for example:\n"
58 <<
" " << obsName <<
".setRange(\"fitRange\", " << lo <<
", " <<
hi <<
");\n"
59 <<
" pdf.fitTo(data, RooFit::Range(\"fitRange\"));\n"
60 <<
"This way, only the events inside \"fitRange\" enter the likelihood, consistent with how the "
61 <<
"pdf is normalized.";
62 oocoutE(
nullptr, InputArguments) << errMsg.str() << std::endl;
63 throw std::runtime_error(errMsg.str());
85 for (
auto const &nameIdx : simPdf->indexCat()) {
86 RooAbsPdf *channelPdf = simPdf->getPdf(nameIdx.first);
89 const std::string prefix =
"_" + nameIdx.first +
"_";
90 std::unique_ptr<RooArgSet> vars{channelPdf->
getVariables()};
91 std::unique_ptr<RooArgSet> obs{vars->selectByAttrib(
"__obs__",
true)};
93 auto *realVar =
dynamic_cast<RooRealVar *
>(arg);
97 if (it == dataSpans.end())
99 std::string obsName = realVar->GetName();
100 if (obsName.rfind(prefix, 0) == 0) {
101 obsName = obsName.substr(prefix.size());
103 checkObservableSpanInRange(*realVar, obsName,
data.GetName(), it->second);
112 auto *realVar =
dynamic_cast<RooRealVar *
>(arg);
116 if (it == dataSpans.end())
118 checkObservableSpanInRange(*realVar, realVar->GetName(),
data.GetName(), it->second);
127 std::string
const &rangeName,
RooAbsPdf const *pdf,
128 bool takeGlobalObservablesFromData,
int nWorkers)
129 :
RooAbsReal{
"RooEvaluatorWrapper",
"RooEvaluatorWrapper"},
130 _evaluator{std::make_unique<
RooFit::Evaluator>(topNode, useGPU)},
131 _topNode(
"topNode",
"top node", this, topNode, false, false),
133 _paramSet(
"paramSet",
"Set of parameters", this),
134 _rangeName{rangeName},
136 _takeGlobalObservablesFromData{takeGlobalObservablesFromData}
138 if (nWorkers > 1 && !useGPU) {
139 _evaluator->setNThreads(nWorkers);
142 setData(*
data,
false);
144 _paramSet.add(_evaluator->getParameters());
145 for (
auto const &item : _dataSpans) {
146 _paramSet.remove(*_paramSet.find(item.first->GetName()));
150RooEvaluatorWrapper::RooEvaluatorWrapper(
const RooEvaluatorWrapper &other,
const char *
name)
152 _evaluator{other._evaluator},
153 _topNode(
"topNode", this, other._topNode),
155 _paramSet(
"paramSet",
"Set of parameters", this),
156 _rangeName{other._rangeName},
158 _takeGlobalObservablesFromData{other._takeGlobalObservablesFromData},
159 _dataSpans{other._dataSpans}
161 _paramSet.add(other._paramSet);
164RooEvaluatorWrapper::~RooEvaluatorWrapper() =
default;
166bool RooEvaluatorWrapper::getParameters(
const RooArgSet *observables,
RooArgSet &outputSet,
167 bool stripDisconnected)
const
169 outputSet.
add(_evaluator->getParameters());
171 outputSet.
remove(*observables,
false,
true);
174 for (
auto const &item : _dataSpans) {
175 if (_data->getGlobalObservables() && _data->getGlobalObservables()->find(item.first->GetName())) {
187 if (_takeGlobalObservablesFromData && _data->getGlobalObservables()) {
188 outputSet.
replace(*_data->getGlobalObservables());
195 if (stripDisconnected) {
197 _topNode->getParameters(observables, paramsStripped,
true);
200 if (!paramsStripped.
find(param->GetName())) {
201 toRemove.
add(*param);
204 outputSet.
remove(toRemove,
false,
true);
214class RooFuncWrapper {
217 std::string
const &rangeName,
bool skipZeroWeights);
219 bool hasGradient()
const {
return _hasGradient; }
220 bool hasHessian()
const {
return _hasHessian; }
221 void gradient(
double *out)
const
223 updateGradientVarBuffer();
224 std::fill(out, out + _params.size(), 0.0);
225 _grad(_varBuffer.data(), _observables.data(), _xlArr.data(), out);
227 void hessian(
double *out)
const
229 updateGradientVarBuffer();
230 std::fill(out, out + _params.size() * _params.size(), 0.0);
231 _hessian(_varBuffer.data(), _observables.data(), _xlArr.data(), out);
234 void createGradient();
235 void createHessian();
237 void writeDebugMacro(std::string
const &)
const;
239 std::vector<std::string>
const &collectedFunctions() {
return _collectedFunctions; }
243 updateGradientVarBuffer();
244 return _func(_varBuffer.data(), _observables.data(), _xlArr.data());
251 void updateGradientVarBuffer()
const;
253 void buildFuncAndGradFunctors();
255 using Func =
double (*)(
double *,
double const *,
double const *);
256 using Grad = void (*)(
double *,
double const *,
double const *,
double *);
257 using Hessian = void (*)(
double *,
double const *,
double const *,
double *);
260 std::string _funcName;
264 bool _hasGradient =
false;
265 bool _hasHessian =
false;
266 mutable std::vector<double> _varBuffer;
267 std::vector<double> _observables;
268 std::unordered_map<RooFit::Detail::DataKey, std::size_t> _obsInfos;
269 std::vector<double> _xlArr;
270 std::vector<std::string> _collectedFunctions;
275void replaceAll(std::string &str,
const std::string &from,
const std::string &to)
279 size_t start_pos = 0;
280 while ((start_pos = str.find(from, start_pos)) != std::string::npos) {
281 str.replace(start_pos, from.length(), to);
282 start_pos += to.length();
291 std::unordered_set<RooFit::Detail::DataKey> dependsOnData;
293 dependsOnData.insert(arg);
297 if (arg->getAttribute(
"__obs__")) {
298 dependsOnData.insert(arg);
300 for (
RooAbsArg *server : arg->servers()) {
301 if (server->isValueServer(*arg)) {
302 if (dependsOnData.find(server) != dependsOnData.end() && !arg->isReducerNode()) {
303 dependsOnData.insert(arg);
310 return dependsOnData;
316 RooArgSet const ¶mSet, std::string
const &rangeName,
bool skipZeroWeights)
320 loadData(*
data, simPdf, rangeName, skipZeroWeights);
324 for (
auto *param : paramSet) {
325 if (_obsInfos.find(param) == _obsInfos.end()) {
329 _varBuffer.resize(_params.size());
332 std::unordered_set<RooFit::Detail::DataKey> dependsOnData;
334 dependsOnData = getDependsOnData(obj, *
data->get());
343 ctx.
addResult(param,
"params[" + std::to_string(idx) +
"]");
347 for (
auto const &item : _obsInfos) {
348 const char *obsName = item.first->GetName();
354 auto print = [](std::string
const &msg) {
oocoutI(
nullptr, Fitting) << msg << std::endl; };
359 gInterpreter->Declare(
"#include <RooFit/CodegenImpl.h>\n");
362 std::stringstream errorMsg;
363 std::string debugFileName =
"_codegen_" + _funcName +
".cxx";
364 errorMsg <<
"Function " << _funcName <<
" could not be compiled. See above for details. Full code dumped to file "
365 << debugFileName <<
" for debugging";
367 std::ofstream outFile;
368 outFile.open(debugFileName.c_str());
371 oocoutE(
nullptr, InputArguments) << errorMsg.str() << std::endl;
372 throw std::runtime_error(errorMsg.str().c_str());
375 _func =
reinterpret_cast<Func
>(
gInterpreter->ProcessLine((_funcName +
";").c_str()));
377 _xlArr = ctx.
xlArr();
382 bool skipZeroWeights)
385 std::stack<std::vector<double>> vectorBuffers;
387 RooFit::BatchModeDataHelpers::getDataSpans(
data, rangeName, simPdf, skipZeroWeights,
false, vectorBuffers);
389 _observables.clear();
391 std::size_t
total = 0;
392 _observables.reserve(2 * spans.size());
394 for (
auto const &item : spans) {
395 _obsInfos.emplace(item.first, idx);
396 _observables.push_back(
total + 2 * spans.size());
397 _observables.push_back(item.second.size());
398 total += item.second.size();
402 for (
auto const &item : spans) {
403 std::size_t
n = item.second.size();
404 _observables.reserve(_observables.size() +
n);
405 for (std::size_t i = 0; i <
n; ++i) {
406 _observables.push_back(item.second[i]);
412void RooFuncWrapper::createGradient()
415 std::string gradName = _funcName +
"_grad_0";
416 std::string requestName = _funcName +
"_req";
419 gInterpreter->Declare(
"#include <Math/CladDerivator.h>\n");
422 std::stringstream requestFuncStrm;
423 requestFuncStrm <<
"#pragma clad ON\n"
424 "void " << requestName <<
"() {\n"
425 " clad::gradient(" << _funcName <<
", \"params\");\n"
429 auto print = [](std::string
const &msg) {
oocoutI(
nullptr, Fitting) << msg << std::endl; };
431 bool cladSuccess =
false;
434 cladSuccess = !
gInterpreter->Declare(requestFuncStrm.str().c_str());
437 std::stringstream errorMsg;
438 errorMsg <<
"Function could not be differentiated. See above for details.";
439 oocoutE(
nullptr, InputArguments) << errorMsg.str() << std::endl;
440 throw std::runtime_error(errorMsg.str().c_str());
446 std::stringstream ss;
448 ss <<
"static_cast<void (*)(double *, double const *, double const *, double *)>(" << gradName <<
");";
449 _grad =
reinterpret_cast<Grad
>(
gInterpreter->ProcessLine(ss.str().c_str()));
452 _hasGradient =
false;
453 std::stringstream errorMsg;
454 errorMsg <<
"Function could not be differentiated since ROOT was built without Clad support.";
455 oocoutE(
nullptr, InputArguments) << errorMsg.str() << std::endl;
456 throw std::runtime_error(errorMsg.str().c_str());
460void RooFuncWrapper::createHessian()
463 std::string hessianName = _funcName +
"_hessian_0";
464 std::string requestName = _funcName +
"_hessian_req";
467 gInterpreter->Declare(
"#include <Math/CladDerivator.h>\n");
470 std::stringstream requestFuncStrm;
471 std::string paramsStr =
472 _params.size() == 1 ?
"\"params[0]\"" : (
"\"params[0:" + std::to_string(_params.size() - 1) +
"]\"");
473 requestFuncStrm <<
"#pragma clad ON\n"
474 "void " << requestName <<
"() {\n"
475 " clad::hessian(" << _funcName <<
", " << paramsStr <<
");\n"
479 auto print = [](std::string
const &msg) {
oocoutI(
nullptr, Fitting) << msg << std::endl; };
481 bool cladSuccess =
false;
484 cladSuccess = !
gInterpreter->Declare(requestFuncStrm.str().c_str());
487 std::stringstream errorMsg;
488 errorMsg <<
"Function could not be differentiated. See above for details.";
489 oocoutE(
nullptr, InputArguments) << errorMsg.str() << std::endl;
490 throw std::runtime_error(errorMsg.str().c_str());
496 std::stringstream ss;
498 ss <<
"static_cast<void (*)(double *, double const *, double const *, double *)>(" << hessianName <<
");";
499 _hessian =
reinterpret_cast<Hessian
>(
gInterpreter->ProcessLine(ss.str().c_str()));
503 std::stringstream errorMsg;
504 errorMsg <<
"Function could not be differentiated since ROOT was built without Clad support.";
505 oocoutE(
nullptr, InputArguments) << errorMsg.str() << std::endl;
506 throw std::runtime_error(errorMsg.str().c_str());
510void RooFuncWrapper::updateGradientVarBuffer()
const
512 std::transform(_params.begin(), _params.end(), _varBuffer.begin(), [](
RooAbsArg *obj) {
513 return obj->isCategory() ? static_cast<RooAbsCategory *>(obj)->getCurrentIndex()
514 : static_cast<RooAbsReal *>(obj)->getVal();
519void RooFuncWrapper::writeDebugMacro(std::string
const &
filename)
const
521 std::stringstream allCode;
522 std::set<std::string> seenFunctions;
525 for (std::string
const &
name : _collectedFunctions) {
526 if (seenFunctions.count(
name) > 0) {
529 seenFunctions.insert(
name);
530 std::unique_ptr<TInterpreterValue>
v =
gInterpreter->MakeInterpreterValue();
532 std::string s =
v->ToString();
533 for (
int i = 0; i < 2; ++i) {
534 s = s.erase(0, s.find(
"\n") + 1);
536 allCode << s << std::endl;
539 std::ofstream outFile;
540 std::string paramsStr =
541 _params.size() == 1 ?
"\"params[0]\"" : (
"\"params[0:" + std::to_string(_params.size() - 1) +
"]\"");
543 outFile << R
"(//auto-generated test macro
544#include <RooFit/Detail/MathFuncs.h>
545#include <Math/CladDerivator.h>
552void gradient_request() {
554 << _funcName << R"(, "params");
557 << _funcName << ", " << paramsStr << R
"();
563 updateGradientVarBuffer();
565 auto writeVector = [&](std::string
const &
name, std::span<const double> vec) {
566 std::stringstream decl;
567 decl <<
"std::vector<double> " <<
name <<
" = {";
568 for (std::size_t i = 0; i < vec.size(); ++i) {
572 if (i < vec.size() - 1)
577 std::string declStr = decl.str();
579 replaceAll(declStr,
"inf",
"std::numeric_limits<double>::infinity()");
585 outFile <<
"// clang-format off\n" << std::endl;
586 writeVector(
"parametersVec", _varBuffer);
587 outFile << std::endl;
588 writeVector(
"observablesVec", _observables);
589 outFile << std::endl;
590 writeVector(
"auxConstantsVec", _xlArr);
591 outFile << std::endl;
592 outFile <<
"// clang-format on\n" << std::endl;
595// To run as a ROOT macro
599 const std::size_t n = parametersVec.size();
601 std::vector<double> gradientVec(n);
603 auto func = [&](std::span<double> params) {
605 << _funcName << R"((params.data(), observablesVec.data(), auxConstantsVec.data());
607 auto grad = [&](std::span<double> params, std::span<double> out) {
609 << _funcName << R"(_grad_0(parametersVec.data(), observablesVec.data(), auxConstantsVec.data(),
613 grad(parametersVec, gradientVec);
615 auto numDiff = [&](int i) {
616 const double eps = 1e-6;
617 std::vector<double> p{parametersVec};
618 p[i] = parametersVec[i] - eps;
619 double funcValDown = func(p);
620 p[i] = parametersVec[i] + eps;
621 double funcValUp = func(p);
622 return (funcValUp - funcValDown) / (2 * eps);
625 for (std::size_t i = 0; i < parametersVec.size(); ++i) {
626 std::cout << i << ":" << std::endl;
627 std::cout << " numr : " << numDiff(i) << std::endl;
628 std::cout << " clad : " << gradientVec[i] << std::endl;
634 auto hess = [&](std::span<double> params, std::span<double> out) {
636 << _funcName << R"(_hessian_0(params.data(), observablesVec.data(), auxConstantsVec.data(), out.data());
639 std::vector<double> hessianVec(n * n);
640 hess(parametersVec, hessianVec);
642 // ---------- Numerical Hessian ----------
643 // Uses central differences:
644 // diag: (f(x+ei)-2f(x)+f(x-ei))/eps^2
645 // offdiag: (f(++ ) - f(+-) - f(-+) + f(--)) / (4 eps^2)
646 auto numHess = [&](std::size_t i, std::size_t j) {
647 const double eps = 1e-5; // often needs to be a bit larger than grad eps
648 std::vector<double> p(parametersVec.begin(), parametersVec.end());
651 const double f0 = func(p);
653 p[i] = parametersVec[i] + eps;
654 const double fUp = func(p);
656 p[i] = parametersVec[i] - eps;
657 const double fDown = func(p);
659 return (fUp - 2.0 * f0 + fDown) / (eps * eps);
661 // f(x_i + eps, x_j + eps)
662 p[i] = parametersVec[i] + eps;
663 p[j] = parametersVec[j] + eps;
664 const double fPP = func(p);
666 // f(x_i + eps, x_j - eps)
667 p[i] = parametersVec[i] + eps;
668 p[j] = parametersVec[j] - eps;
669 const double fPM = func(p);
671 // f(x_i - eps, x_j + eps)
672 p[i] = parametersVec[i] - eps;
673 p[j] = parametersVec[j] + eps;
674 const double fMP = func(p);
676 // f(x_i - eps, x_j - eps)
677 p[i] = parametersVec[i] - eps;
678 p[j] = parametersVec[j] - eps;
679 const double fMM = func(p);
681 return (fPP - fPM - fMP + fMM) / (4.0 * eps * eps);
685 // Compute full numerical Hessian
686 std::vector<double> numHessianVec(n * n);
687 for (std::size_t i = 0; i < n; ++i) {
688 for (std::size_t j = 0; j < n; ++j) {
689 numHessianVec[i + n * j] = numHess(i, j); // keep same layout as your print
693 // ---------- Compare & print ----------
694 std::cout << "Hessian comparison (clad vs numeric vs diff):\n\n";
696 for (std::size_t i = 0; i < n; ++i) {
697 for (std::size_t j = 0; j < n; ++j) {
698 const std::size_t idx = i + n * j; // same indexing you used
699 const double cladH = hessianVec[idx];
700 const double numH = numHessianVec[idx];
701 const double diff = cladH - numH;
703 std::cout << "[" << i << "," << j << "] "
704 << "clad=" << cladH << " num=" << numH << " diff=" << diff << "\n";
708 std::cout << "\nRaw Clad Hessian matrix:\n";
709 for (std::size_t i = 0; i < n; ++i) {
710 for (std::size_t j = 0; j < n; ++j) {
711 std::cout << hessianVec[i + n * j] << " ";
716 std::cout << "\nRaw Numerical Hessian matrix:\n";
717 for (std::size_t i = 0; i < n; ++i) {
718 for (std::size_t j = 0; j < n; ++j) {
719 std::cout << numHessianVec[i + n * j] << " ";
728double RooEvaluatorWrapper::evaluate()
const
730 if (_useGeneratedFunctionCode)
731 return _funcWrapper->evaluate();
737 :
RooFit::EvalContext::OffsetMode::WithOffset);
739 return _evaluator->run()[0];
748 constexpr auto errMsg =
"Error in RooAbsReal::setData(): only resetting with same-structured data is supported.";
751 bool isInitializing = _paramSet.empty();
752 const std::size_t oldSize = _dataSpans.size();
754 std::stack<std::vector<double>>{}.swap(_vectorBuffers);
755 const bool isChi2 = _topNode->getAttribute(
"Chi2EvaluationActive");
756 bool skipZeroWeights = !isChi2 && (!_pdf || !_pdf->getAttribute(
"BinnedLikelihoodActive"));
758 _dataSpans = RooFit::BatchModeDataHelpers::getDataSpans(*_data, _rangeName, simPdf, skipZeroWeights,
759 _takeGlobalObservablesFromData, _vectorBuffers);
760 if (_rangeName.empty()) {
761 validateObservableRanges(_pdf, *_data, _dataSpans);
763 if (!isInitializing && _dataSpans.size() != oldSize) {
764 coutE(DataHandling) << errMsg << std::endl;
765 throw std::runtime_error(errMsg);
767 for (
auto const &item : _dataSpans) {
768 const char *
name = item.first->GetName();
769 _evaluator->setInput(
name, item.second,
false);
770 if (_paramSet.find(
name)) {
771 coutE(DataHandling) << errMsg << std::endl;
772 throw std::runtime_error(errMsg);
776 _funcWrapper->loadData(*_data, simPdf, _rangeName, skipZeroWeights);
781void RooEvaluatorWrapper::createFuncWrapper()
785 this->getParameters(_data ? _data->get() : nullptr, paramSet, false);
787 const bool isChi2 = _topNode->getAttribute(
"Chi2EvaluationActive");
788 const bool skipZeroWeights = !isChi2 && (!_pdf || !_pdf->getAttribute(
"BinnedLikelihoodActive"));
789 _funcWrapper = std::make_unique<RooFuncWrapper>(*_topNode, _data,
dynamic_cast<RooSimultaneous const *
>(_pdf),
790 paramSet, _rangeName, skipZeroWeights);
793void RooEvaluatorWrapper::generateGradient()
797 if (!_funcWrapper->hasGradient())
798 _funcWrapper->createGradient();
801void RooEvaluatorWrapper::generateHessian()
805 if (!_funcWrapper->hasHessian())
806 _funcWrapper->createHessian();
809void RooEvaluatorWrapper::setUseGeneratedFunctionCode(
bool flag)
811 _useGeneratedFunctionCode = flag;
812 if (!_funcWrapper && _useGeneratedFunctionCode)
816void RooEvaluatorWrapper::gradient(
double *out)
const
818 _funcWrapper->gradient(out);
821void RooEvaluatorWrapper::hessian(
double *out)
const
823 _funcWrapper->hessian(out);
826bool RooEvaluatorWrapper::hasGradient()
const
828 return _funcWrapper && _funcWrapper->hasGradient();
831bool RooEvaluatorWrapper::hasHessian()
const
833 return _funcWrapper && _funcWrapper->hasHessian();
836void RooEvaluatorWrapper::writeDebugMacro(std::string
const &
filename)
const
839 return _funcWrapper->writeDebugMacro(
filename);
842std::unique_ptr<ChangeOperModeRAII> RooEvaluatorWrapper::setOperModes(
RooAbsArg::OperMode opMode)
844 return _evaluator->setOperModes(opMode);
static unsigned int total
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void data
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 filename
Common abstract base class for objects that represent a value and a "shape" in RooFit.
RooFit::OwningPtr< RooArgSet > getObservables(const RooArgSet &set, bool valueOnly=true) const
Given a set of possible observables, return the observables that this PDF depends on.
RooFit::OwningPtr< RooArgSet > getVariables(bool stripDisconnected=true) const
Return RooArgSet with all variables (tree leaf nodes of expression tree)
virtual bool remove(const RooAbsArg &var, bool silent=false, bool matchByNameOnly=false)
Remove the specified argument from our list.
virtual bool add(const RooAbsArg &var, bool silent=false)
Add the specified argument to list.
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 binned and unbinned datasets.
Abstract interface for all probability density functions.
virtual double getMax(const char *name=nullptr) const
Get maximum of currently defined range.
virtual double getMin(const char *name=nullptr) const
Get minimum of currently defined range.
bool inRange(const char *name) const override
Check if current value is inside range with given name.
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.
A class to maintain the context for squashing of RooFit models into code.
void addResult(RooAbsArg const *key, std::string const &value)
A function to save an expression that includes/depends on the result of the input node.
void addVecObs(const char *key, int idx)
Since the squashed code represents all observables as a single flattened array, it is important to ke...
std::string buildFunction(RooAbsArg const &arg, std::unordered_set< RooFit::Detail::DataKey > const &dependsOnData={})
Assemble and return the final code with the return expression and global statements.
std::vector< std::string > const & collectedFunctions()
std::string const & collectedCode()
std::vector< double > const & xlArr()
Variable that can be changed from the outside.
Facilitates simultaneous fitting of multiple PDFs to subsets of a given dataset.
void replaceAll(std::string &inOut, std::string_view what, std::string_view with)
The namespace RooFit contains mostly switches that change the behaviour of functions of PDFs (or othe...
void getSortedComputationGraph(RooAbsArg const &func, RooArgSet &out)
void evaluate(typename Architecture_t::Tensor_t &A, EActivationFunction f)
Apply the given activation function to each value in the given tensor A.