JAPAn
Just Another Parity Analyzer
Loading...
Searching...
No Matches
QwInterpolator.h
Go to the documentation of this file.
1/*!n * \file QwInterpolator.h
2 * \brief Multi-dimensional grid interpolation methods
3 */
4
5#pragma once
6
7// System headers
8#include <vector>
9#include <fstream>
10#include <iostream>
11#include <stdexcept>
12#include <stdint.h>
13
14// Qweak headers
15#include "QwLog.h"
16
17/// Allowed interpolation methods
23
24// Define of the log stream and end line
25#define mycout QwMessage
26#define mycerr QwError
27#define myendl QwLog::endl
28
29// Type of grid coordinates
30typedef double coord_t;
31
32/**
33 * \class QwInterpolator
34 * \ingroup QwAnalysis
35 * \brief A multi-dimensional grid of values with interpolation methods
36 *
37 * This class provides various interpolation methods on a multi-dimensional grid
38 * of multi-dimensional values. Linear interpolation and nearest-neighbor are
39 * implemented for all dimensions.
40 *
41 * The template arguments are the internal storage data type (defaults to float)
42 * and the number of dimensions of the stored data at each grid point (defaults
43 * to one). The dimension of the grid itself is set through the constructor.
44 * To describe a double vector field with 5 components on a 3-dimensional grid,
45 * you would write
46 * \code
47 * QwInterpolate<float,5> *field = new QwInterpolator<float,5>(3);
48 * \endcode
49 *
50 * The minimum, maximum, and step size of the grid have to be known before
51 * the values are filled.
52 */
53template <class value_t = float, unsigned int value_n = 1>
55
56 public: // constructors and destructor
57
58 /// Constructor with number of dimensions
59 QwInterpolator(const unsigned int ndim = 1) {
60 SetDimensions(ndim);
62 f_cell_index = new unsigned int[fNDim];
63 f_cell_local = new double[fNDim];
64 };
65 /// Constructor with minimum, maximum, and step size
66 QwInterpolator(const std::vector<coord_t>& min,
67 const std::vector<coord_t>& max,
68 const std::vector<coord_t>& step) {
69 SetDimensions(min.size());
71 SetMinimumMaximumStep(min,max,step);
72 f_cell_index = new unsigned int[fNDim];
73 f_cell_local = new double[fNDim];
74 };
75 /// Constructor with file name
76 QwInterpolator(const std::string& filename) {
77 ReadBinaryFile(filename);
79 f_cell_index = new unsigned int[fNDim];
80 f_cell_local = new double[fNDim];
81 };
82 /// Destructor
83 virtual ~QwInterpolator() {
84 delete[] f_cell_index;
85 delete[] f_cell_local;
86 };
87
88 private: // private member fields
89
90 /// Number of dimensions in coordinates
91 unsigned int fNDim;
92
93 /// Minimum in each dimension
94 std::vector<coord_t> fMin;
95 /// Maximum in each dimension
96 std::vector<coord_t> fMax;
97 /// Step size in each dimension
98 std::vector<coord_t> fStep;
99 /// Number of points in each dimension
100 std::vector<size_t> fSize;
101 /// Wrap around this coordinate
102 std::vector<size_t> fWrap;
103 /// Data reduction factor
104 std::vector<size_t> fRedux;
105
106 /// Linear extent between neighbor points in each dimension (e.g. for the
107 /// least significant index this will be 1, for the next index the number
108 /// of points in the first index, etc...)
109 std::vector<size_t> fExtent;
110
111 /// Table with pointers to arrays of values
112 std::vector<value_t> fValues[value_n];
113
114 /// Number of values read in
115 unsigned int fCurrentEntries;
116 /// Maximum number of values
117 unsigned int fMaximumEntries;
118
119 /// Pre-allocated cell index
120 unsigned int* f_cell_index;
121 /// Pre-allocated local coordinates
123
124
125 /// Interpolation method
127
128 public: // public methods
129
130 /// Set the number of coordinate dimensions and resize vectors
131 void SetDimensions(const unsigned int ndim) {
132 if (ndim == 0) {
133 mycerr << "Dimensions of the grid should be strictly positive!" << myendl;
134 return;
135 }
136 fNDim = ndim;
137 fMin.resize(fNDim); fMax.resize(fNDim); fStep.resize(fNDim); fWrap.resize(fNDim);
138 fSize.resize(fNDim); fExtent.resize(fNDim+1);
139 };
140 /// Set minimum, maximum, and step size to single values
141 void SetMinimumMaximumStep(const coord_t min, const coord_t max, const coord_t step) {
142 SetMinimumMaximumStep(std::vector<coord_t>(fNDim,min),
143 std::vector<coord_t>(fNDim,max),
144 std::vector<coord_t>(fNDim,step));
145 };
146 /// Set minimum, maximum, and step size to different values
147 void SetMinimumMaximumStep(const std::vector<coord_t>& min,
148 const std::vector<coord_t>& max,
149 const std::vector<coord_t>& step) {
150 // Set the dimensionality
151 if (min.size() != fNDim) SetDimensions(min.size());
152 // Check the dimensionality and assign boundaries and step size vectors
153 if (min.size() != fNDim || min.size() != fNDim || step.size() != fNDim) return;
154 fMin = min; fMax = max; fStep = step;
155 fExtent[0] = 1;
156 for (size_t i = 0; i < fMin.size(); i++) {
157 coord_t int_part; // safer to use modf than a direct static cast
158 coord_t frac_part = modf((fMax[i] - fMin[i]) / fStep[i] + 1.0, &int_part);
159 fSize[i] = static_cast<unsigned int>(int_part) + (frac_part > 0.5 ? 1 : 0);
160 fExtent[i+1] = fExtent[i] * fSize[i];
161 }
162 // Try resizing to allocate memory and initialize with zeroes
163 fMaximumEntries = fExtent[fNDim]; fCurrentEntries = 0; // no entries read yet
164 for (unsigned int i = 0; i < value_n; i++) {
165 try {
166 fValues[i].resize(fMaximumEntries,0);
167 } catch (std::bad_alloc& e) {
168 mycerr << "QwInterpolator could not allocate memory for values!" << myendl;
169 }
170 }
171 };
172 /// Get minimum in dimension
173 coord_t GetMinimum(const unsigned int dim) const { return fMin.at(dim); };
174 /// Get maximum in dimension
175 coord_t GetMaximum(const unsigned int dim) const { return fMax.at(dim); };
176 /// Get minimum in dimension
177 coord_t GetStepSize(const unsigned int dim) const { return fStep.at(dim); };
178 /// Get the maximum number of entries
179 unsigned int GetMaximumEntries() const { return fMaximumEntries; };
180 /// Get the current number of entries
181 unsigned int GetCurrentEntries() const { return fCurrentEntries; };
182
183 /// Get wrapping coordinate
184 unsigned int GetWrapCoordinate(const unsigned int dim) const
185 { return fWrap.at(dim); }
186 /// Set wrapping coordinate
187 void SetWrapCoordinate(const unsigned int dim, const size_t wrap = 1)
188 { fWrap.at(dim) = wrap; }
189 void SetWrapCoordinate(const std::vector<size_t>& wrap) {
190 if (wrap.size() != fNDim) return;
191 fWrap = wrap;
192 }
193
194 /// Get data reduction factor
195 int GetDataReductionFactor(const unsigned int dim) const
196 { return fRedux.at(dim); }
197 /// Set data reduction factor
198 void SetDataReductionFactor(const unsigned int dim, const unsigned int redux)
199 { fRedux.at(dim) = redux; }
200 void SetDataReductionFactor(const unsigned int redux) {
201 for (unsigned int dim = 0; dim < fNDim; dim++)
202 SetDataReductionFactor(dim,redux);
203 }
204 void SetDataReductionFactor(const std::vector<unsigned int>& redux) {
205 if (redux.size() != fNDim) return;
206 fRedux = redux;
207 }
208
209 /// Set the interpolation method
212 /// Get the interpolation method
215
216
217 /// Print coverage map for all bins in one dimension
218 void PrintCoverage(const unsigned int dim) {
219 // Initialize coverage
220 unsigned int* cover = new unsigned int[fSize[dim]];
221 unsigned int* total = new unsigned int[fSize[dim]];
222 for (unsigned int i = 0; i < fSize[dim]; i++) {
223 cover[i] = 0;
224 total[i] = 0;
225 }
226 // Loop over all entries
227 value_t value[value_n];
228 for (unsigned int linear_index = 0; linear_index < fMaximumEntries; linear_index++) {
229 Cell(linear_index,f_cell_index);
230 total[f_cell_index[dim]]++;
231 if (Get(linear_index,value) && value[0] != 0)
232 cover[f_cell_index[dim]]++; // non-zero field
233 }
234 // Print coverage
235 coord_t* coord = new coord_t[fNDim];
236 for (size_t i = 0; i < fSize[dim]; i++) {
237 f_cell_index[dim] = i;
238 Coord(f_cell_index,coord);
239 mycout << "bin " << i << ", coord " << coord[dim] << ": "
240 << double(cover[i]) / double(total[i]) * 100 << "%"<< myendl;
241 }
242 delete[] coord;
243 delete[] cover;
244 delete[] total;
245 }
246
247 /// Return true if the coordinate is in bounds
248 bool InBounds(const coord_t* coord) const {
249 return Check(coord);
250 };
251
252
253 /// \name Functions to write grid values
254 // @{
255 /// Set a single value at a coordinate (false if not possible)
256 bool Set(const coord_t& coord, const value_t& value) {
257 if (value_n != 1) return false; // only for one-dimensional values
258 if (fNDim != 1) return false; // only for one-dimensional grids
259 return Set(&coord, &value);
260 };
261 /// Set a single value at a coordinate (false if not possible)
262 bool Set(const coord_t* coord, const value_t& value) {
263 if (value_n != 1) return false; // only for one-dimensional values
264 return Set(coord, &value);
265 };
266 /// Set a set of values at a coordinate (false if not possible)
267 bool Set(const coord_t* coord, const value_t* value) {
268 Nearest(coord, f_cell_index); // nearest cell
269 if (! Check(f_cell_index)) return false; // out of bounds
270 bool status = true;
271 bool written = false;
272 unsigned int linear_index;
273 for (unsigned int dim = 0; dim < fNDim; dim++) {
274 // skip dimensions that are not wrapped around
275 if (fWrap[dim] == 0) continue;
276 // FIXME only one wrapping coordinate correctly supported in Set()
277 if ((f_cell_index[dim] < fWrap[dim]) ||
278 (fSize[dim] - f_cell_index[dim] - 1 < fWrap[dim])) {
279 // there are equivalent grid points
280 for (size_t wrap = 0; wrap < fWrap[dim]; wrap++) {
281 // at the minimum
282 f_cell_index[dim] = wrap;
283 linear_index = Index(f_cell_index);
284 status &= Set(linear_index, value);
285 // at the maximum
286 f_cell_index[dim] = fSize[dim] - wrap - 1;
287 linear_index = Index(f_cell_index);
288 status &= Set(linear_index, value);
289 // set flag
290 written = true;
291 }
292 }
293 }
294 if (not written) {
295 // this is an unambiguous grid point
296 linear_index = Index(f_cell_index);
297 status &= Set(linear_index, value);
298 }
299 return status;
300 };
301
302 /// Set a single value at a linearized index (false if not possible)
303 bool Set(const unsigned int linear_index, const value_t& value) {
304 if (value_n != 1) return false; // only for one-dimensional values
305 return Set(linear_index, &value);
306 };
307 /// Set a set of values at a linearized index (false if not possible)
308 bool Set(const unsigned int linear_index, const value_t* value) {
309 if (! Check(linear_index)) return false; // out of bounds
310 for (unsigned int i = 0; i < value_n; i++)
311 fValues[i][linear_index] = value[i];
313 return true;
314 };
315
316 /// Set a single value at a grid point (false if out of bounds)
317 bool Set(const unsigned int* cell_index, const value_t& value) {
318 if (value_n != 1) return false; // only for one-dimensional values
319 return Set(cell_index, &value);
320 };
321 /// Set a set of values at a grid point (false if out of bounds)
322 bool Set(const unsigned int* cell_index, const value_t* value) {
323 if (! Check(cell_index)) return false; // out of bounds
324 return Set(Index(cell_index),value);
325 };
326 // @}
327
328
329 /// \name Functions to retrieve interpolated values
330 // @{
331 /// Get the interpolated value at coordinate (zero if out of bounds)
332 value_t GetValue(const coord_t& coord) const {
333 if (value_n != 1) return false; // only for one-dimensional values
334 if (fNDim != 1) return false; // only for one-dimensional grids
335 value_t value;
336 if (GetValue(&coord, &value)) return value;
337 else return 0; // interpolation failed
338 };
339 /// Get the interpolated value at coordinate (zero if out of bounds)
340 value_t GetValue(const coord_t* coord) const {
341 if (value_n != 1) return 0; // only for one-dimensional values
342 value_t value;
343 if (GetValue(coord, &value)) return value;
344 else return 0; // interpolation failed
345 };
346 /// Get the interpolated value at coordinate (zero if out of bounds)
347 bool GetValue(const coord_t* coord, double& value) const {
348 if (value_n != 1) return false; // only for one-dimensional values
349 return GetValue(coord, &value);
350 };
351 /// Get the interpolated value at coordinate (zero if out of bounds)
352 bool GetValue(const coord_t* coord, double* value) const {
353 for (unsigned int i = 0; i < value_n; i++) value[i] = 0.0; // zero
354 if (! Check(coord)) return false; // out of bounds
355 value_t result[value_n]; // we need a local copy of type value_t
356 switch (fInterpolationMethod) {
357 // return interpolation status
358 case kMultiLinear:
359 if (! Linear(coord, result)) return false;
360 break;
361 case kNearestNeighbor:
362 if (! NearestNeighbor(coord, result)) return false;
363 break;
364 default: return false;
365 }
366 for (unsigned int i = 0; i < value_n; i++) value[i] = result[i]; // cast
367 return true;
368 };
369 // @}
370
371
372 /// \name File reading and writing
373 // @{
374 /// \brief Write the grid as text
375 bool WriteText(std::ostream& stream) const;
376 /// Write the grid to text file
377 bool WriteTextFile(const std::string& filename) const {
378 std::ofstream file(filename.c_str());
379 if (! file.is_open()) return false;
380 WriteText(file);
381 file.close();
382 return true;
383 };
384 /// Write the grid to screen
385 bool WriteTextScreen() const {
386 WriteText(std::cout);
387 return true;
388 };
389 /// \brief Read the grid from text
390 bool ReadText(std::istream& stream);
391 /// Read the grid from text file
392 bool ReadTextFile(const std::string& filename) {
393 std::ifstream file(filename.c_str());
394 if (! file.is_open()) return false;
395 if (! ReadText(file)) return false;
396 file.close();
397 return true;
398 };
399 /// \brief Write the grid values to binary file
400 bool WriteBinaryFile(const std::string& filename) const;
401 /// \brief Read the grid values from binary file
402 bool ReadBinaryFile(const std::string& filename);
403 // @}
404
405
406 /// \name Indexing functions (publicly available and unchecked)
407 // @{
408 /// Return the linearized index based on the point coordinates (unchecked)
409 unsigned int Index(const coord_t* coord) const {
410 Cell(coord, f_cell_index);
411 return Index(f_cell_index);
412 };
413
414 /// \brief Return the linearized index based on the cell indices (unchecked)
415 unsigned int Index(const unsigned int* cell_index) const;
416 /// \brief Return the linearized index based on the cell indices and offset (unchecked)
417 unsigned int Index(const unsigned int* cell_index, const unsigned int offset) const;
418
419 /// \brief Return the cell index and local coordinates in one dimension (unchecked)
420 void Cell(const coord_t coord, unsigned int& cell_index, double& cell_local, const unsigned int dim) const;
421 /// \brief Return the cell index and local coordinates (unchecked)
422 void Cell(const coord_t* coord, unsigned int* cell_index, double* cell_local) const;
423 /// \brief Return the cell index (unchecked)
424 void Cell(const coord_t* coord, unsigned int* cell_index) const;
425 /// \brief Return the cell index based on the linearized index (unchecked)
426 void Cell(unsigned int linear_index, unsigned int* cell_index) const;
427
428 /// \brief Return the coordinates based on the cell index (unchecked)
429 void Coord(const unsigned int* cell_index, coord_t* coord) const;
430 /// \brief Return the coordinates based on the linearized index (unchecked)
431 void Coord(const unsigned int linear_index, coord_t* coord) const;
432 // @}
433
434 private: // private methods
435
436 /// Return the cell index closest to the coordinate (could be above) (unchecked)
437 void Nearest(const coord_t* coord, unsigned int* cell_index) const {
438 Cell(coord, cell_index, f_cell_local);
439 // Loop over all dimensions and add one if larger than 0.5
440 for (unsigned int dim = 0; dim < fNDim; dim++)
441 if (f_cell_local[dim] > 0.5) cell_index[dim]++;
442 };
443
444 /// \brief Linear interpolation (unchecked)
445 bool Linear(const coord_t* coord, value_t* value) const;
446 /// \brief Nearest-neighbor (unchecked)
447 bool NearestNeighbor(const coord_t* coord, value_t* value) const;
448
449 /// \brief Check for boundaries with coordinate argument
450 bool Check(const coord_t* coord) const;
451 /// \brief Check for boundaries with cell index argument
452 bool Check(const unsigned int* cell_index) const;
453 /// \brief Check for boundaries with linearized index argument
454 bool Check(const unsigned int linear_index) const;
455
456 /// Get a single value by cell index (unchecked)
457 value_t Get(const unsigned int* cell_index) const {
458 if (value_n != 1) return 0; // only for one-dimensional values
459 return fValues[0][Index(cell_index)];
460 };
461
462 /// Get a single value by linearized index (unchecked)
463 value_t Get(const unsigned int index) const {
464 return fValues[0][index];
465 };
466 /// Get a vector value by linearized index (unchecked)
467 bool Get(const unsigned int index, value_t* value) const {
468 for (unsigned int i = 0; i < value_n; i++)
469 value[i] = fValues[i][index];
470 return true;
471 };
472
473}; // class QwInterpolator
474
475
476
477/**
478 * Perform the multi-dimensional linear interpolation (unchecked)
479 * @param coord Point coordinates
480 * @param value Interpolated value (reference)
481 */
482template <class value_t, unsigned int value_n>
484 const coord_t* coord,
485 value_t* value) const
486{
487 // Get cell and local normalized coordinates
489 // Initialize to zero
490 for (unsigned int i = 0; i < value_n; i++) value[i] = 0.0;
491 // Calculate the interpolated value
492 // by summing the 2^fNDim = 1 << fNDim neighbor points (1U is unsigned one)
493 for (unsigned int offset = 0; offset < (1U << fNDim); offset++) {
494 value_t neighbor[value_n];
495 if (! Get(Index(f_cell_index,offset), neighbor)) return false;
496 // ... with appropriate weighting factors (1 - cell_local or cell_local)
497 double fac = 1.0;
498 for (unsigned int dim = 0; dim < fNDim; dim++)
499 fac *= ((offset >> dim) & 0x1)? f_cell_local[dim] : (1 - f_cell_local[dim]);
500 // ... for all vector components
501 for (unsigned int i = 0; i < value_n; i++)
502 value[i] += fac * neighbor[i];
503 }
504 return true;
505}
506
507/**
508 * Perform the nearest-neighbor interpolation (unchecked)
509 * @param coord Point coordinates
510 * @param value Interpolated value (reference)
511 */
512template <class value_t, unsigned int value_n>
514 const coord_t* coord,
515 value_t* value) const
516{
517 // Get nearest cell
518 Nearest(coord, f_cell_index);
519 return Get(Index(f_cell_index), value);
520}
521
522/**
523 * Check whether the point is inside the valid region
524 * @param coord Point coordinates
525 * @return True if the coordinates are in the valid region
526 */
527template <class value_t, unsigned int value_n>
528inline bool QwInterpolator<value_t,value_n>::Check(const coord_t* coord) const
529{
530 for (unsigned int dim = 0; dim < fNDim; dim++)
531 if (fWrap[dim] == 0 && (coord[dim] < fMin[dim] || coord[dim] > fMax[dim]))
532 return false;
533 // Otherwise
534 return true;
535}
536
537/**
538 * Check whether the cell index is inside the valid region
539 * @param cell_index Cell index
540 * @return True if the cell index is in the valid region
541 */
542template <class value_t, unsigned int value_n>
543inline bool QwInterpolator<value_t,value_n>::Check(const unsigned int* cell_index) const
544{
545 for (unsigned int dim = 0; dim < fNDim; dim++)
546 if (cell_index[dim] >= fSize[dim])
547 return false;
548 // Otherwise
549 return true;
550}
551
552/**
553 * Check whether the linearized index is inside the valid region
554 * @param linear_index Linearized index
555 * @return True if the cell index is in the valid region
556 */
557template <class value_t, unsigned int value_n>
558inline bool QwInterpolator<value_t,value_n>::Check(const unsigned int linear_index) const
559{
560 if (linear_index >= fMaximumEntries)
561 return false;
562 // Otherwise
563 return true;
564}
565
566/**
567 * Return the linearized index based on the cell indices (unchecked)
568 * @param cell_index Index in each dimension
569 * @return Linearized index
570 */
571template <class value_t, unsigned int value_n>
573 const unsigned int* cell_index) const
574{
575 unsigned int linear_index = 0;
576 // Loop over dimensions
577 for (unsigned int dim = 0; dim < fNDim; dim++)
578 // ... and use the stored extents for every dimensions
579 linear_index += fExtent[dim] * cell_index[dim];
580 return linear_index;
581}
582
583/**
584 * Return the linearized index based on the cell indices and offset (unchecked)
585 * @param cell_index Index in each dimension
586 * @param pattern Bit pattern with offsets in each dimension
587 * @return Linearized index
588 */
589template <class value_t, unsigned int value_n>
591 const unsigned int* cell_index,
592 const unsigned int pattern) const
593{
594 unsigned int linear_index = 0;
595 // Loop over dimensions
596 for (unsigned int dim = 0; dim < fNDim; dim++) {
597 // Add offset of one based on the bit at position dim
598 unsigned int offset = (pattern >> dim) & 0x1;
599 linear_index += fExtent[dim] * (cell_index[dim] + offset);
600 }
601 return linear_index;
602}
603
604/**
605 * Return the cell index and local coordinates in one dimension (unchecked)
606 * @param coord Point coordinate in one dimension
607 * @param cell_index Cell index of the point (reference)
608 * @param cell_local Local coordinates in cell (reference)
609 * @param dim Dimension
610 */
611template <class value_t, unsigned int value_n>
613 const coord_t coord,
614 unsigned int &cell_index,
615 double &cell_local,
616 const unsigned int dim) const
617{
618 // Normalize coordinate (positive, with integers on grid points)
619 double norm_coord = (coord - fMin[dim]) / fStep[dim];
620 // Split in fractional and integer part
621 double frac_part, int_part;
622 frac_part = modf(norm_coord, &int_part);
623 cell_local = frac_part;
624 cell_index = static_cast<int>(int_part); // cast to integer
625 // Wrap index
626 if (fWrap[dim] > 0) cell_index %= (fSize[dim] - fWrap[dim]);
627}
628
629/**
630 * Return the cell index and local coordinates (unchecked)
631 * @param coord Point coordinates
632 * @param cell_index Cell index of the point (reference)
633 * @param cell_local Local coordinates in cell (reference)
634 */
635template <class value_t, unsigned int value_n>
637 const coord_t* coord,
638 unsigned int* cell_index,
639 double* cell_local) const
640{
641 // Get cell index and local coordinates in each dimension
642 for (unsigned int dim = 0; dim < fNDim; dim++)
643 Cell(coord[dim], cell_index[dim], cell_local[dim], dim);
644}
645
646/**
647 * Return the cell index (unchecked)
648 * @param coord Point coordinates
649 * @param cell_index Cell index of the point (reference)
650 */
651template <class value_t, unsigned int value_n>
653 const coord_t* coord,
654 unsigned int* cell_index) const
655{
656 // Get cell index and ignore local coordinates
657 Cell(coord, cell_index, f_cell_local);
658}
659
660/**
661 * Return the cell index based on the linearized index (unchecked)
662 * @param linear_index Linearized index
663 * @param cell_index Cell index (reference)
664 */
665template <class value_t, unsigned int value_n>
667 unsigned int linear_index,
668 unsigned int* cell_index) const
669{
670 // This does not work with unsigned int, because that is always >= 0 and wraps
671 for (int dim = fNDim-1; dim >= 0; dim--) {
672 cell_index[dim] = linear_index / fExtent[dim];
673 linear_index -= cell_index[dim] * fExtent[dim];
674 }
675}
676
677/**
678 * Return the coordinates based on the cell index (unchecked)
679 * @param cell_index Cell index
680 * @param coord Point coordinates (reference)
681 */
682template <class value_t, unsigned int value_n>
684 const unsigned int* cell_index,
685 coord_t* coord) const
686{
687 for (unsigned int dim = 0; dim < fNDim; dim++)
688 coord[dim] = fMin[dim] + cell_index[dim] * fStep[dim];
689}
690
691/**
692 * Return the coordinates based on the linearized index (unchecked)
693 * @param linear_index Linearized index
694 * @param coord Point coordinates (reference)
695 */
696template <class value_t, unsigned int value_n>
698 const unsigned int linear_index,
699 coord_t* coord) const
700{
701 Cell(linear_index,f_cell_index);
702 Coord(f_cell_index,coord);
703}
704
705/**
706 * Write the grid values to a text stream
707 * @param stream Output stream
708 */
709template <class value_t, unsigned int value_n>
710inline bool QwInterpolator<value_t,value_n>::WriteText(std::ostream& stream) const
711{
712 // Informational message
713 mycout << "Writing text stream: ";
714 // Write the dimensions
715 stream << fNDim << "\t" << value_n << std::endl;
716 // Write the grid parameters
717 for (unsigned int dim = 0; dim < fNDim; dim++)
718 stream << dim << "\t" << fMin[dim] << "\t" << fMax[dim] << "\t" << fStep[dim] << std::endl;
719 // Write the values
720 stream << fValues[0].size() << std::endl;
721 unsigned int entries = fValues[0].size();
722 for (unsigned int index = 0; index < entries; index++) {
723 // Write values
724 for (unsigned int i = 0; i < value_n; i++) {
725 stream << fValues[i][index] << "\t";
726 }
727 stream << std::endl;
728 // Progress bar
729 if (index % (entries / 10) == 0)
730 mycout << index / (entries / 100) << "%" << QwLog::flush;
731 if (index % (entries / 10) != 0
732 && index % (entries / 40) == 0)
733 mycout << "." << QwLog::flush;
734 }
735 stream << "end" << std::endl;
736 mycout << myendl;
737 return true;
738}
739
740/**
741 * Read the grid values from a text stream
742 * @param stream Input stream
743 * @return True if successfully read all values
744 */
745template <class value_t, unsigned int value_n>
746inline bool QwInterpolator<value_t,value_n>::ReadText(std::istream& stream)
747{
748 // Informational message
749 mycout << "Reading text stream: ";
750 // Read the dimensions
751 unsigned int n;
752 stream >> fNDim >> n;
753 if (n != value_n) return false; // not same dimensionality
755 // Read the grid parameters
756 for (unsigned int dim = 0; dim < fNDim; dim++)
757 stream >> dim >> fMin[dim] >> fMax[dim] >> fStep[dim];
759 // Read the grid values
760 unsigned int entries;
761 stream >> entries;
762 for (unsigned int index = 0; index < entries; index++) {
763 // Read values
764 for (unsigned int i = 0; i < value_n; i++) {
765 stream >> fValues[i][index];
766 }
767 // Progress bar
768 if (index % (entries / 10) == 0)
769 mycout << index / (entries / 100) << "%" << QwLog::flush;
770 if (index % (entries / 10) != 0
771 && index % (entries / 40) == 0)
772 mycout << "." << QwLog::flush;
773 }
774 // Check for end of file
775 std::string end;
776 stream >> end;
777 // Informational message
778 mycout << myendl;
779 if (end == "end") return true;
780 else return false;
781}
782
783/**
784 * Write the grid values to binary file (should be 64-bit safe, untested)
785 *
786 * Integer data types can be stored differently on 32-bit and 64-bit systems.
787 * Fixed-length types uint32_t and u_int32_t are provided in stdint.h and
788 * sys/types.h, respectively. The floating point types float and double will
789 * always have a length of 32 and 64 bit, per the IEEE convention.
790 *
791 * @param filename File name
792 * @return True if written successfully
793 */
794template <class value_t, unsigned int value_n>
795inline bool QwInterpolator<value_t,value_n>::WriteBinaryFile(const std::string& filename) const
796{
797 std::ofstream file(filename.c_str(), std::ios::binary);
798 if (! file.is_open()) return false;
799 // Informational message
800 mycout << "Writing binary file: ";
801 // Write template parameters
802 uint32_t n = value_n; // uint32_t has length of 32 bits on any system
803 uint32_t size = sizeof(value_t);
804 file.write(reinterpret_cast<const char*>(&n), sizeof(n));
805 file.write(reinterpret_cast<const char*>(&size), sizeof(size));
806 // Write grid parameters
807 uint32_t ndim = fNDim;
808 file.write(reinterpret_cast<const char*>(&ndim), sizeof(ndim));
809 for (unsigned int dim = 0; dim < fNDim; dim++) {
810 file.write(reinterpret_cast<const char*>(&fMin[dim]),sizeof(fMin[dim]));
811 file.write(reinterpret_cast<const char*>(&fMax[dim]),sizeof(fMax[dim]));
812 file.write(reinterpret_cast<const char*>(&fStep[dim]),sizeof(fStep[dim]));
813 }
814 uint32_t entries = fValues[0].size();
815 file.write(reinterpret_cast<const char*>(&entries),sizeof(entries));
816 for (unsigned int index = 0; index < entries; index++) {
817 // Write values
818 for (unsigned int i = 0; i < value_n; i++) {
819 value_t value = fValues[i][index];
820 file.write(reinterpret_cast<const char*>(&value),sizeof(value));
821 }
822 // Progress bar
823 if (index % (entries / 10) == 0)
824 mycout << index / (entries / 100) << "%" << QwLog::flush;
825 if (index % (entries / 10) != 0
826 && index % (entries / 40) == 0)
827 mycout << "." << QwLog::flush;
828 }
829 mycout << myendl;
830 file.close();
831 return true;
832}
833
834/**
835 * Read the grid values from binary file (should be 64-bit safe, untested)
836 * @param filename File name
837 * @return True if read successfully
838 */
839template <class value_t, unsigned int value_n>
840inline bool QwInterpolator<value_t,value_n>::ReadBinaryFile(const std::string& filename)
841{
842 std::ifstream file(filename.c_str(), std::ios::binary);
843 if (! file.is_open()) return false;
844 // Informational message
845 mycout << "Reading binary file: ";
846 // Go to end and store length (could also use std::ios::ate)
847 file.seekg(0, std::ios::end);
848 // Go to begin and start reading template parameters
849 file.seekg(0, std::ios::beg);
850 uint32_t n, size;
851 file.read(reinterpret_cast<char*>(&n), sizeof(n));
852 file.read(reinterpret_cast<char*>(&size), sizeof(size));
853 if (n != value_n) return false; // not same dimensionality
854 if (size != sizeof(value_t)) return false; // not same type
855 // Read grid parameters
856 uint32_t ndim;
857 file.read(reinterpret_cast<char*>(&ndim), sizeof(ndim));
858 SetDimensions(ndim);
859 // Read sizes
860 for (unsigned int dim = 0; dim < fNDim; dim++) {
861 file.read(reinterpret_cast<char*>(&fMin[dim]),sizeof(fMin[dim]));
862 file.read(reinterpret_cast<char*>(&fMax[dim]),sizeof(fMax[dim]));
863 file.read(reinterpret_cast<char*>(&fStep[dim]),sizeof(fStep[dim]));
864 }
865 SetMinimumMaximumStep(fMin, fMax, fStep); // calculates fMaximumEntries
866 // Read values
867 uint32_t maximum_entries;
868 file.read(reinterpret_cast<char*>(&maximum_entries),sizeof(maximum_entries));
869 if (maximum_entries != fMaximumEntries) return false; // not expected number of entries
870 int value_size = sizeof(value_t);
871 unsigned int entries = fValues[0].size();
872 for (unsigned int index = 0; index < entries; index++) {
873 // Read values
874 for (unsigned int i = 0; i < value_n; i++) {
875 file.read((char*)(&fValues[i][index]),value_size);
876 }
877 // Progress bar
878 if (index % (entries / 10) == 0)
879 mycout << index / (entries / 100) << "%" << QwLog::flush;
880 if (index % (entries / 10) != 0
881 && index % (entries / 40) == 0)
882 mycout << "." << QwLog::flush;
883 }
884 mycout << myendl;
885 file.close();
886 return true;
887}
A logfile class, based on an identical class in the Hermes analyzer.
#define mycerr
double coord_t
#define myendl
EQwInterpolationMethod
Allowed interpolation methods.
@ kNearestNeighbor
@ kMultiLinear
@ kInterpolationMethodUnknown
#define mycout
void SetMinimumMaximumStep(const std::vector< coord_t > &min, const std::vector< coord_t > &max, const std::vector< coord_t > &step)
Set minimum, maximum, and step size to different values.
virtual ~QwInterpolator()
Destructor.
std::vector< size_t > fWrap
Wrap around this coordinate.
int GetDataReductionFactor(const unsigned int dim) const
Get data reduction factor.
bool Set(const unsigned int *cell_index, const value_t *value)
Set a set of values at a grid point (false if out of bounds)
unsigned int * f_cell_index
Pre-allocated cell index.
bool Set(const unsigned int linear_index, const value_t &value)
Set a single value at a linearized index (false if not possible)
void SetDimensions(const unsigned int ndim)
Set the number of coordinate dimensions and resize vectors.
coord_t GetMinimum(const unsigned int dim) const
Get minimum in dimension.
std::vector< size_t > fExtent
void SetDataReductionFactor(const unsigned int dim, const unsigned int redux)
Set data reduction factor.
void SetDataReductionFactor(const unsigned int redux)
bool WriteTextScreen() const
Write the grid to screen.
std::vector< value_t > fValues[value_n]
Table with pointers to arrays of values.
bool GetValue(const coord_t *coord, double *value) const
Get the interpolated value at coordinate (zero if out of bounds)
void PrintCoverage(const unsigned int dim)
Print coverage map for all bins in one dimension.
bool Set(const unsigned int *cell_index, const value_t &value)
Set a single value at a grid point (false if out of bounds)
bool ReadBinaryFile(const std::string &filename)
Read the grid values from binary file.
unsigned int GetWrapCoordinate(const unsigned int dim) const
Get wrapping coordinate.
QwInterpolator(const std::string &filename)
Constructor with file name.
bool Set(const coord_t *coord, const value_t &value)
Set a single value at a coordinate (false if not possible)
coord_t GetStepSize(const unsigned int dim) const
Get minimum in dimension.
void Coord(const unsigned int *cell_index, coord_t *coord) const
Return the coordinates based on the cell index (unchecked)
bool Get(const unsigned int index, value_t *value) const
Get a vector value by linearized index (unchecked)
void SetWrapCoordinate(const unsigned int dim, const size_t wrap=1)
Set wrapping coordinate.
EQwInterpolationMethod fInterpolationMethod
Interpolation method.
unsigned int GetCurrentEntries() const
Get the current number of entries.
unsigned int GetMaximumEntries() const
Get the maximum number of entries.
std::vector< coord_t > fMin
Minimum in each dimension.
unsigned int fNDim
Number of dimensions in coordinates.
QwInterpolator(const unsigned int ndim=1)
Constructor with number of dimensions.
bool Set(const coord_t &coord, const value_t &value)
Set a single value at a coordinate (false if not possible)
bool WriteBinaryFile(const std::string &filename) const
Write the grid values to binary file.
unsigned int fMaximumEntries
Maximum number of values.
unsigned int fCurrentEntries
Number of values read in.
std::vector< coord_t > fStep
Step size in each dimension.
bool Check(const coord_t *coord) const
Check for boundaries with coordinate argument.
std::vector< size_t > fSize
Number of points in each dimension.
void SetMinimumMaximumStep(const coord_t min, const coord_t max, const coord_t step)
Set minimum, maximum, and step size to single values.
value_t Get(const unsigned int *cell_index) const
Get a single value by cell index (unchecked)
void SetInterpolationMethod(const EQwInterpolationMethod method)
Set the interpolation method.
value_t Get(const unsigned int index) const
Get a single value by linearized index (unchecked)
coord_t GetMaximum(const unsigned int dim) const
Get maximum in dimension.
EQwInterpolationMethod GetInterpolationMethod() const
Get the interpolation method.
unsigned int Index(const coord_t *coord) const
Return the linearized index based on the point coordinates (unchecked)
bool InBounds(const coord_t *coord) const
Return true if the coordinate is in bounds.
bool WriteTextFile(const std::string &filename) const
Write the grid to text file.
bool ReadText(std::istream &stream)
Read the grid from text.
void Cell(const coord_t coord, unsigned int &cell_index, double &cell_local, const unsigned int dim) const
Return the cell index and local coordinates in one dimension (unchecked)
void Nearest(const coord_t *coord, unsigned int *cell_index) const
Return the cell index closest to the coordinate (could be above) (unchecked)
std::vector< size_t > fRedux
Data reduction factor.
bool Set(const coord_t *coord, const value_t *value)
Set a set of values at a coordinate (false if not possible)
bool Set(const unsigned int linear_index, const value_t *value)
Set a set of values at a linearized index (false if not possible)
bool WriteText(std::ostream &stream) const
Write the grid as text.
bool ReadTextFile(const std::string &filename)
Read the grid from text file.
void SetWrapCoordinate(const std::vector< size_t > &wrap)
void SetDataReductionFactor(const std::vector< unsigned int > &redux)
value_t GetValue(const coord_t &coord) const
Get the interpolated value at coordinate (zero if out of bounds)
bool Linear(const coord_t *coord, value_t *value) const
Linear interpolation (unchecked)
bool NearestNeighbor(const coord_t *coord, value_t *value) const
Nearest-neighbor (unchecked)
std::vector< coord_t > fMax
Maximum in each dimension.
bool GetValue(const coord_t *coord, double &value) const
Get the interpolated value at coordinate (zero if out of bounds)
value_t GetValue(const coord_t *coord) const
Get the interpolated value at coordinate (zero if out of bounds)
QwInterpolator(const std::vector< coord_t > &min, const std::vector< coord_t > &max, const std::vector< coord_t > &step)
Constructor with minimum, maximum, and step size.
double * f_cell_local
Pre-allocated local coordinates.
static std::ostream & flush(std::ostream &)
Flush the streams.
Definition QwLog.cc:317