IIINSTRUMENT Pipeline Reference Manual 4.4.12
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
54static cpl_error_code naco_img_detlin_load(cpl_imagelist *, cpl_vector *,
55 const cpl_parameterlist *,
56 const irplib_framelist *,
57 const irplib_framelist *);
58
59static cpl_image * naco_img_detlin_limit(const cpl_imagelist *);
60static cpl_image * naco_img_detlin_bpm(const cpl_imagelist *,
61 const cpl_vector *,
62 const cpl_image *);
63
64static cpl_error_code naco_img_detlin_dit_diff(cpl_vector *);
65
66static 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
73static cpl_imagelist * naco_imagelist_fit_polynomial(const cpl_imagelist *,
74 const double *, int);
75
76NACO_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/*----------------------------------------------------------------------------*/
103static 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/*----------------------------------------------------------------------------*/
224static 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
277 = irplib_framelist_get_propertylist_const(lamps, i);
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/*----------------------------------------------------------------------------*/
363static 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/*----------------------------------------------------------------------------*/
427static 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/*----------------------------------------------------------------------------*/
469static 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/*----------------------------------------------------------------------------*/
568static 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/*----------------------------------------------------------------------------*/
663static 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_free(pv); /* Free explicitly - to avoid cppcheck false positive */
773 (void)cpl_matrix_unwrap(mv);
774 (void)cpl_matrix_unwrap(mb);
775
776 if (nsing == npix) {
777 cpl_imagelist_delete(fitres);
778 cpl_ensure(0, CPL_ERROR_SINGULAR_MATRIX, NULL);
779 }
780
781
782 } while (0);
783
784
785 return fitres;
786}
int naco_dfs_set_groups(cpl_frameset *set)
Set the group as RAW or CALIB in a frameset.
Definition: naco_dfs.c:62
cpl_boolean naco_parameterlist_get_bool(const cpl_parameterlist *self, const char *recipe, naco_parameter bitmask)
Retrieve the value of a NACO boolean parameter.
double naco_pfits_get_dit(const cpl_propertylist *self)
find out the DIT
Definition: naco_pfits.c:131