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 cx_string *slit_name = NULL;
101
102 cpl_table *fibers = NULL;
103 cpl_table *_slits;
104 cpl_table *_ozpoz;
105
106 cpl_propertylist *properties = NULL;
107 cpl_propertylist *sorting_order = NULL;
108
109 GiTable *slits = NULL;
110 GiTable *ozpoz = NULL;
111
112 GiInstrumentMode mode;
113
114
115
116 if (!filename) {
117 return NULL;
118 }
119
120
121 /*
122 * Check whether the input file is a calibration and retrieve the
123 * name of the slit in use.
124 */
125
126 properties = cpl_propertylist_load(filename, 0);
127
128 if (properties == NULL) {
129 cpl_msg_error(fctid, "Cannot load properties of data set 0 "
130 "from `%s'!", filename);
131 cpl_propertylist_delete(properties);
132 return NULL;
133 }
134 else {
135
136 if (!cpl_propertylist_has(properties, GIALIAS_STSCFF) &&
137 !cpl_propertylist_has(properties, GIALIAS_STSCTAL)) {
138 cpl_msg_warning(fctid, "%s: Properties (%s, %s) not found! "
139 "Simultaneous calibration lamps assumed to "
140 "be off!", filename, GIALIAS_STSCFF,
141 GIALIAS_STSCTAL);
142 calsim = FALSE;
143 }
144 else {
145
146 cxint scff = cpl_propertylist_get_bool(properties,
147 GIALIAS_STSCFF);
148 cxint sctal= cpl_propertylist_get_bool(properties,
149 GIALIAS_STSCTAL);
150
151
152 if (scff || sctal) {
153 cpl_msg_info(fctid, "Simultaneous calibration lamps "
154 "are on.");
155 calsim = TRUE;
156 }
157 else {
158 cpl_msg_info(fctid, "Simultaneous calibration lamps "
159 "are off.");
160 calsim = FALSE;
161 }
162
163 }
164
165
166 slit_name =
167 cx_string_create(cpl_propertylist_get_string(properties,
168 GIALIAS_SLITNAME));
169 if (!slit_name) {
170 cpl_msg_error(fctid, "%s: Property (%s) not found!", filename,
171 GIALIAS_SLITNAME);
172 cpl_propertylist_delete(properties);
173 return NULL;
174 }
175 else {
176 cx_string_strip(slit_name);
177 }
178
179 mode = giraffe_get_mode(properties);
180
181 if (mode == GIMODE_NONE) {
182 cpl_msg_error(fctid, "Invalid instrument mode!");
183
184 cx_string_delete(slit_name);
185 cpl_propertylist_delete(properties);
186
187 return NULL;
188 }
189
190 cpl_propertylist_delete(properties);
191 }
192
193
194 /*
195 * Load OzPoz table from current frame
196 */
197
198 ozpoz = giraffe_table_new();
199 cx_assert(ozpoz != NULL);
200
201 giraffe_error_push();
202
203 status = giraffe_table_load(ozpoz, filename, GIOZPOZ_EXTENSION,
204 GIOZPOZ_MAGIC);
205
206 if (status) {
207 if (cpl_error_get_code() == CPL_ERROR_BAD_FILE_FORMAT) {
208 cpl_msg_error(fctid, "Data set %d in `%s' is not an "
209 "OzPoz table!", GIOZPOZ_EXTENSION, filename);
211 cpl_table_delete(fibers);
212
213 return NULL;
214 }
215 else {
216 if (status != 2) {
217 cpl_msg_error(fctid, "No OzPoz table found in `%s'!",
218 filename);
220 return NULL;
221 }
222
223 cpl_msg_warning(fctid, "Empty OzPoz table found in `%s'.",
224 filename);
225
226 }
227 }
228
229 giraffe_error_pop();
230
231 _ozpoz = giraffe_table_get(ozpoz);
232
233
234 /*
235 * Load fiber table from current frame.
236 */
237
238 slits = giraffe_table_new();
239 cx_assert(slits != NULL);
240
241 giraffe_error_push();
242
243 if (giraffe_table_load(slits, filename, GIFIBER_EXTENSION,
244 GIFIBER_MAGIC)) {
245 if (cpl_error_get_code() == CPL_ERROR_BAD_FILE_FORMAT) {
246 cpl_msg_error(fctid, "Data set %d in `%s' is not a fiber table!",
247 GIFIBER_EXTENSION, filename);
249 return NULL;
250 }
251 else {
252 cpl_msg_error(fctid, "Cannot load data set %d (fiber table) "
253 "from `%s'!", GIFIBER_EXTENSION, filename);
255 return NULL;
256 }
257 }
258
259 giraffe_error_pop();
260
261 _slits = giraffe_table_get(slits);
262
263
264 /*
265 * Select all entries with the appropriate slit name from the table
266 */
267
268 cpl_table_select_all(_slits);
269 cpl_table_and_selected_string(_slits, "Slit", CPL_NOT_EQUAL_TO,
270 cx_string_get(slit_name));
271
272 giraffe_error_push();
273
274 cpl_table_erase_selected(_slits);
275
276 if (cpl_error_get_code() != CPL_ERROR_NONE) {
277 cpl_msg_error(fctid, "Invalid slit `%s' selected. No fibers found.",
278 cx_string_get(slit_name));
279
280 cx_string_delete(slit_name);
281 slit_name = NULL;
282
284 slits = NULL;
285
286 return NULL;
287 }
288
289 giraffe_error_pop();
290
291 cx_string_delete(slit_name);
292 slit_name = NULL;
293
294
295 /*
296 * Move the relevant columns from the fiber table to the
297 * final fibers list.
298 */
299
300 nfibers = cpl_table_get_nrow(_slits);
301 fibers = cpl_table_new(nfibers);
302
303 giraffe_error_push();
304
305 cpl_table_new_column(fibers, "INDEX", CPL_TYPE_INT);
306 cpl_table_new_column(fibers, "FPS", CPL_TYPE_INT);
307 cpl_table_new_column(fibers, "SSN", CPL_TYPE_INT);
308 cpl_table_new_column(fibers, "PSSN", CPL_TYPE_INT);
309 cpl_table_new_column(fibers, "RP", CPL_TYPE_INT);
310
311 for (i = 0; i < nfibers; i++) {
312
313 cxchar *s;
314
315 cxint fps = strtol(cpl_table_get_string(_slits, "FPS", i), NULL, 10);
316 cxint ssn = strtol(cpl_table_get_string(_slits, "SSN", i), NULL, 10);
317 cxint pssn = strtol(cpl_table_get_string(_slits, "PSSN", i),
318 NULL, 10);
319 cxint rp = -1;
320
321
322 s = (cxchar*) cpl_table_get_string(_slits, "RP", i);
323
324 if (s != NULL) {
325 rp = strtol(s, NULL, 10);
326 }
327 else {
328 if (mode == GIMODE_ARGUS) {
329
330 const cxchar *rpid = cpl_table_get_string(_slits,
331 "Retractor", i);
332
333 if (cx_strncasecmp(rpid, "Cal", 3) != 0) {
334 rp = 0;
335 }
336
337 }
338 }
339
340 cpl_table_set_int(fibers, "FPS", i, fps);
341 cpl_table_set_int(fibers, "SSN", i, ssn);
342 cpl_table_set_int(fibers, "PSSN", i, pssn);
343 cpl_table_set_int(fibers, "RP", i, rp);
344
345 }
346
347 if (mode == GIMODE_IFU || mode == GIMODE_ARGUS) {
348
349 if (cpl_table_has_column(_slits, "X") &&
350 cpl_table_has_column(_slits, "Y")) {
351
352 cpl_table_new_column(fibers, "X", CPL_TYPE_INT);
353 cpl_table_new_column(fibers, "Y", CPL_TYPE_INT);
354
355 for (i = 0; i < nfibers; i++) {
356 const cxchar *s;
357
358 cxint x = 0;
359 cxint y = 0;
360
361
362 s = cpl_table_get_string(_slits, "X", i);
363
364 if (s != NULL) {
365 x = strtol(s, NULL, 10);
366 }
367
368 s = cpl_table_get_string(_slits, "Y", i);
369
370 if (s != NULL) {
371 y = strtol(s, NULL, 10);
372 }
373
374 cpl_table_set_int(fibers, "X", i, x);
375 cpl_table_set_int(fibers, "Y", i, y);
376 }
377
378 }
379
380 }
381
382 cpl_table_move_column(fibers, "Retractor", _slits);
383
384 if (cpl_error_get_code() != CPL_ERROR_NONE) {
385 cpl_msg_error(fctid, "Data set %d in `%s' is not a valid "
386 "fiber table!", GIFIBER_EXTENSION, filename);
388 cpl_table_delete(fibers);
389
390 return NULL;
391 }
392
393 giraffe_error_pop();
394
396
397
398 /*
399 * For Argus the slit is mirrored compared to IFU and Medusa
400 * and we have to reverse the order of the slits table.
401 */
402
403 if (mode == GIMODE_ARGUS) {
404
405 sorting_order = cpl_propertylist_new();
406
407 cpl_propertylist_append_bool(sorting_order, "FPS", 1);
408 cpl_table_sort(fibers, sorting_order);
409
410 cpl_propertylist_delete(sorting_order);
411 sorting_order = NULL;
412
413 }
414
415
416 /*
417 * Postprocess initial fiber table
418 */
419
420 for (i = 0; i < nfibers; i++) {
421
422 const cxchar *s = cpl_table_get_string(fibers, "Retractor", i);
423
424
425 if (strstr(s, "Calibration")) {
426 cpl_table_set_int(fibers, "RP", i, -1);
427 }
428
429 cpl_table_set_int(fibers, "INDEX", i, i + 1);
430
431 }
432
433 if (!cpl_table_has_column(fibers, "FPD")) {
434 cpl_table_duplicate_column(fibers, "FPD", fibers, "INDEX");
435 }
436
437 cpl_table_new_column(fibers, "OBJECT", CPL_TYPE_STRING);
438 cpl_table_new_column(fibers, "R", CPL_TYPE_DOUBLE);
439 cpl_table_new_column(fibers, "THETA", CPL_TYPE_DOUBLE);
440 cpl_table_new_column(fibers, "ORIENT", CPL_TYPE_DOUBLE);
441 cpl_table_new_column(fibers, "TYPE", CPL_TYPE_STRING);
442
443 cpl_table_fill_column_window_double(fibers, "R", 0, nfibers, 0.);
444 cpl_table_fill_column_window_double(fibers, "THETA", 0, nfibers, 0.);
445 cpl_table_fill_column_window_double(fibers, "ORIENT", 0, nfibers, 0.);
446
447 if (_ozpoz != NULL) {
448 if (cpl_table_has_column(_ozpoz, "RA")) {
449 cpl_table_new_column(fibers, "RA", CPL_TYPE_DOUBLE);
450 cpl_table_fill_column_window_double(fibers, "RA", 0,
451 nfibers, 0.);
452 }
453
454 if (cpl_table_has_column(_ozpoz, "DEC")) {
455 cpl_table_new_column(fibers, "DEC", CPL_TYPE_DOUBLE);
456 cpl_table_fill_column_window_double(fibers, "DEC", 0,
457 nfibers, 0.);
458 }
459
460 if (cpl_table_has_column(_ozpoz, "MAGNITUDE")) {
461 cpl_table_new_column(fibers, "MAGNITUDE", CPL_TYPE_DOUBLE);
462 cpl_table_fill_column_window_double(fibers, "MAGNITUDE", 0,
463 nfibers, 0.);
464 }
465
466 if (cpl_table_has_column(_ozpoz, "B_V")) {
467 cpl_table_new_column(fibers, "B_V", CPL_TYPE_DOUBLE);
468 cpl_table_fill_column_window_double(fibers, "B_V", 0,
469 nfibers, 0.);
470 }
471 }
472
473
474 /*
475 * Select rows in the fiber table which have a corresponding entry
476 * in the OzPoz table. Both tables are associated using the
477 * `button number'. For matching entries the OzPoz data is copied
478 * to the fiber table. Also the simultaneous calibration fibers
479 * are copied.
480 */
481
482 nbuttons = _ozpoz == NULL ? 0 : cpl_table_get_nrow(_ozpoz);
483
484 cpl_table_select_all(fibers);
485
486 for (i = 0; i < nfibers; i++) {
487
488 cxbool missing = TRUE;
489
490 cxint fiber = cpl_table_get_int(fibers, "RP", i, NULL);
491
492
493 /*
494 * If fiber equals -1 it is a simultaneous calibration, which
495 * has no entry in the OzPoz table. Otherwise we try to find it
496 * in the OzPoz table and copy the data for this fiber.
497 */
498
499 if (fiber == -1 && calsim == TRUE) {
500 cpl_table_set_string(fibers, "OBJECT", i, "CALSIM");
501 cpl_table_unselect_row(fibers, i);
502 missing = FALSE;
503 }
504 else if (fiber == 0 && mode == GIMODE_ARGUS) {
505 cpl_table_unselect_row(fibers, i);
506 missing = FALSE;
507 }
508 else {
509
510 register cxint j;
511
512
513 for (j = 0; j < nbuttons; j++) {
514
515 cxint button = cpl_table_get_int(_ozpoz, "BUTTON", j, NULL);
516
517
518 if (fiber == button) {
519 const cxchar *object;
520 const cxchar *otype;
521
522 cxdouble r, theta, orient;
523
524 cxdouble ra = 0.;
525 cxdouble dec = 0.;
526 cxdouble mag = 0.;
527 cxdouble b_v = 0.;
528
529
530 object = cpl_table_get_string(_ozpoz, "OBJECT", j);
531 otype = cpl_table_get_string(_ozpoz, "TYPE", j);
532
533 r = cpl_table_get_double(_ozpoz, "R", j, NULL);
534 theta = cpl_table_get_double(_ozpoz, "THETA", j, NULL);
535 orient = cpl_table_get_double(_ozpoz, "ORIENT", j, NULL);
536
537 if (cpl_table_has_column(_ozpoz, "RA")) {
538 ra = cpl_table_get_double(_ozpoz, "RA", j, NULL);
539 }
540
541 if (cpl_table_has_column(_ozpoz, "DEC")) {
542 dec = cpl_table_get_double(_ozpoz, "DEC", j, NULL);
543 }
544
545 if (cpl_table_has_column(_ozpoz, "MAGNITUDE")) {
546 mag = cpl_table_get_float(_ozpoz, "MAGNITUDE", j,
547 NULL);
548 }
549
550 if (cpl_table_has_column(_ozpoz, "B_V")) {
551 b_v = cpl_table_get_double(_ozpoz, "B_V", j, NULL);
552 b_v = CX_CLAMP(b_v, -5., 5.);
553 }
554
555 cpl_table_set_string(fibers, "OBJECT", i, object);
556 cpl_table_set_string(fibers, "TYPE", i, otype);
557
558 cpl_table_set_double(fibers, "R", i, r);
559 cpl_table_set_double(fibers, "THETA", i, theta);
560 cpl_table_set_double(fibers, "ORIENT", i, orient);
561
562 if (cpl_table_has_column(fibers, "RA")) {
563 cpl_table_set_double(fibers, "RA", i, ra);
564 }
565
566 if (cpl_table_has_column(fibers, "DEC")) {
567 cpl_table_set_double(fibers, "DEC", i, dec);
568 }
569
570 if (cpl_table_has_column(fibers, "MAGNITUDE")) {
571 cpl_table_set_double(fibers, "MAGNITUDE", i, mag);
572 }
573
574 if (cpl_table_has_column(fibers, "B_V")) {
575 cpl_table_set_double(fibers, "B_V", i, b_v);
576 }
577
578 cpl_table_unselect_row(fibers, i);
579 missing = FALSE;
580 break;
581 }
582 }
583 }
584
585 if (missing == TRUE) {
586
587 cxint _fps = cpl_table_get_int(fibers, "FPS", i, NULL);
588 cpl_msg_debug(fctid, "Fiber at FPS = %d is not used", _fps);
589
590 }
591
592 }
593
594
595 giraffe_error_push();
596
597 cpl_table_erase_selected(fibers);
598
599 if (cpl_error_get_code() != CPL_ERROR_NONE) {
600 cpl_table_delete(fibers);
601 return NULL;
602 }
603
604 giraffe_error_pop();
605
607 ozpoz = NULL;
608
609
610 /*
611 * Finalize the fiber list by applying the user specified fiber
612 * selection list. Fibers which do not have an entry in the
613 * OzPoz table or which are beyond the limits are ignored.
614 */
615
616 if (spectra && nspec > 0) {
617
618 register cxint rows = cpl_table_get_nrow(fibers);
619
620
621 cx_assert(cpl_table_get_column_type(fibers, "FPD") == CPL_TYPE_INT);
622
623 cpl_table_select_all(fibers);
624
625 for (i = 0; i < rows; i++) {
626
627 register cxint j;
628 register cxint selected = 0;
629 register cxint idx = cpl_table_get_int(fibers, "FPD", i, NULL);
630
631
632 for (j = 0; j < nspec; j++) {
633 if (idx == spectra[j]) {
634 selected = 1;
635 break;
636 }
637 }
638
639 if (selected) {
640 cpl_table_unselect_row(fibers, i);
641 }
642 else {
643 cpl_table_select_row(fibers, i);
644 }
645
646 }
647
648 giraffe_error_push();
649
650 cpl_table_erase_selected(fibers);
651
652 if (cpl_error_get_code() != CPL_ERROR_NONE) {
653 cpl_table_delete(fibers);
654 return NULL;
655 }
656
657 giraffe_error_pop();
658
659 }
660
661
662 /*
663 * Update index column
664 */
665
666 for (i = 0; i < cpl_table_get_nrow(fibers); i++) {
667 cpl_table_set_int(fibers, "INDEX", i, i + 1);
668 }
669
670
671 /*
672 * Sort the final table according to the INDEX column
673 */
674
675 cx_assert(sorting_order == NULL);
676
677 sorting_order = cpl_propertylist_new();
678 cpl_propertylist_append_bool(sorting_order, "INDEX", 0);
679
680 cpl_table_sort(fibers, sorting_order);
681
682 cpl_propertylist_delete(sorting_order);
683 sorting_order = NULL;
684
685
686 return fibers;
687
688}
689
690
714GiTable *
715giraffe_fiberlist_load(const cxchar *filename, cxint dataset,
716 const cxchar *tag)
717{
718
719 const cxchar *fctid = "giraffe_fiberlist_load";
720
721
722 GiTable *fibers = giraffe_table_new();
723
724
725 cx_assert(fibers != NULL);
726
727 giraffe_error_push();
728
729 if (giraffe_table_load(fibers, filename, dataset, tag)) {
730 if (cpl_error_get_code() == CPL_ERROR_BAD_FILE_FORMAT) {
731 cpl_msg_error(fctid, "Data set %d in `%s' is not a fiber table!",
732 dataset, filename);
733 giraffe_table_delete(fibers);
734 return NULL;
735 }
736 else {
737 cpl_msg_error(fctid, "Cannot load data set %d (fiber table) "
738 "from `%s'!", dataset, filename);
739 giraffe_table_delete(fibers);
740 return NULL;
741 }
742 }
743
744 giraffe_error_pop();
745
746 return fibers;
747
748}
749
750
767cxint
768giraffe_fiberlist_save(GiTable *fibers, const cxchar *filename)
769{
770
771 const cxchar *fctid = "giraffe_fiberlist_save";
772
773 cxbool created = FALSE;
774
775 cxint code;
776
777 cpl_propertylist *properties = NULL;
778 cpl_table *table = NULL;
779
780
781 if (fibers == NULL || filename == NULL) {
782 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
783 return 1;
784 }
785
786 table = giraffe_table_get(fibers);
787
788 if (table == NULL) {
789 cpl_error_set(fctid, CPL_ERROR_DATA_NOT_FOUND);
790 return 1;
791 }
792
793 properties = giraffe_table_get_properties(fibers);
794
795 if (properties == NULL) {
796 properties = cpl_propertylist_new();
797
798 cpl_propertylist_append_string(properties, GIALIAS_EXTNAME,
799 GIFRAME_FIBER_SETUP);
800 created = TRUE;
801
802 giraffe_table_set_properties(fibers, properties);
803 }
804 else {
805 if (cpl_propertylist_has(properties, GIALIAS_EXTNAME)) {
806 cpl_propertylist_set_string(properties, GIALIAS_EXTNAME,
807 GIFRAME_FIBER_SETUP);
808 }
809 else {
810 cpl_propertylist_append_string(properties, GIALIAS_EXTNAME,
811 GIFRAME_FIBER_SETUP);
812 }
813 }
814 cpl_propertylist_set_comment(properties, GIALIAS_EXTNAME,
815 "FITS Extension name");
816
817 code = cpl_table_save(table, NULL, properties, filename, CPL_IO_EXTEND);
818
819 if (created == TRUE) {
820 cpl_propertylist_delete(properties);
821 }
822
823 return code == CPL_ERROR_NONE ? 0 : 1;
824
825}
826
827
844cxint
845giraffe_fiberlist_attach(cpl_frame *frame, GiTable *fibers)
846{
847
848 const cxchar *fctid = "giraffe_fiberlist_attach";
849
850
851 cxbool created = FALSE;
852
853 cxint status = 0;
854
855 cpl_propertylist *properties = NULL;
856
857 GiTable *_fibers = NULL;
858
859
860 if (frame == NULL || fibers == NULL) {
861 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
862 return 1;
863 }
864
865 _fibers = giraffe_table_duplicate(fibers);
866
867 properties = giraffe_table_get_properties(_fibers);
868
869 if (properties == NULL) {
870 properties = cpl_propertylist_new();
871 giraffe_table_set_properties(_fibers, properties);
872 created = TRUE;
873 }
874
875 if (cpl_table_has_column(giraffe_table_get(_fibers), "RINDEX")) {
876 cpl_table_erase_column(giraffe_table_get(_fibers), "RINDEX");
877 }
878
879 status = giraffe_frame_attach_table(frame, _fibers, GIFRAME_FIBER_SETUP,
880 TRUE);
881
882 if (created == TRUE) {
883 cpl_propertylist_delete(properties);
884 }
885
886 properties = NULL;
887
888 giraffe_table_delete(_fibers);
889 _fibers = NULL;
890
891 return status;
892
893}
894
895
913cxint giraffe_fiberlist_compare(const GiTable *fibers,
914 const GiTable *reference)
915{
916
917 register cxint i;
918 cxint equal = 1;
919
920 cpl_table *_fibers = giraffe_table_get(fibers);
921 cpl_table *_reference = giraffe_table_get(reference);
922
923
924 if (_fibers == NULL || _reference == NULL) {
925 return -1;
926 }
927
928 if (!cpl_table_has_column(_fibers, "FPS") ||
929 !cpl_table_has_column(_reference, "FPS")) {
930 return -2;
931 }
932
933
934 for (i = 0; i < cpl_table_get_nrow(_reference); i++) {
935
936 cxbool found = FALSE;
937
938 cxint j;
939 cxint fps = cpl_table_get_int(_reference, "FPS", i, NULL);
940
941 for (j = 0; j < cpl_table_get_nrow(_fibers); j++) {
942 cxint _fps = cpl_table_get_int(_fibers, "FPS", j, NULL);
943
944 if (fps == _fps) {
945 found = TRUE;
946 break;
947 }
948 }
949
950 if (found == FALSE) {
951 equal = 0;
952 break;
953 }
954
955 }
956
957 return equal;
958
959}
960
961
982cxint
983giraffe_fiberlist_associate(GiTable *fibers, const GiTable *reference)
984{
985
986 const cxchar *fctid = "giraffe_fiberlist_associate";
987
988 register cxint i;
989
990 cxint nf = 0;
991 cxint nr = 0;
992
993 cpl_table *_fibers = NULL;
994 cpl_table *_reference = NULL;
995
996
997 if (fibers == NULL) {
998 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
999 return 1;
1000 }
1001
1002 if (reference == NULL) {
1003 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
1004 return 1;
1005 }
1006
1007 _fibers = giraffe_table_get(fibers);
1008 _reference = giraffe_table_get(reference);
1009
1010 if (!cpl_table_has_column(_fibers, "FPS")) {
1011 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
1012 return 1;
1013 }
1014
1015 if (!cpl_table_has_column(_reference, "FPS")) {
1016 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
1017 return 1;
1018 }
1019
1020
1021 /*
1022 * Create new column containing the fiber index of the calibration
1023 * spectrum in the reference table which is used to process the current
1024 * spectrum.
1025 */
1026
1027 if (!cpl_table_has_column(_fibers, "RINDEX")) {
1028
1029 cxint size = cpl_table_get_nrow(_fibers);
1030
1031 cxint status = cpl_table_duplicate_column(_fibers, "RINDEX",
1032 _fibers, "INDEX");
1033
1034 if (status != CPL_ERROR_NONE) {
1035 return 2;
1036 }
1037
1038 status = cpl_table_fill_column_window_int(_fibers, "RINDEX", 0,
1039 size, -1);
1040
1041 if (status != CPL_ERROR_NONE) {
1042 return 2;
1043 }
1044
1045 }
1046
1047
1048 /*
1049 * Write the reference fiber index of all fibers with a corresponding
1050 * entry in the reference fiber list to the input fiber list and select
1051 * it. Extract all selected fibers.
1052 */
1053
1054 nf = cpl_table_get_nrow(_fibers);
1055 nr = cpl_table_get_nrow(_reference);
1056
1057 cpl_table_unselect_all(_fibers);
1058
1059 for (i = 0; i < nf; i++) {
1060
1061 register cxint j;
1062
1063 cxint fps = cpl_table_get_int(_fibers, "FPS", i, NULL);
1064
1065
1066 for (j = 0; j < nr; j++) {
1067
1068 cxint _fps = cpl_table_get_int(_reference, "FPS", j, NULL);
1069
1070
1071 if (fps == _fps) {
1072
1073 cxint ridx = cpl_table_get_int(_reference, "INDEX", j, NULL);
1074
1075 cpl_table_set_int(_fibers, "RINDEX", i, ridx);
1076 cpl_table_select_row(_fibers, i);
1077
1078 break;
1079 }
1080 }
1081 }
1082
1083
1084 /*
1085 * From this point on, _fibers is not just a reference anymore, but
1086 * points to a newly allocated table object, which must be managed
1087 * properly.
1088 */
1089
1090 _fibers = cpl_table_extract_selected(_fibers);
1091
1092
1093 /*
1094 * Rewrite index column
1095 */
1096
1097 for (i = 0; i < cpl_table_get_nrow(_fibers); i++) {
1098 cpl_table_set_int(_fibers, "INDEX", i, i + 1);
1099 }
1100
1101
1102 giraffe_table_set(fibers, _fibers);
1103
1104 cpl_table_delete(_fibers);
1105
1106 return 0;
1107
1108}
1109
1110
1124cxint
1126{
1127
1128 cpl_table* _fibers = NULL;
1129
1130 if (fibers == NULL) {
1131 return -1;
1132 }
1133
1134 _fibers = giraffe_table_get(fibers);
1135
1136 if (_fibers == NULL) {
1137 return 1;
1138 }
1139
1140 giraffe_error_push();
1141
1142 if (cpl_table_has_column(_fibers, "RINDEX") == TRUE) {
1143 cpl_table_erase_column(_fibers, "RINDEX");
1144 }
1145
1146 if (cpl_error_get_code() != CPL_ERROR_NONE) {
1147 return 2;
1148 }
1149
1150 giraffe_error_pop();
1151
1152 return 0;
1153
1154}
1170const cxchar *
1171giraffe_fiberlist_query_index(const cpl_table *fibers)
1172{
1173
1174 const cxchar *names[] = {"RINDEX", "INDEX", NULL};
1175 const cxchar **idx = names;
1176
1177
1178 while (*idx != NULL) {
1179
1180 if (cpl_table_has_column((cpl_table *)fibers, *idx) != 0) {
1181 break;
1182 }
1183
1184 ++idx;
1185 }
1186
1187 return *idx;
1188
1189}
1190
1191
1207cpl_array*
1208giraffe_fiberlist_get_subslits(const cpl_table* fibers)
1209{
1210
1211 cxint nfibers = 0;
1212
1213 cpl_array* subslits = NULL;
1214
1215
1216 cx_assert(fibers != NULL);
1217
1218 nfibers = cpl_table_get_nrow(fibers);
1219
1220
1221 if (nfibers > 0) {
1222
1223 cxint i = 0;
1224 cxint nss = 0;
1225 cxint* ssn = NULL;
1226
1227
1228 subslits = cpl_array_new(nfibers, CPL_TYPE_INT);
1229 cpl_array_fill_window(subslits, 0, nfibers, 0);
1230
1231 ssn = cpl_array_get_data_int(subslits);
1232
1233
1234 /*
1235 * Create sorted list of subslit numbers
1236 */
1237
1238 for (i = 0; i < nfibers; ++i) {
1239 ssn[i] = cpl_table_get_int(fibers, "SSN", i, NULL);
1240 }
1241
1242 qsort(ssn, nfibers, sizeof(cxint), _giraffe_compare_int);
1243
1244
1245 /*
1246 * Remove duplicate subslit numbers from the list
1247 */
1248
1249 for (i = 1; i < nfibers; ++i) {
1250 if (ssn[i] != ssn[nss]) {
1251 ssn[++nss] = ssn[i];
1252 }
1253 }
1254
1255 ++nss;
1256 cpl_array_set_size(subslits, nss);
1257
1258 }
1259
1260 return subslits;
1261
1262}
1263
1264
1294cxint *
1295giraffe_parse_spectrum_selection(const cxchar *selection, cxint *nspec)
1296{
1297
1298 cxchar **lists = NULL;
1299 cxchar **ranges = NULL;
1300
1301 cxint i;
1302 cxint first = 0;
1303 cxint nfibers = 0;
1304 cxint *fibers = NULL;
1305 cxint *_fibers = NULL;
1306
1307 cx_slist *fl = NULL;
1308
1309 cx_slist_iterator pos;
1310
1311
1312 *nspec = 0;
1313
1314 lists = cx_strsplit(selection, ";", 2);
1315
1316 if (lists == NULL) {
1317 return NULL;
1318 }
1319
1320 if (lists[1] != NULL) {
1321 gi_warning("Usage of fiber exclusion lists is not supported! "
1322 "The given exclusion list is ignored!");
1323 }
1324
1325 ranges = cx_strsplit(lists[0], ",", -1);
1326
1327 if (ranges == NULL) {
1328 cx_strfreev(lists);
1329 return NULL;
1330 }
1331
1332 i = 0;
1333 while (ranges[i] != NULL) {
1334
1335 cxchar **bounds = cx_strsplit(ranges[i], "-", 2);
1336
1337 cxint j;
1338
1339
1340 if (bounds == NULL) {
1341 cx_strfreev(ranges);
1342 cx_strfreev(lists);
1343
1344 if (fibers) {
1345 cx_free(fibers);
1346 }
1347
1348 return NULL;
1349 }
1350 else {
1351
1352 cxchar *last;
1353
1354 cxlong lower = -1;
1355 cxlong upper = -1;
1356
1357
1358 lower = strtol(bounds[0], &last, 10);
1359
1360 if (*last != '\0') {
1361 cx_strfreev(bounds);
1362 cx_strfreev(ranges);
1363 cx_strfreev(lists);
1364
1365 if (fibers) {
1366 cx_free(fibers);
1367 }
1368
1369 return NULL;
1370 }
1371
1372 if (bounds[1] != NULL) {
1373
1374 upper = strtol(bounds[1], &last, 10);
1375
1376 if (*last != '\0') {
1377 cx_strfreev(bounds);
1378 cx_strfreev(ranges);
1379 cx_strfreev(lists);
1380
1381 if (fibers) {
1382 cx_free(fibers);
1383 }
1384
1385 return NULL;
1386 }
1387 }
1388
1389 upper = upper > 0 ? upper : lower;
1390
1391 if (lower <= 0 || upper <= 0 || upper < lower) {
1392 cx_strfreev(bounds);
1393 cx_strfreev(ranges);
1394 cx_strfreev(lists);
1395
1396 if (fibers) {
1397 cx_free(fibers);
1398 }
1399
1400 return NULL;
1401 }
1402
1403 ++nfibers;
1404
1405 if (upper > lower) {
1406 nfibers += upper - lower;
1407 }
1408
1409 fibers = cx_realloc(fibers, nfibers * sizeof(cxint));
1410
1411 for (j = first; j < nfibers; j++) {
1412 fibers[j] = lower + j - first;
1413 }
1414
1415 first = nfibers;
1416
1417 }
1418
1419 cx_strfreev(bounds);
1420 bounds = NULL;
1421
1422 ++i;
1423
1424 }
1425
1426 cx_strfreev(ranges);
1427 cx_strfreev(lists);
1428
1429 qsort(fibers, nfibers, sizeof(cxint), _giraffe_compare_int);
1430
1431
1432 /*
1433 * Remove duplicates from the fiber list
1434 */
1435
1436 fl = cx_slist_new();
1437
1438 for (i = 0; i < nfibers; i++) {
1439 cx_slist_push_back(fl, fibers + i);
1440 }
1441
1442 cx_slist_unique(fl, _giraffe_compare_int);
1443
1444 nfibers = cx_slist_size(fl);
1445 _fibers = cx_malloc(nfibers * sizeof(cxint));
1446
1447 i = 0;
1448
1449 pos = cx_slist_begin(fl);
1450 while (pos != cx_slist_end(fl)) {
1451
1452 cxint *fn = cx_slist_get(fl, pos);
1453
1454 cx_assert(fn != NULL);
1455 _fibers[i] = *fn;
1456
1457 pos = cx_slist_next(fl, pos);
1458 ++i;
1459 }
1460 cx_slist_delete(fl);
1461 cx_free(fibers);
1462
1463 *nspec = nfibers;
1464 return _fibers;
1465
1466}
1467
1468
1480cxint *
1482 const GiTable *reference, cxint *nspec)
1483{
1484
1485 cpl_table *fibers = giraffe_fiberlist_create(filename, 0, NULL);
1486 cpl_table *_reference = giraffe_table_get(reference);
1487
1488 cxint i = 0;
1489 cxint nspectra = 0;
1490 cxint nfibers = cpl_table_get_nrow(fibers);
1491 cxint nactive = cpl_table_get_nrow(_reference);
1492 cxint *spectra = NULL;
1493
1494
1495 if (fibers == NULL) {
1496 return NULL;
1497 }
1498
1499 if (!cpl_table_has_column(fibers, "FPS") ||
1500 !cpl_table_has_column(fibers, "FPD")) {
1501 cpl_table_delete(fibers);
1502 return NULL;
1503 }
1504
1505 if (!cpl_table_has_column(_reference, "FPS")) {
1506 cpl_table_delete(fibers);
1507 return NULL;
1508 }
1509
1510 if (nactive > nfibers) {
1511 cpl_table_delete(fibers);
1512 return NULL;
1513 }
1514
1515 *nspec = 0;
1516 spectra = cx_malloc(nactive * sizeof(cxint));
1517
1518 for (i = 0; i < nactive; ++i) {
1519
1520 cxint j = 0;
1521 cxint fps = cpl_table_get_int(_reference, "FPS", i, NULL);
1522
1523 for (j = 0; j < nfibers; ++j) {
1524
1525 cxint _fps = cpl_table_get_int(fibers, "FPS", j, NULL);
1526 cxint _fpd = cpl_table_get_int(fibers, "FPD", j, NULL);
1527
1528 if (_fps == fps) {
1529 spectra[nspectra] = _fpd;
1530 ++nspectra;
1531 break;
1532 }
1533
1534 }
1535
1536 }
1537
1538 cpl_table_delete(fibers);
1539
1540 if (nspectra < nactive) {
1541 spectra = cx_realloc(spectra, nspectra * sizeof(cxint));
1542 }
1543
1544 qsort(spectra, nspectra, sizeof(cxint), _giraffe_compare_int);
1545 *nspec = nspectra;
1546
1547 return spectra;
1548
1549}
GiTable * giraffe_fiberlist_load(const cxchar *filename, cxint dataset, const cxchar *tag)
Load a fiber table from a file.
Definition: gifiberutils.c:715
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:768
cxint giraffe_fiberlist_compare(const GiTable *fibers, const GiTable *reference)
Compare two fiber lists.
Definition: gifiberutils.c:913
cxint giraffe_fiberlist_attach(cpl_frame *frame, GiTable *fibers)
Attach a fiber table to a frame.
Definition: gifiberutils.c:845
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.
Definition: gifiberutils.c:983
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:634
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:440

This file is part of the GIRAFFE Pipeline Reference Manual 2.16.12.
Documentation copyright © 2002-2006 European Southern Observatory.
Generated on Thu Feb 20 2025 19:48:51 by doxygen 1.9.6 written by Dimitri van Heesch, © 1997-2004