UVES Pipeline Reference Manual  5.4.6
uves_wavecal_utils.c
1 /* *
2  * This file is part of the ESO UVES Pipeline *
3  * Copyright (C) 2004,2005 European Southern Observatory *
4  * *
5  * This library is free software; you can redistribute it and/or modify *
6  * it under the terms of the GNU General Public License as published by *
7  * the Free Software Foundation; either version 2 of the License, or *
8  * (at your option) any later version. *
9  * *
10  * This program is distributed in the hope that it will be useful, *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13  * GNU General Public License for more details. *
14  * *
15  * You should have received a copy of the GNU General Public License *
16  * along with this program; if not, write to the Free Software *
17  * Foundation, 51 Franklin St, Fifth Floor, Boston, MA 02111-1307 USA *
18  * */
19 
20 /*
21  * $Author: amodigli $
22  * $Date: 2010-09-24 09:32:10 $
23  * $Revision: 1.13 $
24  * $Name: not supported by cvs2svn $
25  * $Log: not supported by cvs2svn $
26  * Revision 1.11 2007/06/06 08:17:34 amodigli
27  * replace tab with 4 spaces
28  *
29  * Revision 1.10 2007/05/07 14:25:43 jmlarsen
30  * Changed formatting
31  *
32  * Revision 1.9 2007/03/05 10:43:16 jmlarsen
33  * Reject outliers based on line FWHM and fit residual
34  *
35  * Revision 1.8 2006/11/06 15:19:42 jmlarsen
36  * Removed unused include directives
37  *
38  * Revision 1.7 2006/10/10 11:20:11 jmlarsen
39  * Renamed line table columns to match MIDAS
40  *
41  * Revision 1.6 2006/07/14 12:52:57 jmlarsen
42  * Exported/renamed function find_nearest
43  *
44  * Revision 1.5 2006/06/06 08:40:25 jmlarsen
45  * Shortened max line length
46  *
47  * Revision 1.4 2006/06/01 14:43:17 jmlarsen
48  * Added missing documentation
49  *
50  * Revision 1.3 2006/04/21 12:29:30 jmlarsen
51  * Write QC parameters to line table
52  *
53  * Revision 1.2 2006/02/15 13:19:15 jmlarsen
54  * Reduced source code max. line length
55  *
56  * Revision 1.1 2006/02/03 07:46:30 jmlarsen
57  * Moved recipe implementations to ./uves directory
58  *
59  * Revision 1.3 2005/12/19 16:17:55 jmlarsen
60  * Replaced bool -> int
61  *
62  * Revision 1.2 2005/11/14 13:18:44 jmlarsen
63  * Minor update
64  *
65  * Revision 1.1 2005/11/11 13:18:54 jmlarsen
66  * Reorganized code, renamed source files
67  *
68  */
69 
70 #ifdef HAVE_CONFIG_H
71 # include <config.h>
72 #endif
73 
74 /*----------------------------------------------------------------------------*/
78 /*----------------------------------------------------------------------------*/
81 /*-----------------------------------------------------------------------------
82  Includes
83  -----------------------------------------------------------------------------*/
84 
85 #include <uves_wavecal_utils.h>
86 #include <uves_utils.h>
87 #include <uves_utils_wrappers.h>
88 #include <uves_error.h>
89 #include <uves_msg.h>
90 
91 #include <cpl.h>
92 
93 /*-----------------------------------------------------------------------------
94  Functions prototypes
95  -----------------------------------------------------------------------------*/
96 
97 /*-----------------------------------------------------------------------------
98  Implementation
99  -----------------------------------------------------------------------------*/
100 /*----------------------------------------------------------------------------*/
108 /*----------------------------------------------------------------------------*/
109 
110 lt_type *uves_lt_new(int windows, int traces)
111 {
112  /* Allocate all line tables for this chip */
113  lt_type *lt = cpl_malloc(sizeof(lt_type));
114 
115  assure_mem( lt );
116 
117  lt->windows = windows;
118  lt->traces = traces;
119 
120  /* Initialize pointer to NULL */
121  lt->table = cpl_calloc(windows*traces, sizeof(cpl_table *));
122  lt->dispersion_relation = cpl_calloc(windows*traces, sizeof(polynomial *));
123  lt->absolute_order = cpl_calloc(windows*traces, sizeof(polynomial *));
124  lt->first_absolute_order = cpl_calloc(windows*traces, sizeof(int));
125  lt->last_absolute_order = cpl_calloc(windows*traces, sizeof(int));
126 
127  cleanup:
128  return lt;
129 }
130 
131 /*----------------------------------------------------------------------------*/
136 /*----------------------------------------------------------------------------*/
137 
139 {
140  if (lt != NULL && *lt != NULL)
141  {
142  int i;
143  for (i = 0; i < (*lt)->windows * (*lt)->traces; i++)
144  {
145  uves_free_table (&((*lt)->table[i]));
146  uves_polynomial_delete(&((*lt)->dispersion_relation[i]));
147  uves_polynomial_delete(&((*lt)->absolute_order[i]));
148  }
149 
150  cpl_free((*lt)->table);
151  cpl_free((*lt)->dispersion_relation);
152  cpl_free((*lt)->absolute_order);
153  cpl_free((*lt)->first_absolute_order);
154  cpl_free((*lt)->last_absolute_order);
155 
156  cpl_free(*lt);
157  }
158 
159  return;
160 }
161 
162 /*----------------------------------------------------------------------------*/
170 /*----------------------------------------------------------------------------*/
171 cpl_table **
172 uves_lt_get_table(const lt_type *lt, int window, int trace)
173 {
174  return &(lt->table[trace + (window-1)*lt->traces]);
175 }
176 
177 /*----------------------------------------------------------------------------*/
185 /*----------------------------------------------------------------------------*/
186 polynomial **
187 uves_lt_get_disprel(const lt_type *lt, int window, int trace)
188 {
189  return &(lt->dispersion_relation[trace + (window-1)*lt->traces]);
190 }
191 /*----------------------------------------------------------------------------*/
199 /*----------------------------------------------------------------------------*/
200 polynomial **
201 uves_lt_get_absord(const lt_type *lt, int window, int trace)
202 {
203  return &(lt->absolute_order[trace + (window-1)*lt->traces]);
204 }
205 /*----------------------------------------------------------------------------*/
213 /*----------------------------------------------------------------------------*/
214 int *
215 uves_lt_get_firstabs(const lt_type *lt, int window, int trace)
216 {
217  return &(lt->first_absolute_order[trace + (window-1)*lt->traces]);
218 }
219 /*----------------------------------------------------------------------------*/
227 /*----------------------------------------------------------------------------*/
228 int *
229 uves_lt_get_lastabs(const lt_type *lt, int window, int trace)
230 {
231  return &(lt->last_absolute_order[trace + (window-1)*lt->traces]);
232 }
233 
234 /*----------------------------------------------------------------------------*/
250 /*----------------------------------------------------------------------------*/
251 int
252 uves_wavecal_find_nearest(const cpl_table *line_refer, double lambda, int lo, int hi)
253 {
254  if (lo == hi) /* One-row interval */
255  {
256  return lo;
257  }
258  else if (lo + 1 == hi)
259  { /* Two-row interval */
260  double llo, lhi;
261  lhi = cpl_table_get_double(line_refer, "Wave", hi, NULL);
262  llo = cpl_table_get_double(line_refer, "Wave", lo, NULL);
263 
264  /* Return the one of 'llo' and 'lhi' that is closest to 'lambda' */
265  return ((llo-lambda)*(llo-lambda) < (lhi-lambda)*(lhi-lambda)) ? lo : hi;
266  }
267  else
268  { /* Three or more rows to consider */
269  double lmid;
270  int mid = (lo + hi)/2;
271  /* mid is different from both 'lo' and 'hi', so this will terminate */
272 
273  lmid = cpl_table_get_double(line_refer, "Wave", mid, NULL);
274 
275  if (lmid < lambda)
276  {
277  return uves_wavecal_find_nearest(line_refer, lambda, mid, hi);
278  }
279  else
280  {
281  return uves_wavecal_find_nearest(line_refer, lambda, lo, mid);
282  }
283  }
284 }
285 
286 
287 /*----------------------------------------------------------------------------*/
302 /*----------------------------------------------------------------------------*/
303 int
304 uves_delete_bad_lines(cpl_table *table, double TOLERANCE, double kappa)
305 {
306  int result = 0;
307  int numb_lines = cpl_table_get_nrow(table);
308 
309  /* Delete rows with invalid 'Ident' (and therefore invalid 'Residual_xxx') */
310  check( uves_erase_invalid_table_rows(table, "Ident"),
311  "Error erasing un-identified lines");
312 
313  assure( cpl_table_has_column(table, "Residual_pix"),
314  CPL_ERROR_DATA_NOT_FOUND,
315  "Missing column 'Residual_pix'");
316 
317  assure( cpl_table_has_column(table, LINETAB_RESIDUAL),
318  CPL_ERROR_DATA_NOT_FOUND,
319  "Missing column '" LINETAB_RESIDUAL "'");
320 
321  if (TOLERANCE > 0)
322  {
323  /* Pixel units */
324  check(( uves_erase_table_rows(table, /* > tol */
325  "Residual_pix", CPL_GREATER_THAN, TOLERANCE),
326  uves_erase_table_rows(table, /* < -tol */
327  "Residual_pix", CPL_LESS_THAN , -TOLERANCE)),
328  "Error removing rows");
329  }
330  else
331  {
332  /* Wavelength units */
333  check(( uves_erase_table_rows(table, /* > |tol| */
334  LINETAB_RESIDUAL, CPL_GREATER_THAN, -TOLERANCE),
335  uves_erase_table_rows(table, /* < -|tol| */
336  LINETAB_RESIDUAL, CPL_LESS_THAN , TOLERANCE)),
337  "Error removing rows");
338  }
339 
340 
341  /* Also reject outliers (if more than 2 points)
342  by kappa sigma clipping */
343 
344  if (cpl_table_get_nrow(table) - cpl_table_count_invalid(table, "Residual_pix") >= 2)
345  {
347  "Residual_pix", "temp",
348  kappa));
349 
351  "Xwidth", "temp",
352  kappa));
353 
354 
355  /* Don't do this:
356  the same is achieved by detecting fewer
357  lines from the start
358  check_nomsg( uves_erase_table_rows(table,
359  "Peak",
360  CPL_LESS_THAN,
361  0.5 *
362  cpl_table_get_column_median(table, "Peak")));
363  */
364  }
365 
366  result = numb_lines - cpl_table_get_nrow(table);
367 
368  cleanup:
369  return result;
370 }
371 
372 /*----------------------------------------------------------------------------*/
402 /*----------------------------------------------------------------------------*/
403 cpl_error_code
404 uves_draw_lines(cpl_image *image, polynomial *dispersion,
405  const polynomial *order_locations, const cpl_table *t,
406  const char *lambda_column, const char *abs_order,
407  const int *relative_order, int minorder, int maxorder,
408  bool vertical, int offset)
409 {
410  int nx, ny;
411  int row;
412 
413  /* Check input */
414  passure( image != NULL, " ");
415  passure( dispersion != NULL, " ");
416  passure( uves_polynomial_get_dimension(dispersion) == 2, "%d",
417  uves_polynomial_get_dimension(dispersion));
418  passure( order_locations != NULL, " ");
419  passure( uves_polynomial_get_dimension(order_locations) == 2, "%d",
420  uves_polynomial_get_dimension(order_locations));
421  passure( t != NULL, " ");
422  passure( cpl_table_has_column(t, lambda_column), "%s", lambda_column);
423  if (abs_order != NULL)
424  {
425  passure( cpl_table_has_column(t, abs_order), "%s", abs_order);
426  }
427 
428  nx = cpl_image_get_size_x(image);
429  ny = cpl_image_get_size_y(image);
430 
431  for (row = 0; row < cpl_table_get_nrow(t); row++) {
432  double x, xguess;
433  double lambda, lambda_left, lambda_right;
434  int order;
435 
436  check( lambda = cpl_table_get_double(t, lambda_column, row, NULL),
437  "Error reading table");
438 
439  if (abs_order != NULL)
440  check (minorder = maxorder = cpl_table_get_int(t, abs_order, row, NULL),
441  "Error reading table");
442 
443  for (order = minorder; order <= maxorder; order++) {
444  lambda_left = uves_polynomial_evaluate_2d(dispersion, 1 , order)/order;
445  lambda_right = uves_polynomial_evaluate_2d(dispersion, nx, order)/order;
446 
447  /* Solve dispersion(x, m) = ident*m */
448  xguess = 1 + (nx - 1) * (lambda - lambda_left)/(lambda_right - lambda_left);
449  /* Simple linear interpolation */
450 
451  /* Skip if lambda is not in this order */
452  if (1 <= xguess && xguess <= nx) {
453  x = uves_polynomial_solve_2d(dispersion, lambda*order, xguess,
454  1, /* multiplicity */
455  2, /* fix this variable number */
456  order); /* ... to this value */
457 
458  /* Ignore if solve failed */
459  if (cpl_error_get_code() != CPL_ERROR_NONE)
460  {
462  }
463  else {
464  /* Otherwise plot the solution */
465  uves_msg_debug("lambda(x=%f)\t = %f", x ,
466  uves_polynomial_evaluate_2d(dispersion, x , order)/order);
467  uves_msg_debug("lambda(x0=%f)\t = %f", xguess,
468  uves_polynomial_evaluate_2d(dispersion, xguess, order)/order);
469 
470  if (1 <= x && x <= nx) {
471  double y = uves_polynomial_evaluate_2d(order_locations, x,
472  relative_order[order]);
473  int i;
474 
475  for (i = -3; i <= 3; i++) {
476  if (vertical) {
477  check( cpl_image_set(image,
478  uves_min_int(nx, uves_max_int(1, x )),
479  uves_min_int(ny, uves_max_int(1, (int) y + i +
480  offset)), 0),
481  "Error writing image");
482  }
483  else {
484  check( cpl_image_set(image,
485  uves_min_int(nx, uves_max_int(1, x - i)),
486  uves_min_int(ny, uves_max_int(1, (int) y +
487  offset)), 0),
488  "Error writing image");
489  }
490  }
491  }
492  } /* Solve succeeded */
493  } /* if lambda was inside this order */
494 
495  } /* for each order */
496 
497  } /* for each lambda */
498 
499  cleanup:
500  return cpl_error_get_code();
501 }
502 
cpl_table ** uves_lt_get_table(const lt_type *lt, int window, int trace)
Get the table structure.
int uves_polynomial_get_dimension(const polynomial *p)
Get the dimension of a polynomial.
double uves_polynomial_solve_2d(const polynomial *p, double value, double guess, int multiplicity, int varno, double x_value)
Solve p(x1, x2) = value.
void uves_polynomial_delete(polynomial **p)
Delete a polynomial.
int * last_absolute_order
int * uves_lt_get_lastabs(const lt_type *lt, int window, int trace)
Get last absolute order.
#define check_nomsg(CMD)
Definition: uves_error.h:204
lt_type * uves_lt_new(int windows, int traces)
Allocate line table.
polynomial ** absolute_order
#define passure(BOOL,...)
Definition: uves_error.h:207
double uves_average_reject(cpl_table *t, const char *column, const char *residual2, double kappa)
Get average with iterative rejection.
Definition: uves_utils.c:2513
polynomial ** dispersion_relation
polynomial ** uves_lt_get_disprel(const lt_type *lt, int window, int trace)
Get dispersion relation.
cpl_error_code uves_draw_lines(cpl_image *image, polynomial *dispersion, const polynomial *order_locations, const cpl_table *t, const char *lambda_column, const char *abs_order, const int *relative_order, int minorder, int maxorder, bool vertical, int offset)
Draw lines in an echelle image.
int uves_delete_bad_lines(cpl_table *table, double TOLERANCE, double kappa)
Delete bad lines from line table.
#define assure_mem(PTR)
Definition: uves_error.h:181
double uves_polynomial_evaluate_2d(const polynomial *p, double x1, double x2)
Evaluate a 2d polynomial.
int * uves_lt_get_firstabs(const lt_type *lt, int window, int trace)
Get first absolute order.
void uves_lt_delete(lt_type **lt)
Deallocate line table.
#define uves_error_reset()
Definition: uves_error.h:215
#define uves_msg_debug(...)
Print a debug message.
Definition: uves_msg.h:97
int uves_wavecal_find_nearest(const cpl_table *line_refer, double lambda, int lo, int hi)
Find best matching catalogue wavelength.
cpl_table ** table
#define check(CMD,...)
Definition: uves_error.h:198
polynomial ** uves_lt_get_absord(const lt_type *lt, int window, int trace)
Get absolute order polynomial.
int * first_absolute_order