57 create(
RooFactoryWSTool &ft,
const char *typeName,
const char *instanceName, std::vector<std::string> args)
override;
73bool makeAndCompileClass(std::string
const &baseClassName, std::string
const &
name, std::string
const &expression,
74 const RooArgList &vars, std::string
const &intExpression)
80 ClassInfo(std::string
const &baseClassName, std::string
const &
name, std::string
const &expression,
81 const RooArgList &vars, std::string
const &intExpression)
82 : _baseClassName{baseClassName}, _name{
name}, _expression{expression}, _intExpression{intExpression}
84 _argNames.reserve(vars.
size());
85 _argsAreCategories.reserve(vars.
size());
87 _argNames.emplace_back(arg->GetName());
88 _argsAreCategories.emplace_back(arg->isCategory());
93 return other._baseClassName == _baseClassName && other._name == _name && other._expression == _expression &&
94 other._argNames == _argNames && other._argsAreCategories == _argsAreCategories &&
95 other._intExpression == _intExpression;
98 std::string _baseClassName;
100 std::string _expression;
101 std::vector<std::string> _argNames;
102 std::vector<bool> _argsAreCategories;
103 std::string _intExpression;
106 static std::vector<ClassInfo> infosVec;
107 static std::mutex infosVecMutex;
109 ClassInfo info{baseClassName,
name, expression, vars, intExpression};
112 auto found = std::find_if(infosVec.begin(), infosVec.end(), [&](
auto const &elem) { return elem._name == name; });
113 if (found != infosVec.end()) {
114 if (*found == info) {
117 std::stringstream ss;
118 ss <<
"RooClassFactory ERROR The type, expressions, or variables for the class \"" <<
name
119 <<
"\" are not identical to what you passed last time this class was compiled! This is not allowed.";
120 oocoutE(
nullptr, InputArguments) << ss.str() << std::endl;
121 throw std::runtime_error(ss.str());
125 const std::lock_guard<std::mutex> lock(infosVecMutex);
127 infosVec.emplace_back(info);
129 std::string realArgNames, catArgNames;
132 if (!realArgNames.empty())
134 realArgNames += arg->GetName();
135 }
else if (arg->isCategory()) {
136 if (!catArgNames.empty())
138 catArgNames += arg->GetName();
140 oocoutE(
nullptr, InputArguments) <<
"RooClassFactory ERROR input argument " << arg->GetName()
141 <<
" is neither RooAbsReal nor RooAbsCategory and is ignored" << endl;
146 !intExpression.empty(),
false, intExpression);
156RooAbsReal *makeClassInstance(std::string
const &baseClassName, std::string
const &className, std::string
const &
name,
157 std::string
const &expression,
const RooArgList &vars, std::string
const &intExpression)
160 bool error = makeAndCompileClass(baseClassName, className, expression, vars, intExpression);
168 std::string
line = std::string(
"new ") + className +
"(\"" +
name +
"\",\"" +
name +
"\"";
178 argList +=
Form(
",*reinterpret_cast<RooAbsReal*>(0x%zx)", (std::size_t)var);
183 if (var->isCategory()) {
184 argList +=
Form(
",*reinterpret_cast<RooAbsCategory*>(0x%zx)", (std::size_t)var);
188 line += argList +
") ;";
199 std::string
const &intExpression)
201 return makeAndCompileClass(
"RooAbsPdf",
name, expression, vars, intExpression);
218 const RooArgList &vars, std::string
const &intExpression)
220 return makeAndCompileClass(
"RooAbsReal",
name, expression, vars, intExpression);
244 const RooArgList &vars, std::string
const &intExpression)
247 std::string tmpName(
name);
248 tmpName[0] = toupper(tmpName[0]);
249 string className =
"Roo" + tmpName +
"Func";
275 std::string
const &expression,
const RooArgList &vars,
276 std::string
const &intExpression)
278 return static_cast<RooAbsReal *
>(makeClassInstance(
"RooAbsRal", className,
name, expression, vars, intExpression));
289 const RooArgList &vars, std::string
const &intExpression)
292 std::string tmpName(
name);
293 tmpName[0] = toupper(tmpName[0]);
294 string className =
"Roo" + tmpName +
"Pdf";
320 std::string
const &expression,
const RooArgList &vars,
321 std::string
const &intExpression)
323 return static_cast<RooAbsPdf *
>(makeClassInstance(
"RooAbsPdf", className,
name, expression, vars, intExpression));
335 std::string
const &expression,
bool hasAnaInt,
bool hasIntGen,
336 std::string
const &intExpression)
338 return makeClass(
"RooAbsPdf",
name, argNames, catArgNames, expression, hasAnaInt, hasIntGen, intExpression);
358 std::string
const &expression,
bool hasAnaInt, std::string
const &intExpression)
360 return makeClass(
"RooAbsReal",
name, argNames, catArgNames, expression, hasAnaInt,
false, intExpression);
365std::string listVars(std::vector<std::string>
const &alist, std::vector<bool>
const &isCat = {})
367 std::stringstream ss;
368 for (std::size_t i = 0; i < alist.size(); ++i) {
369 if (!isCat.empty()) {
370 ss << (isCat[i] ?
"int" :
"double") <<
" ";
373 if (i < alist.size() - 1) {
380std::string declareVarSpans(std::vector<std::string>
const &alist)
382 std::stringstream ss;
383 for (std::size_t i = 0; i < alist.size(); ++i) {
385 <<
"std::span<const double> " << alist[i] <<
"Span = dataMap.at(" << alist[i] <<
");\n";
390std::string getFromVarSpans(std::vector<std::string>
const &alist)
392 std::stringstream ss;
393 for (std::size_t i = 0; i < alist.size(); ++i) {
394 std::string
name = alist[i] +
"Span";
395 ss <<
name <<
".size() > 1 ? " <<
name <<
"[i] : " <<
name <<
"[0]";
396 if (i < alist.size() - 1) {
404void replaceAll(std::string &inOut, std::string_view
what, std::string_view with)
406 for (std::string::size_type pos{}; inOut.npos != (pos = inOut.find(
what.data(), pos,
what.length()));
407 pos += with.length()) {
408 inOut.replace(pos,
what.length(), with.data(), with.length());
412inline bool isSpecial(
char c)
414 return c !=
'_' && !std::isalnum(
c);
417bool isComplex(std::string
const &expression)
421 for (std::size_t i = 0; i < expression.size(); ++i) {
422 bool leftOkay = (i == 0) || isSpecial(expression[i - 1]);
423 bool rightOkay = (i == expression.size() - 1) || isSpecial(expression[i + 1]);
424 if (expression[i] ==
'I' && leftOkay && rightOkay)
451 std::string
const &realArgNames, std::string
const &catArgNames,
452 std::string
const &expression,
bool hasAnaInt,
bool hasIntGen,
453 std::string
const &intExpression)
457 if (realArgNames.empty() && catArgNames.empty()) {
458 oocoutE(
nullptr, InputArguments)
459 <<
"RooClassFactory::makeClass: ERROR: A list of input argument names must be given" << endl;
463 if (!intExpression.empty() && !hasAnaInt) {
464 oocoutE(
nullptr, InputArguments) <<
"RooClassFactory::makeClass: ERROR no analytical integration code "
465 "requestion, but expression for analytical integral provided"
471 vector<string> alist;
474 for (
auto const &token :
ROOT::Split(realArgNames,
",",
true)) {
475 alist.push_back(token);
476 isCat.push_back(
false);
478 for (
auto const &token :
ROOT::Split(catArgNames,
",",
true)) {
479 alist.push_back(token);
480 isCat.push_back(
true);
484 std::stringstream hf;
485 hf << R
"(/*****************************************************************************
488 * This code was autogenerated by RooClassFactory *
489 *****************************************************************************/
494#include <BASE_NAME.h>
495#include <RooRealProxy.h>
496#include <RooCategoryProxy.h>
497#include <RooAbsReal.h>
498#include <RooAbsCategory.h>
502class CLASS_NAME : public BASE_NAME {
505 CLASS_NAME(const char *name, const char *title,)";
509 for (i=0 ; i<alist.size() ; i++) {
511 hf <<
" RooAbsReal& _" ;
513 hf <<
" RooAbsCategory& _" ;
516 if (i==alist.size()-1) {
523 hf << R
"( CLASS_NAME(CLASS_NAME const &other, const char *name=nullptr);
524 TObject* clone(const char *newname) const override { return new CLASS_NAME(*this, newname); }
529 int getAnalyticalIntegral(RooArgSet& allVars, RooArgSet& analVars, const char *rangeName=nullptr) const override;
530 double analyticalIntegral(int code, const char *rangeName=nullptr) const override;
536 int getGenerator(const RooArgSet& directVars, RooArgSet &generateVars, bool staticInitOK=true) const override;
537 void initGenerator(int code) override {} // optional pre-generation initialization
538 void generateEvent(int code) override;
542 hf << "protected:" << endl
546 for (i=0 ; i<alist.size() ; i++) {
548 hf <<
" RooRealProxy " << alist[i] <<
" ;" << endl ;
550 hf <<
" RooCategoryProxy " << alist[i] <<
" ;" << endl ;
555 double evaluate() const override;
556 void computeBatch(double* output, std::size_t size, RooFit::Detail::DataMap const&) const override;
557 void translate(RooFit::Detail::CodeSquashContext &ctx) const override;
561 ClassDefOverride(CLASS_NAME, 1) // Your description goes here...
566 << "inline double CLASS_NAME_evaluate(" << listVars(alist, isCat) <<
") ";
571 if (isComplex(expression)) {
573 // Support also using the imaginary unit
574 using namespace std::complex_literals;
575 // To be able to also comile C code, we define a variable that behaves like the "I" macro from C.
576 constexpr auto I = 1i;
581 // ENTER EXPRESSION IN TERMS OF VARIABLE ARGUMENTS HERE
584 << " return " << expression <<
"; " << endl
588 hf <<
"\n#endif // CLASS_NAME_h";
590 std::stringstream cf;
592 cf << R
"(/*****************************************************************************
595 * This code was autogenerated by RooClassFactory *
596 *****************************************************************************/
598// Your description goes here...
600#include "CLASS_NAME.h"
602#include <RooAbsReal.h>
603#include <RooAbsCategory.h>
605#include <Riostream.h>
612CLASS_NAME::CLASS_NAME(const char *name, const char *title,
616 for (i=0 ; i<alist.size() ; i++) {
618 cf <<
" RooAbsReal& _" << alist[i] ;
620 cf <<
" RooAbsCategory& _" << alist[i] ;
622 if (i<alist.size()-1) {
631 cf <<
" : BASE_NAME(name,title)," << endl ;
634 for (i=0 ; i<alist.size() ; i++) {
635 cf <<
" " << alist[i] <<
"(\"" << alist[i] <<
"\",\"" << alist[i] <<
"\",this,_" << alist[i] <<
")" ;
636 if (i<alist.size()-1) {
646 <<
"CLASS_NAME::CLASS_NAME(CLASS_NAME const &other, const char *name)" << endl
647 <<
" : BASE_NAME(other,name)," << endl ;
649 for (i=0 ; i<alist.size() ; i++) {
650 cf <<
" " << alist[i] <<
"(\"" << alist[i] <<
"\",this,other." << alist[i] <<
")" ;
651 if (i<alist.size()-1) {
661 <<
"double CLASS_NAME::evaluate() const " << endl
663 <<
" return CLASS_NAME_evaluate(" << listVars(alist) <<
"); " << endl
666 <<
"void CLASS_NAME::computeBatch(double *output, std::size_t size, RooFit::Detail::DataMap const &dataMap) const " << endl
668 << declareVarSpans(alist)
670 <<
" for (std::size_t i = 0; i < size; ++i) {\n"
671 <<
" output[i] = CLASS_NAME_evaluate(" << getFromVarSpans(alist) <<
");\n"
675cf <<
"void CLASS_NAME::translate(RooFit::Detail::CodeSquashContext &ctx) const\n"
677<<
" ctx.addResult(this, ctx.buildCall(\"CLASS_NAME_evaluate\", " << listVars(alist) <<
"));\n"
682 vector<string> intObs ;
683 vector<string> intExpr ;
686 if (!intExpression.empty()) {
687 const std::size_t bufSize = intExpression.size()+1;
688 std::vector<char> buf(bufSize);
689 strlcpy(buf.data(),intExpression.c_str(),bufSize) ;
690 char* ptr = strtok(buf.data(),
":") ;
692 intObs.push_back(ptr) ;
693 intExpr.push_back(strtok(
nullptr,
";")) ;
694 ptr = strtok(
nullptr,
":") ;
699int CLASS_NAME::getAnalyticalIntegral(RooArgSet& allVars, RooArgSet& analVars, const char */*rangeName*/) const
701 // Support also using the imaginary unit
702 using namespace std::complex_literals;
703 // To be able to also comile C code, we define a variable that behaves like the "I" macro from C.
704 constexpr auto I = 1i;
706 // LIST HERE OVER WHICH VARIABLES ANALYTICAL INTEGRATION IS SUPPORTED,
707 // ASSIGN A NUMERIC CODE FOR EACH SUPPORTED (SET OF) PARAMETERS. THE EXAMPLE
708 // BELOW ASSIGNS CODE 1 TO INTEGRATION OVER VARIABLE X YOU CAN ALSO
709 // IMPLEMENT MORE THAN ONE ANALYTICAL INTEGRAL BY REPEATING THE matchArgs
710 // EXPRESSION MULTIPLE TIMES.
713 if (!intObs.empty()) {
714 for (std::size_t ii=0 ; ii<intObs.size() ; ii++) {
715 cf <<
" if (matchArgs(allVars,analVars," << intObs[ii] <<
")) return " << ii+1 <<
" ; " << endl ;
718 cf <<
" // if (matchArgs(allVars,analVars,x)) return 1 ; " << endl ;
721 cf <<
" return 0 ; " << endl
726 << R
"(double CLASS_NAME::analyticalIntegral(int code, const char *rangeName) const
728 // RETURN ANALYTICAL INTEGRAL DEFINED BY RETURN CODE ASSIGNED BY
729 // getAnalyticalIntegral(). THE MEMBER FUNCTION x.min(rangeName) AND
730 // x.max(rangeName) WILL RETURN THE INTEGRATION BOUNDARIES FOR EACH
734 if (!intObs.empty()) {
735 for (std::size_t ii=0 ; ii<intObs.size() ; ii++) {
736 cf <<
" if (code==" << ii+1 <<
") { return (" << intExpr[ii] <<
") ; } " << endl ;
739 cf <<
" // assert(code==1) ; " << endl
740 <<
" // return (x.max(rangeName)-x.min(rangeName)) ; " << endl ;
743 cf <<
" return 0 ; " << endl
749int CLASS_NAME::getGenerator(const RooArgSet &directVars, RooArgSet &generateVars, bool /*staticInitOK*/) const
751 // LIST HERE OVER WHICH VARIABLES INTERNAL GENERATION IS SUPPORTED, ASSIGN A
752 // NUMERIC CODE FOR EACH SUPPORTED (SET OF) PARAMETERS. THE EXAMPLE BELOW
753 // ASSIGNS CODE 1 TO INTEGRATION OVER VARIABLE X. YOU CAN ALSO IMPLEMENT
754 // MORE THAN ONE GENERATOR CONFIGURATION BY REPEATING THE matchArgs
755 // EXPRESSION MULTIPLE TIMES. IF THE FLAG staticInitOK IS TRUE, THEN IT IS
756 // SAFE TO PRECALCULATE INTERMEDIATE QUANTITIES IN initGenerator(), IF IT IS
757 // NOT SET THEN YOU SHOULD NOT ADVERTISE ANY GENERATOR METHOD THAT RELIES ON
758 // PRECALCULATIONS IN initGenerator().
760 // if (matchArgs(directVars,generateVars,x)) return 1;
764void CLASS_NAME::generateEvent(int code)
766 // GENERATE SET OF OBSERVABLES DEFINED BY RETURN CODE ASSIGNED BY
767 // getGenerator(). RETURN THE GENERATED VALUES BY ASSIGNING THEM TO THE
768 // PROXY DATA MEMBERS THAT REPRESENT THE CHOSEN OBSERVABLES.
779 std::ofstream ohf(className +
".h");
780 std::ofstream ocf(className +
".cxx");
781 std::string headerCode = hf.str();
782 std::string sourceCode = cf.str();
783 replaceAll(headerCode,
"CLASS_NAME", className);
784 replaceAll(sourceCode,
"CLASS_NAME", className);
785 replaceAll(headerCode,
"BASE_NAME", baseName);
786 replaceAll(sourceCode,
"BASE_NAME", baseName);
797std::string ClassFacIFace::create(
RooFactoryWSTool &ft,
const char *typeName,
const char *instanceName,
798 std::vector<std::string> args)
800 static int classCounter = 0;
804 if (args.size() < 2) {
805 throw std::runtime_error(
Form(
"RooClassFactory::ClassFacIFace::create() ERROR: CEXPR requires at least 2 "
806 "arguments (expr,var,...), but only %u args found",
813 strncpy(expr, args[0].c_str() + 1, args[0].
size() - 2);
814 expr[args[0].size() - 2] = 0;
818 if (args.size() == 2) {
822 for (
unsigned int i = 1; i < args.size(); i++) {
823 varList.
add(ft.
asARG(args[i].c_str()));
829 className =
Form(
"RooCFAuto%03d%s%s", classCounter, (tn ==
"CEXPR") ?
"Pdf" :
"Func", ft.autoClassNamePostFix());
843 throw std::runtime_error(
844 Form(
"RooClassFactory::ClassFacIFace::create() ERROR creating %s %s with RooClassFactory",
845 ((tn ==
"CEXPR") ?
"pdf" :
"function"), instanceName));
854 return string(instanceName);
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
Bool_t operator==(const TDatime &d1, const TDatime &d2)
char * Form(const char *fmt,...)
Formats a string in a circular formatting buffer.
Common abstract base class for objects that represent a value and a "shape" in RooFit.
virtual bool add(const RooAbsArg &var, bool silent=false)
Add the specified argument to list.
Storage_t::size_type size() const
Abstract interface for all probability density functions.
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.
static bool makePdf(std::string const &name, std::string const &realArgNames="", std::string const &catArgNames="", std::string const &expression="1.0", bool hasAnaInt=false, bool hasIntGen=false, std::string const &intExpression="")
Write code for a RooAbsPdf implementation with class name 'name'.
static bool makeAndCompilePdf(std::string const &name, std::string const &expression, const RooArgList &vars, std::string const &intExpression="")
static RooAbsReal * makeFunctionInstance(std::string const &className, std::string const &name, std::string const &expression, const RooArgList &vars, std::string const &intExpression="")
Write, compile and load code and instantiate object for a RooAbsReal implementation with class name '...
static bool makeFunction(std::string const &name, std::string const &realArgNames="", std::string const &catArgNames="", std::string const &expression="1.0", bool hasAnaInt=false, std::string const &intExpression="")
Write code for a RooAbsReal implementation with class name 'name', taking RooAbsReal arguments with n...
static RooAbsPdf * makePdfInstance(std::string const &className, std::string const &name, std::string const &expression, const RooArgList &vars, std::string const &intExpression="")
Write, compile and load code and instantiate object for a RooAbsPdf implementation with class name 'n...
static bool makeClass(std::string const &baseName, const std::string &className, std::string const &realArgNames="", std::string const &catArgNames="", std::string const &expression="1.0", bool hasAnaInt=false, bool hasIntGen=false, std::string const &intExpression="")
Write code for a 'baseName' implementation with class name 'className', taking RooAbsReal arguments w...
static bool makeAndCompileFunction(std::string const &name, std::string const &expression, const RooArgList &args, std::string const &intExpression="")
Write, compile and load code for a RooAbsReal implementation with class name 'name',...
static void softAbort()
Soft abort function that interrupts macro execution but doesn't kill ROOT.
bool importClassCode(const char *pat="*", bool doReplace=false)
Import code of all classes in the workspace that have a class name that matches pattern 'pat' and whi...
bool import(const RooAbsArg &arg, const RooCmdArg &arg1={}, const RooCmdArg &arg2={}, const RooCmdArg &arg3={}, const RooCmdArg &arg4={}, const RooCmdArg &arg5={}, const RooCmdArg &arg6={}, const RooCmdArg &arg7={}, const RooCmdArg &arg8={}, const RooCmdArg &arg9={})
Import a RooAbsArg object, e.g.
TClass instances represent classes, structs and namespaces in the ROOT type system.
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
TClass * IsA() const override
RooCmdArg Silence(bool flag=true)
void(off) SmallVectorTemplateBase< T
std::vector< std::string > Split(std::string_view str, std::string_view delims, bool skipEmpty=false)
Splits a string at each character in delims.
void init()
Inspect hardware capabilities, and load the optimal library for RooFit computations.