IIINSTRUMENT Pipeline Reference Manual  4.4.11
naco_util_spc_model.c
1 /* $Id: naco_util_spc_model.c,v 1.10 2011-12-22 11:21:03 llundin Exp $
2  *
3  * This file is part of the NACO 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: 2011-12-22 11:21:03 $
24  * $Revision: 1.10 $
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 
38 #include "naco_recipe.h"
39 
40 #include "naco_spc.h"
41 
42 /*-----------------------------------------------------------------------------
43  Recipe defines
44  -----------------------------------------------------------------------------*/
45 
46 #define RECIPE_STRING "naco_util_spc_model"
47 
48 #ifndef NACO_SPC_MODEL_SIZE
49 #define NACO_SPC_MODEL_SIZE 1024
50 #endif
51 
52 /*-----------------------------------------------------------------------------
53  Private Functions prototypes
54  -----------------------------------------------------------------------------*/
55 
56 NACO_RECIPE_DEFINE(naco_util_spc_model, 0,
57  "Generate FITS table with physical spectro model",
58  "The sof file shall consist of 1 line with the name of an "
59  "ASCII-file\n"
60  "currently tagged with " NACO_SPC_MODEL_ASCII ".\n"
61  "The file must comprise these "
62  IRPLIB_STRINGIFY(NACO_SPC_MODEL_COLS) " columns:\n"
63  NACO_SPC_LAB_MODE
64  " (with a value found in " NACO_PFITS_STRING_SPECMODE ")\n"
65  NACO_SPC_LAB_RESID
66  " (with fitting residual, currently ignored)\n"
67  NACO_SPC_LAB_ORDER
68  " (with the number of fitted coefficients in the "
69  "Legendre polynomial)\n"
70  NACO_SPC_LAB_XMIN
71  " (with the minimum pixel value used for the fit)\n"
72  NACO_SPC_LAB_XMAX
73  " (with the maximum pixel value used for the fit)\n"
74  NACO_SPC_LAB_C1
75  " (with the coefficient of the 1st Legendre term)\n"
76  NACO_SPC_LAB_C2
77  " (with the coefficient of the 2nd Legendre term)\n"
78  NACO_SPC_LAB_C3
79  " (with the coefficient of the 3rd Legendre term)\n"
80  NACO_SPC_LAB_C4
81  " (with the coefficient of the 4th Legendre term)\n"
82  "\n"
83  "The default input ASCII-file is in the catalogs/ "
84  "directory of the NACO source-code distribution.");
85 
86 static IRPLIB_UTIL_SET_ROW(naco_util_spc_model_set_row);
87 static IRPLIB_UTIL_CHECK(naco_util_spc_model_check);
88 
89 static double naco_util_spc_model_eval(double, double *, double, double,
90  double, double, double, double);
91 
92 /*----------------------------------------------------------------------------*/
96 /*----------------------------------------------------------------------------*/
97 
98 /*-----------------------------------------------------------------------------
99 
100  Functions code
101  -----------------------------------------------------------------------------*/
102 
103 /*----------------------------------------------------------------------------*/
110 /*----------------------------------------------------------------------------*/
111 static int naco_util_spc_model(cpl_frameset * framelist,
112  const cpl_parameterlist * parlist)
113 {
114  irplib_framelist * allframes = NULL;
115  irplib_framelist * rawframes = NULL;
116  cpl_frameset * useframes = NULL;
117  cpl_table * self = NULL;
118 
119 
120  if (cpl_error_get_code()) return cpl_error_get_code();
121 
122  /* Identify the RAW frames in the input frameset */
123  skip_if (naco_dfs_set_groups(framelist));
124 
125  /* FIXME: Using framelists is the simplest way to extract the relevant
126  frames :-( */
127 
128  allframes = irplib_framelist_cast(framelist);
129  bug_if(allframes == NULL);
130 
131  rawframes = irplib_framelist_extract(allframes, NACO_SPC_MODEL_ASCII);
132  skip_if (rawframes == NULL);
133 
134  irplib_framelist_empty(allframes);
135 
136  useframes = irplib_frameset_cast(rawframes);
137  bug_if(allframes == NULL);
138 
139  /* At least one row per file */
140  self = cpl_table_new(irplib_framelist_get_size(rawframes));
141 
142  irplib_framelist_empty(rawframes);
143 
144 
145  /* Create the table columns - with units */
146  bug_if (cpl_table_new_column(self, NACO_SPC_LAB_MODE, CPL_TYPE_STRING));
147  bug_if (cpl_table_new_column(self, NACO_SPC_LAB_ORDER, CPL_TYPE_INT));
148  bug_if (cpl_table_new_column(self, NACO_SPC_LAB_RESID, CPL_TYPE_DOUBLE));
149  bug_if (cpl_table_new_column(self, NACO_SPC_LAB_XMIN, CPL_TYPE_DOUBLE));
150  bug_if (cpl_table_new_column(self, NACO_SPC_LAB_XMAX, CPL_TYPE_DOUBLE));
151  bug_if (cpl_table_new_column(self, NACO_SPC_LAB_C1, CPL_TYPE_DOUBLE));
152  bug_if (cpl_table_new_column(self, NACO_SPC_LAB_C2, CPL_TYPE_DOUBLE));
153  bug_if (cpl_table_new_column(self, NACO_SPC_LAB_C3, CPL_TYPE_DOUBLE));
154  bug_if (cpl_table_new_column(self, NACO_SPC_LAB_C4, CPL_TYPE_DOUBLE));
155 
156  bug_if(cpl_table_set_column_unit(self, NACO_SPC_LAB_XMIN, "pixel"));
157  bug_if(cpl_table_set_column_unit(self, NACO_SPC_LAB_XMAX, "pixel"));
158  bug_if(cpl_table_set_column_unit(self, NACO_SPC_LAB_C1, "Angstrom"));
159  bug_if(cpl_table_set_column_unit(self, NACO_SPC_LAB_C2, "Angstrom"));
160  bug_if(cpl_table_set_column_unit(self, NACO_SPC_LAB_C3, "Angstrom"));
161  bug_if(cpl_table_set_column_unit(self, NACO_SPC_LAB_C4, "Angstrom"));
162 
163 
164  skip_if(irplib_dfs_table_convert(self, framelist, useframes,
165  NACO_SPC_MODEL_SIZE, '#', NULL,
166  NACO_SPC_MODEL, parlist, RECIPE_STRING,
167  NULL, NULL, NULL, "NACO", naco_pipe_id,
168  naco_util_spc_model_set_row,
169  naco_util_spc_model_check));
170  end_skip;
171 
172  cpl_table_delete(self);
173  cpl_frameset_delete(useframes);
174  irplib_framelist_delete(allframes);
175  irplib_framelist_delete(rawframes);
176 
177  return cpl_error_get_code();
178 }
179 
180 /*----------------------------------------------------------------------------*/
192 /*----------------------------------------------------------------------------*/
193 static
194 cpl_boolean naco_util_spc_model_set_row(cpl_table * self,
195  const char * line,
196  int irow,
197  const cpl_frame * rawframe,
198  const cpl_parameterlist * parlist)
199 {
200 
201 
202  /* gcc can only check sscanf()s format when it is a string literal */
203 #define FORMAT "%" CPL_STRINGIFY(NACO_SPC_MODEL_SIZE) \
204  "s %lg %d %lg %lg %lg %lg %lg %lg"
205 
206  int nvals;
207  char mode[NACO_SPC_MODEL_SIZE + 1];
208  double resid, xmin, xmax;
209  double c1, c2, c3, c4;
210  int order;
211 
212  double wlmin, wlmax;
213  double nf, wlf, pposf;
214  double nc, wlc, pposc;
215  double nl, wll, pposl;
216 
217 
218  bug_if(0);
219  bug_if(self == NULL);
220  bug_if(line == NULL);
221  bug_if(irow < 0);
222  bug_if(rawframe == NULL);
223  bug_if(parlist == NULL);
224 
225  nvals = sscanf(line, FORMAT, mode, &resid, &order, &xmin, &xmax,
226  &c1, &c2, &c3, &c4);
227 
228  error_if (nvals != NACO_SPC_MODEL_COLS, CPL_ERROR_BAD_FILE_FORMAT,
229  "Line with length=%u has %d not "
230  IRPLIB_STRINGIFY(NACO_SPC_MODEL_COLS) " items formatted: %s",
231  (unsigned)strlen(line), nvals, FORMAT);
232 
233  error_if (order > NACO_SPC_MODEL_COEFFS, CPL_ERROR_BAD_FILE_FORMAT,
234  "Too high fit order=%d > " IRPLIB_STRINGIFY(NACO_SPC_MODEL_COEFFS)
235  " in line %s", order, line);
236 
237  error_if (order < 2, CPL_ERROR_BAD_FILE_FORMAT,
238  "Too low fit order=%d < 2 in line %s", order, line);
239 
240  error_if (xmin < 0.0, CPL_ERROR_BAD_FILE_FORMAT,
241  "Negative XMin=%g in line %s", xmin, line);
242 
243  error_if (xmax <= xmin, CPL_ERROR_BAD_FILE_FORMAT,
244  "XMax=%g is not greater than XMin=%g in line %s", xmax,
245  xmin, line);
246 
247 
248  bug_if(cpl_table_set_string(self, NACO_SPC_LAB_MODE, irow, mode));
249  bug_if(cpl_table_set_double(self, NACO_SPC_LAB_RESID, irow, resid));
250  bug_if(cpl_table_set_int (self, NACO_SPC_LAB_ORDER, irow, order));
251  bug_if(cpl_table_set_double(self, NACO_SPC_LAB_XMIN, irow, xmin));
252  bug_if(cpl_table_set_double(self, NACO_SPC_LAB_XMAX, irow, xmax));
253  bug_if(cpl_table_set_double(self, NACO_SPC_LAB_C1, irow, c1));
254  bug_if(cpl_table_set_double(self, NACO_SPC_LAB_C2, irow, c2));
255  bug_if(cpl_table_set_double(self, NACO_SPC_LAB_C3, irow, c3));
256  bug_if(cpl_table_set_double(self, NACO_SPC_LAB_C4, irow, c4));
257 
258  wlmin = naco_util_spc_model_eval(-1.0, NULL, xmin, xmax, c1, c2, c3, c4);
259  wlmax = naco_util_spc_model_eval( 1.0, NULL, xmin, xmax, c1, c2, c3, c4);
260 
261  cpl_msg_info(cpl_func, "%-10s has range [Angstrom @ pixel]: "
262  "%8.2f @ %6.2f => %8.2f @ %6.2f", mode, wlmin, xmin, wlmax, xmax);
263 
264  /* Pixel position 1, 512.5 and 1024 */
265  nf = (2.0 * 1.0 - (xmax + xmin)) / (xmax - xmin);
266  wlf = naco_util_spc_model_eval(nf, &pposf, xmin, xmax, c1, c2, c3, c4);
267 
268  nc = (2.0 * 512.5 - (xmax + xmin)) / (xmax - xmin);
269  wlc = naco_util_spc_model_eval(nc, &pposc, xmin, xmax, c1, c2, c3, c4);
270 
271  nl = (2.0 * 1024.0 - (xmax + xmin)) / (xmax - xmin);
272  wll = naco_util_spc_model_eval(nl, &pposl, xmin, xmax, c1, c2, c3, c4);
273 
274  cpl_msg_info(cpl_func, "%-10s detector full range [Angstrom @ pixel]: "
275  "%8.2f @ %6.2f => %8.2f @ %6.2f => %8.2f @ %6.2f", mode, wlf, pposf, wlc, pposc, wll, pposl);
276 
277 
278  end_skip;
279 
280  return CPL_TRUE;
281 
282 }
283 
284 
285 /*----------------------------------------------------------------------------*/
294 /*----------------------------------------------------------------------------*/
295 static
296 cpl_error_code naco_util_spc_model_check(cpl_table * self,
297  const cpl_frameset * useframes,
298  const cpl_parameterlist * parlist)
299 {
300 
301  bug_if(0);
302  bug_if(self == NULL);
303  bug_if(parlist == NULL);
304 
305  cpl_msg_info(cpl_func, "Created table of %d spectrum modes from %d file(s)",
306  (int)cpl_table_get_nrow(self),
307  (int)cpl_frameset_get_size(useframes));
308 
309  end_skip;
310 
311  return cpl_error_get_code();
312 }
313 
314 /*----------------------------------------------------------------------------*/
338 /*----------------------------------------------------------------------------*/
339 static double naco_util_spc_model_eval(double x, double * pp, double pmin,
340  double pmax,
341  double c1, double c2,
342  double c3, double c4)
343 {
344 
345  const double value
346  = c1 - 0.5*c3 + x*( c2 - 1.5 * c4 + x*( 1.5 * c3 + x*( 2.5 * c4 )));
347 
348  if (pp != NULL) *pp = 0.5 * ( (pmax + pmin) + x * (pmax - pmin) );
349 
350  return value;
351 
352 }
int naco_dfs_set_groups(cpl_frameset *set)
Set the group as RAW or CALIB in a frameset.
Definition: naco_dfs.c:62