27 #include <cxstrutils.h>
28 #include <cxmessages.h>
30 #include <cpl_array.h>
31 #include <cpl_propertylist.h>
36 #include "gimessages.h"
37 #include "gigrating.h"
39 #include "gifiberutils.h"
54 _giraffe_compare_int(cxcptr first, cxcptr second)
57 cxint *_first = (cxint *)first;
58 cxint *_second = (cxint *)second;
60 return *_first - *_second;
66 _giraffe_fov_create_cube(
const GiImage* spectra,
67 const cpl_table* fibers,
68 const GiRange* limits)
90 if ((properties == NULL) || (_spectra == NULL)) {
99 if (cpl_propertylist_has(properties, GIALIAS_BINWLMIN) == FALSE) {
103 wmin = cpl_propertylist_get_double(properties, GIALIAS_BINWLMIN);
106 if (cpl_propertylist_has(properties, GIALIAS_BINWLMAX) == FALSE) {
110 wmax = cpl_propertylist_get_double(properties, GIALIAS_BINWLMAX);
113 if (cpl_propertylist_has(properties, GIALIAS_BINSTEP) == FALSE) {
117 wstep = cpl_propertylist_get_double(properties, GIALIAS_BINSTEP);
126 last = cpl_image_get_size_y(_spectra) - 1;
128 if (limits != NULL) {
157 giraffe_error_push();
159 nx = (cxint) cpl_table_get_column_max(fibers,
"X");
160 ny = (cxint) cpl_table_get_column_max(fibers,
"Y");
162 if (cpl_error_get_code() == CPL_ERROR_DATA_NOT_FOUND) {
169 nz = last - first + 1;
188 register cxint i = 0;
189 register cxint nf = cpl_table_get_nrow(fibers);
191 cxint ns = cpl_image_get_size_x(_spectra);
193 cxdouble* spixels = cpl_image_get_data_double(_spectra);
197 cx_assert(spixels != NULL);
198 cx_assert(cpixels != NULL);
201 for (i = 0; i < nf; ++i) {
203 register cxint j = 0;
205 cxint idx = cpl_table_get_int(fibers,
"INDEX", i, NULL) - 1;
206 cxint x = cpl_table_get_int(fibers,
"X", i, NULL) - 1;
207 cxint y = cpl_table_get_int(fibers,
"Y", i, NULL) - 1;
215 if ((x >= 0) && (y >= 0)) {
217 for (j = 0; j < nz; ++j) {
218 cpixels[(ny * j + y) * nx + x] =
219 spixels[(first + j) * ns + idx];
237 inline static cpl_image*
238 _giraffe_fov_arrange_images(
const cx_slist* subimages,
239 cxsize nrows, cxsize ncolumns, cxint offset)
248 cxint xshift = offset;
249 cxint yshift = offset;
254 cx_slist_iterator pos;
256 cpl_image* image = NULL;
259 cx_assert(subimages != NULL);
260 cx_assert(nrows > 0);
261 cx_assert(ncolumns > 0);
270 pos = cx_slist_begin(subimages);
272 while (pos != cx_slist_end(subimages)) {
274 const cpl_image* simage = cx_slist_get(subimages, pos);
276 if (simage != NULL) {
278 cxint _nx = cpl_image_get_size_x(simage);
279 cxint _ny = cpl_image_get_size_y(simage);
281 sx = CX_MAX(nx, _nx);
282 sy = CX_MAX(ny, _ny);
286 pos = cx_slist_next(subimages, pos);
295 nslit = cx_slist_size(subimages);
296 nrows = CX_MAX(nslit / ncolumns, nrows);
298 if (nslit % ncolumns != 0) {
312 xshift = nx / -offset + 1;
313 yshift = ny / -offset + 1;
316 nx += ncolumns * xshift - (xshift % 2);
317 ny += nrows * yshift - (yshift % 2);
324 image = cpl_image_new(nx, ny, CPL_TYPE_DOUBLE);
329 pos = cx_slist_begin(subimages);
331 while (pos != cx_slist_end(subimages)) {
333 const cpl_image* simage = cx_slist_get(subimages, pos);
335 if (simage != NULL) {
337 cpl_error_code status = cpl_image_copy(image, simage,
340 if (status != CPL_ERROR_NONE) {
341 cpl_image_delete(image);
349 if (column < ncolumns) {
359 pos = cx_slist_next(subimages, pos);
368 inline static cpl_image*
369 _giraffe_fov_integrate_cube(
const GiCube* cube,
const GiRange* limits)
380 cpl_image* image = NULL;
383 cx_assert(cube != NULL);
388 wmax = wmin + depth * wstep;
429 GiTable* fibers, GiTable* wsolution,
430 GiTable* grating, GiTable* slitgeometry,
431 GiFieldOfViewConfig* config)
434 const cxchar*
const fctid =
"giraffe_fov_build";
436 cxbool log_scale = FALSE;
438 cx_slist* simages = NULL;
439 cx_slist* eimages = NULL;
440 cx_slist* scubes = NULL;
441 cx_slist* ecubes = NULL;
443 cpl_propertylist* properties = NULL;
445 cpl_array* ssn = NULL;
447 cpl_image* fov = NULL;
449 cpl_table* _fibers = NULL;
451 GiInstrumentMode mode;
453 GiRange* limits = NULL;
456 if (result == NULL) {
457 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
470 if (rebinning == NULL) {
471 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
475 if (rebinning->spectra == NULL || rebinning->errors == NULL) {
476 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
480 if (fibers == NULL) {
481 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
487 if (_fibers == NULL) {
488 cpl_error_set(fctid, CPL_ERROR_DATA_NOT_FOUND);
492 if (!cpl_table_has_column(_fibers,
"X") ||
493 !cpl_table_has_column(_fibers,
"Y")) {
494 cpl_error_set(fctid, CPL_ERROR_DATA_NOT_FOUND);
498 if (config == NULL) {
499 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
513 if (properties == NULL) {
514 cpl_error_set(fctid, CPL_ERROR_DATA_NOT_FOUND);
529 grating, slitgeometry, TRUE);
531 if (limits == NULL) {
532 cpl_msg_error(fctid,
"Computation of spectra common wavelength "
537 if (config->minimum > 0.) {
539 cpl_msg_warning(fctid,
"Ignoring invalid wavelength range "
540 "minimum %.3f nm", config->minimum);
547 if (config->maximum > 0.) {
549 cpl_msg_warning(fctid,
"Ignoring invalid wavelength range "
550 "maximum %.3f nm", config->maximum);
557 cpl_msg_info(fctid,
"Building image for wavelength range [%.3f nm, "
566 if (cpl_propertylist_has(properties, GIALIAS_BINSCALE)) {
568 const cxchar* s = cpl_propertylist_get_string(properties,
571 if (cx_strncasecmp(s,
"log", 3) == 0) {
579 cpl_msg_warning(fctid,
"Could not determine spectrum wavelength "
580 "scaling method. Missing property `%s'. Assuming "
581 "scaling method `linear'!", GIALIAS_BINSCALE);
590 simages = cx_slist_new();
591 eimages = cx_slist_new();
592 scubes = cx_slist_new();
593 ecubes = cx_slist_new();
602 cpl_array* _ssn = NULL;
604 cpl_image* smosaic = NULL;
605 cpl_image* emosaic = NULL;
607 GiImage* variance = NULL;
617 cx_slist_destroy(simages, (cx_free_func)cpl_image_delete);
620 cx_slist_destroy(eimages, (cx_free_func)cpl_image_delete);
632 cpl_msg_error(fctid,
"Sub-slit data missing in fiber table!");
644 if (variance == NULL) {
645 cpl_array_delete(ssn);
648 cx_slist_destroy(simages, (cx_free_func)cpl_image_delete);
651 cx_slist_destroy(eimages, (cx_free_func)cpl_image_delete);
663 cpl_msg_error(fctid,
"Failed to create variance map!");
675 _ssn = cpl_array_duplicate(ssn);
677 for (i = 0; i < cpl_array_get_size(_ssn); ++i) {
679 cxbool failed = FALSE;
681 cxint nss = cpl_array_get_int(_ssn, i, NULL);
683 cpl_table* ssf = NULL;
685 cpl_table_unselect_all(_fibers);
686 cpl_table_or_selected_int(_fibers,
"SSN", CPL_EQUAL_TO, nss);
693 cpl_table_and_selected_int(_fibers,
"X", CPL_GREATER_THAN, 0);
694 cpl_table_and_selected_int(_fibers,
"Y", CPL_GREATER_THAN, 0);
696 ssf = cpl_table_extract_selected(_fibers);
698 if ((ssf != NULL) && (cpl_table_get_nrow(ssf) > 0)) {
700 cpl_matrix* transform = NULL;
702 cpl_propertylist* wcs = NULL;
704 cpl_image* _simage = NULL;
705 cpl_image* _eimage = NULL;
707 GiCube* _scube = NULL;
708 GiCube* _ecube = NULL;
711 _scube = _giraffe_fov_create_cube(rebinning->spectra,
718 if (_scube != NULL) {
724 cpl_table_get_double(ssf,
"RA", 0, NULL);
726 cpl_table_get_double(ssf,
"DEC", 0, NULL);
727 cxdouble orientation =
728 cpl_table_get_double(ssf,
"ORIENT", 0, NULL);
730 cxdouble zvalue = 0.;
732 cxdouble angle = GI_IFU_POSANG_OFFSET - orientation;
733 cxdouble pixscale = GI_IFU_PIXSCALE / 3600.;
736 transform = cpl_matrix_new(3, 3);
738 wcs = cpl_propertylist_new();
740 cpl_propertylist_update_double(wcs,
"XORIGIN", xorigin);
741 cpl_propertylist_update_double(wcs,
"YORIGIN", yorigin);
742 cpl_propertylist_update_double(wcs,
"ZORIGIN", 1.);
746 cpl_propertylist_update_double(wcs,
"XPOINT", xvalue);
747 cpl_propertylist_update_double(wcs,
"YPOINT", yvalue);
748 cpl_propertylist_update_double(wcs,
"ZPOINT", zvalue);
750 cpl_propertylist_update_string(wcs,
"XTYPE",
752 cpl_propertylist_update_string(wcs,
"YTYPE",
755 if (log_scale == TRUE) {
756 cpl_propertylist_update_string(wcs,
757 "ZTYPE",
"AWAV-LOG");
760 cpl_propertylist_update_string(wcs,
764 cpl_propertylist_update_string(wcs,
"XUNIT",
"deg");
765 cpl_propertylist_update_string(wcs,
"YUNIT",
"deg");
766 cpl_propertylist_update_string(wcs,
"ZUNIT",
"nm");
775 angle *= CX_PI / 180.;
777 cpl_matrix_set(transform, 0, 0, -pixscale * cos(angle));
778 cpl_matrix_set(transform, 0, 1, pixscale * -sin(angle));
779 cpl_matrix_set(transform, 1, 0, -pixscale * sin(angle));
780 cpl_matrix_set(transform, 1, 1, pixscale * cos(angle));
781 cpl_matrix_set(transform, 2, 2, zstep);
785 if (_scube != NULL) {
786 _simage = _giraffe_fov_integrate_cube(_scube, limits);
789 if ((_scube == NULL) || (_simage == NULL)) {
791 cpl_image_delete(_simage);
799 cpl_msg_error(fctid,
"Cannot create data cube for "
805 cx_slist_push_back(scubes, _scube);
806 cx_slist_push_back(simages, _simage);
811 _ecube = _giraffe_fov_create_cube(variance,
814 if (_ecube != NULL) {
815 _eimage = _giraffe_fov_integrate_cube(_ecube,
819 if ((_ecube == NULL) || (_eimage == NULL)) {
821 cpl_image_delete(_eimage);
829 cpl_msg_error(fctid,
"Cannot create error "
830 "cube for sub-slit %d", nss);
834 cpl_image_power(_eimage, 0.5);
838 cx_slist_push_back(ecubes, _ecube);
839 cx_slist_push_back(eimages, _eimage);
844 cpl_propertylist_delete(wcs);
847 cpl_matrix_delete(transform);
852 cpl_table_delete(ssf);
858 cpl_array_delete(_ssn);
861 cpl_array_delete(ssn);
864 cx_slist_destroy(simages,
865 (cx_free_func)cpl_image_delete);
868 cx_slist_destroy(eimages,
869 (cx_free_func)cpl_image_delete);
872 cx_slist_destroy(scubes,
876 cx_slist_destroy(ecubes,
891 cpl_msg_debug(fctid,
"Unused IFU button detected. "
892 "Skipping sub-slit %d", nss);
894 cpl_array_set_invalid(_ssn, i);
896 cx_slist_push_back(simages, NULL);
897 cx_slist_push_back(eimages, NULL);
901 cpl_table_delete(ssf);
911 if (cpl_array_count_invalid(_ssn) > 0) {
916 cpl_array_set_size(ssn, cpl_array_get_size(ssn) -
917 cpl_array_count_invalid(_ssn));
919 for (k = 0; k < cpl_array_get_size(_ssn); ++k) {
923 register cxint idx = cpl_array_get_int(_ssn, k, &invalid);
926 cpl_array_set_int(ssn, j, idx);
934 cpl_array_delete(_ssn);
948 smosaic = _giraffe_fov_arrange_images(simages, 5, 3, -4);
949 emosaic = _giraffe_fov_arrange_images(eimages, 5, 3, -4);
951 if ((smosaic == NULL) || (emosaic == NULL)) {
953 cpl_image_delete(smosaic);
956 cpl_image_delete(emosaic);
959 cx_slist_destroy(simages, (cx_free_func)cpl_image_delete);
962 cx_slist_destroy(eimages, (cx_free_func)cpl_image_delete);
971 cpl_array_delete(ssn);
981 cx_slist_push_front(simages, smosaic);
982 cx_slist_push_front(eimages, emosaic);
989 cxbool failed = FALSE;
991 cpl_image* simage = NULL;
992 cpl_image* eimage = NULL;
994 cpl_matrix* transform = NULL;
996 cpl_propertylist* wcs = NULL;
998 GiImage* variance = NULL;
1000 GiCube* scube = NULL;
1001 GiCube* ecube = NULL;
1010 if (variance == NULL) {
1012 cx_slist_destroy(simages, (cx_free_func)cpl_image_delete);
1015 cx_slist_destroy(eimages, (cx_free_func)cpl_image_delete);
1027 cpl_msg_error(fctid,
"Failed to create variance map!");
1039 scube = _giraffe_fov_create_cube(rebinning->spectra,
1060 if (scube != NULL) {
1065 cxdouble xvalue = cpl_propertylist_get_double(properties,
1067 cxdouble yvalue = cpl_propertylist_get_double(properties,
1069 cxdouble zvalue = 0.;
1070 cxdouble zstep = 0.;
1071 cxdouble angle = -90. -
1072 (cpl_propertylist_get_double(properties,
1074 GI_ARGUS_POSANG_OFFSET);
1076 cxdouble pixscale = GI_ARGUS_PIXSCALE_LOW;
1078 const cxchar* scale =
1079 cpl_propertylist_get_string(properties,
1080 GIALIAS_ARGUS_SCALE);
1083 if ((scale != NULL) && (strcmp(scale,
"POS_1_67") == 0)) {
1084 pixscale = GI_ARGUS_PIXSCALE_HIGH;
1092 transform = cpl_matrix_new(3, 3);
1094 wcs = cpl_propertylist_new();
1096 cpl_propertylist_update_double(wcs,
"XORIGIN", xorigin);
1097 cpl_propertylist_update_double(wcs,
"YORIGIN", yorigin);
1098 cpl_propertylist_update_double(wcs,
"ZORIGIN", 1.);
1102 cpl_propertylist_update_double(wcs,
"XPOINT", xvalue);
1103 cpl_propertylist_update_double(wcs,
"YPOINT", yvalue);
1104 cpl_propertylist_update_double(wcs,
"ZPOINT", zvalue);
1106 cpl_propertylist_update_string(wcs,
"XTYPE",
"RA---TAN");
1107 cpl_propertylist_update_string(wcs,
"YTYPE",
"DEC--TAN");
1109 if (log_scale == TRUE) {
1110 cpl_propertylist_update_string(wcs,
1111 "ZTYPE",
"AWAV-LOG");
1114 cpl_propertylist_update_string(wcs,
1118 cpl_propertylist_update_string(wcs,
"XUNIT",
"deg");
1119 cpl_propertylist_update_string(wcs,
"YUNIT",
"deg");
1120 cpl_propertylist_update_string(wcs,
"ZUNIT",
"nm");
1129 angle *= CX_PI / 180.;
1131 cpl_matrix_set(transform, 0, 0, -pixscale * cos(angle));
1132 cpl_matrix_set(transform, 0, 1, pixscale * -sin(angle));
1133 cpl_matrix_set(transform, 1, 0, -pixscale * sin(angle));
1134 cpl_matrix_set(transform, 1, 1, pixscale * cos(angle));
1135 cpl_matrix_set(transform, 2, 2, zstep);
1140 if (scube != NULL) {
1141 simage = _giraffe_fov_integrate_cube(scube, limits);
1144 if ((scube == NULL) || (simage == NULL)) {
1146 cpl_image_delete(simage);
1154 cpl_msg_error(fctid,
"Cannot create data cube!");
1161 cx_slist_push_back(scubes, scube);
1162 cx_slist_push_back(simages, simage);
1169 ecube = _giraffe_fov_create_cube(variance, _fibers, NULL);
1170 eimage = _giraffe_fov_integrate_cube(ecube, limits);
1172 if ((ecube == NULL) || (eimage == NULL)) {
1174 cpl_image_delete(eimage);
1182 cpl_msg_error(fctid,
"Cannot create error cube!");
1188 cpl_image_power(eimage, 0.5);
1192 cx_slist_push_back(ecubes, ecube);
1193 cx_slist_push_back(eimages, eimage);
1199 cpl_propertylist_delete(wcs);
1202 cpl_matrix_delete(transform);
1210 cx_slist_destroy(simages, (cx_free_func)cpl_image_delete);
1213 cx_slist_destroy(eimages, (cx_free_func)cpl_image_delete);
1242 result->mode = mode;
1247 fov = cx_slist_pop_front(simages);
1257 giraffe_propertylist_update_wcs(properties, 0, NULL, NULL, NULL,
1260 cpl_propertylist_update_double(properties, GIALIAS_FOV_BANDMIN,
1262 cpl_propertylist_set_comment(properties, GIALIAS_FOV_BANDMIN,
1263 "Minimum wavelength of FOV band");
1265 cpl_propertylist_update_double(properties, GIALIAS_FOV_BANDMAX,
1267 cpl_propertylist_set_comment(properties, GIALIAS_FOV_BANDMAX,
1268 "Maximum wavelength of FOV band");
1270 cpl_image_delete(fov);
1275 fov = cx_slist_pop_front(eimages);
1285 giraffe_propertylist_update_wcs(properties, 0, NULL, NULL, NULL,
1287 cpl_propertylist_update_double(properties, GIALIAS_FOV_BANDMIN,
1289 cpl_propertylist_set_comment(properties, GIALIAS_FOV_BANDMIN,
1290 "Minimum wavelength of FOV band");
1292 cpl_propertylist_update_double(properties, GIALIAS_FOV_BANDMAX,
1294 cpl_propertylist_set_comment(properties, GIALIAS_FOV_BANDMAX,
1295 "Maximum wavelength of FOV band");
1297 cpl_image_delete(fov);
1300 if (!cx_slist_empty(simages)) {
1302 cx_slist_iterator pos = cx_slist_begin(simages);
1304 result->images.spectra = cx_slist_new();
1306 while (pos != cx_slist_end(simages)) {
1311 cx_slist_push_back(result->images.spectra, image);
1313 pos = cx_slist_next(simages, pos);
1318 if (!cx_slist_empty(eimages)) {
1320 cx_slist_iterator pos = cx_slist_begin(eimages);
1322 result->images.errors = cx_slist_new();
1324 while (pos != cx_slist_end(eimages)) {
1329 cx_slist_push_back(result->images.errors, image);
1331 pos = cx_slist_next(eimages, pos);
1336 if (config->cube == TRUE) {
1338 if (!cx_slist_empty(scubes)) {
1339 result->cubes.spectra = scubes;
1343 if (!cx_slist_empty(ecubes)) {
1344 result->cubes.errors = ecubes;
1358 cx_slist_destroy(simages, (cx_free_func)cpl_image_delete);
1361 cx_slist_destroy(eimages, (cx_free_func)cpl_image_delete);
1364 if (scubes != NULL) {
1369 if (ecubes != NULL) {
1395 GiFieldOfView*
self = cx_malloc(
sizeof *
self);
1397 self->mode = GIMODE_NONE;
1400 self->fov.spectra = NULL;
1401 self->fov.errors = NULL;
1403 self->images.spectra = NULL;
1404 self->images.errors = NULL;
1406 self->cubes.spectra = NULL;
1407 self->cubes.errors = NULL;
1432 if (self->cubes.errors != NULL) {
1433 cx_slist_destroy(self->cubes.errors,
1435 self->cubes.errors = NULL;
1438 if (self->cubes.spectra != NULL) {
1439 cx_slist_destroy(self->cubes.spectra,
1441 self->cubes.spectra = NULL;
1444 if (self->images.errors != NULL) {
1445 cx_slist_destroy(self->images.errors,
1447 self->images.errors = NULL;
1450 if (self->images.spectra != NULL) {
1451 cx_slist_destroy(self->images.spectra,
1453 self->images.spectra = NULL;
1456 if (self->fov.errors != NULL) {
1458 self->fov.errors = NULL;
1461 if (self->fov.spectra != NULL) {
1463 self->fov.spectra = NULL;
1466 if (self->ssn != NULL) {
1467 cpl_array_delete(self->ssn);
1471 self->mode = GIMODE_NONE;
1531 cpl_propertylist* properties,
1532 const cxchar* filename, cxptr data)
1536 cxint component = 0;
1538 cx_slist* cubes = NULL;
1541 if ((
self == NULL) || (properties == NULL) || (filename == NULL)) {
1551 component = *((cxuint*)data);
1554 if (component == 0) {
1555 cubes =
self->cubes.spectra;
1558 cubes =
self->cubes.errors;
1561 if (cubes == NULL) {
1566 if (!cx_slist_empty(cubes)) {
1568 if (self->mode == GIMODE_ARGUS) {
1571 cxint iomode = CPL_IO_CREATE;
1573 GiCube* cube = cx_slist_front(cubes);
1586 cxint iomode = CPL_IO_CREATE;
1588 cx_slist_const_iterator pos = cx_slist_begin(cubes);
1590 cx_string* name = NULL;
1592 cpl_propertylist* xproperties = NULL;
1602 name = cx_string_new();
1603 xproperties = cpl_propertylist_new();
1605 iomode = CPL_IO_EXTEND;
1607 while (pos != cx_slist_end(cubes)) {
1609 cxint ssn = cpl_array_get_int(self->ssn, nss, NULL);
1611 GiCube* cube = cx_slist_get(cubes, pos);
1614 cx_string_sprintf(name,
"SSN%-d", ssn);
1615 cpl_propertylist_update_string(xproperties,
"EXTNAME",
1616 cx_string_get(name));
1623 cpl_propertylist_delete(xproperties);
1626 cx_string_delete(name);
1633 pos = cx_slist_next(cubes, pos);
1638 cpl_propertylist_delete(xproperties);
1641 cx_string_delete(name);
1674 cpl_propertylist* properties,
1675 const cxchar* filename, cxptr data)
1678 const cxchar* data_name =
"SPECTRA";
1679 const cxchar* error_name =
"ERRORS";
1680 const cxchar* link_names[2] = {
"SCIDATA",
"ERRDATA"};
1682 cx_slist* scubes = NULL;
1683 cx_slist* ecubes = NULL;
1691 if ((
self == NULL) || (properties == NULL) || (filename == NULL)) {
1695 if (self->cubes.spectra == NULL) {
1699 if ((cpl_propertylist_has(properties, GIALIAS_EQUINOX) == FALSE) ||
1700 (cpl_propertylist_get_type(properties, GIALIAS_EQUINOX)
1701 != CPL_TYPE_DOUBLE)) {
1711 scubes =
self->cubes.spectra;
1713 if (cx_slist_empty(scubes)) {
1717 if (self->cubes.errors != NULL) {
1719 ecubes =
self->cubes.errors;
1721 if (cx_slist_size(scubes) != cx_slist_size(ecubes)) {
1728 if (self->mode == GIMODE_ARGUS) {
1731 cxint iomode = CPL_IO_CREATE;
1733 cxdouble equinox = cpl_propertylist_get_double(properties,
1736 cpl_propertylist* xproperties = NULL;
1738 GiCube* scube = cx_slist_front(scubes);
1748 iomode = CPL_IO_EXTEND;
1750 xproperties = cpl_propertylist_new();
1752 cpl_propertylist_update_string(xproperties, GIALIAS_EXTNAME, data_name);
1753 cpl_propertylist_set_comment(xproperties, GIALIAS_EXTNAME,
1754 "FITS Extension name");
1756 cpl_propertylist_update_string(xproperties,
"HDUCLASS",
"ESO");
1757 cpl_propertylist_set_comment(xproperties,
"HDUCLASS",
1758 "Conforms to ESO data cube conventions");
1760 cpl_propertylist_update_string(xproperties,
"HDUDOC",
"DICD");
1761 cpl_propertylist_set_comment(xproperties,
"HDUDOC",
1762 "Data format specification document");
1764 cpl_propertylist_update_string(xproperties,
"HDUVERS",
1766 cpl_propertylist_set_comment(xproperties,
"HDUVERS",
1767 "Specific version of the data format "
1770 cpl_propertylist_update_string(xproperties,
"HDUCLAS1",
"IMAGE");
1771 cpl_propertylist_set_comment(xproperties,
"HDUCLAS1",
1772 "Image data format");
1774 cpl_propertylist_update_string(xproperties,
"HDUCLAS2",
"DATA");
1775 cpl_propertylist_set_comment(xproperties,
"HDUCLAS2",
1776 "Science data extension");
1777 cpl_propertylist_update_string(xproperties, link_names[1], error_name);
1778 cpl_propertylist_set_comment(xproperties, link_names[1],
1779 "Linked error data extension");
1781 cpl_propertylist_update_double(xproperties, GIALIAS_EQUINOX,
1789 cpl_propertylist_delete(xproperties);
1796 cpl_propertylist_erase(xproperties, link_names[1]);
1797 cpl_propertylist_erase(xproperties,
"BUNIT");
1798 cpl_propertylist_erase(xproperties,
"DATAMIN");
1799 cpl_propertylist_erase(xproperties,
"DATAMAX");
1802 if (ecubes != NULL) {
1804 GiCube* ecube = cx_slist_front(ecubes);
1807 cpl_propertylist_update_string(xproperties,
"EXTNAME", error_name);
1809 cpl_propertylist_update_string(xproperties,
"HDUCLAS2",
"ERROR");
1810 cpl_propertylist_set_comment(xproperties,
"HDUCLAS2",
1811 "Error data extension");
1813 cpl_propertylist_update_string(xproperties,
"HDUCLAS3",
"RMSE");
1814 cpl_propertylist_set_comment(xproperties,
"HDUCLAS3",
1815 "Type of error: root mean squared");
1817 cpl_propertylist_update_string(xproperties, link_names[0],
1819 cpl_propertylist_set_comment(xproperties, link_names[0],
1820 "Linked science data extension");
1827 cpl_propertylist_delete(xproperties);
1836 cpl_propertylist_delete(xproperties);
1844 cxint iomode = CPL_IO_CREATE;
1846 cxdouble equinox = cpl_propertylist_get_double(properties,
1849 cx_slist_const_iterator spos = cx_slist_begin(scubes);
1850 cx_slist_const_iterator epos = cx_slist_begin(ecubes);
1852 cx_string* name = NULL;
1854 cpl_propertylist* xproperties = NULL;
1864 name = cx_string_new();
1865 xproperties = cpl_propertylist_new();
1867 iomode = CPL_IO_EXTEND;
1869 while (spos != cx_slist_end(scubes)) {
1871 cxint ssn = cpl_array_get_int(self->ssn, nss, NULL);
1873 GiCube* scube = cx_slist_get(scubes, spos);
1876 cx_string_sprintf(name,
"SSN%-d.%s", ssn, data_name);
1878 cpl_propertylist_update_string(xproperties, GIALIAS_EXTNAME,
1879 cx_string_get(name));
1880 cpl_propertylist_set_comment(xproperties, GIALIAS_EXTNAME,
1881 "FITS Extension name");
1883 cpl_propertylist_update_string(xproperties,
"HDUCLASS",
"ESO");
1884 cpl_propertylist_set_comment(xproperties,
"HDUCLASS",
1885 "Conforms to ESO data cube "
1888 cpl_propertylist_update_string(xproperties,
"HDUDOC",
"DICD");
1889 cpl_propertylist_set_comment(xproperties,
"HDUDOC",
1890 "Data format specification document");
1892 cpl_propertylist_update_string(xproperties,
"HDUVERS",
1894 cpl_propertylist_set_comment(xproperties,
"HDUVERS",
1895 "Specific version of the data format "
1898 cpl_propertylist_update_string(xproperties,
"HDUCLAS1",
"IMAGE");
1899 cpl_propertylist_set_comment(xproperties,
"HDUCLAS1",
1900 "Image data format");
1902 cpl_propertylist_update_string(xproperties,
"HDUCLAS2",
"DATA");
1903 cpl_propertylist_set_comment(xproperties,
"HDUCLAS2",
1904 "Science data extension");
1906 cx_string_sprintf(name,
"SSN%-d.%s", ssn, error_name);
1908 cpl_propertylist_update_string(xproperties, link_names[1],
1909 cx_string_get(name));
1910 cpl_propertylist_set_comment(xproperties, link_names[1],
1911 "Linked error data extension");
1913 cpl_propertylist_update_double(xproperties, GIALIAS_EQUINOX,
1921 cpl_propertylist_delete(xproperties);
1924 cx_string_delete(name);
1931 cpl_propertylist_erase(xproperties, link_names[1]);
1932 cpl_propertylist_erase(xproperties,
"BUNIT");
1933 cpl_propertylist_erase(xproperties,
"DATAMIN");
1934 cpl_propertylist_erase(xproperties,
"DATAMAX");
1937 if (ecubes != NULL) {
1939 GiCube* ecube = cx_slist_get(ecubes, epos);
1942 cx_string_sprintf(name,
"SSN%-d.%s", ssn, error_name);
1944 cpl_propertylist_update_string(xproperties,
"EXTNAME",
1945 cx_string_get(name));
1947 cpl_propertylist_update_string(xproperties,
"HDUCLAS2",
"ERROR");
1948 cpl_propertylist_set_comment(xproperties,
"HDUCLAS2",
1949 "Error data extension");
1951 cpl_propertylist_update_string(xproperties,
"HDUCLAS3",
"RMSE");
1952 cpl_propertylist_set_comment(xproperties,
"HDUCLAS3",
1953 "Type of error: root mean squared");
1955 cx_string_sprintf(name,
"SSN%-d.%s", ssn, data_name);
1957 cpl_propertylist_update_string(xproperties, link_names[0],
1958 cx_string_get(name));
1959 cpl_propertylist_set_comment(xproperties, link_names[0],
1960 "Linked science data extension");
1968 cpl_propertylist_delete(xproperties);
1971 cx_string_delete(name);
1978 epos = cx_slist_next(ecubes, epos);
1982 spos = cx_slist_next(scubes, spos);
1987 cpl_propertylist_delete(xproperties);
1990 cx_string_delete(name);
2011 GiFieldOfViewConfig*
2015 const cxchar* s = NULL;
2019 GiFieldOfViewConfig* config = NULL;
2026 config = cx_calloc(1,
sizeof *config);
2029 p = cpl_parameterlist_find(list,
"giraffe.fov.range.minimum");
2030 config->minimum = cpl_parameter_get_double(p);
2032 p = cpl_parameterlist_find(list,
"giraffe.fov.range.maximum");
2033 config->maximum = cpl_parameter_get_double(p);
2035 p = cpl_parameterlist_find(list,
"giraffe.fov.cube");
2036 config->cube = cpl_parameter_get_bool(p);
2038 p = cpl_parameterlist_find(list,
"giraffe.fov.cube.format");
2039 s = cpl_parameter_get_string(p);
2041 if (strcmp(s,
"single") == 0) {
2042 config->format = GIFOV_FORMAT_SINGLE;
2044 else if (strcmp(s,
"eso3d") == 0) {
2045 config->format = GIFOV_FORMAT_ESO3D;
2070 if (config != NULL) {
2099 p = cpl_parameter_new_value(
"giraffe.fov.range.minimum",
2101 "Minimum wavelength for image reconstruction",
2102 "giraffe.fov.range",
2104 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"recon-min");
2105 cpl_parameterlist_append(list, p);
2108 p = cpl_parameter_new_value(
"giraffe.fov.range.maximum",
2110 "Maximum wavelength for image reconstruction",
2111 "giraffe.fov.range",
2113 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"recon-max");
2114 cpl_parameterlist_append(list, p);
2117 p = cpl_parameter_new_value(
"giraffe.fov.cube",
2119 "Turns data cube creation on and off",
2122 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"recon-cube");
2123 cpl_parameterlist_append(list, p);
2125 p = cpl_parameter_new_enum(
"giraffe.fov.cube.format",
2127 "Selects the file format for cubes",
2129 "single", 2,
"single",
"eso3d");
2130 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"recon-format");
2131 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.
cxint giraffe_cube_set_zaxis(GiCube *self, cxdouble start, cxdouble step)
Set the data cube's z-axis start value and step size.
cxint giraffe_cube_set_xaxis(GiCube *self, cxdouble start, cxdouble step)
Set the data cube's x-axis start value and step size.
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.
GiCube * giraffe_cube_create(cxsize width, cxsize height, cxsize depth, cxdouble *data)
Create a data cube with the given width, height and depth.
cxsize giraffe_cube_get_height(const GiCube *self)
Get the height of the given data cube.
cpl_image * giraffe_cube_integrate(const GiCube *self, cxdouble start, cxdouble end)
Integrate a cube along the z-axis.
cxint giraffe_cube_sqrt(GiCube *self)
Compute the square root of the elements of a cube.
cxdouble * giraffe_cube_get_data(const GiCube *self)
Get a reference to the data cube's pixel buffer.
cpl_array * giraffe_fiberlist_get_subslits(const cpl_table *fibers)
Get the list of subslit identifiers from a fiber setup.
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.
GiFieldOfViewConfig * giraffe_fov_config_create(cpl_parameterlist *list)
Creates a setup structure for 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.
void giraffe_image_delete(GiImage *self)
Destroys an image.
cpl_propertylist * giraffe_image_get_properties(const GiImage *self)
Get the properties of an image.
cpl_image * giraffe_image_get(const GiImage *self)
Gets the image data.
GiImage * giraffe_image_new(cpl_type type)
Creates an empty image container.
cxint giraffe_image_set(GiImage *self, cpl_image *image)
Sets the image data.
cxint giraffe_image_set_properties(GiImage *self, cpl_propertylist *properties)
Attaches a property list to an image.
GiImage * giraffe_image_duplicate(const GiImage *self)
Creates a copy of 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.