Project
Loading...
Searching...
No Matches
IrregularSpline2D3DCalibrator.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
17
18#include "IrregularSpline2D3D.h"
20#include "GPUCommonLogger.h"
21
22#include <cmath>
23#include <iostream>
24
25namespace o2
26{
27namespace gpu
28{
29
36
37void IrregularSpline2D3DCalibrator::setRasterSize(int32_t nKnotsU, int32_t nKnotsV)
38{
40
41 int32_t n[2] = {nKnotsU, nKnotsV};
42
43 for (int32_t uv = 0; uv < 2; ++uv) {
44 if (n[uv] < mMaxNKnots[uv]) {
45 n[uv] = mMaxNKnots[uv];
46 }
47 }
48
49 mRaster.constructRegular(n[0], n[1]);
50}
51
52void IrregularSpline2D3DCalibrator::setMaxNKnots(int32_t nKnotsU, int32_t nKnotsV)
53{
55
56 mMaxNKnots[0] = nKnotsU;
57 mMaxNKnots[1] = nKnotsV;
58
59 for (int32_t uv = 0; uv < 2; ++uv) {
60 if (mMaxNKnots[uv] < 5) {
61 mMaxNKnots[uv] = 5;
62 }
63 }
64}
65
66void IrregularSpline2D3DCalibrator::startCalibration(std::function<void(float, float, float&, float&, float&)> F)
67{
68 // initialize everything for the calibration
69
70 // fill the raster data
71 mRasterData.resize(mRaster.getNumberOfKnots() * 3);
72
73 for (int32_t i = 0; i < mRaster.getNumberOfKnots(); ++i) {
74 float u = 0, v = 0, fx = 0, fy = 0, fz = 0;
75 mRaster.getKnotUV(i, u, v);
76 F(u, v, fx, fy, fz);
77 mRasterData[3 * i + 0] = fx;
78 mRasterData[3 * i + 1] = fy;
79 mRasterData[3 * i + 2] = fz;
80 }
81
82 mRaster.correctEdges(mRasterData.data());
83
84 // create current spline
85 for (int32_t uv = 0; uv < 2; ++uv) {
86 // LOG(info)<<"n Raster knots: "<<mRaster.getGrid(uv).getNumberOfKnots();
87 mKnots[uv].clear();
88 double du = 1. / (mMaxNKnots[uv] - 1);
89 int32_t lastKnot = 0;
90 for (int32_t i = 1; i < mMaxNKnots[uv] - 1; ++i) {
91 KnotData d;
92 d.uv = uv;
93 double u = i * du;
94 d.rasterKnot = nearbyint(u * (mRaster.getGrid(uv).getNumberOfKnots() - 1));
95 // LOG(info)<<"uv "<<uv<<" i "<<d.rasterKnot<<" u "<<u;
96 if (d.rasterKnot <= lastKnot) {
97 continue;
98 }
99 if (d.rasterKnot >= mRaster.getGrid(uv).getNumberOfKnots() - 1) {
100 continue;
101 }
102 mKnots[uv].push_back(d);
103 lastKnot = d.rasterKnot;
104 }
105 }
106
107 createCurrentSpline();
108}
109
110void IrregularSpline2D3DCalibrator::createCurrentSpline()
111{
112 createSpline(mSpline, mSplineData);
113}
114
115void IrregularSpline2D3DCalibrator::createActionSpline()
116{
117 createSpline(mActionSpline, mActionSplineData);
118}
119
120void IrregularSpline2D3DCalibrator::createSpline(IrregularSpline2D3D& sp, std::vector<float>& data)
121{
122 // recreate a spline with respect to knots in mKnots[] lists
123
124 for (int32_t uv = 0; uv < 2; ++uv) {
125 mTemp[uv].reserve(mMaxNKnots[uv]);
126 mTemp[uv].clear();
127 mTemp[uv].push_back(0.f);
128 for (std::list<KnotData>::iterator i = mKnots[uv].begin(); i != mKnots[uv].end(); ++i) {
129 // LOG(info)<<"uv "<<uv<<" i "<<i->rasterKnot<<" u "<<mRaster.getGrid(uv).getKnot(i->rasterKnot).u;
130 mTemp[uv].push_back(mRaster.getGrid(uv).getKnot(i->rasterKnot).u);
131 }
132 mTemp[uv].push_back(1.f);
133 }
134
135 sp.construct(mTemp[0].size(), mTemp[0].data(), mRaster.getGrid(0).getNumberOfKnots(),
136 mTemp[1].size(), mTemp[1].data(), mRaster.getGrid(1).getNumberOfKnots());
137
138 data.resize(sp.getNumberOfKnots() * 3);
139 for (int32_t i = 0; i < sp.getNumberOfKnots(); ++i) {
140 float u = 0, v = 0, fx = 0, fy = 0, fz = 0;
141 sp.getKnotUV(i, u, v);
142 mRaster.getSplineVec(mRasterData.data(), u, v, fx, fy, fz);
143 data[3 * i + 0] = fx;
144 data[3 * i + 1] = fy;
145 data[3 * i + 2] = fz;
146 }
147 sp.correctEdges(data.data());
148}
149
150IrregularSpline2D3DCalibrator::Action IrregularSpline2D3DCalibrator::checkActionShift(std::list<KnotData>::iterator& knot)
151{
152 // estimate the cost change when the knot i is shifted up or down
153
154 Action ret;
155 ret.action = Action::Move::No;
156 ret.cost = mMaxDeviation + 1.e10;
157 ret.iter = knot;
158
159 int32_t uv = knot->uv;
160
161 bool isSpaceUp = 0;
162
163 if (knot->rasterKnot < mRaster.getGrid(uv).getNumberOfKnots() - 2) {
164 isSpaceUp = 1;
165 std::list<KnotData>::iterator next = knot;
166 ++next;
167 if (next != mKnots[uv].end()) {
168 if (next->rasterKnot <= knot->rasterKnot + 1) {
169 isSpaceUp = 0;
170 }
171 }
172 }
173
174 bool isSpaceDn = 0;
175
176 if (knot->rasterKnot > 1) {
177 isSpaceDn = 1;
178 std::list<KnotData>::iterator prev = knot;
179 if (prev != mKnots[uv].begin()) {
180 --prev;
181 if (prev->rasterKnot >= knot->rasterKnot - 1) {
182 isSpaceDn = 0;
183 }
184 }
185 }
186
187 if (!isSpaceUp && !isSpaceDn) {
188 return ret;
189 }
190 // get the area of interest
191
192 int32_t regionKnotFirst = knot->rasterKnot;
193 int32_t regionKnotLast = knot->rasterKnot;
194 getRegionOfInfluence(knot, regionKnotFirst, regionKnotLast);
195
196 // get the current cost
197
198 double costCurrent = getIntegralDeviationArea(mSpline, mSplineData, uv, regionKnotFirst, regionKnotLast);
199
200 // get the cost when moving up
201
202 if (isSpaceUp) {
203 knot->rasterKnot++;
204 createActionSpline();
205 knot->rasterKnot--;
206 ret.action = Action::Move::Up;
207 ret.cost = getIntegralDeviationArea(mActionSpline, mActionSplineData, uv, regionKnotFirst, regionKnotLast) - costCurrent;
208 }
209
210 if (isSpaceDn) {
211 knot->rasterKnot--;
212 createActionSpline();
213 knot->rasterKnot++;
214 double costDn = getIntegralDeviationArea(mActionSpline, mActionSplineData, uv, regionKnotFirst, regionKnotLast) - costCurrent;
215 if (costDn < ret.cost) {
216 ret.action = Action::Move::Down;
217 ret.cost = costDn;
218 }
219 }
220 // if( ret.cost<0 ) LOG(info)<<"knot "<<knot->rasterKnot<<" area: "<<regionKnotFirst<<"<->"<<regionKnotLast<<" costCurrent "<<costCurrent;
221
222 return ret;
223}
224
225IrregularSpline2D3DCalibrator::Action IrregularSpline2D3DCalibrator::checkActionRemove(std::list<KnotData>::iterator& knot)
226{
227 // estimate the cost change when the knot i is shifted up or down
228
229 Action ret;
230 ret.action = Action::Move::No;
231 ret.cost = mMaxDeviation + 1.e10;
232 ret.iter = knot;
233
234 int32_t uv = knot->uv;
235
236 if (mSpline.getGrid(uv).getNumberOfKnots() <= 5) {
237 return ret;
238 }
239 // get the area of interest
240
241 int32_t regionKnotFirst = knot->rasterKnot;
242 int32_t regionKnotLast = knot->rasterKnot;
243
244 getRegionOfInfluence(knot, regionKnotFirst, regionKnotLast);
245
246 // LOG(info)<<"uv "<<uv<<" knot "<<knot->rasterKnot<<" region: "<<regionKnotFirst<<" <-> "<<regionKnotLast;
247
248 KnotData tmp = *knot;
249 std::list<KnotData>::iterator next = mKnots[uv].erase(knot);
250 createActionSpline();
251 knot = mKnots[uv].insert(next, tmp);
252
253 // get the cost
254
255 ret.action = Action::Move::Remove;
256 ret.cost = getMaxDeviationArea(mActionSpline, mActionSplineData, uv, regionKnotFirst, regionKnotLast);
257 ret.iter = knot;
258
259 return ret;
260}
261
262void IrregularSpline2D3DCalibrator::getRegionOfInfluence(std::list<KnotData>::iterator knot, int32_t& regionKnotFirst, int32_t& regionKnotLast) const
263{
264 int32_t uv = knot->uv;
265 regionKnotFirst = knot->rasterKnot;
266 regionKnotLast = knot->rasterKnot;
267 std::list<KnotData>::iterator next = knot;
268 std::list<KnotData>::iterator prev = knot;
269 for (int32_t i = 0; i < 3; ++i) {
270 if (prev != mKnots[uv].begin()) {
271 --prev;
272 regionKnotFirst = prev->rasterKnot;
273 } else {
274 regionKnotFirst = 0;
275 }
276
277 if (next != mKnots[uv].end()) {
278 ++next;
279 if (next != mKnots[uv].end()) {
280 regionKnotLast = next->rasterKnot;
281 } else {
282 regionKnotLast = mRaster.getGrid(uv).getNumberOfKnots() - 1;
283 }
284 }
285 }
286}
287
289{
290 // perform one step of the calibration
291
292 // first, try to move a knot
293 // LOG(info)<<"do step.. ";
294 Action bestAction;
295 bestAction.action = Action::Move::No;
296 bestAction.cost = 1.e10;
297
298 for (int32_t uv = 0; uv < 2; ++uv) {
299 for (std::list<KnotData>::iterator i = mKnots[uv].begin(); i != mKnots[uv].end(); ++i) {
300 Action a = checkActionShift(i);
301 if (a.cost < bestAction.cost) {
302 bestAction = a;
303 }
304 }
305 }
306
307 // LOG(info)<<"move cost: "<<bestAction.cost;
308 if (bestAction.cost < 0) { // shift the best knot
309 if (bestAction.action == Action::Move::Up) {
310 // LOG(info)<<"move Up uv "<< bestAction.iter->uv<<" knot "<<bestAction.iter->rasterKnot<<" -> "<<bestAction.iter->rasterKnot+1;
311 bestAction.iter->rasterKnot++;
312 } else if (bestAction.action == Action::Move::Down) {
313 // LOG(info)<<"move Down uv "<< bestAction.iter->uv<<" knot "<<bestAction.iter->rasterKnot<<" -> "<<bestAction.iter->rasterKnot-1;
314 bestAction.iter->rasterKnot--;
315 } else {
316 std::cerr << "Internal error!!!";
317 return 0;
318 }
319 createCurrentSpline();
320 return 1;
321 }
322
323 // second, try to remove a knot
324
325 // for (int32_t axis = 0; axis < 2; axis++) {
326 bestAction.action = Action::Move::No;
327 bestAction.cost = mMaxDeviation + 1.e10;
328
329 for (int32_t uv = 0; uv < 2; ++uv) {
330
331 for (std::list<KnotData>::iterator i = mKnots[uv].begin(); i != mKnots[uv].end(); ++i) {
332 Action a = checkActionRemove(i);
333 if (a.cost < bestAction.cost) {
334 bestAction = a;
335 }
336 }
337 }
338 bestAction.cost = sqrt(bestAction.cost / 3.);
339
340 // LOG(info)<<"remove cost: "<<bestAction.cost;
341
342 if (bestAction.cost <= mMaxDeviation) { // move the best knot
343 if (bestAction.action == Action::Move::Remove) {
344 // LOG(info)<<"remove uv "<< bestAction.iter->uv<<" knot "<<bestAction.iter->rasterKnot;
345 mKnots[bestAction.iter->uv].erase(bestAction.iter);
346 } else {
347 LOG(info) << "Internal error!!!";
348 return 0;
349 }
350 createCurrentSpline();
351 return 1;
352 }
353
354 return 0;
355}
356
358 std::function<void(float, float, float&, float&, float&)> F)
359{
360 // main method: spline calibration
361
363 while (doCalibrationStep()) {
364 ;
365 }
366 createCurrentSpline();
367 spline_uv.cloneFromObject(mSpline, nullptr);
368 std::unique_ptr<float[]> tmp(new float[mSpline.getNumberOfKnots()]);
369 for (int32_t i = 0; i < mSpline.getNumberOfKnots(); ++i) {
370 tmp[i] = mSplineData[i];
371 }
372 return tmp;
373}
374
375double IrregularSpline2D3DCalibrator::getMaxDeviationLine(const IrregularSpline2D3D& spline, const std::vector<float>& data, int32_t axis0, int32_t knot0) const
376{
377 int32_t axis1 = (axis0 == 0) ? 1 : 0;
378 float u[2];
379 u[axis0] = mRaster.getGrid(axis0).getKnot(knot0).u;
380
381 double dMax2 = 0.;
382
383 for (int32_t knot1 = 0; knot1 < mRaster.getGrid(axis1).getNumberOfKnots(); ++knot1) {
384 u[axis1] = mRaster.getGrid(axis1).getKnot(knot1).u;
385 float fx0, fy0, fz0, fx, fy, fz;
386 mRaster.getSplineVec(mRasterData.data(), u[0], u[1], fx0, fy0, fz0);
387 spline.getSplineVec(data.data(), u[0], u[1], fx, fy, fz);
388 double dx = fx - fx0;
389 double dy = fy - fy0;
390 double dz = fz - fz0;
391 double d2 = dx * dx + dy * dy + dz * dz;
392 if (dMax2 < d2) {
393 dMax2 = d2;
394 }
395 }
396 return dMax2;
397}
398
399double IrregularSpline2D3DCalibrator::getMaxDeviationArea(const IrregularSpline2D3D& spline, const std::vector<float>& data,
400 int32_t axis, int32_t knotFirst, int32_t knotLast) const
401{
402 double dMax = 0.;
403 for (int32_t knot = knotFirst; knot <= knotLast; ++knot) {
404 double d = getMaxDeviationLine(spline, data, axis, knot);
405 if (dMax < d) {
406 dMax = d;
407 }
408 }
409 return dMax;
410}
411
412double IrregularSpline2D3DCalibrator::getIntegralDeviationLine(const IrregularSpline2D3D& spline, const std::vector<float>& data, int32_t axis0, int32_t knot0) const
413{
414 int32_t axis1 = (axis0 == 0) ? 1 : 0;
415 float u[2];
416 u[axis0] = mRaster.getGrid(axis0).getKnot(knot0).u;
417
418 double sum = 0.;
419
420 for (int32_t knot1 = 0; knot1 < mRaster.getGrid(axis1).getNumberOfKnots(); ++knot1) {
421 u[axis1] = mRaster.getGrid(axis1).getKnot(knot1).u;
422 float fx0, fy0, fz0, fx, fy, fz;
423 mRaster.getSplineVec(mRasterData.data(), u[0], u[1], fx0, fy0, fz0);
424 spline.getSplineVec(data.data(), u[0], u[1], fx, fy, fz);
425 double dx = fx - fx0;
426 double dy = fy - fy0;
427 double dz = fz - fz0;
428 double d2 = dx * dx + dy * dy + dz * dz;
429 sum += sqrt(d2 / 3.);
430 }
431 //sum = sqrt(sum/3.);
432 return sum;
433}
434
435double IrregularSpline2D3DCalibrator::getIntegralDeviationArea(const IrregularSpline2D3D& spline, const std::vector<float>& data,
436 int32_t axis, int32_t knotFirst, int32_t knotLast) const
437{
438 double sum = 0.;
439 for (int32_t knot = knotFirst; knot <= knotLast; ++knot) {
440 sum += getIntegralDeviationLine(spline, data, axis, knot);
441 }
442 return sum;
443}
444
445} // namespace gpu
446} // namespace o2
int32_t i
Definition of IrregularSpline2D3DCalibrator class.
Definition of IrregularSpline2D3D class.
std::unique_ptr< float[]> calibrateSpline(IrregularSpline2D3D &spline_uv, std::function< void(float, float, float &, float &, float &)> F)
void startCalibration(std::function< void(float, float, float &, float &, float &)> F)
void setMaxNKnots(int32_t nKnotsU, int32_t nKnotsV)
set maximal size of the spline grid
IrregularSpline2D3DCalibrator()
_____________ Constructors / destructors __________________________
void setRasterSize(int32_t nKnotsU, int32_t nKnotsV)
set size of the raster grid
void cloneFromObject(const IrregularSpline2D3D &obj, char *newFlatBufferPtr)
Construction interface.
void constructRegular(int32_t numberOfKnotsU, int32_t numberOfKnotsV)
Constructor for a regular spline.
float sum(float s, o2::dcs::DataPointValue v)
Definition dcs-ccdb.cxx:39
GLdouble n
Definition glcorearb.h:1982
GLsizeiptr size
Definition glcorearb.h:659
GLuint GLuint end
Definition glcorearb.h:469
const GLdouble * v
Definition glcorearb.h:832
GLboolean * data
Definition glcorearb.h:298
GLboolean GLboolean GLboolean GLboolean a
Definition glcorearb.h:1233
Enum< T >::Iterator begin(Enum< T >)
Definition Defs.h:173
value_T d2
Definition TrackUtils.h:135
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
define the action to be done by the writer
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"