27#include <cxstrutils.h>
29#include <cxmessages.h>
32#include <cpl_propertylist.h>
37#include "gimessages.h"
40#include "gifiberutils.h"
56_giraffe_fov_create_cube(
const GiImage* spectra,
57 const cpl_table* fibers,
58 const GiRange* limits)
80 if ((properties == NULL) || (_spectra == NULL)) {
89 if (cpl_propertylist_has(properties, GIALIAS_BINWLMIN) == FALSE) {
93 wmin = cpl_propertylist_get_double(properties, GIALIAS_BINWLMIN);
96 if (cpl_propertylist_has(properties, GIALIAS_BINWLMAX) == FALSE) {
100 wmax = cpl_propertylist_get_double(properties, GIALIAS_BINWLMAX);
103 if (cpl_propertylist_has(properties, GIALIAS_BINSTEP) == FALSE) {
107 wstep = cpl_propertylist_get_double(properties, GIALIAS_BINSTEP);
116 last = cpl_image_get_size_y(_spectra) - 1;
118 if (limits != NULL) {
147 giraffe_error_push();
149 nx = (cxint) cpl_table_get_column_max(fibers,
"X");
150 ny = (cxint) cpl_table_get_column_max(fibers,
"Y");
152 if (cpl_error_get_code() == CPL_ERROR_DATA_NOT_FOUND) {
159 nz = last - first + 1;
178 register cxint i = 0;
179 register cxint nf = cpl_table_get_nrow(fibers);
181 cxint ns = cpl_image_get_size_x(_spectra);
183 cxdouble* spixels = cpl_image_get_data_double(_spectra);
187 cx_assert(spixels != NULL);
188 cx_assert(cpixels != NULL);
191 for (i = 0; i < nf; ++i) {
193 register cxint j = 0;
195 cxint idx = cpl_table_get_int(fibers,
"INDEX", i, NULL) - 1;
196 cxint x = cpl_table_get_int(fibers,
"X", i, NULL) - 1;
197 cxint y = cpl_table_get_int(fibers,
"Y", i, NULL) - 1;
205 if ((x >= 0) && (y >= 0)) {
207 for (j = 0; j < nz; ++j) {
208 cpixels[(ny * j + y) * nx + x] =
209 spixels[(first + j) * ns + idx];
227inline static cpl_image*
228_giraffe_fov_arrange_images(
const cx_slist* subimages,
229 cxsize nrows, cxsize ncolumns, cxint offset)
238 cxint xshift = offset;
239 cxint yshift = offset;
244 cx_slist_iterator pos;
246 cpl_image* image = NULL;
249 cx_assert(subimages != NULL);
250 cx_assert(nrows > 0);
251 cx_assert(ncolumns > 0);
260 pos = cx_slist_begin(subimages);
262 while (pos != cx_slist_end(subimages)) {
264 const cpl_image* simage = cx_slist_get(subimages, pos);
266 if (simage != NULL) {
268 cxint _nx = cpl_image_get_size_x(simage);
269 cxint _ny = cpl_image_get_size_y(simage);
271 sx = CX_MAX(nx, _nx);
272 sy = CX_MAX(ny, _ny);
276 pos = cx_slist_next(subimages, pos);
285 nslit = cx_slist_size(subimages);
286 nrows = CX_MAX(nslit / ncolumns, nrows);
288 if (nslit % ncolumns != 0) {
302 xshift = nx / -offset + 1;
303 yshift = ny / -offset + 1;
306 nx += ncolumns * xshift - (xshift % 2);
307 ny += nrows * yshift - (yshift % 2);
314 image = cpl_image_new(nx, ny, CPL_TYPE_DOUBLE);
319 pos = cx_slist_begin(subimages);
321 while (pos != cx_slist_end(subimages)) {
323 const cpl_image* simage = cx_slist_get(subimages, pos);
325 if (simage != NULL) {
327 cpl_error_code status = cpl_image_copy(image, simage,
330 if (status != CPL_ERROR_NONE) {
331 cpl_image_delete(image);
339 if (column < ncolumns) {
349 pos = cx_slist_next(subimages, pos);
358inline static cpl_image*
359_giraffe_fov_integrate_cube(
const GiCube* cube,
const GiRange* limits)
370 cpl_image* image = NULL;
373 cx_assert(cube != NULL);
378 wmax = wmin + depth * wstep;
419 GiTable* fibers, GiTable* wsolution,
420 GiTable* grating, GiTable* slitgeometry,
421 GiFieldOfViewConfig* config)
424 const cxchar*
const fctid =
"giraffe_fov_build";
426 cxbool log_scale = FALSE;
428 cx_slist* simages = NULL;
429 cx_slist* eimages = NULL;
430 cx_slist* scubes = NULL;
431 cx_slist* ecubes = NULL;
433 cpl_propertylist* properties = NULL;
435 cpl_array* ssn = NULL;
437 cpl_image* fov = NULL;
439 cpl_table* _fibers = NULL;
441 GiInstrumentMode mode;
443 GiRange* limits = NULL;
446 if (result == NULL) {
447 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
460 if (rebinning == NULL) {
461 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
465 if (rebinning->spectra == NULL || rebinning->errors == NULL) {
466 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
470 if (fibers == NULL) {
471 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
477 if (_fibers == NULL) {
478 cpl_error_set(fctid, CPL_ERROR_DATA_NOT_FOUND);
482 if (!cpl_table_has_column(_fibers,
"X") ||
483 !cpl_table_has_column(_fibers,
"Y")) {
484 cpl_error_set(fctid, CPL_ERROR_DATA_NOT_FOUND);
488 if (config == NULL) {
489 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
503 if (properties == NULL) {
504 cpl_error_set(fctid, CPL_ERROR_DATA_NOT_FOUND);
519 grating, slitgeometry, TRUE);
521 if (limits == NULL) {
522 cpl_msg_error(fctid,
"Computation of spectra common wavelength "
527 if (config->minimum > 0.) {
529 cpl_msg_warning(fctid,
"Ignoring invalid wavelength range "
530 "minimum %.3f nm", config->minimum);
537 if (config->maximum > 0.) {
539 cpl_msg_warning(fctid,
"Ignoring invalid wavelength range "
540 "maximum %.3f nm", config->maximum);
547 cpl_msg_info(fctid,
"Building image for wavelength range [%.3f nm, "
556 if (cpl_propertylist_has(properties, GIALIAS_BINSCALE)) {
558 const cxchar* s = cpl_propertylist_get_string(properties,
561 if (cx_strncasecmp(s,
"log", 3) == 0) {
569 cpl_msg_warning(fctid,
"Could not determine spectrum wavelength "
570 "scaling method. Missing property `%s'. Assuming "
571 "scaling method `linear'!", GIALIAS_BINSCALE);
580 simages = cx_slist_new();
581 eimages = cx_slist_new();
582 scubes = cx_slist_new();
583 ecubes = cx_slist_new();
592 cpl_array* _ssn = NULL;
594 cpl_image* smosaic = NULL;
595 cpl_image* emosaic = NULL;
597 GiImage* variance = NULL;
607 cx_slist_destroy(simages, (cx_free_func)cpl_image_delete);
610 cx_slist_destroy(eimages, (cx_free_func)cpl_image_delete);
622 cpl_msg_error(fctid,
"Sub-slit data missing in fiber table!");
634 if (variance == NULL) {
635 cpl_array_delete(ssn);
638 cx_slist_destroy(simages, (cx_free_func)cpl_image_delete);
641 cx_slist_destroy(eimages, (cx_free_func)cpl_image_delete);
653 cpl_msg_error(fctid,
"Failed to create variance map!");
665 _ssn = cpl_array_duplicate(ssn);
667 for (i = 0; i < cpl_array_get_size(_ssn); ++i) {
669 cxbool failed = FALSE;
671 cxint nss = cpl_array_get_int(_ssn, i, NULL);
673 cpl_table* ssf = NULL;
675 cpl_table_unselect_all(_fibers);
676 cpl_table_or_selected_int(_fibers,
"SSN", CPL_EQUAL_TO, nss);
683 cpl_table_and_selected_int(_fibers,
"X", CPL_GREATER_THAN, 0);
684 cpl_table_and_selected_int(_fibers,
"Y", CPL_GREATER_THAN, 0);
686 ssf = cpl_table_extract_selected(_fibers);
688 if ((ssf != NULL) && (cpl_table_get_nrow(ssf) > 0)) {
690 cpl_matrix* transform = NULL;
692 cpl_propertylist* wcs = NULL;
694 cpl_image* _simage = NULL;
695 cpl_image* _eimage = NULL;
697 GiCube* _scube = NULL;
698 GiCube* _ecube = NULL;
701 _scube = _giraffe_fov_create_cube(rebinning->spectra,
708 if (_scube != NULL) {
714 cpl_table_get_double(ssf,
"RA", 0, NULL);
716 cpl_table_get_double(ssf,
"DEC", 0, NULL);
717 cxdouble orientation =
718 cpl_table_get_double(ssf,
"ORIENT", 0, NULL);
720 cxdouble zvalue = 0.;
722 cxdouble angle = GI_IFU_POSANG_OFFSET - orientation;
723 cxdouble pixscale = GI_IFU_PIXSCALE / 3600.;
726 transform = cpl_matrix_new(3, 3);
728 wcs = cpl_propertylist_new();
730 cpl_propertylist_update_double(wcs,
"XORIGIN", xorigin);
731 cpl_propertylist_update_double(wcs,
"YORIGIN", yorigin);
732 cpl_propertylist_update_double(wcs,
"ZORIGIN", 1.);
736 cpl_propertylist_update_double(wcs,
"XPOINT", xvalue);
737 cpl_propertylist_update_double(wcs,
"YPOINT", yvalue);
738 cpl_propertylist_update_double(wcs,
"ZPOINT", zvalue);
740 cpl_propertylist_update_string(wcs,
"XTYPE",
742 cpl_propertylist_update_string(wcs,
"YTYPE",
745 if (log_scale == TRUE) {
746 cpl_propertylist_update_string(wcs,
747 "ZTYPE",
"AWAV-LOG");
750 cpl_propertylist_update_string(wcs,
754 cpl_propertylist_update_string(wcs,
"XUNIT",
"deg");
755 cpl_propertylist_update_string(wcs,
"YUNIT",
"deg");
756 cpl_propertylist_update_string(wcs,
"ZUNIT",
"nm");
765 angle *= CX_PI / 180.;
767 cpl_matrix_set(transform, 0, 0, -pixscale * cos(angle));
768 cpl_matrix_set(transform, 0, 1, pixscale * -sin(angle));
769 cpl_matrix_set(transform, 1, 0, -pixscale * sin(angle));
770 cpl_matrix_set(transform, 1, 1, pixscale * cos(angle));
771 cpl_matrix_set(transform, 2, 2, zstep);
775 if (_scube != NULL) {
776 _simage = _giraffe_fov_integrate_cube(_scube, limits);
779 if ((_scube == NULL) || (_simage == NULL)) {
781 cpl_image_delete(_simage);
789 cpl_msg_error(fctid,
"Cannot create data cube for "
795 cx_slist_push_back(scubes, _scube);
796 cx_slist_push_back(simages, _simage);
801 _ecube = _giraffe_fov_create_cube(variance,
804 if (_ecube != NULL) {
805 _eimage = _giraffe_fov_integrate_cube(_ecube,
809 if ((_ecube == NULL) || (_eimage == NULL)) {
811 cpl_image_delete(_eimage);
819 cpl_msg_error(fctid,
"Cannot create error "
820 "cube for sub-slit %d", nss);
824 cpl_image_power(_eimage, 0.5);
828 cx_slist_push_back(ecubes, _ecube);
829 cx_slist_push_back(eimages, _eimage);
834 cpl_propertylist_delete(wcs);
837 cpl_matrix_delete(transform);
842 cpl_table_delete(ssf);
848 cpl_array_delete(_ssn);
851 cpl_array_delete(ssn);
854 cx_slist_destroy(simages,
855 (cx_free_func)cpl_image_delete);
858 cx_slist_destroy(eimages,
859 (cx_free_func)cpl_image_delete);
862 cx_slist_destroy(scubes,
866 cx_slist_destroy(ecubes,
881 cpl_msg_debug(fctid,
"Unused IFU button detected. "
882 "Skipping sub-slit %d", nss);
884 cpl_array_set_invalid(_ssn, i);
886 cx_slist_push_back(simages, NULL);
887 cx_slist_push_back(eimages, NULL);
891 cpl_table_delete(ssf);
901 if (cpl_array_count_invalid(_ssn) > 0) {
906 cpl_array_set_size(ssn, cpl_array_get_size(ssn) -
907 cpl_array_count_invalid(_ssn));
909 for (k = 0; k < cpl_array_get_size(_ssn); ++k) {
913 register cxint idx = cpl_array_get_int(_ssn, k, &invalid);
916 cpl_array_set_int(ssn, j, idx);
924 cpl_array_delete(_ssn);
938 smosaic = _giraffe_fov_arrange_images(simages, 5, 3, -4);
939 emosaic = _giraffe_fov_arrange_images(eimages, 5, 3, -4);
941 if ((smosaic == NULL) || (emosaic == NULL)) {
943 cpl_image_delete(smosaic);
946 cpl_image_delete(emosaic);
949 cx_slist_destroy(simages, (cx_free_func)cpl_image_delete);
952 cx_slist_destroy(eimages, (cx_free_func)cpl_image_delete);
961 cpl_array_delete(ssn);
971 cx_slist_push_front(simages, smosaic);
972 cx_slist_push_front(eimages, emosaic);
979 cxbool failed = FALSE;
981 cpl_image* simage = NULL;
982 cpl_image* eimage = NULL;
984 cpl_matrix* transform = NULL;
986 cpl_propertylist* wcs = NULL;
988 GiImage* variance = NULL;
990 GiCube* scube = NULL;
991 GiCube* ecube = NULL;
1000 if (variance == NULL) {
1002 cx_slist_destroy(simages, (cx_free_func)cpl_image_delete);
1005 cx_slist_destroy(eimages, (cx_free_func)cpl_image_delete);
1017 cpl_msg_error(fctid,
"Failed to create variance map!");
1029 scube = _giraffe_fov_create_cube(rebinning->spectra,
1050 if (scube != NULL) {
1055 cxdouble xvalue = cpl_propertylist_get_double(properties,
1057 cxdouble yvalue = cpl_propertylist_get_double(properties,
1059 cxdouble zvalue = 0.;
1060 cxdouble zstep = 0.;
1061 cxdouble angle = -90. -
1062 (cpl_propertylist_get_double(properties,
1064 GI_ARGUS_POSANG_OFFSET);
1066 cxdouble pixscale = GI_ARGUS_PIXSCALE_LOW;
1068 const cxchar* scale =
1069 cpl_propertylist_get_string(properties,
1070 GIALIAS_ARGUS_SCALE);
1073 if ((scale != NULL) && (strcmp(scale,
"POS_1_67") == 0)) {
1074 pixscale = GI_ARGUS_PIXSCALE_HIGH;
1082 transform = cpl_matrix_new(3, 3);
1084 wcs = cpl_propertylist_new();
1086 cpl_propertylist_update_double(wcs,
"XORIGIN", xorigin);
1087 cpl_propertylist_update_double(wcs,
"YORIGIN", yorigin);
1088 cpl_propertylist_update_double(wcs,
"ZORIGIN", 1.);
1092 cpl_propertylist_update_double(wcs,
"XPOINT", xvalue);
1093 cpl_propertylist_update_double(wcs,
"YPOINT", yvalue);
1094 cpl_propertylist_update_double(wcs,
"ZPOINT", zvalue);
1096 cpl_propertylist_update_string(wcs,
"XTYPE",
"RA---TAN");
1097 cpl_propertylist_update_string(wcs,
"YTYPE",
"DEC--TAN");
1099 if (log_scale == TRUE) {
1100 cpl_propertylist_update_string(wcs,
1101 "ZTYPE",
"AWAV-LOG");
1104 cpl_propertylist_update_string(wcs,
1108 cpl_propertylist_update_string(wcs,
"XUNIT",
"deg");
1109 cpl_propertylist_update_string(wcs,
"YUNIT",
"deg");
1110 cpl_propertylist_update_string(wcs,
"ZUNIT",
"nm");
1119 angle *= CX_PI / 180.;
1121 cpl_matrix_set(transform, 0, 0, -pixscale * cos(angle));
1122 cpl_matrix_set(transform, 0, 1, pixscale * -sin(angle));
1123 cpl_matrix_set(transform, 1, 0, -pixscale * sin(angle));
1124 cpl_matrix_set(transform, 1, 1, pixscale * cos(angle));
1125 cpl_matrix_set(transform, 2, 2, zstep);
1130 if (scube != NULL) {
1131 simage = _giraffe_fov_integrate_cube(scube, limits);
1134 if ((scube == NULL) || (simage == NULL)) {
1136 cpl_image_delete(simage);
1144 cpl_msg_error(fctid,
"Cannot create data cube!");
1151 cx_slist_push_back(scubes, scube);
1152 cx_slist_push_back(simages, simage);
1159 ecube = _giraffe_fov_create_cube(variance, _fibers, NULL);
1160 eimage = _giraffe_fov_integrate_cube(ecube, limits);
1162 if ((ecube == NULL) || (eimage == NULL)) {
1164 cpl_image_delete(eimage);
1172 cpl_msg_error(fctid,
"Cannot create error cube!");
1178 cpl_image_power(eimage, 0.5);
1182 cx_slist_push_back(ecubes, ecube);
1183 cx_slist_push_back(eimages, eimage);
1189 cpl_propertylist_delete(wcs);
1192 cpl_matrix_delete(transform);
1200 cx_slist_destroy(simages, (cx_free_func)cpl_image_delete);
1203 cx_slist_destroy(eimages, (cx_free_func)cpl_image_delete);
1232 result->mode = mode;
1237 fov = cx_slist_pop_front(simages);
1247 giraffe_propertylist_update_wcs(properties, 0, NULL, NULL, NULL,
1250 cpl_propertylist_update_double(properties, GIALIAS_FOV_BANDMIN,
1252 cpl_propertylist_set_comment(properties, GIALIAS_FOV_BANDMIN,
1253 "Minimum wavelength of FOV band");
1255 cpl_propertylist_update_double(properties, GIALIAS_FOV_BANDMAX,
1257 cpl_propertylist_set_comment(properties, GIALIAS_FOV_BANDMAX,
1258 "Maximum wavelength of FOV band");
1260 cpl_image_delete(fov);
1265 fov = cx_slist_pop_front(eimages);
1275 giraffe_propertylist_update_wcs(properties, 0, NULL, NULL, NULL,
1277 cpl_propertylist_update_double(properties, GIALIAS_FOV_BANDMIN,
1279 cpl_propertylist_set_comment(properties, GIALIAS_FOV_BANDMIN,
1280 "Minimum wavelength of FOV band");
1282 cpl_propertylist_update_double(properties, GIALIAS_FOV_BANDMAX,
1284 cpl_propertylist_set_comment(properties, GIALIAS_FOV_BANDMAX,
1285 "Maximum wavelength of FOV band");
1287 cpl_image_delete(fov);
1290 if (!cx_slist_empty(simages)) {
1292 cx_slist_iterator pos = cx_slist_begin(simages);
1294 result->images.spectra = cx_slist_new();
1296 while (pos != cx_slist_end(simages)) {
1301 cx_slist_push_back(result->images.spectra, image);
1303 pos = cx_slist_next(simages, pos);
1308 if (!cx_slist_empty(eimages)) {
1310 cx_slist_iterator pos = cx_slist_begin(eimages);
1312 result->images.errors = cx_slist_new();
1314 while (pos != cx_slist_end(eimages)) {
1319 cx_slist_push_back(result->images.errors, image);
1321 pos = cx_slist_next(eimages, pos);
1326 if (config->cube == TRUE) {
1328 if (!cx_slist_empty(scubes)) {
1329 result->cubes.spectra = scubes;
1333 if (!cx_slist_empty(ecubes)) {
1334 result->cubes.errors = ecubes;
1348 cx_slist_destroy(simages, (cx_free_func)cpl_image_delete);
1351 cx_slist_destroy(eimages, (cx_free_func)cpl_image_delete);
1354 if (scubes != NULL) {
1359 if (ecubes != NULL) {
1385 GiFieldOfView* self = cx_malloc(
sizeof *self);
1387 self->mode = GIMODE_NONE;
1390 self->fov.spectra = NULL;
1391 self->fov.errors = NULL;
1393 self->images.spectra = NULL;
1394 self->images.errors = NULL;
1396 self->cubes.spectra = NULL;
1397 self->cubes.errors = NULL;
1422 if (self->cubes.errors != NULL) {
1423 cx_slist_destroy(self->cubes.errors,
1425 self->cubes.errors = NULL;
1428 if (self->cubes.spectra != NULL) {
1429 cx_slist_destroy(self->cubes.spectra,
1431 self->cubes.spectra = NULL;
1434 if (self->images.errors != NULL) {
1435 cx_slist_destroy(self->images.errors,
1437 self->images.errors = NULL;
1440 if (self->images.spectra != NULL) {
1441 cx_slist_destroy(self->images.spectra,
1443 self->images.spectra = NULL;
1446 if (self->fov.errors != NULL) {
1448 self->fov.errors = NULL;
1451 if (self->fov.spectra != NULL) {
1453 self->fov.spectra = NULL;
1456 if (self->ssn != NULL) {
1457 cpl_array_delete(self->ssn);
1461 self->mode = GIMODE_NONE;
1521 cpl_propertylist* properties,
1522 const cxchar* filename, cxptr data)
1526 cxint component = 0;
1528 cx_slist* cubes = NULL;
1531 if ((self == NULL) || (properties == NULL) || (filename == NULL)) {
1541 component = *((cxuint*)data);
1544 if (component == 0) {
1545 cubes = self->cubes.spectra;
1548 cubes = self->cubes.errors;
1551 if (cubes == NULL) {
1556 if (!cx_slist_empty(cubes)) {
1558 if (self->mode == GIMODE_ARGUS) {
1561 cxint iomode = CPL_IO_CREATE;
1563 GiCube* cube = cx_slist_front(cubes);
1576 cxint iomode = CPL_IO_CREATE;
1578 cx_slist_const_iterator pos = cx_slist_begin(cubes);
1580 cx_string* name = NULL;
1582 cpl_propertylist* xproperties = NULL;
1592 name = cx_string_new();
1593 xproperties = cpl_propertylist_new();
1595 iomode = CPL_IO_EXTEND;
1597 while (pos != cx_slist_end(cubes)) {
1599 cxint ssn = cpl_array_get_int(self->ssn, nss, NULL);
1601 GiCube* cube = cx_slist_get(cubes, pos);
1604 cx_string_sprintf(name,
"SSN%-d", ssn);
1605 cpl_propertylist_update_string(xproperties,
"EXTNAME",
1606 cx_string_get(name));
1613 cpl_propertylist_delete(xproperties);
1616 cx_string_delete(name);
1623 pos = cx_slist_next(cubes, pos);
1628 cpl_propertylist_delete(xproperties);
1631 cx_string_delete(name);
1664 cpl_propertylist* properties,
1665 const cxchar* filename, cxptr data)
1668 const cxchar* data_name =
"SPECTRA";
1669 const cxchar* error_name =
"ERRORS";
1670 const cxchar* link_names[2] = {
"SCIDATA",
"ERRDATA"};
1672 cx_slist* scubes = NULL;
1673 cx_slist* ecubes = NULL;
1681 if ((self == NULL) || (properties == NULL) || (filename == NULL)) {
1685 if (self->cubes.spectra == NULL) {
1689 if ((cpl_propertylist_has(properties, GIALIAS_EQUINOX) == FALSE) ||
1690 (cpl_propertylist_get_type(properties, GIALIAS_EQUINOX)
1691 != CPL_TYPE_DOUBLE)) {
1701 scubes = self->cubes.spectra;
1703 if (cx_slist_empty(scubes)) {
1707 if (self->cubes.errors != NULL) {
1709 ecubes = self->cubes.errors;
1711 if (cx_slist_size(scubes) != cx_slist_size(ecubes)) {
1718 if (self->mode == GIMODE_ARGUS) {
1721 cxint iomode = CPL_IO_CREATE;
1723 cxdouble equinox = cpl_propertylist_get_double(properties,
1726 cpl_propertylist* xproperties = NULL;
1728 GiCube* scube = cx_slist_front(scubes);
1738 iomode = CPL_IO_EXTEND;
1740 xproperties = cpl_propertylist_new();
1742 cpl_propertylist_update_string(xproperties, GIALIAS_EXTNAME, data_name);
1743 cpl_propertylist_set_comment(xproperties, GIALIAS_EXTNAME,
1744 "FITS Extension name");
1746 cpl_propertylist_update_string(xproperties,
"HDUCLASS",
"ESO");
1747 cpl_propertylist_set_comment(xproperties,
"HDUCLASS",
1748 "Conforms to ESO data cube conventions");
1750 cpl_propertylist_update_string(xproperties,
"HDUDOC",
"DICD");
1751 cpl_propertylist_set_comment(xproperties,
"HDUDOC",
1752 "Data format specification document");
1754 cpl_propertylist_update_string(xproperties,
"HDUVERS",
1756 cpl_propertylist_set_comment(xproperties,
"HDUVERS",
1757 "Specific version of the data format "
1760 cpl_propertylist_update_string(xproperties,
"HDUCLAS1",
"IMAGE");
1761 cpl_propertylist_set_comment(xproperties,
"HDUCLAS1",
1762 "Image data format");
1764 cpl_propertylist_update_string(xproperties,
"HDUCLAS2",
"DATA");
1765 cpl_propertylist_set_comment(xproperties,
"HDUCLAS2",
1766 "Science data extension");
1767 cpl_propertylist_update_string(xproperties, link_names[1], error_name);
1768 cpl_propertylist_set_comment(xproperties, link_names[1],
1769 "Linked error data extension");
1771 cpl_propertylist_update_double(xproperties, GIALIAS_EQUINOX,
1779 cpl_propertylist_delete(xproperties);
1786 cpl_propertylist_erase(xproperties, link_names[1]);
1787 cpl_propertylist_erase(xproperties,
"BUNIT");
1788 cpl_propertylist_erase(xproperties,
"DATAMIN");
1789 cpl_propertylist_erase(xproperties,
"DATAMAX");
1792 if (ecubes != NULL) {
1794 GiCube* ecube = cx_slist_front(ecubes);
1797 cpl_propertylist_update_string(xproperties,
"EXTNAME", error_name);
1799 cpl_propertylist_update_string(xproperties,
"HDUCLAS2",
"ERROR");
1800 cpl_propertylist_set_comment(xproperties,
"HDUCLAS2",
1801 "Error data extension");
1803 cpl_propertylist_update_string(xproperties,
"HDUCLAS3",
"RMSE");
1804 cpl_propertylist_set_comment(xproperties,
"HDUCLAS3",
1805 "Type of error: root mean squared");
1807 cpl_propertylist_update_string(xproperties, link_names[0],
1809 cpl_propertylist_set_comment(xproperties, link_names[0],
1810 "Linked science data extension");
1817 cpl_propertylist_delete(xproperties);
1826 cpl_propertylist_delete(xproperties);
1834 cxint iomode = CPL_IO_CREATE;
1836 cxdouble equinox = cpl_propertylist_get_double(properties,
1839 cx_slist_const_iterator spos = cx_slist_begin(scubes);
1840 cx_slist_const_iterator epos = cx_slist_begin(ecubes);
1842 cx_string* name = NULL;
1844 cpl_propertylist* xproperties = NULL;
1854 name = cx_string_new();
1855 xproperties = cpl_propertylist_new();
1857 iomode = CPL_IO_EXTEND;
1859 while (spos != cx_slist_end(scubes)) {
1861 cxint ssn = cpl_array_get_int(self->ssn, nss, NULL);
1863 GiCube* scube = cx_slist_get(scubes, spos);
1866 cx_string_sprintf(name,
"SSN%-d.%s", ssn, data_name);
1868 cpl_propertylist_update_string(xproperties, GIALIAS_EXTNAME,
1869 cx_string_get(name));
1870 cpl_propertylist_set_comment(xproperties, GIALIAS_EXTNAME,
1871 "FITS Extension name");
1873 cpl_propertylist_update_string(xproperties,
"HDUCLASS",
"ESO");
1874 cpl_propertylist_set_comment(xproperties,
"HDUCLASS",
1875 "Conforms to ESO data cube "
1878 cpl_propertylist_update_string(xproperties,
"HDUDOC",
"DICD");
1879 cpl_propertylist_set_comment(xproperties,
"HDUDOC",
1880 "Data format specification document");
1882 cpl_propertylist_update_string(xproperties,
"HDUVERS",
1884 cpl_propertylist_set_comment(xproperties,
"HDUVERS",
1885 "Specific version of the data format "
1888 cpl_propertylist_update_string(xproperties,
"HDUCLAS1",
"IMAGE");
1889 cpl_propertylist_set_comment(xproperties,
"HDUCLAS1",
1890 "Image data format");
1892 cpl_propertylist_update_string(xproperties,
"HDUCLAS2",
"DATA");
1893 cpl_propertylist_set_comment(xproperties,
"HDUCLAS2",
1894 "Science data extension");
1896 cx_string_sprintf(name,
"SSN%-d.%s", ssn, error_name);
1898 cpl_propertylist_update_string(xproperties, link_names[1],
1899 cx_string_get(name));
1900 cpl_propertylist_set_comment(xproperties, link_names[1],
1901 "Linked error data extension");
1903 cpl_propertylist_update_double(xproperties, GIALIAS_EQUINOX,
1911 cpl_propertylist_delete(xproperties);
1914 cx_string_delete(name);
1921 cpl_propertylist_erase(xproperties, link_names[1]);
1922 cpl_propertylist_erase(xproperties,
"BUNIT");
1923 cpl_propertylist_erase(xproperties,
"DATAMIN");
1924 cpl_propertylist_erase(xproperties,
"DATAMAX");
1927 if (ecubes != NULL) {
1929 GiCube* ecube = cx_slist_get(ecubes, epos);
1932 cx_string_sprintf(name,
"SSN%-d.%s", ssn, error_name);
1934 cpl_propertylist_update_string(xproperties,
"EXTNAME",
1935 cx_string_get(name));
1937 cpl_propertylist_update_string(xproperties,
"HDUCLAS2",
"ERROR");
1938 cpl_propertylist_set_comment(xproperties,
"HDUCLAS2",
1939 "Error data extension");
1941 cpl_propertylist_update_string(xproperties,
"HDUCLAS3",
"RMSE");
1942 cpl_propertylist_set_comment(xproperties,
"HDUCLAS3",
1943 "Type of error: root mean squared");
1945 cx_string_sprintf(name,
"SSN%-d.%s", ssn, data_name);
1947 cpl_propertylist_update_string(xproperties, link_names[0],
1948 cx_string_get(name));
1949 cpl_propertylist_set_comment(xproperties, link_names[0],
1950 "Linked science data extension");
1958 cpl_propertylist_delete(xproperties);
1961 cx_string_delete(name);
1968 epos = cx_slist_next(ecubes, epos);
1972 spos = cx_slist_next(scubes, spos);
1977 cpl_propertylist_delete(xproperties);
1980 cx_string_delete(name);
2005 const cxchar* s = NULL;
2009 GiFieldOfViewConfig* config = NULL;
2016 config = cx_calloc(1,
sizeof *config);
2019 p = cpl_parameterlist_find(list,
"giraffe.fov.range.minimum");
2020 config->minimum = cpl_parameter_get_double(p);
2022 p = cpl_parameterlist_find(list,
"giraffe.fov.range.maximum");
2023 config->maximum = cpl_parameter_get_double(p);
2025 p = cpl_parameterlist_find(list,
"giraffe.fov.cube");
2026 config->cube = cpl_parameter_get_bool(p);
2028 p = cpl_parameterlist_find(list,
"giraffe.fov.cube.format");
2029 s = cpl_parameter_get_string(p);
2031 if (strcmp(s,
"single") == 0) {
2032 config->format = GIFOV_FORMAT_SINGLE;
2034 else if (strcmp(s,
"eso3d") == 0) {
2035 config->format = GIFOV_FORMAT_ESO3D;
2060 if (config != NULL) {
2089 p = cpl_parameter_new_value(
"giraffe.fov.range.minimum",
2091 "Minimum wavelength for image reconstruction",
2092 "giraffe.fov.range",
2094 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"recon-min");
2095 cpl_parameterlist_append(list, p);
2098 p = cpl_parameter_new_value(
"giraffe.fov.range.maximum",
2100 "Maximum wavelength for image reconstruction",
2101 "giraffe.fov.range",
2103 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"recon-max");
2104 cpl_parameterlist_append(list, p);
2107 p = cpl_parameter_new_value(
"giraffe.fov.cube",
2109 "Turns data cube creation on and off",
2112 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"recon-cube");
2113 cpl_parameterlist_append(list, p);
2115 p = cpl_parameter_new_enum(
"giraffe.fov.cube.format",
2117 "Selects the file format for cubes",
2119 "single", 2,
"single",
"eso3d");
2120 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"recon-format");
2121 cpl_parameterlist_append(list, p);
cxsize giraffe_cube_get_width(const GiCube *self)
Get the width of the given data cube.
cxsize giraffe_cube_get_depth(const GiCube *self)
Get the depth of the given data cube.
cxint giraffe_cube_set_yaxis(GiCube *self, cxdouble start, cxdouble step)
Set the data cube's y-axis start value and step size.
cxint giraffe_cube_get_zaxis(const GiCube *self, cxdouble *start, cxdouble *step)
Get the data cube's z-axis start value and step size.
cxint giraffe_cube_set_wcs(GiCube *self, const cpl_propertylist *axes, const cpl_matrix *transformation)
Set the data cube's world coordinate system.
cpl_image * giraffe_cube_integrate(const GiCube *self, cxdouble start, cxdouble end)
Integrate a cube along the z-axis.
cxint giraffe_cube_set_zaxis(GiCube *self, cxdouble start, cxdouble step)
Set the data cube's z-axis start value and step size.
GiCube * giraffe_cube_create(cxsize width, cxsize height, cxsize depth, cxdouble *data)
Create a data cube with the given width, height and depth.
cxint giraffe_cube_set_xaxis(GiCube *self, cxdouble start, cxdouble step)
Set the data cube's x-axis start value and step size.
cxdouble * giraffe_cube_get_data(const GiCube *self)
Get a reference to the data cube's pixel buffer.
void giraffe_cube_delete(GiCube *self)
Destroys a cube object.
cxint giraffe_cube_save(const GiCube *self, cpl_propertylist *properties, const cxchar *filename, cxcptr data)
Save the given data cube to disk.
cxsize giraffe_cube_get_height(const GiCube *self)
Get the height of the given data cube.
cxint giraffe_cube_sqrt(GiCube *self)
Compute the square root of the elements of a cube.
cpl_array * giraffe_fiberlist_get_subslits(const cpl_table *fibers)
Get the list of subslit identifiers from a fiber setup.
GiFieldOfViewConfig * giraffe_fov_config_create(cpl_parameterlist *list)
Creates a setup structure for the field of view reconstruction.
void giraffe_fov_clear(GiFieldOfView *self)
Delete the contents of a field of view object.
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_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_duplicate(const GiImage *self)
Creates a copy of an image.
cxint giraffe_image_set(GiImage *self, cpl_image *image)
Sets the image data.
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.
void giraffe_range_set_min(GiRange *self, cxdouble min)
Set the minimum of a range.
void giraffe_range_delete(GiRange *self)
Destroys a range object.
cxdouble giraffe_range_get_min(const GiRange *const self)
Get the minimum of a range.
cxdouble giraffe_range_get_max(const GiRange *const self)
Get the maximum of a range.
void giraffe_range_set_max(GiRange *self, cxdouble max)
Set the maximum of a range.
GiRange * giraffe_rebin_get_wavelength_range(GiImage *spectra, GiTable *wlsolution, GiTable *grating, GiTable *slitgeometry, cxbool common)
Compute the wavelenght range of spectra.
cpl_table * giraffe_table_get(const GiTable *self)
Get the table data from a Giraffe table.
GiInstrumentMode giraffe_get_mode(cpl_propertylist *properties)
Determines the instrument mode from a property list.