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)
150 for (
auto const &term : other.
_terms) {
151 _terms.emplace_back(std::make_unique<RooListProxy>(term->GetName(),
this, *term));
160 std::stringstream ss;
162 for (
const auto &term :
_terms) {
163 size_t n_vars = term->size() - 1;
164 auto coef =
dynamic_cast<RooRealVar *
>(term->at(n_vars));
165 if (coef->getVal() > 0 && !first)
169 for (
size_t i_var = 0; i_var < n_vars; ++i_var) {
171 auto exp =
dynamic_cast<RooRealVar *
>(term->at(i_var));
172 if (exp->getVal() == 0)
179 ss <<
"pow(" << var->
GetName() <<
"," << exp->getVal() <<
")";
193 double poly_sum(0.0);
194 for (
const auto &term :
_terms) {
195 double poly_term(1.0);
196 size_t n_vars = term->size() - 1;
197 for (
size_t i_var = 0; i_var < n_vars; ++i_var) {
199 auto exp =
dynamic_cast<RooRealVar *
>(term->at(i_var));
200 poly_term *= pow(var->getVal(), exp->getVal());
202 auto coef =
dynamic_cast<RooRealVar *
>(term->at(n_vars));
203 poly_sum += coef->getVal() * poly_term;
211 std::size_t iObs = 0;
212 for (
auto *var : static_range_cast<RooRealVar *>(observables)) {
213 var->setVal(observableValues[iObs++]);
219 for (
auto *var : static_range_cast<RooRealVar *>(observables)) {
220 var->setConstant(
true);
241std::unique_ptr<RooPolyFunc>
243 int order, std::vector<double>
const &observableValues,
double eps1,
double eps2)
246 auto taylorPoly = std::make_unique<RooPolyFunc>(
name, title, observables);
252 obsSet.
add(*obs,
true);
254 if (obsSet.
size() != observables.
size()) {
255 std::stringstream errorMsgStream;
256 errorMsgStream <<
"RooPolyFunc::taylorExpand(" <<
name <<
") ERROR: duplicate input observables!";
257 const auto errorMsg = errorMsgStream.str();
259 throw std::invalid_argument(errorMsg);
264 std::vector<double> obsValues;
265 if (observableValues.empty()) {
266 obsValues.reserve(observables.
size());
267 for (
auto *var : static_range_cast<RooRealVar *>(observables)) {
268 obsValues.push_back(var->getVal());
270 }
else if (observableValues.size() == 1) {
271 obsValues.resize(observables.
size());
272 std::fill(obsValues.begin(), obsValues.end(), observableValues[0]);
273 }
else if (observableValues.size() == observables.
size()) {
274 obsValues = observableValues;
276 std::stringstream errorMsgStream;
277 errorMsgStream <<
"RooPolyFunc::taylorExpand(" <<
name
278 <<
") ERROR: observableValues must be empty, contain one element, or match observables.size()!";
279 const auto errorMsg = errorMsgStream.str();
281 throw std::invalid_argument(errorMsg);
285 if (order >= 3 || order <= 0) {
286 std::stringstream errorMsgStream;
287 errorMsgStream <<
"RooPolyFunc::taylorExpand(" <<
name <<
") ERROR: order must be 0, 1, or 2";
288 const auto errorMsg = errorMsgStream.str();
290 throw std::invalid_argument(errorMsg);
301 for (
int i_order = 0; i_order <= order; ++i_order) {
304 taylorPoly->addTerm(func.
getVal());
308 for (
auto *var : static_range_cast<RooRealVar *>(observables)) {
309 double var1_val = var->getVal();
311 double deriv_val = deriv->
getVal();
313 taylorPoly->addTerm(deriv_val, *var, 1);
314 if (var1_val != 0.0) {
315 taylorPoly->addTerm(deriv_val * var1_val * -1.0);
321 for (
auto *var1 : static_range_cast<RooRealVar *>(observables)) {
322 double var1_val = var1->getVal();
323 auto deriv1 = func.
derivative(*var1, 1, eps1);
324 for (
auto *var2 : static_range_cast<RooRealVar *>(observables)) {
325 double var2_val = var2->
getVal();
326 double deriv_val = 0.0;
327 if (strcmp(var1->GetName(), var2->GetName()) == 0) {
328 auto deriv2 = func.
derivative(*var2, 2, eps2);
329 deriv_val = 0.5 * deriv2->getVal();
332 auto deriv2 = deriv1->derivative(*var2, 1, eps2);
333 deriv_val = 0.5 * deriv2->getVal();
336 taylorPoly->addTerm(deriv_val, *var1, 1, *var2, 1);
337 if (var1_val != 0.0 || var2_val != 0.0) {
338 taylorPoly->addTerm(deriv_val * var1_val * var2_val);
339 taylorPoly->addTerm(deriv_val * var2_val * -1.0, *var1, 1);
340 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.
Common abstract base class for objects that represent a value and a "shape" in RooFit.
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
bool addTyped(const RooAbsCollection &list, bool silent=false)
Adds elements of a given RooAbsCollection to the container if they match the specified type.
Abstract base class for objects that represent a real value and implements functionality common to al...
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.
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
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...