35 #include <cxstrutils.h>
36 #include <cxmessages.h>
38 #include <cpl_array.h>
39 #include <cpl_propertylist.h>
44 #include "gimessages.h"
45 #include "gigrating.h"
47 #include "gifiberutils.h"
62 _giraffe_compare_int(cxcptr first, cxcptr second)
65 cxint *_first = (cxint *)first;
66 cxint *_second = (cxint *)second;
68 return *_first - *_second;
74 _giraffe_fov_create_cube(
const GiImage* spectra,
75 const cpl_table* fibers,
76 const GiRange* limits)
98 if ((properties == NULL) || (_spectra == NULL)) {
107 if (cpl_propertylist_has(properties, GIALIAS_BINWLMIN) == FALSE) {
111 wmin = cpl_propertylist_get_double(properties, GIALIAS_BINWLMIN);
114 if (cpl_propertylist_has(properties, GIALIAS_BINWLMAX) == FALSE) {
118 wmax = cpl_propertylist_get_double(properties, GIALIAS_BINWLMAX);
121 if (cpl_propertylist_has(properties, GIALIAS_BINSTEP) == FALSE) {
125 wstep = cpl_propertylist_get_double(properties, GIALIAS_BINSTEP);
134 last = cpl_image_get_size_y(_spectra) - 1;
136 if (limits != NULL) {
165 giraffe_error_push();
167 nx = (cxint) cpl_table_get_column_max(fibers,
"X");
168 ny = (cxint) cpl_table_get_column_max(fibers,
"Y");
170 if (cpl_error_get_code() == CPL_ERROR_DATA_NOT_FOUND) {
177 nz = last - first + 1;
196 register cxint i = 0;
197 register cxint nf = cpl_table_get_nrow(fibers);
199 cxint ns = cpl_image_get_size_x(_spectra);
201 cxdouble* spixels = cpl_image_get_data_double(_spectra);
205 cx_assert(spixels != NULL);
206 cx_assert(cpixels != NULL);
209 for (i = 0; i < nf; ++i) {
211 register cxint j = 0;
213 cxint idx = cpl_table_get_int(fibers,
"INDEX", i, NULL) - 1;
214 cxint x = cpl_table_get_int(fibers,
"X", i, NULL) - 1;
215 cxint y = cpl_table_get_int(fibers,
"Y", i, NULL) - 1;
223 if ((x >= 0) && (y >= 0)) {
225 for (j = 0; j < nz; ++j) {
226 cpixels[(ny * j + y) * nx + x] =
227 spixels[(first + j) * ns + idx];
245 inline static cpl_image*
246 _giraffe_fov_arrange_images(
const cx_slist* subimages,
247 cxsize nrows, cxsize ncolumns, cxint offset)
256 cxint xshift = offset;
257 cxint yshift = offset;
262 cx_slist_iterator pos;
264 cpl_image* image = NULL;
267 cx_assert(subimages != NULL);
268 cx_assert(nrows > 0);
269 cx_assert(ncolumns > 0);
278 pos = cx_slist_begin(subimages);
280 while (pos != cx_slist_end(subimages)) {
282 const cpl_image* simage = cx_slist_get(subimages, pos);
284 if (simage != NULL) {
286 cxint _nx = cpl_image_get_size_x(simage);
287 cxint _ny = cpl_image_get_size_y(simage);
289 sx = CX_MAX(nx, _nx);
290 sy = CX_MAX(ny, _ny);
294 pos = cx_slist_next(subimages, pos);
303 nslit = cx_slist_size(subimages);
304 nrows = CX_MAX(nslit / ncolumns, nrows);
306 if (nslit % ncolumns != 0) {
320 xshift = nx / -offset + 1;
321 yshift = ny / -offset + 1;
324 nx += ncolumns * xshift - (xshift % 2);
325 ny += nrows * yshift - (yshift % 2);
332 image = cpl_image_new(nx, ny, CPL_TYPE_DOUBLE);
337 pos = cx_slist_begin(subimages);
339 while (pos != cx_slist_end(subimages)) {
341 const cpl_image* simage = cx_slist_get(subimages, pos);
343 if (simage != NULL) {
345 cpl_error_code status = cpl_image_copy(image, simage,
348 if (status != CPL_ERROR_NONE) {
349 cpl_image_delete(image);
357 if (column < ncolumns) {
367 pos = cx_slist_next(subimages, pos);
376 inline static cpl_image*
377 _giraffe_fov_integrate_cube(
const GiCube* cube,
const GiRange* limits)
388 cpl_image* image = NULL;
391 cx_assert(cube != NULL);
396 wmax = wmin + depth * wstep;
437 GiTable* fibers, GiTable* wsolution,
438 GiTable* grating, GiTable* slitgeometry,
439 GiFieldOfViewConfig* config)
442 const cxchar*
const fctid =
"giraffe_fov_build";
444 cxbool log_scale = FALSE;
446 cx_slist* simages = NULL;
447 cx_slist* eimages = NULL;
448 cx_slist* scubes = NULL;
449 cx_slist* ecubes = NULL;
451 cpl_propertylist* properties = NULL;
453 cpl_array* ssn = NULL;
455 cpl_image* fov = NULL;
457 cpl_table* _fibers = NULL;
459 GiInstrumentMode mode;
461 GiRange* limits = NULL;
464 if (result == NULL) {
465 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
478 if (rebinning == NULL) {
479 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
483 if (rebinning->spectra == NULL || rebinning->errors == NULL) {
484 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
488 if (fibers == NULL) {
489 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
495 if (_fibers == NULL) {
496 cpl_error_set(fctid, CPL_ERROR_DATA_NOT_FOUND);
500 if (!cpl_table_has_column(_fibers,
"X") ||
501 !cpl_table_has_column(_fibers,
"Y")) {
502 cpl_error_set(fctid, CPL_ERROR_DATA_NOT_FOUND);
506 if (config == NULL) {
507 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
521 if (properties == NULL) {
522 cpl_error_set(fctid, CPL_ERROR_DATA_NOT_FOUND);
537 grating, slitgeometry, TRUE);
539 if (limits == NULL) {
540 cpl_msg_error(fctid,
"Computation of spectra common wavelength "
545 if (config->minimum > 0.) {
547 cpl_msg_warning(fctid,
"Ignoring invalid wavelength range "
548 "minimum %.3f nm", config->minimum);
555 if (config->maximum > 0.) {
557 cpl_msg_warning(fctid,
"Ignoring invalid wavelength range "
558 "maximum %.3f nm", config->maximum);
565 cpl_msg_info(fctid,
"Building image for wavelength range [%.3f nm, "
574 if (cpl_propertylist_has(properties, GIALIAS_BINSCALE)) {
576 const cxchar* s = cpl_propertylist_get_string(properties,
579 if (cx_strncasecmp(s,
"log", 3) == 0) {
587 cpl_msg_warning(fctid,
"Could not determine spectrum wavelength "
588 "scaling method. Missing property `%s'. Assuming "
589 "scaling method `linear'!", GIALIAS_BINSCALE);
598 simages = cx_slist_new();
599 eimages = cx_slist_new();
600 scubes = cx_slist_new();
601 ecubes = cx_slist_new();
610 cpl_array* _ssn = NULL;
612 cpl_image* smosaic = NULL;
613 cpl_image* emosaic = NULL;
615 GiImage* variance = NULL;
625 cx_slist_destroy(simages, (cx_free_func)cpl_image_delete);
628 cx_slist_destroy(eimages, (cx_free_func)cpl_image_delete);
634 cx_slist_destroy(ecubes, (cx_free_func)giraffe_cube_delete);
640 cpl_msg_error(fctid,
"Sub-slit data missing in fiber table!");
652 if (variance == NULL) {
653 cpl_array_delete(ssn);
656 cx_slist_destroy(simages, (cx_free_func)cpl_image_delete);
659 cx_slist_destroy(eimages, (cx_free_func)cpl_image_delete);
665 cx_slist_destroy(ecubes, (cx_free_func)giraffe_cube_delete);
671 cpl_msg_error(fctid,
"Failed to create variance map!");
683 _ssn = cpl_array_duplicate(ssn);
685 for (i = 0; i < cpl_array_get_size(_ssn); ++i) {
687 cxbool failed = FALSE;
689 cxint nss = cpl_array_get_int(_ssn, i, NULL);
691 cpl_table* ssf = NULL;
693 cpl_table_unselect_all(_fibers);
694 cpl_table_or_selected_int(_fibers,
"SSN", CPL_EQUAL_TO, nss);
701 cpl_table_and_selected_int(_fibers,
"X", CPL_GREATER_THAN, 0);
702 cpl_table_and_selected_int(_fibers,
"Y", CPL_GREATER_THAN, 0);
704 ssf = cpl_table_extract_selected(_fibers);
706 if ((ssf != NULL) && (cpl_table_get_nrow(ssf) > 0)) {
708 cpl_matrix* transform = NULL;
710 cpl_propertylist* wcs = NULL;
712 cpl_image* _simage = NULL;
713 cpl_image* _eimage = NULL;
715 GiCube* _scube = NULL;
716 GiCube* _ecube = NULL;
719 _scube = _giraffe_fov_create_cube(rebinning->spectra,
726 if (_scube != NULL) {
732 cpl_table_get_double(ssf,
"RA", 0, NULL);
734 cpl_table_get_double(ssf,
"DEC", 0, NULL);
735 cxdouble orientation =
736 cpl_table_get_double(ssf,
"ORIENT", 0, NULL);
738 cxdouble zvalue = 0.;
740 cxdouble angle = GI_IFU_POSANG_OFFSET - orientation;
741 cxdouble pixscale = GI_IFU_PIXSCALE / 3600.;
744 transform = cpl_matrix_new(3, 3);
746 wcs = cpl_propertylist_new();
748 cpl_propertylist_update_double(wcs,
"XORIGIN", xorigin);
749 cpl_propertylist_update_double(wcs,
"YORIGIN", yorigin);
750 cpl_propertylist_update_double(wcs,
"ZORIGIN", 1.);
754 cpl_propertylist_update_double(wcs,
"XPOINT", xvalue);
755 cpl_propertylist_update_double(wcs,
"YPOINT", yvalue);
756 cpl_propertylist_update_double(wcs,
"ZPOINT", zvalue);
758 cpl_propertylist_update_string(wcs,
"XTYPE",
760 cpl_propertylist_update_string(wcs,
"YTYPE",
763 if (log_scale == TRUE) {
764 cpl_propertylist_update_string(wcs,
765 "ZTYPE",
"AWAV-LOG");
768 cpl_propertylist_update_string(wcs,
772 cpl_propertylist_update_string(wcs,
"XUNIT",
"deg");
773 cpl_propertylist_update_string(wcs,
"YUNIT",
"deg");
774 cpl_propertylist_update_string(wcs,
"ZUNIT",
"nm");
783 angle *= CX_PI / 180.;
785 cpl_matrix_set(transform, 0, 0, -pixscale * cos(angle));
786 cpl_matrix_set(transform, 0, 1, pixscale * -sin(angle));
787 cpl_matrix_set(transform, 1, 0, -pixscale * sin(angle));
788 cpl_matrix_set(transform, 1, 1, pixscale * cos(angle));
789 cpl_matrix_set(transform, 2, 2, zstep);
793 if (_scube != NULL) {
794 _simage = _giraffe_fov_integrate_cube(_scube, limits);
797 if ((_scube == NULL) || (_simage == NULL)) {
799 cpl_image_delete(_simage);
807 cpl_msg_error(fctid,
"Cannot create data cube for "
813 cx_slist_push_back(scubes, _scube);
814 cx_slist_push_back(simages, _simage);
819 _ecube = _giraffe_fov_create_cube(variance,
822 if (_ecube != NULL) {
823 _eimage = _giraffe_fov_integrate_cube(_ecube,
827 if ((_ecube == NULL) || (_eimage == NULL)) {
829 cpl_image_delete(_eimage);
837 cpl_msg_error(fctid,
"Cannot create error "
838 "cube for sub-slit %d", nss);
842 cpl_image_power(_eimage, 0.5);
846 cx_slist_push_back(ecubes, _ecube);
847 cx_slist_push_back(eimages, _eimage);
852 cpl_propertylist_delete(wcs);
855 cpl_matrix_delete(transform);
860 cpl_table_delete(ssf);
866 cpl_array_delete(_ssn);
869 cpl_array_delete(ssn);
872 cx_slist_destroy(simages,
873 (cx_free_func)cpl_image_delete);
876 cx_slist_destroy(eimages,
877 (cx_free_func)cpl_image_delete);
880 cx_slist_destroy(scubes,
884 cx_slist_destroy(ecubes,
885 (cx_free_func)giraffe_cube_delete);
899 cpl_msg_debug(fctid,
"Unused IFU button detected. "
900 "Skipping sub-slit %d", nss);
902 cpl_array_set_invalid(_ssn, i);
904 cx_slist_push_back(simages, NULL);
905 cx_slist_push_back(eimages, NULL);
909 cpl_table_delete(ssf);
919 if (cpl_array_count_invalid(_ssn) > 0) {
924 cpl_array_set_size(ssn, cpl_array_get_size(ssn) -
925 cpl_array_count_invalid(_ssn));
927 for (k = 0; k < cpl_array_get_size(_ssn); ++k) {
931 register cxint idx = cpl_array_get_int(_ssn, k, &invalid);
934 cpl_array_set_int(ssn, j, idx);
942 cpl_array_delete(_ssn);
956 smosaic = _giraffe_fov_arrange_images(simages, 5, 3, -4);
957 emosaic = _giraffe_fov_arrange_images(eimages, 5, 3, -4);
959 if ((smosaic == NULL) || (emosaic == NULL)) {
961 cpl_image_delete(smosaic);
964 cpl_image_delete(emosaic);
967 cx_slist_destroy(simages, (cx_free_func)cpl_image_delete);
970 cx_slist_destroy(eimages, (cx_free_func)cpl_image_delete);
976 cx_slist_destroy(ecubes, (cx_free_func)giraffe_cube_delete);
979 cpl_array_delete(ssn);
989 cx_slist_push_front(simages, smosaic);
990 cx_slist_push_front(eimages, emosaic);
997 cxbool failed = FALSE;
999 cpl_image* simage = NULL;
1000 cpl_image* eimage = NULL;
1002 cpl_matrix* transform = NULL;
1004 cpl_propertylist* wcs = NULL;
1006 GiImage* variance = NULL;
1008 GiCube* scube = NULL;
1009 GiCube* ecube = NULL;
1018 if (variance == NULL) {
1020 cx_slist_destroy(simages, (cx_free_func)cpl_image_delete);
1023 cx_slist_destroy(eimages, (cx_free_func)cpl_image_delete);
1029 cx_slist_destroy(ecubes, (cx_free_func)giraffe_cube_delete);
1035 cpl_msg_error(fctid,
"Failed to create variance map!");
1047 scube = _giraffe_fov_create_cube(rebinning->spectra,
1068 if (scube != NULL) {
1073 cxdouble xvalue = cpl_propertylist_get_double(properties,
1075 cxdouble yvalue = cpl_propertylist_get_double(properties,
1077 cxdouble zvalue = 0.;
1078 cxdouble zstep = 0.;
1079 cxdouble angle = -90. -
1080 (cpl_propertylist_get_double(properties,
1082 GI_ARGUS_POSANG_OFFSET);
1084 cxdouble pixscale = GI_ARGUS_PIXSCALE_LOW;
1086 const cxchar* scale =
1087 cpl_propertylist_get_string(properties,
1088 GIALIAS_ARGUS_SCALE);
1091 if ((scale != NULL) && (strcmp(scale,
"POS_1_67") == 0)) {
1092 pixscale = GI_ARGUS_PIXSCALE_HIGH;
1100 transform = cpl_matrix_new(3, 3);
1102 wcs = cpl_propertylist_new();
1104 cpl_propertylist_update_double(wcs,
"XORIGIN", xorigin);
1105 cpl_propertylist_update_double(wcs,
"YORIGIN", yorigin);
1106 cpl_propertylist_update_double(wcs,
"ZORIGIN", 1.);
1110 cpl_propertylist_update_double(wcs,
"XPOINT", xvalue);
1111 cpl_propertylist_update_double(wcs,
"YPOINT", yvalue);
1112 cpl_propertylist_update_double(wcs,
"ZPOINT", zvalue);
1114 cpl_propertylist_update_string(wcs,
"XTYPE",
"RA---TAN");
1115 cpl_propertylist_update_string(wcs,
"YTYPE",
"DEC--TAN");
1117 if (log_scale == TRUE) {
1118 cpl_propertylist_update_string(wcs,
1119 "ZTYPE",
"AWAV-LOG");
1122 cpl_propertylist_update_string(wcs,
1126 cpl_propertylist_update_string(wcs,
"XUNIT",
"deg");
1127 cpl_propertylist_update_string(wcs,
"YUNIT",
"deg");
1128 cpl_propertylist_update_string(wcs,
"ZUNIT",
"nm");
1137 angle *= CX_PI / 180.;
1139 cpl_matrix_set(transform, 0, 0, -pixscale * cos(angle));
1140 cpl_matrix_set(transform, 0, 1, pixscale * -sin(angle));
1141 cpl_matrix_set(transform, 1, 0, -pixscale * sin(angle));
1142 cpl_matrix_set(transform, 1, 1, pixscale * cos(angle));
1143 cpl_matrix_set(transform, 2, 2, zstep);
1148 if (scube != NULL) {
1149 simage = _giraffe_fov_integrate_cube(scube, limits);
1152 if ((scube == NULL) || (simage == NULL)) {
1154 cpl_image_delete(simage);
1162 cpl_msg_error(fctid,
"Cannot create data cube!");
1169 cx_slist_push_back(scubes, scube);
1170 cx_slist_push_back(simages, simage);
1177 ecube = _giraffe_fov_create_cube(variance, _fibers, NULL);
1178 eimage = _giraffe_fov_integrate_cube(ecube, limits);
1180 if ((ecube == NULL) || (eimage == NULL)) {
1182 cpl_image_delete(eimage);
1190 cpl_msg_error(fctid,
"Cannot create error cube!");
1196 cpl_image_power(eimage, 0.5);
1200 cx_slist_push_back(ecubes, ecube);
1201 cx_slist_push_back(eimages, eimage);
1207 cpl_propertylist_delete(wcs);
1210 cpl_matrix_delete(transform);
1218 cx_slist_destroy(simages, (cx_free_func)cpl_image_delete);
1221 cx_slist_destroy(eimages, (cx_free_func)cpl_image_delete);
1227 cx_slist_destroy(ecubes, (cx_free_func)giraffe_cube_delete);
1250 result->mode = mode;
1255 fov = cx_slist_pop_front(simages);
1265 giraffe_propertylist_update_wcs(properties, 0, NULL, NULL, NULL,
1268 cpl_propertylist_update_double(properties, GIALIAS_FOV_BANDMIN,
1270 cpl_propertylist_set_comment(properties, GIALIAS_FOV_BANDMIN,
1271 "Minimum wavelength of FOV band");
1273 cpl_propertylist_update_double(properties, GIALIAS_FOV_BANDMAX,
1275 cpl_propertylist_set_comment(properties, GIALIAS_FOV_BANDMAX,
1276 "Maximum wavelength of FOV band");
1278 cpl_image_delete(fov);
1283 fov = cx_slist_pop_front(eimages);
1293 giraffe_propertylist_update_wcs(properties, 0, NULL, NULL, NULL,
1295 cpl_propertylist_update_double(properties, GIALIAS_FOV_BANDMIN,
1297 cpl_propertylist_set_comment(properties, GIALIAS_FOV_BANDMIN,
1298 "Minimum wavelength of FOV band");
1300 cpl_propertylist_update_double(properties, GIALIAS_FOV_BANDMAX,
1302 cpl_propertylist_set_comment(properties, GIALIAS_FOV_BANDMAX,
1303 "Maximum wavelength of FOV band");
1305 cpl_image_delete(fov);
1308 if (!cx_slist_empty(simages)) {
1310 cx_slist_iterator pos = cx_slist_begin(simages);
1312 result->images.spectra = cx_slist_new();
1314 while (pos != cx_slist_end(simages)) {
1319 cx_slist_push_back(result->images.spectra, image);
1321 pos = cx_slist_next(simages, pos);
1326 if (!cx_slist_empty(eimages)) {
1328 cx_slist_iterator pos = cx_slist_begin(eimages);
1330 result->images.errors = cx_slist_new();
1332 while (pos != cx_slist_end(eimages)) {
1337 cx_slist_push_back(result->images.errors, image);
1339 pos = cx_slist_next(eimages, pos);
1344 if (config->cube == TRUE) {
1346 if (!cx_slist_empty(scubes)) {
1347 result->cubes.spectra = scubes;
1351 if (!cx_slist_empty(ecubes)) {
1352 result->cubes.errors = ecubes;
1366 cx_slist_destroy(simages, (cx_free_func)cpl_image_delete);
1369 cx_slist_destroy(eimages, (cx_free_func)cpl_image_delete);
1372 if (scubes != NULL) {
1377 if (ecubes != NULL) {
1403 GiFieldOfView*
self = cx_malloc(
sizeof *
self);
1405 self->mode = GIMODE_NONE;
1408 self->fov.spectra = NULL;
1409 self->fov.errors = NULL;
1411 self->images.spectra = NULL;
1412 self->images.errors = NULL;
1414 self->cubes.spectra = NULL;
1415 self->cubes.errors = NULL;
1440 if (self->cubes.errors != NULL) {
1441 cx_slist_destroy(self->cubes.errors,
1443 self->cubes.errors = NULL;
1446 if (self->cubes.spectra != NULL) {
1447 cx_slist_destroy(self->cubes.spectra,
1449 self->cubes.spectra = NULL;
1452 if (self->images.errors != NULL) {
1453 cx_slist_destroy(self->images.errors,
1455 self->images.errors = NULL;
1458 if (self->images.spectra != NULL) {
1459 cx_slist_destroy(self->images.spectra,
1461 self->images.spectra = NULL;
1464 if (self->fov.errors != NULL) {
1466 self->fov.errors = NULL;
1469 if (self->fov.spectra != NULL) {
1471 self->fov.spectra = NULL;
1474 if (self->ssn != NULL) {
1475 cpl_array_delete(self->ssn);
1479 self->mode = GIMODE_NONE;
1539 cpl_propertylist* properties,
1540 const cxchar* filename, cxptr data)
1544 cxint component = 0;
1546 cx_slist* cubes = NULL;
1549 if ((
self == NULL) || (properties == NULL) || (filename == NULL)) {
1559 component = *((cxuint*)data);
1562 if (component == 0) {
1563 cubes =
self->cubes.spectra;
1566 cubes =
self->cubes.errors;
1569 if (cubes == NULL) {
1574 if (!cx_slist_empty(cubes)) {
1576 if (self->mode == GIMODE_ARGUS) {
1579 cxint iomode = CPL_IO_CREATE;
1581 GiCube* cube = cx_slist_front(cubes);
1594 cxint iomode = CPL_IO_CREATE;
1596 cx_slist_const_iterator pos = cx_slist_begin(cubes);
1598 cx_string* name = NULL;
1600 cpl_propertylist* xproperties = NULL;
1610 name = cx_string_new();
1611 xproperties = cpl_propertylist_new();
1613 iomode = CPL_IO_EXTEND;
1615 while (pos != cx_slist_end(cubes)) {
1617 cxint ssn = cpl_array_get_int(self->ssn, nss, NULL);
1619 GiCube* cube = cx_slist_get(cubes, pos);
1622 cx_string_sprintf(name,
"SSN%-d", ssn);
1623 cpl_propertylist_update_string(xproperties,
"EXTNAME",
1624 cx_string_get(name));
1631 cpl_propertylist_delete(xproperties);
1634 cx_string_delete(name);
1641 pos = cx_slist_next(cubes, pos);
1646 cpl_propertylist_delete(xproperties);
1649 cx_string_delete(name);
1682 cpl_propertylist* properties,
1683 const cxchar* filename, cxptr data)
1686 const cxchar* data_name =
"SPECTRA";
1687 const cxchar* error_name =
"ERRORS";
1688 const cxchar* link_names[2] = {
"SCIDATA",
"ERRDATA"};
1690 cx_slist* scubes = NULL;
1691 cx_slist* ecubes = NULL;
1699 if ((
self == NULL) || (properties == NULL) || (filename == NULL)) {
1703 if (self->cubes.spectra == NULL) {
1707 if ((cpl_propertylist_has(properties, GIALIAS_EQUINOX) == FALSE) ||
1708 (cpl_propertylist_get_type(properties, GIALIAS_EQUINOX)
1709 != CPL_TYPE_DOUBLE)) {
1719 scubes =
self->cubes.spectra;
1721 if (cx_slist_empty(scubes)) {
1725 if (self->cubes.errors != NULL) {
1727 ecubes =
self->cubes.errors;
1729 if (cx_slist_size(scubes) != cx_slist_size(ecubes)) {
1736 if (self->mode == GIMODE_ARGUS) {
1739 cxint iomode = CPL_IO_CREATE;
1741 cxdouble equinox = cpl_propertylist_get_double(properties,
1744 cpl_propertylist* xproperties = NULL;
1746 GiCube* scube = cx_slist_front(scubes);
1756 iomode = CPL_IO_EXTEND;
1758 xproperties = cpl_propertylist_new();
1760 cpl_propertylist_update_string(xproperties, GIALIAS_EXTNAME, data_name);
1761 cpl_propertylist_set_comment(xproperties, GIALIAS_EXTNAME,
1762 "FITS Extension name");
1764 cpl_propertylist_update_string(xproperties,
"HDUCLASS",
"ESO");
1765 cpl_propertylist_set_comment(xproperties,
"HDUCLASS",
1766 "Conforms to ESO data cube conventions");
1768 cpl_propertylist_update_string(xproperties,
"HDUDOC",
"DICD");
1769 cpl_propertylist_set_comment(xproperties,
"HDUDOC",
1770 "Data format specification document");
1772 cpl_propertylist_update_string(xproperties,
"HDUVERS",
1774 cpl_propertylist_set_comment(xproperties,
"HDUVERS",
1775 "Specific version of the data format "
1778 cpl_propertylist_update_string(xproperties,
"HDUCLAS1",
"IMAGE");
1779 cpl_propertylist_set_comment(xproperties,
"HDUCLAS1",
1780 "Image data format");
1782 cpl_propertylist_update_string(xproperties,
"HDUCLAS2",
"DATA");
1783 cpl_propertylist_set_comment(xproperties,
"HDUCLAS2",
1784 "Science data extension");
1785 cpl_propertylist_update_string(xproperties, link_names[1], error_name);
1786 cpl_propertylist_set_comment(xproperties, link_names[1],
1787 "Linked error data extension");
1789 cpl_propertylist_update_double(xproperties, GIALIAS_EQUINOX,
1797 cpl_propertylist_delete(xproperties);
1804 cpl_propertylist_erase(xproperties, link_names[1]);
1805 cpl_propertylist_erase(xproperties,
"BUNIT");
1806 cpl_propertylist_erase(xproperties,
"DATAMIN");
1807 cpl_propertylist_erase(xproperties,
"DATAMAX");
1810 if (ecubes != NULL) {
1812 GiCube* ecube = cx_slist_front(ecubes);
1815 cpl_propertylist_update_string(xproperties,
"EXTNAME", error_name);
1817 cpl_propertylist_update_string(xproperties,
"HDUCLAS2",
"ERROR");
1818 cpl_propertylist_set_comment(xproperties,
"HDUCLAS2",
1819 "Error data extension");
1821 cpl_propertylist_update_string(xproperties,
"HDUCLAS3",
"RMSE");
1822 cpl_propertylist_set_comment(xproperties,
"HDUCLAS3",
1823 "Type of error: root mean squared");
1825 cpl_propertylist_update_string(xproperties, link_names[0],
1827 cpl_propertylist_set_comment(xproperties, link_names[0],
1828 "Linked science data extension");
1835 cpl_propertylist_delete(xproperties);
1844 cpl_propertylist_delete(xproperties);
1852 cxint iomode = CPL_IO_CREATE;
1854 cxdouble equinox = cpl_propertylist_get_double(properties,
1857 cx_slist_const_iterator spos = cx_slist_begin(scubes);
1858 cx_slist_const_iterator epos = cx_slist_begin(ecubes);
1860 cx_string* name = NULL;
1862 cpl_propertylist* xproperties = NULL;
1872 name = cx_string_new();
1873 xproperties = cpl_propertylist_new();
1875 iomode = CPL_IO_EXTEND;
1877 while (spos != cx_slist_end(scubes)) {
1879 cxint ssn = cpl_array_get_int(self->ssn, nss, NULL);
1881 GiCube* scube = cx_slist_get(scubes, spos);
1884 cx_string_sprintf(name,
"SSN%-d.%s", ssn, data_name);
1886 cpl_propertylist_update_string(xproperties, GIALIAS_EXTNAME,
1887 cx_string_get(name));
1888 cpl_propertylist_set_comment(xproperties, GIALIAS_EXTNAME,
1889 "FITS Extension name");
1891 cpl_propertylist_update_string(xproperties,
"HDUCLASS",
"ESO");
1892 cpl_propertylist_set_comment(xproperties,
"HDUCLASS",
1893 "Conforms to ESO data cube "
1896 cpl_propertylist_update_string(xproperties,
"HDUDOC",
"DICD");
1897 cpl_propertylist_set_comment(xproperties,
"HDUDOC",
1898 "Data format specification document");
1900 cpl_propertylist_update_string(xproperties,
"HDUVERS",
1902 cpl_propertylist_set_comment(xproperties,
"HDUVERS",
1903 "Specific version of the data format "
1906 cpl_propertylist_update_string(xproperties,
"HDUCLAS1",
"IMAGE");
1907 cpl_propertylist_set_comment(xproperties,
"HDUCLAS1",
1908 "Image data format");
1910 cpl_propertylist_update_string(xproperties,
"HDUCLAS2",
"DATA");
1911 cpl_propertylist_set_comment(xproperties,
"HDUCLAS2",
1912 "Science data extension");
1914 cx_string_sprintf(name,
"SSN%-d.%s", ssn, error_name);
1916 cpl_propertylist_update_string(xproperties, link_names[1],
1917 cx_string_get(name));
1918 cpl_propertylist_set_comment(xproperties, link_names[1],
1919 "Linked error data extension");
1921 cpl_propertylist_update_double(xproperties, GIALIAS_EQUINOX,
1929 cpl_propertylist_delete(xproperties);
1932 cx_string_delete(name);
1939 cpl_propertylist_erase(xproperties, link_names[1]);
1940 cpl_propertylist_erase(xproperties,
"BUNIT");
1941 cpl_propertylist_erase(xproperties,
"DATAMIN");
1942 cpl_propertylist_erase(xproperties,
"DATAMAX");
1945 if (ecubes != NULL) {
1947 GiCube* ecube = cx_slist_get(ecubes, epos);
1950 cx_string_sprintf(name,
"SSN%-d.%s", ssn, error_name);
1952 cpl_propertylist_update_string(xproperties,
"EXTNAME",
1953 cx_string_get(name));
1955 cpl_propertylist_update_string(xproperties,
"HDUCLAS2",
"ERROR");
1956 cpl_propertylist_set_comment(xproperties,
"HDUCLAS2",
1957 "Error data extension");
1959 cpl_propertylist_update_string(xproperties,
"HDUCLAS3",
"RMSE");
1960 cpl_propertylist_set_comment(xproperties,
"HDUCLAS3",
1961 "Type of error: root mean squared");
1963 cx_string_sprintf(name,
"SSN%-d.%s", ssn, data_name);
1965 cpl_propertylist_update_string(xproperties, link_names[0],
1966 cx_string_get(name));
1967 cpl_propertylist_set_comment(xproperties, link_names[0],
1968 "Linked science data extension");
1976 cpl_propertylist_delete(xproperties);
1979 cx_string_delete(name);
1986 epos = cx_slist_next(ecubes, epos);
1990 spos = cx_slist_next(scubes, spos);
1995 cpl_propertylist_delete(xproperties);
1998 cx_string_delete(name);
2019 GiFieldOfViewConfig*
2023 const cxchar* s = NULL;
2027 GiFieldOfViewConfig* config = NULL;
2034 config = cx_calloc(1,
sizeof *config);
2037 p = cpl_parameterlist_find(list,
"giraffe.fov.range.minimum");
2038 config->minimum = cpl_parameter_get_double(p);
2040 p = cpl_parameterlist_find(list,
"giraffe.fov.range.maximum");
2041 config->maximum = cpl_parameter_get_double(p);
2043 p = cpl_parameterlist_find(list,
"giraffe.fov.cube");
2044 config->cube = cpl_parameter_get_bool(p);
2046 p = cpl_parameterlist_find(list,
"giraffe.fov.cube.format");
2047 s = cpl_parameter_get_string(p);
2049 if (strcmp(s,
"single") == 0) {
2050 config->format = GIFOV_FORMAT_SINGLE;
2052 else if (strcmp(s,
"eso3d") == 0) {
2053 config->format = GIFOV_FORMAT_ESO3D;
2078 if (config != NULL) {
2107 p = cpl_parameter_new_value(
"giraffe.fov.range.minimum",
2109 "Minimum wavelength for image reconstruction",
2110 "giraffe.fov.range",
2112 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"recon-min");
2113 cpl_parameterlist_append(list, p);
2116 p = cpl_parameter_new_value(
"giraffe.fov.range.maximum",
2118 "Maximum wavelength for image reconstruction",
2119 "giraffe.fov.range",
2121 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"recon-max");
2122 cpl_parameterlist_append(list, p);
2125 p = cpl_parameter_new_value(
"giraffe.fov.cube",
2127 "Turns data cube creation on and off",
2130 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"recon-cube");
2131 cpl_parameterlist_append(list, p);
2133 p = cpl_parameter_new_enum(
"giraffe.fov.cube.format",
2135 "Selects the file format for cubes",
2137 "single", 2,
"single",
"eso3d");
2138 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"recon-format");
2139 cpl_parameterlist_append(list, p);
cxdouble giraffe_range_get_min(const GiRange *const self)
Get the minimum of a range.
GiFieldOfView * giraffe_fov_new(void)
Create an empty container for the results of the field of view reconstruction.
cxsize giraffe_cube_get_height(const GiCube *self)
Get the height of the given data cube.
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_image_set(GiImage *self, cpl_image *image)
Sets the image data.
void giraffe_fov_config_add(cpl_parameterlist *list)
Adds parameters for the image and data cube construction.
void giraffe_fov_clear(GiFieldOfView *self)
Delete the contents of a field of view object.
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.
cpl_table * giraffe_table_get(const GiTable *self)
Get the table data from a Giraffe table.
void giraffe_range_set_min(GiRange *self, cxdouble min)
Set the minimum of a range.
cxsize giraffe_cube_get_depth(const GiCube *self)
Get the depth of the given data cube.
cxint giraffe_cube_save(const GiCube *self, cpl_propertylist *properties, const cxchar *filename, cxcptr data)
Save the given data cube to disk.
void giraffe_range_set_max(GiRange *self, cxdouble max)
Set the maximum of a range.
cxint giraffe_cube_set_wcs(GiCube *self, const cpl_propertylist *axes, const cpl_matrix *transformation)
Set the data cube's world coordinate system.
void giraffe_image_delete(GiImage *self)
Destroys an image.
GiImage * giraffe_image_duplicate(const GiImage *self)
Creates a copy of an image.
cxdouble * giraffe_cube_get_data(const GiCube *self)
Get a reference to the data cube's pixel buffer.
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_cube_set_zaxis(GiCube *self, cxdouble start, cxdouble step)
Set the data cube's z-axis start value and step size.
GiImage * giraffe_image_new(cpl_type type)
Creates an empty image container.
cxint giraffe_cube_set_xaxis(GiCube *self, cxdouble start, cxdouble step)
Set the data cube's x-axis start value and step size.
cxsize giraffe_cube_get_width(const GiCube *self)
Get the width of the given data cube.
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.
cxint giraffe_cube_get_zaxis(const GiCube *self, cxdouble *start, cxdouble *step)
Get the data cube's z-axis start value and step size.
void giraffe_cube_delete(GiCube *self)
Destroys a cube object.
cpl_array * giraffe_fiberlist_get_subslits(const cpl_table *fibers)
Get the list of subslit identifiers from a fiber setup.
cpl_image * giraffe_image_get(const GiImage *self)
Gets the image data.
cxint giraffe_cube_sqrt(GiCube *self)
Compute the square root of the elements of a cube.
cxint giraffe_image_set_properties(GiImage *self, cpl_propertylist *properties)
Attaches a property list to an image.
GiRange * giraffe_rebin_get_wavelength_range(GiImage *spectra, GiTable *wlsolution, GiTable *grating, GiTable *slitgeometry, cxbool common)
Compute the wavelenght range of spectra.
void giraffe_range_delete(GiRange *self)
Destroys a range object.
cpl_propertylist * giraffe_image_get_properties(const GiImage *self)
Get the properties of an image.
cxdouble giraffe_range_get_max(const GiRange *const self)
Get the maximum of a range.
void giraffe_fov_config_destroy(GiFieldOfViewConfig *config)
Destroys a field of view setup structure.
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_yaxis(GiCube *self, cxdouble start, cxdouble step)
Set the data cube's y-axis start value and step size.
cpl_image * giraffe_cube_integrate(const GiCube *self, cxdouble start, cxdouble end)
Integrate a cube along the z-axis.