00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031
00032
00033
00034
00035
00036 #include <string.h>
00037
00038 #include "naco_recipe.h"
00039
00040 #include "naco_spc.h"
00041
00042
00043
00044
00045
00046 #define RECIPE_STRING "naco_util_spc_model"
00047
00048 #ifndef NACO_SPC_MODEL_SIZE
00049 #define NACO_SPC_MODEL_SIZE 1024
00050 #endif
00051
00052
00053
00054
00055
00056 NACO_RECIPE_DEFINE(naco_util_spc_model, 0,
00057 "Generate FITS table with physical spectro model",
00058 "The sof file shall consist of 1 line with the name of an "
00059 "ASCII-file\n"
00060 "currently tagged with " NACO_SPC_MODEL_ASCII ".\n"
00061 "The file must comprise these "
00062 IRPLIB_STRINGIFY(NACO_SPC_MODEL_COLS) " columns:\n"
00063 NACO_SPC_LAB_MODE
00064 " (with a value found in " NACO_PFITS_STRING_SPECMODE ")\n"
00065 NACO_SPC_LAB_RESID
00066 " (with fitting residual, currently ignored)\n"
00067 NACO_SPC_LAB_ORDER
00068 " (with the number of fitted coefficients in the "
00069 "Legendre polynomial)\n"
00070 NACO_SPC_LAB_XMIN
00071 " (with the minimum pixel value used for the fit)\n"
00072 NACO_SPC_LAB_XMAX
00073 " (with the maximum pixel value used for the fit)\n"
00074 NACO_SPC_LAB_C1
00075 " (with the coefficient of the 1st Legendre term)\n"
00076 NACO_SPC_LAB_C2
00077 " (with the coefficient of the 2nd Legendre term)\n"
00078 NACO_SPC_LAB_C3
00079 " (with the coefficient of the 3rd Legendre term)\n"
00080 NACO_SPC_LAB_C4
00081 " (with the coefficient of the 4th Legendre term)\n"
00082 "\n"
00083 "The default input ASCII-file is in the catalogs/ "
00084 "directory of the NACO source-code distribution.");
00085
00086 static IRPLIB_UTIL_SET_ROW(naco_util_spc_model_set_row);
00087 static IRPLIB_UTIL_CHECK(naco_util_spc_model_check);
00088
00089 static double naco_util_spc_model_eval(double, double *, double, double,
00090 double, double, double, double);
00091
00092
00096
00097
00098
00099
00100
00101
00102
00103
00110
00111 static int naco_util_spc_model(cpl_frameset * framelist,
00112 const cpl_parameterlist * parlist)
00113 {
00114 irplib_framelist * allframes = NULL;
00115 irplib_framelist * rawframes = NULL;
00116 cpl_frameset * useframes = NULL;
00117 cpl_table * self = NULL;
00118
00119
00120 if (cpl_error_get_code()) return cpl_error_get_code();
00121
00122
00123 skip_if (naco_dfs_set_groups(framelist));
00124
00125
00126
00127
00128 allframes = irplib_framelist_cast(framelist);
00129 bug_if(allframes == NULL);
00130
00131 rawframes = irplib_framelist_extract(allframes, NACO_SPC_MODEL_ASCII);
00132 skip_if (rawframes == NULL);
00133
00134 irplib_framelist_empty(allframes);
00135
00136 useframes = irplib_frameset_cast(rawframes);
00137 bug_if(allframes == NULL);
00138
00139
00140 self = cpl_table_new(irplib_framelist_get_size(rawframes));
00141
00142 irplib_framelist_empty(rawframes);
00143
00144
00145
00146 bug_if (cpl_table_new_column(self, NACO_SPC_LAB_MODE, CPL_TYPE_STRING));
00147 bug_if (cpl_table_new_column(self, NACO_SPC_LAB_ORDER, CPL_TYPE_INT));
00148 bug_if (cpl_table_new_column(self, NACO_SPC_LAB_RESID, CPL_TYPE_DOUBLE));
00149 bug_if (cpl_table_new_column(self, NACO_SPC_LAB_XMIN, CPL_TYPE_DOUBLE));
00150 bug_if (cpl_table_new_column(self, NACO_SPC_LAB_XMAX, CPL_TYPE_DOUBLE));
00151 bug_if (cpl_table_new_column(self, NACO_SPC_LAB_C1, CPL_TYPE_DOUBLE));
00152 bug_if (cpl_table_new_column(self, NACO_SPC_LAB_C2, CPL_TYPE_DOUBLE));
00153 bug_if (cpl_table_new_column(self, NACO_SPC_LAB_C3, CPL_TYPE_DOUBLE));
00154 bug_if (cpl_table_new_column(self, NACO_SPC_LAB_C4, CPL_TYPE_DOUBLE));
00155
00156 bug_if(cpl_table_set_column_unit(self, NACO_SPC_LAB_XMIN, "pixel"));
00157 bug_if(cpl_table_set_column_unit(self, NACO_SPC_LAB_XMAX, "pixel"));
00158 bug_if(cpl_table_set_column_unit(self, NACO_SPC_LAB_C1, "Angstrom"));
00159 bug_if(cpl_table_set_column_unit(self, NACO_SPC_LAB_C2, "Angstrom"));
00160 bug_if(cpl_table_set_column_unit(self, NACO_SPC_LAB_C3, "Angstrom"));
00161 bug_if(cpl_table_set_column_unit(self, NACO_SPC_LAB_C4, "Angstrom"));
00162
00163
00164 skip_if(irplib_dfs_table_convert(self, framelist, useframes,
00165 NACO_SPC_MODEL_SIZE, '#', NULL,
00166 NACO_SPC_MODEL, parlist, RECIPE_STRING,
00167 NULL, NULL, NULL, "NACO", naco_pipe_id,
00168 naco_util_spc_model_set_row,
00169 naco_util_spc_model_check));
00170 end_skip;
00171
00172 cpl_table_delete(self);
00173 cpl_frameset_delete(useframes);
00174 irplib_framelist_delete(allframes);
00175 irplib_framelist_delete(rawframes);
00176
00177 return cpl_error_get_code();
00178 }
00179
00180
00192
00193 static
00194 cpl_boolean naco_util_spc_model_set_row(cpl_table * self,
00195 const char * line,
00196 int irow,
00197 const cpl_frame * rawframe,
00198 const cpl_parameterlist * parlist)
00199 {
00200
00201
00202
00203 #define FORMAT "%s %lg %d %lg %lg %lg %lg %lg %lg"
00204
00205 int nvals;
00206 char mode[NACO_SPC_MODEL_SIZE];
00207 double resid, xmin, xmax;
00208 double c1, c2, c3, c4;
00209 int order;
00210
00211 double wlmin, wlmax;
00212 double nf, wlf, pposf;
00213 double nc, wlc, pposc;
00214 double nl, wll, pposl;
00215
00216
00217 bug_if(0);
00218 bug_if(self == NULL);
00219 bug_if(line == NULL);
00220 bug_if(irow < 0);
00221 bug_if(rawframe == NULL);
00222 bug_if(parlist == NULL);
00223
00224 nvals = sscanf(line, FORMAT, mode, &resid, &order, &xmin, &xmax,
00225 &c1, &c2, &c3, &c4);
00226
00227 error_if (nvals != NACO_SPC_MODEL_COLS, CPL_ERROR_BAD_FILE_FORMAT,
00228 "Line with length=%u has %d not "
00229 IRPLIB_STRINGIFY(NACO_SPC_MODEL_COLS) " items formatted: %s",
00230 (unsigned)strlen(line), nvals, FORMAT);
00231
00232 error_if (order > NACO_SPC_MODEL_COEFFS, CPL_ERROR_BAD_FILE_FORMAT,
00233 "Too high fit order=%d > " IRPLIB_STRINGIFY(NACO_SPC_MODEL_COEFFS)
00234 " in line %s", order, line);
00235
00236 error_if (order < 2, CPL_ERROR_BAD_FILE_FORMAT,
00237 "Too low fit order=%d < 2 in line %s", order, line);
00238
00239 error_if (xmin < 0.0, CPL_ERROR_BAD_FILE_FORMAT,
00240 "Negative XMin=%g in line %s", xmin, line);
00241
00242 error_if (xmax <= xmin, CPL_ERROR_BAD_FILE_FORMAT,
00243 "XMax=%g is not greater than XMin=%g in line %s", xmax,
00244 xmin, line);
00245
00246
00247 bug_if(cpl_table_set_string(self, NACO_SPC_LAB_MODE, irow, mode));
00248 bug_if(cpl_table_set_double(self, NACO_SPC_LAB_RESID, irow, resid));
00249 bug_if(cpl_table_set_int (self, NACO_SPC_LAB_ORDER, irow, order));
00250 bug_if(cpl_table_set_double(self, NACO_SPC_LAB_XMIN, irow, xmin));
00251 bug_if(cpl_table_set_double(self, NACO_SPC_LAB_XMAX, irow, xmax));
00252 bug_if(cpl_table_set_double(self, NACO_SPC_LAB_C1, irow, c1));
00253 bug_if(cpl_table_set_double(self, NACO_SPC_LAB_C2, irow, c2));
00254 bug_if(cpl_table_set_double(self, NACO_SPC_LAB_C3, irow, c3));
00255 bug_if(cpl_table_set_double(self, NACO_SPC_LAB_C4, irow, c4));
00256
00257 wlmin = naco_util_spc_model_eval(-1.0, NULL, xmin, xmax, c1, c2, c3, c4);
00258 wlmax = naco_util_spc_model_eval( 1.0, NULL, xmin, xmax, c1, c2, c3, c4);
00259
00260 cpl_msg_info(cpl_func, "%-10s has range [Angstrom @ pixel]: "
00261 "%8.2f @ %6.2f => %8.2f @ %6.2f", mode, wlmin, xmin, wlmax, xmax);
00262
00263
00264 nf = (2.0 * 1.0 - (xmax + xmin)) / (xmax - xmin);
00265 wlf = naco_util_spc_model_eval(nf, &pposf, xmin, xmax, c1, c2, c3, c4);
00266
00267 nc = (2.0 * 512.5 - (xmax + xmin)) / (xmax - xmin);
00268 wlc = naco_util_spc_model_eval(nc, &pposc, xmin, xmax, c1, c2, c3, c4);
00269
00270 nl = (2.0 * 1024.0 - (xmax + xmin)) / (xmax - xmin);
00271 wll = naco_util_spc_model_eval(nl, &pposl, xmin, xmax, c1, c2, c3, c4);
00272
00273 cpl_msg_info(cpl_func, "%-10s detector full range [Angstrom @ pixel]: "
00274 "%8.2f @ %6.2f => %8.2f @ %6.2f => %8.2f @ %6.2f", mode, wlf, pposf, wlc, pposc, wll, pposl);
00275
00276
00277 end_skip;
00278
00279 return CPL_TRUE;
00280
00281 }
00282
00283
00284
00293
00294 static
00295 cpl_error_code naco_util_spc_model_check(cpl_table * self,
00296 const cpl_frameset * useframes,
00297 const cpl_parameterlist * parlist)
00298 {
00299
00300 bug_if(0);
00301 bug_if(self == NULL);
00302 bug_if(parlist == NULL);
00303
00304 cpl_msg_info(cpl_func, "Created table of %d spectrum modes from %d file(s)",
00305 cpl_table_get_nrow(self), cpl_frameset_get_size(useframes));
00306
00307 end_skip;
00308
00309 return cpl_error_get_code();
00310 }
00311
00312
00336
00337 static double naco_util_spc_model_eval(double x, double * pp, double pmin,
00338 double pmax,
00339 double c1, double c2,
00340 double c3, double c4)
00341 {
00342
00343 const double value
00344 = c1 - 0.5*c3 + x*( c2 - 1.5 * c4 + x*( 1.5 * c3 + x*( 2.5 * c4 )));
00345
00346 if (pp != NULL) *pp = 0.5 * ( (pmax + pmin) + x * (pmax - pmin) );
00347
00348 return value;
00349
00350 }