GIRAFFE Pipeline Reference Manual

gicube.c
1 /* $Id$
2  *
3  * This file is part of the GIRAFFE Pipeline
4  * Copyright (C) 2002-2007 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 #include <math.h>
34 
35 #include <cxmemory.h>
36 #include <cxmessages.h>
37 #include <cxstrutils.h>
38 
39 #include <cpl_error.h>
40 #include <cpl_array.h>
41 #include <cpl_matrix.h>
42 #include <cpl_image.h>
43 #include <cpl_imagelist.h>
44 #include <cpl_propertylist.h>
45 
46 #include "gialias.h"
47 #include "gierror.h"
48 #include "gicube.h"
49 #include "giutils.h"
50 
51 
60 enum GiCubeAxes {
61  GICUBE_X = 0,
62  GICUBE_Y = 1,
63  GICUBE_Z = 2,
64  GICUBE_AXES
65 };
66 
67 typedef enum GiCubeAxes GiCubeAxes;
68 
69 
70 struct GiCubeAxis {
71  cxdouble start;
72  cxdouble step;
73 };
74 
75 typedef struct GiCubeAxis GiCubeAxis;
76 
77 
78 struct GiCubeWCS {
79  cxdouble origin[GICUBE_AXES];
80  cxdouble point[GICUBE_AXES];
81 
82  cxchar* axis_type[GICUBE_AXES];
83  cxchar* axis_unit[GICUBE_AXES];
84 
85  cpl_matrix* transform;
86 };
87 
88 typedef struct GiCubeWCS GiCubeWCS;
89 
90 
91 struct GiCube {
92  cxsize width;
93  cxsize height;
94  cxsize depth;
95  cxsize size;
96 
97  GiCubeAxis* axes[GICUBE_AXES];
98 
99  GiCubeWCS* wcs;
100 
101  cxdouble* pixels;
102 
103  cpl_imagelist* planes;
104 };
105 
106 
107 
108 inline static void
109 _giraffe_cube_clear_wcs(GiCube* self)
110 {
111 
112  register cxsize axis = 0;
113 
114  for (axis = 0; axis < GICUBE_AXES; ++axis) {
115 
116  if (self->wcs->axis_type[axis] != NULL) {
117  cx_free(self->wcs->axis_type[axis]);
118  self->wcs->axis_type[axis] = NULL;
119  }
120 
121  if (self->wcs->axis_unit[axis] != NULL) {
122  cx_free(self->wcs->axis_unit[axis]);
123  self->wcs->axis_unit[axis] = NULL;
124  }
125 
126  }
127 
128  cpl_matrix_delete(self->wcs->transform);
129  self->wcs->transform = NULL;
130 
131  cx_free(self->wcs);
132  self->wcs = NULL;
133 
134  return;
135 
136 }
137 
138 
139 inline static void
140 _giraffe_cube_set_wcs(GiCube* self, const cpl_propertylist* axes,
141  const cpl_matrix* transform)
142 {
143 
144  GiCubeWCS* wcs = NULL;
145 
146  cx_assert(self != NULL);
147  cx_assert(axes != NULL);
148  cx_assert(transform != NULL);
149 
150  wcs = cx_malloc(sizeof *self->wcs);
151 
152  wcs->transform = cpl_matrix_duplicate(transform);
153 
154  wcs->origin[GICUBE_X] = cpl_propertylist_get_double(axes, "XORIGIN");
155  wcs->origin[GICUBE_Y] = cpl_propertylist_get_double(axes, "YORIGIN");
156  wcs->origin[GICUBE_Z] = cpl_propertylist_get_double(axes, "ZORIGIN");
157 
158  wcs->point[GICUBE_X] = cpl_propertylist_get_double(axes, "XPOINT");
159  wcs->point[GICUBE_Y] = cpl_propertylist_get_double(axes, "YPOINT");
160  wcs->point[GICUBE_Z] = cpl_propertylist_get_double(axes, "ZPOINT");
161 
162  wcs->axis_type[GICUBE_X] =
163  cx_strdup(cpl_propertylist_get_string(axes, "XTYPE"));
164  wcs->axis_type[GICUBE_Y] =
165  cx_strdup(cpl_propertylist_get_string(axes, "YTYPE"));
166  wcs->axis_type[GICUBE_Z] =
167  cx_strdup(cpl_propertylist_get_string(axes, "ZTYPE"));
168 
169  wcs->axis_unit[GICUBE_X] =
170  cx_strdup(cpl_propertylist_get_string(axes, "XUNIT"));
171  wcs->axis_unit[GICUBE_Y] =
172  cx_strdup(cpl_propertylist_get_string(axes, "YUNIT"));
173  wcs->axis_unit[GICUBE_Z] =
174  cx_strdup(cpl_propertylist_get_string(axes, "ZUNIT"));
175 
176 
177  if (self->wcs != NULL) {
178  _giraffe_cube_clear_wcs(self);
179  }
180 
181  self->wcs = wcs;
182 
183  return;
184 
185 }
186 
187 
188 inline static cxdouble
189 _giraffe_cube_get_wcs_origin(const GiCube* self, GiCubeAxes axis)
190 {
191  return self->wcs->origin[axis];
192 }
193 
194 
195 inline static cxdouble
196 _giraffe_cube_get_wcs_point(const GiCube* self, GiCubeAxes axis)
197 {
198  return self->wcs->point[axis];
199 }
200 
201 
202 inline static const cxchar*
203 _giraffe_cube_get_wcs_axistype(const GiCube* self, GiCubeAxes axis)
204 {
205  return self->wcs->axis_type[axis];
206 }
207 
208 
209 inline static const cxchar*
210 _giraffe_cube_get_wcs_axisunit(const GiCube* self, GiCubeAxes axis)
211 {
212  return self->wcs->axis_unit[axis];
213 }
214 
215 
216 inline static const cpl_matrix*
217 _giraffe_cube_get_wcs_transform(const GiCube* self)
218 {
219  return self->wcs->transform;
220 }
221 
222 
223 inline static void
224 _giraffe_cube_set_size(GiCube* self, cxsize width, cxsize height,
225  cxsize depth)
226 {
227 
228  self->width = width;
229  self->height = height;
230  self->depth = depth;
231 
232  self->size = self->width * self->height * self->depth;
233 
234  return;
235 
236 }
237 
238 
239 inline static GiCube*
240 _giraffe_cube_new(void)
241 {
242 
243  GiCube* self = cx_malloc(sizeof *self);
244 
245 
246  if (self != NULL) {
247  _giraffe_cube_set_size(self, 0, 0, 0);
248 
249  self->axes[GICUBE_X] = NULL;
250  self->axes[GICUBE_Y] = NULL;
251  self->axes[GICUBE_Z] = NULL;
252 
253  self->wcs = NULL;
254 
255  self->pixels = NULL;
256  self->planes = NULL;
257  }
258 
259  return self;
260 
261 }
262 
263 
264 inline static cxint
265 _giraffe_cube_init_planes(GiCube* self)
266 {
267 
268  register cxsize i = 0;
269 
270  register cxdouble* base = NULL;
271 
272 
273  self->planes = cpl_imagelist_new();
274  cx_assert(self->planes != NULL);
275 
276 
277  base = self->pixels;
278 
279  for (i = 0; i < self->depth; i++) {
280 
281  cpl_image* plane = cpl_image_wrap_double(self->width, self->height,
282  base);
283 
284  cx_assert(plane != NULL);
285  cpl_imagelist_set(self->planes, plane, i);
286 
287  base += self->width * self->height;
288 
289  }
290 
291  return 0;
292 
293 }
294 
295 
296 inline static void
297 _giraffe_cube_clear_planes(GiCube* self)
298 {
299 
300  register cxsize i = 0;
301 
302 
303  for (i = 0; i < self->depth; i++) {
304 
305  cpl_image* plane = cpl_imagelist_unset(self->planes, 0);
306 
307  cpl_image_unwrap(plane);
308 
309  }
310 
311  cx_assert(cpl_imagelist_get_size(self->planes) == 0);
312 
313  cpl_imagelist_delete(self->planes);
314  self->planes =NULL;
315 
316  return;
317 
318 }
319 
320 
321 inline static void
322 _giraffe_cube_delete(GiCube* self)
323 {
324 
325  register cxint i = 0;
326 
327  for (i = 0; i < GICUBE_AXES; i++) {
328  if (self->axes[i] != NULL) {
329  cx_free(self->axes[i]);
330  self->axes[i] = NULL;
331  }
332  }
333 
334  if (self->wcs != NULL) {
335  _giraffe_cube_clear_wcs(self);
336  self->wcs = NULL;
337  }
338 
339  if (self->planes != NULL) {
340  _giraffe_cube_clear_planes(self);
341  self->planes = NULL;
342  }
343 
344  if (self->pixels != NULL) {
345  cx_free(self->pixels);
346  self->pixels = NULL;
347  }
348 
349  cx_free(self);
350 
351  return;
352 
353 }
354 
355 
356 inline static cxbool
357 _giraffe_cube_has_axis(const GiCube* self, GiCubeAxes axis)
358 {
359  return (self->axes[axis] == NULL) ? FALSE : TRUE;
360 }
361 
362 
363 inline static cxint
364 _giraffe_cube_get_axis(const GiCube* self, GiCubeAxes axis, cxdouble* start,
365  cxdouble* step)
366 {
367 
368  if (self->axes[axis] == NULL) {
369  return 1;
370  }
371  else {
372 
373  if (start != NULL) {
374  *start = self->axes[axis]->start;
375  }
376 
377  if (step != NULL) {
378  *step = self->axes[axis]->step;
379  }
380 
381  }
382 
383  return 0;
384 
385 }
386 
387 
388 inline static cxint
389 _giraffe_cube_set_axis(GiCube* self, GiCubeAxes axis, cxdouble start,
390  cxdouble step)
391 {
392 
393  if (self->axes[axis] == NULL) {
394  self->axes[axis] = cx_calloc(1, sizeof(GiCubeAxis));
395  }
396 
397  cx_assert(self->axes[axis] != NULL);
398 
399  self->axes[axis]->start = start;
400  self->axes[axis]->step = step;
401 
402  return 0;
403 
404 }
405 
406 
419 GiCube*
421 {
422 
423  return _giraffe_cube_new();
424 
425 }
426 
427 
454 GiCube*
455 giraffe_cube_create(cxsize width, cxsize height, cxsize depth, cxdouble* data)
456 {
457 
458  GiCube* self = _giraffe_cube_new();
459 
460 
461  _giraffe_cube_set_size(self, width, height, depth);
462 
463  if (self->size == 0) {
464  _giraffe_cube_delete(self);
465  return NULL;
466  }
467 
468  if (data != NULL) {
469  self->pixels = data;
470  }
471  else {
472  self->pixels = cx_calloc(self->size, sizeof(cxdouble));
473  }
474 
475  cx_assert(self->pixels != NULL);
476 
477 
478  /*
479  * Create the image list object for accessing the cube plane by plane.
480  * It is also needed (for the time being) to save a cube to disk.
481  */
482 
483  giraffe_error_push();
484 
485  _giraffe_cube_init_planes(self);
486 
487  if (cpl_error_get_code() != CPL_ERROR_NONE) {
488  _giraffe_cube_delete(self);
489  return NULL;
490  }
491 
492  giraffe_error_pop();
493 
494  return self;
495 
496 }
497 
498 
511 void
512 giraffe_cube_delete(GiCube* self)
513 {
514 
515  if (self != NULL) {
516  _giraffe_cube_delete(self);
517  }
518 
519  return;
520 
521 }
522 
523 
537 cxsize
538 giraffe_cube_get_width(const GiCube* self)
539 {
540 
541  cx_assert(self != NULL);
542  return self->width;
543 
544 }
545 
546 
560 cxsize
561 giraffe_cube_get_height(const GiCube* self)
562 {
563 
564  cx_assert(self != NULL);
565  return self->height;
566 
567 }
568 
569 
583 cxsize
584 giraffe_cube_get_depth(const GiCube* self)
585 {
586 
587  cx_assert(self != NULL);
588  return self->depth;
589 
590 }
591 
592 
606 cxsize
607 giraffe_cube_get_size(const GiCube* self)
608 {
609 
610  cx_assert(self != NULL);
611  return self->size;
612 
613 }
614 
615 
634 cxint
635 giraffe_cube_set_size(GiCube* self, cxsize width, cxsize height, cxsize depth)
636 {
637 
638  const cxchar* const _id = "giraffe_cube_set_size";
639 
640 
641  cx_assert(self != NULL);
642 
643  if ((width == 0) || (height == 0) || (depth == 0)) {
644  cpl_error_set(_id, CPL_ERROR_ILLEGAL_INPUT);
645  return 1;
646  }
647 
648  if ((self->width == width) && (self->height == height) &&
649  (self->depth == depth)) {
650  memset(self->pixels, 0, self->size * sizeof(cxdouble));
651  }
652  else {
653 
654  /*
655  * Clear the list of planes and destroy the old pixel buffer
656  */
657 
658  if (self->planes != NULL) {
659  _giraffe_cube_clear_planes(self);
660  }
661 
662  if (self->pixels != NULL) {
663  cx_free(self->pixels);
664  }
665 
666 
667  /*
668  * Set the new sizes
669  */
670 
671  _giraffe_cube_set_size(self, width, height, depth);
672 
673 
674  /*
675  * Re-create the pixel buffer and the list of planes from the updated
676  * size specifications.
677  */
678 
679  self->pixels = cx_calloc(self->size, sizeof(cxdouble));
680  cx_assert(self->pixels);
681 
682 
683  giraffe_error_push();
684 
685  _giraffe_cube_init_planes(self);
686 
687  if (cpl_error_get_code() != CPL_ERROR_NONE) {
688  return 1;
689  }
690 
691  giraffe_error_pop();
692 
693  }
694 
695  return 0;
696 
697 }
698 
699 
714 cxdouble*
715 giraffe_cube_get_data(const GiCube* self)
716 {
717 
718  const cxchar* const _id = "giraffe_cube_get_data";
719 
720 
721  if (self == NULL) {
722  cpl_error_set(_id, CPL_ERROR_NULL_INPUT);
723  return 0;
724  }
725 
726  return self->pixels;
727 
728 }
729 
730 
745 cxbool
746 giraffe_cube_has_xaxis(const GiCube* self)
747 {
748  return _giraffe_cube_has_axis(self, GICUBE_X);
749 }
750 
751 
766 cxbool
767 giraffe_cube_has_yaxis(const GiCube* self)
768 {
769  return _giraffe_cube_has_axis(self, GICUBE_Y);
770 }
771 
772 
787 cxbool
788 giraffe_cube_has_zaxis(const GiCube* self)
789 {
790  return _giraffe_cube_has_axis(self, GICUBE_Z);
791 }
792 
793 
808 cxbool
809 giraffe_cube_has_wcs(const GiCube* self)
810 {
811  return self->wcs != NULL;
812 }
813 
814 
835 cxint
836 giraffe_cube_get_xaxis(const GiCube* self, cxdouble* start, cxdouble* step)
837 {
838 
839  cx_assert(self != NULL);
840 
841  return _giraffe_cube_get_axis(self, GICUBE_X, start, step);
842 
843 }
844 
845 
866 cxint
867 giraffe_cube_get_yaxis(const GiCube* self, cxdouble* start, cxdouble* step)
868 {
869 
870  cx_assert(self != NULL);
871 
872  return _giraffe_cube_get_axis(self, GICUBE_Y, start, step);
873 
874 }
875 
876 
897 cxint
898 giraffe_cube_get_zaxis(const GiCube* self, cxdouble* start, cxdouble* step)
899 {
900 
901  cx_assert(self != NULL);
902 
903  return _giraffe_cube_get_axis(self, GICUBE_Z, start, step);
904 
905 }
906 
907 
923 cxint
924 giraffe_cube_set_xaxis(GiCube* self, cxdouble start, cxdouble step)
925 {
926 
927  cx_assert(self != NULL);
928 
929  return _giraffe_cube_set_axis(self, GICUBE_X, start, step);
930 
931 }
932 
933 
949 cxint
950 giraffe_cube_set_yaxis(GiCube* self, cxdouble start, cxdouble step)
951 {
952 
953  cx_assert(self != NULL);
954 
955  return _giraffe_cube_set_axis(self, GICUBE_Y, start, step);
956 
957 }
958 
959 
975 cxint
976 giraffe_cube_set_zaxis(GiCube* self, cxdouble start, cxdouble step)
977 {
978 
979  cx_assert(self != NULL);
980 
981  return _giraffe_cube_set_axis(self, GICUBE_Z, start, step);
982 
983 }
984 
985 
1000 void
1002 {
1003 
1004  if (self->wcs != NULL) {
1005  _giraffe_cube_clear_wcs(self);
1006  }
1007 
1008  return;
1009 
1010 }
1011 
1012 
1039 cxint
1040 giraffe_cube_set_wcs(GiCube* self, const cpl_propertylist* axes,
1041  const cpl_matrix* transformation)
1042 {
1043 
1044  cx_assert(self != NULL);
1045 
1046  if ((axes == NULL) || (transformation == NULL)) {
1047  return -1;
1048  }
1049 
1050  if ((cpl_matrix_get_nrow(transformation) != GICUBE_AXES) ||
1051  (cpl_matrix_get_ncol(transformation) != GICUBE_AXES)) {
1052  return 3;
1053  }
1054 
1055  if ((cpl_propertylist_has(axes, "XORIGIN") == FALSE) ||
1056  (cpl_propertylist_has(axes, "YORIGIN") == FALSE) ||
1057  (cpl_propertylist_has(axes, "ZORIGIN") == FALSE)) {
1058  return 2;
1059  }
1060 
1061  if ((cpl_propertylist_has(axes, "XPOINT") == FALSE) ||
1062  (cpl_propertylist_has(axes, "YPOINT") == FALSE) ||
1063  (cpl_propertylist_has(axes, "ZPOINT") == FALSE)) {
1064  return 2;
1065  }
1066 
1067  if ((cpl_propertylist_has(axes, "XTYPE") == FALSE) ||
1068  (cpl_propertylist_has(axes, "YTYPE") == FALSE) ||
1069  (cpl_propertylist_has(axes, "ZTYPE") == FALSE)) {
1070  return 2;
1071  }
1072 
1073  if ((cpl_propertylist_has(axes, "XUNIT") == FALSE) ||
1074  (cpl_propertylist_has(axes, "YUNIT") == FALSE) ||
1075  (cpl_propertylist_has(axes, "ZUNIT") == FALSE)) {
1076  return 2;
1077  }
1078 
1079  _giraffe_cube_set_wcs(self, axes, transformation);
1080 
1081  return 1;
1082 }
1083 
1084 
1098 cxint
1099 giraffe_cube_sqrt(GiCube* self)
1100 {
1101 
1102  cpl_error_code status = CPL_ERROR_NONE;
1103 
1104 
1105  if (self == NULL) {
1106  return -1;
1107  }
1108 
1109  cx_assert(self->planes != NULL);
1110 
1111  status = cpl_imagelist_power(self->planes, 0.5);
1112 
1113  if (status != CPL_ERROR_NONE) {
1114  return 1;
1115  }
1116 
1117  return 0;
1118 
1119 }
1120 
1121 
1149 cpl_image*
1150 giraffe_cube_integrate(const GiCube* self, cxdouble start, cxdouble end)
1151 {
1152 
1153  cxsize depth = 0;
1154  cxsize first = (cxsize)ceil(start);
1155  cxsize last = (cxsize)floor(end);
1156 
1157  cpl_image* image = NULL;
1158 
1159 
1160  if (self == NULL) {
1161  return NULL;
1162  }
1163 
1164  depth = giraffe_cube_get_depth(self);
1165 
1166  if ((start >= end) || (start < 0.) || (end > depth)) {
1167  return NULL;
1168  }
1169 
1170 
1171  image = cpl_image_duplicate(cpl_imagelist_get(self->planes, first));
1172 
1173  if (image != NULL) {
1174 
1175  if (first == last) {
1176  cpl_image_multiply_scalar(image, (end - start));
1177  }
1178  else {
1179 
1180  cxsize i = 0;
1181 
1182  cxdouble fstart = first - start;
1183  cxdouble fend = end - last;
1184 
1185 
1186  for (i = first + 1; i < last; ++i) {
1187  cpl_image_add(image,
1188  cpl_imagelist_get_const(self->planes, i));
1189  }
1190 
1191 
1192  /*
1193  * Correct for the pixel fractions at both ends of the
1194  * integration domain.
1195  */
1196 
1197  if ((fstart > 0.) && (first > 0)) {
1198  cpl_image* tmp = cpl_imagelist_get(self->planes, first - 1);
1199 
1200  tmp = cpl_image_multiply_scalar_create(tmp, fstart);
1201  cpl_image_add(image, tmp);
1202 
1203  cpl_image_delete(tmp);
1204  tmp = NULL;
1205  }
1206 
1207  if ((fend > 0.) && (last < depth)) {
1208  cpl_image* tmp = cpl_imagelist_get(self->planes, last);
1209 
1210  tmp = cpl_image_multiply_scalar_create(tmp, fend);
1211  cpl_image_add(image, tmp);
1212 
1213  cpl_image_delete(tmp);
1214  tmp = NULL;
1215  }
1216 
1217  }
1218 
1219  }
1220 
1221  return image;
1222 
1223 }
1224 
1225 
1243 cxint
1244 giraffe_cube_save(const GiCube* self, cpl_propertylist* properties,
1245  const cxchar* filename, cxcptr data)
1246 {
1247 
1248  cxbool xaxis = FALSE;
1249  cxbool yaxis = FALSE;
1250  cxbool zaxis = FALSE;
1251 
1252  cxdouble xstart = 0.;
1253  cxdouble xstep = 0.;
1254  cxdouble ystart = 0.;
1255  cxdouble ystep = 0.;
1256  cxdouble zstart = 0.;
1257  cxdouble zstep = 0.;
1258 
1259  cxuint iomode = CPL_IO_CREATE;
1260 
1261 
1262  if (properties == NULL || filename == NULL) {
1263  return -1;
1264  }
1265 
1266 
1267  /*
1268  * If present use the cube writer configuration
1269  */
1270 
1271  if (data != NULL) {
1272  iomode = *((cxuint*)data);
1273  }
1274 
1275 
1276  if (self == NULL) {
1277 
1278  /*
1279  * If no cube has been provided, but properties and a filename
1280  * were given an empty cube is written to the file. Currently
1281  * this is restricted to creating a new cube file, to avoid
1282  * turning the property list into a valid extension header.
1283  */
1284 
1285  if (iomode != CPL_IO_CREATE) {
1286  return -2;
1287  }
1288 
1289  giraffe_error_push();
1290 
1291  cpl_propertylist_erase_regexp(properties, "CRVAL[0-9]*", 0);
1292  cpl_propertylist_erase_regexp(properties, "CRPIX[0-9]*", 0);
1293  cpl_propertylist_erase_regexp(properties, "CDELT[0-9]*", 0);
1294  cpl_propertylist_erase_regexp(properties, "CTYPE[0-9]*", 0);
1295  cpl_propertylist_erase_regexp(properties, "CUNIT[0-9]*", 0);
1296 
1297  cpl_propertylist_erase(properties, GIALIAS_BUNIT);
1298 
1299  cpl_propertylist_erase(properties, "DATAMIN");
1300  cpl_propertylist_erase(properties, "DATAMAX");
1301 
1302  cpl_propertylist_erase(properties, GIALIAS_DATAMEAN);
1303  cpl_propertylist_erase(properties, GIALIAS_DATAMEDI);
1304  cpl_propertylist_erase(properties, GIALIAS_DATASIG);
1305 
1306  cpl_propertylist_save(properties, filename, iomode);
1307 
1308  if (cpl_error_get_code() != CPL_ERROR_NONE) {
1309  return 1;
1310  }
1311 
1312  giraffe_error_pop();
1313 
1314  }
1315  else {
1316 
1317  cxsize size = 0;
1318 
1319  const cpl_array* pixels = NULL;
1320 
1321 
1322  /*
1323  * Update the data cube's properties. The world coordinates are only
1324  * written if a world coordinate system has been previously defined.
1325  * If a full world coordinate system is not present, the world
1326  * coordinates as defined by the cube's axes are used provided that
1327  * the information is present for all three axes. If this information
1328  * is missing too, no world coordinates are written.
1329  */
1330 
1331  if (giraffe_cube_get_xaxis(self, &xstart, &xstep) == 0) {
1332  xaxis = TRUE;
1333  }
1334 
1335  if (giraffe_cube_get_yaxis(self, &ystart, &ystep) == 0) {
1336  yaxis = TRUE;
1337  }
1338 
1339  if (giraffe_cube_get_zaxis(self, &zstart, &zstep) == 0) {
1340  zaxis = TRUE;
1341  }
1342 
1343 
1344  if (giraffe_cube_has_wcs(self) == TRUE) {
1345 
1346  const cxchar* ctype[GICUBE_AXES];
1347  const cxchar* cunit[GICUBE_AXES];
1348 
1349  cxint status = 0;
1350 
1351  cxdouble crpix[GICUBE_AXES];
1352  cxdouble crval[GICUBE_AXES];
1353 
1354  const cpl_matrix* cd = _giraffe_cube_get_wcs_transform(self);
1355 
1356 
1357  crpix[GICUBE_X] = _giraffe_cube_get_wcs_origin(self, GICUBE_X);
1358  crpix[GICUBE_Y] = _giraffe_cube_get_wcs_origin(self, GICUBE_Y);
1359  crpix[GICUBE_Z] = _giraffe_cube_get_wcs_origin(self, GICUBE_Z);
1360 
1361  crval[GICUBE_X] = _giraffe_cube_get_wcs_point(self, GICUBE_X);
1362  crval[GICUBE_Y] = _giraffe_cube_get_wcs_point(self, GICUBE_Y);
1363  crval[GICUBE_Z] = _giraffe_cube_get_wcs_point(self, GICUBE_Z);
1364 
1365  ctype[GICUBE_X] = _giraffe_cube_get_wcs_axistype(self, GICUBE_X);
1366  ctype[GICUBE_Y] = _giraffe_cube_get_wcs_axistype(self, GICUBE_Y);
1367  ctype[GICUBE_Z] = _giraffe_cube_get_wcs_axistype(self, GICUBE_Z);
1368 
1369  cunit[GICUBE_X] = _giraffe_cube_get_wcs_axisunit(self, GICUBE_X);
1370  cunit[GICUBE_Y] = _giraffe_cube_get_wcs_axisunit(self, GICUBE_Y);
1371  cunit[GICUBE_Z] = _giraffe_cube_get_wcs_axisunit(self, GICUBE_Z);
1372 
1373  status = giraffe_propertylist_update_wcs(properties, GICUBE_AXES,
1374  crpix, crval, ctype, cunit,
1375  cd);
1376 
1377  if (status != 0) {
1378  giraffe_propertylist_update_wcs(properties, 0, NULL, NULL, NULL,
1379  NULL, NULL);
1380  }
1381 
1382  }
1383  else if ((xaxis == TRUE) && (yaxis == TRUE) && (zaxis == TRUE)) {
1384 
1385  const cxchar* ctype[] = {"PIXEL", "PIXEL", "AWAV"};
1386  const cxchar* cunit[] = {"bin", "bin", "nm"};
1387 
1388  cxint status = 0;
1389 
1390  cxdouble crpix[] = {1., 1., 1.};
1391  cxdouble crval[] = {xstart, ystart, zstart};
1392 
1393  cpl_matrix* cd = cpl_matrix_new(3, 3);
1394 
1395  cpl_matrix_set(cd, 0, 0, xstep);
1396  cpl_matrix_set(cd, 1, 1, ystep);
1397  cpl_matrix_set(cd, 2, 2, zstep);
1398 
1399  status = giraffe_propertylist_update_wcs(properties, GICUBE_AXES,
1400  crpix, crval, ctype, cunit,
1401  cd);
1402 
1403  if (status != 0) {
1404  giraffe_propertylist_update_wcs(properties, 0, NULL, NULL, NULL,
1405  NULL, NULL);
1406  }
1407 
1408  cpl_matrix_delete(cd);
1409  cd = NULL;
1410 
1411  }
1412  else {
1413 
1414  giraffe_propertylist_update_wcs(properties, 0, NULL, NULL, NULL,
1415  NULL, NULL);
1416 
1417  }
1418 
1419 
1420  /*
1421  * Update data properties
1422  */
1423 
1424  giraffe_error_push();
1425 
1426  size = giraffe_cube_get_size(self);
1427  pixels = cpl_array_wrap_double(giraffe_cube_get_data(self), size);
1428 
1429 
1430  cpl_propertylist_update_string(properties, GIALIAS_BUNIT,
1431  "adu");
1432 
1433  cpl_propertylist_update_double(properties, GIALIAS_DATAMIN,
1434  cpl_array_get_min(pixels));
1435  cpl_propertylist_set_comment(properties, GIALIAS_DATAMIN,
1436  "Minimal pixel value");
1437 
1438  cpl_propertylist_update_double(properties, GIALIAS_DATAMAX,
1439  cpl_array_get_max(pixels));
1440  cpl_propertylist_set_comment(properties, GIALIAS_DATAMAX,
1441  "Maximum pixel value");
1442 
1443  cpl_propertylist_update_double(properties, GIALIAS_DATAMEAN,
1444  cpl_array_get_mean(pixels));
1445  cpl_propertylist_set_comment(properties, GIALIAS_DATAMEAN,
1446  "Mean of pixel values");
1447 
1448  cpl_propertylist_update_double(properties, GIALIAS_DATASIG,
1449  cpl_array_get_stdev(pixels));
1450  cpl_propertylist_set_comment(properties, GIALIAS_DATASIG,
1451  "Standard deviation of pixel values");
1452 
1453  cpl_propertylist_update_double(properties, GIALIAS_DATAMEDI,
1454  cpl_array_get_median(pixels));
1455  cpl_propertylist_set_comment(properties, GIALIAS_DATAMEDI,
1456  "Median of pixel values");
1457 
1458  cpl_array_unwrap((cpl_array*)pixels);
1459  pixels = NULL;
1460 
1461  if (cpl_error_get_code() != CPL_ERROR_NONE) {
1462  return 1;
1463  }
1464 
1465  giraffe_error_pop();
1466 
1467 
1468  /*
1469  * Write the data cube to the output file
1470  */
1471 
1472  giraffe_error_push();
1473 
1474  cpl_imagelist_save(self->planes, filename, CPL_BPP_IEEE_FLOAT,
1475  properties, iomode);
1476 
1477  if (cpl_error_get_code() != CPL_ERROR_NONE) {
1478  return 1;
1479  }
1480 
1481  giraffe_error_pop();
1482 
1483  }
1484 
1485  return 0;
1486 
1487 }
cxbool giraffe_cube_has_xaxis(const GiCube *self)
Check whether an x-axis is defined for the given cube.
Definition: gicube.c:746
cxsize giraffe_cube_get_height(const GiCube *self)
Get the height of the given data cube.
Definition: gicube.c:561
cxint giraffe_cube_get_yaxis(const GiCube *self, cxdouble *start, cxdouble *step)
Get the data cube's y-axis start value and step size.
Definition: gicube.c:867
cxsize giraffe_cube_get_depth(const GiCube *self)
Get the depth of the given data cube.
Definition: gicube.c:584
cxint giraffe_cube_save(const GiCube *self, cpl_propertylist *properties, const cxchar *filename, cxcptr data)
Save the given data cube to disk.
Definition: gicube.c:1244
cxint giraffe_cube_set_size(GiCube *self, cxsize width, cxsize height, cxsize depth)
Set the size of a data cube.
Definition: gicube.c:635
cxbool giraffe_cube_has_wcs(const GiCube *self)
Check whether a world coordinate system is defined for the given cube.
Definition: gicube.c:809
cxint giraffe_cube_set_wcs(GiCube *self, const cpl_propertylist *axes, const cpl_matrix *transformation)
Set the data cube's world coordinate system.
Definition: gicube.c:1040
cxbool giraffe_cube_has_zaxis(const GiCube *self)
Check whether a z-axis is defined for the given cube.
Definition: gicube.c:788
cxdouble * giraffe_cube_get_data(const GiCube *self)
Get a reference to the data cube's pixel buffer.
Definition: gicube.c:715
cxint giraffe_cube_set_zaxis(GiCube *self, cxdouble start, cxdouble step)
Set the data cube's z-axis start value and step size.
Definition: gicube.c:976
cxint giraffe_cube_set_xaxis(GiCube *self, cxdouble start, cxdouble step)
Set the data cube's x-axis start value and step size.
Definition: gicube.c:924
cxsize giraffe_cube_get_width(const GiCube *self)
Get the width of the given data cube.
Definition: gicube.c:538
GiCube * giraffe_cube_new(void)
Create an empty data cube.
Definition: gicube.c:420
cxint giraffe_cube_get_zaxis(const GiCube *self, cxdouble *start, cxdouble *step)
Get the data cube's z-axis start value and step size.
Definition: gicube.c:898
cxbool giraffe_cube_has_yaxis(const GiCube *self)
Check whether a y-axis is defined for the given cube.
Definition: gicube.c:767
void giraffe_cube_delete(GiCube *self)
Destroys a cube object.
Definition: gicube.c:512
cxsize giraffe_cube_get_size(const GiCube *self)
Get the size of the given data cube.
Definition: gicube.c:607
cxint giraffe_cube_sqrt(GiCube *self)
Compute the square root of the elements of a cube.
Definition: gicube.c:1099
cxint giraffe_cube_get_xaxis(const GiCube *self, cxdouble *start, cxdouble *step)
Get the data cube's x-axis start value and step size.
Definition: gicube.c:836
void giraffe_cube_clear_wcs(GiCube *self)
Remove the world coordinate system from the cube.
Definition: gicube.c:1001
GiCube * giraffe_cube_create(cxsize width, cxsize height, cxsize depth, cxdouble *data)
Create a data cube with the given width, height and depth.
Definition: gicube.c:455
cxint giraffe_cube_set_yaxis(GiCube *self, cxdouble start, cxdouble step)
Set the data cube's y-axis start value and step size.
Definition: gicube.c:950
cpl_image * giraffe_cube_integrate(const GiCube *self, cxdouble start, cxdouble end)
Integrate a cube along the z-axis.
Definition: gicube.c:1150

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