26 #ifndef LEAST_SQ_FITTER_2D
27 #define LEAST_SQ_FITTER_2D
40 namespace except = lsst::pex::exceptions;
71 LeastSqFitter2d(
const std::vector<double> &
x,
const std::vector<double> &
y,
const std::vector<double> &z,
72 const std::vector<double> &s,
int order);
76 double valueAt(
double x,
double y);
87 double func2d(
double x,
double y,
int term);
88 double func1d(
double value,
int exponent);
95 Eigen::JacobiSVD<Eigen::MatrixXd>
_svd;
107 namespace sip = lsst::meas::astrom::sip;
108 namespace math = lsst::afw::math;
120 const std::vector<double> &
y,
const std::vector<double> &z,
const std::vector<double> &s,
int order) :
121 _x(x), _y(y), _z(z), _s(s), _order(order), _nPar(0), _par(1) {
125 for (
int i = 0; i < order; ++i) {
131 if (
_nData != static_cast<int>(
_y.size())) {
132 throw LSST_EXCEPT(except::RuntimeError,
"x and y vectors of different lengths");
134 if (
_nData != static_cast<int>(
_s.size())) {
135 throw LSST_EXCEPT(except::RuntimeError,
"x and s vectors of different lengths");
137 if (
_nData != static_cast<int>(
_z.size())) {
138 throw LSST_EXCEPT(except::RuntimeError,
"x and z vectors of different lengths");
141 for (
int i = 0; i <
_nData; ++i) {
142 if (
_s[i] == 0.0 ) {
143 std::string msg =
"Illegal zero value for fit weight encountered.";
149 throw LSST_EXCEPT(except::RuntimeError,
"Fewer data points than parameters");
154 Eigen::MatrixXd design(_nData,
_nPar);
155 Eigen::VectorXd rhs(_nData);
156 for (
int i = 0; i <
_nData; ++i) {
157 rhs[i] = z[i] / s[i];
158 for (
int j = 0; j <
_nPar; ++j) {
162 _svd.compute(design, Eigen::ComputeThinU | Eigen::ComputeThinV);
177 return expandParams(_par);
181 template<
class FittingFunc>
183 Eigen::MatrixXd out = Eigen::MatrixXd::Zero(_order, _order);
185 for (
int i = 0; i < _order; ++i) {
186 for (
int j = 0; j < _order - i; ++j) {
187 out(i, j) = input[count++];
198 for (
int i = 0; i < _nData; ++i) {
199 double val = _z[i] - valueAt(_x[i], _y[i]);
201 chisq += pow(val, 2);
214 return getChiSq()/(double) (_nData - _nPar);
224 for (
int i = 0; i < _nPar; ++i) {
225 val += _par[i] * func2d(x, y, i);
234 std::vector<double> out;
237 for (
int i = 0; i < _nData; ++i) {
238 out.push_back(_z[i] - valueAt(_x[i], _y[i]));
246 template<
class FittingFunc>
248 Eigen::ArrayXd variance(_nPar);
249 for (
int i = 0; i < _nPar; ++i) {
250 variance[i] =
_svd.matrixV().row(i).dot(
251 (
_svd.singularValues().array().inverse().square() *
_svd.matrixV().col(i).array()).matrix()
254 return expandParams(variance.sqrt().matrix());
260 _funcArray.reserve(_order);
262 std::vector<double> coeff;
263 coeff.reserve( _order);
266 for (
int i = 0; i < _order; ++i) {
267 std::shared_ptr<FittingFunc> p(
new FittingFunc(coeff));
268 _funcArray.push_back(p);
283 for (
int i = 0; i<term; ++i) {
284 yexp = (yexp + 1) % (_order - xexp);
290 double xcomp = func1d(x, xexp);
291 double ycomp = func1d(y, yexp);
293 #if 0 //A useful debugging printf statement
294 printf(
"The %i(th) function: x^%i * y^%i = %.1f * %.1f\n", term, xexp, yexp, xcomp, ycomp);
301 return (*_funcArray[exponent])(value);
double func1d(double value, int exponent)
Fit an lsst::afw::math::Function1 object to a set of data points in two dimensions.
double func2d(double x, double y, int term)
Define a collection of useful Functions.
Eigen::JacobiSVD< Eigen::MatrixXd > _svd
Eigen::MatrixXd getParams()
Build up a triangular matrix of the parameters.
LeastSqFitter2d(const std::vector< double > &x, const std::vector< double > &y, const std::vector< double > &z, const std::vector< double > &s, int order)
Fit a 2d polynomial to a set of data points z(x, y)
double valueAt(double x, double y)
Return the value of the best fit function at a given position (x,y)
double getChiSq()
Return a measure of the goodness of fit.
#define LSST_EXCEPT(type,...)
Create an exception with a given type and message and optionally other arguments (dependent on the ty...
double getReducedChiSq()
Return a measure of the goodness of fit.
std::vector< double > residuals()
Return a vector of residuals of the fit (i.e the difference between the input z values, and the value of the fitting function at that point.
std::vector< std::shared_ptr< FittingFunc > > _funcArray
Eigen::JacobiSVD< Eigen::MatrixXd > _svd
Eigen::MatrixXd expandParams(Eigen::VectorXd const &input) const
Turn a flattened parameter-like vector into a triangular matrix.
Eigen::MatrixXd getErrors()
Companion function to getParams(). Returns uncertainties in the parameters as a matrix.