36 #include <cxstrutils.h>
38 #include <cpl_propertylist.h>
40 #include <cpl_error.h>
46 #include "gimessages.h"
48 #include "gifiberutils.h"
60 _giraffe_compare_int(cxcptr first, cxcptr second)
63 cxint *_first = (cxint *)first;
64 cxint *_second = (cxint *)second;
66 return *_first - *_second;
96 const cxchar *
const fctid =
"giraffe_fiberlist_create";
107 cx_string *slit_name = NULL;
109 cpl_table *fibers = NULL;
113 cpl_propertylist *properties = NULL;
114 cpl_propertylist *sorting_order = NULL;
116 GiTable *slits = NULL;
117 GiTable *ozpoz = NULL;
119 GiInstrumentMode mode;
133 properties = cpl_propertylist_load(filename, 0);
135 if (properties == NULL) {
136 cpl_msg_error(fctid,
"Cannot load properties of data set 0 "
137 "from `%s'!", filename);
138 cpl_propertylist_delete(properties);
143 if (!cpl_propertylist_has(properties, GIALIAS_STSCFF) &&
144 !cpl_propertylist_has(properties, GIALIAS_STSCTAL)) {
145 cpl_msg_warning(fctid,
"%s: Properties (%s, %s) not found! "
146 "Simultaneous calibration lamps assumed to "
147 "be off!", filename, GIALIAS_STSCFF,
153 cxint scff = cpl_propertylist_get_bool(properties,
155 cxint sctal= cpl_propertylist_get_bool(properties,
160 cpl_msg_info(fctid,
"Simultaneous calibration lamps "
165 cpl_msg_info(fctid,
"Simultaneous calibration lamps "
174 cx_string_create(cpl_propertylist_get_string(properties,
177 cpl_msg_error(fctid,
"%s: Property (%s) not found!", filename,
179 cpl_propertylist_delete(properties);
183 cx_string_strip(slit_name);
188 if (mode == GIMODE_NONE) {
189 cpl_msg_error(fctid,
"Invalid instrument mode!");
191 cx_string_delete(slit_name);
192 cpl_propertylist_delete(properties);
197 cpl_propertylist_delete(properties);
206 cx_assert(ozpoz != NULL);
208 giraffe_error_push();
214 if (cpl_error_get_code() == CPL_ERROR_BAD_FILE_FORMAT) {
215 cpl_msg_error(fctid,
"Data set %d in `%s' is not an "
216 "OzPoz table!", GIOZPOZ_EXTENSION, filename);
218 cpl_table_delete(fibers);
224 cpl_msg_error(fctid,
"No OzPoz table found in `%s'!",
230 cpl_msg_warning(fctid,
"Empty OzPoz table found in `%s'.",
246 cx_assert(slits != NULL);
248 giraffe_error_push();
252 if (cpl_error_get_code() == CPL_ERROR_BAD_FILE_FORMAT) {
253 cpl_msg_error(fctid,
"Data set %d in `%s' is not a fiber table!",
254 GIFIBER_EXTENSION, filename);
259 cpl_msg_error(fctid,
"Cannot load data set %d (fiber table) "
260 "from `%s'!", GIFIBER_EXTENSION, filename);
275 cpl_table_select_all(_slits);
276 cpl_table_and_selected_string(_slits,
"Slit", CPL_NOT_EQUAL_TO,
277 cx_string_get(slit_name));
279 giraffe_error_push();
281 cpl_table_erase_selected(_slits);
283 if (cpl_error_get_code() != CPL_ERROR_NONE) {
284 cpl_msg_error(fctid,
"Invalid slit `%s' selected. No fibers found.",
285 cx_string_get(slit_name));
287 cx_string_delete(slit_name);
298 cx_string_delete(slit_name);
307 nfibers = cpl_table_get_nrow(_slits);
308 fibers = cpl_table_new(nfibers);
310 giraffe_error_push();
312 cpl_table_new_column(fibers,
"INDEX", CPL_TYPE_INT);
313 cpl_table_new_column(fibers,
"FPS", CPL_TYPE_INT);
314 cpl_table_new_column(fibers,
"SSN", CPL_TYPE_INT);
315 cpl_table_new_column(fibers,
"PSSN", CPL_TYPE_INT);
316 cpl_table_new_column(fibers,
"RP", CPL_TYPE_INT);
318 for (i = 0; i < nfibers; i++) {
322 cxint fps = strtol(cpl_table_get_string(_slits,
"FPS", i), NULL, 10);
323 cxint ssn = strtol(cpl_table_get_string(_slits,
"SSN", i), NULL, 10);
324 cxint pssn = strtol(cpl_table_get_string(_slits,
"PSSN", i),
329 s = (cxchar*) cpl_table_get_string(_slits,
"RP", i);
332 rp = strtol(s, NULL, 10);
335 if (mode == GIMODE_ARGUS) {
337 const cxchar *rpid = cpl_table_get_string(_slits,
340 if (cx_strncasecmp(rpid,
"Cal", 3) != 0) {
347 cpl_table_set_int(fibers,
"FPS", i, fps);
348 cpl_table_set_int(fibers,
"SSN", i, ssn);
349 cpl_table_set_int(fibers,
"PSSN", i, pssn);
350 cpl_table_set_int(fibers,
"RP", i, rp);
354 if (mode == GIMODE_IFU || mode == GIMODE_ARGUS) {
356 if (cpl_table_has_column(_slits,
"X") &&
357 cpl_table_has_column(_slits,
"Y")) {
359 cpl_table_new_column(fibers,
"X", CPL_TYPE_INT);
360 cpl_table_new_column(fibers,
"Y", CPL_TYPE_INT);
362 for (i = 0; i < nfibers; i++) {
369 s = cpl_table_get_string(_slits,
"X", i);
372 x = strtol(s, NULL, 10);
375 s = cpl_table_get_string(_slits,
"Y", i);
378 y = strtol(s, NULL, 10);
381 cpl_table_set_int(fibers,
"X", i, x);
382 cpl_table_set_int(fibers,
"Y", i, y);
389 cpl_table_move_column(fibers,
"Retractor", _slits);
391 if (cpl_error_get_code() != CPL_ERROR_NONE) {
392 cpl_msg_error(fctid,
"Data set %d in `%s' is not a valid "
393 "fiber table!", GIFIBER_EXTENSION, filename);
395 cpl_table_delete(fibers);
410 if (mode == GIMODE_ARGUS) {
412 sorting_order = cpl_propertylist_new();
414 cpl_propertylist_append_bool(sorting_order,
"FPS", 1);
415 cpl_table_sort(fibers, sorting_order);
417 cpl_propertylist_delete(sorting_order);
418 sorting_order = NULL;
427 for (i = 0; i < nfibers; i++) {
429 const cxchar *s = cpl_table_get_string(fibers,
"Retractor", i);
432 if (strstr(s,
"Calibration")) {
433 cpl_table_set_int(fibers,
"RP", i, -1);
436 cpl_table_set_int(fibers,
"INDEX", i, i + 1);
440 if (!cpl_table_has_column(fibers,
"FPD")) {
441 cpl_table_duplicate_column(fibers,
"FPD", fibers,
"INDEX");
444 cpl_table_new_column(fibers,
"OBJECT", CPL_TYPE_STRING);
445 cpl_table_new_column(fibers,
"R", CPL_TYPE_DOUBLE);
446 cpl_table_new_column(fibers,
"THETA", CPL_TYPE_DOUBLE);
447 cpl_table_new_column(fibers,
"ORIENT", CPL_TYPE_DOUBLE);
448 cpl_table_new_column(fibers,
"TYPE", CPL_TYPE_STRING);
450 cpl_table_fill_column_window_double(fibers,
"R", 0, nfibers, 0.);
451 cpl_table_fill_column_window_double(fibers,
"THETA", 0, nfibers, 0.);
452 cpl_table_fill_column_window_double(fibers,
"ORIENT", 0, nfibers, 0.);
454 if (_ozpoz != NULL) {
455 if (cpl_table_has_column(_ozpoz,
"RA")) {
456 cpl_table_new_column(fibers,
"RA", CPL_TYPE_DOUBLE);
457 cpl_table_fill_column_window_double(fibers,
"RA", 0,
461 if (cpl_table_has_column(_ozpoz,
"DEC")) {
462 cpl_table_new_column(fibers,
"DEC", CPL_TYPE_DOUBLE);
463 cpl_table_fill_column_window_double(fibers,
"DEC", 0,
467 if (cpl_table_has_column(_ozpoz,
"MAGNITUDE")) {
468 cpl_table_new_column(fibers,
"MAGNITUDE", CPL_TYPE_DOUBLE);
469 cpl_table_fill_column_window_double(fibers,
"MAGNITUDE", 0,
473 if (cpl_table_has_column(_ozpoz,
"B_V")) {
474 cpl_table_new_column(fibers,
"B_V", CPL_TYPE_DOUBLE);
475 cpl_table_fill_column_window_double(fibers,
"B_V", 0,
489 nbuttons = _ozpoz == NULL ? 0 : cpl_table_get_nrow(_ozpoz);
491 cpl_table_select_all(fibers);
493 for (i = 0; i < nfibers; i++) {
495 cxbool missing = TRUE;
497 cxint fiber = cpl_table_get_int(fibers,
"RP", i, NULL);
506 if (fiber == -1 && calsim == TRUE) {
507 cpl_table_set_string(fibers,
"OBJECT", i,
"CALSIM");
508 cpl_table_unselect_row(fibers, i);
511 else if (fiber == 0 && mode == GIMODE_ARGUS) {
512 cpl_table_unselect_row(fibers, i);
520 for (j = 0; j < nbuttons; j++) {
522 cxint button = cpl_table_get_int(_ozpoz,
"BUTTON", j, NULL);
525 if (fiber == button) {
526 const cxchar *object;
529 cxdouble r, theta, orient;
537 object = cpl_table_get_string(_ozpoz,
"OBJECT", j);
538 otype = cpl_table_get_string(_ozpoz,
"TYPE", j);
540 r = cpl_table_get_double(_ozpoz,
"R", j, NULL);
541 theta = cpl_table_get_double(_ozpoz,
"THETA", j, NULL);
542 orient = cpl_table_get_double(_ozpoz,
"ORIENT", j, NULL);
544 if (cpl_table_has_column(_ozpoz,
"RA")) {
545 ra = cpl_table_get_double(_ozpoz,
"RA", j, NULL);
548 if (cpl_table_has_column(_ozpoz,
"DEC")) {
549 dec = cpl_table_get_double(_ozpoz,
"DEC", j, NULL);
552 if (cpl_table_has_column(_ozpoz,
"MAGNITUDE")) {
553 mag = cpl_table_get_float(_ozpoz,
"MAGNITUDE", j,
557 if (cpl_table_has_column(_ozpoz,
"B_V")) {
558 b_v = cpl_table_get_double(_ozpoz,
"B_V", j, NULL);
559 b_v = CX_CLAMP(b_v, -5., 5.);
562 cpl_table_set_string(fibers,
"OBJECT", i,
object);
563 cpl_table_set_string(fibers,
"TYPE", i, otype);
565 cpl_table_set_double(fibers,
"R", i, r);
566 cpl_table_set_double(fibers,
"THETA", i, theta);
567 cpl_table_set_double(fibers,
"ORIENT", i, orient);
569 if (cpl_table_has_column(fibers,
"RA")) {
570 cpl_table_set_double(fibers,
"RA", i, ra);
573 if (cpl_table_has_column(fibers,
"DEC")) {
574 cpl_table_set_double(fibers,
"DEC", i, dec);
577 if (cpl_table_has_column(fibers,
"MAGNITUDE")) {
578 cpl_table_set_double(fibers,
"MAGNITUDE", i, mag);
581 if (cpl_table_has_column(fibers,
"B_V")) {
582 cpl_table_set_double(fibers,
"B_V", i, b_v);
585 cpl_table_unselect_row(fibers, i);
592 if (missing == TRUE) {
594 cxint _fps = cpl_table_get_int(fibers,
"FPS", i, NULL);
595 cpl_msg_debug(fctid,
"Fiber at FPS = %d is not used", _fps);
602 giraffe_error_push();
604 cpl_table_erase_selected(fibers);
606 if (cpl_error_get_code() != CPL_ERROR_NONE) {
607 cpl_table_delete(fibers);
623 if (spectra && nspec > 0) {
625 register cxint rows = cpl_table_get_nrow(fibers);
628 cx_assert(cpl_table_get_column_type(fibers,
"FPD") == CPL_TYPE_INT);
630 cpl_table_select_all(fibers);
632 for (i = 0; i < rows; i++) {
635 register cxint selected = 0;
636 register cxint idx = cpl_table_get_int(fibers,
"FPD", i, NULL);
639 for (j = 0; j < nspec; j++) {
640 if (idx == spectra[j]) {
647 cpl_table_unselect_row(fibers, i);
650 cpl_table_select_row(fibers, i);
655 giraffe_error_push();
657 cpl_table_erase_selected(fibers);
659 if (cpl_error_get_code() != CPL_ERROR_NONE) {
660 cpl_table_delete(fibers);
673 for (i = 0; i < cpl_table_get_nrow(fibers); i++) {
674 cpl_table_set_int(fibers,
"INDEX", i, i + 1);
682 cx_assert(sorting_order == NULL);
684 sorting_order = cpl_propertylist_new();
685 cpl_propertylist_append_bool(sorting_order,
"INDEX", 0);
687 cpl_table_sort(fibers, sorting_order);
689 cpl_propertylist_delete(sorting_order);
690 sorting_order = NULL;
726 const cxchar *fctid =
"giraffe_fiberlist_load";
732 cx_assert(fibers != NULL);
734 giraffe_error_push();
737 if (cpl_error_get_code() == CPL_ERROR_BAD_FILE_FORMAT) {
738 cpl_msg_error(fctid,
"Data set %d in `%s' is not a fiber table!",
744 cpl_msg_error(fctid,
"Cannot load data set %d (fiber table) "
745 "from `%s'!", dataset, filename);
778 const cxchar *fctid =
"giraffe_fiberlist_save";
780 cxbool created = FALSE;
784 cpl_propertylist *properties = NULL;
785 cpl_table *table = NULL;
788 if (fibers == NULL || filename == NULL) {
789 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
796 cpl_error_set(fctid, CPL_ERROR_DATA_NOT_FOUND);
802 if (properties == NULL) {
803 properties = cpl_propertylist_new();
805 cpl_propertylist_append_string(properties, GIALIAS_EXTNAME,
806 GIFRAME_FIBER_SETUP);
812 if (cpl_propertylist_has(properties, GIALIAS_EXTNAME)) {
813 cpl_propertylist_set_string(properties, GIALIAS_EXTNAME,
814 GIFRAME_FIBER_SETUP);
817 cpl_propertylist_append_string(properties, GIALIAS_EXTNAME,
818 GIFRAME_FIBER_SETUP);
821 cpl_propertylist_set_comment(properties, GIALIAS_EXTNAME,
822 "FITS Extension name");
824 code = cpl_table_save(table, NULL, properties, filename, CPL_IO_EXTEND);
826 if (created == TRUE) {
827 cpl_propertylist_delete(properties);
830 return code == CPL_ERROR_NONE ? 0 : 1;
855 const cxchar *fctid =
"giraffe_fiberlist_attach";
858 cxbool created = FALSE;
862 cpl_propertylist *properties = NULL;
864 GiTable *_fibers = NULL;
867 if (frame == NULL || fibers == NULL) {
868 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
876 if (properties == NULL) {
877 properties = cpl_propertylist_new();
889 if (created == TRUE) {
890 cpl_propertylist_delete(properties);
921 const GiTable *reference)
931 if (_fibers == NULL || _reference == NULL) {
935 if (!cpl_table_has_column(_fibers,
"FPS") ||
936 !cpl_table_has_column(_reference,
"FPS")) {
941 for (i = 0; i < cpl_table_get_nrow(_reference); i++) {
943 cxbool found = FALSE;
946 cxint fps = cpl_table_get_int(_reference,
"FPS", i, NULL);
948 for (j = 0; j < cpl_table_get_nrow(_fibers); j++) {
949 cxint _fps = cpl_table_get_int(_fibers,
"FPS", j, NULL);
957 if (found == FALSE) {
993 const cxchar *fctid =
"giraffe_fiberlist_associate";
1000 cpl_table *_fibers = NULL;
1001 cpl_table *_reference = NULL;
1004 if (fibers == NULL) {
1005 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
1009 if (reference == NULL) {
1010 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
1017 if (!cpl_table_has_column(_fibers,
"FPS")) {
1018 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
1022 if (!cpl_table_has_column(_reference,
"FPS")) {
1023 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
1034 if (!cpl_table_has_column(_fibers,
"RINDEX")) {
1036 cxint size = cpl_table_get_nrow(_fibers);
1038 cxint status = cpl_table_duplicate_column(_fibers,
"RINDEX",
1041 if (status != CPL_ERROR_NONE) {
1045 status = cpl_table_fill_column_window_int(_fibers,
"RINDEX", 0,
1048 if (status != CPL_ERROR_NONE) {
1061 nf = cpl_table_get_nrow(_fibers);
1062 nr = cpl_table_get_nrow(_reference);
1064 cpl_table_unselect_all(_fibers);
1066 for (i = 0; i < nf; i++) {
1070 cxint fps = cpl_table_get_int(_fibers,
"FPS", i, NULL);
1073 for (j = 0; j < nr; j++) {
1075 cxint _fps = cpl_table_get_int(_reference,
"FPS", j, NULL);
1080 cxint ridx = cpl_table_get_int(_reference,
"INDEX", j, NULL);
1082 cpl_table_set_int(_fibers,
"RINDEX", i, ridx);
1083 cpl_table_select_row(_fibers, i);
1097 _fibers = cpl_table_extract_selected(_fibers);
1104 for (i = 0; i < cpl_table_get_nrow(_fibers); i++) {
1105 cpl_table_set_int(_fibers,
"INDEX", i, i + 1);
1111 cpl_table_delete(_fibers);
1135 cpl_table* _fibers = NULL;
1137 if (fibers == NULL) {
1143 if (_fibers == NULL) {
1147 giraffe_error_push();
1149 if (cpl_table_has_column(_fibers,
"RINDEX") == TRUE) {
1150 cpl_table_erase_column(_fibers,
"RINDEX");
1153 if (cpl_error_get_code() != CPL_ERROR_NONE) {
1157 giraffe_error_pop();
1181 const cxchar *names[] = {
"RINDEX",
"INDEX", NULL};
1182 const cxchar **idx = names;
1185 while (*idx != NULL) {
1187 if (cpl_table_has_column((cpl_table *)fibers, *idx) != 0) {
1220 cpl_array* subslits = NULL;
1223 cx_assert(fibers != NULL);
1225 nfibers = cpl_table_get_nrow(fibers);
1235 subslits = cpl_array_new(nfibers, CPL_TYPE_INT);
1236 cpl_array_fill_window(subslits, 0, nfibers, 0);
1238 ssn = cpl_array_get_data_int(subslits);
1245 for (i = 0; i < nfibers; ++i) {
1246 ssn[i] = cpl_table_get_int(fibers,
"SSN", i, NULL);
1249 qsort(ssn, nfibers,
sizeof(cxint), _giraffe_compare_int);
1256 for (i = 1; i < nfibers; ++i) {
1257 if (ssn[i] != ssn[nss]) {
1258 ssn[++nss] = ssn[i];
1263 cpl_array_set_size(subslits, nss);
1305 cxchar **lists = NULL;
1306 cxchar **ranges = NULL;
1311 cxint *fibers = NULL;
1312 cxint *_fibers = NULL;
1314 cx_slist *fl = NULL;
1316 cx_slist_iterator pos;
1321 lists = cx_strsplit(selection,
";", 2);
1323 if (lists == NULL) {
1327 if (lists[1] != NULL) {
1328 gi_warning(
"Usage of fiber exclusion lists is not supported! "
1329 "The given exclusion list is ignored!");
1332 ranges = cx_strsplit(lists[0],
",", -1);
1334 if (ranges == NULL) {
1340 while (ranges[i] != NULL) {
1342 cxchar **bounds = cx_strsplit(ranges[i],
"-", 2);
1347 if (bounds == NULL) {
1348 cx_strfreev(ranges);
1365 lower = strtol(bounds[0], &last, 10);
1367 if (*last !=
'\0') {
1368 cx_strfreev(bounds);
1369 cx_strfreev(ranges);
1379 if (bounds[1] != NULL) {
1381 upper = strtol(bounds[1], &last, 10);
1383 if (*last !=
'\0') {
1384 cx_strfreev(bounds);
1385 cx_strfreev(ranges);
1396 upper = upper > 0 ? upper : lower;
1398 if (lower <= 0 || upper <= 0 || upper < lower) {
1399 cx_strfreev(bounds);
1400 cx_strfreev(ranges);
1412 if (upper > lower) {
1413 nfibers += upper - lower;
1416 fibers = cx_realloc(fibers, nfibers *
sizeof(cxint));
1418 for (j = first; j < nfibers; j++) {
1419 fibers[j] = lower + j - first;
1426 cx_strfreev(bounds);
1433 cx_strfreev(ranges);
1436 qsort(fibers, nfibers,
sizeof(cxint), _giraffe_compare_int);
1443 fl = cx_slist_new();
1445 for (i = 0; i < nfibers; i++) {
1446 cx_slist_push_back(fl, fibers + i);
1449 cx_slist_unique(fl, _giraffe_compare_int);
1451 nfibers = cx_slist_size(fl);
1452 _fibers = cx_malloc(nfibers *
sizeof(cxint));
1456 pos = cx_slist_begin(fl);
1457 while (pos != cx_slist_end(fl)) {
1459 cxint *fn = cx_slist_get(fl, pos);
1461 cx_assert(fn != NULL);
1464 pos = cx_slist_next(fl, pos);
1467 cx_slist_delete(fl);
1489 const GiTable *reference, cxint *nspec)
1497 cxint nfibers = cpl_table_get_nrow(fibers);
1498 cxint nactive = cpl_table_get_nrow(_reference);
1499 cxint *spectra = NULL;
1502 if (fibers == NULL) {
1506 if (!cpl_table_has_column(fibers,
"FPS") ||
1507 !cpl_table_has_column(fibers,
"FPD")) {
1508 cpl_table_delete(fibers);
1512 if (!cpl_table_has_column(_reference,
"FPS")) {
1513 cpl_table_delete(fibers);
1517 if (nactive > nfibers) {
1518 cpl_table_delete(fibers);
1523 spectra = cx_malloc(nactive *
sizeof(cxint));
1525 for (i = 0; i < nactive; ++i) {
1528 cxint fps = cpl_table_get_int(_reference,
"FPS", i, NULL);
1530 for (j = 0; j < nfibers; ++j) {
1532 cxint _fps = cpl_table_get_int(fibers,
"FPS", j, NULL);
1533 cxint _fpd = cpl_table_get_int(fibers,
"FPD", j, NULL);
1536 spectra[nspectra] = _fpd;
1545 cpl_table_delete(fibers);
1547 if (nspectra < nactive) {
1548 spectra = cx_realloc(spectra, nspectra *
sizeof(cxint));
1551 qsort(spectra, nspectra,
sizeof(cxint), _giraffe_compare_int);