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 #include "naco_spc.h"
00039
00040
00041
00042
00043
00044 #define RECIPE_STRING "naco_spc_lampflat"
00045
00046 #ifndef NACO_SPC_MEDIAN_XSIZE
00047 #define NACO_SPC_MEDIAN_XSIZE 200
00048 #endif
00049
00050 #ifndef NACO_SPC_MEDIAN_YSIZE
00051 #define NACO_SPC_MEDIAN_YSIZE NACO_SPC_MEDIAN_XSIZE
00052 #endif
00053
00054
00055
00056
00057
00058 static cpl_image * naco_spc_lampflat_reduce(cpl_propertylist *,
00059 const irplib_framelist *,
00060 const cpl_parameterlist *);
00061
00062 static cpl_error_code naco_spc_lampflat_qc(cpl_propertylist *,
00063 cpl_propertylist *,
00064 const irplib_framelist *);
00065
00066 static cpl_error_code naco_spc_lampflat_save(cpl_frameset *,
00067 const cpl_parameterlist *,
00068 const cpl_propertylist *,
00069 const cpl_propertylist *,
00070 const cpl_image *,
00071 int, const irplib_framelist *);
00072
00073 NACO_RECIPE_DEFINE(naco_spc_lampflat,
00074 NACO_PARAM_REJBORD | NACO_PARAM_HOT_LIM | NACO_PARAM_COLD_LIM,
00075 "Spectrocopic flat recipe using a lamp",
00076 RECIPE_STRING " -- NACO spectrocopy flat-field creation from "
00077 "lamp images.\n"
00078 "The files listed in the Set Of Frames (sof-file) "
00079 "must be tagged:\n"
00080 "NACO-raw-file.fits " NACO_SPC_LAMPFLAT_RAW "\n"
00081 "\n"
00082 NACO_SPC_MAN_MODESPLIT "\n\n"
00083 "Furthermore, the input set of frames must have values of "
00084 "the FITS key "
00085 NACO_PFITS_INT_LAMP2 " that of zero for off-frames and "
00086 "non-zero for on-frames.\n");
00087
00088
00089
00093
00094
00095
00096
00097
00098
00099
00106
00107 static int naco_spc_lampflat(cpl_frameset * framelist,
00108 const cpl_parameterlist * parlist)
00109 {
00110 cpl_errorstate cleanstate = cpl_errorstate_get();
00111 irplib_framelist * allframes = NULL;
00112 irplib_framelist * rawframes = NULL;
00113 irplib_framelist * f_one = NULL;
00114 const char ** taglist = NULL;
00115 cpl_image * lamp_flat = NULL;
00116 cpl_propertylist * qclist = cpl_propertylist_new();
00117 cpl_propertylist * paflist = cpl_propertylist_new();
00118 int nb_good = 0;
00119 int nsets;
00120 int i;
00121
00122
00123
00124 skip_if (naco_dfs_set_groups(framelist));
00125
00126 allframes = irplib_framelist_cast(framelist);
00127 skip_if(allframes == NULL);
00128
00129 rawframes = irplib_framelist_extract(allframes, NACO_SPC_LAMPFLAT_RAW);
00130 skip_if(rawframes == NULL);
00131 irplib_framelist_empty(allframes);
00132
00133 skip_if(irplib_framelist_load_propertylist_all(rawframes, 0, "^("
00134 NACO_PFITS_REGEXP_SPCFLAT "|"
00135 NACO_PFITS_REGEXP_SPCFLAT_PAF
00136 ")$", CPL_FALSE));
00137
00138 taglist = naco_framelist_set_tag(rawframes, naco_spc_make_tag, &nsets);
00139 skip_if(taglist == NULL);
00140
00141 cpl_msg_info(cpl_func, "Identified %d setting(s) in %d frames",
00142 nsets, irplib_framelist_get_size(rawframes));
00143
00144
00145 for (i=0 ; i < nsets ; i++) {
00146
00147
00148 cpl_msg_info(cpl_func, "Reducing data set %d of %d", i+1, nsets);
00149
00150
00151 f_one = irplib_framelist_extract(rawframes, taglist[i]);
00152
00153
00154 skip_if(irplib_framelist_set_tag_all(f_one, NACO_SPC_LAMPFLAT_RAW));
00155
00156 cpl_msg_info(cpl_func, "Reducing frame set %d of %d (size=%d) with "
00157 "setting: %s", i+1, nsets,
00158 irplib_framelist_get_size(f_one), taglist[i]);
00159
00160 skip_if (f_one == NULL);
00161
00162 lamp_flat = naco_spc_lampflat_reduce(qclist, f_one, parlist);
00163
00164
00165 if (lamp_flat == NULL) {
00166 if (nsets > 1)
00167 irplib_error_recover(cleanstate, "Could not compute the flat for "
00168 "this setting");
00169 } else {
00170 skip_if(naco_spc_lampflat_qc(qclist, paflist, f_one));
00171
00172 bug_if (cpl_propertylist_append_string(paflist, CPL_DFS_PRO_CATG,
00173 NACO_CALIB_SPCFLAT));
00174 skip_if(naco_spc_lampflat_save(framelist, parlist, qclist, paflist,
00175 lamp_flat, i+1, f_one));
00176 cpl_image_delete(lamp_flat);
00177 lamp_flat = NULL;
00178 nb_good++;
00179 }
00180 cpl_propertylist_empty(qclist);
00181 cpl_propertylist_empty(paflist);
00182 irplib_framelist_delete(f_one);
00183 f_one = NULL;
00184 }
00185
00186 irplib_ensure(nb_good > 0, CPL_ERROR_DATA_NOT_FOUND,
00187 "None of the %d sets could be reduced", nsets);
00188
00189 end_skip;
00190
00191 cpl_free(taglist);
00192 cpl_image_delete(lamp_flat);
00193 irplib_framelist_delete(f_one);
00194 irplib_framelist_delete(allframes);
00195 irplib_framelist_delete(rawframes);
00196 cpl_propertylist_delete(qclist);
00197 cpl_propertylist_delete(paflist);
00198
00199 return cpl_error_get_code();
00200 }
00201
00202
00210
00211 static cpl_image * naco_spc_lampflat_reduce(cpl_propertylist * qclist,
00212 const irplib_framelist * framelist,
00213 const cpl_parameterlist * parlist)
00214 {
00215 cpl_image * self = NULL;
00216 cpl_imagelist * difflist = cpl_imagelist_new();
00217 cpl_mask * bpm = NULL;
00218 cpl_vector * medians = NULL;
00219 const double hot_thresh
00220 = naco_parameterlist_get_double(parlist, RECIPE_STRING,
00221 NACO_PARAM_HOT_LIM);
00222 const double cold_thresh = 1.0 /
00223 naco_parameterlist_get_double(parlist, RECIPE_STRING,
00224 NACO_PARAM_COLD_LIM);
00225 const char * rej_bord
00226 = naco_parameterlist_get_string(parlist, RECIPE_STRING,
00227 NACO_PARAM_REJBORD);
00228 cpl_propertylist * lampkeys = cpl_propertylist_new();
00229 int rej_left, rej_right, rej_bottom, rej_top;
00230 int nflat, nbad;
00231 int ndiff, idiff;
00232
00233
00234 skip_if (0);
00235 bug_if (qclist == NULL);
00236 bug_if (framelist == NULL);
00237 bug_if (parlist == NULL);
00238
00239 skip_if(cold_thresh <= 0.0);
00240 skip_if(cold_thresh >= 1.0);
00241 skip_if(hot_thresh <= 1.0);
00242
00243 skip_if (sscanf(rej_bord, "%d %d %d %d",
00244 &rej_left, &rej_right, &rej_bottom, &rej_top) != 4);
00245
00246
00247 bug_if(cpl_propertylist_append_int(lampkeys, NACO_PFITS_INT_LAMP2, 1));
00248 bug_if(cpl_propertylist_append_int(lampkeys, NACO_PFITS_BOOL_LAMP1, 0));
00249
00250 skip_if(naco_imagelist_load_diff(difflist, framelist, lampkeys));
00251
00252 ndiff = cpl_imagelist_get_size(difflist);
00253
00254 medians = cpl_vector_new(ndiff);
00255
00256 bug_if(0);
00257
00258 for (idiff = 0, nflat = 0; idiff < ndiff; idiff++) {
00259 cpl_image * diff = cpl_imagelist_get(difflist, nflat);
00260 const int nx = cpl_image_get_size_x(diff);
00261 const int ny = cpl_image_get_size_y(diff);
00262
00263 double median;
00264 const double mean
00265 = cpl_image_get_mean_window(diff,
00266 rej_left, nx - rej_right,
00267 rej_bottom, ny - rej_top);
00268
00269 skip_if(0);
00270
00271 if (mean <= 0.0) {
00272 cpl_msg_warning(cpl_func, "Ignoring difference image %d with an "
00273 "invalid mean: %g", 1+idiff, mean);
00274 cpl_image_delete(cpl_imagelist_unset(difflist, nflat));
00275 continue;
00276 }
00277
00278
00279 median = cpl_image_get_median_window(diff,
00280 (nx-NACO_SPC_MEDIAN_XSIZE)/2,
00281 (ny-NACO_SPC_MEDIAN_YSIZE)/2,
00282 (nx+NACO_SPC_MEDIAN_XSIZE)/2,
00283 (ny+NACO_SPC_MEDIAN_YSIZE)/2);
00284 skip_if(0);
00285
00286
00287 bug_if(cpl_image_divide_scalar(diff, mean));
00288
00289
00290 bpm = cpl_mask_threshold_image_create(diff, cold_thresh, hot_thresh);
00291 bug_if(bpm == NULL);
00292
00293 if (cpl_mask_is_empty(bpm)) {
00294 cpl_msg_warning(cpl_func, "Ignoring difference image %d with no "
00295 "good pixels", 1+idiff);
00296 cpl_mask_delete(bpm);
00297 bpm = NULL;
00298 cpl_image_delete(cpl_imagelist_unset(difflist, nflat));
00299 continue;
00300 }
00301
00302 bug_if(cpl_mask_not(bpm));
00303
00304 cpl_msg_info(cpl_func, "Difference image %d has %d bad pixels", 1+idiff,
00305 cpl_mask_count(bpm));
00306
00307
00308 bug_if(cpl_mask_or(cpl_image_get_bpm(diff), bpm));
00309
00310 cpl_mask_delete(bpm);
00311 bpm = NULL;
00312
00313 bug_if (cpl_vector_set(medians, nflat, median));
00314
00315 nflat++;
00316 }
00317
00318 bug_if(nflat != cpl_imagelist_get_size(difflist));
00319
00320 error_if(nflat == 0, CPL_ERROR_DATA_NOT_FOUND,
00321 "The %d difference images are all invalid", ndiff);
00322
00323 self = cpl_imagelist_collapse_create(difflist);
00324 bug_if(0);
00325
00326 nbad = cpl_image_count_rejected(self);
00327 bug_if(0);
00328
00329 if (nbad > 0) {
00330 cpl_msg_info(cpl_func, "Setting %d bad pixels in master flat to 1.0",
00331 nbad);
00332 bug_if(cpl_image_fill_rejected(self, 1.0));
00333 }
00334
00335 bug_if(cpl_vector_set_size(medians, nflat));
00336
00337 bug_if(cpl_propertylist_append_double(qclist, "ESO QC SPECFLAT NCOUNTS",
00338 cpl_vector_get_mean(medians)));
00339 bug_if(cpl_propertylist_append_double(qclist, "ESO QC SPECFLAT STDEV",
00340 cpl_vector_get_stdev(medians)));
00341
00342 end_skip;
00343
00344 if (cpl_error_get_code()) {
00345 cpl_image_delete(self);
00346 self = NULL;
00347 }
00348
00349 cpl_propertylist_delete(lampkeys);
00350 cpl_imagelist_delete(difflist);
00351 cpl_mask_delete(bpm);
00352 cpl_vector_delete(medians);
00353
00354 return self;
00355 }
00356
00357
00358
00366
00367 static cpl_error_code naco_spc_lampflat_qc(cpl_propertylist * qclist,
00368 cpl_propertylist * paflist,
00369 const irplib_framelist * rawframes)
00370 {
00371
00372 const cpl_propertylist * reflist
00373 = irplib_framelist_get_propertylist_const(rawframes, 0);
00374 const char pafcopy[] = "^(" NACO_PFITS_REGEXP_SPCFLAT_PAF ")$";
00375
00376
00377 bug_if (0);
00378
00379
00380
00381 skip_if (cpl_propertylist_copy_property_regexp(paflist, reflist, pafcopy,
00382 0));
00383 skip_if (cpl_propertylist_append(paflist, qclist));
00384
00385 bug_if (cpl_propertylist_copy_property_regexp(qclist, reflist, "^("
00386 IRPLIB_PFITS_REGEXP_RECAL_LAMP
00387 ")$", 0));
00388
00389 end_skip;
00390
00391 return cpl_error_get_code();
00392 }
00393
00394
00406
00407 static cpl_error_code naco_spc_lampflat_save(cpl_frameset * set_tot,
00408 const cpl_parameterlist * parlist,
00409 const cpl_propertylist * qclist,
00410 const cpl_propertylist * paflist,
00411 const cpl_image * flat,
00412 int set_nb,
00413 const irplib_framelist * rawframes)
00414 {
00415 cpl_frameset * proframes = irplib_frameset_cast(rawframes);
00416 char * filename = NULL;
00417
00418
00419
00420
00421 bug_if (0);
00422
00423
00424 filename = cpl_sprintf(RECIPE_STRING "_set%02d" CPL_DFS_FITS, set_nb);
00425 skip_if (irplib_dfs_save_image(set_tot, parlist, proframes, flat,
00426 CPL_BPP_IEEE_FLOAT, RECIPE_STRING,
00427 NACO_CALIB_SPCFLAT, qclist, NULL,
00428 naco_pipe_id, filename));
00429
00430 #ifdef NACO_SAVE_PAF
00431 cpl_free(filename);
00432 filename = cpl_sprintf(RECIPE_STRING "_set%02d" CPL_DFS_PAF, set_nb);
00433 skip_if (cpl_dfs_save_paf("NACO", RECIPE_STRING, paflist, filename));
00434 #else
00435 bug_if(paflist == NULL);
00436 #endif
00437
00438 end_skip;
00439
00440 cpl_free(filename);
00441 cpl_frameset_delete(proframes);
00442
00443 return cpl_error_get_code();
00444
00445 }