Project
Loading...
Searching...
No Matches
Spline2DHelper.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
16
17#include "Spline2DHelper.h"
18#include "Spline1DHelper.h"
19
20#include "SymMatrixSolver.h"
21#include "GPUCommonDef.h"
22#include "GPUCommonLogger.h"
23
24#include "TMath.h"
25#include "TMatrixD.h"
26#include "TVectorD.h"
27#include "TDecompBK.h"
28
29#include <vector>
30#include "TRandom.h"
31#include "TMath.h"
32#include "TCanvas.h"
33#include "TNtuple.h"
34#include "TFile.h"
35#include "GPUCommonMath.h"
36#include <iostream>
37#include <chrono>
38
39using namespace o2::gpu;
40
41template <typename DataT>
42Spline2DHelper<DataT>::Spline2DHelper() : mError(), mFdimensions(0), mHelperU1(), mHelperU2()
43{
44}
45
46template <typename DataT>
47int32_t Spline2DHelper<DataT>::storeError(int32_t code, const char* msg)
48{
49 mError = msg;
50 return code;
51}
52
53template <typename DataT>
55 DataT* Fparameters, double x1Min, double x1Max, double x2Min, double x2Max,
56 std::function<void(double x1, double x2, double f[/*spline.getYdimensions()*/])> F) const
57{
60
61 std::vector<double> dataPointF(getNumberOfDataPoints() * mFdimensions);
62
63 double scaleX1 = (x1Max - x1Min) / ((double)mHelperU1.getSpline().getUmax());
64 double scaleX2 = (x2Max - x2Min) / ((double)mHelperU2.getSpline().getUmax());
65
66 for (int32_t iv = 0; iv < getNumberOfDataPointsU2(); iv++) {
67 double x2 = x2Min + mHelperU2.getDataPoint(iv).u * scaleX2;
68 for (int32_t iu = 0; iu < getNumberOfDataPointsU1(); iu++) {
69 double x1 = x1Min + mHelperU1.getDataPoint(iu).u * scaleX1;
70 F(x1, x2, &dataPointF[(iv * getNumberOfDataPointsU1() + iu) * mFdimensions]);
71 }
72 }
73 approximateFunction(Fparameters, dataPointF.data());
74}
75
76template <typename DataT>
78 DataT* Fparameters, double x1Min, double x1Max, double x2Min, double x2Max,
79 std::function<void(const std::vector<double>& x1, const std::vector<double>& x2, std::vector<double> f[/*mFdimensions*/])> F,
80 uint32_t batchsize) const
81{
85
86 std::vector<double> dataPointF(getNumberOfDataPoints() * mFdimensions);
87
88 double scaleX1 = (x1Max - x1Min) / ((double)mHelperU1.getSpline().getUmax());
89 double scaleX2 = (x2Max - x2Min) / ((double)mHelperU2.getSpline().getUmax());
90
91 std::vector<double> x1;
92 x1.reserve(batchsize);
93
94 std::vector<double> x2;
95 x2.reserve(batchsize);
96
97 std::vector<int32_t> index;
98 index.reserve(batchsize);
99
100 std::vector<double> dataPointFTmp[mFdimensions];
101 for (int32_t iDim = 0; iDim < mFdimensions; ++iDim) {
102 dataPointFTmp[iDim].reserve(batchsize);
103 }
104
105 uint32_t counter = 0;
106 for (int32_t iv = 0; iv < getNumberOfDataPointsU2(); iv++) {
107 double x2Tmp = x2Min + mHelperU2.getDataPoint(iv).u * scaleX2;
108 for (int32_t iu = 0; iu < getNumberOfDataPointsU1(); iu++) {
109 double x1Tmp = x1Min + mHelperU1.getDataPoint(iu).u * scaleX1;
110 x1.emplace_back(x1Tmp);
111 x2.emplace_back(x2Tmp);
112 index.emplace_back((iv * getNumberOfDataPointsU1() + iu) * mFdimensions);
113 ++counter;
114
115 if (counter == batchsize || (iu == (getNumberOfDataPointsU1() - 1) && (iv == (getNumberOfDataPointsU2() - 1)))) {
116 counter = 0;
117 F(x1, x2, dataPointFTmp);
118 uint32_t entries = index.size();
119
120 for (uint32_t i = 0; i < entries; ++i) {
121 const uint32_t indexTmp = index[i];
122 for (int32_t iDim = 0; iDim < mFdimensions; ++iDim) {
123 dataPointF[indexTmp + iDim] = dataPointFTmp[iDim][i];
124 }
125 }
126
127 x1.clear();
128 x2.clear();
129 index.clear();
130 for (int32_t iDim = 0; iDim < mFdimensions; ++iDim) {
131 dataPointFTmp[iDim].clear();
132 }
133 }
134 }
135 }
136 approximateFunction(Fparameters, dataPointF.data());
137}
138
139template <typename DataT>
141 DataT* Fparameters, const double DataPointF[/*getNumberOfDataPoints() x nFdim*/]) const
142{
144
145 const int32_t Ndim = mFdimensions;
146 const int32_t Ndim2 = 2 * Ndim;
147 const int32_t Ndim3 = 3 * Ndim;
148 const int32_t Ndim4 = 4 * Ndim;
149
150 int32_t nDataPointsU = getNumberOfDataPointsU1();
151 int32_t nDataPointsV = getNumberOfDataPointsU2();
152
153 int32_t nKnotsU = mHelperU1.getSpline().getNumberOfKnots();
154 int32_t nKnotsV = mHelperU2.getSpline().getNumberOfKnots();
155
156 std::unique_ptr<double[]> rotDataPointF(new double[nDataPointsU * nDataPointsV * Ndim]); // U DataPoints x V DataPoints : rotated DataPointF for one output dimension
157 std::unique_ptr<double[]> Dv(new double[nKnotsV * nDataPointsU * Ndim]); // V knots x U DataPoints
158
159 std::unique_ptr<DataT[]> parU(new DataT[mHelperU1.getSpline().calcNumberOfParameters(Ndim)]);
160 std::unique_ptr<DataT[]> parV(new DataT[mHelperU2.getSpline().calcNumberOfParameters(Ndim)]);
161
162 std::unique_ptr<double[]> parUdbl(new double[mHelperU1.getSpline().calcNumberOfParameters(Ndim)]);
163 std::unique_ptr<double[]> parVdbl(new double[mHelperU2.getSpline().calcNumberOfParameters(Ndim)]);
164
165 // rotated data points (u,v)->(v,u)
166
167 for (int32_t ipu = 0; ipu < nDataPointsU; ipu++) {
168 for (int32_t ipv = 0; ipv < nDataPointsV; ipv++) {
169 for (int32_t dim = 0; dim < Ndim; dim++) {
170 rotDataPointF[Ndim * (ipu * nDataPointsV + ipv) + dim] = DataPointF[Ndim * (ipv * nDataPointsU + ipu) + dim];
171 }
172 }
173 }
174
175 // get S and S'u at all the knots by interpolating along the U axis
176
177 for (int32_t iKnotV = 0; iKnotV < nKnotsV; ++iKnotV) {
178 int32_t ipv = mHelperU2.getKnotDataPoint(iKnotV);
179 const double* DataPointFrow = &(DataPointF[Ndim * ipv * nDataPointsU]);
180 mHelperU1.approximateFunctionGradually(parU.get(), DataPointFrow);
181
182 for (int32_t i = 0; i < mHelperU1.getSpline().calcNumberOfParameters(Ndim); i++) {
183 parUdbl[i] = parU[i];
184 }
185 for (int32_t iKnotU = 0; iKnotU < nKnotsU; ++iKnotU) {
186 DataT* knotPar = &Fparameters[Ndim4 * (iKnotV * nKnotsU + iKnotU)];
187 for (int32_t dim = 0; dim < Ndim; ++dim) {
188 knotPar[dim] = parU[Ndim * (2 * iKnotU) + dim]; // store S for all the knots
189 knotPar[Ndim2 + dim] = parU[Ndim * (2 * iKnotU) + Ndim + dim]; // store S'u for all the knots //SG!!!
190 }
191 }
192
193 // recalculate F values for all ipu DataPoints at V = ipv
194 for (int32_t ipu = 0; ipu < nDataPointsU; ipu++) {
195 double splineF[Ndim];
196 double u = mHelperU1.getDataPoint(ipu).u;
197 mHelperU1.getSpline().interpolateU(Ndim, parUdbl.get(), u, splineF);
198 for (int32_t dim = 0; dim < Ndim; dim++) {
199 rotDataPointF[(ipu * nDataPointsV + ipv) * Ndim + dim] = splineF[dim];
200 }
201 }
202 }
203
204 // calculate S'v at all data points with V == V of a knot
205
206 for (int32_t ipu = 0; ipu < nDataPointsU; ipu++) {
207 const double* DataPointFcol = &(rotDataPointF[ipu * nDataPointsV * Ndim]);
208 mHelperU2.approximateFunctionGradually(parV.get(), DataPointFcol);
209 for (int32_t iKnotV = 0; iKnotV < nKnotsV; iKnotV++) {
210 for (int32_t dim = 0; dim < Ndim; dim++) {
211 double dv = parV[(iKnotV * 2 + 1) * Ndim + dim];
212 Dv[(iKnotV * nDataPointsU + ipu) * Ndim + dim] = dv;
213 }
214 }
215 }
216
217 // fit S'v and S''_vu at all the knots
218
219 for (int32_t iKnotV = 0; iKnotV < nKnotsV; ++iKnotV) {
220 const double* Dvrow = &(Dv[iKnotV * nDataPointsU * Ndim]);
221 mHelperU1.approximateFunction(parU.get(), Dvrow);
222 for (int32_t iKnotU = 0; iKnotU < nKnotsU; ++iKnotU) {
223 for (int32_t dim = 0; dim < Ndim; ++dim) {
224 Fparameters[Ndim4 * (iKnotV * nKnotsU + iKnotU) + Ndim + dim] = parU[Ndim * 2 * iKnotU + dim]; // store S'v for all the knots
225 Fparameters[Ndim4 * (iKnotV * nKnotsU + iKnotU) + Ndim3 + dim] = parU[Ndim * 2 * iKnotU + Ndim + dim]; // store S''vu for all the knots
226 }
227 }
228 }
229}
230
231template <typename DataT>
234 double x1Min, double x1Max, double x2Min, double x2Max,
235 std::function<void(double x1, double x2, double f[/*spline.getYdimensions()*/])> F,
236 int32_t nAuxiliaryDataPointsU1, int32_t nAuxiliaryDataPointsU2)
237{
239
240 setSpline(spline, nAuxiliaryDataPointsU1, nAuxiliaryDataPointsU2);
241 mFdimensions = spline.getYdimensions();
242 std::vector<double> dataPointX1(getNumberOfDataPoints());
243 std::vector<double> dataPointX2(getNumberOfDataPoints());
244 std::vector<double> dataPointF(getNumberOfDataPoints() * mFdimensions);
245
246 double scaleX1 = (x1Max - x1Min) / ((double)mHelperU1.getSpline().getUmax());
247 double scaleX2 = (x2Max - x2Min) / ((double)mHelperU2.getSpline().getUmax());
248
249 for (int32_t iv = 0; iv < getNumberOfDataPointsU2(); iv++) {
250 double x2 = x2Min + mHelperU2.getDataPoint(iv).u * scaleX2;
251 for (int32_t iu = 0; iu < getNumberOfDataPointsU1(); iu++) {
252 double x1 = x1Min + mHelperU1.getDataPoint(iu).u * scaleX1;
253 int32_t ind = iv * getNumberOfDataPointsU1() + iu;
254 dataPointX1[ind] = x1;
255 dataPointX2[ind] = x2;
256 F(x1, x2, &dataPointF[ind * mFdimensions]);
257 }
258 }
259 approximateDataPoints(spline, spline.getParameters(), x1Min, x1Max, x2Min, x2Max, &dataPointX1[0], &dataPointX2[0], &dataPointF[0], getNumberOfDataPoints());
260}
261
262template <typename DataT>
263void Spline2DHelper<DataT>::setGrid(Spline2DContainer<DataT>& spline, double x1Min, double x1Max, double x2Min, double x2Max)
264{
265 mFdimensions = spline.getYdimensions();
266 spline.setXrange(x1Min, x1Max, x2Min, x2Max);
267 {
268 std::vector<int32_t> knots;
269 for (int32_t i = 0; i < spline.getGridX1().getNumberOfKnots(); i++) {
270 knots.push_back(spline.getGridX1().getKnot(i).getU());
271 }
272 fGridU.recreate(0, knots.size(), knots.data());
273 fGridU.setXrange(x1Min, x1Max);
274 }
275 {
276 std::vector<int32_t> knots;
277 for (int32_t i = 0; i < spline.getGridX2().getNumberOfKnots(); i++) {
278 knots.push_back(spline.getGridX2().getKnot(i).getU());
279 }
280 fGridV.recreate(0, knots.size(), knots.data());
281 fGridV.setXrange(x2Min, x2Max);
282 }
283}
284
285template <typename DataT>
286void Spline2DHelper<DataT>::getScoefficients(int32_t iu, int32_t iv, double u, double v,
287 double coeff[16], int32_t indices[16])
288{
289 const typename Spline1D<double>::Knot& knotU = fGridU.getKnot(iu);
290 const typename Spline1D<double>::Knot& knotV = fGridV.getKnot(iv);
291 int32_t nu = fGridU.getNumberOfKnots();
292
293 // indices of parameters that are involved in spline calculation, 1D case
294 int32_t i00 = (nu * iv + iu) * 4; // values { S, S'v, S'u, S''vu } at {u0, v0}
295 int32_t i01 = i00 + 4 * nu; // values { ... } at {u0, v1}
296 int32_t i10 = i00 + 4;
297 int32_t i11 = i01 + 4;
298
299 double dSl, dDl, dSr, dDr;
300 Spline1DHelper<double>::getScoefficients(knotU, u, dSl, dDl, dSr, dDr);
301 double dSd, dDd, dSu, dDu;
302 Spline1DHelper<double>::getScoefficients(knotV, v, dSd, dDd, dSu, dDu);
303
304 // A = Parameters + i00, B = Parameters + i01
305 // S = dSl * (dSd * A[0] + dDd * A[1]) + dDl * (dSd * A[2] + dDd * A[3]) +
306 // dSr * (dSd * A[4] + dDd * A[5]) + dDr * (dSd * A[6] + dDd * A[7]) +
307 // dSl * (dSu * B[0] + dDu * B[1]) + dDl * (dSu * B[2] + dDu * B[3]) +
308 // dSr * (dSu * B[4] + dDu * B[5]) + dDr * (dSu * B[6] + dDu * B[7]);
309
310 double c[16] = {dSl * dSd, dSl * dDd, dDl * dSd, dDl * dDd,
311 dSr * dSd, dSr * dDd, dDr * dSd, dDr * dDd,
312 dSl * dSu, dSl * dDu, dDl * dSu, dDl * dDu,
313 dSr * dSu, dSr * dDu, dDr * dSu, dDr * dDu};
314 for (int32_t i = 0; i < 16; i++) {
315 coeff[i] = c[i];
316 }
317 for (int32_t i = 0; i < 4; i++) {
318 indices[0 + i] = i00 + i;
319 indices[4 + i] = i10 + i;
320 indices[8 + i] = i01 + i;
321 indices[12 + i] = i11 + i;
322 }
323}
324
325template <typename DataT>
327 Spline2DContainer<DataT>& spline, DataT* splineParameters, double x1Min, double x1Max, double x2Min, double x2Max,
328 const double dataPointX1[], const double dataPointX2[], const double dataPointF[/*getNumberOfDataPoints() x nFdim*/],
329 int32_t nDataPoints)
330{
332
333 setGrid(spline, x1Min, x1Max, x2Min, x2Max);
334
335 int32_t nFdim = spline.getYdimensions();
336 int32_t nu = fGridU.getNumberOfKnots();
337 int32_t nv = fGridV.getNumberOfKnots();
338
339 const int32_t nPar = 4 * spline.getNumberOfKnots(); // n parameters for 1-dimensional F
340
341 SymMatrixSolver solver(nPar, nFdim);
342
343 for (int32_t iPoint = 0; iPoint < nDataPoints; ++iPoint) {
344 double u = fGridU.convXtoU(dataPointX1[iPoint]);
345 double v = fGridV.convXtoU(dataPointX2[iPoint]);
346 int32_t iu = fGridU.getLeftKnotIndexForU(u);
347 int32_t iv = fGridV.getLeftKnotIndexForU(v);
348 double c[16];
349 int32_t ind[16];
350 getScoefficients(iu, iv, u, v, c, ind);
351
352 // S(u,v) = sum c[i]*Parameters[ind[i]]
353
354 for (int32_t i = 0; i < 16; i++) {
355 for (int32_t j = i; j < 16; j++) {
356 solver.A(ind[i], ind[j]) += c[i] * c[j];
357 }
358 }
359
360 for (int32_t iDim = 0; iDim < nFdim; iDim++) {
361 double f = (double)dataPointF[iPoint * nFdim + iDim];
362 for (int32_t i = 0; i < 16; i++) {
363 solver.B(ind[i], iDim) += f * c[i];
364 }
365 }
366 } // data points
367
368 // add extra smoothness in case some data is missing
369
370 for (int32_t iu = 0; iu < nu - 1; iu++) {
371 for (int32_t iv = 0; iv < nv - 1; iv++) {
372 int32_t smoothPoint[4][2] = {
373 {-1, -1},
374 {-1, +1},
375 {+1, -1},
376 {+1, +1}};
377 for (int32_t iSet = 0; iSet < 4; iSet++) {
378 int32_t pu = iu + smoothPoint[iSet][0];
379 int32_t pv = iv + smoothPoint[iSet][1];
380 int32_t ip = (nu * pv + pu) * 4;
381 if (pu < 0 || pv < 0 || pu >= nu || pv >= nv) {
382 continue;
383 }
384 double c[17];
385 int32_t ind[17];
386 getScoefficients(iu, iv, fGridU.getKnot(pu).u, fGridV.getKnot(pv).u, c, ind);
387 c[16] = -1.;
388 ind[16] = ip;
389 // S = sum c[i]*Par[ind[i]]
390 double w = 1.e-8;
391 for (int32_t i = 0; i < 17; i++) {
392 for (int32_t j = i; j < 17; j++) {
393 solver.A(ind[i], ind[j]) += w * c[i] * c[j];
394 }
395 }
396 }
397 }
398 }
399
400 solver.solve();
401 for (int32_t i = 0; i < nPar; i++) {
402 for (int32_t iDim = 0; iDim < nFdim; iDim++) {
403 splineParameters[i * nFdim + iDim] = solver.B(i, iDim);
404 }
405 }
406}
407
408template <typename DataT>
409int32_t Spline2DHelper<DataT>::test(const bool draw, const bool drawDataPoints)
410{
411 using namespace std;
412
413 const int32_t Ndim = 3;
414
415 const int32_t Fdegree = 4;
416
417 double Fcoeff[Ndim][4 * (Fdegree + 1) * (Fdegree + 1)];
418
419 constexpr int32_t nKnots = 10;
420 constexpr int32_t nAuxiliaryPoints = 2;
421 constexpr int32_t uMax = nKnots; //* 3;
422
423 auto F = [&](double u, double v, double Fuv[]) {
424 const double scale = TMath::Pi() / uMax;
425 double uu = u * scale;
426 double vv = v * scale;
427 double cosu[Fdegree + 1], sinu[Fdegree + 1], cosv[Fdegree + 1], sinv[Fdegree + 1];
428 double ui = 0, vi = 0;
429 for (int32_t i = 0; i <= Fdegree; i++, ui += uu, vi += vv) {
430 GPUCommonMath::SinCosd(ui, sinu[i], cosu[i]);
431 GPUCommonMath::SinCosd(vi, sinv[i], cosv[i]);
432 }
433 for (int32_t dim = 0; dim < Ndim; dim++) {
434 double f = 0; // Fcoeff[dim][0]/2;
435 for (int32_t i = 1; i <= Fdegree; i++) {
436 for (int32_t j = 1; j <= Fdegree; j++) {
437 double* c = &(Fcoeff[dim][4 * (i * Fdegree + j)]);
438 f += c[0] * cosu[i] * cosv[j];
439 f += c[1] * cosu[i] * sinv[j];
440 f += c[2] * sinu[i] * cosv[j];
441 f += c[3] * sinu[i] * sinv[j];
442 }
443 }
444 Fuv[dim] = f;
445 }
446 };
447
448 TCanvas* canv = nullptr;
449 TNtuple* nt = nullptr;
450 TNtuple* knots = nullptr;
451
452 auto ask = [&]() -> bool {
453 if (!canv) {
454 return 0;
455 }
456 canv->Update();
457 LOG(info) << "type 'q ' to exit";
458 std::string str;
459 std::getline(std::cin, str);
460 return (str != "q" && str != ".q");
461 };
462
463 LOG(info) << "Test 2D interpolation with the compact spline";
464
465 int32_t nTries = 100;
466
467 if (draw) {
468 canv = new TCanvas("cQA", "Spline2D QA", 1500, 800);
469 nTries = 10000;
470 }
471
472 double statDf = 0;
473 double statDf1D = 0;
474 double statN = 0;
475
476 auto statTime = std::chrono::nanoseconds::zero();
477
478 for (int32_t seed = 1; seed < nTries + 1; seed++) {
479 // LOG(info) << "next try.." ;
480
481 gRandom->SetSeed(seed);
482
483 for (int32_t dim = 0; dim < Ndim; dim++) {
484 for (int32_t i = 0; i < 4 * (Fdegree + 1) * (Fdegree + 1); i++) {
485 Fcoeff[dim][i] = gRandom->Uniform(-1, 1);
486 }
487 }
488
490
491 int32_t knotsU[nKnots], knotsV[nKnots];
492 do {
493 knotsU[0] = 0;
494 knotsV[0] = 0;
495 double du = 1. * uMax / (nKnots - 1);
496 for (int32_t i = 1; i < nKnots; i++) {
497 knotsU[i] = (int32_t)(i * du); // + gRandom->Uniform(-du / 3, du / 3);
498 knotsV[i] = (int32_t)(i * du); // + gRandom->Uniform(-du / 3, du / 3);
499 }
500 knotsU[nKnots - 1] = uMax;
501 knotsV[nKnots - 1] = uMax;
502 spline.recreate(nKnots, knotsU, nKnots, knotsV);
503
504 if (nKnots != spline.getGridX1().getNumberOfKnots() ||
505 nKnots != spline.getGridX2().getNumberOfKnots()) {
506 LOG(info) << "warning: n knots changed during the initialisation " << nKnots
507 << " -> " << spline.getNumberOfKnots();
508 continue;
509 }
510 } while (0);
511
512 std::string err = FlatObject::stressTest(spline);
513 if (!err.empty()) {
514 LOG(info) << "error at FlatObject functionality: " << err;
515 return -1;
516 } else {
517 // LOG(info) << "flat object functionality is ok" ;
518 }
519
520 // Ndim-D spline
521
522 auto startTime = std::chrono::high_resolution_clock::now();
523 spline.approximateFunctionViaDataPoints(0., uMax, 0., uMax, F, nAuxiliaryPoints, nAuxiliaryPoints);
524 auto stopTime = std::chrono::high_resolution_clock::now();
525 statTime += std::chrono::duration_cast<std::chrono::nanoseconds>(stopTime - startTime);
526
527 // if (itry == 0)
528 if (0) {
529 TFile outf("testSpline2D.root", "recreate");
530 if (outf.IsZombie()) {
531 LOG(info) << "Failed to open output file testSpline2D.root ";
532 } else {
533 const char* name = "spline2Dtest";
534 spline.writeToFile(outf, name);
536 if (p == nullptr) {
537 LOG(info) << "Failed to read Spline1DOld from file testSpline1DOld.root ";
538 } else {
539 spline = *p;
540 }
541 outf.Close();
542 }
543 }
544
545 // 1-D splines for each of Ndim dimensions
546
547 Spline2D<DataT, 1> splines1D[Ndim];
548
549 for (int32_t dim = 0; dim < Ndim; dim++) {
550 auto F1 = [&](double x1, double x2, double f[]) {
551 double ff[Ndim];
552 F(x1, x2, ff);
553 f[0] = ff[dim];
554 };
555 splines1D[dim].recreate(nKnots, knotsU, nKnots, knotsV);
556 splines1D[dim].approximateFunctionViaDataPoints(0., uMax, 0., uMax, F1, nAuxiliaryPoints, nAuxiliaryPoints);
557 }
558
559 double stepU = .1;
560 for (double u = 0; u < uMax; u += stepU) {
561 for (double v = 0; v < uMax; v += stepU) {
562 double f[Ndim];
563 F(u, v, f);
564 DataT s[Ndim];
565 spline.interpolate(u, v, s);
566 for (int32_t dim = 0; dim < Ndim; dim++) {
567 statDf += (s[dim] - f[dim]) * (s[dim] - f[dim]);
568 DataT s1 = splines1D[dim].interpolate(u, v);
569 statDf1D += (s[dim] - s1) * (s[dim] - s1);
570 }
571 statN += Ndim;
572 // LOG(info) << u << " " << v << ": f " << f << " s " << s << " df "
573 // << s - f << " " << sqrt(statDf / statN) ;
574 }
575 }
576 // LOG(info) << "Spline2D standard deviation : " << sqrt(statDf / statN)
577 // ;
578
579 if (draw) {
580 delete nt;
581 delete knots;
582 nt = new TNtuple("nt", "nt", "u:v:f:s");
583 knots = new TNtuple("knots", "knots", "type:u:v:s");
584 double stepU = .3;
585 for (double u = 0; u < uMax; u += stepU) {
586 for (double v = 0; v < uMax; v += stepU) {
587 double f[Ndim];
588 F(u, v, f);
589 DataT s[Ndim];
590 spline.interpolate(u, v, s);
591 nt->Fill(u, v, f[0], s[0]);
592 }
593 }
594 nt->SetMarkerStyle(8);
595
596 nt->SetMarkerSize(.5);
597 nt->SetMarkerColor(kBlue);
598 nt->Draw("s:u:v", "", "");
599
600 nt->SetMarkerColor(kGray);
601 nt->SetMarkerSize(2.);
602 nt->Draw("f:u:v", "", "same");
603
604 nt->SetMarkerSize(.5);
605 nt->SetMarkerColor(kBlue);
606 nt->Draw("s:u:v", "", "same");
607
608 for (int32_t i = 0; i < nKnots; i++) {
609 for (int32_t j = 0; j < nKnots; j++) {
610 double u = spline.getGridX1().getKnot(i).u;
611 double v = spline.getGridX2().getKnot(j).u;
612 DataT s[Ndim];
613 spline.interpolate(u, v, s);
614 knots->Fill(1, u, v, s[0]);
615 }
616 }
617
618 knots->SetMarkerStyle(8);
619 knots->SetMarkerSize(1.5);
620 knots->SetMarkerColor(kRed);
621 knots->SetMarkerSize(1.5);
622 knots->Draw("s:u:v", "type==1", "same"); // knots
623
624 if (drawDataPoints) {
626 helper.setSpline(spline, 4, 4);
627 for (int32_t ipu = 0; ipu < helper.getHelperU1().getNumberOfDataPoints(); ipu++) {
628 const typename Spline1DHelperOld<DataT>::DataPoint& pu = helper.getHelperU1().getDataPoint(ipu);
629 for (int32_t ipv = 0; ipv < helper.getHelperU2().getNumberOfDataPoints(); ipv++) {
630 const typename Spline1DHelperOld<DataT>::DataPoint& pv = helper.getHelperU2().getDataPoint(ipv);
631 if (pu.isKnot && pv.isKnot) {
632 continue;
633 }
634 DataT s[Ndim];
635 spline.interpolate(pu.u, pv.u, s);
636 knots->Fill(2, pu.u, pv.u, s[0]);
637 }
638 }
639 knots->SetMarkerColor(kBlack);
640 knots->SetMarkerSize(1.);
641 knots->Draw("s:u:v", "type==2", "same"); // data points
642 }
643
644 if (!ask()) {
645 break;
646 }
647 }
648 }
649 // delete canv;
650 // delete nt;
651 // delete knots;
652
653 statDf = sqrt(statDf / statN);
654 statDf1D = sqrt(statDf1D / statN);
655
656 LOG(info) << "\n std dev for Spline2D : " << statDf;
657 LOG(info) << " mean difference between 1-D and " << Ndim
658 << "-D splines : " << statDf1D;
659 LOG(info) << " approximation time " << statTime.count() / 1000. / nTries << " ms";
660
661 if (statDf < 0.15 && statDf1D < 1.e-20) {
662 LOG(info) << "Everything is fine";
663 } else {
664 LOG(info) << "Something is wrong!!";
665 return -2;
666 }
667
668 return 0;
669}
670
671template class o2::gpu::Spline2DHelper<float>;
int32_t i
Definition of SymMatrixSolver class.
uint32_t j
Definition RawData.h:0
uint32_t c
Definition RawData.h:2
Definition of Spline1DHelper class.
Definition of Spline2DHelper class.
static std::string stressTest(T &obj)
Test the flat object functionality for a child class T.
Definition FlatObject.h:411
static void getScoefficients(const typename Spline1D< double >::Knot &knotL, double u, double &cSl, double &cDl, double &cSr, double &cDr)
mGridX2 setXrange(x2Min, x2Max)
int32_t setSpline(const Spline2DContainer< DataT > &spline, int32_t nAuxiliaryPointsU1, int32_t nAuxiliaryPointsU2)
_______________ Interface for a step-wise construction of the best-fit spline _______________________...
const Spline1DHelperOld< DataT > & getHelperU2() const
const Spline1DHelperOld< DataT > & getHelperU1() const
void approximateFunction(Spline2DContainer< DataT > &spline, double x1Min, double x1Max, double x2Min, double x2Max, std::function< void(double x1, double x2, double f[])> F, int32_t nAuxiliaryDataPointsU1=4, int32_t nAuxiliaryDataPointsU2=4)
_______________ Main functionality ________________________
void approximateFunctionViaDataPoints(Spline2DContainer< DataT > &spline, double x1Min, double x1Max, double x2Min, double x2Max, std::function< void(double x1, double x2, double f[])> F, int32_t nAuxiliaryDataPointsU1=4, int32_t nAuxiliaryDataPointsU2=4)
void approximateFunctionBatch(DataT *Fparameters, double x1Min, double x1Max, double x2Min, double x2Max, std::function< void(const std::vector< double > &x1, const std::vector< double > &x2, std::vector< double > f[])> F, uint32_t batchsize) const
approximate std::function, output in Fparameters. F calculates values for a batch of points.
void approximateDataPoints(Spline2DContainer< DataT > &spline, DataT *splineParameters, double x1Min, double x1Max, double x2Min, double x2Max, const double dataPointX1[], const double dataPointX2[], const double dataPointF[], int32_t nDataPoints)
Create best-fit spline parameters for a given set of data points.
Spline2DHelper()
_____________ Constructors / destructors __________________________
static int32_t test(const bool draw=0, const bool drawDataPoints=1)
Test the Spline2D class functionality.
static Spline2D * readFromFile(TFile &inpf, const char *name)
read a class object from the file
Definition Spline2D.h:101
double & B(int32_t i, int32_t j)
access to B elements
double & A(int32_t i, int32_t j)
access to A elements
const GLdouble * v
Definition glcorearb.h:832
GLuint GLfloat GLfloat GLfloat x1
Definition glcorearb.h:5034
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat s1
Definition glcorearb.h:5034
GLuint index
Definition glcorearb.h:781
GLuint const GLchar * name
Definition glcorearb.h:781
GLdouble f
Definition glcorearb.h:310
GLsizei GLenum const void * indices
Definition glcorearb.h:400
GLubyte GLubyte GLubyte GLubyte w
Definition glcorearb.h:852
GLuint counter
Definition glcorearb.h:3987
Defining DataPointCompositeObject explicitly as copiable.
Helper structure for 1D spline construction.
bool isKnot
is the point placed at a knot
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
const std::string str
uint64_t const void const *restrict const msg
Definition x9.h:153