00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031
00032
00033
00034
00035
00036 #include <string.h>
00037
00038 #include "visir_recipe.h"
00039 #include "irplib_flat.h"
00040
00041
00042
00043
00044
00045 #define PAFCOPY "^(DATE-OBS|ARCFILE|ESO TPL ID|ESO DET DIT|MJD-OBS)$"
00046 #define PAF_IMG "^(ESO INS FILT1 NAME|ESO INS PFOV)$"
00047 #define PAF_SPC "^(ESO INS FILT2 NAME|ESO INS RESOL|ESO INS SLIT1 WID" \
00048 "|ESO INS GRAT1 WLEN|ESO INS GRAT1 NAME)$"
00049
00050 #ifndef VISIR_IMG_FF_BORDER
00051 #define VISIR_IMG_FF_BORDER 64
00052 #endif
00053
00054
00055 #define visir_ff_mode_default (1<<0)
00056 #define visir_ff_mode_spc (1<<1)
00057 #define visir_ff_mode_tech (1<<2)
00058
00059 #define RECIPE_STRING "visir_img_ff"
00060
00061
00062
00063
00064
00065 static cpl_imagelist * visir_img_ff_reduce(const irplib_framelist *);
00066
00067 static cpl_error_code visir_img_ff_qc(cpl_propertylist *,
00068 cpl_propertylist *,
00069 const irplib_framelist *);
00070
00071 static cpl_error_code visir_img_ff_save(cpl_frameset *,
00072 const cpl_parameterlist *,
00073 const cpl_propertylist *,
00074 const cpl_propertylist *,
00075 const cpl_imagelist *,
00076 const cpl_image *);
00077
00078 VISIR_RECIPE_DEFINE(visir_img_ff, VISIR_PARAM_LOWLIM | VISIR_PARAM_HIGHLIM,
00079 "Flat field recipe",
00080 "This recipe computes the flatfield.\n"
00081 "The files listed in the Set Of Frames (sof-file) must be "
00082 "tagged either\n"
00083 "VISIR-flatfield-raw-file.fits " VISIR_IMG_FF_RAW " or\n"
00084 "VISIR-flatfield-raw-file.fits " VISIR_IMG_TECH_FF_RAW
00085 " or\n"
00086 "VISIR-flatfield-raw-file.fits " VISIR_SPC_FF_RAW " or\n"
00087 "VISIR-flatfield-raw-file.fits " VISIR_SPC_TECH_FF_RAW "\n"
00088 "\n"
00089 "The corresponding primary product will have a FITS card\n"
00090 "'HIERARCH ESO PRO CATG' with a value of\n"
00091 VISIR_IMG_FF_PROCATG " or\n"
00092 VISIR_IMG_TECH_FF_PROCATG " or\n"
00093 VISIR_SPC_FF_PROCATG " or\n"
00094 VISIR_SPC_TECH_FF_PROCATG
00095 "\n");
00096
00097
00098
00099
00100
00101 const unsigned visir_img_ff_border = VISIR_IMG_FF_BORDER;
00102
00103 enum _visir_ff_mode_ {
00104 visir_ff_none = 0,
00105 visir_ff_img = visir_ff_mode_default,
00106 visir_ff_spc = visir_ff_mode_default | visir_ff_mode_spc,
00107 visir_ff_img_tech = visir_ff_mode_default | visir_ff_mode_tech,
00108 visir_ff_spc_tech = visir_ff_mode_default | visir_ff_mode_tech
00109 | visir_ff_mode_spc
00110 };
00111
00112 typedef enum _visir_ff_mode_ visir_ff_mode;
00113
00114 static struct {
00115
00116 visir_ff_mode img_mode;
00117 double bpm_lo_thresh;
00118 double bpm_hi_thresh;
00119
00120 const char * procatg_ff;
00121 const char * procatg_bpm;
00122 int bpm_nb_bad;
00123 cpl_boolean is_lamp;
00124 double fp_noise;
00125 double lamp_flux;
00126
00127 } visir_img_ff_config;
00128
00129
00133
00134
00135
00136
00137
00138
00145
00146 static int visir_img_ff(cpl_frameset * framelist,
00147 const cpl_parameterlist * parlist)
00148 {
00149 irplib_framelist * allframes = NULL;
00150 irplib_framelist * rawframes = NULL;
00151 cpl_propertylist * qclist = cpl_propertylist_new();
00152 cpl_propertylist * paflist = cpl_propertylist_new();
00153 cpl_imagelist * flat = NULL;
00154 cpl_image * bpm_int = NULL;
00155 cpl_mask * bpm = NULL;
00156
00157
00158
00159 visir_img_ff_config.bpm_lo_thresh =
00160 visir_parameterlist_get_double(parlist, RECIPE_STRING, VISIR_PARAM_LOWLIM);
00161 visir_img_ff_config.bpm_hi_thresh =
00162 visir_parameterlist_get_double(parlist, RECIPE_STRING, VISIR_PARAM_HIGHLIM);
00163
00164 skip_if (0);
00165
00166
00167 skip_if (visir_dfs_set_groups(framelist));
00168
00169
00170 allframes = irplib_framelist_cast(framelist);
00171 skip_if(allframes == NULL);
00172 rawframes = irplib_framelist_extract_regexp(allframes, "^(" VISIR_IMG_FF_RAW
00173 "|" VISIR_IMG_TECH_FF_RAW
00174 "|" VISIR_SPC_TECH_FF_RAW
00175 "|" VISIR_SPC_FF_RAW ")$",
00176 CPL_FALSE);
00177 skip_if (rawframes == NULL);
00178 irplib_framelist_empty(allframes);
00179
00180 skip_if(irplib_framelist_load_propertylist_all(rawframes, 0,
00181 visir_property_regexp,
00182 CPL_FALSE));
00183
00184 skip_if(visir_dfs_check_framelist_tag(rawframes));
00185
00186
00187 visir_img_ff_config.img_mode = visir_ff_none;
00188 if (cpl_frameset_find(framelist, VISIR_IMG_FF_RAW)) {
00189 visir_img_ff_config.img_mode = visir_ff_img;
00190 visir_img_ff_config.procatg_ff = VISIR_IMG_FF_PROCATG;
00191 visir_img_ff_config.procatg_bpm = VISIR_IMG_FF_BPM_PROCATG;
00192 }
00193 if (cpl_frameset_find(framelist, VISIR_SPC_FF_RAW)) {
00194 skip_if (visir_img_ff_config.img_mode);
00195 visir_img_ff_config.img_mode = visir_ff_spc;
00196 visir_img_ff_config.procatg_ff = VISIR_SPC_FF_PROCATG;
00197 visir_img_ff_config.procatg_bpm = VISIR_SPC_FF_BPM_PROCATG;
00198 }
00199 if (cpl_frameset_find(framelist, VISIR_IMG_TECH_FF_RAW)) {
00200 skip_if (visir_img_ff_config.img_mode);
00201 visir_img_ff_config.img_mode = visir_ff_img_tech;
00202 visir_img_ff_config.procatg_ff = VISIR_IMG_TECH_FF_PROCATG;
00203 visir_img_ff_config.procatg_bpm = VISIR_IMG_TECH_FF_BPM_PROCATG;
00204 }
00205 if (cpl_frameset_find(framelist, VISIR_SPC_TECH_FF_RAW)) {
00206 skip_if (visir_img_ff_config.img_mode);
00207 visir_img_ff_config.img_mode = visir_ff_spc_tech;
00208 visir_img_ff_config.procatg_ff = VISIR_SPC_TECH_FF_PROCATG;
00209 visir_img_ff_config.procatg_bpm = VISIR_SPC_TECH_FF_BPM_PROCATG;
00210 }
00211
00212
00213 cpl_msg_info(cpl_func, "Compute the flatfield");
00214 if ((flat = visir_img_ff_reduce(rawframes)) == NULL) {
00215 cpl_msg_error(cpl_func, "Could not compute the flatfield image");
00216 skip_if(1);
00217 }
00218
00219
00220 cpl_msg_info(cpl_func, "Compute the bad pixels map");
00221 bpm = cpl_mask_threshold_image_create(cpl_imagelist_get(flat, 0),
00222 visir_img_ff_config.bpm_lo_thresh,
00223 visir_img_ff_config.bpm_hi_thresh);
00224 if (bpm == NULL) {
00225 cpl_msg_error(cpl_func, "Could not compute the bad pixel map");
00226 skip_if(1);
00227 }
00228 skip_if (cpl_mask_not(bpm));
00229 visir_img_ff_config.bpm_nb_bad = cpl_mask_count(bpm);
00230 bpm_int = cpl_image_new_from_mask(bpm);
00231
00232
00233 skip_if (cpl_image_threshold(cpl_imagelist_get(flat, 0),
00234 visir_img_ff_config.bpm_lo_thresh,
00235 visir_img_ff_config.bpm_hi_thresh,
00236 1.0, 1.0));
00237
00238 skip_if (visir_img_ff_qc(qclist, paflist, rawframes));
00239 irplib_framelist_empty(rawframes);
00240
00241 skip_if (visir_img_ff_save(framelist, parlist, qclist, paflist, flat,
00242 bpm_int));
00243
00244 end_skip;
00245
00246 cpl_propertylist_delete(paflist);
00247 cpl_propertylist_delete(qclist);
00248 irplib_framelist_delete(allframes);
00249 irplib_framelist_delete(rawframes);
00250 cpl_imagelist_delete(flat);
00251 cpl_mask_delete(bpm);
00252 cpl_image_delete(bpm_int);
00253
00254 return cpl_error_get_code();
00255 }
00256
00257
00263
00264 static cpl_imagelist * visir_img_ff_reduce(const irplib_framelist * rawframes)
00265 {
00266 cpl_imagelist * iset = NULL;
00267 cpl_imagelist * fitted = NULL;
00268 cpl_image * diff = NULL;
00269 cpl_image * prev = NULL;
00270 cpl_image * image = NULL;
00271 const cpl_propertylist * plist;
00272 const char * sval;
00273
00274
00275 bug_if (0);
00276 bug_if (rawframes == NULL);
00277
00278 plist = irplib_framelist_get_propertylist_const(rawframes, 0);
00279 bug_if(plist == NULL);
00280
00281
00282 sval = irplib_pfits_get_dpr_type(plist);
00283 skip_if (sval == NULL);
00284 visir_img_ff_config.is_lamp
00285 = strstr(sval, "SKY") == NULL ? CPL_TRUE : CPL_FALSE;
00286
00287
00288 iset = irplib_imagelist_load_framelist(rawframes, CPL_TYPE_FLOAT, 0, 0);
00289 skip_if (iset == NULL);
00290
00291
00292 fitted = irplib_flat_fit_set(iset, 1);
00293
00294 skip_if (fitted == NULL);
00295
00296 if (visir_img_ff_config.is_lamp) {
00297
00298 double std_diff[3];
00299 double upright_x, upright_y;
00300 int i;
00301
00302 upright_x = cpl_image_get_size_x(cpl_imagelist_get(iset, 0));
00303 upright_y = cpl_image_get_size_y(cpl_imagelist_get(iset, 0));
00304 upright_x -= visir_img_ff_border;
00305 upright_y -= visir_img_ff_border;
00306 skip_if(upright_x <= visir_img_ff_border);
00307 skip_if(upright_y <= visir_img_ff_border);
00308
00309 for (i=0; i < 4 && i < cpl_imagelist_get_size(iset); i++) {
00310
00311 double noise;
00312
00313
00314 cpl_image_delete(prev);
00315 prev = image;
00316 image = cpl_image_extract(cpl_imagelist_get(iset, i),
00317 visir_img_ff_border,
00318 visir_img_ff_border,
00319 upright_x,
00320 upright_y);
00321 bug_if (image == NULL);
00322
00323 if (i == 0) continue;
00324
00325 diff = cpl_image_subtract_create(prev, image);
00326 bug_if (diff == NULL);
00327
00328 bug_if(cpl_flux_get_noise_window(diff, NULL, -1, -1,
00329 &noise, NULL));
00330
00331 std_diff[i-1] = noise * noise;
00332
00333 cpl_msg_debug(cpl_func, "SQ-Noise(%d): %g", i, std_diff[i-1]);
00334
00335 if (i == 1) {
00336 const double median = cpl_image_get_median(diff);
00337 const double ditval = visir_pfits_get_dit(plist);
00338
00339 skip_if (0);
00340 skip_if (ditval <= 0.0);
00341
00342 visir_img_ff_config.lamp_flux = median / ditval;
00343 cpl_msg_info(cpl_func, "Lamp Flux: %g",
00344 visir_img_ff_config.lamp_flux);
00345 }
00346
00347 cpl_image_delete(diff);
00348 diff = NULL;
00349
00350 }
00351
00352 if (i == 4) {
00353
00354
00355 const double square = std_diff[0] - std_diff[1] - std_diff[2];
00356 visir_img_ff_config.fp_noise = square > 0.0 ? sqrt(square) : 0.0;
00357
00358 cpl_msg_info(cpl_func, "Noise: %g",
00359 visir_img_ff_config.fp_noise);
00360
00361 }
00362 }
00363
00364 end_skip;
00365
00366 cpl_image_delete(diff);
00367 cpl_image_delete(image);
00368 cpl_image_delete(prev);
00369 cpl_imagelist_delete(iset);
00370
00371 return fitted;
00372 }
00373
00374
00375
00383
00384 static cpl_error_code visir_img_ff_qc(cpl_propertylist * qclist,
00385 cpl_propertylist * paflist,
00386 const irplib_framelist * rawframes)
00387 {
00388
00389 const cpl_propertylist * reflist
00390 = irplib_framelist_get_propertylist_const(rawframes, 0);
00391
00392 bug_if (0);
00393
00394
00395 skip_if (visir_qc_append_capa(qclist, rawframes));
00396
00397
00398 bug_if(cpl_propertylist_append_int(qclist, "ESO QC NBBADPIX",
00399 visir_img_ff_config.bpm_nb_bad));
00400
00401 if (visir_img_ff_config.is_lamp) {
00402 bug_if(cpl_propertylist_append_double(qclist, "ESO QC FPNOISE",
00403 visir_img_ff_config.fp_noise));
00404 bug_if(cpl_propertylist_append_double(qclist, "ESO QC LAMPFLUX",
00405 visir_img_ff_config.lamp_flux));
00406 }
00407
00408 bug_if (cpl_propertylist_append(paflist, qclist));
00409
00410 bug_if (cpl_propertylist_copy_property_regexp(paflist, reflist,
00411 (visir_img_ff_config.img_mode & visir_ff_mode_spc)
00412 ? PAFCOPY "|" PAF_SPC : PAFCOPY "|" PAF_IMG, 0));
00413
00414
00415 bug_if (cpl_propertylist_append_string(paflist, CPL_DFS_PRO_CATG,
00416 visir_img_ff_config.procatg_ff));
00417
00418 bug_if (cpl_propertylist_copy_property_regexp(qclist, reflist,
00419 "^(" VISIR_PFITS_FF_COPY
00420 ")$", 0));
00421
00422 bug_if (irplib_pfits_set_airmass(qclist, rawframes));
00423
00424 end_skip;
00425
00426 return cpl_error_get_code();
00427
00428 }
00429
00430
00431
00442
00443 static cpl_error_code visir_img_ff_save(cpl_frameset * set,
00444 const cpl_parameterlist * parlist,
00445 const cpl_propertylist * qclist,
00446 const cpl_propertylist * paflist,
00447 const cpl_imagelist * flat,
00448 const cpl_image * bpm)
00449 {
00450
00451 skip_if (irplib_dfs_save_image(set, parlist, set,
00452 cpl_imagelist_get_const(flat, 0),
00453 CPL_BPP_IEEE_FLOAT, RECIPE_STRING,
00454 visir_img_ff_config.procatg_ff, qclist, NULL,
00455 visir_pipe_id, RECIPE_STRING CPL_DFS_FITS));
00456
00457
00458 skip_if (irplib_dfs_save_image(set, parlist, set, bpm, CPL_BPP_32_SIGNED,
00459 RECIPE_STRING, visir_img_ff_config.procatg_bpm,
00460 qclist, NULL, visir_pipe_id,
00461 RECIPE_STRING "_bpm" CPL_DFS_FITS));
00462
00463 #ifdef VISIR_SAVE_PAF
00464 skip_if (cpl_dfs_save_paf("VISIR", RECIPE_STRING, paflist,
00465 RECIPE_STRING CPL_DFS_PAF));
00466 #else
00467 bug_if(paflist == NULL);
00468 #endif
00469
00470 end_skip;
00471
00472 return cpl_error_get_code();
00473
00474 }