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();
128 allframes = irplib_framelist_cast(framelist);
129 bug_if(allframes == NULL);
131 rawframes = irplib_framelist_extract(allframes, NACO_SPC_MODEL_ASCII);
132 skip_if (rawframes == NULL);
134 irplib_framelist_empty(allframes);
136 useframes = irplib_frameset_cast(rawframes);
137 bug_if(allframes == NULL);
140 self = cpl_table_new(irplib_framelist_get_size(rawframes));
142 irplib_framelist_empty(rawframes);
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"));
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));
172 cpl_table_delete(
self);
173 cpl_frameset_delete(useframes);
174 irplib_framelist_delete(allframes);
175 irplib_framelist_delete(rawframes);
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 "%" CPL_STRINGIFY(NACO_SPC_MODEL_SIZE) \
204 "s %lg %d %lg %lg %lg %lg %lg %lg"
207 char mode[NACO_SPC_MODEL_SIZE + 1];
208 double resid, xmin, xmax;
209 double c1, c2, c3, c4;
213 double nf, wlf, pposf;
214 double nc, wlc, pposc;
215 double nl, wll, pposl;
219 bug_if(
self == NULL);
220 bug_if(line == NULL);
222 bug_if(rawframe == NULL);
223 bug_if(parlist == NULL);
225 nvals = sscanf(line, FORMAT, mode, &resid, &order, &xmin, &xmax,
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);
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);
237 error_if (order < 2, CPL_ERROR_BAD_FILE_FORMAT,
238 "Too low fit order=%d < 2 in line %s", order, line);
240 error_if (xmin < 0.0, CPL_ERROR_BAD_FILE_FORMAT,
241 "Negative XMin=%g in line %s", xmin, line);
243 error_if (xmax <= xmin, CPL_ERROR_BAD_FILE_FORMAT,
244 "XMax=%g is not greater than XMin=%g in line %s", xmax,
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));
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);
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);
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);
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);
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);
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);
296 cpl_error_code naco_util_spc_model_check(cpl_table *
self,
297 const cpl_frameset * useframes,
298 const cpl_parameterlist * parlist)
302 bug_if(
self == NULL);
303 bug_if(parlist == NULL);
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));
311 return cpl_error_get_code();
339 static double naco_util_spc_model_eval(
double x,
double * pp,
double pmin,
341 double c1,
double c2,
342 double c3,
double c4)
346 = c1 - 0.5*c3 + x*( c2 - 1.5 * c4 + x*( 1.5 * c3 + x*( 2.5 * c4 )));
348 if (pp != NULL) *pp = 0.5 * ( (pmax + pmin) + x * (pmax - pmin) );