IIINSTRUMENT Pipeline Reference Manual 6.2.5
isaac_spc_arc.c
1/* $Id: isaac_spc_arc.c,v 1.58 2013-03-12 08:06:48 llundin Exp $
2 *
3 * This file is part of the ISAAC 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., 51 Franklin St, Fifth Floor, Boston, MA 02111-1307 USA
19 */
20
21/*
22 * $Author: llundin $
23 * $Date: 2013-03-12 08:06:48 $
24 * $Revision: 1.58 $
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 <string.h>
37#include <math.h>
38#include <float.h>
39#include <cpl.h>
40
41#include "irplib_plugin.h"
42#include "irplib_utils.h"
43#include "irplib_distortion.h"
44
45#include "isaac_utils.h"
46#include "isaac_wavelength.h"
47#include "isaac_physicalmodel.h"
48#include "isaac_pfits.h"
49#include "isaac_dfs.h"
50
51/*-----------------------------------------------------------------------------
52 Define
53 -----------------------------------------------------------------------------*/
54
55#define RECIPE_STRING "isaac_spc_arc"
56
57#define ISAAC_ARC_SATURATION 20000
58
59/*-----------------------------------------------------------------------------
60 Functions prototypes
61 -----------------------------------------------------------------------------*/
62
63static int isaac_spc_arc_reduce_sw(cpl_frameset *, const cpl_parameterlist *,
64 const char *, const char *, cpl_frameset *);
65static int isaac_spc_arc_reduce_lw(cpl_frameset *, const cpl_parameterlist *,
66 const char *, const char *, cpl_frameset *);
67static cpl_table * isaac_spc_arc_compute(const cpl_image *, const char *,
68 const char *, const char *, const char *, cpl_table **, cpl_image **);
69static int isaac_spc_arc_save(const cpl_table *, const cpl_table *,
70 const cpl_image *, const char *, cpl_frameset *,
71 const cpl_parameterlist *, cpl_frameset *);
72static int isaac_spc_arc_compare(const cpl_frame *, const cpl_frame *);
73static int * isaac_spc_arc_find_lamps(cpl_frameset *);
74static int isaac_is_xenon_lamp_active(const cpl_propertylist *);
75static int isaac_is_argon_lamp_active(const cpl_propertylist *);
76
77
78cpl_recipe_define(isaac_spc_arc, ISAAC_BINARY_VERSION,
79 "Lars Lundin", PACKAGE_BUGREPORT, "2002, 2003, 2008",
80 "ISAAC Spectro arc recipe",
81 RECIPE_STRING " -- ISAAC Spectro arc recipe\n"
82 "The files listed in the Set Of Frames (sof-file) "
83 "must be tagged:\n"
84 "raw-file.fits "ISAAC_SPC_ARC_RAW" or\n"
85 "xe-cat.fits "ISAAC_CALPRO_XE_CAT" or\n"
86 "ar-cat.fits "ISAAC_CALPRO_AR_CAT"\n");
87
88
89/*-----------------------------------------------------------------------------
90 Static variables
91 -----------------------------------------------------------------------------*/
92
93static struct {
94 /* Inputs */
95 int rej_left;
96 int rej_right;
97 int rej_bottom;
98 int rej_top;
99 int sub_dark;
100 int arc_max_width;
101 int max_offset;
102 double arc_kappa;
103 int out_corr;
104 /* Outputs */
105 int set_nb;
106 int pair_nb;
107 int nb_saturated;
108 int arm;
109 char resol;
110 double disprel_cc;
111 int disprel_clines;
112 int disprel_dlines;
113 double disprel_rms;
114 double disprel_offset;
115 double fwhm_med;
116 int fwhm_good;
117} isaac_spc_arc_config;
118
119/*-----------------------------------------------------------------------------
120 Functions code
121 -----------------------------------------------------------------------------*/
122
123/*----------------------------------------------------------------------------*/
131/*----------------------------------------------------------------------------*/
132static
133cpl_error_code isaac_spc_arc_fill_parameterlist(cpl_parameterlist * self)
134{
135 const char * context = PACKAGE "." RECIPE_STRING;
136 cpl_error_code err;
137
138 cpl_ensure_code(self, CPL_ERROR_NULL_INPUT);
139
140 /* Fill the parameters list */
141
142 /* --rejected */
143 err = irplib_parameterlist_set_string(self, PACKAGE, RECIPE_STRING,
144 "rejected", "-1,-1,100,100", "rej",
145 context,
146 "left right bottom top rejections");
147 cpl_ensure_code(!err, err);
148
149 /* --subdark */
150 err = irplib_parameterlist_set_bool(self, PACKAGE, RECIPE_STRING,
151 "subdark", CPL_FALSE, NULL, context,
152 "Flag to subtract the dark");
153 cpl_ensure_code(!err, err);
154
155 /* --arc_max_w */
156 err = irplib_parameterlist_set_int(self, PACKAGE, RECIPE_STRING,
157 "arc_max_w", 33, NULL, context,
158 "Maximum arc width allowed in pixels");
159 cpl_ensure_code(!err, err);
160
161 /* --max_offset */
162 err = irplib_parameterlist_set_int(self, PACKAGE, RECIPE_STRING,
163 "max_offset", 50, NULL, context,
164 "Maximum offset from the physical "
165 "model allowed in pixels");
166 cpl_ensure_code(!err, err);
167
168 /* --arc_kappa */
169 err = irplib_parameterlist_set_double(self, PACKAGE, RECIPE_STRING,
170 "arc_kappa", 0.33, NULL, context,
171 "kappa for the threshold used for "
172 "arcs detection");
173 cpl_ensure_code(!err, err);
174
175 /* --out_corr */
176 err = irplib_parameterlist_set_bool(self, PACKAGE, RECIPE_STRING,
177 "out_corr", CPL_FALSE, NULL, context,
178 "Flag to output corrected images");
179 cpl_ensure_code(!err, err);
180
181 return CPL_ERROR_NONE;
182}
183
184/*----------------------------------------------------------------------------*/
191/*----------------------------------------------------------------------------*/
192static int isaac_spc_arc(cpl_frameset * framelist,
193 const cpl_parameterlist * parlist)
194{
195 const char * sval;
196 cpl_size * labels = NULL;
197 cpl_size nlabels = 0;
198 const char * xe;
199 const char * ar;
200 cpl_propertylist * plist = NULL;
201 cpl_frameset * arcframes = NULL;
202 cpl_frameset * arc_one = NULL;
203 int i;
204
205 /* Retrieve input parameters */
206 /* Rejection parameters */
207 sval = irplib_parameterlist_get_string(parlist, PACKAGE, RECIPE_STRING,
208 "rejected");
209 skip_if(sval == NULL);
210 error_if (sscanf(sval, "%d,%d,%d,%d",
211 &isaac_spc_arc_config.rej_left,
212 &isaac_spc_arc_config.rej_right,
213 &isaac_spc_arc_config.rej_bottom,
214 &isaac_spc_arc_config.rej_top) != 4,
215 CPL_ERROR_DATA_NOT_FOUND, "Parameter not in format %s: %s",
216 "%d,%d,%d,%d", sval);
217
218 /* Output corrected images */
219 isaac_spc_arc_config.out_corr
220 = irplib_parameterlist_get_bool(parlist, PACKAGE, RECIPE_STRING,
221 "out_corr");
222 /* Dark subtraction */
223 isaac_spc_arc_config.sub_dark
224 = irplib_parameterlist_get_bool(parlist, PACKAGE, RECIPE_STRING,
225 "subdark");
226
227 /* Arc max width in pixels */
228 isaac_spc_arc_config.arc_max_width
229 = irplib_parameterlist_get_int(parlist, PACKAGE, RECIPE_STRING,
230 "arc_max_w");
231
232 /* Max offset in pixels */
233 isaac_spc_arc_config.max_offset
234 = irplib_parameterlist_get_int(parlist, PACKAGE, RECIPE_STRING,
235 "max_offset");
236 /* Arc detection kappa */
237 isaac_spc_arc_config.arc_kappa
238 = irplib_parameterlist_get_double(parlist, PACKAGE, RECIPE_STRING,
239 "arc_kappa");
240
241 /* Identify the RAW and CALIB frames in the input frameset */
242 skip_if (isaac_dfs_set_groups(framelist));
243
244 /* Retrieve raw frames */
245 arcframes = isaac_extract_frameset(framelist, ISAAC_SPC_ARC_RAW);
246 error_if (arcframes == NULL, CPL_ERROR_DATA_NOT_FOUND,
247 "No frames are tagged %s", ISAAC_SPC_ARC_RAW);
248
249 /* Retrieve calibration data */
250 xe = isaac_extract_filename(framelist, ISAAC_CALPRO_XE_CAT);
251 error_if (xe == NULL, CPL_ERROR_DATA_NOT_FOUND,
252 "Xe catalogue not found");
253
254 ar = isaac_extract_filename(framelist, ISAAC_CALPRO_AR_CAT);
255 error_if (ar == NULL, CPL_ERROR_DATA_NOT_FOUND,
256 "Ar catalogue not found");
257
258 /* Labelise all input frames */
259 labels = cpl_frameset_labelise(arcframes, isaac_spc_arc_compare, &nlabels);
260 any_if ("Could not labelise input frames (nlabels=%d)", (int)nlabels);
261
262 /* Extract settings and reduce each of them */
263 for (i=0; i < nlabels; i++) {
264 const cpl_frame * cur_frame;
265 const char * filename;
266 int error;
267
268 /* Reduce data set nb i */
269 cpl_msg_info(cpl_func, "Reducing data set %d of %d", i+1, (int)nlabels);
270 isaac_spc_arc_config.set_nb = i+1;
271 cpl_frameset_delete(arc_one);
272 arc_one = cpl_frameset_extract(arcframes, labels, i);
273
274 /* Get the arm used (SW or LW) */
275 cur_frame = cpl_frameset_get_position(arc_one, 0);
276 filename = cpl_frame_get_filename(cur_frame);
277 cpl_propertylist_delete(plist);
278 plist = cpl_propertylist_load(filename, 0);
279 sval = isaac_pfits_get_arm(plist);
280 any_if ("Could not get the arm from %s in set %d of %d", filename,
281 i+1, (int)nlabels);
282
283 if (sval[0] == 'S') {
284 isaac_spc_arc_config.arm = 1;
285 } else if (sval[0] == 'L') {
286 isaac_spc_arc_config.arm = 2;
287 } else {
288 isaac_spc_arc_config.arm = 0;
289 error_if(1, CPL_ERROR_UNSUPPORTED_MODE,
290 "Unsupported arm in %s in set %d of %d: %s", filename,
291 i+1, (int)nlabels, sval);
292 }
293
294 /* Get the resolution */
295 sval = isaac_pfits_get_resolution(plist);
296 any_if ("Could not get the resolution from %s in set %d of %d",
297 filename, i+1, (int)nlabels);
298
299 if (sval[0]=='L') isaac_spc_arc_config.resol = 'L';
300 else if (sval[0]=='M') isaac_spc_arc_config.resol = 'M';
301 else isaac_spc_arc_config.resol = 'U';
302 cpl_propertylist_empty(plist);
303
304 error = isaac_spc_arc_config.arm == 1 ?
305 /* SW mode */
306 isaac_spc_arc_reduce_sw(arc_one, parlist, ar, xe, framelist) :
307 /* LW mode */
308 isaac_spc_arc_reduce_lw(arc_one, parlist, ar, xe, framelist);
309
310 error_if(error, cpl_error_get_code(),
311 "Could not reduce set %d of %d", i+1, (int)nlabels);
312 }
313
314 end_skip;
315
316 cpl_frameset_delete(arc_one);
317 cpl_frameset_delete(arcframes);
318 cpl_free(labels);
319 cpl_propertylist_delete(plist);
320
321 return cpl_error_get_code();
322}
323
324/*----------------------------------------------------------------------------*/
334/*----------------------------------------------------------------------------*/
335static int isaac_spc_arc_reduce_sw(
336 cpl_frameset * arcframes,
337 const cpl_parameterlist * parlist,
338 const char * ar,
339 const char * xe,
340 cpl_frameset * set_tot)
341{
342 int * lamps;
343 int nframes;
344 char lines_table[16];
345 cpl_frame * cur_frame;
346 const char * cur_fname;
347 cpl_image * xenon;
348 cpl_image * argon;
349 cpl_image * xe_ar;
350 cpl_image * dark;
351 cpl_image * to_compute;
352 cpl_table * arcs_fwhm;
353 cpl_image * out_corr;
354 cpl_table * out_table;
355 int i;
356
357 /* Initialise */
358 nframes = cpl_frameset_get_size(arcframes);
359 isaac_spc_arc_config.pair_nb = 0;
360 to_compute = NULL;
361
362 /* Look for each file which lamp is activated */
363 /* lamps[i]==0 ---> frame i : lamps off */
364 /* lamps[i]==1 ---> frame i : Xenon lamp on */
365 /* lamps[i]==2 ---> frame i : Argon lamp on */
366 /* lamps[i]==3 ---> frame i : Arg and Xe lamps on */
367 if ((lamps=isaac_spc_arc_find_lamps(arcframes)) == NULL) {
368 cpl_msg_error(cpl_func, "in finding the activated lamps");
369 return CPL_ERROR_UNSPECIFIED;
370 }
371
372 /* Get the images */
373 xenon = argon = xe_ar = dark = NULL;
374 for (i=0; i<nframes; i++) {
375 cur_frame = cpl_frameset_get_position(arcframes, i);
376 cur_fname = cpl_frame_get_filename(cur_frame);
377 if ((lamps[i] == 0) && (dark == NULL)) {
378 cpl_msg_info(cpl_func, "Dark image: [%s]", cur_fname);
379 dark = cpl_image_load(cur_fname, CPL_TYPE_FLOAT, 0, 0);
380 } else if ((lamps[i] == 1) && (xenon == NULL)) {
381 cpl_msg_info(cpl_func, "Xenon lamp: [%s]", cur_fname);
382 xenon = cpl_image_load(cur_fname, CPL_TYPE_FLOAT, 0, 0);
383 } else if ((lamps[i] == 2) && (argon == NULL)) {
384 cpl_msg_info(cpl_func, "Argon lamp: [%s]", cur_fname);
385 argon = cpl_image_load(cur_fname, CPL_TYPE_FLOAT, 0, 0);
386 } else if ((lamps[i] == 3) && (xe_ar == NULL)) {
387 cpl_msg_info(cpl_func, "Xenon+Argon lamp: [%s]", cur_fname);
388 xe_ar = cpl_image_load(cur_fname, CPL_TYPE_FLOAT, 0, 0);
389 }
390 }
391 cpl_free(lamps);
392
393 /* All lamps are switched off */
394 if (!xenon && !argon && !xe_ar) {
395 cpl_msg_error(cpl_func, "neither xenon nor argon lamp activated");
396 if (dark) cpl_image_delete(dark);
397 return CPL_ERROR_UNSPECIFIED;
398 }
399
400 /* Get the first file name */
401 cur_frame = cpl_frameset_get_position(arcframes, 0);
402 cur_fname = cpl_frame_get_filename(cur_frame);
403
404 /* Reduction in LR */
405 if (isaac_spc_arc_config.resol == 'L') {
406 cpl_msg_info(cpl_func, "Low resolution");
407
408 /* Xenon lines */
409 if (xenon) {
410 if (dark) to_compute = cpl_image_subtract_create(xenon, dark);
411 else to_compute = cpl_image_duplicate(xenon);
412 cpl_image_delete(xenon);
413 strcpy(lines_table, "Xe");
414
415 /* Apply the reduction */
416 cpl_msg_info(cpl_func, "Apply the reduction");
417 isaac_spc_arc_config.pair_nb ++;
418 cpl_msg_indent_more();
419 if ((out_table = isaac_spc_arc_compute(to_compute, cur_fname,
420 lines_table, ar, xe, &arcs_fwhm,
421 &out_corr)) == NULL) {
422 cpl_msg_error(cpl_func, "arc reduction computation failed");
423 cpl_image_delete(to_compute);
424 } else {
425 /* Save the products */
426 cpl_image_delete(to_compute);
427 cpl_msg_info(cpl_func, "Save the products");
428 isaac_spc_arc_save(out_table, arcs_fwhm, out_corr, lines_table,
429 arcframes, parlist, set_tot);
430 cpl_table_delete(out_table);
431 if (arcs_fwhm) cpl_table_delete(arcs_fwhm);
432 if (out_corr) cpl_image_delete(out_corr);
433 }
434 cpl_msg_indent_less();
435 }
436
437 /* Argon lines */
438 if (argon) {
439 if (dark) to_compute = cpl_image_subtract_create(argon, dark);
440 else to_compute = cpl_image_duplicate(argon);
441 cpl_image_delete(argon);
442 strcpy(lines_table, "Ar");
443
444 /* Apply the reduction */
445 cpl_msg_info(cpl_func, "Apply the reduction");
446 isaac_spc_arc_config.pair_nb ++;
447 cpl_msg_indent_more();
448 if ((out_table = isaac_spc_arc_compute(to_compute, cur_fname,
449 lines_table, ar, xe, &arcs_fwhm,
450 &out_corr)) == NULL) {
451 cpl_msg_error(cpl_func, "arc reduction computation failed");
452 cpl_image_delete(to_compute);
453 } else {
454 /* Save the products */
455 cpl_image_delete(to_compute);
456 cpl_msg_info(cpl_func, "Save the products");
457 isaac_spc_arc_save(out_table, arcs_fwhm, out_corr, lines_table,
458 arcframes, parlist, set_tot);
459 cpl_table_delete(out_table);
460 if (arcs_fwhm) cpl_table_delete(arcs_fwhm);
461 if (out_corr) cpl_image_delete(out_corr);
462 }
463 cpl_msg_indent_less();
464 }
465
466 /* Xenon+Argon lines */
467 if (xe_ar) {
468 if (dark) to_compute = cpl_image_subtract_create(xe_ar, dark);
469 else to_compute = cpl_image_duplicate(xe_ar);
470 cpl_image_delete(xe_ar);
471 strcpy(lines_table, "Xe+Ar");
472
473 /* Apply the reduction */
474 cpl_msg_info(cpl_func, "Apply the reduction");
475 isaac_spc_arc_config.pair_nb ++;
476 cpl_msg_indent_more();
477 if ((out_table = isaac_spc_arc_compute(to_compute, cur_fname,
478 lines_table, ar, xe, &arcs_fwhm,
479 &out_corr)) == NULL) {
480 cpl_msg_error(cpl_func, "arc reduction computation failed");
481 cpl_image_delete(to_compute);
482 } else {
483 /* Save the products */
484 cpl_image_delete(to_compute);
485 cpl_msg_info(cpl_func, "Save the products");
486 isaac_spc_arc_save(out_table, arcs_fwhm, out_corr, lines_table,
487 arcframes, parlist, set_tot);
488 cpl_table_delete(out_table);
489 if (arcs_fwhm) cpl_table_delete(arcs_fwhm);
490 if (out_corr) cpl_image_delete(out_corr);
491 }
492 cpl_msg_indent_less();
493 }
494
495 } else if (isaac_spc_arc_config.resol == 'M') {
496 cpl_msg_info(cpl_func, "Medium resolution");
497 /* Get the input image */
498 if (xenon && argon) {
499 if (dark) {
500 cpl_image_subtract(xenon, dark);
501 cpl_image_subtract(argon, dark);
502 to_compute = cpl_image_add_create(xenon, argon);
503 } else to_compute = cpl_image_add_create(xenon, argon);
504 cpl_image_delete(xenon);
505 cpl_image_delete(argon);
506 strcpy(lines_table, "Xe+Ar");
507 } else if (xenon) {
508 if (dark) to_compute = cpl_image_subtract_create(xenon, dark);
509 else to_compute = cpl_image_duplicate(xenon);
510 cpl_image_delete(xenon);
511 strcpy(lines_table, "Xe");
512 } else if (argon) {
513 if (dark) to_compute = cpl_image_subtract_create(argon, dark);
514 else to_compute = cpl_image_duplicate(argon);
515 cpl_image_delete(argon);
516 strcpy(lines_table, "Ar");
517 } else if (xe_ar) {
518 if (dark) to_compute = cpl_image_subtract_create(xe_ar, dark);
519 else to_compute = cpl_image_duplicate(xe_ar);
520 cpl_image_delete(xe_ar);
521 strcpy(lines_table, "Xe+Ar");
522 }
523
524 /* Apply the reduction */
525 cpl_msg_info(cpl_func, "Apply the reduction");
526 isaac_spc_arc_config.pair_nb ++;
527 cpl_msg_indent_more();
528 if ((out_table = isaac_spc_arc_compute(to_compute, cur_fname,
529 lines_table, ar, xe, &arcs_fwhm,
530 &out_corr)) == NULL) {
531 cpl_msg_error(cpl_func, "arc reduction computation failed");
532 cpl_image_delete(to_compute);
533 } else {
534 /* Save the products */
535 cpl_image_delete(to_compute);
536 cpl_msg_info(cpl_func, "Save the products");
537 isaac_spc_arc_save(out_table, arcs_fwhm, out_corr, lines_table,
538 arcframes, parlist, set_tot);
539 cpl_table_delete(out_table);
540 if (arcs_fwhm) cpl_table_delete(arcs_fwhm);
541 if (out_corr) cpl_image_delete(out_corr);
542 }
543 cpl_msg_indent_less();
544 }
545
546 if (dark) cpl_image_delete(dark);
547
548 return 0;
549}
550
551/*----------------------------------------------------------------------------*/
561/*----------------------------------------------------------------------------*/
562static int isaac_spc_arc_reduce_lw(
563 cpl_frameset * arcframes,
564 const cpl_parameterlist * parlist,
565 const char * ar,
566 const char * xe,
567 cpl_frameset * set_tot)
568{
569 int * lamps;
570 int nframes;
571 char lines_table[16];
572 cpl_frame * cur_frame;
573 const char * cur_fname;
574 cpl_image * to_compute;
575 cpl_image * dark;
576 cpl_table * arcs_fwhm;
577 cpl_image * out_corr;
578 cpl_table * out_table;
579 cpl_boolean did_reduce = CPL_FALSE;
580 int i;
581
582 /* Initialise */
583 nframes = cpl_frameset_get_size(arcframes);
584
585 /* The number of frames must be even */
586 if (nframes % 2) {
587 cpl_msg_error(cpl_func, "An even nb of frames expected in input %d",
588 nframes);
589 return CPL_ERROR_UNSPECIFIED;
590 }
591
592 /* Look for each file which lamp is activated */
593 /* lamps[i]==0 ---> frame i : lamps off */
594 /* lamps[i]==1 ---> frame i : Xenon lamp on */
595 /* lamps[i]==2 ---> frame i : Argon lamp on */
596 /* lamps[i]==3 ---> frame i : Arg and Xe lamps on */
597 if ((lamps=isaac_spc_arc_find_lamps(arcframes)) == NULL) {
598 cpl_msg_error(cpl_func, "in finding the activated lamps");
599 return CPL_ERROR_UNSPECIFIED;
600 }
601
602 /* Loop on the pairs */
603 for (i=0; i<nframes/2; i++) {
604 isaac_spc_arc_config.pair_nb = i+1;
605 /* Load the image */
606 cur_frame = cpl_frameset_get_position(arcframes, 2*i);
607 cur_fname = cpl_frame_get_filename(cur_frame);
608 if ((to_compute = cpl_image_load(cur_fname,CPL_TYPE_FLOAT,0,0))==NULL){
609 cpl_msg_error(cpl_func, "Could not load frame %s", cur_fname);
610 cpl_free(lamps);
611 }
612 cpl_msg_info(cpl_func, "Pair %d: Lamp and dark identification", i+1);
613 switch (lamps[2*i]) {
614 /* Xenon lamp */
615 case 1:
616 strcpy(lines_table, "Xe");
617 cpl_msg_info(cpl_func, "Xenon lamp: [%s]", cur_fname);
618 break;
619 /* Argon lamp */
620 case 2:
621 strcpy(lines_table, "Ar");
622 cpl_msg_info(cpl_func, "Argon lamp: [%s]", cur_fname);
623 break;
624 /* Xenon+Argon lamp */
625 case 3:
626 strcpy(lines_table, "Xe+Ar");
627 cpl_msg_info(cpl_func, "Xenon+Argon lamp: [%s]", cur_fname);
628 break;
629 default:
630 cpl_image_delete(to_compute);
631 cpl_msg_info(cpl_func, "Lamps are off. Next pair...");
632 continue;
633 }
634
635 /* Get the dark if present */
636 if (lamps[2*i+1] == 0) {
637 cur_frame = cpl_frameset_get_position(arcframes, 2*i+1);
638 cur_fname = cpl_frame_get_filename(cur_frame);
639 dark = cpl_image_load(cur_fname, CPL_TYPE_FLOAT, 0, 0);
640 cpl_image_subtract(to_compute, dark);
641 cpl_image_delete(dark);
642 cpl_msg_info(cpl_func, "Dark frame : [%s]", cur_fname);
643 } else {
644 cpl_msg_info(cpl_func, "No dark frame");
645 }
646
647 /* Get the file name */
648 cur_frame = cpl_frameset_get_position(arcframes, 2*i);
649 cur_fname = cpl_frame_get_filename(cur_frame);
650
651 /* Apply the reduction */
652 cpl_msg_info(cpl_func, "Apply the reduction");
653 cpl_msg_indent_more();
654 if ((out_table = isaac_spc_arc_compute(to_compute, cur_fname,
655 lines_table, ar, xe, &arcs_fwhm,
656 &out_corr)) == NULL) {
657 cpl_msg_error(cpl_func, "arc reduction computation failed");
658 cpl_image_delete(to_compute);
659 } else {
660 /* Save the products */
661 cpl_image_delete(to_compute);
662 cpl_msg_info(cpl_func, "Save the products");
663 isaac_spc_arc_save(out_table, arcs_fwhm, out_corr, lines_table,
664 arcframes, parlist, set_tot);
665 cpl_table_delete(out_table);
666 if (arcs_fwhm) cpl_table_delete(arcs_fwhm);
667 if (out_corr) cpl_image_delete(out_corr);
668 if (!cpl_error_get_code()) did_reduce = CPL_TRUE;
669 }
670 cpl_msg_indent_less();
671 }
672
673 /* Free and return */
674 cpl_free(lamps);
675 cpl_ensure_code(did_reduce, CPL_ERROR_ILLEGAL_INPUT);
676
677 return cpl_error_set_where(cpl_func); /* Propagate error, if any */
678}
679
680/*----------------------------------------------------------------------------*/
693/*----------------------------------------------------------------------------*/
694static cpl_table * isaac_spc_arc_compute(
695 const cpl_image * in,
696 const char * in_name,
697 const char * lines_table,
698 const char * ar,
699 const char * xe,
700 cpl_table ** arcs_fwhm,
701 cpl_image ** out_corr)
702{
703 cpl_table * out_tab;
704 int xmin, ymin, xmax, ymax;
705 int nx, ny;
706 cpl_mask * saturation_map;
707 double slit_width;
708 int order;
709 cpl_polynomial * distor_poly;
710 cpl_polynomial * poly2d_id;
711 cpl_vector * profile;
712 cpl_image * in_corr;
713 cpl_apertures * arcs;
714 double * phdisprel;
715 computed_disprel * disprel;
716 cpl_size power[2];
717 double fwhm_x, fwhm_y;
718 cpl_vector * fwhm_valid;
719 int i;
720
721 /* Initialise */
722 nx = cpl_image_get_size_x(in);
723 ny = cpl_image_get_size_y(in);
724 *arcs_fwhm = NULL;
725 *out_corr = NULL;
726
727 /* Define zone */
728 xmin = 1;
729 xmax = nx;
730 ymin = isaac_spc_arc_config.rej_bottom + 1;
731 ymax = ny - isaac_spc_arc_config.rej_top;
732
733 /* Compute the number of saturated pixels */
734 saturation_map = cpl_mask_threshold_image_create(in, ISAAC_ARC_SATURATION,
735 DBL_MAX);
736 if (saturation_map != NULL) {
737 isaac_spc_arc_config.nb_saturated = cpl_mask_count(saturation_map);
738 cpl_mask_delete(saturation_map);
739 } else {
740 isaac_spc_arc_config.nb_saturated = 0;
741 }
742
743 /* Distortion estimation */
744 cpl_msg_info(cpl_func, "Estimate the distortion");
745 cpl_msg_indent_more();
746 if ((distor_poly = irplib_distortion_estimate(in, xmin, ymin, xmax, ymax,
747 isaac_spc_arc_config.sub_dark, ISAAC_ARC_SATURATION,
748 isaac_spc_arc_config.arc_max_width,
749 isaac_spc_arc_config.arc_kappa, 2, &arcs)) == NULL) {
750 cpl_msg_error(cpl_func, "Could not estimage distortion");
751 cpl_msg_indent_less();
752 return NULL;
753 }
754 cpl_msg_indent_less();
755
756 /* Distortion correction */
757 cpl_msg_info(cpl_func, "Correct the distortion");
758 cpl_msg_indent_more();
759 in_corr = cpl_image_duplicate(in);
760
761 /* Create the identity polynomial */
762 poly2d_id = cpl_polynomial_new(2);
763 power[0] = 0; power[1] = 1;
764 cpl_polynomial_set_coeff(poly2d_id, power, 1.0);
765
766 /* Create the kernel */
767 profile = cpl_vector_new(CPL_KERNEL_DEF_SAMPLES);
768 cpl_vector_fill_kernel_profile(profile, CPL_KERNEL_DEFAULT,
769 CPL_KERNEL_DEF_WIDTH);
770
771 /* Apply the distortion */
772 if (cpl_image_warp_polynomial(in_corr, in, distor_poly,
773 poly2d_id, profile, CPL_KERNEL_DEF_WIDTH, profile,
774 CPL_KERNEL_DEF_WIDTH) != CPL_ERROR_NONE) {
775 cpl_msg_error(cpl_func, "Could not correct the distortion");
776 cpl_image_delete(in_corr);
777 cpl_polynomial_delete(poly2d_id);
778 cpl_polynomial_delete(distor_poly);
779 cpl_vector_delete(profile);
780 cpl_msg_indent_less();
781 return NULL;
782 }
783 cpl_polynomial_delete(poly2d_id);
784 cpl_vector_delete(profile);
785 cpl_msg_indent_less();
786
787 /* Compute the FWHM of the detected arcs */
788 cpl_msg_info(cpl_func, "Compute the FWHM of the detected arcs");
789 /* Create the fwhms table */
790 *arcs_fwhm = cpl_table_new(cpl_apertures_get_size(arcs));
791 cpl_table_new_column(*arcs_fwhm, "XPOS", CPL_TYPE_DOUBLE);
792 cpl_table_new_column(*arcs_fwhm, "FWHM", CPL_TYPE_DOUBLE);
793 cpl_table_new_column(*arcs_fwhm, "FLUX", CPL_TYPE_DOUBLE);
794 /* Compute the fwhms */
795 isaac_spc_arc_config.fwhm_good = 0;
796 for (i=0; i<cpl_apertures_get_size(arcs); i++) {
797 cpl_table_set_double(*arcs_fwhm, "XPOS", i,
798 cpl_apertures_get_centroid_x(arcs, i+1));
799 cpl_table_set_double(*arcs_fwhm, "FLUX", i,
800 cpl_apertures_get_flux(arcs, i+1));
801 if (cpl_image_get_fwhm(in_corr, cpl_apertures_get_centroid_x(arcs, i+1),
802 512, &fwhm_x, &fwhm_y) != CPL_ERROR_NONE) {
803 cpl_msg_warning(cpl_func, "Could not get the FWHM");
804 cpl_error_reset();
805 }
806 cpl_table_set_double(*arcs_fwhm, "FWHM", i, fwhm_x);
807 if (fwhm_x > 0) isaac_spc_arc_config.fwhm_good ++;
808 }
809 cpl_apertures_delete(arcs);
810
811 /* Compute the median of the good fwhms */
812 if (isaac_spc_arc_config.fwhm_good > 0) {
813 fwhm_valid = cpl_vector_new(isaac_spc_arc_config.fwhm_good);
814 isaac_spc_arc_config.fwhm_good = 0;
815 for (i=0; i<cpl_table_get_nrow(*arcs_fwhm); i++) {
816 fwhm_x = cpl_table_get_double(*arcs_fwhm, "FWHM", i, NULL);
817 if (fwhm_x > 0) {
818 cpl_vector_set(fwhm_valid, isaac_spc_arc_config.fwhm_good,
819 fwhm_x);
820 isaac_spc_arc_config.fwhm_good ++;
821 }
822 }
823 isaac_spc_arc_config.fwhm_med = cpl_vector_get_median_const(fwhm_valid);
824 cpl_vector_delete(fwhm_valid);
825 } else isaac_spc_arc_config.fwhm_med = 0.0;
826
827 /* Wavelength calibration */
828
829 /* Compute the slit_width */
830 if ((slit_width = isaac_get_slitwidth(in_name)) == -1) {
831 cpl_msg_error(cpl_func, "Could not get the slit width");
832 cpl_polynomial_delete(distor_poly);
833 cpl_image_delete(in_corr);
834 cpl_table_delete(*arcs_fwhm);
835 *arcs_fwhm = NULL;
836 return NULL;
837 }
838
839 /* Get the order */
840 if ((order = isaac_find_order(in_name)) == -1) {
841 cpl_msg_error(cpl_func, "Could not get the order");
842 cpl_polynomial_delete(distor_poly);
843 cpl_image_delete(in_corr);
844 cpl_table_delete(*arcs_fwhm);
845 *arcs_fwhm = NULL;
846 return NULL;
847 }
848
849 /* First estimation using a physical model */
850 cpl_msg_info(cpl_func, "Compute the physical model");
851 cpl_msg_indent_more();
852 if ((phdisprel = isaac_get_disprel_estimate(in_name, 3)) == NULL) {
853 cpl_msg_error(cpl_func, "Could not estimate the dispersion relation");
854 cpl_polynomial_delete(distor_poly);
855 cpl_image_delete(in_corr);
856 cpl_table_delete(*arcs_fwhm);
857 *arcs_fwhm = NULL;
858 cpl_msg_indent_less();
859 return NULL;
860 }
861 cpl_msg_info(cpl_func, "f(x)=%g + %g*x + %g*x^2 + %g*x^3",
862 phdisprel[0], phdisprel[1], phdisprel[2], phdisprel[3]);
863 cpl_msg_indent_less();
864
865 /* Compute the dispersion relation */
866 cpl_msg_info(cpl_func, "Compute the dispersion relation");
867 cpl_msg_indent_more();
868 if ((disprel = spectro_compute_disprel(in_corr,
869 isaac_spc_arc_config.rej_bottom,
870 isaac_spc_arc_config.rej_top,
871 isaac_spc_arc_config.rej_left,
872 isaac_spc_arc_config.rej_right,
873 isaac_spc_arc_config.max_offset,
874 isaac_has_thermal(in_name) > 0,
875 lines_table, NULL, ar, xe, slit_width, order,
876 (int)(cpl_msg_get_level() == CPL_MSG_DEBUG),
877 phdisprel)) == NULL) {
878 cpl_msg_error(cpl_func, "Could not compute the dispersion relation");
879 cpl_polynomial_delete(distor_poly);
880 cpl_image_delete(in_corr);
881 cpl_free(phdisprel);
882 cpl_table_delete(*arcs_fwhm);
883 *arcs_fwhm = NULL;
884 cpl_msg_indent_less();
885 return NULL;
886 }
887 if (isaac_spc_arc_config.out_corr) {
888 *out_corr = in_corr;
889 in_corr = NULL;
890 } else {
891 cpl_image_delete(in_corr);
892 }
893 cpl_free(phdisprel);
894 cpl_msg_info(cpl_func, "Cross correlation factor: %g", disprel->cc);
895 cpl_msg_info(cpl_func, "f(x)=%g + %g*x + %g*x^2 + %g*x^3",
896 disprel->poly[0], disprel->poly[1], disprel->poly[2],
897 disprel->poly[3]);
898 cpl_msg_indent_less();
899
900 /* Create the output table and store the relevant information */
901 out_tab = cpl_table_new(6);
902
903 /* Fill distortion polynomial */
904 cpl_table_new_column(out_tab, "Degree_of_x", CPL_TYPE_INT);
905 cpl_table_new_column(out_tab, "Degree_of_y", CPL_TYPE_INT);
906 cpl_table_new_column(out_tab, "poly2d_coef", CPL_TYPE_DOUBLE);
907 power[0] = 0; power[1] = 0;
908 cpl_table_set_int(out_tab, "Degree_of_x", 0, power[0]);
909 cpl_table_set_int(out_tab, "Degree_of_y", 0, power[1]);
910 cpl_table_set_double(out_tab, "poly2d_coef", 0,
911 cpl_polynomial_get_coeff(distor_poly, power));
912 power[0] = 1; power[1] = 0;
913 cpl_table_set_int(out_tab, "Degree_of_x", 1, power[0]);
914 cpl_table_set_int(out_tab, "Degree_of_y", 1, power[1]);
915 cpl_table_set_double(out_tab, "poly2d_coef", 1,
916 cpl_polynomial_get_coeff(distor_poly, power));
917 power[0] = 0; power[1] = 1;
918 cpl_table_set_int(out_tab, "Degree_of_x", 2, power[0]);
919 cpl_table_set_int(out_tab, "Degree_of_y", 2, power[1]);
920 cpl_table_set_double(out_tab, "poly2d_coef", 2,
921 cpl_polynomial_get_coeff(distor_poly, power));
922 power[0] = 1; power[1] = 1;
923 cpl_table_set_int(out_tab, "Degree_of_x", 3, power[0]);
924 cpl_table_set_int(out_tab, "Degree_of_y", 3, power[1]);
925 cpl_table_set_double(out_tab, "poly2d_coef", 3,
926 cpl_polynomial_get_coeff(distor_poly, power));
927 power[0] = 2; power[1] = 0;
928 cpl_table_set_int(out_tab, "Degree_of_x", 4, power[0]);
929 cpl_table_set_int(out_tab, "Degree_of_y", 4, power[1]);
930 cpl_table_set_double(out_tab, "poly2d_coef", 4,
931 cpl_polynomial_get_coeff(distor_poly, power));
932 power[0] = 0; power[1] = 2;
933 cpl_table_set_int(out_tab, "Degree_of_x", 5, power[0]);
934 cpl_table_set_int(out_tab, "Degree_of_y", 5, power[1]);
935 cpl_table_set_double(out_tab, "poly2d_coef", 5,
936 cpl_polynomial_get_coeff(distor_poly, power));
937
938 /* Fill dispersion relation */
939 cpl_table_new_column(out_tab, "WL_coefficients", CPL_TYPE_DOUBLE);
940 cpl_table_set_double(out_tab, "WL_coefficients", 0, disprel->poly[0]);
941 cpl_table_set_double(out_tab, "WL_coefficients", 1, disprel->poly[1]);
942 cpl_table_set_double(out_tab, "WL_coefficients", 2, disprel->poly[2]);
943 cpl_table_set_double(out_tab, "WL_coefficients", 3, disprel->poly[3]);
944 cpl_table_set_double(out_tab, "WL_coefficients", 4, 0.0);
945 cpl_table_set_double(out_tab, "WL_coefficients", 5, 0.0);
946 isaac_spc_arc_config.disprel_cc = disprel->cc;
947 isaac_spc_arc_config.disprel_clines = disprel->clines;
948 isaac_spc_arc_config.disprel_dlines = disprel->dlines;
949 isaac_spc_arc_config.disprel_rms = disprel->rms;
950 isaac_spc_arc_config.disprel_offset = disprel->offset;
951
952 /* Free and return */
953 cpl_polynomial_delete(distor_poly);
954 if (disprel->poly != NULL) cpl_free(disprel->poly);
955 cpl_free(disprel);
956 return out_tab;
957}
958
959/*----------------------------------------------------------------------------*/
971/*----------------------------------------------------------------------------*/
972static int isaac_spc_arc_save(
973 const cpl_table * tab,
974 const cpl_table * fwhms,
975 const cpl_image * corr,
976 const char * lines_table,
977 cpl_frameset * set,
978 const cpl_parameterlist * parlist,
979 cpl_frameset * set_tot)
980{
981 cpl_propertylist * plist;
982 cpl_propertylist * qclist;
983 cpl_propertylist * paflist;
984 const cpl_frame * ref_frame;
985 const char * sval;
986 char qc_str[128];
987 const char * procat = isaac_spc_arc_config.arm == 1
988 ? ISAAC_SPC_ARC_SW_RES : ISAAC_SPC_ARC_LW_RES;
989 char * filename;
990 int i;
991
992
993 /* Get the QC params in qclist */
994 qclist = cpl_propertylist_new();
995
996 /* Get the reference frame */
997 ref_frame = irplib_frameset_get_first_from_group(set, CPL_FRAME_GROUP_RAW);
998 if ((plist=cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
999 0)) == NULL) {
1000 cpl_msg_error(cpl_func, "getting header from reference frame");
1001 cpl_propertylist_delete(qclist);
1002 return CPL_ERROR_UNSPECIFIED;
1003 }
1004 /* Test the status */
1005 if (cpl_error_get_code()) {
1006 cpl_propertylist_delete(qclist);
1007 cpl_propertylist_delete(plist);
1008 return CPL_ERROR_UNSPECIFIED;
1009 }
1010 sval = isaac_pfits_get_filter(plist);
1011 if (cpl_error_get_code()) cpl_error_reset();
1012 else cpl_propertylist_append_string(qclist, "ESO QC FILTER OBS", sval);
1013 cpl_propertylist_delete(plist);
1014 cpl_propertylist_append_string(qclist, "ESO QC LAMP", lines_table);
1015 cpl_propertylist_append_double(qclist, "ESO QC DISP XCORR",
1016 isaac_spc_arc_config.disprel_cc);
1017 cpl_propertylist_append_int(qclist, "ESO QC DISP NUMCAT",
1018 isaac_spc_arc_config.disprel_clines);
1019 cpl_propertylist_append_int(qclist, "ESO QC DISP NUMMATCH",
1020 isaac_spc_arc_config.disprel_dlines);
1021 cpl_propertylist_append_double(qclist, "ESO QC DISP STDEV",
1022 isaac_spc_arc_config.disprel_rms);
1023 cpl_propertylist_append_double(qclist, "ESO QC DISP OFFSET",
1024 isaac_spc_arc_config.disprel_offset);
1025 cpl_propertylist_append_double(qclist, "ESO QC DISPCO1",
1026 cpl_table_get_double(tab, "WL_coefficients", 0, NULL));
1027 cpl_propertylist_append_double(qclist, "ESO QC DISPCO2",
1028 cpl_table_get_double(tab, "WL_coefficients", 1, NULL));
1029 cpl_propertylist_append_double(qclist, "ESO QC DISPCO3",
1030 cpl_table_get_double(tab, "WL_coefficients", 2, NULL));
1031 cpl_propertylist_append_double(qclist, "ESO QC DISPCO4",
1032 cpl_table_get_double(tab, "WL_coefficients", 3, NULL));
1033 cpl_propertylist_append_double(qclist, "ESO QC DIST1",
1034 cpl_table_get_double(tab, "poly2d_coef", 0, NULL));
1035 cpl_propertylist_append_double(qclist, "ESO QC DISTX",
1036 cpl_table_get_double(tab, "poly2d_coef", 1, NULL));
1037 cpl_propertylist_append_double(qclist, "ESO QC DISTY",
1038 cpl_table_get_double(tab, "poly2d_coef", 2, NULL));
1039 cpl_propertylist_append_double(qclist, "ESO QC DISTXY",
1040 cpl_table_get_double(tab, "poly2d_coef", 3, NULL));
1041 cpl_propertylist_append_double(qclist, "ESO QC DISTXX",
1042 cpl_table_get_double(tab, "poly2d_coef", 4, NULL));
1043 cpl_propertylist_append_double(qclist, "ESO QC DISTYY",
1044 cpl_table_get_double(tab, "poly2d_coef", 5, NULL));
1045 cpl_propertylist_append_int(qclist, "ESO QC SATUR NBPIX",
1046 isaac_spc_arc_config.nb_saturated);
1047 cpl_propertylist_append_double(qclist, "ESO QC WLEN",
1048 (double)(cpl_table_get_double(tab, "WL_coefficients", 0, NULL) +
1049 512*cpl_table_get_double(tab, "WL_coefficients", 1, NULL) +
1050 512*512*cpl_table_get_double(tab, "WL_coefficients", 2, NULL) +
1051 512*512*512*cpl_table_get_double(tab, "WL_coefficients", 3, NULL)));
1052
1053 if (fwhms) {
1054 cpl_propertylist_append_int(qclist, "ESO QC ARCS NUM",
1055 cpl_table_get_nrow(fwhms));
1056 for(i=0; i<cpl_table_get_nrow(fwhms); i++) {
1057 sprintf(qc_str, "ESO QC ARCS%d XPOS", i+1);
1058 cpl_propertylist_append_double(qclist, qc_str,
1059 cpl_table_get_double(fwhms, "XPOS", i, NULL));
1060 sprintf(qc_str, "ESO QC ARCS%d FWHM", i+1);
1061 cpl_propertylist_append_double(qclist, qc_str,
1062 cpl_table_get_double(fwhms, "FWHM", i, NULL));
1063 sprintf(qc_str, "ESO QC ARCS%d FLUX", i+1);
1064 cpl_propertylist_append_double(qclist, qc_str,
1065 cpl_table_get_double(fwhms, "FLUX", i, NULL));
1066 }
1067 cpl_propertylist_append_int(qclist, "ESO QC ARCS NUMGOOD",
1068 isaac_spc_arc_config.fwhm_good);
1069 cpl_propertylist_append_double(qclist, "ESO QC FWHM MED",
1070 isaac_spc_arc_config.fwhm_med);
1071 }
1072
1073
1074 /* Write the arc table */
1075 filename = cpl_sprintf("isaac_spc_arc_set%d_pair%d.fits",
1076 isaac_spc_arc_config.set_nb, isaac_spc_arc_config.pair_nb);
1077 irplib_dfs_save_table(set_tot,
1078 parlist,
1079 set,
1080 tab,
1081 NULL,
1082 "isaac_spc_arc",
1083 procat,
1084 qclist,
1085 NULL,
1086 PACKAGE "/" PACKAGE_VERSION,
1087 filename);
1088 cpl_free(filename);
1089
1090 /* Write the corrected image */
1091 if (corr) {
1092 const char * procatc = isaac_spc_arc_config.arm == 1
1093 ? ISAAC_SPC_ARC_SW_CORR : ISAAC_SPC_ARC_LW_CORR;
1094 filename = cpl_sprintf("isaac_spc_arc_set%d_pair%d_corr.fits",
1095 isaac_spc_arc_config.set_nb, isaac_spc_arc_config.pair_nb);
1096 irplib_dfs_save_image(set_tot,
1097 parlist,
1098 set,
1099 corr,
1100 CPL_BPP_IEEE_FLOAT,
1101 "isaac_spc_arc",
1102 procatc,
1103 qclist,
1104 NULL,
1105 PACKAGE "/" PACKAGE_VERSION,
1106 filename);
1107 cpl_free(filename);
1108 }
1109
1110 /* Get the reference frame */
1111 ref_frame = irplib_frameset_get_first_from_group(set, CPL_FRAME_GROUP_RAW);
1112
1113 /* Get FITS header from reference file */
1114 if ((plist=cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
1115 0)) == NULL) {
1116 cpl_msg_error(cpl_func, "getting header from reference frame");
1117 cpl_propertylist_delete(qclist);
1118 return CPL_ERROR_UNSPECIFIED;
1119 }
1120
1121 /* Get the keywords for the paf file */
1122 paflist = cpl_propertylist_new();
1123 cpl_propertylist_copy_property_regexp(paflist, plist,
1124 "^(ARCFILE|MJD-OBS|INSTRUME|ESO TPL ID|ESO TPL NEXP|ESO DPR CATG|"
1125 "ESO DPR TECH|ESO DPR TYPE|DATE-OBS|ESO INS GRAT NAME|"
1126 "ESO INS GRAT WLEN|ESO INS GRAT ORDER|ESO INS MODE|"
1127 "ESO INS OPTI1 ID)$", 0);
1128 cpl_propertylist_delete(plist);
1129
1130 /* Copy the QC in paflist */
1131 cpl_propertylist_copy_property_regexp(paflist, qclist, ".", 0);
1132 cpl_propertylist_delete(qclist);
1133
1134 /* PRO.CATG */
1135 cpl_propertylist_update_string(paflist, CPL_DFS_PRO_CATG, procat);
1136
1137 /* Save the PAF file */
1138 filename = cpl_sprintf("isaac_spc_arc_set%d_pair%d.paf",
1139 isaac_spc_arc_config.set_nb, isaac_spc_arc_config.pair_nb);
1140 cpl_dfs_save_paf("ISAAC",
1141 "isaac_spc_arc",
1142 paflist,
1143 filename);
1144 cpl_free(filename);
1145 cpl_propertylist_delete(paflist);
1146 return 0;
1147}
1148
1149/*----------------------------------------------------------------------------*/
1156/*----------------------------------------------------------------------------*/
1157static int isaac_spc_arc_compare(const cpl_frame * frame1,
1158 const cpl_frame * frame2)
1159{
1160 int comparison = 1;
1161 const char * file1 = cpl_frame_get_filename(frame1);
1162 const char * file2 = cpl_frame_get_filename(frame2);
1163 cpl_propertylist * plist1 = NULL;
1164 cpl_propertylist * plist2 = NULL;
1165 const char * sval1,
1166 * sval2;
1167 double dval1, dval2;
1168
1169 bug_if(frame1 == NULL);
1170 bug_if(frame2 == NULL);
1171
1172 /* Get property lists */
1173 plist1 = cpl_propertylist_load(file1, 0);
1174 any_if("Could not load header from 1st frame %s", file1);
1175
1176 plist2 = cpl_propertylist_load(file2, 0);
1177 any_if("Could not load header from 2nd frame %s", file2);
1178
1179 /* Compare the slit used */
1180 sval1 = isaac_pfits_get_opti1_id(plist1);
1181 any_if("Could not get slit from 1st frame %s", file1);
1182
1183 sval2 = isaac_pfits_get_opti1_id(plist2);
1184 any_if("Could not get slit from 2nd frame %s", file2);
1185
1186 if (strcmp(sval1, sval2)) comparison = 0;
1187
1188 /* Compare the resolution */
1189 sval1 = isaac_pfits_get_resolution(plist1);
1190 any_if("Could not get resolution from 1st frame %s", file1);
1191
1192 sval2 = isaac_pfits_get_resolution(plist2);
1193 any_if("Could not get resolution from 2nd frame %s", file2);
1194
1195 if (strcmp(sval1, sval2)) comparison = 0;
1196
1197 /* Compare the central wavelength */
1198 dval1 = isaac_pfits_get_wlen(plist1);
1199 any_if("Could not get wavelength from 1st frame %s", file1);
1200
1201 dval2 = isaac_pfits_get_wlen(plist2);
1202 any_if("Could not get wavelength from 2nd frame %s", file2);
1203
1204 if (fabs(dval1-dval2) > 1e-4) comparison = 0;
1205
1206 end_skip;
1207
1208 cpl_propertylist_delete(plist1);
1209 cpl_propertylist_delete(plist2);
1210
1211 return cpl_error_get_code() ? -1 : comparison;
1212}
1213
1214/*----------------------------------------------------------------------------*/
1221/*----------------------------------------------------------------------------*/
1222static int * isaac_spc_arc_find_lamps(cpl_frameset * fset)
1223{
1224 int * lamps;
1225 int nframes;
1226 cpl_frame * cur_frame;
1227 cpl_propertylist * plist;
1228 int xenon, argon;
1229 int i;
1230
1231 /* Check entries */
1232 if (fset == NULL) return NULL;
1233
1234 /* Initialise */
1235 nframes = cpl_frameset_get_size(fset);
1236 xenon = argon = 0;
1237
1238 /* Allocate the output array */
1239 lamps = cpl_malloc(nframes * sizeof(int));
1240
1241 for (i=0; i<nframes; i++) {
1242 cur_frame = cpl_frameset_get_position(fset, i);
1243 plist=cpl_propertylist_load(cpl_frame_get_filename(cur_frame), 0);
1244 xenon = isaac_is_xenon_lamp_active(plist);
1245 argon = isaac_is_argon_lamp_active(plist);
1246 cpl_propertylist_delete(plist);
1247 if ((argon != 0 && argon != 1) || (xenon != 0 && xenon != 1)) {
1248 cpl_msg_error(cpl_func, "Could not check which lamp is on");
1249 cpl_free(lamps);
1250 return NULL;
1251 }
1252 if (xenon == 1) {
1253 if (argon == 1) lamps[i] = 3;
1254 else if (argon == 0) lamps[i] = 1;
1255 } else if (xenon == 0 ) {
1256 if (argon == 1) lamps[i] = 2;
1257 else if (argon == 0) lamps[i] = 0;
1258 }
1259 }
1260
1261 /* Free and return */
1262 return lamps;
1263}
1264
1265/*----------------------------------------------------------------------------*/
1271/*----------------------------------------------------------------------------*/
1272static int isaac_is_argon_lamp_active(const cpl_propertylist * plist)
1273{
1274 int status1, status2;
1275
1276 /* Test error */
1277 if (cpl_error_get_code()) return CPL_ERROR_UNSPECIFIED;
1278 status1 = isaac_pfits_get_lamp1_status(plist);
1279 if (cpl_error_get_code()) return CPL_ERROR_UNSPECIFIED;
1280 if (status1 == 1) {
1281 /* Still has to verify that shutter is open */
1282 status2 = isaac_pfits_get_calshut_status(plist);
1283 if (cpl_error_get_code()) {
1284 cpl_error_reset();
1285 return 1;
1286 }
1287 if (status2 == 1) return 1;
1288 }
1289 return 0;
1290}
1291
1292/*----------------------------------------------------------------------------*/
1298/*----------------------------------------------------------------------------*/
1299static int isaac_is_xenon_lamp_active(const cpl_propertylist * plist)
1300{
1301 int status1, status2;
1302
1303 /* Test error */
1304 if (cpl_error_get_code()) return CPL_ERROR_UNSPECIFIED;
1305 status1 = isaac_pfits_get_lamp2_status(plist);
1306 if (cpl_error_get_code()) return CPL_ERROR_UNSPECIFIED;
1307 if (status1 == 1) {
1308 /* Still has to verify that shutter is open */
1309 status2 = isaac_pfits_get_calshut_status(plist);
1310 if (cpl_error_get_code()) {
1311 cpl_error_reset();
1312 return 1;
1313 }
1314 if (status2 == 1) return 1;
1315 }
1316 return 0;
1317}
1318
1319
int isaac_dfs_set_groups(cpl_frameset *set)
Set the group as RAW or CALIB in a frameset.
Definition: isaac_dfs.c:60
const char * isaac_pfits_get_filter(const cpl_propertylist *plist)
find out the filter
Definition: isaac_pfits.c:880
int isaac_pfits_get_lamp1_status(const cpl_propertylist *plist)
find out the lamp1 status
Definition: isaac_pfits.c:462
int isaac_pfits_get_lamp2_status(const cpl_propertylist *plist)
find out the lamp2 status
Definition: isaac_pfits.c:492
const char * isaac_pfits_get_arm(const cpl_propertylist *plist)
find out the arm which is active
Definition: isaac_pfits.c:106
int isaac_pfits_get_calshut_status(const cpl_propertylist *plist)
find out the shutter status
Definition: isaac_pfits.c:121
double isaac_pfits_get_wlen(const cpl_propertylist *plist)
find out the central wavelength
Definition: isaac_pfits.c:865
const char * isaac_pfits_get_opti1_id(const cpl_propertylist *plist)
find out the OPTI1.ID key
Definition: isaac_pfits.c:700
const char * isaac_pfits_get_resolution(const cpl_propertylist *plist)
find out the resolution
Definition: isaac_pfits.c:775
double * isaac_get_disprel_estimate(const char *filename, cpl_size poly_deg)
Estimate the instrument wavelength range.
cpl_frameset * isaac_extract_frameset(const cpl_frameset *self, const char *tag)
Extract the frames with the given tag from a frameset.
Definition: isaac_utils.c:356
const char * isaac_extract_filename(const cpl_frameset *self, const char *tag)
Extract the filename of the first frame of the given tag.
Definition: isaac_utils.c:397