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 "visir_recipe.h"
00037
00038
00039
00040
00041
00042 #define RECIPE_STRING "visir_img_dark"
00043
00044
00045
00046
00047
00048
00049 static cpl_error_code visir_img_dark_reduce(cpl_propertylist *,
00050 const irplib_framelist *,
00051 cpl_image **, cpl_mask **,
00052 cpl_mask **, cpl_mask **);
00053
00054 static cpl_error_code visir_img_dark_save(cpl_frameset *,
00055 const cpl_parameterlist *,
00056 const cpl_propertylist *,
00057 const cpl_image *, const cpl_mask *,
00058 const cpl_mask *, const cpl_mask *,
00059 int, const irplib_framelist *);
00060
00061 static char * visir_img_dark_make_tag(const cpl_frame*,
00062 const cpl_propertylist *, int);
00063
00064 VISIR_RECIPE_DEFINE(visir_img_dark,
00065 VISIR_PARAM_REJBORD |
00066 VISIR_PARAM_HOT_LIM |
00067 VISIR_PARAM_COLD_LIM |
00068 VISIR_PARAM_DEV_LIM |
00069 VISIR_PARAM_NSAMPLES |
00070 VISIR_PARAM_HALFSIZE,
00071 "Dark recipe",
00072 "This recipe computes the dark.\n"
00073 "The files listed in the Set Of Frames (sof-file) must be "
00074 "tagged either\n"
00075 "VISIR-dark-image-raw-file.fits " VISIR_IMG_DARK_RAW " or\n"
00076 "VISIR-dark-spectro-raw-file.fits " VISIR_SPC_DARK_RAW "\n"
00077 "\n"
00078 "The corresponding four products will each have a FITS "
00079 "card\n'HIERARCH ESO PRO CATG' with values (for imaging)\n"
00080 VISIR_IMG_DARK_AVG_PROCATG "\n"
00081 VISIR_IMG_DARK_HOT_PROCATG "\n"
00082 VISIR_IMG_DARK_COLD_PROCATG "\n"
00083 VISIR_IMG_DARK_DEV_PROCATG "\n"
00084 " or (for spectroscopy)\n"
00085 VISIR_SPC_DARK_AVG_PROCATG "\n"
00086 VISIR_SPC_DARK_HOT_PROCATG "\n"
00087 VISIR_SPC_DARK_COLD_PROCATG "\n"
00088 VISIR_SPC_DARK_DEV_PROCATG "\n");
00089
00090
00091
00092
00093
00094 enum _visir_dark_mode_ {
00095 visir_dark_none = 0,
00096 visir_dark_img,
00097 visir_dark_spc
00098 };
00099
00100 typedef enum _visir_dark_mode_ visir_dark_mode;
00101
00102 static struct {
00103
00104 visir_dark_mode mode;
00105 int rej_left;
00106 int rej_right;
00107 int rej_bottom;
00108 int rej_top;
00109 double hot_thresh;
00110 double cold_thresh;
00111 double dev_thresh;
00112 int hsize;
00113 int nsamples;
00114 } visir_img_dark_config;
00115
00116
00120
00121
00122
00123
00124
00125
00126
00127
00134
00135 static int visir_img_dark(cpl_frameset * framelist,
00136 const cpl_parameterlist * parlist)
00137 {
00138 irplib_framelist* allframes = NULL;
00139 irplib_framelist* rawframes = NULL;
00140 const char ** taglist = NULL;
00141 const char * rej_bord;
00142 const char * orgtag = NULL;
00143 irplib_framelist* f_one = NULL;
00144 cpl_imagelist * i_one = NULL;
00145 cpl_image * avg = NULL;
00146 cpl_mask * hot = NULL;
00147 cpl_mask * cold = NULL;
00148 cpl_mask * dev = NULL;
00149 cpl_propertylist * qclist = cpl_propertylist_new();
00150 int nsets;
00151 int i;
00152 int nb_good = 0;
00153
00154
00155
00156 rej_bord = visir_parameterlist_get_string(parlist, RECIPE_STRING,
00157 VISIR_PARAM_REJBORD);
00158 skip_if (0);
00159 skip_if (sscanf(rej_bord, "%d %d %d %d",
00160 &visir_img_dark_config.rej_left,
00161 &visir_img_dark_config.rej_right,
00162 &visir_img_dark_config.rej_bottom,
00163 &visir_img_dark_config.rej_top) != 4);
00164
00165 visir_img_dark_config.hot_thresh =
00166 visir_parameterlist_get_double(parlist, RECIPE_STRING,
00167 VISIR_PARAM_HOT_LIM);
00168 visir_img_dark_config.dev_thresh =
00169 visir_parameterlist_get_double(parlist, RECIPE_STRING,
00170 VISIR_PARAM_DEV_LIM);
00171 visir_img_dark_config.cold_thresh =
00172 visir_parameterlist_get_double(parlist, RECIPE_STRING,
00173 VISIR_PARAM_COLD_LIM);
00174 visir_img_dark_config.hsize =
00175 visir_parameterlist_get_int(parlist, RECIPE_STRING, VISIR_PARAM_HALFSIZE);
00176 visir_img_dark_config.nsamples =
00177 visir_parameterlist_get_int(parlist, RECIPE_STRING, VISIR_PARAM_NSAMPLES);
00178
00179 skip_if (0);
00180
00181
00182 skip_if (visir_dfs_set_groups(framelist));
00183
00184 allframes = irplib_framelist_cast(framelist);
00185 skip_if(allframes == NULL);
00186
00187 rawframes = irplib_framelist_extract_regexp(allframes,
00188 "^(" VISIR_IMG_DARK_RAW
00189 "|" VISIR_SPC_DARK_RAW ")$",
00190 CPL_FALSE);
00191 skip_if(rawframes == NULL);
00192
00193
00194 visir_img_dark_config.mode = visir_dark_none;
00195 if (cpl_frameset_find(framelist, VISIR_IMG_DARK_RAW)) {
00196 visir_img_dark_config.mode = visir_dark_img;
00197 orgtag = VISIR_IMG_DARK_RAW;
00198 }
00199 if (cpl_frameset_find(framelist, VISIR_SPC_DARK_RAW)) {
00200 skip_if (visir_img_dark_config.mode);
00201 visir_img_dark_config.mode = visir_dark_spc;
00202 orgtag = VISIR_SPC_DARK_RAW;
00203 }
00204
00205 bug_if(visir_img_dark_config.mode == visir_dark_none);
00206
00207 skip_if(irplib_framelist_load_propertylist_all(rawframes, 0, "^("
00208 VISIR_PFITS_REGEXP_DARK "|"
00209 VISIR_PFITS_REGEXP_DARK_PAF
00210 ")$", CPL_FALSE));
00211
00212 skip_if(visir_dfs_check_framelist_tag(rawframes));
00213
00214 taglist = visir_framelist_set_tag(rawframes, visir_img_dark_make_tag, &nsets);
00215 skip_if(taglist == NULL);
00216
00217 cpl_msg_info(cpl_func, "Identified %d setting(s) in %d frames",
00218 nsets, irplib_framelist_get_size(rawframes));
00219
00220
00221 for (i=0 ; i < nsets ; i++) {
00222
00223
00224 f_one = irplib_framelist_extract(rawframes, taglist[i]);
00225
00226
00227 skip_if(irplib_framelist_set_tag_all(f_one, orgtag));
00228
00229 cpl_msg_info(cpl_func, "Reducing frame set %d of %d (size=%d) with "
00230 "setting: %s", i+1, nsets,
00231 irplib_framelist_get_size(f_one), taglist[i]);
00232
00233 skip_if (f_one == NULL);
00234
00235
00236 if (irplib_framelist_get_size(f_one) < 2) {
00237 cpl_msg_warning(cpl_func, "Setting %d skipped (Need at least 2 "
00238 "frames)", i+1);
00239 irplib_framelist_delete(f_one);
00240 f_one = NULL;
00241 continue;
00242 }
00243
00244 skip_if(visir_img_dark_reduce(qclist, f_one, &avg, &hot, &cold, &dev));
00245
00246
00247 skip_if (visir_img_dark_save(framelist, parlist, qclist, avg, hot,
00248 cold, dev, i+1, f_one));
00249
00250 nb_good++;
00251
00252 cpl_image_delete(avg);
00253 cpl_mask_delete(hot);
00254 cpl_mask_delete(cold);
00255 cpl_mask_delete(dev);
00256 irplib_framelist_delete(f_one);
00257 cpl_propertylist_empty(qclist);
00258 avg = NULL;
00259 cold = NULL;
00260 hot = NULL;
00261 dev = NULL;
00262 f_one = NULL;
00263 }
00264
00265 skip_if (nb_good == 0);
00266
00267 end_skip;
00268
00269 cpl_imagelist_delete(i_one);
00270 cpl_free(taglist);
00271 cpl_image_delete(avg);
00272 cpl_mask_delete(hot);
00273 cpl_mask_delete(cold);
00274 cpl_mask_delete(dev);
00275 irplib_framelist_delete(f_one);
00276 irplib_framelist_delete(allframes);
00277 irplib_framelist_delete(rawframes);
00278 cpl_propertylist_delete(qclist);
00279
00280 return cpl_error_get_code();
00281 }
00282
00283
00296
00297 static cpl_error_code visir_img_dark_reduce(cpl_propertylist * qclist,
00298 const irplib_framelist * f_one,
00299 cpl_image ** pavg, cpl_mask ** phot,
00300 cpl_mask ** pcold, cpl_mask ** pdev)
00301 {
00302
00303 cpl_image * dark = NULL;
00304 cpl_image * diff = NULL;
00305 char * ron_key = NULL;
00306 double rms;
00307 double lower, upper;
00308 double dark_med;
00309 double mean;
00310 int ndevpix;
00311 cpl_size zone[4];
00312 int coldpix_nb;
00313 int hotpix_nb;
00314 int nfiles;
00315 int i;
00316
00317 skip_if (f_one == NULL);
00318
00319 nfiles = irplib_framelist_get_size(f_one);
00320
00321 skip_if (nfiles < 2);
00322
00323 for (i=0 ; i < nfiles ; i++) {
00324 const cpl_frame * frame = irplib_framelist_get_const(f_one, i);
00325 const char * name = cpl_frame_get_filename(frame);
00326 cpl_size next = cpl_frame_get_nextensions(frame);
00327
00328 cpl_image_delete(diff);
00329 diff = dark;
00330 irplib_check(dark = cpl_image_load(name, CPL_TYPE_FLOAT, 0, next),
00331 "Could not load FITS-image from %s", name);
00332
00333 if (i == 0) {
00334 const int nx = cpl_image_get_size_x(dark);
00335 const int ny = cpl_image_get_size_y(dark);
00336
00337 zone[0] = visir_img_dark_config.rej_left+1;
00338 zone[1] = nx - visir_img_dark_config.rej_right;
00339 zone[2] = visir_img_dark_config.rej_bottom+1;
00340 zone[3] = ny - visir_img_dark_config.rej_top;
00341
00342 *pavg = cpl_image_duplicate(dark);
00343 skip_if(*pavg == NULL);
00344 } else {
00345 const cpl_propertylist * plist
00346 = irplib_framelist_get_propertylist_const(f_one, i-1);
00347 const int ndit = visir_pfits_get_ndit(plist);
00348 const char ron_format[] = "ESO QC RON%d";
00349 double ron;
00350
00351 skip_if(0);
00352
00353 irplib_ensure(ndit > 0, CPL_ERROR_ILLEGAL_INPUT,
00354 VISIR_PFITS_INT_NDIT " must be positive, not %d",
00355 ndit);
00356
00357 skip_if(cpl_image_subtract(diff, dark));
00358
00359
00360 irplib_check(cpl_flux_get_noise_window(diff, zone,
00361 visir_img_dark_config.hsize,
00362 visir_img_dark_config.nsamples,
00363 &rms, NULL),
00364 "Cannot compute the RON for difference between images "
00365 "%d and %d", i, i+1);
00366
00367
00368 ron = rms * sqrt(ndit/2.0);
00369
00370
00371 cpl_free(ron_key);
00372 ron_key = cpl_sprintf(ron_format, i);
00373
00374 bug_if(ron_key == NULL);
00375
00376 skip_if(cpl_propertylist_append_double(qclist, ron_key, ron));
00377
00378
00379 skip_if(cpl_image_add(*pavg, dark));
00380
00381 }
00382
00383 }
00384 cpl_image_delete(dark);
00385 dark = NULL;
00386
00387 mean = cpl_image_get_mean(diff);
00388
00389
00390
00391 lower = mean - rms * visir_img_dark_config.dev_thresh;
00392 upper = mean + rms * visir_img_dark_config.dev_thresh;
00393 cpl_mask_delete(*pdev);
00394 irplib_check(*pdev = cpl_mask_threshold_image_create(diff, lower, upper),
00395 "Cannot compute the deviant pixel map");
00396 cpl_image_delete(diff);
00397 diff = NULL;
00398
00399 skip_if (cpl_mask_not(*pdev));
00400 ndevpix = cpl_mask_count(*pdev);
00401 skip_if (0);
00402
00403
00404 skip_if(cpl_image_divide_scalar(*pavg, (double)nfiles));
00405
00406
00407 dark_med = cpl_image_get_median_window(*pavg, zone[0], zone[2], zone[1],
00408 zone[3]);
00409
00410 irplib_check (cpl_flux_get_noise_window(*pavg, zone,
00411 visir_img_dark_config.hsize,
00412 visir_img_dark_config.nsamples,
00413 &rms, NULL),
00414 "Cannot compute the RON of the master dark");
00415
00416 lower = dark_med - rms * visir_img_dark_config.cold_thresh;
00417 upper = dark_med + rms * visir_img_dark_config.hot_thresh;
00418
00419
00420 cpl_mask_delete(*pcold);
00421 irplib_check(*pcold = cpl_mask_threshold_image_create(*pavg, -FLT_MAX,
00422 lower),
00423 "Cannot compute the cold pixel map");
00424 coldpix_nb = cpl_mask_count(*pcold);
00425 skip_if (0);
00426
00427
00428 cpl_mask_delete(*phot);
00429 irplib_check(*phot = cpl_mask_threshold_image_create(*pavg, upper, DBL_MAX),
00430 "Cannot compute the hot pixel map");
00431 hotpix_nb = cpl_mask_count(*phot);
00432 skip_if (0);
00433
00434
00435
00436 skip_if(cpl_propertylist_append_double(qclist, "ESO QC DARKMED", dark_med));
00437 skip_if(cpl_propertylist_append_int(qclist, "ESO QC NBCOLPIX", coldpix_nb));
00438 skip_if(cpl_propertylist_append_int(qclist, "ESO QC NBHOTPIX", hotpix_nb));
00439 skip_if(cpl_propertylist_append_int(qclist, "ESO QC NBDEVPIX", ndevpix));
00440
00441 end_skip;
00442
00443 cpl_image_delete(dark);
00444 cpl_image_delete(diff);
00445 cpl_free(ron_key);
00446
00447 return cpl_error_get_code();
00448 }
00449
00450
00464
00465 static cpl_error_code visir_img_dark_save(cpl_frameset * set_tot,
00466 const cpl_parameterlist * parlist,
00467 const cpl_propertylist * qclist,
00468 const cpl_image * avg,
00469 const cpl_mask * hot,
00470 const cpl_mask * cold,
00471 const cpl_mask * dev,
00472 int set_nb,
00473 const irplib_framelist * f_one)
00474 {
00475 cpl_frameset * set = irplib_frameset_cast(f_one);
00476 const cpl_propertylist * plist
00477 = irplib_framelist_get_propertylist_const(f_one, 0);
00478 cpl_propertylist * paflist = cpl_propertylist_new();
00479 cpl_image * image = NULL;
00480 const char pafcopy[] = "^(" VISIR_PFITS_REGEXP_DARK_PAF ")$";
00481 char * filename = NULL;
00482 const char * procatg_avg;
00483 const char * procatg_dev;
00484 const char * procatg_hot;
00485 const char * procatg_cold;
00486
00487
00488
00489 skip_if (0);
00490
00491
00492 switch (visir_img_dark_config.mode) {
00493 case visir_dark_img:
00494 procatg_avg = VISIR_IMG_DARK_AVG_PROCATG;
00495 procatg_dev = VISIR_IMG_DARK_DEV_PROCATG;
00496 procatg_hot = VISIR_IMG_DARK_HOT_PROCATG;
00497 procatg_cold = VISIR_IMG_DARK_COLD_PROCATG;
00498 break;
00499 case visir_dark_spc:
00500 procatg_avg = VISIR_SPC_DARK_AVG_PROCATG;
00501 procatg_dev = VISIR_SPC_DARK_DEV_PROCATG;
00502 procatg_hot = VISIR_SPC_DARK_HOT_PROCATG;
00503 procatg_cold = VISIR_SPC_DARK_COLD_PROCATG;
00504 break;
00505 default:
00506 bug_if(1);
00507 }
00508
00509
00510
00511 filename = cpl_sprintf(RECIPE_STRING "_set%02d_avg" CPL_DFS_FITS,
00512 set_nb);
00513 skip_if (irplib_dfs_save_image(set_tot, parlist, set, avg, CPL_BPP_IEEE_FLOAT,
00514 RECIPE_STRING, procatg_avg, qclist, NULL,
00515 visir_pipe_id, filename));
00516
00517
00518 image = cpl_image_new_from_mask(hot);
00519 skip_if(0);
00520
00521 cpl_free(filename);
00522 filename = cpl_sprintf(RECIPE_STRING "_set%02d_hotpix" CPL_DFS_FITS,
00523 set_nb);
00524 skip_if (irplib_dfs_save_image(set_tot, parlist, set, image, CPL_BPP_32_SIGNED,
00525 RECIPE_STRING, procatg_hot, qclist, NULL,
00526 visir_pipe_id, filename));
00527 cpl_image_delete(image);
00528 image = NULL;
00529
00530
00531 image = cpl_image_new_from_mask(cold);
00532 skip_if(0);
00533
00534 cpl_free(filename);
00535 filename = cpl_sprintf(RECIPE_STRING "_set%02d_coldpix" CPL_DFS_FITS,
00536 set_nb);
00537 skip_if (irplib_dfs_save_image(set_tot, parlist, set, image, CPL_BPP_32_SIGNED,
00538 RECIPE_STRING, procatg_cold, qclist, NULL,
00539 visir_pipe_id, filename));
00540 cpl_image_delete(image);
00541 image = NULL;
00542
00543
00544 image = cpl_image_new_from_mask(dev);
00545 skip_if(0);
00546
00547 cpl_free(filename);
00548 filename = cpl_sprintf(RECIPE_STRING "_set%02d_devpix" CPL_DFS_FITS,
00549 set_nb);
00550 skip_if (irplib_dfs_save_image(set_tot, parlist, set, image,
00551 CPL_BPP_32_SIGNED, RECIPE_STRING,
00552 procatg_dev, qclist, NULL, visir_pipe_id,
00553 filename));
00554 cpl_image_delete(image);
00555 image = NULL;
00556
00557 #ifdef VISIR_SAVE_PAF
00558
00559
00560 skip_if (cpl_propertylist_copy_property_regexp(paflist, plist, pafcopy, 0));
00561 skip_if (cpl_propertylist_append(paflist, qclist));
00562
00563
00564 bug_if (cpl_propertylist_append_string(paflist, CPL_DFS_PRO_CATG,
00565 procatg_avg));
00566
00567 cpl_free(filename);
00568 filename = cpl_sprintf(RECIPE_STRING "_set%02d" CPL_DFS_PAF, set_nb);
00569 skip_if (cpl_dfs_save_paf("VISIR", RECIPE_STRING, paflist, filename));
00570 #else
00571 bug_if(paflist == NULL);
00572 bug_if(plist == NULL);
00573 bug_if(pafcopy == NULL);
00574 #endif
00575
00576 end_skip;
00577
00578 cpl_image_delete(image);
00579 cpl_frameset_delete(set);
00580 cpl_propertylist_delete(paflist);
00581 cpl_free(filename);
00582
00583 return cpl_error_get_code();
00584 }
00585
00586
00587
00597
00598 static char * visir_img_dark_make_tag(const cpl_frame* self,
00599 const cpl_propertylist * plist, int dummy)
00600 {
00601
00602 char * tag = NULL;
00603 double etime;
00604
00605
00606 skip_if (0);
00607
00608 skip_if(self == NULL);
00609 skip_if(plist == NULL);
00610 skip_if(dummy < 0);
00611
00612
00613 etime = visir_pfits_get_exptime(plist);
00614 skip_if(0);
00615
00616 tag = cpl_sprintf("%.5f", etime);
00617 bug_if(tag == NULL);
00618
00619 end_skip;
00620
00621 if (cpl_error_get_code()) {
00622 cpl_free(tag);
00623 tag = NULL;
00624 }
00625
00626 return tag;
00627
00628 }
00629