CMS 3D CMS Logo

LinInterpolatedTable1D.h
Go to the documentation of this file.
1 //=========================================================================
2 // LinInterpolatedTable1D.h
3 //
4 // This class can be used to linearly interpolate data in one dimension.
5 // It differs from similar facilities in the fftjet package by its handling
6 // of the extrapolation beyound the grid limits.
7 //
8 // I. Volobouev
9 // April 2011
10 //=========================================================================
11 
12 #ifndef RecoJets_FFTJetAlgorithms_LinInterpolatedTable1D_h
13 #define RecoJets_FFTJetAlgorithms_LinInterpolatedTable1D_h
14 
15 #include <utility>
16 #include <vector>
17 #include <memory>
18 #include <algorithm>
19 
20 #include "fftjet/SimpleFunctors.hh"
22 
23 namespace fftjetcms {
24  class LinInterpolatedTable1D : public fftjet::Functor1<double,double>
25  {
26  public:
27  // Constructor from a regularly spaced data. Extrapolation
28  // from the edge to infinity can be either linear or constant.
29  // "npoints" must be larger than 1.
30  template <typename RealN>
31  LinInterpolatedTable1D(const RealN* data, unsigned npoints,
32  double x_min, double x_max,
35 
36  // Constructor from a list of points, not necessarily regularly
37  // spaced (but must be sorted in the increasing order). The first
38  // member of the pair is the x coordinate, the second is the
39  // tabulated function value. The input list will be interpolated
40  // to "npoints" internal points linearly.
41  template <typename RealN>
42  LinInterpolatedTable1D(const std::vector<std::pair<RealN,RealN> >& v,
43  unsigned npoints,
44  bool leftExtrapolationLinear,
45  bool rightExtrapolationLinear);
46 
47  // Constructor which builds a function returning the given constant
48  explicit LinInterpolatedTable1D(double c);
49 
50  inline ~LinInterpolatedTable1D() override {}
51 
52  // Main calculations are performed inside the following operator
53  double operator()(const double& x) const override;
54 
55  // Comparisons (useful for testing)
56  bool operator==(const LinInterpolatedTable1D& r) const;
57  inline bool operator!=(const LinInterpolatedTable1D& r) const
58  {return !(*this == r);}
59 
60  // Various simple inspectors
61  inline double xmin() const {return xmin_;}
62  inline double xmax() const {return xmax_;}
63  inline unsigned npoints() const {return npoints_;}
64  inline bool leftExtrapolationLinear() const
65  {return leftExtrapolationLinear_;}
66  inline bool rightExtrapolationLinear() const
68  inline const double* data() const {return &data_[0];}
69 
70  // The following checks whether the table is monotonous
71  // (and, therefore, can be inverted). Possible flat regions
72  // at the edges are not taken into account.
73  bool isMonotonous() const;
74 
75  // Generate the inverse lookup table. Note that it is only
76  // possible if the original table is monotonous (not taking
77  // into account possible flat regions at the edges). If the
78  // inversion is not possible, NULL pointer will be returned.
79  //
80  // The new table will have "npoints" points. The parameters
81  // "leftExtrapolationLinear" and "rightExtrapolationLinear"
82  // refer to the inverted table (note that left and right will
83  // exchange places if the original table is decreasing).
84  //
85  std::unique_ptr<LinInterpolatedTable1D> inverse(
86  unsigned npoints, bool leftExtrapolationLinear,
87  bool rightExtrapolationLinear) const;
88 
89  private:
90  static inline double interpolateSimple(
91  const double x0, const double x1,
92  const double y0, const double y1,
93  const double x)
94  {
95  return y0 + (y1 - y0)*((x - x0)/(x1 - x0));
96  }
97 
98  std::vector<double> data_;
99  double xmin_;
100  double xmax_;
101  double binwidth_;
102  unsigned npoints_;
105  mutable bool monotonous_;
106  mutable bool monotonicityKnown_;
107  };
108 }
109 
110 
111 // Implementation of the templated constructors
112 namespace fftjetcms {
113  template <typename RealN>
115  const RealN* data, const unsigned npoints,
116  const double x_min, const double x_max,
117  const bool leftExtrapolationLinear,
118  const bool rightExtrapolationLinear)
119  : data_(data, data+npoints),
120  xmin_(x_min),
121  xmax_(x_max),
122  binwidth_((x_max - x_min)/(npoints - 1U)),
123  npoints_(npoints),
124  leftExtrapolationLinear_(leftExtrapolationLinear),
125  rightExtrapolationLinear_(rightExtrapolationLinear),
128  {
129  if (!data)
130  throw cms::Exception("FFTJetBadConfig")
131  << "No data configured" << std::endl;
132  if (npoints <= 1U)
133  throw cms::Exception("FFTJetBadConfig")
134  << "Not enough data points" << std::endl;
135  }
136 
137  template <typename RealN>
139  const std::vector<std::pair<RealN,RealN> >& v,
140  const unsigned npoints,
141  const bool leftExtrapolationLinear,
142  const bool rightExtrapolationLinear)
143  : xmin_(v[0].first),
144  xmax_(v[v.size() - 1U].first),
145  binwidth_((xmax_ - xmin_)/(npoints - 1U)),
146  npoints_(npoints),
147  leftExtrapolationLinear_(leftExtrapolationLinear),
148  rightExtrapolationLinear_(rightExtrapolationLinear),
151  {
152  const unsigned len = v.size();
153  if (len <= 1U)
154  throw cms::Exception("FFTJetBadConfig")
155  << "Not enough data for interpolation"
156  << std::endl;
157 
158  if (npoints <= 1U)
159  throw cms::Exception("FFTJetBadConfig")
160  << "Not enough interpolation table entries"
161  << std::endl;
162 
163  const std::pair<RealN,RealN>* vdata = &v[0];
164  for (unsigned i=1; i<len; ++i)
165  if (vdata[i-1U].first >= vdata[i].first)
166  throw cms::Exception("FFTJetBadConfig")
167  << "Input data is not sorted properly"
168  << std::endl;
169 
170  unsigned shift = 0U;
171  if (leftExtrapolationLinear)
172  {
173  ++npoints_;
174  xmin_ -= binwidth_;
175  shift = 1U;
176  }
177  if (rightExtrapolationLinear)
178  {
179  ++npoints_;
180  xmax_ += binwidth_;
181  }
182 
183  data_.resize(npoints_);
184 
185  if (leftExtrapolationLinear)
186  {
188  vdata[0].first, vdata[1].first,
189  vdata[0].second, vdata[1].second, xmin_);
190  }
191  if (rightExtrapolationLinear)
192  {
194  vdata[len - 2U].first, vdata[len - 1U].first,
195  vdata[len - 2U].second, vdata[len - 1U].second, xmax_);
196  }
197 
198  data_[shift] = vdata[0].second;
199  data_[npoints - 1U + shift] = vdata[len - 1U].second;
200  unsigned ibelow = 0, iabove = 1;
201  for (unsigned i=1; i<npoints-1; ++i)
202  {
203  const double x = xmin_ + (i + shift)*binwidth_;
204  while (static_cast<double>(v[iabove].first) <= x)
205  {
206  ++ibelow;
207  ++iabove;
208  }
209  if (v[ibelow].first == v[iabove].first)
210  data_[i + shift] = (v[ibelow].second + v[iabove].second)/2.0;
211  else
213  v[ibelow].first, v[iabove].first,
214  v[ibelow].second, v[iabove].second, x);
215  }
216  }
217 }
218 
219 #endif // RecoJets_FFTJetAlgorithms_LinInterpolatedTable1D_h
size
Write out results.
bool operator==(const LinInterpolatedTable1D &r) const
U second(std::pair< T, U > const &p)
static double interpolateSimple(const double x0, const double x1, const double y0, const double y1, const double x)
double operator()(const double &x) const override
std::unique_ptr< LinInterpolatedTable1D > inverse(unsigned npoints, bool leftExtrapolationLinear, bool rightExtrapolationLinear) const
bool operator!=(const LinInterpolatedTable1D &r) const
static unsigned int const shift
LinInterpolatedTable1D(const RealN *data, unsigned npoints, double x_min, double x_max, bool leftExtrapolationLinear, bool rightExtrapolationLinear)