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 <math.h>
00037 #include <cpl.h>
00038
00039 #include "irplib_utils.h"
00040
00041 #include "isaac_utils.h"
00042 #include "isaac_wavelength.h"
00043 #include "isaac_physicalmodel.h"
00044 #include "isaac_pfits.h"
00045 #include "isaac_dfs.h"
00046
00047
00048
00049
00050
00051 static int isaac_spc_wlcalib_create(cpl_plugin *);
00052 static int isaac_spc_wlcalib_exec(cpl_plugin *);
00053 static int isaac_spc_wlcalib_destroy(cpl_plugin *);
00054 static int isaac_spc_wlcalib(cpl_parameterlist *, cpl_frameset *);
00055 static cpl_table * isaac_spc_wlcalib_compute(const char *, const char *,
00056 const char *, const char *);
00057 static int isaac_spc_wlcalib_save(const cpl_table *, int, cpl_parameterlist *,
00058 cpl_frameset *);
00059
00060
00061
00062
00063
00064 static struct {
00065
00066 int rej_left;
00067 int rej_right;
00068 int rej_bottom;
00069 int rej_top;
00070 int max_offset;
00071 int lines_table;
00072
00073 double disprel_cc;
00074 int disprel_clines;
00075 int disprel_dlines;
00076 double disprel_rms;
00077 } isaac_spc_wlcalib_config;
00078
00079 static char isaac_spc_wlcalib_description[] =
00080 "isaac_spc_wlcalib -- ISAAC wavelength calibration recipe\n"
00081 "The files listed in the Set Of Frames (sof-file) must be tagged:\n"
00082 "oh-cat.fits "ISAAC_CALPRO_OH_CAT" or\n"
00083 "xe-cat.fits "ISAAC_CALPRO_XE_CAT" or\n"
00084 "ar-cat.fits "ISAAC_CALPRO_AR_CAT"\n";
00085
00086
00087
00088
00089
00090
00098
00099 int cpl_plugin_get_info(cpl_pluginlist * list)
00100 {
00101 cpl_recipe * recipe = cpl_calloc(1, sizeof(*recipe));
00102 cpl_plugin * plugin = &recipe->interface;
00103
00104 cpl_plugin_init(plugin,
00105 CPL_PLUGIN_API,
00106 ISAAC_BINARY_VERSION,
00107 CPL_PLUGIN_TYPE_RECIPE,
00108 "isaac_spc_wlcalib",
00109 "Spectro wavelength calibration",
00110 isaac_spc_wlcalib_description,
00111 "Lars Lundin",
00112 PACKAGE_BUGREPORT,
00113 isaac_get_license(),
00114 isaac_spc_wlcalib_create,
00115 isaac_spc_wlcalib_exec,
00116 isaac_spc_wlcalib_destroy);
00117
00118 cpl_pluginlist_append(list, plugin);
00119
00120 return 0;
00121 }
00122
00123
00132
00133 static int isaac_spc_wlcalib_create(cpl_plugin * plugin)
00134 {
00135 cpl_recipe * recipe;
00136 cpl_parameter * p;
00137
00138
00139 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
00140 recipe = (cpl_recipe *)plugin;
00141 else return -1;
00142
00143
00144 recipe->parameters = cpl_parameterlist_new();
00145
00146
00147
00148 p = cpl_parameter_new_value("isaac.isaac_spc_wlcalib.rejected",
00149 CPL_TYPE_STRING, "left right bottom top rejections",
00150 "isaac.isaac_spc_wlcalib", "-1 -1 100 100");
00151 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "rej");
00152 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00153 cpl_parameterlist_append(recipe->parameters, p);
00154
00155 p = cpl_parameter_new_value("isaac.isaac_spc_wlcalib.max_offset",
00156 CPL_TYPE_INT, "maximum offset from the physical model "
00157 "allowed in pixels", "isaac.isaac_spc_wlcalib", 50);
00158 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "max_offset");
00159 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00160 cpl_parameterlist_append(recipe->parameters, p);
00161
00162 p = cpl_parameter_new_value("isaac.isaac_spc_wlcalib.lines", CPL_TYPE_INT,
00163 "1 for oh, 2 for xe, 3 for ar, 4 for xe+ar",
00164 "isaac.isaac_spc_wlcalib", -1);
00165 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "lines");
00166 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00167 cpl_parameterlist_append(recipe->parameters, p);
00168 return 0;
00169 }
00170
00171
00177
00178 static int isaac_spc_wlcalib_exec(cpl_plugin * plugin)
00179 {
00180 cpl_recipe * recipe;
00181
00182
00183 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
00184 recipe = (cpl_recipe *)plugin;
00185 else return -1;
00186
00187 return isaac_spc_wlcalib(recipe->parameters, recipe->frames);
00188 }
00189
00190
00196
00197 static int isaac_spc_wlcalib_destroy(cpl_plugin * plugin)
00198 {
00199 cpl_recipe * recipe;
00200
00201
00202 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
00203 recipe = (cpl_recipe *)plugin;
00204 else return -1;
00205
00206 cpl_parameterlist_delete(recipe->parameters);
00207 return 0;
00208 }
00209
00210
00217
00218 static int isaac_spc_wlcalib(
00219 cpl_parameterlist * parlist,
00220 cpl_frameset * framelist)
00221 {
00222 cpl_parameter * par;
00223 cpl_frame * cur_frame;
00224 const char * cur_fname;
00225 const char * sval;
00226 const char * oh;
00227 const char * xe;
00228 const char * ar;
00229 cpl_table * tab;
00230
00231
00232 par = NULL;
00233
00234
00235
00236 par = cpl_parameterlist_find(parlist, "isaac.isaac_spc_wlcalib.rejected");
00237 sval = cpl_parameter_get_string(par);
00238 if (sscanf(sval, "%d %d %d %d",
00239 &isaac_spc_wlcalib_config.rej_left,
00240 &isaac_spc_wlcalib_config.rej_right,
00241 &isaac_spc_wlcalib_config.rej_bottom,
00242 &isaac_spc_wlcalib_config.rej_top) != 4) {
00243 return -1;
00244 }
00245
00246
00247 par = cpl_parameterlist_find(parlist, "isaac.isaac_spc_wlcalib.max_offset");
00248 isaac_spc_wlcalib_config.max_offset = cpl_parameter_get_int(par);
00249
00250
00251 par = cpl_parameterlist_find(parlist, "isaac.isaac_spc_wlcalib.lines");
00252 isaac_spc_wlcalib_config.lines_table=cpl_parameter_get_int(par);
00253
00254
00255 if (isaac_spc_wlcalib_config.lines_table < 1) {
00256 cpl_msg_error(cpl_func, "Please specify the catalog");
00257 return -1;
00258 }
00259
00260
00261 oh = isaac_extract_filename(framelist, ISAAC_CALPRO_OH_CAT);
00262 xe = isaac_extract_filename(framelist, ISAAC_CALPRO_XE_CAT);
00263 ar = isaac_extract_filename(framelist, ISAAC_CALPRO_AR_CAT);
00264
00265
00266 cur_frame = cpl_frameset_get_frame(framelist, 0);
00267 cur_fname = cpl_frame_get_filename(cur_frame);
00268 cpl_msg_info(cpl_func, "Reduce %s", cur_fname);
00269 cpl_msg_indent_more();
00270
00271
00272 if ((tab = isaac_spc_wlcalib_compute(cur_fname, oh, ar, xe)) == NULL) {
00273 cpl_msg_warning(cpl_func, "cannot reduce");
00274 } else {
00275
00276 if (isaac_spc_wlcalib_save(tab, 1, parlist, framelist) != 0) {
00277 cpl_msg_warning(cpl_func, "cannot save");
00278 }
00279 cpl_table_delete(tab);
00280 }
00281 cpl_msg_indent_less();
00282
00283
00284 return 0;
00285 }
00286
00287
00297
00298 static cpl_table * isaac_spc_wlcalib_compute(
00299 const char * in_name,
00300 const char * oh,
00301 const char * ar,
00302 const char * xe)
00303 {
00304 double slit_width;
00305 int order;
00306 double * phdisprel;
00307 cpl_image * in;
00308 computed_disprel * disprel;
00309 cpl_table * out_tab;
00310 const char * lines_tab;
00311
00312
00313 if ((slit_width = isaac_get_slitwidth(in_name)) == -1) {
00314 cpl_msg_error(cpl_func, "cannot get the slit width");
00315 return NULL;
00316 }
00317
00318
00319 if ((order = isaac_find_order(in_name)) == -1) {
00320 cpl_msg_error(cpl_func, "cannot get the order");
00321 return NULL;
00322 }
00323
00324
00325 cpl_msg_info(cpl_func, "Compute the physical model");
00326 cpl_msg_indent_more();
00327 if ((phdisprel = isaac_get_disprel_estimate(in_name, 3)) == NULL) {
00328 cpl_msg_error(cpl_func, "cannot estimate the dispersion relation");
00329 cpl_msg_indent_less();
00330 return NULL;
00331 }
00332 cpl_msg_info(cpl_func, "f(x)=%g + %g*x + %g*x^2 + %g*x^3",
00333 phdisprel[0], phdisprel[1], phdisprel[2], phdisprel[3]);
00334 cpl_msg_indent_less();
00335
00336
00337 if ((in = cpl_image_load(in_name, CPL_TYPE_FLOAT, 0, 0)) == NULL) {
00338 cpl_msg_error(cpl_func, "cannot load the image");
00339 cpl_free(phdisprel);
00340 return NULL;
00341 }
00342
00343
00344 switch (isaac_spc_wlcalib_config.lines_table) {
00345 case 1: lines_tab = (char*)"oh"; break;
00346 case 2: lines_tab = (char*)"Xe"; break;
00347 case 3: lines_tab = (char*)"Ar"; break;
00348 case 4: lines_tab = (char*)"Xe+Ar"; break;
00349 default:
00350 cpl_image_delete(in);
00351 return NULL;
00352 }
00353 cpl_msg_info(cpl_func, "Compute the dispersion relation");
00354 cpl_msg_indent_more();
00355 if ((disprel = spectro_compute_disprel(in,
00356 isaac_spc_wlcalib_config.rej_bottom,
00357 isaac_spc_wlcalib_config.rej_top,
00358 isaac_spc_wlcalib_config.rej_left,
00359 isaac_spc_wlcalib_config.rej_right,
00360 isaac_spc_wlcalib_config.max_offset,
00361 isaac_has_thermal(in_name) > 0,
00362 lines_tab, oh, ar, xe, slit_width, order,
00363 (int)(cpl_msg_get_level() == CPL_MSG_DEBUG),
00364 phdisprel)) == NULL) {
00365 cpl_msg_error(cpl_func, "cannot compute the dispersion relation");
00366 cpl_image_delete(in);
00367 cpl_free(phdisprel);
00368 cpl_msg_indent_less();
00369 return NULL;
00370 }
00371 cpl_image_delete(in);
00372 cpl_free(phdisprel);
00373
00374 cpl_msg_info(cpl_func, "Cross correlation factor: %g", disprel->cc);
00375 cpl_msg_info(cpl_func, "f(x)=%g + %g*x + %g*x^2 + %g*x^3",
00376 disprel->poly[0], disprel->poly[1], disprel->poly[2],
00377 disprel->poly[3]);
00378 cpl_msg_indent_less();
00379
00380
00381 out_tab = cpl_table_new(4);
00382
00383
00384 cpl_table_new_column(out_tab, "WL_coefficients", CPL_TYPE_DOUBLE);
00385 cpl_table_set_double(out_tab, "WL_coefficients", 0, disprel->poly[0]);
00386 cpl_table_set_double(out_tab, "WL_coefficients", 1, disprel->poly[1]);
00387 cpl_table_set_double(out_tab, "WL_coefficients", 2, disprel->poly[2]);
00388 cpl_table_set_double(out_tab, "WL_coefficients", 3, disprel->poly[3]);
00389 isaac_spc_wlcalib_config.disprel_cc = disprel->cc;
00390 isaac_spc_wlcalib_config.disprel_clines = disprel->clines;
00391 isaac_spc_wlcalib_config.disprel_dlines = disprel->dlines;
00392 isaac_spc_wlcalib_config.disprel_rms = disprel->rms;
00393
00394
00395 if (disprel->poly != NULL) cpl_free(disprel->poly);
00396 cpl_free(disprel);
00397 return out_tab;
00398 }
00399
00400
00409
00410 static int isaac_spc_wlcalib_save(
00411 const cpl_table * tab,
00412 int nb,
00413 cpl_parameterlist * parlist,
00414 cpl_frameset * set)
00415 {
00416 cpl_propertylist * plist;
00417 cpl_propertylist * qclist;
00418 cpl_propertylist * paflist;
00419 const cpl_frame * ref_frame;
00420 const char * sval;
00421 char * filename;
00422
00423
00424 qclist = cpl_propertylist_new();
00425
00426
00427 ref_frame = irplib_frameset_get_first_from_group(set, CPL_FRAME_GROUP_RAW);
00428 if ((plist=cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
00429 0)) == NULL) {
00430 cpl_msg_error(cpl_func, "getting header from reference frame");
00431 cpl_propertylist_delete(qclist);
00432 return -1;
00433 }
00434
00435 if (cpl_error_get_code()) {
00436 cpl_propertylist_delete(qclist);
00437 cpl_propertylist_delete(plist);
00438 return -1;
00439 }
00440 sval = isaac_pfits_get_filter(plist);
00441 if (cpl_error_get_code()) cpl_error_reset();
00442 else cpl_propertylist_append_string(plist, "ESO QC FILTER OBS", sval);
00443 cpl_propertylist_delete(plist);
00444 cpl_propertylist_append_int(plist, "ESO QC LAMP",
00445 isaac_spc_wlcalib_config.lines_table);
00446 cpl_propertylist_append_double(plist, "ESO QC DISP XCORR",
00447 isaac_spc_wlcalib_config.disprel_cc);
00448 cpl_propertylist_append_int(plist, "ESO QC DISP NUMCAT",
00449 isaac_spc_wlcalib_config.disprel_clines);
00450 cpl_propertylist_append_int(plist, "ESO QC DISP NUMMATCH",
00451 isaac_spc_wlcalib_config.disprel_dlines);
00452 cpl_propertylist_append_double(plist, "ESO QC DISP STDEV",
00453 isaac_spc_wlcalib_config.disprel_rms);
00454 cpl_propertylist_append_double(plist, "ESO QC DISPCO1",
00455 cpl_table_get_double(tab, "WL_coefficients", 0, NULL));
00456 cpl_propertylist_append_double(plist, "ESO QC DISPCO2",
00457 cpl_table_get_double(tab, "WL_coefficients", 1, NULL));
00458 cpl_propertylist_append_double(plist, "ESO QC DISPCO3",
00459 cpl_table_get_double(tab, "WL_coefficients", 2, NULL));
00460 cpl_propertylist_append_double(plist, "ESO QC DISPCO4",
00461 cpl_table_get_double(tab, "WL_coefficients", 3, NULL));
00462 cpl_propertylist_append_double(plist, "ESO QC WLEN",
00463 (double)(cpl_table_get_double(tab, "WL_coefficients", 0, NULL) +
00464 512*cpl_table_get_double(tab, "WL_coefficients", 1, NULL) +
00465 512*512*cpl_table_get_double(tab, "WL_coefficients", 2, NULL) +
00466 512*512*512*cpl_table_get_double(tab, "WL_coefficients", 3, NULL)));
00467
00468
00469 filename = cpl_sprintf("isaac_spc_wlcalib_%d.fits", nb);
00470 irplib_dfs_save_table(set,
00471 parlist,
00472 set,
00473 tab,
00474 NULL,
00475 "isaac_spc_wlcalib",
00476 ISAAC_SPC_WLCALIB_RES,
00477 qclist,
00478 NULL,
00479 PACKAGE "/" PACKAGE_VERSION,
00480 filename);
00481 cpl_free(filename);
00482
00483
00484 ref_frame = irplib_frameset_get_first_from_group(set, CPL_FRAME_GROUP_RAW);
00485
00486
00487 if ((plist=cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
00488 0)) == NULL) {
00489 cpl_msg_error(cpl_func, "getting header from reference frame");
00490 cpl_propertylist_delete(qclist);
00491 return -1;
00492 }
00493
00494
00495 paflist = cpl_propertylist_new();
00496 cpl_propertylist_copy_property_regexp(paflist, plist,
00497 "^(ARCFILE|MJD-OBS|INSTRUME|ESO TPL ID|ESO TPL NEXP|ESO DPR CATG|"
00498 "ESO DPR TECH|ESO DPR TYPE|DATE-OBS|ESO INS GRAT NAME|"
00499 "ESO INS GRAT WLEN|ESO INS GRAT ORDER|ESO INS MODE|"
00500 "ESO INS OPTI1 ID)$", 0);
00501 cpl_propertylist_delete(plist);
00502
00503
00504 cpl_propertylist_copy_property_regexp(paflist, qclist, "", 0);
00505 cpl_propertylist_delete(qclist);
00506
00507
00508 cpl_propertylist_update_string(paflist, CPL_DFS_PRO_CATG,
00509 ISAAC_SPC_WLCALIB_RES);
00510
00511
00512 filename = cpl_sprintf("isaac_spc_wlcalib_%d.paf", nb);
00513 cpl_dfs_save_paf("ISAAC",
00514 "isaac_spc_wlcalib",
00515 paflist,
00516 filename);
00517 cpl_free(filename);
00518 cpl_propertylist_delete(paflist);
00519 return 0;
00520 }
00521