46 int n_terms =
_terms.size();
47 std::string coeff_name =
Form(
"%s_c%d",
GetName(), n_terms);
48 std::string term_name =
Form(
"%s_t%d",
GetName(), n_terms);
49 auto termList = std::make_unique<RooListProxy>(term_name.c_str(), term_name.c_str(),
this);
50 auto coeff = std::make_unique<RooRealVar>(coeff_name.c_str(), coeff_name.c_str(), coefficient);
53 for (
const auto &var :
_vars) {
54 std::string exponent_name =
Form(
"%s_%s^%d",
GetName(), var->GetName(), 0);
55 auto exponent = std::make_unique<RooRealVar>(exponent_name.c_str(), exponent_name.c_str(), 0);
56 exponents.addOwned(std::move(exponent));
59 termList->addOwned(std::move(exponents));
60 termList->addOwned(std::move(coeff));
61 _terms.push_back(std::move(termList));
66 int n_terms =
_terms.size();
67 std::string coeff_name =
Form(
"%s_c%d",
GetName(), n_terms);
68 std::string term_name =
Form(
"%s_t%d",
GetName(), n_terms);
69 auto termList = std::make_unique<RooListProxy>(term_name.c_str(), term_name.c_str(),
this);
70 auto coeff = std::make_unique<RooRealVar>(coeff_name.c_str(), coeff_name.c_str(), coefficient);
74 for (
const auto &var :
_vars) {
76 if (strcmp(var1.
GetName(), var->GetName()) == 0)
78 std::string exponent_name =
Form(
"%s_%s^%d",
GetName(), var->GetName(), exp);
79 auto exponent = std::make_unique<RooRealVar>(exponent_name.c_str(), exponent_name.c_str(), exp);
80 exponents.addOwned(std::move(exponent));
83 termList->addOwned(std::move(exponents));
84 termList->addOwned(std::move(coeff));
85 _terms.push_back(std::move(termList));
91 int n_terms =
_terms.size();
92 std::string coeff_name =
Form(
"%s_c%d",
GetName(), n_terms);
93 std::string term_name =
Form(
"%s_t%d",
GetName(), n_terms);
94 auto termList = std::make_unique<RooListProxy>(term_name.c_str(), term_name.c_str(),
this);
95 auto coeff = std::make_unique<RooRealVar>(coeff_name.c_str(), coeff_name.c_str(), coefficient);
98 for (
const auto &var :
_vars) {
100 if (strcmp(var1.
GetName(), var->GetName()) == 0)
102 if (strcmp(var2.
GetName(), var->GetName()) == 0)
104 std::string exponent_name =
Form(
"%s_%s^%d",
GetName(), var->GetName(), exp);
105 auto exponent = std::make_unique<RooRealVar>(exponent_name.c_str(), exponent_name.c_str(), exp);
106 exponents.addOwned(std::move(exponent));
108 termList->addOwned(std::move(exponents));
109 termList->addOwned(std::move(coeff));
110 _terms.push_back(std::move(termList));
117 << exponents.
size() <<
") provided do not match the number of variables (" <<
_vars.
size()
120 int n_terms =
_terms.size();
121 std::string coeff_name =
Form(
"%s_c%d",
GetName(), n_terms);
122 std::string term_name =
Form(
"%s_t%d",
GetName(), n_terms);
123 auto termList = std::make_unique<RooListProxy>(term_name.c_str(), term_name.c_str(),
this);
124 auto coeff = std::make_unique<RooRealVar>(coeff_name.c_str(), coeff_name.c_str(), coefficient);
125 termList->addOwned(exponents);
126 termList->addOwned(std::move(coeff));
127 _terms.push_back(std::move(termList));
139 :
RooAbsReal(
name, title), _vars(
"x",
"list of dependent variables", this)
141 for (
const auto &var : vars) {
143 std::stringstream ss;
144 ss <<
"RooPolyFunc::ctor(" <<
GetName() <<
") ERROR: coefficient " << var->
GetName()
145 <<
" is not of type RooAbsReal";
146 const std::string errorMsg = ss.str();
148 throw std::runtime_error(errorMsg);
160 for (
auto const &term : other.
_terms) {
161 _terms.emplace_back(std::make_unique<RooListProxy>(term->GetName(),
this, *term));
170 std::stringstream ss;
172 for (
const auto &term :
_terms) {
173 size_t n_vars = term->size() - 1;
174 auto coef =
dynamic_cast<RooRealVar *
>(term->at(n_vars));
175 if (coef->getVal() > 0 && !
first)
179 for (
size_t i_var = 0; i_var < n_vars; ++i_var) {
181 auto exp =
dynamic_cast<RooRealVar *
>(term->at(i_var));
182 if (exp->getVal() == 0)
188 ss <<
"pow(" << var->
GetName() <<
"," << exp->getVal() <<
")";
202 double poly_sum(0.0);
203 for (
const auto &term :
_terms) {
204 double poly_term(1.0);
205 size_t n_vars = term->size() - 1;
206 for (
size_t i_var = 0; i_var < n_vars; ++i_var) {
208 auto exp =
dynamic_cast<RooRealVar *
>(term->at(i_var));
209 poly_term *= pow(var->getVal(), exp->getVal());
211 auto coef =
dynamic_cast<RooRealVar *
>(term->at(n_vars));
212 poly_sum += coef->getVal() * poly_term;
220 std::size_t iObs = 0;
221 for (
auto *var : static_range_cast<RooRealVar *>(observables)) {
222 var->setVal(observableValues[iObs++]);
228 for (
auto *var : static_range_cast<RooRealVar *>(observables)) {
229 var->setConstant(
true);
250std::unique_ptr<RooPolyFunc>
252 int order, std::vector<double>
const &observableValues,
double eps1,
double eps2)
255 auto taylorPoly = std::make_unique<RooPolyFunc>(
name, title, observables);
261 obsSet.
add(*obs,
true);
263 if (obsSet.
size() != observables.
size()) {
264 std::stringstream errorMsgStream;
265 errorMsgStream <<
"RooPolyFunc::taylorExpand(" <<
name <<
") ERROR: duplicate input observables!";
266 const auto errorMsg = errorMsgStream.str();
268 throw std::invalid_argument(errorMsg);
273 std::vector<double> obsValues;
274 if (observableValues.empty()) {
275 obsValues.reserve(observables.
size());
276 for (
auto *var : static_range_cast<RooRealVar *>(observables)) {
277 obsValues.push_back(var->getVal());
279 }
else if (observableValues.size() == 1) {
280 obsValues.resize(observables.
size());
281 std::fill(obsValues.begin(), obsValues.end(), observableValues[0]);
282 }
else if (observableValues.size() == observables.
size()) {
283 obsValues = observableValues;
285 std::stringstream errorMsgStream;
286 errorMsgStream <<
"RooPolyFunc::taylorExpand(" <<
name
287 <<
") ERROR: observableValues must be empty, contain one element, or match observables.size()!";
288 const auto errorMsg = errorMsgStream.str();
290 throw std::invalid_argument(errorMsg);
294 if (order >= 3 || order <= 0) {
295 std::stringstream errorMsgStream;
296 errorMsgStream <<
"RooPolyFunc::taylorExpand(" <<
name <<
") ERROR: order must be 0, 1, or 2";
297 const auto errorMsg = errorMsgStream.str();
299 throw std::invalid_argument(errorMsg);
310 for (
int i_order = 0; i_order <= order; ++i_order) {
313 taylorPoly->addTerm(func.
getVal());
317 for (
auto *var : static_range_cast<RooRealVar *>(observables)) {
318 double var1_val = var->getVal();
320 double deriv_val = deriv->
getVal();
322 taylorPoly->addTerm(deriv_val, *var, 1);
323 if (var1_val != 0.0) {
324 taylorPoly->addTerm(deriv_val * var1_val * -1.0);
330 for (
auto *var1 : static_range_cast<RooRealVar *>(observables)) {
331 double var1_val = var1->getVal();
332 auto deriv1 = func.
derivative(*var1, 1, eps1);
333 for (
auto *var2 : static_range_cast<RooRealVar *>(observables)) {
334 double var2_val = var2->
getVal();
335 double deriv_val = 0.0;
336 if (strcmp(var1->GetName(), var2->GetName()) == 0) {
337 auto deriv2 = func.
derivative(*var2, 2, eps2);
338 deriv_val = 0.5 * deriv2->getVal();
341 auto deriv2 = deriv1->derivative(*var2, 1, eps2);
342 deriv_val = 0.5 * deriv2->getVal();
345 taylorPoly->addTerm(deriv_val, *var1, 1, *var2, 1);
346 if (var1_val != 0.0 || var2_val != 0.0) {
347 taylorPoly->addTerm(deriv_val * var1_val * var2_val);
348 taylorPoly->addTerm(deriv_val * var2_val * -1.0, *var1, 1);
349 taylorPoly->addTerm(deriv_val * var1_val * -1.0, *var2, 1);
void fixObservables(const RooAbsCollection &observables)
void setCoordinates(const RooAbsCollection &observables, std::vector< double > const &observableValues)
char * Form(const char *fmt,...)
Formats a string in a circular formatting buffer.
RooAbsArg is the common abstract base class for objects that represent a value and a "shape" in RooFi...
RooAbsCollection is an abstract container object that can hold multiple RooAbsArg objects.
virtual bool add(const RooAbsArg &var, bool silent=false)
Add the specified argument to list.
Storage_t::size_type size() const
RooAbsReal is the common abstract base class for objects that represent a real value and implements f...
double getVal(const RooArgSet *normalisationSet=nullptr) const
Evaluate object.
RooDerivative * derivative(RooRealVar &obs, Int_t order=1, double eps=0.001)
Return function representing first, second or third order derivative of this function.
RooArgList is a container object that can hold multiple RooAbsArg objects.
RooAbsArg * at(Int_t idx) const
Return object at given index, or nullptr if index is out of range.
RooArgSet is a container object that can hold multiple RooAbsArg objects.
bool add(const RooAbsArg &var, bool valueServer, bool shapeServer, bool silent)
Overloaded RooCollection_t::add() method insert object into set and registers object as server to own...
RooPolyFunc implements a polynomial function in multi-variables.
double evaluate() const override
Evaluation.
RooPolyFunc()
Default constructor.
void addTerm(double coefficient)
coverity[UNINIT_CTOR]
static std::unique_ptr< RooPolyFunc > taylorExpand(const char *name, const char *title, RooAbsReal &func, const RooArgList &observables, int order=1, std::vector< double > const &observableValues={}, double eps1=1e-6, double eps2=1e-3)
Taylor expanding given function in terms of observables around observableValues.
std::string asString() const
Return to RooPolyFunc as a string.
std::vector< std::unique_ptr< RooListProxy > > _terms
RooRealVar represents a variable that can be changed from the outside.
const char * GetName() const override
Returns name of object.
The namespace RooFit contains mostly switches that change the behaviour of functions of PDFs (or othe...