37 #include "crires_recipe.h"
39 #include "irplib_wlxcorr.h"
40 #include "irplib_utils.h"
42 #include "crires_wlcalib.h"
43 #include "crires_wlestimate.h"
49 #define RECIPE_STRING "crires_util_wlcalib"
55 static int crires_util_wlcalib_save(
const cpl_imagelist *,
const cpl_table **,
56 const cpl_table **,
const cpl_parameterlist *, cpl_frameset *) ;
58 static char crires_util_wlcalib_description[] =
59 "This recipe accepts 2 parameters:\n"
60 "First parameter: the extracted spectrum in pixels.\n"
61 " (PRO TYPE = "CRIRES_PROTYPE_SPEC_PIX
")\n"
62 "Second parameter: the table with the lines catalog.\n"
63 " (PRO TYPE = "CRIRES_PROTYPE_CATALOG
")\n"
65 "This recipe produces 2 files:\n"
66 "First product: the image with the wavelength values.\n"
67 " (PRO TYPE = "CRIRES_PROTYPE_WL_MAP
")\n"
68 "Second product: the table with the wavelength polynomial coefficients.\n"
69 " (PRO TYPE = "CRIRES_PROTYPE_WL_POLY
")\n" ;
71 CRIRES_RECIPE_DEFINE(crires_util_wlcalib,
73 CRIRES_PARAM_DISPLAY |
75 CRIRES_PARAM_WL_NOLIMIT |
76 CRIRES_PARAM_WL_ERROR |
77 CRIRES_PARAM_XC_LIMIT |
78 CRIRES_PARAM_WL_NBSAMPLES |
80 CRIRES_PARAM_WL_CLEAN |
82 CRIRES_PARAM_FIRST_PLOTTED |
83 CRIRES_PARAM_LAST_PLOTTED,
84 "Wavelength calibration of a spectrum",
85 crires_util_wlcalib_description) ;
93 double wstart[CRIRES_NB_DETECTORS] ;
94 double wstop[CRIRES_NB_DETECTORS] ;
107 int first_plotted_line ;
108 int last_plotted_line ;
111 crires_illum_period period ;
112 double qc_wlcent[CRIRES_NB_DETECTORS] ;
113 double qc_wldisp[CRIRES_NB_DETECTORS] ;
114 double qc_wlxc[CRIRES_NB_DETECTORS] ;
115 } crires_util_wlcalib_config ;
129 static int crires_util_wlcalib(
130 cpl_frameset * frameset,
131 const cpl_parameterlist * parlist)
133 cpl_table * ext_spec ;
135 cpl_propertylist * plist ;
139 cpl_polynomial * phdisp ;
140 cpl_polynomial * poly_sol ;
141 cpl_matrix * samppos ;
142 cpl_size mindeg, maxdeg ;
143 cpl_bivector * lines_biv ;
146 cpl_table * real_sol ;
147 int nrows, spec_pos ;
148 cpl_bivector * cat_biv ;
153 cpl_polynomial * disp_poly ;
154 cpl_table * wl_infos[CRIRES_NB_DETECTORS] ;
155 cpl_table * wl_tab[CRIRES_NB_DETECTORS] ;
156 cpl_imagelist * wl_map ;
160 setlocale(LC_NUMERIC,
"C");
163 for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
164 crires_util_wlcalib_config.qc_wlcent[i] = -1.0 ;
165 crires_util_wlcalib_config.qc_wldisp[i] = -1.0 ;
166 crires_util_wlcalib_config.qc_wlxc[i] = -1.0 ;
170 crires_util_wlcalib_config.lines = NULL ;
171 crires_util_wlcalib_config.use_ppm = 0 ;
172 crires_util_wlcalib_config.slitw = 2 ;
173 crires_util_wlcalib_config.fwhm = 2 ;
176 sval = crires_parameterlist_get_string(parlist, RECIPE_STRING,
177 CRIRES_PARAM_WAVES) ;
178 if (sscanf(sval,
"%lg,%lg,%lg,%lg,%lg,%lg,%lg,%lg",
179 &crires_util_wlcalib_config.wstart[0],
180 &crires_util_wlcalib_config.wstop[0],
181 &crires_util_wlcalib_config.wstart[1],
182 &crires_util_wlcalib_config.wstop[1],
183 &crires_util_wlcalib_config.wstart[2],
184 &crires_util_wlcalib_config.wstop[2],
185 &crires_util_wlcalib_config.wstart[3],
186 &crires_util_wlcalib_config.wstop[3])!=2*CRIRES_NB_DETECTORS){
189 crires_util_wlcalib_config.display = crires_parameterlist_get_int(parlist,
190 RECIPE_STRING, CRIRES_PARAM_DISPLAY) ;
191 crires_util_wlcalib_config.degree = crires_parameterlist_get_int(parlist,
192 RECIPE_STRING, CRIRES_PARAM_DEGREE) ;
193 crires_util_wlcalib_config.wl_log = crires_parameterlist_get_bool(parlist,
194 RECIPE_STRING, CRIRES_PARAM_WL_LOG) ;
195 crires_util_wlcalib_config.wl_nolimit = crires_parameterlist_get_bool(
196 parlist, RECIPE_STRING, CRIRES_PARAM_WL_NOLIMIT) ;
197 crires_util_wlcalib_config.wl_err = crires_parameterlist_get_double(parlist,
198 RECIPE_STRING, CRIRES_PARAM_WL_ERROR) ;
199 crires_util_wlcalib_config.wl_xclimit = crires_parameterlist_get_double(
200 parlist, RECIPE_STRING, CRIRES_PARAM_XC_LIMIT) ;
201 crires_util_wlcalib_config.wl_nsamples = crires_parameterlist_get_int(
202 parlist, RECIPE_STRING, CRIRES_PARAM_WL_NBSAMPLES) ;
203 crires_util_wlcalib_config.wl_clean = crires_parameterlist_get_bool(parlist,
204 RECIPE_STRING, CRIRES_PARAM_WL_CLEAN) ;
205 crires_util_wlcalib_config.lines = crires_parameterlist_get_string(parlist,
206 RECIPE_STRING, CRIRES_PARAM_LINES) ;
207 crires_util_wlcalib_config.first_plotted_line=crires_parameterlist_get_int(
208 parlist, RECIPE_STRING, CRIRES_PARAM_FIRST_PLOTTED) ;
209 crires_util_wlcalib_config.last_plotted_line=crires_parameterlist_get_int(
210 parlist, RECIPE_STRING, CRIRES_PARAM_LAST_PLOTTED) ;
213 if (crires_dfs_set_groups(frameset, NULL)) {
214 cpl_msg_error(__func__,
"Cannot identify RAW and CALIB frames") ;
219 if (cpl_frameset_get_size(frameset) != 2) {
220 cpl_msg_error(__func__,
"Expects 2 files in input") ;
225 fr = cpl_frameset_get_position(frameset, 0);
226 crires_util_wlcalib_config.period =
227 crires_get_detector_illum_period(cpl_frame_get_filename(fr)) ;
228 if (crires_util_wlcalib_config.period == CRIRES_ILLUM_UNKNOWN) {
229 cpl_msg_error(__func__,
230 "Cannot determine the detector illumination period") ;
235 if ((plist=cpl_propertylist_load(cpl_frame_get_filename(fr), 0)) == NULL)
237 sval = crires_pfits_get_ncorrs(plist) ;
238 if (!strcmp(sval,
"FowlerNsampGRstWin")) {
239 crires_util_wlcalib_config.period = CRIRES_ILLUM_FULL_DETECTOR ;
240 crires_util_wlcalib_config.win_mode = 1 ;
242 crires_util_wlcalib_config.win_mode = 0 ;
244 cpl_propertylist_delete(plist) ;
247 crires_display_detector_illum(crires_util_wlcalib_config.period) ;
250 cpl_msg_info(__func__,
"Second frame validity check") ;
251 cpl_msg_indent_more() ;
252 fr = cpl_frameset_get_position(frameset, 1);
253 cat = crires_load_table_check(cpl_frame_get_filename(fr), 1,
254 CRIRES_PROTYPE_CATALOG, -1, -1, 0) ;
256 cpl_msg_error(__func__,
"Second frame is incorrect") ;
257 cpl_msg_indent_less() ;
260 cpl_msg_indent_less() ;
263 nrows = cpl_table_get_nrow(cat) ;
264 cat_biv = cpl_bivector_new(nrows) ;
265 cat_biv_x = cpl_bivector_get_x_data(cat_biv) ;
266 cat_biv_y = cpl_bivector_get_y_data(cat_biv) ;
267 for (i=0 ; i<nrows ; i++) {
268 cat_biv_x[i] = cpl_table_get(cat, CRIRES_COL_WAVELENGTH, i, NULL) ;
269 val = cpl_table_get(cat, CRIRES_COL_EMISSION, i, NULL) ;
270 if (crires_util_wlcalib_config.wl_log && val > 0)
271 cat_biv_y[i] = log10(val) ;
275 cpl_table_delete(cat) ;
278 fr = cpl_frameset_get_position(frameset, 0);
279 fname = cpl_frame_get_filename(fr) ;
282 if (crires_util_wlcalib_config.wl_nolimit == 0) {
283 plist = cpl_propertylist_load(fname, 0) ;
284 wmin = crires_pfits_get_wlen_min(plist) ;
285 wmax = crires_pfits_get_wlen_max(plist) ;
286 cpl_propertylist_delete(plist) ;
287 if (cpl_error_get_code()) {
296 for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
298 if ((i==0 || i==CRIRES_NB_DETECTORS-1) &&
299 (crires_util_wlcalib_config.win_mode == 1)) {
303 cpl_msg_info(__func__,
"Wavelength calibration for chip %d", i+1) ;
305 cpl_msg_info(__func__,
"Load the extracted table") ;
306 cpl_msg_indent_more() ;
307 if ((ext_spec=crires_load_table_check(fname, i+1,
308 CRIRES_PROTYPE_SPEC_PIX, -1, -1, 0)) == NULL) {
309 cpl_msg_warning(__func__,
"Empty extension") ;
310 cpl_msg_indent_less() ;
313 cpl_msg_indent_less() ;
316 cpl_msg_info(__func__,
"Wavelength estimation") ;
317 cpl_msg_indent_more() ;
318 if ((phdisp = crires_wlestimate_compute(
319 crires_util_wlcalib_config.wstart[i],
320 crires_util_wlcalib_config.wstop[i])) == NULL) {
321 if ((phdisp = crires_wlestimate_get(fname, i+1)) == NULL) {
322 cpl_msg_error(__func__,
"Cannot get the wavelength estimate") ;
323 cpl_msg_indent_less() ;
324 cpl_table_delete(ext_spec) ;
328 cpl_msg_indent_less() ;
331 nrows = cpl_table_get_nrow(ext_spec) ;
332 spec = cpl_vector_new(nrows) ;
333 pspec = cpl_vector_get_data(spec) ;
334 for (j=0 ; j<nrows ; j++) {
335 pspec[j] = cpl_table_get(ext_spec, CRIRES_COL_EXTRACT_INT_RECT, j,
338 cpl_table_delete(ext_spec) ;
341 cpl_msg_info(__func__,
"Wavelength calibration computation") ;
342 cpl_msg_indent_more() ;
343 if ((disp_poly = crires_wlcalib_engine(spec, cat_biv, phdisp,
344 crires_util_wlcalib_config.slitw,
345 crires_util_wlcalib_config.fwhm,
346 crires_util_wlcalib_config.degree,
348 crires_util_wlcalib_config.wl_err,
349 crires_util_wlcalib_config.wl_nsamples,
350 crires_util_wlcalib_config.wl_clean,
351 crires_util_wlcalib_config.wl_xclimit,
352 crires_util_wlcalib_config.use_ppm,
353 (i+1==crires_util_wlcalib_config.display),
354 crires_util_wlcalib_config.first_plotted_line,
355 crires_util_wlcalib_config.last_plotted_line,
356 &((crires_util_wlcalib_config.qc_wlxc)[i]),
358 cpl_msg_error(__func__,
359 "Wavelength calibration failed - use estimate") ;
360 disp_poly = cpl_polynomial_duplicate(phdisp) ;
361 crires_util_wlcalib_config.qc_wlxc[i] = -1.0 ;
363 cpl_msg_indent_less() ;
366 crires_util_wlcalib_config.qc_wlcent[i] =
367 cpl_polynomial_eval_1d(disp_poly, (
double)512, NULL) ;
368 crires_util_wlcalib_config.qc_wldisp[i] =
369 (cpl_polynomial_eval_1d(disp_poly, (
double)1024, NULL) -
370 cpl_polynomial_eval_1d(disp_poly, (
double)1, NULL)) / 1023 ;
373 if (crires_util_wlcalib_config.display==i+1) {
376 if (crires_util_wlcalib_config.lines != NULL &&
377 crires_util_wlcalib_config.lines[0] != (
char)0) {
379 cpl_bivector_read((
char*)crires_util_wlcalib_config.lines);
380 if ((lines_biv != NULL) &&
381 (cpl_bivector_get_size(lines_biv)>crires_util_wlcalib_config.degree)) {
382 poly_sol = cpl_polynomial_new(1);
383 samppos = cpl_matrix_wrap(1,
384 cpl_bivector_get_size(lines_biv),
385 cpl_bivector_get_x_data(lines_biv)) ;
387 maxdeg = (cpl_size)crires_util_wlcalib_config.degree ;
388 cpl_polynomial_fit(poly_sol,
390 cpl_bivector_get_y(lines_biv),
394 cpl_matrix_unwrap(samppos) ;
396 if (lines_biv != NULL) cpl_bivector_delete(lines_biv) ;
398 irplib_wlxcorr_plot_solution(phdisp, disp_poly, poly_sol, 1, 1024);
399 if (poly_sol != NULL) {
400 real_sol = irplib_wlxcorr_gen_spc_table(spec, cat_biv,
401 crires_util_wlcalib_config.slitw,
402 crires_util_wlcalib_config.fwhm,
404 irplib_wlxcorr_plot_spc_table(real_sol,
"Real",
405 crires_util_wlcalib_config.first_plotted_line,
406 crires_util_wlcalib_config.last_plotted_line) ;
407 cpl_table_delete(real_sol) ;
409 if (poly_sol != NULL) cpl_polynomial_delete(poly_sol) ;
413 wl_infos[i] = irplib_wlxcorr_gen_spc_table(spec, cat_biv,
414 crires_util_wlcalib_config.slitw,
415 crires_util_wlcalib_config.fwhm,
419 cpl_vector_delete(spec) ;
420 cpl_polynomial_delete(phdisp) ;
423 if (crires_util_wlcalib_config.qc_wlxc[i] > 0)
424 spec_pos = crires_get_y_spec_position(fname, i+1) ;
427 wl_tab[i] = crires_wlcalib_gen_wltab_one(
428 (
const cpl_polynomial *)disp_poly,
430 crires_util_wlcalib_config.qc_wlxc[i]) ;
431 cpl_polynomial_delete(disp_poly) ;
433 cpl_bivector_delete(cat_biv) ;
436 if (crires_util_wlcalib_config.win_mode == 1) {
437 if (wl_tab[1] != NULL) {
438 wl_tab[0] = cpl_table_duplicate(wl_tab[1]) ;
439 cpl_table_set_size(wl_tab[0], 0) ;
440 wl_tab[CRIRES_NB_DETECTORS-1] = cpl_table_duplicate(wl_tab[0]) ;
442 if (wl_infos[1] != NULL) {
443 wl_infos[0] = cpl_table_duplicate(wl_infos[1]) ;
444 cpl_table_set_size(wl_infos[0], 0) ;
445 wl_infos[CRIRES_NB_DETECTORS-1] = cpl_table_duplicate(wl_infos[0]) ;
450 if ((wl_map = crires_wlcalib_gen_wlmap((
const cpl_table **)wl_tab))
452 cpl_msg_error(__func__,
"Cannot create WL Map") ;
453 for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
454 if (wl_tab[i] != NULL) cpl_table_delete(wl_tab[i]) ;
455 if (wl_infos[i] != NULL) cpl_table_delete(wl_infos[i]) ;
461 cpl_msg_info(__func__,
"Save the products") ;
462 cpl_msg_indent_more() ;
463 if (crires_util_wlcalib_save(wl_map, (
const cpl_table **)wl_tab,
464 (
const cpl_table **)wl_infos, parlist, frameset) == -1) {
465 cpl_msg_error(__func__,
"Cannot save products");
466 cpl_msg_indent_less() ;
467 cpl_imagelist_delete(wl_map) ;
468 for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
469 if (wl_tab[i] != NULL) cpl_table_delete(wl_tab[i]) ;
470 if (wl_infos[i] != NULL) cpl_table_delete(wl_infos[i]) ;
474 cpl_msg_indent_less() ;
475 cpl_imagelist_delete(wl_map) ;
476 for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
477 if (wl_tab[i] != NULL) cpl_table_delete(wl_tab[i]) ;
478 if (wl_infos[i] != NULL) cpl_table_delete(wl_infos[i]) ;
482 if (cpl_error_get_code())
return -1 ;
497 static int crires_util_wlcalib_save(
498 const cpl_imagelist * ilist,
499 const cpl_table ** tab,
500 const cpl_table ** xctab,
501 const cpl_parameterlist * parlist,
504 cpl_propertylist ** qclists ;
505 const cpl_frame * ref_frame ;
506 cpl_propertylist * inputlist ;
507 const char * recipe_name =
"crires_util_wlcalib" ;
511 ref_frame = irplib_frameset_get_first_from_group(set, CPL_FRAME_GROUP_RAW) ;
514 qclists = cpl_malloc(CRIRES_NB_DETECTORS *
sizeof(cpl_propertylist*)) ;
515 for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
516 qclists[i] = cpl_propertylist_new() ;
517 cpl_propertylist_append_double(qclists[i],
"ESO QC CENTWL",
518 crires_util_wlcalib_config.qc_wlcent[i]) ;
519 cpl_propertylist_append_double(qclists[i],
"ESO QC DISPWL",
520 crires_util_wlcalib_config.qc_wldisp[i]) ;
521 cpl_propertylist_append_double(qclists[i],
"ESO QC XCORR",
522 crires_util_wlcalib_config.qc_wlxc[i]) ;
525 inputlist = cpl_propertylist_load_regexp(
526 cpl_frame_get_filename(ref_frame), i+1,
527 CRIRES_HEADER_EXT_FORWARD, 0) ;
528 cpl_propertylist_copy_property_regexp(qclists[i], inputlist,
529 CRIRES_HEADER_EXT_FORWARD, 0) ;
530 cpl_propertylist_delete(inputlist) ;
534 crires_image_save(set,
540 CRIRES_PROTYPE_WL_MAP,
541 crires_util_wlcalib_config.period,
543 (
const cpl_propertylist **)qclists,
544 PACKAGE
"/" PACKAGE_VERSION,
545 "crires_util_wlcalib_ima.fits") ;
548 crires_table_save(set,
554 CRIRES_PROTYPE_WL_POLY,
556 (
const cpl_propertylist **)qclists,
557 PACKAGE
"/" PACKAGE_VERSION,
558 "crires_util_wlcalib_tab.fits") ;
560 if (xctab[0] != NULL) {
562 crires_table_save(set,
568 CRIRES_PROTYPE_XCORR,
570 (
const cpl_propertylist **)qclists,
571 PACKAGE
"/" PACKAGE_VERSION,
572 "crires_util_wlcalib_xctab.fits") ;
576 for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
577 cpl_propertylist_delete(qclists[i]) ;