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 #include <math.h>
00033 #include <cpl.h>
00034 #include <moses.h>
00035 #include <fors_dfs.h>
00036
00037 static int fors_wave_calib_lss_create(cpl_plugin *);
00038 static int fors_wave_calib_lss_exec(cpl_plugin *);
00039 static int fors_wave_calib_lss_destroy(cpl_plugin *);
00040 static int fors_wave_calib_lss(cpl_parameterlist *, cpl_frameset *);
00041
00042 static char fors_wave_calib_lss_description[] =
00043 "This recipe is used to wavelength calibrate one long slit spectrum, i.e.,\n"
00044 "a FORS spectral obtained either in LSS mode or in MOS/MXU mode with all\n"
00045 "slits at the same offset. A pattern-matching algorithm is applied as in\n"
00046 "recipe fors_detect_spectra. For more details on this data reduction\n"
00047 "strategy please refer to the FORS Pipeline User's Manual.\n"
00048 "\n"
00049 "Note that specifying an input GRISM_TABLE will set some of the recipe\n"
00050 "configuration parameters to default values valid for a particular grism.\n"
00051 "\n"
00052 "In the table below the LSS acronym can be alternatively read as MOS or\n"
00053 "MXU.\n\n"
00054 "Input files:\n\n"
00055 " DO category: Type: Explanation: Required:\n"
00056 " LAMP_UNBIAS_LSS Calib Arc lamp exposure Y\n"
00057 " MASTER_LINECAT Calib Line catalog Y\n"
00058 " GRISM_TABLE Calib Grism table .\n\n"
00059 "Output files:\n\n"
00060 " DO category: Data type: Explanation:\n"
00061 " REDUCED_LAMP_LSS FITS image Calibrated arc lamp exposure\n"
00062 " DISP_COEFF_LSS FITS table Inverse dispersion coefficients\n"
00063 " DISP_RESIDUALS_LSS FITS image Image of modeling residuals\n"
00064 " WAVELENGTH_MAP_LSS FITS image Wavelengths mapped on CCD\n"
00065 " SLIT_LOCATION_LSS FITS image Background subtracted arc frame\n"
00066 " SPECTRAL_RESOLUTION_LSS FITS table Spectral resolution table\n\n";
00067
00068 #define fors_wave_calib_lss_exit(message) \
00069 { \
00070 if ((const char *)message != NULL) cpl_msg_error(recipe, message); \
00071 cpl_image_delete(spectra); \
00072 cpl_image_delete(residual); \
00073 cpl_image_delete(rectified); \
00074 cpl_image_delete(wavemap); \
00075 cpl_table_delete(grism_table); \
00076 cpl_table_delete(wavelengths); \
00077 cpl_table_delete(maskslits); \
00078 cpl_table_delete(idscoeff); \
00079 cpl_table_delete(idscoeff_all); \
00080 cpl_table_delete(restab); \
00081 cpl_table_delete(slits); \
00082 cpl_vector_delete(lines); \
00083 cpl_propertylist_delete(header); \
00084 cpl_propertylist_delete(save_header); \
00085 cpl_msg_indent_less(); \
00086 return -1; \
00087 }
00088
00089 #define fors_wave_calib_lss_exit_memcheck(message) \
00090 { \
00091 if ((const char *)message != NULL) cpl_msg_info(recipe, message); \
00092 printf("free spectra (%p)\n", spectra); \
00093 cpl_image_delete(spectra); \
00094 printf("free residual (%p)\n", residual); \
00095 cpl_image_delete(residual); \
00096 printf("free rectified (%p)\n", rectified); \
00097 cpl_image_delete(rectified); \
00098 printf("free wavemap (%p)\n", wavemap); \
00099 cpl_image_delete(wavemap); \
00100 printf("free grism_table (%p)\n", grism_table); \
00101 cpl_table_delete(grism_table); \
00102 printf("free wavelengths (%p)\n", wavelengths); \
00103 cpl_table_delete(wavelengths); \
00104 printf("free maskslits (%p)\n", maskslits); \
00105 cpl_table_delete(maskslits); \
00106 printf("free idscoeff (%p)\n", idscoeff); \
00107 cpl_table_delete(idscoeff); \
00108 printf("free idscoeff_all (%p)\n", idscoeff_all); \
00109 cpl_table_delete(idscoeff_all); \
00110 printf("free restab (%p)\n", restab); \
00111 cpl_table_delete(restab); \
00112 printf("free slits (%p)\n", slits); \
00113 cpl_table_delete(slits); \
00114 printf("free lines (%p)\n", lines); \
00115 cpl_vector_delete(lines); \
00116 printf("free header (%p)\n", header); \
00117 cpl_propertylist_delete(header); \
00118 printf("free save_header (%p)\n", save_header); \
00119 cpl_propertylist_delete(save_header); \
00120 cpl_msg_indent_less(); \
00121 return 0; \
00122 }
00123
00124
00136 int cpl_plugin_get_info(cpl_pluginlist *list)
00137 {
00138 cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe );
00139 cpl_plugin *plugin = &recipe->interface;
00140
00141 cpl_plugin_init(plugin,
00142 CPL_PLUGIN_API,
00143 FORS_BINARY_VERSION,
00144 CPL_PLUGIN_TYPE_RECIPE,
00145 "fors_wave_calib_lss",
00146 "Derive dispersion relation from long-slit arc lamp frame",
00147 fors_wave_calib_lss_description,
00148 "Carlo Izzo",
00149 PACKAGE_BUGREPORT,
00150 "This file is currently part of the FORS Instrument Pipeline\n"
00151 "Copyright (C) 2002-2010 European Southern Observatory\n\n"
00152 "This program is free software; you can redistribute it and/or modify\n"
00153 "it under the terms of the GNU General Public License as published by\n"
00154 "the Free Software Foundation; either version 2 of the License, or\n"
00155 "(at your option) any later version.\n\n"
00156 "This program is distributed in the hope that it will be useful,\n"
00157 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
00158 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
00159 "GNU General Public License for more details.\n\n"
00160 "You should have received a copy of the GNU General Public License\n"
00161 "along with this program; if not, write to the Free Software Foundation,\n"
00162 "Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\n",
00163 fors_wave_calib_lss_create,
00164 fors_wave_calib_lss_exec,
00165 fors_wave_calib_lss_destroy);
00166
00167 cpl_pluginlist_append(list, plugin);
00168
00169 return 0;
00170 }
00171
00172
00183 static int fors_wave_calib_lss_create(cpl_plugin *plugin)
00184 {
00185 cpl_recipe *recipe;
00186 cpl_parameter *p;
00187
00188
00189
00190
00191
00192 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
00193 recipe = (cpl_recipe *)plugin;
00194 else
00195 return -1;
00196
00197
00198
00199
00200
00201 recipe->parameters = cpl_parameterlist_new();
00202
00203
00204
00205
00206
00207 p = cpl_parameter_new_value("fors.fors_wave_calib_lss.dispersion",
00208 CPL_TYPE_DOUBLE,
00209 "Expected spectral dispersion (Angstrom/pixel)",
00210 "fors.fors_wave_calib_lss",
00211 0.0);
00212 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "dispersion");
00213 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00214 cpl_parameterlist_append(recipe->parameters, p);
00215
00216
00217
00218
00219
00220 p = cpl_parameter_new_value("fors.fors_wave_calib_lss.peakdetection",
00221 CPL_TYPE_DOUBLE,
00222 "Initial peak detection threshold (ADU)",
00223 "fors.fors_wave_calib_lss",
00224 0.0);
00225 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "peakdetection");
00226 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00227 cpl_parameterlist_append(recipe->parameters, p);
00228
00229
00230
00231
00232
00233 p = cpl_parameter_new_value("fors.fors_wave_calib_lss.wdegree",
00234 CPL_TYPE_INT,
00235 "Degree of wavelength calibration polynomial",
00236 "fors.fors_wave_calib_lss",
00237 0);
00238 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wdegree");
00239 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00240 cpl_parameterlist_append(recipe->parameters, p);
00241
00242
00243
00244
00245
00246 p = cpl_parameter_new_value("fors.fors_wave_calib_lss.wradius",
00247 CPL_TYPE_INT,
00248 "Search radius if iterating pattern-matching "
00249 "with first-guess method",
00250 "fors.fors_wave_calib_lss",
00251 4);
00252 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wradius");
00253 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00254 cpl_parameterlist_append(recipe->parameters, p);
00255
00256
00257
00258
00259
00260 p = cpl_parameter_new_value("fors.fors_wave_calib_lss.wreject",
00261 CPL_TYPE_DOUBLE,
00262 "Rejection threshold in dispersion "
00263 "relation fit (pixel)",
00264 "fors.fors_wave_calib_lss",
00265 0.7);
00266 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wreject");
00267 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00268 cpl_parameterlist_append(recipe->parameters, p);
00269
00270
00271
00272
00273
00274 p = cpl_parameter_new_value("fors.fors_wave_calib_lss.wcolumn",
00275 CPL_TYPE_STRING,
00276 "Name of line catalog table column "
00277 "with wavelengths",
00278 "fors.fors_wave_calib_lss",
00279 "WLEN");
00280 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcolumn");
00281 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00282 cpl_parameterlist_append(recipe->parameters, p);
00283
00284
00285
00286
00287
00288 p = cpl_parameter_new_value("fors.fors_wave_calib_lss.startwavelength",
00289 CPL_TYPE_DOUBLE,
00290 "Start wavelength in spectral extraction",
00291 "fors.fors_wave_calib_lss",
00292 0.0);
00293 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "startwavelength");
00294 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00295 cpl_parameterlist_append(recipe->parameters, p);
00296
00297
00298
00299
00300
00301 p = cpl_parameter_new_value("fors.fors_wave_calib_lss.endwavelength",
00302 CPL_TYPE_DOUBLE,
00303 "End wavelength in spectral extraction",
00304 "fors.fors_wave_calib_lss",
00305 0.0);
00306 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "endwavelength");
00307 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00308 cpl_parameterlist_append(recipe->parameters, p);
00309
00310
00311
00312
00313
00314 p = cpl_parameter_new_value("fors.fors_wave_calib_lss.wmode",
00315 CPL_TYPE_INT,
00316 "Interpolation mode of wavelength solution "
00317 "(0 = no interpolation, 1 = fill gaps, "
00318 "2 = global model)",
00319 "fors.fors_wave_calib_lss",
00320 2);
00321 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wmode");
00322 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00323 cpl_parameterlist_append(recipe->parameters, p);
00324
00325 return 0;
00326 }
00327
00328
00337 static int fors_wave_calib_lss_exec(cpl_plugin *plugin)
00338 {
00339 cpl_recipe *recipe;
00340
00341 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
00342 recipe = (cpl_recipe *)plugin;
00343 else
00344 return -1;
00345
00346 return fors_wave_calib_lss(recipe->parameters, recipe->frames);
00347 }
00348
00349
00358 static int fors_wave_calib_lss_destroy(cpl_plugin *plugin)
00359 {
00360 cpl_recipe *recipe;
00361
00362 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
00363 recipe = (cpl_recipe *)plugin;
00364 else
00365 return -1;
00366
00367 cpl_parameterlist_delete(recipe->parameters);
00368
00369 return 0;
00370 }
00371
00372
00382 static int fors_wave_calib_lss(cpl_parameterlist *parlist,
00383 cpl_frameset *frameset)
00384 {
00385
00386 const char *recipe = "fors_wave_calib_lss";
00387
00388
00389
00390
00391
00392
00393 double dispersion;
00394 double peakdetection;
00395 int wdegree;
00396 int wradius;
00397 double wreject;
00398 int wmode;
00399 const char *wcolumn;
00400 double startwavelength;
00401 double endwavelength;
00402
00403
00404
00405
00406
00407 cpl_image *spectra = NULL;
00408 cpl_image *rectified = NULL;
00409 cpl_image *wavemap = NULL;
00410 cpl_image *residual = NULL;
00411 cpl_image *dummy = NULL;
00412 cpl_table *grism_table = NULL;
00413 cpl_table *wavelengths = NULL;
00414 cpl_table *slits = NULL;
00415 cpl_table *idscoeff = NULL;
00416 cpl_table *idscoeff_all = NULL;
00417 cpl_table *maskslits = NULL;
00418 cpl_table *restab = NULL;
00419 cpl_vector *lines = NULL;
00420 cpl_propertylist *header = NULL;
00421 cpl_propertylist *save_header = NULL;
00422
00423
00424
00425
00426
00427 char version[80];
00428 const char *arc_tag;
00429 const char *reduced_lamp_tag;
00430 const char *wavelength_map_tag;
00431 const char *disp_residuals_tag;
00432 const char *disp_coeff_tag;
00433 const char *slit_location_tag;
00434 const char *spectral_resolution_tag;
00435 int mxu;
00436 int mos;
00437 int lss;
00438 int treat_as_lss = 0;
00439 double mean_rms;
00440 int narc;
00441 int nlines;
00442 int rebin;
00443 double *line;
00444 double *fiterror = NULL;
00445 int *fitlines = NULL;
00446 int nx, ny;
00447 int first_row, last_row;
00448 int ylow, yhig;
00449 double reference;
00450 int i;
00451
00452 char *instrume = NULL;
00453
00454
00455 cpl_msg_set_indentation(2);
00456
00457
00458
00459
00460
00461 cpl_msg_info(recipe, "Recipe %s configuration parameters:", recipe);
00462 cpl_msg_indent_more();
00463
00464 if (cpl_frameset_count_tags(frameset, "GRISM_TABLE") > 1)
00465 fors_wave_calib_lss_exit("Too many in input: GRISM_TABLE");
00466
00467 grism_table = dfs_load_table(frameset, "GRISM_TABLE", 1);
00468
00469 dispersion = dfs_get_parameter_double(parlist,
00470 "fors.fors_wave_calib_lss.dispersion", grism_table);
00471
00472 if (dispersion <= 0.0)
00473 fors_wave_calib_lss_exit("Invalid spectral dispersion value");
00474
00475 peakdetection = dfs_get_parameter_double(parlist,
00476 "fors.fors_wave_calib_lss.peakdetection", grism_table);
00477 if (peakdetection <= 0.0)
00478 fors_wave_calib_lss_exit("Invalid peak detection level");
00479
00480 wdegree = dfs_get_parameter_int(parlist,
00481 "fors.fors_wave_calib_lss.wdegree", grism_table);
00482
00483 if (wdegree < 1)
00484 fors_wave_calib_lss_exit("Invalid polynomial degree");
00485
00486 if (wdegree > 5)
00487 fors_wave_calib_lss_exit("Max allowed polynomial degree is 5");
00488
00489 wradius = dfs_get_parameter_int(parlist,
00490 "fors.fors_wave_calib_lss.wradius", NULL);
00491
00492 if (wradius < 0)
00493 fors_wave_calib_lss_exit("Invalid search radius");
00494
00495 wreject = dfs_get_parameter_double(parlist,
00496 "fors.fors_wave_calib_lss.wreject", NULL);
00497
00498 if (wreject <= 0.0)
00499 fors_wave_calib_lss_exit("Invalid rejection threshold");
00500
00501 wmode = dfs_get_parameter_int(parlist,
00502 "fors.fors_wave_calib_lss.wmode", NULL);
00503
00504 if (wmode < 0 || wmode > 2)
00505 fors_wave_calib_lss_exit("Invalid interpolation mode");
00506
00507 wcolumn = dfs_get_parameter_string(parlist,
00508 "fors.fors_wave_calib_lss.wcolumn", NULL);
00509
00510 startwavelength = dfs_get_parameter_double(parlist,
00511 "fors.fors_wave_calib_lss.startwavelength", grism_table);
00512 if (startwavelength > 1.0)
00513 if (startwavelength < 3000.0 || startwavelength > 13000.0)
00514 fors_wave_calib_lss_exit("Invalid wavelength");
00515
00516 endwavelength = dfs_get_parameter_double(parlist,
00517 "fors.fors_wave_calib_lss.endwavelength", grism_table);
00518 if (endwavelength > 1.0) {
00519 if (endwavelength < 3000.0 || endwavelength > 13000.0)
00520 fors_wave_calib_lss_exit("Invalid wavelength");
00521 if (startwavelength < 1.0)
00522 fors_wave_calib_lss_exit("Invalid wavelength interval");
00523 }
00524
00525 if (startwavelength > 1.0)
00526 if (endwavelength - startwavelength <= 0.0)
00527 fors_wave_calib_lss_exit("Invalid wavelength interval");
00528
00529 cpl_table_delete(grism_table); grism_table = NULL;
00530
00531 if (cpl_error_get_code())
00532 fors_wave_calib_lss_exit("Failure reading the configuration "
00533 "parameters");
00534
00535
00536 cpl_msg_indent_less();
00537 cpl_msg_info(recipe, "Check input set-of-frames:");
00538 cpl_msg_indent_more();
00539
00540 if (cpl_frameset_count_tags(frameset, "MASTER_LINECAT") == 0)
00541 fors_wave_calib_lss_exit("Missing required input: MASTER_LINECAT");
00542
00543 if (cpl_frameset_count_tags(frameset, "MASTER_LINECAT") > 1)
00544 fors_wave_calib_lss_exit("Too many in input: MASTER_LINECAT");
00545
00546 mxu = cpl_frameset_count_tags(frameset, "LAMP_UNBIAS_MXU");
00547 mos = cpl_frameset_count_tags(frameset, "LAMP_UNBIAS_MOS");
00548 lss = cpl_frameset_count_tags(frameset, "LAMP_UNBIAS_LSS");
00549
00550 narc = mxu + mos + lss;
00551
00552 if (narc == 0) {
00553 fors_wave_calib_lss_exit("Missing input long-slit arc lamp frame");
00554 }
00555 if (narc > 1) {
00556 cpl_msg_error(recipe, "Too many input arc lamp frames (%d > 1)", narc);
00557 fors_wave_calib_lss_exit(NULL);
00558 }
00559
00560 if (mxu) {
00561 arc_tag = "LAMP_UNBIAS_MXU";
00562 slit_location_tag = "SLIT_LOCATION_MXU";
00563 reduced_lamp_tag = "REDUCED_LAMP_MXU";
00564 disp_residuals_tag = "DISP_RESIDUALS_MXU";
00565 disp_coeff_tag = "DISP_COEFF_MXU";
00566 wavelength_map_tag = "WAVELENGTH_MAP_MXU";
00567 spectral_resolution_tag = "SPECTRAL_RESOLUTION_MXU";
00568 }
00569 else if (mos) {
00570 arc_tag = "LAMP_UNBIAS_MOS";
00571 slit_location_tag = "SLIT_LOCATION_MOS";
00572 reduced_lamp_tag = "REDUCED_LAMP_MOS";
00573 disp_residuals_tag = "DISP_RESIDUALS_MOS";
00574 disp_coeff_tag = "DISP_COEFF_MOS";
00575 wavelength_map_tag = "WAVELENGTH_MAP_MOS";
00576 spectral_resolution_tag = "SPECTRAL_RESOLUTION_MOS";
00577 }
00578 else if (lss) {
00579 arc_tag = "LAMP_UNBIAS_LSS";
00580 slit_location_tag = "SLIT_LOCATION_LSS";
00581 reduced_lamp_tag = "REDUCED_LAMP_LSS";
00582 disp_residuals_tag = "DISP_RESIDUALS_LSS";
00583 disp_coeff_tag = "DISP_COEFF_LSS";
00584 wavelength_map_tag = "WAVELENGTH_MAP_LSS";
00585 spectral_resolution_tag = "SPECTRAL_RESOLUTION_LSS";
00586 }
00587
00588
00589 if (!dfs_equal_keyword(frameset, "ESO INS GRIS1 ID"))
00590 cpl_msg_warning(cpl_func,"Input frames are not from the same grism");
00591
00592 if (!dfs_equal_keyword(frameset, "ESO INS FILT1 ID"))
00593 cpl_msg_warning(cpl_func,"Input frames are not from the same filter");
00594
00595 if (!dfs_equal_keyword(frameset, "ESO DET CHIP1 ID"))
00596 cpl_msg_warning(cpl_func,"Input frames are not from the same chip");
00597
00598
00599
00600
00601
00602
00603
00604 header = dfs_load_header(frameset, arc_tag, 0);
00605
00606 if (header == NULL)
00607 fors_wave_calib_lss_exit("Cannot load arc lamp header");
00608
00609 instrume = (char *)cpl_propertylist_get_string(header, "INSTRUME");
00610 if (instrume == NULL)
00611 fors_wave_calib_lss_exit("Missing keyword INSTRUME in arc lamp header");
00612
00613 if (instrume[4] == '1')
00614 snprintf(version, 80, "%s/%s", "fors1", VERSION);
00615 if (instrume[4] == '2')
00616 snprintf(version, 80, "%s/%s", "fors2", VERSION);
00617
00618 reference = cpl_propertylist_get_double(header, "ESO INS GRIS1 WLEN");
00619
00620 if (cpl_error_get_code() != CPL_ERROR_NONE)
00621 fors_wave_calib_lss_exit("Missing keyword ESO INS GRIS1 WLEN "
00622 "in arc lamp frame header");
00623
00624 if (reference < 3000.0)
00625 reference *= 10;
00626
00627 if (reference < 3000.0 || reference > 13000.0) {
00628 cpl_msg_error(recipe, "Invalid central wavelength %.2f read from "
00629 "keyword ESO INS GRIS1 WLEN in arc lamp frame header",
00630 reference);
00631 fors_wave_calib_lss_exit(NULL);
00632 }
00633
00634 cpl_msg_info(recipe, "The central wavelength is: %.2f", reference);
00635
00636 rebin = cpl_propertylist_get_int(header, "ESO DET WIN1 BINX");
00637
00638 if (cpl_error_get_code() != CPL_ERROR_NONE)
00639 fors_wave_calib_lss_exit("Missing keyword ESO DET WIN1 BINX "
00640 "in arc lamp frame header");
00641
00642 if (rebin != 1) {
00643 dispersion *= rebin;
00644 cpl_msg_warning(recipe, "The rebin factor is %d, and therefore the "
00645 "working dispersion used is %f A/pixel", rebin,
00646 dispersion);
00647 }
00648
00649
00650 if (mos || mxu) {
00651
00652 int nslits_out_det = 0;
00653
00654
00655
00656
00657
00658
00659 if (mos)
00660 maskslits = mos_load_slits_fors_mos(header, &nslits_out_det);
00661 else
00662 maskslits = mos_load_slits_fors_mxu(header);
00663
00664 treat_as_lss = fors_mos_is_lss_like(maskslits, nslits_out_det);
00665
00666 cpl_table_delete(maskslits); maskslits = NULL;
00667
00668 if (!treat_as_lss)
00669 fors_wave_calib_lss_exit("Input data are not long-slit data");
00670 }
00671
00672
00673 cpl_msg_indent_less();
00674 cpl_msg_info(recipe, "Load arc lamp exposure...");
00675 cpl_msg_indent_more();
00676
00677 spectra = dfs_load_image(frameset, arc_tag, CPL_TYPE_FLOAT, 0, 0);
00678
00679 if (spectra == NULL)
00680 fors_wave_calib_lss_exit("Cannot load arc lamp exposure");
00681
00682
00683 cpl_msg_indent_less();
00684 cpl_msg_info(recipe, "Load input line catalog...");
00685 cpl_msg_indent_more();
00686
00687 wavelengths = dfs_load_table(frameset, "MASTER_LINECAT", 1);
00688
00689 if (wavelengths == NULL)
00690 fors_wave_calib_lss_exit("Cannot load line catalog");
00691
00692
00693
00694
00695
00696
00697 nlines = cpl_table_get_nrow(wavelengths);
00698
00699 if (nlines == 0)
00700 fors_wave_calib_lss_exit("Empty input line catalog");
00701
00702 if (cpl_table_has_column(wavelengths, wcolumn) != 1) {
00703 cpl_msg_error(recipe, "Missing column %s in input line catalog table",
00704 wcolumn);
00705 fors_wave_calib_lss_exit(NULL);
00706 }
00707
00708 line = cpl_malloc(nlines * sizeof(double));
00709
00710 for (i = 0; i < nlines; i++)
00711 line[i] = cpl_table_get(wavelengths, wcolumn, i, NULL);
00712
00713 cpl_table_delete(wavelengths); wavelengths = NULL;
00714
00715 lines = cpl_vector_wrap(nlines, line);
00716
00717
00718 cpl_msg_indent_less();
00719 cpl_msg_info(recipe, "Perform wavelength calibration...");
00720 cpl_msg_indent_more();
00721
00722 nx = cpl_image_get_size_x(spectra);
00723 ny = cpl_image_get_size_y(spectra);
00724
00725 wavemap = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
00726 idscoeff_all = cpl_table_new(ny);
00727
00728 if (mos_saturation_process(spectra))
00729 fors_wave_calib_lss_exit("Cannot process saturation");
00730
00731 if (mos_subtract_background(spectra))
00732 fors_wave_calib_lss_exit("Cannot subtract the background");
00733
00734 rectified = mos_wavelength_calibration_raw(spectra, lines, dispersion,
00735 peakdetection, wradius,
00736 wdegree, wreject, reference,
00737 &startwavelength,
00738 &endwavelength, NULL,
00739 NULL, idscoeff_all, wavemap,
00740 NULL, NULL, NULL, NULL);
00741
00742 if (rectified == NULL)
00743 fors_wave_calib_lss_exit("Wavelength calibration failure.");
00744
00745 cpl_image_delete(rectified); rectified = NULL;
00746
00747 first_row = 0;
00748 while (!cpl_table_is_valid(idscoeff_all, "c0", first_row))
00749 first_row++;
00750
00751 last_row = ny - 1;
00752 while (!cpl_table_is_valid(idscoeff_all, "c0", last_row))
00753 last_row--;
00754
00755 ylow = first_row + 1;
00756 yhig = last_row + 1;
00757
00758 dummy = cpl_image_extract(spectra, 1, ylow, nx, yhig);
00759 cpl_image_delete(spectra); spectra = dummy;
00760
00761 ny = cpl_image_get_size_y(spectra);
00762
00763 residual = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
00764
00765 fiterror = cpl_calloc(ny, sizeof(double));
00766 fitlines = cpl_calloc(ny, sizeof(int));
00767 idscoeff = cpl_table_new(ny);
00768
00769 if (mos_saturation_process(spectra))
00770 fors_wave_calib_lss_exit("Cannot process saturation");
00771
00772 if (mos_subtract_background(spectra))
00773 fors_wave_calib_lss_exit("Cannot subtract the background");
00774
00775 rectified = mos_wavelength_calibration_raw(spectra, lines, dispersion,
00776 peakdetection, wradius,
00777 wdegree, wreject, reference,
00778 &startwavelength,
00779 &endwavelength, fitlines,
00780 fiterror, idscoeff, NULL,
00781 residual, NULL, NULL, NULL);
00782
00783 if (rectified == NULL)
00784 fors_wave_calib_lss_exit("Wavelength calibration failure.");
00785
00786
00787
00788
00789
00790 slits = cpl_table_new(1);
00791 cpl_table_new_column(slits, "slit_id", CPL_TYPE_INT);
00792 cpl_table_new_column(slits, "xtop", CPL_TYPE_DOUBLE);
00793 cpl_table_new_column(slits, "ytop", CPL_TYPE_DOUBLE);
00794 cpl_table_new_column(slits, "xbottom", CPL_TYPE_DOUBLE);
00795 cpl_table_new_column(slits, "ybottom", CPL_TYPE_DOUBLE);
00796 cpl_table_new_column(slits, "position", CPL_TYPE_INT);
00797 cpl_table_new_column(slits, "length", CPL_TYPE_INT);
00798 cpl_table_set_column_unit(slits, "xtop", "pixel");
00799 cpl_table_set_column_unit(slits, "ytop", "pixel");
00800 cpl_table_set_column_unit(slits, "xbottom", "pixel");
00801 cpl_table_set_column_unit(slits, "ybottom", "pixel");
00802 cpl_table_set_column_unit(slits, "position", "pixel");
00803 cpl_table_set_column_unit(slits, "length", "pixel");
00804 cpl_table_set_int(slits, "slit_id", 0, 0);
00805 cpl_table_set_double(slits, "xtop", 0, 0);
00806 cpl_table_set_double(slits, "ytop", 0, last_row);
00807 cpl_table_set_double(slits, "xbottom", 0, 0);
00808 cpl_table_set_double(slits, "ybottom", 0, first_row);
00809 cpl_table_set_int(slits, "position", 0, 0);
00810 cpl_table_set_int(slits, "length", 0, ny);
00811
00812 if (dfs_save_table(frameset, slits, slit_location_tag, NULL,
00813 parlist, recipe, version))
00814 fors_wave_calib_lss_exit(NULL);
00815
00816 cpl_table_delete(slits); slits = NULL;
00817
00818 if (wmode) {
00819 cpl_image_delete(rectified); rectified = NULL;
00820 cpl_image_delete(wavemap); wavemap = NULL;
00821
00822
00823
00824
00825
00826 mos_interpolate_wavecalib(idscoeff, wavemap, wmode, 2);
00827 mos_interpolate_wavecalib(idscoeff_all, wavemap, wmode, 2);
00828
00829 wavemap = mos_map_idscoeff(idscoeff_all, nx, reference,
00830 startwavelength, endwavelength);
00831 rectified = mos_wavelength_calibration(spectra, reference,
00832 startwavelength,
00833 endwavelength, dispersion,
00834 idscoeff, 0);
00835 }
00836
00837 cpl_table_delete(idscoeff_all); idscoeff_all = NULL;
00838
00839 cpl_table_wrap_double(idscoeff, fiterror, "error"); fiterror = NULL;
00840 cpl_table_set_column_unit(idscoeff, "error", "pixel");
00841 cpl_table_wrap_int(idscoeff, fitlines, "nlines"); fitlines = NULL;
00842
00843 for (i = 0; i < ny; i++)
00844 if (!cpl_table_is_valid(idscoeff, "c0", i))
00845 cpl_table_set_invalid(idscoeff, "error", i);
00846
00847 cpl_msg_info(recipe, "Valid solutions found: %d out of %d rows",
00848 ny - cpl_table_count_invalid(idscoeff, "c0"), ny);
00849
00850 cpl_image_delete(spectra); spectra = NULL;
00851
00852 mean_rms = mos_distortions_rms(rectified, lines, startwavelength,
00853 dispersion, 6, 0);
00854
00855 cpl_msg_info(recipe, "Mean residual: %f pixel", mean_rms);
00856
00857 mean_rms = cpl_table_get_column_mean(idscoeff, "error");
00858
00859 cpl_msg_info(recipe, "Mean model accuracy: %f pixel (%f A)",
00860 mean_rms, mean_rms * dispersion);
00861
00862 restab = mos_resolution_table(rectified, startwavelength, dispersion,
00863 60000, lines);
00864
00865 if (restab) {
00866 cpl_msg_info(recipe, "Mean spectral resolution: %.2f",
00867 cpl_table_get_column_mean(restab, "resolution"));
00868 cpl_msg_info(recipe,
00869 "Mean reference lines FWHM: %.2f +/- %.2f pixel",
00870 cpl_table_get_column_mean(restab, "fwhm") / dispersion,
00871 cpl_table_get_column_mean(restab, "fwhm_rms") / dispersion);
00872
00873 if (dfs_save_table(frameset, restab, spectral_resolution_tag,
00874 NULL, parlist, recipe, version))
00875 fors_wave_calib_lss_exit(NULL);
00876
00877 cpl_table_delete(restab); restab = NULL;
00878
00879 }
00880 else
00881 fors_wave_calib_lss_exit("Cannot compute the spectral "
00882 "resolution table");
00883
00884 cpl_vector_delete(lines); lines = NULL;
00885
00886
00887
00888
00889
00890
00891 save_header = cpl_propertylist_new();
00892 cpl_propertylist_update_double(save_header, "CRPIX1", 1.0);
00893 cpl_propertylist_update_double(save_header, "CRPIX2", 1.0);
00894 cpl_propertylist_update_double(save_header, "CRVAL1",
00895 startwavelength + dispersion/2);
00896 cpl_propertylist_update_double(save_header, "CRVAL2", 1.0);
00897
00898
00899 cpl_propertylist_update_double(save_header, "CD1_1", dispersion);
00900 cpl_propertylist_update_double(save_header, "CD1_2", 0.0);
00901 cpl_propertylist_update_double(save_header, "CD2_1", 0.0);
00902 cpl_propertylist_update_double(save_header, "CD2_2", 1.0);
00903 cpl_propertylist_update_string(save_header, "CTYPE1", "LINEAR");
00904 cpl_propertylist_update_string(save_header, "CTYPE2", "PIXEL");
00905 cpl_propertylist_update_int(save_header, "ESO PRO DATANCOM", 1);
00906
00907 if (dfs_save_image(frameset, rectified, reduced_lamp_tag, save_header,
00908 parlist, recipe, version))
00909 fors_wave_calib_lss_exit(NULL);
00910
00911 cpl_image_delete(rectified); rectified = NULL;
00912 cpl_propertylist_delete(save_header); save_header = NULL;
00913
00914 if (dfs_save_table(frameset, idscoeff, disp_coeff_tag, NULL,
00915 parlist, recipe, version))
00916 fors_wave_calib_lss_exit(NULL);
00917
00918 cpl_table_delete(idscoeff); idscoeff = NULL;
00919
00920 if (dfs_save_image(frameset, wavemap, wavelength_map_tag, header,
00921 parlist, recipe, version))
00922 fors_wave_calib_lss_exit(NULL);
00923
00924 cpl_image_delete(wavemap); wavemap = NULL;
00925 cpl_propertylist_delete(header); header = NULL;
00926 header = cpl_propertylist_new();
00927
00928 cpl_propertylist_update_double(header, "CRPIX2", 1.0);
00929 cpl_propertylist_update_double(header, "CRVAL2", 1.0);
00930
00931 cpl_propertylist_update_double(header, "CD1_1", 1.0);
00932 cpl_propertylist_update_double(header, "CD1_2", 0.0);
00933 cpl_propertylist_update_double(header, "CD2_1", 0.0);
00934 cpl_propertylist_update_double(header, "CD2_2", 1.0);
00935 cpl_propertylist_update_string(header, "CTYPE1", "LINEAR");
00936 cpl_propertylist_update_string(header, "CTYPE2", "PIXEL");
00937
00938 if (dfs_save_image(frameset, residual, disp_residuals_tag, header,
00939 parlist, recipe, version))
00940 fors_wave_calib_lss_exit(NULL);
00941
00942 cpl_image_delete(residual); residual = NULL;
00943 cpl_propertylist_delete(header); header = NULL;
00944
00945 return 0;
00946 }