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