IIINSTRUMENT Pipeline Reference Manual  1.5.13
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 
63 static 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);
68 static cpl_table * sofi_spc_arc_compute(const cpl_image *, const char *,
69  const char *, const char *, const char *, cpl_table **, cpl_image **);
70 static 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 *);
75 static int sofi_spc_arc_compare(const cpl_frame *, const cpl_frame *);
76 static int * sofi_spc_arc_find_lamps(const cpl_frameset *);
77 static int sofi_is_xenon_lamp_active(const cpl_propertylist *);
78 static int sofi_is_neon_lamp_active(const cpl_propertylist *);
79 
80 cpl_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 
94 static 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 /*----------------------------------------------------------------------------*/
129 static
130 cpl_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 /*----------------------------------------------------------------------------*/
212 static 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 /*----------------------------------------------------------------------------*/
347 static 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 /*----------------------------------------------------------------------------*/
531 static 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 /*----------------------------------------------------------------------------*/
864 static 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) +
934 512.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 /*----------------------------------------------------------------------------*/
1035 static 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 /*----------------------------------------------------------------------------*/
1105 static 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 /*----------------------------------------------------------------------------*/
1150 static 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 /*----------------------------------------------------------------------------*/
1180 static 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 }
sofi_pfits_get_opti1_id
const char * sofi_pfits_get_opti1_id(const cpl_propertylist *plist)
find out the OPTI1.ID key
Definition: sofi_pfits.c:424
sofi_pfits_get_lamp1_name
const char * sofi_pfits_get_lamp1_name(const cpl_propertylist *plist)
find out the lamp1 name
Definition: sofi_pfits.c:289
sofi_extract_frameset
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
sofi_dfs_set_groups
int sofi_dfs_set_groups(cpl_frameset *set)
Set the group as RAW or CALIB in a frameset.
Definition: sofi_dfs.c:60
sofi_pfits_get_lamp2_status
int sofi_pfits_get_lamp2_status(const cpl_propertylist *plist)
find out the lamp2 status
Definition: sofi_pfits.c:327
sofi_wavelength_engine
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.
Definition: sofi_wavelength.c:150
sofi_get_disprel_estimate
cpl_polynomial * sofi_get_disprel_estimate(const char *filename, int poly_deg)
Estimate the instrument dispersion relation.
Definition: sofi_wavelength.c:313
sofi_pfits_get_lamp1_status
int sofi_pfits_get_lamp1_status(const cpl_propertylist *plist)
find out the lamp1 status
Definition: sofi_pfits.c:302
sofi_pfits_get_mode
const char * sofi_pfits_get_mode(const cpl_propertylist *plist)
find out the instrument mode
Definition: sofi_pfits.c:351
sofi_pfits_get_lamp2_name
const char * sofi_pfits_get_lamp2_name(const cpl_propertylist *plist)
find out the lamp2 name
Definition: sofi_pfits.c:314
sofi_extract_filename
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
sofi_get_slitwidth
double sofi_get_slitwidth(const char *filename)
Find out the slit width.
Definition: sofi_wavelength.c:263
sofi_pfits_get_filter
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