Skip to content

Commit 29a6c39

Browse files
TPC: adding function to make polynomial fits from scatter points (#13355)
1 parent 15f38fb commit 29a6c39

File tree

1 file changed

+96
-2
lines changed

1 file changed

+96
-2
lines changed

GPU/TPCFastTransformation/NDPiecewisePolynomials.h

Lines changed: 96 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ struct NDPiecewisePolynomialContainer {
7171
///
7272
/// For usage see: testMultivarPolynomials.cxx
7373
///
74-
/// TODO: add possibillity to perform the fits on scattered data points (+add weighting of points)
74+
/// TODO: add possibillity to perform the fits with weighting of points
7575
///
7676
/// \tparam Dim number of dimensions
7777
/// \tparam Degree degree of the polynomials
@@ -184,6 +184,11 @@ class NDPiecewisePolynomials : public FlatObject
184184
/// \param nAuxiliaryPoints number of points which will be used for the fits (should be at least 2)
185185
void performFits(const std::function<double(const double x[/* Dim */])>& func, const unsigned int nAuxiliaryPoints[/* Dim */]);
186186

187+
/// perform the polynomial fits on scatter points
188+
/// \param x scatter points used to make the fits of size 'y.size() * Dim' as in TLinearFitter
189+
/// \param y response values
190+
void performFits(const std::vector<float>& x, const std::vector<float>& y);
191+
187192
/// load parameters from input file (which were written using the writeToFile method)
188193
/// \param inpf input file
189194
/// \param name name of the object in the file
@@ -537,7 +542,7 @@ void NDPiecewisePolynomials<Dim, Degree, InteractionOnly>::performFits(const std
537542
const bool debug = !(++counter % printDebugForNFits);
538543
if (debug) {
539544
#ifndef GPUCA_ALIROOT_LIB
540-
LOGP(info, "Peforming fit {} out of {}", counter, nTotalFits);
545+
LOGP(info, "Performing fit {} out of {}", counter, nTotalFits);
541546
#endif
542547
}
543548

@@ -554,6 +559,95 @@ void NDPiecewisePolynomials<Dim, Degree, InteractionOnly>::performFits(const std
554559
}
555560
}
556561

562+
template <unsigned int Dim, unsigned int Degree, bool InteractionOnly>
563+
void NDPiecewisePolynomials<Dim, Degree, InteractionOnly>::performFits(const std::vector<float>& x, const std::vector<float>& y)
564+
{
565+
const int nTotalFits = getNPolynomials();
566+
#ifndef GPUCA_ALIROOT_LIB
567+
LOGP(info, "Perform fitting of {}D-Polynomials of degree {} for a total of {} fits.", Dim, Degree, nTotalFits);
568+
#endif
569+
570+
// approximate number of points
571+
unsigned int nPoints = 2 * y.size() / nTotalFits;
572+
573+
// polynomial index -> indices to datapoints
574+
std::unordered_map<int, std::vector<size_t>> dataPointsIndices;
575+
for (int i = 0; i < nTotalFits; ++i) {
576+
dataPointsIndices[i].reserve(nPoints);
577+
}
578+
579+
// check for each data point which polynomial to use
580+
for (size_t i = 0; i < y.size(); ++i) {
581+
std::array<int, Dim> index;
582+
float xVal[Dim];
583+
std::copy(x.begin() + i * Dim, x.begin() + i * Dim + Dim, xVal);
584+
setIndex<Dim - 1>(xVal, index.data());
585+
586+
std::array<int, Dim> indexClamped{index};
587+
clamp<Dim - 1>(xVal, indexClamped.data());
588+
589+
// check if data points are in the grid
590+
if (index == indexClamped) {
591+
// index of the polyniomial
592+
const unsigned int idx = getDataIndex(index.data()) / MultivariatePolynomialParametersHelper::getNParameters(Degree, Dim, InteractionOnly);
593+
594+
// store index to data point
595+
dataPointsIndices[idx].emplace_back(i);
596+
}
597+
}
598+
599+
// for fitting
600+
MultivariatePolynomialHelper<0, 0, false> pol(Dim, Degree, InteractionOnly);
601+
TLinearFitter fitter = pol.getTLinearFitter();
602+
603+
unsigned int counter = 0;
604+
const int printDebugForNFits = int(nTotalFits / 20) + 1;
605+
606+
// temp storage for x and y values for fitting
607+
std::vector<double> xCords;
608+
std::vector<double> response;
609+
610+
for (int i = 0; i < nTotalFits; ++i) {
611+
const bool debug = !(++counter % printDebugForNFits);
612+
if (debug) {
613+
#ifndef GPUCA_ALIROOT_LIB
614+
LOGP(info, "Performing fit {} out of {}", counter, nTotalFits);
615+
#endif
616+
}
617+
618+
// store values for fitting
619+
if (dataPointsIndices[i].empty()) {
620+
#ifndef GPUCA_ALIROOT_LIB
621+
LOGP(info, "No data points to fit");
622+
#endif
623+
continue;
624+
}
625+
626+
const auto nP = dataPointsIndices[i].size();
627+
xCords.reserve(Dim * nP);
628+
response.reserve(nP);
629+
xCords.clear();
630+
response.clear();
631+
632+
// add datapoints to fit
633+
for (size_t j = 0; j < nP; ++j) {
634+
const size_t idxOrig = dataPointsIndices[i][j];
635+
636+
// insert x values at the end of xCords
637+
const int idxXStart = idxOrig * Dim;
638+
xCords.insert(xCords.end(), x.begin() + idxXStart, x.begin() + idxXStart + Dim);
639+
response.emplace_back(y[idxOrig]);
640+
}
641+
642+
// perform the fit on the points TODO make errors configurable
643+
std::vector<double> error;
644+
const auto params = MultivariatePolynomialHelper<0, 0, false>::fit(fitter, xCords, response, error, true);
645+
646+
// store parameters
647+
std::copy(params.begin(), params.end(), &mParams[i * MultivariatePolynomialParametersHelper::getNParameters(Degree, Dim, InteractionOnly)]);
648+
}
649+
}
650+
557651
template <unsigned int Dim, unsigned int Degree, bool InteractionOnly>
558652
void NDPiecewisePolynomials<Dim, Degree, InteractionOnly>::fitInnerGrid(const std::function<double(const double x[/* Dim */])>& func, const unsigned int nAuxiliaryPoints[/* Dim */], const int currentIndex[/* Dim */], TLinearFitter& fitter, std::vector<double>& xCords, std::vector<double>& response)
559653
{

0 commit comments

Comments
 (0)