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#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE)
19#include "TLinearFitter.h"
20#include <algorithm>
21#endif
22
23using namespace o2::gpu;
24
25#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE)
27{
28#ifndef GPUCA_NO_FMT
29 LOGP(info, fmt::runtime(getFormula().c_str()));
30#endif
31}
32
34{
35 std::string formula = getFormula();
36 formula.replace(formula.find("p"), formula.find("]") + 1, "1");
37 size_t pos = std::string::npos;
38 while ((pos = formula.find("* p")) != std::string::npos) {
39 size_t end_pos = formula.find("]", pos) + 2;
40 formula.erase(pos, end_pos - pos);
41 }
42
43 while ((pos = formula.find(" + ")) != std::string::npos) {
44 formula.replace(pos + 1, 1, "++");
45 }
46 return formula;
47}
48
50{
51 std::string formula = "";
52#ifndef GPUCA_NO_FMT
53 const auto terms = getTerms();
54 for (int32_t i = 0; i < (int32_t)terms.size() - 1; ++i) {
55 formula += fmt::format("{} + ", terms[i]);
56 }
57 formula += terms.back();
58#endif
59 return formula;
60}
61
62std::vector<std::string> MultivariatePolynomialHelper<0, 0, false>::getTerms() const
63{
64 std::vector<std::string> terms{"par[0]"};
65 int32_t indexPar = 1;
66 for (uint32_t deg = 1; deg <= mDegree; ++deg) {
67 const auto strTmp = combination_with_repetiton<std::vector<std::string>>(deg, mDim, nullptr, indexPar, nullptr, mInteractionOnly);
68 terms.insert(terms.end(), strTmp.begin(), strTmp.end());
69 }
70 return terms;
71}
72
74{
75 const std::string formula = getTLinearFitterFormula();
76 TLinearFitter fitter(int32_t(mDim), formula.data(), "");
77 return fitter;
78}
79
80std::vector<float> MultivariatePolynomialHelper<0, 0, false>::fit(TLinearFitter& fitter, std::vector<double>& x, std::vector<double>& y, std::vector<double>& error, const bool clearPoints)
81{
82 if (clearPoints) {
83 fitter.ClearPoints();
84 }
85 const int32_t nDim = static_cast<int32_t>(x.size() / y.size());
86 fitter.AssignData(static_cast<int32_t>(y.size()), nDim, x.data(), y.data(), error.empty() ? nullptr : error.data());
87
88 const int32_t status = fitter.Eval();
89 if (status != 0) {
90#ifndef GPUCA_NO_FMT
91 LOGP(info, "Fitting failed with status: {}", status);
92#endif
93 return std::vector<float>();
94 }
95
96 TVectorD params;
97 fitter.GetParameters(params);
98 std::vector<float> paramsFloat;
99 paramsFloat.reserve(static_cast<uint32_t>(params.GetNrows()));
100 std::copy(params.GetMatrixArray(), params.GetMatrixArray() + params.GetNrows(), std::back_inserter(paramsFloat));
101 return paramsFloat;
102}
103
104std::vector<float> MultivariatePolynomialHelper<0, 0, false>::fit(std::vector<double>& x, std::vector<double>& y, std::vector<double>& error, const bool clearPoints) const
105{
106 TLinearFitter fitter = getTLinearFitter();
107 return fit(fitter, x, y, error, clearPoints);
108}
109
110template <class Type>
111Type 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
112{
113 {
114 // each digit represents the currently set dimension
115 uint32_t pos[FMaxdegree + 1]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
116
117 // return value is either the sum of all polynomials or a vector of strings containing the formula for each polynomial
118 Type val(0);
119 for (;;) {
120 // starting on the rightmost digit
121 for (uint32_t i = degree; i > 0; --i) {
122 // check if digit of current position is at is max position
123 if (pos[i] == dim) {
124 // increase digit of left position
125 ++pos[i - 1];
126 // resetting the indices of the digits to the right
127 for (uint32_t j = i; j <= degree; ++j) {
128 pos[j] = pos[i - 1];
129 }
130 }
131 }
132
133 // check if all combinations are processed
134 if (pos[0] == 1) {
135 break;
136 } else {
137
138 if (interactionOnly) {
139 bool checkInteraction = false;
140 for (size_t i = 1; i < degree; ++i) {
141 checkInteraction = pos[i] == pos[i + 1];
142 if (checkInteraction) {
143 break;
144 }
145 }
146 if (checkInteraction) {
147 ++pos[degree];
148 continue;
149 }
150 }
151
152 if constexpr (std::is_same_v<Type, float>) {
153 float term = par[indexPar++];
154 for (size_t i = 1; i <= degree; ++i) {
155 term *= x[pos[i]];
156 }
157 val += term;
158 } else {
159 std::string term{};
160 for (size_t i = 1; i <= degree; ++i) {
161 term += fmt::format("x[{}] * ", pos[i]);
162 }
163 term += fmt::format("par[{}]", indexPar++);
164 val.emplace_back(term);
165 }
166 }
167
168 // increase the rightmost digit
169 ++pos[degree];
170 }
171 return val;
172 }
173}
174
175float MultivariatePolynomialHelper<0, 0, false>::evalPol(const float par[], const float x[], const uint32_t degree, const uint32_t dim, const bool interactionOnly) const
176{
177 float val = par[0];
178 int32_t indexPar = 1;
179 for (uint32_t deg = 1; deg <= degree; ++deg) {
180 val += combination_with_repetiton<float>(deg, dim, par, indexPar, x, interactionOnly);
181 }
182 return val;
183}
184
185#endif
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
TFitResultPtr fit(const size_t nBins, const T *arr, const T xMin, const T xMax, TF1 &func, std::string_view option="")
Definition fit.h:59