36 #include <cxstrutils.h>
37 #include <cxmessages.h>
39 #include <cpl_propertylist.h>
41 #include <cpl_error.h>
47 #include "gimessages.h"
49 #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;
97 const cxchar *
const fctid =
"giraffe_fiberlist_create";
108 cx_string *slit_name = NULL;
110 cpl_table *fibers = NULL;
114 cpl_propertylist *properties = NULL;
115 cpl_propertylist *sorting_order = NULL;
117 GiTable *slits = NULL;
118 GiTable *ozpoz = NULL;
120 GiInstrumentMode mode;
134 properties = cpl_propertylist_load(filename, 0);
136 if (properties == NULL) {
137 cpl_msg_error(fctid,
"Cannot load properties of data set 0 "
138 "from `%s'!", filename);
139 cpl_propertylist_delete(properties);
144 if (!cpl_propertylist_has(properties, GIALIAS_STSCFF) &&
145 !cpl_propertylist_has(properties, GIALIAS_STSCTAL)) {
146 cpl_msg_warning(fctid,
"%s: Properties (%s, %s) not found! "
147 "Simultaneous calibration lamps assumed to "
148 "be off!", filename, GIALIAS_STSCFF,
154 cxint scff = cpl_propertylist_get_bool(properties,
156 cxint sctal= cpl_propertylist_get_bool(properties,
161 cpl_msg_info(fctid,
"Simultaneous calibration lamps "
166 cpl_msg_info(fctid,
"Simultaneous calibration lamps "
175 cx_string_create(cpl_propertylist_get_string(properties,
178 cpl_msg_error(fctid,
"%s: Property (%s) not found!", filename,
180 cpl_propertylist_delete(properties);
184 cx_string_strip(slit_name);
189 if (mode == GIMODE_NONE) {
190 cpl_msg_error(fctid,
"Invalid instrument mode!");
192 cx_string_delete(slit_name);
193 cpl_propertylist_delete(properties);
198 cpl_propertylist_delete(properties);
207 cx_assert(ozpoz != NULL);
209 giraffe_error_push();
215 if (cpl_error_get_code() == CPL_ERROR_BAD_FILE_FORMAT) {
216 cpl_msg_error(fctid,
"Data set %d in `%s' is not an "
217 "OzPoz table!", GIOZPOZ_EXTENSION, filename);
219 cpl_table_delete(fibers);
225 cpl_msg_error(fctid,
"No OzPoz table found in `%s'!",
231 cpl_msg_warning(fctid,
"Empty OzPoz table found in `%s'.",
247 cx_assert(slits != NULL);
249 giraffe_error_push();
253 if (cpl_error_get_code() == CPL_ERROR_BAD_FILE_FORMAT) {
254 cpl_msg_error(fctid,
"Data set %d in `%s' is not a fiber table!",
255 GIFIBER_EXTENSION, filename);
260 cpl_msg_error(fctid,
"Cannot load data set %d (fiber table) "
261 "from `%s'!", GIFIBER_EXTENSION, filename);
276 cpl_table_select_all(_slits);
277 cpl_table_and_selected_string(_slits,
"Slit", CPL_NOT_EQUAL_TO,
278 cx_string_get(slit_name));
280 giraffe_error_push();
282 cpl_table_erase_selected(_slits);
284 if (cpl_error_get_code() != CPL_ERROR_NONE) {
285 cpl_msg_error(fctid,
"Invalid slit `%s' selected. No fibers found.",
286 cx_string_get(slit_name));
288 cx_string_delete(slit_name);
299 cx_string_delete(slit_name);
308 nfibers = cpl_table_get_nrow(_slits);
309 fibers = cpl_table_new(nfibers);
311 giraffe_error_push();
313 cpl_table_new_column(fibers,
"INDEX", CPL_TYPE_INT);
314 cpl_table_new_column(fibers,
"FPS", CPL_TYPE_INT);
315 cpl_table_new_column(fibers,
"SSN", CPL_TYPE_INT);
316 cpl_table_new_column(fibers,
"PSSN", CPL_TYPE_INT);
317 cpl_table_new_column(fibers,
"RP", CPL_TYPE_INT);
319 for (i = 0; i < nfibers; i++) {
323 cxint fps = strtol(cpl_table_get_string(_slits,
"FPS", i), NULL, 10);
324 cxint ssn = strtol(cpl_table_get_string(_slits,
"SSN", i), NULL, 10);
325 cxint pssn = strtol(cpl_table_get_string(_slits,
"PSSN", i),
330 s = (cxchar*) cpl_table_get_string(_slits,
"RP", i);
333 rp = strtol(s, NULL, 10);
336 if (mode == GIMODE_ARGUS) {
338 const cxchar *rpid = cpl_table_get_string(_slits,
341 if (cx_strncasecmp(rpid,
"Cal", 3) != 0) {
348 cpl_table_set_int(fibers,
"FPS", i, fps);
349 cpl_table_set_int(fibers,
"SSN", i, ssn);
350 cpl_table_set_int(fibers,
"PSSN", i, pssn);
351 cpl_table_set_int(fibers,
"RP", i, rp);
355 if (mode == GIMODE_IFU || mode == GIMODE_ARGUS) {
357 if (cpl_table_has_column(_slits,
"X") &&
358 cpl_table_has_column(_slits,
"Y")) {
360 cpl_table_new_column(fibers,
"X", CPL_TYPE_INT);
361 cpl_table_new_column(fibers,
"Y", CPL_TYPE_INT);
363 for (i = 0; i < nfibers; i++) {
370 s = cpl_table_get_string(_slits,
"X", i);
373 x = strtol(s, NULL, 10);
376 s = cpl_table_get_string(_slits,
"Y", i);
379 y = strtol(s, NULL, 10);
382 cpl_table_set_int(fibers,
"X", i, x);
383 cpl_table_set_int(fibers,
"Y", i, y);
390 cpl_table_move_column(fibers,
"Retractor", _slits);
392 if (cpl_error_get_code() != CPL_ERROR_NONE) {
393 cpl_msg_error(fctid,
"Data set %d in `%s' is not a valid "
394 "fiber table!", GIFIBER_EXTENSION, filename);
396 cpl_table_delete(fibers);
411 if (mode == GIMODE_ARGUS) {
413 sorting_order = cpl_propertylist_new();
415 cpl_propertylist_append_bool(sorting_order,
"FPS", 1);
416 cpl_table_sort(fibers, sorting_order);
418 cpl_propertylist_delete(sorting_order);
419 sorting_order = NULL;
428 for (i = 0; i < nfibers; i++) {
430 const cxchar *s = cpl_table_get_string(fibers,
"Retractor", i);
433 if (strstr(s,
"Calibration")) {
434 cpl_table_set_int(fibers,
"RP", i, -1);
437 cpl_table_set_int(fibers,
"INDEX", i, i + 1);
441 if (!cpl_table_has_column(fibers,
"FPD")) {
442 cpl_table_duplicate_column(fibers,
"FPD", fibers,
"INDEX");
445 cpl_table_new_column(fibers,
"OBJECT", CPL_TYPE_STRING);
446 cpl_table_new_column(fibers,
"R", CPL_TYPE_DOUBLE);
447 cpl_table_new_column(fibers,
"THETA", CPL_TYPE_DOUBLE);
448 cpl_table_new_column(fibers,
"ORIENT", CPL_TYPE_DOUBLE);
449 cpl_table_new_column(fibers,
"TYPE", CPL_TYPE_STRING);
451 cpl_table_fill_column_window_double(fibers,
"R", 0, nfibers, 0.);
452 cpl_table_fill_column_window_double(fibers,
"THETA", 0, nfibers, 0.);
453 cpl_table_fill_column_window_double(fibers,
"ORIENT", 0, nfibers, 0.);
455 if (_ozpoz != NULL) {
456 if (cpl_table_has_column(_ozpoz,
"RA")) {
457 cpl_table_new_column(fibers,
"RA", CPL_TYPE_DOUBLE);
458 cpl_table_fill_column_window_double(fibers,
"RA", 0,
462 if (cpl_table_has_column(_ozpoz,
"DEC")) {
463 cpl_table_new_column(fibers,
"DEC", CPL_TYPE_DOUBLE);
464 cpl_table_fill_column_window_double(fibers,
"DEC", 0,
468 if (cpl_table_has_column(_ozpoz,
"MAGNITUDE")) {
469 cpl_table_new_column(fibers,
"MAGNITUDE", CPL_TYPE_DOUBLE);
470 cpl_table_fill_column_window_double(fibers,
"MAGNITUDE", 0,
474 if (cpl_table_has_column(_ozpoz,
"B_V")) {
475 cpl_table_new_column(fibers,
"B_V", CPL_TYPE_DOUBLE);
476 cpl_table_fill_column_window_double(fibers,
"B_V", 0,
490 nbuttons = _ozpoz == NULL ? 0 : cpl_table_get_nrow(_ozpoz);
492 cpl_table_select_all(fibers);
494 for (i = 0; i < nfibers; i++) {
496 cxbool missing = TRUE;
498 cxint fiber = cpl_table_get_int(fibers,
"RP", i, NULL);
507 if (fiber == -1 && calsim == TRUE) {
508 cpl_table_set_string(fibers,
"OBJECT", i,
"CALSIM");
509 cpl_table_unselect_row(fibers, i);
512 else if (fiber == 0 && mode == GIMODE_ARGUS) {
513 cpl_table_unselect_row(fibers, i);
521 for (j = 0; j < nbuttons; j++) {
523 cxint button = cpl_table_get_int(_ozpoz,
"BUTTON", j, NULL);
526 if (fiber == button) {
527 const cxchar *object;
530 cxdouble r, theta, orient;
538 object = cpl_table_get_string(_ozpoz,
"OBJECT", j);
539 otype = cpl_table_get_string(_ozpoz,
"TYPE", j);
541 r = cpl_table_get_double(_ozpoz,
"R", j, NULL);
542 theta = cpl_table_get_double(_ozpoz,
"THETA", j, NULL);
543 orient = cpl_table_get_double(_ozpoz,
"ORIENT", j, NULL);
545 if (cpl_table_has_column(_ozpoz,
"RA")) {
546 ra = cpl_table_get_double(_ozpoz,
"RA", j, NULL);
549 if (cpl_table_has_column(_ozpoz,
"DEC")) {
550 dec = cpl_table_get_double(_ozpoz,
"DEC", j, NULL);
553 if (cpl_table_has_column(_ozpoz,
"MAGNITUDE")) {
554 mag = cpl_table_get_float(_ozpoz,
"MAGNITUDE", j,
558 if (cpl_table_has_column(_ozpoz,
"B_V")) {
559 b_v = cpl_table_get_double(_ozpoz,
"B_V", j, NULL);
560 b_v = CX_CLAMP(b_v, -5., 5.);
563 cpl_table_set_string(fibers,
"OBJECT", i,
object);
564 cpl_table_set_string(fibers,
"TYPE", i, otype);
566 cpl_table_set_double(fibers,
"R", i, r);
567 cpl_table_set_double(fibers,
"THETA", i, theta);
568 cpl_table_set_double(fibers,
"ORIENT", i, orient);
570 if (cpl_table_has_column(fibers,
"RA")) {
571 cpl_table_set_double(fibers,
"RA", i, ra);
574 if (cpl_table_has_column(fibers,
"DEC")) {
575 cpl_table_set_double(fibers,
"DEC", i, dec);
578 if (cpl_table_has_column(fibers,
"MAGNITUDE")) {
579 cpl_table_set_double(fibers,
"MAGNITUDE", i, mag);
582 if (cpl_table_has_column(fibers,
"B_V")) {
583 cpl_table_set_double(fibers,
"B_V", i, b_v);
586 cpl_table_unselect_row(fibers, i);
593 if (missing == TRUE) {
595 cxint _fps = cpl_table_get_int(fibers,
"FPS", i, NULL);
596 cpl_msg_debug(fctid,
"Fiber at FPS = %d is not used", _fps);
603 giraffe_error_push();
605 cpl_table_erase_selected(fibers);
607 if (cpl_error_get_code() != CPL_ERROR_NONE) {
608 cpl_table_delete(fibers);
624 if (spectra && nspec > 0) {
626 register cxint rows = cpl_table_get_nrow(fibers);
629 cx_assert(cpl_table_get_column_type(fibers,
"FPD") == CPL_TYPE_INT);
631 cpl_table_select_all(fibers);
633 for (i = 0; i < rows; i++) {
636 register cxint selected = 0;
637 register cxint idx = cpl_table_get_int(fibers,
"FPD", i, NULL);
640 for (j = 0; j < nspec; j++) {
641 if (idx == spectra[j]) {
648 cpl_table_unselect_row(fibers, i);
651 cpl_table_select_row(fibers, i);
656 giraffe_error_push();
658 cpl_table_erase_selected(fibers);
660 if (cpl_error_get_code() != CPL_ERROR_NONE) {
661 cpl_table_delete(fibers);
674 for (i = 0; i < cpl_table_get_nrow(fibers); i++) {
675 cpl_table_set_int(fibers,
"INDEX", i, i + 1);
683 cx_assert(sorting_order == NULL);
685 sorting_order = cpl_propertylist_new();
686 cpl_propertylist_append_bool(sorting_order,
"INDEX", 0);
688 cpl_table_sort(fibers, sorting_order);
690 cpl_propertylist_delete(sorting_order);
691 sorting_order = NULL;
727 const cxchar *fctid =
"giraffe_fiberlist_load";
733 cx_assert(fibers != NULL);
735 giraffe_error_push();
738 if (cpl_error_get_code() == CPL_ERROR_BAD_FILE_FORMAT) {
739 cpl_msg_error(fctid,
"Data set %d in `%s' is not a fiber table!",
745 cpl_msg_error(fctid,
"Cannot load data set %d (fiber table) "
746 "from `%s'!", dataset, filename);
779 const cxchar *fctid =
"giraffe_fiberlist_save";
781 cxbool created = FALSE;
785 cpl_propertylist *properties = NULL;
786 cpl_table *table = NULL;
789 if (fibers == NULL || filename == NULL) {
790 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
797 cpl_error_set(fctid, CPL_ERROR_DATA_NOT_FOUND);
803 if (properties == NULL) {
804 properties = cpl_propertylist_new();
806 cpl_propertylist_append_string(properties, GIALIAS_EXTNAME,
807 GIFRAME_FIBER_SETUP);
813 if (cpl_propertylist_has(properties, GIALIAS_EXTNAME)) {
814 cpl_propertylist_set_string(properties, GIALIAS_EXTNAME,
815 GIFRAME_FIBER_SETUP);
818 cpl_propertylist_append_string(properties, GIALIAS_EXTNAME,
819 GIFRAME_FIBER_SETUP);
822 cpl_propertylist_set_comment(properties, GIALIAS_EXTNAME,
823 "FITS Extension name");
825 code = cpl_table_save(table, NULL, properties, filename, CPL_IO_EXTEND);
827 if (created == TRUE) {
828 cpl_propertylist_delete(properties);
831 return code == CPL_ERROR_NONE ? 0 : 1;
856 const cxchar *fctid =
"giraffe_fiberlist_attach";
859 cxbool created = FALSE;
863 cpl_propertylist *properties = NULL;
865 GiTable *_fibers = NULL;
868 if (frame == NULL || fibers == NULL) {
869 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
877 if (properties == NULL) {
878 properties = cpl_propertylist_new();
890 if (created == TRUE) {
891 cpl_propertylist_delete(properties);
922 const GiTable *reference)
932 if (_fibers == NULL || _reference == NULL) {
936 if (!cpl_table_has_column(_fibers,
"FPS") ||
937 !cpl_table_has_column(_reference,
"FPS")) {
942 for (i = 0; i < cpl_table_get_nrow(_reference); i++) {
944 cxbool found = FALSE;
947 cxint fps = cpl_table_get_int(_reference,
"FPS", i, NULL);
949 for (j = 0; j < cpl_table_get_nrow(_fibers); j++) {
950 cxint _fps = cpl_table_get_int(_fibers,
"FPS", j, NULL);
958 if (found == FALSE) {
994 const cxchar *fctid =
"giraffe_fiberlist_associate";
1001 cpl_table *_fibers = NULL;
1002 cpl_table *_reference = NULL;
1005 if (fibers == NULL) {
1006 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
1010 if (reference == NULL) {
1011 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
1018 if (!cpl_table_has_column(_fibers,
"FPS")) {
1019 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
1023 if (!cpl_table_has_column(_reference,
"FPS")) {
1024 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
1035 if (!cpl_table_has_column(_fibers,
"RINDEX")) {
1037 cxint size = cpl_table_get_nrow(_fibers);
1039 cxint status = cpl_table_duplicate_column(_fibers,
"RINDEX",
1042 if (status != CPL_ERROR_NONE) {
1046 status = cpl_table_fill_column_window_int(_fibers,
"RINDEX", 0,
1049 if (status != CPL_ERROR_NONE) {
1062 nf = cpl_table_get_nrow(_fibers);
1063 nr = cpl_table_get_nrow(_reference);
1065 cpl_table_unselect_all(_fibers);
1067 for (i = 0; i < nf; i++) {
1071 cxint fps = cpl_table_get_int(_fibers,
"FPS", i, NULL);
1074 for (j = 0; j < nr; j++) {
1076 cxint _fps = cpl_table_get_int(_reference,
"FPS", j, NULL);
1081 cxint ridx = cpl_table_get_int(_reference,
"INDEX", j, NULL);
1083 cpl_table_set_int(_fibers,
"RINDEX", i, ridx);
1084 cpl_table_select_row(_fibers, i);
1098 _fibers = cpl_table_extract_selected(_fibers);
1105 for (i = 0; i < cpl_table_get_nrow(_fibers); i++) {
1106 cpl_table_set_int(_fibers,
"INDEX", i, i + 1);
1112 cpl_table_delete(_fibers);
1136 cpl_table* _fibers = NULL;
1138 if (fibers == NULL) {
1144 if (_fibers == NULL) {
1148 giraffe_error_push();
1150 if (cpl_table_has_column(_fibers,
"RINDEX") == TRUE) {
1151 cpl_table_erase_column(_fibers,
"RINDEX");
1154 if (cpl_error_get_code() != CPL_ERROR_NONE) {
1158 giraffe_error_pop();
1182 const cxchar *names[] = {
"RINDEX",
"INDEX", NULL};
1183 const cxchar **idx = names;
1186 while (*idx != NULL) {
1188 if (cpl_table_has_column((cpl_table *)fibers, *idx) != 0) {
1221 cpl_array* subslits = NULL;
1224 cx_assert(fibers != NULL);
1226 nfibers = cpl_table_get_nrow(fibers);
1236 subslits = cpl_array_new(nfibers, CPL_TYPE_INT);
1237 cpl_array_fill_window(subslits, 0, nfibers, 0);
1239 ssn = cpl_array_get_data_int(subslits);
1246 for (i = 0; i < nfibers; ++i) {
1247 ssn[i] = cpl_table_get_int(fibers,
"SSN", i, NULL);
1250 qsort(ssn, nfibers,
sizeof(cxint), _giraffe_compare_int);
1257 for (i = 1; i < nfibers; ++i) {
1258 if (ssn[i] != ssn[nss]) {
1259 ssn[++nss] = ssn[i];
1264 cpl_array_set_size(subslits, nss);
1306 cxchar **lists = NULL;
1307 cxchar **ranges = NULL;
1312 cxint *fibers = NULL;
1313 cxint *_fibers = NULL;
1315 cx_slist *fl = NULL;
1317 cx_slist_iterator pos;
1322 lists = cx_strsplit(selection,
";", 2);
1324 if (lists == NULL) {
1328 if (lists[1] != NULL) {
1329 gi_warning(
"Usage of fiber exclusion lists is not supported! "
1330 "The given exclusion list is ignored!");
1333 ranges = cx_strsplit(lists[0],
",", -1);
1335 if (ranges == NULL) {
1341 while (ranges[i] != NULL) {
1343 cxchar **bounds = cx_strsplit(ranges[i],
"-", 2);
1348 if (bounds == NULL) {
1349 cx_strfreev(ranges);
1366 lower = strtol(bounds[0], &last, 10);
1368 if (*last !=
'\0') {
1369 cx_strfreev(bounds);
1370 cx_strfreev(ranges);
1380 if (bounds[1] != NULL) {
1382 upper = strtol(bounds[1], &last, 10);
1384 if (*last !=
'\0') {
1385 cx_strfreev(bounds);
1386 cx_strfreev(ranges);
1397 upper = upper > 0 ? upper : lower;
1399 if (lower <= 0 || upper <= 0 || upper < lower) {
1400 cx_strfreev(bounds);
1401 cx_strfreev(ranges);
1413 if (upper > lower) {
1414 nfibers += upper - lower;
1417 fibers = cx_realloc(fibers, nfibers *
sizeof(cxint));
1419 for (j = first; j < nfibers; j++) {
1420 fibers[j] = lower + j - first;
1427 cx_strfreev(bounds);
1434 cx_strfreev(ranges);
1437 qsort(fibers, nfibers,
sizeof(cxint), _giraffe_compare_int);
1444 fl = cx_slist_new();
1446 for (i = 0; i < nfibers; i++) {
1447 cx_slist_push_back(fl, fibers + i);
1450 cx_slist_unique(fl, _giraffe_compare_int);
1452 nfibers = cx_slist_size(fl);
1453 _fibers = cx_malloc(nfibers *
sizeof(cxint));
1457 pos = cx_slist_begin(fl);
1458 while (pos != cx_slist_end(fl)) {
1460 cxint *fn = cx_slist_get(fl, pos);
1462 cx_assert(fn != NULL);
1465 pos = cx_slist_next(fl, pos);
1468 cx_slist_delete(fl);
1490 const GiTable *reference, cxint *nspec)
1498 cxint nfibers = cpl_table_get_nrow(fibers);
1499 cxint nactive = cpl_table_get_nrow(_reference);
1500 cxint *spectra = NULL;
1503 if (fibers == NULL) {
1507 if (!cpl_table_has_column(fibers,
"FPS") ||
1508 !cpl_table_has_column(fibers,
"FPD")) {
1509 cpl_table_delete(fibers);
1513 if (!cpl_table_has_column(_reference,
"FPS")) {
1514 cpl_table_delete(fibers);
1518 if (nactive > nfibers) {
1519 cpl_table_delete(fibers);
1524 spectra = cx_malloc(nactive *
sizeof(cxint));
1526 for (i = 0; i < nactive; ++i) {
1529 cxint fps = cpl_table_get_int(_reference,
"FPS", i, NULL);
1531 for (j = 0; j < nfibers; ++j) {
1533 cxint _fps = cpl_table_get_int(fibers,
"FPS", j, NULL);
1534 cxint _fpd = cpl_table_get_int(fibers,
"FPD", j, NULL);
1537 spectra[nspectra] = _fpd;
1546 cpl_table_delete(fibers);
1548 if (nspectra < nactive) {
1549 spectra = cx_realloc(spectra, nspectra *
sizeof(cxint));
1552 qsort(spectra, nspectra,
sizeof(cxint), _giraffe_compare_int);
void gi_warning(const cxchar *format,...)
Log a warning.
GiInstrumentMode giraffe_get_mode(cpl_propertylist *properties)
Determines the instrument mode from a property list.
cpl_table * giraffe_table_get(const GiTable *self)
Get the table data from a Giraffe table.
cxint giraffe_table_set(GiTable *self, cpl_table *table)
Sets the table data.
cpl_table * giraffe_fiberlist_create(const cxchar *filename, cxint nspec, const cxint *spectra)
Creates the fiber table.
void giraffe_table_delete(GiTable *self)
Destroys a Giraffe table.
const cxchar * giraffe_fiberlist_query_index(const cpl_table *fibers)
Query a fiber list for the name of the fiber reference index column.
GiTable * giraffe_table_new(void)
Creates a new, empty Giraffe table.
cxint giraffe_table_set_properties(GiTable *self, cpl_propertylist *properties)
Attaches a property list to an table.
cxint giraffe_table_load(GiTable *self, const cxchar *filename, cxint position, const cxchar *id)
Reads a data set from a file into a Giraffe table.
cxint giraffe_fiberlist_attach(cpl_frame *frame, GiTable *fibers)
Attach a fiber table to a frame.
GiTable * giraffe_table_duplicate(const GiTable *src)
Duplicate a Giraffe table.
cxint * giraffe_parse_spectrum_selection(const cxchar *selection, cxint *nspec)
Parses a spectrum selection string.
cxint giraffe_fiberlist_clear_index(GiTable *fibers)
Remove the reference index column from a fiber list.
cxint giraffe_fiberlist_associate(GiTable *fibers, const GiTable *reference)
Associate a fiberlist with a reference list.
cxint giraffe_frame_attach_table(cpl_frame *frame, GiTable *table, const cxchar *tag, cxbool update)
Attach a table to a product frame.
cpl_array * giraffe_fiberlist_get_subslits(const cpl_table *fibers)
Get the list of subslit identifiers from a fiber setup.
cxint giraffe_fiberlist_save(GiTable *fibers, const cxchar *filename)
Save a fiber table to a file.
cxint * giraffe_create_spectrum_selection(const cxchar *filename, const GiTable *reference, cxint *nspec)
Create a spectrum selection from a reference table.
cpl_propertylist * giraffe_table_get_properties(const GiTable *self)
Gets the table properties.
cxint giraffe_fiberlist_compare(const GiTable *fibers, const GiTable *reference)
Compare two fiber lists.
GiTable * giraffe_fiberlist_load(const cxchar *filename, cxint dataset, const cxchar *tag)
Load a fiber table from a file.