IIINSTRUMENT Pipeline Reference Manual 1.5.16
sofi_spc_arc.c
1/* $Id: sofi_spc_arc.c,v 1.51 2013-03-12 08:04:53 llundin Exp $
2 *
3 * This file is part of the SOFI 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:04:53 $
24 * $Revision: 1.51 $
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#include "irplib_wlxcorr.h"
45
46#include "sofi_utils.h"
47#include "sofi_wavelength.h"
48#include "sofi_pfits.h"
49#include "sofi_dfs.h"
50
51/*-----------------------------------------------------------------------------
52 Defines
53 -----------------------------------------------------------------------------*/
54
55#define RECIPE_STRING "sofi_spc_arc"
56
57#define SOFI_ARC_SATURATION 20000
58
59/*-----------------------------------------------------------------------------
60 Functions prototypes
61 -----------------------------------------------------------------------------*/
62
63static cpl_error_code sofi_spc_arc_reduce(cpl_frameset *,
64 const cpl_parameterlist *,
65 const char *, const char *,
66 const cpl_frameset *,
67 cpl_errorstate);
68static cpl_table * sofi_spc_arc_compute(const cpl_image *, const char *,
69 const char *, const char *, const char *, cpl_table **, cpl_image **);
70static cpl_error_code sofi_spc_arc_save(cpl_frameset *, const cpl_table *,
71 const cpl_table *,
72 const cpl_image *, const char *,
73 const cpl_frameset *,
74 const cpl_parameterlist *);
75static int sofi_spc_arc_compare(const cpl_frame *, const cpl_frame *);
76static int * sofi_spc_arc_find_lamps(const cpl_frameset *);
77static int sofi_is_xenon_lamp_active(const cpl_propertylist *);
78static int sofi_is_neon_lamp_active(const cpl_propertylist *);
79
80cpl_recipe_define(sofi_spc_arc, SOFI_BINARY_VERSION,
81 "Lars Lundin", PACKAGE_BUGREPORT, "2002,2003,2009",
82 "SOFI Spectro arc recipe",
83 RECIPE_STRING " -- SOFI Spectro arc recipe.\n"
84 "The files listed in the Set Of Frames (sof-file) "
85 "must be tagged:\n"
86 "raw-file.fits "SOFI_SPC_ARC_RAW" or\n"
87 "xe-cat.fits "SOFI_CALPRO_XE_CAT" or\n"
88 "ne-cat.fits "SOFI_CALPRO_NE_CAT"\n");
89
90/*-----------------------------------------------------------------------------
91 Static variables
92 -----------------------------------------------------------------------------*/
93
94static struct {
95 /* Inputs */
96 int display;
97 int rej_left;
98 int rej_right;
99 int subdark;
100 int arc_max_w;
101 int out_corr;
102 cpl_size degree;
103 double wl_err;
104 int wl_nsamples;
105 int ppm;
106 const char * lines;
107 /* Outputs */
108 int set_nb;
109 int frame_nb;
110 int nb_saturated;
111 double disprel_cc;
112 double fwhm_med;
113 int fwhm_good;
114} sofi_spc_arc_config;
115
116/*-----------------------------------------------------------------------------
117 Functions code
118 -----------------------------------------------------------------------------*/
119
120/*----------------------------------------------------------------------------*/
128/*----------------------------------------------------------------------------*/
129static
130cpl_error_code sofi_spc_arc_fill_parameterlist(cpl_parameterlist * self)
131{
132 const char * context = PACKAGE "." RECIPE_STRING;
133 cpl_error_code err;
134
135 cpl_ensure_code(self, CPL_ERROR_NULL_INPUT);
136
137 /* Fill the parameters list */
138
139 /* --rejected */
140 err = irplib_parameterlist_set_string(self, PACKAGE, RECIPE_STRING,
141 "rejected", "100,100", "rej", context,
142 "Left, right rejections [pixel]");
143 cpl_ensure_code(!err, err);
144
145 /* --subdark */
146 err = irplib_parameterlist_set_bool(self, PACKAGE, RECIPE_STRING, "subdark",
147 CPL_FALSE, NULL, context,
148 "Enable dark subtraction");
149 cpl_ensure_code(!err, err);
150
151 /* --arc_max_w */
152 err = irplib_parameterlist_set_int(self, PACKAGE, RECIPE_STRING, "arc_max_w",
153 33, NULL, context, "Maximum supported "
154 "arc width [pixel]");
155 cpl_ensure_code(!err, err);
156
157 /* --out_corr */
158 err = irplib_parameterlist_set_bool(self, PACKAGE, RECIPE_STRING, "out_corr",
159 CPL_FALSE, NULL, context,
160 "Enable correction of output images");
161 cpl_ensure_code(!err, err);
162
163 /* --display */
164 err = irplib_parameterlist_set_bool(self, PACKAGE, RECIPE_STRING, "display",
165 CPL_FALSE, NULL, context,
166 "Enable plotting");
167 cpl_ensure_code(!err, err);
168
169 /* --degree */
170 err = irplib_parameterlist_set_int(self, PACKAGE, RECIPE_STRING, "degree",
171 2, NULL, context, "Degree of the "
172 "wavelength dispersion polynomial");
173 cpl_ensure_code(!err, err);
174
175 /* --wl_nsamples */
176 err = irplib_parameterlist_set_int(self, PACKAGE, RECIPE_STRING,
177 "wl_nsamples", 100, NULL, context,
178 "Number of samples for the wavelength "
179 "calibration");
180 cpl_ensure_code(!err, err);
181
182 /* --wl_err */
183 err = irplib_parameterlist_set_double(self, PACKAGE, RECIPE_STRING,
184 "wl_err", 1000.0, NULL, context,
185 "The wavelength error [Angstrom]");
186 cpl_ensure_code(!err, err);
187
188 /* --lines */
189 err = irplib_parameterlist_set_string(self, PACKAGE, RECIPE_STRING,
190 "lines", NULL, NULL, context,
191 "Lines ASCII-file");
192 cpl_ensure_code(!err, err);
193
194 /* --ppm */
195 err = irplib_parameterlist_set_bool(self, PACKAGE, RECIPE_STRING, "ppm",
196 CPL_FALSE, NULL, context,
197 "Enable Point Pattern Matching");
198 cpl_ensure_code(!err, err);
199
200 return CPL_ERROR_NONE;
201}
202
203
204/*----------------------------------------------------------------------------*/
211/*----------------------------------------------------------------------------*/
212static int sofi_spc_arc(cpl_frameset * framelist,
213 const cpl_parameterlist * parlist)
214{
215 cpl_errorstate prestate = cpl_errorstate_get();
216 const char * sval;
217 cpl_size * labels = NULL;
218 cpl_size nlabels;
219 const int nframes = cpl_frameset_get_size(framelist);
220 int narcs;
221 const char * xe;
222 const char * ne;
223 cpl_frameset * arcframes = NULL;
224 cpl_frameset * arc_one = NULL;
225 int i;
226
227 /* Initialise */
228 sofi_spc_arc_config.lines = NULL;
229
230 /* Retrieve input parameters */
231
232 /* Rejection parameters */
233 sval = irplib_parameterlist_get_string(parlist, PACKAGE, RECIPE_STRING,
234 "rejected");
235 bug_if(sval == NULL);
236
237 skip_if (sscanf(sval, "%d,%d",
238 &sofi_spc_arc_config.rej_left,
239 &sofi_spc_arc_config.rej_right) != 2);
240
241 /* Output corrected images */
242 sofi_spc_arc_config.out_corr
243 = irplib_parameterlist_get_bool(parlist, PACKAGE, RECIPE_STRING,
244 "out_corr");
245 /* Dark subtraction */
246 sofi_spc_arc_config.subdark
247 = irplib_parameterlist_get_bool(parlist, PACKAGE, RECIPE_STRING,
248 "subdark");
249 /* ppm */
250 sofi_spc_arc_config.ppm
251 = irplib_parameterlist_get_bool(parlist, PACKAGE, RECIPE_STRING,
252 "ppm");
253 /* Polynomial degree */
254 sofi_spc_arc_config.degree
255 = irplib_parameterlist_get_int(parlist, PACKAGE, RECIPE_STRING,
256 "degree");
257
258 /* Number of samples */
259 sofi_spc_arc_config.wl_nsamples
260 = irplib_parameterlist_get_int(parlist, PACKAGE, RECIPE_STRING,
261 "wl_nsamples");
262
263 /* Wavelength error factor */
264 sofi_spc_arc_config.wl_err
265 = irplib_parameterlist_get_double(parlist, PACKAGE, RECIPE_STRING,
266 "wl_err");
267
268 /* Arc max width in pixels */
269 sofi_spc_arc_config.arc_max_w
270 = irplib_parameterlist_get_int(parlist, PACKAGE, RECIPE_STRING,
271 "arc_max_w");
272
273 /* Display */
274 sofi_spc_arc_config.display
275 = irplib_parameterlist_get_bool(parlist, PACKAGE, RECIPE_STRING,
276 "display");
277
278 /* Lines */
279 sofi_spc_arc_config.lines
280 = irplib_parameterlist_get_string(parlist, PACKAGE, RECIPE_STRING,
281 "lines");
282
283 /* Identify the RAW and CALIB frames in the input frameset */
284 skip_if (sofi_dfs_set_groups(framelist));
285
286 /* Retrieve raw frames */
287 arcframes = sofi_extract_frameset(framelist, SOFI_SPC_ARC_RAW);
288 error_if (arcframes == NULL, CPL_ERROR_DATA_NOT_FOUND,
289 "Cannot find arc frames in the input frame set");
290
291 narcs = cpl_frameset_get_size(arcframes);
292
293 /* Retrieve calibration data */
294 xe = sofi_extract_filename(framelist, SOFI_CALPRO_XE_CAT);
295 ne = sofi_extract_filename(framelist, SOFI_CALPRO_NE_CAT);
296
297 /* Labelise all input frames */
298 labels = cpl_frameset_labelise(arcframes, sofi_spc_arc_compare, &nlabels);
299 error_if (labels == NULL, CPL_ERROR_ILLEGAL_INPUT,
300 "Cannot labelise the input frames");
301
302 /* Extract settings and reduce each of them */
303 for (i=0; i < nlabels; i++) {
304
305 /* Reduce data set nb i */
306 cpl_msg_info(cpl_func, "Reducing set %d/%d", i+1, (int)nlabels);
307
308 sofi_spc_arc_config.set_nb = i+1;
309
310 cpl_frameset_delete(arc_one);
311 arc_one = cpl_frameset_extract(arcframes, labels, i);
312
313 /* Reduce the set */
314 if (sofi_spc_arc_reduce(framelist, parlist, xe, ne, arc_one, prestate))
315 (void)cpl_error_set_message(cpl_func, cpl_error_get_code(), "Could "
316 "not reduce set %d of %d with %d arc "
317 "frame(s)", i+1, (int)nlabels,
318 (int)cpl_frameset_get_size(arc_one));
319 }
320
321 error_if (cpl_frameset_get_size(framelist) == nframes,
322 CPL_ERROR_ILLEGAL_INPUT, "No products produced from %d arc "
323 "frames grouped into %d set(s)", narcs, (int)nlabels);
324
325 end_skip;
326
327 cpl_frameset_delete(arcframes);
328 cpl_frameset_delete(arc_one);
329 cpl_free(labels);
330
331 return cpl_error_get_code();
332}
333
334/*----------------------------------------------------------------------------*/
346/*----------------------------------------------------------------------------*/
347static cpl_error_code sofi_spc_arc_reduce(cpl_frameset * set_tot,
348 const cpl_parameterlist * parlist,
349 const char * xe,
350 const char * ne,
351 const cpl_frameset * arcframes,
352 cpl_errorstate prestate)
353{
354 /* Look for each file which lamp is activated */
355 /* lamps[i]==0 ---> frame i : lamps off */
356 /* lamps[i]==1 ---> frame i : Xenon lamp on */
357 /* lamps[i]==2 ---> frame i : Neon lamp on */
358 /* lamps[i]==3 ---> frame i : Ne and Xe lamps on */
359 int * lamps = sofi_spc_arc_find_lamps(arcframes);
360 const int nframes = cpl_frameset_get_size(arcframes);
361 char lines_table[16];
362 const cpl_frame * cur_frame;
363 const char * cur_fname;
364 cpl_image * xenon = NULL;
365 cpl_image * neon = NULL;
366 cpl_image * xe_ne = NULL;
367 cpl_image * dark = NULL;
368 cpl_image * to_compute;
369 cpl_table * arcs_fwhm;
370 cpl_image * out_corr;
371 cpl_table * out_table;
372 int i;
373
374 /* Initialise */
375 sofi_spc_arc_config.frame_nb = 0;
376
377 if (lamps == NULL) return cpl_error_set_where(cpl_func);
378
379 /* Get the images */
380 for (i=0; i<nframes; i++) {
381 cur_frame = cpl_frameset_get_position_const(arcframes, i);
382 cur_fname = cpl_frame_get_filename(cur_frame);
383 if ((lamps[i] == 0) && (dark == NULL)) {
384 cpl_msg_info(cpl_func, "Dark image: [%s]", cur_fname);
385 dark = cpl_image_load(cur_fname, CPL_TYPE_FLOAT, 0, 0);
386 } else if ((lamps[i] == 1) && (xenon == NULL)) {
387 cpl_msg_info(cpl_func, "Xenon lamp: [%s]", cur_fname);
388 xenon = cpl_image_load(cur_fname, CPL_TYPE_FLOAT, 0, 0);
389 } else if ((lamps[i] == 2) && (neon == NULL)) {
390 cpl_msg_info(cpl_func, "Neon lamp: [%s]", cur_fname);
391 neon = cpl_image_load(cur_fname, CPL_TYPE_FLOAT, 0, 0);
392 } else if ((lamps[i] == 3) && (xe_ne == NULL)) {
393 cpl_msg_info(cpl_func, "Xenon+Neon lamp: [%s]", cur_fname);
394 xe_ne = cpl_image_load(cur_fname, CPL_TYPE_FLOAT, 0, 0);
395 }
396 }
397 cpl_free(lamps);
398
399 /* All lamps are switched off */
400 if (!xenon && !neon && !xe_ne) {
401 cpl_image_delete(dark);
402 return cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
403 "Neither xenon nor neon lamp activated");
404 }
405
406 /* Get the first file name */
407 cur_frame = cpl_frameset_get_position_const(arcframes, 0);
408 cur_fname = cpl_frame_get_filename(cur_frame);
409
410 /* Xenon lines */
411 if (xenon) {
412 if (!cpl_errorstate_is_equal(prestate)) {
413 cpl_msg_warning(cpl_func, "Resetting CPL error before reducing "
414 "Xenon data:");
415 cpl_errorstate_dump(prestate, CPL_FALSE, NULL);
416 cpl_errorstate_set(prestate);
417 }
418 if (dark) to_compute = cpl_image_subtract_create(xenon, dark);
419 else to_compute = cpl_image_duplicate(xenon);
420 cpl_image_delete(xenon);
421 strcpy(lines_table, "Xe");
422
423 /* Apply the reduction */
424 cpl_msg_info(cpl_func, "Apply the reduction");
425 sofi_spc_arc_config.frame_nb ++;
426 cpl_msg_indent_more();
427 if ((out_table = sofi_spc_arc_compute(to_compute, cur_fname,
428 lines_table, xe, ne, &arcs_fwhm, &out_corr)) == NULL) {
429 cpl_msg_error(cpl_func, "arc reduction computation failed");
430 cpl_image_delete(to_compute);
431 } else {
432 /* Save the products */
433 cpl_image_delete(to_compute);
434 cpl_msg_info(cpl_func, "Save the products");
435 sofi_spc_arc_save(set_tot, out_table, arcs_fwhm, out_corr,
436 lines_table, arcframes, parlist);
437 cpl_table_delete(out_table);
438 if (arcs_fwhm) cpl_table_delete(arcs_fwhm);
439 if (out_corr) cpl_image_delete(out_corr);
440 }
441 cpl_msg_indent_less();
442 }
443
444 /* Neon lines */
445 if (neon) {
446 if (!cpl_errorstate_is_equal(prestate)) {
447 cpl_msg_warning(cpl_func, "Resetting CPL error before reducing "
448 "Neon data:");
449 cpl_errorstate_dump(prestate, CPL_FALSE, NULL);
450 cpl_errorstate_set(prestate);
451 }
452 if (dark) to_compute = cpl_image_subtract_create(neon, dark);
453 else to_compute = cpl_image_duplicate(neon);
454 cpl_image_delete(neon);
455 strcpy(lines_table, "Ne");
456
457 /* Apply the reduction */
458 cpl_msg_info(cpl_func, "Apply the reduction");
459 sofi_spc_arc_config.frame_nb ++;
460 cpl_msg_indent_more();
461 if ((out_table = sofi_spc_arc_compute(to_compute, cur_fname,
462 lines_table, xe, ne, &arcs_fwhm, &out_corr)) == NULL) {
463 cpl_msg_error(cpl_func, "arc reduction computation failed");
464 cpl_image_delete(to_compute);
465 } else {
466 /* Save the products */
467 cpl_image_delete(to_compute);
468 cpl_msg_info(cpl_func, "Save the products");
469 sofi_spc_arc_save(set_tot, out_table, arcs_fwhm, out_corr,
470 lines_table, arcframes, parlist);
471 cpl_table_delete(out_table);
472 if (arcs_fwhm) cpl_table_delete(arcs_fwhm);
473 if (out_corr) cpl_image_delete(out_corr);
474 }
475 cpl_msg_indent_less();
476 }
477
478
479 /* Xenon+Neon lines */
480 if (xe_ne) {
481 if (!cpl_errorstate_is_equal(prestate)) {
482 cpl_msg_warning(cpl_func, "Resetting CPL error before reducing "
483 "Xenon+Neon data:");
484 cpl_errorstate_dump(prestate, CPL_FALSE, NULL);
485 cpl_errorstate_set(prestate);
486 }
487 if (dark) to_compute = cpl_image_subtract_create(xe_ne, dark);
488 else to_compute = cpl_image_duplicate(xe_ne);
489 cpl_image_delete(xe_ne);
490 strcpy(lines_table, "Xe+Ne");
491
492 /* Apply the reduction */
493 cpl_msg_info(cpl_func, "Apply the reduction");
494 sofi_spc_arc_config.frame_nb ++;
495 cpl_msg_indent_more();
496 if ((out_table = sofi_spc_arc_compute(to_compute, cur_fname,
497 lines_table, xe, ne, &arcs_fwhm, &out_corr)) == NULL) {
498 cpl_msg_error(cpl_func, "arc reduction computation failed");
499 cpl_image_delete(to_compute);
500 } else {
501 /* Save the products */
502 cpl_image_delete(to_compute);
503 cpl_msg_info(cpl_func, "Save the products");
504 sofi_spc_arc_save(set_tot, out_table, arcs_fwhm, out_corr,
505 lines_table, arcframes, parlist);
506 cpl_table_delete(out_table);
507 if (arcs_fwhm) cpl_table_delete(arcs_fwhm);
508 if (out_corr) cpl_image_delete(out_corr);
509 }
510 cpl_msg_indent_less();
511 }
512 cpl_image_delete(dark);
513
514 return cpl_error_get_code();
515}
516
517/*----------------------------------------------------------------------------*/
530/*----------------------------------------------------------------------------*/
531static cpl_table * sofi_spc_arc_compute(
532 const cpl_image * in,
533 const char * in_name,
534 const char * lines_table,
535 const char * xe,
536 const char * ne,
537 cpl_table ** arcs_fwhm,
538 cpl_image ** out_corr)
539{
540 cpl_image * flipped;
541 cpl_table * out_tab;
542 int xmin, ymin, xmax, ymax;
543 int nx, ny;
544 cpl_mask * saturation_map;
545 double slit_width;
546 cpl_polynomial * distor_poly_flipped;
547 cpl_polynomial * distor_poly;
548 cpl_polynomial * poly2d_id;
549 cpl_vector * profile;
550 cpl_image * in_corr;
551 cpl_apertures * arcs;
552 cpl_polynomial * phdisprel;
553 cpl_polynomial * disprel;
554 cpl_size power[5];
555 int degree;
556 double a, b, c, d, e, xc;
557 cpl_size power_flipped[2];
558 double fwhm_x, fwhm_y;
559 cpl_vector * fwhm_valid;
560 int i;
561
562 /* Initialise */
563 nx = cpl_image_get_size_x(in);
564 ny = cpl_image_get_size_y(in);
565 *arcs_fwhm = NULL;
566 *out_corr = NULL;
567
568 /* Define zone */
569 xmin = sofi_spc_arc_config.rej_left + 1;
570 xmax = nx - sofi_spc_arc_config.rej_right;
571 ymin = 1;
572 ymax = ny;
573
574 /* Compute the number of saturated pixels */
575 saturation_map = cpl_mask_threshold_image_create(in,
576 SOFI_ARC_SATURATION, DBL_MAX);
577 if (saturation_map != NULL) {
578 sofi_spc_arc_config.nb_saturated = cpl_mask_count(saturation_map);
579 cpl_mask_delete(saturation_map);
580 } else {
581 sofi_spc_arc_config.nb_saturated = 0;
582 }
583
584 /* Distortion estimation */
585 cpl_msg_info(cpl_func, "Estimate the distortion");
586 cpl_msg_indent_more();
587 /* Flip the image */
588 flipped = cpl_image_duplicate(in);
589 cpl_image_flip(flipped, 1);
590 if ((distor_poly_flipped = irplib_distortion_estimate(flipped,
591 ymin, xmin, ymax, xmax,
592 sofi_spc_arc_config.subdark, SOFI_ARC_SATURATION,
593 sofi_spc_arc_config.arc_max_w, 0.33,2,&arcs)) == NULL) {
594 cpl_msg_error(cpl_func, "cannot estimage distortion");
595 cpl_image_delete(flipped);
596 cpl_msg_indent_less();
597 return NULL;
598 }
599 cpl_image_delete(flipped);
600 cpl_msg_indent_less();
601
602 /* Flip the polynomial back */
603 distor_poly = cpl_polynomial_duplicate(distor_poly_flipped);
604 power[0] = 1; power[1] = 0; power_flipped[0] = 0; power_flipped[1] = 1;
605 cpl_polynomial_set_coeff(distor_poly, power,
606 cpl_polynomial_get_coeff(distor_poly_flipped, power_flipped));
607
608 power[0] = 2; power[1] = 0; power_flipped[0] = 0; power_flipped[1] = 2;
609 cpl_polynomial_set_coeff(distor_poly, power,
610 cpl_polynomial_get_coeff(distor_poly_flipped, power_flipped));
611
612 power[0] = 0; power[1] = 1; power_flipped[0] = 1; power_flipped[1] = 0;
613 cpl_polynomial_set_coeff(distor_poly, power,
614 cpl_polynomial_get_coeff(distor_poly_flipped, power_flipped));
615
616 power[0] = 0; power[1] = 2; power_flipped[0] = 2; power_flipped[1] = 0;
617 cpl_polynomial_set_coeff(distor_poly, power,
618 cpl_polynomial_get_coeff(distor_poly_flipped, power_flipped));
619 cpl_polynomial_delete(distor_poly_flipped);
620
621 /* Distortion correction */
622 cpl_msg_info(cpl_func, "Correct the distortion");
623 cpl_msg_indent_more();
624 in_corr = cpl_image_duplicate(in);
625
626 /* Create the identity polynomial */
627 poly2d_id = cpl_polynomial_new(2);
628 power[0] = 1; power[1] = 0;
629 cpl_polynomial_set_coeff(poly2d_id, power, 1.0);
630
631 /* Create the kernel */
632 profile = cpl_vector_new(CPL_KERNEL_DEF_SAMPLES);
633 cpl_vector_fill_kernel_profile(profile, CPL_KERNEL_DEFAULT,
634 CPL_KERNEL_DEF_WIDTH);
635
636 /* Apply the distortion */
637 if (cpl_image_warp_polynomial(in_corr, in, poly2d_id, distor_poly,
638 profile, CPL_KERNEL_DEF_WIDTH, profile,
639 CPL_KERNEL_DEF_WIDTH) != CPL_ERROR_NONE) {
640 cpl_msg_error(cpl_func, "cannot correct the distortion");
641 cpl_image_delete(in_corr);
642 cpl_polynomial_delete(poly2d_id);
643 cpl_polynomial_delete(distor_poly);
644 cpl_vector_delete(profile);
645 cpl_msg_indent_less();
646 return NULL;
647 }
648 cpl_polynomial_delete(poly2d_id);
649 cpl_vector_delete(profile);
650 cpl_msg_indent_less();
651
652 /* Compute the FWHM of the detected arcs */
653 cpl_msg_info(cpl_func, "Compute the FWHM of the detected arcs");
654 /* Create the fwhms table */
655 *arcs_fwhm = cpl_table_new(cpl_apertures_get_size(arcs));
656 cpl_table_new_column(*arcs_fwhm, "POS", CPL_TYPE_DOUBLE);
657 cpl_table_new_column(*arcs_fwhm, "FWHM", CPL_TYPE_DOUBLE);
658 cpl_table_new_column(*arcs_fwhm, "FLUX", CPL_TYPE_DOUBLE);
659 /* Compute the fwhms */
660 sofi_spc_arc_config.fwhm_good = 0;
661 for (i=0; i<cpl_apertures_get_size(arcs); i++) {
662 cpl_table_set_double(*arcs_fwhm, "POS", i,
663 cpl_apertures_get_centroid_x(arcs, i+1));
664 cpl_table_set_double(*arcs_fwhm, "FLUX", i,
665 cpl_apertures_get_flux(arcs, i+1));
666 if (cpl_image_get_fwhm(in_corr, cpl_apertures_get_centroid_x(arcs, i+1),
667 512, &fwhm_x, &fwhm_y) != CPL_ERROR_NONE) {
668 cpl_msg_warning(cpl_func, "Cannot get the FWHM");
669 cpl_error_reset();
670 }
671 cpl_table_set_double(*arcs_fwhm, "FWHM", i, fwhm_x);
672 if (fwhm_x > 0) sofi_spc_arc_config.fwhm_good ++;
673 }
674 cpl_apertures_delete(arcs);
675
676 /* Compute the median of the good fwhms */
677 if (sofi_spc_arc_config.fwhm_good > 0) {
678 fwhm_valid = cpl_vector_new(sofi_spc_arc_config.fwhm_good);
679 sofi_spc_arc_config.fwhm_good = 0;
680 for (i=0; i<cpl_table_get_nrow(*arcs_fwhm); i++) {
681 fwhm_x = cpl_table_get_double(*arcs_fwhm, "FWHM", i, NULL);
682 if (fwhm_x > 0) {
683 cpl_vector_set(fwhm_valid, sofi_spc_arc_config.fwhm_good,
684 fwhm_x);
685 sofi_spc_arc_config.fwhm_good ++;
686 }
687 }
688 sofi_spc_arc_config.fwhm_med = cpl_vector_get_median_const(fwhm_valid);
689 cpl_vector_delete(fwhm_valid);
690 } else sofi_spc_arc_config.fwhm_med = 0.0;
691
692 /* Wavelength calibration */
693
694 /* Compute the slit_width */
695 if ((slit_width = sofi_get_slitwidth(in_name)) == -1) {
696 cpl_msg_error(cpl_func, "cannot get the slit width");
697 cpl_polynomial_delete(distor_poly);
698 cpl_image_delete(in_corr);
699 cpl_table_delete(*arcs_fwhm);
700 *arcs_fwhm = NULL;
701 return NULL;
702 }
703
704 /* First estimation */
705 cpl_msg_info(cpl_func, "Get the dispersion estimation");
706 cpl_msg_indent_more();
707 if ((phdisprel = sofi_get_disprel_estimate(in_name, 1)) == NULL) {
708 cpl_msg_error(cpl_func, "cannot estimate the dispersion relation");
709 cpl_polynomial_delete(distor_poly);
710 cpl_image_delete(in_corr);
711 cpl_table_delete(*arcs_fwhm);
712 *arcs_fwhm = NULL;
713 cpl_msg_indent_less();
714 return NULL;
715 }
716 power[0] = 0; power[1] = 1;
717 a = cpl_polynomial_get_coeff(phdisprel, power);
718 b = cpl_polynomial_get_coeff(phdisprel, power + 1);
719 cpl_msg_info(cpl_func, "f(x)=%g + %g*x", a, b);
720 cpl_msg_indent_less();
721
722 /* Compute the dispersion relation */
723 cpl_msg_info(cpl_func, "Compute the dispersion relation");
724 cpl_msg_indent_more();
725 if ((disprel = sofi_wavelength_engine(in_corr, lines_table, NULL, xe, ne,
726 phdisprel, slit_width, sofi_spc_arc_config.degree,
727 sofi_spc_arc_config.wl_err,
728 sofi_spc_arc_config.wl_nsamples,
729 sofi_spc_arc_config.ppm, sofi_spc_arc_config.display,
730 &xc)) == NULL) {
731 cpl_msg_error(cpl_func, "cannot compute the dispersion relation");
732 cpl_polynomial_delete(distor_poly);
733 cpl_image_delete(in_corr);
734 cpl_polynomial_delete(phdisprel);
735 cpl_table_delete(*arcs_fwhm);
736 *arcs_fwhm = NULL;
737 cpl_msg_indent_less();
738 return NULL;
739 }
740 if (sofi_spc_arc_config.out_corr) {
741 *out_corr = in_corr;
742 in_corr = NULL;
743 } else {
744 cpl_image_delete(in_corr);
745 }
746
747 /* Plot if requested */
748 if (sofi_spc_arc_config.display && sofi_spc_arc_config.lines != NULL &&
749 sofi_spc_arc_config.lines[0] != (char)0) {
750
751 cpl_bivector * lines_biv
752 = cpl_bivector_read(sofi_spc_arc_config.lines);
753 const int nlines = cpl_bivector_get_size(lines_biv);
754
755 if (nlines > sofi_spc_arc_config.degree) {
756
757 /* Compute the solution from the passed associated lines */
758 cpl_matrix * xpos
759 = cpl_matrix_wrap(1, nlines, cpl_bivector_get_x_data(lines_biv));
760 cpl_polynomial * poly_sol = cpl_polynomial_new(1);
761
762 if (!cpl_polynomial_fit(poly_sol, xpos, NULL,
763 cpl_bivector_get_y(lines_biv), NULL,
764 CPL_FALSE, NULL,
765 &(sofi_spc_arc_config.degree))) {
766 irplib_wlxcorr_plot_solution(phdisprel, disprel, poly_sol, 1,
767 1024);
768 }
769 (void)cpl_matrix_unwrap(xpos);
770 cpl_polynomial_delete(poly_sol);
771 }
772 cpl_bivector_delete(lines_biv);
773 }
774 cpl_polynomial_delete(phdisprel);
775 cpl_msg_info(cpl_func, "Cross correlation factor: %g", xc);
776 power[0] = 0; power[1] = 1; power[2] = 2; power[3] = 3; power[4] = 4;
777 a = b = c = d = e = 0.0;
778 degree = cpl_polynomial_get_degree(disprel);
779 a = cpl_polynomial_get_coeff(disprel, power);
780 if (degree > 0) b = cpl_polynomial_get_coeff(disprel, power + 1);
781 if (degree > 1) c = cpl_polynomial_get_coeff(disprel, power + 2);
782 if (degree > 2) d = cpl_polynomial_get_coeff(disprel, power + 3);
783 if (degree > 3) e = cpl_polynomial_get_coeff(disprel, power + 4);
784 cpl_polynomial_delete(disprel);
785 if (degree == 0)
786 cpl_msg_info(cpl_func, "f(x)=%g", a);
787 if (degree == 1)
788 cpl_msg_info(cpl_func, "f(x)=%g + %g*x", a, b);
789 if (degree == 2)
790 cpl_msg_info(cpl_func, "f(x)=%g + %g*x + %g*x^2", a, b, c);
791 if (degree == 3)
792 cpl_msg_info(cpl_func, "f(x)=%g + %g*x + %g*x^2 + %g*x^3", a, b, c, d);
793 if (degree == 4)
794 cpl_msg_info(cpl_func, "f(x)=%g + %g*x + %g*x^2 + %g*x^3 + %g*x^4",
795 a, b, c, d, e);
796 cpl_msg_indent_less();
797
798 /* Create the output table and store the relevant information */
799 out_tab = cpl_table_new(6);
800
801 /* Fill distortion polynomial */
802 cpl_table_new_column(out_tab, "Degree_of_x", CPL_TYPE_INT);
803 cpl_table_new_column(out_tab, "Degree_of_y", CPL_TYPE_INT);
804 cpl_table_new_column(out_tab, "poly2d_coef", CPL_TYPE_DOUBLE);
805 power[0] = 0; power[1] = 0;
806 cpl_table_set_int(out_tab, "Degree_of_x", 0, power[0]);
807 cpl_table_set_int(out_tab, "Degree_of_y", 0, power[1]);
808 cpl_table_set_double(out_tab, "poly2d_coef", 0,
809 cpl_polynomial_get_coeff(distor_poly, power));
810 power[0] = 1; power[1] = 0;
811 cpl_table_set_int(out_tab, "Degree_of_x", 1, power[0]);
812 cpl_table_set_int(out_tab, "Degree_of_y", 1, power[1]);
813 cpl_table_set_double(out_tab, "poly2d_coef", 1,
814 cpl_polynomial_get_coeff(distor_poly, power));
815 power[0] = 0; power[1] = 1;
816 cpl_table_set_int(out_tab, "Degree_of_x", 2, power[0]);
817 cpl_table_set_int(out_tab, "Degree_of_y", 2, power[1]);
818 cpl_table_set_double(out_tab, "poly2d_coef", 2,
819 cpl_polynomial_get_coeff(distor_poly, power));
820 power[0] = 1; power[1] = 1;
821 cpl_table_set_int(out_tab, "Degree_of_x", 3, power[0]);
822 cpl_table_set_int(out_tab, "Degree_of_y", 3, power[1]);
823 cpl_table_set_double(out_tab, "poly2d_coef", 3,
824 cpl_polynomial_get_coeff(distor_poly, power));
825 power[0] = 2; power[1] = 0;
826 cpl_table_set_int(out_tab, "Degree_of_x", 4, power[0]);
827 cpl_table_set_int(out_tab, "Degree_of_y", 4, power[1]);
828 cpl_table_set_double(out_tab, "poly2d_coef", 4,
829 cpl_polynomial_get_coeff(distor_poly, power));
830 power[0] = 0; power[1] = 2;
831 cpl_table_set_int(out_tab, "Degree_of_x", 5, power[0]);
832 cpl_table_set_int(out_tab, "Degree_of_y", 5, power[1]);
833 cpl_table_set_double(out_tab, "poly2d_coef", 5,
834 cpl_polynomial_get_coeff(distor_poly, power));
835
836 /* Fill dispersion relation */
837 cpl_table_new_column(out_tab, "WL_coefficients", CPL_TYPE_DOUBLE);
838 cpl_table_set_double(out_tab, "WL_coefficients", 0, a);
839 cpl_table_set_double(out_tab, "WL_coefficients", 1, b);
840 cpl_table_set_double(out_tab, "WL_coefficients", 2, c);
841 cpl_table_set_double(out_tab, "WL_coefficients", 3, d);
842 cpl_table_set_double(out_tab, "WL_coefficients", 4, e);
843 cpl_table_set_double(out_tab, "WL_coefficients", 5, 0.0);
844 sofi_spc_arc_config.disprel_cc = xc;
845
846 /* Free and return */
847 cpl_polynomial_delete(distor_poly);
848 return out_tab;
849}
850
851/*----------------------------------------------------------------------------*/
863/*----------------------------------------------------------------------------*/
864static cpl_error_code sofi_spc_arc_save(cpl_frameset * set_tot,
865 const cpl_table * tab,
866 const cpl_table * fwhms,
867 const cpl_image * corr,
868 const char * lines_table,
869 const cpl_frameset * set,
870 const cpl_parameterlist * parlist)
871{
872 cpl_propertylist * plist;
873 cpl_propertylist * qclist;
874 cpl_propertylist * paflist;
875 const cpl_frame * ref_frame;
876 const char * sval;
877 char qc_str[128];
878 char * filename;
879 int i;
880
881 /* Get the QC params in qclist */
882 qclist = cpl_propertylist_new();
883
884 /* Get the reference frame */
885 ref_frame = irplib_frameset_get_first_from_group(set, CPL_FRAME_GROUP_RAW);
886 if ((plist=cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
887 0)) == NULL) {
888 cpl_msg_error(cpl_func, "getting header from reference frame");
889 cpl_propertylist_delete(qclist);
890 return cpl_error_set_where(cpl_func);
891 }
892 /* Test the status */
893 if (cpl_error_get_code()) {
894 cpl_propertylist_delete(qclist);
895 cpl_propertylist_delete(plist);
896 return cpl_error_set_where(cpl_func);
897 }
898 sval = sofi_pfits_get_filter(plist);
899 if (cpl_error_get_code()) cpl_error_reset();
900 else cpl_propertylist_append_string(qclist, "ESO QC FILTER OBS", sval);
901 cpl_propertylist_delete(plist);
902 cpl_propertylist_append_string(qclist, "ESO QC LAMP", lines_table);
903 cpl_propertylist_append_double(qclist, "ESO QC DISP XCORR",
904 sofi_spc_arc_config.disprel_cc);
905 cpl_propertylist_append_double(qclist, "ESO QC DISPCO1",
906 cpl_table_get_double(tab, "WL_coefficients", 0, NULL));
907 cpl_propertylist_append_double(qclist, "ESO QC DISPCO2",
908 cpl_table_get_double(tab, "WL_coefficients", 1, NULL));
909 cpl_propertylist_append_double(qclist, "ESO QC DISPCO3",
910 cpl_table_get_double(tab, "WL_coefficients", 2, NULL));
911 cpl_propertylist_append_double(qclist, "ESO QC DISPCO4",
912 cpl_table_get_double(tab, "WL_coefficients", 3, NULL));
913 cpl_propertylist_append_double(qclist, "ESO QC DISPCO5",
914 cpl_table_get_double(tab, "WL_coefficients", 4, NULL));
915 cpl_propertylist_append_double(qclist, "ESO QC DIST1",
916 cpl_table_get_double(tab, "poly2d_coef", 0, NULL));
917 cpl_propertylist_append_double(qclist, "ESO QC DISTX",
918 cpl_table_get_double(tab, "poly2d_coef", 1, NULL));
919 cpl_propertylist_append_double(qclist, "ESO QC DISTY",
920 cpl_table_get_double(tab, "poly2d_coef", 2, NULL));
921 cpl_propertylist_append_double(qclist, "ESO QC DISTXY",
922 cpl_table_get_double(tab, "poly2d_coef", 3, NULL));
923 cpl_propertylist_append_double(qclist, "ESO QC DISTXX",
924 cpl_table_get_double(tab, "poly2d_coef", 4, NULL));
925 cpl_propertylist_append_double(qclist, "ESO QC DISTYY",
926 cpl_table_get_double(tab, "poly2d_coef", 5, NULL));
927 cpl_propertylist_append_int(qclist, "ESO QC SATUR NBPIX",
928 sofi_spc_arc_config.nb_saturated);
929 cpl_propertylist_append_double(qclist, "ESO QC WLEN",
930 (double)(cpl_table_get_double(tab, "WL_coefficients", 0, NULL) +
931 512.0*cpl_table_get_double(tab, "WL_coefficients", 1, NULL) +
932 512.0*512.0*cpl_table_get_double(tab, "WL_coefficients", 2, NULL) +
933 512.0*512.0*512.0*cpl_table_get_double(tab, "WL_coefficients", 3, NULL) +
934512.0*512.0*512.0*512.0*cpl_table_get_double(tab, "WL_coefficients", 4, NULL)));
935
936 if (fwhms) {
937 cpl_propertylist_append_int(qclist, "ESO QC ARCS NUM",
938 cpl_table_get_nrow(fwhms));
939 for(i=0; i<cpl_table_get_nrow(fwhms); i++) {
940 sprintf(qc_str, "ESO QC ARCS%d XPOS", i+1);
941 cpl_propertylist_append_double(qclist, qc_str,
942 cpl_table_get_double(fwhms, "POS", i, NULL));
943 sprintf(qc_str, "ESO QC ARCS%d FWHM", i+1);
944 cpl_propertylist_append_double(qclist, qc_str,
945 cpl_table_get_double(fwhms, "FWHM", i, NULL));
946 sprintf(qc_str, "ESO QC ARCS%d FLUX", i+1);
947 cpl_propertylist_append_double(qclist, qc_str,
948 cpl_table_get_double(fwhms, "FLUX", i, NULL));
949 }
950 cpl_propertylist_append_int(qclist, "ESO QC ARCS NUMGOOD",
951 sofi_spc_arc_config.fwhm_good);
952 cpl_propertylist_append_double(qclist, "ESO QC FWHM MED",
953 sofi_spc_arc_config.fwhm_med);
954 }
955
956 /* Write the arc table */
957 filename = cpl_sprintf("sofi_spc_arc_set%d_frame%d.fits",
958 sofi_spc_arc_config.set_nb, sofi_spc_arc_config.frame_nb);
959 irplib_dfs_save_table(set_tot,
960 parlist,
961 set,
962 tab,
963 NULL,
964 "sofi_spc_arc",
965 SOFI_SPC_ARC_RES,
966 qclist,
967 NULL,
968 PACKAGE "/" PACKAGE_VERSION,
969 filename);
970 cpl_free(filename);
971
972 /* Write the corrected image */
973 if (corr) {
974 filename = cpl_sprintf("sofi_spc_arc_set%d_frame%d_corr.fits",
975 sofi_spc_arc_config.set_nb, sofi_spc_arc_config.frame_nb);
976 irplib_dfs_save_image(set_tot,
977 parlist,
978 set,
979 corr,
980 CPL_BPP_IEEE_FLOAT,
981 "sofi_spc_arc",
982 SOFI_SPC_ARC_CORR,
983 qclist,
984 NULL,
985 PACKAGE "/" PACKAGE_VERSION,
986 filename);
987 cpl_free(filename);
988 }
989
990 /* Get the reference frame */
991 ref_frame = irplib_frameset_get_first_from_group(set, CPL_FRAME_GROUP_RAW);
992
993 /* Get FITS header from reference file */
994 if ((plist=cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
995 0)) == NULL) {
996 cpl_msg_error(cpl_func, "getting header from reference frame");
997 cpl_propertylist_delete(qclist);
998 return cpl_error_set_where(cpl_func);
999 }
1000
1001 /* Get the keywords for the paf file */
1002 paflist = cpl_propertylist_new();
1003 cpl_propertylist_copy_property_regexp(paflist, plist,
1004 "^(ARCFILE|MJD-OBS|INSTRUME|ESO TPL ID|ESO TPL NEXP|ESO DPR CATG|"
1005 "ESO DPR TECH|ESO DPR TYPE|DATE-OBS|ESO INS GRAT NAME|"
1006 "ESO INS GRAT WLEN|ESO INS GRAT ORDER|ESO INS MODE|"
1007 "ESO INS OPTI1 ID)$", 0);
1008 cpl_propertylist_delete(plist);
1009
1010 /* Copy the QC in paflist */
1011 cpl_propertylist_copy_property_regexp(paflist, qclist, ".", 0);
1012 cpl_propertylist_delete(qclist);
1013
1014 /* Save the PAF file */
1015 filename = cpl_sprintf("sofi_spc_arc_set%d_frame%d.paf",
1016 sofi_spc_arc_config.set_nb, sofi_spc_arc_config.frame_nb);
1017 cpl_dfs_save_paf("SOFI",
1018 "sofi_spc_arc",
1019 paflist,
1020 filename);
1021 cpl_free(filename);
1022 cpl_propertylist_delete(paflist);
1023
1024 return cpl_error_get_code();
1025}
1026
1027/*----------------------------------------------------------------------------*/
1034/*----------------------------------------------------------------------------*/
1035static int sofi_spc_arc_compare(
1036 const cpl_frame * frame1,
1037 const cpl_frame * frame2)
1038{
1039 int comparison;
1040 cpl_propertylist * plist1;
1041 cpl_propertylist * plist2;
1042 const char * sval1,
1043 * sval2;
1044
1045 /* Test entries */
1046 if (frame1==NULL || frame2==NULL) return CPL_ERROR_UNSPECIFIED;
1047
1048 /* Get property lists */
1049 if ((plist1=cpl_propertylist_load(cpl_frame_get_filename(frame1),
1050 0)) == NULL) {
1051 cpl_msg_error(cpl_func, "getting header from reference frame");
1052 return CPL_ERROR_UNSPECIFIED;
1053 }
1054 if ((plist2=cpl_propertylist_load(cpl_frame_get_filename(frame2),
1055 0)) == NULL) {
1056 cpl_msg_error(cpl_func, "getting header from reference frame");
1057 cpl_propertylist_delete(plist1);
1058 return CPL_ERROR_UNSPECIFIED;
1059 }
1060
1061 /* Test status */
1062 if (cpl_error_get_code()) {
1063 cpl_propertylist_delete(plist1);
1064 cpl_propertylist_delete(plist2);
1065 return CPL_ERROR_UNSPECIFIED;
1066 }
1067
1068 comparison = 1;
1069
1070 /* Compare the slit used */
1071 sval1 = sofi_pfits_get_opti1_id(plist1);
1072 sval2 = sofi_pfits_get_opti1_id(plist2);
1073 if (cpl_error_get_code()) {
1074 cpl_msg_error(cpl_func, "cannot get the slit used");
1075 cpl_propertylist_delete(plist1);
1076 cpl_propertylist_delete(plist2);
1077 return CPL_ERROR_UNSPECIFIED;
1078 }
1079 if (strcmp(sval1, sval2)) comparison = 0;
1080
1081 /* Compare the mode */
1082 sval1 = sofi_pfits_get_mode(plist1);
1083 sval2 = sofi_pfits_get_mode(plist2);
1084 if (cpl_error_get_code()) {
1085 cpl_msg_error(cpl_func, "cannot get the mode");
1086 cpl_propertylist_delete(plist1);
1087 cpl_propertylist_delete(plist2);
1088 return CPL_ERROR_UNSPECIFIED;
1089 }
1090 if (strcmp(sval1, sval2)) comparison = 0;
1091
1092 cpl_propertylist_delete(plist1);
1093 cpl_propertylist_delete(plist2);
1094 return comparison;
1095}
1096
1097/*----------------------------------------------------------------------------*/
1104/*----------------------------------------------------------------------------*/
1105static int * sofi_spc_arc_find_lamps(const cpl_frameset * fset)
1106{
1107 const int nframes = cpl_frameset_get_size(fset);
1108 int * lamps;
1109 int i;
1110
1111 cpl_ensure(nframes > 0, CPL_ERROR_UNSPECIFIED, NULL); /* A bug */
1112
1113 /* Allocate the output array */
1114 lamps = (int*)cpl_malloc(nframes * sizeof(int));
1115
1116 for (i=0; i<nframes; i++) {
1117 const cpl_frame * cur_frame = cpl_frameset_get_position_const(fset, i);
1118 cpl_propertylist * plist
1119 = cpl_propertylist_load(cpl_frame_get_filename(cur_frame), 0);
1120 const int xenon = sofi_is_xenon_lamp_active(plist);
1121 const int neon = sofi_is_neon_lamp_active(plist);
1122
1123 cpl_propertylist_delete(plist);
1124 if ((neon != 0 && neon != 1) || (xenon != 0 && xenon != 1)) {
1125 cpl_free(lamps);
1126 (void)cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
1127 "Cannot check which lamp is on for "
1128 "frame %d", i+1);
1129 return NULL;
1130 }
1131 if (xenon == 1) {
1132 if (neon == 1) lamps[i] = 3;
1133 else if (neon == 0) lamps[i] = 1;
1134 } else if (xenon == 0 ) {
1135 if (neon == 1) lamps[i] = 2;
1136 else if (neon == 0) lamps[i] = 0;
1137 }
1138 }
1139
1140 return lamps;
1141}
1142
1143/*----------------------------------------------------------------------------*/
1149/*----------------------------------------------------------------------------*/
1150static int sofi_is_neon_lamp_active(const cpl_propertylist * plist)
1151{
1152 int status;
1153 const char * lamp;
1154
1155 /* Test error */
1156 if (cpl_error_get_code()) return CPL_ERROR_UNSPECIFIED;
1157
1158 if ((lamp=sofi_pfits_get_lamp2_name(plist)) == NULL) {
1159 cpl_error_reset();
1160 return 0;
1161 }
1162 if (!strcmp(lamp, "Neon")) {
1163 status = sofi_pfits_get_lamp2_status(plist);
1164 if (cpl_error_get_code()) {
1165 cpl_error_reset();
1166 return 0;
1167 }
1168 if (status == 1) return 1;
1169 }
1170 return 0;
1171}
1172
1173/*----------------------------------------------------------------------------*/
1179/*----------------------------------------------------------------------------*/
1180static int sofi_is_xenon_lamp_active(const cpl_propertylist * plist)
1181{
1182 int status;
1183 const char * lamp;
1184
1185 /* Test error */
1186 if (cpl_error_get_code()) return CPL_ERROR_UNSPECIFIED;
1187
1188 if ((lamp=sofi_pfits_get_lamp1_name(plist)) == NULL) {
1189 cpl_error_reset();
1190 return 0;
1191 }
1192 if (!strcmp(lamp, "Xenon")) {
1193 status = sofi_pfits_get_lamp1_status(plist);
1194 if (cpl_error_get_code()) {
1195 cpl_error_reset();
1196 return 0;
1197 }
1198 if (status == 1) return 1;
1199 }
1200 return 0;
1201}
int sofi_dfs_set_groups(cpl_frameset *set)
Set the group as RAW or CALIB in a frameset.
Definition sofi_dfs.c:60
const char * sofi_pfits_get_opti1_id(const cpl_propertylist *plist)
find out the OPTI1.ID key
Definition sofi_pfits.c:424
const char * sofi_pfits_get_mode(const cpl_propertylist *plist)
find out the instrument mode
Definition sofi_pfits.c:351
const char * sofi_pfits_get_lamp2_name(const cpl_propertylist *plist)
find out the lamp2 name
Definition sofi_pfits.c:314
int sofi_pfits_get_lamp2_status(const cpl_propertylist *plist)
find out the lamp2 status
Definition sofi_pfits.c:327
const char * sofi_pfits_get_lamp1_name(const cpl_propertylist *plist)
find out the lamp1 name
Definition sofi_pfits.c:289
int sofi_pfits_get_lamp1_status(const cpl_propertylist *plist)
find out the lamp1 status
Definition sofi_pfits.c:302
const char * sofi_pfits_get_filter(const cpl_propertylist *plist)
find out which wave band is active in short wavelength
Definition sofi_pfits.c:243
cpl_frameset * sofi_extract_frameset(const cpl_frameset *in, const char *tag)
Extract the frames with the given tag from a frameset.
Definition sofi_utils.c:298
const char * sofi_extract_filename(const cpl_frameset *in, const char *tag)
Extract the filename ffor the first frame of the given tag.
Definition sofi_utils.c:342
cpl_polynomial * sofi_get_disprel_estimate(const char *filename, int poly_deg)
Estimate the instrument dispersion relation.
double sofi_get_slitwidth(const char *filename)
Find out the slit width.
cpl_polynomial * sofi_wavelength_engine(const cpl_image *in, const char *table_name, const char *oh, const char *xe, const char *ne, const cpl_polynomial *phdisprel, double slit_width, int degree, double wl_err, int nsamples, int use_ppm, int plot, double *xcorr)
Compute a dispersion relation.