STIR 6.4.0
linear_regression.inl
Go to the documentation of this file.
1//
2//
15/*
16 Copyright (C) 2000- 2011, Hammersmith Imanet Ltd
17 This file is part of STIR.
18
19 SPDX-License-Identifier: Apache-2.0 AND License-ref-PARAPET-license
20
21 See STIR/LICENSE.txt for details
22*/
23#include <cstddef> // for size_t
24START_NAMESPACE_STIR
25
26namespace detail
27{
28/*
29 We compute the linear regression using
30 Numerical Recipes formulas for numerical stability
31
32 Correspondence with their notation:
33 y_i = measured_data[i]
34 x_i = coordinates[i]
35 sigma_i = 1/sqrt(weights[i])
36
37 t_i = sqrt(weights[i]) (x[i] - Sx/S)
38
39 This last one is computed here in terms of
40 wti = (x[i] - Sx/S)
41
42 Further notation:
43 S = sum of the weights
44 Sx = weights . coordinates
45 Sy = weights . measured
46 Sty = weights . (wt*measured)
47 etc.
48 (Syy is used to compute chi_square in the current implementation)
49
50 The fit is split up into 2 functions:
51 - linear_regression_compute_S
52 - linear_regression_compute_fit_from_S
53
54 The main reason for this is that *compute_S needs to be
55 templated in 3 different argument types for maximum
56 flexibility. This in practice means it needs to be
57 an inline function (to avoid problems at linking time).
58 In contrast, linear_regression_compute_fit_from_S
59 is only templated in the Value type, which will be
60 float or double anyway.
61*/
62
63// defined in .cxx
64template <class Value>
65void linear_regression_compute_fit_from_S(Value& constant,
66 Value& scale,
67 Value& chi_square,
68 Value& variance_of_constant,
69 Value& variance_of_scale,
70 Value& covariance_of_constant_with_scale,
71 const double S,
72 const double Sx,
73 const double Sy,
74 const double Syy,
75 const double Stt,
76 const double Sty,
77 const std::size_t data_size,
78 const bool use_estimated_variance);
79
80template <class DataIter, class CoordinatesIter, class WeightsIter>
81inline void
82linear_regression_compute_S(double& S,
83 double& Sx,
84 double& Sy,
85 double& Syy,
86 double& Stt,
87 double& Sty,
88 const DataIter data_begin,
89 const DataIter data_end,
90 const CoordinatesIter coords_begin,
91 const WeightsIter weights_begin)
92{
93 DataIter data_iter = data_begin;
94 CoordinatesIter coords_iter = coords_begin;
95 WeightsIter weights_iter = weights_begin;
96
97 for (; data_iter != data_end; ++data_iter, ++coords_iter, ++weights_iter)
98 {
99 const double weight = static_cast<double>(*weights_iter);
100 S += weight;
101 Sx += weight * (*coords_iter);
102 Sy += weight * (*data_iter);
103 Syy += weight * square(static_cast<double>(*data_iter));
104 }
105
106 data_iter = data_begin;
107 coords_iter = coords_begin;
108 weights_iter = weights_begin;
109
110 for (; data_iter != data_end; ++data_iter, ++coords_iter, ++weights_iter)
111 {
112 const double wti = (*coords_iter - Sx / S);
113 Stt += *weights_iter * wti * wti;
114 Sty += *weights_iter * wti * *data_iter;
115 }
116}
117
118} // end namespace detail
119
120template <class Value, class DataIter, class CoordinatesIter, class WeightsIter>
121inline void
122linear_regression(Value& constant,
123 Value& scale,
124 Value& chi_square,
125 Value& variance_of_constant,
126 Value& variance_of_scale,
127 Value& covariance_of_constant_with_scale,
128 DataIter data_begin,
129 DataIter data_end,
130 CoordinatesIter coords_begin,
131 WeightsIter weights_begin,
132 const bool use_estimated_variance)
133{
134 double Sy = 0;
135 double Sx = 0;
136 double S = 0;
137 double Syy = 0;
138 double Stt = 0;
139 double Sty = 0;
140
141 detail::linear_regression_compute_S(S, Sx, Sy, Syy, Stt, Sty, data_begin, data_end, coords_begin, weights_begin);
142
143 detail::linear_regression_compute_fit_from_S(constant,
144 scale,
145 chi_square,
146 variance_of_constant,
147 variance_of_scale,
148 covariance_of_constant_with_scale,
149 S,
150 Sx,
151 Sy,
152 Syy,
153 Stt,
154 Sty,
155 static_cast<std::size_t>(data_end - data_begin),
156 use_estimated_variance);
157}
158
159template <class Value, class DataType, class CoordinatesType>
160inline void
161linear_regression(Value& constant,
162 Value& scale,
163 Value& chi_square,
164 Value& variance_of_constant,
165 Value& variance_of_scale,
166 Value& covariance_of_constant_with_scale,
167 const VectorWithOffset<DataType>& measured_data,
168 const VectorWithOffset<CoordinatesType>& coordinates,
169 const VectorWithOffset<float>& weights,
170 const bool use_estimated_variance)
171{
172 assert(measured_data.get_min_index() == coordinates.get_min_index());
173 assert(measured_data.get_min_index() == weights.get_min_index());
174 assert(measured_data.get_max_index() == coordinates.get_max_index());
175 assert(measured_data.get_max_index() == weights.get_max_index());
176
177 linear_regression(constant,
178 scale,
179 chi_square,
180 variance_of_constant,
181 variance_of_scale,
182 covariance_of_constant_with_scale,
183 measured_data.begin(),
184 measured_data.end(),
185 coordinates.begin(),
186 weights.begin(),
187 use_estimated_variance);
188}
189
190template <class ValueIter, class DataIter, class CoordinatesIter, class WeightsIter>
191inline void
192linear_regression(ValueIter value_begin,
193 DataIter data_begin,
194 DataIter data_end,
195 CoordinatesIter coords_begin,
196 WeightsIter weights_begin,
197 const bool use_estimated_variance)
198{
199 double Sy = 0;
200 double Sx = 0;
201 double S = 0;
202 double Syy = 0;
203 double Stt = 0;
204 double Sty = 0;
205
206 detail::linear_regression_compute_S(S, Sx, Sy, Syy, Stt, Sty, data_begin, data_end, coords_begin, weights_begin);
207
208 ValueIter value_iter = value_begin;
209
210 detail::linear_regression_compute_fit_from_S(*value_iter,
211 *(value_iter + 1),
212 *(value_iter + 2),
213 *(value_iter + 3),
214 *(value_iter + 4),
215 *(value_iter + 5),
216 S,
217 Sx,
218 Sy,
219 Syy,
220 Stt,
221 Sty,
222 data_end - data_begin,
223 use_estimated_variance);
224 *(value_iter + 6) = *(value_iter)*Sx / Sy;
225}
226
227END_NAMESPACE_STIR
A templated class for vectors, but with indices starting not from 0.
Definition VectorWithOffset.h:65
iterator begin()
use to initialise an iterator to the first element of the vector
Definition VectorWithOffset.inl:190
int get_max_index() const
get value of last valid index
Definition VectorWithOffset.inl:131
int get_min_index() const
get value of first valid index
Definition VectorWithOffset.inl:124
iterator end()
iterator 'past' the last element of the vector
Definition VectorWithOffset.inl:206
void linear_regression(Value &constant, Value &scale, Value &chi_square, Value &variance_of_constant, Value &variance_of_scale, Value &covariance_of_constant_with_scale, const VectorWithOffset< DataType > &measured_data, const VectorWithOffset< CoordinatesType > &coordinates, const VectorWithOffset< float > &weights, const bool use_estimated_variance=true)
Implements standard linear regression on VectorWithOffset data.
Definition linear_regression.inl:161
NUMBER square(const NUMBER &x)
returns the square of a number, templated.
Definition common.h:154