45 int n_terms =
_terms.size();
46 std::string coeff_name =
Form(
"%s_c%d",
GetName(), n_terms);
47 std::string term_name =
Form(
"%s_t%d",
GetName(), n_terms);
48 auto termList = std::make_unique<RooListProxy>(term_name.c_str(), term_name.c_str(),
this);
49 auto coeff = std::make_unique<RooRealVar>(coeff_name.c_str(), coeff_name.c_str(), coefficient);
52 for (
const auto &var :
_vars) {
53 std::string exponent_name =
Form(
"%s_%s^%d",
GetName(), var->GetName(), 0);
54 auto exponent = std::make_unique<RooRealVar>(exponent_name.c_str(), exponent_name.c_str(), 0);
55 exponents.
addOwned(std::move(exponent));
58 termList->
addOwned(std::move(exponents));
59 termList->addOwned(std::move(coeff));
60 _terms.push_back(std::move(termList));
65 int n_terms =
_terms.size();
66 std::string coeff_name =
Form(
"%s_c%d",
GetName(), n_terms);
67 std::string term_name =
Form(
"%s_t%d",
GetName(), n_terms);
68 auto termList = std::make_unique<RooListProxy>(term_name.c_str(), term_name.c_str(),
this);
69 auto coeff = std::make_unique<RooRealVar>(coeff_name.c_str(), coeff_name.c_str(), coefficient);
73 for (
const auto &var :
_vars) {
75 if (strcmp(var1.
GetName(), var->GetName()) == 0)
77 std::string exponent_name =
Form(
"%s_%s^%d",
GetName(), var->GetName(), exp);
78 auto exponent = std::make_unique<RooRealVar>(exponent_name.c_str(), exponent_name.c_str(), exp);
79 exponents.
addOwned(std::move(exponent));
82 termList->
addOwned(std::move(exponents));
83 termList->addOwned(std::move(coeff));
84 _terms.push_back(std::move(termList));
90 int n_terms =
_terms.size();
91 std::string coeff_name =
Form(
"%s_c%d",
GetName(), n_terms);
92 std::string term_name =
Form(
"%s_t%d",
GetName(), n_terms);
93 auto termList = std::make_unique<RooListProxy>(term_name.c_str(), term_name.c_str(),
this);
94 auto coeff = std::make_unique<RooRealVar>(coeff_name.c_str(), coeff_name.c_str(), coefficient);
97 for (
const auto &var :
_vars) {
99 if (strcmp(var1.
GetName(), var->GetName()) == 0)
101 if (strcmp(var2.
GetName(), var->GetName()) == 0)
103 std::string exponent_name =
Form(
"%s_%s^%d",
GetName(), var->GetName(), exp);
104 auto exponent = std::make_unique<RooRealVar>(exponent_name.c_str(), exponent_name.c_str(), exp);
105 exponents.
addOwned(std::move(exponent));
107 termList->
addOwned(std::move(exponents));
108 termList->addOwned(std::move(coeff));
109 _terms.push_back(std::move(termList));
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());
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());
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);
322 double var1_val = var1->getVal();
323 auto deriv1 = func.
derivative(*var1, 1, eps1);
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);
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.