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 <string.h>
00034 #include <ctype.h>
00035 #include <cpl.h>
00036 #include <moses.h>
00037 #include <fors_stack.h>
00038 #include <fors_dfs.h>
00039 #include <fors_qc.h>
00040
00041 #define OFFSET 50
00042 #define TOLERANCE 10
00043
00044 static int fors_pmos_calib_create(cpl_plugin *);
00045 static int fors_pmos_calib_exec(cpl_plugin *);
00046 static int fors_pmos_calib_destroy(cpl_plugin *);
00047 static int fors_pmos_calib(cpl_parameterlist *, cpl_frameset *);
00048
00049 static char fors_pmos_calib_description[] =
00050 "This recipe is used to identify reference lines on PMOS arc lamp\n"
00051 "exposures, and trace the spectral edges on the corresponding flat field\n"
00052 "exposures. This information is used to determine the spectral extraction\n"
00053 "mask to be applied in the scientific data reduction, performed with the\n"
00054 "recipe fors_science.\n"
00055 "This recipe accepts both FORS1 and FORS2 frames. The input arc lamps and\n"
00056 "flat field exposures are assumed to be obtained quasi-simultaneously, so\n"
00057 "that they would be described by exactly the same instrument distortions.\n"
00058 "A line catalog must be specified, containing the wavelengths of the\n"
00059 "reference arc lamp lines used for the wavelength calibration. A grism\n"
00060 "table (typically depending on the instrument mode, and in particular on\n"
00061 "the grism used) may also be specified: this table contains a default\n"
00062 "recipe parameter setting to control the way spectra are extracted for\n"
00063 "a specific instrument mode, as it is used for automatic run of the\n"
00064 "pipeline on Paranal and in Garching. If this table is specified, it\n"
00065 "will modify the default recipe parameter setting, with the exception of\n"
00066 "those parameters which have been explicitly modifyed on the command line.\n"
00067 "If a grism table is not specified, the input recipe parameters values\n"
00068 "will always be read from the command line, or from an esorex configuration\n"
00069 "file if present, or from their generic default values (that are rarely\n"
00070 "meaningful). Finally a master bias frame must be input to this recipe.\n"
00071 "The products SPECTRA_DETECTION_PMOS, SLIT_MAP_PMOS, and DISP_RESIDUALS_PMOS,\n"
00072 "are just created if the --check parameter is set to true.\n"
00073 "The MASTER_DISTORTION_TABLE is marked as required, but it is not so if all\n"
00074 "slits have different offsets, and in the case of FORS1 observations made\n"
00075 "with the old TK2048EB4-1 1604 chip read in windowed mode (2048x400)\n\n"
00076 "Input files:\n\n"
00077 " DO category: Type: Explanation: Required:\n"
00078 " SCREEN_FLAT_PMOS Raw Flat field exposures Y\n"
00079 " LAMP_PMOS Raw Arc lamp exposure Y\n"
00080 " MASTER_BIAS or BIAS Calib Bias frame Y\n"
00081 " MASTER_LINECAT Calib Line catalog Y\n"
00082 " GRISM_TABLE Calib Grism table .\n"
00083 " MASTER_DISTORTION_TABLE Calib Master distortions table Y\n\n"
00084 "Output files:\n\n"
00085 " DO category: Data type: Explanation:\n"
00086 " MASTER_SCREEN_FLAT_PMOS FITS image Combined (sum) flat field\n"
00087 " MASTER_NORM_FLAT_PMOS FITS image Normalised flat field\n"
00088 " MAPPED_SCREEN_FLAT_PMOS FITS image Wavelength calibrated flat field\n"
00089 " MAPPED_NORM_FLAT_PMOS FITS image Wavelength calibrated normalised flat\n"
00090 " REDUCED_LAMP_PMOS FITS image Wavelength calibrated arc spectrum\n"
00091 " DISP_COEFF_PMOS FITS table Inverse dispersion coefficients\n"
00092 " DISP_RESIDUALS_PMOS FITS image Residuals in wavelength calibration\n"
00093 " DISP_RESIDUALS_TABLE_PMOS FITS table Residuals in wavelength calibration\n"
00094 " DELTA_IMAGE_PMOS FITS image Offset vs linear wavelength calib\n"
00095 " WAVELENGTH_MAP_PMOS FITS image Wavelength for each pixel on CCD\n"
00096 " SPECTRA_DETECTION_PMOS FITS image Check for preliminary detection\n"
00097 " SLIT_MAP_PMOS FITS image Map of central wavelength on CCD\n"
00098 " CURV_TRACES_PMOS FITS table Spectral curvature traces\n"
00099 " CURV_COEFF_PMOS FITS table Spectral curvature coefficients\n"
00100 " SPATIAL_MAP_PMOS FITS image Spatial position along slit on CCD\n"
00101 " SPECTRAL_RESOLUTION_PMOS FITS table Resolution at reference arc lines\n"
00102 " SLIT_LOCATION_PMOS FITS table Slits on product frames and CCD\n\n";
00103
00104 #define fors_pmos_calib_exit(message) \
00105 { \
00106 if (message) cpl_msg_error(recipe, message); \
00107 cpl_free(instrume); \
00108 cpl_free(pipefile); \
00109 cpl_free(fiterror); \
00110 cpl_free(fitlines); \
00111 cpl_image_delete(bias); \
00112 cpl_image_delete(master_bias); \
00113 cpl_image_delete(coordinate); \
00114 cpl_image_delete(checkwave); \
00115 cpl_image_delete(flat); \
00116 cpl_image_delete(master_flat); \
00117 cpl_image_delete(added_flat); \
00118 cpl_image_delete(norm_flat); \
00119 cpl_image_delete(mapped_flat); \
00120 cpl_image_delete(mapped_nflat); \
00121 cpl_image_delete(rainbow); \
00122 cpl_image_delete(rectified); \
00123 cpl_image_delete(residual); \
00124 cpl_image_delete(smo_flat); \
00125 cpl_image_delete(spatial); \
00126 cpl_image_delete(spectra); \
00127 cpl_image_delete(wavemap); \
00128 cpl_image_delete(delta); \
00129 cpl_image_delete(rect_flat); \
00130 cpl_image_delete(rect_nflat); \
00131 cpl_image_delete(mapped_flat); \
00132 cpl_image_delete(mapped_nflat); \
00133 cpl_mask_delete(refmask); \
00134 cpl_propertylist_delete(header); \
00135 cpl_propertylist_delete(save_header); \
00136 cpl_propertylist_delete(qclist); \
00137 cpl_table_delete(grism_table); \
00138 cpl_table_delete(idscoeff); \
00139 cpl_table_delete(idscoeff_all); \
00140 cpl_table_delete(restable); \
00141 cpl_table_delete(maskslits); \
00142 cpl_table_delete(overscans); \
00143 cpl_table_delete(traces); \
00144 cpl_table_delete(polytraces); \
00145 cpl_table_delete(slits); \
00146 cpl_table_delete(restab); \
00147 cpl_table_delete(global); \
00148 cpl_table_delete(wavelengths); \
00149 cpl_vector_delete(lines); \
00150 cpl_msg_indent_less(); \
00151 return -1; \
00152 }
00153
00154 #define fors_pmos_calib_exit_memcheck(message) \
00155 { \
00156 if (message) cpl_msg_info(recipe, message); \
00157 printf("free instrume (%p)\n", instrume); \
00158 cpl_free(instrume); \
00159 printf("free pipefile (%p)\n", pipefile); \
00160 cpl_free(pipefile); \
00161 printf("free fiterror (%p)\n", fiterror); \
00162 cpl_free(fiterror); \
00163 printf("free fitlines (%p)\n", fitlines); \
00164 cpl_free(fitlines); \
00165 printf("free bias (%p)\n", bias); \
00166 cpl_image_delete(bias); \
00167 printf("free master_bias (%p)\n", master_bias); \
00168 cpl_image_delete(master_bias); \
00169 printf("free coordinate (%p)\n", coordinate); \
00170 cpl_image_delete(coordinate); \
00171 printf("free checkwave (%p)\n", checkwave); \
00172 cpl_image_delete(checkwave); \
00173 printf("free flat (%p)\n", flat); \
00174 cpl_image_delete(flat); \
00175 printf("free master_flat (%p)\n", master_flat); \
00176 cpl_image_delete(master_flat); \
00177 printf("free norm_flat (%p)\n", norm_flat); \
00178 cpl_image_delete(norm_flat); \
00179 printf("free mapped_flat (%p)\n", mapped_flat); \
00180 cpl_image_delete(mapped_flat); \
00181 printf("free mapped_nflat (%p)\n", mapped_nflat); \
00182 cpl_image_delete(mapped_nflat); \
00183 printf("free rainbow (%p)\n", rainbow); \
00184 cpl_image_delete(rainbow); \
00185 printf("free rectified (%p)\n", rectified); \
00186 cpl_image_delete(rectified); \
00187 printf("free residual (%p)\n", residual); \
00188 cpl_image_delete(residual); \
00189 printf("free smo_flat (%p)\n", smo_flat); \
00190 cpl_image_delete(smo_flat); \
00191 printf("free spatial (%p)\n", spatial); \
00192 cpl_image_delete(spatial); \
00193 printf("free spectra (%p)\n", spectra); \
00194 cpl_image_delete(spectra); \
00195 printf("free wavemap (%p)\n", wavemap); \
00196 cpl_image_delete(wavemap); \
00197 printf("free delta (%p)\n", delta); \
00198 cpl_image_delete(delta); \
00199 printf("free rect_flat (%p)\n", rect_flat); \
00200 cpl_image_delete(rect_flat); \
00201 printf("free rect_nflat (%p)\n", rect_nflat); \
00202 cpl_image_delete(rect_nflat); \
00203 printf("free refmask (%p)\n", refmask); \
00204 cpl_mask_delete(refmask); \
00205 printf("free header (%p)\n", header); \
00206 cpl_propertylist_delete(header); \
00207 printf("free save_header (%p)\n", save_header); \
00208 cpl_propertylist_delete(save_header); \
00209 printf("free qclist (%p)\n", qclist); \
00210 cpl_propertylist_delete(qclist); \
00211 printf("free grism_table (%p)\n", grism_table); \
00212 cpl_table_delete(grism_table); \
00213 printf("free idscoeff (%p)\n", idscoeff); \
00214 cpl_table_delete(idscoeff); \
00215 printf("free idscoeff_all (%p)\n", idscoeff_all); \
00216 cpl_table_delete(idscoeff_all); \
00217 printf("free restable (%p)\n", restable); \
00218 cpl_table_delete(restable); \
00219 printf("free maskslits (%p)\n", maskslits); \
00220 cpl_table_delete(maskslits); \
00221 printf("free overscans (%p)\n", overscans); \
00222 cpl_table_delete(overscans); \
00223 printf("free traces (%p)\n", traces); \
00224 cpl_table_delete(traces); \
00225 printf("free polytraces (%p)\n", polytraces); \
00226 cpl_table_delete(polytraces); \
00227 printf("free slits (%p)\n", slits); \
00228 cpl_table_delete(slits); \
00229 printf("free restab (%p)\n", restab); \
00230 cpl_table_delete(restab); \
00231 printf("free global (%p)\n", global); \
00232 cpl_table_delete(global); \
00233 printf("free wavelengths (%p)\n", wavelengths); \
00234 cpl_table_delete(wavelengths); \
00235 printf("free lines (%p)\n", lines); \
00236 cpl_vector_delete(lines); \
00237 cpl_msg_indent_less(); \
00238 return 0; \
00239 }
00240
00241
00253 int cpl_plugin_get_info(cpl_pluginlist *list)
00254 {
00255 cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe );
00256 cpl_plugin *plugin = &recipe->interface;
00257
00258 cpl_plugin_init(plugin,
00259 CPL_PLUGIN_API,
00260 FORS_BINARY_VERSION,
00261 CPL_PLUGIN_TYPE_RECIPE,
00262 "fors_pmos_calib",
00263 "Determination of the extraction mask",
00264 fors_pmos_calib_description,
00265 "Carlo Izzo",
00266 PACKAGE_BUGREPORT,
00267 "This file is currently part of the FORS Instrument Pipeline\n"
00268 "Copyright (C) 2002-2010 European Southern Observatory\n\n"
00269 "This program is free software; you can redistribute it and/or modify\n"
00270 "it under the terms of the GNU General Public License as published by\n"
00271 "the Free Software Foundation; either version 2 of the License, or\n"
00272 "(at your option) any later version.\n\n"
00273 "This program is distributed in the hope that it will be useful,\n"
00274 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
00275 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
00276 "GNU General Public License for more details.\n\n"
00277 "You should have received a copy of the GNU General Public License\n"
00278 "along with this program; if not, write to the Free Software Foundation,\n"
00279 "Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\n",
00280 fors_pmos_calib_create,
00281 fors_pmos_calib_exec,
00282 fors_pmos_calib_destroy);
00283
00284 cpl_pluginlist_append(list, plugin);
00285
00286 return 0;
00287 }
00288
00289
00300 static int fors_pmos_calib_create(cpl_plugin *plugin)
00301 {
00302 cpl_recipe *recipe;
00303 cpl_parameter *p;
00304
00305
00306
00307
00308
00309
00310 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
00311 recipe = (cpl_recipe *)plugin;
00312 else
00313 return -1;
00314
00315
00316
00317
00318
00319 recipe->parameters = cpl_parameterlist_new();
00320
00321
00322
00323
00324
00325
00326 p = cpl_parameter_new_value("fors.fors_pmos_calib.dispersion",
00327 CPL_TYPE_DOUBLE,
00328 "Expected spectral dispersion (Angstrom/pixel)",
00329 "fors.fors_pmos_calib",
00330 0.0);
00331 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "dispersion");
00332 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00333 cpl_parameterlist_append(recipe->parameters, p);
00334
00335
00336
00337
00338
00339 p = cpl_parameter_new_value("fors.fors_pmos_calib.peakdetection",
00340 CPL_TYPE_DOUBLE,
00341 "Initial peak detection threshold (ADU)",
00342 "fors.fors_pmos_calib",
00343 0.0);
00344 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "peakdetection");
00345 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00346 cpl_parameterlist_append(recipe->parameters, p);
00347
00348
00349
00350
00351
00352 p = cpl_parameter_new_value("fors.fors_pmos_calib.wdegree",
00353 CPL_TYPE_INT,
00354 "Degree of wavelength calibration polynomial",
00355 "fors.fors_pmos_calib",
00356 0);
00357 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wdegree");
00358 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00359 cpl_parameterlist_append(recipe->parameters, p);
00360
00361
00362
00363
00364
00365 p = cpl_parameter_new_value("fors.fors_pmos_calib.wradius",
00366 CPL_TYPE_INT,
00367 "Search radius if iterating pattern-matching "
00368 "with first-guess method",
00369 "fors.fors_pmos_calib",
00370 4);
00371 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wradius");
00372 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00373 cpl_parameterlist_append(recipe->parameters, p);
00374
00375
00376
00377
00378
00379 p = cpl_parameter_new_value("fors.fors_pmos_calib.wreject",
00380 CPL_TYPE_DOUBLE,
00381 "Rejection threshold in dispersion "
00382 "relation fit (pixel)",
00383 "fors.fors_pmos_calib",
00384 0.7);
00385 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wreject");
00386 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00387 cpl_parameterlist_append(recipe->parameters, p);
00388
00389
00390
00391
00392
00393 p = cpl_parameter_new_value("fors.fors_pmos_calib.wcolumn",
00394 CPL_TYPE_STRING,
00395 "Name of line catalog table column "
00396 "with wavelengths",
00397 "fors.fors_pmos_calib",
00398 "WLEN");
00399 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcolumn");
00400 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00401 cpl_parameterlist_append(recipe->parameters, p);
00402
00403
00404
00405
00406
00407 p = cpl_parameter_new_value("fors.fors_pmos_calib.cdegree",
00408 CPL_TYPE_INT,
00409 "Degree of spectral curvature polynomial",
00410 "fors.fors_pmos_calib",
00411 0);
00412 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "cdegree");
00413 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00414 cpl_parameterlist_append(recipe->parameters, p);
00415
00416
00417
00418
00419
00420 p = cpl_parameter_new_value("fors.fors_pmos_calib.cmode",
00421 CPL_TYPE_INT,
00422 "Interpolation mode of curvature solution "
00423 "(0 = no "
00424 "interpolation, 1 = fill gaps, 2 = global "
00425 "model)",
00426 "fors.fors_pmos_calib",
00427 1);
00428 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "cmode");
00429 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00430 cpl_parameterlist_append(recipe->parameters, p);
00431
00432
00433
00434
00435
00436 p = cpl_parameter_new_value("fors.fors_pmos_calib.startwavelength",
00437 CPL_TYPE_DOUBLE,
00438 "Start wavelength in spectral extraction",
00439 "fors.fors_pmos_calib",
00440 0.0);
00441 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "startwavelength");
00442 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00443 cpl_parameterlist_append(recipe->parameters, p);
00444
00445
00446
00447
00448
00449 p = cpl_parameter_new_value("fors.fors_pmos_calib.endwavelength",
00450 CPL_TYPE_DOUBLE,
00451 "End wavelength in spectral extraction",
00452 "fors.fors_pmos_calib",
00453 0.0);
00454 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "endwavelength");
00455 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00456 cpl_parameterlist_append(recipe->parameters, p);
00457
00458
00459
00460
00461
00462 fors_stack_define_parameters(recipe->parameters, "fors.fors_pmos_calib",
00463 "average");
00464
00465
00466
00467
00468
00469 p = cpl_parameter_new_value("fors.fors_pmos_calib.ddegree",
00470 CPL_TYPE_INT,
00471 "Degree of flat field fitting polynomial "
00472 "along dispersion direction",
00473 "fors.fors_pmos_calib",
00474 -1);
00475 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "ddegree");
00476 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00477 cpl_parameterlist_append(recipe->parameters, p);
00478
00479
00480
00481
00482
00483 p = cpl_parameter_new_value("fors.fors_pmos_calib.dradius",
00484 CPL_TYPE_INT,
00485 "Smooth box radius for flat field along "
00486 "dispersion direction",
00487 "fors.fors_pmos_calib",
00488 10);
00489 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "dradius");
00490 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00491 cpl_parameterlist_append(recipe->parameters, p);
00492
00493
00494
00495
00496
00497 p = cpl_parameter_new_value("fors.fors_pmos_calib.qc",
00498 CPL_TYPE_BOOL,
00499 "Compute QC1 parameters",
00500 "fors.fors_pmos_calib",
00501 TRUE);
00502 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "qc");
00503 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00504 cpl_parameterlist_append(recipe->parameters, p);
00505
00506
00507
00508
00509
00510 p = cpl_parameter_new_value("fors.fors_pmos_calib.check",
00511 CPL_TYPE_BOOL,
00512 "Create intermediate products",
00513 "fors.fors_pmos_calib",
00514 FALSE);
00515 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "check");
00516 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00517 cpl_parameterlist_append(recipe->parameters, p);
00518
00519 return 0;
00520 }
00521
00522
00531 static int fors_pmos_calib_exec(cpl_plugin *plugin)
00532 {
00533 cpl_recipe *recipe;
00534
00535 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
00536 recipe = (cpl_recipe *)plugin;
00537 else
00538 return -1;
00539
00540 return fors_pmos_calib(recipe->parameters, recipe->frames);
00541 }
00542
00543
00552 static int fors_pmos_calib_destroy(cpl_plugin *plugin)
00553 {
00554 cpl_recipe *recipe;
00555
00556 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
00557 recipe = (cpl_recipe *)plugin;
00558 else
00559 return -1;
00560
00561 cpl_parameterlist_delete(recipe->parameters);
00562
00563 return 0;
00564 }
00565
00566
00576 static int fors_pmos_calib(cpl_parameterlist *parlist, cpl_frameset *frameset)
00577 {
00578
00579 const char *recipe = "fors_pmos_calib";
00580
00581
00582
00583
00584
00585
00586 double dispersion;
00587 double peakdetection;
00588 int wdegree;
00589 int wradius;
00590 double wreject;
00591 const char *wcolumn;
00592 int cdegree;
00593 int cmode;
00594 double startwavelength;
00595 double endwavelength;
00596 int ddegree;
00597 int dradius;
00598 int qc;
00599 int check;
00600 const char *stack_method;
00601 int min_reject;
00602 int max_reject;
00603 double klow;
00604 double khigh;
00605 int kiter;
00606
00607
00608
00609
00610
00611
00612 cpl_imagelist *biases = NULL;
00613 cpl_image *bias = NULL;
00614 cpl_image *master_bias = NULL;
00615 cpl_image *multi_bias = NULL;
00616 cpl_image *flat = NULL;
00617 cpl_image *master_flat = NULL;
00618 cpl_image *added_flat = NULL;
00619 cpl_image *trace_flat = NULL;
00620 cpl_image *smo_flat = NULL;
00621 cpl_image *norm_flat = NULL;
00622 cpl_image *spectra = NULL;
00623 cpl_image *wavemap = NULL;
00624 cpl_image *delta = NULL;
00625 cpl_image *residual = NULL;
00626 cpl_image *checkwave = NULL;
00627 cpl_image *rectified = NULL;
00628 cpl_image *dummy = NULL;
00629 cpl_image *add_dummy = NULL;
00630 cpl_image *refimage = NULL;
00631 cpl_image *coordinate = NULL;
00632 cpl_image *rainbow = NULL;
00633 cpl_image *spatial = NULL;
00634 cpl_image *rect_flat = NULL;
00635 cpl_image *rect_nflat = NULL;
00636 cpl_image *mapped_flat = NULL;
00637 cpl_image *mapped_nflat = NULL;
00638
00639 cpl_mask *refmask = NULL;
00640
00641 cpl_table *grism_table = NULL;
00642 cpl_table *overscans = NULL;
00643 cpl_table *wavelengths = NULL;
00644 cpl_table *idscoeff = NULL;
00645 cpl_table *idscoeff_all = NULL;
00646 cpl_table *restable = NULL;
00647 cpl_table *slits = NULL;
00648 cpl_table *positions = NULL;
00649 cpl_table *maskslits = NULL;
00650 cpl_table *traces = NULL;
00651 cpl_table *polytraces = NULL;
00652 cpl_table *restab = NULL;
00653 cpl_table *global = NULL;
00654
00655 cpl_vector *lines = NULL;
00656
00657 cpl_propertylist *header_dist = NULL;
00658 cpl_propertylist *header = NULL;
00659 cpl_propertylist *save_header = NULL;
00660 cpl_propertylist *qclist = NULL;
00661
00662
00663
00664
00665
00666 char version[80];
00667 const char *arc_tag;
00668 const char *flat_tag;
00669 const char *master_screen_flat_tag;
00670 const char *master_norm_flat_tag;
00671 const char *reduced_lamp_tag;
00672 const char *disp_residuals_tag;
00673 const char *disp_coeff_tag;
00674 const char *wavelength_map_tag;
00675 const char *spectra_detection_tag;
00676 const char *spectral_resolution_tag;
00677 const char *slit_map_tag;
00678 const char *curv_traces_tag;
00679 const char *curv_coeff_tag;
00680 const char *spatial_map_tag;
00681 const char *slit_location_tag;
00682 const char *master_distortion_tag = "MASTER_DISTORTION_TABLE";
00683 const char *disp_residuals_table_tag;
00684 const char *delta_image_tag;
00685 const char *mapped_screen_flat_tag;
00686 const char *mapped_norm_flat_tag;
00687 const char *keyname;
00688 int pmos;
00689 int same_offset = 0;
00690 int nslits;
00691 float *data;
00692 double *xpos;
00693 double mxpos;
00694 double mean_rms;
00695 double mean_rms_err;
00696 double alltime;
00697 int nflats;
00698 int nbias;
00699 int nlines;
00700 int rebin, rebin_dist;
00701 double *line;
00702 double *fiterror = NULL;
00703 int *fitlines = NULL;
00704 int nx, ny;
00705 double reference;
00706 double gain;
00707 int ccd_xsize, ccd_ysize;
00708 int i, j;
00709
00710 char *instrume = NULL;
00711 char *pipefile = NULL;
00712
00713
00714
00715
00716
00717 int bagoo = 0;
00718 int doit = 0;
00719 double blevel = 0.0;
00720 double ron = 0.0;
00721
00722 snprintf(version, 80, "%s-%s", PACKAGE, PACKAGE_VERSION);
00723
00724 cpl_msg_set_indentation(2);
00725
00726 if (dfs_files_dont_exist(frameset))
00727 fors_pmos_calib_exit(NULL);
00728
00729 fors_dfs_set_groups(frameset);
00730
00731
00732
00733
00734
00735 cpl_msg_info(recipe, "Recipe %s configuration parameters:", recipe);
00736 cpl_msg_indent_more();
00737
00738 if (cpl_frameset_count_tags(frameset, "GRISM_TABLE") > 1)
00739 fors_pmos_calib_exit("Too many in input: GRISM_TABLE");
00740
00741 grism_table = dfs_load_table(frameset, "GRISM_TABLE", 1);
00742
00743 dispersion = dfs_get_parameter_double(parlist,
00744 "fors.fors_pmos_calib.dispersion", grism_table);
00745
00746 if (dispersion <= 0.0)
00747 fors_pmos_calib_exit("Invalid spectral dispersion value");
00748
00749 peakdetection = dfs_get_parameter_double(parlist,
00750 "fors.fors_pmos_calib.peakdetection", grism_table);
00751 if (peakdetection <= 0.0)
00752 fors_pmos_calib_exit("Invalid peak detection level");
00753
00754 wdegree = dfs_get_parameter_int(parlist,
00755 "fors.fors_pmos_calib.wdegree", grism_table);
00756
00757 if (wdegree < 1)
00758 fors_pmos_calib_exit("Invalid polynomial degree");
00759
00760 if (wdegree > 5)
00761 fors_pmos_calib_exit("Max allowed polynomial degree is 5");
00762
00763 wradius = dfs_get_parameter_int(parlist,
00764 "fors.fors_pmos_calib.wradius", NULL);
00765
00766 if (wradius < 0)
00767 fors_pmos_calib_exit("Invalid search radius");
00768
00769 wreject = dfs_get_parameter_double(parlist,
00770 "fors.fors_pmos_calib.wreject", NULL);
00771
00772 if (wreject <= 0.0)
00773 fors_pmos_calib_exit("Invalid rejection threshold");
00774
00775 wcolumn = dfs_get_parameter_string(parlist,
00776 "fors.fors_pmos_calib.wcolumn", NULL);
00777
00778 cdegree = dfs_get_parameter_int(parlist,
00779 "fors.fors_pmos_calib.cdegree", grism_table);
00780
00781 if (cdegree < 1)
00782 fors_pmos_calib_exit("Invalid polynomial degree");
00783
00784 if (cdegree > 5)
00785 fors_pmos_calib_exit("Max allowed polynomial degree is 5");
00786
00787 cmode = dfs_get_parameter_int(parlist, "fors.fors_pmos_calib.cmode", NULL);
00788
00789 if (cmode < 0 || cmode > 2)
00790 fors_pmos_calib_exit("Invalid curvature solution interpolation mode");
00791
00792 startwavelength = dfs_get_parameter_double(parlist,
00793 "fors.fors_pmos_calib.startwavelength", grism_table);
00794 if (startwavelength > 1.0)
00795 if (startwavelength < 3000.0 || startwavelength > 13000.0)
00796 fors_pmos_calib_exit("Invalid wavelength");
00797
00798 endwavelength = dfs_get_parameter_double(parlist,
00799 "fors.fors_pmos_calib.endwavelength", grism_table);
00800 if (endwavelength > 1.0) {
00801 if (endwavelength < 3000.0 || endwavelength > 13000.0)
00802 fors_pmos_calib_exit("Invalid wavelength");
00803 if (startwavelength < 1.0)
00804 fors_pmos_calib_exit("Invalid wavelength interval");
00805 }
00806
00807 if (startwavelength > 1.0)
00808 if (endwavelength - startwavelength <= 0.0)
00809 fors_pmos_calib_exit("Invalid wavelength interval");
00810
00811 stack_method = dfs_get_parameter_string(parlist,
00812 "fors.fors_pmos_calib.stack_method",
00813 NULL);
00814
00815 if (strcmp(stack_method, "minmax") == 0) {
00816 min_reject = dfs_get_parameter_int(parlist,
00817 "fors.fors_pmos_calib.minrejection", NULL);
00818 if (min_reject < 0)
00819 fors_pmos_calib_exit("Invalid number of lower rejections");
00820
00821 max_reject = dfs_get_parameter_int(parlist,
00822 "fors.fors_pmos_calib.maxrejection", NULL);
00823 if (max_reject < 0)
00824 fors_pmos_calib_exit("Invalid number of upper rejections");
00825 }
00826
00827 if (strcmp(stack_method, "ksigma") == 0) {
00828 klow = dfs_get_parameter_double(parlist,
00829 "fors.fors_pmos_calib.klow", NULL);
00830 if (klow < 0.1)
00831 fors_pmos_calib_exit("Invalid lower K-sigma");
00832
00833 khigh = dfs_get_parameter_double(parlist,
00834 "fors.fors_pmos_calib.khigh", NULL);
00835 if (khigh < 0.1)
00836 fors_pmos_calib_exit("Invalid lower K-sigma");
00837
00838 kiter = dfs_get_parameter_int(parlist,
00839 "fors.fors_pmos_calib.kiter", NULL);
00840 if (kiter < 1)
00841 fors_pmos_calib_exit("Invalid number of iterations");
00842 }
00843
00844 ddegree = dfs_get_parameter_int(parlist,
00845 "fors.fors_pmos_calib.ddegree", NULL);
00846 dradius = dfs_get_parameter_int(parlist,
00847 "fors.fors_pmos_calib.dradius", NULL);
00848
00849 if (dradius < 1)
00850 fors_pmos_calib_exit("Invalid smoothing box radius");
00851
00852 qc = dfs_get_parameter_bool(parlist, "fors.fors_pmos_calib.qc", NULL);
00853
00854 check = dfs_get_parameter_bool(parlist, "fors.fors_pmos_calib.check", NULL);
00855
00856 cpl_table_delete(grism_table); grism_table = NULL;
00857
00858 if (cpl_error_get_code())
00859 fors_pmos_calib_exit("Failure getting the configuration parameters");
00860
00861
00862
00863
00864
00865
00866 cpl_msg_indent_less();
00867 cpl_msg_info(recipe, "Check input set-of-frames:");
00868 cpl_msg_indent_more();
00869
00870 {
00871 cpl_frameset *subframeset = cpl_frameset_duplicate(frameset);
00872 cpl_frameset_erase(subframeset, "BIAS");
00873 cpl_frameset_erase(subframeset, "MASTER_BIAS");
00874
00875 if (!dfs_equal_keyword(subframeset, "ESO INS GRIS1 ID"))
00876 fors_pmos_calib_exit("Input frames are not from the same grism");
00877
00878 if (!dfs_equal_keyword(subframeset, "ESO INS FILT1 ID"))
00879 fors_pmos_calib_exit("Input frames are not from the same filter");
00880
00881 if (!dfs_equal_keyword(subframeset, "ESO DET CHIP1 ID"))
00882 fors_pmos_calib_exit("Input frames are not from the same chip");
00883
00884 cpl_frameset_delete(subframeset);
00885 }
00886
00887 pmos = cpl_frameset_count_tags(frameset, "LAMP_PMOS");
00888
00889 if (pmos == 0)
00890 fors_pmos_calib_exit("Missing input arc lamp frame");
00891
00892 if (pmos) {
00893 cpl_msg_info(recipe, "PMOS data found");
00894 arc_tag = "LAMP_PMOS";
00895 flat_tag = "SCREEN_FLAT_PMOS";
00896 master_screen_flat_tag = "MASTER_SCREEN_FLAT_PMOS";
00897 master_norm_flat_tag = "MASTER_NORM_FLAT_PMOS";
00898 reduced_lamp_tag = "REDUCED_LAMP_PMOS";
00899 disp_residuals_tag = "DISP_RESIDUALS_PMOS";
00900 disp_coeff_tag = "DISP_COEFF_PMOS";
00901 wavelength_map_tag = "WAVELENGTH_MAP_PMOS";
00902 spectra_detection_tag = "SPECTRA_DETECTION_PMOS";
00903 spectral_resolution_tag = "SPECTRAL_RESOLUTION_PMOS";
00904 slit_map_tag = "SLIT_MAP_PMOS";
00905 curv_traces_tag = "CURV_TRACES_PMOS";
00906 curv_coeff_tag = "CURV_COEFF_PMOS";
00907 spatial_map_tag = "SPATIAL_MAP_PMOS";
00908 slit_location_tag = "SLIT_LOCATION_PMOS";
00909 disp_residuals_table_tag = "DISP_RESIDUALS_TABLE_PMOS";
00910 delta_image_tag = "DELTA_IMAGE_PMOS";
00911 mapped_screen_flat_tag = "MAPPED_SCREEN_FLAT_PMOS";
00912 mapped_norm_flat_tag = "MAPPED_NORM_FLAT_PMOS";
00913 }
00914
00915 nbias = 0;
00916 if (cpl_frameset_count_tags(frameset, "MASTER_BIAS") == 0) {
00917 if (cpl_frameset_count_tags(frameset, "BIAS") == 0)
00918 fors_pmos_calib_exit("Missing required input: MASTER_BIAS or BIAS");
00919 nbias = cpl_frameset_count_tags(frameset, "BIAS");
00920 }
00921
00922 if (cpl_frameset_count_tags(frameset, "MASTER_BIAS") > 1)
00923 fors_pmos_calib_exit("Too many in input: MASTER_BIAS");
00924
00925 if (cpl_frameset_count_tags(frameset, "MASTER_LINECAT") == 0)
00926 fors_pmos_calib_exit("Missing required input: MASTER_LINECAT");
00927
00928 if (cpl_frameset_count_tags(frameset, "MASTER_LINECAT") > 1)
00929 fors_pmos_calib_exit("Too many in input: MASTER_LINECAT");
00930
00931 if (cpl_frameset_count_tags(frameset, "MASTER_LINECAT") == 0)
00932 fors_pmos_calib_exit("Missing required input: MASTER_LINECAT");
00933
00934 if (cpl_frameset_count_tags(frameset, "MASTER_LINECAT") > 1)
00935 fors_pmos_calib_exit("Too many in input: MASTER_LINECAT");
00936
00937
00938
00939
00940
00941
00942 if (cpl_frameset_count_tags(frameset, master_distortion_tag) > 1)
00943 fors_pmos_calib_exit("Too many in input: MASTER_DISTORTION_TABLE");
00944
00945 nflats = cpl_frameset_count_tags(frameset, flat_tag);
00946
00947 if (nflats < 1) {
00948 cpl_msg_error(recipe, "Missing required input: %s", flat_tag);
00949 fors_pmos_calib_exit(NULL);
00950 }
00951
00952 cpl_msg_indent_less();
00953
00954 if (nflats > 1)
00955 cpl_msg_info(recipe, "Load %d flat field frames and stack them "
00956 "with method \"%s\"", nflats, stack_method);
00957 else
00958 cpl_msg_info(recipe, "Load flat field exposure...");
00959
00960 cpl_msg_indent_more();
00961
00962 header = dfs_load_header(frameset, flat_tag, 0);
00963
00964 if (header == NULL)
00965 fors_pmos_calib_exit("Cannot load flat field frame header");
00966
00967 alltime = cpl_propertylist_get_double(header, "EXPTIME");
00968
00969 if (cpl_error_get_code() != CPL_ERROR_NONE)
00970 fors_pmos_calib_exit("Missing keyword EXPTIME in flat field "
00971 "frame header");
00972
00973 cpl_propertylist_delete(header);
00974
00975 for (i = 1; i < nflats; i++) {
00976
00977 header = dfs_load_header(frameset, NULL, 0);
00978
00979 if (header == NULL)
00980 fors_pmos_calib_exit("Cannot load flat field frame header");
00981
00982 alltime += cpl_propertylist_get_double(header, "EXPTIME");
00983
00984 if (cpl_error_get_code() != CPL_ERROR_NONE)
00985 fors_pmos_calib_exit("Missing keyword EXPTIME in flat field "
00986 "frame header");
00987
00988 cpl_propertylist_delete(header);
00989
00990 }
00991
00992 if (bagoo) {
00993 char *montecarlo = getenv("MONTECARLO");
00994
00995 if (montecarlo)
00996 doit = atoi(montecarlo);
00997
00998 if (doit) {
00999 master_bias = dfs_load_image(frameset, "MASTER_BIAS",
01000 CPL_TYPE_FLOAT, 0, 1);
01001 if (master_bias == NULL)
01002 fors_pmos_calib_exit("Cannot load master bias");
01003
01004 blevel = cpl_image_get_mean(master_bias);
01005
01006 cpl_image_delete(master_bias);
01007 }
01008 }
01009
01010 master_flat = dfs_load_image(frameset, flat_tag, CPL_TYPE_FLOAT, 0, 0);
01011
01012 if (master_flat == NULL)
01013 fors_pmos_calib_exit("Cannot load flat field");
01014
01015 if (doit) {
01016 header = dfs_load_header(frameset, flat_tag, 0);
01017
01018 gain = cpl_propertylist_get_double(header, "ESO DET OUT1 CONAD");
01019
01020 if (cpl_error_get_code() != CPL_ERROR_NONE)
01021 fors_pmos_calib_exit("Missing keyword ESO DET OUT1 CONAD "
01022 "in flat field frame header");
01023
01024 ron = cpl_propertylist_get_double(header, "ESO DET OUT1 RON");
01025
01026 if (cpl_error_get_code() != CPL_ERROR_NONE)
01027 fors_pmos_calib_exit("Missing keyword ESO DET OUT1 RON "
01028 "in flat field frame header");
01029
01030 cpl_propertylist_delete(header);
01031
01032 ron /= gain;
01033
01034 mos_randomise_image(master_flat, ron, gain, blevel);
01035 }
01036
01037 ny = cpl_image_get_size_y(master_flat);
01038
01039 if (nflats > 1) {
01040 if (strcmp(stack_method, "average") == 0) {
01041 for (i = 1; i < nflats; i++) {
01042 flat = dfs_load_image(frameset, NULL, CPL_TYPE_FLOAT, 0, 0);
01043 if (flat) {
01044 if (doit) {
01045 mos_randomise_image(flat, ron, gain, blevel);
01046 }
01047 cpl_image_add(master_flat, flat);
01048 cpl_image_delete(flat); flat = NULL;
01049 }
01050 else
01051 fors_pmos_calib_exit("Cannot load flat field");
01052 }
01053
01054
01055
01056
01057
01058
01059 }
01060 else {
01061 cpl_imagelist *flatlist = NULL;
01062 double rflux, flux;
01063
01064 added_flat = cpl_image_duplicate(master_flat);
01065
01066 flatlist = cpl_imagelist_new();
01067 cpl_imagelist_set(flatlist, master_flat,
01068 cpl_imagelist_get_size(flatlist));
01069
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079 rflux = cpl_image_get_mean(master_flat);
01080
01081 for (i = 1; i < nflats; i++) {
01082 flat = dfs_load_image(frameset, NULL, CPL_TYPE_FLOAT, 0, 0);
01083 if (flat) {
01084 if (doit) {
01085 mos_randomise_image(flat, ron, gain, blevel);
01086 }
01087 cpl_image_add(added_flat, flat);
01088 flux = cpl_image_get_mean(flat);
01089 cpl_image_multiply_scalar(flat, rflux / flux);
01090 cpl_imagelist_set(flatlist, flat,
01091 cpl_imagelist_get_size(flatlist));
01092 }
01093 else {
01094 fors_pmos_calib_exit("Cannot load flat field");
01095 }
01096 }
01097
01098 if (strcmp(stack_method, "median") == 0) {
01099 master_flat = cpl_imagelist_collapse_median_create(flatlist);
01100 }
01101
01102 if (strcmp(stack_method, "minmax") == 0) {
01103 master_flat = cpl_imagelist_collapse_minmax_create(flatlist,
01104 min_reject,
01105 max_reject);
01106 }
01107
01108 if (strcmp(stack_method, "ksigma") == 0) {
01109 master_flat = mos_ksigma_stack(flatlist,
01110 klow, khigh, kiter, NULL);
01111 }
01112 }
01113 }
01114
01115
01116
01117
01118
01119
01120
01121 header = dfs_load_header(frameset, arc_tag, 0);
01122
01123 if (header == NULL)
01124 fors_pmos_calib_exit("Cannot load arc lamp header");
01125
01126 instrume = (char *)cpl_propertylist_get_string(header, "INSTRUME");
01127 if (instrume == NULL)
01128 fors_pmos_calib_exit("Missing keyword INSTRUME in arc lamp header");
01129
01130 instrume = cpl_strdup(instrume);
01131
01132 if (instrume[4] == '1')
01133 snprintf(version, 80, "%s/%s", "fors1", VERSION);
01134 if (instrume[4] == '2')
01135 snprintf(version, 80, "%s/%s", "fors2", VERSION);
01136
01137 reference = cpl_propertylist_get_double(header, "ESO INS GRIS1 WLEN");
01138
01139 if (cpl_error_get_code() != CPL_ERROR_NONE)
01140 fors_pmos_calib_exit("Missing keyword ESO INS GRIS1 WLEN in arc lamp "
01141 "frame header");
01142
01143 if (reference < 3000.0)
01144 reference *= 10;
01145
01146 if (reference < 3000.0 || reference > 13000.0) {
01147 cpl_msg_error(recipe, "Invalid central wavelength %.2f read from "
01148 "keyword ESO INS GRIS1 WLEN in arc lamp frame header",
01149 reference);
01150 fors_pmos_calib_exit(NULL);
01151 }
01152
01153 cpl_msg_info(recipe, "The central wavelength is: %.2f", reference);
01154
01155 rebin = cpl_propertylist_get_int(header, "ESO DET WIN1 BINX");
01156
01157 if (cpl_error_get_code() != CPL_ERROR_NONE)
01158 fors_pmos_calib_exit("Missing keyword ESO DET WIN1 BINX in arc lamp "
01159 "frame header");
01160
01161 if (rebin != 1) {
01162 dispersion *= rebin;
01163 cpl_msg_warning(recipe, "The rebin factor is %d, and therefore the "
01164 "working dispersion used is %f A/pixel", rebin,
01165 dispersion);
01166 }
01167
01168 gain = cpl_propertylist_get_double(header, "ESO DET OUT1 CONAD");
01169
01170 if (cpl_error_get_code() != CPL_ERROR_NONE)
01171 fors_pmos_calib_exit("Missing keyword ESO DET OUT1 CONAD in arc lamp "
01172 "frame header");
01173
01174 cpl_msg_info(recipe, "The gain factor is: %.2f e-/ADU", gain);
01175
01176 if (pmos) {
01177 cpl_msg_info(recipe, "Produce mask slit position table...");
01178
01179 maskslits = mos_load_slits_fors_mos(header);
01180
01181
01182
01183
01184
01185
01186 mxpos = cpl_table_get_column_median(maskslits, "xtop");
01187 xpos = cpl_table_get_data_double(maskslits, "xtop");
01188 nslits = cpl_table_get_nrow(maskslits);
01189
01190 same_offset = 1;
01191 for (i = 0; i < nslits; i++) {
01192 if (fabs(mxpos-xpos[i]) > 0.01) {
01193 same_offset = 0;
01194 break;
01195 }
01196 }
01197
01198 if (same_offset) {
01199 cpl_msg_info(recipe, "All slits have same offset: %.2f", mxpos);
01200 }
01201 else {
01202 cpl_msg_info(recipe, "All slits have different offsets");
01203 }
01204
01205 if (ny != 400 && ny != 500) {
01206 if (cpl_frameset_count_tags(frameset,
01207 master_distortion_tag) == 0)
01208 fors_pmos_calib_exit(
01209 "Missing required input: MASTER_DISTORTION_TABLE");
01210
01211 header_dist = dfs_load_header(frameset,
01212 master_distortion_tag, 0);
01213 rebin_dist = cpl_propertylist_get_int(header_dist,
01214 "ESO DET WIN1 BINX");
01215 cpl_propertylist_delete(header_dist);
01216 }
01217 }
01218
01219
01220
01221
01222
01223
01224
01225
01226 if (nbias) {
01227
01228
01229
01230
01231
01232 cpl_msg_info(recipe, "Generate the master from input raw biases...");
01233
01234 if (nbias > 1) {
01235
01236 biases = cpl_imagelist_new();
01237
01238 bias = dfs_load_image(frameset, "BIAS", CPL_TYPE_FLOAT, 0, 0);
01239
01240 if (bias == NULL)
01241 fors_pmos_calib_exit("Cannot load bias frame");
01242
01243 cpl_imagelist_set(biases, bias, 0);
01244
01245 for (i = 1; i < nbias; i++) {
01246 bias = dfs_load_image(frameset, NULL, CPL_TYPE_FLOAT, 0, 0);
01247 if (bias)
01248 cpl_imagelist_set(biases, bias, i);
01249 else
01250 fors_pmos_calib_exit("Cannot load bias frame");
01251 }
01252
01253 master_bias = cpl_imagelist_collapse_median_create(biases);
01254
01255 cpl_imagelist_delete(biases);
01256 }
01257 else {
01258 master_bias = dfs_load_image(frameset, "BIAS",
01259 CPL_TYPE_FLOAT, 0, 1);
01260 if (master_bias == NULL)
01261 fors_pmos_calib_exit("Cannot load bias");
01262 }
01263
01264 }
01265 else {
01266 master_bias = dfs_load_image(frameset, "MASTER_BIAS",
01267 CPL_TYPE_FLOAT, 0, 1);
01268 if (master_bias == NULL)
01269 fors_pmos_calib_exit("Cannot load master bias");
01270 }
01271
01272 cpl_msg_info(recipe, "Remove the master bias...");
01273
01274 overscans = mos_load_overscans_fors(header);
01275 cpl_propertylist_delete(header); header = NULL;
01276
01277 if (nbias) {
01278 int xlow = cpl_table_get_int(overscans, "xlow", 0, NULL);
01279 int ylow = cpl_table_get_int(overscans, "ylow", 0, NULL);
01280 int xhig = cpl_table_get_int(overscans, "xhig", 0, NULL);
01281 int yhig = cpl_table_get_int(overscans, "yhig", 0, NULL);
01282 dummy = cpl_image_extract(master_bias, xlow+1, ylow+1, xhig, yhig);
01283 cpl_image_delete(master_bias); master_bias = dummy;
01284
01285 if (dfs_save_image(frameset, master_bias, "MASTER_BIAS",
01286 NULL, parlist, recipe, version))
01287 fors_pmos_calib_exit(NULL);
01288 }
01289
01290 if (nflats > 1) {
01291 multi_bias = cpl_image_multiply_scalar_create(master_bias, nflats);
01292 dummy = mos_remove_bias(master_flat, multi_bias, overscans);
01293 if (added_flat)
01294 add_dummy = mos_remove_bias(added_flat, multi_bias, overscans);
01295 cpl_image_delete(multi_bias);
01296 }
01297 else {
01298 dummy = mos_remove_bias(master_flat, master_bias, overscans);
01299 }
01300 cpl_image_delete(master_flat);
01301 master_flat = dummy;
01302
01303 if (master_flat == NULL)
01304 fors_pmos_calib_exit("Cannot remove bias from flat field");
01305
01306 if (added_flat) {
01307 cpl_image_delete(added_flat);
01308 added_flat = add_dummy;
01309
01310 if (added_flat == NULL)
01311 fors_pmos_calib_exit("Cannot remove bias from added flat field");
01312
01313 trace_flat = added_flat;
01314 }
01315 else
01316 trace_flat = master_flat;
01317
01318 wavelengths = dfs_load_table(frameset, "MASTER_LINECAT", 1);
01319
01320 if (wavelengths == NULL)
01321 fors_pmos_calib_exit("Cannot load line catalog");
01322
01323
01324
01325
01326
01327 nlines = cpl_table_get_nrow(wavelengths);
01328
01329 if (nlines == 0)
01330 fors_pmos_calib_exit("Empty input line catalog");
01331
01332 if (cpl_table_has_column(wavelengths, wcolumn) != 1) {
01333 cpl_msg_error(recipe, "Missing column %s in input line catalog table",
01334 wcolumn);
01335 fors_pmos_calib_exit(NULL);
01336 }
01337
01338 line = cpl_malloc(nlines * sizeof(double));
01339
01340 for (i = 0; i < nlines; i++)
01341 line[i] = cpl_table_get(wavelengths, wcolumn, i, NULL);
01342
01343 lines = cpl_vector_wrap(nlines, line);
01344
01345 for (j = 0; j < pmos; j++) {
01346 int k;
01347
01348 cpl_msg_indent_less();
01349 cpl_msg_info(recipe, "Processing arc lamp nb %d out of %d ...",
01350 j + 1, pmos);
01351 cpl_msg_indent_more();
01352
01353 cpl_msg_info(recipe, "Load arc lamp exposure...");
01354 cpl_msg_indent_more();
01355
01356 spectra = dfs_load_image(frameset, arc_tag, CPL_TYPE_FLOAT, 0, 0);
01357
01358
01359
01360
01361
01362
01363 for (k = 0; k < j; k ++) {
01364 cpl_image_delete(spectra);
01365 spectra = dfs_load_image(frameset, NULL, CPL_TYPE_FLOAT, 0, 0);
01366 }
01367
01368 if (spectra == NULL)
01369 fors_pmos_calib_exit("Cannot load arc lamp exposure");
01370
01371 if (doit) {
01372 mos_randomise_image(spectra, ron, gain, blevel);
01373 }
01374
01375 cpl_msg_info(recipe, "Remove the master bias...");
01376
01377 dummy = mos_remove_bias(spectra, master_bias, overscans);
01378 cpl_image_delete(spectra); spectra = dummy;
01379
01380 if (spectra == NULL)
01381 fors_pmos_calib_exit("Cannot remove bias from arc lamp exposure");
01382
01383 cpl_msg_indent_less();
01384 cpl_msg_info(recipe, "Load input line catalog...");
01385 cpl_msg_indent_more();
01386
01387
01388
01389
01390
01391 if (mos_saturation_process(spectra))
01392 fors_pmos_calib_exit("Cannot process saturation");
01393
01394 if (mos_subtract_background(spectra))
01395 fors_pmos_calib_exit("Cannot subtract the background");
01396
01397 if (!j) {
01398
01399
01400
01401
01402 cpl_msg_indent_less();
01403 cpl_msg_info(recipe, "Detecting spectra on CCD...");
01404 cpl_msg_indent_more();
01405
01406 ccd_xsize = nx = cpl_image_get_size_x(spectra);
01407 ccd_ysize = ny = cpl_image_get_size_y(spectra);
01408
01409 refmask = cpl_mask_new(nx, ny);
01410
01411 checkwave =
01412 mos_wavelength_calibration_raw(spectra, lines, dispersion,
01413 peakdetection, wradius,
01414 wdegree, wreject, reference,
01415 &startwavelength, &endwavelength,
01416 NULL, NULL, NULL, NULL, NULL,
01417 NULL, refmask);
01418
01419 if (checkwave == NULL)
01420 fors_pmos_calib_exit("Wavelength calibration failure.");
01421
01422
01423
01424
01425
01426 header = cpl_propertylist_new();
01427 cpl_propertylist_update_double(header, "CRPIX1", 1.0);
01428 cpl_propertylist_update_double(header, "CRPIX2", 1.0);
01429 cpl_propertylist_update_double(header, "CRVAL1",
01430 startwavelength + dispersion/2);
01431 cpl_propertylist_update_double(header, "CRVAL2", 1.0);
01432
01433
01434 cpl_propertylist_update_double(header, "CD1_1", dispersion);
01435 cpl_propertylist_update_double(header, "CD1_2", 0.0);
01436 cpl_propertylist_update_double(header, "CD2_1", 0.0);
01437 cpl_propertylist_update_double(header, "CD2_2", 1.0);
01438 cpl_propertylist_update_string(header, "CTYPE1", "LINEAR");
01439 cpl_propertylist_update_string(header, "CTYPE2", "PIXEL");
01440
01441 if (check) {
01442 if (!j) {
01443 if(dfs_save_image_null(frameset, parlist,
01444 spectra_detection_tag,
01445 recipe, version)) {
01446 fors_pmos_calib_exit(NULL);
01447 }
01448 }
01449
01450 if (dfs_save_image_ext(checkwave,
01451 spectra_detection_tag, header)) {
01452 fors_pmos_calib_exit(NULL);
01453 }
01454 }
01455
01456 cpl_image_delete(checkwave); checkwave = NULL;
01457 cpl_propertylist_delete(header); header = NULL;
01458
01459 if (cpl_mask_is_empty(refmask))
01460 fors_pmos_calib_exit("Wavelength calibration failure.");
01461
01462 if (mos_refmask_find_gaps(refmask, trace_flat, -1.0))
01463 fors_pmos_calib_exit("The gaps could not be found");
01464
01465 cpl_msg_info(recipe,
01466 "Locate slits at reference wavelength on CCD...");
01467 slits = mos_locate_spectra(refmask);
01468
01469 if (!slits) {
01470 cpl_msg_error(cpl_error_get_where(), cpl_error_get_message());
01471 fors_pmos_calib_exit("No slits could be detected!");
01472 }
01473
01474 if (same_offset) {
01475 if (ny != 400 && ny != 500) {
01476 float rescale = (float) rebin_dist / rebin;
01477 if (mos_check_slits(slits, rescale)) {
01478 fors_pmos_calib_exit("Some slits are missing. "
01479 "Cannot recover!");
01480 }
01481 }
01482 }
01483
01484 refimage = cpl_image_new_from_mask(refmask);
01485 cpl_mask_delete(refmask); refmask = NULL;
01486
01487 if (check) {
01488 if (!j) {
01489 if(dfs_save_image_null(frameset, parlist,
01490 slit_map_tag,
01491 recipe, version)) {
01492 fors_pmos_calib_exit(NULL);
01493 }
01494 }
01495
01496 save_header = dfs_load_header(frameset, arc_tag, 0);
01497
01498 for (k = 0; k < j; k ++) {
01499 cpl_propertylist_delete(save_header);
01500 save_header = dfs_load_header(frameset, NULL, 0);
01501 }
01502
01503 if (dfs_save_image_ext(refimage, slit_map_tag, save_header)) {
01504 fors_pmos_calib_exit(NULL);
01505 }
01506 cpl_propertylist_delete(save_header); save_header = NULL;
01507 }
01508
01509 cpl_image_delete(refimage); refimage = NULL;
01510
01511
01512
01513 same_offset = 1;
01514 if (0) {
01515
01516
01517
01518
01519
01520
01521
01522
01523
01524
01525
01526
01527
01528
01529
01530
01531
01532 cpl_msg_indent_less();
01533 cpl_msg_info(recipe,
01534 "Attempt slit identification (optional)...");
01535 cpl_msg_indent_more();
01536
01537 positions = mos_identify_slits(slits, maskslits, NULL);
01538
01539 if (positions) {
01540 cpl_table_delete(slits);
01541 slits = positions;
01542
01543
01544
01545
01546
01547 cpl_table_and_selected_double(slits,
01548 "ytop", CPL_GREATER_THAN, ny);
01549 cpl_table_or_selected_double(slits,
01550 "ybottom", CPL_LESS_THAN, 0);
01551 cpl_table_erase_selected(slits);
01552
01553 nslits = cpl_table_get_nrow(slits);
01554
01555 if (nslits == 0)
01556 fors_pmos_calib_exit("No slits found on the CCD");
01557
01558 cpl_msg_info(recipe,
01559 "%d slits are entirely contained in CCD",
01560 nslits);
01561 }
01562 else {
01563 same_offset = 1;
01564 cpl_msg_info(recipe,
01565 "Global distortion model cannot be computed");
01566 if (cpl_error_get_code() != CPL_ERROR_NONE) {
01567 fors_pmos_calib_exit(NULL);
01568 }
01569 }
01570 }
01571
01572
01573 if (ny == 400 || ny == 500) {
01574
01575
01576
01577
01578
01579
01580 nslits = cpl_table_get_nrow(slits);
01581
01582 if (nslits > 4) {
01583 cpl_table_unselect_all(slits);
01584 for (k = 0; k < cpl_table_get_nrow(slits); k++) {
01585 double jump = cpl_table_get(slits, "ytop", k, NULL)
01586 - cpl_table_get(slits, "ybottom", k, NULL);
01587 if (jump < 50.) {
01588 cpl_table_select_row(slits, k);
01589 }
01590 }
01591 cpl_table_erase_selected(slits);
01592 nslits = cpl_table_get_nrow(slits);
01593 }
01594
01595 if (nslits == 0)
01596 fors_pmos_calib_exit("No slits found on the CCD");
01597
01598 if (nslits == 4) {
01599 cpl_table_unselect_all(slits);
01600 cpl_table_select_row(slits, 0);
01601 cpl_table_select_row(slits, cpl_table_get_nrow(slits)-1);
01602 cpl_table_erase_selected(slits);
01603 }
01604
01605 cpl_msg_info(recipe,
01606 "%d slits are entirely contained in CCD", nslits);
01607 }
01608 else {
01609 cpl_table_unselect_all(slits);
01610 for (k = 0; k < cpl_table_get_nrow(slits); k++) {
01611 double jump = cpl_table_get(slits, "ytop", k, NULL)
01612 - cpl_table_get(slits, "ybottom", k, NULL);
01613 if (jump < 10.) {
01614 cpl_table_select_row(slits, k);
01615 }
01616 }
01617 cpl_table_erase_selected(slits);
01618 nslits = cpl_table_get_nrow(slits);
01619 }
01620
01621
01622
01623
01624
01625
01626 cpl_msg_indent_less();
01627 cpl_msg_info(recipe, "Determining spectral curvature...");
01628 cpl_msg_indent_more();
01629
01630 cpl_msg_info(recipe, "Tracing master flat field spectra edges...");
01631 traces = mos_trace_flat(trace_flat, slits, reference,
01632 startwavelength, endwavelength, dispersion);
01633
01634 if (!traces)
01635 fors_pmos_calib_exit("Tracing failure");
01636
01637 cpl_image_delete(added_flat); added_flat = NULL;
01638
01639 cpl_msg_info(recipe, "Fitting flat field spectra edges...");
01640 polytraces = mos_poly_trace(slits, traces, cdegree);
01641
01642 if (!polytraces)
01643 fors_pmos_calib_exit("Trace fitting failure");
01644
01645 if (cmode) {
01646 cpl_msg_info(recipe,
01647 "Computing global spectral curvature model...");
01648 mos_global_trace(slits, polytraces, cmode);
01649 }
01650
01651 if (!j) {
01652 if(dfs_save_image_null(frameset, parlist, curv_traces_tag,
01653 recipe, version)) {
01654 fors_pmos_calib_exit(NULL);
01655 }
01656 }
01657
01658 if (dfs_save_table_ext(traces, curv_traces_tag, NULL)) {
01659 fors_pmos_calib_exit(NULL);
01660 }
01661
01662 cpl_table_delete(traces); traces = NULL;
01663
01664 coordinate = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
01665
01666 }
01667
01668 spatial = mos_spatial_calibration(spectra, slits, polytraces,
01669 reference,
01670 startwavelength, endwavelength,
01671 dispersion, 0, j ? NULL: coordinate);
01672
01673 if (!j) {
01674
01675 if (same_offset) {
01676 cpl_image_delete(spectra); spectra = NULL;
01677 }
01678
01679
01680
01681
01682
01683
01684
01685 cpl_msg_indent_less();
01686 cpl_msg_info(recipe, "Perform flat field normalisation...");
01687 cpl_msg_indent_more();
01688
01689 norm_flat = cpl_image_duplicate(master_flat);
01690
01691 smo_flat = mos_normalise_flat(norm_flat, coordinate, slits,
01692 polytraces, reference,
01693 startwavelength, endwavelength,
01694 dispersion, dradius, ddegree);
01695
01696
01697 cpl_image_delete(smo_flat); smo_flat = NULL;
01698
01699
01700 save_header = dfs_load_header(frameset, flat_tag, 0);
01701 cpl_propertylist_update_int(save_header, "ESO PRO DATANCOM",
01702 nflats);
01703
01704 rect_flat = mos_spatial_calibration(master_flat, slits, polytraces,
01705 reference, startwavelength,
01706 endwavelength, dispersion, 0,
01707 NULL);
01708 rect_nflat = mos_spatial_calibration(norm_flat, slits, polytraces,
01709 reference, startwavelength,
01710 endwavelength, dispersion, 0,
01711 NULL);
01712
01713
01714 if (dfs_save_image(frameset, master_flat, master_screen_flat_tag,
01715 save_header, parlist, recipe, version))
01716 fors_pmos_calib_exit(NULL);
01717
01718
01719 if (dfs_save_image(frameset, norm_flat, master_norm_flat_tag,
01720 save_header, parlist, recipe, version))
01721 fors_pmos_calib_exit(NULL);
01722
01723 cpl_image_delete(norm_flat); norm_flat = NULL;
01724 cpl_propertylist_delete(save_header); save_header = NULL;
01725
01726 }
01727
01728
01729
01730
01731
01732
01733
01734 cpl_msg_indent_less();
01735 cpl_msg_info(recipe, "Perform final wavelength calibration...");
01736 cpl_msg_indent_more();
01737
01738 nx = cpl_image_get_size_x(spatial);
01739 ny = cpl_image_get_size_y(spatial);
01740
01741 idscoeff = cpl_table_new(ny);
01742 restable = cpl_table_new(nlines);
01743 rainbow = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
01744 if (check)
01745 residual = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
01746 fiterror = cpl_calloc(ny, sizeof(double));
01747 fitlines = cpl_calloc(ny, sizeof(int));
01748
01749 rectified = mos_wavelength_calibration_final(spatial, slits, lines,
01750 dispersion, peakdetection,
01751 wradius, wdegree, wreject,
01752 reference,
01753 &startwavelength,
01754 &endwavelength, fitlines,
01755 fiterror, idscoeff,
01756 rainbow,
01757 residual, restable);
01758
01759 if (rectified == NULL)
01760 fors_pmos_calib_exit("Wavelength calibration failure.");
01761
01762 if (!j) {
01763 if(dfs_save_image_null(frameset, parlist, disp_residuals_table_tag,
01764 recipe, version)) {
01765 fors_pmos_calib_exit(NULL);
01766 }
01767 }
01768
01769 header = dfs_load_header(frameset, arc_tag, 0);
01770
01771 for (k = 0; k < j; k ++) {
01772 cpl_propertylist_delete(header);
01773 header = dfs_load_header(frameset, NULL, 0);
01774 }
01775
01776 if (dfs_save_table_ext(restable, disp_residuals_table_tag, header)) {
01777 fors_pmos_calib_exit(NULL);
01778 }
01779
01780 cpl_propertylist_delete(header);
01781
01782 cpl_table_delete(restable); restable = NULL;
01783
01784 cpl_table_wrap_double(idscoeff, fiterror, "error"); fiterror = NULL;
01785 cpl_table_set_column_unit(idscoeff, "error", "pixel");
01786 cpl_table_wrap_int(idscoeff, fitlines, "nlines"); fitlines = NULL;
01787
01788 for (i = 0; i < ny; i++)
01789 if (!cpl_table_is_valid(idscoeff, "c0", i))
01790 cpl_table_set_invalid(idscoeff, "error", i);
01791
01792 delta = mos_map_pixel(idscoeff, reference, startwavelength,
01793 endwavelength, dispersion, 2);
01794
01795 header = dfs_load_header(frameset, arc_tag, 0);
01796
01797 for (k = 0; k < j; k ++) {
01798 cpl_propertylist_delete(header);
01799 header = dfs_load_header(frameset, NULL, 0);
01800 }
01801
01802 cpl_propertylist_update_double(header, "CRPIX1", 1.0);
01803 cpl_propertylist_update_double(header, "CRPIX2", 1.0);
01804 cpl_propertylist_update_double(header, "CRVAL1",
01805 startwavelength + dispersion/2);
01806 cpl_propertylist_update_double(header, "CRVAL2", 1.0);
01807
01808
01809 cpl_propertylist_update_double(header, "CD1_1", dispersion);
01810 cpl_propertylist_update_double(header, "CD1_2", 0.0);
01811 cpl_propertylist_update_double(header, "CD2_1", 0.0);
01812 cpl_propertylist_update_double(header, "CD2_2", 1.0);
01813 cpl_propertylist_update_string(header, "CTYPE1", "LINEAR");
01814 cpl_propertylist_update_string(header, "CTYPE2", "PIXEL");
01815
01816 if (!j) {
01817 if(dfs_save_image_null(frameset, parlist, delta_image_tag,
01818 recipe, version)) {
01819 fors_pmos_calib_exit(NULL);
01820 }
01821 }
01822
01823 if (dfs_save_image_ext(delta, delta_image_tag, header)) {
01824 fors_pmos_calib_exit(NULL);
01825 }
01826
01827 cpl_image_delete(delta); delta = NULL;
01828 cpl_propertylist_delete(header); header = NULL;
01829
01830 mean_rms = mos_distortions_rms(rectified, lines, startwavelength,
01831 dispersion, 6, 0);
01832
01833 cpl_msg_info(recipe, "Mean residual: %f pixel", mean_rms);
01834
01835 mean_rms = cpl_table_get_column_mean(idscoeff, "error");
01836 mean_rms_err = cpl_table_get_column_stdev(idscoeff, "error");
01837
01838 cpl_msg_info(recipe, "Mean model accuracy: %f pixel (%f A)",
01839 mean_rms, mean_rms * dispersion);
01840
01841 restab = mos_resolution_table(rectified, startwavelength, dispersion,
01842 60000, lines);
01843
01844 if (restab) {
01845 cpl_msg_info(recipe, "Mean spectral resolution: %.2f",
01846 cpl_table_get_column_mean(restab, "resolution"));
01847 cpl_msg_info(recipe,
01848 "Mean reference lines FWHM: %.2f +/- %.2f pixel",
01849 cpl_table_get_column_mean(restab, "fwhm") / dispersion,
01850 cpl_table_get_column_mean(restab, "fwhm_rms") / dispersion);
01851
01852 cpl_table_duplicate_column(restab, "dlambda",
01853 restab, "fwhm");
01854 cpl_table_multiply_scalar(restab, "dlambda", dispersion);
01855 cpl_table_duplicate_column(restab, "dlambda_rms",
01856 restab, "fwhm_rms");
01857 cpl_table_multiply_scalar(restab, "dlambda_rms", dispersion);
01858
01859 if (qc) {
01860
01861 header = dfs_load_header(frameset, arc_tag, 0);
01862
01863 for (k = 0; k < j; k ++) {
01864 cpl_propertylist_delete(header);
01865 header = dfs_load_header(frameset, NULL, 0);
01866 }
01867
01868 if (header == NULL)
01869 fors_pmos_calib_exit("Cannot reload arc lamp header");
01870
01871 qclist = cpl_propertylist_new();
01872
01873 fors_qc_start_group(qclist, "2.0", instrume);
01874
01875
01876
01877
01878
01879
01880 if (fors_qc_write_string("PRO.CATG", spectral_resolution_tag,
01881 "Product category", instrume))
01882 fors_pmos_calib_exit("Cannot write product category to "
01883 "QC log file");
01884
01885 if (fors_qc_keyword_to_paf(header, "ESO DPR TYPE", NULL,
01886 "DPR type", instrume))
01887 fors_pmos_calib_exit("Missing keyword DPR TYPE in arc "
01888 "lamp header");
01889
01890 if (fors_qc_keyword_to_paf(header, "ESO TPL ID", NULL,
01891 "Template", instrume))
01892 fors_pmos_calib_exit("Missing keyword TPL ID in arc "
01893 "lamp header");
01894
01895 if (fors_qc_keyword_to_paf(header, "ESO INS GRIS1 NAME", NULL,
01896 "Grism name", instrume))
01897 fors_pmos_calib_exit("Missing keyword INS GRIS1 NAME in "
01898 "arc lamp header");
01899
01900 if (fors_qc_keyword_to_paf(header, "ESO INS GRIS1 ID", NULL,
01901 "Grism identifier", instrume))
01902 fors_pmos_calib_exit("Missing keyword INS GRIS1 ID in arc "
01903 "lamp header");
01904
01905 if (cpl_propertylist_has(header, "ESO INS FILT1 NAME"))
01906 fors_qc_keyword_to_paf(header, "ESO INS FILT1 NAME", NULL,
01907 "Filter name", instrume);
01908
01909 if (fors_qc_keyword_to_paf(header, "ESO INS COLL NAME", NULL,
01910 "Collimator name", instrume))
01911 fors_pmos_calib_exit("Missing keyword INS COLL NAME in arc "
01912 "lamp header");
01913
01914 if (fors_qc_keyword_to_paf(header, "ESO DET CHIP1 ID", NULL,
01915 "Chip identifier", instrume))
01916 fors_pmos_calib_exit("Missing keyword DET CHIP1 ID in arc "
01917 "lamp header");
01918
01919 if (fors_qc_keyword_to_paf(header, "ARCFILE", NULL,
01920 "Archive name of input data",
01921 instrume))
01922 fors_pmos_calib_exit("Missing keyword ARCFILE in arc "
01923 "lamp header");
01924
01925 cpl_propertylist_delete(header); header = NULL;
01926
01927 pipefile = dfs_generate_filename_tfits(spectral_resolution_tag);
01928 if (fors_qc_write_string("PIPEFILE", pipefile,
01929 "Pipeline product name", instrume))
01930 fors_pmos_calib_exit("Cannot write PIPEFILE to QC logfile");
01931 cpl_free(pipefile); pipefile = NULL;
01932
01933
01934
01935
01936
01937
01938 keyname = "QC.PMOS.RESOLUTION";
01939
01940 if (fors_qc_write_qc_double(qclist,
01941 cpl_table_get_column_mean(restab,
01942 "resolution"),
01943 keyname,
01944 "Angstrom",
01945 "Mean spectral resolution",
01946 instrume)) {
01947 fors_pmos_calib_exit("Cannot write mean spectral "
01948 "resolution to QC log file");
01949 }
01950
01951 keyname = "QC.PMOS.RESOLUTION.RMS";
01952
01953 if (fors_qc_write_qc_double(qclist,
01954 cpl_table_get_column_stdev(restab,
01955 "resolution"),
01956 keyname,
01957 "Angstrom",
01958 "Scatter of spectral resolution",
01959 instrume)) {
01960 fors_pmos_calib_exit("Cannot write spectral resolution "
01961 "scatter to QC log file");
01962 }
01963
01964 keyname = "QC.PMOS.RESOLUTION.NWAVE";
01965
01966 if (fors_qc_write_qc_int(qclist, cpl_table_get_nrow(restab) -
01967 cpl_table_count_invalid(restab,
01968 "resolution"),
01969 keyname,
01970 NULL,
01971 "Number of examined wavelengths "
01972 "for resolution computation",
01973 instrume)) {
01974 fors_pmos_calib_exit("Cannot write number of lines used "
01975 "in spectral resolution computation "
01976 "to QC log file");
01977 }
01978
01979 keyname = "QC.PMOS.RESOLUTION.MEANRMS";
01980
01981 if (fors_qc_write_qc_double(qclist,
01982 cpl_table_get_column_mean(restab,
01983 "resolution_rms"),
01984 keyname, NULL,
01985 "Mean error on spectral "
01986 "resolution computation",
01987 instrume)) {
01988 fors_pmos_calib_exit("Cannot write mean error in "
01989 "spectral resolution computation "
01990 "to QC log file");
01991 }
01992
01993 keyname = "QC.PMOS.RESOLUTION.NLINES";
01994
01995 if (fors_qc_write_qc_int(qclist,
01996 cpl_table_get_column_mean(restab,
01997 "nlines") *
01998 cpl_table_get_nrow(restab),
01999 keyname, NULL,
02000 "Number of lines for spectral "
02001 "resolution computation",
02002 instrume)) {
02003 fors_pmos_calib_exit("Cannot write number of examined "
02004 "wavelengths in spectral resolution "
02005 "computation to QC log file");
02006 }
02007
02008 fors_qc_end_group();
02009
02010 }
02011
02012 if (!j) {
02013 if(dfs_save_image_null(frameset, parlist,
02014 spectral_resolution_tag,
02015 recipe, version)) {
02016 fors_pmos_calib_exit(NULL);
02017 }
02018 }
02019
02020 header = dfs_load_header(frameset, arc_tag, 0);
02021
02022 for (k = 0; k < j; k ++) {
02023 cpl_propertylist_delete(header);
02024 header = dfs_load_header(frameset, NULL, 0);
02025 }
02026
02027 cpl_propertylist_append(header, qclist);
02028
02029 if (dfs_save_table_ext(restab, spectral_resolution_tag, header)) {
02030 fors_pmos_calib_exit(NULL);
02031 }
02032
02033 cpl_table_delete(restab); restab = NULL;
02034 cpl_propertylist_delete(qclist); qclist = NULL;
02035 cpl_propertylist_delete(header); header = NULL;
02036
02037 }
02038 else
02039 fors_pmos_calib_exit("Cannot compute the spectral "
02040 "resolution table");
02041
02042 if (!j) {
02043 if(dfs_save_image_null(frameset, parlist, disp_coeff_tag,
02044 recipe, version)) {
02045 fors_pmos_calib_exit(NULL);
02046 }
02047 }
02048
02049 header = dfs_load_header(frameset, arc_tag, 0);
02050
02051 for (k = 0; k < j; k ++) {
02052 cpl_propertylist_delete(header);
02053 header = dfs_load_header(frameset, NULL, 0);
02054 }
02055
02056 if (dfs_save_table_ext(idscoeff, disp_coeff_tag, header)) {
02057 fors_pmos_calib_exit(NULL);
02058 }
02059
02060 cpl_propertylist_delete(header);
02061
02062 if (!j) {
02063 mapped_flat = mos_wavelength_calibration(rect_flat, reference,
02064 startwavelength,
02065 endwavelength,
02066 dispersion, idscoeff, 0);
02067
02068 mapped_nflat = mos_wavelength_calibration(rect_nflat, reference,
02069 startwavelength,
02070 endwavelength,
02071 dispersion, idscoeff, 0);
02072
02073 cpl_image_delete(rect_flat); rect_flat = NULL;
02074 cpl_image_delete(rect_nflat); rect_nflat = NULL;
02075 }
02076
02077
02078
02079 cpl_table_delete(idscoeff); idscoeff = NULL;
02080
02081 header = dfs_load_header(frameset, arc_tag, 0);
02082
02083 for (k = 0; k < j; k ++) {
02084 cpl_propertylist_delete(header);
02085 header = dfs_load_header(frameset, NULL, 0);
02086 }
02087
02088 cpl_propertylist_update_double(header, "CRPIX1", 1.0);
02089 cpl_propertylist_update_double(header, "CRPIX2", 1.0);
02090 cpl_propertylist_update_double(header, "CRVAL1",
02091 startwavelength + dispersion/2);
02092 cpl_propertylist_update_double(header, "CRVAL2", 1.0);
02093
02094
02095 cpl_propertylist_update_double(header, "CD1_1", dispersion);
02096 cpl_propertylist_update_double(header, "CD1_2", 0.0);
02097 cpl_propertylist_update_double(header, "CD2_1", 0.0);
02098 cpl_propertylist_update_double(header, "CD2_2", 1.0);
02099 cpl_propertylist_update_string(header, "CTYPE1", "LINEAR");
02100 cpl_propertylist_update_string(header, "CTYPE2", "PIXEL");
02101 cpl_propertylist_update_int(header, "ESO PRO DATANCOM", 1);
02102
02103 if (!j) {
02104 if(dfs_save_image_null(frameset, parlist, reduced_lamp_tag,
02105 recipe, version)) {
02106 fors_pmos_calib_exit(NULL);
02107 }
02108 }
02109
02110 if (dfs_save_image_ext(rectified, reduced_lamp_tag, header)) {
02111 fors_pmos_calib_exit(NULL);
02112 }
02113
02114 cpl_image_delete(rectified); rectified = NULL;
02115
02116 cpl_propertylist_update_int(header, "ESO PRO DATANCOM", nflats);
02117
02118 if (!j) {
02119 if (dfs_save_image(frameset, mapped_flat, mapped_screen_flat_tag,
02120 header, parlist, recipe, version))
02121 fors_pmos_calib_exit(NULL);
02122 cpl_image_delete(mapped_flat); mapped_flat = NULL;
02123
02124 if (dfs_save_image(frameset, mapped_nflat, mapped_norm_flat_tag,
02125 header, parlist, recipe, version))
02126 fors_pmos_calib_exit(NULL);
02127 cpl_image_delete(mapped_nflat); mapped_nflat = NULL;
02128 }
02129
02130 cpl_propertylist_delete(header); header = NULL;
02131
02132 if (check) {
02133 save_header = dfs_load_header(frameset, arc_tag, 0);
02134 for (k = 0; k < j; k ++) {
02135 cpl_propertylist_delete(save_header);
02136 save_header = dfs_load_header(frameset, NULL, 0);
02137 }
02138
02139 cpl_propertylist_update_double(save_header, "CRPIX2", 1.0);
02140 cpl_propertylist_update_double(save_header, "CRVAL2", 1.0);
02141
02142 cpl_propertylist_update_double(save_header, "CD1_1", 1.0);
02143 cpl_propertylist_update_double(save_header, "CD1_2", 0.0);
02144 cpl_propertylist_update_double(save_header, "CD2_1", 0.0);
02145 cpl_propertylist_update_double(save_header, "CD2_2", 1.0);
02146 cpl_propertylist_update_string(save_header, "CTYPE1", "LINEAR");
02147 cpl_propertylist_update_string(save_header, "CTYPE2", "PIXEL");
02148
02149 if (!j) {
02150 if(dfs_save_image_null(frameset, parlist, disp_residuals_tag,
02151 recipe, version)) {
02152 fors_pmos_calib_exit(NULL);
02153 }
02154 }
02155
02156 if (dfs_save_image_ext(residual, disp_residuals_tag, save_header)) {
02157 fors_pmos_calib_exit(NULL);
02158 }
02159
02160 cpl_image_delete(residual); residual = NULL;
02161 cpl_propertylist_delete(save_header); save_header = NULL;
02162 }
02163
02164 wavemap = mos_map_wavelengths(coordinate, rainbow, slits, polytraces,
02165 reference, startwavelength, endwavelength,
02166 dispersion);
02167
02168 cpl_image_delete(rainbow); rainbow = NULL;
02169
02170 save_header = dfs_load_header(frameset, arc_tag, 0);
02171
02172 for (k = 0; k < j; k ++) {
02173 cpl_propertylist_delete(save_header);
02174 save_header = dfs_load_header(frameset, NULL, 0);
02175 }
02176
02177 if (qc) {
02178 fors_qc_start_group(save_header, "2.0", instrume);
02179
02180
02181
02182
02183
02184 if (fors_qc_write_string("PRO.CATG", wavelength_map_tag,
02185 "Product category", instrume))
02186 fors_pmos_calib_exit("Cannot write product category to "
02187 "QC log file");
02188
02189 if (fors_qc_keyword_to_paf(save_header, "ESO DPR TYPE", NULL,
02190 "DPR type", instrume))
02191 fors_pmos_calib_exit("Missing keyword DPR TYPE in arc "
02192 "lamp header");
02193
02194 if (fors_qc_keyword_to_paf(save_header, "ESO TPL ID", NULL,
02195 "Template", instrume))
02196 fors_pmos_calib_exit("Missing keyword TPL ID in arc "
02197 "lamp header");
02198
02199 if (fors_qc_keyword_to_paf(save_header, "ESO INS GRIS1 NAME", NULL,
02200 "Grism name", instrume))
02201 fors_pmos_calib_exit("Missing keyword INS GRIS1 NAME in arc "
02202 "lamp header");
02203
02204 if (fors_qc_keyword_to_paf(save_header, "ESO INS GRIS1 ID", NULL,
02205 "Grism identifier", instrume))
02206 fors_pmos_calib_exit("Missing keyword INS GRIS1 ID in arc "
02207 "lamp header");
02208
02209 if (cpl_propertylist_has(save_header, "ESO INS FILT1 NAME"))
02210 fors_qc_keyword_to_paf(save_header, "ESO INS FILT1 NAME", NULL,
02211 "Filter name", instrume);
02212
02213 if (fors_qc_keyword_to_paf(save_header, "ESO INS COLL NAME", NULL,
02214 "Collimator name", instrume))
02215 fors_pmos_calib_exit("Missing keyword INS COLL NAME in arc "
02216 "lamp header");
02217
02218 if (fors_qc_keyword_to_paf(save_header, "ESO DET CHIP1 ID", NULL,
02219 "Chip identifier", instrume))
02220 fors_pmos_calib_exit("Missing keyword DET CHIP1 ID in arc "
02221 "lamp header");
02222
02223 if (fors_qc_keyword_to_paf(save_header, "ESO DET WIN1 BINX", NULL,
02224 "Binning factor along X", instrume))
02225 fors_pmos_calib_exit("Missing keyword ESO DET WIN1 BINX "
02226 "in frame header");
02227
02228 if (fors_qc_keyword_to_paf(save_header, "ESO DET WIN1 BINY", NULL,
02229 "Binning factor along Y", instrume))
02230 fors_pmos_calib_exit("Missing keyword ESO DET WIN1 BINY "
02231 "in frame header");
02232
02233 if (fors_qc_keyword_to_paf(save_header, "ARCFILE", NULL,
02234 "Archive name of input data",
02235 instrume))
02236 fors_pmos_calib_exit("Missing keyword ARCFILE in arc "
02237 "lamp header");
02238
02239 pipefile = dfs_generate_filename(wavelength_map_tag);
02240 if (fors_qc_write_string("PIPEFILE", pipefile,
02241 "Pipeline product name", instrume))
02242 fors_pmos_calib_exit("Cannot write PIPEFILE to QC log file");
02243 cpl_free(pipefile); pipefile = NULL;
02244
02245
02246
02247
02248
02249
02250 if (fors_qc_write_qc_double(save_header,
02251 mean_rms,
02252 "QC.WAVE.ACCURACY",
02253 "pixel",
02254 "Mean accuracy of wavecalib model",
02255 instrume)) {
02256 fors_pmos_calib_exit("Cannot write mean wavelength calibration "
02257 "accuracy to QC log file");
02258 }
02259
02260
02261 if (fors_qc_write_qc_double(save_header,
02262 mean_rms_err,
02263 "QC.WAVE.ACCURACY.ERROR",
02264 "pixel",
02265 "Error on accuracy of wavecalib model",
02266 instrume)) {
02267 fors_pmos_calib_exit("Cannot write error on wavelength "
02268 "calibration accuracy to QC log file");
02269 }
02270
02271 if (same_offset && fabs(mxpos) < 0.05) {
02272
02273
02274 data = cpl_image_get_data(wavemap);
02275
02276 if (fors_qc_write_qc_double(save_header,
02277 data[nx/2 + ccd_ysize*nx/2],
02278 "QC.PMOS.CENTRAL.WAVELENGTH",
02279 "Angstrom",
02280 "Wavelength at CCD center",
02281 instrume)) {
02282 fors_pmos_calib_exit("Cannot write central wavelength "
02283 "to QC log file");
02284 }
02285 }
02286
02287 fors_qc_end_group();
02288
02289 }
02290
02291 if (!j) {
02292 if(dfs_save_image_null(frameset, parlist, wavelength_map_tag,
02293 recipe, version)) {
02294 fors_pmos_calib_exit(NULL);
02295 }
02296 }
02297
02298 if (dfs_save_image_ext(wavemap, wavelength_map_tag, save_header)) {
02299 fors_pmos_calib_exit(NULL);
02300 }
02301
02302 cpl_image_delete(wavemap); wavemap = NULL;
02303
02304 cpl_propertylist_erase_regexp(save_header, "^ESO QC ", 0);
02305
02306 cpl_propertylist_delete(save_header); save_header = NULL;
02307
02308 cpl_msg_indent_less();
02309
02310 }
02311
02312 if (dfs_save_image(frameset, coordinate, spatial_map_tag, save_header,
02313 parlist, recipe, version))
02314 fors_pmos_calib_exit(NULL);
02315
02316 cpl_image_delete(coordinate); coordinate = NULL;
02317 cpl_propertylist_delete(save_header); save_header = NULL;
02318
02319 header = NULL;
02320
02321 if (qc) {
02322
02323 double maxpos, maxneg, maxcurve, maxslope;
02324
02325 header = dfs_load_header(frameset, arc_tag, 0);
02326
02327 fors_qc_start_group(header, "2.0", instrume);
02328
02329
02330
02331
02332
02333 if (fors_qc_write_string("PRO.CATG", curv_coeff_tag,
02334 "Product category", instrume))
02335 fors_pmos_calib_exit("Cannot write product category to "
02336 "QC log file");
02337
02338 if (fors_qc_keyword_to_paf(header, "ESO DPR TYPE", NULL,
02339 "DPR type", instrume))
02340 fors_pmos_calib_exit("Missing keyword DPR TYPE in arc "
02341 "lamp header");
02342
02343 if (fors_qc_keyword_to_paf(header, "ESO TPL ID", NULL,
02344 "Template", instrume))
02345 fors_pmos_calib_exit("Missing keyword TPL ID in arc "
02346 "lamp header");
02347 if (fors_qc_keyword_to_paf(header, "ARCFILE", NULL,
02348 "Archive name of input data",
02349 instrume))
02350 fors_pmos_calib_exit("Missing keyword ARCFILE in arc "
02351 "lamp header");
02352
02353 pipefile = dfs_generate_filename(curv_coeff_tag);
02354 if (fors_qc_write_string("PIPEFILE", pipefile,
02355 "Pipeline product name", instrume))
02356 fors_pmos_calib_exit("Cannot write PIPEFILE to QC log file");
02357 cpl_free(pipefile); pipefile = NULL;
02358
02359
02360
02361
02362
02363 maxpos = fabs(cpl_table_get_column_max(polytraces, "c2"));
02364 maxneg = fabs(cpl_table_get_column_min(polytraces, "c2"));
02365 maxcurve = maxpos > maxneg ? maxpos : maxneg;
02366 if (fors_qc_write_qc_double(header,
02367 maxcurve,
02368 "QC.TRACE.MAX.CURVATURE",
02369 "Y pixel / X pixel ^2",
02370 "Max observed curvature in spectral tracing",
02371 instrume)) {
02372 fors_pmos_calib_exit("Cannot write max observed curvature in "
02373 "spectral tracing to QC log file");
02374 }
02375
02376 maxpos = fabs(cpl_table_get_column_max(polytraces, "c1"));
02377 maxneg = fabs(cpl_table_get_column_min(polytraces, "c1"));
02378 maxslope = maxpos > maxneg ? maxpos : maxneg;
02379
02380 if (fors_qc_write_qc_double(header,
02381 maxslope,
02382 "QC.TRACE.MAX.SLOPE",
02383 "Y pixel / X pixel",
02384 "Max observed slope in spectral tracing",
02385 instrume)) {
02386 fors_pmos_calib_exit("Cannot write max observed slope in spectral "
02387 "tracing to QC log file");
02388 }
02389
02390 fors_qc_end_group();
02391 }
02392
02393 if (dfs_save_table(frameset, polytraces, curv_coeff_tag, header,
02394 parlist, recipe, version)) {
02395 fors_pmos_calib_exit(NULL);
02396 }
02397
02398 cpl_propertylist_delete(header); header = NULL;
02399 cpl_table_delete(polytraces); polytraces = NULL;
02400
02401
02402
02403
02404 if (same_offset) {
02405 cpl_table *globaltbl;
02406 cpl_table *slitpos;
02407 double *l_ytop;
02408 int *l_id;
02409 int npairs;
02410 double *ytop = cpl_table_get_data_double(slits, "ytop");
02411 double *ybot = cpl_table_get_data_double(slits, "ybottom");
02412 int k;
02413
02414
02415
02416 nslits = cpl_table_get_nrow(slits);
02417
02418 cpl_table_new_column(slits, "pair_id", CPL_TYPE_INT);
02419
02420
02421 if (ccd_ysize == 400 || ccd_ysize == 500) {
02422
02423
02424
02425
02426
02427 l_ytop = cpl_malloc(sizeof(double));
02428 l_ytop[0] = 255.0;
02429 l_id = cpl_malloc(sizeof(double));
02430 l_id[0] = 10;
02431 npairs = 1;
02432 }
02433 else {
02434 globaltbl = dfs_load_table(frameset, master_distortion_tag, 1);
02435 slitpos = mos_build_slit_location(globaltbl, maskslits, ccd_ysize);
02436 l_ytop = cpl_table_get_data_double(slitpos, "ytop");
02437 l_id = cpl_table_get_data_int(slitpos, "slit_id");
02438 npairs = cpl_table_get_nrow(slitpos);
02439 if (rebin_dist != rebin) {
02440 float rescale = (float)rebin_dist / rebin;
02441 for (i = 0; i < npairs; i++) {
02442 l_ytop[i] *= rescale;
02443 }
02444 }
02445 }
02446
02447 for (k = 0; k < npairs; k++) {
02448 int h;
02449
02450 for (h = 0; h < nslits; h++) {
02451
02452 if (l_ytop[k] < ytop[h] && l_ytop[k] > ybot[h]) {
02453 if (h + 1 < nslits) {
02454 cpl_table_set_int(slits, "pair_id", h, l_id[k]);
02455 cpl_table_set_int(slits, "pair_id", h + 1, l_id[k]);
02456 }
02457 }
02458 }
02459 }
02460
02461
02462
02463 cpl_table_fill_invalid_int(slits, "pair_id", -1);
02464
02465 if (ccd_ysize == 400 || ccd_ysize == 500) {
02466 cpl_free(l_ytop);
02467 cpl_free(l_id);
02468 }
02469 else {
02470 cpl_table_delete(slitpos); slitpos = NULL;
02471 cpl_table_delete(globaltbl); globaltbl = NULL;
02472
02473 cpl_table_delete(maskslits); maskslits = NULL;
02474 }
02475 }
02476
02477 if (dfs_save_table(frameset, slits, slit_location_tag, NULL,
02478 parlist, recipe, version)) {
02479 fors_pmos_calib_exit(NULL);
02480 }
02481
02482 cpl_table_delete(slits); slits = NULL;
02483
02484 cpl_image_delete(spatial); spatial = NULL;
02485
02486 cpl_free(instrume); instrume = NULL;
02487
02488 cpl_table_delete(overscans); overscans = NULL;
02489 cpl_image_delete(master_bias); master_bias = NULL;
02490 cpl_image_delete(master_flat); master_flat = NULL;
02491
02492 cpl_table_delete(wavelengths); wavelengths = NULL;
02493 cpl_vector_delete(lines); lines = NULL;
02494
02495 if (cpl_error_get_code()) {
02496 cpl_msg_error(cpl_error_get_where(), cpl_error_get_message());
02497 fors_pmos_calib_exit(NULL);
02498 }
02499
02500 return 0;
02501 }