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