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 skip_if(naco_img_lampflat_save(framelist, parlist, qclist, paflist,
00176 lamp_flat, i+1, f_one));
00177 cpl_image_delete(lamp_flat);
00178 lamp_flat = NULL;
00179 nb_good++;
00180 }
00181 cpl_propertylist_empty(qclist);
00182 cpl_propertylist_empty(paflist);
00183 irplib_framelist_delete(f_one);
00184 f_one = NULL;
00185 }
00186
00187 irplib_ensure(nb_good > 0, CPL_ERROR_DATA_NOT_FOUND,
00188 "None of the %d sets could be reduced", nsets);
00189
00190 end_skip;
00191
00192 cpl_free(taglist);
00193 cpl_image_delete(lamp_flat);
00194 irplib_framelist_delete(f_one);
00195 irplib_framelist_delete(allframes);
00196 irplib_framelist_delete(rawframes);
00197 cpl_propertylist_delete(qclist);
00198 cpl_propertylist_delete(paflist);
00199
00200 return cpl_error_get_code();
00201 }
00202
00203
00214
00215 static cpl_image * naco_img_lampflat_reduce(cpl_propertylist * qclist,
00216 const irplib_framelist * framelist,
00217 int rej_left, int rej_right,
00218 int rej_bottom, int rej_top)
00219 {
00220 int nfiles;
00221 cpl_image * image = NULL;
00222 cpl_image * aver = NULL;
00223 cpl_image * diff = NULL;
00224 cpl_image * prev = NULL;
00225 cpl_image * image0= NULL;
00226 double gain, fp_noise;
00227 double lamp_flux = DBL_MAX;
00228 double std_diff[3];
00229 double mean = DBL_MAX;
00230 double square;
00231 int i;
00232
00233
00234 bug_if (framelist == NULL);
00235
00236 nfiles = irplib_framelist_get_size(framelist);
00237
00238
00239 skip_if_lt(nfiles, 4, "frames");
00240
00241
00242 irplib_ensure (nfiles % 2 == 0, CPL_ERROR_ILLEGAL_INPUT,
00243 "The number of frames must be even, not %d", nfiles);
00244
00245 skip_if (irplib_framelist_contains(framelist, NACO_PFITS_DOUBLE_DIT,
00246 CPL_TYPE_DOUBLE, CPL_TRUE, 1e-5));
00247
00248 skip_if (irplib_framelist_contains(framelist, NACO_PFITS_INT_LAMP2,
00249 CPL_TYPE_INT, CPL_FALSE, 0.0));
00250
00251
00252
00253 for (i=0 ; i < nfiles ; i++) {
00254 const cpl_frame * frame = irplib_framelist_get_const(framelist, i);
00255 const char * name = cpl_frame_get_filename(frame);
00256 const cpl_propertylist * plist
00257 = irplib_framelist_get_propertylist_const(framelist, i);
00258 int ival;
00259
00260 skip_if(name == NULL);
00261 skip_if(plist == NULL);
00262
00263 if (i == 0) {
00264
00265 const char * sval = naco_pfits_get_filter(plist);
00266
00267 skip_if (0);
00268 cpl_msg_info(cpl_func, "Filter: [%s]", sval);
00269
00270
00271 skip_if(cpl_propertylist_append_string(qclist, "ESO QC FILTER OBS",
00272 sval));
00273 sval = naco_pfits_get_opti3_name(plist);
00274 skip_if (0);
00275 skip_if(cpl_propertylist_append_string(qclist, "ESO QC FILTER NDENS",
00276 sval));
00277 sval = naco_pfits_get_opti4_name(plist);
00278 skip_if (0);
00279 skip_if(cpl_propertylist_append_string(qclist, "ESO QC FILTER POL",
00280 sval));
00281 }
00282
00283 cpl_msg_info(cpl_func, "File %02d: %s", i+1, name);
00284
00285
00286 ival = naco_pfits_get_lamp2(plist);
00287 if (i % 2) {
00288 irplib_ensure (ival == 0, CPL_ERROR_ILLEGAL_INPUT,
00289 "Frame number %d must have %s set to zero, not %d",
00290 i+1, NACO_PFITS_INT_LAMP2, ival);
00291 } else {
00292 irplib_ensure (ival != 0, CPL_ERROR_ILLEGAL_INPUT,
00293 "Frame number %d must have a non-zero %s",
00294 i+1, NACO_PFITS_INT_LAMP2);
00295 }
00296
00297 irplib_check(image = cpl_image_load(name, CPL_TYPE_FLOAT, 0, 0),
00298 "Could not load FITS-image from %s", name);
00299
00300 if (i == 0) {
00301 irplib_check(mean = cpl_image_get_mean(image),
00302 "Could not compute mean");
00303 image0 = image;
00304 } else if (i <= 3) {
00305 const int ifirst = i == 3 ? 1 : 0;
00306 double noise;
00307
00308
00309
00310 irplib_check(diff = cpl_image_subtract_create(image0, image),
00311 "Could not subtract the images %d and %d",
00312 ifirst+1, i+1);
00313
00314 irplib_check(cpl_flux_get_noise_window(diff, NULL, -1, -1,
00315 &noise, NULL),
00316 "Could not compute noise on difference between"
00317 " images %d and %d", ifirst+1, i+1);
00318
00319 std_diff[i-1] = noise * noise;
00320
00321 if (i == 1) {
00322
00323
00324 const double median = cpl_image_get_median(diff);
00325 const double ditval = naco_pfits_get_dit(plist);
00326
00327 skip_if (cpl_error_get_code());
00328 skip_if (ditval <= 0.0);
00329
00330 lamp_flux = median / ditval;
00331
00332
00333 aver = diff;
00334
00335 } else {
00336 cpl_image_delete(diff);
00337 diff = NULL;
00338
00339 cpl_image_delete(image0);
00340
00341 image0 = i == 2 ? prev : NULL;
00342 }
00343
00344 }
00345
00346 if (i > 1 && i % 2 != 0) {
00347
00348 irplib_check(cpl_image_subtract(prev, image),
00349 "Could not correct for the dark");
00350
00351
00352 irplib_check(cpl_image_add(aver, prev),
00353 "Could not sum up the dark corrected images");
00354
00355 cpl_image_delete(image);
00356 cpl_image_delete(prev);
00357 prev = NULL;
00358 } else {
00359 prev = image;
00360 }
00361 image = NULL;
00362 }
00363
00364
00365 cpl_msg_info(cpl_func, "Computing the QC parameters");
00366
00367
00368 square = std_diff[1] - std_diff[2];
00369 if (square != 0.0) square = 2.0*mean/square;
00370 gain = square > 0.0 ? sqrt(square) : 0.0;
00371
00372
00373 square = std_diff[0] - std_diff[1] - std_diff[2];
00374 fp_noise = square > 0.0 ? sqrt(square) : 0.0;
00375
00376
00377 cpl_msg_info(cpl_func, "Gain: %g", gain);
00378 cpl_msg_info(cpl_func, "Noise: %g", fp_noise);
00379 cpl_msg_info(cpl_func, "Lamp flux: %g", lamp_flux);
00380
00381
00382 cpl_msg_info(cpl_func, "Average the dark corrected frames");
00383 irplib_check(cpl_image_divide_scalar(aver, (double)(nfiles/2)),
00384 "Could not average the %d dark corrected frames", nfiles/2);
00385
00386
00387 irplib_check(mean
00388 = cpl_image_get_mean_window(aver, rej_left,
00389 cpl_image_get_size_x(aver)
00390 -rej_right,
00391 rej_bottom,
00392 cpl_image_get_size_y(aver)
00393 -rej_top);
00394 cpl_image_divide_scalar(aver, mean),
00395 "Could not average the %d dark corrected frames", nfiles/2);
00396
00397
00398 skip_if(cpl_propertylist_append_double(qclist, "ESO QC GAIN", gain));
00399 skip_if(cpl_propertylist_append_double(qclist, "ESO QC FPNOISE", fp_noise));
00400 skip_if(cpl_propertylist_append_double(qclist, "ESO QC LAMPFLUX",
00401 lamp_flux));
00402
00403 end_skip;
00404
00405 if (cpl_error_get_code()) {
00406 cpl_image_delete(aver);
00407 aver = NULL;
00408 }
00409
00410 cpl_image_delete(image);
00411 cpl_image_delete(diff);
00412 cpl_image_delete(prev);
00413 cpl_image_delete(image0);
00414
00415 return aver;
00416 }
00417
00418
00419
00427
00428 static cpl_error_code naco_img_lampflat_qc(cpl_propertylist * qclist,
00429 cpl_propertylist * paflist,
00430 const irplib_framelist * rawframes)
00431 {
00432
00433 const cpl_propertylist * reflist
00434 = irplib_framelist_get_propertylist_const(rawframes, 0);
00435 const char pafcopy[] = "^(" NACO_PFITS_REGEXP_LAMPFLAT_PAF ")$";
00436
00437
00438 bug_if (0);
00439
00440
00441
00442 skip_if (cpl_propertylist_copy_property_regexp(paflist, reflist, pafcopy,
00443 0));
00444 skip_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
00469
00470 static cpl_error_code naco_img_lampflat_save(cpl_frameset * set_tot,
00471 const cpl_parameterlist * parlist,
00472 const cpl_propertylist * qclist,
00473 const cpl_propertylist * paflist,
00474 const cpl_image * flat,
00475 int set_nb,
00476 const irplib_framelist * rawframes)
00477 {
00478 cpl_frameset * proframes = irplib_frameset_cast(rawframes);
00479 char * filename = NULL;
00480
00481
00482
00483
00484 bug_if (0);
00485
00486
00487 filename = cpl_sprintf(RECIPE_STRING "_set%02d" CPL_DFS_FITS, set_nb);
00488 skip_if (irplib_dfs_save_image(set_tot, parlist, proframes, flat,
00489 CPL_BPP_IEEE_FLOAT, RECIPE_STRING,
00490 NACO_IMG_LAMPFLAT_RES, qclist, NULL,
00491 naco_pipe_id, filename));
00492
00493 cpl_free(filename);
00494 filename = cpl_sprintf(RECIPE_STRING "_set%02d" CPL_DFS_PAF, set_nb);
00495 skip_if (cpl_dfs_save_paf("NACO", RECIPE_STRING, paflist, filename));
00496
00497 end_skip;
00498
00499 cpl_free(filename);
00500 cpl_frameset_delete(proframes);
00501
00502 return cpl_error_get_code();
00503
00504 }
00505
00506
00507
00517
00518 static char * naco_img_lampflat_make_tag(const cpl_frame* self,
00519 const cpl_propertylist * plist,
00520 int dummy)
00521 {
00522
00523 char * tag = NULL;
00524 const char * filter;
00525 const char * opti3;
00526 const char * opti7;
00527 const char * rom;
00528 const char * mode;
00529 double dit;
00530
00531
00532 skip_if (cpl_error_get_code());
00533
00534 skip_if(self == NULL);
00535 skip_if(plist == NULL);
00536 skip_if(dummy < 0);
00537
00538
00539
00540 filter = naco_pfits_get_filter(plist);
00541 skip_if(cpl_error_get_code());
00542
00543
00544 opti7 = naco_pfits_get_opti7_name(plist);
00545 skip_if(cpl_error_get_code());
00546
00547
00548 opti3 = naco_pfits_get_opti3_name(plist);
00549 skip_if(cpl_error_get_code());
00550
00551
00552 rom = naco_pfits_get_rom_name(plist);
00553 skip_if(cpl_error_get_code());
00554
00555
00556 mode = naco_pfits_get_mode(plist);
00557 skip_if(cpl_error_get_code());
00558
00559
00560 dit = naco_pfits_get_dit(plist);
00561 skip_if(cpl_error_get_code());
00562
00563
00564 tag = cpl_sprintf("%s:%s:%s:%s:%s:%.5f", filter,
00565 opti7, opti3, rom, mode, dit);
00566 bug_if(tag == NULL);
00567
00568 end_skip;
00569
00570 if (cpl_error_get_code()) {
00571 cpl_free(tag);
00572 tag = NULL;
00573 }
00574
00575 return tag;
00576
00577 }