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 "naco_recipe.h"
00037
00038
00039
00040
00041
00042 #define RECIPE_STRING "naco_img_dark"
00043
00044
00045
00046
00047
00048 static cpl_error_code naco_img_dark_reduce(cpl_propertylist *,
00049 const irplib_framelist *,
00050 cpl_image **, cpl_mask **,
00051 cpl_mask **, cpl_mask **);
00052
00053 static cpl_error_code naco_img_dark_qc(cpl_propertylist *,
00054 cpl_propertylist *,
00055 const irplib_framelist *);
00056
00057 static cpl_error_code naco_img_dark_save(cpl_frameset *,
00058 const cpl_parameterlist *,
00059 const cpl_propertylist *,
00060 const cpl_propertylist *,
00061 const cpl_image *, const cpl_mask *,
00062 const cpl_mask *, const cpl_mask *,
00063 int, const irplib_framelist *);
00064
00065 static char * naco_img_dark_make_tag(const cpl_frame*,
00066 const cpl_propertylist *, int);
00067
00068 NACO_RECIPE_DEFINE(naco_img_dark,
00069 NACO_PARAM_REJBORD |
00070 NACO_PARAM_HOT_LIM |
00071 NACO_PARAM_COLD_LIM |
00072 NACO_PARAM_DEV_LIM |
00073 NACO_PARAM_NSAMPLES |
00074 NACO_PARAM_HALFSIZE,
00075 "Dark recipe",
00076 "naco_img_dark -- NACO imaging dark recipe.\n"
00077 "The files listed in the Set Of Frames (sof-file) "
00078 "must be tagged:\n"
00079 "NACO-raw-file.fits " NACO_IMG_DARK_RAW "\n");
00080
00081
00082
00083
00084
00085 static struct {
00086
00087 int rej_left;
00088 int rej_right;
00089 int rej_bottom;
00090 int rej_top;
00091 double hot_thresh;
00092 double cold_thresh;
00093 double dev_thresh;
00094 int hsize;
00095 int nsamples;
00096 } naco_img_dark_config;
00097
00098
00102
00103
00104
00105
00106
00107
00108
00109
00116
00117 static int naco_img_dark(cpl_frameset * framelist,
00118 const cpl_parameterlist * parlist)
00119 {
00120 irplib_framelist* allframes = NULL;
00121 irplib_framelist* rawframes = NULL;
00122 const char ** taglist = NULL;
00123 const char * rej_bord;
00124 irplib_framelist* f_one = NULL;
00125 cpl_imagelist * i_one = NULL;
00126 cpl_image * avg = NULL;
00127 cpl_mask * hot = NULL;
00128 cpl_mask * cold = NULL;
00129 cpl_mask * dev = NULL;
00130 cpl_propertylist * qclist = cpl_propertylist_new();
00131 cpl_propertylist * paflist = cpl_propertylist_new();
00132 int nsets;
00133 int i;
00134 int nb_good = 0;
00135
00136
00137
00138 rej_bord = naco_parameterlist_get_string(parlist, RECIPE_STRING, NACO_PARAM_REJBORD);
00139 skip_if (0);
00140 skip_if (sscanf(rej_bord, "%d %d %d %d",
00141 &naco_img_dark_config.rej_left,
00142 &naco_img_dark_config.rej_right,
00143 &naco_img_dark_config.rej_bottom,
00144 &naco_img_dark_config.rej_top) != 4);
00145
00146 naco_img_dark_config.hot_thresh =
00147 naco_parameterlist_get_double(parlist, RECIPE_STRING, NACO_PARAM_HOT_LIM);
00148 naco_img_dark_config.dev_thresh =
00149 naco_parameterlist_get_double(parlist, RECIPE_STRING, NACO_PARAM_DEV_LIM);
00150 naco_img_dark_config.cold_thresh =
00151 naco_parameterlist_get_double(parlist, RECIPE_STRING, NACO_PARAM_COLD_LIM);
00152 naco_img_dark_config.hsize =
00153 naco_parameterlist_get_int(parlist, RECIPE_STRING, NACO_PARAM_HALFSIZE);
00154 naco_img_dark_config.nsamples =
00155 naco_parameterlist_get_int(parlist, RECIPE_STRING, NACO_PARAM_NSAMPLES);
00156
00157 skip_if (0);
00158
00159
00160 skip_if (naco_dfs_set_groups(framelist));
00161
00162 allframes = irplib_framelist_cast(framelist);
00163 skip_if(allframes == NULL);
00164
00165 rawframes = irplib_framelist_extract(allframes, NACO_IMG_DARK_RAW);
00166 skip_if(rawframes == NULL);
00167 irplib_framelist_empty(allframes);
00168
00169 skip_if(irplib_framelist_load_propertylist_all(rawframes, 0, "^("
00170 IRPLIB_PFITS_REGEXP_RECAL "|"
00171 NACO_PFITS_REGEXP_DARK "|"
00172 NACO_PFITS_REGEXP_DARK_PAF
00173 ")$", CPL_FALSE));
00174
00175 taglist = naco_framelist_set_tag(rawframes, naco_img_dark_make_tag, &nsets);
00176 skip_if(taglist == NULL);
00177
00178 cpl_msg_info(cpl_func, "Identified %d setting(s) in %d frames",
00179 nsets, irplib_framelist_get_size(rawframes));
00180
00181
00182 for (i=0 ; i < nsets ; i++) {
00183
00184
00185 f_one = irplib_framelist_extract(rawframes, taglist[i]);
00186
00187
00188 skip_if(irplib_framelist_set_tag_all(f_one, NACO_IMG_DARK_RAW));
00189
00190 cpl_msg_info(cpl_func, "Reducing frame set %d of %d (size=%d) with "
00191 "setting: %s", i+1, nsets,
00192 irplib_framelist_get_size(f_one), taglist[i]);
00193
00194 skip_if (f_one == NULL);
00195
00196
00197 if (irplib_framelist_get_size(f_one) < 2) {
00198 cpl_msg_warning(cpl_func, "Setting %d skipped (Need at least 2 "
00199 "frames)", i+1);
00200 irplib_framelist_delete(f_one);
00201 f_one = NULL;
00202 continue;
00203 }
00204
00205 skip_if(naco_img_dark_reduce(qclist, f_one, &avg, &hot, &cold, &dev));
00206
00207 skip_if(naco_img_dark_qc(qclist, paflist, f_one));
00208
00209
00210 skip_if (naco_img_dark_save(framelist, parlist, qclist, paflist,
00211 avg, hot, cold, dev, i+1, f_one));
00212
00213 nb_good++;
00214
00215 cpl_image_delete(avg);
00216 cpl_mask_delete(hot);
00217 cpl_mask_delete(cold);
00218 cpl_mask_delete(dev);
00219 irplib_framelist_delete(f_one);
00220 cpl_propertylist_empty(qclist);
00221 cpl_propertylist_empty(paflist);
00222 avg = NULL;
00223 cold = NULL;
00224 hot = NULL;
00225 dev = NULL;
00226 f_one = NULL;
00227 }
00228
00229 skip_if (nb_good == 0);
00230
00231 end_skip;
00232
00233 cpl_imagelist_delete(i_one);
00234 cpl_free(taglist);
00235 cpl_image_delete(avg);
00236 cpl_mask_delete(hot);
00237 cpl_mask_delete(cold);
00238 cpl_mask_delete(dev);
00239 irplib_framelist_delete(f_one);
00240 irplib_framelist_delete(allframes);
00241 irplib_framelist_delete(rawframes);
00242 cpl_propertylist_delete(qclist);
00243 cpl_propertylist_delete(paflist);
00244
00245 return cpl_error_get_code();
00246 }
00247
00248
00261
00262 static cpl_error_code naco_img_dark_reduce(cpl_propertylist * qclist,
00263 const irplib_framelist * f_one,
00264 cpl_image ** pavg, cpl_mask ** phot,
00265 cpl_mask ** pcold, cpl_mask ** pdev)
00266 {
00267
00268 cpl_image * dark = NULL;
00269 cpl_image * diff = NULL;
00270 char * ron_key = NULL;
00271 double rms;
00272 double lower, upper;
00273 double dark_med;
00274 double mean;
00275 int ndevpix;
00276 cpl_size zone[4];
00277 int coldpix_nb;
00278 int hotpix_nb;
00279 int nfiles;
00280 int i;
00281
00282 skip_if (f_one == NULL);
00283
00284 nfiles = irplib_framelist_get_size(f_one);
00285
00286 skip_if (nfiles < 2);
00287
00288 skip_if (irplib_framelist_contains(f_one, "NAXIS1",
00289 CPL_TYPE_INT, CPL_TRUE, 0.0));
00290
00291 skip_if (irplib_framelist_contains(f_one, "NAXIS2",
00292 CPL_TYPE_INT, CPL_TRUE, 0.0));
00293
00294 for (i=0 ; i < nfiles ; i++) {
00295 const cpl_frame * frame = irplib_framelist_get_const(f_one, i);
00296 const char * name = cpl_frame_get_filename(frame);
00297
00298 cpl_image_delete(diff);
00299 diff = dark;
00300 irplib_check(dark = cpl_image_load(name, CPL_TYPE_FLOAT, 0, 0),
00301 "Could not load FITS-image from %s", name);
00302
00303 if (i == 0) {
00304 const int nx = cpl_image_get_size_x(dark);
00305 const int ny = cpl_image_get_size_y(dark);
00306
00307 zone[0] = naco_img_dark_config.rej_left+1;
00308 zone[1] = nx - naco_img_dark_config.rej_right;
00309 zone[2] = naco_img_dark_config.rej_bottom+1;
00310 zone[3] = ny - naco_img_dark_config.rej_top;
00311
00312 *pavg = cpl_image_duplicate(dark);
00313 skip_if(*pavg == NULL);
00314 } else {
00315 const cpl_propertylist * plist
00316 = irplib_framelist_get_propertylist_const(f_one, i-1);
00317 const int ndit = naco_pfits_get_ndit(plist);
00318 const char ron_format[] = "ESO QC RON%d";
00319 double ron;
00320
00321 skip_if(0);
00322
00323 irplib_ensure(ndit > 0, CPL_ERROR_ILLEGAL_INPUT,
00324 NACO_PFITS_INT_NDIT " must be positive, not %d",
00325 ndit);
00326
00327 skip_if(cpl_image_subtract(diff, dark));
00328
00329
00330 irplib_check(cpl_flux_get_noise_window(diff, zone,
00331 naco_img_dark_config.hsize,
00332 naco_img_dark_config.nsamples,
00333 &rms, NULL),
00334 "Cannot compute the RON for difference between images "
00335 "%d and %d", i, i+1);
00336
00337
00338 ron = rms * sqrt(ndit/2.0);
00339
00340
00341 cpl_free(ron_key);
00342 ron_key = cpl_sprintf(ron_format, i);
00343
00344 bug_if(ron_key == NULL);
00345
00346 skip_if(cpl_propertylist_append_double(qclist, ron_key, ron));
00347
00348
00349 skip_if(cpl_image_add(*pavg, dark));
00350
00351 }
00352
00353 }
00354 cpl_image_delete(dark);
00355 dark = NULL;
00356
00357 mean = cpl_image_get_mean(diff);
00358
00359
00360
00361 lower = mean - rms * naco_img_dark_config.dev_thresh;
00362 upper = mean + rms * naco_img_dark_config.dev_thresh;
00363 cpl_mask_delete(*pdev);
00364 irplib_check(*pdev = cpl_mask_threshold_image_create(diff, lower, upper),
00365 "Cannot compute the deviant pixel map");
00366 cpl_image_delete(diff);
00367 diff = NULL;
00368
00369 skip_if (cpl_mask_not(*pdev));
00370 ndevpix = cpl_mask_count(*pdev);
00371 skip_if (0);
00372
00373
00374 skip_if(cpl_image_divide_scalar(*pavg, (double)nfiles));
00375
00376
00377 dark_med = cpl_image_get_median_window(*pavg, zone[0], zone[2], zone[1],
00378 zone[3]);
00379
00380 irplib_check (cpl_flux_get_noise_window(*pavg, zone,
00381 naco_img_dark_config.hsize,
00382 naco_img_dark_config.nsamples,
00383 &rms, NULL),
00384 "Cannot compute the RON of the master dark");
00385
00386 lower = dark_med - rms * naco_img_dark_config.cold_thresh;
00387 upper = dark_med + rms * naco_img_dark_config.hot_thresh;
00388
00389
00390 cpl_mask_delete(*pcold);
00391 irplib_check(*pcold = cpl_mask_threshold_image_create(*pavg, -FLT_MAX,
00392 lower),
00393 "Cannot compute the cold pixel map");
00394 coldpix_nb = cpl_mask_count(*pcold);
00395 skip_if (0);
00396
00397
00398 cpl_mask_delete(*phot);
00399 irplib_check(*phot = cpl_mask_threshold_image_create(*pavg, upper, DBL_MAX),
00400 "Cannot compute the hot pixel map");
00401 hotpix_nb = cpl_mask_count(*phot);
00402 skip_if (0);
00403
00404
00405
00406 skip_if(cpl_propertylist_append_double(qclist, "ESO QC DARKMED", dark_med));
00407 skip_if(cpl_propertylist_append_int(qclist, "ESO QC NBCOLPIX", coldpix_nb));
00408 skip_if(cpl_propertylist_append_int(qclist, "ESO QC NBHOTPIX", hotpix_nb));
00409 skip_if(cpl_propertylist_append_int(qclist, "ESO QC NBDEVPIX", ndevpix));
00410
00411 end_skip;
00412
00413 cpl_image_delete(dark);
00414 cpl_image_delete(diff);
00415 cpl_free(ron_key);
00416
00417 return cpl_error_get_code();
00418 }
00419
00420
00421
00429
00430 static cpl_error_code naco_img_dark_qc(cpl_propertylist * qclist,
00431 cpl_propertylist * paflist,
00432 const irplib_framelist * rawframes)
00433 {
00434
00435 const cpl_propertylist * reflist
00436 = irplib_framelist_get_propertylist_const(rawframes, 0);
00437 const char pafcopy[] = "^(" NACO_PFITS_REGEXP_DARK_PAF ")$";
00438
00439
00440 bug_if (0);
00441
00442 bug_if (cpl_propertylist_copy_property_regexp(paflist, reflist, pafcopy,
00443 0));
00444 bug_if (cpl_propertylist_append(paflist, qclist));
00445
00446 bug_if (cpl_propertylist_copy_property_regexp(qclist, reflist, "^("
00447 IRPLIB_PFITS_REGEXP_RECAL
00448 ")$", 0));
00449
00450 bug_if (irplib_pfits_set_airmass(qclist, rawframes));
00451
00452 end_skip;
00453
00454 return cpl_error_get_code();
00455 }
00456
00457
00472
00473 static cpl_error_code naco_img_dark_save(cpl_frameset * set_tot,
00474 const cpl_parameterlist * parlist,
00475 const cpl_propertylist * qclist,
00476 const cpl_propertylist * paflist,
00477 const cpl_image * avg,
00478 const cpl_mask * hot,
00479 const cpl_mask * cold,
00480 const cpl_mask * dev,
00481 int set_nb,
00482 const irplib_framelist * f_one)
00483 {
00484 cpl_frameset * set_one = irplib_frameset_cast(f_one);
00485 cpl_image * image = NULL;
00486 char * filename = NULL;
00487
00488
00489 bug_if (0);
00490
00491
00492 filename = cpl_sprintf(RECIPE_STRING "_set%02d_avg" CPL_DFS_FITS,
00493 set_nb);
00494 skip_if (irplib_dfs_save_image(set_tot, parlist, set_one, avg,
00495 CPL_BPP_IEEE_FLOAT, RECIPE_STRING,
00496 NACO_IMG_DARK_AVG, qclist, NULL, naco_pipe_id,
00497 filename));
00498
00499
00500 image = cpl_image_new_from_mask(hot);
00501 bug_if(0);
00502
00503 cpl_free(filename);
00504 filename = cpl_sprintf(RECIPE_STRING "_set%02d_hotpix" CPL_DFS_FITS,
00505 set_nb);
00506 skip_if (irplib_dfs_save_image(set_tot, parlist, set_one, image,
00507 CPL_BPP_8_UNSIGNED, RECIPE_STRING, NACO_IMG_DARK_HOT,
00508 qclist, NULL, naco_pipe_id, filename));
00509
00510
00511 cpl_image_delete(image);
00512 image = cpl_image_new_from_mask(cold);
00513 bug_if(0);
00514
00515 cpl_free(filename);
00516 filename = cpl_sprintf(RECIPE_STRING "_set%02d_coldpix" CPL_DFS_FITS,
00517 set_nb);
00518 skip_if (irplib_dfs_save_image(set_tot, parlist, set_one, image,
00519 CPL_BPP_8_UNSIGNED, RECIPE_STRING,
00520 NACO_IMG_DARK_COLD, qclist, NULL, naco_pipe_id,
00521 filename));
00522
00523
00524 cpl_image_delete(image);
00525 image = cpl_image_new_from_mask(dev);
00526 bug_if(0);
00527
00528 cpl_free(filename);
00529 filename = cpl_sprintf(RECIPE_STRING "_set%02d_devpix" CPL_DFS_FITS,
00530 set_nb);
00531 skip_if (irplib_dfs_save_image(set_tot, parlist, set_one, image,
00532 CPL_BPP_8_UNSIGNED, RECIPE_STRING, NACO_IMG_DARK_DEV,
00533 qclist, NULL, naco_pipe_id, filename));
00534 cpl_image_delete(image);
00535 image = NULL;
00536
00537 #ifdef NACO_SAVE_PAF
00538
00539
00540
00541 bug_if(cpl_propertylist_append_string(paflist, CPL_DFS_PRO_CATG,
00542 NACO_IMG_DARK_AVG));
00543
00544 cpl_free(filename);
00545 filename = cpl_sprintf(RECIPE_STRING "_set%02d" CPL_DFS_PAF, set_nb);
00546 skip_if (cpl_dfs_save_paf("NACO", RECIPE_STRING, paflist, filename));
00547 #else
00548 bug_if(paflist == NULL);
00549 #endif
00550
00551 end_skip;
00552
00553 cpl_image_delete(image);
00554 cpl_frameset_delete(set_one);
00555 cpl_free(filename);
00556
00557 return cpl_error_get_code();
00558 }
00559
00560
00561
00571
00572 static char * naco_img_dark_make_tag(const cpl_frame* self,
00573 const cpl_propertylist * plist, int dummy)
00574 {
00575
00576 char * tag = NULL;
00577 const char * mode;
00578 const char * name;
00579 double etime;
00580 int irom;
00581
00582
00583 skip_if (cpl_error_get_code());
00584
00585 skip_if(self == NULL);
00586 skip_if(plist == NULL);
00587 skip_if(dummy < 0);
00588
00589
00590 etime = naco_pfits_get_exptime(plist);
00591 skip_if(cpl_error_get_code());
00592
00593
00594 irom = naco_pfits_get_rom(plist);
00595 skip_if(cpl_error_get_code());
00596
00597
00598
00599 mode = naco_pfits_get_mode(plist);
00600 skip_if(cpl_error_get_code());
00601
00602
00603 name = naco_pfits_get_opti7_name(plist);
00604 skip_if(cpl_error_get_code());
00605
00606 tag = cpl_sprintf("%s:%s:%d:%.5f", name, mode, irom,
00607 etime);
00608 bug_if(tag == NULL);
00609
00610 end_skip;
00611
00612 if (cpl_error_get_code()) {
00613 cpl_free(tag);
00614 tag = NULL;
00615 }
00616
00617 return tag;
00618
00619 }