36 #include "naco_recipe.h"
42 #define RECIPE_STRING "naco_img_detlin"
44 #define DETLIN_LIMIT 0.75
45 #define DETLIN_STABILITY 1/100.0
47 #define DETLIN_MAX_GRAD 1.5
48 #define DETLIN_MAX_RESI 10.0
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 *);
59 static cpl_image * naco_img_detlin_limit(
const cpl_imagelist *);
60 static cpl_image * naco_img_detlin_bpm(
const cpl_imagelist *,
64 static cpl_error_code naco_img_detlin_dit_diff(cpl_vector *);
66 static cpl_error_code naco_img_detlin_save(cpl_frameset *,
67 const cpl_parameterlist *,
68 const cpl_propertylist *,
69 const cpl_imagelist *,
73 static cpl_imagelist * naco_imagelist_fit_polynomial(
const cpl_imagelist *,
76 NACO_RECIPE_DEFINE(naco_img_detlin,
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");
103 static int naco_img_detlin(cpl_frameset * framelist,
104 const cpl_parameterlist * parlist)
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);
114 cpl_imagelist * fitres = NULL;
115 cpl_image * bpm = NULL;
116 cpl_image * residual = NULL;
123 skip_if(allframes == NULL);
126 skip_if (darkframes == NULL);
129 skip_if (lampframes == NULL);
132 cpl_msg_info(cpl_func,
"Load the data");
134 NACO_PFITS_REGEXP_DETLIN_FIRST
138 NACO_PFITS_REGEXP_DETLIN
143 NACO_PFITS_REGEXP_DETLIN
146 skip_if (naco_img_detlin_load(iset, ditval, parlist, lampframes,
150 bug_if (cpl_propertylist_copy_property_regexp(qclist, reflist,
"^("
151 NACO_PFITS_REGEXP_DETLIN_COPY
160 cpl_msg_info(cpl_func,
"Compute the linearity limit");
161 lin_limit = naco_img_detlin_limit(iset);
162 skip_if (lin_limit == NULL);
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),
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);
176 bug_if (cpl_imagelist_set(fitres, residual, 4));
179 fitres = naco_imagelist_fit_polynomial(iset, cpl_vector_get_data(ditval), 4);
180 skip_if (fitres == NULL);
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);
193 cpl_msg_info(cpl_func,
"Save the products");
194 skip_if (naco_img_detlin_save(framelist, parlist, qclist, fitres,
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);
210 return cpl_error_get_code();
224 static cpl_error_code naco_img_detlin_load(cpl_imagelist * lamplist,
226 const cpl_parameterlist * parlist,
227 const irplib_framelist * lamps,
228 const irplib_framelist * darks)
230 cpl_image * imlamp = NULL;
231 cpl_image * imdark = NULL;
232 double refmean, refdit;
233 double dit_min, dit_max;
243 bug_if (lamplist == NULL);
244 bug_if (darks == NULL);
245 bug_if (ditval == NULL);
247 skip_if_lt(nb_lamps, 3,
"lamp images");
253 cpl_msg_info(cpl_func,
"Checking DIT consistency");
256 CPL_TYPE_DOUBLE, CPL_FALSE, 0.0));
259 CPL_TYPE_DOUBLE, CPL_FALSE, 0.0));
262 cpl_msg_info(cpl_func,
"Compute the differences lamp - dark");
265 cpl_msg_info(cpl_func,
"Check the lamp stability");
267 bug_if(cpl_vector_set_size(ditval, nb_lamps));
268 refmean = refdit = dit_max = dit_min = 0.0;
269 for (i=0 ; i < nb_lamps ; i++) {
270 const char * lampname
272 const char * darkname
276 const cpl_propertylist * plist
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);
295 irplib_check(imlamp = cpl_image_load(lampname, CPL_TYPE_FLOAT, 0, 0),
296 "Could not load FITS-image from %s", lampname);
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);
302 bug_if (cpl_image_subtract(imlamp, imdark));
305 if (i > 0 && dit_lamp != refdit) {
306 bug_if(cpl_imagelist_set(lamplist, imlamp, dit_var));
308 bug_if(cpl_vector_set(ditval, dit_var, dit_lamp));
310 if (dit_lamp > dit_max) dit_max = dit_lamp;
311 if (dit_lamp < dit_min) dit_min = dit_lamp;
313 const double mean = cpl_image_get_mean(imlamp);
315 cpl_image_delete(imlamp);
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));
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));
337 skip_if_lt(i - dit_var, 2,
"lamp frames for stability check");
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);
346 bug_if(cpl_vector_set_size(ditval, dit_var));
350 cpl_image_delete(imlamp);
351 cpl_image_delete(imdark);
353 return cpl_error_get_code();
363 static cpl_image * naco_img_detlin_limit(
const cpl_imagelist * iset)
365 cpl_image * lin_limit = NULL;
370 float ref_diff, cur_diff;
374 if (cpl_error_get_code())
return NULL;
376 skip_if_lt(cpl_imagelist_get_size(iset), 3,
"images to compute the "
377 "detector linearity limit");
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));
384 lin_limit = cpl_image_new(size_x, size_y, CPL_TYPE_FLOAT);
386 skip_if (lin_limit == NULL);
388 plin_limit = cpl_image_get_data_float(lin_limit);
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) {
405 plin_limit[i] = pim1[i];
409 if (j+1 == cpl_imagelist_get_size(iset)-1)
410 plin_limit[i] = (float)0.0;
427 static cpl_error_code naco_img_detlin_dit_diff(cpl_vector *
self)
434 bug_if(
self == NULL);
436 dits = cpl_vector_get_data(
self);
438 for (i = cpl_vector_get_size(
self)-1; i > 0 ; i--) {
439 dits[i] -= dits[i-1];
441 if (dits[i] == 0.0)
break;
446 cpl_msg_error(cpl_func,
"Consecutive (%d and %d) DITS are equal: "
447 "%g", i-1, i, dits[i-1]);
449 cpl_error_set(cpl_func, CPL_ERROR_ILLEGAL_INPUT);
455 return cpl_error_get_code();
469 static cpl_image * naco_img_detlin_bpm(
const cpl_imagelist * iset,
470 const cpl_vector * ditdiff,
471 const cpl_image * err_im)
473 cpl_image * imdiff = NULL;
474 cpl_image * bpm = NULL;
476 const double * perr_im;
480 const double * ditval = cpl_vector_get_data_const(ditdiff);
481 float dit_ref, curr_val;
487 skip_if_lt(cpl_imagelist_get_size(iset), 3,
"images to compute the "
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));
497 bpm = cpl_image_new(size_x, size_y, CPL_TYPE_INT);
499 pbpm = cpl_image_get_data_int(bpm);
501 imdiff = cpl_image_new(size_x, 1, CPL_TYPE_FLOAT);
503 pimdiff = cpl_image_get_data_float(imdiff);
506 dit_ref = (float)ditval[1];
507 perr_im = cpl_image_get_data_double_const(err_im);
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));
513 for (i=0 ; i < size_x ; i++, ii++) {
514 const float fdiff = pim1[ii] - pim2[ii];
519 if (fdiff * dit_ref < 0.0) pbpm[ii] |= 2;
522 if (perr_im[ii] > DETLIN_MAX_RESI) pbpm[ii] |= 4;
525 for (k=1 ; k < cpl_imagelist_get_size(iset)-1 ; k++) {
526 const float dit_diff = ditval[k+1] * DETLIN_MAX_GRAD;
529 pim1 = cpl_image_get_data_float_const(
530 cpl_imagelist_get_const(iset, k+1));
533 for (i=0 ; i < size_x ; i++, ii++) {
534 if ((pbpm[ii] & 1) == 0) {
536 const float fdiff = pimdiff[i];
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)) {
551 cpl_image_delete(imdiff);
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)
580 cpl_imagelist_get_const(fitres, 0),
581 CPL_BPP_IEEE_FLOAT, RECIPE_STRING,
582 NACO_IMG_DETLIN_A, qclist, NULL,
584 RECIPE_STRING
"_A" CPL_DFS_FITS));
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));
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));
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));
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));
616 RECIPE_STRING, NACO_IMG_DETLIN_LIM, qclist, NULL,
618 RECIPE_STRING
"_limit" CPL_DFS_FITS));
622 RECIPE_STRING, NACO_IMG_DETLIN_BPM, qclist, NULL,
624 RECIPE_STRING
"_bpm" CPL_DFS_FITS));
628 return cpl_error_get_code();
663 static cpl_imagelist * naco_imagelist_fit_polynomial(
664 const cpl_imagelist * ilist,
668 cpl_imagelist * fitres;
669 const cpl_image * image;
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);
677 ni = cpl_imagelist_get_size(ilist);
678 cpl_ensure(ni >= deg, CPL_ERROR_INCOMPATIBLE_INPUT, NULL);
680 image = cpl_imagelist_get_const(ilist, 0);
682 cpl_ensure(cpl_image_get_type(image) == CPL_TYPE_FLOAT,
683 CPL_ERROR_TYPE_MISMATCH, NULL);
685 nx = cpl_image_get_size_x(image);
686 ny = cpl_image_get_size_y(image);
697 const int npix = nx * ny;
700 cpl_errorstate prestate = cpl_errorstate_get();
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),
711 pv = cpl_malloc(ni * deg *
sizeof(
double));
712 mv = cpl_matrix_wrap(ni, deg, pv);
716 mb = cpl_matrix_wrap(ni, 1, (
double*)dit);
719 for (i=0; i < npix; i++) {
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];
725 for (k=1; k < deg; k++) {
727 pv[deg * j + k] = f_prod;
734 mx = cpl_matrix_solve_normal(mv, mb);
737 cpl_errorstate_set(prestate);
738 for (k=0; k < deg+1; k++) {
740 cpl_image_get_data_double(cpl_imagelist_get(fitres,k));
746 const double * px = cpl_matrix_get_data(mx);
749 for (k=0; k < deg; k++) {
750 pimad = cpl_image_get_data_double(
751 cpl_imagelist_get(fitres, k));
757 for (j=0; j < ni; j++) {
761 for (k=0; k < deg; k++)
762 err -= px[k] * pv[deg * j + k];
765 sq_err /= (double)ni;
766 pimad=cpl_image_get_data_double(cpl_imagelist_get(fitres, deg));
768 cpl_matrix_delete(mx);
772 cpl_matrix_delete(mv);
773 (void)cpl_matrix_unwrap(mb);
776 cpl_imagelist_delete(fitres);
777 cpl_ensure(0, CPL_ERROR_SINGULAR_MATRIX, NULL);
double naco_pfits_get_dit(const cpl_propertylist *self)
find out the DIT
int naco_dfs_set_groups(cpl_frameset *set)
Set the group as RAW or CALIB in a frameset.
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.
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.