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 
52 inline 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 
84 cpl_table *
85 giraffe_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);
210  giraffe_table_delete(ozpoz);
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);
219  giraffe_table_delete(ozpoz);
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);
248  giraffe_table_delete(slits);
249  return NULL;
250  }
251  else {
252  cpl_msg_error(fctid, "Cannot load data set %d (fiber table) "
253  "from `%s'!", GIFIBER_EXTENSION, filename);
254  giraffe_table_delete(slits);
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 
283  giraffe_table_delete(slits);
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);
387  giraffe_table_delete(slits);
388  cpl_table_delete(fibers);
389 
390  return NULL;
391  }
392 
393  giraffe_error_pop();
394 
395  giraffe_table_delete(slits);
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 
606  giraffe_table_delete(ozpoz);
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 
714 GiTable *
715 giraffe_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 
767 cxint
768 giraffe_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 
844 cxint
845 giraffe_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 
913 cxint 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 
982 cxint
983 giraffe_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 
1124 cxint
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 }
1170 const cxchar *
1171 giraffe_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 
1207 cpl_array*
1208 giraffe_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 
1294 cxint *
1295 giraffe_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 
1480 cxint *
1481 giraffe_create_spectrum_selection(const cxchar *filename,
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 }
cxint * giraffe_create_spectrum_selection(const cxchar *filename, const GiTable *reference, cxint *nspec)
Create a spectrum selection from a reference table.
cxint * giraffe_parse_spectrum_selection(const cxchar *selection, cxint *nspec)
Parses a spectrum selection string.
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
GiTable * giraffe_fiberlist_load(const cxchar *filename, cxint dataset, const cxchar *tag)
Load a fiber table from a file.
Definition: gifiberutils.c:715
const cxchar * giraffe_fiberlist_query_index(const cpl_table *fibers)
Query a fiber list for the name of the fiber reference index column.
cpl_array * giraffe_fiberlist_get_subslits(const cpl_table *fibers)
Get the list of subslit identifiers from a fiber setup.
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
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
cpl_propertylist * giraffe_table_get_properties(const GiTable *self)
Gets the table properties.
Definition: gitable.c:489
GiTable * giraffe_table_new(void)
Creates a new, empty Giraffe table.
Definition: gitable.c:85
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
GiTable * giraffe_table_duplicate(const GiTable *src)
Duplicate a Giraffe table.
Definition: gitable.c:176
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.10.
Documentation copyright © 2002-2006 European Southern Observatory.
Generated on Thu Dec 15 2022 21:18:51 by doxygen 1.9.1 written by Dimitri van Heesch, © 1997-2004