CRIRES Pipeline Reference Manual  2.3.15
crires_spec_astro.c
1 /*
2  * This file is part of the CRIRES Pipeline
3  * Copyright (C) 2002,2003 European Southern Observatory
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  */
19 
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23 
24 /*-----------------------------------------------------------------------------
25  Includes
26  -----------------------------------------------------------------------------*/
27 
28 #include <locale.h>
29 #include "crires_recipe.h"
30 
31 #include "crires_model_kernel.h"
32 #include "crires_combine.h"
33 #include "crires_extract.h"
34 #include "crires_photom.h"
35 #include "crires_wlcalib.h"
36 #include "irplib_utils.h"
37 
38 /*-----------------------------------------------------------------------------
39  Define
40  -----------------------------------------------------------------------------*/
41 
42 #define RECIPE_STRING "crires_spec_astro"
43 
44 /*-----------------------------------------------------------------------------
45  Functions prototypes
46  -----------------------------------------------------------------------------*/
47 
48 static int crires_spec_astro_compare(const cpl_frame *, const cpl_frame *) ;
49 static cpl_imagelist ** crires_spec_astro_reduce(cpl_frameset *,
50  const char *, const char *, const char *, const char *, const char *,
51  const char *, const char *, const char *, cpl_imagelist **,
52  cpl_imagelist **, cpl_imagelist **, cpl_imagelist **,
53  cpl_table **, cpl_table **, cpl_table **, cpl_table **) ;
54 static int crires_spec_astro_save(const cpl_imagelist **,
55  const cpl_imagelist *, const cpl_imagelist *, const cpl_table **,
56  const cpl_imagelist *, const cpl_imagelist *, int,
57  const cpl_frameset *, const cpl_parameterlist *, cpl_frameset *) ;
58 
59 static char crires_spec_astro_description[] =
60 "crires_spec_astro -- Astrometry recipe\n"
61 "The files listed in the Set Of Frames (sof-file) must be tagged:\n"
62 "raw-file.fits "CRIRES_SPEC_ASTRO_RAW" or\n"
63 "flat-file.fits "CRIRES_CALPRO_FLAT" or\n"
64 "bpm-file.fits "CRIRES_CALPRO_BPM" or\n"
65 "dark-file.fits "CRIRES_CALPRO_DARK" or\n"
66 "detlin-file.fits "CRIRES_CALPRO_COEFFS_CUBE" or\n"
67 "wavecal-file.fits "CRIRES_CALPRO_WAVE" or\n"
68 "catalog-file.fits "CRIRES_CALPRO_OH_CAT" or\n"
69 "catalog-file.fits "CRIRES_CALPRO_HITRAN_CAT" or\n"
70 "model-config-file.fits "CRIRES_CALPRO_MODEL_CONFIG".\n"
71 "\n"
72 "The input data set is a series of nodding observations using different\n"
73 " derotator position angles. The data are reduced separately for each\n"
74 " of those positions. In order not to degrade the instrument high\n"
75 " resolution, the combined images using only NODA or NODB nodding\n"
76 " positions can be produced on request. (see --onlyA/B)\n"
77 " In this case, the following spectrum extraction can be applied \n"
78 " either on the usual combined image or on those NODA/B combined\n"
79 " images (see --comb_used).\n"
80 "\n"
81 "This recipe produces 6 to 11 files per rotation angle:\n"
82 " The combined image (PRO TYPE = "CRIRES_PROTYPE_COMBINED")\n"
83 " The contribution map (PRO TYPE = "CRIRES_PROTYPE_CONTRIB")\n"
84 " The combined image using only Nodding A frames (optional)\n"
85 " (PRO TYPE = "CRIRES_PROTYPE_COMBINED")\n"
86 " The contribution map using only Nodding A frames (optional)\n"
87 " (PRO TYPE = "CRIRES_PROTYPE_CONTRIB")\n"
88 " The combined image using only Nodding B frames (optional)\n"
89 " (PRO TYPE = "CRIRES_PROTYPE_COMBINED")\n"
90 " The contribution map using only Nodding B frames (optional)\n"
91 " (PRO TYPE = "CRIRES_PROTYPE_CONTRIB")\n"
92 " The table with the extracted spectrum\n"
93 " (PRO TYPE = "CRIRES_PROTYPE_SPEC_WL")\n"
94 " The profile image (PRO TYPE = "CRIRES_PROTYPE_PROFILE")\n"
95 " The background map (PRO TYPE = "CRIRES_PROTYPE_BGD_MAP")\n"
96 " The wavelength map (PRO TYPE = "CRIRES_PROTYPE_WL_MAP")\n"
97 " The wavelength map from the model (optional)\n"
98 " (PRO TYPE = "CRIRES_PROTYPE_WL_MAP")\n" ;
99 
100 CRIRES_RECIPE_DEFINE(crires_spec_astro,
101  CRIRES_PARAM_WAVES |
102  CRIRES_PARAM_DISPLAY |
103  CRIRES_PARAM_REFINE |
104  CRIRES_PARAM_ONLYA |
105  CRIRES_PARAM_ONLYB |
106  CRIRES_PARAM_COMB_USED |
107  CRIRES_PARAM_BLIND |
108  CRIRES_PARAM_HOR_SIZE |
109  CRIRES_PARAM_SPEC_HSIZE |
110  CRIRES_PARAM_KAPPA |
111  CRIRES_PARAM_CLOSING_HSIZE |
112  CRIRES_PARAM_CLEAN_RATE |
113  CRIRES_PARAM_REJECT |
114  CRIRES_PARAM_Y_SPEC_ZONE_CHIP1 |
115  CRIRES_PARAM_Y_SPEC_ZONE_CHIP2 |
116  CRIRES_PARAM_Y_SPEC_ZONE_CHIP3 |
117  CRIRES_PARAM_Y_SPEC_ZONE_CHIP4 |
118  CRIRES_PARAM_WL_ERROR |
119  CRIRES_PARAM_XC_LIMIT |
120  CRIRES_PARAM_WL_LOG |
121  CRIRES_PARAM_WL_NOLIMIT |
122  CRIRES_PARAM_WL_NBSAMPLES |
123  CRIRES_PARAM_Y_POS_CHIP1 |
124  CRIRES_PARAM_Y_POS_CHIP2 |
125  CRIRES_PARAM_Y_POS_CHIP3 |
126  CRIRES_PARAM_Y_POS_CHIP4 |
127  CRIRES_PARAM_Y_WIDTH |
128  CRIRES_PARAM_DEGREE |
129  CRIRES_PARAM_WL_CLEAN,
130  "Astrometry recipe",
131  crires_spec_astro_description) ;
132 
133 /*-----------------------------------------------------------------------------
134  Static variables
135  -----------------------------------------------------------------------------*/
136 
137 static struct {
138  /* Inputs */
139  int comb_blind ;
140  int comb_refine ;
141  int comb_onlyA ;
142  int comb_onlyB ;
143  crires_comb_method comb_used ;
144  double wstart[CRIRES_NB_DETECTORS] ;
145  double wstop[CRIRES_NB_DETECTORS] ;
146  int wl_nolimit ;
147  int wl_log ;
148  const char * wl_ypos_c1 ;
149  const char * wl_ypos_c2 ;
150  const char * wl_ypos_c3 ;
151  const char * wl_ypos_c4 ;
152  int wl_width ;
153  double wl_fwhm ;
154  double wl_slitw ;
155  int wl_degree ;
156  double wl_err ;
157  int wl_samples ;
158  int wl_clean ;
159  double wl_xclimit ;
160  int wl_ppm ;
161  int extr_box_hor_size ;
162  int extr_spec_hsize ;
163  double extr_kappa ;
164  int extr_closing_hs ;
165  int extr_clean_rate ;
166  int extr_rej_left ;
167  int extr_rej_right ;
168  const char * extr_y_spec_zone_c1 ;
169  const char * extr_y_spec_zone_c2 ;
170  const char * extr_y_spec_zone_c3 ;
171  const char * extr_y_spec_zone_c4 ;
172  int extr_spec_stopy ;
173  int display ;
174  /* Outputs */
175  crires_illum_period period ;
176  int qc_specpos[CRIRES_NB_DETECTORS] ;
177  int qc_specwrec[CRIRES_NB_DETECTORS] ;
178  int qc_specwopt[CRIRES_NB_DETECTORS] ;
179  double qc_specoptmed[CRIRES_NB_DETECTORS] ;
180  double qc_s2nmed[CRIRES_NB_DETECTORS] ;
181  double qc_wlxc[CRIRES_NB_DETECTORS] ;
182  double qc_wlcent[CRIRES_NB_DETECTORS] ;
183  double qc_wldisp[CRIRES_NB_DETECTORS] ;
184  double qc_fwhm_comb_pix[CRIRES_NB_DETECTORS] ;
185  double qc_fwhm_comb_as[CRIRES_NB_DETECTORS] ;
186  double qc_fwhm_prof_pix[CRIRES_NB_DETECTORS] ;
187  double qc_fwhm_prof_as[CRIRES_NB_DETECTORS] ;
188  double qc_fwhm_diff[CRIRES_NB_DETECTORS] ;
189 } crires_spec_astro_config ;
190 
191 /*-----------------------------------------------------------------------------
192  Functions code
193  -----------------------------------------------------------------------------*/
194 
195 /*----------------------------------------------------------------------------*/
202 /*----------------------------------------------------------------------------*/
203 static int crires_spec_astro(
204  cpl_frameset * frameset,
205  const cpl_parameterlist * parlist)
206 {
207  cpl_frameset * raw_one ;
208  const char * sval ;
209  cpl_frameset * rawframes ;
210  const char * flat ;
211  const char * dark ;
212  const char * bpm ;
213  const char * detlin ;
214  const char * wavecal ;
215  const char * oh_cat ;
216  const char * hitran_cat ;
217  const char * cfg_model ;
218  cpl_size * labels ;
219  cpl_size nlabels ;
220  cpl_imagelist ** comblist ;
221  cpl_table * extr_tab[CRIRES_NB_DETECTORS] ;
222  cpl_imagelist * prof_list ;
223  cpl_imagelist * bgmap_list ;
224  cpl_imagelist * wl_map ;
225  cpl_imagelist * wl_map_model ;
226  int i, j ;
227 
228  /* Needed for sscanf() */
229  setlocale(LC_NUMERIC, "C");
230 
231  /* Initialise */
232  rawframes = NULL ;
233  crires_spec_astro_config.wl_ppm = 0 ;
234  crires_spec_astro_config.wl_slitw = 2.0 ;
235  crires_spec_astro_config.wl_fwhm = 2.0 ;
236 
237  /* Retrieve input parameters */
238  crires_spec_astro_config.display = crires_parameterlist_get_int(parlist,
239  RECIPE_STRING, CRIRES_PARAM_DISPLAY) ;
240  crires_spec_astro_config.comb_refine = crires_parameterlist_get_bool(
241  parlist, RECIPE_STRING, CRIRES_PARAM_REFINE) ;
242  crires_spec_astro_config.comb_onlyA = crires_parameterlist_get_bool(
243  parlist, RECIPE_STRING, CRIRES_PARAM_ONLYA) ;
244  crires_spec_astro_config.comb_onlyB = crires_parameterlist_get_bool(
245  parlist, RECIPE_STRING, CRIRES_PARAM_ONLYB) ;
246  sval = crires_parameterlist_get_string(parlist, RECIPE_STRING,
247  CRIRES_PARAM_COMB_USED) ;
248  if (!strcmp(sval, "NODA"))
249  crires_spec_astro_config.comb_used = CRIRES_COMB_METHOD_NODA ;
250  else if (!strcmp(sval, "NODB"))
251  crires_spec_astro_config.comb_used = CRIRES_COMB_METHOD_NODB ;
252  else if (!strcmp(sval, "COMB"))
253  crires_spec_astro_config.comb_used = CRIRES_COMB_METHOD_COMB ;
254  else {
255  cpl_msg_error(__func__, "Invalid combination method specified");
256  cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
257  return -1;
258  }
259  crires_spec_astro_config.comb_blind = crires_parameterlist_get_bool(
260  parlist, RECIPE_STRING, CRIRES_PARAM_BLIND) ;
261  sval = crires_parameterlist_get_string(parlist, RECIPE_STRING,
262  CRIRES_PARAM_WAVES) ;
263  if (sscanf(sval, "%lg,%lg,%lg,%lg,%lg,%lg,%lg,%lg",
264  &crires_spec_astro_config.wstart[0],
265  &crires_spec_astro_config.wstop[0],
266  &crires_spec_astro_config.wstart[1],
267  &crires_spec_astro_config.wstop[1],
268  &crires_spec_astro_config.wstart[2],
269  &crires_spec_astro_config.wstop[2],
270  &crires_spec_astro_config.wstart[3],
271  &crires_spec_astro_config.wstop[3])!=2*CRIRES_NB_DETECTORS){
272  cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
273  return -1 ;
274  }
275  crires_spec_astro_config.wl_log = crires_parameterlist_get_bool(parlist,
276  RECIPE_STRING, CRIRES_PARAM_WL_LOG) ;
277  crires_spec_astro_config.wl_nolimit = crires_parameterlist_get_bool(
278  parlist, RECIPE_STRING, CRIRES_PARAM_WL_NOLIMIT) ;
279  crires_spec_astro_config.wl_degree = crires_parameterlist_get_int(parlist,
280  RECIPE_STRING, CRIRES_PARAM_DEGREE) ;
281  crires_spec_astro_config.wl_err = crires_parameterlist_get_double(parlist,
282  RECIPE_STRING, CRIRES_PARAM_WL_ERROR) ;
283  crires_spec_astro_config.wl_xclimit = crires_parameterlist_get_double(
284  parlist, RECIPE_STRING, CRIRES_PARAM_XC_LIMIT) ;
285  crires_spec_astro_config.wl_samples = crires_parameterlist_get_int(parlist,
286  RECIPE_STRING, CRIRES_PARAM_WL_NBSAMPLES) ;
287  crires_spec_astro_config.wl_clean = crires_parameterlist_get_bool(parlist,
288  RECIPE_STRING, CRIRES_PARAM_WL_CLEAN) ;
289  crires_spec_astro_config.wl_ypos_c1=(char*)crires_parameterlist_get_string(
290  parlist, RECIPE_STRING, CRIRES_PARAM_Y_POS_CHIP1) ;
291  crires_spec_astro_config.wl_ypos_c2=(char*)crires_parameterlist_get_string(
292  parlist, RECIPE_STRING, CRIRES_PARAM_Y_POS_CHIP2) ;
293  crires_spec_astro_config.wl_ypos_c3=(char*)crires_parameterlist_get_string(
294  parlist, RECIPE_STRING, CRIRES_PARAM_Y_POS_CHIP3) ;
295  crires_spec_astro_config.wl_ypos_c4=(char*)crires_parameterlist_get_string(
296  parlist, RECIPE_STRING, CRIRES_PARAM_Y_POS_CHIP4) ;
297  crires_spec_astro_config.wl_width= crires_parameterlist_get_int(parlist,
298  RECIPE_STRING, CRIRES_PARAM_Y_WIDTH) ;
299  crires_spec_astro_config.extr_box_hor_size = crires_parameterlist_get_int(
300  parlist, RECIPE_STRING, CRIRES_PARAM_HOR_SIZE) ;
301  crires_spec_astro_config.extr_spec_hsize = crires_parameterlist_get_int(
302  parlist, RECIPE_STRING, CRIRES_PARAM_SPEC_HSIZE) ;
303  crires_spec_astro_config.extr_kappa = crires_parameterlist_get_double(
304  parlist, RECIPE_STRING, CRIRES_PARAM_KAPPA) ;
305  crires_spec_astro_config.extr_closing_hs = crires_parameterlist_get_int(
306  parlist, RECIPE_STRING, CRIRES_PARAM_CLOSING_HSIZE) ;
307  crires_spec_astro_config.extr_clean_rate = crires_parameterlist_get_double(
308  parlist, RECIPE_STRING, CRIRES_PARAM_CLEAN_RATE) ;
309  sval = crires_parameterlist_get_string(parlist, RECIPE_STRING,
310  CRIRES_PARAM_REJECT) ;
311  if (sscanf(sval, "%d,%d",
312  &crires_spec_astro_config.extr_rej_left,
313  &crires_spec_astro_config.extr_rej_right)!=2) {
314  cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
315  return -1 ;
316  }
317  crires_spec_astro_config.extr_y_spec_zone_c1 =
318  crires_parameterlist_get_string(parlist, RECIPE_STRING,
319  CRIRES_PARAM_Y_SPEC_ZONE_CHIP1) ;
320  crires_spec_astro_config.extr_y_spec_zone_c2 =
321  crires_parameterlist_get_string(parlist, RECIPE_STRING,
322  CRIRES_PARAM_Y_SPEC_ZONE_CHIP2) ;
323  crires_spec_astro_config.extr_y_spec_zone_c3 =
324  crires_parameterlist_get_string(parlist, RECIPE_STRING,
325  CRIRES_PARAM_Y_SPEC_ZONE_CHIP3) ;
326  crires_spec_astro_config.extr_y_spec_zone_c4 =
327  crires_parameterlist_get_string(parlist, RECIPE_STRING,
328  CRIRES_PARAM_Y_SPEC_ZONE_CHIP4) ;
329 
330  /* Identify the RAW and CALIB frames in the input frameset */
331  if (crires_dfs_set_groups(frameset, "crires_spec_astro")) {
332  cpl_msg_error(__func__, "Cannot identify RAW and CALIB frames") ;
333  cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
334  return -1 ;
335  }
336 
337  /* Retrieve calibration data */
338  flat = crires_extract_filename(frameset, CRIRES_CALPRO_FLAT) ;
339  dark = crires_extract_filename(frameset, CRIRES_CALPRO_DARK) ;
340  bpm = crires_extract_filename(frameset, CRIRES_CALPRO_BPM) ;
341  detlin = crires_extract_filename(frameset, CRIRES_CALPRO_COEFFS_CUBE) ;
342  wavecal = crires_extract_filename(frameset, CRIRES_CALPRO_WAVE) ;
343  oh_cat = crires_extract_filename(frameset, CRIRES_CALPRO_OH_CAT) ;
344  hitran_cat = crires_extract_filename(frameset, CRIRES_CALPRO_HITRAN_CAT) ;
345  cfg_model = crires_extract_filename(frameset, CRIRES_CALPRO_MODEL_CONFIG);
346 
347  /* Retrieve raw frames */
348  if ((rawframes = crires_extract_frameset(frameset,
349  CRIRES_SPEC_ASTRO_RAW)) == NULL) {
350  cpl_msg_error(__func__, "No raw frame in input") ;
351  cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
352  return -1 ;
353  }
354 
355  /* Checks on the parameters validity */
356  if ((crires_spec_astro_config.comb_used == CRIRES_COMB_METHOD_NODA)
357  && (crires_spec_astro_config.comb_onlyA == 0)) {
358  cpl_msg_warning(__func__,
359  "You forgot to require the NODA image to be produced !") ;
360  crires_spec_astro_config.comb_onlyA = 1 ;
361  }
362  if ((crires_spec_astro_config.comb_used == CRIRES_COMB_METHOD_NODB)
363  && (crires_spec_astro_config.comb_onlyB == 0)) {
364  cpl_msg_warning(__func__,
365  "You forgot to require the NODB image to be produced !") ;
366  crires_spec_astro_config.comb_onlyB = 1 ;
367  }
368 
369  /* Get the detector illumination period */
370  crires_spec_astro_config.period =
371  crires_get_detector_illum_period(
372  cpl_frame_get_filename(cpl_frameset_get_position(rawframes, 0))) ;
373  if (crires_spec_astro_config.period == CRIRES_ILLUM_UNKNOWN) {
374  cpl_msg_error(__func__,
375  "Cannot determine the detector illumination period") ;
376  cpl_frameset_delete(rawframes) ;
377  cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
378  return -1 ;
379  } else {
380  crires_display_detector_illum(crires_spec_astro_config.period) ;
381  }
382 
383  /* Labelise the raw frames with the DROT POSANG */
384  if ((labels = cpl_frameset_labelise(rawframes, crires_spec_astro_compare,
385  &nlabels)) == NULL) {
386  cpl_msg_error(__func__, "Cannot labelise input frames") ;
387  cpl_frameset_delete(rawframes) ;
388  cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
389  return -1 ;
390  }
391 
392  /* Loop on the settings */
393  for (i=0 ; i<(int)nlabels ; i++) {
394 
395  /* Initialise */
396  for (j=0 ; j<CRIRES_NB_DETECTORS ; j++) {
397  crires_spec_astro_config.qc_specpos[j] = -1 ;
398  crires_spec_astro_config.qc_specwrec[j] = -1 ;
399  crires_spec_astro_config.qc_specwopt[j] = -1 ;
400  crires_spec_astro_config.qc_specoptmed[j] = -1.0 ;
401  crires_spec_astro_config.qc_s2nmed[j] = -1.0 ;
402  crires_spec_astro_config.qc_wlxc[j] = -1.0 ;
403  crires_spec_astro_config.qc_wlcent[j] = -1.0 ;
404  crires_spec_astro_config.qc_wldisp[j] = -1.0 ;
405  crires_spec_astro_config.qc_fwhm_comb_pix[j] = -1.0 ;
406  crires_spec_astro_config.qc_fwhm_comb_as[j] = -1.0 ;
407  crires_spec_astro_config.qc_fwhm_prof_pix[j] = -1.0 ;
408  crires_spec_astro_config.qc_fwhm_prof_as[j] = -1.0 ;
409  crires_spec_astro_config.qc_fwhm_diff[j] = -1.0 ;
410  }
411 
412  /* Get the frames for the current setting */
413  raw_one = cpl_frameset_extract(rawframes, labels, (cpl_size)i) ;
414 
415  /* Reduce data set nb i */
416  cpl_msg_info(__func__, "Reduce data set %d / %"CPL_SIZE_FORMAT,
417  i+1, nlabels);
418  cpl_msg_indent_more() ;
419 
420  /* Apply the reduction */
421  if ((comblist = crires_spec_astro_reduce(raw_one, flat, dark, bpm,
422  detlin, wavecal, oh_cat, hitran_cat, cfg_model,
423  &wl_map,
424  &wl_map_model,
425  &prof_list,
426  &bgmap_list,
427  &(extr_tab[0]),
428  &(extr_tab[1]),
429  &(extr_tab[2]),
430  &(extr_tab[3]))) == NULL) {
431  cpl_msg_error(__func__, "Cannot reduce setting") ;
432  cpl_frameset_delete(rawframes) ;
433  cpl_frameset_delete(raw_one) ;
434  cpl_free(labels) ;
435  cpl_msg_indent_less() ;
436  return -1 ;
437  }
438 
439  /* Save the product */
440  cpl_msg_info(__func__, "Save the products") ;
441  cpl_msg_indent_more() ;
442  if (crires_spec_astro_save((const cpl_imagelist **)comblist,
443  prof_list, bgmap_list,
444  (const cpl_table **)extr_tab, wl_map, wl_map_model,
445  i+1, raw_one, parlist, frameset)) {
446  cpl_msg_error(__func__, "Cannot save the product") ;
447  cpl_imagelist_delete(comblist[0]) ;
448  cpl_imagelist_delete(comblist[1]) ;
449  if (crires_spec_astro_config.comb_onlyA) {
450  cpl_imagelist_delete(comblist[2]) ;
451  cpl_imagelist_delete(comblist[3]) ;
452  }
453  if (crires_spec_astro_config.comb_onlyB) {
454  cpl_imagelist_delete(comblist[4]) ;
455  cpl_imagelist_delete(comblist[5]) ;
456  }
457  cpl_free(comblist) ;
458  cpl_imagelist_delete(prof_list) ;
459  cpl_imagelist_delete(bgmap_list) ;
460  for (j=0 ; j<CRIRES_NB_DETECTORS ; j++)
461  if (extr_tab[j] != NULL) cpl_table_delete(extr_tab[j]) ;
462  cpl_imagelist_delete(wl_map) ;
463  if (wl_map_model) cpl_imagelist_delete(wl_map_model) ;
464  cpl_frameset_delete(raw_one) ;
465  cpl_frameset_delete(rawframes) ;
466  cpl_free(labels) ;
467  cpl_msg_indent_less() ;
468  return -1 ;
469  }
470  cpl_imagelist_delete(comblist[0]) ;
471  cpl_imagelist_delete(comblist[1]) ;
472  if (crires_spec_astro_config.comb_onlyA) {
473  cpl_imagelist_delete(comblist[2]) ;
474  cpl_imagelist_delete(comblist[3]) ;
475  }
476  if (crires_spec_astro_config.comb_onlyB) {
477  cpl_imagelist_delete(comblist[4]) ;
478  cpl_imagelist_delete(comblist[5]) ;
479  }
480  cpl_free(comblist) ;
481  cpl_imagelist_delete(prof_list) ;
482  cpl_imagelist_delete(bgmap_list) ;
483  for (j=0 ; j<CRIRES_NB_DETECTORS ; j++)
484  if (extr_tab[j] != NULL) cpl_table_delete(extr_tab[j]) ;
485  cpl_imagelist_delete(wl_map) ;
486  if (wl_map_model) cpl_imagelist_delete(wl_map_model) ;
487  cpl_frameset_delete(raw_one) ;
488  cpl_msg_indent_less() ;
489  }
490  cpl_frameset_delete(rawframes) ;
491  cpl_free(labels) ;
492 
493  /* Here comes the postprocessing on the 180 degrees difference spectra */
494 
495 
496 
497 
498  /* Return */
499  if (cpl_error_get_code()) return -1 ;
500  else return 0 ;
501 }
502 
503 /*----------------------------------------------------------------------------*/
508 /*----------------------------------------------------------------------------*/
509 static cpl_imagelist ** crires_spec_astro_reduce(
510  cpl_frameset * rawframes,
511  const char * flat,
512  const char * dark,
513  const char * bpm,
514  const char * detlin,
515  const char * wavecal,
516  const char * oh_cat,
517  const char * hitran_cat,
518  const char * cfg_model,
519  cpl_imagelist ** wl_map,
520  cpl_imagelist ** wl_map_model,
521  cpl_imagelist ** prof_list,
522  cpl_imagelist ** bgmap_list,
523  cpl_table ** extr_tab1,
524  cpl_table ** extr_tab2,
525  cpl_table ** extr_tab3,
526  cpl_table ** extr_tab4)
527 {
528  cpl_frame * fr ;
529  const char * fname ;
530  const char * wl_ypos ;
531  const char * y_pos ;
532  cpl_propertylist * plist ;
533  double wmin, wmax ;
534  double tot_ndit ;
535  cpl_imagelist ** comblist ;
536  int comblist_offset ;
537  cpl_table * wave_tab[CRIRES_NB_DETECTORS] ;
538  cpl_image * profiles[CRIRES_NB_DETECTORS] ;
539  cpl_image * bg_maps[CRIRES_NB_DETECTORS] ;
540  cpl_imagelist * wl_map_loc ;
541  cpl_imagelist * wl_map_model_loc ;
542  cpl_imagelist * prof_list_loc ;
543  cpl_imagelist * bgmap_list_loc ;
544  cpl_table * extr_tab[CRIRES_NB_DETECTORS] ;
545  cpl_vector ** wavelengths ;
546  cpl_vector * wave_ypos ;
547  int pix ;
548  int extr_spec_stopy, extr_spec_starty ;
549  int i, j ;
550 
551  /* Set comblist_offset */
552  if (crires_spec_astro_config.comb_used == CRIRES_COMB_METHOD_COMB)
553  comblist_offset = 0 ;
554  else if (crires_spec_astro_config.comb_used == CRIRES_COMB_METHOD_NODA)
555  comblist_offset = 1 ;
556  else if (crires_spec_astro_config.comb_used == CRIRES_COMB_METHOD_NODB)
557  comblist_offset = 2 ;
558 
559  /* Get the total number of NDIT */
560  fr = cpl_frameset_get_position(rawframes, 0);
561  tot_ndit = crires_get_totndit(cpl_frame_get_filename(fr)) ;
562  if (tot_ndit < 0) {
563  cpl_msg_error(__func__, "Cannot get the total number of NDIT") ;
564  return NULL ;
565  }
566  tot_ndit *= cpl_frameset_get_size(rawframes) ;
567 
568  /* Images recombination */
569  cpl_msg_info(__func__, "Images combination") ;
570  cpl_msg_indent_more() ;
571  if ((comblist = crires_combine_imagelist(rawframes, NULL,
572  crires_spec_astro_config.period,
573  flat, dark, bpm, detlin, 1,
574  crires_spec_astro_config.comb_blind,
575  crires_spec_astro_config.comb_refine,
576  crires_spec_astro_config.comb_onlyA,
577  crires_spec_astro_config.comb_onlyB)) == NULL) {
578  cpl_msg_error(__func__, "Cannot combine the images") ;
579  cpl_msg_indent_less() ;
580  return NULL ;
581  }
582  cpl_msg_indent_less() ;
583 
584  /* Spectrum extraction */
585  cpl_msg_info(__func__, "Spectrum extraction") ;
586  cpl_msg_indent_more() ;
587  for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
588  cpl_msg_info(__func__, "Chip number %d extraction", i+1) ;
589  cpl_msg_indent_more() ;
590 
591  /* Where is the spectrum extraction zone ? */
592  y_pos = "" ;
593  if (i+1 == 1) y_pos = crires_spec_astro_config.extr_y_spec_zone_c1 ;
594  if (i+1 == 2) y_pos = crires_spec_astro_config.extr_y_spec_zone_c1 ;
595  if (i+1 == 3) y_pos = crires_spec_astro_config.extr_y_spec_zone_c3 ;
596  if (i+1 == 4) y_pos = crires_spec_astro_config.extr_y_spec_zone_c4 ;
597  if (sscanf(y_pos,"%d,%d", &extr_spec_starty, &extr_spec_stopy)!=2) {
598  cpl_msg_warning(__func__, "Wrong Spectral Zone specified: %s",
599  y_pos) ;
600  extr_spec_starty = extr_spec_stopy = -1 ;
601  }
602 
603  /* Extraction */
604  if ((extr_tab[i] = crires_extract_spectrum(
605  cpl_imagelist_get(comblist[0+2*comblist_offset], i),
606  cpl_imagelist_get(comblist[1+2*comblist_offset], i),
607  crires_spec_astro_config.extr_box_hor_size,
608  crires_spec_astro_config.extr_spec_hsize,
609  crires_spec_astro_config.extr_kappa,
610  crires_spec_astro_config.extr_closing_hs,
611  crires_spec_astro_config.extr_clean_rate,
612  crires_spec_astro_config.extr_rej_left,
613  crires_spec_astro_config.extr_rej_right,
614  extr_spec_starty, extr_spec_stopy,
615  i+1,
616  tot_ndit,
617  crires_spec_astro_config.period,
618  &(crires_spec_astro_config.qc_specpos[i]),
619  &(crires_spec_astro_config.qc_specwrec[i]),
620  &(crires_spec_astro_config.qc_specwopt[i]),
621  &(crires_spec_astro_config.qc_specoptmed[i]),
622  &(crires_spec_astro_config.qc_s2nmed[i]),
623  &(profiles[i]),
624  &(bg_maps[i]))) == NULL) {
625  cpl_msg_error(__func__, "Cannot extract the spectrum") ;
626  cpl_msg_indent_less() ;
627  cpl_msg_indent_less() ;
628  for (j=0 ; j<i ; j++)
629  cpl_table_delete(extr_tab[j]) ;
630  for (j=0 ; j<i ; j++)
631  cpl_image_delete(profiles[j]) ;
632  for (j=0 ; j<i ; j++)
633  cpl_image_delete(bg_maps[j]) ;
634  cpl_imagelist_delete(comblist[0]) ;
635  cpl_imagelist_delete(comblist[1]) ;
636  if (crires_spec_astro_config.comb_onlyA) {
637  cpl_imagelist_delete(comblist[2]) ;
638  cpl_imagelist_delete(comblist[3]) ;
639  }
640  if (crires_spec_astro_config.comb_onlyB) {
641  cpl_imagelist_delete(comblist[4]) ;
642  cpl_imagelist_delete(comblist[5]) ;
643  }
644  cpl_free(comblist) ;
645  return NULL ;
646  }
647  cpl_msg_info(__func__, "Chip number %d FWHM Computation", i+1) ;
648  if (crires_extract_qc_fwhm(
649  cpl_imagelist_get(comblist[0+2*comblist_offset], i),
650  profiles[i],
651  &(crires_spec_astro_config.qc_fwhm_comb_pix[i]),
652  &(crires_spec_astro_config.qc_fwhm_comb_as[i]),
653  &(crires_spec_astro_config.qc_fwhm_prof_pix[i]),
654  &(crires_spec_astro_config.qc_fwhm_prof_as[i]),
655  &(crires_spec_astro_config.qc_fwhm_diff[i])) == -1) {
656  cpl_msg_warning(__func__, "Failed for FWHM computation") ;
657  crires_spec_astro_config.qc_fwhm_comb_pix[i] = -1.0 ;
658  crires_spec_astro_config.qc_fwhm_comb_as[i] = -1.0 ;
659  crires_spec_astro_config.qc_fwhm_prof_pix[i] = -1.0 ;
660  crires_spec_astro_config.qc_fwhm_prof_as[i] = -1.0 ;
661  crires_spec_astro_config.qc_fwhm_diff[i] = -1.0 ;
662  }
663  cpl_msg_indent_less() ;
664  }
665 
666  /* Create the profile and bg maps */
667  prof_list_loc = cpl_imagelist_new() ;
668  bgmap_list_loc = cpl_imagelist_new() ;
669  for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
670  cpl_imagelist_set(prof_list_loc, profiles[i], i) ;
671  cpl_imagelist_set(bgmap_list_loc, bg_maps[i], i) ;
672  }
673 
674  /* Test that the spectrum is at the same place in all detectors */
675  for (i=1 ; i<CRIRES_NB_DETECTORS ; i++) {
676  if (crires_spec_astro_config.qc_specpos[i-1] > 0 &&
677  crires_spec_astro_config.qc_specpos[i] > 0 &&
678  fabs(crires_spec_astro_config.qc_specpos[i-1] -
679  crires_spec_astro_config.qc_specpos[i]) >
680  CRIRES_SPEC_POS_TOLERANCE) {
681  cpl_msg_warning(__func__,
682  "The spectrum positions in chip %d and chip %d are too different: %d -> %d",
683  i, i+1, crires_spec_astro_config.qc_specpos[i-1],
684  crires_spec_astro_config.qc_specpos[i]) ;
685  }
686  }
687  cpl_msg_indent_less() ;
688 
689  /* Wavelength calibration */
690  cpl_msg_info(__func__, "Wavelength Calibration") ;
691  cpl_msg_indent_more() ;
692  if (wavecal != NULL) {
693  /* Wavelength solution is provided */
694  cpl_msg_info(__func__, "Use the provided solution") ;
695  for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
696  if ((wave_tab[i] = crires_load_table_check(wavecal, i+1,
697  CRIRES_PROTYPE_WL_POLY, -1, -1, 0)) == NULL) {
698  cpl_msg_error(__func__, "Cannot load the wavelength table") ;
699  cpl_msg_indent_less() ;
700  cpl_imagelist_delete(comblist[0]) ;
701  cpl_imagelist_delete(comblist[1]) ;
702  if (crires_spec_astro_config.comb_onlyA) {
703  cpl_imagelist_delete(comblist[2]) ;
704  cpl_imagelist_delete(comblist[3]) ;
705  }
706  if (crires_spec_astro_config.comb_onlyB) {
707  cpl_imagelist_delete(comblist[4]) ;
708  cpl_imagelist_delete(comblist[5]) ;
709  }
710  cpl_free(comblist) ;
711  cpl_imagelist_delete(prof_list_loc) ;
712  cpl_imagelist_delete(bgmap_list_loc) ;
713  for (j=0 ; j<CRIRES_NB_DETECTORS ; j++)
714  cpl_table_delete(extr_tab[j]) ;
715  return NULL ;
716  }
717  }
718  } else {
719  /* Calibrate from the science */
720  cpl_msg_info(__func__, "Use the science frame sky to calibrate") ;
721 
722  /* first raw frame */
723  fname = cpl_frame_get_filename(cpl_frameset_get_position(rawframes,0)) ;
724 
725  /* Get the Minimum and Maximum wavelengths */
726  if (crires_spec_astro_config.wl_nolimit == 0) {
727  plist = cpl_propertylist_load(fname, 0) ;
728  wmin = crires_pfits_get_wlen_min(plist) ;
729  wmax = crires_pfits_get_wlen_max(plist) ;
730  cpl_propertylist_delete(plist) ;
731  if (cpl_error_get_code()) {
732  wmin = wmax = -1.0 ;
733  cpl_error_reset() ;
734  }
735  } else {
736  wmin = wmax = -1.0 ;
737  }
738 
739  /* Loop on detectors */
740  for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
741  cpl_msg_info(__func__, "Calibrate chip number %d", i+1) ;
742  cpl_msg_indent_more() ;
743 
744  /* Where Compute the wavelength from ? */
745  if (i+1 == 1) wl_ypos = crires_spec_astro_config.wl_ypos_c1 ;
746  if (i+1 == 2) wl_ypos = crires_spec_astro_config.wl_ypos_c2 ;
747  if (i+1 == 3) wl_ypos = crires_spec_astro_config.wl_ypos_c3 ;
748  if (i+1 == 4) wl_ypos = crires_spec_astro_config.wl_ypos_c4 ;
749 
750  if (!strcmp(wl_ypos, "")) {
751  /* Use the spectrum position for the wavelength calibration */
752  cpl_msg_info(__func__,
753  "Compute the wavelength at the spectrum position: %d",
754  crires_spec_astro_config.qc_specpos[i]) ;
755  wave_ypos = cpl_vector_new(1) ;
756  cpl_vector_set(wave_ypos, 0,
757  (double)(crires_spec_astro_config.qc_specpos[i])) ;
758  } else {
759  cpl_msg_info(__func__,
760  "Use the Y positions provided on the command line") ;
761  if ((wave_ypos = crires_parse_y_positions(wl_ypos)) == NULL) {
762  cpl_msg_error(__func__,
763  "Cannot parse the y_pos value : %s - use %d",
764  wl_ypos, crires_spec_astro_config.qc_specpos[i]) ;
765  wave_ypos = cpl_vector_new(1) ;
766  cpl_vector_set(wave_ypos, 0,
767  (double)(crires_spec_astro_config.qc_specpos[i])) ;
768  }
769  }
770 
771  /* Wavelength Calibration */
772  wave_tab[i] = crires_wlcalib_sky(fname,
773  crires_spec_astro_config.period,
774  oh_cat, hitran_cat, crires_spec_astro_config.wl_log,
775  flat, dark, bpm, detlin,
776  crires_spec_astro_config.wstart[i],
777  crires_spec_astro_config.wstop[i],
778  wmin, wmax, i+1,
779  wave_ypos,
780  crires_spec_astro_config.wl_width,
781  crires_spec_astro_config.wl_degree,
782  crires_spec_astro_config.wl_slitw,
783  crires_spec_astro_config.wl_fwhm,
784  crires_spec_astro_config.wl_err,
785  crires_spec_astro_config.wl_samples,
786  crires_spec_astro_config.wl_clean,
787  crires_spec_astro_config.wl_xclimit,
788  crires_spec_astro_config.wl_ppm,
789  (i+1==crires_spec_astro_config.display)) ;
790  cpl_msg_indent_less() ;
791 
792  cpl_vector_delete(wave_ypos) ;
793  }
794  }
795 
796  /* Create the wave map */
797  if ((wl_map_loc = crires_wlcalib_gen_wlmap((const cpl_table **)wave_tab))
798  == NULL) {
799  cpl_msg_error(__func__, "Cannot compute the Wavelength Map") ;
800  cpl_imagelist_delete(comblist[0]) ;
801  cpl_imagelist_delete(comblist[1]) ;
802  if (crires_spec_astro_config.comb_onlyA) {
803  cpl_imagelist_delete(comblist[2]) ;
804  cpl_imagelist_delete(comblist[3]) ;
805  }
806  if (crires_spec_astro_config.comb_onlyB) {
807  cpl_imagelist_delete(comblist[4]) ;
808  cpl_imagelist_delete(comblist[5]) ;
809  }
810  cpl_free(comblist) ;
811  cpl_imagelist_delete(prof_list_loc) ;
812  cpl_imagelist_delete(bgmap_list_loc) ;
813  for (j=0 ; j<CRIRES_NB_DETECTORS ; j++) {
814  cpl_table_delete(extr_tab[j]) ;
815  if (wave_tab[j] != NULL) cpl_table_delete(wave_tab[j]);
816  }
817  return NULL ;
818  }
819 
820  /* Compute the QC parameters */
821  for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
822  crires_spec_astro_config.qc_wlcent[i] =
823  cpl_image_get(cpl_imagelist_get(wl_map_loc, i),
824  512, crires_spec_astro_config.qc_specpos[i], &pix) ;
825  crires_spec_astro_config.qc_wldisp[i] =
826  ((cpl_image_get(cpl_imagelist_get(wl_map_loc, i), 1024,
827  crires_spec_astro_config.qc_specpos[i], &pix)) -
828  (cpl_image_get(cpl_imagelist_get(wl_map_loc, i), 1,
829  crires_spec_astro_config.qc_specpos[i], &pix)))
830  / 1023 ;
831  crires_spec_astro_config.qc_wlxc[i] =
832  crires_wlcalib_get_better_xc(wave_tab[i]) ;
833  }
834  for (i=0 ; i<CRIRES_NB_DETECTORS ; i++)
835  if (wave_tab[i] != NULL) cpl_table_delete(wave_tab[i]);
836 
837  /* Get the wl map from the model */
838  fname = cpl_frame_get_filename(cpl_frameset_get_position(rawframes,0)) ;
839  if ((cfg_model != NULL) && (!crires_model_off()) &&
840  (crires_model_config_check(cfg_model, fname) == 0)) {
841  cpl_msg_info(__func__, "Call the model to get the wavelength map") ;
842  cpl_msg_indent_more() ;
843  wl_map_model_loc = crires_model_wavpix(fname, cfg_model, -1) ;
844  if (wl_map_model_loc == NULL) {
845  cpl_msg_warning(__func__, "Model function returns NULL") ;
846  cpl_error_reset() ;
847  }
848  cpl_msg_indent_less() ;
849  } else {
850  wl_map_model_loc = NULL ;
851  }
852 
853  /* Apply the wavelength */
854  for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
855  cpl_table_new_column(extr_tab[i], CRIRES_COL_WAVELENGTH,
856  CPL_TYPE_DOUBLE) ;
857  for (j=0 ; j<cpl_table_get_nrow(extr_tab[i]) ; j++) {
858  cpl_table_set_double(extr_tab[i], CRIRES_COL_WAVELENGTH, j,
859  cpl_image_get(cpl_imagelist_get_const(wl_map_loc, i), j+1,
860  crires_spec_astro_config.qc_specpos[i], &pix));
861  }
862  }
863 
864  /* Add the Model Wavelength and Call the model to fill it */
865  for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
866  cpl_table_new_column(extr_tab[i], CRIRES_COL_WAVELENGTH_MODEL,
867  CPL_TYPE_DOUBLE) ;
868  cpl_table_fill_column_window_double(extr_tab[i],
869  CRIRES_COL_WAVELENGTH_MODEL, 0,
870  cpl_table_get_nrow(extr_tab[i]), -1.0) ;
871  }
872  if ((cfg_model != NULL) && (!crires_model_off()) && (1)) {
873  cpl_msg_info(__func__, "Call the model to get the wavelengths") ;
874  cpl_msg_indent_more() ;
875  wavelengths = crires_model_wavelengths(
876  cpl_frame_get_filename(cpl_frameset_get_position(rawframes,0)),
877  cfg_model, -1,
878  (double)(crires_spec_astro_config.qc_specpos[0]),
879  wl_map_model_loc) ;
880  if (wavelengths != NULL) {
881  /* Loop on the detectors */
882  for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
883  /* Loop on the x values */
884  for (j=0 ; j<cpl_vector_get_size(wavelengths[i]) ; j++) {
885  cpl_table_set_double(extr_tab[i],
886  CRIRES_COL_WAVELENGTH_MODEL, j,
887  cpl_vector_get(wavelengths[i], j)) ;
888  }
889  }
890  for (i=0 ; i<CRIRES_NB_DETECTORS ; i++)
891  cpl_vector_delete(wavelengths[i]) ;
892  cpl_free(wavelengths) ;
893  } else {
894  cpl_msg_warning(__func__, "Model function returns NULL") ;
895  cpl_error_reset() ;
896  }
897  cpl_msg_indent_less() ;
898  }
899 
900  /* Return */
901  if (wl_map != NULL) *wl_map = wl_map_loc ;
902  else cpl_imagelist_delete(wl_map_loc) ;
903  if (wl_map_model != NULL) *wl_map_model = wl_map_model_loc ;
904  else cpl_imagelist_delete(wl_map_model_loc) ;
905  if (prof_list != NULL) *prof_list = prof_list_loc ;
906  else cpl_imagelist_delete(prof_list_loc) ;
907  if (bgmap_list != NULL) *bgmap_list = bgmap_list_loc ;
908  else cpl_imagelist_delete(bgmap_list_loc) ;
909  if (extr_tab1 != NULL) *extr_tab1 = extr_tab[0] ;
910  else cpl_table_delete(extr_tab[0]) ;
911  if (extr_tab2 != NULL) *extr_tab2 = extr_tab[1] ;
912  else cpl_table_delete(extr_tab[1]) ;
913  if (extr_tab3 != NULL) *extr_tab3 = extr_tab[2] ;
914  else cpl_table_delete(extr_tab[2]) ;
915  if (extr_tab4 != NULL) *extr_tab4 = extr_tab[3] ;
916  else cpl_table_delete(extr_tab[3]) ;
917  return comblist ;
918 }
919 
920 /*----------------------------------------------------------------------------*/
936 /*----------------------------------------------------------------------------*/
937 static int crires_spec_astro_save(
938  const cpl_imagelist ** images,
939  const cpl_imagelist * prof,
940  const cpl_imagelist * bgmap,
941  const cpl_table ** extr_tab,
942  const cpl_imagelist * wl_map,
943  const cpl_imagelist * wl_map_model,
944  int setting,
945  const cpl_frameset * cur_set,
946  const cpl_parameterlist * parlist,
947  cpl_frameset * set)
948 {
949  cpl_propertylist ** qclists ;
950  const cpl_frame * ref_frame ;
951  char * filename ;
952  cpl_propertylist * inputlist ;
953  const char * recipe_name = "crires_spec_astro" ;
954  int i ;
955 
956  /* Get the reference frame */
957  ref_frame = irplib_frameset_get_first_from_group(cur_set,
958  CPL_FRAME_GROUP_RAW) ;
959 
960  /* Create the QC lists */
961  qclists = cpl_malloc(CRIRES_NB_DETECTORS * sizeof(cpl_propertylist*)) ;
962  for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
963  qclists[i] = cpl_propertylist_new() ;
964  cpl_propertylist_append_int(qclists[i], "ESO QC SPECPOS",
965  crires_spec_astro_config.qc_specpos[i]) ;
966  cpl_propertylist_append_int(qclists[i], "ESO QC SPECWREC",
967  crires_spec_astro_config.qc_specwrec[i]) ;
968  cpl_propertylist_append_int(qclists[i], "ESO QC SPECWOPT",
969  crires_spec_astro_config.qc_specwopt[i]) ;
970  cpl_propertylist_append_double(qclists[i], "ESO QC SIGNAL MED",
971  crires_spec_astro_config.qc_specoptmed[i]) ;
972  cpl_propertylist_append_double(qclists[i], "ESO QC S2NMED",
973  crires_spec_astro_config.qc_s2nmed[i]) ;
974  cpl_propertylist_append_double(qclists[i], "ESO QC XCORR",
975  crires_spec_astro_config.qc_wlxc[i]) ;
976  cpl_propertylist_append_double(qclists[i], "ESO QC CENTWL",
977  crires_spec_astro_config.qc_wlcent[i]) ;
978  cpl_propertylist_append_double(qclists[i], "ESO QC DISPWL",
979  crires_spec_astro_config.qc_wldisp[i]) ;
980  cpl_propertylist_append_double(qclists[i], "ESO QC FWHMPIX COMBINED",
981  crires_spec_astro_config.qc_fwhm_comb_pix[i]) ;
982  cpl_propertylist_append_double(qclists[i], "ESO QC FWHMARC COMBINED",
983  crires_spec_astro_config.qc_fwhm_comb_as[i]) ;
984  cpl_propertylist_append_double(qclists[i], "ESO QC FWHMPIX PROFILE",
985  crires_spec_astro_config.qc_fwhm_prof_pix[i]) ;
986  cpl_propertylist_append_double(qclists[i], "ESO QC FWHMARC PROFILE",
987  crires_spec_astro_config.qc_fwhm_prof_as[i]) ;
988  cpl_propertylist_append_double(qclists[i], "ESO QC FWHM DIFF",
989  crires_spec_astro_config.qc_fwhm_diff[i]) ;
990  /* Propagate some keywords from input raw frame extensions */
991  inputlist = cpl_propertylist_load_regexp(
992  cpl_frame_get_filename(ref_frame), i+1,
993  CRIRES_HEADER_EXT_FORWARD, 0) ;
994  cpl_propertylist_copy_property_regexp(qclists[i], inputlist,
995  CRIRES_HEADER_EXT_FORWARD, 0) ;
996  cpl_propertylist_delete(inputlist) ;
997  }
998 
999  /* Write the combined image */
1000  filename = cpl_sprintf("%s_comb_set%02d.fits", recipe_name, setting) ;
1001  crires_image_save(set,
1002  parlist,
1003  cur_set,
1004  images[0],
1005  recipe_name,
1006  CRIRES_ASTRO_COMBINED_IMA,
1007  CRIRES_PROTYPE_COMBINED,
1008  crires_spec_astro_config.period,
1009  NULL,
1010  (const cpl_propertylist **)qclists,
1011  PACKAGE "/" PACKAGE_VERSION,
1012  filename) ;
1013  cpl_free(filename) ;
1014 
1015  /* Write the contribution map */
1016  filename = cpl_sprintf("%s_contrib_set%02d.fits", recipe_name, setting) ;
1017  crires_image_save(set,
1018  parlist,
1019  cur_set,
1020  images[1],
1021  recipe_name,
1022  CRIRES_ASTRO_CONTRIBUTION_IMA,
1023  CRIRES_PROTYPE_CONTRIB,
1024  crires_spec_astro_config.period,
1025  NULL,
1026  (const cpl_propertylist **)qclists,
1027  PACKAGE "/" PACKAGE_VERSION,
1028  filename) ;
1029  cpl_free(filename) ;
1030 
1031  /* Nodded A support */
1032  if (crires_spec_astro_config.comb_onlyA) {
1033  /* Write the combined image */
1034  filename = cpl_sprintf("%s_comb_noddedA_set%02d.fits",
1035  recipe_name, setting) ;
1036  crires_image_save(set,
1037  parlist,
1038  cur_set,
1039  images[2],
1040  recipe_name,
1041  CRIRES_ASTRO_COMBINED_IMA,
1042  CRIRES_PROTYPE_COMBINED,
1043  crires_spec_astro_config.period,
1044  NULL,
1045  (const cpl_propertylist **)qclists,
1046  PACKAGE "/" PACKAGE_VERSION,
1047  filename) ;
1048  cpl_free(filename) ;
1049 
1050  /* Write the contribution map */
1051  filename = cpl_sprintf("%s_contrib_noddedA_set%02d.fits",
1052  recipe_name, setting) ;
1053  crires_image_save(set,
1054  parlist,
1055  cur_set,
1056  images[3],
1057  recipe_name,
1058  CRIRES_ASTRO_CONTRIBUTION_IMA,
1059  CRIRES_PROTYPE_CONTRIB,
1060  crires_spec_astro_config.period,
1061  NULL,
1062  (const cpl_propertylist **)qclists,
1063  PACKAGE "/" PACKAGE_VERSION,
1064  filename) ;
1065  cpl_free(filename) ;
1066  }
1067 
1068  /* Nodded B support */
1069  if (crires_spec_astro_config.comb_onlyB) {
1070  /* Write the combined image */
1071  filename = cpl_sprintf("%s_comb_noddedB_set%02d.fits",
1072  recipe_name, setting) ;
1073  crires_image_save(set,
1074  parlist,
1075  cur_set,
1076  images[4],
1077  recipe_name,
1078  CRIRES_ASTRO_COMBINED_IMA,
1079  CRIRES_PROTYPE_COMBINED,
1080  crires_spec_astro_config.period,
1081  NULL,
1082  (const cpl_propertylist **)qclists,
1083  PACKAGE "/" PACKAGE_VERSION,
1084  filename) ;
1085  cpl_free(filename) ;
1086 
1087  /* Write the contribution map */
1088  filename = cpl_sprintf("%s_contrib_noddedB_set%02d.fits",
1089  recipe_name, setting) ;
1090  crires_image_save(set,
1091  parlist,
1092  cur_set,
1093  images[5],
1094  recipe_name,
1095  CRIRES_ASTRO_CONTRIBUTION_IMA,
1096  CRIRES_PROTYPE_CONTRIB,
1097  crires_spec_astro_config.period,
1098  NULL,
1099  (const cpl_propertylist **)qclists,
1100  PACKAGE "/" PACKAGE_VERSION,
1101  filename) ;
1102  cpl_free(filename) ;
1103  }
1104 
1105  /* Write the profile image */
1106  filename = cpl_sprintf("%s_prof_set%02d.fits", recipe_name, setting) ;
1107  crires_image_save(set,
1108  parlist,
1109  cur_set,
1110  prof,
1111  recipe_name,
1112  CRIRES_ASTRO_EXTRACT_PROFILE_IMA,
1113  CRIRES_PROTYPE_PROFILE,
1114  crires_spec_astro_config.period,
1115  NULL,
1116  (const cpl_propertylist **)qclists,
1117  PACKAGE "/" PACKAGE_VERSION,
1118  filename) ;
1119  cpl_free(filename) ;
1120 
1121  /* Write the background image */
1122  filename = cpl_sprintf("%s_bgmap_set%02d.fits", recipe_name, setting) ;
1123  crires_image_save(set,
1124  parlist,
1125  cur_set,
1126  bgmap,
1127  recipe_name,
1128  CRIRES_ASTRO_EXTRACT_BGMAP_IMA,
1129  CRIRES_PROTYPE_BGD_MAP,
1130  crires_spec_astro_config.period,
1131  NULL,
1132  (const cpl_propertylist **)qclists,
1133  PACKAGE "/" PACKAGE_VERSION,
1134  filename) ;
1135  cpl_free(filename) ;
1136 
1137  /* Write the map */
1138  filename = cpl_sprintf("%s_wlmap_set%02d.fits", recipe_name, setting) ;
1139  crires_image_save(set,
1140  parlist,
1141  cur_set,
1142  wl_map,
1143  recipe_name,
1144  CRIRES_ASTRO_WL_MAP_IMA,
1145  CRIRES_PROTYPE_WL_MAP,
1146  crires_spec_astro_config.period,
1147  NULL,
1148  (const cpl_propertylist **)qclists,
1149  PACKAGE "/" PACKAGE_VERSION,
1150  filename) ;
1151  cpl_free(filename) ;
1152 
1153  if (wl_map_model != NULL) {
1154  /* Write the model map */
1155  filename = cpl_sprintf("%s_wlmap_model_set%02d.fits", recipe_name,
1156  setting) ;
1157  crires_image_save(set,
1158  parlist,
1159  cur_set,
1160  wl_map_model,
1161  recipe_name,
1162  CRIRES_ASTRO_WL_MAP_MODEL_IMA,
1163  CRIRES_PROTYPE_WL_MAP,
1164  crires_spec_astro_config.period,
1165  NULL,
1166  (const cpl_propertylist **)qclists,
1167  PACKAGE "/" PACKAGE_VERSION,
1168  filename) ;
1169  cpl_free(filename) ;
1170  }
1171 
1172  /* Write the extracted spectra */
1173  filename = cpl_sprintf("%s_extracted_set%02d.fits", recipe_name, setting);
1174  crires_table_save(set,
1175  parlist,
1176  cur_set,
1177  extr_tab,
1178  recipe_name,
1179  CRIRES_ASTRO_EXTRACT_WL_TAB,
1180  CRIRES_PROTYPE_SPEC_WL,
1181  NULL,
1182  (const cpl_propertylist **)qclists,
1183  PACKAGE "/" PACKAGE_VERSION,
1184  filename) ;
1185  cpl_free(filename) ;
1186 
1187  /* Free and return */
1188  for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
1189  cpl_propertylist_delete(qclists[i]) ;
1190  }
1191  cpl_free(qclists) ;
1192  return 0;
1193 }
1194 
1195 /*----------------------------------------------------------------------------*/
1202 /*----------------------------------------------------------------------------*/
1203 static int crires_spec_astro_compare(
1204  const cpl_frame * frame1,
1205  const cpl_frame * frame2)
1206 {
1207  int comparison ;
1208  cpl_propertylist * plist1 ;
1209  cpl_propertylist * plist2 ;
1210  double dval1, dval2 ;
1211  int ival1, ival2 ;
1212 
1213  /* Test entries */
1214  if (frame1==NULL || frame2==NULL) return -1 ;
1215 
1216  /* Get property lists */
1217  if ((plist1=cpl_propertylist_load(cpl_frame_get_filename(frame1),0))==NULL){
1218  cpl_msg_error(__func__, "getting header from reference frame");
1219  return -1 ;
1220  }
1221  if ((plist2=cpl_propertylist_load(cpl_frame_get_filename(frame2),0))==NULL){
1222  cpl_msg_error(__func__, "getting header from reference frame");
1223  cpl_propertylist_delete(plist1) ;
1224  return -1 ;
1225  }
1226 
1227  /* Test status */
1228  if (cpl_error_get_code()) {
1229  cpl_propertylist_delete(plist1) ;
1230  cpl_propertylist_delete(plist2) ;
1231  return -1 ;
1232  }
1233 
1234  comparison = 1 ;
1235 
1236  /* Compare the DROT POSANG used */
1237  dval1 = crires_pfits_get_dit(plist1) ;
1238  dval2 = crires_pfits_get_dit(plist2) ;
1239  if (cpl_error_get_code()) {
1240  cpl_msg_error(__func__, "Cannot get the POSANG");
1241  cpl_propertylist_delete(plist1) ;
1242  cpl_propertylist_delete(plist2) ;
1243  return -1 ;
1244  }
1245  if (fabs(dval1-dval2) > 1e-3) comparison = 0 ;
1246 
1247  /* Check if the frames are consecutive */
1248  ival1 = crires_pfits_get_expno(plist1) ;
1249  ival2 = crires_pfits_get_expno(plist2) ;
1250  if (cpl_error_get_code()) {
1251  cpl_msg_error(__func__, "Cannot get the EXPNO");
1252  cpl_propertylist_delete(plist1) ;
1253  cpl_propertylist_delete(plist2) ;
1254  return -1 ;
1255  }
1256  if (fabs(ival2-ival1) != 1.0) comparison = 0 ;
1257 
1258  cpl_propertylist_delete(plist1) ;
1259  cpl_propertylist_delete(plist2) ;
1260  return comparison ;
1261 }