IIINSTRUMENT Pipeline Reference Manual  6.2.2
isaac_spc_startrace.c
1 /* $Id: isaac_spc_startrace.c,v 1.51 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.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 <math.h>
37 #include <float.h>
38 #include <cpl.h>
39 
40 #include "irplib_plugin.h"
41 #include "irplib_utils.h"
42 #include "irplib_spectrum.h"
43 
44 #include "isaac_utils.h"
45 #include "isaac_pfits.h"
46 #include "isaac_dfs.h"
47 
48 /*-----------------------------------------------------------------------------
49  Define
50  -----------------------------------------------------------------------------*/
51 
52 #define RECIPE_STRING "isaac_spc_startrace"
53 
54 #define Z_LR_LEFT_REJ 300
55 #define Z_LR_RIGHT_REJ 325
56 #define SZ_LR_LEFT_REJ 300
57 #define SZ_LR_RIGHT_REJ 325
58 #define J_LR_LEFT_REJ 200
59 #define J_LR_RIGHT_REJ 200
60 #define SH_LR_LEFT_REJ 150
61 #define SH_LR_RIGHT_REJ 175
62 #define SK_LR_LEFT_REJ 150
63 #define SK_LR_RIGHT_REJ 175
64 #define MR_LEFT_REJ 30
65 #define MR_RIGHT_REJ 30
66 
67 /*-----------------------------------------------------------------------------
68  Functions prototypes
69  -----------------------------------------------------------------------------*/
70 
71 static cpl_error_code isaac_spc_startrace_reduce(cpl_frameset *,
72  const cpl_frameset *,
73  const cpl_matrix *, char,
74  const cpl_parameterlist *);
75 
76 static cpl_size * isaac_spc_startrace_resol(cpl_frameset *);
77 static cpl_imagelist * isaac_spc_startrace_load(const cpl_frameset *);
78 static cpl_matrix * isaac_spc_startrace_starpos(const cpl_frameset *);
79 static cpl_polynomial * isaac_spc_startrace_shape(cpl_image *, double, char,
80  double *);
81 static cpl_polynomial * isaac_spc_startrace_distor(cpl_polynomial **,
82  cpl_vector *, int, int);
83 static cpl_error_code isaac_spc_startrace_save(cpl_frameset *,
84  const cpl_table *,
85  const cpl_matrix *,
86  const cpl_vector *,
87  cpl_polynomial **,
88  const cpl_frameset *,
89  char,
90  const cpl_parameterlist *);
91 
92 
93 cpl_recipe_define(isaac_spc_startrace, ISAAC_BINARY_VERSION,
94  "Lars Lundin", PACKAGE_BUGREPORT, "2002, 2003, 2008",
95  "ISAAC Spectro startrace recipe",
96  RECIPE_STRING " -- ISAAC Spectro startrace recipe\n"
97  "The files listed in the Set Of Frames (sof-file) "
98  "must be tagged:\n"
99  "raw-file.fits "ISAAC_SPC_STARTRACE_IM_RAW" or\n"
100  "raw-file.fits "ISAAC_SPC_STARTRACE_SP_RAW"\n"
101  "Given N imaging frames, the spectro frames must consist of "
102  "N (or zero) low resolution frames and "
103  "N (or zero) medium resolution frames.");
104 
105 /*-----------------------------------------------------------------------------
106  Static variables
107  -----------------------------------------------------------------------------*/
108 
109 static struct {
110  /* Inputs */
111  cpl_size degree;
112  int spec_width;
113  int reject_left;
114  int reject_right;
115  int display;
116  /* Outputs */
117  int arm;
118  isaac_band band;
119  double corr_is1;
120  double corr_is2;
121  double corr_is3;
122  double shapes_fit_q;
123  double dist1;
124  double distx;
125  double disty;
126  double distxy;
127  double distxx;
128  double distyy;
129 } isaac_spc_startrace_config;
130 
131 /*-----------------------------------------------------------------------------
132  Functions code
133  -----------------------------------------------------------------------------*/
134 
135 /*----------------------------------------------------------------------------*/
143 /*----------------------------------------------------------------------------*/
144 static
145 cpl_error_code isaac_spc_startrace_fill_parameterlist(cpl_parameterlist * self)
146 {
147  const char * context = PACKAGE "." RECIPE_STRING;
148  cpl_error_code err;
149 
150  cpl_ensure_code(self, CPL_ERROR_NULL_INPUT);
151 
152  /* Fill the parameters list */
153 
154  /* --degree */
155  err = irplib_parameterlist_set_int(self, PACKAGE, RECIPE_STRING,
156  "degree", 3, "deg",
157  context, "polynomial degree");
158  cpl_ensure_code(!err, err);
159 
160  /* --spec_width */
161  err = irplib_parameterlist_set_int(self, PACKAGE, RECIPE_STRING,
162  "spectrum_width", 40, "spec_width",
163  context, "spectrum width");
164  cpl_ensure_code(!err, err);
165 
166  /* --reject_left */
167  err = irplib_parameterlist_set_int(self, PACKAGE, RECIPE_STRING,
168  "reject_left", -1, NULL,
169  context, "left part rejection");
170  cpl_ensure_code(!err, err);
171 
172  /* --reject_right */
173  err = irplib_parameterlist_set_int(self, PACKAGE, RECIPE_STRING,
174  "reject_right", -1, NULL,
175  context, "right part rejection");
176  cpl_ensure_code(!err, err);
177 
178  /* --display */
179  err = irplib_parameterlist_set_bool(self, PACKAGE, RECIPE_STRING,
180  "display", CPL_FALSE, NULL, context,
181  "Flag to make plots");
182  cpl_ensure_code(!err, err);
183 
184  return CPL_ERROR_NONE;
185 }
186 
187 
188 /*----------------------------------------------------------------------------*/
196 /*----------------------------------------------------------------------------*/
197 static int isaac_spc_startrace(cpl_frameset * framelist,
198  const cpl_parameterlist * parlist)
199 {
200  const char * sval;
201  cpl_size * labels = NULL;
202  const cpl_frame * cur_frame;
203  cpl_propertylist * plist = NULL;
204  cpl_frameset * imframes = NULL;
205  cpl_frameset * spframes = NULL;
206  cpl_frameset * spframes_lr = NULL;
207  cpl_frameset * spframes_mr = NULL;
208  cpl_matrix * star_pos = NULL;
209  int ndone = 0;
210 
211 
212  bug_if(0);
213 
214  /* Retrieve input parameters */
215 
216  /* Polynomial degree */
217  isaac_spc_startrace_config.degree
218  = irplib_parameterlist_get_int(parlist, PACKAGE, RECIPE_STRING,
219  "degree");
220  /* Spectrum width */
221  isaac_spc_startrace_config.spec_width
222  = irplib_parameterlist_get_int(parlist, PACKAGE, RECIPE_STRING,
223  "spectrum_width");
224  /* Rejection parameters */
225  isaac_spc_startrace_config.reject_left
226  = irplib_parameterlist_get_int(parlist, PACKAGE, RECIPE_STRING,
227  "reject_left");
228  isaac_spc_startrace_config.reject_right
229  = irplib_parameterlist_get_int(parlist, PACKAGE, RECIPE_STRING,
230  "reject_right");
231  /* Display */
232  isaac_spc_startrace_config.display
233  = irplib_parameterlist_get_bool(parlist, PACKAGE, RECIPE_STRING,
234  "display");
235 
236  /* Identify the RAW and CALIB frames in the input frameset */
237  skip_if (isaac_dfs_set_groups(framelist));
238 
239  /* Get the arm used (SW or LW) */
240  cur_frame = cpl_frameset_get_position_const(framelist,0);
241  error_if(cur_frame == NULL, CPL_ERROR_DATA_NOT_FOUND,
242  "Could not get 1st frame from frameset");
243  plist = cpl_propertylist_load(cpl_frame_get_filename(cur_frame), 0);
244  any_if("Could not load propertylist from 1st frame");
245 
246  sval = isaac_pfits_get_arm(plist);
247  any_if("Could not get the arm");
248 
249  if (sval[0] == 'S') {
250  isaac_spc_startrace_config.arm = 1;
251  } else if (sval[0] == 'L') {
252  isaac_spc_startrace_config.arm = 2;
253  } else {
254  error_if(1, CPL_ERROR_UNSUPPORTED_MODE, "Unsupported arm: %s", sval);
255  }
256 
257  /* Get the band */
258  sval = isaac_pfits_get_filter(plist);
259  any_if("Could not get the filter");
260 
261  isaac_spc_startrace_config.band = isaac_get_bbfilter(sval);
262  any_if("Could not get the band");
263 
264  cpl_propertylist_empty(plist);
265 
266  /* Retrieve raw frames */
267  imframes = isaac_extract_frameset(framelist, ISAAC_SPC_STARTRACE_IM_RAW);
268  error_if(imframes == NULL, CPL_ERROR_DATA_NOT_FOUND, "Could not find the "
269  "imframes in the input list");
270 
271  spframes = isaac_extract_frameset(framelist, ISAAC_SPC_STARTRACE_SP_RAW);
272  error_if(spframes == NULL, CPL_ERROR_DATA_NOT_FOUND, "Could not find the "
273  "spframes in the input list");
274 
275  /* Separate LR and MR spectra */
276  labels = isaac_spc_startrace_resol(spframes);
277  error_if(labels == NULL, cpl_error_get_code(), "Could not differentiate "
278  "LR and MR");
279 
280  spframes_lr = cpl_frameset_extract(spframes, labels, 1);
281  spframes_mr = cpl_frameset_extract(spframes, labels, 2);
282  cpl_free(labels);
283  labels = NULL;
284 
285  /* Get the star positions */
286  cpl_msg_info(cpl_func, "Get the star positions");
287  star_pos = isaac_spc_startrace_starpos(imframes);
288  error_if(star_pos == NULL, cpl_error_get_code(), "Could not find star the "
289  "positions");
290 
291  cpl_frameset_delete(imframes);
292  imframes = NULL;
293 
294  error_if (spframes_lr == NULL && spframes_mr == NULL,
295  CPL_ERROR_UNSUPPORTED_MODE, "The %d spectro frames are not LR "
296  "nor MR", (int)cpl_frameset_get_size(spframes));
297  cpl_frameset_delete(spframes);
298  spframes = NULL;
299 
300  if (spframes_lr != NULL) {
301  cpl_errorstate prestate = cpl_errorstate_get();
302  /* Reduction in LR */
303  cpl_msg_info(cpl_func, "Reducing the LR spectra");
304  if (isaac_spc_startrace_reduce(framelist, spframes_lr, star_pos,
305  'L', parlist)) {
306  irplib_error_recover(prestate, "Could not reduce the LR spectra");
307  } else {
308  ndone++;
309  }
310  cpl_frameset_delete(spframes_lr);
311  spframes_lr = NULL;
312  }
313  if (spframes_mr != NULL) {
314  cpl_errorstate prestate = cpl_errorstate_get();
315  /* Reduction in MR */
316  cpl_msg_info(cpl_func, "Reducing the MR spectra");
317  if (isaac_spc_startrace_reduce(framelist, spframes_mr, star_pos,
318  'M', parlist)) {
319  irplib_error_recover(prestate, "Could not reduce the MR spectra");
320  } else {
321  ndone++;
322  }
323  cpl_frameset_delete(spframes_mr);
324  spframes_mr = NULL;
325  }
326 
327  error_if(!ndone, CPL_ERROR_ILLEGAL_INPUT, "Could not reduce the spectra");
328 
329  end_skip;
330 
331  cpl_free(labels);
332  cpl_propertylist_delete(plist);
333  cpl_frameset_delete(imframes);
334  cpl_frameset_delete(spframes);
335  cpl_frameset_delete(spframes_lr);
336  cpl_frameset_delete(spframes_mr);
337  cpl_matrix_delete(star_pos);
338 
339  return cpl_error_get_code();
340 }
341 
342 /*----------------------------------------------------------------------------*/
353 /*----------------------------------------------------------------------------*/
354 static
355 cpl_error_code isaac_spc_startrace_reduce(cpl_frameset * framelist,
356  const cpl_frameset * spframes,
357  const cpl_matrix * star_pos,
358  char resol,
359  const cpl_parameterlist * parlist)
360 {
361  /* Load the input images */
362  cpl_imagelist * ilist = isaac_spc_startrace_load(spframes);
363  const int nframes = cpl_frameset_get_size(spframes);
364  cpl_vector * spec_pos = cpl_vector_new(nframes);
365  double * pspec_pos = cpl_vector_get_data(spec_pos);
366  cpl_polynomial * corresp = cpl_polynomial_new(1);
367  cpl_polynomial ** shapes = cpl_calloc(nframes, sizeof(cpl_polynomial*));
368  cpl_vector * fit_q = cpl_vector_new(nframes);
369  double * pfit_q = cpl_vector_get_data(fit_q);
370  const int nx = cpl_image_get_size_x(cpl_imagelist_get(ilist, 0));
371  cpl_polynomial * distor = NULL;
372  cpl_table * out_tab = NULL;
373  cpl_size power[2];
374  const cpl_size maxdeg = 2;
375  cpl_size i;
376 
377  bug_if(0);
378  bug_if(framelist == NULL);
379  bug_if(star_pos == NULL);
380  bug_if(parlist == NULL);
381 
382  error_if(cpl_matrix_get_ncol(star_pos) != nframes,
383  CPL_ERROR_INCOMPATIBLE_INPUT, "Number of spectro frames (%d) "
384  "differ from number of star positions (%d)", nframes,
385  (int)cpl_matrix_get_ncol(star_pos));
386 
387  /* Find the spectra positions */
388  for (i=0; i<nframes; i++) {
389  const cpl_image * image = cpl_imagelist_get_const(ilist, i);
390  const double mean = cpl_image_get_mean(image);
391  const double min_bright = 20.0 * mean;
392 
393  error_if (irplib_spectrum_find_brightest(image, 0, NO_SHADOW,
394  min_bright, 0, &(pspec_pos[i])),
395  cpl_error_get_code(), "Could not detect spectrum in frame %d "
396  "of %d with mean flux=%g", (int)i+1, nframes, mean);
397  }
398 
399  /* Compute spectra / star correspondance */
400  error_if (cpl_polynomial_fit(corresp, star_pos, NULL, spec_pos, NULL,
401  CPL_FALSE, NULL, &maxdeg), cpl_error_get_code(),
402  "Could not fit a %d degree polynomial to the %d positions",
403  (int)maxdeg, nframes);
404 
405  /* Store the result coefficients */
406  i = 0;
407  isaac_spc_startrace_config.corr_is1 = cpl_polynomial_get_coeff(corresp, &i);
408  i = 1;
409  isaac_spc_startrace_config.corr_is2 = cpl_polynomial_get_coeff(corresp, &i);
410  i = 2;
411  isaac_spc_startrace_config.corr_is3 = cpl_polynomial_get_coeff(corresp, &i);
412  cpl_polynomial_delete(corresp);
413  corresp = NULL;
414 
415  /* Compute the spectra shapes */
416  for (i=0; i<nframes; i++) {
417  shapes[i] = isaac_spc_startrace_shape(cpl_imagelist_get(ilist, i),
418  cpl_vector_get(spec_pos, i),
419  resol,
420  &(pfit_q[i]));
421 
422  error_if (shapes[i] == NULL, cpl_error_get_code(), "Could not get the "
423  "shape of frame %d of %d", (int)i+1, nframes);
424 
425  cpl_msg_info(cpl_func, "Spectrum %d : Y = %g; Fit mse = %g", (int)i+1,
426  cpl_vector_get(spec_pos, i), pfit_q[i]);
427  }
428  isaac_spc_startrace_config.shapes_fit_q = cpl_vector_get_median_const(fit_q);
429  cpl_vector_delete(fit_q);
430  fit_q = NULL;
431  cpl_imagelist_delete(ilist);
432  ilist = NULL;
433 
434  /* Compute the 2d distortion */
435  distor = isaac_spc_startrace_distor(shapes, spec_pos, nframes, nx);
436  error_if (distor == NULL, cpl_error_get_code(), "Could not compute the "
437  "distortion");
438 
439  /* Create the table */
440  out_tab = cpl_table_new(6);
441  cpl_table_new_column(out_tab, "Degree_of_x", CPL_TYPE_INT);
442  cpl_table_new_column(out_tab, "Degree_of_y", CPL_TYPE_INT);
443  cpl_table_new_column(out_tab, "poly2d_coef", CPL_TYPE_DOUBLE);
444  power[0] = 0; power[1] = 0;
445  cpl_table_set_int(out_tab, "Degree_of_x", 0, power[0]);
446  cpl_table_set_int(out_tab, "Degree_of_y", 0, power[1]);
447  isaac_spc_startrace_config.dist1 = cpl_polynomial_get_coeff(distor, power);
448  cpl_table_set_double(out_tab, "poly2d_coef", 0,
449  isaac_spc_startrace_config.dist1);
450  power[0] = 1; power[1] = 0;
451  cpl_table_set_int(out_tab, "Degree_of_x", 1, power[0]);
452  cpl_table_set_int(out_tab, "Degree_of_y", 1, power[1]);
453  isaac_spc_startrace_config.distx = cpl_polynomial_get_coeff(distor, power);
454  cpl_table_set_double(out_tab, "poly2d_coef", 1,
455  isaac_spc_startrace_config.distx);
456  power[0] = 0; power[1] = 1;
457  cpl_table_set_int(out_tab, "Degree_of_x", 2, power[0]);
458  cpl_table_set_int(out_tab, "Degree_of_y", 2, power[1]);
459  isaac_spc_startrace_config.disty = cpl_polynomial_get_coeff(distor, power);
460  cpl_table_set_double(out_tab, "poly2d_coef", 2,
461  isaac_spc_startrace_config.disty);
462  power[0] = 1; power[1] = 1;
463  cpl_table_set_int(out_tab, "Degree_of_x", 3, power[0]);
464  cpl_table_set_int(out_tab, "Degree_of_y", 3, power[1]);
465  isaac_spc_startrace_config.distxy = cpl_polynomial_get_coeff(distor, power);
466  cpl_table_set_double(out_tab, "poly2d_coef", 3,
467  isaac_spc_startrace_config.distxy);
468  power[0] = 2; power[1] = 0;
469  cpl_table_set_int(out_tab, "Degree_of_x", 4, power[0]);
470  cpl_table_set_int(out_tab, "Degree_of_y", 4, power[1]);
471  isaac_spc_startrace_config.distxx = cpl_polynomial_get_coeff(distor, power);
472  cpl_table_set_double(out_tab, "poly2d_coef", 4,
473  isaac_spc_startrace_config.distxx);
474  power[0] = 0; power[1] = 2;
475  cpl_table_set_int(out_tab, "Degree_of_x", 5, power[0]);
476  cpl_table_set_int(out_tab, "Degree_of_y", 5, power[1]);
477  isaac_spc_startrace_config.distyy = cpl_polynomial_get_coeff(distor, power);
478  cpl_table_set_double(out_tab, "poly2d_coef", 5,
479  isaac_spc_startrace_config.distyy);
480 
481  cpl_polynomial_delete(distor);
482  distor = NULL;
483 
484  /* Display result */
485  cpl_msg_info(cpl_func,
486  "Distortion : Y(x,y) = a + bx + cy + dxy + exx + fyy");
487  cpl_msg_info(cpl_func, "a = %g", isaac_spc_startrace_config.dist1);
488  cpl_msg_info(cpl_func, "b = %g", isaac_spc_startrace_config.distx);
489  cpl_msg_info(cpl_func, "c = %g", isaac_spc_startrace_config.disty);
490  cpl_msg_info(cpl_func, "d = %g", isaac_spc_startrace_config.distxy);
491  cpl_msg_info(cpl_func, "e = %g", isaac_spc_startrace_config.distxx);
492  cpl_msg_info(cpl_func, "f = %g", isaac_spc_startrace_config.distyy);
493 
494  /* Write the product */
495  skip_if (isaac_spc_startrace_save(framelist, out_tab, star_pos, spec_pos,
496  shapes, spframes, resol, parlist));
497 
498  end_skip;
499 
500  cpl_polynomial_delete(distor);
501  cpl_vector_delete(fit_q);
502  cpl_polynomial_delete(corresp);
503  if (shapes != NULL) {
504  for (i = 0; i < nframes; i++) cpl_polynomial_delete(shapes[i]);
505  cpl_free(shapes);
506  }
507  cpl_vector_delete(spec_pos);
508  cpl_imagelist_delete(ilist);
509  cpl_table_delete(out_tab);
510 
511  return cpl_error_get_code();
512 }
513 
514 /*----------------------------------------------------------------------------*/
522 /*----------------------------------------------------------------------------*/
523 static cpl_size * isaac_spc_startrace_resol(cpl_frameset * spframes)
524 {
525  int nframes;
526  cpl_size * labels;
527  cpl_frame * cur_frame;
528  cpl_propertylist * plist;
529  const char * sval;
530  int i;
531 
532  /* Test entries */
533  if (spframes == NULL) return NULL;
534 
535  /* Initialise */
536  nframes = cpl_frameset_get_size(spframes);
537 
538  /* Create output array */
539  labels = (cpl_size*)cpl_malloc(nframes * sizeof(*labels));
540 
541  /* Loop on the frames */
542  for (i=0; i<nframes; i++) {
543  cur_frame = cpl_frameset_get_position(spframes, i);
544  plist=cpl_propertylist_load(cpl_frame_get_filename(cur_frame), 0);
545  /* Get the resolution */
546  if ((sval = isaac_pfits_get_resolution(plist)) == NULL) {
547  cpl_free(labels);
548  cpl_msg_error(cpl_func,"cannot get the resolution");
549  return NULL;
550  }
551  if (sval[0]=='L') labels[i] = 1;
552  else if (sval[0]=='M') labels[i] = 2;
553  else labels[i] = 0;
554  cpl_propertylist_delete(plist);
555  }
556  return labels;
557 }
558 
559 /*----------------------------------------------------------------------------*/
566 /*----------------------------------------------------------------------------*/
567 static cpl_matrix * isaac_spc_startrace_starpos(const cpl_frameset * imframes)
568 {
569  int nframes;
570  cpl_matrix * ypositions;
571  cpl_apertures * objects;
572  double * ypos;
573  cpl_imagelist * ilist;
574  int i;
575 
576  /* Test entries */
577  if (imframes == NULL) return NULL;
578 
579  /* Load the input images */
580  if ((ilist = isaac_spc_startrace_load(imframes)) == NULL) return NULL;
581 
582  /* Initialise */
583  nframes = cpl_frameset_get_size(imframes);
584 
585  /* Create bivector */
586  ypositions = cpl_matrix_new(1, nframes);
587  ypos = cpl_matrix_get_data(ypositions);
588 
589  /* Loop on the frames */
590  for (i=0; i<nframes; i++) {
591  double xpos;
592  if ((objects = cpl_apertures_extract_sigma(cpl_imagelist_get(ilist, i),
593  2.0)) == NULL) {
594  cpl_msg_error(cpl_func, "cannot detect any object");
595  cpl_matrix_delete(ypositions);
596  cpl_imagelist_delete(ilist);
597  return NULL;
598  }
599  cpl_apertures_sort_by_flux(objects);
600  xpos = cpl_apertures_get_centroid_x(objects, 1);
601  ypos[i] = cpl_apertures_get_centroid_y(objects, 1);
602  cpl_apertures_delete(objects);
603  cpl_msg_info(cpl_func, "Image %d: Position (%g, %g)", i+1,xpos, ypos[i]);
604  }
605  cpl_imagelist_delete(ilist);
606  return ypositions;
607 }
608 
609 /*----------------------------------------------------------------------------*/
616 /*----------------------------------------------------------------------------*/
617 static cpl_imagelist * isaac_spc_startrace_load(const cpl_frameset * inframes)
618 {
619  cpl_imagelist * ilist;
620  int nframes;
621  cpl_image * tmp_im;
622  int i;
623 
624  /* Test entries */
625  if (inframes == NULL) return NULL;
626 
627  /* Initialise */
628  nframes = cpl_frameset_get_size(inframes);
629 
630  /* Load the images */
631  if ((ilist = cpl_imagelist_load_frameset(inframes, CPL_TYPE_FLOAT, 1,
632  0)) == NULL) return NULL;
633 
634  /* In LW that's it */
635  if (isaac_spc_startrace_config.arm == 2) return ilist;
636 
637  /* In SW, the frames are subtracted to remove the background */
638  tmp_im = cpl_image_duplicate(cpl_imagelist_get(ilist, 0));
639  for (i=0; i<nframes-1; i++) {
640  if (cpl_image_subtract(cpl_imagelist_get(ilist, i),
641  cpl_imagelist_get(ilist, i+1)) != CPL_ERROR_NONE) {
642  cpl_msg_error(cpl_func, "cannot subtract images");
643  cpl_imagelist_delete(ilist);
644  cpl_image_delete(tmp_im);
645  return NULL;
646  }
647  }
648  /* Handle last frame */
649  if (cpl_image_subtract(cpl_imagelist_get(ilist, nframes-1),
650  tmp_im) != CPL_ERROR_NONE) {
651  cpl_msg_error(cpl_func, "cannot subtract images");
652  cpl_imagelist_delete(ilist);
653  cpl_image_delete(tmp_im);
654  return NULL;
655  }
656  cpl_image_delete(tmp_im);
657 
658  /* Set negative pixels to 0 */
659  cpl_imagelist_threshold(ilist, 0.0, DBL_MAX, 0.0, 0.0);
660 
661  return ilist;
662 }
663 
664 /*----------------------------------------------------------------------------*/
674 /*----------------------------------------------------------------------------*/
675 static cpl_polynomial * isaac_spc_startrace_shape(
676  cpl_image * in,
677  double ypos,
678  char resol,
679  double * fit_quality)
680 {
681  int reject_left, reject_right;
682  cpl_image * filtered;
683  int low_side, up_side;
684  cpl_mask * kernel;
685  cpl_matrix * fit_x;
686  cpl_vector * fit_y;
687  double * pfit_x;
688  double * pfit_y;
689  cpl_polynomial * fitted;
690  cpl_bivector * toplot;
691  int i;
692  int nsamples;
693  const cpl_boolean sampsym = CPL_TRUE; /* fit_x is symmetric */
694 
695  /* Check entries */
696  if ((in == NULL) || (ypos < 0) || (fit_quality == NULL)) return NULL;
697 
698  /* Initialise */
699  reject_left = isaac_spc_startrace_config.reject_left;
700  reject_right = isaac_spc_startrace_config.reject_right;
701  low_side = (int)(ypos - (isaac_spc_startrace_config.spec_width)/2);
702  up_side = low_side + isaac_spc_startrace_config.spec_width;
703 
704  /* Test spectrum position */
705  if ((low_side < 1) || (up_side > cpl_image_get_size_y(in))) {
706  cpl_msg_error(cpl_func, "spectrum too close to the image border");
707  return NULL;
708  }
709 
710  /* Get rejection parameters */
711  if (isaac_spc_startrace_config.arm == 1) {
712  /* SW */
713  if (reject_left < 0) {
714  if (resol == 'M') reject_left = MR_LEFT_REJ;
715  else if (resol == 'L') {
716  switch (isaac_spc_startrace_config.band) {
717  case ISAAC_BAND_Z: reject_left = Z_LR_LEFT_REJ; break;
718  case ISAAC_BAND_SZ: reject_left = SZ_LR_LEFT_REJ; break;
719  case ISAAC_BAND_JBLOCK:
720  case ISAAC_BAND_J: reject_left = J_LR_LEFT_REJ; break;
721  case ISAAC_BAND_SH: reject_left = SH_LR_LEFT_REJ; break;
722  case ISAAC_BAND_SK: reject_left = SK_LR_LEFT_REJ; break;
723  default:
724  cpl_msg_warning(cpl_func, "unsupported filter");
725  reject_left = 0;
726  break;
727  }
728  }
729  }
730  if (reject_right < 0) {
731  if (resol == 'M') reject_right = MR_RIGHT_REJ;
732  else if (resol == 'L') {
733  switch (isaac_spc_startrace_config.band) {
734  case ISAAC_BAND_Z: reject_right = Z_LR_RIGHT_REJ; break;
735  case ISAAC_BAND_SZ: reject_right = SZ_LR_RIGHT_REJ;break;
736  case ISAAC_BAND_JBLOCK:
737  case ISAAC_BAND_J: reject_right = J_LR_RIGHT_REJ; break;
738  case ISAAC_BAND_SH: reject_right = SH_LR_RIGHT_REJ;break;
739  case ISAAC_BAND_SK: reject_right = SK_LR_RIGHT_REJ;break;
740  default:
741  cpl_msg_warning(cpl_func, "unsupported filter");
742  reject_right = 0;
743  break;
744  }
745  }
746  }
747  } else if (isaac_spc_startrace_config.arm == 2) {
748  /* LW */
749  if (reject_left < 0) reject_left = 150;
750  if (reject_right < 0) reject_right = 150;
751 
752  } else {
753  cpl_msg_error(cpl_func, "Unrecognized mode - abort");
754  return NULL;
755  }
756 
757  /* Filter the image */
758  kernel = cpl_mask_new(3, 3);
759  cpl_mask_not(kernel);
760  filtered = cpl_image_new(cpl_image_get_size_x(in), cpl_image_get_size_y(in),
761  cpl_image_get_type(in));
762  if (cpl_image_filter_mask(filtered, in, kernel, CPL_FILTER_MEDIAN,
763  CPL_BORDER_FILTER)) {
764  cpl_msg_error(cpl_func, "cannot filter the image");
765  cpl_mask_delete(kernel);
766  return NULL;
767  }
768  cpl_mask_delete(kernel);
769 
770  /* Fill the vector to fit */
771  nsamples = cpl_image_get_size_x(in) - reject_right - reject_left;
772  fit_x = cpl_matrix_new(1, nsamples);
773  pfit_x = cpl_matrix_get_data(fit_x);
774  fit_y = cpl_vector_new(nsamples);
775  pfit_y = cpl_vector_get_data(fit_y);
776  for (i=0; i < nsamples; i++) {
777  pfit_x[i] = (double)(i+1+reject_left);
778  pfit_y[i] = cpl_image_get_centroid_y_window(filtered, i+1+reject_left,
779  low_side, i+1+reject_left, up_side);
780  }
781  cpl_image_delete(filtered);
782 
783  /* Apply the fit */
784  fitted = cpl_polynomial_new(1);
785  if (cpl_polynomial_fit(fitted, fit_x, &sampsym, fit_y, NULL, CPL_FALSE,
786  NULL, &(isaac_spc_startrace_config.degree))) {
787  cpl_msg_error(cpl_func, "cannot fit the shape");
788  cpl_polynomial_delete(fitted);
789  cpl_matrix_delete(fit_x);
790  cpl_vector_delete(fit_y);
791  return NULL;
792  }
793 
794  /* Display if requested */
795  if (isaac_spc_startrace_config.display) {
796  cpl_vector * vfit_x
797  = cpl_vector_wrap(nsamples, pfit_x);
798  toplot = cpl_bivector_wrap_vectors(vfit_x, fit_y);
799  cpl_plot_bivector(NULL, NULL, NULL, toplot);
800  cpl_bivector_unwrap_vectors(toplot);
801  (void)cpl_vector_unwrap(vfit_x);
802  }
803 
804  cpl_vector_fill_polynomial_fit_residual(fit_y, fit_y, NULL, fitted,
805  fit_x, NULL);
806  *fit_quality = cpl_vector_product(fit_y, fit_y) / nsamples;
807 
808  /* Display if requested */
809  if (isaac_spc_startrace_config.display) {
810  cpl_vector * vfit_x
811  = cpl_vector_wrap(nsamples, pfit_x);
812  toplot = cpl_bivector_wrap_vectors(vfit_x, fit_y);
813  for (i=0; i<nsamples; i++) {
814  pfit_y[i] = cpl_polynomial_eval_1d(fitted, pfit_x[i], NULL);
815  }
816  cpl_plot_bivector(NULL, NULL, NULL, toplot);
817  cpl_bivector_unwrap_vectors(toplot);
818  (void)cpl_vector_unwrap(vfit_x);
819  }
820 
821  /* Free and return */
822  cpl_matrix_delete(fit_x);
823  cpl_vector_delete(fit_y);
824  return fitted;
825 }
826 
827 /*----------------------------------------------------------------------------*/
837 /*----------------------------------------------------------------------------*/
838 static cpl_polynomial * isaac_spc_startrace_distor(
839  cpl_polynomial ** shapes,
840  cpl_vector * spec_pos,
841  int nshapes,
842  int nx)
843 {
844  cpl_polynomial * distor;
845  cpl_matrix * xy_vec;
846  double * x_data;
847  double * y_data;
848  cpl_vector * z_vec;
849  double * z_data;
850  int nb_xpoints, npoints;
851  int pos;
852  int i, j;
853  const cpl_size maxdeg = 2;
854 
855  /* Initialise */
856  nb_xpoints = 20;
857  npoints = nb_xpoints * nshapes;
858 
859  /* Prepare the surface */
860  xy_vec = cpl_matrix_new(2, npoints);
861  x_data = cpl_matrix_get_data(xy_vec);
862  y_data = x_data + npoints;
863  z_vec = cpl_vector_new(npoints);
864  z_data = cpl_vector_get_data(z_vec);
865  for (j=0; j<nshapes; j++) {
866  for (i=0; i<nb_xpoints; i++) {
867  pos = i + j*nb_xpoints;
868  x_data[pos] = nx * (i+1) / nb_xpoints;
869  y_data[pos] = cpl_vector_get(spec_pos, j);
870  z_data[pos] = cpl_polynomial_eval_1d(shapes[j], x_data[pos], NULL);
871  }
872  }
873 
874  /* Apply the fit */
875  distor = cpl_polynomial_new(2);
876  if (cpl_polynomial_fit(distor, xy_vec, NULL, z_vec, NULL, CPL_FALSE, NULL,
877  &maxdeg)) {
878  cpl_msg_error(cpl_func, "cannot fit the distortion");
879  cpl_matrix_delete(xy_vec);
880  cpl_vector_delete(z_vec);
881  cpl_polynomial_delete(distor);
882  return NULL;
883  }
884  cpl_matrix_delete(xy_vec);
885  cpl_vector_delete(z_vec);
886 
887  return distor;
888 }
889 
890 /*----------------------------------------------------------------------------*/
904 /*----------------------------------------------------------------------------*/
905 static
906 cpl_error_code isaac_spc_startrace_save(cpl_frameset * set_tot,
907  const cpl_table * tab,
908  const cpl_matrix * star_pos,
909  const cpl_vector * spec_pos,
910  cpl_polynomial ** shapes,
911  const cpl_frameset * set,
912  char resol,
913  const cpl_parameterlist * parlist)
914 {
915  cpl_propertylist * plist;
916  cpl_propertylist * qclist;
917  cpl_propertylist * paflist;
918  const cpl_frame * ref_frame;
919  char colname[128];
920  cpl_table * shapes_table;
921  cpl_table * pos_table;
922  const char * procatt;
923  const char * procat;
924  char * filename;
925  int i;
926 
927  /* Get the QC params in qclist */
928  qclist = cpl_propertylist_new();
929 
930  /* Add QC parameters */
931  cpl_propertylist_append_double(qclist, "ESO QC CORR_IS1",
932  isaac_spc_startrace_config.corr_is1);
933  cpl_propertylist_append_double(qclist, "ESO QC CORR_IS2",
934  isaac_spc_startrace_config.corr_is2);
935  cpl_propertylist_append_double(qclist, "ESO QC CORR_IS3",
936  isaac_spc_startrace_config.corr_is3);
937  cpl_propertylist_append_double(qclist, "ESO QC FITMSE",
938  isaac_spc_startrace_config.shapes_fit_q);
939  cpl_propertylist_append_double(qclist, "ESO QC DIST1",
940  isaac_spc_startrace_config.dist1);
941  cpl_propertylist_append_double(qclist, "ESO QC DISTX",
942  isaac_spc_startrace_config.distx);
943  cpl_propertylist_append_double(qclist, "ESO QC DISTY",
944  isaac_spc_startrace_config.disty);
945  cpl_propertylist_append_double(qclist, "ESO QC DISTXY",
946  isaac_spc_startrace_config.distxy);
947  cpl_propertylist_append_double(qclist, "ESO QC DISTXX",
948  isaac_spc_startrace_config.distxx);
949  cpl_propertylist_append_double(qclist, "ESO QC DISTYY",
950  isaac_spc_startrace_config.distyy);
951 
952  /* Write the distortion table */
953  procatt = isaac_spc_startrace_config.arm == 1
954  ? ISAAC_SPC_STARTRACE_SW_RES : ISAAC_SPC_STARTRACE_LW_RES;
955  filename = cpl_sprintf("isaac_spc_startrace_2dpoly_%cR.fits", resol);
956  irplib_dfs_save_table(set_tot,
957  parlist,
958  set,
959  tab,
960  NULL,
961  "isaac_spc_startrace",
962  procatt,
963  qclist,
964  NULL,
965  PACKAGE "/" PACKAGE_VERSION,
966  filename);
967  cpl_free(filename);
968 
969  /* Save the positions table */
970  pos_table = cpl_table_new(cpl_matrix_get_ncol(star_pos));
971 
972  /* star_pos is _not_ modified */
973  cpl_table_wrap_double(pos_table, cpl_matrix_get_data((cpl_matrix*)star_pos),
974  "Star_positions");
975  /* spec_pos is _not_ modified */
976  cpl_table_wrap_double(pos_table, cpl_vector_get_data((cpl_vector*)spec_pos),
977  "Spec_positions");
978 
979  procat = isaac_spc_startrace_config.arm == 1
980  ? ISAAC_SPC_STARTRACE_SW_POS : ISAAC_SPC_STARTRACE_LW_POS;
981  filename = cpl_sprintf("isaac_spc_startrace_positions_%cR.fits", resol);
982  irplib_dfs_save_table(set_tot,
983  parlist,
984  set,
985  tab,
986  NULL,
987  "isaac_spc_startrace",
988  procat,
989  qclist,
990  NULL,
991  PACKAGE "/" PACKAGE_VERSION,
992  filename);
993  cpl_free(filename);
994 
995  (void)cpl_table_unwrap(pos_table, "Star_positions");
996  (void)cpl_table_unwrap(pos_table, "Spec_positions");
997  cpl_table_delete(pos_table);
998 
999  /* Save the shapes table */
1000  shapes_table = cpl_table_new(isaac_spc_startrace_config.degree + 1);
1001  for (i=0; i<cpl_vector_get_size(spec_pos); i++) {
1002  sprintf(colname, "Spec_%d", i+1);
1003  cpl_table_new_column(shapes_table, colname, CPL_TYPE_DOUBLE);
1004  }
1005  for (i=0; i<cpl_vector_get_size(spec_pos); i++) {
1006  cpl_size j;
1007  sprintf(colname, "Spec_%d", i+1);
1008  for (j=0; j<isaac_spc_startrace_config.degree + 1; j++) {
1009  cpl_table_set_double(shapes_table, colname, j,
1010  cpl_polynomial_get_coeff(shapes[i], &j));
1011  }
1012  }
1013  procat = isaac_spc_startrace_config.arm == 1 ?
1014  ISAAC_SPC_STARTRACE_SW_SHAPE : ISAAC_SPC_STARTRACE_LW_SHAPE;
1015  filename = cpl_sprintf("isaac_spc_startrace_shapes_%cR.fits", resol);
1016  irplib_dfs_save_table(set_tot,
1017  parlist,
1018  set,
1019  tab,
1020  NULL,
1021  "isaac_spc_startrace",
1022  procat,
1023  qclist,
1024  NULL,
1025  PACKAGE "/" PACKAGE_VERSION,
1026  filename);
1027  cpl_free(filename);
1028  cpl_table_delete(shapes_table);
1029 
1030  /* Get the reference frame */
1031  ref_frame = irplib_frameset_get_first_from_group(set, CPL_FRAME_GROUP_RAW);
1032 
1033  /* Get FITS header from reference file */
1034  if ((plist=cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
1035  0)) == NULL) {
1036  cpl_msg_error(cpl_func, "getting header from reference frame");
1037  cpl_propertylist_delete(qclist);
1038  return CPL_ERROR_UNSPECIFIED;
1039  }
1040 
1041  /* Get the keywords for the paf file */
1042  paflist = cpl_propertylist_new();
1043  cpl_propertylist_copy_property_regexp(paflist, plist,
1044  "^(ARCFILE|MJD-OBS|INSTRUME|ESO TPL ID|ESO TPL NEXP|ESO DPR CATG|"
1045  "ESO DPR TECH|ESO DPR TYPE|DATE-OBS|ESO INS GRAT NAME|"
1046  "ESO OCS SELECT-ARM)$", 0);
1047  cpl_propertylist_delete(plist);
1048 
1049  /* Copy the QC in paflist */
1050  cpl_propertylist_copy_property_regexp(paflist, qclist, ".", 0);
1051  cpl_propertylist_delete(qclist);
1052 
1053  /* PRO.CATG */
1054  cpl_propertylist_update_string(paflist, CPL_DFS_PRO_CATG, procatt);
1055 
1056  /* Save the PAF file */
1057  filename = cpl_sprintf("isaac_spc_startrace_%cR.paf", resol);
1058  cpl_dfs_save_paf("ISAAC",
1059  "isaac_spc_startrace",
1060  paflist,
1061  filename);
1062  cpl_free(filename);
1063  cpl_propertylist_delete(paflist);
1064  return 0;
1065 }
1066 
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_arm(const cpl_propertylist *plist)
find out the arm which is active
Definition: isaac_pfits.c:106
const char * isaac_pfits_get_resolution(const cpl_propertylist *plist)
find out the resolution
Definition: isaac_pfits.c:775
const char * isaac_pfits_get_filter(const cpl_propertylist *plist)
find out the filter
Definition: isaac_pfits.c:880
isaac_band isaac_get_bbfilter(const char *f)
Get the broad band filter.
Definition: isaac_utils.c:144
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