GIRAFFE Pipeline Reference Manual

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

This file is part of the GIRAFFE Pipeline Reference Manual 2.14.
Documentation copyright © 2002-2006 European Southern Observatory.
Generated on Wed Mar 11 2015 13:19:41 by doxygen 1.8.9.1 written by Dimitri van Heesch, © 1997-2004