27#include <cxmessages.h>
29#include <cpl_recipe.h>
30#include <cpl_plugininfo.h>
31#include <cpl_parameterlist.h>
32#include <cpl_frameset.h>
34#include <cpl_errorstate.h>
36#include <irplib_sdp_spectrum.h>
42#include "gifiberutils.h"
43#include "gislitgeometry.h"
49#include "gitransmission.h"
50#include "girebinning.h"
51#include "gisgcalibration.h"
52#include "giastrometry.h"
54#include "gimessages.h"
58const char *sciqcpar[] = {
59 GIALIAS_QCSCHEME, GIALIAS_WLSTART, GIALIAS_WLEND,
60 GIALIAS_WLSTEP, GIALIAS_QCAIR, GIALIAS_QCFWHM,
61 GIALIAS_QCNFIB, GIALIAS_QCNFIBSCI, GIALIAS_QCNFIBSKY,
62 GIALIAS_QCMEANRED, GIALIAS_QCNSATSCI, GIALIAS_QCSNR,
63 GIALIAS_QCMAG, GIALIAS_QCDLTTEMP, GIALIAS_QCDLTTIME,
64 GIALIAS_QCBRIGHTFLG, GIALIAS_QCFLAG
67static cxint giscience(cpl_parameterlist*, cpl_frameset*);
69static cxint _giraffe_make_sdp_spectra(
const cxchar* flux_filename,
70 const cxchar* err_filename,
72 cpl_frameset* allframes,
73 const cpl_parameterlist* parlist,
74 const cxchar* recipe_id);
76const cxdouble saturation = 60000.;
82 static void replace_spaces_with_underscores(
char *str)
85 for (
int i = 0; str[i] !=
'\0'; i++) {
98giscience_create(cpl_plugin* plugin)
101 cpl_recipe* recipe = (cpl_recipe*)plugin;
103 cpl_parameter* p = NULL;
106 giraffe_error_init();
115 recipe->parameters = cpl_parameterlist_new();
116 cx_assert(recipe->parameters != NULL);
145 p = cpl_parameter_new_value(
"giraffe.siwc.apply",
147 "Enable simultaneous wavelength calibration "
152 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"siwc-apply");
153 cpl_parameterlist_append(recipe->parameters, p);
163 p = cpl_parameter_new_value(
"giraffe.sdp.format.generate",
165 "TRUE if additional files should be generated"
166 " in Science Data Product (SDP) format.",
170 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"generate-SDP-format");
171 cpl_parameterlist_append(recipe->parameters, p);
173 p = cpl_parameter_new_value(
"giraffe.sdp.nassoc.keys",
175 "Sets the number of dummy (empty) ASSONi,"
176 " ASSOCi and ASSOMi keywords to create.",
180 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
181 "dummy-association-keys");
182 cpl_parameterlist_append(recipe->parameters, p);
194giscience_exec(cpl_plugin* plugin)
197 cpl_errorstate prev_state;
199 cpl_recipe* recipe = (cpl_recipe*)plugin;
202 cx_assert(recipe->parameters != NULL);
203 cx_assert(recipe->frames != NULL);
205 prev_state = cpl_errorstate_get();
206 result = giscience(recipe->parameters, recipe->frames);
208 cpl_errorstate_dump(prev_state, CPL_FALSE, cpl_errorstate_dump_one);
215giscience_destroy(cpl_plugin* plugin)
218 cpl_recipe* recipe = (cpl_recipe*)plugin;
227 cpl_parameterlist_delete(recipe->parameters);
229 giraffe_error_clear();
241giscience(cpl_parameterlist* config, cpl_frameset* set)
244 const cxchar*
const _id =
"giscience";
247 const cxchar* filename = NULL;
250 cxbool calsim = FALSE;
252 cxbool gensdp = FALSE;
253 cxint nassoc_keys = 0;
254 cxchar* flux_filename = NULL;
255 cxchar* err_filename = NULL;
262 cxdouble exptime = 0.;
264 cx_slist* slist = NULL;
266 cpl_propertylist* properties = NULL;
268 cpl_matrix* biasareas = NULL;
270 cpl_frame* science_frame = NULL;
271 cpl_frame* mbias_frame = NULL;
272 cpl_frame* mdark_frame = NULL;
273 cpl_frame* bpixel_frame = NULL;
274 cpl_frame* slight_frame = NULL;
275 cpl_frame* locy_frame = NULL;
276 cpl_frame* locw_frame = NULL;
277 cpl_frame* psfdata_frame = NULL;
278 cpl_frame* grating_frame = NULL;
279 cpl_frame* linemask_frame = NULL;
280 cpl_frame* slit_frame = NULL;
281 cpl_frame* wcal_frame = NULL;
282 cpl_frame* rscience_frame = NULL;
283 cpl_frame* sext_frame = NULL;
284 cpl_frame* rbin_frame = NULL;
286 cpl_parameter* p = NULL;
288 GiImage* mbias = NULL;
289 GiImage* mdark = NULL;
290 GiImage* bpixel = NULL;
291 GiImage* slight = NULL;
292 GiImage* sscience = NULL;
293 GiImage* rscience = NULL;
295 GiTable* fibers = NULL;
296 GiTable* slitgeometry = NULL;
297 GiTable* grating = NULL;
298 GiTable* wcalcoeff = NULL;
300 GiLocalization* localization = NULL;
301 GiExtraction* extraction = NULL;
302 GiRebinning* rebinning = NULL;
304 GiBiasConfig* bias_config = NULL;
305 GiExtractConfig* extract_config = NULL;
306 GiFlatConfig* flat_config = NULL;
307 GiRebinConfig* rebin_config = NULL;
309 GiInstrumentMode mode;
311 GiRecipeInfo info = {(cxchar*)_id, 1, NULL, config};
313 GiGroupInfo groups[] = {
314 {GIFRAME_SCIENCE, CPL_FRAME_GROUP_RAW},
315 {GIFRAME_BADPIXEL_MAP, CPL_FRAME_GROUP_CALIB},
316 {GIFRAME_BIAS_MASTER, CPL_FRAME_GROUP_CALIB},
317 {GIFRAME_DARK_MASTER, CPL_FRAME_GROUP_CALIB},
318 {GIFRAME_FIBER_FLAT_EXTSPECTRA, CPL_FRAME_GROUP_CALIB},
319 {GIFRAME_FIBER_FLAT_EXTERRORS, CPL_FRAME_GROUP_CALIB},
320 {GIFRAME_SCATTERED_LIGHT_MODEL, CPL_FRAME_GROUP_CALIB},
321 {GIFRAME_LOCALIZATION_CENTROID, CPL_FRAME_GROUP_CALIB},
322 {GIFRAME_LOCALIZATION_WIDTH, CPL_FRAME_GROUP_CALIB},
323 {GIFRAME_PSF_CENTROID, CPL_FRAME_GROUP_CALIB},
324 {GIFRAME_PSF_WIDTH, CPL_FRAME_GROUP_CALIB},
325 {GIFRAME_PSF_DATA, CPL_FRAME_GROUP_CALIB},
326 {GIFRAME_WAVELENGTH_SOLUTION, CPL_FRAME_GROUP_CALIB},
327 {GIFRAME_LINE_MASK, CPL_FRAME_GROUP_CALIB},
328 {GIFRAME_SLITSETUP, CPL_FRAME_GROUP_CALIB},
329 {GIFRAME_SLITMASTER, CPL_FRAME_GROUP_CALIB},
330 {GIFRAME_GRATING, CPL_FRAME_GROUP_CALIB},
331 {NULL, CPL_FRAME_GROUP_NONE}
337 cpl_msg_error(_id,
"Invalid parameter list! Aborting ...");
342 cpl_msg_error(_id,
"Invalid frame set! Aborting ...");
346 status = giraffe_frameset_set_groups(set, groups);
349 cpl_msg_error(_id,
"Setting frame group information failed!");
358 nscience = cpl_frameset_count_tags(set, GIFRAME_SCIENCE);
361 cpl_msg_error(_id,
"Too few (%ld) raw frames (%s) present in "
362 "frame set! Aborting ...", nscience, GIFRAME_SCIENCE);
366 locy_frame = cpl_frameset_find(set, GIFRAME_PSF_CENTROID);
368 if (locy_frame == NULL) {
370 locy_frame = cpl_frameset_find(set, GIFRAME_LOCALIZATION_CENTROID);
372 if (locy_frame == NULL) {
373 cpl_msg_info(_id,
"No master localization (centroid position) "
374 "present in frame set. Aborting ...");
380 locw_frame = cpl_frameset_find(set, GIFRAME_PSF_WIDTH);
382 if (locw_frame == NULL) {
384 locw_frame = cpl_frameset_find(set, GIFRAME_LOCALIZATION_WIDTH);
386 if (locw_frame == NULL) {
387 cpl_msg_info(_id,
"No master localization (spectrum width) "
388 "present in frame set. Aborting ...");
394 grating_frame = cpl_frameset_find(set, GIFRAME_GRATING);
396 if (!grating_frame) {
397 cpl_msg_error(_id,
"No grating data present in frame set. "
405 cpl_msg_error(_id,
"No slit geometry present in frame set. "
410 wcal_frame = cpl_frameset_find(set, GIFRAME_WAVELENGTH_SOLUTION);
413 cpl_msg_error(_id,
"No dispersion solution present in frame set. "
418 linemask_frame = cpl_frameset_find(set, GIFRAME_LINE_MASK);
420 if (!linemask_frame) {
421 cpl_msg_warning(_id,
"No reference line mask present in frame set.");
424 bpixel_frame = cpl_frameset_find(set, GIFRAME_BADPIXEL_MAP);
427 cpl_msg_info(_id,
"No bad pixel map present in frame set.");
430 mbias_frame = cpl_frameset_find(set, GIFRAME_BIAS_MASTER);
433 cpl_msg_info(_id,
"No master bias present in frame set.");
436 mdark_frame = cpl_frameset_find(set, GIFRAME_DARK_MASTER);
439 cpl_msg_info(_id,
"No master dark present in frame set.");
442 slight_frame = cpl_frameset_find(set, GIFRAME_SCATTERED_LIGHT_MODEL);
445 cpl_msg_info(_id,
"No scattered light model present in frame set.");
448 psfdata_frame = cpl_frameset_find(set, GIFRAME_PSF_DATA);
450 if (!psfdata_frame) {
451 cpl_msg_info(_id,
"No PSF profile parameters present in frame set.");
459 slist = cx_slist_new();
461 science_frame = cpl_frameset_find(set, GIFRAME_SCIENCE);
463 for (i = 0; i < nscience; i++) {
465 filename = cpl_frame_get_filename(science_frame);
473 cpl_msg_error(_id,
"Cannot load raw science frame from '%s'. "
474 "Aborting ...", filename);
481 cx_slist_push_back(slist, raw);
483 science_frame = cpl_frameset_find(set, NULL);
487 nscience = (cxint)cx_slist_size(slist);
488 sscience = cx_slist_pop_front(slist);
491 cx_assert(properties != NULL);
493 cpl_errorstate tempes = cpl_errorstate_get();
497 double *scipix = cpl_image_get_data_double(sciim);
498 if (scipix != NULL) {
499 const size_t nxy = (size_t)(cpl_image_get_size_x(sciim) *
500 cpl_image_get_size_y(sciim));
503 for (scii = 0; scii < nxy; scii++) {
504 if (scipix[scii] > saturation)
509 cpl_errorstate_set(tempes);
512 cpl_propertylist_update_int(properties, GIALIAS_QCNSATSCI, nsaturated);
521 cpl_msg_info(_id,
"Averaging science frames ...");
523 exptime = cpl_propertylist_get_double(properties, GIALIAS_EXPTIME);
525 for (i = 1; i < nscience; i++) {
527 cpl_propertylist* _properties;
529 GiImage* science = cx_slist_pop_front(slist);
536 cx_assert(_properties != NULL);
538 exptime += cpl_propertylist_get_double(_properties, GIALIAS_EXPTIME);
547 cx_assert(cx_slist_empty(slist));
548 cx_slist_delete(slist);
558 cpl_msg_info(_id,
"Updating stacked science image properties ...");
560 cpl_propertylist_set_double(properties, GIALIAS_EXPTIME,
563 cpl_propertylist_append_double(properties, GIALIAS_EXPTTOT, exptime);
564 cpl_propertylist_set_comment(properties, GIALIAS_EXPTTOT,
565 "Total exposure time of all frames "
568 cpl_propertylist_erase(properties, GIALIAS_TPLEXPNO);
572 cpl_propertylist_append_int(properties, GIALIAS_DATANCOM, nscience);
573 cpl_propertylist_set_comment(properties, GIALIAS_DATANCOM,
574 "Number of combined frames");
588 if (bias_config->method == GIBIAS_METHOD_MASTER ||
589 bias_config->method == GIBIAS_METHOD_ZMASTER) {
592 cpl_msg_error(_id,
"Missing master bias frame! Selected bias "
593 "removal method requires a master bias frame!");
601 filename = cpl_frame_get_filename(mbias_frame);
608 cpl_msg_error(_id,
"Cannot load master bias from '%s'. "
609 "Aborting ...", filename);
626 filename = cpl_frame_get_filename(bpixel_frame);
633 cpl_msg_error(_id,
"Cannot load bad pixel map from '%s'. "
634 "Aborting ...", filename);
675 cpl_msg_error(_id,
"Bias removal failed. Aborting ...");
680 if (bpixel != NULL) {
696 GiDarkConfig dark_config = {GIDARK_METHOD_ZMASTER, 0.};
699 cpl_msg_info(_id,
"Correcting for dark current ...");
701 filename = cpl_frame_get_filename(mdark_frame);
707 cpl_msg_error(_id,
"Cannot load master dark from '%s'. "
708 "Aborting ...", filename);
713 if (bpixel != NULL) {
725 cpl_msg_error(_id,
"Dark subtraction failed! Aborting ...");
733 if (bpixel != NULL) {
752 cpl_msg_info(_id,
"Writing pre-processed science image ...");
757 GIFRAME_SCIENCE_REDUCED,
758 CPL_FRAME_LEVEL_INTERMEDIATE,
761 if (rscience_frame == NULL) {
762 cpl_msg_error(_id,
"Cannot create local file! Aborting ...");
769 cpl_frameset_insert(set, rscience_frame);
776 science_frame = cpl_frameset_find(set, GIFRAME_SCIENCE);
778 cpl_msg_info(_id,
"Building fiber setup for frame '%s'.",
779 cpl_frame_get_filename(science_frame));
784 cpl_msg_error(_id,
"Cannot create fiber setup for frame '%s'! "
785 "Aborting ...", cpl_frame_get_filename(science_frame));
798 cpl_msg_info(_id,
"Fiber reference setup taken from localization "
799 "frame '%s'.", cpl_frame_get_filename(locy_frame));
806 localization = giraffe_localization_new();
808 filename = cpl_frame_get_filename(locy_frame);
815 cpl_msg_error(_id,
"Cannot load localization (centroid "
816 "position) frame from '%s'. Aborting ...",
819 giraffe_localization_destroy(localization);
833 filename = cpl_frame_get_filename(locw_frame);
840 cpl_msg_error(_id,
"Cannot load localization (spectrum width) "
841 "frame from '%s'. Aborting ...", filename);
843 giraffe_localization_destroy(localization);
863 filename = cpl_frame_get_filename(slight_frame);
870 cpl_msg_error(_id,
"Cannot load scattered light model from '%s'. "
871 "Aborting ...", filename);
875 giraffe_localization_destroy(localization);
894 if ((extract_config->emethod == GIEXTRACT_OPTIMAL) ||
895 (extract_config->emethod == GIEXTRACT_HORNE)) {
897 if (psfdata_frame == NULL) {
899 const cxchar* emethod =
"Optimal";
901 if (extract_config->emethod == GIEXTRACT_HORNE) {
905 cpl_msg_error(_id,
"%s spectrum extraction requires PSF "
906 "profile data. Aborting ...", emethod);
909 extract_config = NULL;
911 if (slight != NULL) {
916 giraffe_localization_destroy(localization);
935 filename = cpl_frame_get_filename(psfdata_frame);
938 localization->psf = giraffe_psfdata_new();
939 status = giraffe_psfdata_load(localization->psf, filename);
942 cpl_msg_error(_id,
"Cannot load PSF profile data frame from "
943 "'%s'. Aborting ...", filename);
946 extract_config = NULL;
948 if (slight != NULL) {
953 giraffe_localization_destroy(localization);
976 extraction = giraffe_extraction_new();
979 localization, bpixel, slight,
983 cpl_msg_error(_id,
"Spectrum extraction failed! Aborting ...");
985 giraffe_extraction_destroy(extraction);
990 giraffe_localization_destroy(localization);
1023 if (flat_config->load == TRUE) {
1025 cpl_frame* flat_frame = NULL;
1027 GiImage* flat = NULL;
1030 flat_frame = cpl_frameset_find(set, GIFRAME_FIBER_FLAT_EXTSPECTRA);
1032 if (flat_frame == NULL) {
1033 cpl_msg_error(_id,
"Missing flat field spectra frame!");
1037 giraffe_extraction_destroy(extraction);
1038 giraffe_localization_destroy(localization);
1048 filename = cpl_frame_get_filename(flat_frame);
1054 cpl_msg_error(_id,
"Cannot load flat field spectra from '%s'. "
1055 "Aborting ...", filename);
1061 giraffe_extraction_destroy(extraction);
1062 giraffe_localization_destroy(localization);
1072 if (flat_config->apply == TRUE) {
1074 GiImage* errors = NULL;
1077 flat_frame = cpl_frameset_find(set, GIFRAME_FIBER_FLAT_EXTERRORS);
1079 if (flat_frame == NULL) {
1080 cpl_msg_warning(_id,
"Missing flat field spectra errors "
1085 filename = cpl_frame_get_filename(flat_frame);
1091 cpl_msg_error(_id,
"Cannot load flat field spectra "
1092 "errors from '%s'. Aborting ...",
1100 giraffe_extraction_destroy(extraction);
1101 giraffe_localization_destroy(localization);
1113 cpl_msg_info(_id,
"Applying flat field correction ...");
1119 cpl_msg_error(_id,
"Flat field correction failed! "
1127 giraffe_extraction_destroy(extraction);
1128 giraffe_localization_destroy(localization);
1143 if (flat_config->transmission == TRUE) {
1145 const cxchar* _filename = cpl_frame_get_filename(flat_frame);
1147 GiTable* _fibers = NULL;
1150 cpl_msg_info(_id,
"Loading fiber setup for frame '%s'.",
1156 cpl_msg_error(_id,
"Cannot create fiber setup for "
1157 "frame '%s'! Aborting ...", _filename);
1163 giraffe_extraction_destroy(extraction);
1164 giraffe_localization_destroy(localization);
1174 cpl_msg_info(_id,
"Applying relative fiber transmission "
1177 status = giraffe_transmission_setup(fibers, _fibers);
1181 status = giraffe_transmission_apply(extraction, fibers);
1186 cpl_msg_error(_id,
"Relative transmission correction failed! "
1193 giraffe_extraction_destroy(extraction);
1194 giraffe_localization_destroy(localization);
1219 cpl_msg_info(_id,
"Writing extracted spectra ...");
1227 giraffe_qc_update_sci_props(extprop, fibers);
1231 GIFRAME_SCIENCE_EXTSPECTRA,
1232 CPL_FRAME_LEVEL_FINAL,
1235 if (sext_frame == NULL) {
1236 cpl_msg_error(_id,
"Cannot create local file! Aborting ...");
1238 giraffe_extraction_destroy(extraction);
1239 giraffe_localization_destroy(localization);
1252 cpl_msg_error(_id,
"Cannot attach fiber setup to local file '%s'! "
1253 "Aborting ...", cpl_frame_get_filename(sext_frame));
1255 cpl_frame_delete(sext_frame);
1257 giraffe_extraction_destroy(extraction);
1258 giraffe_localization_destroy(localization);
1268 cpl_frameset_insert(set, sext_frame);
1276 giraffe_qc_update_sci_props(exterrprop, fibers);
1282 GIFRAME_SCIENCE_EXTERRORS,
1283 CPL_FRAME_LEVEL_FINAL,
1286 if (sext_frame == NULL) {
1287 cpl_msg_error(_id,
"Cannot create local file! Aborting ...");
1289 giraffe_extraction_destroy(extraction);
1290 giraffe_localization_destroy(localization);
1303 cpl_msg_error(_id,
"Cannot attach fiber setup to local file '%s'! "
1304 "Aborting ...", cpl_frame_get_filename(sext_frame));
1306 cpl_frame_delete(sext_frame);
1308 giraffe_extraction_destroy(extraction);
1309 giraffe_localization_destroy(localization);
1319 cpl_frameset_insert(set, sext_frame);
1323 if (extraction->npixels != NULL) {
1327 giraffe_qc_update_sci_props(extpixprop, fibers);
1332 GIFRAME_SCIENCE_EXTPIXELS,
1333 CPL_FRAME_LEVEL_FINAL,
1336 if (sext_frame == NULL) {
1337 cpl_msg_error(_id,
"Cannot create local file! Aborting ...");
1339 giraffe_extraction_destroy(extraction);
1340 giraffe_localization_destroy(localization);
1353 cpl_msg_error(_id,
"Cannot attach fiber setup to local file '%s'! "
1354 "Aborting ...", cpl_frame_get_filename(sext_frame));
1356 cpl_frame_delete(sext_frame);
1358 giraffe_extraction_destroy(extraction);
1359 giraffe_localization_destroy(localization);
1369 cpl_frameset_insert(set, sext_frame);
1378 GIFRAME_SCIENCE_EXTTRACE,
1379 CPL_FRAME_LEVEL_FINAL,
1382 if (sext_frame == NULL) {
1383 cpl_msg_error(_id,
"Cannot create local file! Aborting ...");
1385 giraffe_extraction_destroy(extraction);
1386 giraffe_localization_destroy(localization);
1399 cpl_msg_error(_id,
"Cannot attach fiber setup to local file '%s'! "
1400 "Aborting ...", cpl_frame_get_filename(sext_frame));
1402 cpl_frame_delete(sext_frame);
1404 giraffe_extraction_destroy(extraction);
1405 giraffe_localization_destroy(localization);
1415 cpl_frameset_insert(set, sext_frame);
1419 if (extraction->model != NULL) {
1424 GIFRAME_SCIENCE_EXTMODEL,
1425 CPL_FRAME_LEVEL_FINAL,
1428 if (sext_frame == NULL) {
1429 cpl_msg_error(_id,
"Cannot create local file! Aborting ...");
1431 giraffe_extraction_destroy(extraction);
1432 giraffe_localization_destroy(localization);
1445 cpl_msg_error(_id,
"Cannot attach fiber setup to local file '%s'! "
1446 "Aborting ...", cpl_frame_get_filename(sext_frame));
1448 cpl_frame_delete(sext_frame);
1450 giraffe_extraction_destroy(extraction);
1451 giraffe_localization_destroy(localization);
1461 cpl_frameset_insert(set, sext_frame);
1471 filename = (cxchar *)cpl_frame_get_filename(wcal_frame);
1473 tempes = cpl_errorstate_get();
1475 const char qcdltcopy[] =
"^(ESO INS TEMP53 VAL|MJD-OBS)$";
1476 cpl_propertylist * qcdltlist = cpl_propertylist_load_regexp(filename, 0,
1478 cpl_errorstate_set(tempes);
1484 cpl_msg_error(_id,
"Cannot load dispersion solution from "
1485 "'%s'. Aborting ...", filename);
1487 giraffe_extraction_destroy(extraction);
1488 giraffe_localization_destroy(localization);
1503 filename = (cxchar *)cpl_frame_get_filename(grating_frame);
1511 cpl_msg_error(_id,
"Cannot load grating data from '%s'. "
1512 "Aborting ...", filename);
1514 giraffe_extraction_destroy(extraction);
1515 giraffe_localization_destroy(localization);
1531 filename = (cxchar *)cpl_frame_get_filename(slit_frame);
1535 if (slitgeometry == NULL) {
1536 cpl_msg_error(_id,
"Cannot load slit geometry data from '%s'. "
1537 "Aborting ...", filename);
1541 giraffe_extraction_destroy(extraction);
1542 giraffe_localization_destroy(localization);
1560 cpl_msg_error(_id,
"Slit geometry data from '%s' is not "
1561 "applicable for current fiber setup! "
1562 "Aborting ...", filename);
1567 giraffe_extraction_destroy(extraction);
1568 giraffe_localization_destroy(localization);
1586 cpl_msg_info(_id,
"Spectrum rebinning");
1593 localization, grating, slitgeometry,
1594 wcalcoeff, rebin_config);
1597 cpl_msg_error(_id,
"Rebinning of science spectra failed! Aborting...");
1601 giraffe_extraction_destroy(extraction);
1602 giraffe_localization_destroy(localization);
1623 p = cpl_parameterlist_find(config,
"giraffe.siwc.apply");
1624 cx_assert(p != NULL);
1626 siwc = cpl_parameter_get_bool(p);
1630 cx_assert(properties != NULL);
1633 if (cpl_propertylist_has(properties, GIALIAS_STSCTAL) == TRUE) {
1634 calsim = cpl_propertylist_get_bool(properties, GIALIAS_STSCTAL);
1638 if ((siwc == TRUE) && (calsim == TRUE) && (linemask_frame != NULL)) {
1647 if (siwc_config == NULL) {
1654 giraffe_extraction_destroy(extraction);
1655 giraffe_localization_destroy(localization);
1669 filename = cpl_frame_get_filename(linemask_frame);
1674 cpl_msg_error(_id,
"Cannot load line reference mask from '%s'. "
1675 "Aborting ...", filename);
1685 giraffe_extraction_destroy(extraction);
1686 giraffe_localization_destroy(localization);
1702 linemask, siwc_config);
1705 cpl_msg_error(_id,
"Applying simultaneous wavelength "
1706 "calibration correction failed! Aborting...");
1716 giraffe_extraction_destroy(extraction);
1717 giraffe_localization_destroy(localization);
1741 localization, grating, slitgeometry,
1742 wcalcoeff, rebin_config);
1745 cpl_msg_error(_id,
"Rebinning of science spectra failed! "
1750 giraffe_extraction_destroy(extraction);
1751 giraffe_localization_destroy(localization);
1767 giraffe_extraction_destroy(extraction);
1770 giraffe_localization_destroy(localization);
1771 localization = NULL;
1774 rebin_config = NULL;
1791 cpl_msg_warning(_id,
"Missing observation time properties! "
1792 "Barycentric correction computation "
1799 cpl_msg_warning(_id,
"Missing telescope location properties! "
1800 "Barycentric correction computation "
1807 cpl_msg_warning(_id,
"Object positions are not available "
1808 "Barycentric correction computation "
1815 cpl_msg_error(_id,
"Barycentric correction computation "
1816 "failed! Aborting...");
1843 tempes = cpl_errorstate_get();
1855 double dlttemp = cpl_propertylist_get_double(rbprop,
"ESO INS TEMP53 VAL");
1856 dlttemp -= cpl_propertylist_get_double(qcdltlist,
"ESO INS TEMP53 VAL");
1858 double dltdate = cpl_propertylist_get_double(rbprop,
"MJD-OBS");
1859 dltdate -= cpl_propertylist_get_double(qcdltlist,
"MJD-OBS");
1861 cpl_propertylist_append_double(rbprop, GIALIAS_QCDLTTEMP, dlttemp);
1862 cpl_propertylist_append_double(rbprop, GIALIAS_QCDLTTIME, dltdate);
1871 int bitmask = pow(2, nbits) - 1;
1873 if (-1.5 < dlttemp && dlttemp < 1.5) {
1877 if (-1.0 < dltdate && dltdate < 1.0) {
1881 if (nsaturated < 1000){
1885 if (cpl_propertylist_get_int(rbprop, GIALIAS_QCNFIBSCI) >= 10) {
1889 if (cpl_propertylist_get_int(rbprop, GIALIAS_QCNFIBSKY) >= 1) {
1898 char bitmaskstr[nbits + 1];
1900 for (
int biti = 0; biti < nbits; biti++) {
1901 bitmaskstr[biti] = (bitmask & (1 << biti)) ?
'1' :
'0';
1903 bitmaskstr[nbits] =
'\0';
1905 cpl_propertylist_append_string(rbprop, GIALIAS_QCFLAG, bitmaskstr);
1907 cpl_errorstate_set(tempes);
1912 GIFRAME_SCIENCE_RBNSPECTRA,
1913 CPL_FRAME_LEVEL_FINAL,
1916 if (rbin_frame == NULL) {
1917 cpl_msg_error(_id,
"Cannot create local file! Aborting ...");
1933 cpl_msg_error(_id,
"Cannot attach fiber setup to local "
1934 "file '%s'! Aborting ...",
1935 cpl_frame_get_filename(rbin_frame));
1944 cpl_frame_delete(rbin_frame);
1949 cpl_frameset_insert(set, rbin_frame);
1950 flux_filename = cpl_strdup(cpl_frame_get_filename(rbin_frame));
1954 tempes = cpl_errorstate_get();
1966 cpl_propertylist_append_double(rberrprop, GIALIAS_QCDLTTEMP, dlttemp);
1967 cpl_propertylist_append_double(rberrprop, GIALIAS_QCDLTTIME, dltdate);
1969 cpl_propertylist_append_string(rberrprop, GIALIAS_QCFLAG, bitmaskstr);
1973 cpl_errorstate_set(tempes);
1976 GIFRAME_SCIENCE_RBNERRORS,
1977 CPL_FRAME_LEVEL_FINAL,
1980 if (rbin_frame == NULL) {
1981 cpl_msg_error(_id,
"Cannot create local file! Aborting ...");
1990 cpl_free(flux_filename);
1998 cpl_msg_error(_id,
"Cannot attach fiber setup to local "
1999 "file '%s'! Aborting ...",
2000 cpl_frame_get_filename(rbin_frame));
2010 cpl_frame_delete(rbin_frame);
2011 cpl_free(flux_filename);
2016 cpl_frameset_insert(set, rbin_frame);
2017 err_filename = cpl_strdup(cpl_frame_get_filename(rbin_frame));
2025 p = cpl_parameterlist_find(config,
"giraffe.sdp.format.generate");
2026 cx_assert(p != NULL);
2027 gensdp = cpl_parameter_get_bool(p);
2028 p = cpl_parameterlist_find(config,
"giraffe.sdp.nassoc.keys");
2029 cx_assert(p != NULL);
2030 nassoc_keys = cpl_parameter_get_int(p);
2033 if (mode == GIMODE_MEDUSA) {
2034 status = _giraffe_make_sdp_spectra(flux_filename, err_filename,
2035 nassoc_keys, set, config, _id);
2037 cpl_msg_error(_id,
"Failed to generate spectra in Science Data"
2038 " Product format.");
2048 cpl_free(flux_filename);
2049 cpl_free(err_filename);
2054 cpl_msg_warning(_id,
"Requested to generate SDP 1D spectra, but"
2055 " this is currently only supported for the MEDUSA"
2056 " mode. Skipping SDP generation.");
2059 cpl_free(flux_filename);
2060 cpl_free(err_filename);
2067 if (mode == GIMODE_IFU || mode == GIMODE_ARGUS) {
2069 cpl_frame* rimg_frame = NULL;
2071 GiFieldOfView* fov = NULL;
2073 GiFieldOfViewConfig* fov_config = NULL;
2075 GiFieldOfViewCubeFormat cube_format = GIFOV_FORMAT_ESO3D;
2080 cube_format = fov_config->format;
2083 cpl_msg_info(_id,
"Reconstructing image and data cube from rebinned "
2089 slitgeometry, fov_config);
2094 cpl_msg_warning(_id,
"No reconstructed image was built. "
2095 "Fiber list has no fiber position "
2099 cpl_msg_error(_id,
"Image reconstruction failed! Aborting...");
2129 GIFRAME_SCIENCE_RCSPECTRA,
2130 CPL_FRAME_LEVEL_FINAL,
2133 if (rimg_frame == NULL) {
2134 cpl_msg_error(_id,
"Cannot create local file! Aborting ...");
2148 cpl_frameset_insert(set, rimg_frame);
2156 GIFRAME_SCIENCE_RCERRORS,
2157 CPL_FRAME_LEVEL_FINAL,
2160 if (rimg_frame == NULL) {
2161 cpl_msg_error(_id,
"Cannot create local file! Aborting ...");
2175 cpl_frameset_insert(set, rimg_frame);
2180 if (cube_format == GIFOV_FORMAT_SINGLE) {
2184 if (fov->cubes.spectra != NULL) {
2186 cxint component = 0;
2192 properties = cpl_propertylist_duplicate(properties);
2197 CPL_FRAME_LEVEL_FINAL,
2203 cpl_propertylist_delete(properties);
2206 if (rimg_frame == NULL) {
2207 cpl_msg_error(_id,
"Cannot create local file! Aborting ...");
2219 slitgeometry = NULL;
2233 cpl_msg_error(_id,
"Cannot attach fiber setup to local "
2234 "file '%s'! Aborting ...",
2235 cpl_frame_get_filename(rimg_frame));
2237 cpl_frame_delete(rimg_frame);
2249 slitgeometry = NULL;
2260 cpl_frameset_insert(set, rimg_frame);
2266 if (fov->cubes.errors != NULL) {
2268 cxint component = 1;
2274 properties = cpl_propertylist_duplicate(properties);
2279 CPL_FRAME_LEVEL_FINAL,
2285 cpl_propertylist_delete(properties);
2288 if (rimg_frame == NULL) {
2289 cpl_msg_error(_id,
"Cannot create local file! Aborting ...");
2301 slitgeometry = NULL;
2315 cpl_msg_error(_id,
"Cannot attach fiber setup to local "
2316 "file '%s'! Aborting ...",
2317 cpl_frame_get_filename(rimg_frame));
2319 cpl_frame_delete(rimg_frame);
2331 slitgeometry = NULL;
2342 cpl_frameset_insert(set, rimg_frame);
2353 properties = cpl_propertylist_duplicate(properties);
2358 CPL_FRAME_LEVEL_FINAL,
2364 cpl_propertylist_delete(properties);
2367 if (rimg_frame == NULL) {
2368 cpl_msg_error(_id,
"Cannot create local file! Aborting ...");
2380 slitgeometry = NULL;
2394 cpl_msg_error(_id,
"Cannot attach fiber setup to local "
2395 "file '%s'! Aborting ...",
2396 cpl_frame_get_filename(rimg_frame));
2398 cpl_frame_delete(rimg_frame);
2410 slitgeometry = NULL;
2421 cpl_frameset_insert(set, rimg_frame);
2454cpl_plugin_get_info(cpl_pluginlist* list)
2457 cpl_recipe* recipe = cx_calloc(1,
sizeof *recipe);
2458 cpl_plugin* plugin = &recipe->interface;
2461 cpl_plugin_init(plugin,
2463 GIRAFFE_BINARY_VERSION,
2464 CPL_PLUGIN_TYPE_RECIPE,
2466 "Process a science observation.",
2467 "For detailed information please refer to the "
2468 "GIRAFFE pipeline user manual.\nIt is available at "
2469 "http://www.eso.org/pipelines.",
2477 cpl_pluginlist_append(list, plugin);
2486typedef struct _giraffe_lut_entry {
2487 const char* expmode;
2502static cpl_boolean _giraffe_lut_is_sorted(
const giraffe_lut_entry* lut,
2506 if (nentries < 2)
return CPL_TRUE;
2507 for (i = 0; i < nentries - 1; ++i) {
2508 if (strcmp(lut[i].expmode, lut[i+1].expmode) >= 0) {
2525static const giraffe_lut_entry* _giraffe_find_lut_entry(
const char* expmode)
2527 static giraffe_lut_entry lut[] = {
2532 {
"H379.", 25000, 0.2250, 20.0, 60},
2533 {
"H379.0", 25000, 0.2250, 20.0, 60},
2534 {
"H395.8", 22000, 0.1913, 21.1, 53},
2535 {
"H412.4", 30000, 0.1326, 22.3, 48},
2536 {
"H429.7", 23000, 0.1471, 23.5, 67},
2537 {
"H447.1", 20000, 0.0906, 24.9, 63},
2538 {
"H447.1A", 20000, 0.0906, 24.9, 63},
2539 {
"H447.1B", 31000, 0.1297, 23.5, 58},
2540 {
"H465.6", 23000, 0.1573, 22.4, 57},
2541 {
"H484.5", 19000, 0.1175, 23.5, 57},
2542 {
"H484.5A", 19000, 0.1175, 23.5, 57},
2543 {
"H484.5B", 33000, 0.0907, 24.6, 61},
2544 {
"H504.8", 22000, 0.1726, 25.2, 56},
2545 {
"H525.8", 17000, 0.1397, 25.8, 49},
2546 {
"H525.8A", 17000, 0.1397, 25.8, 49},
2547 {
"H525.8B", 29000, 0.2014, 26.4, 44},
2548 {
"H548.8", 20000, 0.2389, 26.9, 51},
2549 {
"H572.8", 27000, 0.1844, 27.5, 49},
2550 {
"H599.3", 18000, 0.1683, 28.3, 57},
2551 {
"H627.3", 24000, 0.1268, 29.0, 50},
2552 {
"H651.5", 17000, 0.1185, 30.0, 42},
2553 {
"H651.5A", 17000, 0.1185, 30.0, 42},
2554 {
"H651.5B", 35000, 0.1253, 31.5, 37},
2555 {
"H665.", 17000, 0.2076, 33.0, 45},
2556 {
"H665.0", 17000, 0.2076, 33.0, 45},
2557 {
"H679.7", 19000, 0.1621, 34.5, 51},
2558 {
"H710.5", 25000, 0.1495, 36.0, 48},
2559 {
"H737.", 16000, 0.1456, 37.5, 47},
2560 {
"H737.0", 16000, 0.1456, 37.5, 47},
2561 {
"H737.0A", 16000, 0.1456, 37.5, 47},
2562 {
"H737.0B", 35000, 0.1147, 39.5, 40},
2563 {
"H769.1", 19000, 0.2811, 41.8, 35},
2564 {
"H805.3", 14000, 0.2662, 42.4, 39},
2565 {
"H805.3A", 14000, 0.2662, 42.4, 39},
2566 {
"H805.3B", 25000, 0.2342, 42.9, 28},
2567 {
"H836.6", 16000, 0.2032, 43.3, 21},
2568 {
"H836.6A", 16000, 0.2032, 43.3, 21},
2569 {
"H836.6B", 34000, 0.1073, 43.7, 14},
2570 {
"H875.7", 18000, 0.2026, 44.3, 29},
2571 {
"H920.5", 12000, 0.1568, 44.9, 32},
2572 {
"H920.5A", 12000, 0.1568, 44.9, 32},
2573 {
"H920.5B", 24000, 0.2531, 45.9, 28},
2574 {
"L385.7", 7500, 0.3358, 58.0, 43},
2575 {
"L427.2", 6300, 0.2152, 61.1, 62},
2576 {
"L479.7", 7500, 0.1554, 71.0, 61},
2577 {
"L543.1", 5800, 0.2065, 82.1, 58},
2578 {
"L614.2", 6600, 0.1803, 79.0, 51},
2579 {
"L682.2", 8100, 0.1843, 74.0, 50},
2580 {
"L773.4", 5400, 0.1617, 94.0, 44},
2581 {
"L881.7", 6600, 0.1614, 119.0, 29}
2583 static const size_t nentries =
sizeof(lut) /
sizeof(giraffe_lut_entry);
2585 int high = (int)nentries - 1;
2587 assert(_giraffe_lut_is_sorted(lut, nentries));
2588 assert(expmode != NULL);
2592 int mid = (low + high) >> 1;
2593 int result = strcmp(expmode, lut[mid].expmode);
2596 }
else if (result < 0) {
2601 }
while (high >= low);
2611static double _giraffe_lookup_specres(
const char* expmode)
2613 const giraffe_lut_entry* entry = _giraffe_find_lut_entry(expmode);
2614 if (entry == NULL)
return NAN;
2615 return entry->specres;
2624static double _giraffe_lookup_lamrms(
const char* expmode)
2626 const giraffe_lut_entry* entry = _giraffe_find_lut_entry(expmode);
2627 if (entry == NULL)
return NAN;
2628 if (isnan(entry->lamrms) || isnan(entry->spec_length))
return NAN;
2629 return entry->lamrms * entry->spec_length / 4100.;
2638static double _giraffe_lookup_lamnlin(
const char* expmode)
2640 const giraffe_lut_entry* entry = _giraffe_find_lut_entry(expmode);
2641 if (entry == NULL)
return -1;
2642 return entry->lamnlin;
2656static cpl_type _giraffe_calc_wave_type(
double crval2,
double crpix2,
2657 double cdelt2, cpl_size naxis2)
2659 static const double errfrac = 0.02;
2660 static const double single_precision_digits = 7;
2661 double lo = (1.0 - crpix2) * cdelt2;
2662 double hi = ((double)naxis2 - crpix2) * cdelt2;
2663 double maxwave = crval2 + (hi > lo ? hi : lo);
2664 double binfrac = (maxwave != 0.0) ? fabs(cdelt2 / maxwave) : 0.0;
2665 if (binfrac * errfrac < pow(10, -single_precision_digits)) {
2666 return CPL_TYPE_DOUBLE;
2668 return CPL_TYPE_FLOAT;
2682static cpl_boolean _giraffe_ancillary_data_available(
const char* filename,
2683 const GiTable* fibertable)
2687 const char** spectypes = NULL;
2689 assert(filename != NULL);
2691 cpl_error_ensure(tbl != NULL, cpl_error_get_code(),
return CPL_FALSE,
2692 "The fiber table is not available for '%s'.", filename);
2694 spectypes = cpl_table_get_data_string_const(tbl, GIALIAS_COLUMN_TYPE);
2695 cpl_error_ensure(spectypes != NULL, cpl_error_get_code(),
return CPL_FALSE,
2696 "Could not fetch the '%s' column from the fiber setup"
2697 " table in '%s'.", GIALIAS_COLUMN_TYPE, filename);
2703 for (i = 0; i < cpl_table_get_nrow(tbl); ++i) {
2704 if ((spectypes[i][0] !=
'\0') && (strcmp(spectypes[i],
"M") != 0)) {
2731static cpl_error_code _giraffe_make_ancillary_file(cpl_frameset* allframes,
2732 const char* outputfile,
2733 const char* infilename,
2734 const GiImage* fluximage,
2735 const GiTable* fibertable)
2737 cpl_error_code error = CPL_ERROR_NONE;
2739 cpl_frame* frame = NULL;
2741 GiImage* image = NULL;
2743 cpl_image* img = NULL;
2745 cpl_image* subimg = NULL;
2746 cpl_propertylist* comments = NULL;
2748 int* indices = NULL;
2749 const char** spectypes = NULL;
2751 assert(allframes != NULL);
2752 assert(outputfile != NULL);
2753 assert(infilename != NULL);
2755 cpl_error_ensure(srcimg != NULL && table != NULL && tbl != NULL,
2756 cpl_error_get_code(),
goto cleanup,
2757 "The image or table are not available for '%s'.",
2761 frame = cpl_frame_new();
2762 error |= cpl_frame_set_filename(frame, outputfile);
2763 error |= cpl_frame_set_tag(frame, GIALIAS_ASSO_PROCATG_VALUE);
2764 error |= cpl_frame_set_type(frame, CPL_FRAME_TYPE_IMAGE);
2765 error |= cpl_frame_set_group(frame, CPL_FRAME_GROUP_PRODUCT);
2766 error |= cpl_frame_set_level(frame, CPL_FRAME_LEVEL_FINAL);
2767 cpl_error_ensure(! error, cpl_error_get_code(),
goto cleanup,
2768 "Failed to setup a new output frame for '%s'.",
2777 error |= cpl_table_unselect_all(tbl);
2778 cpl_error_ensure(! error, cpl_error_get_code(),
goto cleanup,
2779 "Failed to unselect all entries in fiber setup table from"
2780 " '%s'.", infilename);
2781 cpl_table_or_selected_string(tbl, GIALIAS_COLUMN_TYPE, CPL_NOT_EQUAL_TO,
2783 cpl_table_and_selected_int(tbl, GIALIAS_COLUMN_RP, CPL_NOT_EQUAL_TO, -1);
2784 cpl_table_not_selected(tbl);
2785 error |= cpl_table_erase_selected(tbl);
2786 cpl_error_ensure(! error, cpl_error_get_code(),
goto cleanup,
2787 "Failed to erase selected entries in fiber setup table"
2788 " from '%s'.", infilename);
2792 ny = cpl_image_get_size_y(srcimg);
2794 cpl_table_get_nrow(tbl), ny);
2798 cpl_error_ensure(image != NULL && img != NULL && retcode == 0,
2799 cpl_error_get_code(),
goto cleanup,
2800 "Failed to create image for output file '%s'.",
2805 GIALIAS_ASSO_PROCATG_VALUE);
2806 cpl_error_ensure(! error, cpl_error_get_code(),
goto cleanup,
2807 "Could not update keyword '%s' for output file '%s'.",
2808 GIALIAS_PROCATG, outputfile);
2813 GIALIAS_PRODCATG_MOSSKY);
2814 cpl_error_ensure(! error, cpl_error_get_code(),
goto cleanup,
2815 "Could not update keyword '%s' for output file '%s'.",
2816 GIALIAS_PRODCATG, outputfile);
2821 const char* comments_to_remove[] = {
2822 " FITS (Flexible Image Transport System) format is defined in"
2824 " and Astrophysics', volume 376, page 359; bibcode: 2001A&A..."
2829 comments = cpl_propertylist_new();
2830 error |= cpl_propertylist_copy_property_regexp(comments, props,
2832 cpl_propertylist_erase_regexp(props,
"^COMMENT$", 0);
2833 for (ic = 0; ic < cpl_propertylist_get_size(comments); ++ic) {
2834 const char** cmnt_str;
2835 cpl_property* p = cpl_propertylist_get(comments, ic);
2836 for (cmnt_str = comments_to_remove; *cmnt_str != NULL; ++cmnt_str) {
2837 if (strcmp(cpl_property_get_string(p), *cmnt_str) == 0) {
2838 goto dont_add_comment;
2842 error |= cpl_propertylist_append_property(props, p);
2848 cpl_error_ensure(! error, cpl_error_get_code(),
goto cleanup,
2849 "Failed to cleanup comments in primary HDU for '%s'.",
2851 cpl_propertylist_delete(comments);
2857 indices = cpl_table_get_data_int(tbl, GIALIAS_COLUMN_INDEX);
2858 cpl_error_ensure(indices != NULL, cpl_error_get_code(),
goto cleanup,
2859 "Could not fetch the '%s' column from the fiber setup"
2860 " table in '%s'.", GIALIAS_COLUMN_INDEX, infilename);
2861 for (i = 0; i < cpl_table_get_nrow(tbl); ++i) {
2862 cpl_size oldindex = indices[i];
2863 cpl_size newindex = i+1;
2864 indices[i] = newindex;
2865 subimg = cpl_image_extract(srcimg, oldindex, 1, oldindex, ny);
2866 cpl_error_ensure(subimg != NULL, cpl_error_get_code(),
goto cleanup,
2867 "Could not extract sub image from '%s' at column %"
2868 CPL_SIZE_FORMAT
".", infilename, oldindex);
2869 error |= cpl_image_copy(img, subimg, newindex, 1);
2870 cpl_image_delete(subimg);
2872 cpl_error_ensure(! error, cpl_error_get_code(),
goto cleanup,
2873 "Could write sub image from '%s' at column %"
2874 CPL_SIZE_FORMAT
" to new image in '%s' at column %"
2875 CPL_SIZE_FORMAT
".", infilename, oldindex, outputfile,
2881 cpl_error_ensure(retcode == 0, cpl_error_get_code(),
goto cleanup,
2882 "Failed to write image to file '%s'.", outputfile);
2884 cpl_error_ensure(retcode == 0, cpl_error_get_code(),
goto cleanup,
2885 "Failed to attach the fiber setup table to file '%s'.",
2891 error |= cpl_frameset_insert(allframes, frame);
2892 cpl_error_ensure(! error, cpl_error_get_code(),
goto cleanup,
2893 "Could not add a new frame to the frame list for '%s'.",
2898 return CPL_ERROR_NONE;
2902 cpl_image_delete(subimg);
2905 cpl_frame_delete(frame);
2906 cpl_propertylist_delete(comments);
2907 return cpl_error_get_code();
2917static char* _giraffe_calc_format_string(cpl_size maxfiles)
2919 double ndigits = 1.0;
2923 ndigits = ceil(log10((
double)maxfiles + 1.0));
2925 return cpl_sprintf(
"science_spectrum_%%0%.0f"CPL_SIZE_FORMAT
".fits",
2946static cxint _giraffe_make_sdp_spectra(
const cxchar* flux_filename,
2947 const cxchar* err_filename,
2949 cpl_frameset* allframes,
2950 const cpl_parameterlist* parlist,
2951 const cxchar* recipe_id)
2953 cxint result_code = 1;
2955 cpl_error_code error = CPL_ERROR_NONE;
2956 cpl_errorstate prestate;
2957 const char* ancillary_filename =
"science_ancillary.fits";
2960 GiTable* fibertable = NULL;
2961 const cxchar* fibertable_name = NULL;
2962 irplib_sdp_spectrum* spectrum = NULL;
2963 cpl_propertylist* extrakeys = cpl_propertylist_new();
2964 cpl_propertylist* tablekeys = cpl_propertylist_new();
2965 cpl_propertylist* props;
2966 char* pipe_id = cpl_sprintf(
"%s/%s", PACKAGE, VERSION);
2967 const char* dict_id = PRODUCT_DID;
2968 const cpl_frame* inherit = NULL;
2969 cpl_frameset* usedframes = NULL;
2970 cpl_frameset* rawframes = NULL;
2971 cpl_frameset_iterator* iterator = NULL;
2972 cpl_size nx, ny, i, filecount;
2973 double exptime = NAN;
2974 double mjdobs = NAN;
2975 double mjdend = NAN;
2976 double wavelmin = NAN;
2977 double wavelmax = NAN;
2978 double specbin = NAN;
2979 double crpix2 = NAN;
2980 double crval2 = NAN;
2981 double cdelt2 = NAN;
2982 const char* cunit2 = NULL;
2984 const char* expmode = NULL;
2986 const int* indices = NULL;
2987 const int* fps = NULL;
2988 const char** objects = NULL;
2989 const char** spectypes = NULL;
2990 const double* ras = NULL;
2991 const double* decs = NULL;
2992 const double* gcorr = NULL;
2993 const double* hcorr = NULL;
2994 const double* bcorr = NULL;
2995 char* formatstr = NULL;
2996 char* filename = NULL;
2997 cpl_type wavecoltype;
2998 cpl_array* refwavearray = NULL;
2999 cpl_array* array = NULL;
3000 float* data_float = NULL;
3001 double* data_double = NULL;
3002 cpl_vector* fluximgcol = NULL;
3003 cpl_vector* errimgcol = NULL;
3004 cpl_boolean got_ancillary_data = CPL_FALSE;
3005 cpl_size assoc_key_offset = 1;
3007 double lamrms = NAN;
3008 double specerr = NAN;
3009 double specsye = NAN;
3011 const char *dateobs = NULL;
3013 cpl_error_ensure(flux_filename != NULL && err_filename != NULL
3014 && allframes != NULL && parlist != NULL
3015 && recipe_id != NULL, CPL_ERROR_NULL_INPUT,
goto cleanup,
3016 "NULL input parameters.");
3018 error |= cpl_propertylist_append_string(extrakeys, GIALIAS_PROCATG,
3019 GIALIAS_PROCATG_RBNSPEC_IDP);
3020 error |= cpl_propertylist_set_comment(extrakeys, GIALIAS_PROCATG,
3021 GIALIAS_PROCATG_COMMENT);
3022 cpl_error_ensure(! error, cpl_error_get_code(),
goto cleanup,
3023 "Could not set keyword '%s'.", GIALIAS_PROCATG);
3027 cpl_error_ensure(errorcode == 0, cpl_error_get_code(),
goto cleanup,
3028 "Could not load image data in primary HDU from '%s'.",
3031 cpl_error_ensure(errorcode == 0, cpl_error_get_code(),
goto cleanup,
3032 "Could not load image data in primary HDU from '%s'.",
3035 giraffe_error_push();
3037 if (fibertable == NULL) {
3039 GIALIAS_FIBER_SETUP);
3040 fibertable_name = err_filename;
3042 fibertable_name = flux_filename;
3044 cpl_error_ensure(fibertable != NULL, CPL_ERROR_DATA_NOT_FOUND,
goto cleanup,
3045 "Could not load the %s table from either '%s' or '%s'.",
3046 GIALIAS_FIBER_SETUP, flux_filename, err_filename);
3047 giraffe_error_pop();
3054 CPL_ERROR_INCOMPATIBLE_INPUT,
goto cleanup,
3055 "The images in files '%s' and '%s' are not the same size.",
3056 flux_filename, err_filename);
3060 usedframes = cpl_frameset_new();
3061 rawframes = cpl_frameset_new();
3062 iterator = cpl_frameset_iterator_new(allframes);
3064 const cpl_frame* frame = cpl_frameset_iterator_get_const(iterator);
3065 if (frame != NULL) {
3066 switch (cpl_frame_get_group(frame)) {
3067 case CPL_FRAME_GROUP_RAW:
3069 if (inherit == NULL) inherit = frame;
3070 error |= cpl_frameset_insert(rawframes,
3071 cpl_frame_duplicate(frame));
3072 error |= cpl_frameset_insert(usedframes,
3073 cpl_frame_duplicate(frame));
3075 case CPL_FRAME_GROUP_CALIB:
3076 error |= cpl_frameset_insert(usedframes,
3077 cpl_frame_duplicate(frame));
3083 prestate = cpl_errorstate_get();
3084 error |= cpl_frameset_iterator_advance(iterator, 1);
3085 if (error == CPL_ERROR_ACCESS_OUT_OF_RANGE) {
3086 cpl_errorstate_set(prestate);
3088 }
else if (error != CPL_ERROR_NONE) {
3093 cpl_error_ensure(inherit != NULL, CPL_ERROR_DATA_NOT_FOUND,
goto cleanup,
3094 "No raw input frames found.");
3098 prestate = cpl_errorstate_get();
3099 exptime = cpl_propertylist_get_double(props, GIALIAS_EXPTIME);
3100 cpl_error_ensure(cpl_errorstate_is_equal(prestate), cpl_error_get_code(),
3101 goto cleanup,
"Could not find keyword '%s' in '%s'.",
3102 GIALIAS_EXPTIME, flux_filename);
3103 mjdobs = cpl_propertylist_get_double(props, GIALIAS_MJDOBS);
3104 cpl_error_ensure(cpl_errorstate_is_equal(prestate), cpl_error_get_code(),
3105 goto cleanup,
"Could not find keyword '%s' in '%s'.",
3106 GIALIAS_MJDOBS, flux_filename);
3108 mjdend = mjdobs + exptime / 86400.;
3112 dateobs = cpl_propertylist_get_string(props, GIALIAS_DATEOBS);
3113 cpl_error_ensure(cpl_errorstate_is_equal(prestate), cpl_error_get_code(),
3114 goto cleanup,
"Could not find keyword '%s' in '%s'.",
3115 GIALIAS_DATEOBS, flux_filename);
3117 obsid = cpl_propertylist_get_int(props, GIALIAS_OBSID);
3118 cpl_error_ensure(cpl_errorstate_is_equal(prestate), cpl_error_get_code(),
3119 goto cleanup,
"Could not find keyword '%s' in '%s'.",
3120 GIALIAS_OBSID, flux_filename);
3124 crpix2 = cpl_propertylist_get_double(props, GIALIAS_CRPIX2);
3125 cpl_error_ensure(cpl_errorstate_is_equal(prestate), cpl_error_get_code(),
3126 goto cleanup,
"Could not find keyword '%s' in '%s'.",
3127 GIALIAS_CRPIX2, flux_filename);
3128 crval2 = cpl_propertylist_get_double(props, GIALIAS_CRVAL2);
3129 cpl_error_ensure(cpl_errorstate_is_equal(prestate), cpl_error_get_code(),
3130 goto cleanup,
"Could not find keyword '%s' in '%s'.",
3131 GIALIAS_CRVAL2, flux_filename);
3132 cdelt2 = cpl_propertylist_get_double(props, GIALIAS_CDELT2);
3133 cpl_error_ensure(cpl_errorstate_is_equal(prestate), cpl_error_get_code(),
3134 goto cleanup,
"Could not find keyword '%s' in '%s'.",
3135 GIALIAS_CDELT2, flux_filename);
3136 cunit2 = cpl_propertylist_get_string(props, GIALIAS_CUNIT2);
3137 cpl_error_ensure(cunit2 != NULL, cpl_error_get_code(),
3138 goto cleanup,
"Could not find keyword '%s' in '%s'.",
3139 GIALIAS_CUNIT2, flux_filename);
3141 if (strcmp(cunit2,
"nm") == 0) {
3142 wavelmin = (1.0 - crpix2) * cdelt2 + crval2;
3143 wavelmax = ((double)ny - crpix2) * cdelt2 + crval2;
3144 if (wavelmax < wavelmin) {
3145 double tmp = wavelmin;
3146 wavelmin = wavelmax;
3149 specbin = fabs(cdelt2);
3151 cpl_msg_warning(cpl_func,
"Do not know how to handle keyword %s = '%s'."
3152 " Will not set WAVELMIN, WAVELMAX or SPEC_BIN.",
3153 GIALIAS_CUNIT2, cunit2);
3156 if (cpl_propertylist_has(props, GIALIAS_SETUPNAME)) {
3157 expmode = cpl_propertylist_get_string(props, GIALIAS_SETUPNAME);
3158 cpl_error_ensure(expmode != NULL, cpl_error_get_code(),
goto cleanup,
3159 "Could not fetch the keyword '%s' from '%s'.",
3160 GIALIAS_SETUPNAME, flux_filename);
3161 }
else if (cpl_propertylist_has(props, GIALIAS_GRATNAME)) {
3162 const char* name = cpl_propertylist_get_string(props, GIALIAS_GRATNAME);
3163 cpl_error_ensure(name != NULL, cpl_error_get_code(),
goto cleanup,
3164 "Could not fetch the keyword '%s' from '%s'.",
3165 GIALIAS_GRATNAME, flux_filename);
3166 double wlen = cpl_propertylist_get_double(props, GIALIAS_GRATWLEN);
3167 cpl_error_ensure(cpl_errorstate_is_equal(prestate),
3168 cpl_error_get_code(),
goto cleanup,
3169 "Could not find keyword '%s' in '%s'.",
3170 GIALIAS_GRATWLEN, flux_filename);
3171 strbuf[0] = name[0];
3172 char* numstr = cpl_sprintf(
"%.1f", wlen);
3173 strncpy(strbuf+1, numstr,
sizeof(strbuf)-1);
3175 strbuf[
sizeof(strbuf)-1] =
'\0';
3178 cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
3179 "Neither '%s' nor '%s' and '%s' keywords were found in the"
3180 " file '%s'.", GIALIAS_SETUPNAME, GIALIAS_GRATNAME,
3181 GIALIAS_GRATWLEN, flux_filename);
3185 specres = _giraffe_lookup_specres(expmode);
3186 if (isnan(specres)) {
3187 cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
3188 "The exposure mode '%s' is invalid or an unknown value."
3189 " Could not lookup the spectral resolution for 'SPEC_RES'.",
3196 if (cpl_propertylist_has(props,
"FILTER")) {
3197 prestate = cpl_errorstate_get();
3198 cpl_propertylist_copy_property(extrakeys, props,
"FILTER");
3199 cpl_property* prop = cpl_propertylist_get_property(extrakeys,
"FILTER");
3200 cpl_property_set_name(prop,
"OFILTER");
3201 cpl_error_ensure(cpl_errorstate_is_equal(prestate),
3202 cpl_error_get_code(),
goto cleanup,
3203 "Could not rename the 'FILTER' keyword.");
3207 prestate = cpl_errorstate_get();
3208 got_ancillary_data = _giraffe_ancillary_data_available(flux_filename,
3210 if (! cpl_errorstate_is_equal(prestate))
goto cleanup;
3211 if (got_ancillary_data) {
3212 error = _giraffe_make_ancillary_file(allframes, ancillary_filename,
3213 flux_filename, fluximage,
3215 cpl_error_ensure(! error, cpl_error_get_code(),
goto cleanup,
3216 "Failed to write the ancillary file '%s'.",
3217 ancillary_filename);
3221 spectrum = irplib_sdp_spectrum_new();
3222 error = CPL_ERROR_NONE;
3223 error |= irplib_sdp_spectrum_set_origin(spectrum, GIALIAS_ORIGIN_VALUE);
3224 error |= irplib_sdp_spectrum_set_prodlvl(spectrum, GIALIAS_PRODLVL_VALUE);
3225 error |= irplib_sdp_spectrum_copy_dispelem(spectrum,
3226 props, GIALIAS_GRATNAME);
3227 error |= irplib_sdp_spectrum_set_specsys(spectrum, GIALIAS_SPECSYS_VALUE);
3228 error |= irplib_sdp_spectrum_set_extobj(spectrum, GIALIAS_EXT_OBJ_VALUE);
3231 error |= irplib_sdp_spectrum_set_object(spectrum,
"");
3232 error |= irplib_sdp_spectrum_set_ra(spectrum, 0.0);
3233 error |= irplib_sdp_spectrum_set_dec(spectrum, 0.0);
3234 error |= irplib_sdp_spectrum_copy_exptime(spectrum, props, GIALIAS_EXPTIME);
3235 error |= irplib_sdp_spectrum_copy_texptime(spectrum,
3236 props, GIALIAS_EXPTIME);
3237 error |= irplib_sdp_spectrum_copy_mjdobs(spectrum, props, GIALIAS_MJDOBS);
3238 error |= irplib_sdp_spectrum_set_mjdend(spectrum, mjdend);
3239 if (cpl_propertylist_has(props, GIALIAS_TIMESYS)) {
3240 error |= irplib_sdp_spectrum_copy_timesys(spectrum,
3241 props, GIALIAS_TIMESYS);
3243 error |= irplib_sdp_spectrum_copy_progid(spectrum, props, GIALIAS_PROGID);
3244 error |= irplib_sdp_spectrum_copy_obid(spectrum, 1, props, GIALIAS_OBSID);
3245 error |= irplib_sdp_spectrum_set_mepoch(spectrum, GIALIAS_M_EPOCH_VALUE);
3246 error |= irplib_sdp_spectrum_append_prov(spectrum, 1, rawframes);
3247 error |= irplib_sdp_spectrum_copy_procsoft(spectrum,
3248 props, GIALIAS_PROPIPEID);
3249 error |= irplib_sdp_spectrum_copy_obstech(spectrum, props, GIALIAS_PROTECH);
3250 error |= irplib_sdp_spectrum_set_prodcatg(spectrum, GIALIAS_PRODCATG_VALUE);
3251 error |= irplib_sdp_spectrum_set_fluxcal(spectrum, GIALIAS_FLUXCAL_VALUE);
3252 error |= irplib_sdp_spectrum_set_contnorm(spectrum, GIALIAS_CONTNORM_VALUE);
3256 error |= irplib_sdp_spectrum_set_wavelmin(spectrum, 0.0);
3257 error |= irplib_sdp_spectrum_set_wavelmax(spectrum, 0.0);
3258 error |= irplib_sdp_spectrum_set_specbin(spectrum, 0.0);
3259 error |= irplib_sdp_spectrum_set_totflux(spectrum, GIALIAS_TOTFLUX_VALUE);
3260 error |= irplib_sdp_spectrum_set_fluxerr(spectrum, GIALIAS_FLUXERR_VALUE);
3261 error |= irplib_sdp_spectrum_set_ncombine(spectrum,
3262 cpl_frameset_get_size(rawframes));
3263 error |= irplib_sdp_spectrum_set_referenc(spectrum, GIALIAS_REFERENC);
3266 error |= irplib_sdp_spectrum_set_snr(spectrum, 0.0);
3269 if (cpl_propertylist_has(props, GIALIAS_LAMNLIN)) {
3270 error |= irplib_sdp_spectrum_copy_lamnlin(spectrum, props,
3272 lamnlin = irplib_sdp_spectrum_get_lamnlin(spectrum);
3274 lamnlin = _giraffe_lookup_lamnlin(expmode);
3275 if (lamnlin != -1) {
3276 error |= irplib_sdp_spectrum_set_lamnlin(spectrum, lamnlin);
3283 if (cpl_propertylist_has(props, GIALIAS_LAMRMS)) {
3284 error |= irplib_sdp_spectrum_copy_lamrms(spectrum, props,
3286 lamrms = irplib_sdp_spectrum_get_lamrms(spectrum);
3288 lamrms = _giraffe_lookup_lamrms(expmode);
3289 if (! isnan(lamrms)) {
3290 error |= irplib_sdp_spectrum_set_lamrms(spectrum, lamrms);
3304 if (cpl_propertylist_has(props, GIALIAS_SPEC_ERR)) {
3305 error |= irplib_sdp_spectrum_copy_specerr(spectrum, props,
3307 specerr = irplib_sdp_spectrum_get_specerr(spectrum);
3308 }
else if (lamnlin > 0) {
3309 if (cpl_propertylist_has(props, GIALIAS_CRDER1)) {
3310 prestate = cpl_errorstate_get();
3311 double crder1 = cpl_propertylist_get_double(props, GIALIAS_CRDER1);
3312 if (cpl_errorstate_is_equal(prestate) && crder1 > 0) {
3313 specerr = crder1 / sqrt(lamnlin);
3315 error = cpl_error_get_code();
3317 }
else if (! isnan(lamrms)) {
3318 specerr = lamrms / sqrt(lamnlin);
3320 if (! isnan(specerr)) {
3321 error |= irplib_sdp_spectrum_set_specerr(spectrum, specerr);
3328 if (cpl_propertylist_has(props, GIALIAS_SPEC_SYE)) {
3329 error |= irplib_sdp_spectrum_copy_specsye(spectrum, props,
3331 specsye = irplib_sdp_spectrum_get_specsye(spectrum);
3336 error |= irplib_sdp_spectrum_set_specsye(spectrum, 0.002);
3339 error |= irplib_sdp_spectrum_set_specres(spectrum, specres);
3340 error |= irplib_sdp_spectrum_copy_gain(spectrum, props, GIALIAS_CONAD);
3341 error |= irplib_sdp_spectrum_copy_detron(spectrum, props, GIALIAS_RON);
3342 if (got_ancillary_data) {
3343 error |= irplib_sdp_spectrum_set_asson(spectrum, 1, ancillary_filename);
3344 error |= irplib_sdp_spectrum_set_assoc(spectrum, 1,
3345 GIALIAS_ASSOC_VALUE);
3346 error |= irplib_sdp_spectrum_set_assom(spectrum, 1,
"");
3347 assoc_key_offset = 2;
3349 for (i = assoc_key_offset; i < nassoc_keys + assoc_key_offset; ++i) {
3351 error |= irplib_sdp_spectrum_set_asson(spectrum, i,
"");
3352 error |= irplib_sdp_spectrum_set_assoc(spectrum, i,
"");
3353 error |= irplib_sdp_spectrum_set_assom(spectrum, i,
"");
3356 error |= irplib_sdp_spectrum_set_voclass(spectrum, GIALIAS_VOCLASS_VALUE);
3357 error |= irplib_sdp_spectrum_set_vopub(spectrum, GIALIAS_VOPUB_VALUE);
3358 error |= irplib_sdp_spectrum_set_title(spectrum,
"");
3359 error |= cpl_propertylist_append_double(tablekeys, GIALIAS_APERTURE,
3360 GIALIAS_APERTURE_VALUE);
3361 error |= cpl_propertylist_set_comment(tablekeys, GIALIAS_APERTURE,
3362 GIALIAS_APERTURE_COMMENT);
3371 error |= irplib_sdp_spectrum_set_telapse(spectrum, exptime);
3372 error |= irplib_sdp_spectrum_set_tmid(spectrum, (mjdobs + mjdend) * 0.5);
3376 error |= irplib_sdp_spectrum_set_specval(spectrum, 0.0);
3377 error |= irplib_sdp_spectrum_set_specbw(spectrum, 0.0);
3378 error |= irplib_sdp_spectrum_set_nelem(spectrum, ny);
3379 error |= irplib_sdp_spectrum_set_tdmin(spectrum, 0.0);
3380 error |= irplib_sdp_spectrum_set_tdmax(spectrum, 0.0);
3383 error |= cpl_propertylist_append_int(extrakeys, GIALIAS_FPS, -1);
3384 error |= cpl_propertylist_set_comment(extrakeys, GIALIAS_FPS,
3385 GIALIAS_FPS_COMMENT);
3388 error |= cpl_propertylist_append_double(extrakeys, GIALIAS_GEOCORR, NAN);
3389 error |= cpl_propertylist_set_comment(extrakeys, GIALIAS_GEOCORR,
3390 GIALIAS_GEOCORR_COMMENT);
3391 error |= cpl_propertylist_append_double(extrakeys, GIALIAS_HELICORR, NAN);
3392 error |= cpl_propertylist_set_comment(extrakeys, GIALIAS_HELICORR,
3393 GIALIAS_HELICORR_COMMENT);
3394 error |= cpl_propertylist_append_double(extrakeys, GIALIAS_BARYCORR, NAN);
3395 error |= cpl_propertylist_set_comment(extrakeys, GIALIAS_BARYCORR,
3396 GIALIAS_BARYCORR_COMMENT);
3398 cpl_error_ensure(! error, cpl_error_get_code(),
goto cleanup,
3399 "Could not setup the common SDP spectrum keywords.");
3401 for (
int qci = 0; qci <
sizeof(sciqcpar) /
sizeof(sciqcpar[0]); qci++) {
3402 if (cpl_propertylist_has(props, sciqcpar[qci])) {
3403 cpl_propertylist_copy_property(extrakeys, props, sciqcpar[qci]);
3409 wavecoltype = _giraffe_calc_wave_type(crval2, crpix2, cdelt2, ny);
3412 refwavearray = cpl_array_new(ny, CPL_TYPE_DOUBLE);
3413 data_double = cpl_array_get_data_double(refwavearray);
3414 assert(data_double != NULL);
3415 for (i = 1; i <= ny; ++i) {
3416 data_double[i-1] = (i-crpix2) * cdelt2 + crval2;
3421 error |= irplib_sdp_spectrum_add_column(
3422 spectrum, GIALIAS_COLUMN_WAVE, wavecoltype,
3423 GIALIAS_COLUMN_WAVE_UNIT, NULL, GIALIAS_COLUMN_WAVE_TUTYP,
3424 GIALIAS_COLUMN_WAVE_TUCD, NULL);
3427 error |= irplib_sdp_spectrum_replace_column_comment(
3428 spectrum, GIALIAS_COLUMN_WAVE,
"TUCD",
"Air wavelength");
3430 error |= irplib_sdp_spectrum_set_column_tcomm(
3431 spectrum, GIALIAS_COLUMN_WAVE, GIALIAS_COLUMN_WAVE_TCOMM);
3432 error |= irplib_sdp_spectrum_add_column(
3433 spectrum, GIALIAS_COLUMN_FLUX_REDUCED, CPL_TYPE_DOUBLE,
3434 GIALIAS_COLUMN_FLUX_REDUCED_UNIT, NULL,
3435 GIALIAS_COLUMN_FLUX_REDUCED_TUTYP,
3436 GIALIAS_COLUMN_FLUX_REDUCED_TUCD, NULL);
3437 error |= irplib_sdp_spectrum_set_column_tcomm(
3438 spectrum, GIALIAS_COLUMN_FLUX_REDUCED,
"");
3439 error |= irplib_sdp_spectrum_add_column(
3440 spectrum, GIALIAS_COLUMN_ERR_REDUCED, CPL_TYPE_DOUBLE,
3441 GIALIAS_COLUMN_ERR_REDUCED_UNIT, NULL,
3442 GIALIAS_COLUMN_ERR_REDUCED_TUTYP,
3443 GIALIAS_COLUMN_ERR_REDUCED_TUCD, NULL);
3444 error |= irplib_sdp_spectrum_set_column_tcomm(
3445 spectrum, GIALIAS_COLUMN_ERR_REDUCED,
"");
3446 error |= irplib_sdp_spectrum_add_column(
3447 spectrum, GIALIAS_COLUMN_SNR, CPL_TYPE_DOUBLE,
3448 GIALIAS_COLUMN_SNR_UNIT, NULL, GIALIAS_COLUMN_SNR_TUTYP,
3449 GIALIAS_COLUMN_SNR_TUCD, NULL);
3450 error |= irplib_sdp_spectrum_set_column_tcomm(
3451 spectrum, GIALIAS_COLUMN_SNR, GIALIAS_COLUMN_SNR_TCOMM);
3452 cpl_error_ensure(! error, cpl_error_get_code(),
goto cleanup,
3453 "Could not setup the SDP spectrum columns.");
3456 GIALIAS_COLUMN_INDEX);
3460 GIALIAS_COLUMN_OBJECT);
3462 GIALIAS_COLUMN_TYPE);
3466 GIALIAS_COLUMN_DEC);
3468 GIALIAS_COLUMN_GCORR);
3470 GIALIAS_COLUMN_HCORR);
3472 GIALIAS_COLUMN_BCORR);
3473 cpl_error_ensure(indices != NULL && fps != NULL && objects != NULL
3474 && spectypes != NULL && ras != NULL && decs != NULL
3475 && gcorr != NULL && hcorr != NULL && bcorr != NULL,
3476 cpl_error_get_code(),
goto cleanup,
3477 "Could not fetch data from the fiber setup table in '%s'.",
3480 formatstr = _giraffe_calc_format_string(
3483 cpl_errorstate tempes = cpl_errorstate_get();
3488 cpl_image_get_maxpos(maxim, &maxx, &maxy);
3490 cpl_image_delete(maxim);
3492 cpl_errorstate_set(tempes);
3497 const double* wave_data;
3503 const char* remregexp =
"^(CDELT[0-9]+|CD[0-9]+_[0-9]+|CRPIX[0-9]+"
3504 "|CRDER[0-9]+|CSYER[0-9]+|BUNIT|BSCALE|BZERO"
3506 cpl_size specindex = indices[i];
3507 double vela, velb, beta;
3508 double correction_factor = 1.0;
3511 if (strcmp(spectypes[i],
"M") != 0)
continue;
3513 filename = cpl_sprintf(formatstr, ++filecount);
3518 vela = gcorr[i] * 1e3;
3519 velb = hcorr[i] * 1e3;
3520 beta = (vela + velb) / CPL_PHYS_C;
3521 cpl_error_ensure(-1 <= beta && beta <= 1,
3522 CPL_ERROR_ILLEGAL_OUTPUT,
goto cleanup,
3523 "The velocities GCORR = %g and HCORR = %g for spectrum"
3524 "%"CPL_SIZE_FORMAT
" in file '%s' give invalid"
3525 " Heliocentric correction factor values.",
3526 gcorr[i], hcorr[i], specindex, flux_filename);
3527 correction_factor = sqrt((1.0 + beta) / (1.0 - beta));
3531 wave_data = cpl_array_get_data_double_const(refwavearray);
3532 if (wavecoltype == CPL_TYPE_FLOAT) {
3533 data_float = cpl_malloc(ny *
sizeof(
float));
3534 for (j = 0; j < ny; ++j) {
3535 data_float[j] = wave_data[j] * correction_factor;
3537 array = cpl_array_wrap_float(data_float, ny);
3539 data_double = cpl_malloc(ny *
sizeof(
double));
3540 for (j = 0; j < ny; ++j) {
3541 data_double[j] = wave_data[j] * correction_factor;
3543 array = cpl_array_wrap_double(data_double, ny);
3545 error |= irplib_sdp_spectrum_set_column_data(
3546 spectrum, GIALIAS_COLUMN_WAVE, array);
3547 cpl_array_unwrap(array);
3550 fluximgcol = cpl_vector_new_from_image_column(
3552 flux_data = cpl_vector_get_data(fluximgcol);
3553 cpl_error_ensure(flux_data != NULL, cpl_error_get_code(),
goto cleanup,
3554 "Unable to extract data in column %"CPL_SIZE_FORMAT
3555 " from image in file '%s'.", specindex, flux_filename);
3556 array = cpl_array_wrap_double(flux_data, ny);
3559 cpl_propertylist_update_char(extrakeys, GIALIAS_QCBRIGHTFLG,
'Y');
3562 cpl_propertylist_update_char(extrakeys, GIALIAS_QCBRIGHTFLG,
'N');
3565 double fluxmean = cpl_array_get_mean(array);
3566 cpl_propertylist_update_double(extrakeys, GIALIAS_QCMEANRED, fluxmean);
3567 error |= irplib_sdp_spectrum_set_column_data(
3568 spectrum, GIALIAS_COLUMN_FLUX_REDUCED, array);
3569 cpl_array_unwrap(array);
3572 errimgcol = cpl_vector_new_from_image_column(
3574 err_data = cpl_vector_get_data(errimgcol);
3575 cpl_error_ensure(err_data != NULL, cpl_error_get_code(),
goto cleanup,
3576 "Unable to extract data in column %"CPL_SIZE_FORMAT
3577 " from image in file '%s'.", specindex, err_filename);
3578 array = cpl_array_wrap_double(err_data, ny);
3579 error |= irplib_sdp_spectrum_set_column_data(
3580 spectrum, GIALIAS_COLUMN_ERR_REDUCED, array);
3581 cpl_array_unwrap(array);
3584 data_double = cpl_malloc(ny *
sizeof(
double));
3585 for (j = 0; j < ny; ++j) {
3586 data_double[j] = (err_data[j] != 0.0) ? flux_data[j] / err_data[j]
3589 array = cpl_array_wrap_double(data_double, ny);
3590 snr = cpl_array_get_median(array);
3591 double snrmean = cpl_array_get_mean(array);
3592 cpl_propertylist_update_double(extrakeys, GIALIAS_QCSNR, snrmean);
3593 error |= irplib_sdp_spectrum_set_column_data(spectrum,
3594 GIALIAS_COLUMN_SNR, array);
3595 cpl_array_unwrap(array);
3597 cpl_free(data_double);
3600 cpl_vector_delete(fluximgcol);
3602 cpl_vector_delete(errimgcol);
3607 estmag = cpl_table_get_double(
giraffe_table_get(fibertable),
"MAGNITUDE", i, NULL);
3609 cpl_propertylist_update_double(extrakeys, GIALIAS_QCMAG, estmag);
3611 cpl_error_ensure(! error, cpl_error_get_code(),
goto cleanup,
3612 "Could not setup the SDP spectrum columns for '%s'.",
3615 error |= irplib_sdp_spectrum_set_object(spectrum, objects[i]);
3619 tmp_string = cpl_sprintf(
"%s_%d_%s",
3625 replace_spaces_with_underscores(tmp_string);
3627 error |= irplib_sdp_spectrum_set_title(spectrum, tmp_string);
3629 cpl_free(tmp_string);
3631 error |= irplib_sdp_spectrum_set_ra(spectrum, ras[i]);
3632 error |= irplib_sdp_spectrum_set_dec(spectrum, decs[i]);
3633 error |= irplib_sdp_spectrum_set_snr(spectrum, snr);
3634 error |= irplib_sdp_spectrum_set_column_tcomm(
3635 spectrum, GIALIAS_COLUMN_FLUX_REDUCED, flux_filename);
3636 error |= irplib_sdp_spectrum_set_column_tcomm(
3637 spectrum, GIALIAS_COLUMN_ERR_REDUCED, err_filename);
3639 error |= cpl_propertylist_update_int(extrakeys, GIALIAS_FPS, fps[i]);
3640 error |= cpl_propertylist_update_double(extrakeys, GIALIAS_GEOCORR,
3642 error |= cpl_propertylist_update_double(extrakeys, GIALIAS_HELICORR,
3644 error |= cpl_propertylist_update_double(extrakeys, GIALIAS_BARYCORR,
3648 error |= irplib_sdp_spectrum_set_wavelmin(spectrum,
3649 wavelmin * correction_factor);
3650 error |= irplib_sdp_spectrum_set_wavelmax(spectrum,
3651 wavelmax * correction_factor);
3652 error |= irplib_sdp_spectrum_set_specval(spectrum,
3653 (wavelmax + wavelmin) * 0.5 * correction_factor);
3654 error |= irplib_sdp_spectrum_set_specbw(spectrum,
3655 (wavelmax - wavelmin) * correction_factor);
3656 error |= irplib_sdp_spectrum_set_tdmin(spectrum,
3657 wavelmin * correction_factor);
3658 error |= irplib_sdp_spectrum_set_tdmax(spectrum,
3659 wavelmax * correction_factor);
3660 error |= irplib_sdp_spectrum_set_specbin(spectrum,
3661 specbin * correction_factor);
3662 if (! isnan(lamrms)) {
3663 error |= irplib_sdp_spectrum_set_lamrms(spectrum,
3664 lamrms * correction_factor);
3666 if (! isnan(specerr)) {
3667 error |= irplib_sdp_spectrum_set_specerr(spectrum,
3668 specerr * correction_factor);
3670 if (! isnan(specsye)) {
3671 error |= irplib_sdp_spectrum_set_specsye(spectrum,
3672 specsye * correction_factor);
3675 cpl_error_ensure(! error, cpl_error_get_code(),
goto cleanup,
3676 "Could not setup the SDP spectrum keywords for '%s'.",
3679 error |= irplib_dfs_save_spectrum(allframes, NULL, parlist, usedframes,
3680 inherit, spectrum, recipe_id,
3681 extrakeys, tablekeys, remregexp,
3682 pipe_id, dict_id, filename);
3683 cpl_error_ensure(! error, cpl_error_get_code(),
goto cleanup,
3684 "Failed to save SDP spectrum %"CPL_SIZE_FORMAT
3685 " to file '%s'.", specindex, filename);
3687 error |= irplib_fits_update_checksums(filename);
3688 cpl_error_ensure(! error, cpl_error_get_code(),
goto cleanup,
3689 "Failed to save update checksums for file '%s'.",
3695 if (filecount == 0) {
3696 cpl_msg_warning(cpl_func,
"No science spectra found in '%s'."
3697 " No SDP spectra created.", flux_filename);
3705 cpl_vector_delete(fluximgcol);
3706 cpl_vector_delete(errimgcol);
3707 cpl_array_unwrap(array);
3708 cpl_array_delete(refwavearray);
3709 cpl_free(data_float);
3710 cpl_free(data_double);
3712 cpl_free(formatstr);
3713 cpl_frameset_delete(usedframes);
3714 cpl_frameset_delete(rawframes);
3715 cpl_frameset_iterator_delete(iterator);
3717 cpl_propertylist_delete(tablekeys);
3718 cpl_propertylist_delete(extrakeys);
3722 irplib_sdp_spectrum_delete(spectrum);
cxint giraffe_add_rvcorrection(GiTable *fibers, const GiImage *spectra)
Add the barycentric and heliocentric corrections to the given fiber setup.
GiBiasConfig * giraffe_bias_config_create(cpl_parameterlist *list)
Creates a setup structure for a bias removal task.
void giraffe_bias_config_add(cpl_parameterlist *list)
Adds parameters for the bias removal.
cxint giraffe_bias_remove(GiImage *result, const GiImage *raw, const GiImage *master_bias, const GiImage *bad_pixels, const cpl_matrix *biaslimits, const GiBiasConfig *config)
Removes the bias from an image.
void giraffe_bias_config_destroy(GiBiasConfig *config)
Destroys a bias removal setup structure.
cxint giraffe_subtract_dark(GiImage *image, const GiImage *dark, const GiImage *bpixel, GiDarkResults *data, const GiDarkConfig *config)
Subtract the dark current from a bias corrected image.
GiTable * giraffe_fibers_setup(const cpl_frame *frame, const cpl_frame *reference)
Setup a fiber list.
GiTable * giraffe_fiberlist_load(const cxchar *filename, cxint dataset, const cxchar *tag)
Load a fiber table from a file.
cxint giraffe_fiberlist_compare(const GiTable *fibers, const GiTable *reference)
Compare two fiber lists.
cxint giraffe_fiberlist_attach(cpl_frame *frame, GiTable *fibers)
Attach a fiber table to a frame.
GiFlatConfig * giraffe_flat_config_create(cpl_parameterlist *list)
Creates a setup structure for the flat field correction.
void giraffe_flat_config_destroy(GiFlatConfig *config)
Destroys a flat field setup structure.
void giraffe_flat_config_add(cpl_parameterlist *list)
Adds parameters for the flat field correction.
cxint giraffe_flat_apply(GiExtraction *extraction, const GiTable *fibers, const GiImage *flat, const GiImage *errors, GiFlatConfig *config)
Apply the flat field correction to the given extracted spectra.
GiFieldOfViewConfig * giraffe_fov_config_create(cpl_parameterlist *list)
Creates a setup structure for the field of view reconstruction.
void giraffe_fov_config_destroy(GiFieldOfViewConfig *config)
Destroys a field of view setup structure.
GiFieldOfView * giraffe_fov_new(void)
Create an empty container for the results of the field of view reconstruction.
cxint giraffe_fov_save_cubes_eso3d(const GiFieldOfView *self, cpl_propertylist *properties, const cxchar *filename, cxptr data)
Write the cube components of a field-of-view object to a file.
void giraffe_fov_delete(GiFieldOfView *self)
Deallocate a field of view object and its contents.
cxint giraffe_fov_build(GiFieldOfView *result, GiRebinning *rebinning, GiTable *fibers, GiTable *wsolution, GiTable *grating, GiTable *slitgeometry, GiFieldOfViewConfig *config)
Create and image and a data cube from extracted and rebinned spectra.
cxint giraffe_fov_save_cubes(const GiFieldOfView *self, cpl_propertylist *properties, const cxchar *filename, cxptr data)
Write the cube components of a field-of-view object to a file.
void giraffe_fov_config_add(cpl_parameterlist *list)
Adds parameters for the image and data cube construction.
cpl_frame * giraffe_frame_create(const cxchar *tag, cpl_frame_level level, const cpl_propertylist *properties, cxcptr object, cxcptr data, GiFrameCreator creator)
Create a product frame using a provided frame creator.
cpl_frame * giraffe_frame_create_image(GiImage *image, const cxchar *tag, cpl_frame_level level, cxbool save, cxbool update)
Create an image product frame.
cpl_frame * giraffe_get_slitgeometry(const cpl_frameset *set)
Get the slit geometry frame from a frame set.
cpl_image * giraffe_image_get(const GiImage *self)
Gets the image data.
cpl_propertylist * giraffe_image_get_properties(const GiImage *self)
Get the properties of an image.
void giraffe_image_delete(GiImage *self)
Destroys an image.
GiImage * giraffe_image_create(cpl_type type, cxint nx, cxint ny)
Creates an image container of a given type.
cxint giraffe_image_add_info(GiImage *image, const GiRecipeInfo *info, const cpl_frameset *set)
Add additional frame information to an image.
cxint giraffe_image_save(GiImage *self, const cxchar *filename)
Write a Giraffe image to a file.
GiImage * giraffe_image_new(cpl_type type)
Creates an empty image container.
cxint giraffe_image_set_properties(GiImage *self, cpl_propertylist *properties)
Attaches a property list to an image.
cxint giraffe_image_load(GiImage *self, const cxchar *filename, cxint position)
Gets image data and properties from a file.
void giraffe_rebin_config_destroy(GiRebinConfig *config)
Destroys a spectrum extraction setup structure.
cxint giraffe_rebin_spectra(GiRebinning *rebinning, const GiExtraction *extraction, const GiTable *fibers, const GiLocalization *localization, const GiTable *grating, const GiTable *slitgeo, const GiTable *solution, const GiRebinConfig *config)
Rebin an Extracted Spectra Frame and associated Errors Frame.
GiRebinConfig * giraffe_rebin_config_create(cpl_parameterlist *list)
Creates a setup structure for the rebinning.
GiRebinning * giraffe_rebinning_new(void)
Create an empty rebinning results container.
void giraffe_rebinning_destroy(GiRebinning *rebinning)
Destroys a rebinning results container and its contents.
void giraffe_rebin_config_add(cpl_parameterlist *list)
Adds parameters for the rebinning.
GiSGCalConfig * giraffe_sgcalibration_config_create(cpl_parameterlist *list)
Creates a setup structure for the slit geometry calibration.
cxint giraffe_compute_offsets(GiTable *fibers, const GiRebinning *rebinning, const GiTable *grating, const GiTable *mask, const GiSGCalConfig *config)
Compute wavelength offsets for a set of rebinned input spectrum.
void giraffe_sgcalibration_config_destroy(GiSGCalConfig *config)
Destroys a sgcalibration field setup structure.
void giraffe_sgcalibration_config_add(cpl_parameterlist *list)
Adds parameters for the sgcalibration correction computation.
GiTable * giraffe_slitgeometry_load(const GiTable *fibers, const cxchar *filename, cxint pos, const cxchar *tag)
Load the slit geometry information for a given fiber setup.
GiTable * giraffe_table_new(void)
Creates a new, empty Giraffe table.
GiTable * giraffe_table_duplicate(const GiTable *src)
Duplicate a Giraffe table.
cxint giraffe_table_load(GiTable *self, const cxchar *filename, cxint position, const cxchar *id)
Reads a data set from a file into a Giraffe table.
void giraffe_table_delete(GiTable *self)
Destroys a Giraffe table.
cpl_table * giraffe_table_get(const GiTable *self)
Get the table data from a Giraffe table.
cxint giraffe_add_frameset_info(cpl_propertylist *plist, const cpl_frameset *set, cxint sequence)
Add frameset specific information to a property list.
cxint giraffe_propertylist_copy(cpl_propertylist *self, const cxchar *name, const cpl_propertylist *other, const cxchar *othername)
Copy a property from one list to another.
const cxchar * giraffe_get_license(void)
Get the pipeline copyright and license.
GiInstrumentMode giraffe_get_mode(cpl_propertylist *properties)
Determines the instrument mode from a property list.
Slit geometry calibration configuration data structure.