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_lampflat"
00043
00044
00045
00046
00047
00048 static cpl_image * naco_img_lampflat_reduce(cpl_propertylist *,
00049 const irplib_framelist *,
00050 int, int, int, int);
00051
00052 static cpl_error_code naco_img_lampflat_qc(cpl_propertylist *,
00053 cpl_propertylist *,
00054 const irplib_framelist *);
00055
00056 static cpl_error_code naco_img_lampflat_save(cpl_frameset *,
00057 const cpl_parameterlist *,
00058 const cpl_propertylist *,
00059 const cpl_propertylist *,
00060 const cpl_image *,
00061 int, const irplib_framelist *);
00062
00063 static char * naco_img_lampflat_make_tag(const cpl_frame*,
00064 const cpl_propertylist *, int);
00065
00066 NACO_RECIPE_DEFINE(naco_img_lampflat, NACO_PARAM_REJBORD,
00067 "Flat recipe using a lamp",
00068 RECIPE_STRING " -- NACO imaging flat-field creation from "
00069 "lamp images.\n"
00070 "The files listed in the Set Of Frames (sof-file) "
00071 "must be tagged:\n"
00072 "NACO-raw-file.fits " NACO_IMG_LAMPFLAT_RAW "\n"
00073 "\n"
00074 "Furthermore, the input set of frames must have values of "
00075 "the FITS key "
00076 NACO_PFITS_INT_LAMP2 " that alternate between zero and "
00077 "non-zero (with non-zero for the first frame).\n"
00078 "It is further required that the light from the lamp is "
00079 "in a range without a significant thermal background.");
00080
00081
00082
00086
00087
00088
00089
00090
00091
00092
00099
00100 static int naco_img_lampflat(cpl_frameset * framelist,
00101 const cpl_parameterlist * parlist)
00102 {
00103 cpl_errorstate cleanstate = cpl_errorstate_get();
00104 irplib_framelist * allframes = NULL;
00105 irplib_framelist * rawframes = NULL;
00106 irplib_framelist * f_one = NULL;
00107 const char ** taglist = NULL;
00108 const char * rej_bord;
00109 cpl_image * lamp_flat = NULL;
00110 cpl_propertylist * qclist = cpl_propertylist_new();
00111 cpl_propertylist * paflist = cpl_propertylist_new();
00112 int nb_good = 0;
00113 int nsets;
00114 int rej_left, rej_right, rej_bottom, rej_top;
00115 int i;
00116
00117
00118
00119 rej_bord = naco_parameterlist_get_string(parlist, RECIPE_STRING, NACO_PARAM_REJBORD);
00120 skip_if (0);
00121 skip_if (sscanf(rej_bord, "%d %d %d %d",
00122 &rej_left, &rej_right, &rej_bottom, &rej_top) != 4);
00123
00124
00125 skip_if (naco_dfs_set_groups(framelist));
00126
00127 allframes = irplib_framelist_cast(framelist);
00128 skip_if(allframes == NULL);
00129
00130 rawframes = irplib_framelist_extract(allframes, NACO_IMG_LAMPFLAT_RAW);
00131 skip_if(rawframes == NULL);
00132 irplib_framelist_empty(allframes);
00133
00134 skip_if(irplib_framelist_load_propertylist_all(rawframes, 0, "^("
00135 IRPLIB_PFITS_REGEXP_RECAL "|"
00136 NACO_PFITS_REGEXP_LAMPFLAT "|"
00137 NACO_PFITS_REGEXP_LAMPFLAT_PAF
00138 ")$", CPL_FALSE));
00139
00140 taglist = naco_framelist_set_tag(rawframes, naco_img_lampflat_make_tag,
00141 &nsets);
00142 skip_if(taglist == NULL);
00143
00144 cpl_msg_info(cpl_func, "Identified %d setting(s) in %d frames",
00145 nsets, irplib_framelist_get_size(rawframes));
00146
00147
00148 for (i=0 ; i < nsets ; i++) {
00149
00150
00151 cpl_msg_info(cpl_func, "Reducing data set %d of %d", i+1, nsets);
00152
00153
00154 f_one = irplib_framelist_extract(rawframes, taglist[i]);
00155
00156
00157 skip_if(irplib_framelist_set_tag_all(f_one, NACO_IMG_LAMPFLAT_RAW));
00158
00159 cpl_msg_info(cpl_func, "Reducing frame set %d of %d (size=%d) with "
00160 "setting: %s", i+1, nsets,
00161 irplib_framelist_get_size(f_one), taglist[i]);
00162
00163 skip_if (f_one == NULL);
00164
00165 lamp_flat = naco_img_lampflat_reduce(qclist, f_one, rej_left, rej_right,
00166 rej_bottom, rej_top);
00167
00168
00169 if (lamp_flat == NULL) {
00170 if (nsets > 1)
00171 irplib_error_recover(cleanstate, "Could not compute the flat for "
00172 "this setting");
00173 } else {
00174 skip_if(naco_img_lampflat_qc(qclist, paflist, f_one));
00175
00176 bug_if(cpl_propertylist_append_string(paflist, CPL_DFS_PRO_CATG,
00177 NACO_IMG_LAMPFLAT_RES));
00178 skip_if(naco_img_lampflat_save(framelist, parlist, qclist, paflist,
00179 lamp_flat, i+1, f_one));
00180 cpl_image_delete(lamp_flat);
00181 lamp_flat = NULL;
00182 nb_good++;
00183 }
00184 cpl_propertylist_empty(qclist);
00185 cpl_propertylist_empty(paflist);
00186 irplib_framelist_delete(f_one);
00187 f_one = NULL;
00188 }
00189
00190 irplib_ensure(nb_good > 0, CPL_ERROR_DATA_NOT_FOUND,
00191 "None of the %d sets could be reduced", nsets);
00192
00193 end_skip;
00194
00195 cpl_free(taglist);
00196 cpl_image_delete(lamp_flat);
00197 irplib_framelist_delete(f_one);
00198 irplib_framelist_delete(allframes);
00199 irplib_framelist_delete(rawframes);
00200 cpl_propertylist_delete(qclist);
00201 cpl_propertylist_delete(paflist);
00202
00203 return cpl_error_get_code();
00204 }
00205
00206
00217
00218 static cpl_image * naco_img_lampflat_reduce(cpl_propertylist * qclist,
00219 const irplib_framelist * framelist,
00220 int rej_left, int rej_right,
00221 int rej_bottom, int rej_top)
00222 {
00223 int nfiles;
00224 cpl_image * image = NULL;
00225 cpl_image * aver = NULL;
00226 cpl_image * diff = NULL;
00227 cpl_image * prev = NULL;
00228 cpl_image * image0= NULL;
00229 double gain, fp_noise;
00230 double lamp_flux = DBL_MAX;
00231 double std_diff[3];
00232 double mean = DBL_MAX;
00233 double square;
00234 int i;
00235
00236
00237 bug_if (framelist == NULL);
00238
00239 nfiles = irplib_framelist_get_size(framelist);
00240
00241
00242 skip_if_lt(nfiles, 4, "frames");
00243
00244
00245 irplib_ensure (nfiles % 2 == 0, CPL_ERROR_ILLEGAL_INPUT,
00246 "The number of frames must be even, not %d", nfiles);
00247
00248 skip_if (irplib_framelist_contains(framelist, NACO_PFITS_DOUBLE_DIT,
00249 CPL_TYPE_DOUBLE, CPL_TRUE, 1e-5));
00250
00251 skip_if (irplib_framelist_contains(framelist, NACO_PFITS_INT_LAMP2,
00252 CPL_TYPE_INT, CPL_FALSE, 0.0));
00253
00254
00255
00256 for (i=0 ; i < nfiles ; i++) {
00257 const cpl_frame * frame = irplib_framelist_get_const(framelist, i);
00258 const char * name = cpl_frame_get_filename(frame);
00259 const cpl_propertylist * plist
00260 = irplib_framelist_get_propertylist_const(framelist, i);
00261 int ival;
00262
00263 skip_if(name == NULL);
00264 skip_if(plist == NULL);
00265
00266 if (i == 0) {
00267
00268 const char * sval = naco_pfits_get_filter(plist);
00269
00270 skip_if (0);
00271 cpl_msg_info(cpl_func, "Filter: [%s]", sval);
00272
00273
00274 skip_if(cpl_propertylist_append_string(qclist, "ESO QC FILTER OBS",
00275 sval));
00276 sval = naco_pfits_get_opti3_name(plist);
00277 skip_if (0);
00278 skip_if(cpl_propertylist_append_string(qclist, "ESO QC FILTER NDENS",
00279 sval));
00280 sval = naco_pfits_get_opti4_name(plist);
00281 skip_if (0);
00282 skip_if(cpl_propertylist_append_string(qclist, "ESO QC FILTER POL",
00283 sval));
00284 }
00285
00286 cpl_msg_info(cpl_func, "File %02d: %s", i+1, name);
00287
00288
00289 ival = naco_pfits_get_lamp2(plist);
00290 if (i % 2) {
00291 irplib_ensure (ival == 0, CPL_ERROR_ILLEGAL_INPUT,
00292 "Frame number %d must have %s set to zero, not %d",
00293 i+1, NACO_PFITS_INT_LAMP2, ival);
00294 } else {
00295 irplib_ensure (ival != 0, CPL_ERROR_ILLEGAL_INPUT,
00296 "Frame number %d must have a non-zero %s",
00297 i+1, NACO_PFITS_INT_LAMP2);
00298 }
00299
00300 irplib_check(image = cpl_image_load(name, CPL_TYPE_FLOAT, 0, 0),
00301 "Could not load FITS-image from %s", name);
00302
00303 if (i == 0) {
00304 irplib_check(mean = cpl_image_get_mean(image),
00305 "Could not compute mean");
00306 image0 = image; image = NULL;
00307 } else if (i <= 3) {
00308 const int ifirst = i == 3 ? 1 : 0;
00309 double noise;
00310
00311
00312
00313 irplib_check(diff = cpl_image_subtract_create(image0, image),
00314 "Could not subtract the images %d and %d",
00315 ifirst+1, i+1);
00316
00317 irplib_check(cpl_flux_get_noise_window(diff, NULL, -1, -1,
00318 &noise, NULL),
00319 "Could not compute noise on difference between"
00320 " images %d and %d", ifirst+1, i+1);
00321
00322 std_diff[i-1] = noise * noise;
00323
00324 if (i == 1) {
00325
00326
00327 const double median = cpl_image_get_median(diff);
00328 const double ditval = naco_pfits_get_dit(plist);
00329
00330 skip_if (cpl_error_get_code());
00331 skip_if (ditval <= 0.0);
00332
00333 lamp_flux = median / ditval;
00334
00335
00336 aver = diff;
00337
00338 } else {
00339 cpl_image_delete(diff);
00340 diff = NULL;
00341
00342 cpl_image_delete(image0);
00343
00344 image0 = i == 2 ? prev : NULL;
00345 }
00346
00347 }
00348
00349 if (i > 1 && i % 2 != 0) {
00350
00351 irplib_check(cpl_image_subtract(prev, image),
00352 "Could not correct for the dark");
00353
00354
00355 irplib_check(cpl_image_add(aver, prev),
00356 "Could not sum up the dark corrected images");
00357
00358 cpl_image_delete(image);
00359 cpl_image_delete(prev);
00360 prev = NULL;
00361 } else {
00362 prev = image;
00363 }
00364 image = NULL;
00365 }
00366
00367
00368 cpl_msg_info(cpl_func, "Computing the QC parameters");
00369
00370
00371 square = std_diff[1] - std_diff[2];
00372 if (square != 0.0) square = 2.0*mean/square;
00373 gain = square > 0.0 ? sqrt(square) : 0.0;
00374
00375
00376 square = std_diff[0] - std_diff[1] - std_diff[2];
00377 fp_noise = square > 0.0 ? sqrt(square) : 0.0;
00378
00379
00380 cpl_msg_info(cpl_func, "Gain: %g", gain);
00381 cpl_msg_info(cpl_func, "Noise: %g", fp_noise);
00382 cpl_msg_info(cpl_func, "Lamp flux: %g", lamp_flux);
00383
00384
00385 cpl_msg_info(cpl_func, "Average the dark corrected frames");
00386 irplib_check(cpl_image_divide_scalar(aver, (double)(nfiles/2)),
00387 "Could not average the %d dark corrected frames", nfiles/2);
00388
00389
00390 irplib_check(mean
00391 = cpl_image_get_mean_window(aver, rej_left,
00392 cpl_image_get_size_x(aver)
00393 -rej_right,
00394 rej_bottom,
00395 cpl_image_get_size_y(aver)
00396 -rej_top);
00397 cpl_image_divide_scalar(aver, mean),
00398 "Could not average the %d dark corrected frames", nfiles/2);
00399
00400
00401 skip_if(cpl_propertylist_append_double(qclist, "ESO QC GAIN", gain));
00402 skip_if(cpl_propertylist_append_double(qclist, "ESO QC FPNOISE", fp_noise));
00403 skip_if(cpl_propertylist_append_double(qclist, "ESO QC LAMPFLUX",
00404 lamp_flux));
00405
00406 end_skip;
00407
00408 if (cpl_error_get_code()) {
00409 cpl_image_delete(aver);
00410 aver = NULL;
00411 }
00412
00413 cpl_image_delete(image);
00414 cpl_image_delete(diff);
00415 cpl_image_delete(prev);
00416 cpl_image_delete(image0);
00417
00418 return aver;
00419 }
00420
00421
00422
00430
00431 static cpl_error_code naco_img_lampflat_qc(cpl_propertylist * qclist,
00432 cpl_propertylist * paflist,
00433 const irplib_framelist * rawframes)
00434 {
00435
00436 const cpl_propertylist * reflist
00437 = irplib_framelist_get_propertylist_const(rawframes, 0);
00438 const char pafcopy[] = "^(" NACO_PFITS_REGEXP_LAMPFLAT_PAF ")$";
00439
00440
00441 bug_if (0);
00442
00443
00444
00445 skip_if (cpl_propertylist_copy_property_regexp(paflist, reflist, pafcopy,
00446 0));
00447 skip_if (cpl_propertylist_append(paflist, qclist));
00448
00449 bug_if (cpl_propertylist_copy_property_regexp(qclist, reflist, "^("
00450 IRPLIB_PFITS_REGEXP_RECAL
00451 ")$", 0));
00452
00453 bug_if (irplib_pfits_set_airmass(qclist, rawframes));
00454
00455 end_skip;
00456
00457 return cpl_error_get_code();
00458 }
00459
00460
00472
00473 static cpl_error_code naco_img_lampflat_save(cpl_frameset * set_tot,
00474 const cpl_parameterlist * parlist,
00475 const cpl_propertylist * qclist,
00476 const cpl_propertylist * paflist,
00477 const cpl_image * flat,
00478 int set_nb,
00479 const irplib_framelist * rawframes)
00480 {
00481 cpl_frameset * proframes = irplib_frameset_cast(rawframes);
00482 char * filename = NULL;
00483
00484
00485
00486
00487 bug_if (0);
00488
00489
00490 filename = cpl_sprintf(RECIPE_STRING "_set%02d" CPL_DFS_FITS, set_nb);
00491 skip_if (irplib_dfs_save_image(set_tot, parlist, proframes, flat,
00492 CPL_BPP_IEEE_FLOAT, RECIPE_STRING,
00493 NACO_IMG_LAMPFLAT_RES, qclist, NULL,
00494 naco_pipe_id, filename));
00495
00496 #ifdef NACO_SAVE_PAF
00497 cpl_free(filename);
00498 filename = cpl_sprintf(RECIPE_STRING "_set%02d" CPL_DFS_PAF, set_nb);
00499 skip_if (cpl_dfs_save_paf("NACO", RECIPE_STRING, paflist, filename));
00500 #else
00501 bug_if(paflist == NULL);
00502 #endif
00503
00504 end_skip;
00505
00506 cpl_free(filename);
00507 cpl_frameset_delete(proframes);
00508
00509 return cpl_error_get_code();
00510
00511 }
00512
00513
00514
00524
00525 static char * naco_img_lampflat_make_tag(const cpl_frame* self,
00526 const cpl_propertylist * plist,
00527 int dummy)
00528 {
00529
00530 char * tag = NULL;
00531 const char * filter;
00532 const char * opti3;
00533 const char * opti7;
00534 const char * rom;
00535 const char * mode;
00536 double dit;
00537
00538
00539 skip_if (cpl_error_get_code());
00540
00541 skip_if(self == NULL);
00542 skip_if(plist == NULL);
00543 skip_if(dummy < 0);
00544
00545
00546
00547 filter = naco_pfits_get_filter(plist);
00548 skip_if(cpl_error_get_code());
00549
00550
00551 opti7 = naco_pfits_get_opti7_name(plist);
00552 skip_if(cpl_error_get_code());
00553
00554
00555 opti3 = naco_pfits_get_opti3_name(plist);
00556 skip_if(cpl_error_get_code());
00557
00558
00559 rom = naco_pfits_get_rom_name(plist);
00560 skip_if(cpl_error_get_code());
00561
00562
00563 mode = naco_pfits_get_mode(plist);
00564 skip_if(cpl_error_get_code());
00565
00566
00567 dit = naco_pfits_get_dit(plist);
00568 skip_if(cpl_error_get_code());
00569
00570
00571 tag = cpl_sprintf("%s:%s:%s:%s:%s:%.5f", filter,
00572 opti7, opti3, rom, mode, dit);
00573 bug_if(tag == NULL);
00574
00575 end_skip;
00576
00577 if (cpl_error_get_code()) {
00578 cpl_free(tag);
00579 tag = NULL;
00580 }
00581
00582 return tag;
00583
00584 }