CRIRES Pipeline Reference Manual  2.3.15
crires_win_flat.c
1 /* $Id: crires_win_flat.c,v 1.7 2012-09-19 14:52:00 yjung Exp $
2  *
3  * This file is part of the CRIRES Pipeline
4  * Copyright (C) 2002,2003 European Southern Observatory
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  */
20 
21 /*
22  * $Author: yjung $
23  * $Date: 2012-09-19 14:52:00 $
24  * $Revision: 1.7 $
25  * $Name: not supported by cvs2svn $
26  */
27 
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31 
32 /*-----------------------------------------------------------------------------
33  Includes
34  -----------------------------------------------------------------------------*/
35 
36 #include <locale.h>
37 #include "crires_recipe.h"
38 #include "irplib_utils.h"
39 
40 #include "crires_combine.h"
41 
42 /*-----------------------------------------------------------------------------
43  Define
44  -----------------------------------------------------------------------------*/
45 
46 #define RECIPE_STRING "crires_win_flat"
47 
48 /*-----------------------------------------------------------------------------
49  Functions prototypes
50  -----------------------------------------------------------------------------*/
51 
52 static cpl_imagelist * crires_win_flat_reduce(cpl_frameset *, const char *,
53  const char *) ;
54 static cpl_imagelist * crires_win_flat_bpm(cpl_imagelist *, double,
55  double, double) ;
56 static int crires_win_flat_save(const cpl_imagelist *, const cpl_imagelist *,
57  int, cpl_frameset *, const cpl_parameterlist *, cpl_frameset *) ;
58 static int crires_win_flat_compare(const cpl_frame *, const cpl_frame *) ;
59 
60 static char crires_win_flat_description[] =
61 "crires_win_flat -- Flat-field recipe in Windowing mode\n"
62 "The files listed in the Set Of Frames (sof-file) must be tagged:\n"
63 "raw-file.fits "CRIRES_WIN_FLAT_RAW" or\n"
64 "dark-file.fits "CRIRES_CALPRO_DARK" or\n"
65 "detlin-file.fits "CRIRES_CALPRO_COEFFS_CUBE".\n" ;
66 
67 CRIRES_RECIPE_DEFINE(crires_win_flat,
68  CRIRES_PARAM_THRESHOLDS |
69  CRIRES_PARAM_BPM_RATE |
70  CRIRES_PARAM_REPLACE |
71  CRIRES_PARAM_KAPPA_SIGCLIP |
72  CRIRES_PARAM_COLLAPSE_METH,
73  "Flatfield recipe in Windowing mode",
74  crires_win_flat_description) ;
75 
76 /*-----------------------------------------------------------------------------
77  Static variables
78  -----------------------------------------------------------------------------*/
79 
80 static struct {
81  /* Input */
82  double bpm_low ;
83  double bpm_high ;
84  double bpm_lines_ratio ;
85  int replace_flag ;
86  double kappa_sigclip ;
87  crires_collapse_method coll_meth ;
88  /* Output */
89  int bpm_nb[CRIRES_NB_DETECTORS] ;
90  double flat_mean[CRIRES_NB_DETECTORS] ;
91  double flat_stdev[CRIRES_NB_DETECTORS] ;
92  double flat_flux[CRIRES_NB_DETECTORS] ;
93  double flat_master_rms[CRIRES_NB_DETECTORS] ;
94 } crires_win_flat_config ;
95 
96 /*-----------------------------------------------------------------------------
97  Functions code
98  -----------------------------------------------------------------------------*/
99 
100 /*----------------------------------------------------------------------------*/
107 /*----------------------------------------------------------------------------*/
108 static int crires_win_flat(
109  cpl_frameset * frameset,
110  const cpl_parameterlist * parlist)
111 {
112  const char * sval ;
113  cpl_size * labels ;
114  cpl_size nlabels ;
115  cpl_frameset * rawframes ;
116  const char * dark ;
117  const char * detlin ;
118  cpl_imagelist * flat ;
119  cpl_frameset * flat_one ;
120  cpl_imagelist * bpm ;
121  int i ;
122 
123  /* Needed for sscanf() */
124  setlocale(LC_NUMERIC, "C");
125 
126  /* Initialise */
127  rawframes = NULL ;
128  for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
129  crires_win_flat_config.bpm_nb[i] = -1 ;
130  crires_win_flat_config.flat_mean[i] = -1.0 ;
131  crires_win_flat_config.flat_stdev[i] = -1.0 ;
132  crires_win_flat_config.flat_flux[i] = -1.0 ;
133  crires_win_flat_config.flat_master_rms[i] = -1.0 ;
134  }
135 
136  /* Retrieve input parameters */
137  sval = crires_parameterlist_get_string(parlist, RECIPE_STRING,
138  CRIRES_PARAM_THRESHOLDS) ;
139  if (sscanf(sval, "%lg,%lg",
140  &crires_win_flat_config.bpm_low,
141  &crires_win_flat_config.bpm_high)!=2) {
142  return -1 ;
143  }
144  crires_win_flat_config.replace_flag = crires_parameterlist_get_bool(
145  parlist, RECIPE_STRING, CRIRES_PARAM_REPLACE) ;
146  crires_win_flat_config.bpm_lines_ratio = crires_parameterlist_get_double(
147  parlist, RECIPE_STRING, CRIRES_PARAM_BPM_RATE) ;
148  crires_win_flat_config.kappa_sigclip = crires_parameterlist_get_double(
149  parlist, RECIPE_STRING, CRIRES_PARAM_KAPPA_SIGCLIP) ;
150  sval = crires_parameterlist_get_string(parlist, RECIPE_STRING,
151  CRIRES_PARAM_COLLAPSE_METH) ;
152  if (!strcmp(sval, "avg"))
153  crires_win_flat_config.coll_meth = CRIRES_COLLAPSE_AVG ;
154  else if (!strcmp(sval, "med"))
155  crires_win_flat_config.coll_meth = CRIRES_COLLAPSE_MED ;
156  else if (!strcmp(sval, "sig"))
157  crires_win_flat_config.coll_meth = CRIRES_COLLAPSE_SIG ;
158  else {
159  cpl_msg_error(__func__, "Invalid collapse method specified");
160  return -1;
161  }
162 
163  /* Identify the RAW and CALIB frames in the input frameset */
164  if (crires_dfs_set_groups(frameset, "crires_win_flat")) {
165  cpl_msg_error(__func__, "Cannot identify RAW and CALIB frames") ;
166  return -1 ;
167  }
168 
169  /* Retrieve calibration data */
170  dark = crires_extract_filename(frameset, CRIRES_CALPRO_DARK_WIN) ;
171  detlin = crires_extract_filename(frameset, CRIRES_CALPRO_COEFFS_CUBE) ;
172 
173  /* Retrieve raw frames */
174  if ((rawframes = crires_extract_frameset(frameset,
175  CRIRES_WIN_FLAT_RAW)) == NULL) {
176  cpl_msg_error(__func__, "No raw frame in input") ;
177  return -1 ;
178  }
179 
180  /* Labelise all input frames */
181  if ((labels = cpl_frameset_labelise(rawframes, crires_win_flat_compare,
182  &nlabels)) == NULL) {
183  cpl_msg_error(__func__, "Cannot labelise input frames") ;
184  cpl_frameset_delete(rawframes) ;
185  return -1 ;
186  }
187 
188  /* Extract settings and reduce each of them */
189  for (i=0 ; i<(int)nlabels ; i++) {
190  /* Reduce data set nb i */
191  cpl_msg_info(__func__, "Reduce data set %d / %"CPL_SIZE_FORMAT,
192  i+1, nlabels);
193  cpl_msg_indent_more() ;
194  flat_one = cpl_frameset_extract(rawframes, labels, (cpl_size)i) ;
195  flat = crires_win_flat_reduce(flat_one, dark, detlin) ;
196  cpl_msg_indent_less() ;
197 
198  /* Save the products */
199  cpl_msg_info(__func__, "Save the products") ;
200  cpl_msg_indent_more() ;
201  if (flat == NULL) {
202  cpl_msg_warning(__func__, "Cannot reduce set nb %d", i+1) ;
203  } else {
204  if ((bpm = crires_win_flat_bpm(flat,
205  crires_win_flat_config.bpm_low,
206  crires_win_flat_config.bpm_high,
207  crires_win_flat_config.bpm_lines_ratio)) == NULL) {
208  cpl_msg_warning(__func__, "Cannot create bad pixels map") ;
209  }
210  crires_win_flat_save(flat, bpm, i+1, flat_one, parlist, frameset) ;
211  cpl_imagelist_delete(flat) ;
212  cpl_imagelist_delete(bpm) ;
213  }
214  cpl_msg_indent_less() ;
215  cpl_frameset_delete(flat_one) ;
216  }
217  cpl_frameset_delete(rawframes) ;
218  cpl_free(labels) ;
219 
220  /* Return */
221  if (cpl_error_get_code()) return -1 ;
222  else return 0 ;
223 }
224 
225 /*----------------------------------------------------------------------------*/
233 /*----------------------------------------------------------------------------*/
234 static cpl_imagelist * crires_win_flat_reduce(
235  cpl_frameset * flatframes,
236  const char * dark,
237  const char * detlin)
238 {
239  cpl_propertylist * plist ;
240  cpl_frame * ref_frame ;
241  const char * fname ;
242  int nframes ;
243  double dit_frame, dit_dark ;
244  cpl_imagelist * in ;
245  cpl_imagelist * out ;
246  cpl_vector * medians ;
247  double median ;
248  cpl_image * ima[CRIRES_NB_DETECTORS] ;
249  int offset_y, stripe_y, center_y ;
250  int i, j, k ;
251 
252  /* Test entries */
253  if (flatframes == NULL) return NULL ;
254 
255  /* Initialize */
256  for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
257  ima[i] = NULL ;
258  }
259  nframes = cpl_frameset_get_size(flatframes) ;
260 
261  /* Get the DIT from the RAW frame */
262  ref_frame = cpl_frameset_get_position(flatframes, 0) ;
263  fname = cpl_frame_get_filename(ref_frame) ;
264  if ((plist=cpl_propertylist_load(fname, 0)) == NULL) {
265  cpl_msg_error(__func__, "Getting header from RAW file");
266  cpl_msg_indent_less() ;
267  return NULL ;
268  }
269  dit_frame = crires_pfits_get_dit(plist) ;
270  offset_y = crires_pfits_get_stripe_offsety(plist) ;
271  center_y = crires_pfits_get_stripe_centery(plist) ;
272  cpl_propertylist_delete(plist) ;
273  if (cpl_error_get_code()) {
274  cpl_msg_error(__func__,
275  "Cannot get the DIT or STRIPE keywords from RAW file") ;
276  cpl_msg_indent_less() ;
277  return NULL ;
278  }
279  cpl_msg_info(__func__, "DIT value: %g sec.", dit_frame) ;
280 
281  /* Verify the DIT of the dark */
282  if (dark != NULL) {
283  cpl_msg_info(__func__, "Verify the dark DIT") ;
284  cpl_msg_indent_more() ;
285  if ((plist=cpl_propertylist_load(dark, 0)) == NULL) {
286  cpl_msg_error(__func__, "Getting header from DARK");
287  cpl_msg_indent_less() ;
288  return NULL ;
289  }
290  dit_dark = crires_pfits_get_dit(plist) ;
291  cpl_propertylist_delete(plist) ;
292  if (cpl_error_get_code()) {
293  cpl_msg_error(__func__, "Cannot get the DIT from DARK") ;
294  cpl_msg_indent_less() ;
295  return NULL ;
296  }
297  if (fabs(dit_dark-dit_frame) > 1e-5) {
298  cpl_msg_error(__func__, "Mismatch RAW DIT (%g) / DARK DIT (%g)",
299  dit_frame, dit_dark) ;
300  cpl_msg_indent_less() ;
301  return NULL ;
302  }
303  cpl_msg_indent_less() ;
304 
305  /* Verify the STRIPE keys conformity */
306  if (crire_stripe_keys_mismatch(fname, dark)) {
307  cpl_msg_error(__func__,
308  "Mismatch of STRIPE keys with the dark frame") ;
309  return NULL ;
310  }
311  }
312 
313  /* Loop on the detectors */
314  for (i=1 ; i<CRIRES_NB_DETECTORS-1 ; i++) {
315  cpl_msg_info(__func__, "Compute the MASTER FLAT for chip nb %d", i+1) ;
316  cpl_msg_indent_more() ;
317 
318  /* Load the data */
319  in = crires_load_frameset(flatframes, CRIRES_ILLUM_FULL_DETECTOR,
320  i+1, CPL_TYPE_FLOAT) ;
321  stripe_y = (int)(cpl_image_get_size_y(cpl_imagelist_get(in, 0))/2.0) ;
322 
323  /* Correct for dark */
324  if (crires_calib_chip_list(in, CRIRES_ILLUM_FULL_DETECTOR, i+1,
325  NULL, dark, NULL, detlin, dit_frame, center_y, offset_y,
326  stripe_y)) {
327  cpl_msg_error(__func__, "Cannot apply the calibrations") ;
328  cpl_imagelist_delete(in) ;
329  for (j=1 ; j<i ; j++)
330  cpl_image_delete(ima[j]);
331  return NULL ;
332  }
333 
334  /* Create medians vector */
335  medians = cpl_vector_new(nframes) ;
336 
337  /* Loop on all the frames */
338  cpl_msg_info(__func__, "Normalise with the median") ;
339  for (j=0 ; j<nframes ; j++) {
340  median = cpl_image_get_median(cpl_imagelist_get(in, j)) ;
341  if (cpl_error_get_code()) {
342  cpl_msg_error(__func__, "Cannot compute the median") ;
343  cpl_imagelist_delete(in) ;
344  cpl_vector_delete(medians) ;
345  for (k=1 ; k<i ; k++)
346  cpl_image_delete(ima[k]);
347  return NULL ;
348  }
349  cpl_vector_set(medians, j, median) ;
350  if (fabs(median) > 1e-3)
351  cpl_image_divide_scalar(cpl_imagelist_get(in, j), median) ;
352  }
353 
354  /* Fill QCs */
355  crires_win_flat_config.flat_mean[i] = cpl_vector_get_mean(medians) ;
356  if (cpl_vector_get_size(medians) > 1)
357  crires_win_flat_config.flat_stdev[i]=cpl_vector_get_stdev(medians);
358  else
359  crires_win_flat_config.flat_stdev[i] = -1.0 ;
360  crires_win_flat_config.flat_flux[i] =
361  crires_win_flat_config.flat_mean[i] / dit_frame ;
362 
363  /* Collapse the frames */
364  if ((ima[i] = crires_combine_collapse_imagelist(in, medians,
365  crires_win_flat_config.kappa_sigclip,
366  i+1,
367  crires_win_flat_config.coll_meth)) == NULL) {
368  cpl_msg_error(__func__, "Cannot average the flats") ;
369  cpl_imagelist_delete(in) ;
370  cpl_vector_delete(medians) ;
371  for (j=1 ; j<i ; j++)
372  cpl_image_delete(ima[j]);
373  return NULL ;
374  }
375  cpl_vector_delete(medians) ;
376  cpl_imagelist_delete(in) ;
377 
378  /* Add QC */
379  crires_win_flat_config.flat_master_rms[i] =
380  cpl_image_get_stdev(ima[i]) ;
381 
382  cpl_msg_indent_less() ;
383  }
384 
385  /* Reconstruct chips (windowing mode) using detector 2 */
386  if (ima[1] != NULL) {
387  ima[0] = cpl_image_duplicate(ima[1]) ;
388  cpl_image_multiply_scalar(ima[0], 0.0) ;
389  ima[CRIRES_NB_DETECTORS-1] = cpl_image_duplicate(ima[0]) ;
390  }
391 
392  /* Create the image list */
393  out = cpl_imagelist_new() ;
394  for (i=0 ; i<CRIRES_NB_DETECTORS ; i++)
395  cpl_imagelist_set(out, ima[i], i) ;
396 
397  return out ;
398 }
399 
400 /*----------------------------------------------------------------------------*/
409 /*----------------------------------------------------------------------------*/
410 static cpl_imagelist * crires_win_flat_bpm(
411  cpl_imagelist * flat,
412  double low,
413  double high,
414  double bad_per_line_limit)
415 {
416  cpl_imagelist * bpm ;
417  int nima ;
418  cpl_image * bpm_cur ;
419  cpl_mask * mask_cur ;
420  cpl_binary * pmask_cur ;
421  int nx, ny, cur_bp_nb ;
422  int i, j, k ;
423 
424  /* Test entries */
425  if (flat == NULL) return NULL ;
426 
427  /* Initialise */
428  nima = cpl_imagelist_get_size(flat) ;
429 
430  /* Create the output image list */
431  bpm = cpl_imagelist_new() ;
432 
433  /* Loop on the images */
434  for (i=0 ; i<nima ; i++) {
435  /* Threshold to get the BPMs */
436  if ((mask_cur = cpl_mask_threshold_image_create(
437  cpl_imagelist_get(flat, i), low, high)) == NULL) {
438  cpl_msg_error(__func__, "Cannot create bad pixels map") ;
439  cpl_imagelist_delete(bpm) ;
440  return NULL ;
441  }
442  cpl_mask_not(mask_cur) ;
443 
444  /*
445  Post processing : Big zones of bad pixels are not considered as
446  bad pixels. Each line containing more than
447  100*bad_per_line_limit percent bad pixels is reset to contain
448  anly good pixels.
449  */
450  nx = cpl_mask_get_size_x(mask_cur) ;
451  ny = cpl_mask_get_size_y(mask_cur) ;
452  pmask_cur = cpl_mask_get_data(mask_cur) ;
453  for (j=0 ; j<ny ; j++) {
454  cur_bp_nb = cpl_mask_count_window(mask_cur, 1, j+1, nx, j+1) ;
455  /* Check if the line has too many bad pixels */
456  if (cur_bp_nb > bad_per_line_limit * nx) {
457  /* Reset the bad pixels on the current line */
458  for (k=0 ; k<nx ; k++) {
459  pmask_cur[k+j*nx] = CPL_BINARY_0 ;
460  }
461  }
462  }
463 
464  /* Convert mask to image */
465  bpm_cur = cpl_image_new_from_mask(mask_cur) ;
466  crires_win_flat_config.bpm_nb[i] = cpl_mask_count(mask_cur) ;
467  cpl_mask_delete(mask_cur) ;
468  cpl_imagelist_set(bpm, bpm_cur, i) ;
469 
470  /* Set the flat to 1 outside of the bounds */
471  if (crires_win_flat_config.replace_flag) {
472  cpl_image_threshold(cpl_imagelist_get(flat, i),
473  low, high, 1.0, 1.0) ;
474  }
475  }
476  return bpm ;
477 }
478 
479 /*----------------------------------------------------------------------------*/
489 /*----------------------------------------------------------------------------*/
490 static int crires_win_flat_save(
491  const cpl_imagelist * flat,
492  const cpl_imagelist * bpm,
493  int set_nb,
494  cpl_frameset * set,
495  const cpl_parameterlist * parlist,
496  cpl_frameset * set_tot)
497 {
498  cpl_propertylist ** qclists ;
499  const cpl_frame * ref_frame ;
500  char * filename ;
501  cpl_propertylist * inputlist ;
502  const char * recipe_name = "crires_win_flat" ;
503  int i ;
504 
505  /* Get the reference frame */
506  ref_frame = irplib_frameset_get_first_from_group(set, CPL_FRAME_GROUP_RAW) ;
507 
508  /* Create the QC lists */
509  qclists = cpl_malloc(CRIRES_NB_DETECTORS * sizeof(cpl_propertylist*)) ;
510  for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
511  qclists[i] = cpl_propertylist_new() ;
512  cpl_propertylist_append_int(qclists[i], "ESO QC NBBAD",
513  crires_win_flat_config.bpm_nb[i]) ;
514  cpl_propertylist_append_double(qclists[i], "ESO QC FLAT MEAN",
515  crires_win_flat_config.flat_mean[i]) ;
516  cpl_propertylist_append_double(qclists[i], "ESO QC FLAT STDEV",
517  crires_win_flat_config.flat_stdev[i]) ;
518  cpl_propertylist_append_double(qclists[i], "ESO QC FLAT FLUX",
519  crires_win_flat_config.flat_flux[i]) ;
520  cpl_propertylist_append_double(qclists[i], "ESO QC FLAT MASTER RMS",
521  crires_win_flat_config.flat_master_rms[i]) ;
522 
523  /* Propagate some keywords from input raw frame extensions */
524  inputlist = cpl_propertylist_load_regexp(
525  cpl_frame_get_filename(ref_frame), i+1,
526  CRIRES_HEADER_EXT_FORWARD, 0) ;
527  cpl_propertylist_copy_property_regexp(qclists[i], inputlist,
528  CRIRES_HEADER_EXT_FORWARD, 0) ;
529  cpl_propertylist_delete(inputlist) ;
530  }
531 
532  /* Write the flat image */
533  filename = cpl_sprintf("%s_set%02d.fits", recipe_name, set_nb) ;
534  crires_image_save(set_tot,
535  parlist,
536  set,
537  flat,
538  recipe_name,
539  CRIRES_CALPRO_FLAT_WIN,
540  CRIRES_PROTYPE_FLAT,
541  CRIRES_ILLUM_FULL_DETECTOR,
542  NULL,
543  (const cpl_propertylist**)qclists,
544  PACKAGE "/" PACKAGE_VERSION,
545  filename) ;
546  cpl_free(filename) ;
547 
548  /* Write the BPM */
549  if (bpm != NULL) {
550  filename = cpl_sprintf("%s_set%02d_bpm.fits", recipe_name, set_nb) ;
551  crires_image_save(set_tot,
552  parlist,
553  set,
554  bpm,
555  recipe_name,
556  CRIRES_CALPRO_BPM_WIN,
557  CRIRES_PROTYPE_BPM,
558  CRIRES_ILLUM_FULL_DETECTOR,
559  NULL,
560  (const cpl_propertylist**)qclists,
561  PACKAGE "/" PACKAGE_VERSION,
562  filename) ;
563  cpl_free(filename) ;
564  }
565 
566  /* Free and return */
567  for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
568  cpl_propertylist_delete(qclists[i]) ;
569  }
570  cpl_free(qclists) ;
571  return 0;
572 }
573 
574 /*----------------------------------------------------------------------------*/
581 /*----------------------------------------------------------------------------*/
582 static int crires_win_flat_compare(
583  const cpl_frame * frame1,
584  const cpl_frame * frame2)
585 {
586  int comparison ;
587  cpl_propertylist * plist1 ;
588  cpl_propertylist * plist2 ;
589  double dval1, dval2 ;
590 
591  /* Test entries */
592  if (frame1==NULL || frame2==NULL) return -1 ;
593 
594  /* Get property lists */
595  if ((plist1=cpl_propertylist_load(cpl_frame_get_filename(frame1),0))==NULL){
596  cpl_msg_error(__func__, "getting header from reference frame");
597  return -1 ;
598  }
599  if ((plist2=cpl_propertylist_load(cpl_frame_get_filename(frame2),0))==NULL){
600  cpl_msg_error(__func__, "getting header from reference frame");
601  cpl_propertylist_delete(plist1) ;
602  return -1 ;
603  }
604 
605  /* Test status */
606  if (cpl_error_get_code()) {
607  cpl_propertylist_delete(plist1) ;
608  cpl_propertylist_delete(plist2) ;
609  return -1 ;
610  }
611 
612  comparison = 1 ;
613 
614  /* Compare the DIT used */
615  dval1 = crires_pfits_get_dit(plist1) ;
616  dval2 = crires_pfits_get_dit(plist2) ;
617  if (cpl_error_get_code()) {
618  cpl_msg_error(__func__, "Cannot get the DIT");
619  cpl_propertylist_delete(plist1) ;
620  cpl_propertylist_delete(plist2) ;
621  return -1 ;
622  }
623  if (fabs(dval1-dval2) > 1e-3) comparison = 0 ;
624 
625  /* Compare the WLEN REF used */
626  dval1 = crires_pfits_get_refwlen(plist1) ;
627  dval2 = crires_pfits_get_refwlen(plist2) ;
628  if (cpl_error_get_code()) {
629  cpl_msg_error(__func__, "Cannot get the reference wavelength");
630  cpl_propertylist_delete(plist1) ;
631  cpl_propertylist_delete(plist2) ;
632  return -1 ;
633  }
634  if (fabs(dval1-dval2) > 1e-3) comparison = 0 ;
635 
636  /* Compare the SHUT1 POS used */
637  dval1 = crires_pfits_get_bafflepos(plist1) ;
638  dval2 = crires_pfits_get_bafflepos(plist2) ;
639  if (cpl_error_get_code()) {
640  cpl_msg_error(__func__, "Cannot get the baffle position");
641  cpl_propertylist_delete(plist1) ;
642  cpl_propertylist_delete(plist2) ;
643  return -1 ;
644  }
645  if (fabs(dval1-dval2) > 1e-3) comparison = 0 ;
646 
647  cpl_propertylist_delete(plist1) ;
648  cpl_propertylist_delete(plist2) ;
649  return comparison ;
650 }
651