NACO Pipeline Reference Manual  4.4.0
naco_img_detlin.c
1 /* $Id: naco_img_detlin.c,v 1.41 2009-01-29 08:54:58 llundin Exp $
2  *
3  * This file is part of the NACO Pipeline
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: 2009-01-29 08:54:58 $
24  * $Revision: 1.41 $
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 "naco_recipe.h"
37 
38 /*-----------------------------------------------------------------------------
39  Define
40  -----------------------------------------------------------------------------*/
41 
42 #define RECIPE_STRING "naco_img_detlin"
43 
44 #define DETLIN_LIMIT 0.75
45 #define DETLIN_STABILITY 1/100.0
46 
47 #define DETLIN_MAX_GRAD 1.5 /* Maximum gradient */
48 #define DETLIN_MAX_RESI 10.0 /* Maximum residual */
49 
50 /*-----------------------------------------------------------------------------
51  Private Functions prototypes
52  -----------------------------------------------------------------------------*/
53 
54 static cpl_error_code naco_img_detlin_load(cpl_imagelist *, cpl_vector *,
55  const cpl_parameterlist *,
56  const irplib_framelist *,
57  const irplib_framelist *);
58 
59 static cpl_image * naco_img_detlin_limit(const cpl_imagelist *);
60 static cpl_image * naco_img_detlin_bpm(const cpl_imagelist *,
61  const cpl_vector *,
62  const cpl_image *);
63 
64 static cpl_error_code naco_img_detlin_dit_diff(cpl_vector *);
65 
66 static cpl_error_code naco_img_detlin_save(cpl_frameset *,
67  const cpl_parameterlist *,
68  const cpl_propertylist *,
69  const cpl_imagelist *,
70  const cpl_image *,
71  const cpl_image *);
72 
73 static cpl_imagelist * naco_imagelist_fit_polynomial(const cpl_imagelist *,
74  const double *, int);
75 
76 NACO_RECIPE_DEFINE(naco_img_detlin,
77  NACO_PARAM_FORCE,
78  "Detector linearity recipe",
79  RECIPE_STRING " -- NACO imaging detector linearity recipe.\n"
80  "The Set Of Frames (sof-file) must specify at least three "
81  "pairs of files which must be tagged\n"
82  "NACO-raw-file.fits " NACO_IMG_DETLIN_LAMP " and\n"
83  "NACO-raw-file.fits " NACO_IMG_DETLIN_DARK "\n");
84 
85 /*----------------------------------------------------------------------------*/
89 /*----------------------------------------------------------------------------*/
90 
91 /*-----------------------------------------------------------------------------
92  Functions code
93  -----------------------------------------------------------------------------*/
94 
95 /*----------------------------------------------------------------------------*/
102 /*----------------------------------------------------------------------------*/
103 static int naco_img_detlin(cpl_frameset * framelist,
104  const cpl_parameterlist * parlist)
105 {
106  irplib_framelist * allframes = NULL;
107  irplib_framelist * darkframes = NULL;
108  irplib_framelist * lampframes = NULL;
109  cpl_propertylist * qclist = cpl_propertylist_new();
110  const cpl_propertylist * reflist;
111  cpl_imagelist * iset = cpl_imagelist_new();
112  cpl_image * lin_limit = NULL;
113  cpl_vector * ditval = cpl_vector_new(4); /* 4 is minimum */
114  cpl_imagelist * fitres = NULL;
115  cpl_image * bpm = NULL;
116  cpl_image * residual = NULL;
117 
118 
119  /* Identify the RAW and CALIB frames in the input frameset */
120  skip_if (naco_dfs_set_groups(framelist));
121 
122  allframes = irplib_framelist_cast(framelist);
123  skip_if(allframes == NULL);
124 
125  darkframes = irplib_framelist_extract(allframes, NACO_IMG_DETLIN_DARK);
126  skip_if (darkframes == NULL);
127 
128  lampframes = irplib_framelist_extract(allframes, NACO_IMG_DETLIN_LAMP);
129  skip_if (lampframes == NULL);
130 
131  /* Load the data and check the DIT consistency */
132  cpl_msg_info(cpl_func, "Load the data");
133  skip_if( irplib_framelist_load_propertylist(lampframes, 0, 0, "^("
134  NACO_PFITS_REGEXP_DETLIN_FIRST
135  ")$", CPL_FALSE));
136 
137  skip_if(irplib_framelist_load_propertylist_all(lampframes, 0, "^("
138  NACO_PFITS_REGEXP_DETLIN
139  ")$",
140  CPL_FALSE));
141 
142  skip_if(irplib_framelist_load_propertylist_all(darkframes, 0, "^("
143  NACO_PFITS_REGEXP_DETLIN
144  ")$", CPL_FALSE));
145 
146  skip_if (naco_img_detlin_load(iset, ditval, parlist, lampframes,
147  darkframes));
148 
149  reflist = irplib_framelist_get_propertylist_const(lampframes, 0);
150  bug_if (cpl_propertylist_copy_property_regexp(qclist, reflist, "^("
151  NACO_PFITS_REGEXP_DETLIN_COPY
152  ")$", 0));
153 
154  irplib_framelist_delete(lampframes);
155  lampframes = NULL;
156  irplib_framelist_delete(darkframes);
157  darkframes = NULL;
158 
159  /* Compute the linearity limit */
160  cpl_msg_info(cpl_func, "Compute the linearity limit");
161  lin_limit = naco_img_detlin_limit(iset);
162  skip_if (lin_limit == NULL);
163 
164  /* Compute the linearity coefficients */
165  cpl_msg_info(cpl_func, "Compute the linearity coefficients");
166 #if defined USE_CPL_FIT_IMAGELIST_POLYNOMIAL
167  residual = cpl_image_new(cpl_image_get_size_x(lin_limit),
168  cpl_image_get_size_y(lin_limit),
169  CPL_TYPE_FLOAT);
170  bug_if(0);
171  cpl_vector_dump(ditval, stderr);
172  fitres = cpl_fit_imagelist_polynomial(ditval, iset, 1, 4, CPL_FALSE,
173  CPL_TYPE_FLOAT, residual);
174  skip_if (fitres == NULL);
175 
176  bug_if (cpl_imagelist_set(fitres, residual, 4));
177  residual = NULL;
178 #else
179  fitres = naco_imagelist_fit_polynomial(iset, cpl_vector_get_data(ditval), 4);
180  skip_if (fitres == NULL);
181 #endif
182 
183  /* Compute the bad pixels map */
184  cpl_msg_info(cpl_func, "Compute the bad pixels map");
185  skip_if (naco_img_detlin_dit_diff(ditval));
186  bpm = naco_img_detlin_bpm(iset, ditval, cpl_imagelist_get(fitres, 4));
187  cpl_imagelist_delete(iset);
188  iset = NULL;
189 
190  skip_if (bpm==NULL);
191 
192  /* Save the products */
193  cpl_msg_info(cpl_func, "Save the products");
194  skip_if (naco_img_detlin_save(framelist, parlist, qclist, fitres,
195  lin_limit, bpm));
196 
197  end_skip;
198 
199  irplib_framelist_delete(allframes);
200  irplib_framelist_delete(lampframes);
201  irplib_framelist_delete(darkframes);
202  cpl_image_delete(lin_limit);
203  cpl_image_delete(residual);
204  cpl_imagelist_delete(fitres);
205  cpl_image_delete(bpm);
206  cpl_imagelist_delete(iset);
207  cpl_vector_delete(ditval);
208  cpl_propertylist_delete(qclist);
209 
210  return cpl_error_get_code();
211 }
212 
213 /*----------------------------------------------------------------------------*/
223 /*----------------------------------------------------------------------------*/
224 static cpl_error_code naco_img_detlin_load(cpl_imagelist * lamplist,
225  cpl_vector * ditval,
226  const cpl_parameterlist * parlist,
227  const irplib_framelist * lamps,
228  const irplib_framelist * darks)
229 {
230  cpl_image * imlamp = NULL;
231  cpl_image * imdark = NULL;
232  double refmean, refdit;
233  double dit_min, dit_max;
234  const int nb_lamps = irplib_framelist_get_size(lamps);
235  int dit_var = 0;
236  int i;
237  const cpl_boolean force = naco_parameterlist_get_bool(parlist, RECIPE_STRING,
238  NACO_PARAM_FORCE);
239 
240 
241  bug_if (0);
242 
243  bug_if (lamplist == NULL);
244  bug_if (darks == NULL);
245  bug_if (ditval == NULL);
246 
247  skip_if_lt(nb_lamps, 3, "lamp images");
248 
249  /* Check that there are as many lamp as darks */
250  skip_if (irplib_framelist_get_size(darks) != nb_lamps);
251 
252  /* Check out that they have consistent integration times */
253  cpl_msg_info(cpl_func, "Checking DIT consistency");
254 
255  skip_if(irplib_framelist_contains(lamps, NACO_PFITS_DOUBLE_DIT,
256  CPL_TYPE_DOUBLE, CPL_FALSE, 0.0));
257 
258  skip_if(irplib_framelist_contains(darks, NACO_PFITS_DOUBLE_DIT,
259  CPL_TYPE_DOUBLE, CPL_FALSE, 0.0));
260 
261  /* Load the data and compute lamp-dark */
262  cpl_msg_info(cpl_func, "Compute the differences lamp - dark");
263 
264  /* Check the lamp stability */
265  cpl_msg_info(cpl_func, "Check the lamp stability");
266 
267  bug_if(cpl_vector_set_size(ditval, nb_lamps));
268  refmean = refdit = dit_max = dit_min = 0.0; /* Avoid uninit warning */
269  for (i=0 ; i < nb_lamps ; i++) {
270  const char * lampname
271  = cpl_frame_get_filename(irplib_framelist_get_const(lamps, i));
272  const char * darkname
273  = cpl_frame_get_filename(irplib_framelist_get_const(darks, i));
274 
275  /* DIT from LAMP */
276  const cpl_propertylist * plist
278  const double dit_lamp = (double)naco_pfits_get_dit(plist);
279  double dit_dark;
280 
281 
282  bug_if (0);
283 
284  /* DIT from DARK */
285  plist = irplib_framelist_get_propertylist_const(darks, i);
286  dit_dark = naco_pfits_get_dit(plist);
287  bug_if (0);
288 
289  /* Check consistency */
290  irplib_ensure(fabs(dit_dark-dit_lamp) <= 1e-3,
291  CPL_ERROR_INCOMPATIBLE_INPUT,
292  "LAMP-DIT=%g and DARK-DIT=%g differ by more than %g",
293  dit_lamp, dit_dark, 1e-3);
294 
295  irplib_check(imlamp = cpl_image_load(lampname, CPL_TYPE_FLOAT, 0, 0),
296  "Could not load FITS-image from %s", lampname);
297 
298  cpl_image_delete(imdark);
299  irplib_check(imdark = cpl_image_load(darkname, CPL_TYPE_FLOAT, 0, 0),
300  "Could not load FITS-image from %s", darkname);
301 
302  bug_if (cpl_image_subtract(imlamp, imdark));
303 
304  /* Set selection */
305  if (i > 0 && dit_lamp != refdit) {
306  bug_if(cpl_imagelist_set(lamplist, imlamp, dit_var));
307  imlamp = NULL;
308  bug_if(cpl_vector_set(ditval, dit_var, dit_lamp));
309  dit_var++;
310  if (dit_lamp > dit_max) dit_max = dit_lamp;
311  if (dit_lamp < dit_min) dit_min = dit_lamp;
312  } else {
313  const double mean = cpl_image_get_mean(imlamp);
314 
315  cpl_image_delete(imlamp);
316  imlamp = NULL;
317 
318  bug_if(0);
319 
320  if (i == 0) {
321  refmean = mean;
322  dit_max = dit_min = refdit = dit_lamp;
323  } else if ((mean - refmean) > refmean * (DETLIN_STABILITY)) {
324  irplib_ensure(force, CPL_ERROR_INCOMPATIBLE_INPUT,
325  "Relative level difference # %d is too high:"
326  " (%g - %g)/%g > %g", i+1, mean, refmean,
327  refmean, (DETLIN_STABILITY));
328 
329  cpl_msg_warning(cpl_func, "Relative level difference # %d "
330  "is high: (%g - %g)/%g > %g", i+1, mean,
331  refmean, refmean, (DETLIN_STABILITY));
332  }
333  }
334  }
335 
336  /* Check if there are enough DITs for stability check */
337  skip_if_lt(i - dit_var, 2, "lamp frames for stability check");
338 
339  if (dit_min >= dit_max) {
340  cpl_msg_error(cpl_func, "Too small DIT range: %g - %g = %g", dit_max,
341  dit_min, dit_max - dit_min);
342  cpl_error_set(cpl_func, CPL_ERROR_DATA_NOT_FOUND);
343  skip_if(1);
344  }
345 
346  bug_if(cpl_vector_set_size(ditval, dit_var));
347 
348  end_skip;
349 
350  cpl_image_delete(imlamp);
351  cpl_image_delete(imdark);
352 
353  return cpl_error_get_code();
354 }
355 
356 /*----------------------------------------------------------------------------*/
362 /*----------------------------------------------------------------------------*/
363 static cpl_image * naco_img_detlin_limit(const cpl_imagelist * iset)
364 {
365  cpl_image * lin_limit = NULL;
366  int size_x, size_y;
367  float * plin_limit;
368  const float * pim1;
369  const float * pim2;
370  float ref_diff, cur_diff;
371  int i, j;
372 
373 
374  if (cpl_error_get_code()) return NULL;
375 
376  skip_if_lt(cpl_imagelist_get_size(iset), 3, "images to compute the "
377  "detector linearity limit");
378 
379  /* Get image size */
380  size_x = cpl_image_get_size_x(cpl_imagelist_get_const(iset, 0));
381  size_y = cpl_image_get_size_y(cpl_imagelist_get_const(iset, 0));
382 
383  /* Create the output image */
384  lin_limit = cpl_image_new(size_x, size_y, CPL_TYPE_FLOAT);
385 
386  skip_if (lin_limit == NULL);
387 
388  plin_limit = cpl_image_get_data_float(lin_limit);
389 
390  bug_if(0);
391 
392  /* Compute the limit for each pixel */
393  for (i=0 ; i<size_x*size_y ; i++) {
394  pim1 = cpl_image_get_data_float_const(cpl_imagelist_get_const(iset, 0));
395  pim2 = cpl_image_get_data_float_const(cpl_imagelist_get_const(iset, 1));
396  ref_diff = pim2[i] - pim1[i];
397  for (j=1 ; j<cpl_imagelist_get_size(iset)-1 ; j++) {
398  pim1 = cpl_image_get_data_float_const(
399  cpl_imagelist_get_const(iset, j));
400  pim2 = cpl_image_get_data_float_const(
401  cpl_imagelist_get_const(iset, j+1));
402  cur_diff = pim2[i] - pim1[i];
403  if (cur_diff < DETLIN_LIMIT*ref_diff) {
404  /* The limit is reached */
405  plin_limit[i] = pim1[i];
406  break;
407  }
408  /* The limit is undefined */
409  if (j+1 == cpl_imagelist_get_size(iset)-1)
410  plin_limit[i] = (float)0.0;
411  }
412  }
413 
414  end_skip;
415 
416  return lin_limit;
417 }
418 
419 /*----------------------------------------------------------------------------*/
426 /*----------------------------------------------------------------------------*/
427 static cpl_error_code naco_img_detlin_dit_diff(cpl_vector * self)
428 {
429 
430  double * dits;
431  int i;
432 
433  bug_if(0);
434  bug_if(self == NULL);
435 
436  dits = cpl_vector_get_data(self);
437 
438  for (i = cpl_vector_get_size(self)-1; i > 0 ; i--) {
439  dits[i] -= dits[i-1];
440 
441  if (dits[i] == 0.0) break;
442 
443  }
444 
445  if (i > 0) {
446  cpl_msg_error(cpl_func, "Consecutive (%d and %d) DITS are equal: "
447  "%g", i-1, i, dits[i-1]);
448 
449  cpl_error_set(cpl_func, CPL_ERROR_ILLEGAL_INPUT);
450  skip_if(1);
451  }
452 
453  end_skip;
454 
455  return cpl_error_get_code();
456 
457 }
458 
459 
460 /*----------------------------------------------------------------------------*/
468 /*----------------------------------------------------------------------------*/
469 static cpl_image * naco_img_detlin_bpm(const cpl_imagelist * iset,
470  const cpl_vector * ditdiff,
471  const cpl_image * err_im)
472 {
473  cpl_image * imdiff = NULL;
474  cpl_image * bpm = NULL;
475  int * pbpm;
476  const double * perr_im;
477  const float * pim1;
478  const float * pim2;
479  float * pimdiff;
480  const double * ditval = cpl_vector_get_data_const(ditdiff);
481  float dit_ref, curr_val;
482  int size_x, size_y;
483  int ii, i, j, k;
484 
485 
486  bug_if(0);
487  skip_if_lt(cpl_imagelist_get_size(iset), 3, "images to compute the "
488  "bad pixel map");
489 
490  /* Get size */
491  size_x = cpl_image_get_size_x(cpl_imagelist_get_const(iset, 0));
492  size_y = cpl_image_get_size_y(cpl_imagelist_get_const(iset, 0));
493  bug_if(0);
494 
495  /* Create the output image */
496  /* - with all pixels zero-valued - i.e. they are assumed to be good */
497  bpm = cpl_image_new(size_x, size_y, CPL_TYPE_INT);
498  bug_if(0);
499  pbpm = cpl_image_get_data_int(bpm);
500 
501  imdiff = cpl_image_new(size_x, 1, CPL_TYPE_FLOAT);
502  bug_if(0);
503  pimdiff = cpl_image_get_data_float(imdiff);
504 
505  /* Compute the bad pixel value for each pixel */
506  dit_ref = (float)ditval[1];
507  perr_im = cpl_image_get_data_double_const(err_im);
508 
509  for (ii = 0, j=0 ; j < size_y ; j++) {
510  pim1 = cpl_image_get_data_float_const(cpl_imagelist_get_const(iset, 1));
511  pim2 = cpl_image_get_data_float_const(cpl_imagelist_get_const(iset, 0));
512 
513  for (i=0 ; i < size_x ; i++, ii++) {
514  const float fdiff = pim1[ii] - pim2[ii];
515 
516  pimdiff[i] = fdiff;
517 
518  /* Second test */
519  if (fdiff * dit_ref < 0.0) pbpm[ii] |= 2;
520 
521  /* Third test */
522  if (perr_im[ii] > DETLIN_MAX_RESI) pbpm[ii] |= 4;
523  }
524 
525  for (k=1 ; k < cpl_imagelist_get_size(iset)-1 ; k++) {
526  const float dit_diff = ditval[k+1] * DETLIN_MAX_GRAD;
527 
528  pim2 = pim1;
529  pim1 = cpl_image_get_data_float_const(
530  cpl_imagelist_get_const(iset, k+1));
531 
532  ii -= size_x;
533  for (i=0 ; i < size_x ; i++, ii++) {
534  if ((pbpm[ii] & 1) == 0) {
535 
536  const float fdiff = pimdiff[i];
537 
538  curr_val = pim1[ii] - pim2[ii];
539  if (dit_diff * dit_ref < 0.0
540  ? (curr_val * dit_ref < fdiff * dit_diff)
541  : (curr_val * dit_ref > fdiff * dit_diff)) {
542  pbpm[ii] |= 1;
543  }
544  }
545  }
546  }
547  }
548 
549  end_skip;
550 
551  cpl_image_delete(imdiff);
552 
553  return bpm;
554 }
555 
556 /*----------------------------------------------------------------------------*/
567 /*----------------------------------------------------------------------------*/
568 static cpl_error_code naco_img_detlin_save(cpl_frameset * set,
569  const cpl_parameterlist * parlist,
570  const cpl_propertylist * qclist,
571  const cpl_imagelist * fitres,
572  const cpl_image * lin_limit,
573  const cpl_image * bpm)
574 {
575 
576  bug_if(0);
577 
578  /* Write the _A FITS FILE */
579  skip_if (irplib_dfs_save_image(set, parlist, set,
580  cpl_imagelist_get_const(fitres, 0),
581  CPL_BPP_IEEE_FLOAT, RECIPE_STRING,
582  NACO_IMG_DETLIN_A, qclist, NULL,
583  naco_pipe_id,
584  RECIPE_STRING "_A" CPL_DFS_FITS));
585 
586  /* Write the _B FITS FILE */
587  skip_if (irplib_dfs_save_image(set, parlist, set,
588  cpl_imagelist_get_const(fitres, 1),
589  CPL_BPP_IEEE_FLOAT, RECIPE_STRING,
590  NACO_IMG_DETLIN_B, qclist, NULL, naco_pipe_id,
591  RECIPE_STRING "_B" CPL_DFS_FITS));
592 
593  /* Write the _C FITS FILE */
594  skip_if (irplib_dfs_save_image(set, parlist, set,
595  cpl_imagelist_get_const(fitres, 2),
596  CPL_BPP_IEEE_FLOAT, RECIPE_STRING,
597  NACO_IMG_DETLIN_C, qclist, NULL, naco_pipe_id,
598  RECIPE_STRING "_C" CPL_DFS_FITS));
599 
600  /* Write the _D FITS FILE */
601  skip_if (irplib_dfs_save_image(set, parlist, set,
602  cpl_imagelist_get_const(fitres, 3),
603  CPL_BPP_IEEE_FLOAT, RECIPE_STRING,
604  NACO_IMG_DETLIN_D, qclist, NULL, naco_pipe_id,
605  RECIPE_STRING "_D" CPL_DFS_FITS));
606 
607  /* Write the _Q FITS FILE */
608  skip_if (irplib_dfs_save_image(set, parlist, set,
609  cpl_imagelist_get_const(fitres, 4),
610  CPL_BPP_IEEE_FLOAT, RECIPE_STRING,
611  NACO_IMG_DETLIN_Q, qclist, NULL, naco_pipe_id,
612  RECIPE_STRING "_Q" CPL_DFS_FITS));
613 
614  /* Write the _limit FITS FILE */
615  skip_if (irplib_dfs_save_image(set, parlist, set, lin_limit, CPL_BPP_IEEE_FLOAT,
616  RECIPE_STRING, NACO_IMG_DETLIN_LIM, qclist, NULL,
617  naco_pipe_id,
618  RECIPE_STRING "_limit" CPL_DFS_FITS));
619 
620  /* Write the _bpm FITS FILE */
621  skip_if (irplib_dfs_save_image(set, parlist, set, bpm, CPL_BPP_8_UNSIGNED,
622  RECIPE_STRING, NACO_IMG_DETLIN_BPM, qclist, NULL,
623  naco_pipe_id,
624  RECIPE_STRING "_bpm" CPL_DFS_FITS));
625 
626  end_skip;
627 
628  return cpl_error_get_code();
629 }
630 
631 
632 
633 /*----------------------------------------------------------------------------*/
662 /*----------------------------------------------------------------------------*/
663 static cpl_imagelist * naco_imagelist_fit_polynomial(
664  const cpl_imagelist * ilist,
665  const double * dit,
666  int deg)
667 {
668  cpl_imagelist * fitres;
669  const cpl_image * image;
670  int ni, nx, ny;
671 
672  /* Check entries */
673  cpl_ensure(ilist != NULL, CPL_ERROR_NULL_INPUT, NULL);
674  cpl_ensure(dit != NULL, CPL_ERROR_NULL_INPUT, NULL);
675  cpl_ensure(deg > 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
676 
677  ni = cpl_imagelist_get_size(ilist);
678  cpl_ensure(ni >= deg, CPL_ERROR_INCOMPATIBLE_INPUT, NULL);
679 
680  image = cpl_imagelist_get_const(ilist, 0);
681 
682  cpl_ensure(cpl_image_get_type(image) == CPL_TYPE_FLOAT,
683  CPL_ERROR_TYPE_MISMATCH, NULL);
684 
685  nx = cpl_image_get_size_x(image);
686  ny = cpl_image_get_size_y(image);
687 
688  do {
689 
690  double f, f_prod;
691  double * pimad;
692  const float* pi;
693  cpl_matrix * mv;
694  cpl_matrix * mb;
695  cpl_matrix * mx;
696  double * pv;
697  const int npix = nx * ny;
698  int nsing = 0;
699  int i, j, k;
700  cpl_errorstate prestate = cpl_errorstate_get();
701 
702 
703  /* Allocate deg+1 images to store the results */
704  fitres = cpl_imagelist_new();
705  for (i=0; i < deg+1; i++) {
706  cpl_imagelist_set(fitres, cpl_image_new(nx, ny, CPL_TYPE_DOUBLE),
707  i);
708  }
709 
710  /* Create matrices */
711  pv = cpl_malloc(ni * deg * sizeof(double));
712  mv = cpl_matrix_wrap(ni, deg, pv);
713 
714  /* Fill RHS matrix
715  - mb is _not_ modified */
716  mb = cpl_matrix_wrap(ni, 1, (double*)dit);
717 
718  /* Loop on pixels */
719  for (i=0; i < npix; i++) {
720  /* Fill Vandermonde matrix */
721  for (j=0; j < ni; j++) {
722  pi = cpl_image_get_data_const(cpl_imagelist_get_const(ilist,j));
723  f_prod = f = (double)pi[i];
724  pv[deg * j] = f;
725  for (k=1; k < deg; k++) {
726  f_prod *= f;
727  pv[deg * j + k] = f_prod;
728  }
729  }
730 
731  /* Solve least-squares */
732  /* FIXME: See cpl_polynomial_fit_1d_create() for how to
733  reduce the solve time */
734  mx = cpl_matrix_solve_normal(mv, mb);
735 
736  if (mx == NULL) {
737  cpl_errorstate_set(prestate);
738  for (k=0; k < deg+1; k++) {
739  pimad =
740  cpl_image_get_data_double(cpl_imagelist_get(fitres,k));
741  pimad[i] = 0.0;
742  }
743  nsing++;
744  } else {
745  double err, sq_err;
746  const double * px = cpl_matrix_get_data(mx);
747 
748  /* Store results */
749  for (k=0; k < deg; k++) {
750  pimad = cpl_image_get_data_double(
751  cpl_imagelist_get(fitres, k));
752  pimad[i] = px[k];
753  }
754 
755  /* Goodness of fit */
756  sq_err=0.0;
757  for (j=0; j < ni; j++) {
758  /* Error between model and reality */
759  err = dit[j];
760  /* Computed by model */
761  for (k=0; k < deg; k++)
762  err -= px[k] * pv[deg * j + k];
763  sq_err += err * err;
764  }
765  sq_err /= (double)ni;
766  pimad=cpl_image_get_data_double(cpl_imagelist_get(fitres, deg));
767  pimad[i] = sq_err;
768  cpl_matrix_delete(mx);
769  }
770  }
771 
772  cpl_matrix_delete(mv);
773  (void)cpl_matrix_unwrap(mb);
774 
775  if (nsing == npix) {
776  cpl_imagelist_delete(fitres);
777  cpl_ensure(0, CPL_ERROR_SINGULAR_MATRIX, NULL);
778  }
779 
780 
781  } while (0);
782 
783 
784  return fitres;
785 }
double naco_pfits_get_dit(const cpl_propertylist *self)
find out the DIT
Definition: naco_pfits.c:131
int naco_dfs_set_groups(cpl_frameset *set)
Set the group as RAW or CALIB in a frameset.
Definition: naco_dfs.c:62
const cpl_propertylist * irplib_framelist_get_propertylist_const(const irplib_framelist *self, int pos)
Get the propertylist of the specified frame in the framelist.
cpl_error_code irplib_dfs_save_image(cpl_frameset *allframes, const cpl_parameterlist *parlist, const cpl_frameset *usedframes, const cpl_image *image, cpl_type_bpp bpp, const char *recipe, const char *procat, const cpl_propertylist *applist, const char *remregexp, const char *pipe_id, const char *filename)
Save an image as a DFS-compliant pipeline product.
Definition: irplib_utils.c:208
cpl_error_code irplib_framelist_load_propertylist_all(irplib_framelist *self, int ind, const char *regexp, cpl_boolean invert)
Load the propertylists of all frames in the framelist.
cpl_boolean naco_parameterlist_get_bool(const cpl_parameterlist *self, const char *recipe, naco_parameter bitmask)
Retrieve the value of a NACO boolean parameter.
irplib_framelist * irplib_framelist_extract(const irplib_framelist *self, const char *tag)
Extract the frames with the given tag from a framelist.
const cpl_frame * irplib_framelist_get_const(const irplib_framelist *self, int pos)
Get the specified frame from the framelist.
void irplib_framelist_delete(irplib_framelist *self)
Deallocate an irplib_framelist with its frames and properties.
cpl_error_code irplib_framelist_contains(const irplib_framelist *self, const char *key, cpl_type type, cpl_boolean is_equal, double fp_tol)
Verify that a property is present for all frames.
cpl_error_code irplib_framelist_load_propertylist(irplib_framelist *self, int pos, int ind, const char *regexp, cpl_boolean invert)
Load the propertylist of the specified frame in the framelist.
irplib_framelist * irplib_framelist_cast(const cpl_frameset *frameset)
Create an irplib_framelist from a cpl_framelist.
int irplib_framelist_get_size(const irplib_framelist *self)
Get the size of a framelist.