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 "crires_recipe.h"
00037
00038 #include "crires_combine.h"
00039
00040
00041
00042
00043
00044 #define RECIPE_STRING "crires_win_flat"
00045
00046
00047
00048
00049
00050 static cpl_imagelist * crires_win_flat_reduce(cpl_frameset *, const char *) ;
00051 static cpl_imagelist * crires_win_flat_bpm(cpl_imagelist *, double,
00052 double, double) ;
00053 static int crires_win_flat_save(const cpl_imagelist *, const cpl_imagelist *,
00054 int, cpl_frameset *, const cpl_parameterlist *, cpl_frameset *) ;
00055 static int crires_win_flat_compare(const cpl_frame *, const cpl_frame *) ;
00056
00057 static char crires_win_flat_description[] =
00058 "crires_win_flat -- Flat-field recipe in Windowing mode\n"
00059 "The files listed in the Set Of Frames (sof-file) must be tagged:\n"
00060 "raw-file.fits "CRIRES_WIN_FLAT_RAW" or\n"
00061 "dark-file.fits "CRIRES_CALPRO_DARK".\n" ;
00062
00063 CRIRES_RECIPE_DEFINE(crires_win_flat,
00064 CRIRES_PARAM_THRESHOLDS |
00065 CRIRES_PARAM_BPM_RATE |
00066 CRIRES_PARAM_REPLACE |
00067 CRIRES_PARAM_KAPPA_SIGCLIP |
00068 CRIRES_PARAM_COLLAPSE_METH,
00069 "Flatfield recipe in Windowing mode",
00070 crires_win_flat_description) ;
00071
00072
00073
00074
00075
00076 static struct {
00077
00078 double bpm_low ;
00079 double bpm_high ;
00080 double bpm_lines_ratio ;
00081 int replace_flag ;
00082 double kappa_sigclip ;
00083 crires_collapse_method coll_meth ;
00084
00085 int bpm_nb[CRIRES_NB_DETECTORS] ;
00086 double flat_mean[CRIRES_NB_DETECTORS] ;
00087 double flat_stdev[CRIRES_NB_DETECTORS] ;
00088 double flat_flux[CRIRES_NB_DETECTORS] ;
00089 double flat_master_rms[CRIRES_NB_DETECTORS] ;
00090 } crires_win_flat_config ;
00091
00092
00093
00094
00095
00096
00103
00104 static int crires_win_flat(
00105 cpl_frameset * frameset,
00106 const cpl_parameterlist * parlist)
00107 {
00108 const char * sval ;
00109 cpl_size * labels ;
00110 cpl_size nlabels ;
00111 cpl_frameset * rawframes ;
00112 const char * dark ;
00113 cpl_imagelist * flat ;
00114 cpl_frameset * flat_one ;
00115 cpl_imagelist * bpm ;
00116 int i ;
00117
00118
00119 rawframes = NULL ;
00120 for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
00121 crires_win_flat_config.bpm_nb[i] = -1 ;
00122 crires_win_flat_config.flat_mean[i] = -1.0 ;
00123 crires_win_flat_config.flat_stdev[i] = -1.0 ;
00124 crires_win_flat_config.flat_flux[i] = -1.0 ;
00125 crires_win_flat_config.flat_master_rms[i] = -1.0 ;
00126 }
00127
00128
00129 sval = crires_parameterlist_get_string(parlist, RECIPE_STRING,
00130 CRIRES_PARAM_THRESHOLDS) ;
00131 if (sscanf(sval, "%lg,%lg",
00132 &crires_win_flat_config.bpm_low,
00133 &crires_win_flat_config.bpm_high)!=2) {
00134 return -1 ;
00135 }
00136 crires_win_flat_config.replace_flag = crires_parameterlist_get_bool(
00137 parlist, RECIPE_STRING, CRIRES_PARAM_REPLACE) ;
00138 crires_win_flat_config.bpm_lines_ratio = crires_parameterlist_get_double(
00139 parlist, RECIPE_STRING, CRIRES_PARAM_BPM_RATE) ;
00140 crires_win_flat_config.kappa_sigclip = crires_parameterlist_get_double(
00141 parlist, RECIPE_STRING, CRIRES_PARAM_KAPPA_SIGCLIP) ;
00142 sval = crires_parameterlist_get_string(parlist, RECIPE_STRING,
00143 CRIRES_PARAM_COLLAPSE_METH) ;
00144 if (!strcmp(sval, "avg"))
00145 crires_win_flat_config.coll_meth = CRIRES_COLLAPSE_AVG ;
00146 else if (!strcmp(sval, "med"))
00147 crires_win_flat_config.coll_meth = CRIRES_COLLAPSE_MED ;
00148 else if (!strcmp(sval, "sig"))
00149 crires_win_flat_config.coll_meth = CRIRES_COLLAPSE_SIG ;
00150 else {
00151 cpl_msg_error(__func__, "Invalid collapse method specified");
00152 return -1;
00153 }
00154
00155
00156 if (crires_dfs_set_groups(frameset, "crires_win_flat")) {
00157 cpl_msg_error(__func__, "Cannot identify RAW and CALIB frames") ;
00158 return -1 ;
00159 }
00160
00161
00162 dark = crires_extract_filename(frameset, CRIRES_CALPRO_DARK_WIN) ;
00163
00164
00165 if ((rawframes = crires_extract_frameset(frameset,
00166 CRIRES_WIN_FLAT_RAW)) == NULL) {
00167 cpl_msg_error(__func__, "No raw frame in input") ;
00168 return -1 ;
00169 }
00170
00171
00172 if ((labels = cpl_frameset_labelise(rawframes, crires_win_flat_compare,
00173 &nlabels)) == NULL) {
00174 cpl_msg_error(__func__, "Cannot labelise input frames") ;
00175 cpl_frameset_delete(rawframes) ;
00176 return -1 ;
00177 }
00178
00179
00180 for (i=0 ; i<(int)nlabels ; i++) {
00181
00182 cpl_msg_info(__func__, "Reduce data set %d / %"CPL_SIZE_FORMAT,
00183 i+1, nlabels);
00184 cpl_msg_indent_more() ;
00185 flat_one = cpl_frameset_extract(rawframes, labels, (cpl_size)i) ;
00186 flat = crires_win_flat_reduce(flat_one, dark) ;
00187 cpl_msg_indent_less() ;
00188
00189
00190 cpl_msg_info(__func__, "Save the products") ;
00191 cpl_msg_indent_more() ;
00192 if (flat == NULL) {
00193 cpl_msg_warning(__func__, "Cannot reduce set nb %d", i+1) ;
00194 } else {
00195 if ((bpm = crires_win_flat_bpm(flat,
00196 crires_win_flat_config.bpm_low,
00197 crires_win_flat_config.bpm_high,
00198 crires_win_flat_config.bpm_lines_ratio)) == NULL) {
00199 cpl_msg_warning(__func__, "Cannot create bad pixels map") ;
00200 }
00201 crires_win_flat_save(flat, bpm, i+1, flat_one, parlist, frameset) ;
00202 cpl_imagelist_delete(flat) ;
00203 cpl_imagelist_delete(bpm) ;
00204 }
00205 cpl_msg_indent_less() ;
00206 cpl_frameset_delete(flat_one) ;
00207 }
00208 cpl_frameset_delete(rawframes) ;
00209 cpl_free(labels) ;
00210
00211
00212 if (cpl_error_get_code()) return -1 ;
00213 else return 0 ;
00214 }
00215
00216
00223
00224 static cpl_imagelist * crires_win_flat_reduce(
00225 cpl_frameset * flatframes,
00226 const char * dark)
00227 {
00228 cpl_propertylist * plist ;
00229 cpl_frame * ref_frame ;
00230 const char * fname ;
00231 int nframes ;
00232 double dit_frame, dit_dark ;
00233 cpl_imagelist * in ;
00234 cpl_imagelist * out ;
00235 cpl_vector * medians ;
00236 double median ;
00237 cpl_image * ima ;
00238 int i, j ;
00239
00240
00241 if (flatframes == NULL) return NULL ;
00242
00243
00244 nframes = cpl_frameset_get_size(flatframes) ;
00245
00246
00247 ref_frame = cpl_frameset_get_frame(flatframes, 0) ;
00248 fname = cpl_frame_get_filename(ref_frame) ;
00249 if ((plist=cpl_propertylist_load(fname, 0)) == NULL) {
00250 cpl_msg_error(__func__, "Getting header from RAW file");
00251 cpl_msg_indent_less() ;
00252 return NULL ;
00253 }
00254 dit_frame = crires_pfits_get_dit(plist) ;
00255 cpl_propertylist_delete(plist) ;
00256 if (cpl_error_get_code()) {
00257 cpl_msg_error(__func__, "Cannot get the DIT from RAW file") ;
00258 cpl_msg_indent_less() ;
00259 return NULL ;
00260 }
00261 cpl_msg_info(__func__, "DIT value: %g sec.", dit_frame) ;
00262
00263
00264 if (dark != NULL) {
00265 cpl_msg_info(__func__, "Verify the dark DIT") ;
00266 cpl_msg_indent_more() ;
00267 if ((plist=cpl_propertylist_load(dark, 0)) == NULL) {
00268 cpl_msg_error(__func__, "Getting header from DARK");
00269 cpl_msg_indent_less() ;
00270 return NULL ;
00271 }
00272 dit_dark = crires_pfits_get_dit(plist) ;
00273 cpl_propertylist_delete(plist) ;
00274 if (cpl_error_get_code()) {
00275 cpl_msg_error(__func__, "Cannot get the DIT from DARK") ;
00276 cpl_msg_indent_less() ;
00277 return NULL ;
00278 }
00279 if (fabs(dit_dark-dit_frame) > 1e-5) {
00280 cpl_msg_error(__func__, "Mismatch RAW DIT (%g) / DARK DIT (%g)",
00281 dit_frame, dit_dark) ;
00282 cpl_msg_indent_less() ;
00283 return NULL ;
00284 }
00285 cpl_msg_indent_less() ;
00286
00287
00288 if (crire_stripe_keys_mismatch(fname, dark)) {
00289 cpl_msg_error(__func__,
00290 "Mismatch of STRIPE keys with the dark frame") ;
00291 return NULL ;
00292 }
00293 }
00294
00295
00296 out = cpl_imagelist_new() ;
00297
00298
00299 for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
00300 cpl_msg_info(__func__, "Compute the MASTER FLAT for chip nb %d", i+1) ;
00301 cpl_msg_indent_more() ;
00302
00303
00304 in = crires_load_frameset(flatframes, CRIRES_ILLUM_FULL_DETECTOR,
00305 i+1, CPL_TYPE_FLOAT) ;
00306
00307
00308 if (crires_calib_chip_list(in, CRIRES_ILLUM_FULL_DETECTOR, i+1,
00309 NULL, dark, NULL, NULL, dit_frame)) {
00310 cpl_msg_error(__func__, "Cannot apply the calibrations") ;
00311 cpl_imagelist_delete(in) ;
00312 return NULL ;
00313 }
00314
00315
00316 medians = cpl_vector_new(nframes) ;
00317
00318
00319 cpl_msg_info(__func__, "Normalise with the median") ;
00320 for (j=0 ; j<nframes ; j++) {
00321 median = cpl_image_get_median(cpl_imagelist_get(in, j)) ;
00322 if (cpl_error_get_code()) {
00323 cpl_msg_error(__func__, "Cannot compute the median") ;
00324 cpl_imagelist_delete(in) ;
00325 cpl_vector_delete(medians) ;
00326 return NULL ;
00327 }
00328 cpl_vector_set(medians, j, median) ;
00329 if (fabs(median) > 1e-3)
00330 cpl_image_divide_scalar(cpl_imagelist_get(in, j), median) ;
00331 }
00332
00333
00334 crires_win_flat_config.flat_mean[i] = cpl_vector_get_mean(medians) ;
00335 if (cpl_vector_get_size(medians) > 1)
00336 crires_win_flat_config.flat_stdev[i]=cpl_vector_get_stdev(medians);
00337 else
00338 crires_win_flat_config.flat_stdev[i] = -1.0 ;
00339 crires_win_flat_config.flat_flux[i] =
00340 crires_win_flat_config.flat_mean[i] / dit_frame ;
00341
00342
00343 if ((ima = crires_combine_collapse_imagelist(in, medians,
00344 crires_win_flat_config.kappa_sigclip,
00345 i+1,
00346 crires_win_flat_config.coll_meth)) == NULL) {
00347 cpl_msg_error(__func__, "Cannot average the flats") ;
00348 cpl_imagelist_delete(in) ;
00349 cpl_vector_delete(medians) ;
00350 return NULL ;
00351 }
00352 cpl_vector_delete(medians) ;
00353 cpl_imagelist_delete(in) ;
00354
00355
00356 crires_win_flat_config.flat_master_rms[i] =
00357 cpl_image_get_stdev(ima) ;
00358
00359
00360 cpl_imagelist_set(out, ima, i) ;
00361 cpl_msg_indent_less() ;
00362 }
00363
00364 return out ;
00365 }
00366
00367
00376
00377 static cpl_imagelist * crires_win_flat_bpm(
00378 cpl_imagelist * flat,
00379 double low,
00380 double high,
00381 double bad_per_line_limit)
00382 {
00383 cpl_imagelist * bpm ;
00384 int nima ;
00385 cpl_image * bpm_cur ;
00386 cpl_mask * mask_cur ;
00387 cpl_binary * pmask_cur ;
00388 int nx, ny, cur_bp_nb ;
00389 int i, j, k ;
00390
00391
00392 if (flat == NULL) return NULL ;
00393
00394
00395 nima = cpl_imagelist_get_size(flat) ;
00396
00397
00398 bpm = cpl_imagelist_new() ;
00399
00400
00401 for (i=0 ; i<nima ; i++) {
00402
00403 if ((mask_cur = cpl_mask_threshold_image_create(
00404 cpl_imagelist_get(flat, i), low, high)) == NULL) {
00405 cpl_msg_error(__func__, "Cannot create bad pixels map") ;
00406 cpl_imagelist_delete(bpm) ;
00407 return NULL ;
00408 }
00409 cpl_mask_not(mask_cur) ;
00410
00411
00412
00413
00414
00415
00416
00417 nx = cpl_mask_get_size_x(mask_cur) ;
00418 ny = cpl_mask_get_size_y(mask_cur) ;
00419 pmask_cur = cpl_mask_get_data(mask_cur) ;
00420 for (j=0 ; j<ny ; j++) {
00421 cur_bp_nb = cpl_mask_count_window(mask_cur, 1, j+1, nx, j+1) ;
00422
00423 if (cur_bp_nb > bad_per_line_limit * nx) {
00424
00425 for (k=0 ; k<nx ; k++) {
00426 pmask_cur[k+j*nx] = CPL_BINARY_0 ;
00427 }
00428 }
00429 }
00430
00431
00432 bpm_cur = cpl_image_new_from_mask(mask_cur) ;
00433 crires_win_flat_config.bpm_nb[i] = cpl_mask_count(mask_cur) ;
00434 cpl_mask_delete(mask_cur) ;
00435 cpl_imagelist_set(bpm, bpm_cur, i) ;
00436
00437
00438 if (crires_win_flat_config.replace_flag) {
00439 cpl_image_threshold(cpl_imagelist_get(flat, i),
00440 low, high, 1.0, 1.0) ;
00441 }
00442 }
00443 return bpm ;
00444 }
00445
00446
00456
00457 static int crires_win_flat_save(
00458 const cpl_imagelist * flat,
00459 const cpl_imagelist * bpm,
00460 int set_nb,
00461 cpl_frameset * set,
00462 const cpl_parameterlist * parlist,
00463 cpl_frameset * set_tot)
00464 {
00465 cpl_propertylist ** qclists ;
00466 const cpl_frame * ref_frame ;
00467 char * filename ;
00468 cpl_propertylist * inputlist ;
00469 const char * recipe_name = "crires_win_flat" ;
00470 int i ;
00471
00472
00473 ref_frame = irplib_frameset_get_first_from_group(set, CPL_FRAME_GROUP_RAW) ;
00474
00475
00476 qclists = cpl_malloc(CRIRES_NB_DETECTORS * sizeof(cpl_propertylist*)) ;
00477 for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
00478 qclists[i] = cpl_propertylist_new() ;
00479 cpl_propertylist_append_int(qclists[i], "ESO QC NBBAD",
00480 crires_win_flat_config.bpm_nb[i]) ;
00481 cpl_propertylist_append_double(qclists[i], "ESO QC FLAT MEAN",
00482 crires_win_flat_config.flat_mean[i]) ;
00483 cpl_propertylist_append_double(qclists[i], "ESO QC FLAT STDEV",
00484 crires_win_flat_config.flat_stdev[i]) ;
00485 cpl_propertylist_append_double(qclists[i], "ESO QC FLAT FLUX",
00486 crires_win_flat_config.flat_flux[i]) ;
00487 cpl_propertylist_append_double(qclists[i], "ESO QC FLAT MASTER RMS",
00488 crires_win_flat_config.flat_master_rms[i]) ;
00489
00490
00491 inputlist = cpl_propertylist_load_regexp(
00492 cpl_frame_get_filename(ref_frame), i+1,
00493 CRIRES_HEADER_EXT_FORWARD, 0) ;
00494 cpl_propertylist_copy_property_regexp(qclists[i], inputlist,
00495 CRIRES_HEADER_EXT_FORWARD, 0) ;
00496 cpl_propertylist_delete(inputlist) ;
00497 }
00498
00499
00500 filename = cpl_sprintf("%s_set%02d.fits", recipe_name, set_nb) ;
00501 crires_image_save(set_tot,
00502 parlist,
00503 set,
00504 flat,
00505 recipe_name,
00506 CRIRES_CALPRO_FLAT_WIN,
00507 CRIRES_PROTYPE_FLAT,
00508 CRIRES_ILLUM_FULL_DETECTOR,
00509 NULL,
00510 (const cpl_propertylist**)qclists,
00511 PACKAGE "/" PACKAGE_VERSION,
00512 filename) ;
00513 cpl_free(filename) ;
00514
00515
00516 if (bpm != NULL) {
00517 filename = cpl_sprintf("%s_set%02d_bpm.fits", recipe_name, set_nb) ;
00518 crires_image_save(set_tot,
00519 parlist,
00520 set,
00521 bpm,
00522 recipe_name,
00523 CRIRES_CALPRO_BPM_WIN,
00524 CRIRES_PROTYPE_BPM,
00525 CRIRES_ILLUM_FULL_DETECTOR,
00526 NULL,
00527 (const cpl_propertylist**)qclists,
00528 PACKAGE "/" PACKAGE_VERSION,
00529 filename) ;
00530 cpl_free(filename) ;
00531 }
00532
00533
00534 for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
00535 cpl_propertylist_delete(qclists[i]) ;
00536 }
00537 cpl_free(qclists) ;
00538 return 0;
00539 }
00540
00541
00548
00549 static int crires_win_flat_compare(
00550 const cpl_frame * frame1,
00551 const cpl_frame * frame2)
00552 {
00553 int comparison ;
00554 cpl_propertylist * plist1 ;
00555 cpl_propertylist * plist2 ;
00556 double dval1, dval2 ;
00557
00558
00559 if (frame1==NULL || frame2==NULL) return -1 ;
00560
00561
00562 if ((plist1=cpl_propertylist_load(cpl_frame_get_filename(frame1),0))==NULL){
00563 cpl_msg_error(__func__, "getting header from reference frame");
00564 return -1 ;
00565 }
00566 if ((plist2=cpl_propertylist_load(cpl_frame_get_filename(frame2),0))==NULL){
00567 cpl_msg_error(__func__, "getting header from reference frame");
00568 cpl_propertylist_delete(plist1) ;
00569 return -1 ;
00570 }
00571
00572
00573 if (cpl_error_get_code()) {
00574 cpl_propertylist_delete(plist1) ;
00575 cpl_propertylist_delete(plist2) ;
00576 return -1 ;
00577 }
00578
00579 comparison = 1 ;
00580
00581
00582 dval1 = crires_pfits_get_dit(plist1) ;
00583 dval2 = crires_pfits_get_dit(plist2) ;
00584 if (cpl_error_get_code()) {
00585 cpl_msg_error(__func__, "Cannot get the DIT");
00586 cpl_propertylist_delete(plist1) ;
00587 cpl_propertylist_delete(plist2) ;
00588 return -1 ;
00589 }
00590 if (fabs(dval1-dval2) > 1e-3) comparison = 0 ;
00591
00592
00593 dval1 = crires_pfits_get_refwlen(plist1) ;
00594 dval2 = crires_pfits_get_refwlen(plist2) ;
00595 if (cpl_error_get_code()) {
00596 cpl_msg_error(__func__, "Cannot get the reference wavelength");
00597 cpl_propertylist_delete(plist1) ;
00598 cpl_propertylist_delete(plist2) ;
00599 return -1 ;
00600 }
00601 if (fabs(dval1-dval2) > 1e-3) comparison = 0 ;
00602
00603
00604 dval1 = crires_pfits_get_bafflepos(plist1) ;
00605 dval2 = crires_pfits_get_bafflepos(plist2) ;
00606 if (cpl_error_get_code()) {
00607 cpl_msg_error(__func__, "Cannot get the baffle position");
00608 cpl_propertylist_delete(plist1) ;
00609 cpl_propertylist_delete(plist2) ;
00610 return -1 ;
00611 }
00612 if (fabs(dval1-dval2) > 1e-3) comparison = 0 ;
00613
00614 cpl_propertylist_delete(plist1) ;
00615 cpl_propertylist_delete(plist2) ;
00616 return comparison ;
00617 }
00618