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

This file is part of the GIRAFFE Pipeline Reference Manual 2.12.
Documentation copyright © 2002-2006 European Southern Observatory.
Generated on Mon Mar 24 2014 11:43:52 by doxygen 1.8.2 written by Dimitri van Heesch, © 1997-2004