Project
Loading...
Searching...
No Matches
MultivariatePolynomialHelper.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
14
16#include "GPUCommonLogger.h"
17
18#include "TLinearFitter.h"
19#include <algorithm>
20
21using namespace o2::gpu;
22
24{
25 LOGP(info, fmt::runtime(getFormula().c_str()));
26}
27
29{
30 std::string formula = getFormula();
31 formula.replace(formula.find("p"), formula.find("]") + 1, "1");
32 size_t pos = std::string::npos;
33 while ((pos = formula.find("* p")) != std::string::npos) {
34 size_t end_pos = formula.find("]", pos) + 2;
35 formula.erase(pos, end_pos - pos);
36 }
37
38 while ((pos = formula.find(" + ")) != std::string::npos) {
39 formula.replace(pos + 1, 1, "++");
40 }
41 return formula;
42}
43
45{
46 std::string formula = "";
47 const auto terms = getTerms();
48 for (int32_t i = 0; i < (int32_t)terms.size() - 1; ++i) {
49 formula += fmt::format("{} + ", terms[i]);
50 }
51 formula += terms.back();
52 return formula;
53}
54
55std::vector<std::string> MultivariatePolynomialHelper<0, 0, false>::getTerms() const
56{
57 std::vector<std::string> terms{"par[0]"};
58 int32_t indexPar = 1;
59 for (uint32_t deg = 1; deg <= mDegree; ++deg) {
60 const auto strTmp = combination_with_repetiton<std::vector<std::string>>(deg, mDim, nullptr, indexPar, nullptr, mInteractionOnly);
61 terms.insert(terms.end(), strTmp.begin(), strTmp.end());
62 }
63 return terms;
64}
65
67{
68 const std::string formula = getTLinearFitterFormula();
69 return TLinearFitter(int32_t(mDim), formula.data(), "");
70}
71
72std::vector<float> MultivariatePolynomialHelper<0, 0, false>::fit(TLinearFitter& fitter, std::vector<double>& x, std::vector<double>& y, std::vector<double>& error, const bool clearPoints)
73{
74 if (clearPoints) {
75 fitter.ClearPoints();
76 }
77 const int32_t nDim = static_cast<int32_t>(x.size() / y.size());
78 fitter.AssignData(static_cast<int32_t>(y.size()), nDim, x.data(), y.data(), error.empty() ? nullptr : error.data());
79
80 const int32_t status = fitter.Eval();
81 if (status != 0) {
82 LOGP(info, "Fitting failed with status: {}", status);
83 return std::vector<float>();
84 }
85
86 TVectorD params;
87 fitter.GetParameters(params);
88 std::vector<float> paramsFloat;
89 paramsFloat.reserve(static_cast<uint32_t>(params.GetNrows()));
90 std::copy(params.GetMatrixArray(), params.GetMatrixArray() + params.GetNrows(), std::back_inserter(paramsFloat));
91 return paramsFloat;
92}
93
94std::vector<float> MultivariatePolynomialHelper<0, 0, false>::fit(std::vector<double>& x, std::vector<double>& y, std::vector<double>& error, const bool clearPoints) const
95{
96 TLinearFitter fitter = getTLinearFitter();
97 return fit(fitter, x, y, error, clearPoints);
98}
99
100template <class Type>
101Type MultivariatePolynomialHelper<0, 0, false>::combination_with_repetiton(const uint32_t degree, const uint32_t dim, const float par[], int32_t& indexPar, const float x[], const bool interactionOnly) const
102{
103 {
104 // each digit represents the currently set dimension
105 uint32_t pos[FMaxdegree + 1]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
106
107 // return value is either the sum of all polynomials or a vector of strings containing the formula for each polynomial
108 Type val(0);
109 for (;;) {
110 // starting on the rightmost digit
111 for (uint32_t i = degree; i > 0; --i) {
112 // check if digit of current position is at is max position
113 if (pos[i] == dim) {
114 // increase digit of left position
115 ++pos[i - 1];
116 // resetting the indices of the digits to the right
117 for (uint32_t j = i; j <= degree; ++j) {
118 pos[j] = pos[i - 1];
119 }
120 }
121 }
122
123 // check if all combinations are processed
124 if (pos[0] == 1) {
125 break;
126 } else {
127
128 if (interactionOnly) {
129 bool checkInteraction = false;
130 for (size_t i = 1; i < degree; ++i) {
131 checkInteraction = pos[i] == pos[i + 1];
132 if (checkInteraction) {
133 break;
134 }
135 }
136 if (checkInteraction) {
137 ++pos[degree];
138 continue;
139 }
140 }
141
142 if constexpr (std::is_same_v<Type, float>) {
143 float term = par[indexPar++];
144 for (size_t i = 1; i <= degree; ++i) {
145 term *= x[pos[i]];
146 }
147 val += term;
148 } else {
149 std::string term{};
150 for (size_t i = 1; i <= degree; ++i) {
151 term += fmt::format("x[{}] * ", pos[i]);
152 }
153 term += fmt::format("par[{}]", indexPar++);
154 val.emplace_back(term);
155 }
156 }
157
158 // increase the rightmost digit
159 ++pos[degree];
160 }
161 return val;
162 }
163}
164
165float MultivariatePolynomialHelper<0, 0, false>::evalPol(const float par[], const float x[], const uint32_t degree, const uint32_t dim, const bool interactionOnly) const
166{
167 float val = par[0];
168 int32_t indexPar = 1;
169 for (uint32_t deg = 1; deg <= degree; ++deg) {
170 val += combination_with_repetiton<float>(deg, dim, par, indexPar, x, interactionOnly);
171 }
172 return val;
173}
int32_t i
uint16_t pos
Definition RawData.h:3
uint32_t j
Definition RawData.h:0
GLint GLenum GLint x
Definition glcorearb.h:403
GLenum const GLfloat * params
Definition glcorearb.h:272
GLuint GLfloat * val
Definition glcorearb.h:1582
Node par(int index)
Parameters.
TFitResultPtr fit(const size_t nBins, const T *arr, const T xMin, const T xMax, TF1 &func, std::string_view option="")
Definition fit.h:60