35 #include <cxstrutils.h>
37 #include <cpl_array.h>
38 #include <cpl_propertylist.h>
43 #include "gimessages.h"
44 #include "gigrating.h"
46 #include "gifiberutils.h"
61 _giraffe_compare_int(cxcptr first, cxcptr second)
64 cxint *_first = (cxint *)first;
65 cxint *_second = (cxint *)second;
67 return *_first - *_second;
73 _giraffe_fov_create_cube(
const GiImage* spectra,
74 const cpl_table* fibers,
75 const GiRange* limits)
97 if ((properties == NULL) || (_spectra == NULL)) {
106 if (cpl_propertylist_has(properties, GIALIAS_BINWLMIN) == FALSE) {
110 wmin = cpl_propertylist_get_double(properties, GIALIAS_BINWLMIN);
113 if (cpl_propertylist_has(properties, GIALIAS_BINWLMAX) == FALSE) {
117 wmax = cpl_propertylist_get_double(properties, GIALIAS_BINWLMAX);
120 if (cpl_propertylist_has(properties, GIALIAS_BINSTEP) == FALSE) {
124 wstep = cpl_propertylist_get_double(properties, GIALIAS_BINSTEP);
133 last = cpl_image_get_size_y(_spectra) - 1;
135 if (limits != NULL) {
143 fstart = pixel - first;
164 giraffe_error_push();
166 nx = (cxint) cpl_table_get_column_max(fibers,
"X");
167 ny = (cxint) cpl_table_get_column_max(fibers,
"Y");
169 if (cpl_error_get_code() == CPL_ERROR_DATA_NOT_FOUND) {
176 nz = last - first + 1;
195 register cxint i = 0;
196 register cxint nf = cpl_table_get_nrow(fibers);
198 cxint ns = cpl_image_get_size_x(_spectra);
200 cxdouble* spixels = cpl_image_get_data_double(_spectra);
204 cx_assert(spixels != NULL);
205 cx_assert(cpixels != NULL);
208 for (i = 0; i < nf; ++i) {
210 register cxint j = 0;
212 cxint idx = cpl_table_get_int(fibers,
"INDEX", i, NULL) - 1;
213 cxint x = cpl_table_get_int(fibers,
"X", i, NULL) - 1;
214 cxint y = cpl_table_get_int(fibers,
"Y", i, NULL) - 1;
222 if ((x >= 0) && (y >= 0)) {
224 for (j = 0; j < nz; ++j) {
225 cpixels[(ny * j + y) * nx + x] =
226 spixels[(first + j) * ns + idx];
244 inline static cpl_image*
245 _giraffe_fov_arrange_images(
const cx_slist* subimages,
246 cxsize nrows, cxsize ncolumns, cxint offset)
255 cxint xshift = offset;
256 cxint yshift = offset;
261 cx_slist_iterator pos;
263 cpl_image* image = NULL;
266 cx_assert(subimages != NULL);
267 cx_assert(nrows > 0);
268 cx_assert(ncolumns > 0);
277 pos = cx_slist_begin(subimages);
279 while (pos != cx_slist_end(subimages)) {
281 const cpl_image* simage = cx_slist_get(subimages, pos);
283 if (simage != NULL) {
285 cxint _nx = cpl_image_get_size_x(simage);
286 cxint _ny = cpl_image_get_size_y(simage);
288 sx = CX_MAX(nx, _nx);
289 sy = CX_MAX(ny, _ny);
293 pos = cx_slist_next(subimages, pos);
302 nslit = cx_slist_size(subimages);
303 nrows = CX_MAX(nslit / ncolumns, nrows);
305 if (nslit % ncolumns != 0) {
319 xshift = nx / -offset + 1;
320 yshift = ny / -offset + 1;
323 nx += ncolumns * xshift - (xshift % 2);
324 ny += nrows * yshift - (yshift % 2);
331 image = cpl_image_new(nx, ny, CPL_TYPE_DOUBLE);
336 pos = cx_slist_begin(subimages);
338 while (pos != cx_slist_end(subimages)) {
340 const cpl_image* simage = cx_slist_get(subimages, pos);
342 if (simage != NULL) {
344 cpl_error_code status = cpl_image_copy(image, simage,
347 if (status != CPL_ERROR_NONE) {
348 cpl_image_delete(image);
356 if (column < ncolumns) {
366 pos = cx_slist_next(subimages, pos);
375 inline static cpl_image*
376 _giraffe_fov_integrate_cube(
const GiCube* cube,
const GiRange* limits)
387 cpl_image* image = NULL;
390 cx_assert(cube != NULL);
395 wmax = wmin + depth * wstep;
436 GiTable* fibers, GiTable* wsolution,
437 GiTable* grating, GiTable* slitgeometry,
438 GiFieldOfViewConfig* config)
441 const cxchar*
const fctid =
"giraffe_fov_build";
443 cxbool log_scale = FALSE;
445 cx_slist* simages = NULL;
446 cx_slist* eimages = NULL;
447 cx_slist* scubes = NULL;
448 cx_slist* ecubes = NULL;
450 cpl_propertylist* properties = NULL;
452 cpl_array* ssn = NULL;
454 cpl_image* fov = NULL;
456 cpl_table* _fibers = NULL;
458 GiInstrumentMode mode;
460 GiRange* limits = NULL;
463 if (result == NULL) {
464 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
477 if (rebinning == NULL) {
478 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
482 if (rebinning->spectra == NULL || rebinning->errors == NULL) {
483 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
487 if (fibers == NULL) {
488 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
494 if (_fibers == NULL) {
495 cpl_error_set(fctid, CPL_ERROR_DATA_NOT_FOUND);
499 if (!cpl_table_has_column(_fibers,
"X") ||
500 !cpl_table_has_column(_fibers,
"Y")) {
501 cpl_error_set(fctid, CPL_ERROR_DATA_NOT_FOUND);
505 if (config == NULL) {
506 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
520 if (properties == NULL) {
521 cpl_error_set(fctid, CPL_ERROR_DATA_NOT_FOUND);
536 grating, slitgeometry, TRUE);
538 if (limits == NULL) {
539 cpl_msg_error(fctid,
"Computation of spectra common wavelength "
544 if (config->minimum > 0.) {
546 cpl_msg_warning(fctid,
"Ignoring invalid wavelength range "
547 "minimum %.3f nm", config->minimum);
554 if (config->maximum > 0.) {
556 cpl_msg_warning(fctid,
"Ignoring invalid wavelength range "
557 "maximum %.3f nm", config->maximum);
564 cpl_msg_info(fctid,
"Building image for wavelength range [%.3f nm, "
573 if (cpl_propertylist_has(properties, GIALIAS_BINSCALE)) {
575 const cxchar* s = cpl_propertylist_get_string(properties,
578 if (cx_strncasecmp(s,
"log", 3) == 0) {
586 cpl_msg_warning(fctid,
"Could not determine spectrum wavelength "
587 "scaling method. Missing property `%s'. Assuming "
588 "scaling method `linear'!", GIALIAS_BINSCALE);
597 simages = cx_slist_new();
598 eimages = cx_slist_new();
599 scubes = cx_slist_new();
600 ecubes = cx_slist_new();
609 cpl_array* _ssn = NULL;
611 cpl_image* smosaic = NULL;
612 cpl_image* emosaic = NULL;
614 GiImage* variance = NULL;
624 cx_slist_destroy(simages, (cx_free_func)cpl_image_delete);
627 cx_slist_destroy(eimages, (cx_free_func)cpl_image_delete);
633 cx_slist_destroy(ecubes, (cx_free_func)giraffe_cube_delete);
639 cpl_msg_error(fctid,
"Sub-slit data missing in fiber table!");
651 if (variance == NULL) {
652 cpl_array_delete(ssn);
655 cx_slist_destroy(simages, (cx_free_func)cpl_image_delete);
658 cx_slist_destroy(eimages, (cx_free_func)cpl_image_delete);
664 cx_slist_destroy(ecubes, (cx_free_func)giraffe_cube_delete);
670 cpl_msg_error(fctid,
"Failed to create variance map!");
682 _ssn = cpl_array_duplicate(ssn);
684 for (i = 0; i < cpl_array_get_size(_ssn); ++i) {
686 cxbool failed = FALSE;
688 cxint nss = cpl_array_get_int(_ssn, i, NULL);
690 cpl_table* ssf = NULL;
692 cpl_table_unselect_all(_fibers);
693 cpl_table_or_selected_int(_fibers,
"SSN", CPL_EQUAL_TO, nss);
700 cpl_table_and_selected_int(_fibers,
"X", CPL_GREATER_THAN, 0);
701 cpl_table_and_selected_int(_fibers,
"Y", CPL_GREATER_THAN, 0);
703 ssf = cpl_table_extract_selected(_fibers);
705 if ((ssf != NULL) && (cpl_table_get_nrow(ssf) > 0)) {
707 cpl_matrix* transform = NULL;
709 cpl_propertylist* wcs = NULL;
711 cpl_image* _simage = NULL;
712 cpl_image* _eimage = NULL;
714 GiCube* _scube = NULL;
715 GiCube* _ecube = NULL;
718 _scube = _giraffe_fov_create_cube(rebinning->spectra,
725 if (_scube != NULL) {
731 cpl_table_get_double(ssf,
"RA", 0, NULL);
733 cpl_table_get_double(ssf,
"DEC", 0, NULL);
734 cxdouble orientation =
735 cpl_table_get_double(ssf,
"ORIENT", 0, NULL);
737 cxdouble zvalue = 0.;
739 cxdouble angle = GI_IFU_POSANG_OFFSET - orientation;
740 cxdouble pixscale = GI_IFU_PIXSCALE / 3600.;
743 transform = cpl_matrix_new(3, 3);
745 wcs = cpl_propertylist_new();
747 cpl_propertylist_update_double(wcs,
"XORIGIN", xorigin);
748 cpl_propertylist_update_double(wcs,
"YORIGIN", yorigin);
749 cpl_propertylist_update_double(wcs,
"ZORIGIN", 1.);
753 cpl_propertylist_update_double(wcs,
"XPOINT", xvalue);
754 cpl_propertylist_update_double(wcs,
"YPOINT", yvalue);
755 cpl_propertylist_update_double(wcs,
"ZPOINT", zvalue);
757 cpl_propertylist_update_string(wcs,
"XTYPE",
759 cpl_propertylist_update_string(wcs,
"YTYPE",
762 if (log_scale == TRUE) {
763 cpl_propertylist_update_string(wcs,
764 "ZTYPE",
"AWAV-LOG");
767 cpl_propertylist_update_string(wcs,
771 cpl_propertylist_update_string(wcs,
"XUNIT",
"deg");
772 cpl_propertylist_update_string(wcs,
"YUNIT",
"deg");
773 cpl_propertylist_update_string(wcs,
"ZUNIT",
"nm");
782 angle *= CX_PI / 180.;
784 cpl_matrix_set(transform, 0, 0, -pixscale * cos(angle));
785 cpl_matrix_set(transform, 0, 1, pixscale * -sin(angle));
786 cpl_matrix_set(transform, 1, 0, -pixscale * sin(angle));
787 cpl_matrix_set(transform, 1, 1, pixscale * cos(angle));
788 cpl_matrix_set(transform, 2, 2, zstep);
792 if (_scube != NULL) {
793 _simage = _giraffe_fov_integrate_cube(_scube, limits);
796 if ((_scube == NULL) || (_simage == NULL)) {
798 cpl_image_delete(_simage);
806 cpl_msg_error(fctid,
"Cannot create data cube for "
812 cx_slist_push_back(scubes, _scube);
813 cx_slist_push_back(simages, _simage);
818 _ecube = _giraffe_fov_create_cube(variance,
821 if (_ecube != NULL) {
822 _eimage = _giraffe_fov_integrate_cube(_ecube,
826 if ((_ecube == NULL) || (_eimage == NULL)) {
828 cpl_image_delete(_eimage);
836 cpl_msg_error(fctid,
"Cannot create error "
837 "cube for sub-slit %d", nss);
841 cpl_image_power(_eimage, 0.5);
845 cx_slist_push_back(ecubes, _ecube);
846 cx_slist_push_back(eimages, _eimage);
851 cpl_propertylist_delete(wcs);
854 cpl_matrix_delete(transform);
859 cpl_table_delete(ssf);
865 cpl_array_delete(_ssn);
868 cpl_array_delete(ssn);
871 cx_slist_destroy(simages,
872 (cx_free_func)cpl_image_delete);
875 cx_slist_destroy(eimages,
876 (cx_free_func)cpl_image_delete);
879 cx_slist_destroy(scubes,
883 cx_slist_destroy(ecubes,
884 (cx_free_func)giraffe_cube_delete);
898 cpl_msg_debug(fctid,
"Unused IFU button detected. "
899 "Skipping sub-slit %d", nss);
901 cpl_array_erase_window(ssn, i, 1);
903 cx_slist_push_back(simages, NULL);
904 cx_slist_push_back(eimages, NULL);
908 cpl_table_delete(ssf);
913 cpl_array_delete(_ssn);
927 smosaic = _giraffe_fov_arrange_images(simages, 5, 3, -4);
928 emosaic = _giraffe_fov_arrange_images(eimages, 5, 3, -4);
930 if ((smosaic == NULL) || (emosaic == NULL)) {
932 cpl_image_delete(smosaic);
935 cpl_image_delete(emosaic);
938 cx_slist_destroy(simages, (cx_free_func)cpl_image_delete);
941 cx_slist_destroy(eimages, (cx_free_func)cpl_image_delete);
947 cx_slist_destroy(ecubes, (cx_free_func)giraffe_cube_delete);
950 cpl_array_delete(ssn);
960 cx_slist_push_front(simages, smosaic);
961 cx_slist_push_front(eimages, emosaic);
968 cxbool failed = FALSE;
970 cpl_image* simage = NULL;
971 cpl_image* eimage = NULL;
973 cpl_matrix* transform = NULL;
975 cpl_propertylist* wcs = NULL;
977 GiImage* variance = NULL;
979 GiCube* scube = NULL;
980 GiCube* ecube = NULL;
989 if (variance == NULL) {
991 cx_slist_destroy(simages, (cx_free_func)cpl_image_delete);
994 cx_slist_destroy(eimages, (cx_free_func)cpl_image_delete);
1000 cx_slist_destroy(ecubes, (cx_free_func)giraffe_cube_delete);
1006 cpl_msg_error(fctid,
"Failed to create variance map!");
1018 scube = _giraffe_fov_create_cube(rebinning->spectra,
1039 if (scube != NULL) {
1044 cxdouble xvalue = cpl_propertylist_get_double(properties,
1046 cxdouble yvalue = cpl_propertylist_get_double(properties,
1048 cxdouble zvalue = 0.;
1049 cxdouble zstep = 0.;
1050 cxdouble angle = -90. -
1051 (cpl_propertylist_get_double(properties,
1053 GI_ARGUS_POSANG_OFFSET);
1055 cxdouble pixscale = GI_ARGUS_PIXSCALE_LOW;
1057 const cxchar* scale =
1058 cpl_propertylist_get_string(properties,
1059 GIALIAS_ARGUS_SCALE);
1062 if ((scale != NULL) && (strcmp(scale,
"POS_1_67") == 0)) {
1063 pixscale = GI_ARGUS_PIXSCALE_HIGH;
1071 transform = cpl_matrix_new(3, 3);
1073 wcs = cpl_propertylist_new();
1075 cpl_propertylist_update_double(wcs,
"XORIGIN", xorigin);
1076 cpl_propertylist_update_double(wcs,
"YORIGIN", yorigin);
1077 cpl_propertylist_update_double(wcs,
"ZORIGIN", 1.);
1081 cpl_propertylist_update_double(wcs,
"XPOINT", xvalue);
1082 cpl_propertylist_update_double(wcs,
"YPOINT", yvalue);
1083 cpl_propertylist_update_double(wcs,
"ZPOINT", zvalue);
1085 cpl_propertylist_update_string(wcs,
"XTYPE",
"RA---TAN");
1086 cpl_propertylist_update_string(wcs,
"YTYPE",
"DEC--TAN");
1088 if (log_scale == TRUE) {
1089 cpl_propertylist_update_string(wcs,
1090 "ZTYPE",
"AWAV-LOG");
1093 cpl_propertylist_update_string(wcs,
1097 cpl_propertylist_update_string(wcs,
"XUNIT",
"deg");
1098 cpl_propertylist_update_string(wcs,
"YUNIT",
"deg");
1099 cpl_propertylist_update_string(wcs,
"ZUNIT",
"nm");
1108 angle *= CX_PI / 180.;
1110 cpl_matrix_set(transform, 0, 0, -pixscale * cos(angle));
1111 cpl_matrix_set(transform, 0, 1, pixscale * -sin(angle));
1112 cpl_matrix_set(transform, 1, 0, -pixscale * sin(angle));
1113 cpl_matrix_set(transform, 1, 1, pixscale * cos(angle));
1114 cpl_matrix_set(transform, 2, 2, zstep);
1119 if (scube != NULL) {
1120 simage = _giraffe_fov_integrate_cube(scube, limits);
1123 if ((scube == NULL) || (simage == NULL)) {
1125 cpl_image_delete(simage);
1133 cpl_msg_error(fctid,
"Cannot create data cube!");
1140 cx_slist_push_back(scubes, scube);
1141 cx_slist_push_back(simages, simage);
1148 ecube = _giraffe_fov_create_cube(variance, _fibers, NULL);
1149 eimage = _giraffe_fov_integrate_cube(ecube, limits);
1151 if ((ecube == NULL) || (eimage == NULL)) {
1153 cpl_image_delete(eimage);
1161 cpl_msg_error(fctid,
"Cannot create error cube!");
1167 cpl_image_power(eimage, 0.5);
1171 cx_slist_push_back(ecubes, ecube);
1172 cx_slist_push_back(eimages, eimage);
1178 cpl_propertylist_delete(wcs);
1181 cpl_matrix_delete(transform);
1189 cx_slist_destroy(simages, (cx_free_func)cpl_image_delete);
1192 cx_slist_destroy(eimages, (cx_free_func)cpl_image_delete);
1198 cx_slist_destroy(ecubes, (cx_free_func)giraffe_cube_delete);
1221 result->mode = mode;
1226 fov = cx_slist_pop_front(simages);
1236 giraffe_propertylist_update_wcs(properties, 0, NULL, NULL, NULL,
1239 cpl_propertylist_update_double(properties, GIALIAS_FOV_BANDMIN,
1241 cpl_propertylist_set_comment(properties, GIALIAS_FOV_BANDMIN,
1242 "Minimum wavelength of FOV band");
1244 cpl_propertylist_update_double(properties, GIALIAS_FOV_BANDMAX,
1246 cpl_propertylist_set_comment(properties, GIALIAS_FOV_BANDMAX,
1247 "Maximum wavelength of FOV band");
1249 cpl_image_delete(fov);
1254 fov = cx_slist_pop_front(eimages);
1264 giraffe_propertylist_update_wcs(properties, 0, NULL, NULL, NULL,
1266 cpl_propertylist_update_double(properties, GIALIAS_FOV_BANDMIN,
1268 cpl_propertylist_set_comment(properties, GIALIAS_FOV_BANDMIN,
1269 "Minimum wavelength of FOV band");
1271 cpl_propertylist_update_double(properties, GIALIAS_FOV_BANDMAX,
1273 cpl_propertylist_set_comment(properties, GIALIAS_FOV_BANDMAX,
1274 "Maximum wavelength of FOV band");
1276 cpl_image_delete(fov);
1279 if (!cx_slist_empty(simages)) {
1281 cx_slist_iterator pos = cx_slist_begin(simages);
1283 result->images.spectra = cx_slist_new();
1285 while (pos != cx_slist_end(simages)) {
1290 cx_slist_push_back(result->images.spectra, image);
1292 pos = cx_slist_next(simages, pos);
1297 if (!cx_slist_empty(eimages)) {
1299 cx_slist_iterator pos = cx_slist_begin(eimages);
1301 result->images.errors = cx_slist_new();
1303 while (pos != cx_slist_end(eimages)) {
1308 cx_slist_push_back(result->images.errors, image);
1310 pos = cx_slist_next(eimages, pos);
1315 if (config->cube == TRUE) {
1317 if (!cx_slist_empty(scubes)) {
1318 result->cubes.spectra = scubes;
1322 if (!cx_slist_empty(ecubes)) {
1323 result->cubes.errors = ecubes;
1337 cx_slist_destroy(simages, (cx_free_func)cpl_image_delete);
1340 cx_slist_destroy(eimages, (cx_free_func)cpl_image_delete);
1343 if (scubes != NULL) {
1348 if (ecubes != NULL) {
1374 GiFieldOfView*
self = cx_malloc(
sizeof *
self);
1376 self->mode = GIMODE_NONE;
1379 self->fov.spectra = NULL;
1380 self->fov.errors = NULL;
1382 self->images.spectra = NULL;
1383 self->images.errors = NULL;
1385 self->cubes.spectra = NULL;
1386 self->cubes.errors = NULL;
1411 if (self->cubes.errors != NULL) {
1412 cx_slist_destroy(self->cubes.errors,
1414 self->cubes.errors = NULL;
1417 if (self->cubes.spectra != NULL) {
1418 cx_slist_destroy(self->cubes.spectra,
1420 self->cubes.spectra = NULL;
1423 if (self->images.errors != NULL) {
1424 cx_slist_destroy(self->images.errors,
1426 self->images.errors = NULL;
1429 if (self->images.spectra != NULL) {
1430 cx_slist_destroy(self->images.spectra,
1432 self->images.spectra = NULL;
1435 if (self->fov.errors != NULL) {
1437 self->fov.errors = NULL;
1440 if (self->fov.spectra != NULL) {
1442 self->fov.spectra = NULL;
1445 if (self->ssn != NULL) {
1446 cpl_array_delete(self->ssn);
1450 self->mode = GIMODE_NONE;
1510 cpl_propertylist* properties,
1511 const cxchar* filename, cxptr data)
1515 cxint component = 0;
1517 cx_slist* cubes = NULL;
1520 if ((
self == NULL) || (properties == NULL) || (filename == NULL)) {
1530 component = *((cxuint*)data);
1533 if (component == 0) {
1534 cubes =
self->cubes.spectra;
1537 cubes =
self->cubes.errors;
1540 if (cubes == NULL) {
1545 if (!cx_slist_empty(cubes)) {
1547 if (self->mode == GIMODE_ARGUS) {
1550 cxint iomode = CPL_IO_CREATE;
1552 GiCube* cube = cx_slist_front(cubes);
1565 cxint iomode = CPL_IO_CREATE;
1567 cx_slist_const_iterator pos = cx_slist_begin(cubes);
1569 cx_string* name = NULL;
1571 cpl_propertylist* xproperties = NULL;
1581 name = cx_string_new();
1582 xproperties = cpl_propertylist_new();
1584 iomode = CPL_IO_EXTEND;
1586 while (pos != cx_slist_end(cubes)) {
1588 cxint ssn = cpl_array_get_int(self->ssn, nss, NULL);
1590 GiCube* cube = cx_slist_get(cubes, pos);
1593 cx_string_sprintf(name,
"SSN%-d", ssn);
1594 cpl_propertylist_update_string(xproperties,
"EXTNAME",
1595 cx_string_get(name));
1602 cpl_propertylist_delete(xproperties);
1605 cx_string_delete(name);
1612 pos = cx_slist_next(cubes, pos);
1617 cpl_propertylist_delete(xproperties);
1620 cx_string_delete(name);
1653 cpl_propertylist* properties,
1654 const cxchar* filename, cxptr data)
1657 const cxchar* data_name =
"SPECTRA";
1658 const cxchar* error_name =
"ERRORS";
1659 const cxchar* link_names[2] = {
"SCIDATA",
"ERRDATA"};
1661 cx_slist* scubes = NULL;
1662 cx_slist* ecubes = NULL;
1670 if ((
self == NULL) || (properties == NULL) || (filename == NULL)) {
1674 if (self->cubes.spectra == NULL) {
1678 if ((cpl_propertylist_has(properties, GIALIAS_EQUINOX) == FALSE) ||
1679 (cpl_propertylist_get_type(properties, GIALIAS_EQUINOX)
1680 != CPL_TYPE_DOUBLE)) {
1690 scubes =
self->cubes.spectra;
1692 if (cx_slist_empty(scubes)) {
1696 if (self->cubes.errors != NULL) {
1698 ecubes =
self->cubes.errors;
1700 if (cx_slist_size(scubes) != cx_slist_size(ecubes)) {
1707 if (self->mode == GIMODE_ARGUS) {
1710 cxint iomode = CPL_IO_CREATE;
1712 cxdouble equinox = cpl_propertylist_get_double(properties,
1715 cpl_propertylist* xproperties = NULL;
1717 GiCube* scube = cx_slist_front(scubes);
1727 iomode = CPL_IO_EXTEND;
1729 xproperties = cpl_propertylist_new();
1731 cpl_propertylist_update_string(xproperties, GIALIAS_EXTNAME, data_name);
1732 cpl_propertylist_set_comment(xproperties, GIALIAS_EXTNAME,
1733 "FITS Extension name");
1735 cpl_propertylist_update_string(xproperties,
"HDUCLASS",
"ESO");
1736 cpl_propertylist_set_comment(xproperties,
"HDUCLASS",
1737 "Conforms to ESO data cube conventions");
1739 cpl_propertylist_update_string(xproperties,
"HDUDOC",
"DICD");
1740 cpl_propertylist_set_comment(xproperties,
"HDUDOC",
1741 "Data format specification document");
1743 cpl_propertylist_update_string(xproperties,
"HDUVERS",
1745 cpl_propertylist_set_comment(xproperties,
"HDUVERS",
1746 "Specific version of the data format "
1749 cpl_propertylist_update_string(xproperties,
"HDUCLAS1",
"IMAGE");
1750 cpl_propertylist_set_comment(xproperties,
"HDUCLAS1",
1751 "Image data format");
1753 cpl_propertylist_update_string(xproperties,
"HDUCLAS2",
"DATA");
1754 cpl_propertylist_set_comment(xproperties,
"HDUCLAS2",
1755 "Science data extension");
1756 cpl_propertylist_update_string(xproperties, link_names[1], error_name);
1757 cpl_propertylist_set_comment(xproperties, link_names[1],
1758 "Linked error data extension");
1760 cpl_propertylist_update_double(xproperties, GIALIAS_EQUINOX,
1768 cpl_propertylist_delete(xproperties);
1775 cpl_propertylist_erase(xproperties, link_names[1]);
1776 cpl_propertylist_erase(xproperties,
"BUNIT");
1777 cpl_propertylist_erase(xproperties,
"DATAMIN");
1778 cpl_propertylist_erase(xproperties,
"DATAMAX");
1781 if (ecubes != NULL) {
1783 GiCube* ecube = cx_slist_front(ecubes);
1786 cpl_propertylist_update_string(xproperties,
"EXTNAME", error_name);
1788 cpl_propertylist_update_string(xproperties,
"HDUCLAS2",
"ERROR");
1789 cpl_propertylist_set_comment(xproperties,
"HDUCLAS2",
1790 "Error data extension");
1792 cpl_propertylist_update_string(xproperties,
"HDUCLAS3",
"RMSE");
1793 cpl_propertylist_set_comment(xproperties,
"HDUCLAS3",
1794 "Type of error: root mean squared");
1796 cpl_propertylist_update_string(xproperties, link_names[0],
1798 cpl_propertylist_set_comment(xproperties, link_names[0],
1799 "Linked science data extension");
1806 cpl_propertylist_delete(xproperties);
1815 cpl_propertylist_delete(xproperties);
1823 cxint iomode = CPL_IO_CREATE;
1825 cxdouble equinox = cpl_propertylist_get_double(properties,
1828 cx_slist_const_iterator spos = cx_slist_begin(scubes);
1829 cx_slist_const_iterator epos = cx_slist_begin(ecubes);
1831 cx_string* name = NULL;
1833 cpl_propertylist* xproperties = NULL;
1843 name = cx_string_new();
1844 xproperties = cpl_propertylist_new();
1846 iomode = CPL_IO_EXTEND;
1848 while (spos != cx_slist_end(scubes)) {
1850 cxint ssn = cpl_array_get_int(self->ssn, nss, NULL);
1852 GiCube* scube = cx_slist_get(scubes, spos);
1855 cx_string_sprintf(name,
"SSN%-d.%s", ssn, data_name);
1857 cpl_propertylist_update_string(xproperties, GIALIAS_EXTNAME,
1858 cx_string_get(name));
1859 cpl_propertylist_set_comment(xproperties, GIALIAS_EXTNAME,
1860 "FITS Extension name");
1862 cpl_propertylist_update_string(xproperties,
"HDUCLASS",
"ESO");
1863 cpl_propertylist_set_comment(xproperties,
"HDUCLASS",
1864 "Conforms to ESO data cube "
1867 cpl_propertylist_update_string(xproperties,
"HDUDOC",
"DICD");
1868 cpl_propertylist_set_comment(xproperties,
"HDUDOC",
1869 "Data format specification document");
1871 cpl_propertylist_update_string(xproperties,
"HDUVERS",
1873 cpl_propertylist_set_comment(xproperties,
"HDUVERS",
1874 "Specific version of the data format "
1877 cpl_propertylist_update_string(xproperties,
"HDUCLAS1",
"IMAGE");
1878 cpl_propertylist_set_comment(xproperties,
"HDUCLAS1",
1879 "Image data format");
1881 cpl_propertylist_update_string(xproperties,
"HDUCLAS2",
"DATA");
1882 cpl_propertylist_set_comment(xproperties,
"HDUCLAS2",
1883 "Science data extension");
1885 cx_string_sprintf(name,
"SSN%-d.%s", ssn, error_name);
1887 cpl_propertylist_update_string(xproperties, link_names[1],
1888 cx_string_get(name));
1889 cpl_propertylist_set_comment(xproperties, link_names[1],
1890 "Linked error data extension");
1892 cpl_propertylist_update_double(xproperties, GIALIAS_EQUINOX,
1900 cpl_propertylist_delete(xproperties);
1903 cx_string_delete(name);
1910 cpl_propertylist_erase(xproperties, link_names[1]);
1911 cpl_propertylist_erase(xproperties,
"BUNIT");
1912 cpl_propertylist_erase(xproperties,
"DATAMIN");
1913 cpl_propertylist_erase(xproperties,
"DATAMAX");
1916 if (ecubes != NULL) {
1918 GiCube* ecube = cx_slist_get(ecubes, epos);
1921 cx_string_sprintf(name,
"SSN%-d.%s", ssn, error_name);
1923 cpl_propertylist_update_string(xproperties,
"EXTNAME",
1924 cx_string_get(name));
1926 cpl_propertylist_update_string(xproperties,
"HDUCLAS2",
"ERROR");
1927 cpl_propertylist_set_comment(xproperties,
"HDUCLAS2",
1928 "Error data extension");
1930 cpl_propertylist_update_string(xproperties,
"HDUCLAS3",
"RMSE");
1931 cpl_propertylist_set_comment(xproperties,
"HDUCLAS3",
1932 "Type of error: root mean squared");
1934 cx_string_sprintf(name,
"SSN%-d.%s", ssn, data_name);
1936 cpl_propertylist_update_string(xproperties, link_names[0],
1937 cx_string_get(name));
1938 cpl_propertylist_set_comment(xproperties, link_names[0],
1939 "Linked science data extension");
1947 cpl_propertylist_delete(xproperties);
1950 cx_string_delete(name);
1957 epos = cx_slist_next(ecubes, epos);
1961 spos = cx_slist_next(scubes, spos);
1966 cpl_propertylist_delete(xproperties);
1969 cx_string_delete(name);
1990 GiFieldOfViewConfig*
1994 const cxchar* s = NULL;
1998 GiFieldOfViewConfig* config = NULL;
2005 config = cx_calloc(1,
sizeof *config);
2008 p = cpl_parameterlist_find(list,
"giraffe.fov.range.minimum");
2009 config->minimum = cpl_parameter_get_double(p);
2011 p = cpl_parameterlist_find(list,
"giraffe.fov.range.maximum");
2012 config->maximum = cpl_parameter_get_double(p);
2014 p = cpl_parameterlist_find(list,
"giraffe.fov.cube");
2015 config->cube = cpl_parameter_get_bool(p);
2017 p = cpl_parameterlist_find(list,
"giraffe.fov.cube.format");
2018 s = cpl_parameter_get_string(p);
2020 if (strcmp(s,
"single") == 0) {
2021 config->format = GIFOV_FORMAT_SINGLE;
2023 else if (strcmp(s,
"eso3d") == 0) {
2024 config->format = GIFOV_FORMAT_ESO3D;
2049 if (config != NULL) {
2078 p = cpl_parameter_new_value(
"giraffe.fov.range.minimum",
2080 "Minimum wavelength for image reconstruction",
2081 "giraffe.fov.range",
2083 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"recon-min");
2084 cpl_parameterlist_append(list, p);
2087 p = cpl_parameter_new_value(
"giraffe.fov.range.maximum",
2089 "Maximum wavelength for image reconstruction",
2090 "giraffe.fov.range",
2092 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"recon-max");
2093 cpl_parameterlist_append(list, p);
2096 p = cpl_parameter_new_value(
"giraffe.fov.cube",
2098 "Turns data cube creation on and off",
2101 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"recon-cube");
2102 cpl_parameterlist_append(list, p);
2104 p = cpl_parameter_new_enum(
"giraffe.fov.cube.format",
2106 "Selects the file format for cubes",
2108 "single", 2,
"single",
"eso3d");
2109 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"recon-format");
2110 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.