37 static int fors_detect_spectra_create(cpl_plugin *);
38 static int fors_detect_spectra_exec(cpl_plugin *);
39 static int fors_detect_spectra_destroy(cpl_plugin *);
40 static int fors_detect_spectra(cpl_parameterlist *, cpl_frameset *);
42 static char fors_detect_spectra_description[] =
43 "This recipe is used to detect and locate MOS/MXU slit spectra on the CCD,\n"
44 "applying a pattern-matching algorithm. The input spectral exposure must\n"
45 "contain spectra with the dispersion direction approximately horizontal,\n"
46 "with blue on the left and red on the right. Use recipe fors_wave_calib_lss\n"
47 "for LSS data, or for MOS/MXU data where all slits have the same offset.\n"
49 "The rows of the input spectral exposure are processed separately, one\n"
50 "by one. First, the background continuum is removed. Second, a list of\n"
51 "positions of reference lines candidates is created. Only peaks above a\n"
52 "given threshold (specified by the parameter --peakdetection) are selected.\n"
53 "Third, the pattern-matching task selects from the found peaks the ones\n"
54 "corresponding to the reference lines, listed in the input line catalog,\n"
55 "associating them to the appropriate wavelengths. The ensuing polynomial\n"
56 "fit is used to locate the central wavelength of the applied grism along\n"
57 "each image row. The contributions from all rows form an image of the\n"
58 "location of all spectra, that can be used as a starting point for the\n"
59 "proper modeling of the optical and spectral distortions. For more details\n"
60 "on this reduction strategy please refer to the FORS Pipeline User's Manual.\n"
62 "Note that specifying an input GRISM_TABLE will set some of the recipe\n"
63 "configuration parameters to default values valid for a particular grism.\n"
64 "Again, see the pipeline manual for more details.\n"
66 "In the table below the MXU acronym can be alternatively read as MOS.\n\n"
68 " DO category: Type: Explanation: Required:\n"
69 " LAMP_UNBIAS_MXU Calib Bias subtracted arc Y\n"
70 " MASTER_LINECAT Calib Line catalog Y\n"
71 " GRISM_TABLE Calib Grism table .\n\n"
73 " DO category: Data type: Explanation:\n"
74 " SLIT_MAP_MXU FITS image Map of central wavelength on CCD\n"
75 " SLIT_LOCATION_DETECT_MXU FITS table Slits positions on CCD\n"
76 " SPECTRA_DETECTION_MXU FITS image Check of preliminary detection\n\n";
78 #define fors_detect_spectra_exit(message) \
80 if ((const char *)message != NULL) cpl_msg_error(recipe, message); \
81 cpl_image_delete(spectra); \
82 cpl_image_delete(checkwave); \
83 cpl_image_delete(refimage); \
84 cpl_mask_delete(refmask); \
85 cpl_table_delete(grism_table); \
86 cpl_table_delete(wavelengths); \
87 cpl_table_delete(maskslits); \
88 cpl_table_delete(slits); \
89 cpl_vector_delete(lines); \
90 cpl_propertylist_delete(header); \
91 cpl_msg_indent_less(); \
95 #define fors_detect_spectra_exit_memcheck(message) \
97 if ((const char *)message != NULL) cpl_msg_info(recipe, message); \
98 printf("free spectra (%p)\n", spectra); \
99 cpl_image_delete(spectra); \
100 printf("free checkwave (%p)\n", checkwave); \
101 cpl_image_delete(checkwave); \
102 printf("free refimage (%p)\n", refimage); \
103 cpl_image_delete(refimage); \
104 printf("free refmask (%p)\n", refmask); \
105 cpl_mask_delete(refmask); \
106 printf("free grism_table (%p)\n", grism_table); \
107 cpl_table_delete(grism_table); \
108 printf("free wavelengths (%p)\n", wavelengths); \
109 cpl_table_delete(wavelengths); \
110 printf("free maskslits (%p)\n", maskslits); \
111 cpl_table_delete(maskslits); \
112 printf("free slits (%p)\n", slits); \
113 cpl_table_delete(slits); \
114 printf("free lines (%p)\n", lines); \
115 cpl_vector_delete(lines); \
116 printf("free header (%p)\n", header); \
117 cpl_propertylist_delete(header); \
118 cpl_msg_indent_less(); \
136 cpl_recipe *recipe = cpl_calloc(1,
sizeof *recipe );
137 cpl_plugin *plugin = &recipe->interface;
139 cpl_plugin_init(plugin,
142 CPL_PLUGIN_TYPE_RECIPE,
143 "fors_detect_spectra",
144 "Detect MOS/MXU spectra on CCD",
145 fors_detect_spectra_description,
148 "This file is currently part of the FORS Instrument Pipeline\n"
149 "Copyright (C) 2002-2010 European Southern Observatory\n\n"
150 "This program is free software; you can redistribute it and/or modify\n"
151 "it under the terms of the GNU General Public License as published by\n"
152 "the Free Software Foundation; either version 2 of the License, or\n"
153 "(at your option) any later version.\n\n"
154 "This program is distributed in the hope that it will be useful,\n"
155 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
156 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
157 "GNU General Public License for more details.\n\n"
158 "You should have received a copy of the GNU General Public License\n"
159 "along with this program; if not, write to the Free Software Foundation,\n"
160 "Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\n",
161 fors_detect_spectra_create,
162 fors_detect_spectra_exec,
163 fors_detect_spectra_destroy);
165 cpl_pluginlist_append(list, plugin);
181 static int fors_detect_spectra_create(cpl_plugin *plugin)
190 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
191 recipe = (cpl_recipe *)plugin;
199 recipe->parameters = cpl_parameterlist_new();
205 p = cpl_parameter_new_value(
"fors.fors_detect_spectra.dispersion",
207 "Expected spectral dispersion (Angstrom/pixel)",
208 "fors.fors_detect_spectra",
210 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"dispersion");
211 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
212 cpl_parameterlist_append(recipe->parameters, p);
218 p = cpl_parameter_new_value(
"fors.fors_detect_spectra.peakdetection",
220 "Initial peak detection threshold (ADU)",
221 "fors.fors_detect_spectra",
223 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"peakdetection");
224 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
225 cpl_parameterlist_append(recipe->parameters, p);
231 p = cpl_parameter_new_value(
"fors.fors_detect_spectra.wdegree",
233 "Degree of wavelength calibration polynomial",
234 "fors.fors_detect_spectra",
236 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"wdegree");
237 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
238 cpl_parameterlist_append(recipe->parameters, p);
244 p = cpl_parameter_new_value(
"fors.fors_detect_spectra.wradius",
246 "Search radius if iterating pattern-matching "
247 "with first-guess method",
248 "fors.fors_detect_spectra",
250 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"wradius");
251 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
252 cpl_parameterlist_append(recipe->parameters, p);
258 p = cpl_parameter_new_value(
"fors.fors_detect_spectra.wreject",
260 "Rejection threshold in dispersion "
261 "relation fit (pixel)",
262 "fors.fors_detect_spectra",
264 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"wreject");
265 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
266 cpl_parameterlist_append(recipe->parameters, p);
272 p = cpl_parameter_new_value(
"fors.fors_detect_spectra.wcolumn",
274 "Name of line catalog table column "
276 "fors.fors_detect_spectra",
278 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"wcolumn");
279 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
280 cpl_parameterlist_append(recipe->parameters, p);
286 p = cpl_parameter_new_value(
"fors.fors_detect_spectra.startwavelength",
288 "Start wavelength in spectral extraction",
289 "fors.fors_detect_spectra",
291 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"startwavelength");
292 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
293 cpl_parameterlist_append(recipe->parameters, p);
299 p = cpl_parameter_new_value(
"fors.fors_detect_spectra.endwavelength",
301 "End wavelength in spectral extraction",
302 "fors.fors_detect_spectra",
304 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"endwavelength");
305 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
306 cpl_parameterlist_append(recipe->parameters, p);
312 p = cpl_parameter_new_value(
"fors.fors_detect_spectra.slit_ident",
314 "Attempt slit identification for MOS or MXU",
315 "fors.fors_detect_spectra",
317 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"slit_ident");
318 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
319 cpl_parameterlist_append(recipe->parameters, p);
334 static int fors_detect_spectra_exec(cpl_plugin *plugin)
338 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
339 recipe = (cpl_recipe *)plugin;
343 return fors_detect_spectra(recipe->parameters, recipe->frames);
355 static int fors_detect_spectra_destroy(cpl_plugin *plugin)
359 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
360 recipe = (cpl_recipe *)plugin;
364 cpl_parameterlist_delete(recipe->parameters);
379 static int fors_detect_spectra(cpl_parameterlist *parlist,
380 cpl_frameset *frameset)
383 const char *recipe =
"fors_detect_spectra";
391 double peakdetection;
396 double startwavelength;
397 double endwavelength;
404 cpl_image *spectra = NULL;
405 cpl_image *checkwave = NULL;
406 cpl_image *refimage = NULL;
407 cpl_mask *refmask = NULL;
408 cpl_table *grism_table = NULL;
409 cpl_table *wavelengths = NULL;
410 cpl_table *slits = NULL;
411 cpl_table *positions = NULL;
412 cpl_table *maskslits = NULL;
413 cpl_vector *lines = NULL;
414 cpl_propertylist *header = NULL;
422 const char *spectra_detection_tag;
423 const char *slit_map_tag;
424 const char *slit_location_tag;
429 int treat_as_lss = 0;
439 int nslits_out_det = 0;
441 char *instrume = NULL;
444 cpl_msg_set_indentation(2);
450 cpl_msg_info(recipe,
"Recipe %s configuration parameters:", recipe);
451 cpl_msg_indent_more();
453 if (cpl_frameset_count_tags(frameset,
"GRISM_TABLE") > 1)
454 fors_detect_spectra_exit(
"Too many in input: GRISM_TABLE");
459 "fors.fors_detect_spectra.dispersion", grism_table);
461 if (dispersion <= 0.0)
462 fors_detect_spectra_exit(
"Invalid spectral dispersion value");
465 "fors.fors_detect_spectra.peakdetection", grism_table);
466 if (peakdetection <= 0.0)
467 fors_detect_spectra_exit(
"Invalid peak detection level");
470 "fors.fors_detect_spectra.wdegree", grism_table);
473 fors_detect_spectra_exit(
"Invalid polynomial degree");
476 fors_detect_spectra_exit(
"Max allowed polynomial degree is 5");
479 "fors.fors_detect_spectra.wradius", NULL);
482 fors_detect_spectra_exit(
"Invalid search radius");
485 "fors.fors_detect_spectra.wreject", NULL);
488 fors_detect_spectra_exit(
"Invalid rejection threshold");
491 "fors.fors_detect_spectra.wcolumn", NULL);
494 "fors.fors_detect_spectra.startwavelength", grism_table);
495 if (startwavelength > 1.0)
496 if (startwavelength < 3000.0 || startwavelength > 13000.0)
497 fors_detect_spectra_exit(
"Invalid wavelength");
500 "fors.fors_detect_spectra.endwavelength", grism_table);
501 if (endwavelength > 1.0) {
502 if (endwavelength < 3000.0 || endwavelength > 13000.0)
503 fors_detect_spectra_exit(
"Invalid wavelength");
504 if (startwavelength < 1.0)
505 fors_detect_spectra_exit(
"Invalid wavelength interval");
508 if (startwavelength > 1.0)
509 if (endwavelength - startwavelength <= 0.0)
510 fors_detect_spectra_exit(
"Invalid wavelength interval");
513 "fors.fors_detect_spectra.slit_ident", NULL);
515 cpl_table_delete(grism_table); grism_table = NULL;
517 if (cpl_error_get_code())
518 fors_detect_spectra_exit(
"Failure reading the "
519 "configuration parameters");
522 cpl_msg_indent_less();
523 cpl_msg_info(recipe,
"Check input set-of-frames:");
524 cpl_msg_indent_more();
526 narc = lamp_mxu = cpl_frameset_count_tags(frameset,
"LAMP_UNBIAS_MXU");
527 narc += lamp_mos = cpl_frameset_count_tags(frameset,
"LAMP_UNBIAS_MOS");
528 narc += lamp_lss = cpl_frameset_count_tags(frameset,
"LAMP_UNBIAS_LSS");
531 fors_detect_spectra_exit(
"Missing input arc lamp frame");
534 cpl_msg_error(recipe,
"Too many input arc lamp frames (%d > 1)", narc);
535 fors_detect_spectra_exit(NULL);
541 arc_tag =
"LAMP_UNBIAS_MXU";
542 spectra_detection_tag =
"SPECTRA_DETECTION_MXU";
543 slit_map_tag =
"SLIT_MAP_MXU";
544 slit_location_tag =
"SLIT_LOCATION_DETECT_MXU";
548 arc_tag =
"LAMP_UNBIAS_MOS";
549 spectra_detection_tag =
"SPECTRA_DETECTION_MOS";
550 slit_map_tag =
"SLIT_MAP_MOS";
551 slit_location_tag =
"SLIT_LOCATION_DETECT_MOS";
554 fors_detect_spectra_exit(
"Use recipe fors_wave_calib_lss "
555 "for LSS data reduction");
559 if (cpl_frameset_count_tags(frameset,
"MASTER_LINECAT") == 0)
560 fors_detect_spectra_exit(
"Missing required input: MASTER_LINECAT");
562 if (cpl_frameset_count_tags(frameset,
"MASTER_LINECAT") > 1)
563 fors_detect_spectra_exit(
"Too many in input: MASTER_LINECAT");
566 cpl_msg_warning(cpl_func,
"Input frames are not from the same grism");
569 cpl_msg_warning(cpl_func,
"Input frames are not from the same filter");
572 cpl_msg_warning(cpl_func,
"Input frames are not from the same chip");
583 fors_detect_spectra_exit(
"Cannot load arc lamp header");
585 instrume = (
char *)cpl_propertylist_get_string(header,
"INSTRUME");
586 if (instrume == NULL)
587 fors_detect_spectra_exit(
"Missing keyword INSTRUME in arc lamp header");
589 if (instrume[4] ==
'1')
590 snprintf(version, 80,
"%s/%s",
"fors1", VERSION);
591 if (instrume[4] ==
'2')
592 snprintf(version, 80,
"%s/%s",
"fors2", VERSION);
594 reference = cpl_propertylist_get_double(header,
"ESO INS GRIS1 WLEN");
596 if (cpl_error_get_code() != CPL_ERROR_NONE)
597 fors_detect_spectra_exit(
"Missing keyword ESO INS GRIS1 WLEN "
598 "in arc lamp frame header");
600 if (reference < 3000.0)
603 if (reference < 3000.0 || reference > 13000.0) {
604 cpl_msg_error(recipe,
"Invalid central wavelength %.2f read from "
605 "keyword ESO INS GRIS1 WLEN in arc lamp frame header",
607 fors_detect_spectra_exit(NULL);
610 cpl_msg_info(recipe,
"The central wavelength is: %.2f", reference);
612 rebin = cpl_propertylist_get_int(header,
"ESO DET WIN1 BINX");
614 if (cpl_error_get_code() != CPL_ERROR_NONE)
615 fors_detect_spectra_exit(
"Missing keyword ESO DET WIN1 BINX "
616 "in arc lamp frame header");
620 cpl_msg_warning(recipe,
"The rebin factor is %d, and therefore the "
621 "working dispersion used is %f A/pixel", rebin,
626 cpl_msg_info(recipe,
"Produce mask slit position table...");
633 cpl_propertylist_delete(header); header = NULL;
641 treat_as_lss = fors_mos_is_lss_like(maskslits, nslits_out_det);
644 cpl_msg_error(recipe,
"All slits have the same offset: %.2f mm\n"
645 "The LSS data reduction strategy must be applied: "
646 "please use recipe fors_wave_calib_lss", mxpos);
647 fors_detect_spectra_exit(NULL);
650 if (slit_ident == 0) {
651 cpl_table_delete(maskslits); maskslits = NULL;
655 cpl_msg_indent_less();
656 cpl_msg_info(recipe,
"Load arc lamp exposure...");
657 cpl_msg_indent_more();
659 spectra =
dfs_load_image(frameset, arc_tag, CPL_TYPE_FLOAT, 0, 0);
662 fors_detect_spectra_exit(
"Cannot load arc lamp exposure");
665 cpl_msg_indent_less();
666 cpl_msg_info(recipe,
"Load input line catalog...");
667 cpl_msg_indent_more();
671 if (wavelengths == NULL)
672 fors_detect_spectra_exit(
"Cannot load line catalog");
679 nlines = cpl_table_get_nrow(wavelengths);
682 fors_detect_spectra_exit(
"Empty input line catalog");
684 if (cpl_table_has_column(wavelengths, wcolumn) != 1) {
685 cpl_msg_error(recipe,
"Missing column %s in input line catalog table",
687 fors_detect_spectra_exit(NULL);
690 line = cpl_malloc(nlines *
sizeof(
double));
692 for (i = 0; i < nlines; i++)
693 line[i] = cpl_table_get(wavelengths, wcolumn, i, NULL);
695 cpl_table_delete(wavelengths); wavelengths = NULL;
697 lines = cpl_vector_wrap(nlines, line);
700 cpl_msg_indent_less();
701 cpl_msg_info(recipe,
"Detecting spectra on CCD...");
702 cpl_msg_indent_more();
704 nx = cpl_image_get_size_x(spectra);
705 ny = cpl_image_get_size_y(spectra);
707 refmask = cpl_mask_new(nx, ny);
710 fors_detect_spectra_exit(
"Cannot process saturation");
713 fors_detect_spectra_exit(
"Cannot subtract the background");
716 peakdetection, wradius,
717 wdegree, wreject, reference,
718 &startwavelength, &endwavelength,
719 NULL, NULL, NULL, NULL, NULL,
720 NULL, refmask, NULL);
722 cpl_image_delete(spectra); spectra = NULL;
723 cpl_vector_delete(lines); lines = NULL;
725 if (checkwave == NULL)
726 fors_detect_spectra_exit(
"Wavelength calibration failure.");
733 header = cpl_propertylist_new();
734 cpl_propertylist_update_double(header,
"CRPIX1", 1.0);
735 cpl_propertylist_update_double(header,
"CRPIX2", 1.0);
736 cpl_propertylist_update_double(header,
"CRVAL1",
737 startwavelength + dispersion/2);
738 cpl_propertylist_update_double(header,
"CRVAL2", 1.0);
741 cpl_propertylist_update_double(header,
"CD1_1", dispersion);
742 cpl_propertylist_update_double(header,
"CD1_2", 0.0);
743 cpl_propertylist_update_double(header,
"CD2_1", 0.0);
744 cpl_propertylist_update_double(header,
"CD2_2", 1.0);
745 cpl_propertylist_update_string(header,
"CTYPE1",
"LINEAR");
746 cpl_propertylist_update_string(header,
"CTYPE2",
"PIXEL");
748 if (
dfs_save_image(frameset, checkwave, spectra_detection_tag, header,
749 parlist, recipe, version))
750 fors_detect_spectra_exit(NULL);
752 cpl_image_delete(checkwave); checkwave = NULL;
753 cpl_propertylist_delete(header); header = NULL;
756 cpl_msg_info(recipe,
"Locate slits at reference wavelength on CCD...");
760 cpl_msg_error(cpl_error_get_where(),
"%s", cpl_error_get_message());
761 fors_detect_spectra_exit(
"No slits could be detected!");
764 refimage = cpl_image_new_from_mask(refmask);
765 cpl_mask_delete(refmask); refmask = NULL;
769 parlist, recipe, version))
770 fors_detect_spectra_exit(NULL);
771 cpl_propertylist_delete(header); header = NULL;
773 cpl_image_delete(refimage); refimage = NULL;
791 cpl_msg_indent_less();
792 cpl_msg_info(recipe,
"Attempt slit identification (optional)...");
793 cpl_msg_indent_more();
796 cpl_table_delete(maskslits); maskslits = NULL;
799 cpl_table_delete(slits);
806 cpl_table_and_selected_double(slits,
807 "ybottom", CPL_GREATER_THAN, ny-1);
808 cpl_table_or_selected_double(slits,
809 "ytop", CPL_LESS_THAN, 0);
810 cpl_table_erase_selected(slits);
812 nslits = cpl_table_get_nrow(slits);
815 fors_detect_spectra_exit(
"No slits found on the CCD");
817 cpl_msg_info(recipe,
"%d slits are entirely or partially "
818 "contained in CCD", nslits);
823 cpl_msg_info(recipe,
"Global distortion model cannot be computed");
824 if (cpl_error_get_code() != CPL_ERROR_NONE) {
825 fors_detect_spectra_exit(NULL);
831 parlist, recipe, version))
832 fors_detect_spectra_exit(NULL);
834 cpl_table_delete(slits); slits = NULL;
int cpl_plugin_get_info(cpl_pluginlist *list)
Build the list of available plugins, for this module.
cpl_image * dfs_load_image(cpl_frameset *frameset, const char *category, cpl_type type, int ext, int calib)
Loading image data of given category.
const char * dfs_get_parameter_string(cpl_parameterlist *parlist, const char *name, const cpl_table *defaults)
Reading a recipe string parameter value.
cpl_image * mos_wavelength_calibration_raw(const cpl_image *image, cpl_vector *lines, double dispersion, float level, int sradius, int order, double reject, double refwave, double *wavestart, double *waveend, int *nlines, double *error, cpl_table *idscoeff, cpl_image *calibration, cpl_image *residuals, cpl_table *restable, cpl_mask *refmask, cpl_table *detected_lines)
Derive wavelength calibration from a raw arc lamp or sky exposure.
cpl_propertylist * dfs_load_header(cpl_frameset *frameset, const char *category, int ext)
Loading header associated to data of given category.
cpl_table * mos_load_slits_fors_mxu(cpl_propertylist *header)
Create slit location table from FITS header of FORS2-MXU data.
cpl_table * mos_identify_slits(cpl_table *slits, cpl_table *maskslits, cpl_table *global)
Identify slits listed in a slit location table.
cpl_table * mos_load_slits_fors_mos(cpl_propertylist *header, int *nslits_out_det)
Create slit location table from FITS header of FORS1/2 MOS data.
cpl_error_code mos_subtract_background(cpl_image *image)
Subtract the background.
int dfs_get_parameter_bool(cpl_parameterlist *parlist, const char *name, const cpl_table *defaults)
Reading a recipe boolean parameter value.
int dfs_equal_keyword(cpl_frameset *frameset, const char *keyword)
Saving table data of given category.
int dfs_save_image(cpl_frameset *frameset, const cpl_image *image, const char *category, cpl_propertylist *header, const cpl_parameterlist *parlist, const char *recipename, const char *version)
Saving image data of given category.
cpl_table * dfs_load_table(cpl_frameset *frameset, const char *category, int ext)
Loading table data of given category.
int dfs_get_parameter_int(cpl_parameterlist *parlist, const char *name, const cpl_table *defaults)
Reading a recipe integer parameter value.
int dfs_save_table(cpl_frameset *frameset, const cpl_table *table, const char *category, cpl_propertylist *header, const cpl_parameterlist *parlist, const char *recipename, const char *version)
Saving table data of given category.
cpl_table * mos_locate_spectra(cpl_mask *mask)
Find the location of detected spectra on the CCD.
double dfs_get_parameter_double(cpl_parameterlist *parlist, const char *name, const cpl_table *defaults)
Reading a recipe double parameter value.
cpl_error_code mos_saturation_process(cpl_image *image)
Process saturation.