CR2RE Pipeline Reference Manual 1.6.8
irplib_flat.c
1/* $Id: irplib_flat.c,v 1.15 2007-08-07 12:15:41 llundin Exp $
2 *
3 * This file is part of the irplib package
4 * Copyright (C) 2002,2003 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., 51 Franklin St, Fifth Floor, Boston, MA 02111-1307 USA
19 */
20
21/*
22 * $Author: llundin $
23 * $Date: 2007-08-07 12:15:41 $
24 * $Revision: 1.15 $
25 * $Name: not supported by cvs2svn $
26 */
27
28#ifdef HAVE_CONFIG_H
29#include <config.h>
30#endif
31
32/*-----------------------------------------------------------------------------
33 Includes
34 -----------------------------------------------------------------------------*/
35
36#include "irplib_flat.h"
37#include <math.h>
38
39/*-----------------------------------------------------------------------------
40 Functions prototypes
41 -----------------------------------------------------------------------------*/
42
43static double * irplib_flat_fit_proportional(double *, double *, int) ;
44
45/*----------------------------------------------------------------------------*/
49/*----------------------------------------------------------------------------*/
50
53/*----------------------------------------------------------------------------*/
84/*----------------------------------------------------------------------------*/
85cpl_imagelist * irplib_flat_fit_set(
86 cpl_imagelist * raw,
87 int mode)
88{
89 double * plane_med = NULL ;
90 double * slope = NULL ;
91 cpl_image * gain = NULL ;
92 double * pgain = NULL ;
93 cpl_image * intercept = NULL ;
94 double * pintercept = NULL ;
95 cpl_image * sq_err = NULL ;
96 double * psq_err = NULL ;
97 double * timeline = NULL ;
98 float * raw_im_data = NULL ;
99 cpl_imagelist * result = NULL ;
100 const int nx = cpl_image_get_size_x(cpl_imagelist_get(raw, 0));
101 const int ny = cpl_image_get_size_y(cpl_imagelist_get(raw, 0));
102 const int ni = cpl_imagelist_get_size(raw);
103 int i, j ;
104
105 /* Check entries */
106 if (raw==NULL) return NULL ;
107 if ((mode != 0) && (mode != 1)) return NULL ;
108 if (cpl_image_get_type(cpl_imagelist_get(raw, 0)) != CPL_TYPE_FLOAT)
109 return NULL ;
110 if (cpl_imagelist_get_size(raw) <= 1) return NULL ;
111
112 /* Compute median for all planes */
113 plane_med = cpl_malloc(ni * sizeof(double)) ;
114 for (i=0 ; i<ni ; i++)
115 plane_med[i] = cpl_image_get_median(cpl_imagelist_get(raw, i));
116
117 /* Create result images */
118 gain = cpl_image_new(nx, ny, CPL_TYPE_DOUBLE) ;
119 pgain = cpl_image_get_data_double(gain) ;
120 if (mode == 1) {
121 intercept = cpl_image_new(nx, ny, CPL_TYPE_DOUBLE) ;
122 pintercept = cpl_image_get_data_double(intercept) ;
123 }
124 sq_err = cpl_image_new(nx, ny, CPL_TYPE_DOUBLE) ;
125 psq_err = cpl_image_get_data_double(sq_err) ;
126 timeline = cpl_malloc(ni * sizeof(double)) ;
127
128 /* Loop on all pixel positions */
129 cpl_msg_info(cpl_func, "Computing gains for all positions (long)...") ;
130 for (i=0 ; i<nx * ny ; i++) {
131 /* extract time line */
132 for (j=0 ; j<ni ; j++) {
133 raw_im_data = cpl_image_get_data_float(cpl_imagelist_get(raw, j)) ;
134 timeline[j] = (double)raw_im_data[i] ;
135 }
136 /* Fit slope to this time line */
137 if (mode == 1) {
138 slope = irplib_flat_fit_slope_robust(plane_med, timeline, ni) ;
139 pintercept[i] = slope[0] ;
140 pgain[i] = slope[1] ;
141 psq_err[i] = slope[2] ;
142 /* Set results in output images */
143 } else {
144 slope = irplib_flat_fit_proportional(plane_med, timeline, ni) ;
145 /* Set results in output images */
146 pgain[i] = slope[0] ;
147 psq_err[i] = slope[1] ;
148 }
149 cpl_free(slope);
150 }
151 cpl_free(plane_med) ;
152 cpl_free(timeline) ;
153
154 /* Return */
155 result = cpl_imagelist_new() ;
156 if (mode == 1) {
157 cpl_imagelist_set(result, gain, 0) ;
158 cpl_imagelist_set(result, intercept, 1) ;
159 cpl_imagelist_set(result, sq_err, 2) ;
160 } else {
161 cpl_imagelist_set(result, gain, 0) ;
162 cpl_imagelist_set(result, sq_err, 1) ;
163 }
164 return result ;
165}
166
167/* @cond */
168#define SIGN(a,b) ((b) >= 0.0 ? fabs(a) : -fabs(a))
169#define MAX_ITERATE 30
170/* @endcond */
171/*----------------------------------------------------------------------------*/
188/*----------------------------------------------------------------------------*/
190 double * x,
191 double * y,
192 int np)
193{
194 double * c ;
195 double aa, bb, bcomp, b1, b2, del, abdevt, f1, f2, sigb,
196 d, sum ;
197 double sx, sy, sxy, sxx, chisq ;
198 cpl_vector * arr ;
199 double * parr ;
200 double aa_ls, bb_ls ;
201 int iter ;
202 int i ;
203
204 /* Check entries */
205 if (x==NULL || y==NULL) return NULL ;
206
207 c = cpl_malloc(3 * sizeof(double)) ;
208
209 sx = sy = sxx = sxy = 0.00 ;
210 for (i=0 ; i<np ; i++) {
211 sx += x[i];
212 sy += y[i];
213 sxy += x[i] * y[i];
214 sxx += x[i] * x[i];
215 }
216
217 del = np * sxx - sx * sx;
218 aa_ls = aa = (sxx * sy - sx * sxy) / del;
219 bb_ls = bb = (np * sxy - sx * sy) / del;
220
221 chisq = 0.00 ;
222 for (i=0;i<np;i++) {
223 double temp = y[i] - (aa+bb*x[i]) ;
224 temp *= temp ;
225 chisq += temp ;
226 }
227
228 arr = cpl_vector_new(np) ;
229 parr = cpl_vector_get_data(arr) ;
230 sigb = sqrt(chisq/del);
231 b1 = bb ;
232
233 bcomp = b1 ;
234 sum = 0.00 ;
235 for (i=0 ; i<np ; i++) {
236 parr[i] = y[i] - bcomp * x[i];
237 }
238 aa = cpl_vector_get_median(arr); /* arr permuted */
239 abdevt = 0.0;
240 for (i=0 ; i<np ; i++) {
241 d = y[i] - (bcomp * x[i] + aa);
242 abdevt += fabs(d);
243 if (fabs(y[i]) > 1e-7) d /= fabs(y[i]);
244 if (fabs(d) > 1e-7) sum += (d >= 0.0 ? x[i] : -x[i]);
245 }
246 f1 = sum ;
247 b2 = bb + SIGN(3.0 * sigb, f1);
248 bcomp = b2 ;
249 sum = 0.00 ;
250 for (i=0 ; i<np ; i++) parr[i] = y[i] - bcomp * x[i];
251 aa = cpl_vector_get_median(arr); /* arr permuted */
252 abdevt = 0.0;
253 for (i=0 ; i<np ; i++) {
254 d = y[i] - (bcomp * x[i] + aa);
255 abdevt += fabs(d);
256 if (fabs(y[i]) > 1e-7) d /= fabs(y[i]);
257 if (fabs(d) > 1e-7) sum += (d >= 0.0 ? x[i] : -x[i]);
258 }
259 f2 = sum ;
260
261 if (fabs(b2-b1)<1e-7) {
262 c[0] = aa ;
263 c[1] = bb ;
264 c[2] = abdevt / (double)np;
265 cpl_vector_delete(arr);
266 return c ;
267 }
268
269 iter = 0 ;
270 while (f1*f2 > 0.0) {
271 bb = 2.0*b2-b1;
272 b1 = b2;
273 f1 = f2;
274 b2 = bb;
275
276 bcomp = b2 ;
277 sum = 0.00 ;
278 for (i=0 ; i<np ; i++) parr[i] = y[i] - bcomp * x[i];
279 aa = cpl_vector_get_median(arr); /* arr permuted */
280 abdevt = 0.0;
281 for (i=0 ; i<np ; i++) {
282 d = y[i] - (bcomp * x[i] + aa);
283 abdevt += fabs(d);
284 if (fabs(y[i]) > 1e-7) d /= fabs(y[i]);
285 if (fabs(d) > 1e-7) sum += (d >= 0.0 ? x[i] : -x[i]);
286 }
287 f2 = sum ;
288 iter++;
289 if (iter>=MAX_ITERATE) break ;
290 }
291 if (iter>=MAX_ITERATE) {
292 c[0] = aa_ls ;
293 c[1] = bb_ls ;
294 c[2] = -1.0 ;
295 cpl_vector_delete(arr);
296 return c ;
297 }
298
299 sigb = 0.01 * sigb;
300 while (fabs(b2-b1) > sigb) {
301 double f;
302 bb = 0.5 * (b1 + b2) ;
303 if ((fabs(bb-b1)<1e-7) || (fabs(bb-b2)<1e-7)) break;
304 bcomp = bb ;
305 sum = 0.00 ;
306 for (i=0 ; i<np ; i++) parr[i] = y[i] - bcomp * x[i];
307 aa = cpl_vector_get_median(arr); /* arr permuted */
308 abdevt = 0.0;
309 for (i=0 ; i<np ; i++) {
310 d = y[i] - (bcomp * x[i] + aa);
311 abdevt += fabs(d);
312 if (fabs(y[i]) > 1e-7) d /= fabs(y[i]);
313 if (fabs(d) > 1e-7) sum += (d >= 0.0 ? x[i] : -x[i]);
314 }
315 f = sum ;
316
317 if (f*f1 >= 0.0) {
318 f1=f;
319 b1=bb;
320 } else {
321 /*f2=f;*/
322 b2=bb;
323 }
324 }
325 cpl_vector_delete(arr) ;
326 c[0]=aa;
327 c[1]=bb;
328 c[2]=abdevt/np;
329 return c ;
330}
331#undef MAX_ITERATE
332#undef SIGN
333
334
337/*----------------------------------------------------------------------------*/
361/*----------------------------------------------------------------------------*/
362#define FITPROP_BIG_SLOPE 1e30
363static double * irplib_flat_fit_proportional(
364 double * x,
365 double * y,
366 int np)
367{
368 cpl_vector * slopes ;
369 double * pslopes ;
370 double * med_slope ;
371 double sq_err ;
372 int i ;
373
374 /* Check entries */
375 if (x==NULL || y==NULL) return NULL ;
376
377 slopes = cpl_vector_new(np) ;
378 pslopes = cpl_vector_get_data(slopes) ;
379 for (i=0 ; i<np ; i++) {
380 if (fabs(x[i])>1e-30) pslopes[i] = y[i] / x[i] ;
381 else pslopes[i] = FITPROP_BIG_SLOPE ;
382 }
383 med_slope = cpl_malloc(2 * sizeof(double));
384 med_slope[0] = cpl_vector_get_median(slopes); /* slopes permuted */
385 cpl_vector_delete(slopes);
386
387 sq_err = 0.00 ;
388 for (i=0 ; i<np ; i++) {
389 double val = med_slope[0] * x[i] ;
390 sq_err += (val-y[i])*(val-y[i]) ;
391 }
392 sq_err /= (double)np ;
393 med_slope[1] = sq_err ;
394
395 return med_slope ;
396#undef FITPROP_BIG_SLOPE
397}
398
399
400
cpl_imagelist * irplib_flat_fit_set(cpl_imagelist *raw, int mode)
Compute a flat-field out of a set of exposures.
Definition: irplib_flat.c:85
double * irplib_flat_fit_slope_robust(double *x, double *y, int np)
Fit a slope to a list of points (robust fit).
Definition: irplib_flat.c:189