CRIRES Pipeline Reference Manual  2.3.15
crires_spec_flat.c
1 /* $Id: crires_spec_flat.c,v 1.56 2012-09-19 14:10:27 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:10:27 $
24  * $Revision: 1.56 $
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_spec_flat"
47 
48 /*-----------------------------------------------------------------------------
49  Functions prototypes
50  -----------------------------------------------------------------------------*/
51 
52 static cpl_imagelist * crires_spec_flat_reduce(cpl_frameset *, const char *,
53  const char *) ;
54 static cpl_imagelist * crires_spec_flat_bpm(cpl_imagelist *, double,
55  double, double) ;
56 static int crires_spec_flat_save(const cpl_imagelist *, const cpl_imagelist *,
57  int, cpl_frameset *, const cpl_parameterlist *, cpl_frameset *) ;
58 static int crires_spec_flat_compare(const cpl_frame *, const cpl_frame *) ;
59 
60 static char crires_spec_flat_description[] =
61 "crires_spec_flat -- Flat-field recipe\n"
62 "The files listed in the Set Of Frames (sof-file) must be tagged:\n"
63 "raw-file.fits "CRIRES_SPEC_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_spec_flat,
68  CRIRES_PARAM_THRESHOLDS |
69  CRIRES_PARAM_BPM_RATE |
70  CRIRES_PARAM_REPLACE |
71  CRIRES_PARAM_CLEAN_FLAT |
72  CRIRES_PARAM_NORM_STARTY |
73  CRIRES_PARAM_NORM_STOPY |
74  CRIRES_PARAM_KAPPA_SIGCLIP |
75  CRIRES_PARAM_COLLAPSE_METH,
76  "Flatfield recipe",
77  crires_spec_flat_description) ;
78 
79 /*-----------------------------------------------------------------------------
80  Static variables
81  -----------------------------------------------------------------------------*/
82 
83 static struct {
84  /* Input */
85  double bpm_low ;
86  double bpm_high ;
87  double bpm_lines_ratio ;
88  int replace_flag ;
89  int clean_flat_flag ;
90  int starty ;
91  int stopy ;
92  double kappa_sigclip ;
93  crires_collapse_method coll_meth ;
94  /* Output */
95  crires_illum_period period ;
96  int bpm_nb[CRIRES_NB_DETECTORS] ;
97  double flat_mean[CRIRES_NB_DETECTORS] ;
98  double flat_stdev[CRIRES_NB_DETECTORS] ;
99  double flat_flux[CRIRES_NB_DETECTORS] ;
100  double flat_master_rms[CRIRES_NB_DETECTORS] ;
101 } crires_spec_flat_config ;
102 
103 /*-----------------------------------------------------------------------------
104  Functions code
105  -----------------------------------------------------------------------------*/
106 
107 /*----------------------------------------------------------------------------*/
114 /*----------------------------------------------------------------------------*/
115 static int crires_spec_flat(
116  cpl_frameset * frameset,
117  const cpl_parameterlist * parlist)
118 {
119  const char * sval ;
120  cpl_size * labels ;
121  cpl_size nlabels ;
122  cpl_frameset * rawframes ;
123  const char * dark ;
124  const char * detlin ;
125  cpl_imagelist * flat ;
126  cpl_frameset * flat_one ;
127  cpl_imagelist * bpm ;
128  int i ;
129 
130  /* Needed for sscanf() */
131  setlocale(LC_NUMERIC, "C");
132 
133  /* Initialise */
134  rawframes = NULL ;
135  for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
136  crires_spec_flat_config.bpm_nb[i] = -1 ;
137  crires_spec_flat_config.flat_mean[i] = -1.0 ;
138  crires_spec_flat_config.flat_stdev[i] = -1.0 ;
139  crires_spec_flat_config.flat_flux[i] = -1.0 ;
140  crires_spec_flat_config.flat_master_rms[i] = -1.0 ;
141  }
142 
143  /* Retrieve input parameters */
144  sval = crires_parameterlist_get_string(parlist, RECIPE_STRING,
145  CRIRES_PARAM_THRESHOLDS) ;
146 
147  if (sscanf(sval, "%lg,%lg",
148  &crires_spec_flat_config.bpm_low,
149  &crires_spec_flat_config.bpm_high)!=2) {
150  return -1 ;
151  }
152  crires_spec_flat_config.replace_flag = crires_parameterlist_get_bool(
153  parlist, RECIPE_STRING, CRIRES_PARAM_REPLACE) ;
154  crires_spec_flat_config.clean_flat_flag = crires_parameterlist_get_bool(
155  parlist, RECIPE_STRING, CRIRES_PARAM_CLEAN_FLAT) ;
156  crires_spec_flat_config.bpm_lines_ratio = crires_parameterlist_get_double(
157  parlist, RECIPE_STRING, CRIRES_PARAM_BPM_RATE) ;
158  crires_spec_flat_config.starty = crires_parameterlist_get_int(parlist,
159  RECIPE_STRING, CRIRES_PARAM_NORM_STARTY) ;
160  crires_spec_flat_config.stopy = crires_parameterlist_get_int(parlist,
161  RECIPE_STRING, CRIRES_PARAM_NORM_STOPY) ;
162  crires_spec_flat_config.kappa_sigclip = crires_parameterlist_get_double(
163  parlist, RECIPE_STRING, CRIRES_PARAM_KAPPA_SIGCLIP) ;
164  sval = crires_parameterlist_get_string(parlist, RECIPE_STRING,
165  CRIRES_PARAM_COLLAPSE_METH) ;
166  if (!strcmp(sval, "avg"))
167  crires_spec_flat_config.coll_meth = CRIRES_COLLAPSE_AVG ;
168  else if (!strcmp(sval, "med"))
169  crires_spec_flat_config.coll_meth = CRIRES_COLLAPSE_MED ;
170  else if (!strcmp(sval, "sig"))
171  crires_spec_flat_config.coll_meth = CRIRES_COLLAPSE_SIG ;
172  else {
173  cpl_msg_error(__func__, "Invalid collapse method specified");
174  return -1;
175  }
176 
177  /* Identify the RAW and CALIB frames in the input frameset */
178  if (crires_dfs_set_groups(frameset, "crires_spec_flat")) {
179  cpl_msg_error(__func__, "Cannot identify RAW and CALIB frames") ;
180  return -1 ;
181  }
182 
183  /* Retrieve calibration data */
184  dark = crires_extract_filename(frameset, CRIRES_CALPRO_DARK) ;
185  detlin = crires_extract_filename(frameset, CRIRES_CALPRO_COEFFS_CUBE) ;
186 
187  /* Retrieve raw frames */
188  if ((rawframes = crires_extract_frameset(frameset,
189  CRIRES_SPEC_FLAT_RAW)) == NULL) {
190  cpl_msg_error(__func__, "No raw frame in input") ;
191  return -1 ;
192  }
193 
194  /* Get the detector illumination period */
195  crires_spec_flat_config.period =
196  crires_get_detector_illum_period(
197  cpl_frame_get_filename(cpl_frameset_get_position(rawframes, 0))) ;
198  if (crires_spec_flat_config.period == CRIRES_ILLUM_UNKNOWN) {
199  cpl_msg_error(__func__,
200  "Cannot determine the detector illumination period") ;
201  cpl_frameset_delete(rawframes) ;
202  return -1 ;
203  } else {
204  crires_display_detector_illum(crires_spec_flat_config.period) ;
205  }
206 
207  /* Labelise all input frames */
208  if ((labels = cpl_frameset_labelise(rawframes, crires_spec_flat_compare,
209  &nlabels)) == NULL) {
210  cpl_msg_error(__func__, "Cannot labelise input frames") ;
211  cpl_frameset_delete(rawframes) ;
212  return -1 ;
213  }
214 
215  /* Extract settings and reduce each of them */
216  for (i=0 ; i<(int)nlabels ; i++) {
217  /* Reduce data set nb i */
218  cpl_msg_info(__func__, "Reduce data set %d / %"CPL_SIZE_FORMAT,
219  i+1, nlabels);
220  cpl_msg_indent_more() ;
221  flat_one = cpl_frameset_extract(rawframes, labels, (cpl_size)i) ;
222  flat = crires_spec_flat_reduce(flat_one, dark, detlin) ;
223  cpl_msg_indent_less() ;
224 
225  /* Save the products */
226  cpl_msg_info(__func__, "Save the products") ;
227  cpl_msg_indent_more() ;
228  if (flat == NULL) {
229  cpl_msg_warning(__func__, "Cannot reduce set nb %d", i+1) ;
230  } else {
231  if ((bpm = crires_spec_flat_bpm(flat,
232  crires_spec_flat_config.bpm_low,
233  crires_spec_flat_config.bpm_high,
234  crires_spec_flat_config.bpm_lines_ratio)) == NULL) {
235  cpl_msg_warning(__func__, "Cannot create bad pixels map") ;
236  }
237  crires_spec_flat_save(flat, bpm, i+1, flat_one, parlist, frameset) ;
238  cpl_imagelist_delete(flat) ;
239  cpl_imagelist_delete(bpm) ;
240  }
241  cpl_msg_indent_less() ;
242  cpl_frameset_delete(flat_one) ;
243  }
244  cpl_frameset_delete(rawframes) ;
245  cpl_free(labels) ;
246 
247  /* Return */
248  if (cpl_error_get_code()) return -1 ;
249  else return 0 ;
250 }
251 
252 /*----------------------------------------------------------------------------*/
260 /*----------------------------------------------------------------------------*/
261 static cpl_imagelist * crires_spec_flat_reduce(
262  cpl_frameset * flatframes,
263  const char * dark,
264  const char * detlin)
265 {
266  cpl_propertylist * plist ;
267  cpl_frame * ref_frame ;
268  const char * fname ;
269  int nframes ;
270  double dit_frame, dit_dark ;
271  cpl_imagelist * in ;
272  cpl_imagelist * out ;
273  cpl_vector * medians ;
274  double median ;
275  cpl_image * ima ;
276  int nx, ny, starty, stopy, ly ;
277  int i, j ;
278 
279  /* Test entries */
280  if (flatframes == NULL) return NULL ;
281 
282  /* Initialize */
283  nframes = cpl_frameset_get_size(flatframes) ;
284  ly = -1 ;
285 
286  /* Get the DIT from the RAW frame */
287  ref_frame = cpl_frameset_get_position(flatframes, 0) ;
288  fname = cpl_frame_get_filename(ref_frame) ;
289  if ((plist=cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
290  0)) == NULL) {
291  cpl_msg_error(__func__, "Getting header from RAW file");
292  cpl_msg_indent_less() ;
293  return NULL ;
294  }
295  dit_frame = crires_pfits_get_dit(plist) ;
296  cpl_propertylist_delete(plist) ;
297  if (cpl_error_get_code()) {
298  cpl_msg_error(__func__, "Cannot get the DIT from RAW file") ;
299  cpl_msg_indent_less() ;
300  return NULL ;
301  }
302  cpl_msg_info(__func__, "DIT value: %g sec.", dit_frame) ;
303 
304  /* Verify the DIT of the dark */
305  if (dark != NULL) {
306  cpl_msg_info(__func__, "Verify the dark DIT") ;
307  cpl_msg_indent_more() ;
308  if ((plist=cpl_propertylist_load(dark, 0)) == NULL) {
309  cpl_msg_error(__func__, "Getting header from DARK");
310  cpl_msg_indent_less() ;
311  return NULL ;
312  }
313  dit_dark = crires_pfits_get_dit(plist) ;
314  cpl_propertylist_delete(plist) ;
315  if (cpl_error_get_code()) {
316  cpl_msg_error(__func__, "Cannot get the DIT from DARK") ;
317  cpl_msg_indent_less() ;
318  return NULL ;
319  }
320  if (fabs(dit_dark-dit_frame) > 1e-5) {
321  cpl_msg_error(__func__, "Mismatch RAW DIT (%g) / DARK DIT (%g)",
322  dit_frame, dit_dark) ;
323  cpl_msg_indent_less() ;
324  return NULL ;
325  }
326  cpl_msg_indent_less() ;
327  }
328 
329  /* Create the image list */
330  out = cpl_imagelist_new() ;
331 
332  /* Loop on the detectors */
333  for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
334  cpl_msg_info(__func__, "Compute the MASTER FLAT for chip nb %d", i+1) ;
335  cpl_msg_indent_more() ;
336 
337  /* Load the data */
338  in = crires_load_frameset(flatframes, crires_spec_flat_config.period,
339  i+1, CPL_TYPE_FLOAT) ;
340  nx = cpl_image_get_size_x(cpl_imagelist_get(in, 0)) ;
341  ny = cpl_image_get_size_y(cpl_imagelist_get(in, 0)) ;
342 
343  /* Correct for dark and non-linearity */
344  if (crires_calib_chip_list(in, crires_spec_flat_config.period, i+1,
345  NULL, dark, NULL, detlin, dit_frame, -1, -1, -1)) {
346  cpl_msg_error(__func__, "Cannot apply the calibrations") ;
347  cpl_imagelist_delete(in) ;
348  return NULL ;
349  }
350 
351  /* Create medians vector */
352  medians = cpl_vector_new(nframes) ;
353 
354  /* Handle Vignetting */
355  if (i+1 == 1)
356  ly = crires_get_detector_ly1(crires_spec_flat_config.period) ;
357  if (i+1 == 2)
358  ly = crires_get_detector_ly2(crires_spec_flat_config.period) ;
359  if (i+1 == 3)
360  ly = crires_get_detector_ly3(crires_spec_flat_config.period) ;
361  if (i+1 == 4)
362  ly = crires_get_detector_ly4(crires_spec_flat_config.period) ;
363  /* If ly not found, use the bottom of the image */
364  if (ly < 0) ly = 1 ;
365 
366  starty = crires_spec_flat_config.starty ;
367  if (starty < 0) {
368  starty = 1 ;
369  } else {
370  starty -= (ly - 1) ;
371  }
372  stopy = crires_spec_flat_config.stopy ;
373  if (stopy < 0) {
374  stopy = ny ;
375  } else {
376  stopy -= (ly - 1) ;
377  }
378 
379  /* Loop on all the frames */
380  cpl_msg_info(__func__, "Normalise with the median") ;
381  for (j=0 ; j<nframes ; j++) {
382  median = cpl_image_get_median_window(cpl_imagelist_get(in, j),
383  1, starty, nx, stopy) ;
384  if (cpl_error_get_code()) {
385  cpl_msg_error(__func__, "Invalid bounds Y : %d-%d", ly,
386  ly+ny-1) ;
387  cpl_imagelist_delete(in) ;
388  cpl_vector_delete(medians) ;
389  return NULL ;
390  }
391  cpl_vector_set(medians, j, median) ;
392  cpl_image_divide_scalar(cpl_imagelist_get(in, j), median) ;
393  }
394 
395  /* Fill QCs */
396  crires_spec_flat_config.flat_mean[i] = cpl_vector_get_mean(medians) ;
397  if (cpl_vector_get_size(medians) > 1)
398  crires_spec_flat_config.flat_stdev[i]=cpl_vector_get_stdev(medians);
399  else
400  crires_spec_flat_config.flat_stdev[i] = -1.0 ;
401  crires_spec_flat_config.flat_flux[i] =
402  crires_spec_flat_config.flat_mean[i] / dit_frame ;
403 
404  /* Collapse the frames */
405  if ((ima = crires_combine_collapse_imagelist(in, medians,
406  crires_spec_flat_config.kappa_sigclip,
407  i+1,
408  crires_spec_flat_config.coll_meth)) == NULL) {
409  cpl_msg_error(__func__, "Cannot average the flats") ;
410  cpl_imagelist_delete(in) ;
411  cpl_vector_delete(medians) ;
412  return NULL ;
413  }
414  cpl_vector_delete(medians) ;
415  cpl_imagelist_delete(in) ;
416 
417  /* Add QC */
418  crires_spec_flat_config.flat_master_rms[i] =
419  cpl_image_get_stdev(ima) ;
420 
421  /* Set the image in the list */
422  cpl_imagelist_set(out, ima, i) ;
423  cpl_msg_indent_less() ;
424  }
425 
426  return out ;
427 }
428 
429 /*----------------------------------------------------------------------------*/
438 /*----------------------------------------------------------------------------*/
439 static cpl_imagelist * crires_spec_flat_bpm(
440  cpl_imagelist * flat,
441  double low,
442  double high,
443  double bad_per_line_limit)
444 {
445  cpl_imagelist * bpm ;
446  int nima ;
447  cpl_image * bpm_cur ;
448  cpl_mask * mask_cur ;
449  cpl_binary * pmask_cur ;
450  int nx, ny, cur_bp_nb ;
451  int i, j, k ;
452 
453  /* Test entries */
454  if (flat == NULL) return NULL ;
455 
456  /* Initialise */
457  nima = cpl_imagelist_get_size(flat) ;
458 
459  /* Create the output image list */
460  bpm = cpl_imagelist_new() ;
461 
462  /* Loop on the images */
463  for (i=0 ; i<nima ; i++) {
464  /* Threshold to get the BPMs */
465  if ((mask_cur = cpl_mask_threshold_image_create(
466  cpl_imagelist_get(flat, i), low, high)) == NULL) {
467  cpl_msg_error(__func__, "Cannot create bad pixels map") ;
468  cpl_imagelist_delete(bpm) ;
469  return NULL ;
470  }
471  cpl_mask_not(mask_cur) ;
472 
473  /*
474  Post processing : Big zones of bad pixels are not considered as
475  bad pixels. Each line containing more than
476  100*bad_per_line_limit percent bad pixels is reset to contain
477  anly good pixels.
478  */
479  nx = cpl_mask_get_size_x(mask_cur) ;
480  ny = cpl_mask_get_size_y(mask_cur) ;
481  pmask_cur = cpl_mask_get_data(mask_cur) ;
482  for (j=0 ; j<ny ; j++) {
483  cur_bp_nb = cpl_mask_count_window(mask_cur, 1, j+1, nx, j+1) ;
484  /* Check if the line has too many bad pixels */
485  if (cur_bp_nb > bad_per_line_limit * nx) {
486  /* Reset the bad pixels on the current line */
487  for (k=0 ; k<nx ; k++) {
488  pmask_cur[k+j*nx] = CPL_BINARY_0 ;
489  }
490  }
491  }
492 
493  /* Convert mask to image */
494  bpm_cur = cpl_image_new_from_mask(mask_cur) ;
495  crires_spec_flat_config.bpm_nb[i] = cpl_mask_count(mask_cur) ;
496  cpl_imagelist_set(bpm, bpm_cur, i) ;
497 
498  /* Clean the flat using the computed BPM */
499  if (crires_spec_flat_config.clean_flat_flag) {
500  cpl_image_reject_from_mask(cpl_imagelist_get(flat, i), mask_cur) ;
501  cpl_detector_interpolate_rejected(cpl_imagelist_get(flat, i)) ;
502  }
503  cpl_mask_delete(mask_cur) ;
504 
505  /* Set the flat to 1 outside of the bounds */
506  if (crires_spec_flat_config.replace_flag) {
507  cpl_image_threshold(cpl_imagelist_get(flat, i),
508  low, high, 1.0, 1.0) ;
509  }
510  }
511  return bpm ;
512 }
513 
514 /*----------------------------------------------------------------------------*/
524 /*----------------------------------------------------------------------------*/
525 static int crires_spec_flat_save(
526  const cpl_imagelist * flat,
527  const cpl_imagelist * bpm,
528  int set_nb,
529  cpl_frameset * set,
530  const cpl_parameterlist * parlist,
531  cpl_frameset * set_tot)
532 {
533  cpl_propertylist ** qclists ;
534  const cpl_frame * ref_frame ;
535  char * filename ;
536  cpl_propertylist * inputlist ;
537  const char * recipe_name = "crires_spec_flat" ;
538  int i ;
539 
540  /* Get the reference frame */
541  ref_frame = irplib_frameset_get_first_from_group(set, CPL_FRAME_GROUP_RAW) ;
542 
543  /* Create the QC lists */
544  qclists = cpl_malloc(CRIRES_NB_DETECTORS * sizeof(cpl_propertylist*)) ;
545  for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
546  qclists[i] = cpl_propertylist_new() ;
547  cpl_propertylist_append_int(qclists[i], "ESO QC NBBAD",
548  crires_spec_flat_config.bpm_nb[i]) ;
549  cpl_propertylist_append_double(qclists[i], "ESO QC FLAT MEAN",
550  crires_spec_flat_config.flat_mean[i]) ;
551  cpl_propertylist_append_double(qclists[i], "ESO QC FLAT STDEV",
552  crires_spec_flat_config.flat_stdev[i]) ;
553  cpl_propertylist_append_double(qclists[i], "ESO QC FLAT FLUX",
554  crires_spec_flat_config.flat_flux[i]) ;
555  cpl_propertylist_append_double(qclists[i], "ESO QC FLAT MASTER RMS",
556  crires_spec_flat_config.flat_master_rms[i]) ;
557 
558  /* Propagate some keywords from input raw frame extensions */
559  inputlist = cpl_propertylist_load_regexp(
560  cpl_frame_get_filename(ref_frame), i+1,
561  CRIRES_HEADER_EXT_FORWARD, 0) ;
562  cpl_propertylist_copy_property_regexp(qclists[i], inputlist,
563  CRIRES_HEADER_EXT_FORWARD, 0) ;
564  cpl_propertylist_delete(inputlist) ;
565  }
566 
567  /* Write the flat image */
568  filename = cpl_sprintf("%s_set%02d.fits", recipe_name, set_nb) ;
569  crires_image_save(set_tot,
570  parlist,
571  set,
572  flat,
573  recipe_name,
574  CRIRES_CALPRO_FLAT,
575  CRIRES_PROTYPE_FLAT,
576  crires_spec_flat_config.period,
577  NULL,
578  (const cpl_propertylist**)qclists,
579  PACKAGE "/" PACKAGE_VERSION,
580  filename) ;
581  cpl_free(filename) ;
582 
583  /* Write the BPM */
584  if (bpm != NULL) {
585  filename = cpl_sprintf("%s_set%02d_bpm.fits", recipe_name, set_nb) ;
586  crires_image_save(set_tot,
587  parlist,
588  set,
589  bpm,
590  recipe_name,
591  CRIRES_CALPRO_BPM,
592  CRIRES_PROTYPE_BPM,
593  crires_spec_flat_config.period,
594  NULL,
595  (const cpl_propertylist**)qclists,
596  PACKAGE "/" PACKAGE_VERSION,
597  filename) ;
598  cpl_free(filename) ;
599  }
600 
601  /* Free and return */
602  for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
603  cpl_propertylist_delete(qclists[i]) ;
604  }
605  cpl_free(qclists) ;
606  return 0;
607 }
608 
609 /*----------------------------------------------------------------------------*/
616 /*----------------------------------------------------------------------------*/
617 static int crires_spec_flat_compare(
618  const cpl_frame * frame1,
619  const cpl_frame * frame2)
620 {
621  int comparison ;
622  cpl_propertylist * plist1 ;
623  cpl_propertylist * plist2 ;
624  double dval1, dval2 ;
625 
626  /* Test entries */
627  if (frame1==NULL || frame2==NULL) return -1 ;
628 
629  /* Get property lists */
630  if ((plist1=cpl_propertylist_load(cpl_frame_get_filename(frame1),0))==NULL){
631  cpl_msg_error(__func__, "getting header from reference frame");
632  return -1 ;
633  }
634  if ((plist2=cpl_propertylist_load(cpl_frame_get_filename(frame2),0))==NULL){
635  cpl_msg_error(__func__, "getting header from reference frame");
636  cpl_propertylist_delete(plist1) ;
637  return -1 ;
638  }
639 
640  /* Test status */
641  if (cpl_error_get_code()) {
642  cpl_propertylist_delete(plist1) ;
643  cpl_propertylist_delete(plist2) ;
644  return -1 ;
645  }
646 
647  comparison = 1 ;
648 
649  /* Compare the DIT used */
650  dval1 = crires_pfits_get_dit(plist1) ;
651  dval2 = crires_pfits_get_dit(plist2) ;
652  if (cpl_error_get_code()) {
653  cpl_msg_error(__func__, "Cannot get the DIT");
654  cpl_propertylist_delete(plist1) ;
655  cpl_propertylist_delete(plist2) ;
656  return -1 ;
657  }
658  if (fabs(dval1-dval2) > 1e-3) comparison = 0 ;
659 
660  /* Compare the WLEN REF used */
661  dval1 = crires_pfits_get_refwlen(plist1) ;
662  dval2 = crires_pfits_get_refwlen(plist2) ;
663  if (cpl_error_get_code()) {
664  cpl_msg_error(__func__, "Cannot get the reference wavelength");
665  cpl_propertylist_delete(plist1) ;
666  cpl_propertylist_delete(plist2) ;
667  return -1 ;
668  }
669  if (fabs(dval1-dval2) > 1e-3) comparison = 0 ;
670 
671  /* Compare the SHUT1 POS used */
672  dval1 = crires_pfits_get_bafflepos(plist1) ;
673  dval2 = crires_pfits_get_bafflepos(plist2) ;
674  if (cpl_error_get_code()) {
675  cpl_msg_error(__func__, "Cannot get the baffle position");
676  cpl_propertylist_delete(plist1) ;
677  cpl_propertylist_delete(plist2) ;
678  return -1 ;
679  }
680  if (fabs(dval1-dval2) > 1e-3) comparison = 0 ;
681 
682  cpl_propertylist_delete(plist1) ;
683  cpl_propertylist_delete(plist2) ;
684  return comparison ;
685 }
686