GIRAFFE Pipeline Reference Manual

gifiberutils.c
1/*
2 * This file is part of the GIRAFFE Pipeline
3 * Copyright (C) 2002-2019 European Southern Observatory
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#ifdef HAVE_CONFIG_H
21# include <config.h>
22#endif
23
24#include <stdlib.h>
25
26#include <cxstring.h>
27#include <cxslist.h>
28#include <cxstrutils.h>
29#include <cxmessages.h>
30
31#include <cpl_propertylist.h>
32#include <cpl_msg.h>
33#include <cpl_error.h>
34
35#include "gialias.h"
36#include "gierror.h"
37#include "giframe.h"
38#include "gitable.h"
39#include "gimessages.h"
40#include "giutils.h"
41#include "gifiberutils.h"
42
43
52inline static cxint
53_giraffe_compare_int(cxcptr first, cxcptr second)
54{
55
56 cxint *_first = (cxint *)first;
57 cxint *_second = (cxint *)second;
58
59 return *_first - *_second;
60
61}
62
63
84cpl_table *
85giraffe_fiberlist_create(const cxchar *filename, cxint nspec,
86 const cxint *spectra)
87{
88
89 const cxchar *const fctid = "giraffe_fiberlist_create";
90
91
92 cxbool calsim;
93
94 cxint i;
95 cxint status = 0;
96
97 cxint nfibers;
98 cxint nbuttons;
99
100 cxint fiberext = 0;
101
102 cx_string *slit_name = NULL;
103
104 cpl_table *fibers = NULL;
105 cpl_table *_slits;
106 cpl_table *_ozpoz = NULL;
107
108 cpl_propertylist *properties = NULL;
109 cpl_propertylist *ozproperties = NULL;
110 cpl_propertylist *sorting_order = NULL;
111
112 GiTable *slits = NULL;
113 GiTable *ozpoz = NULL;
114
115 GiInstrumentMode mode;
116
117
118
119 if (!filename) {
120 return NULL;
121 }
122
123
124 /*
125 * Check whether the input file is a calibration and retrieve the
126 * name of the slit in use.
127 */
128
129 properties = cpl_propertylist_load(filename, 0);
130
131 if (properties == NULL) {
132 cpl_msg_error(fctid, "Cannot load properties of data set 0 "
133 "from `%s'!", filename);
134 cpl_propertylist_delete(properties);
135 return NULL;
136 }
137 else {
138
139 if (!cpl_propertylist_has(properties, GIALIAS_STSCFF) &&
140 !cpl_propertylist_has(properties, GIALIAS_STSCTAL)) {
141 cpl_msg_warning(fctid, "%s: Properties (%s, %s) not found! "
142 "Simultaneous calibration lamps assumed to "
143 "be off!", filename, GIALIAS_STSCFF,
144 GIALIAS_STSCTAL);
145 calsim = FALSE;
146 }
147 else {
148
149 cxint scff = cpl_propertylist_get_bool(properties,
150 GIALIAS_STSCFF);
151 cxint sctal= cpl_propertylist_get_bool(properties,
152 GIALIAS_STSCTAL);
153
154
155 if (scff || sctal) {
156 cpl_msg_info(fctid, "Simultaneous calibration lamps "
157 "are on.");
158 calsim = TRUE;
159 }
160 else {
161 cpl_msg_info(fctid, "Simultaneous calibration lamps "
162 "are off.");
163 calsim = FALSE;
164 }
165
166 }
167
168
169 slit_name =
170 cx_string_create(cpl_propertylist_get_string(properties,
171 GIALIAS_SLITNAME));
172 if (!slit_name) {
173 cpl_msg_error(fctid, "%s: Property (%s) not found!", filename,
174 GIALIAS_SLITNAME);
175 cpl_propertylist_delete(properties);
176 return NULL;
177 }
178 else {
179 cx_string_strip(slit_name);
180 }
181
182 mode = giraffe_get_mode(properties);
183
184 if (mode == GIMODE_NONE) {
185 cpl_msg_error(fctid, "Invalid instrument mode!");
186
187 cx_string_delete(slit_name);
188 cpl_propertylist_delete(properties);
189
190 return NULL;
191 }
192
193 cpl_propertylist_delete(properties);
194 }
195
196 /*
197 * Check if OzPoz table is present in the input file.
198 * If it is, continue the normal processing.
199 * Otherwise, assume this is a CALSIM file and load the fiber table
200 * from the first extension, refered to as GIOZPOZ_EXTENSION.
201 */
202
203 ozproperties = cpl_propertylist_load(filename, GIOZPOZ_EXTENSION);
204
205 cxint ozstatus = 0;
206
207 if (ozproperties && cpl_propertylist_has(ozproperties, GIALIAS_EXTNAME)) {
208 const cxchar *magic;
209
210 magic = cpl_propertylist_get_string(ozproperties, GIALIAS_EXTNAME);
211
212 if (strcmp(GIOZPOZ_MAGIC, magic) == 0) {
213 ozstatus = 1;
214 fiberext = GIFIBER_EXTENSION;
215 }
216
217 if (strcmp(GIFIBER_MAGIC, magic) == 0) {
218 ozstatus = 2;
219 fiberext = GIOZPOZ_EXTENSION;
220 }
221 }
222
223 if (ozproperties) {
224 cpl_propertylist_delete(ozproperties);
225 }
226
227 /*
228 * Load OzPoz table from current frame
229 */
230
231 if (ozstatus == 1) {
232 ozpoz = giraffe_table_new();
233 cx_assert(ozpoz != NULL);
234
235 giraffe_error_push();
236
237 status = giraffe_table_load(ozpoz, filename, GIOZPOZ_EXTENSION,
238 GIOZPOZ_MAGIC);
239
240 if (status)
241 {
242 if (cpl_error_get_code() == CPL_ERROR_BAD_FILE_FORMAT)
243 {
244 cpl_msg_error(fctid, "Data set %d in `%s' is not an "
245 "OzPoz table!",
246 GIOZPOZ_EXTENSION, filename);
248 cpl_table_delete(fibers);
249
250 return NULL;
251 }
252 else
253 {
254 if (status != 2)
255 {
256 cpl_msg_error(fctid, "No OzPoz table found in `%s'!",
257 filename);
259 return NULL;
260 }
261
262 cpl_msg_warning(fctid, "Empty OzPoz table found in `%s'.",
263 filename);
264 }
265 }
266
267 giraffe_error_pop();
268
269 _ozpoz = giraffe_table_get(ozpoz);
270 }
271
272 /*
273 * Load fiber table from current frame.
274 */
275
276 slits = giraffe_table_new();
277 cx_assert(slits != NULL);
278
279 giraffe_error_push();
280
281 if (giraffe_table_load(slits, filename, fiberext,
282 GIFIBER_MAGIC)) {
283 if (cpl_error_get_code() == CPL_ERROR_BAD_FILE_FORMAT) {
284 cpl_msg_error(fctid, "Data set %d in `%s' is not a fiber table!",
285 GIFIBER_EXTENSION, filename);
287 return NULL;
288 }
289 else {
290 cpl_msg_error(fctid, "Cannot load data set %d (fiber table) "
291 "from `%s'!", GIFIBER_EXTENSION, filename);
293 return NULL;
294 }
295 }
296
297 giraffe_error_pop();
298
299 _slits = giraffe_table_get(slits);
300
301
302 /*
303 * Select all entries with the appropriate slit name from the table
304 */
305
306 cpl_table_select_all(_slits);
307 cpl_table_and_selected_string(_slits, "Slit", CPL_NOT_EQUAL_TO,
308 cx_string_get(slit_name));
309
310 giraffe_error_push();
311
312 cpl_table_erase_selected(_slits);
313
314 if (cpl_error_get_code() != CPL_ERROR_NONE) {
315 cpl_msg_error(fctid, "Invalid slit `%s' selected. No fibers found.",
316 cx_string_get(slit_name));
317
318 cx_string_delete(slit_name);
319 slit_name = NULL;
320
322 slits = NULL;
323
324 return NULL;
325 }
326
327 giraffe_error_pop();
328
329 cx_string_delete(slit_name);
330 slit_name = NULL;
331
332
333 /*
334 * Move the relevant columns from the fiber table to the
335 * final fibers list.
336 */
337
338 nfibers = cpl_table_get_nrow(_slits);
339 fibers = cpl_table_new(nfibers);
340
341 giraffe_error_push();
342
343 cpl_table_new_column(fibers, "INDEX", CPL_TYPE_INT);
344 cpl_table_new_column(fibers, "FPS", CPL_TYPE_INT);
345 cpl_table_new_column(fibers, "SSN", CPL_TYPE_INT);
346 cpl_table_new_column(fibers, "PSSN", CPL_TYPE_INT);
347 cpl_table_new_column(fibers, "RP", CPL_TYPE_INT);
348
349 for (i = 0; i < nfibers; i++) {
350
351 cxchar *s;
352
353 cxint fps = strtol(cpl_table_get_string(_slits, "FPS", i), NULL, 10);
354 cxint ssn = strtol(cpl_table_get_string(_slits, "SSN", i), NULL, 10);
355 cxint pssn = strtol(cpl_table_get_string(_slits, "PSSN", i),
356 NULL, 10);
357 cxint rp = -1;
358
359
360 s = (cxchar*) cpl_table_get_string(_slits, "RP", i);
361
362 if (s != NULL) {
363 rp = strtol(s, NULL, 10);
364 }
365 else {
366 if (mode == GIMODE_ARGUS) {
367
368 const cxchar *rpid = cpl_table_get_string(_slits,
369 "Retractor", i);
370
371 if (cx_strncasecmp(rpid, "Cal", 3) != 0) {
372 rp = 0;
373 }
374
375 }
376 }
377
378 cpl_table_set_int(fibers, "FPS", i, fps);
379 cpl_table_set_int(fibers, "SSN", i, ssn);
380 cpl_table_set_int(fibers, "PSSN", i, pssn);
381 cpl_table_set_int(fibers, "RP", i, rp);
382
383 }
384
385 if (mode == GIMODE_IFU || mode == GIMODE_ARGUS) {
386
387 if (cpl_table_has_column(_slits, "X") &&
388 cpl_table_has_column(_slits, "Y")) {
389
390 cpl_table_new_column(fibers, "X", CPL_TYPE_INT);
391 cpl_table_new_column(fibers, "Y", CPL_TYPE_INT);
392
393 for (i = 0; i < nfibers; i++) {
394 const cxchar *s;
395
396 cxint x = 0;
397 cxint y = 0;
398
399
400 s = cpl_table_get_string(_slits, "X", i);
401
402 if (s != NULL) {
403 x = strtol(s, NULL, 10);
404 }
405
406 s = cpl_table_get_string(_slits, "Y", i);
407
408 if (s != NULL) {
409 y = strtol(s, NULL, 10);
410 }
411
412 cpl_table_set_int(fibers, "X", i, x);
413 cpl_table_set_int(fibers, "Y", i, y);
414 }
415
416 }
417
418 }
419
420 cpl_table_move_column(fibers, "Retractor", _slits);
421
422 if (cpl_error_get_code() != CPL_ERROR_NONE) {
423 cpl_msg_error(fctid, "Data set %d in `%s' is not a valid "
424 "fiber table!", GIFIBER_EXTENSION, filename);
426 cpl_table_delete(fibers);
427
428 return NULL;
429 }
430
431 giraffe_error_pop();
432
434
435
436 /*
437 * For Argus the slit is mirrored compared to IFU and Medusa
438 * and we have to reverse the order of the slits table.
439 */
440
441 if (mode == GIMODE_ARGUS) {
442
443 sorting_order = cpl_propertylist_new();
444
445 cpl_propertylist_append_bool(sorting_order, "FPS", 1);
446 cpl_table_sort(fibers, sorting_order);
447
448 cpl_propertylist_delete(sorting_order);
449 sorting_order = NULL;
450
451 }
452
453
454 /*
455 * Postprocess initial fiber table
456 */
457
458 for (i = 0; i < nfibers; i++) {
459
460 const cxchar *s = cpl_table_get_string(fibers, "Retractor", i);
461
462
463 if (strstr(s, "Calibration")) {
464 cpl_table_set_int(fibers, "RP", i, -1);
465 }
466
467 cpl_table_set_int(fibers, "INDEX", i, i + 1);
468
469 }
470
471 if (!cpl_table_has_column(fibers, "FPD")) {
472 cpl_table_duplicate_column(fibers, "FPD", fibers, "INDEX");
473 }
474
475 cpl_table_new_column(fibers, "OBJECT", CPL_TYPE_STRING);
476 cpl_table_new_column(fibers, "R", CPL_TYPE_DOUBLE);
477 cpl_table_new_column(fibers, "THETA", CPL_TYPE_DOUBLE);
478 cpl_table_new_column(fibers, "ORIENT", CPL_TYPE_DOUBLE);
479 cpl_table_new_column(fibers, "TYPE", CPL_TYPE_STRING);
480
481 cpl_table_fill_column_window_double(fibers, "R", 0, nfibers, 0.);
482 cpl_table_fill_column_window_double(fibers, "THETA", 0, nfibers, 0.);
483 cpl_table_fill_column_window_double(fibers, "ORIENT", 0, nfibers, 0.);
484
485 if (_ozpoz != NULL) {
486 if (cpl_table_has_column(_ozpoz, "RA")) {
487 cpl_table_new_column(fibers, "RA", CPL_TYPE_DOUBLE);
488 cpl_table_fill_column_window_double(fibers, "RA", 0,
489 nfibers, 0.);
490 }
491
492 if (cpl_table_has_column(_ozpoz, "DEC")) {
493 cpl_table_new_column(fibers, "DEC", CPL_TYPE_DOUBLE);
494 cpl_table_fill_column_window_double(fibers, "DEC", 0,
495 nfibers, 0.);
496 }
497
498 if (cpl_table_has_column(_ozpoz, "MAGNITUDE")) {
499 cpl_table_new_column(fibers, "MAGNITUDE", CPL_TYPE_DOUBLE);
500 cpl_table_fill_column_window_double(fibers, "MAGNITUDE", 0,
501 nfibers, 0.);
502 }
503
504 if (cpl_table_has_column(_ozpoz, "B_V")) {
505 cpl_table_new_column(fibers, "B_V", CPL_TYPE_DOUBLE);
506 cpl_table_fill_column_window_double(fibers, "B_V", 0,
507 nfibers, 0.);
508 }
509 }
510
511
512 /*
513 * Select rows in the fiber table which have a corresponding entry
514 * in the OzPoz table. Both tables are associated using the
515 * `button number'. For matching entries the OzPoz data is copied
516 * to the fiber table. Also the simultaneous calibration fibers
517 * are copied.
518 */
519
520 nbuttons = _ozpoz == NULL ? 0 : cpl_table_get_nrow(_ozpoz);
521
522 cpl_table_select_all(fibers);
523
524 for (i = 0; i < nfibers; i++) {
525
526 cxbool missing = TRUE;
527
528 cxint fiber = cpl_table_get_int(fibers, "RP", i, NULL);
529
530
531 /*
532 * If fiber equals -1 it is a simultaneous calibration, which
533 * has no entry in the OzPoz table. Otherwise we try to find it
534 * in the OzPoz table and copy the data for this fiber.
535 */
536
537 if (fiber == -1 && calsim == TRUE) {
538 cpl_table_set_string(fibers, "OBJECT", i, "CALSIM");
539 cpl_table_unselect_row(fibers, i);
540 missing = FALSE;
541 }
542 else if (ozstatus==1 && fiber == 0 && mode == GIMODE_ARGUS) {
543 cpl_table_unselect_row(fibers, i);
544 missing = FALSE;
545 }
546 else {
547
548 register cxint j;
549
550
551 for (j = 0; j < nbuttons; j++) {
552
553 cxint button = cpl_table_get_int(_ozpoz, "BUTTON", j, NULL);
554
555
556 if (fiber == button) {
557 const cxchar *object;
558 const cxchar *otype;
559
560 cxdouble r, theta, orient;
561
562 cxdouble ra = 0.;
563 cxdouble dec = 0.;
564 cxdouble mag = 0.;
565 cxdouble b_v = 0.;
566
567
568 object = cpl_table_get_string(_ozpoz, "OBJECT", j);
569 otype = cpl_table_get_string(_ozpoz, "TYPE", j);
570
571 r = cpl_table_get_double(_ozpoz, "R", j, NULL);
572 theta = cpl_table_get_double(_ozpoz, "THETA", j, NULL);
573 orient = cpl_table_get_double(_ozpoz, "ORIENT", j, NULL);
574
575 if (cpl_table_has_column(_ozpoz, "RA")) {
576 ra = cpl_table_get_double(_ozpoz, "RA", j, NULL);
577 }
578
579 if (cpl_table_has_column(_ozpoz, "DEC")) {
580 dec = cpl_table_get_double(_ozpoz, "DEC", j, NULL);
581 }
582
583 if (cpl_table_has_column(_ozpoz, "MAGNITUDE")) {
584 mag = cpl_table_get_float(_ozpoz, "MAGNITUDE", j,
585 NULL);
586 }
587
588 if (cpl_table_has_column(_ozpoz, "B_V")) {
589 b_v = cpl_table_get_double(_ozpoz, "B_V", j, NULL);
590 b_v = CX_CLAMP(b_v, -5., 5.);
591 }
592
593 cpl_table_set_string(fibers, "OBJECT", i, object);
594 cpl_table_set_string(fibers, "TYPE", i, otype);
595
596 cpl_table_set_double(fibers, "R", i, r);
597 cpl_table_set_double(fibers, "THETA", i, theta);
598 cpl_table_set_double(fibers, "ORIENT", i, orient);
599
600 if (cpl_table_has_column(fibers, "RA")) {
601 cpl_table_set_double(fibers, "RA", i, ra);
602 }
603
604 if (cpl_table_has_column(fibers, "DEC")) {
605 cpl_table_set_double(fibers, "DEC", i, dec);
606 }
607
608 if (cpl_table_has_column(fibers, "MAGNITUDE")) {
609 cpl_table_set_double(fibers, "MAGNITUDE", i, mag);
610 }
611
612 if (cpl_table_has_column(fibers, "B_V")) {
613 cpl_table_set_double(fibers, "B_V", i, b_v);
614 }
615
616 cpl_table_unselect_row(fibers, i);
617 missing = FALSE;
618 break;
619 }
620 }
621 }
622
623 if (missing == TRUE) {
624
625 cxint _fps = cpl_table_get_int(fibers, "FPS", i, NULL);
626 cpl_msg_debug(fctid, "Fiber at FPS = %d and RP = %d is not used", _fps, fiber);
627
628 }
629
630 }
631
632
633 giraffe_error_push();
634
635 cpl_table_erase_selected(fibers);
636
637 if (cpl_error_get_code() != CPL_ERROR_NONE) {
638 cpl_table_delete(fibers);
639 return NULL;
640 }
641
642 giraffe_error_pop();
643
645 ozpoz = NULL;
646
647
648 /*
649 * Finalize the fiber list by applying the user specified fiber
650 * selection list. Fibers which do not have an entry in the
651 * OzPoz table or which are beyond the limits are ignored.
652 */
653
654 if (spectra && nspec > 0) {
655
656 register cxint rows = cpl_table_get_nrow(fibers);
657
658
659 cx_assert(cpl_table_get_column_type(fibers, "FPD") == CPL_TYPE_INT);
660
661 cpl_table_select_all(fibers);
662
663 for (i = 0; i < rows; i++) {
664
665 register cxint j;
666 register cxint selected = 0;
667 register cxint idx = cpl_table_get_int(fibers, "FPD", i, NULL);
668
669
670 for (j = 0; j < nspec; j++) {
671 if (idx == spectra[j]) {
672 selected = 1;
673 break;
674 }
675 }
676
677 if (selected) {
678 cpl_table_unselect_row(fibers, i);
679 }
680 else {
681 cpl_table_select_row(fibers, i);
682 }
683
684 }
685
686 giraffe_error_push();
687
688 cpl_table_erase_selected(fibers);
689
690 if (cpl_error_get_code() != CPL_ERROR_NONE) {
691 cpl_table_delete(fibers);
692 return NULL;
693 }
694
695 giraffe_error_pop();
696
697 }
698
699
700 /*
701 * Update index column
702 */
703
704 for (i = 0; i < cpl_table_get_nrow(fibers); i++) {
705 cpl_table_set_int(fibers, "INDEX", i, i + 1);
706 }
707
708
709 /*
710 * Sort the final table according to the INDEX column
711 */
712
713 cx_assert(sorting_order == NULL);
714
715 sorting_order = cpl_propertylist_new();
716 cpl_propertylist_append_bool(sorting_order, "INDEX", 0);
717
718 cpl_table_sort(fibers, sorting_order);
719
720 cpl_propertylist_delete(sorting_order);
721 sorting_order = NULL;
722
723
724 return fibers;
725
726}
727
728
752GiTable *
753giraffe_fiberlist_load(const cxchar *filename, cxint dataset,
754 const cxchar *tag)
755{
756
757 const cxchar *fctid = "giraffe_fiberlist_load";
758
759
760 GiTable *fibers = giraffe_table_new();
761
762
763 cx_assert(fibers != NULL);
764
765 giraffe_error_push();
766
767 if (giraffe_table_load(fibers, filename, dataset, tag)) {
768 if (cpl_error_get_code() == CPL_ERROR_BAD_FILE_FORMAT) {
769 cpl_msg_error(fctid, "Data set %d in `%s' is not a fiber table!",
770 dataset, filename);
771 giraffe_table_delete(fibers);
772 return NULL;
773 }
774 else {
775 cpl_msg_error(fctid, "Cannot load data set %d (fiber table) "
776 "from `%s'!", dataset, filename);
777 giraffe_table_delete(fibers);
778 return NULL;
779 }
780 }
781
782 giraffe_error_pop();
783
784 return fibers;
785
786}
787
788
805cxint
806giraffe_fiberlist_save(GiTable *fibers, const cxchar *filename)
807{
808
809 const cxchar *fctid = "giraffe_fiberlist_save";
810
811 cxbool created = FALSE;
812
813 cxint code;
814
815 cpl_propertylist *properties = NULL;
816 cpl_table *table = NULL;
817
818
819 if (fibers == NULL || filename == NULL) {
820 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
821 return 1;
822 }
823
824 table = giraffe_table_get(fibers);
825
826 if (table == NULL) {
827 cpl_error_set(fctid, CPL_ERROR_DATA_NOT_FOUND);
828 return 1;
829 }
830
831 properties = giraffe_table_get_properties(fibers);
832
833 if (properties == NULL) {
834 properties = cpl_propertylist_new();
835
836 cpl_propertylist_append_string(properties, GIALIAS_EXTNAME,
837 GIFRAME_FIBER_SETUP);
838 created = TRUE;
839
840 giraffe_table_set_properties(fibers, properties);
841 }
842 else {
843 if (cpl_propertylist_has(properties, GIALIAS_EXTNAME)) {
844 cpl_propertylist_set_string(properties, GIALIAS_EXTNAME,
845 GIFRAME_FIBER_SETUP);
846 }
847 else {
848 cpl_propertylist_append_string(properties, GIALIAS_EXTNAME,
849 GIFRAME_FIBER_SETUP);
850 }
851 }
852 cpl_propertylist_set_comment(properties, GIALIAS_EXTNAME,
853 "FITS Extension name");
854
855 code = cpl_table_save(table, NULL, properties, filename, CPL_IO_EXTEND);
856
857 if (created == TRUE) {
858 cpl_propertylist_delete(properties);
859 }
860
861 return code == CPL_ERROR_NONE ? 0 : 1;
862
863}
864
865
882cxint
883giraffe_fiberlist_attach(cpl_frame *frame, GiTable *fibers)
884{
885
886 const cxchar *fctid = "giraffe_fiberlist_attach";
887
888
889 cxbool created = FALSE;
890
891 cxint status = 0;
892
893 cpl_propertylist *properties = NULL;
894
895 GiTable *_fibers = NULL;
896
897
898 if (frame == NULL || fibers == NULL) {
899 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
900 return 1;
901 }
902
903 _fibers = giraffe_table_duplicate(fibers);
904
905 properties = giraffe_table_get_properties(_fibers);
906
907 if (properties == NULL) {
908 properties = cpl_propertylist_new();
909 giraffe_table_set_properties(_fibers, properties);
910 created = TRUE;
911 }
912
913 if (cpl_table_has_column(giraffe_table_get(_fibers), "RINDEX")) {
914 cpl_table_erase_column(giraffe_table_get(_fibers), "RINDEX");
915 }
916
917 status = giraffe_frame_attach_table(frame, _fibers, GIFRAME_FIBER_SETUP,
918 TRUE);
919
920 if (created == TRUE) {
921 cpl_propertylist_delete(properties);
922 }
923
924 properties = NULL;
925
926 giraffe_table_delete(_fibers);
927 _fibers = NULL;
928
929 return status;
930
931}
932
933
951cxint giraffe_fiberlist_compare(const GiTable *fibers,
952 const GiTable *reference)
953{
954
955 register cxint i;
956 cxint equal = 1;
957
958 cpl_table *_fibers = giraffe_table_get(fibers);
959 cpl_table *_reference = giraffe_table_get(reference);
960
961
962 if (_fibers == NULL || _reference == NULL) {
963 return -1;
964 }
965
966 if (!cpl_table_has_column(_fibers, "FPS") ||
967 !cpl_table_has_column(_reference, "FPS")) {
968 return -2;
969 }
970
971
972 for (i = 0; i < cpl_table_get_nrow(_reference); i++) {
973
974 cxbool found = FALSE;
975
976 cxint j;
977 cxint fps = cpl_table_get_int(_reference, "FPS", i, NULL);
978
979 for (j = 0; j < cpl_table_get_nrow(_fibers); j++) {
980 cxint _fps = cpl_table_get_int(_fibers, "FPS", j, NULL);
981
982 if (fps == _fps) {
983 found = TRUE;
984 break;
985 }
986 }
987
988 if (found == FALSE) {
989 equal = 0;
990 break;
991 }
992
993 }
994
995 return equal;
996
997}
998
999
1020cxint
1021giraffe_fiberlist_associate(GiTable *fibers, const GiTable *reference)
1022{
1023
1024 const cxchar *fctid = "giraffe_fiberlist_associate";
1025
1026 register cxint i;
1027
1028 cxint nf = 0;
1029 cxint nr = 0;
1030
1031 cpl_table *_fibers = NULL;
1032 cpl_table *_reference = NULL;
1033
1034
1035 if (fibers == NULL) {
1036 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
1037 return 1;
1038 }
1039
1040 if (reference == NULL) {
1041 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
1042 return 1;
1043 }
1044
1045 _fibers = giraffe_table_get(fibers);
1046 _reference = giraffe_table_get(reference);
1047
1048 if (!cpl_table_has_column(_fibers, "FPS")) {
1049 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
1050 return 1;
1051 }
1052
1053 if (!cpl_table_has_column(_reference, "FPS")) {
1054 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
1055 return 1;
1056 }
1057
1058
1059 /*
1060 * Create new column containing the fiber index of the calibration
1061 * spectrum in the reference table which is used to process the current
1062 * spectrum.
1063 */
1064
1065 if (!cpl_table_has_column(_fibers, "RINDEX")) {
1066
1067 cxint size = cpl_table_get_nrow(_fibers);
1068
1069 cxint status = cpl_table_duplicate_column(_fibers, "RINDEX",
1070 _fibers, "INDEX");
1071
1072 if (status != CPL_ERROR_NONE) {
1073 return 2;
1074 }
1075
1076 status = cpl_table_fill_column_window_int(_fibers, "RINDEX", 0,
1077 size, -1);
1078
1079 if (status != CPL_ERROR_NONE) {
1080 return 2;
1081 }
1082
1083 }
1084
1085
1086 /*
1087 * Write the reference fiber index of all fibers with a corresponding
1088 * entry in the reference fiber list to the input fiber list and select
1089 * it. Extract all selected fibers.
1090 */
1091
1092 nf = cpl_table_get_nrow(_fibers);
1093 nr = cpl_table_get_nrow(_reference);
1094
1095 cpl_table_unselect_all(_fibers);
1096
1097 for (i = 0; i < nf; i++) {
1098
1099 register cxint j;
1100
1101 cxint fps = cpl_table_get_int(_fibers, "FPS", i, NULL);
1102
1103
1104 for (j = 0; j < nr; j++) {
1105
1106 cxint _fps = cpl_table_get_int(_reference, "FPS", j, NULL);
1107
1108
1109 if (fps == _fps) {
1110
1111 cxint ridx = cpl_table_get_int(_reference, "INDEX", j, NULL);
1112
1113 cpl_table_set_int(_fibers, "RINDEX", i, ridx);
1114 cpl_table_select_row(_fibers, i);
1115
1116 break;
1117 }
1118 }
1119 }
1120
1121
1122 /*
1123 * From this point on, _fibers is not just a reference anymore, but
1124 * points to a newly allocated table object, which must be managed
1125 * properly.
1126 */
1127
1128 _fibers = cpl_table_extract_selected(_fibers);
1129
1130
1131 /*
1132 * Rewrite index column
1133 */
1134
1135 for (i = 0; i < cpl_table_get_nrow(_fibers); i++) {
1136 cpl_table_set_int(_fibers, "INDEX", i, i + 1);
1137 }
1138
1139
1140 giraffe_table_set(fibers, _fibers);
1141
1142 cpl_table_delete(_fibers);
1143
1144 return 0;
1145
1146}
1147
1148
1162cxint
1164{
1165
1166 cpl_table* _fibers = NULL;
1167
1168 if (fibers == NULL) {
1169 return -1;
1170 }
1171
1172 _fibers = giraffe_table_get(fibers);
1173
1174 if (_fibers == NULL) {
1175 return 1;
1176 }
1177
1178 giraffe_error_push();
1179
1180 if (cpl_table_has_column(_fibers, "RINDEX") == TRUE) {
1181 cpl_table_erase_column(_fibers, "RINDEX");
1182 }
1183
1184 if (cpl_error_get_code() != CPL_ERROR_NONE) {
1185 return 2;
1186 }
1187
1188 giraffe_error_pop();
1189
1190 return 0;
1191
1192}
1208const cxchar *
1209giraffe_fiberlist_query_index(const cpl_table *fibers)
1210{
1211
1212 const cxchar *names[] = {"RINDEX", "INDEX", NULL};
1213 const cxchar **idx = names;
1214
1215
1216 while (*idx != NULL) {
1217
1218 if (cpl_table_has_column((cpl_table *)fibers, *idx) != 0) {
1219 break;
1220 }
1221
1222 ++idx;
1223 }
1224
1225 return *idx;
1226
1227}
1228
1229
1245cpl_array*
1246giraffe_fiberlist_get_subslits(const cpl_table* fibers)
1247{
1248
1249 cxint nfibers = 0;
1250
1251 cpl_array* subslits = NULL;
1252
1253
1254 cx_assert(fibers != NULL);
1255
1256 nfibers = cpl_table_get_nrow(fibers);
1257
1258
1259 if (nfibers > 0) {
1260
1261 cxint i = 0;
1262 cxint nss = 0;
1263 cxint* ssn = NULL;
1264
1265
1266 subslits = cpl_array_new(nfibers, CPL_TYPE_INT);
1267 cpl_array_fill_window(subslits, 0, nfibers, 0);
1268
1269 ssn = cpl_array_get_data_int(subslits);
1270
1271
1272 /*
1273 * Create sorted list of subslit numbers
1274 */
1275
1276 for (i = 0; i < nfibers; ++i) {
1277 ssn[i] = cpl_table_get_int(fibers, "SSN", i, NULL);
1278 }
1279
1280 qsort(ssn, nfibers, sizeof(cxint), _giraffe_compare_int);
1281
1282
1283 /*
1284 * Remove duplicate subslit numbers from the list
1285 */
1286
1287 for (i = 1; i < nfibers; ++i) {
1288 if (ssn[i] != ssn[nss]) {
1289 ssn[++nss] = ssn[i];
1290 }
1291 }
1292
1293 ++nss;
1294 cpl_array_set_size(subslits, nss);
1295
1296 }
1297
1298 return subslits;
1299
1300}
1301
1302
1332cxint *
1333giraffe_parse_spectrum_selection(const cxchar *selection, cxint *nspec)
1334{
1335
1336 cxchar **lists = NULL;
1337 cxchar **ranges = NULL;
1338
1339 cxint i;
1340 cxint first = 0;
1341 cxint nfibers = 0;
1342 cxint *fibers = NULL;
1343 cxint *_fibers = NULL;
1344
1345 cx_slist *fl = NULL;
1346
1347 cx_slist_iterator pos;
1348
1349
1350 *nspec = 0;
1351
1352 lists = cx_strsplit(selection, ";", 2);
1353
1354 if (lists == NULL) {
1355 return NULL;
1356 }
1357
1358 if (lists[1] != NULL) {
1359 gi_warning("Usage of fiber exclusion lists is not supported! "
1360 "The given exclusion list is ignored!");
1361 }
1362
1363 ranges = cx_strsplit(lists[0], ",", -1);
1364
1365 if (ranges == NULL) {
1366 cx_strfreev(lists);
1367 return NULL;
1368 }
1369
1370 i = 0;
1371 while (ranges[i] != NULL) {
1372
1373 cxchar **bounds = cx_strsplit(ranges[i], "-", 2);
1374
1375 cxint j;
1376
1377
1378 if (bounds == NULL) {
1379 cx_strfreev(ranges);
1380 cx_strfreev(lists);
1381
1382 if (fibers) {
1383 cx_free(fibers);
1384 }
1385
1386 return NULL;
1387 }
1388 else {
1389
1390 cxchar *last;
1391
1392 cxlong lower = -1;
1393 cxlong upper = -1;
1394
1395
1396 lower = strtol(bounds[0], &last, 10);
1397
1398 if (*last != '\0') {
1399 cx_strfreev(bounds);
1400 cx_strfreev(ranges);
1401 cx_strfreev(lists);
1402
1403 if (fibers) {
1404 cx_free(fibers);
1405 }
1406
1407 return NULL;
1408 }
1409
1410 if (bounds[1] != NULL) {
1411
1412 upper = strtol(bounds[1], &last, 10);
1413
1414 if (*last != '\0') {
1415 cx_strfreev(bounds);
1416 cx_strfreev(ranges);
1417 cx_strfreev(lists);
1418
1419 if (fibers) {
1420 cx_free(fibers);
1421 }
1422
1423 return NULL;
1424 }
1425 }
1426
1427 upper = upper > 0 ? upper : lower;
1428
1429 if (lower <= 0 || upper <= 0 || upper < lower) {
1430 cx_strfreev(bounds);
1431 cx_strfreev(ranges);
1432 cx_strfreev(lists);
1433
1434 if (fibers) {
1435 cx_free(fibers);
1436 }
1437
1438 return NULL;
1439 }
1440
1441 ++nfibers;
1442
1443 if (upper > lower) {
1444 nfibers += upper - lower;
1445 }
1446
1447 fibers = cx_realloc(fibers, nfibers * sizeof(cxint));
1448
1449 for (j = first; j < nfibers; j++) {
1450 fibers[j] = lower + j - first;
1451 }
1452
1453 first = nfibers;
1454
1455 }
1456
1457 cx_strfreev(bounds);
1458 bounds = NULL;
1459
1460 ++i;
1461
1462 }
1463
1464 cx_strfreev(ranges);
1465 cx_strfreev(lists);
1466
1467 qsort(fibers, nfibers, sizeof(cxint), _giraffe_compare_int);
1468
1469
1470 /*
1471 * Remove duplicates from the fiber list
1472 */
1473
1474 fl = cx_slist_new();
1475
1476 for (i = 0; i < nfibers; i++) {
1477 cx_slist_push_back(fl, fibers + i);
1478 }
1479
1480 cx_slist_unique(fl, _giraffe_compare_int);
1481
1482 nfibers = cx_slist_size(fl);
1483 _fibers = cx_malloc(nfibers * sizeof(cxint));
1484
1485 i = 0;
1486
1487 pos = cx_slist_begin(fl);
1488 while (pos != cx_slist_end(fl)) {
1489
1490 cxint *fn = cx_slist_get(fl, pos);
1491
1492 cx_assert(fn != NULL);
1493 _fibers[i] = *fn;
1494
1495 pos = cx_slist_next(fl, pos);
1496 ++i;
1497 }
1498 cx_slist_delete(fl);
1499 cx_free(fibers);
1500
1501 *nspec = nfibers;
1502 return _fibers;
1503
1504}
1505
1506
1518cxint *
1520 const GiTable *reference, cxint *nspec)
1521{
1522
1523 cpl_table *fibers = giraffe_fiberlist_create(filename, 0, NULL);
1524 cpl_table *_reference = giraffe_table_get(reference);
1525
1526 cxint i = 0;
1527 cxint nspectra = 0;
1528 cxint nfibers = cpl_table_get_nrow(fibers);
1529 cxint nactive = cpl_table_get_nrow(_reference);
1530 cxint *spectra = NULL;
1531
1532
1533 if (fibers == NULL) {
1534 return NULL;
1535 }
1536
1537 if (!cpl_table_has_column(fibers, "FPS") ||
1538 !cpl_table_has_column(fibers, "FPD")) {
1539 cpl_table_delete(fibers);
1540 return NULL;
1541 }
1542
1543 if (!cpl_table_has_column(_reference, "FPS")) {
1544 cpl_table_delete(fibers);
1545 return NULL;
1546 }
1547
1548 if (nactive > nfibers) {
1549 cpl_table_delete(fibers);
1550 return NULL;
1551 }
1552
1553 *nspec = 0;
1554 spectra = cx_malloc(nactive * sizeof(cxint));
1555
1556 for (i = 0; i < nactive; ++i) {
1557
1558 cxint j = 0;
1559 cxint fps = cpl_table_get_int(_reference, "FPS", i, NULL);
1560
1561 for (j = 0; j < nfibers; ++j) {
1562
1563 cxint _fps = cpl_table_get_int(fibers, "FPS", j, NULL);
1564 cxint _fpd = cpl_table_get_int(fibers, "FPD", j, NULL);
1565
1566 if (_fps == fps) {
1567 spectra[nspectra] = _fpd;
1568 ++nspectra;
1569 break;
1570 }
1571
1572 }
1573
1574 }
1575
1576 cpl_table_delete(fibers);
1577
1578 if (nspectra < nactive) {
1579 spectra = cx_realloc(spectra, nspectra * sizeof(cxint));
1580 }
1581
1582 qsort(spectra, nspectra, sizeof(cxint), _giraffe_compare_int);
1583 *nspec = nspectra;
1584
1585 return spectra;
1586
1587}
GiTable * giraffe_fiberlist_load(const cxchar *filename, cxint dataset, const cxchar *tag)
Load a fiber table from a file.
Definition: gifiberutils.c:753
cpl_table * giraffe_fiberlist_create(const cxchar *filename, cxint nspec, const cxint *spectra)
Creates the fiber table.
Definition: gifiberutils.c:85
cxint giraffe_fiberlist_save(GiTable *fibers, const cxchar *filename)
Save a fiber table to a file.
Definition: gifiberutils.c:806
cxint giraffe_fiberlist_compare(const GiTable *fibers, const GiTable *reference)
Compare two fiber lists.
Definition: gifiberutils.c:951
cxint giraffe_fiberlist_attach(cpl_frame *frame, GiTable *fibers)
Attach a fiber table to a frame.
Definition: gifiberutils.c:883
cpl_array * giraffe_fiberlist_get_subslits(const cpl_table *fibers)
Get the list of subslit identifiers from a fiber setup.
const cxchar * giraffe_fiberlist_query_index(const cpl_table *fibers)
Query a fiber list for the name of the fiber reference index column.
cxint * giraffe_parse_spectrum_selection(const cxchar *selection, cxint *nspec)
Parses a spectrum selection string.
cxint * giraffe_create_spectrum_selection(const cxchar *filename, const GiTable *reference, cxint *nspec)
Create a spectrum selection from a reference table.
cxint giraffe_fiberlist_associate(GiTable *fibers, const GiTable *reference)
Associate a fiberlist with a reference list.
cxint giraffe_fiberlist_clear_index(GiTable *fibers)
Remove the reference index column from a fiber list.
cxint giraffe_frame_attach_table(cpl_frame *frame, GiTable *table, const cxchar *tag, cxbool update)
Attach a table to a product frame.
Definition: giframe.c:638
void gi_warning(const cxchar *format,...)
Log a warning.
Definition: gimessages.c:119
cxint giraffe_table_set(GiTable *self, cpl_table *table)
Sets the table data.
Definition: gitable.c:456
GiTable * giraffe_table_new(void)
Creates a new, empty Giraffe table.
Definition: gitable.c:85
GiTable * giraffe_table_duplicate(const GiTable *src)
Duplicate a Giraffe table.
Definition: gitable.c:176
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.
Definition: gitable.c:562
void giraffe_table_delete(GiTable *self)
Destroys a Giraffe table.
Definition: gitable.c:154
cpl_table * giraffe_table_get(const GiTable *self)
Get the table data from a Giraffe table.
Definition: gitable.c:433
cpl_propertylist * giraffe_table_get_properties(const GiTable *self)
Gets the table properties.
Definition: gitable.c:489
cxint giraffe_table_set_properties(GiTable *self, cpl_propertylist *properties)
Attaches a property list to an table.
Definition: gitable.c:516
GiInstrumentMode giraffe_get_mode(cpl_propertylist *properties)
Determines the instrument mode from a property list.
Definition: giutils.c:442

This file is part of the GIRAFFE Pipeline Reference Manual 2.18.4.
Documentation copyright © 2002-2006 European Southern Observatory.
Generated on Mon Jul 7 2025 10:23:39 by doxygen 1.9.6 written by Dimitri van Heesch, © 1997-2004