ATTPCROOT  0.3.0-alpha
A ROOT-based framework for analyzing data from active target detectors
AtSpline.h
Go to the documentation of this file.
1 /*
2  * spline.h
3  *
4  * simple cubic spline interpolation library without external
5  * dependencies (https://github.com/ttk592/spline and https://kluge.in-chemnitz.de/opensource/spline/)
6  *
7  * Modified April 2023 to allow integration (AK Anthony)
8  *
9  * ---------------------------------------------------------------------
10  * Copyright (C) 2011, 2014, 2016, 2021 Tino Kluge (ttk448 at gmail.com)
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program. If not, see <http://www.gnu.org/licenses/>.
24  * ---------------------------------------------------------------------
25  *
26  */
27 
28 #ifndef TK_SPLINE_H
29 #define TK_SPLINE_H
30 
31 #include <algorithm>
32 #include <cassert>
33 #include <cstdio>
34 #include <vector>
35 #ifdef HAVE_SSTREAM
36 #include <sstream>
37 #include <string>
38 #endif // HAVE_SSTREAM
39 
40 namespace tk {
41 
42 // spline interpolation
43 class spline {
44 public:
45  // spline types
46  enum spline_type {
47  linear = 10, // linear interpolation
48  cspline = 30, // cubic splines (classical C^2)
49  cspline_hermite = 31 // cubic hermite splines (local, only C^1)
50  };
51 
52  // boundary condition type for the spline end-points
53  enum bd_type { first_deriv = 1, second_deriv = 2, not_a_knot = 3 };
54 
55 protected:
56  std::vector<double> m_x, m_y; // x,y coordinates of points
57  // interpolation parameters
58  // f(x) = a_i + b_i*(x-x_i) + c_i*(x-x_i)^2 + d_i*(x-x_i)^3
59  // where a_i = y_i, or else it won't go through grid points
60  std::vector<double> m_b, m_c, m_d; // spline coefficients
61  double m_c0; // for left extrapolation
66 
67  std::vector<double> m_integral; // Integral of spline from m_x[0] to m_x[i]
68 
69  void set_coeffs_from_b(); // calculate c_i, d_i from b_i
70  size_t find_closest(double x) const; // closest idx so that m_x[idx]<=x
71  void set_points_linear();
72  void set_points_cspline();
74  void set_integral();
75 
76 public:
77  // default constructor: set boundary condition to be zero curvature
78  // at both ends, i.e. natural splines
81  m_made_monotonic(false)
82  {
83  ;
84  }
85  spline(const std::vector<double> &X, const std::vector<double> &Y, spline_type type = cspline,
86  bool make_monotonic = false, bd_type left = second_deriv, double left_value = 0.0,
87  bd_type right = second_deriv, double right_value = 0.0)
88  : m_type(type), m_left(left), m_right(right), m_left_value(left_value), m_right_value(right_value),
89  m_made_monotonic(false) // false correct here: make_monotonic() sets it
90  {
91  this->set_points(X, Y, m_type);
92  if (make_monotonic) {
93  this->make_monotonic();
94  }
95  }
96 
97  // modify boundary conditions: if called it must be before set_points()
98  void set_boundary(bd_type left, double left_value, bd_type right, double right_value);
99 
100  // set all data points (cubic_spline=false means linear interpolation)
101  void set_points(const std::vector<double> &x, const std::vector<double> &y, spline_type type = cspline);
102 
103  // adjust coefficients so that the spline becomes piecewise monotonic
104  // where possible
105  // this is done by adjusting slopes at grid points by a non-negative
106  // factor and this will break C^2
107  // this can also break boundary conditions if adjustments need to
108  // be made at the boundary points
109  // returns false if no adjustments have been made, true otherwise
110  bool make_monotonic();
111 
112  // evaluates the spline at point x
113  double operator()(double x) const;
114  double deriv(int order, double x) const;
115  double integrate(double x0, double x1) const;
116 
117  // solves for all x so that: spline(x) = y
118  std::vector<double> solve(double y, bool ignore_extrapolation = true) const;
119 
120  // returns the input data points
121  std::vector<double> get_x() const { return m_x; }
122  std::vector<double> get_y() const { return m_y; }
123  double get_x_min() const
124  {
125  assert(!m_x.empty());
126  return m_x.front();
127  }
128  double get_x_max() const
129  {
130  assert(!m_x.empty());
131  return m_x.back();
132  }
133 
134 #ifdef HAVE_SSTREAM
135  // spline info string, i.e. spline type, boundary conditions etc.
136  std::string info() const;
137 #endif // HAVE_SSTREAM
138 };
139 
140 namespace internal {
141 
142 // band matrix solver
143 class band_matrix {
144 private:
145  std::vector<std::vector<double>> m_upper; // upper band
146  std::vector<std::vector<double>> m_lower; // lower band
147 public:
148  band_matrix(){}; // constructor
149  band_matrix(int dim, int n_u, int n_l); // constructor
150  ~band_matrix(){}; // destructor
151  void resize(int dim, int n_u, int n_l); // init with dim,n_u,n_l
152  int dim() const; // matrix dimension
153  int num_upper() const { return (int)m_upper.size() - 1; }
154  int num_lower() const { return (int)m_lower.size() - 1; }
155  // access operator
156  double &operator()(int i, int j); // write
157  double operator()(int i, int j) const; // read
158  // we can store an additional diagonal (in m_lower)
159  double &saved_diag(int i);
160  double saved_diag(int i) const;
161  void lu_decompose();
162  std::vector<double> r_solve(const std::vector<double> &b) const;
163  std::vector<double> l_solve(const std::vector<double> &b) const;
164  std::vector<double> lu_solve(const std::vector<double> &b, bool is_lu_decomposed = false);
165 };
166 
167 double get_eps();
168 
169 std::vector<double> solve_cubic(double a, double b, double c, double d, int newton_iter = 0);
170 
171 } // namespace internal
172 
173 } // namespace tk
174 
175 #endif /* TK_SPLINE_H */
tk::spline::m_left
bd_type m_left
Definition: AtSpline.h:63
tk::spline::cspline
@ cspline
Definition: AtSpline.h:48
tk::spline::set_points_linear
void set_points_linear()
Definition: AtSpline.cxx:48
tk::spline::set_integral
void set_integral()
Definition: AtSpline.cxx:206
tk::internal::band_matrix::resize
void resize(int dim, int n_u, int n_l)
Definition: AtSpline.cxx:465
tk::spline::linear
@ linear
Definition: AtSpline.h:47
tk::spline::make_monotonic
bool make_monotonic()
Definition: AtSpline.cxx:251
tk::spline::first_deriv
@ first_deriv
Definition: AtSpline.h:53
tk::spline::cspline_hermite
@ cspline_hermite
Definition: AtSpline.h:49
tk::spline::m_x
std::vector< double > m_x
Definition: AtSpline.h:56
tk::internal::band_matrix::~band_matrix
~band_matrix()
Definition: AtSpline.h:150
tk::internal::band_matrix::lu_decompose
void lu_decompose()
Definition: AtSpline.cxx:525
tk::spline::get_x
std::vector< double > get_x() const
Definition: AtSpline.h:121
tk::spline::m_type
spline_type m_type
Definition: AtSpline.h:62
tk::internal::band_matrix::operator()
double & operator()(int i, int j)
Definition: AtSpline.cxx:490
tk::spline::set_boundary
void set_boundary(bd_type left, double left_value, bd_type right, double right_value)
Definition: AtSpline.cxx:16
tk::spline::m_y
std::vector< double > m_y
Definition: AtSpline.h:56
tk::spline::m_c
std::vector< double > m_c
Definition: AtSpline.h:60
tk::spline::spline_type
spline_type
Definition: AtSpline.h:46
tk::spline::m_left_value
double m_left_value
Definition: AtSpline.h:64
tk::spline::set_points_cspline
void set_points_cspline()
Definition: AtSpline.cxx:66
tk::internal::solve_cubic
std::vector< double > solve_cubic(double a, double b, double c, double d, int newton_iter)
Definition: AtSpline.cxx:681
tk::spline::m_d
std::vector< double > m_d
Definition: AtSpline.h:60
tk::spline::set_points_cspline_hermite
void set_points_cspline_hermite()
Definition: AtSpline.cxx:152
tk
Definition: AtSpline.cxx:7
tk::spline::solve
std::vector< double > solve(double y, bool ignore_extrapolation=true) const
Definition: AtSpline.cxx:395
tk::spline::integrate
double integrate(double x0, double x1) const
Definition: AtSpline.cxx:370
tk::internal::band_matrix::band_matrix
band_matrix()
Definition: AtSpline.h:148
tk::spline::set_points
void set_points(const std::vector< double > &x, const std::vector< double > &y, spline_type type=cspline)
Definition: AtSpline.cxx:220
tk::spline::m_c0
double m_c0
Definition: AtSpline.h:61
tk::spline::deriv
double deriv(int order, double x) const
Definition: AtSpline.cxx:336
tk::internal::band_matrix::num_lower
int num_lower() const
Definition: AtSpline.h:154
tk::internal::band_matrix::l_solve
std::vector< double > l_solve(const std::vector< double > &b) const
Definition: AtSpline.cxx:560
tk::internal::get_eps
double get_eps()
Definition: AtSpline.cxx:605
tk::spline::second_deriv
@ second_deriv
Definition: AtSpline.h:53
tk::spline::m_b
std::vector< double > m_b
Definition: AtSpline.h:60
tk::spline::get_x_min
double get_x_min() const
Definition: AtSpline.h:123
tk::internal::band_matrix::r_solve
std::vector< double > r_solve(const std::vector< double > &b) const
Definition: AtSpline.cxx:576
tk::spline
Definition: AtSpline.h:43
y
const double * y
Definition: lmcurve.cxx:20
tk::spline::m_right
bd_type m_right
Definition: AtSpline.h:63
tk::internal::band_matrix::num_upper
int num_upper() const
Definition: AtSpline.h:153
tk::internal::band_matrix::dim
int dim() const
Definition: AtSpline.cxx:479
tk::spline::not_a_knot
@ not_a_knot
Definition: AtSpline.h:53
tk::spline::spline
spline()
Definition: AtSpline.h:79
tk::spline::spline
spline(const std::vector< double > &X, const std::vector< double > &Y, spline_type type=cspline, bool make_monotonic=false, bd_type left=second_deriv, double left_value=0.0, bd_type right=second_deriv, double right_value=0.0)
Definition: AtSpline.h:85
tk::spline::m_integral
std::vector< double > m_integral
Definition: AtSpline.h:67
tk::spline::operator()
double operator()(double x) const
Definition: AtSpline.cxx:311
tk::spline::find_closest
size_t find_closest(double x) const
Definition: AtSpline.cxx:303
tk::spline::get_x_max
double get_x_max() const
Definition: AtSpline.h:128
tk::spline::set_coeffs_from_b
void set_coeffs_from_b()
Definition: AtSpline.cxx:25
tk::internal::band_matrix::saved_diag
double & saved_diag(int i)
Definition: AtSpline.cxx:518
tk::spline::m_right_value
double m_right_value
Definition: AtSpline.h:64
tk::spline::get_y
std::vector< double > get_y() const
Definition: AtSpline.h:122
tk::internal::band_matrix::lu_solve
std::vector< double > lu_solve(const std::vector< double > &b, bool is_lu_decomposed=false)
Definition: AtSpline.cxx:592
tk::spline::m_made_monotonic
bool m_made_monotonic
Definition: AtSpline.h:65
c
constexpr auto c
Definition: AtRadialChargeModel.cxx:20
tk::internal::band_matrix
Definition: AtSpline.h:143
tk::spline::bd_type
bd_type
Definition: AtSpline.h:53