X-shooter Pipeline Reference Manual 3.8.15
xsh_fit_body.h
Go to the documentation of this file.
1/* $Id: xsh_fit_body.h,v 1.3 2007-10-03 14:06:16 rhaigron Exp $
2 *
3 * This file is part of the ESO irplib package
4 * Copyright (C) 2001-2007 European Southern Observatory
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#define TYPE_ADD(a) CONCAT2X(a, CPL_TYPE)
22#define TYPE_ADD_CONST(a) CONCAT2X(TYPE_ADD(a),const)
23#define IMAGE_GET_DATA TYPE_ADD(cpl_image_get_data)
24
25/*----------------------------------------------------------------------------*/
42/*----------------------------------------------------------------------------*/
43static void
45 const cpl_matrix * mh,
46 const cpl_matrix * mv,
47 const cpl_vector * x_pos,
48 const cpl_imagelist * values,
49 const cpl_vector * xpow,
50 double xnmean, int np, int nc,
51 cpl_image * fiterror)
52{
53
54 const cpl_image * value = cpl_imagelist_get_const(values, 0);
55 const int nx = cpl_image_get_size_x(value);
56 const int ny = cpl_image_get_size_y(value);
57
58 const CPL_TYPE * pi;
59 double * pdest;
60 double * px = cpl_malloc(nx * nc * sizeof(double));
61 double * pbw = cpl_malloc(nx * np * sizeof(double));
62 /* The polynomial coefficients to be solved for
63 - transposed, so the nx polynomials are stored consequtively */
64 cpl_matrix * mx = cpl_matrix_wrap(nx, nc, px);
65 /* The transpose of one row of values to be fitted */
66 cpl_matrix * mb = cpl_matrix_wrap(nx, np, pbw);
67 const cpl_image* image = NULL;
68 int i, j, k, jj;
69
70
71 /* Process one image row at a time
72 - Improves cache usage */
73 for (jj = 0; jj < ny; jj++) {
74
75 /* Fill in matrices */
76 for (j=0; j < np; j++) {
77 image = cpl_imagelist_get_const( values, j);
78 pi = TYPE_ADD_CONST(cpl_image_get_data)
79 (image);
80 /* The fact the mb is transposed makes this operation more
81 expensive - which is OK, since it has a lower complexity
82 than the subsequent use of mb */
83 for (i=0; i < nx; i++) {
84 pbw[np * i + j] = (double)pi[nx * jj + i];
85 }
86 }
87
88 /* Form the right hand side of the normal equations, X = V' * B */
90
91 /* In-place solution of the normal equations, V' * V * X = V' * B */
93
94 if (xnmean != 0.0) {
95 /* Shift polynomials back */
96 for (i=0; i < nx; i++) {
97 irplib_polynomial_shift_double(px + i * nc, nc, xnmean);
98 }
99 }
100
101 /* Copy results to output image list */
102
103 for (k=0; k < nc; k++) {
104 pdest = cpl_image_get_data_double(cpl_imagelist_get(self, k));
105 /* The fact the mx is transposed makes this operation more
106 expensive - which is OK, since it has a lower complexity
107 than the other use of mx */
108 for (i=0; i < nx; i++) {
109 pdest[nx * jj + i] = px[nc * i + k];
110 }
111 }
112
113 if (fiterror != NULL) {
114 switch (cpl_image_get_type(fiterror)) {
115 case CPL_TYPE_DOUBLE:
116 irplib_fit_imagelist_residual_double(fiterror, jj, x_pos,
117 xpow, mx, mb);
118 break;
119 case CPL_TYPE_FLOAT:
120 irplib_fit_imagelist_residual_float(fiterror, jj, x_pos,
121 xpow, mx, mb);
122 break;
123 case CPL_TYPE_INT:
124 irplib_fit_imagelist_residual_int(fiterror, jj, x_pos,
125 xpow, mx, mb);
126 break;
127 default:
128 /* It is an error in CPL to reach this point */
129 assert( 0 );
130 }
131 }
132 }
133 cpl_matrix_delete(mx);
134 cpl_matrix_delete(mb);
135
136}
137
138
139/*----------------------------------------------------------------------------*/
154/*----------------------------------------------------------------------------*/
155static void TYPE_ADD(irplib_fit_imagelist_residual)(cpl_image * self,
156 int jj,
157 const cpl_vector * x_pos,
158 const cpl_vector * xpow,
159 const cpl_matrix * mx,
160 const cpl_matrix * mb)
161{
162 double err, sq_err;
163
164 int nx = cpl_matrix_get_nrow(mx);
165 int nc = cpl_matrix_get_ncol(mx);
166 int np = cpl_vector_get_size(x_pos);
167
168 /* pself points to 1st element in jj'th row */
169 CPL_TYPE * pself = nx * jj + TYPE_ADD(cpl_image_get_data)(self);
170
171 const double * pp = cpl_vector_get_data_const(x_pos);
172
173 /* If mindeg == 0 xpow is NULL (since no multiplication is needed) */
174 const double * pm = xpow != NULL ? cpl_vector_get_data_const(xpow) : NULL;
175 const double * px = cpl_matrix_get_data_const(mx);
176 const double * pb = cpl_matrix_get_data_const(mb);
177
178 int i, j, k;
179
180
181 for (i=0; i < nx; i++, pb += np, px += nc) {
182 sq_err = 0.0;
183 for (j=0; j < np; j++) {
184
185 /* Evaluate the polynomial using Horners scheme, see
186 cpl_polynomial_eval_1d() */
187 k = nc;
188 err = px[--k];
189
190 while (k) err = pp[j] * err + px[--k];
191
192 /* Multiply by x^mindeg - wheen needed */
193 /* Substract expected value to compute the residual */
194 if (pm != NULL) {
195 err = err * pm[j] - pb[j];
196 } else {
197 err -= pb[j];
198 }
199
200 sq_err += err * err;
201 }
202 pself[i] = (CPL_TYPE)(sq_err/(double)np);
203 }
204
205}
206
207#undef TYPE_ADD
208#undef IMAGE_GET_DATA
static cpl_error_code irplib_matrix_product_transpose(cpl_matrix *, const cpl_matrix *, const cpl_matrix *)
Fill a matrix with the product of A * B'.
Definition: xsh_fit.c:384
static void irplib_fit_imagelist_residual_float(cpl_image *, int, const cpl_vector *, const cpl_vector *, const cpl_matrix *, const cpl_matrix *)
#define CPL_TYPE
Definition: xsh_fit.c:848
static cpl_error_code irplib_matrix_solve_chol_transpose(const cpl_matrix *, cpl_matrix *)
Solve a L*transpose(L)-system with a transposed Right Hand Side.
Definition: xsh_fit.c:600
static void irplib_polynomial_shift_double(double *, int, double)
Given p and u, modify the polynomial to p(x) := p(x+u)
Definition: xsh_fit.c:445
static void irplib_fit_imagelist_residual_double(cpl_image *, int, const cpl_vector *, const cpl_vector *, const cpl_matrix *, const cpl_matrix *)
static void irplib_fit_imagelist_residual_int(cpl_image *, int, const cpl_vector *, const cpl_vector *, const cpl_matrix *, const cpl_matrix *)
int nx
int ny
static void TYPE_ADD() irplib_fit_imagelist_residual(cpl_image *self, int jj, const cpl_vector *x_pos, const cpl_vector *xpow, const cpl_matrix *mx, const cpl_matrix *mb)
Compute the residual of a polynomial fit to an imagelist.
Definition: xsh_fit_body.h:155
#define TYPE_ADD_CONST(a)
Definition: xsh_fit_body.h:22
#define TYPE_ADD(a)
Definition: xsh_fit_body.h:21
static void TYPE_ADD() irplib_fit_imagelist_polynomial(cpl_imagelist *self, const cpl_matrix *mh, const cpl_matrix *mv, const cpl_vector *x_pos, const cpl_imagelist *values, const cpl_vector *xpow, double xnmean, int np, int nc, cpl_image *fiterror)
Fit a polynomial to each pixel in a list of images.
Definition: xsh_fit_body.h:44