NACO Pipeline Reference Manual  4.4.0
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 "%s %lg %d %lg %lg %lg %lg %lg %lg"
204 
205  int nvals;
206  char mode[NACO_SPC_MODEL_SIZE];
207  double resid, xmin, xmax;
208  double c1, c2, c3, c4;
209  int order;
210 
211  double wlmin, wlmax;
212  double nf, wlf, pposf;
213  double nc, wlc, pposc;
214  double nl, wll, pposl;
215 
216 
217  bug_if(0);
218  bug_if(self == NULL);
219  bug_if(line == NULL);
220  bug_if(irow < 0);
221  bug_if(rawframe == NULL);
222  bug_if(parlist == NULL);
223 
224  nvals = sscanf(line, FORMAT, mode, &resid, &order, &xmin, &xmax,
225  &c1, &c2, &c3, &c4);
226 
227  error_if (nvals != NACO_SPC_MODEL_COLS, CPL_ERROR_BAD_FILE_FORMAT,
228  "Line with length=%u has %d not "
229  IRPLIB_STRINGIFY(NACO_SPC_MODEL_COLS) " items formatted: %s",
230  (unsigned)strlen(line), nvals, FORMAT);
231 
232  error_if (order > NACO_SPC_MODEL_COEFFS, CPL_ERROR_BAD_FILE_FORMAT,
233  "Too high fit order=%d > " IRPLIB_STRINGIFY(NACO_SPC_MODEL_COEFFS)
234  " in line %s", order, line);
235 
236  error_if (order < 2, CPL_ERROR_BAD_FILE_FORMAT,
237  "Too low fit order=%d < 2 in line %s", order, line);
238 
239  error_if (xmin < 0.0, CPL_ERROR_BAD_FILE_FORMAT,
240  "Negative XMin=%g in line %s", xmin, line);
241 
242  error_if (xmax <= xmin, CPL_ERROR_BAD_FILE_FORMAT,
243  "XMax=%g is not greater than XMin=%g in line %s", xmax,
244  xmin, line);
245 
246 
247  bug_if(cpl_table_set_string(self, NACO_SPC_LAB_MODE, irow, mode));
248  bug_if(cpl_table_set_double(self, NACO_SPC_LAB_RESID, irow, resid));
249  bug_if(cpl_table_set_int (self, NACO_SPC_LAB_ORDER, irow, order));
250  bug_if(cpl_table_set_double(self, NACO_SPC_LAB_XMIN, irow, xmin));
251  bug_if(cpl_table_set_double(self, NACO_SPC_LAB_XMAX, irow, xmax));
252  bug_if(cpl_table_set_double(self, NACO_SPC_LAB_C1, irow, c1));
253  bug_if(cpl_table_set_double(self, NACO_SPC_LAB_C2, irow, c2));
254  bug_if(cpl_table_set_double(self, NACO_SPC_LAB_C3, irow, c3));
255  bug_if(cpl_table_set_double(self, NACO_SPC_LAB_C4, irow, c4));
256 
257  wlmin = naco_util_spc_model_eval(-1.0, NULL, xmin, xmax, c1, c2, c3, c4);
258  wlmax = naco_util_spc_model_eval( 1.0, NULL, xmin, xmax, c1, c2, c3, c4);
259 
260  cpl_msg_info(cpl_func, "%-10s has range [Angstrom @ pixel]: "
261  "%8.2f @ %6.2f => %8.2f @ %6.2f", mode, wlmin, xmin, wlmax, xmax);
262 
263  /* Pixel position 1, 512.5 and 1024 */
264  nf = (2.0 * 1.0 - (xmax + xmin)) / (xmax - xmin);
265  wlf = naco_util_spc_model_eval(nf, &pposf, xmin, xmax, c1, c2, c3, c4);
266 
267  nc = (2.0 * 512.5 - (xmax + xmin)) / (xmax - xmin);
268  wlc = naco_util_spc_model_eval(nc, &pposc, xmin, xmax, c1, c2, c3, c4);
269 
270  nl = (2.0 * 1024.0 - (xmax + xmin)) / (xmax - xmin);
271  wll = naco_util_spc_model_eval(nl, &pposl, xmin, xmax, c1, c2, c3, c4);
272 
273  cpl_msg_info(cpl_func, "%-10s detector full range [Angstrom @ pixel]: "
274  "%8.2f @ %6.2f => %8.2f @ %6.2f => %8.2f @ %6.2f", mode, wlf, pposf, wlc, pposc, wll, pposl);
275 
276 
277  end_skip;
278 
279  return CPL_TRUE;
280 
281 }
282 
283 
284 /*----------------------------------------------------------------------------*/
293 /*----------------------------------------------------------------------------*/
294 static
295 cpl_error_code naco_util_spc_model_check(cpl_table * self,
296  const cpl_frameset * useframes,
297  const cpl_parameterlist * parlist)
298 {
299 
300  bug_if(0);
301  bug_if(self == NULL);
302  bug_if(parlist == NULL);
303 
304  cpl_msg_info(cpl_func, "Created table of %d spectrum modes from %d file(s)",
305  (int)cpl_table_get_nrow(self),
306  (int)cpl_frameset_get_size(useframes));
307 
308  end_skip;
309 
310  return cpl_error_get_code();
311 }
312 
313 /*----------------------------------------------------------------------------*/
337 /*----------------------------------------------------------------------------*/
338 static double naco_util_spc_model_eval(double x, double * pp, double pmin,
339  double pmax,
340  double c1, double c2,
341  double c3, double c4)
342 {
343 
344  const double value
345  = c1 - 0.5*c3 + x*( c2 - 1.5 * c4 + x*( 1.5 * c3 + x*( 2.5 * c4 )));
346 
347  if (pp != NULL) *pp = 0.5 * ( (pmax + pmin) + x * (pmax - pmin) );
348 
349  return value;
350 
351 }
cpl_frameset * irplib_frameset_cast(const irplib_framelist *self)
Create a CPL frameset from an irplib_framelist.
int naco_dfs_set_groups(cpl_frameset *set)
Set the group as RAW or CALIB in a frameset.
Definition: naco_dfs.c:62
cpl_error_code irplib_dfs_table_convert(cpl_table *self, cpl_frameset *allframes, const cpl_frameset *useframes, int maxlinelen, char commentchar, const char *product_name, const char *procatg, const cpl_parameterlist *parlist, const char *recipe_name, const cpl_propertylist *mainlist, const cpl_propertylist *extlist, const char *remregexp, const char *instrume, const char *pipe_id, cpl_boolean(*table_set_row)(cpl_table *, const char *, int, const cpl_frame *, const cpl_parameterlist *), cpl_error_code(*table_check)(cpl_table *, const cpl_frameset *, const cpl_parameterlist *))
Create a DFS product with one table from one or more (ASCII) file(s)
Definition: irplib_utils.c:860
void irplib_framelist_empty(irplib_framelist *self)
Erase all frames from a framelist.
irplib_framelist * irplib_framelist_extract(const irplib_framelist *self, const char *tag)
Extract the frames with the given tag from a framelist.
void irplib_framelist_delete(irplib_framelist *self)
Deallocate an irplib_framelist with its frames and properties.
irplib_framelist * irplib_framelist_cast(const cpl_frameset *frameset)
Create an irplib_framelist from a cpl_framelist.
int irplib_framelist_get_size(const irplib_framelist *self)
Get the size of a framelist.