38 #include "naco_recipe.h"
46 #define RECIPE_STRING "naco_util_spc_model"
48 #ifndef NACO_SPC_MODEL_SIZE
49 #define NACO_SPC_MODEL_SIZE 1024
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 "
60 "currently tagged with " NACO_SPC_MODEL_ASCII
".\n"
61 "The file must comprise these "
62 IRPLIB_STRINGIFY(NACO_SPC_MODEL_COLS)
" columns:\n"
64 " (with a value found in " NACO_PFITS_STRING_SPECMODE
")\n"
66 " (with fitting residual, currently ignored)\n"
68 " (with the number of fitted coefficients in the "
69 "Legendre polynomial)\n"
71 " (with the minimum pixel value used for the fit)\n"
73 " (with the maximum pixel value used for the fit)\n"
75 " (with the coefficient of the 1st Legendre term)\n"
77 " (with the coefficient of the 2nd Legendre term)\n"
79 " (with the coefficient of the 3rd Legendre term)\n"
81 " (with the coefficient of the 4th Legendre term)\n"
83 "The default input ASCII-file is in the catalogs/ "
84 "directory of the NACO source-code distribution.");
86 static IRPLIB_UTIL_SET_ROW(naco_util_spc_model_set_row);
87 static IRPLIB_UTIL_CHECK(naco_util_spc_model_check);
89 static double naco_util_spc_model_eval(
double,
double *,
double,
double,
90 double,
double,
double,
double);
111 static int naco_util_spc_model(cpl_frameset * framelist,
112 const cpl_parameterlist * parlist)
114 irplib_framelist * allframes = NULL;
115 irplib_framelist * rawframes = NULL;
116 cpl_frameset * useframes = NULL;
117 cpl_table *
self = NULL;
120 if (cpl_error_get_code())
return cpl_error_get_code();
129 bug_if(allframes == NULL);
132 skip_if (rawframes == NULL);
137 bug_if(allframes == NULL);
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));
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"));
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));
172 cpl_table_delete(
self);
173 cpl_frameset_delete(useframes);
177 return cpl_error_get_code();
194 cpl_boolean naco_util_spc_model_set_row(cpl_table *
self,
197 const cpl_frame * rawframe,
198 const cpl_parameterlist * parlist)
203 #define FORMAT "%s %lg %d %lg %lg %lg %lg %lg %lg"
206 char mode[NACO_SPC_MODEL_SIZE];
207 double resid, xmin, xmax;
208 double c1, c2, c3, c4;
212 double nf, wlf, pposf;
213 double nc, wlc, pposc;
214 double nl, wll, pposl;
218 bug_if(
self == NULL);
219 bug_if(line == NULL);
221 bug_if(rawframe == NULL);
222 bug_if(parlist == NULL);
224 nvals = sscanf(line, FORMAT, mode, &resid, &order, &xmin, &xmax,
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);
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);
236 error_if (order < 2, CPL_ERROR_BAD_FILE_FORMAT,
237 "Too low fit order=%d < 2 in line %s", order, line);
239 error_if (xmin < 0.0, CPL_ERROR_BAD_FILE_FORMAT,
240 "Negative XMin=%g in line %s", xmin, line);
242 error_if (xmax <= xmin, CPL_ERROR_BAD_FILE_FORMAT,
243 "XMax=%g is not greater than XMin=%g in line %s", xmax,
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));
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);
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);
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);
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);
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);
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);
295 cpl_error_code naco_util_spc_model_check(cpl_table *
self,
296 const cpl_frameset * useframes,
297 const cpl_parameterlist * parlist)
301 bug_if(
self == NULL);
302 bug_if(parlist == NULL);
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));
310 return cpl_error_get_code();
338 static double naco_util_spc_model_eval(
double x,
double * pp,
double pmin,
340 double c1,
double c2,
341 double c3,
double c4)
345 = c1 - 0.5*c3 + x*( c2 - 1.5 * c4 + x*( 1.5 * c3 + x*( 2.5 * c4 )));
347 if (pp != NULL) *pp = 0.5 * ( (pmax + pmin) + x * (pmax - pmin) );
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.
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)
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.