27#include <cxstrutils.h>
29#include <cxmessages.h>
32#include <cpl_propertylist.h>
37#include "gimessages.h"
40#include "gifiberutils.h"
55_giraffe_compare_int(cxcptr first, cxcptr second)
58 cxint *_first = (cxint *)first;
59 cxint *_second = (cxint *)second;
61 return *_first - *_second;
67_giraffe_fov_create_cube(
const GiImage* spectra,
68 const cpl_table* fibers,
69 const GiRange* limits)
91 if ((properties == NULL) || (_spectra == NULL)) {
100 if (cpl_propertylist_has(properties, GIALIAS_BINWLMIN) == FALSE) {
104 wmin = cpl_propertylist_get_double(properties, GIALIAS_BINWLMIN);
107 if (cpl_propertylist_has(properties, GIALIAS_BINWLMAX) == FALSE) {
111 wmax = cpl_propertylist_get_double(properties, GIALIAS_BINWLMAX);
114 if (cpl_propertylist_has(properties, GIALIAS_BINSTEP) == FALSE) {
118 wstep = cpl_propertylist_get_double(properties, GIALIAS_BINSTEP);
127 last = cpl_image_get_size_y(_spectra) - 1;
129 if (limits != NULL) {
158 giraffe_error_push();
160 nx = (cxint) cpl_table_get_column_max(fibers,
"X");
161 ny = (cxint) cpl_table_get_column_max(fibers,
"Y");
163 if (cpl_error_get_code() == CPL_ERROR_DATA_NOT_FOUND) {
170 nz = last - first + 1;
189 register cxint i = 0;
190 register cxint nf = cpl_table_get_nrow(fibers);
192 cxint ns = cpl_image_get_size_x(_spectra);
194 cxdouble* spixels = cpl_image_get_data_double(_spectra);
198 cx_assert(spixels != NULL);
199 cx_assert(cpixels != NULL);
202 for (i = 0; i < nf; ++i) {
204 register cxint j = 0;
206 cxint idx = cpl_table_get_int(fibers,
"INDEX", i, NULL) - 1;
207 cxint x = cpl_table_get_int(fibers,
"X", i, NULL) - 1;
208 cxint y = cpl_table_get_int(fibers,
"Y", i, NULL) - 1;
216 if ((x >= 0) && (y >= 0)) {
218 for (j = 0; j < nz; ++j) {
219 cpixels[(ny * j + y) * nx + x] =
220 spixels[(first + j) * ns + idx];
238inline static cpl_image*
239_giraffe_fov_arrange_images(
const cx_slist* subimages,
240 cxsize nrows, cxsize ncolumns, cxint offset)
249 cxint xshift = offset;
250 cxint yshift = offset;
255 cx_slist_iterator pos;
257 cpl_image* image = NULL;
260 cx_assert(subimages != NULL);
261 cx_assert(nrows > 0);
262 cx_assert(ncolumns > 0);
271 pos = cx_slist_begin(subimages);
273 while (pos != cx_slist_end(subimages)) {
275 const cpl_image* simage = cx_slist_get(subimages, pos);
277 if (simage != NULL) {
279 cxint _nx = cpl_image_get_size_x(simage);
280 cxint _ny = cpl_image_get_size_y(simage);
282 sx = CX_MAX(nx, _nx);
283 sy = CX_MAX(ny, _ny);
287 pos = cx_slist_next(subimages, pos);
296 nslit = cx_slist_size(subimages);
297 nrows = CX_MAX(nslit / ncolumns, nrows);
299 if (nslit % ncolumns != 0) {
313 xshift = nx / -offset + 1;
314 yshift = ny / -offset + 1;
317 nx += ncolumns * xshift - (xshift % 2);
318 ny += nrows * yshift - (yshift % 2);
325 image = cpl_image_new(nx, ny, CPL_TYPE_DOUBLE);
330 pos = cx_slist_begin(subimages);
332 while (pos != cx_slist_end(subimages)) {
334 const cpl_image* simage = cx_slist_get(subimages, pos);
336 if (simage != NULL) {
338 cpl_error_code status = cpl_image_copy(image, simage,
341 if (status != CPL_ERROR_NONE) {
342 cpl_image_delete(image);
350 if (column < ncolumns) {
360 pos = cx_slist_next(subimages, pos);
369inline static cpl_image*
370_giraffe_fov_integrate_cube(
const GiCube* cube,
const GiRange* limits)
381 cpl_image* image = NULL;
384 cx_assert(cube != NULL);
389 wmax = wmin + depth * wstep;
430 GiTable* fibers, GiTable* wsolution,
431 GiTable* grating, GiTable* slitgeometry,
432 GiFieldOfViewConfig* config)
435 const cxchar*
const fctid =
"giraffe_fov_build";
437 cxbool log_scale = FALSE;
439 cx_slist* simages = NULL;
440 cx_slist* eimages = NULL;
441 cx_slist* scubes = NULL;
442 cx_slist* ecubes = NULL;
444 cpl_propertylist* properties = NULL;
446 cpl_array* ssn = NULL;
448 cpl_image* fov = NULL;
450 cpl_table* _fibers = NULL;
452 GiInstrumentMode mode;
454 GiRange* limits = NULL;
457 if (result == NULL) {
458 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
471 if (rebinning == NULL) {
472 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
476 if (rebinning->spectra == NULL || rebinning->errors == NULL) {
477 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
481 if (fibers == NULL) {
482 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
488 if (_fibers == NULL) {
489 cpl_error_set(fctid, CPL_ERROR_DATA_NOT_FOUND);
493 if (!cpl_table_has_column(_fibers,
"X") ||
494 !cpl_table_has_column(_fibers,
"Y")) {
495 cpl_error_set(fctid, CPL_ERROR_DATA_NOT_FOUND);
499 if (config == NULL) {
500 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
514 if (properties == NULL) {
515 cpl_error_set(fctid, CPL_ERROR_DATA_NOT_FOUND);
530 grating, slitgeometry, TRUE);
532 if (limits == NULL) {
533 cpl_msg_error(fctid,
"Computation of spectra common wavelength "
538 if (config->minimum > 0.) {
540 cpl_msg_warning(fctid,
"Ignoring invalid wavelength range "
541 "minimum %.3f nm", config->minimum);
548 if (config->maximum > 0.) {
550 cpl_msg_warning(fctid,
"Ignoring invalid wavelength range "
551 "maximum %.3f nm", config->maximum);
558 cpl_msg_info(fctid,
"Building image for wavelength range [%.3f nm, "
567 if (cpl_propertylist_has(properties, GIALIAS_BINSCALE)) {
569 const cxchar* s = cpl_propertylist_get_string(properties,
572 if (cx_strncasecmp(s,
"log", 3) == 0) {
580 cpl_msg_warning(fctid,
"Could not determine spectrum wavelength "
581 "scaling method. Missing property `%s'. Assuming "
582 "scaling method `linear'!", GIALIAS_BINSCALE);
591 simages = cx_slist_new();
592 eimages = cx_slist_new();
593 scubes = cx_slist_new();
594 ecubes = cx_slist_new();
603 cpl_array* _ssn = NULL;
605 cpl_image* smosaic = NULL;
606 cpl_image* emosaic = NULL;
608 GiImage* variance = NULL;
618 cx_slist_destroy(simages, (cx_free_func)cpl_image_delete);
621 cx_slist_destroy(eimages, (cx_free_func)cpl_image_delete);
633 cpl_msg_error(fctid,
"Sub-slit data missing in fiber table!");
645 if (variance == NULL) {
646 cpl_array_delete(ssn);
649 cx_slist_destroy(simages, (cx_free_func)cpl_image_delete);
652 cx_slist_destroy(eimages, (cx_free_func)cpl_image_delete);
664 cpl_msg_error(fctid,
"Failed to create variance map!");
676 _ssn = cpl_array_duplicate(ssn);
678 for (i = 0; i < cpl_array_get_size(_ssn); ++i) {
680 cxbool failed = FALSE;
682 cxint nss = cpl_array_get_int(_ssn, i, NULL);
684 cpl_table* ssf = NULL;
686 cpl_table_unselect_all(_fibers);
687 cpl_table_or_selected_int(_fibers,
"SSN", CPL_EQUAL_TO, nss);
694 cpl_table_and_selected_int(_fibers,
"X", CPL_GREATER_THAN, 0);
695 cpl_table_and_selected_int(_fibers,
"Y", CPL_GREATER_THAN, 0);
697 ssf = cpl_table_extract_selected(_fibers);
699 if ((ssf != NULL) && (cpl_table_get_nrow(ssf) > 0)) {
701 cpl_matrix* transform = NULL;
703 cpl_propertylist* wcs = NULL;
705 cpl_image* _simage = NULL;
706 cpl_image* _eimage = NULL;
708 GiCube* _scube = NULL;
709 GiCube* _ecube = NULL;
712 _scube = _giraffe_fov_create_cube(rebinning->spectra,
719 if (_scube != NULL) {
725 cpl_table_get_double(ssf,
"RA", 0, NULL);
727 cpl_table_get_double(ssf,
"DEC", 0, NULL);
728 cxdouble orientation =
729 cpl_table_get_double(ssf,
"ORIENT", 0, NULL);
731 cxdouble zvalue = 0.;
733 cxdouble angle = GI_IFU_POSANG_OFFSET - orientation;
734 cxdouble pixscale = GI_IFU_PIXSCALE / 3600.;
737 transform = cpl_matrix_new(3, 3);
739 wcs = cpl_propertylist_new();
741 cpl_propertylist_update_double(wcs,
"XORIGIN", xorigin);
742 cpl_propertylist_update_double(wcs,
"YORIGIN", yorigin);
743 cpl_propertylist_update_double(wcs,
"ZORIGIN", 1.);
747 cpl_propertylist_update_double(wcs,
"XPOINT", xvalue);
748 cpl_propertylist_update_double(wcs,
"YPOINT", yvalue);
749 cpl_propertylist_update_double(wcs,
"ZPOINT", zvalue);
751 cpl_propertylist_update_string(wcs,
"XTYPE",
753 cpl_propertylist_update_string(wcs,
"YTYPE",
756 if (log_scale == TRUE) {
757 cpl_propertylist_update_string(wcs,
758 "ZTYPE",
"AWAV-LOG");
761 cpl_propertylist_update_string(wcs,
765 cpl_propertylist_update_string(wcs,
"XUNIT",
"deg");
766 cpl_propertylist_update_string(wcs,
"YUNIT",
"deg");
767 cpl_propertylist_update_string(wcs,
"ZUNIT",
"nm");
776 angle *= CX_PI / 180.;
778 cpl_matrix_set(transform, 0, 0, -pixscale * cos(angle));
779 cpl_matrix_set(transform, 0, 1, pixscale * -sin(angle));
780 cpl_matrix_set(transform, 1, 0, -pixscale * sin(angle));
781 cpl_matrix_set(transform, 1, 1, pixscale * cos(angle));
782 cpl_matrix_set(transform, 2, 2, zstep);
786 if (_scube != NULL) {
787 _simage = _giraffe_fov_integrate_cube(_scube, limits);
790 if ((_scube == NULL) || (_simage == NULL)) {
792 cpl_image_delete(_simage);
800 cpl_msg_error(fctid,
"Cannot create data cube for "
806 cx_slist_push_back(scubes, _scube);
807 cx_slist_push_back(simages, _simage);
812 _ecube = _giraffe_fov_create_cube(variance,
815 if (_ecube != NULL) {
816 _eimage = _giraffe_fov_integrate_cube(_ecube,
820 if ((_ecube == NULL) || (_eimage == NULL)) {
822 cpl_image_delete(_eimage);
830 cpl_msg_error(fctid,
"Cannot create error "
831 "cube for sub-slit %d", nss);
835 cpl_image_power(_eimage, 0.5);
839 cx_slist_push_back(ecubes, _ecube);
840 cx_slist_push_back(eimages, _eimage);
845 cpl_propertylist_delete(wcs);
848 cpl_matrix_delete(transform);
853 cpl_table_delete(ssf);
859 cpl_array_delete(_ssn);
862 cpl_array_delete(ssn);
865 cx_slist_destroy(simages,
866 (cx_free_func)cpl_image_delete);
869 cx_slist_destroy(eimages,
870 (cx_free_func)cpl_image_delete);
873 cx_slist_destroy(scubes,
877 cx_slist_destroy(ecubes,
892 cpl_msg_debug(fctid,
"Unused IFU button detected. "
893 "Skipping sub-slit %d", nss);
895 cpl_array_set_invalid(_ssn, i);
897 cx_slist_push_back(simages, NULL);
898 cx_slist_push_back(eimages, NULL);
902 cpl_table_delete(ssf);
912 if (cpl_array_count_invalid(_ssn) > 0) {
917 cpl_array_set_size(ssn, cpl_array_get_size(ssn) -
918 cpl_array_count_invalid(_ssn));
920 for (k = 0; k < cpl_array_get_size(_ssn); ++k) {
924 register cxint idx = cpl_array_get_int(_ssn, k, &invalid);
927 cpl_array_set_int(ssn, j, idx);
935 cpl_array_delete(_ssn);
949 smosaic = _giraffe_fov_arrange_images(simages, 5, 3, -4);
950 emosaic = _giraffe_fov_arrange_images(eimages, 5, 3, -4);
952 if ((smosaic == NULL) || (emosaic == NULL)) {
954 cpl_image_delete(smosaic);
957 cpl_image_delete(emosaic);
960 cx_slist_destroy(simages, (cx_free_func)cpl_image_delete);
963 cx_slist_destroy(eimages, (cx_free_func)cpl_image_delete);
972 cpl_array_delete(ssn);
982 cx_slist_push_front(simages, smosaic);
983 cx_slist_push_front(eimages, emosaic);
990 cxbool failed = FALSE;
992 cpl_image* simage = NULL;
993 cpl_image* eimage = NULL;
995 cpl_matrix* transform = NULL;
997 cpl_propertylist* wcs = NULL;
999 GiImage* variance = NULL;
1001 GiCube* scube = NULL;
1002 GiCube* ecube = NULL;
1011 if (variance == NULL) {
1013 cx_slist_destroy(simages, (cx_free_func)cpl_image_delete);
1016 cx_slist_destroy(eimages, (cx_free_func)cpl_image_delete);
1028 cpl_msg_error(fctid,
"Failed to create variance map!");
1040 scube = _giraffe_fov_create_cube(rebinning->spectra,
1061 if (scube != NULL) {
1066 cxdouble xvalue = cpl_propertylist_get_double(properties,
1068 cxdouble yvalue = cpl_propertylist_get_double(properties,
1070 cxdouble zvalue = 0.;
1071 cxdouble zstep = 0.;
1072 cxdouble angle = -90. -
1073 (cpl_propertylist_get_double(properties,
1075 GI_ARGUS_POSANG_OFFSET);
1077 cxdouble pixscale = GI_ARGUS_PIXSCALE_LOW;
1079 const cxchar* scale =
1080 cpl_propertylist_get_string(properties,
1081 GIALIAS_ARGUS_SCALE);
1084 if ((scale != NULL) && (strcmp(scale,
"POS_1_67") == 0)) {
1085 pixscale = GI_ARGUS_PIXSCALE_HIGH;
1093 transform = cpl_matrix_new(3, 3);
1095 wcs = cpl_propertylist_new();
1097 cpl_propertylist_update_double(wcs,
"XORIGIN", xorigin);
1098 cpl_propertylist_update_double(wcs,
"YORIGIN", yorigin);
1099 cpl_propertylist_update_double(wcs,
"ZORIGIN", 1.);
1103 cpl_propertylist_update_double(wcs,
"XPOINT", xvalue);
1104 cpl_propertylist_update_double(wcs,
"YPOINT", yvalue);
1105 cpl_propertylist_update_double(wcs,
"ZPOINT", zvalue);
1107 cpl_propertylist_update_string(wcs,
"XTYPE",
"RA---TAN");
1108 cpl_propertylist_update_string(wcs,
"YTYPE",
"DEC--TAN");
1110 if (log_scale == TRUE) {
1111 cpl_propertylist_update_string(wcs,
1112 "ZTYPE",
"AWAV-LOG");
1115 cpl_propertylist_update_string(wcs,
1119 cpl_propertylist_update_string(wcs,
"XUNIT",
"deg");
1120 cpl_propertylist_update_string(wcs,
"YUNIT",
"deg");
1121 cpl_propertylist_update_string(wcs,
"ZUNIT",
"nm");
1130 angle *= CX_PI / 180.;
1132 cpl_matrix_set(transform, 0, 0, -pixscale * cos(angle));
1133 cpl_matrix_set(transform, 0, 1, pixscale * -sin(angle));
1134 cpl_matrix_set(transform, 1, 0, -pixscale * sin(angle));
1135 cpl_matrix_set(transform, 1, 1, pixscale * cos(angle));
1136 cpl_matrix_set(transform, 2, 2, zstep);
1141 if (scube != NULL) {
1142 simage = _giraffe_fov_integrate_cube(scube, limits);
1145 if ((scube == NULL) || (simage == NULL)) {
1147 cpl_image_delete(simage);
1155 cpl_msg_error(fctid,
"Cannot create data cube!");
1162 cx_slist_push_back(scubes, scube);
1163 cx_slist_push_back(simages, simage);
1170 ecube = _giraffe_fov_create_cube(variance, _fibers, NULL);
1171 eimage = _giraffe_fov_integrate_cube(ecube, limits);
1173 if ((ecube == NULL) || (eimage == NULL)) {
1175 cpl_image_delete(eimage);
1183 cpl_msg_error(fctid,
"Cannot create error cube!");
1189 cpl_image_power(eimage, 0.5);
1193 cx_slist_push_back(ecubes, ecube);
1194 cx_slist_push_back(eimages, eimage);
1200 cpl_propertylist_delete(wcs);
1203 cpl_matrix_delete(transform);
1211 cx_slist_destroy(simages, (cx_free_func)cpl_image_delete);
1214 cx_slist_destroy(eimages, (cx_free_func)cpl_image_delete);
1243 result->mode = mode;
1248 fov = cx_slist_pop_front(simages);
1258 giraffe_propertylist_update_wcs(properties, 0, NULL, NULL, NULL,
1261 cpl_propertylist_update_double(properties, GIALIAS_FOV_BANDMIN,
1263 cpl_propertylist_set_comment(properties, GIALIAS_FOV_BANDMIN,
1264 "Minimum wavelength of FOV band");
1266 cpl_propertylist_update_double(properties, GIALIAS_FOV_BANDMAX,
1268 cpl_propertylist_set_comment(properties, GIALIAS_FOV_BANDMAX,
1269 "Maximum wavelength of FOV band");
1271 cpl_image_delete(fov);
1276 fov = cx_slist_pop_front(eimages);
1286 giraffe_propertylist_update_wcs(properties, 0, NULL, NULL, NULL,
1288 cpl_propertylist_update_double(properties, GIALIAS_FOV_BANDMIN,
1290 cpl_propertylist_set_comment(properties, GIALIAS_FOV_BANDMIN,
1291 "Minimum wavelength of FOV band");
1293 cpl_propertylist_update_double(properties, GIALIAS_FOV_BANDMAX,
1295 cpl_propertylist_set_comment(properties, GIALIAS_FOV_BANDMAX,
1296 "Maximum wavelength of FOV band");
1298 cpl_image_delete(fov);
1301 if (!cx_slist_empty(simages)) {
1303 cx_slist_iterator pos = cx_slist_begin(simages);
1305 result->images.spectra = cx_slist_new();
1307 while (pos != cx_slist_end(simages)) {
1312 cx_slist_push_back(result->images.spectra, image);
1314 pos = cx_slist_next(simages, pos);
1319 if (!cx_slist_empty(eimages)) {
1321 cx_slist_iterator pos = cx_slist_begin(eimages);
1323 result->images.errors = cx_slist_new();
1325 while (pos != cx_slist_end(eimages)) {
1330 cx_slist_push_back(result->images.errors, image);
1332 pos = cx_slist_next(eimages, pos);
1337 if (config->cube == TRUE) {
1339 if (!cx_slist_empty(scubes)) {
1340 result->cubes.spectra = scubes;
1344 if (!cx_slist_empty(ecubes)) {
1345 result->cubes.errors = ecubes;
1359 cx_slist_destroy(simages, (cx_free_func)cpl_image_delete);
1362 cx_slist_destroy(eimages, (cx_free_func)cpl_image_delete);
1365 if (scubes != NULL) {
1370 if (ecubes != NULL) {
1396 GiFieldOfView* self = cx_malloc(
sizeof *self);
1398 self->mode = GIMODE_NONE;
1401 self->fov.spectra = NULL;
1402 self->fov.errors = NULL;
1404 self->images.spectra = NULL;
1405 self->images.errors = NULL;
1407 self->cubes.spectra = NULL;
1408 self->cubes.errors = NULL;
1433 if (self->cubes.errors != NULL) {
1434 cx_slist_destroy(self->cubes.errors,
1436 self->cubes.errors = NULL;
1439 if (self->cubes.spectra != NULL) {
1440 cx_slist_destroy(self->cubes.spectra,
1442 self->cubes.spectra = NULL;
1445 if (self->images.errors != NULL) {
1446 cx_slist_destroy(self->images.errors,
1448 self->images.errors = NULL;
1451 if (self->images.spectra != NULL) {
1452 cx_slist_destroy(self->images.spectra,
1454 self->images.spectra = NULL;
1457 if (self->fov.errors != NULL) {
1459 self->fov.errors = NULL;
1462 if (self->fov.spectra != NULL) {
1464 self->fov.spectra = NULL;
1467 if (self->ssn != NULL) {
1468 cpl_array_delete(self->ssn);
1472 self->mode = GIMODE_NONE;
1532 cpl_propertylist* properties,
1533 const cxchar* filename, cxptr data)
1537 cxint component = 0;
1539 cx_slist* cubes = NULL;
1542 if ((self == NULL) || (properties == NULL) || (filename == NULL)) {
1552 component = *((cxuint*)data);
1555 if (component == 0) {
1556 cubes = self->cubes.spectra;
1559 cubes = self->cubes.errors;
1562 if (cubes == NULL) {
1567 if (!cx_slist_empty(cubes)) {
1569 if (self->mode == GIMODE_ARGUS) {
1572 cxint iomode = CPL_IO_CREATE;
1574 GiCube* cube = cx_slist_front(cubes);
1587 cxint iomode = CPL_IO_CREATE;
1589 cx_slist_const_iterator pos = cx_slist_begin(cubes);
1591 cx_string* name = NULL;
1593 cpl_propertylist* xproperties = NULL;
1603 name = cx_string_new();
1604 xproperties = cpl_propertylist_new();
1606 iomode = CPL_IO_EXTEND;
1608 while (pos != cx_slist_end(cubes)) {
1610 cxint ssn = cpl_array_get_int(self->ssn, nss, NULL);
1612 GiCube* cube = cx_slist_get(cubes, pos);
1615 cx_string_sprintf(name,
"SSN%-d", ssn);
1616 cpl_propertylist_update_string(xproperties,
"EXTNAME",
1617 cx_string_get(name));
1624 cpl_propertylist_delete(xproperties);
1627 cx_string_delete(name);
1634 pos = cx_slist_next(cubes, pos);
1639 cpl_propertylist_delete(xproperties);
1642 cx_string_delete(name);
1675 cpl_propertylist* properties,
1676 const cxchar* filename, cxptr data)
1679 const cxchar* data_name =
"SPECTRA";
1680 const cxchar* error_name =
"ERRORS";
1681 const cxchar* link_names[2] = {
"SCIDATA",
"ERRDATA"};
1683 cx_slist* scubes = NULL;
1684 cx_slist* ecubes = NULL;
1692 if ((self == NULL) || (properties == NULL) || (filename == NULL)) {
1696 if (self->cubes.spectra == NULL) {
1700 if ((cpl_propertylist_has(properties, GIALIAS_EQUINOX) == FALSE) ||
1701 (cpl_propertylist_get_type(properties, GIALIAS_EQUINOX)
1702 != CPL_TYPE_DOUBLE)) {
1712 scubes = self->cubes.spectra;
1714 if (cx_slist_empty(scubes)) {
1718 if (self->cubes.errors != NULL) {
1720 ecubes = self->cubes.errors;
1722 if (cx_slist_size(scubes) != cx_slist_size(ecubes)) {
1729 if (self->mode == GIMODE_ARGUS) {
1732 cxint iomode = CPL_IO_CREATE;
1734 cxdouble equinox = cpl_propertylist_get_double(properties,
1737 cpl_propertylist* xproperties = NULL;
1739 GiCube* scube = cx_slist_front(scubes);
1749 iomode = CPL_IO_EXTEND;
1751 xproperties = cpl_propertylist_new();
1753 cpl_propertylist_update_string(xproperties, GIALIAS_EXTNAME, data_name);
1754 cpl_propertylist_set_comment(xproperties, GIALIAS_EXTNAME,
1755 "FITS Extension name");
1757 cpl_propertylist_update_string(xproperties,
"HDUCLASS",
"ESO");
1758 cpl_propertylist_set_comment(xproperties,
"HDUCLASS",
1759 "Conforms to ESO data cube conventions");
1761 cpl_propertylist_update_string(xproperties,
"HDUDOC",
"DICD");
1762 cpl_propertylist_set_comment(xproperties,
"HDUDOC",
1763 "Data format specification document");
1765 cpl_propertylist_update_string(xproperties,
"HDUVERS",
1767 cpl_propertylist_set_comment(xproperties,
"HDUVERS",
1768 "Specific version of the data format "
1771 cpl_propertylist_update_string(xproperties,
"HDUCLAS1",
"IMAGE");
1772 cpl_propertylist_set_comment(xproperties,
"HDUCLAS1",
1773 "Image data format");
1775 cpl_propertylist_update_string(xproperties,
"HDUCLAS2",
"DATA");
1776 cpl_propertylist_set_comment(xproperties,
"HDUCLAS2",
1777 "Science data extension");
1778 cpl_propertylist_update_string(xproperties, link_names[1], error_name);
1779 cpl_propertylist_set_comment(xproperties, link_names[1],
1780 "Linked error data extension");
1782 cpl_propertylist_update_double(xproperties, GIALIAS_EQUINOX,
1790 cpl_propertylist_delete(xproperties);
1797 cpl_propertylist_erase(xproperties, link_names[1]);
1798 cpl_propertylist_erase(xproperties,
"BUNIT");
1799 cpl_propertylist_erase(xproperties,
"DATAMIN");
1800 cpl_propertylist_erase(xproperties,
"DATAMAX");
1803 if (ecubes != NULL) {
1805 GiCube* ecube = cx_slist_front(ecubes);
1808 cpl_propertylist_update_string(xproperties,
"EXTNAME", error_name);
1810 cpl_propertylist_update_string(xproperties,
"HDUCLAS2",
"ERROR");
1811 cpl_propertylist_set_comment(xproperties,
"HDUCLAS2",
1812 "Error data extension");
1814 cpl_propertylist_update_string(xproperties,
"HDUCLAS3",
"RMSE");
1815 cpl_propertylist_set_comment(xproperties,
"HDUCLAS3",
1816 "Type of error: root mean squared");
1818 cpl_propertylist_update_string(xproperties, link_names[0],
1820 cpl_propertylist_set_comment(xproperties, link_names[0],
1821 "Linked science data extension");
1828 cpl_propertylist_delete(xproperties);
1837 cpl_propertylist_delete(xproperties);
1845 cxint iomode = CPL_IO_CREATE;
1847 cxdouble equinox = cpl_propertylist_get_double(properties,
1850 cx_slist_const_iterator spos = cx_slist_begin(scubes);
1851 cx_slist_const_iterator epos = cx_slist_begin(ecubes);
1853 cx_string* name = NULL;
1855 cpl_propertylist* xproperties = NULL;
1865 name = cx_string_new();
1866 xproperties = cpl_propertylist_new();
1868 iomode = CPL_IO_EXTEND;
1870 while (spos != cx_slist_end(scubes)) {
1872 cxint ssn = cpl_array_get_int(self->ssn, nss, NULL);
1874 GiCube* scube = cx_slist_get(scubes, spos);
1877 cx_string_sprintf(name,
"SSN%-d.%s", ssn, data_name);
1879 cpl_propertylist_update_string(xproperties, GIALIAS_EXTNAME,
1880 cx_string_get(name));
1881 cpl_propertylist_set_comment(xproperties, GIALIAS_EXTNAME,
1882 "FITS Extension name");
1884 cpl_propertylist_update_string(xproperties,
"HDUCLASS",
"ESO");
1885 cpl_propertylist_set_comment(xproperties,
"HDUCLASS",
1886 "Conforms to ESO data cube "
1889 cpl_propertylist_update_string(xproperties,
"HDUDOC",
"DICD");
1890 cpl_propertylist_set_comment(xproperties,
"HDUDOC",
1891 "Data format specification document");
1893 cpl_propertylist_update_string(xproperties,
"HDUVERS",
1895 cpl_propertylist_set_comment(xproperties,
"HDUVERS",
1896 "Specific version of the data format "
1899 cpl_propertylist_update_string(xproperties,
"HDUCLAS1",
"IMAGE");
1900 cpl_propertylist_set_comment(xproperties,
"HDUCLAS1",
1901 "Image data format");
1903 cpl_propertylist_update_string(xproperties,
"HDUCLAS2",
"DATA");
1904 cpl_propertylist_set_comment(xproperties,
"HDUCLAS2",
1905 "Science data extension");
1907 cx_string_sprintf(name,
"SSN%-d.%s", ssn, error_name);
1909 cpl_propertylist_update_string(xproperties, link_names[1],
1910 cx_string_get(name));
1911 cpl_propertylist_set_comment(xproperties, link_names[1],
1912 "Linked error data extension");
1914 cpl_propertylist_update_double(xproperties, GIALIAS_EQUINOX,
1922 cpl_propertylist_delete(xproperties);
1925 cx_string_delete(name);
1932 cpl_propertylist_erase(xproperties, link_names[1]);
1933 cpl_propertylist_erase(xproperties,
"BUNIT");
1934 cpl_propertylist_erase(xproperties,
"DATAMIN");
1935 cpl_propertylist_erase(xproperties,
"DATAMAX");
1938 if (ecubes != NULL) {
1940 GiCube* ecube = cx_slist_get(ecubes, epos);
1943 cx_string_sprintf(name,
"SSN%-d.%s", ssn, error_name);
1945 cpl_propertylist_update_string(xproperties,
"EXTNAME",
1946 cx_string_get(name));
1948 cpl_propertylist_update_string(xproperties,
"HDUCLAS2",
"ERROR");
1949 cpl_propertylist_set_comment(xproperties,
"HDUCLAS2",
1950 "Error data extension");
1952 cpl_propertylist_update_string(xproperties,
"HDUCLAS3",
"RMSE");
1953 cpl_propertylist_set_comment(xproperties,
"HDUCLAS3",
1954 "Type of error: root mean squared");
1956 cx_string_sprintf(name,
"SSN%-d.%s", ssn, data_name);
1958 cpl_propertylist_update_string(xproperties, link_names[0],
1959 cx_string_get(name));
1960 cpl_propertylist_set_comment(xproperties, link_names[0],
1961 "Linked science data extension");
1969 cpl_propertylist_delete(xproperties);
1972 cx_string_delete(name);
1979 epos = cx_slist_next(ecubes, epos);
1983 spos = cx_slist_next(scubes, spos);
1988 cpl_propertylist_delete(xproperties);
1991 cx_string_delete(name);
2016 const cxchar* s = NULL;
2020 GiFieldOfViewConfig* config = NULL;
2027 config = cx_calloc(1,
sizeof *config);
2030 p = cpl_parameterlist_find(list,
"giraffe.fov.range.minimum");
2031 config->minimum = cpl_parameter_get_double(p);
2033 p = cpl_parameterlist_find(list,
"giraffe.fov.range.maximum");
2034 config->maximum = cpl_parameter_get_double(p);
2036 p = cpl_parameterlist_find(list,
"giraffe.fov.cube");
2037 config->cube = cpl_parameter_get_bool(p);
2039 p = cpl_parameterlist_find(list,
"giraffe.fov.cube.format");
2040 s = cpl_parameter_get_string(p);
2042 if (strcmp(s,
"single") == 0) {
2043 config->format = GIFOV_FORMAT_SINGLE;
2045 else if (strcmp(s,
"eso3d") == 0) {
2046 config->format = GIFOV_FORMAT_ESO3D;
2071 if (config != NULL) {
2100 p = cpl_parameter_new_value(
"giraffe.fov.range.minimum",
2102 "Minimum wavelength for image reconstruction",
2103 "giraffe.fov.range",
2105 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"recon-min");
2106 cpl_parameterlist_append(list, p);
2109 p = cpl_parameter_new_value(
"giraffe.fov.range.maximum",
2111 "Maximum wavelength for image reconstruction",
2112 "giraffe.fov.range",
2114 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"recon-max");
2115 cpl_parameterlist_append(list, p);
2118 p = cpl_parameter_new_value(
"giraffe.fov.cube",
2120 "Turns data cube creation on and off",
2123 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"recon-cube");
2124 cpl_parameterlist_append(list, p);
2126 p = cpl_parameter_new_enum(
"giraffe.fov.cube.format",
2128 "Selects the file format for cubes",
2130 "single", 2,
"single",
"eso3d");
2131 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"recon-format");
2132 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.