35 #include <cxmessages.h>
37 #include <cpl_recipe.h>
38 #include <cpl_plugininfo.h>
39 #include <cpl_parameterlist.h>
40 #include <cpl_frameset.h>
42 #include <cpl_errorstate.h>
44 #include <irplib_sdp_spectrum.h>
49 #include "gifiberutils.h"
50 #include "gislitgeometry.h"
51 #include "gipsfdata.h"
54 #include "giextract.h"
56 #include "gitransmission.h"
57 #include "girebinning.h"
58 #include "gisgcalibration.h"
59 #include "giastrometry.h"
61 #include "gimessages.h"
66 static cxint giscience(cpl_parameterlist*, cpl_frameset*);
68 static cxint _giraffe_make_sdp_spectra(
const cxchar* flux_filename,
69 const cxchar* err_filename,
71 cpl_frameset* allframes,
72 const cpl_parameterlist* parlist,
73 const cxchar* recipe_id);
82 giscience_create(cpl_plugin* plugin)
85 cpl_recipe* recipe = (cpl_recipe*)plugin;
87 cpl_parameter* p = NULL;
99 recipe->parameters = cpl_parameterlist_new();
100 cx_assert(recipe->parameters != NULL);
129 p = cpl_parameter_new_value(
"giraffe.siwc.apply",
131 "Enable simultaneous wavelength calibration "
136 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"siwc-apply");
137 cpl_parameterlist_append(recipe->parameters, p);
147 p = cpl_parameter_new_value(
"giraffe.sdp.format.generate",
149 "TRUE if additional files should be generated"
150 " in Science Data Product (SDP) format.",
154 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"generate-SDP-format");
155 cpl_parameterlist_append(recipe->parameters, p);
157 p = cpl_parameter_new_value(
"giraffe.sdp.nassoc.keys",
159 "Sets the number of dummy (empty) ASSONi,"
160 " ASSOCi and ASSOMi keywords to create.",
164 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
165 "dummy-association-keys");
166 cpl_parameterlist_append(recipe->parameters, p);
178 giscience_exec(cpl_plugin* plugin)
181 cpl_errorstate prev_state;
183 cpl_recipe* recipe = (cpl_recipe*)plugin;
186 cx_assert(recipe->parameters != NULL);
187 cx_assert(recipe->frames != NULL);
189 prev_state = cpl_errorstate_get();
190 result = giscience(recipe->parameters, recipe->frames);
192 cpl_errorstate_dump(prev_state, CPL_FALSE, cpl_errorstate_dump_one);
199 giscience_destroy(cpl_plugin* plugin)
202 cpl_recipe* recipe = (cpl_recipe*)plugin;
211 cpl_parameterlist_delete(recipe->parameters);
213 giraffe_error_clear();
225 giscience(cpl_parameterlist* config, cpl_frameset* set)
228 const cxchar*
const _id =
"giscience";
231 const cxchar* filename = NULL;
234 cxbool calsim = FALSE;
236 cxbool gensdp = FALSE;
237 cxint nassoc_keys = 0;
238 cxchar* flux_filename = NULL;
239 cxchar* err_filename = NULL;
246 cxdouble exptime = 0.;
248 cx_slist* slist = NULL;
250 cpl_propertylist* properties = NULL;
252 cpl_matrix* biasareas = NULL;
254 cpl_frame* science_frame = NULL;
255 cpl_frame* mbias_frame = NULL;
256 cpl_frame* mdark_frame = NULL;
257 cpl_frame* bpixel_frame = NULL;
258 cpl_frame* slight_frame = NULL;
259 cpl_frame* locy_frame = NULL;
260 cpl_frame* locw_frame = NULL;
261 cpl_frame* psfdata_frame = NULL;
262 cpl_frame* grating_frame = NULL;
263 cpl_frame* linemask_frame = NULL;
264 cpl_frame* slit_frame = NULL;
265 cpl_frame* wcal_frame = NULL;
266 cpl_frame* rscience_frame = NULL;
267 cpl_frame* sext_frame = NULL;
268 cpl_frame* rbin_frame = NULL;
270 cpl_parameter* p = NULL;
272 GiImage* mbias = NULL;
273 GiImage* mdark = NULL;
274 GiImage* bpixel = NULL;
275 GiImage* slight = NULL;
276 GiImage* sscience = NULL;
277 GiImage* rscience = NULL;
279 GiTable* fibers = NULL;
280 GiTable* slitgeometry = NULL;
281 GiTable* grating = NULL;
282 GiTable* wcalcoeff = NULL;
284 GiLocalization* localization = NULL;
285 GiExtraction* extraction = NULL;
286 GiRebinning* rebinning = NULL;
288 GiBiasConfig* bias_config = NULL;
289 GiExtractConfig* extract_config = NULL;
290 GiFlatConfig* flat_config = NULL;
291 GiRebinConfig* rebin_config = NULL;
293 GiInstrumentMode mode;
295 GiRecipeInfo info = {(cxchar*)_id, 1, NULL};
297 GiGroupInfo groups[] = {
298 {GIFRAME_SCIENCE, CPL_FRAME_GROUP_RAW},
299 {GIFRAME_BADPIXEL_MAP, CPL_FRAME_GROUP_CALIB},
300 {GIFRAME_BIAS_MASTER, CPL_FRAME_GROUP_CALIB},
301 {GIFRAME_DARK_MASTER, CPL_FRAME_GROUP_CALIB},
302 {GIFRAME_FIBER_FLAT_EXTSPECTRA, CPL_FRAME_GROUP_CALIB},
303 {GIFRAME_FIBER_FLAT_EXTERRORS, CPL_FRAME_GROUP_CALIB},
304 {GIFRAME_SCATTERED_LIGHT_MODEL, CPL_FRAME_GROUP_CALIB},
305 {GIFRAME_LOCALIZATION_CENTROID, CPL_FRAME_GROUP_CALIB},
306 {GIFRAME_LOCALIZATION_WIDTH, CPL_FRAME_GROUP_CALIB},
307 {GIFRAME_PSF_CENTROID, CPL_FRAME_GROUP_CALIB},
308 {GIFRAME_PSF_WIDTH, CPL_FRAME_GROUP_CALIB},
309 {GIFRAME_PSF_DATA, CPL_FRAME_GROUP_CALIB},
310 {GIFRAME_WAVELENGTH_SOLUTION, CPL_FRAME_GROUP_CALIB},
311 {GIFRAME_LINE_MASK, CPL_FRAME_GROUP_CALIB},
312 {GIFRAME_SLITSETUP, CPL_FRAME_GROUP_CALIB},
313 {GIFRAME_SLITMASTER, CPL_FRAME_GROUP_CALIB},
314 {GIFRAME_GRATING, CPL_FRAME_GROUP_CALIB},
315 {NULL, CPL_FRAME_GROUP_NONE}
321 cpl_msg_error(_id,
"Invalid parameter list! Aborting ...");
326 cpl_msg_error(_id,
"Invalid frame set! Aborting ...");
330 status = giraffe_frameset_set_groups(set, groups);
333 cpl_msg_error(_id,
"Setting frame group information failed!");
342 nscience = cpl_frameset_count_tags(set, GIFRAME_SCIENCE);
345 cpl_msg_error(_id,
"Too few (%ld) raw frames (%s) present in "
346 "frame set! Aborting ...", nscience, GIFRAME_SCIENCE);
350 locy_frame = cpl_frameset_find(set, GIFRAME_PSF_CENTROID);
352 if (locy_frame == NULL) {
354 locy_frame = cpl_frameset_find(set, GIFRAME_LOCALIZATION_CENTROID);
356 if (locy_frame == NULL) {
357 cpl_msg_info(_id,
"No master localization (centroid position) "
358 "present in frame set. Aborting ...");
364 locw_frame = cpl_frameset_find(set, GIFRAME_PSF_WIDTH);
366 if (locw_frame == NULL) {
368 locw_frame = cpl_frameset_find(set, GIFRAME_LOCALIZATION_WIDTH);
370 if (locw_frame == NULL) {
371 cpl_msg_info(_id,
"No master localization (spectrum width) "
372 "present in frame set. Aborting ...");
378 grating_frame = cpl_frameset_find(set, GIFRAME_GRATING);
380 if (!grating_frame) {
381 cpl_msg_error(_id,
"No grating data present in frame set. "
389 cpl_msg_error(_id,
"No slit geometry present in frame set. "
394 wcal_frame = cpl_frameset_find(set, GIFRAME_WAVELENGTH_SOLUTION);
397 cpl_msg_error(_id,
"No dispersion solution present in frame set. "
402 linemask_frame = cpl_frameset_find(set, GIFRAME_LINE_MASK);
404 if (!linemask_frame) {
405 cpl_msg_warning(_id,
"No reference line mask present in frame set.");
408 bpixel_frame = cpl_frameset_find(set, GIFRAME_BADPIXEL_MAP);
411 cpl_msg_info(_id,
"No bad pixel map present in frame set.");
414 mbias_frame = cpl_frameset_find(set, GIFRAME_BIAS_MASTER);
417 cpl_msg_info(_id,
"No master bias present in frame set.");
420 mdark_frame = cpl_frameset_find(set, GIFRAME_DARK_MASTER);
423 cpl_msg_info(_id,
"No master dark present in frame set.");
426 slight_frame = cpl_frameset_find(set, GIFRAME_SCATTERED_LIGHT_MODEL);
429 cpl_msg_info(_id,
"No scattered light model present in frame set.");
432 psfdata_frame = cpl_frameset_find(set, GIFRAME_PSF_DATA);
434 if (!psfdata_frame) {
435 cpl_msg_info(_id,
"No PSF profile parameters present in frame set.");
443 slist = cx_slist_new();
445 science_frame = cpl_frameset_find(set, GIFRAME_SCIENCE);
447 for (i = 0; i < nscience; i++) {
449 filename = cpl_frame_get_filename(science_frame);
457 cpl_msg_error(_id,
"Cannot load raw science frame from '%s'. "
458 "Aborting ...", filename);
465 cx_slist_push_back(slist, raw);
467 science_frame = cpl_frameset_find(set, NULL);
471 nscience = (cxint)cx_slist_size(slist);
472 sscience = cx_slist_pop_front(slist);
475 cx_assert(properties != NULL);
484 cpl_msg_info(_id,
"Averaging science frames ...");
486 exptime = cpl_propertylist_get_double(properties, GIALIAS_EXPTIME);
488 for (i = 1; i < nscience; i++) {
490 cpl_propertylist* _properties;
492 GiImage* science = cx_slist_pop_front(slist);
499 cx_assert(_properties != NULL);
501 exptime += cpl_propertylist_get_double(_properties, GIALIAS_EXPTIME);
510 cx_assert(cx_slist_empty(slist));
511 cx_slist_delete(slist);
521 cpl_msg_info(_id,
"Updating stacked science image properties ...");
523 cpl_propertylist_set_double(properties, GIALIAS_EXPTIME,
526 cpl_propertylist_append_double(properties, GIALIAS_EXPTTOT, exptime);
527 cpl_propertylist_set_comment(properties, GIALIAS_EXPTTOT,
528 "Total exposure time of all frames "
531 cpl_propertylist_append_int(properties, GIALIAS_DATANCOM, nscience);
532 cpl_propertylist_set_comment(properties, GIALIAS_DATANCOM,
533 "Number of frames combined");
535 cpl_propertylist_erase(properties, GIALIAS_TPLEXPNO);
550 if (bias_config->method == GIBIAS_METHOD_MASTER ||
551 bias_config->method == GIBIAS_METHOD_ZMASTER) {
554 cpl_msg_error(_id,
"Missing master bias frame! Selected bias "
555 "removal method requires a master bias frame!");
563 filename = cpl_frame_get_filename(mbias_frame);
570 cpl_msg_error(_id,
"Cannot load master bias from '%s'. "
571 "Aborting ...", filename);
588 filename = cpl_frame_get_filename(bpixel_frame);
595 cpl_msg_error(_id,
"Cannot load bad pixel map from '%s'. "
596 "Aborting ...", filename);
637 cpl_msg_error(_id,
"Bias removal failed. Aborting ...");
642 if (bpixel != NULL) {
658 GiDarkConfig dark_config = {GIDARK_METHOD_ZMASTER, 0.};
661 cpl_msg_info(_id,
"Correcting for dark current ...");
663 filename = cpl_frame_get_filename(mdark_frame);
669 cpl_msg_error(_id,
"Cannot load master dark from '%s'. "
670 "Aborting ...", filename);
675 if (bpixel != NULL) {
687 cpl_msg_error(_id,
"Dark subtraction failed! Aborting ...");
695 if (bpixel != NULL) {
714 cpl_msg_info(_id,
"Writing pre-processed science image ...");
719 GIFRAME_SCIENCE_REDUCED,
720 CPL_FRAME_LEVEL_INTERMEDIATE,
723 if (rscience_frame == NULL) {
724 cpl_msg_error(_id,
"Cannot create local file! Aborting ...");
731 cpl_frameset_insert(set, rscience_frame);
738 science_frame = cpl_frameset_find(set, GIFRAME_SCIENCE);
740 cpl_msg_info(_id,
"Building fiber setup for frame '%s'.",
741 cpl_frame_get_filename(science_frame));
746 cpl_msg_error(_id,
"Cannot create fiber setup for frame '%s'! "
747 "Aborting ...", cpl_frame_get_filename(science_frame));
760 cpl_msg_info(_id,
"Fiber reference setup taken from localization "
761 "frame '%s'.", cpl_frame_get_filename(locy_frame));
768 localization = giraffe_localization_new();
770 filename = cpl_frame_get_filename(locy_frame);
777 cpl_msg_error(_id,
"Cannot load localization (centroid "
778 "position) frame from '%s'. Aborting ...",
781 giraffe_localization_destroy(localization);
795 filename = cpl_frame_get_filename(locw_frame);
802 cpl_msg_error(_id,
"Cannot load localization (spectrum width) "
803 "frame from '%s'. Aborting ...", filename);
805 giraffe_localization_destroy(localization);
825 filename = cpl_frame_get_filename(slight_frame);
832 cpl_msg_error(_id,
"Cannot load scattered light model from '%s'. "
833 "Aborting ...", filename);
837 giraffe_localization_destroy(localization);
856 if ((extract_config->emethod == GIEXTRACT_OPTIMAL) ||
857 (extract_config->emethod == GIEXTRACT_HORNE)) {
859 if (psfdata_frame == NULL) {
861 const cxchar* emethod =
"Optimal";
863 if (extract_config->emethod == GIEXTRACT_HORNE) {
867 cpl_msg_error(_id,
"%s spectrum extraction requires PSF "
868 "profile data. Aborting ...", emethod);
871 extract_config = NULL;
873 if (slight != NULL) {
878 giraffe_localization_destroy(localization);
897 filename = cpl_frame_get_filename(psfdata_frame);
900 localization->psf = giraffe_psfdata_new();
901 status = giraffe_psfdata_load(localization->psf, filename);
904 cpl_msg_error(_id,
"Cannot load PSF profile data frame from "
905 "'%s'. Aborting ...", filename);
908 extract_config = NULL;
910 if (slight != NULL) {
915 giraffe_localization_destroy(localization);
938 extraction = giraffe_extraction_new();
941 localization, bpixel, slight,
945 cpl_msg_error(_id,
"Spectrum extraction failed! Aborting ...");
947 giraffe_extraction_destroy(extraction);
952 giraffe_localization_destroy(localization);
985 if (flat_config->load == TRUE) {
987 cpl_frame* flat_frame = NULL;
989 GiImage* flat = NULL;
992 flat_frame = cpl_frameset_find(set, GIFRAME_FIBER_FLAT_EXTSPECTRA);
994 if (flat_frame == NULL) {
995 cpl_msg_error(_id,
"Missing flat field spectra frame!");
999 giraffe_extraction_destroy(extraction);
1000 giraffe_localization_destroy(localization);
1010 filename = cpl_frame_get_filename(flat_frame);
1016 cpl_msg_error(_id,
"Cannot load flat field spectra from '%s'. "
1017 "Aborting ...", filename);
1023 giraffe_extraction_destroy(extraction);
1024 giraffe_localization_destroy(localization);
1034 if (flat_config->apply == TRUE) {
1036 GiImage* errors = NULL;
1039 flat_frame = cpl_frameset_find(set, GIFRAME_FIBER_FLAT_EXTERRORS);
1041 if (flat_frame == NULL) {
1042 cpl_msg_warning(_id,
"Missing flat field spectra errors "
1047 filename = cpl_frame_get_filename(flat_frame);
1053 cpl_msg_error(_id,
"Cannot load flat field spectra "
1054 "errors from '%s'. Aborting ...",
1062 giraffe_extraction_destroy(extraction);
1063 giraffe_localization_destroy(localization);
1075 cpl_msg_info(_id,
"Applying flat field correction ...");
1081 cpl_msg_error(_id,
"Flat field correction failed! "
1089 giraffe_extraction_destroy(extraction);
1090 giraffe_localization_destroy(localization);
1105 if (flat_config->transmission == TRUE) {
1107 const cxchar* _filename = cpl_frame_get_filename(flat_frame);
1109 GiTable* _fibers = NULL;
1112 cpl_msg_info(_id,
"Loading fiber setup for frame '%s'.",
1118 cpl_msg_error(_id,
"Cannot create fiber setup for "
1119 "frame '%s'! Aborting ...", _filename);
1125 giraffe_extraction_destroy(extraction);
1126 giraffe_localization_destroy(localization);
1136 cpl_msg_info(_id,
"Applying relative fiber transmission "
1139 status = giraffe_transmission_setup(fibers, _fibers);
1143 status = giraffe_transmission_apply(extraction, fibers);
1148 cpl_msg_error(_id,
"Relative transmission correction failed! "
1155 giraffe_extraction_destroy(extraction);
1156 giraffe_localization_destroy(localization);
1181 cpl_msg_info(_id,
"Writing extracted spectra ...");
1188 GIFRAME_SCIENCE_EXTSPECTRA,
1189 CPL_FRAME_LEVEL_FINAL,
1192 if (sext_frame == NULL) {
1193 cpl_msg_error(_id,
"Cannot create local file! Aborting ...");
1195 giraffe_extraction_destroy(extraction);
1196 giraffe_localization_destroy(localization);
1209 cpl_msg_error(_id,
"Cannot attach fiber setup to local file '%s'! "
1210 "Aborting ...", cpl_frame_get_filename(sext_frame));
1212 cpl_frame_delete(sext_frame);
1214 giraffe_extraction_destroy(extraction);
1215 giraffe_localization_destroy(localization);
1225 cpl_frameset_insert(set, sext_frame);
1232 GIFRAME_SCIENCE_EXTERRORS,
1233 CPL_FRAME_LEVEL_FINAL,
1236 if (sext_frame == NULL) {
1237 cpl_msg_error(_id,
"Cannot create local file! Aborting ...");
1239 giraffe_extraction_destroy(extraction);
1240 giraffe_localization_destroy(localization);
1253 cpl_msg_error(_id,
"Cannot attach fiber setup to local file '%s'! "
1254 "Aborting ...", cpl_frame_get_filename(sext_frame));
1256 cpl_frame_delete(sext_frame);
1258 giraffe_extraction_destroy(extraction);
1259 giraffe_localization_destroy(localization);
1269 cpl_frameset_insert(set, sext_frame);
1273 if (extraction->npixels != NULL) {
1278 GIFRAME_SCIENCE_EXTPIXELS,
1279 CPL_FRAME_LEVEL_FINAL,
1282 if (sext_frame == NULL) {
1283 cpl_msg_error(_id,
"Cannot create local file! Aborting ...");
1285 giraffe_extraction_destroy(extraction);
1286 giraffe_localization_destroy(localization);
1299 cpl_msg_error(_id,
"Cannot attach fiber setup to local file '%s'! "
1300 "Aborting ...", cpl_frame_get_filename(sext_frame));
1302 cpl_frame_delete(sext_frame);
1304 giraffe_extraction_destroy(extraction);
1305 giraffe_localization_destroy(localization);
1315 cpl_frameset_insert(set, sext_frame);
1324 GIFRAME_SCIENCE_EXTTRACE,
1325 CPL_FRAME_LEVEL_FINAL,
1328 if (sext_frame == NULL) {
1329 cpl_msg_error(_id,
"Cannot create local file! Aborting ...");
1331 giraffe_extraction_destroy(extraction);
1332 giraffe_localization_destroy(localization);
1345 cpl_msg_error(_id,
"Cannot attach fiber setup to local file '%s'! "
1346 "Aborting ...", cpl_frame_get_filename(sext_frame));
1348 cpl_frame_delete(sext_frame);
1350 giraffe_extraction_destroy(extraction);
1351 giraffe_localization_destroy(localization);
1361 cpl_frameset_insert(set, sext_frame);
1365 if (extraction->model != NULL) {
1370 GIFRAME_SCIENCE_EXTMODEL,
1371 CPL_FRAME_LEVEL_FINAL,
1374 if (sext_frame == NULL) {
1375 cpl_msg_error(_id,
"Cannot create local file! Aborting ...");
1377 giraffe_extraction_destroy(extraction);
1378 giraffe_localization_destroy(localization);
1391 cpl_msg_error(_id,
"Cannot attach fiber setup to local file '%s'! "
1392 "Aborting ...", cpl_frame_get_filename(sext_frame));
1394 cpl_frame_delete(sext_frame);
1396 giraffe_extraction_destroy(extraction);
1397 giraffe_localization_destroy(localization);
1407 cpl_frameset_insert(set, sext_frame);
1417 filename = (cxchar *)cpl_frame_get_filename(wcal_frame);
1423 cpl_msg_error(_id,
"Cannot load dispersion solution from "
1424 "'%s'. Aborting ...", filename);
1426 giraffe_extraction_destroy(extraction);
1427 giraffe_localization_destroy(localization);
1442 filename = (cxchar *)cpl_frame_get_filename(grating_frame);
1450 cpl_msg_error(_id,
"Cannot load grating data from '%s'. "
1451 "Aborting ...", filename);
1453 giraffe_extraction_destroy(extraction);
1454 giraffe_localization_destroy(localization);
1470 filename = (cxchar *)cpl_frame_get_filename(slit_frame);
1474 if (slitgeometry == NULL) {
1475 cpl_msg_error(_id,
"Cannot load slit geometry data from '%s'. "
1476 "Aborting ...", filename);
1480 giraffe_extraction_destroy(extraction);
1481 giraffe_localization_destroy(localization);
1499 cpl_msg_error(_id,
"Slit geometry data from '%s' is not "
1500 "applicable for current fiber setup! "
1501 "Aborting ...", filename);
1506 giraffe_extraction_destroy(extraction);
1507 giraffe_localization_destroy(localization);
1525 cpl_msg_info(_id,
"Spectrum rebinning");
1532 localization, grating, slitgeometry,
1533 wcalcoeff, rebin_config);
1536 cpl_msg_error(_id,
"Rebinning of science spectra failed! Aborting...");
1540 giraffe_extraction_destroy(extraction);
1541 giraffe_localization_destroy(localization);
1562 p = cpl_parameterlist_find(config,
"giraffe.siwc.apply");
1563 cx_assert(p != NULL);
1565 siwc = cpl_parameter_get_bool(p);
1569 cx_assert(properties != NULL);
1572 if (cpl_propertylist_has(properties, GIALIAS_STSCTAL) == TRUE) {
1573 calsim = cpl_propertylist_get_bool(properties, GIALIAS_STSCTAL);
1577 if ((siwc == TRUE) && (calsim == TRUE) && (linemask_frame != NULL)) {
1586 if (siwc_config == NULL) {
1593 giraffe_extraction_destroy(extraction);
1594 giraffe_localization_destroy(localization);
1608 filename = cpl_frame_get_filename(linemask_frame);
1613 cpl_msg_error(_id,
"Cannot load line reference mask from '%s'. "
1614 "Aborting ...", filename);
1624 giraffe_extraction_destroy(extraction);
1625 giraffe_localization_destroy(localization);
1641 linemask, siwc_config);
1644 cpl_msg_error(_id,
"Applying simultaneous wavelength "
1645 "calibration correction failed! Aborting...");
1655 giraffe_extraction_destroy(extraction);
1656 giraffe_localization_destroy(localization);
1680 localization, grating, slitgeometry,
1681 wcalcoeff, rebin_config);
1684 cpl_msg_error(_id,
"Rebinning of science spectra failed! "
1689 giraffe_extraction_destroy(extraction);
1690 giraffe_localization_destroy(localization);
1706 giraffe_extraction_destroy(extraction);
1709 giraffe_localization_destroy(localization);
1710 localization = NULL;
1713 rebin_config = NULL;
1730 cpl_msg_warning(_id,
"Missing observation time properties! "
1731 "Barycentric correction computation "
1738 cpl_msg_warning(_id,
"Missing telescope location properties! "
1739 "Barycentric correction computation "
1746 cpl_msg_warning(_id,
"Object positions are not available "
1747 "Barycentric correction computation "
1754 cpl_msg_error(_id,
"Barycentric correction computation "
1755 "failed! Aborting...");
1781 GIFRAME_SCIENCE_RBNSPECTRA,
1782 CPL_FRAME_LEVEL_FINAL,
1785 if (rbin_frame == NULL) {
1786 cpl_msg_error(_id,
"Cannot create local file! Aborting ...");
1802 cpl_msg_error(_id,
"Cannot attach fiber setup to local "
1803 "file '%s'! Aborting ...",
1804 cpl_frame_get_filename(rbin_frame));
1813 cpl_frame_delete(rbin_frame);
1818 cpl_frameset_insert(set, rbin_frame);
1819 flux_filename = cpl_strdup(cpl_frame_get_filename(rbin_frame));
1826 GIFRAME_SCIENCE_RBNERRORS,
1827 CPL_FRAME_LEVEL_FINAL,
1830 if (rbin_frame == NULL) {
1831 cpl_msg_error(_id,
"Cannot create local file! Aborting ...");
1840 cpl_free(flux_filename);
1848 cpl_msg_error(_id,
"Cannot attach fiber setup to local "
1849 "file '%s'! Aborting ...",
1850 cpl_frame_get_filename(rbin_frame));
1860 cpl_frame_delete(rbin_frame);
1861 cpl_free(flux_filename);
1866 cpl_frameset_insert(set, rbin_frame);
1867 err_filename = cpl_strdup(cpl_frame_get_filename(rbin_frame));
1875 p = cpl_parameterlist_find(config,
"giraffe.sdp.format.generate");
1876 cx_assert(p != NULL);
1877 gensdp = cpl_parameter_get_bool(p);
1878 p = cpl_parameterlist_find(config,
"giraffe.sdp.nassoc.keys");
1879 cx_assert(p != NULL);
1880 nassoc_keys = cpl_parameter_get_int(p);
1883 if (mode == GIMODE_MEDUSA) {
1884 status = _giraffe_make_sdp_spectra(flux_filename, err_filename,
1885 nassoc_keys, set, config, _id);
1887 cpl_msg_error(_id,
"Failed to generate spectra in Science Data"
1888 " Product format.");
1898 cpl_free(flux_filename);
1899 cpl_free(err_filename);
1904 cpl_msg_warning(_id,
"Requested to generate SDP 1D spectra, but"
1905 " this is currently only supported for the MEDUSA"
1906 " mode. Skipping SDP generation.");
1909 cpl_free(flux_filename);
1910 cpl_free(err_filename);
1917 if (mode == GIMODE_IFU || mode == GIMODE_ARGUS) {
1919 cpl_frame* rimg_frame = NULL;
1921 GiFieldOfView* fov = NULL;
1923 GiFieldOfViewConfig* fov_config = NULL;
1925 GiFieldOfViewCubeFormat cube_format = GIFOV_FORMAT_ESO3D;
1930 cube_format = fov_config->format;
1933 cpl_msg_info(_id,
"Reconstructing image and data cube from rebinned "
1939 slitgeometry, fov_config);
1944 cpl_msg_warning(_id,
"No reconstructed image was built. "
1945 "Fiber list has no fiber position "
1949 cpl_msg_error(_id,
"Image reconstruction failed! Aborting...");
1979 GIFRAME_SCIENCE_RCSPECTRA,
1980 CPL_FRAME_LEVEL_FINAL,
1983 if (rimg_frame == NULL) {
1984 cpl_msg_error(_id,
"Cannot create local file! Aborting ...");
1998 cpl_frameset_insert(set, rimg_frame);
2006 GIFRAME_SCIENCE_RCERRORS,
2007 CPL_FRAME_LEVEL_FINAL,
2010 if (rimg_frame == NULL) {
2011 cpl_msg_error(_id,
"Cannot create local file! Aborting ...");
2025 cpl_frameset_insert(set, rimg_frame);
2030 if (cube_format == GIFOV_FORMAT_SINGLE) {
2034 if (fov->cubes.spectra != NULL) {
2036 cxint component = 0;
2042 properties = cpl_propertylist_duplicate(properties);
2047 CPL_FRAME_LEVEL_FINAL,
2053 cpl_propertylist_delete(properties);
2056 if (rimg_frame == NULL) {
2057 cpl_msg_error(_id,
"Cannot create local file! Aborting ...");
2069 slitgeometry = NULL;
2083 cpl_msg_error(_id,
"Cannot attach fiber setup to local "
2084 "file '%s'! Aborting ...",
2085 cpl_frame_get_filename(rimg_frame));
2087 cpl_frame_delete(rimg_frame);
2099 slitgeometry = NULL;
2110 cpl_frameset_insert(set, rimg_frame);
2116 if (fov->cubes.errors != NULL) {
2118 cxint component = 1;
2124 properties = cpl_propertylist_duplicate(properties);
2129 CPL_FRAME_LEVEL_FINAL,
2135 cpl_propertylist_delete(properties);
2138 if (rimg_frame == NULL) {
2139 cpl_msg_error(_id,
"Cannot create local file! Aborting ...");
2151 slitgeometry = NULL;
2165 cpl_msg_error(_id,
"Cannot attach fiber setup to local "
2166 "file '%s'! Aborting ...",
2167 cpl_frame_get_filename(rimg_frame));
2169 cpl_frame_delete(rimg_frame);
2181 slitgeometry = NULL;
2192 cpl_frameset_insert(set, rimg_frame);
2203 properties = cpl_propertylist_duplicate(properties);
2208 CPL_FRAME_LEVEL_FINAL,
2214 cpl_propertylist_delete(properties);
2217 if (rimg_frame == NULL) {
2218 cpl_msg_error(_id,
"Cannot create local file! Aborting ...");
2230 slitgeometry = NULL;
2244 cpl_msg_error(_id,
"Cannot attach fiber setup to local "
2245 "file '%s'! Aborting ...",
2246 cpl_frame_get_filename(rimg_frame));
2248 cpl_frame_delete(rimg_frame);
2260 slitgeometry = NULL;
2271 cpl_frameset_insert(set, rimg_frame);
2304 cpl_plugin_get_info(cpl_pluginlist* list)
2307 cpl_recipe* recipe = cx_calloc(1,
sizeof *recipe);
2308 cpl_plugin* plugin = &recipe->interface;
2311 cpl_plugin_init(plugin,
2313 GIRAFFE_BINARY_VERSION,
2314 CPL_PLUGIN_TYPE_RECIPE,
2316 "Process a science observation.",
2317 "For detailed information please refer to the "
2318 "GIRAFFE pipeline user manual.\nIt is available at "
2319 "http://www.eso.org/pipelines.",
2327 cpl_pluginlist_append(list, plugin);
2336 typedef struct _giraffe_lut_entry {
2337 const char* expmode;
2343 } giraffe_lut_entry;
2352 static cpl_boolean _giraffe_lut_is_sorted(
const giraffe_lut_entry* lut,
2356 if (nentries < 2)
return CPL_TRUE;
2357 for (i = 0; i < nentries - 1; ++i) {
2358 if (strcmp(lut[i].expmode, lut[i+1].expmode) >= 0) {
2375 static const giraffe_lut_entry* _giraffe_find_lut_entry(
const char* expmode)
2377 static giraffe_lut_entry lut[] = {
2382 {
"H379.", 25000, 0.2250, 20.0, 60},
2383 {
"H379.0", 25000, 0.2250, 20.0, 60},
2384 {
"H395.8", 22000, 0.1913, 21.1, 53},
2385 {
"H412.4", 30000, 0.1326, 22.3, 48},
2386 {
"H429.7", 23000, 0.1471, 23.5, 67},
2387 {
"H447.1", 20000, 0.0906, 24.9, 63},
2388 {
"H447.1A", 20000, 0.0906, 24.9, 63},
2389 {
"H447.1B", 31000, 0.1297, 23.5, 58},
2390 {
"H465.6", 23000, 0.1573, 22.4, 57},
2391 {
"H484.5", 19000, 0.1175, 23.5, 57},
2392 {
"H484.5A", 19000, 0.1175, 23.5, 57},
2393 {
"H484.5B", 33000, 0.0907, 24.6, 61},
2394 {
"H504.8", 22000, 0.1726, 25.2, 56},
2395 {
"H525.8", 17000, 0.1397, 25.8, 49},
2396 {
"H525.8A", 17000, 0.1397, 25.8, 49},
2397 {
"H525.8B", 29000, 0.2014, 26.4, 44},
2398 {
"H548.8", 20000, 0.2389, 26.9, 51},
2399 {
"H572.8", 27000, 0.1844, 27.5, 49},
2400 {
"H599.3", 18000, 0.1683, 28.3, 57},
2401 {
"H627.3", 24000, 0.1268, 29.0, 50},
2402 {
"H651.5", 17000, 0.1185, 30.0, 42},
2403 {
"H651.5A", 17000, 0.1185, 30.0, 42},
2404 {
"H651.5B", 35000, 0.1253, 31.5, 37},
2405 {
"H665.", 17000, 0.2076, 33.0, 45},
2406 {
"H665.0", 17000, 0.2076, 33.0, 45},
2407 {
"H679.7", 19000, 0.1621, 34.5, 51},
2408 {
"H710.5", 25000, 0.1495, 36.0, 48},
2409 {
"H737.", 16000, 0.1456, 37.5, 47},
2410 {
"H737.0", 16000, 0.1456, 37.5, 47},
2411 {
"H737.0A", 16000, 0.1456, 37.5, 47},
2412 {
"H737.0B", 35000, 0.1147, 39.5, 40},
2413 {
"H769.1", 19000, 0.2811, 41.8, 35},
2414 {
"H805.3", 14000, 0.2662, 42.4, 39},
2415 {
"H805.3A", 14000, 0.2662, 42.4, 39},
2416 {
"H805.3B", 25000, 0.2342, 42.9, 28},
2417 {
"H836.6", 16000, 0.2032, 43.3, 21},
2418 {
"H836.6A", 16000, 0.2032, 43.3, 21},
2419 {
"H836.6B", 34000, 0.1073, 43.7, 14},
2420 {
"H875.7", 18000, 0.2026, 44.3, 29},
2421 {
"H920.5", 12000, 0.1568, 44.9, 32},
2422 {
"H920.5A", 12000, 0.1568, 44.9, 32},
2423 {
"H920.5B", 24000, 0.2531, 45.9, 28},
2424 {
"L385.7", 7500, 0.3358, 58.0, 43},
2425 {
"L427.2", 6300, 0.2152, 61.1, 62},
2426 {
"L479.7", 7500, 0.1554, 71.0, 61},
2427 {
"L543.1", 5800, 0.2065, 82.1, 58},
2428 {
"L614.2", 6600, 0.1803, 79.0, 51},
2429 {
"L682.2", 8100, 0.1843, 74.0, 50},
2430 {
"L773.4", 5400, 0.1617, 94.0, 44},
2431 {
"L881.7", 6600, 0.1614, 119.0, 29}
2433 static const size_t nentries =
sizeof(lut) /
sizeof(giraffe_lut_entry);
2435 int high = (int)nentries - 1;
2437 assert(_giraffe_lut_is_sorted(lut, nentries));
2438 assert(expmode != NULL);
2442 int mid = (low + high) >> 1;
2443 int result = strcmp(expmode, lut[mid].expmode);
2446 }
else if (result < 0) {
2451 }
while (high >= low);
2461 static double _giraffe_lookup_specres(
const char* expmode)
2463 const giraffe_lut_entry* entry = _giraffe_find_lut_entry(expmode);
2464 if (entry == NULL)
return NAN;
2465 return entry->specres;
2474 static double _giraffe_lookup_lamrms(
const char* expmode)
2476 const giraffe_lut_entry* entry = _giraffe_find_lut_entry(expmode);
2477 if (entry == NULL)
return NAN;
2478 if (isnan(entry->lamrms) || isnan(entry->spec_length))
return NAN;
2479 return entry->lamrms * entry->spec_length / 4100.;
2488 static double _giraffe_lookup_lamnlin(
const char* expmode)
2490 const giraffe_lut_entry* entry = _giraffe_find_lut_entry(expmode);
2491 if (entry == NULL)
return -1;
2492 return entry->lamnlin;
2506 static cpl_type _giraffe_calc_wave_type(
double crval2,
double crpix2,
2507 double cdelt2, cpl_size naxis2)
2509 static const double errfrac = 0.02;
2510 static const double single_precision_digits = 7;
2511 double lo = (1.0 - crpix2) * cdelt2;
2512 double hi = ((double)naxis2 - crpix2) * cdelt2;
2513 double maxwave = crval2 + (hi > lo ? hi : lo);
2514 double binfrac = (maxwave != 0.0) ? fabs(cdelt2 / maxwave) : 0.0;
2515 if (binfrac * errfrac < pow(10, -single_precision_digits)) {
2516 return CPL_TYPE_DOUBLE;
2518 return CPL_TYPE_FLOAT;
2532 static cpl_boolean _giraffe_ancillary_data_available(
const char* filename,
2533 const GiTable* fibertable)
2537 const char** spectypes = NULL;
2539 assert(filename != NULL);
2541 cpl_error_ensure(tbl != NULL, cpl_error_get_code(),
return CPL_FALSE,
2542 "The fiber table is not available for '%s'.", filename);
2544 spectypes = cpl_table_get_data_string_const(tbl, GIALIAS_COLUMN_TYPE);
2545 cpl_error_ensure(spectypes != NULL, cpl_error_get_code(),
return CPL_FALSE,
2546 "Could not fetch the '%s' column from the fiber setup"
2547 " table in '%s'.", GIALIAS_COLUMN_TYPE, filename);
2548 for (i = 0; i < cpl_table_get_nrow(tbl); ++i) {
2549 if (strcmp(spectypes[i],
"M") != 0) {
2576 static cpl_error_code _giraffe_make_ancillary_file(cpl_frameset* allframes,
2577 const char* outputfile,
2578 const char* infilename,
2579 const GiImage* fluximage,
2580 const GiTable* fibertable)
2582 cpl_error_code error = CPL_ERROR_NONE;
2584 cpl_frame* frame = NULL;
2586 GiImage* image = NULL;
2588 cpl_image* img = NULL;
2590 cpl_image* subimg = NULL;
2591 cpl_propertylist* comments = NULL;
2593 int* indices = NULL;
2594 const char** spectypes = NULL;
2596 assert(allframes != NULL);
2597 assert(outputfile != NULL);
2598 assert(infilename != NULL);
2600 cpl_error_ensure(srcimg != NULL && table != NULL && tbl != NULL,
2601 cpl_error_get_code(),
goto cleanup,
2602 "The image or table are not available for '%s'.",
2606 frame = cpl_frame_new();
2607 error |= cpl_frame_set_filename(frame, outputfile);
2608 error |= cpl_frame_set_tag(frame, GIALIAS_ASSO_PROCATG_VALUE);
2609 error |= cpl_frame_set_type(frame, CPL_FRAME_TYPE_IMAGE);
2610 error |= cpl_frame_set_group(frame, CPL_FRAME_GROUP_PRODUCT);
2611 error |= cpl_frame_set_level(frame, CPL_FRAME_LEVEL_FINAL);
2612 cpl_error_ensure(! error, cpl_error_get_code(),
goto cleanup,
2613 "Failed to setup a new output frame for '%s'.",
2619 spectypes = cpl_table_get_data_string_const(tbl, GIALIAS_COLUMN_TYPE);
2620 cpl_error_ensure(spectypes != NULL, cpl_error_get_code(),
goto cleanup,
2621 "Could not fetch the '%s' column from the fiber setup"
2622 " table in '%s'.", GIALIAS_COLUMN_TYPE, infilename);
2623 for (i = 0; i < cpl_table_get_nrow(tbl); ++i) {
2625 if (strcmp(spectypes[i],
"M") != 0) {
2626 error |= cpl_table_unselect_row(tbl, i);
2627 cpl_error_ensure(! error, cpl_error_get_code(),
goto cleanup,
2628 "Failed to deselect row %"CPL_SIZE_FORMAT
2629 " in fiber setup table from '%s'.", i, infilename);
2632 error |= cpl_table_erase_selected(tbl);
2633 cpl_error_ensure(! error, cpl_error_get_code(),
goto cleanup,
2634 "Failed to erase selected entries from fiber setup table"
2635 " in '%s'.", infilename);
2639 ny = cpl_image_get_size_y(srcimg);
2641 cpl_table_get_nrow(tbl), ny);
2645 cpl_error_ensure(image != NULL && img != NULL && retcode == 0,
2646 cpl_error_get_code(),
goto cleanup,
2647 "Failed to create image for output file '%s'.",
2652 GIALIAS_ASSO_PROCATG_VALUE);
2653 cpl_error_ensure(! error, cpl_error_get_code(),
goto cleanup,
2654 "Could not update keyword '%s' for output file '%s'.",
2655 GIALIAS_PROCATG, outputfile);
2660 const char* comments_to_remove[] = {
2661 " FITS (Flexible Image Transport System) format is defined in"
2663 " and Astrophysics', volume 376, page 359; bibcode: 2001A&A..."
2668 comments = cpl_propertylist_new();
2669 error |= cpl_propertylist_copy_property_regexp(comments, props,
2671 cpl_propertylist_erase_regexp(props,
"^COMMENT$", 0);
2672 for (i = 0; i < cpl_propertylist_get_size(comments); ++i) {
2673 const char** cmnt_str;
2674 cpl_property* p = cpl_propertylist_get(comments, i);
2675 for (cmnt_str = comments_to_remove; *cmnt_str != NULL; ++cmnt_str) {
2676 if (strcmp(cpl_property_get_string(p), *cmnt_str) == 0) {
2677 goto dont_add_comment;
2681 error |= cpl_propertylist_append_property(props, p);
2687 cpl_error_ensure(! error, cpl_error_get_code(),
goto cleanup,
2688 "Failed to cleanup comments in primary HDU for '%s'.",
2690 cpl_propertylist_delete(comments);
2696 indices = cpl_table_get_data_int(tbl, GIALIAS_COLUMN_INDEX);
2697 cpl_error_ensure(indices != NULL, cpl_error_get_code(),
goto cleanup,
2698 "Could not fetch the '%s' column from the fiber setup"
2699 " table in '%s'.", GIALIAS_COLUMN_INDEX, infilename);
2700 for (i = 0; i < cpl_table_get_nrow(tbl); ++i) {
2701 cpl_size oldindex = indices[i];
2702 cpl_size newindex = i+1;
2703 indices[i] = newindex;
2704 subimg = cpl_image_extract(srcimg, oldindex, 1, oldindex, ny);
2705 cpl_error_ensure(subimg != NULL, cpl_error_get_code(),
goto cleanup,
2706 "Could not extract sub image from '%s' at column %"
2707 CPL_SIZE_FORMAT
".", infilename, oldindex);
2708 error |= cpl_image_copy(img, subimg, newindex, 1);
2709 cpl_image_delete(subimg);
2711 cpl_error_ensure(! error, cpl_error_get_code(),
goto cleanup,
2712 "Could write sub image from '%s' at column %"
2713 CPL_SIZE_FORMAT
" to new image in '%s' at column %"
2714 CPL_SIZE_FORMAT
".", infilename, oldindex, outputfile,
2720 cpl_error_ensure(retcode == 0, cpl_error_get_code(),
goto cleanup,
2721 "Failed to write image to file '%s'.", outputfile);
2723 cpl_error_ensure(retcode == 0, cpl_error_get_code(),
goto cleanup,
2724 "Failed to attach the fiber setup table to file '%s'.",
2730 error |= cpl_frameset_insert(allframes, frame);
2731 cpl_error_ensure(! error, cpl_error_get_code(),
goto cleanup,
2732 "Could not add a new frame to the frame list for '%s'.",
2737 return CPL_ERROR_NONE;
2741 cpl_image_delete(subimg);
2744 cpl_frame_delete(frame);
2745 cpl_propertylist_delete(comments);
2746 return cpl_error_get_code();
2756 static char* _giraffe_calc_format_string(cpl_size maxfiles)
2758 double ndigits = 1.0;
2762 ndigits = ceil(log10((
double)maxfiles + 1.0));
2764 return cpl_sprintf(
"science_spectrum_%%0%.0f"CPL_SIZE_FORMAT
".fits",
2785 static cxint _giraffe_make_sdp_spectra(
const cxchar* flux_filename,
2786 const cxchar* err_filename,
2788 cpl_frameset* allframes,
2789 const cpl_parameterlist* parlist,
2790 const cxchar* recipe_id)
2792 cxint result_code = 1;
2794 cpl_error_code error = CPL_ERROR_NONE;
2795 cpl_errorstate prestate;
2796 const char* ancillary_filename =
"science_ancillary.fits";
2799 GiTable* fibertable = NULL;
2800 const cxchar* fibertable_name = NULL;
2801 irplib_sdp_spectrum* spectrum = NULL;
2802 cpl_propertylist* extrakeys = cpl_propertylist_new();
2803 cpl_propertylist* tablekeys = cpl_propertylist_new();
2804 cpl_propertylist* props;
2805 char* pipe_id = cpl_sprintf(
"%s/%s", PACKAGE, VERSION);
2806 const char* dict_id = PRODUCT_DID;
2807 const cpl_frame* inherit = NULL;
2808 cpl_frameset* usedframes = NULL;
2809 cpl_frameset* rawframes = NULL;
2810 cpl_frameset_iterator* iterator = NULL;
2811 cpl_size nx, ny, i, filecount;
2812 double exptime = NAN;
2813 double mjdobs = NAN;
2814 double mjdend = NAN;
2815 double wavelmin = NAN;
2816 double wavelmax = NAN;
2817 double specbin = NAN;
2818 double crpix2 = NAN;
2819 double crval2 = NAN;
2820 double cdelt2 = NAN;
2821 const char* cunit2 = NULL;
2823 const char* expmode = NULL;
2825 const int* indices = NULL;
2826 const int* fps = NULL;
2827 const char** objects = NULL;
2828 const char** spectypes = NULL;
2829 const double* ras = NULL;
2830 const double* decs = NULL;
2831 const double* gcorr = NULL;
2832 const double* hcorr = NULL;
2833 const double* bcorr = NULL;
2834 char* formatstr = NULL;
2835 char* filename = NULL;
2836 cpl_type wavecoltype;
2837 cpl_array* refwavearray = NULL;
2838 cpl_array* array = NULL;
2839 float* data_float = NULL;
2840 double* data_double = NULL;
2841 cpl_vector* fluximgcol = NULL;
2842 cpl_vector* errimgcol = NULL;
2843 cpl_boolean got_ancillary_data = CPL_FALSE;
2844 cpl_size assoc_key_offset = 1;
2846 double lamrms = NAN;
2847 double specerr = NAN;
2848 double specsye = NAN;
2850 cpl_error_ensure(flux_filename != NULL && err_filename != NULL
2851 && allframes != NULL && parlist != NULL
2852 && recipe_id != NULL, CPL_ERROR_NULL_INPUT,
goto cleanup,
2853 "NULL input parameters.");
2855 error |= cpl_propertylist_append_string(extrakeys, GIALIAS_PROCATG,
2856 GIALIAS_PROCATG_RBNSPEC_IDP);
2857 error |= cpl_propertylist_set_comment(extrakeys, GIALIAS_PROCATG,
2858 GIALIAS_PROCATG_COMMENT);
2859 cpl_error_ensure(! error, cpl_error_get_code(),
goto cleanup,
2860 "Could not set keyword '%s'.", GIALIAS_PROCATG);
2864 cpl_error_ensure(errorcode == 0, cpl_error_get_code(),
goto cleanup,
2865 "Could not load image data in primary HDU from '%s'.",
2868 cpl_error_ensure(errorcode == 0, cpl_error_get_code(),
goto cleanup,
2869 "Could not load image data in primary HDU from '%s'.",
2872 giraffe_error_push();
2874 if (fibertable == NULL) {
2876 GIALIAS_FIBER_SETUP);
2877 fibertable_name = err_filename;
2879 fibertable_name = flux_filename;
2881 cpl_error_ensure(fibertable != NULL, CPL_ERROR_DATA_NOT_FOUND,
goto cleanup,
2882 "Could not load the %s table from either '%s' or '%s'.",
2883 GIALIAS_FIBER_SETUP, flux_filename, err_filename);
2884 giraffe_error_pop();
2891 CPL_ERROR_INCOMPATIBLE_INPUT,
goto cleanup,
2892 "The images in files '%s' and '%s' are not the same size.",
2893 flux_filename, err_filename);
2897 usedframes = cpl_frameset_new();
2898 rawframes = cpl_frameset_new();
2899 iterator = cpl_frameset_iterator_new(allframes);
2901 const cpl_frame* frame = cpl_frameset_iterator_get_const(iterator);
2902 if (frame != NULL) {
2903 switch (cpl_frame_get_group(frame)) {
2904 case CPL_FRAME_GROUP_RAW:
2906 if (inherit == NULL) inherit = frame;
2907 error |= cpl_frameset_insert(rawframes,
2908 cpl_frame_duplicate(frame));
2909 case CPL_FRAME_GROUP_CALIB:
2910 error |= cpl_frameset_insert(usedframes,
2911 cpl_frame_duplicate(frame));
2917 prestate = cpl_errorstate_get();
2918 error |= cpl_frameset_iterator_advance(iterator, 1);
2919 if (error == CPL_ERROR_ACCESS_OUT_OF_RANGE) {
2920 cpl_errorstate_set(prestate);
2922 }
else if (error != CPL_ERROR_NONE) {
2927 cpl_error_ensure(inherit != NULL, CPL_ERROR_DATA_NOT_FOUND,
goto cleanup,
2928 "No raw input frames found.");
2932 prestate = cpl_errorstate_get();
2933 exptime = cpl_propertylist_get_double(props, GIALIAS_EXPTIME);
2934 cpl_error_ensure(cpl_errorstate_is_equal(prestate), cpl_error_get_code(),
2935 goto cleanup,
"Could not find keyword '%s' in '%s'.",
2936 GIALIAS_EXPTIME, flux_filename);
2937 mjdobs = cpl_propertylist_get_double(props, GIALIAS_MJDOBS);
2938 cpl_error_ensure(cpl_errorstate_is_equal(prestate), cpl_error_get_code(),
2939 goto cleanup,
"Could not find keyword '%s' in '%s'.",
2940 GIALIAS_MJDOBS, flux_filename);
2942 mjdend = mjdobs + exptime / 86400.;
2945 crpix2 = cpl_propertylist_get_double(props, GIALIAS_CRPIX2);
2946 cpl_error_ensure(cpl_errorstate_is_equal(prestate), cpl_error_get_code(),
2947 goto cleanup,
"Could not find keyword '%s' in '%s'.",
2948 GIALIAS_CRPIX2, flux_filename);
2949 crval2 = cpl_propertylist_get_double(props, GIALIAS_CRVAL2);
2950 cpl_error_ensure(cpl_errorstate_is_equal(prestate), cpl_error_get_code(),
2951 goto cleanup,
"Could not find keyword '%s' in '%s'.",
2952 GIALIAS_CRVAL2, flux_filename);
2953 cdelt2 = cpl_propertylist_get_double(props, GIALIAS_CDELT2);
2954 cpl_error_ensure(cpl_errorstate_is_equal(prestate), cpl_error_get_code(),
2955 goto cleanup,
"Could not find keyword '%s' in '%s'.",
2956 GIALIAS_CDELT2, flux_filename);
2957 cunit2 = cpl_propertylist_get_string(props, GIALIAS_CUNIT2);
2958 cpl_error_ensure(cunit2 != NULL, cpl_error_get_code(),
2959 goto cleanup,
"Could not find keyword '%s' in '%s'.",
2960 GIALIAS_CUNIT2, flux_filename);
2962 if (strcmp(cunit2,
"nm") == 0) {
2963 wavelmin = (1.0 - crpix2) * cdelt2 + crval2;
2964 wavelmax = ((double)ny - crpix2) * cdelt2 + crval2;
2965 if (wavelmax < wavelmin) {
2966 double tmp = wavelmin;
2967 wavelmin = wavelmax;
2970 specbin = fabs(cdelt2);
2972 cpl_msg_warning(cpl_func,
"Do not know how to handle keyword %s = '%s'."
2973 " Will not set WAVELMIN, WAVELMAX or SPEC_BIN.",
2974 GIALIAS_CUNIT2, cunit2);
2977 if (cpl_propertylist_has(props, GIALIAS_SETUPNAME)) {
2978 expmode = cpl_propertylist_get_string(props, GIALIAS_SETUPNAME);
2979 cpl_error_ensure(expmode != NULL, cpl_error_get_code(),
goto cleanup,
2980 "Could not fetch the keyword '%s' from '%s'.",
2981 GIALIAS_SETUPNAME, flux_filename);
2982 }
else if (cpl_propertylist_has(props, GIALIAS_GRATNAME)) {
2983 const char* name = cpl_propertylist_get_string(props, GIALIAS_GRATNAME);
2984 cpl_error_ensure(name != NULL, cpl_error_get_code(),
goto cleanup,
2985 "Could not fetch the keyword '%s' from '%s'.",
2986 GIALIAS_GRATNAME, flux_filename);
2987 double wlen = cpl_propertylist_get_double(props, GIALIAS_GRATWLEN);
2988 cpl_error_ensure(cpl_errorstate_is_equal(prestate),
2989 cpl_error_get_code(),
goto cleanup,
2990 "Could not find keyword '%s' in '%s'.",
2991 GIALIAS_GRATWLEN, flux_filename);
2992 strbuf[0] = name[0];
2993 sprintf(strbuf+1,
"%32f", wlen);
2996 cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
2997 "Neither '%s' nor '%s' and '%s' keywords were found in the"
2998 " file '%s'.", GIALIAS_SETUPNAME, GIALIAS_GRATNAME,
2999 GIALIAS_GRATWLEN, flux_filename);
3003 specres = _giraffe_lookup_specres(expmode);
3004 if (isnan(specres)) {
3005 cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
3006 "The exposure mode '%s' is invalid or an unknown value."
3007 " Could not lookup the spectral resolution for 'SPEC_RES'.",
3014 if (cpl_propertylist_has(props,
"FILTER")) {
3015 prestate = cpl_errorstate_get();
3016 cpl_propertylist_copy_property(extrakeys, props,
"FILTER");
3017 cpl_property* prop = cpl_propertylist_get_property(extrakeys,
"FILTER");
3018 cpl_property_set_name(prop,
"OFILTER");
3019 cpl_error_ensure(cpl_errorstate_is_equal(prestate),
3020 cpl_error_get_code(),
goto cleanup,
3021 "Could not rename the 'FILTER' keyword.");
3025 prestate = cpl_errorstate_get();
3026 got_ancillary_data = _giraffe_ancillary_data_available(flux_filename,
3028 if (! cpl_errorstate_is_equal(prestate))
goto cleanup;
3029 if (got_ancillary_data) {
3030 error = _giraffe_make_ancillary_file(allframes, ancillary_filename,
3031 flux_filename, fluximage,
3033 cpl_error_ensure(! error, cpl_error_get_code(),
goto cleanup,
3034 "Failed to write the ancillary file '%s'.",
3035 ancillary_filename);
3039 spectrum = irplib_sdp_spectrum_new();
3040 error = CPL_ERROR_NONE;
3041 error |= irplib_sdp_spectrum_set_origin(spectrum, GIALIAS_ORIGIN_VALUE);
3042 error |= irplib_sdp_spectrum_set_prodlvl(spectrum, GIALIAS_PRODLVL_VALUE);
3043 error |= irplib_sdp_spectrum_copy_dispelem(spectrum,
3044 props, GIALIAS_GRATNAME);
3045 error |= irplib_sdp_spectrum_set_specsys(spectrum, GIALIAS_SPECSYS_VALUE);
3046 error |= irplib_sdp_spectrum_set_extobj(spectrum, GIALIAS_EXT_OBJ_VALUE);
3049 error |= irplib_sdp_spectrum_set_object(spectrum,
"");
3050 error |= irplib_sdp_spectrum_set_ra(spectrum, 0.0);
3051 error |= irplib_sdp_spectrum_set_dec(spectrum, 0.0);
3052 error |= irplib_sdp_spectrum_copy_exptime(spectrum, props, GIALIAS_EXPTIME);
3053 error |= irplib_sdp_spectrum_copy_texptime(spectrum,
3054 props, GIALIAS_EXPTIME);
3055 error |= irplib_sdp_spectrum_copy_mjdobs(spectrum, props, GIALIAS_MJDOBS);
3056 error |= irplib_sdp_spectrum_set_mjdend(spectrum, mjdend);
3057 if (cpl_propertylist_has(props, GIALIAS_TIMESYS)) {
3058 error |= irplib_sdp_spectrum_copy_timesys(spectrum,
3059 props, GIALIAS_TIMESYS);
3061 error |= irplib_sdp_spectrum_copy_progid(spectrum, props, GIALIAS_PROGID);
3062 error |= irplib_sdp_spectrum_copy_obid(spectrum, 1, props, GIALIAS_OBSID);
3063 error |= irplib_sdp_spectrum_set_mepoch(spectrum, GIALIAS_M_EPOCH_VALUE);
3064 error |= irplib_sdp_spectrum_append_prov(spectrum, 1, rawframes);
3065 error |= irplib_sdp_spectrum_copy_procsoft(spectrum,
3066 props, GIALIAS_PROPIPEID);
3067 error |= irplib_sdp_spectrum_copy_obstech(spectrum, props, GIALIAS_PROTECH);
3068 error |= irplib_sdp_spectrum_set_prodcatg(spectrum, GIALIAS_PRODCATG_VALUE);
3069 error |= irplib_sdp_spectrum_set_fluxcal(spectrum, GIALIAS_FLUXCAL_VALUE);
3070 error |= irplib_sdp_spectrum_set_contnorm(spectrum, GIALIAS_CONTNORM_VALUE);
3074 error |= irplib_sdp_spectrum_set_wavelmin(spectrum, 0.0);
3075 error |= irplib_sdp_spectrum_set_wavelmax(spectrum, 0.0);
3076 error |= irplib_sdp_spectrum_set_specbin(spectrum, 0.0);
3077 error |= irplib_sdp_spectrum_set_totflux(spectrum, GIALIAS_TOTFLUX_VALUE);
3078 error |= irplib_sdp_spectrum_set_fluxerr(spectrum, GIALIAS_FLUXERR_VALUE);
3079 error |= irplib_sdp_spectrum_set_ncombine(spectrum,
3080 cpl_frameset_get_size(rawframes));
3081 error |= irplib_sdp_spectrum_set_referenc(spectrum, GIALIAS_REFERENC);
3084 error |= irplib_sdp_spectrum_set_snr(spectrum, 0.0);
3087 if (cpl_propertylist_has(props, GIALIAS_LAMNLIN)) {
3088 error |= irplib_sdp_spectrum_copy_lamnlin(spectrum, props,
3090 lamnlin = irplib_sdp_spectrum_get_lamnlin(spectrum);
3092 lamnlin = _giraffe_lookup_lamnlin(expmode);
3093 if (lamnlin != -1) {
3094 error |= irplib_sdp_spectrum_set_lamnlin(spectrum, lamnlin);
3101 if (cpl_propertylist_has(props, GIALIAS_LAMRMS)) {
3102 error |= irplib_sdp_spectrum_copy_lamrms(spectrum, props,
3104 lamrms = irplib_sdp_spectrum_get_lamrms(spectrum);
3106 lamrms = _giraffe_lookup_lamrms(expmode);
3107 if (! isnan(lamrms)) {
3108 error |= irplib_sdp_spectrum_set_lamrms(spectrum, lamrms);
3122 if (cpl_propertylist_has(props, GIALIAS_SPEC_ERR)) {
3123 error |= irplib_sdp_spectrum_copy_specerr(spectrum, props,
3125 specerr = irplib_sdp_spectrum_get_specerr(spectrum);
3126 }
else if (lamnlin > 0) {
3127 if (cpl_propertylist_has(props, GIALIAS_CRDER1)) {
3128 prestate = cpl_errorstate_get();
3129 double crder1 = cpl_propertylist_get_double(props, GIALIAS_CRDER1);
3130 if (cpl_errorstate_is_equal(prestate) && crder1 > 0) {
3131 specerr = crder1 / sqrt(lamnlin);
3133 error = cpl_error_get_code();
3135 }
else if (! isnan(lamrms)) {
3136 specerr = lamrms / sqrt(lamnlin);
3138 if (! isnan(specerr)) {
3139 error |= irplib_sdp_spectrum_set_specerr(spectrum, specerr);
3146 if (cpl_propertylist_has(props, GIALIAS_SPEC_SYE)) {
3147 error |= irplib_sdp_spectrum_copy_specsye(spectrum, props,
3149 specsye = irplib_sdp_spectrum_get_specsye(spectrum);
3154 error |= irplib_sdp_spectrum_set_specsye(spectrum, 0.002);
3157 error |= irplib_sdp_spectrum_set_specres(spectrum, specres);
3158 error |= irplib_sdp_spectrum_copy_gain(spectrum, props, GIALIAS_CONAD);
3159 error |= irplib_sdp_spectrum_copy_detron(spectrum, props, GIALIAS_RON);
3160 if (got_ancillary_data) {
3161 error |= irplib_sdp_spectrum_set_asson(spectrum, 1, ancillary_filename);
3162 error |= irplib_sdp_spectrum_set_assoc(spectrum, 1,
3163 GIALIAS_ASSOC_VALUE);
3164 error |= irplib_sdp_spectrum_set_assom(spectrum, 1,
"");
3165 assoc_key_offset = 2;
3167 for (i = assoc_key_offset; i < nassoc_keys + assoc_key_offset; ++i) {
3169 error |= irplib_sdp_spectrum_set_asson(spectrum, i,
"");
3170 error |= irplib_sdp_spectrum_set_assoc(spectrum, i,
"");
3171 error |= irplib_sdp_spectrum_set_assom(spectrum, i,
"");
3174 error |= irplib_sdp_spectrum_set_voclass(spectrum, GIALIAS_VOCLASS_VALUE);
3175 error |= irplib_sdp_spectrum_set_vopub(spectrum, GIALIAS_VOPUB_VALUE);
3176 error |= irplib_sdp_spectrum_set_title(spectrum,
"");
3177 error |= cpl_propertylist_append_double(tablekeys, GIALIAS_APERTURE,
3178 GIALIAS_APERTURE_VALUE);
3179 error |= cpl_propertylist_set_comment(tablekeys, GIALIAS_APERTURE,
3180 GIALIAS_APERTURE_COMMENT);
3189 error |= irplib_sdp_spectrum_set_telapse(spectrum, exptime);
3190 error |= irplib_sdp_spectrum_set_tmid(spectrum, (mjdobs + mjdend) * 0.5);
3194 error |= irplib_sdp_spectrum_set_specval(spectrum, 0.0);
3195 error |= irplib_sdp_spectrum_set_specbw(spectrum, 0.0);
3196 error |= irplib_sdp_spectrum_set_nelem(spectrum, ny);
3197 error |= irplib_sdp_spectrum_set_tdmin(spectrum, 0.0);
3198 error |= irplib_sdp_spectrum_set_tdmax(spectrum, 0.0);
3201 error |= cpl_propertylist_append_int(extrakeys, GIALIAS_FPS, -1);
3202 error |= cpl_propertylist_set_comment(extrakeys, GIALIAS_FPS,
3203 GIALIAS_FPS_COMMENT);
3206 error |= cpl_propertylist_append_double(extrakeys, GIALIAS_GEOCORR, NAN);
3207 error |= cpl_propertylist_set_comment(extrakeys, GIALIAS_GEOCORR,
3208 GIALIAS_GEOCORR_COMMENT);
3209 error |= cpl_propertylist_append_double(extrakeys, GIALIAS_HELICORR, NAN);
3210 error |= cpl_propertylist_set_comment(extrakeys, GIALIAS_HELICORR,
3211 GIALIAS_HELICORR_COMMENT);
3212 error |= cpl_propertylist_append_double(extrakeys, GIALIAS_BARYCORR, NAN);
3213 error |= cpl_propertylist_set_comment(extrakeys, GIALIAS_BARYCORR,
3214 GIALIAS_BARYCORR_COMMENT);
3216 cpl_error_ensure(! error, cpl_error_get_code(),
goto cleanup,
3217 "Could not setup the common SDP spectrum keywords.");
3221 wavecoltype = _giraffe_calc_wave_type(crval2, crpix2, cdelt2, ny);
3224 refwavearray = cpl_array_new(ny, CPL_TYPE_DOUBLE);
3225 data_double = cpl_array_get_data_double(refwavearray);
3226 assert(data_double != NULL);
3227 for (i = 1; i <= ny; ++i) {
3228 data_double[i-1] = (i-crpix2) * cdelt2 + crval2;
3233 error |= irplib_sdp_spectrum_add_column(
3234 spectrum, GIALIAS_COLUMN_WAVE, wavecoltype,
3235 GIALIAS_COLUMN_WAVE_UNIT, NULL, GIALIAS_COLUMN_WAVE_TUTYP,
3236 GIALIAS_COLUMN_WAVE_TUCD, NULL);
3237 error |= irplib_sdp_spectrum_set_column_tcomm(
3238 spectrum, GIALIAS_COLUMN_WAVE, GIALIAS_COLUMN_WAVE_TCOMM);
3239 error |= irplib_sdp_spectrum_add_column(
3240 spectrum, GIALIAS_COLUMN_FLUX_REDUCED, CPL_TYPE_DOUBLE,
3241 GIALIAS_COLUMN_FLUX_REDUCED_UNIT, NULL,
3242 GIALIAS_COLUMN_FLUX_REDUCED_TUTYP,
3243 GIALIAS_COLUMN_FLUX_REDUCED_TUCD, NULL);
3244 error |= irplib_sdp_spectrum_set_column_tcomm(
3245 spectrum, GIALIAS_COLUMN_FLUX_REDUCED,
"");
3246 error |= irplib_sdp_spectrum_add_column(
3247 spectrum, GIALIAS_COLUMN_ERR_REDUCED, CPL_TYPE_DOUBLE,
3248 GIALIAS_COLUMN_ERR_REDUCED_UNIT, NULL,
3249 GIALIAS_COLUMN_ERR_REDUCED_TUTYP,
3250 GIALIAS_COLUMN_ERR_REDUCED_TUCD, NULL);
3251 error |= irplib_sdp_spectrum_set_column_tcomm(
3252 spectrum, GIALIAS_COLUMN_ERR_REDUCED,
"");
3253 error |= irplib_sdp_spectrum_add_column(
3254 spectrum, GIALIAS_COLUMN_SNR, CPL_TYPE_DOUBLE,
3255 GIALIAS_COLUMN_SNR_UNIT, NULL, GIALIAS_COLUMN_SNR_TUTYP,
3256 GIALIAS_COLUMN_SNR_TUCD, NULL);
3257 error |= irplib_sdp_spectrum_set_column_tcomm(
3258 spectrum, GIALIAS_COLUMN_SNR, GIALIAS_COLUMN_SNR_TCOMM);
3259 cpl_error_ensure(! error, cpl_error_get_code(),
goto cleanup,
3260 "Could not setup the SDP spectrum columns.");
3263 GIALIAS_COLUMN_INDEX);
3267 GIALIAS_COLUMN_OBJECT);
3269 GIALIAS_COLUMN_TYPE);
3273 GIALIAS_COLUMN_DEC);
3275 GIALIAS_COLUMN_GCORR);
3277 GIALIAS_COLUMN_HCORR);
3279 GIALIAS_COLUMN_BCORR);
3280 cpl_error_ensure(indices != NULL && fps != NULL && objects != NULL
3281 && spectypes != NULL && ras != NULL && decs != NULL
3282 && gcorr != NULL && hcorr != NULL && bcorr != NULL,
3283 cpl_error_get_code(),
goto cleanup,
3284 "Could not fetch data from the fiber setup table in '%s'.",
3287 formatstr = _giraffe_calc_format_string(
3293 const double* wave_data;
3299 const char* remregexp =
"^(CDELT[0-9]+|CD[0-9]+_[0-9]+|CRPIX[0-9]+"
3300 "|CRDER[0-9]+|CSYER[0-9]+|BUNIT|BSCALE|BZERO"
3302 cpl_size specindex = indices[i];
3303 double vela, velb, beta;
3304 double correction_factor = 1.0;
3307 if (strcmp(spectypes[i],
"M") != 0)
continue;
3309 filename = cpl_sprintf(formatstr, ++filecount);
3314 vela = gcorr[i] * 1e3;
3315 velb = hcorr[i] * 1e3;
3316 beta = (vela + velb) / CPL_PHYS_C;
3317 cpl_error_ensure(-1 <= beta && beta <= 1,
3318 CPL_ERROR_ILLEGAL_OUTPUT,
goto cleanup,
3319 "The velocities GCORR = %g and HCORR = %g for spectrum"
3320 "%"CPL_SIZE_FORMAT
" in file '%s' give invalid"
3321 " Heliocentric correction factor values.",
3322 gcorr[i], hcorr[i], specindex, flux_filename);
3323 correction_factor = sqrt((1.0 + beta) / (1.0 - beta));
3327 wave_data = cpl_array_get_data_double_const(refwavearray);
3328 if (wavecoltype == CPL_TYPE_FLOAT) {
3329 data_float = cpl_malloc(ny *
sizeof(
float));
3330 for (j = 0; j < ny; ++j) {
3331 data_float[j] = wave_data[j] * correction_factor;
3333 array = cpl_array_wrap_float(data_float, ny);
3335 data_double = cpl_malloc(ny *
sizeof(
double));
3336 for (j = 0; j < ny; ++j) {
3337 data_double[j] = wave_data[j] * correction_factor;
3339 array = cpl_array_wrap_double(data_double, ny);
3341 error |= irplib_sdp_spectrum_set_column_data(
3342 spectrum, GIALIAS_COLUMN_WAVE, array);
3343 cpl_array_unwrap(array);
3346 fluximgcol = cpl_vector_new_from_image_column(
3348 flux_data = cpl_vector_get_data(fluximgcol);
3349 cpl_error_ensure(flux_data != NULL, cpl_error_get_code(),
goto cleanup,
3350 "Unable to extract data in column %"CPL_SIZE_FORMAT
3351 " from image in file '%s'.", specindex, flux_filename);
3352 array = cpl_array_wrap_double(flux_data, ny);
3353 error |= irplib_sdp_spectrum_set_column_data(
3354 spectrum, GIALIAS_COLUMN_FLUX_REDUCED, array);
3355 cpl_array_unwrap(array);
3358 errimgcol = cpl_vector_new_from_image_column(
3360 err_data = cpl_vector_get_data(errimgcol);
3361 cpl_error_ensure(err_data != NULL, cpl_error_get_code(),
goto cleanup,
3362 "Unable to extract data in column %"CPL_SIZE_FORMAT
3363 " from image in file '%s'.", specindex, err_filename);
3364 array = cpl_array_wrap_double(err_data, ny);
3365 error |= irplib_sdp_spectrum_set_column_data(
3366 spectrum, GIALIAS_COLUMN_ERR_REDUCED, array);
3367 cpl_array_unwrap(array);
3370 data_double = cpl_malloc(ny *
sizeof(
double));
3371 for (j = 0; j < ny; ++j) {
3372 data_double[j] = (err_data[j] != 0.0) ? flux_data[j] / err_data[j]
3375 array = cpl_array_wrap_double(data_double, ny);
3376 snr = cpl_array_get_median(array);
3377 error |= irplib_sdp_spectrum_set_column_data(spectrum,
3378 GIALIAS_COLUMN_SNR, array);
3379 cpl_array_unwrap(array);
3381 cpl_free(data_double);
3384 cpl_vector_delete(fluximgcol);
3386 cpl_vector_delete(errimgcol);
3389 cpl_error_ensure(! error, cpl_error_get_code(),
goto cleanup,
3390 "Could not setup the SDP spectrum columns for '%s'.",
3393 error |= irplib_sdp_spectrum_set_object(spectrum, objects[i]);
3394 error |= irplib_sdp_spectrum_set_title(spectrum, objects[i]);
3395 error |= irplib_sdp_spectrum_set_ra(spectrum, ras[i]);
3396 error |= irplib_sdp_spectrum_set_dec(spectrum, decs[i]);
3397 error |= irplib_sdp_spectrum_set_snr(spectrum, snr);
3398 error |= irplib_sdp_spectrum_set_column_tcomm(
3399 spectrum, GIALIAS_COLUMN_FLUX_REDUCED, flux_filename);
3400 error |= irplib_sdp_spectrum_set_column_tcomm(
3401 spectrum, GIALIAS_COLUMN_ERR_REDUCED, err_filename);
3403 error |= cpl_propertylist_update_int(extrakeys, GIALIAS_FPS, fps[i]);
3404 error |= cpl_propertylist_update_double(extrakeys, GIALIAS_GEOCORR,
3406 error |= cpl_propertylist_update_double(extrakeys, GIALIAS_HELICORR,
3408 error |= cpl_propertylist_update_double(extrakeys, GIALIAS_BARYCORR,
3412 error |= irplib_sdp_spectrum_set_wavelmin(spectrum,
3413 wavelmin * correction_factor);
3414 error |= irplib_sdp_spectrum_set_wavelmax(spectrum,
3415 wavelmax * correction_factor);
3416 error |= irplib_sdp_spectrum_set_specval(spectrum,
3417 (wavelmax + wavelmin) * 0.5 * correction_factor);
3418 error |= irplib_sdp_spectrum_set_specbw(spectrum,
3419 (wavelmax - wavelmin) * correction_factor);
3420 error |= irplib_sdp_spectrum_set_tdmin(spectrum,
3421 wavelmin * correction_factor);
3422 error |= irplib_sdp_spectrum_set_tdmax(spectrum,
3423 wavelmax * correction_factor);
3424 error |= irplib_sdp_spectrum_set_specbin(spectrum,
3425 specbin * correction_factor);
3426 if (! isnan(lamrms)) {
3427 error |= irplib_sdp_spectrum_set_lamrms(spectrum,
3428 lamrms * correction_factor);
3430 if (! isnan(specerr)) {
3431 error |= irplib_sdp_spectrum_set_specerr(spectrum,
3432 specerr * correction_factor);
3434 if (! isnan(specsye)) {
3435 error |= irplib_sdp_spectrum_set_specsye(spectrum,
3436 specsye * correction_factor);
3439 cpl_error_ensure(! error, cpl_error_get_code(),
goto cleanup,
3440 "Could not setup the SDP spectrum keywords for '%s'.",
3443 error |= irplib_dfs_save_spectrum(allframes, NULL, parlist, usedframes,
3444 inherit, spectrum, recipe_id,
3445 extrakeys, tablekeys, remregexp,
3446 pipe_id, dict_id, filename);
3447 cpl_error_ensure(! error, cpl_error_get_code(),
goto cleanup,
3448 "Failed to save SDP spectrum %"CPL_SIZE_FORMAT
3449 " to file '%s'.", specindex, filename);
3451 error |= irplib_fits_update_checksums(filename);
3452 cpl_error_ensure(! error, cpl_error_get_code(),
goto cleanup,
3453 "Failed to save update checksums for file '%s'.",
3459 if (filecount == 0) {
3460 cpl_msg_warning(cpl_func,
"No science spectra found in '%s'."
3461 " No SDP spectra created.", flux_filename);
3469 cpl_vector_delete(fluximgcol);
3470 cpl_vector_delete(errimgcol);
3471 cpl_array_unwrap(array);
3472 cpl_array_delete(refwavearray);
3473 cpl_free(data_float);
3474 cpl_free(data_double);
3476 cpl_free(formatstr);
3477 cpl_frameset_delete(usedframes);
3478 cpl_frameset_delete(rawframes);
3479 cpl_frameset_iterator_delete(iterator);
3481 cpl_propertylist_delete(tablekeys);
3482 cpl_propertylist_delete(extrakeys);
3486 irplib_sdp_spectrum_delete(spectrum);
cpl_frame * giraffe_get_slitgeometry(const cpl_frameset *set)
Get the slit geometry frame from a frame set.
cxint giraffe_image_add_info(GiImage *image, const GiRecipeInfo *info, const cpl_frameset *set)
Add additional frame information to an image.
GiFieldOfView * giraffe_fov_new(void)
Create an empty container for the results of the field of view reconstruction.
GiInstrumentMode giraffe_get_mode(cpl_propertylist *properties)
Determines the instrument mode from a property list.
void giraffe_fov_delete(GiFieldOfView *self)
Deallocate a field of view object and its contents.
cxint giraffe_add_frameset_info(cpl_propertylist *plist, const cpl_frameset *set, cxint sequence)
Add frameset specific information to a property list.
void giraffe_fov_config_add(cpl_parameterlist *list)
Adds parameters for the image and data cube construction.
void giraffe_rebin_config_add(cpl_parameterlist *list)
Adds parameters for the rebinning.
GiFieldOfViewConfig * giraffe_fov_config_create(cpl_parameterlist *list)
Creates a setup structure for the field of view reconstruction.
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.
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.
cpl_table * giraffe_table_get(const GiTable *self)
Get the table data from a Giraffe table.
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.
void giraffe_flat_config_add(cpl_parameterlist *list)
Adds parameters for the flat field correction.
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.
void giraffe_table_delete(GiTable *self)
Destroys a Giraffe table.
GiRebinConfig * giraffe_rebin_config_create(cpl_parameterlist *list)
Creates a setup structure for the rebinning.
GiTable * giraffe_table_new(void)
Creates a new, empty Giraffe table.
void giraffe_sgcalibration_config_destroy(GiSGCalConfig *config)
Destroys a sgcalibration field setup structure.
GiSGCalConfig * giraffe_sgcalibration_config_create(cpl_parameterlist *list)
Creates a setup structure for the slit geometry calibration.
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_image_save(GiImage *self, const cxchar *filename)
Write a Giraffe image to a file.
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.
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.
cxint giraffe_fiberlist_attach(cpl_frame *frame, GiTable *fibers)
Attach a fiber table to a frame.
GiTable * giraffe_table_duplicate(const GiTable *src)
Duplicate a Giraffe table.
GiBiasConfig * giraffe_bias_config_create(cpl_parameterlist *list)
Creates a setup structure for a bias removal task.
void giraffe_image_delete(GiImage *self)
Destroys an image.
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_add_rvcorrection(GiTable *fibers, const GiImage *spectra)
Add the barycentric and heliocentric corrections to the given fiber setup.
GiImage * giraffe_image_new(cpl_type type)
Creates an empty image container.
void giraffe_flat_config_destroy(GiFlatConfig *config)
Destroys a flat field setup structure.
GiTable * giraffe_fibers_setup(const cpl_frame *frame, const cpl_frame *reference)
Setup a fiber list.
void giraffe_rebinning_destroy(GiRebinning *rebinning)
Destroys a rebinning results container and its contents.
void giraffe_bias_config_add(cpl_parameterlist *list)
Adds parameters for the bias removal.
GiImage * giraffe_image_create(cpl_type type, cxint nx, cxint ny)
Creates an image container of a given type.
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.
GiFlatConfig * giraffe_flat_config_create(cpl_parameterlist *list)
Creates a setup structure for the flat field correction.
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.
const cxchar * giraffe_get_license(void)
Get the pipeline copyright and license.
cpl_image * giraffe_image_get(const GiImage *self)
Gets the image data.
GiRebinning * giraffe_rebinning_new(void)
Create an empty rebinning results container.
void giraffe_sgcalibration_config_add(cpl_parameterlist *list)
Adds parameters for the sgcalibration correction computation.
Slit geometry calibration configuration data structure.
cxint giraffe_image_set_properties(GiImage *self, cpl_propertylist *properties)
Attaches a property list to an image.
cpl_frame * giraffe_frame_create_image(GiImage *image, const cxchar *tag, cpl_frame_level level, cxbool save, cxbool update)
Create an image product frame.
cxint giraffe_fiberlist_compare(const GiTable *fibers, const GiTable *reference)
Compare two fiber lists.
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_fiberlist_load(const cxchar *filename, cxint dataset, const cxchar *tag)
Load a fiber table from a file.
cpl_propertylist * giraffe_image_get_properties(const GiImage *self)
Get the properties of an image.
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_fov_config_destroy(GiFieldOfViewConfig *config)
Destroys a field of view setup structure.