CRIRES Pipeline Reference Manual 2.3.18
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
52static cpl_imagelist * crires_spec_flat_reduce(cpl_frameset *, const char *,
53 const char *) ;
54static cpl_imagelist * crires_spec_flat_bpm(cpl_imagelist *, double,
55 double, double) ;
56static int crires_spec_flat_save(const cpl_imagelist *, const cpl_imagelist *,
57 int, cpl_frameset *, const cpl_parameterlist *, cpl_frameset *) ;
58static int crires_spec_flat_compare(const cpl_frame *, const cpl_frame *) ;
59
60static 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
67CRIRES_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
83static 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/*----------------------------------------------------------------------------*/
115static 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/*----------------------------------------------------------------------------*/
261static 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/*----------------------------------------------------------------------------*/
439static 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/*----------------------------------------------------------------------------*/
525static 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/*----------------------------------------------------------------------------*/
617static 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