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 "Wavelength calibration of a spectrum",
00080 crires_util_wlcalib_description) ;
00081
00082
00083
00084
00085
00086 static struct {
00087
00088 double wstart[CRIRES_NB_DETECTORS] ;
00089 double wstop[CRIRES_NB_DETECTORS] ;
00090 int display ;
00091 int degree ;
00092 int wl_nolimit ;
00093 int wl_log ;
00094 double wl_err ;
00095 int wl_nsamples ;
00096 int wl_clean ;
00097 double wl_xclimit ;
00098 int use_ppm ;
00099 int slitw ;
00100 int fwhm ;
00101 const char * lines ;
00102
00103 crires_illum_period period ;
00104 double qc_wlcent[CRIRES_NB_DETECTORS] ;
00105 double qc_wldisp[CRIRES_NB_DETECTORS] ;
00106 double qc_wlxc[CRIRES_NB_DETECTORS] ;
00107 } crires_util_wlcalib_config ;
00108
00109
00110
00111
00112
00113
00120
00121 static int crires_util_wlcalib(
00122 cpl_frameset * frameset,
00123 const cpl_parameterlist * parlist)
00124 {
00125 cpl_table * ext_spec ;
00126 const char * fname ;
00127 cpl_propertylist * plist ;
00128 double wmin, wmax ;
00129 cpl_vector * spec ;
00130 double * pspec ;
00131 cpl_polynomial * phdisp ;
00132 cpl_polynomial * poly_sol ;
00133 cpl_matrix * samppos ;
00134 int mindeg ;
00135 cpl_bivector * lines_biv ;
00136 cpl_table * cat ;
00137 double val ;
00138 cpl_table * real_sol ;
00139 int nrows ;
00140 cpl_bivector * cat_biv ;
00141 double * cat_biv_x ;
00142 double * cat_biv_y ;
00143 const char * sval ;
00144 cpl_frame * fr ;
00145 cpl_polynomial * disp[CRIRES_NB_DETECTORS] ;
00146 cpl_table * wl_infos[CRIRES_NB_DETECTORS] ;
00147 cpl_table ** wl_tab ;
00148 cpl_imagelist * wl_map ;
00149 int i, j ;
00150
00151
00152 crires_util_wlcalib_config.lines = NULL ;
00153 crires_util_wlcalib_config.use_ppm = 0 ;
00154 crires_util_wlcalib_config.slitw = 2 ;
00155 crires_util_wlcalib_config.fwhm = 2 ;
00156
00157
00158 sval = crires_parameterlist_get_string(parlist, RECIPE_STRING,
00159 CRIRES_PARAM_WAVES) ;
00160 if (sscanf(sval, "%lg,%lg,%lg,%lg,%lg,%lg,%lg,%lg",
00161 &crires_util_wlcalib_config.wstart[0],
00162 &crires_util_wlcalib_config.wstop[0],
00163 &crires_util_wlcalib_config.wstart[1],
00164 &crires_util_wlcalib_config.wstop[1],
00165 &crires_util_wlcalib_config.wstart[2],
00166 &crires_util_wlcalib_config.wstop[2],
00167 &crires_util_wlcalib_config.wstart[3],
00168 &crires_util_wlcalib_config.wstop[3])!=2*CRIRES_NB_DETECTORS){
00169 return -1 ;
00170 }
00171 crires_util_wlcalib_config.display = crires_parameterlist_get_int(parlist,
00172 RECIPE_STRING, CRIRES_PARAM_DISPLAY) ;
00173 crires_util_wlcalib_config.degree = crires_parameterlist_get_int(parlist,
00174 RECIPE_STRING, CRIRES_PARAM_DEGREE) ;
00175 crires_util_wlcalib_config.wl_log = crires_parameterlist_get_bool(parlist,
00176 RECIPE_STRING, CRIRES_PARAM_WL_LOG) ;
00177 crires_util_wlcalib_config.wl_nolimit = crires_parameterlist_get_bool(
00178 parlist, RECIPE_STRING, CRIRES_PARAM_WL_NOLIMIT) ;
00179 crires_util_wlcalib_config.wl_err = crires_parameterlist_get_double(parlist,
00180 RECIPE_STRING, CRIRES_PARAM_WL_ERROR) ;
00181 crires_util_wlcalib_config.wl_xclimit = crires_parameterlist_get_double(
00182 parlist, RECIPE_STRING, CRIRES_PARAM_XC_LIMIT) ;
00183 crires_util_wlcalib_config.wl_nsamples = crires_parameterlist_get_int(
00184 parlist, RECIPE_STRING, CRIRES_PARAM_WL_NBSAMPLES) ;
00185 crires_util_wlcalib_config.wl_clean = crires_parameterlist_get_bool(parlist,
00186 RECIPE_STRING, CRIRES_PARAM_WL_CLEAN) ;
00187 crires_util_wlcalib_config.lines = crires_parameterlist_get_string(parlist,
00188 RECIPE_STRING, CRIRES_PARAM_LINES) ;
00189
00190
00191 if (crires_dfs_set_groups(frameset, NULL)) {
00192 cpl_msg_error(__func__, "Cannot identify RAW and CALIB frames") ;
00193 return -1 ;
00194 }
00195
00196
00197 if (cpl_frameset_get_size(frameset) != 2) {
00198 cpl_msg_error(__func__, "Expects 2 files in input") ;
00199 return -1 ;
00200 }
00201
00202
00203 fr = cpl_frameset_get_frame(frameset, 0);
00204 crires_util_wlcalib_config.period =
00205 crires_get_detector_illum_period(cpl_frame_get_filename(fr)) ;
00206 if (crires_util_wlcalib_config.period == CRIRES_ILLUM_UNKNOWN) {
00207 cpl_msg_error(__func__,
00208 "Cannot determine the detector illumination period") ;
00209 return -1 ;
00210 } else {
00211 crires_display_detector_illum(crires_util_wlcalib_config.period) ;
00212 }
00213
00214
00215 cpl_msg_info(__func__, "Second frame validity check") ;
00216 cpl_msg_indent_more() ;
00217 fr = cpl_frameset_get_frame(frameset, 1);
00218 cat = crires_load_table_check(cpl_frame_get_filename(fr), 1,
00219 CRIRES_PROTYPE_CATALOG, -1, -1, 0) ;
00220 if (cat == NULL) {
00221 cpl_msg_error(__func__, "Second frame is incorrect") ;
00222 cpl_msg_indent_less() ;
00223 return -1 ;
00224 }
00225 cpl_msg_indent_less() ;
00226
00227
00228 nrows = cpl_table_get_nrow(cat) ;
00229 cat_biv = cpl_bivector_new(nrows) ;
00230 cat_biv_x = cpl_bivector_get_x_data(cat_biv) ;
00231 cat_biv_y = cpl_bivector_get_y_data(cat_biv) ;
00232 for (i=0 ; i<nrows ; i++) {
00233 cat_biv_x[i] = cpl_table_get(cat, CRIRES_COL_WAVELENGTH, i, NULL) ;
00234 val = cpl_table_get(cat, CRIRES_COL_EMISSION, i, NULL) ;
00235 if (crires_util_wlcalib_config.wl_log && val > 0)
00236 cat_biv_y[i] = log10(val) ;
00237 else
00238 cat_biv_y[i] = val ;
00239 }
00240 cpl_table_delete(cat) ;
00241
00242
00243 fr = cpl_frameset_get_frame(frameset, 0);
00244 fname = cpl_frame_get_filename(fr) ;
00245
00246
00247 if (crires_util_wlcalib_config.wl_nolimit == 0) {
00248 plist = cpl_propertylist_load(fname, 0) ;
00249 wmin = crires_pfits_get_wlen_min(plist) ;
00250 wmax = crires_pfits_get_wlen_max(plist) ;
00251 cpl_propertylist_delete(plist) ;
00252 if (cpl_error_get_code()) {
00253 wmin = wmax = -1.0 ;
00254 cpl_error_reset() ;
00255 }
00256 } else {
00257 wmin = wmax = -1.0 ;
00258 }
00259
00260
00261 for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
00262 cpl_msg_info(__func__, "Wavelength calibration for chip %d", i+1) ;
00263
00264
00265 disp[i] = NULL ;
00266 wl_infos[i] = NULL ;
00267 crires_util_wlcalib_config.qc_wlcent[i] = -1.0 ;
00268 crires_util_wlcalib_config.qc_wldisp[i] = -1.0 ;
00269 crires_util_wlcalib_config.qc_wlxc[i] = -1.0 ;
00270
00271
00272 cpl_msg_info(__func__, "Load the extracted table") ;
00273 cpl_msg_indent_more() ;
00274 if ((ext_spec=crires_load_table_check(fname, i+1,
00275 CRIRES_PROTYPE_SPEC_PIX, -1, -1, 0)) == NULL) {
00276 cpl_msg_warning(__func__, "Empty extension") ;
00277 cpl_msg_indent_less() ;
00278 continue ;
00279 }
00280 cpl_msg_indent_less() ;
00281
00282
00283 cpl_msg_info(__func__, "Wavelength estimation") ;
00284 cpl_msg_indent_more() ;
00285 if ((phdisp = crires_wlestimate_compute(
00286 crires_util_wlcalib_config.wstart[i],
00287 crires_util_wlcalib_config.wstop[i])) == NULL) {
00288 if ((phdisp = crires_wlestimate_get(fname, i+1)) == NULL) {
00289 cpl_msg_error(__func__, "Cannot get the wavelength estimate") ;
00290 cpl_msg_indent_less() ;
00291 cpl_table_delete(ext_spec) ;
00292 continue ;
00293 }
00294 }
00295 cpl_msg_indent_less() ;
00296
00297
00298 nrows = cpl_table_get_nrow(ext_spec) ;
00299 spec = cpl_vector_new(nrows) ;
00300 pspec = cpl_vector_get_data(spec) ;
00301 for (j=0 ; j<nrows ; j++) {
00302 pspec[j] = cpl_table_get(ext_spec, CRIRES_COL_EXTRACT_INT_RECT, j,
00303 NULL);
00304 }
00305 cpl_table_delete(ext_spec) ;
00306
00307
00308 cpl_msg_info(__func__, "Wavelength calibration computation") ;
00309 cpl_msg_indent_more() ;
00310 if ((disp[i] = crires_wlcalib_engine(spec, cat_biv, phdisp,
00311 crires_util_wlcalib_config.slitw,
00312 crires_util_wlcalib_config.fwhm,
00313 crires_util_wlcalib_config.degree,
00314 wmin, wmax,
00315 crires_util_wlcalib_config.wl_err,
00316 crires_util_wlcalib_config.wl_nsamples,
00317 crires_util_wlcalib_config.wl_clean,
00318 crires_util_wlcalib_config.wl_xclimit,
00319 crires_util_wlcalib_config.use_ppm,
00320 (i+1==crires_util_wlcalib_config.display),
00321 &((crires_util_wlcalib_config.qc_wlxc)[i]),
00322 NULL)) == NULL) {
00323 cpl_msg_error(__func__, "Wavelength calibration failed") ;
00324 cpl_msg_indent_less() ;
00325 cpl_vector_delete(spec) ;
00326 cpl_polynomial_delete(phdisp) ;
00327 continue ;
00328 }
00329 cpl_msg_indent_less() ;
00330
00331
00332 crires_util_wlcalib_config.qc_wlcent[i] =
00333 cpl_polynomial_eval_1d(disp[i], (double)512, NULL) ;
00334 crires_util_wlcalib_config.qc_wldisp[i] =
00335 (cpl_polynomial_eval_1d(disp[i], (double)1024, NULL) -
00336 cpl_polynomial_eval_1d(disp[i], (double)1, NULL)) / 1024 ;
00337
00338
00339 if (crires_util_wlcalib_config.display==i+1) {
00340
00341 poly_sol = NULL ;
00342 if (crires_util_wlcalib_config.lines != NULL &&
00343 crires_util_wlcalib_config.lines[0] != (char)0) {
00344 lines_biv =
00345 cpl_bivector_read((char*)crires_util_wlcalib_config.lines);
00346 if ((lines_biv != NULL) &&
00347 (cpl_bivector_get_size(lines_biv)>crires_util_wlcalib_config.degree)) {
00348 poly_sol = cpl_polynomial_new(1);
00349 samppos = cpl_matrix_wrap(1, cpl_bivector_get_size(lines_biv),
00350 cpl_bivector_get_x_data(lines_biv)) ;
00351 mindeg = 1 ;
00352 cpl_polynomial_fit(poly_sol,
00353 samppos, NULL,
00354 cpl_bivector_get_y(lines_biv),
00355 NULL, CPL_FALSE,
00356 &mindeg,
00357 &(crires_util_wlcalib_config.degree)) ;
00358 cpl_matrix_unwrap(samppos) ;
00359 }
00360 if (lines_biv != NULL) cpl_bivector_delete(lines_biv) ;
00361 }
00362 irplib_wlxcorr_plot_solution(phdisp, disp[i], poly_sol, 1, 1024);
00363 if (poly_sol != NULL) {
00364 real_sol = irplib_wlxcorr_gen_spc_table(spec, cat_biv,
00365 crires_util_wlcalib_config.slitw,
00366 crires_util_wlcalib_config.fwhm,
00367 phdisp, poly_sol) ;
00368 irplib_wlxcorr_plot_spc_table(real_sol, "Real") ;
00369 cpl_table_delete(real_sol) ;
00370 }
00371 if (poly_sol != NULL) cpl_polynomial_delete(poly_sol) ;
00372 }
00373
00374
00375 wl_infos[i] = irplib_wlxcorr_gen_spc_table(spec, cat_biv,
00376 crires_util_wlcalib_config.slitw,
00377 crires_util_wlcalib_config.fwhm,
00378 phdisp, disp[i]) ;
00379
00380
00381 cpl_vector_delete(spec) ;
00382 cpl_polynomial_delete(phdisp) ;
00383 }
00384
00385 cpl_bivector_delete(cat_biv) ;
00386
00387
00388 wl_tab = crires_wlcalib_gen_wltab((const cpl_polynomial **)disp) ;
00389 wl_map = crires_wlcalib_gen_wlmap((const cpl_table **)wl_tab) ;
00390
00391 for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
00392 if (disp[i] != NULL) cpl_polynomial_delete(disp[i]) ;
00393 }
00394
00395
00396 cpl_msg_info(__func__, "Save the products") ;
00397 cpl_msg_indent_more() ;
00398 if (crires_util_wlcalib_save(wl_map, (const cpl_table **)wl_tab,
00399 (const cpl_table **)wl_infos, parlist, frameset) == -1) {
00400 cpl_msg_error(__func__, "Cannot save products");
00401 cpl_msg_indent_less() ;
00402 cpl_imagelist_delete(wl_map) ;
00403 for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
00404 cpl_table_delete(wl_tab[i]) ;
00405 if (wl_infos[i] != NULL) cpl_table_delete(wl_infos[i]) ;
00406 }
00407 cpl_free(wl_tab) ;
00408 return -1 ;
00409 }
00410 cpl_msg_indent_less() ;
00411 cpl_imagelist_delete(wl_map) ;
00412 for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
00413 cpl_table_delete(wl_tab[i]) ;
00414 if (wl_infos[i] != NULL) cpl_table_delete(wl_infos[i]) ;
00415 }
00416 cpl_free(wl_tab) ;
00417
00418
00419 if (cpl_error_get_code()) return -1 ;
00420 else return 0 ;
00421 }
00422
00423
00433
00434 static int crires_util_wlcalib_save(
00435 const cpl_imagelist * ilist,
00436 const cpl_table ** tab,
00437 const cpl_table ** xctab,
00438 const cpl_parameterlist * parlist,
00439 cpl_frameset * set)
00440 {
00441 cpl_propertylist ** qclists ;
00442 const cpl_frame * ref_frame ;
00443 cpl_propertylist * inputlist ;
00444 const char * recipe_name = "crires_util_wlcalib" ;
00445 int i ;
00446
00447
00448 ref_frame = irplib_frameset_get_first_from_group(set, CPL_FRAME_GROUP_RAW) ;
00449
00450
00451 qclists = cpl_malloc(CRIRES_NB_DETECTORS * sizeof(cpl_propertylist*)) ;
00452 for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
00453 qclists[i] = cpl_propertylist_new() ;
00454 cpl_propertylist_append_double(qclists[i], "ESO QC CENTWL",
00455 crires_util_wlcalib_config.qc_wlcent[i]) ;
00456 cpl_propertylist_append_double(qclists[i], "ESO QC DISPWL",
00457 crires_util_wlcalib_config.qc_wldisp[i]) ;
00458 cpl_propertylist_append_double(qclists[i], "ESO QC XCORR",
00459 crires_util_wlcalib_config.qc_wlxc[i]) ;
00460
00461
00462 inputlist = cpl_propertylist_load_regexp(
00463 cpl_frame_get_filename(ref_frame), i+1,
00464 CRIRES_HEADER_EXT_FORWARD, 0) ;
00465 cpl_propertylist_copy_property_regexp(qclists[i], inputlist,
00466 CRIRES_HEADER_EXT_FORWARD, 0) ;
00467 cpl_propertylist_delete(inputlist) ;
00468 }
00469
00470
00471 crires_image_save(set,
00472 parlist,
00473 set,
00474 ilist,
00475 recipe_name,
00476 CRIRES_WL_MAP_IMA,
00477 CRIRES_PROTYPE_WL_MAP,
00478 crires_util_wlcalib_config.period,
00479 NULL,
00480 (const cpl_propertylist **)qclists,
00481 PACKAGE "/" PACKAGE_VERSION,
00482 "crires_util_wlcalib_ima.fits") ;
00483
00484
00485 crires_table_save(set,
00486 parlist,
00487 set,
00488 tab,
00489 recipe_name,
00490 CRIRES_CALPRO_WAVE,
00491 CRIRES_PROTYPE_WL_POLY,
00492 NULL,
00493 (const cpl_propertylist **)qclists,
00494 PACKAGE "/" PACKAGE_VERSION,
00495 "crires_util_wlcalib_tab.fits") ;
00496
00497 if (xctab[0] != NULL) {
00498
00499 crires_table_save(set,
00500 parlist,
00501 set,
00502 xctab,
00503 recipe_name,
00504 CRIRES_WL_XCORR_TAB,
00505 CRIRES_PROTYPE_XCORR,
00506 NULL,
00507 (const cpl_propertylist **)qclists,
00508 PACKAGE "/" PACKAGE_VERSION,
00509 "crires_util_wlcalib_xctab.fits") ;
00510 }
00511
00512
00513 for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
00514 cpl_propertylist_delete(qclists[i]) ;
00515 }
00516 cpl_free(qclists) ;
00517 return 0;
00518 }