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 "irplib_wlxcorr.h"
00039 #include "crires_wlcalib.h"
00040 #include "crires_wlestimate.h"
00041
00042
00043
00044
00045
00046 #define RECIPE_STRING "crires_util_wlcalib"
00047
00048
00049
00050
00051
00052 static int crires_util_wlcalib_save(const cpl_imagelist *, const cpl_table **,
00053 const cpl_table **, const cpl_parameterlist *, cpl_frameset *) ;
00054
00055 static char crires_util_wlcalib_description[] =
00056 "This recipe accepts 2 parameters:\n"
00057 "First parameter: the extracted spectrum in pixels.\n"
00058 " (PRO TYPE = "CRIRES_PROTYPE_SPEC_PIX")\n"
00059 "Second parameter: the table with the lines catalog.\n"
00060 " (PRO TYPE = "CRIRES_PROTYPE_CATALOG")\n"
00061 "\n"
00062 "This recipe produces 2 files:\n"
00063 "First product: the image with the wavelength values.\n"
00064 " (PRO TYPE = "CRIRES_PROTYPE_WL_MAP")\n"
00065 "Second product: the table with the wavelength polynomial coefficients.\n"
00066 " (PRO TYPE = "CRIRES_PROTYPE_WL_POLY")\n" ;
00067
00068 CRIRES_RECIPE_DEFINE(crires_util_wlcalib,
00069 CRIRES_PARAM_WAVES |
00070 CRIRES_PARAM_DISPLAY |
00071 CRIRES_PARAM_WL_LOG |
00072 CRIRES_PARAM_WL_NOLIMIT |
00073 CRIRES_PARAM_WL_ERROR |
00074 CRIRES_PARAM_XC_LIMIT |
00075 CRIRES_PARAM_WL_NBSAMPLES |
00076 CRIRES_PARAM_DEGREE |
00077 CRIRES_PARAM_WL_CLEAN |
00078 CRIRES_PARAM_LINES |
00079 CRIRES_PARAM_FIRST_PLOTTED |
00080 CRIRES_PARAM_LAST_PLOTTED,
00081 "Wavelength calibration of a spectrum",
00082 crires_util_wlcalib_description) ;
00083
00084
00085
00086
00087
00088 static struct {
00089
00090 double wstart[CRIRES_NB_DETECTORS] ;
00091 double wstop[CRIRES_NB_DETECTORS] ;
00092 int display ;
00093 int degree ;
00094 int wl_nolimit ;
00095 int wl_log ;
00096 double wl_err ;
00097 int wl_nsamples ;
00098 int wl_clean ;
00099 double wl_xclimit ;
00100 int use_ppm ;
00101 int slitw ;
00102 int fwhm ;
00103 const char * lines ;
00104 int first_plotted_line ;
00105 int last_plotted_line ;
00106
00107 int win_mode ;
00108 crires_illum_period period ;
00109 double qc_wlcent[CRIRES_NB_DETECTORS] ;
00110 double qc_wldisp[CRIRES_NB_DETECTORS] ;
00111 double qc_wlxc[CRIRES_NB_DETECTORS] ;
00112 } crires_util_wlcalib_config ;
00113
00114
00115
00116
00117
00118
00125
00126 static int crires_util_wlcalib(
00127 cpl_frameset * frameset,
00128 const cpl_parameterlist * parlist)
00129 {
00130 cpl_table * ext_spec ;
00131 const char * fname ;
00132 cpl_propertylist * plist ;
00133 double wmin, wmax ;
00134 cpl_vector * spec ;
00135 double * pspec ;
00136 cpl_polynomial * phdisp ;
00137 cpl_polynomial * poly_sol ;
00138 cpl_matrix * samppos ;
00139 cpl_size mindeg, maxdeg ;
00140 cpl_bivector * lines_biv ;
00141 cpl_table * cat ;
00142 double val ;
00143 cpl_table * real_sol ;
00144 int nrows, spec_pos ;
00145 cpl_bivector * cat_biv ;
00146 double * cat_biv_x ;
00147 double * cat_biv_y ;
00148 const char * sval ;
00149 cpl_frame * fr ;
00150 cpl_polynomial * disp_poly ;
00151 cpl_table * wl_infos[CRIRES_NB_DETECTORS] ;
00152 cpl_table * wl_tab[CRIRES_NB_DETECTORS] ;
00153 cpl_imagelist * wl_map ;
00154 int i, j ;
00155
00156
00157 for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
00158 crires_util_wlcalib_config.qc_wlcent[i] = -1.0 ;
00159 crires_util_wlcalib_config.qc_wldisp[i] = -1.0 ;
00160 crires_util_wlcalib_config.qc_wlxc[i] = -1.0 ;
00161 wl_tab[i] = NULL ;
00162 wl_infos[i] = NULL ;
00163 }
00164 crires_util_wlcalib_config.lines = NULL ;
00165 crires_util_wlcalib_config.use_ppm = 0 ;
00166 crires_util_wlcalib_config.slitw = 2 ;
00167 crires_util_wlcalib_config.fwhm = 2 ;
00168
00169
00170 sval = crires_parameterlist_get_string(parlist, RECIPE_STRING,
00171 CRIRES_PARAM_WAVES) ;
00172 if (sscanf(sval, "%lg,%lg,%lg,%lg,%lg,%lg,%lg,%lg",
00173 &crires_util_wlcalib_config.wstart[0],
00174 &crires_util_wlcalib_config.wstop[0],
00175 &crires_util_wlcalib_config.wstart[1],
00176 &crires_util_wlcalib_config.wstop[1],
00177 &crires_util_wlcalib_config.wstart[2],
00178 &crires_util_wlcalib_config.wstop[2],
00179 &crires_util_wlcalib_config.wstart[3],
00180 &crires_util_wlcalib_config.wstop[3])!=2*CRIRES_NB_DETECTORS){
00181 return -1 ;
00182 }
00183 crires_util_wlcalib_config.display = crires_parameterlist_get_int(parlist,
00184 RECIPE_STRING, CRIRES_PARAM_DISPLAY) ;
00185 crires_util_wlcalib_config.degree = crires_parameterlist_get_int(parlist,
00186 RECIPE_STRING, CRIRES_PARAM_DEGREE) ;
00187 crires_util_wlcalib_config.wl_log = crires_parameterlist_get_bool(parlist,
00188 RECIPE_STRING, CRIRES_PARAM_WL_LOG) ;
00189 crires_util_wlcalib_config.wl_nolimit = crires_parameterlist_get_bool(
00190 parlist, RECIPE_STRING, CRIRES_PARAM_WL_NOLIMIT) ;
00191 crires_util_wlcalib_config.wl_err = crires_parameterlist_get_double(parlist,
00192 RECIPE_STRING, CRIRES_PARAM_WL_ERROR) ;
00193 crires_util_wlcalib_config.wl_xclimit = crires_parameterlist_get_double(
00194 parlist, RECIPE_STRING, CRIRES_PARAM_XC_LIMIT) ;
00195 crires_util_wlcalib_config.wl_nsamples = crires_parameterlist_get_int(
00196 parlist, RECIPE_STRING, CRIRES_PARAM_WL_NBSAMPLES) ;
00197 crires_util_wlcalib_config.wl_clean = crires_parameterlist_get_bool(parlist,
00198 RECIPE_STRING, CRIRES_PARAM_WL_CLEAN) ;
00199 crires_util_wlcalib_config.lines = crires_parameterlist_get_string(parlist,
00200 RECIPE_STRING, CRIRES_PARAM_LINES) ;
00201 crires_util_wlcalib_config.first_plotted_line=crires_parameterlist_get_int(
00202 parlist, RECIPE_STRING, CRIRES_PARAM_FIRST_PLOTTED) ;
00203 crires_util_wlcalib_config.last_plotted_line=crires_parameterlist_get_int(
00204 parlist, RECIPE_STRING, CRIRES_PARAM_LAST_PLOTTED) ;
00205
00206
00207 if (crires_dfs_set_groups(frameset, NULL)) {
00208 cpl_msg_error(__func__, "Cannot identify RAW and CALIB frames") ;
00209 return -1 ;
00210 }
00211
00212
00213 if (cpl_frameset_get_size(frameset) != 2) {
00214 cpl_msg_error(__func__, "Expects 2 files in input") ;
00215 return -1 ;
00216 }
00217
00218
00219 fr = cpl_frameset_get_frame(frameset, 0);
00220 crires_util_wlcalib_config.period =
00221 crires_get_detector_illum_period(cpl_frame_get_filename(fr)) ;
00222 if (crires_util_wlcalib_config.period == CRIRES_ILLUM_UNKNOWN) {
00223 cpl_msg_error(__func__,
00224 "Cannot determine the detector illumination period") ;
00225 return -1 ;
00226 }
00227
00228
00229 if ((plist=cpl_propertylist_load(cpl_frame_get_filename(fr), 0)) == NULL)
00230 return -1 ;
00231 sval = crires_pfits_get_ncorrs(plist) ;
00232 if (!strcmp(sval, "FowlerNsampGRstWin")) {
00233 crires_util_wlcalib_config.period = CRIRES_ILLUM_FULL_DETECTOR ;
00234 crires_util_wlcalib_config.win_mode = 1 ;
00235 } else {
00236 crires_util_wlcalib_config.win_mode = 0 ;
00237 }
00238 cpl_propertylist_delete(plist) ;
00239
00240
00241 crires_display_detector_illum(crires_util_wlcalib_config.period) ;
00242
00243
00244 cpl_msg_info(__func__, "Second frame validity check") ;
00245 cpl_msg_indent_more() ;
00246 fr = cpl_frameset_get_frame(frameset, 1);
00247 cat = crires_load_table_check(cpl_frame_get_filename(fr), 1,
00248 CRIRES_PROTYPE_CATALOG, -1, -1, 0) ;
00249 if (cat == NULL) {
00250 cpl_msg_error(__func__, "Second frame is incorrect") ;
00251 cpl_msg_indent_less() ;
00252 return -1 ;
00253 }
00254 cpl_msg_indent_less() ;
00255
00256
00257 nrows = cpl_table_get_nrow(cat) ;
00258 cat_biv = cpl_bivector_new(nrows) ;
00259 cat_biv_x = cpl_bivector_get_x_data(cat_biv) ;
00260 cat_biv_y = cpl_bivector_get_y_data(cat_biv) ;
00261 for (i=0 ; i<nrows ; i++) {
00262 cat_biv_x[i] = cpl_table_get(cat, CRIRES_COL_WAVELENGTH, i, NULL) ;
00263 val = cpl_table_get(cat, CRIRES_COL_EMISSION, i, NULL) ;
00264 if (crires_util_wlcalib_config.wl_log && val > 0)
00265 cat_biv_y[i] = log10(val) ;
00266 else
00267 cat_biv_y[i] = val ;
00268 }
00269 cpl_table_delete(cat) ;
00270
00271
00272 fr = cpl_frameset_get_frame(frameset, 0);
00273 fname = cpl_frame_get_filename(fr) ;
00274
00275
00276 if (crires_util_wlcalib_config.wl_nolimit == 0) {
00277 plist = cpl_propertylist_load(fname, 0) ;
00278 wmin = crires_pfits_get_wlen_min(plist) ;
00279 wmax = crires_pfits_get_wlen_max(plist) ;
00280 cpl_propertylist_delete(plist) ;
00281 if (cpl_error_get_code()) {
00282 wmin = wmax = -1.0 ;
00283 cpl_error_reset() ;
00284 }
00285 } else {
00286 wmin = wmax = -1.0 ;
00287 }
00288
00289
00290 for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
00291
00292 if ((i==0 || i==CRIRES_NB_DETECTORS-1) &&
00293 (crires_util_wlcalib_config.win_mode == 1)) {
00294 continue ;
00295 }
00296
00297 cpl_msg_info(__func__, "Wavelength calibration for chip %d", i+1) ;
00298
00299 cpl_msg_info(__func__, "Load the extracted table") ;
00300 cpl_msg_indent_more() ;
00301 if ((ext_spec=crires_load_table_check(fname, i+1,
00302 CRIRES_PROTYPE_SPEC_PIX, -1, -1, 0)) == NULL) {
00303 cpl_msg_warning(__func__, "Empty extension") ;
00304 cpl_msg_indent_less() ;
00305 continue ;
00306 }
00307 cpl_msg_indent_less() ;
00308
00309
00310 cpl_msg_info(__func__, "Wavelength estimation") ;
00311 cpl_msg_indent_more() ;
00312 if ((phdisp = crires_wlestimate_compute(
00313 crires_util_wlcalib_config.wstart[i],
00314 crires_util_wlcalib_config.wstop[i])) == NULL) {
00315 if ((phdisp = crires_wlestimate_get(fname, i+1)) == NULL) {
00316 cpl_msg_error(__func__, "Cannot get the wavelength estimate") ;
00317 cpl_msg_indent_less() ;
00318 cpl_table_delete(ext_spec) ;
00319 continue ;
00320 }
00321 }
00322 cpl_msg_indent_less() ;
00323
00324
00325 nrows = cpl_table_get_nrow(ext_spec) ;
00326 spec = cpl_vector_new(nrows) ;
00327 pspec = cpl_vector_get_data(spec) ;
00328 for (j=0 ; j<nrows ; j++) {
00329 pspec[j] = cpl_table_get(ext_spec, CRIRES_COL_EXTRACT_INT_RECT, j,
00330 NULL);
00331 }
00332 cpl_table_delete(ext_spec) ;
00333
00334
00335 cpl_msg_info(__func__, "Wavelength calibration computation") ;
00336 cpl_msg_indent_more() ;
00337 if ((disp_poly = crires_wlcalib_engine(spec, cat_biv, phdisp,
00338 crires_util_wlcalib_config.slitw,
00339 crires_util_wlcalib_config.fwhm,
00340 crires_util_wlcalib_config.degree,
00341 wmin, wmax,
00342 crires_util_wlcalib_config.wl_err,
00343 crires_util_wlcalib_config.wl_nsamples,
00344 crires_util_wlcalib_config.wl_clean,
00345 crires_util_wlcalib_config.wl_xclimit,
00346 crires_util_wlcalib_config.use_ppm,
00347 (i+1==crires_util_wlcalib_config.display),
00348 crires_util_wlcalib_config.first_plotted_line,
00349 crires_util_wlcalib_config.last_plotted_line,
00350 &((crires_util_wlcalib_config.qc_wlxc)[i]),
00351 NULL)) == NULL) {
00352 cpl_msg_error(__func__,
00353 "Wavelength calibration failed - use estimate") ;
00354 disp_poly = cpl_polynomial_duplicate(phdisp) ;
00355 crires_util_wlcalib_config.qc_wlxc[i] = -1.0 ;
00356 }
00357 cpl_msg_indent_less() ;
00358
00359
00360 crires_util_wlcalib_config.qc_wlcent[i] =
00361 cpl_polynomial_eval_1d(disp_poly, (double)512, NULL) ;
00362 crires_util_wlcalib_config.qc_wldisp[i] =
00363 (cpl_polynomial_eval_1d(disp_poly, (double)1024, NULL) -
00364 cpl_polynomial_eval_1d(disp_poly, (double)1, NULL)) / 1023 ;
00365
00366
00367 if (crires_util_wlcalib_config.display==i+1) {
00368
00369 poly_sol = NULL ;
00370 if (crires_util_wlcalib_config.lines != NULL &&
00371 crires_util_wlcalib_config.lines[0] != (char)0) {
00372 lines_biv =
00373 cpl_bivector_read((char*)crires_util_wlcalib_config.lines);
00374 if ((lines_biv != NULL) &&
00375 (cpl_bivector_get_size(lines_biv)>crires_util_wlcalib_config.degree)) {
00376 poly_sol = cpl_polynomial_new(1);
00377 samppos = cpl_matrix_wrap(1,
00378 cpl_bivector_get_size(lines_biv),
00379 cpl_bivector_get_x_data(lines_biv)) ;
00380 mindeg = 1 ;
00381 maxdeg = (cpl_size)crires_util_wlcalib_config.degree ;
00382 cpl_polynomial_fit(poly_sol,
00383 samppos, NULL,
00384 cpl_bivector_get_y(lines_biv),
00385 NULL, CPL_FALSE,
00386 &mindeg,
00387 &maxdeg) ;
00388 cpl_matrix_unwrap(samppos) ;
00389 }
00390 if (lines_biv != NULL) cpl_bivector_delete(lines_biv) ;
00391 }
00392 irplib_wlxcorr_plot_solution(phdisp, disp_poly, poly_sol, 1, 1024);
00393 if (poly_sol != NULL) {
00394 real_sol = irplib_wlxcorr_gen_spc_table(spec, cat_biv,
00395 crires_util_wlcalib_config.slitw,
00396 crires_util_wlcalib_config.fwhm,
00397 phdisp, poly_sol) ;
00398 irplib_wlxcorr_plot_spc_table(real_sol, "Real",
00399 crires_util_wlcalib_config.first_plotted_line,
00400 crires_util_wlcalib_config.last_plotted_line) ;
00401 cpl_table_delete(real_sol) ;
00402 }
00403 if (poly_sol != NULL) cpl_polynomial_delete(poly_sol) ;
00404 }
00405
00406
00407 wl_infos[i] = irplib_wlxcorr_gen_spc_table(spec, cat_biv,
00408 crires_util_wlcalib_config.slitw,
00409 crires_util_wlcalib_config.fwhm,
00410 phdisp, disp_poly) ;
00411
00412
00413 cpl_vector_delete(spec) ;
00414 cpl_polynomial_delete(phdisp) ;
00415
00416
00417 if (crires_util_wlcalib_config.qc_wlxc[i] > 0)
00418 spec_pos = crires_get_y_spec_position(fname, i+1) ;
00419 else
00420 spec_pos = -1 ;
00421 wl_tab[i] = crires_wlcalib_gen_wltab_one(
00422 (const cpl_polynomial *)disp_poly,
00423 spec_pos,
00424 crires_util_wlcalib_config.qc_wlxc[i]) ;
00425 cpl_polynomial_delete(disp_poly) ;
00426 }
00427 cpl_bivector_delete(cat_biv) ;
00428
00429
00430 if (crires_util_wlcalib_config.win_mode == 1) {
00431 if (wl_tab[1] != NULL) {
00432 wl_tab[0] = cpl_table_duplicate(wl_tab[1]) ;
00433 cpl_table_set_size(wl_tab[0], 0) ;
00434 wl_tab[CRIRES_NB_DETECTORS-1] = cpl_table_duplicate(wl_tab[0]) ;
00435 }
00436 if (wl_infos[1] != NULL) {
00437 wl_infos[0] = cpl_table_duplicate(wl_infos[1]) ;
00438 cpl_table_set_size(wl_infos[0], 0) ;
00439 wl_infos[CRIRES_NB_DETECTORS-1] = cpl_table_duplicate(wl_infos[0]) ;
00440 }
00441 }
00442
00443
00444 if ((wl_map = crires_wlcalib_gen_wlmap((const cpl_table **)wl_tab))
00445 == NULL) {
00446 cpl_msg_error(__func__, "Cannot create WL Map") ;
00447 for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
00448 if (wl_tab[i] != NULL) cpl_table_delete(wl_tab[i]) ;
00449 if (wl_infos[i] != NULL) cpl_table_delete(wl_infos[i]) ;
00450 }
00451 return -1 ;
00452 }
00453
00454
00455 cpl_msg_info(__func__, "Save the products") ;
00456 cpl_msg_indent_more() ;
00457 if (crires_util_wlcalib_save(wl_map, (const cpl_table **)wl_tab,
00458 (const cpl_table **)wl_infos, parlist, frameset) == -1) {
00459 cpl_msg_error(__func__, "Cannot save products");
00460 cpl_msg_indent_less() ;
00461 cpl_imagelist_delete(wl_map) ;
00462 for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
00463 if (wl_tab[i] != NULL) cpl_table_delete(wl_tab[i]) ;
00464 if (wl_infos[i] != NULL) cpl_table_delete(wl_infos[i]) ;
00465 }
00466 return -1 ;
00467 }
00468 cpl_msg_indent_less() ;
00469 cpl_imagelist_delete(wl_map) ;
00470 for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
00471 if (wl_tab[i] != NULL) cpl_table_delete(wl_tab[i]) ;
00472 if (wl_infos[i] != NULL) cpl_table_delete(wl_infos[i]) ;
00473 }
00474
00475
00476 if (cpl_error_get_code()) return -1 ;
00477 else return 0 ;
00478 }
00479
00480
00490
00491 static int crires_util_wlcalib_save(
00492 const cpl_imagelist * ilist,
00493 const cpl_table ** tab,
00494 const cpl_table ** xctab,
00495 const cpl_parameterlist * parlist,
00496 cpl_frameset * set)
00497 {
00498 cpl_propertylist ** qclists ;
00499 const cpl_frame * ref_frame ;
00500 cpl_propertylist * inputlist ;
00501 const char * recipe_name = "crires_util_wlcalib" ;
00502 int i ;
00503
00504
00505 ref_frame = irplib_frameset_get_first_from_group(set, CPL_FRAME_GROUP_RAW) ;
00506
00507
00508 qclists = cpl_malloc(CRIRES_NB_DETECTORS * sizeof(cpl_propertylist*)) ;
00509 for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
00510 qclists[i] = cpl_propertylist_new() ;
00511 cpl_propertylist_append_double(qclists[i], "ESO QC CENTWL",
00512 crires_util_wlcalib_config.qc_wlcent[i]) ;
00513 cpl_propertylist_append_double(qclists[i], "ESO QC DISPWL",
00514 crires_util_wlcalib_config.qc_wldisp[i]) ;
00515 cpl_propertylist_append_double(qclists[i], "ESO QC XCORR",
00516 crires_util_wlcalib_config.qc_wlxc[i]) ;
00517
00518
00519 inputlist = cpl_propertylist_load_regexp(
00520 cpl_frame_get_filename(ref_frame), i+1,
00521 CRIRES_HEADER_EXT_FORWARD, 0) ;
00522 cpl_propertylist_copy_property_regexp(qclists[i], inputlist,
00523 CRIRES_HEADER_EXT_FORWARD, 0) ;
00524 cpl_propertylist_delete(inputlist) ;
00525 }
00526
00527
00528 crires_image_save(set,
00529 parlist,
00530 set,
00531 ilist,
00532 recipe_name,
00533 CRIRES_WL_MAP_IMA,
00534 CRIRES_PROTYPE_WL_MAP,
00535 crires_util_wlcalib_config.period,
00536 NULL,
00537 (const cpl_propertylist **)qclists,
00538 PACKAGE "/" PACKAGE_VERSION,
00539 "crires_util_wlcalib_ima.fits") ;
00540
00541
00542 crires_table_save(set,
00543 parlist,
00544 set,
00545 tab,
00546 recipe_name,
00547 CRIRES_CALPRO_WAVE,
00548 CRIRES_PROTYPE_WL_POLY,
00549 NULL,
00550 (const cpl_propertylist **)qclists,
00551 PACKAGE "/" PACKAGE_VERSION,
00552 "crires_util_wlcalib_tab.fits") ;
00553
00554 if (xctab[0] != NULL) {
00555
00556 crires_table_save(set,
00557 parlist,
00558 set,
00559 xctab,
00560 recipe_name,
00561 CRIRES_WL_XCORR_TAB,
00562 CRIRES_PROTYPE_XCORR,
00563 NULL,
00564 (const cpl_propertylist **)qclists,
00565 PACKAGE "/" PACKAGE_VERSION,
00566 "crires_util_wlcalib_xctab.fits") ;
00567 }
00568
00569
00570 for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
00571 cpl_propertylist_delete(qclists[i]) ;
00572 }
00573 cpl_free(qclists) ;
00574 return 0;
00575 }