GIRAFFE Pipeline Reference Manual

gitable.c
1 /* $Id$
2  *
3  * This file is part of the GIRAFFE Pipeline
4  * Copyright (C) 2002-2014 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 <string.h>
33 
34 #include <cxmemory.h>
35 #include <cxmessages.h>
36 #include <cxstring.h>
37 
38 #include <cpl_error.h>
39 #include <cpl_array.h>
40 
41 #include "gialias.h"
42 #include "gitable.h"
43 
44 
53 struct GiTable {
54  cpl_table *data;
55  cpl_propertylist *properties;
56 };
57 
58 /*
59  * Clear the table contents. After calling this function the Giraffe
60  * table is empty.
61  */
62 
63 inline static void
64 _giraffe_table_clear(GiTable *self)
65 {
66 
67  if (self->data) {
68  cpl_table_delete(self->data);
69  self->data = NULL;
70  }
71 
72  if (self->properties) {
73  cpl_propertylist_delete(self->properties);
74  self->properties = NULL;
75  }
76 
77  return;
78 
79 }
80 
81 
92 GiTable *
94 {
95 
96  GiTable *self = cx_calloc(1, sizeof(GiTable));
97 
98  self->data = NULL;
99  self->properties = NULL;
100 
101  return self;
102 
103 }
104 
105 
122 GiTable *
123 giraffe_table_create(cpl_table *table, cpl_propertylist *properties)
124 {
125 
126  GiTable *self = NULL;
127 
128  if (table) {
129  self = giraffe_table_new();
130 
131  self->data = cpl_table_duplicate(table);
132  if (!self->data) {
133  return NULL;
134  }
135 
136  if (properties) {
137  self->properties = cpl_propertylist_duplicate(properties);
138  if (!self->properties) {
139  giraffe_table_delete(self);
140  return NULL;
141  }
142  }
143  }
144 
145  return self;
146 
147 }
148 
149 
161 void
162 giraffe_table_delete(GiTable *self)
163 {
164 
165  if (self) {
166  _giraffe_table_clear(self);
167  cx_free(self);
168  }
169 
170  return;
171 
172 }
173 
183 GiTable *
184 giraffe_table_duplicate(const GiTable *src)
185 {
186 
187  GiTable *self = NULL;
188 
189  if (src != NULL) {
190 
191  cpl_propertylist *properties = giraffe_table_get_properties(src);
192  cpl_table *data = giraffe_table_get(src);
193 
194 
195  self = cx_calloc(1, sizeof(GiTable));
196 
197  if (properties) {
198  self->properties = cpl_propertylist_duplicate(properties);
199  }
200 
201  if (data) {
202  self->data = cpl_table_duplicate(data);
203  }
204 
205  }
206 
207  return self;
208 
209 }
210 
211 
212 
213 
214 
227 void
228 giraffe_table_clear(GiTable *self)
229 {
230 
231  if (self) {
232  _giraffe_table_clear(self);
233  }
234 
235  return;
236 
237 }
238 
239 
266 cxint
267 giraffe_table_copy_matrix(GiTable *table, const cxchar *name,
268  cpl_matrix *matrix)
269 {
270 
271  const cxchar *fctid = "giraffe_table_copy_matrix";
272 
273  cxint nrow = 0;
274  cxint ncol = 0;
275  cxint count = 0;
276 
277  cpl_array *labels = NULL;
278  cpl_table *_table = NULL;
279 
280 
281  cx_assert(table != NULL);
282 
283  if (!matrix) {
284  return 1;
285  }
286 
287  nrow = cpl_matrix_get_nrow(matrix);
288  ncol = cpl_matrix_get_ncol(matrix);
289  cx_assert(nrow > 0 && ncol > 0);
290 
291  _table = giraffe_table_get(table);
292 
293  labels = cpl_table_get_column_names(_table);
294  cx_assert(cpl_array_get_size(labels) > 0);
295 
296 
297  if (name != NULL) {
298 
299  if (cpl_table_has_column(_table, name) == 0) {
300 
301  cpl_array_delete(labels);
302  cpl_error_set(fctid, CPL_ERROR_DATA_NOT_FOUND);
303 
304  return 1;
305 
306  }
307  else {
308 
309  /*
310  * Move to the first target column. No check whether count goes
311  * out of range is needed here since it is already known that
312  * a column with name 'name' exists.
313  */
314 
315  while (strcmp(cpl_array_get_string(labels, count), name) != 0) {
316  ++count;
317  }
318 
319  }
320 
321  }
322 
323 
324  if (cpl_table_get_nrow(_table) != nrow ||
325  cpl_table_get_ncol(_table) - count < ncol) {
326 
327  cpl_array_delete(labels);
328  cpl_error_set(fctid, CPL_ERROR_INCOMPATIBLE_INPUT);
329 
330  return 1;
331 
332  }
333  else {
334 
335  cxint i;
336 
337  cxdouble *elements = cpl_matrix_get_data(matrix);
338 
339 
340  for (i = 0; i < ncol; ++i) {
341 
342  const cxchar *label = cpl_array_get_string(labels, count + i);
343 
344  cpl_type type = cpl_table_get_column_type(_table, label);
345 
346 
347  switch (type) {
348  case CPL_TYPE_INT:
349  {
350  register cxint j;
351 
352  for (j = 0; j < nrow; ++j) {
353  cpl_table_set_int(_table, label, j,
354  (cxint) elements[j * ncol + i]);
355  }
356  break;
357  }
358 
359  case CPL_TYPE_FLOAT:
360  {
361  register cxint j;
362 
363  for (j = 0; j < nrow; ++j) {
364  cpl_table_set_float(_table, label, j,
365  (cxfloat) elements[j * ncol + i]);
366  }
367  break;
368  }
369 
370  case CPL_TYPE_DOUBLE:
371  {
372  register cxint j;
373 
374  for (j = 0; j < nrow; ++j) {
375  cpl_table_set_double(_table, label, j,
376  elements[j * ncol + i]);
377  }
378  break;
379  }
380 
381  case CPL_TYPE_STRING:
382  default:
383  {
384  cpl_array_delete(labels);
385  cpl_error_set(fctid, CPL_ERROR_INVALID_TYPE);
386 
387  return 1;
388  break;
389  }
390  }
391 
392  }
393 
394  }
395 
396  cpl_array_delete(labels);
397 
398  return 0;
399 
400 }
401 
402 
415 cxint
417 {
418 
419  if (self->data) {
420  return 0;
421  }
422 
423  return self->properties == NULL ? 1 : 0;
424 
425 }
426 
427 
440 cpl_table *
441 giraffe_table_get(const GiTable *self)
442 {
443 
444  cx_assert(self != NULL);
445 
446  return self->data;
447 
448 }
449 
450 
463 cxint
464 giraffe_table_set(GiTable *self, cpl_table *table)
465 {
466 
467  cpl_table *tmp = NULL;
468 
469  tmp = giraffe_table_get(self);
470 
471  cx_assert(table != NULL);
472 
473  if (tmp != NULL) {
474  cpl_table_delete(tmp);
475  }
476 
477  self->data = cpl_table_duplicate(table);
478 
479  return 0;
480 
481 }
482 
496 cpl_propertylist *
497 giraffe_table_get_properties(const GiTable *self)
498 {
499 
500  cx_assert(self != NULL);
501 
502  return self->properties;
503 
504 }
505 
523 cxint
524 giraffe_table_set_properties(GiTable *self, cpl_propertylist *properties)
525  {
526 
527  if (self == NULL) {
528  return 1;
529  }
530 
531  if (self->properties) {
532  cpl_propertylist_delete(self->properties);
533  self->properties = NULL;
534  }
535 
536  self->properties = cpl_propertylist_duplicate(properties);
537 
538  return self->properties ? 0 : 1;
539 
540 }
541 
569 cxint
570 giraffe_table_load(GiTable *self, const cxchar *filename, cxint position,
571  const cxchar *id)
572 {
573 
574  const cxchar *fctid = "giraffe_table_load";
575 
576 
577  if (!self || !filename) {
578  return 1;
579  }
580 
581  self->data = cpl_table_load((cxchar *)filename, position, 0);
582  if (!self->data) {
583  if (cpl_error_get_code() == CPL_ERROR_NULL_INPUT) {
584  cpl_error_set(fctid, CPL_ERROR_DATA_NOT_FOUND);
585  return 2;
586  }
587 
588  return 1;
589  }
590 
591  self->properties = cpl_propertylist_load(filename, position);
592 
593  if (self->properties == NULL) {
594  _giraffe_table_clear(self);
595  return 1;
596  }
597 
598  if (id) {
599  cxint status = 1;
600 
601  if (self->properties &&
602  cpl_propertylist_has(self->properties, GIALIAS_EXTNAME)) {
603 
604  const cxchar *magic;
605 
606  magic = cpl_propertylist_get_string(self->properties,
607  GIALIAS_EXTNAME);
608 
609  if (strcmp(id, magic) == 0) {
610  status = 0;
611  }
612 
613  }
614 
615  if (status != 0) {
616  _giraffe_table_clear(self);
617  cpl_error_set(fctid, CPL_ERROR_BAD_FILE_FORMAT);
618  return 1;
619  }
620 
621  }
622 
623  return 0;
624 
625 }
626 
627 
643 cxint
644 giraffe_table_save(GiTable *self, const cxchar *filename)
645 {
646 
647  if (filename == NULL) {
648  return 1;
649  }
650 
651  if (self) {
652 
653  cxint code;
654 
655  cpl_table *table = giraffe_table_get(self);
656  cpl_propertylist *plist0 = giraffe_table_get_properties(self);
657  cpl_propertylist *plist1 = NULL;
658 
659 
660  if (cpl_propertylist_is_empty(plist0)) {
661  plist0 = NULL;
662  }
663 
664  plist0 = cpl_propertylist_duplicate(plist0);
665 
666 
667  /*
668  * Remove keywords which may not appear in table headers.
669  */
670 
671  cpl_propertylist_erase(plist0, "BSCALE");
672  cpl_propertylist_erase(plist0, "BZERO");
673  cpl_propertylist_erase(plist0, "BUNIT");
674 
675  cpl_propertylist_erase(plist0, "DATAMIN");
676  cpl_propertylist_erase(plist0, "DATAMAX");
677 
678 
679  /* FIXME: Workaround for CPL deficiency. World coordinate
680  * keywords are not removed from table headers.
681  */
682 
683  cpl_propertylist_erase_regexp(plist0, "^CRPIX[0-9]$", 0);
684  cpl_propertylist_erase_regexp(plist0, "^CRVAL[0-9]$", 0);
685  cpl_propertylist_erase_regexp(plist0, "^CDELT[0-9]$", 0);
686  cpl_propertylist_erase_regexp(plist0, "^CTYPE[0-9]$", 0);
687 
688 
689  /*
690  * Split properties into separate property lists for the primary
691  * and the secondary header
692  */
693 
694  plist1 = cpl_propertylist_duplicate(plist0);
695 
696 
697  /*
698  * Remove header specific keywords from the respective
699  * property list.
700  */
701 
702  cpl_propertylist_erase(plist0, "EXTNAME");
703 
704  cpl_propertylist_erase(plist1, "DATAMD5");
705  cpl_propertylist_erase(plist1, "INHERIT");
706  cpl_propertylist_erase(plist1, "PIPEFILE");
707  cpl_propertylist_erase(plist1, GIALIAS_ANCESTOR);
708 
709 
710  /*
711  * Save the table to disk
712  */
713 
714  code = cpl_table_save(table, plist0, plist1, filename, CPL_IO_CREATE);
715 
716  if (code != CPL_ERROR_NONE) {
717  cpl_propertylist_delete(plist0);
718  plist0 = NULL;
719 
720  cpl_propertylist_delete(plist1);
721  plist1 = NULL;
722 
723  return 1;
724  }
725 
726  cpl_propertylist_delete(plist0);
727  plist0 = NULL;
728 
729  cpl_propertylist_delete(plist1);
730  plist1 = NULL;
731 
732  }
733 
734  return 0;
735 
736 }
737 
738 
756 cxint
757 giraffe_table_attach(GiTable *self, const cxchar *filename, cxint position,
758  const cxchar *id)
759 {
760 
761  cxint code;
762 
763  cpl_table *table = NULL;
764  cpl_propertylist *plist = NULL;
765 
766 
767  cx_assert(self != NULL);
768 
769  if (filename == NULL) {
770  return 1;
771  }
772 
773  if (position < 1) {
774  return 1;
775  }
776 
777  table = giraffe_table_get(self);
778  plist = giraffe_table_get_properties(self);
779 
780  plist = cpl_propertylist_duplicate(plist);
781 
782 
783  /*
784  * Remove keywords which may not appear in table headers.
785  */
786 
787  cpl_propertylist_erase(plist, "BSCALE");
788  cpl_propertylist_erase(plist, "BZERO");
789  cpl_propertylist_erase(plist, "BUNIT");
790 
791  cpl_propertylist_erase(plist, "DATAMIN");
792  cpl_propertylist_erase(plist, "DATAMAX");
793  cpl_propertylist_erase(plist, "DATAMD5");
794  cpl_propertylist_erase(plist, "INHERIT");
795  cpl_propertylist_erase(plist, "PIPEFILE");
796  cpl_propertylist_erase(plist, GIALIAS_ANCESTOR);
797 
798  /* FIXME: Workaround for CPL deficiency. World coordinate
799  * keywords are not removed from table headers.
800  */
801 
802  cpl_propertylist_erase_regexp(plist, "^CRPIX[0-9]$", 0);
803  cpl_propertylist_erase_regexp(plist, "^CRVAL[0-9]$", 0);
804  cpl_propertylist_erase_regexp(plist, "^CDELT[0-9]$", 0);
805  cpl_propertylist_erase_regexp(plist, "^CTYPE[0-9]$", 0);
806 
807 
808  if (id != NULL) {
809  cpl_propertylist_update_string(plist, GIALIAS_EXTNAME, id);
810  cpl_propertylist_set_comment(plist, GIALIAS_EXTNAME,
811  "FITS Extension name");
812  }
813  else {
814  if (cpl_propertylist_is_empty(plist)) {
815  plist = NULL;
816  }
817  }
818 
819  code = cpl_table_save(table, NULL, plist, filename, CPL_IO_EXTEND);
820 
821  if (code != CPL_ERROR_NONE) {
822  cpl_propertylist_delete(plist);
823  plist = NULL;
824 
825  return 1;
826  }
827 
828  cpl_propertylist_delete(plist);
829  plist = NULL;
830 
831  return 0;
832 
833 }
834 
835 
843 cxint
844 giraffe_table_add_info(GiTable *table, const GiRecipeInfo *info ,
845  const cpl_frameset *set)
846 {
847 
848  cxint status = 0;
849 
850  cpl_propertylist *properties = NULL;
851 
852 
853  if (table == NULL) {
854  return -1;
855  }
856 
857  properties = giraffe_table_get_properties(table);
858 
859  if (properties == NULL) {
860  return -2;
861  }
862 
863  if (info != NULL) {
864  status = giraffe_add_recipe_info(properties, info);
865 
866  if (status != 0) {
867  return -3;
868  }
869 
870  if (set != NULL) {
871  status = giraffe_add_frameset_info(properties, set,
872  info->sequence);
873 
874 
875  if (status != 0) {
876  return -4;
877  }
878  }
879  }
880 
881  return 0;
882 
883 }
cxint giraffe_table_add_info(GiTable *table, const GiRecipeInfo *info, const cpl_frameset *set)
Add additional frame information to a table.
Definition: gitable.c:844
cxint giraffe_table_is_empty(GiTable *self)
Check whether a Giraffe table is empty.
Definition: gitable.c:416
cxint giraffe_add_frameset_info(cpl_propertylist *plist, const cpl_frameset *set, cxint sequence)
Add frameset specific information to a property list.
Definition: giutils.c:587
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
void giraffe_table_delete(GiTable *self)
Destroys a Giraffe table.
Definition: gitable.c:162
cxint giraffe_table_attach(GiTable *self, const cxchar *filename, cxint position, const cxchar *id)
Attach a Giraffe table to a file.
Definition: gitable.c:757
GiTable * giraffe_table_new(void)
Creates a new, empty Giraffe table.
Definition: gitable.c:93
void giraffe_table_clear(GiTable *self)
Clears a Giraffe table.
Definition: gitable.c:228
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
GiTable * giraffe_table_duplicate(const GiTable *src)
Duplicate a Giraffe table.
Definition: gitable.c:184
cxint giraffe_table_save(GiTable *self, const cxchar *filename)
Write a Giraffe table to a file.
Definition: gitable.c:644
cxint giraffe_table_copy_matrix(GiTable *table, const cxchar *name, cpl_matrix *matrix)
Copies matrix elements into a table.
Definition: gitable.c:267
cxint giraffe_add_recipe_info(cpl_propertylist *plist, const GiRecipeInfo *info)
Add recipe specific information to a property list.
Definition: giutils.c:489
cpl_propertylist * giraffe_table_get_properties(const GiTable *self)
Gets the table properties.
Definition: gitable.c:497
GiTable * giraffe_table_create(cpl_table *table, cpl_propertylist *properties)
Creates a Giraffe table from a table and a property list.
Definition: gitable.c:123

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:42 by doxygen 1.8.9.1 written by Dimitri van Heesch, © 1997-2004