GIRAFFE Pipeline Reference Manual

gicube.c
1 /*
2  * This file is part of the GIRAFFE Pipeline
3  * Copyright (C) 2002-2019 European Southern Observatory
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18  */
19 
20 #ifdef HAVE_CONFIG_H
21 # include <config.h>
22 #endif
23 
24 #include <string.h>
25 #include <math.h>
26 
27 #include <cxmemory.h>
28 #include <cxmessages.h>
29 #include <cxstrutils.h>
30 
31 #include <cpl_error.h>
32 #include <cpl_array.h>
33 #include <cpl_matrix.h>
34 #include <cpl_image.h>
35 #include <cpl_imagelist.h>
36 #include <cpl_propertylist.h>
37 
38 #include "gialias.h"
39 #include "gierror.h"
40 #include "gicube.h"
41 #include "giutils.h"
42 
43 
52 enum GiCubeAxes {
53  GICUBE_X = 0,
54  GICUBE_Y = 1,
55  GICUBE_Z = 2,
56  GICUBE_AXES
57 };
58 
59 typedef enum GiCubeAxes GiCubeAxes;
60 
61 
62 struct GiCubeAxis {
63  cxdouble start;
64  cxdouble step;
65 };
66 
67 typedef struct GiCubeAxis GiCubeAxis;
68 
69 
70 struct GiCubeWCS {
71  cxdouble origin[GICUBE_AXES];
72  cxdouble point[GICUBE_AXES];
73 
74  cxchar* axis_type[GICUBE_AXES];
75  cxchar* axis_unit[GICUBE_AXES];
76 
77  cpl_matrix* transform;
78 };
79 
80 typedef struct GiCubeWCS GiCubeWCS;
81 
82 
83 struct GiCube {
84  cxsize width;
85  cxsize height;
86  cxsize depth;
87  cxsize size;
88 
89  GiCubeAxis* axes[GICUBE_AXES];
90 
91  GiCubeWCS* wcs;
92 
93  cxdouble* pixels;
94 
95  cpl_imagelist* planes;
96 };
97 
98 
99 
100 inline static void
101 _giraffe_cube_clear_wcs(GiCube* self)
102 {
103 
104  register cxsize axis = 0;
105 
106  for (axis = 0; axis < GICUBE_AXES; ++axis) {
107 
108  if (self->wcs->axis_type[axis] != NULL) {
109  cx_free(self->wcs->axis_type[axis]);
110  self->wcs->axis_type[axis] = NULL;
111  }
112 
113  if (self->wcs->axis_unit[axis] != NULL) {
114  cx_free(self->wcs->axis_unit[axis]);
115  self->wcs->axis_unit[axis] = NULL;
116  }
117 
118  }
119 
120  cpl_matrix_delete(self->wcs->transform);
121  self->wcs->transform = NULL;
122 
123  cx_free(self->wcs);
124  self->wcs = NULL;
125 
126  return;
127 
128 }
129 
130 
131 inline static void
132 _giraffe_cube_set_wcs(GiCube* self, const cpl_propertylist* axes,
133  const cpl_matrix* transform)
134 {
135 
136  GiCubeWCS* wcs = NULL;
137 
138  cx_assert(self != NULL);
139  cx_assert(axes != NULL);
140  cx_assert(transform != NULL);
141 
142  wcs = cx_malloc(sizeof *self->wcs);
143 
144  wcs->transform = cpl_matrix_duplicate(transform);
145 
146  wcs->origin[GICUBE_X] = cpl_propertylist_get_double(axes, "XORIGIN");
147  wcs->origin[GICUBE_Y] = cpl_propertylist_get_double(axes, "YORIGIN");
148  wcs->origin[GICUBE_Z] = cpl_propertylist_get_double(axes, "ZORIGIN");
149 
150  wcs->point[GICUBE_X] = cpl_propertylist_get_double(axes, "XPOINT");
151  wcs->point[GICUBE_Y] = cpl_propertylist_get_double(axes, "YPOINT");
152  wcs->point[GICUBE_Z] = cpl_propertylist_get_double(axes, "ZPOINT");
153 
154  wcs->axis_type[GICUBE_X] =
155  cx_strdup(cpl_propertylist_get_string(axes, "XTYPE"));
156  wcs->axis_type[GICUBE_Y] =
157  cx_strdup(cpl_propertylist_get_string(axes, "YTYPE"));
158  wcs->axis_type[GICUBE_Z] =
159  cx_strdup(cpl_propertylist_get_string(axes, "ZTYPE"));
160 
161  wcs->axis_unit[GICUBE_X] =
162  cx_strdup(cpl_propertylist_get_string(axes, "XUNIT"));
163  wcs->axis_unit[GICUBE_Y] =
164  cx_strdup(cpl_propertylist_get_string(axes, "YUNIT"));
165  wcs->axis_unit[GICUBE_Z] =
166  cx_strdup(cpl_propertylist_get_string(axes, "ZUNIT"));
167 
168 
169  if (self->wcs != NULL) {
170  _giraffe_cube_clear_wcs(self);
171  }
172 
173  self->wcs = wcs;
174 
175  return;
176 
177 }
178 
179 
180 inline static cxdouble
181 _giraffe_cube_get_wcs_origin(const GiCube* self, GiCubeAxes axis)
182 {
183  return self->wcs->origin[axis];
184 }
185 
186 
187 inline static cxdouble
188 _giraffe_cube_get_wcs_point(const GiCube* self, GiCubeAxes axis)
189 {
190  return self->wcs->point[axis];
191 }
192 
193 
194 inline static const cxchar*
195 _giraffe_cube_get_wcs_axistype(const GiCube* self, GiCubeAxes axis)
196 {
197  return self->wcs->axis_type[axis];
198 }
199 
200 
201 inline static const cxchar*
202 _giraffe_cube_get_wcs_axisunit(const GiCube* self, GiCubeAxes axis)
203 {
204  return self->wcs->axis_unit[axis];
205 }
206 
207 
208 inline static const cpl_matrix*
209 _giraffe_cube_get_wcs_transform(const GiCube* self)
210 {
211  return self->wcs->transform;
212 }
213 
214 
215 inline static void
216 _giraffe_cube_set_size(GiCube* self, cxsize width, cxsize height,
217  cxsize depth)
218 {
219 
220  self->width = width;
221  self->height = height;
222  self->depth = depth;
223 
224  self->size = self->width * self->height * self->depth;
225 
226  return;
227 
228 }
229 
230 
231 inline static GiCube*
232 _giraffe_cube_new(void)
233 {
234 
235  GiCube* self = cx_malloc(sizeof *self);
236 
237 
238  if (self != NULL) {
239  _giraffe_cube_set_size(self, 0, 0, 0);
240 
241  self->axes[GICUBE_X] = NULL;
242  self->axes[GICUBE_Y] = NULL;
243  self->axes[GICUBE_Z] = NULL;
244 
245  self->wcs = NULL;
246 
247  self->pixels = NULL;
248  self->planes = NULL;
249  }
250 
251  return self;
252 
253 }
254 
255 
256 inline static cxint
257 _giraffe_cube_init_planes(GiCube* self)
258 {
259 
260  register cxsize i = 0;
261 
262  register cxdouble* base = NULL;
263 
264 
265  self->planes = cpl_imagelist_new();
266  cx_assert(self->planes != NULL);
267 
268 
269  base = self->pixels;
270 
271  for (i = 0; i < self->depth; i++) {
272 
273  cpl_image* plane = cpl_image_wrap_double(self->width, self->height,
274  base);
275 
276  cx_assert(plane != NULL);
277  cpl_imagelist_set(self->planes, plane, i);
278 
279  base += self->width * self->height;
280 
281  }
282 
283  return 0;
284 
285 }
286 
287 
288 inline static void
289 _giraffe_cube_clear_planes(GiCube* self)
290 {
291 
292  register cxsize i = 0;
293 
294 
295  for (i = 0; i < self->depth; i++) {
296 
297  cpl_image* plane = cpl_imagelist_unset(self->planes, 0);
298 
299  cpl_image_unwrap(plane);
300 
301  }
302 
303  cx_assert(cpl_imagelist_get_size(self->planes) == 0);
304 
305  cpl_imagelist_delete(self->planes);
306  self->planes =NULL;
307 
308  return;
309 
310 }
311 
312 
313 inline static void
314 _giraffe_cube_delete(GiCube* self)
315 {
316 
317  register cxint i = 0;
318 
319  for (i = 0; i < GICUBE_AXES; i++) {
320  if (self->axes[i] != NULL) {
321  cx_free(self->axes[i]);
322  self->axes[i] = NULL;
323  }
324  }
325 
326  if (self->wcs != NULL) {
327  _giraffe_cube_clear_wcs(self);
328  self->wcs = NULL;
329  }
330 
331  if (self->planes != NULL) {
332  _giraffe_cube_clear_planes(self);
333  self->planes = NULL;
334  }
335 
336  if (self->pixels != NULL) {
337  cx_free(self->pixels);
338  self->pixels = NULL;
339  }
340 
341  cx_free(self);
342 
343  return;
344 
345 }
346 
347 
348 inline static cxbool
349 _giraffe_cube_has_axis(const GiCube* self, GiCubeAxes axis)
350 {
351  return (self->axes[axis] == NULL) ? FALSE : TRUE;
352 }
353 
354 
355 inline static cxint
356 _giraffe_cube_get_axis(const GiCube* self, GiCubeAxes axis, cxdouble* start,
357  cxdouble* step)
358 {
359 
360  if (self->axes[axis] == NULL) {
361  return 1;
362  }
363  else {
364 
365  if (start != NULL) {
366  *start = self->axes[axis]->start;
367  }
368 
369  if (step != NULL) {
370  *step = self->axes[axis]->step;
371  }
372 
373  }
374 
375  return 0;
376 
377 }
378 
379 
380 inline static cxint
381 _giraffe_cube_set_axis(GiCube* self, GiCubeAxes axis, cxdouble start,
382  cxdouble step)
383 {
384 
385  if (self->axes[axis] == NULL) {
386  self->axes[axis] = cx_calloc(1, sizeof(GiCubeAxis));
387  }
388 
389  cx_assert(self->axes[axis] != NULL);
390 
391  self->axes[axis]->start = start;
392  self->axes[axis]->step = step;
393 
394  return 0;
395 
396 }
397 
398 
411 GiCube*
413 {
414 
415  return _giraffe_cube_new();
416 
417 }
418 
419 
446 GiCube*
447 giraffe_cube_create(cxsize width, cxsize height, cxsize depth, cxdouble* data)
448 {
449 
450  GiCube* self = _giraffe_cube_new();
451 
452 
453  _giraffe_cube_set_size(self, width, height, depth);
454 
455  if (self->size == 0) {
456  _giraffe_cube_delete(self);
457  return NULL;
458  }
459 
460  if (data != NULL) {
461  self->pixels = data;
462  }
463  else {
464  self->pixels = cx_calloc(self->size, sizeof(cxdouble));
465  }
466 
467  cx_assert(self->pixels != NULL);
468 
469 
470  /*
471  * Create the image list object for accessing the cube plane by plane.
472  * It is also needed (for the time being) to save a cube to disk.
473  */
474 
475  giraffe_error_push();
476 
477  _giraffe_cube_init_planes(self);
478 
479  if (cpl_error_get_code() != CPL_ERROR_NONE) {
480  _giraffe_cube_delete(self);
481  return NULL;
482  }
483 
484  giraffe_error_pop();
485 
486  return self;
487 
488 }
489 
490 
503 void
504 giraffe_cube_delete(GiCube* self)
505 {
506 
507  if (self != NULL) {
508  _giraffe_cube_delete(self);
509  }
510 
511  return;
512 
513 }
514 
515 
529 cxsize
530 giraffe_cube_get_width(const GiCube* self)
531 {
532 
533  cx_assert(self != NULL);
534  return self->width;
535 
536 }
537 
538 
552 cxsize
553 giraffe_cube_get_height(const GiCube* self)
554 {
555 
556  cx_assert(self != NULL);
557  return self->height;
558 
559 }
560 
561 
575 cxsize
576 giraffe_cube_get_depth(const GiCube* self)
577 {
578 
579  cx_assert(self != NULL);
580  return self->depth;
581 
582 }
583 
584 
598 cxsize
599 giraffe_cube_get_size(const GiCube* self)
600 {
601 
602  cx_assert(self != NULL);
603  return self->size;
604 
605 }
606 
607 
626 cxint
627 giraffe_cube_set_size(GiCube* self, cxsize width, cxsize height, cxsize depth)
628 {
629 
630  const cxchar* const _id = "giraffe_cube_set_size";
631 
632 
633  cx_assert(self != NULL);
634 
635  if ((width == 0) || (height == 0) || (depth == 0)) {
636  cpl_error_set(_id, CPL_ERROR_ILLEGAL_INPUT);
637  return 1;
638  }
639 
640  if ((self->width == width) && (self->height == height) &&
641  (self->depth == depth)) {
642  memset(self->pixels, 0, self->size * sizeof(cxdouble));
643  }
644  else {
645 
646  /*
647  * Clear the list of planes and destroy the old pixel buffer
648  */
649 
650  if (self->planes != NULL) {
651  _giraffe_cube_clear_planes(self);
652  }
653 
654  if (self->pixels != NULL) {
655  cx_free(self->pixels);
656  }
657 
658 
659  /*
660  * Set the new sizes
661  */
662 
663  _giraffe_cube_set_size(self, width, height, depth);
664 
665 
666  /*
667  * Re-create the pixel buffer and the list of planes from the updated
668  * size specifications.
669  */
670 
671  self->pixels = cx_calloc(self->size, sizeof(cxdouble));
672  cx_assert(self->pixels);
673 
674 
675  giraffe_error_push();
676 
677  _giraffe_cube_init_planes(self);
678 
679  if (cpl_error_get_code() != CPL_ERROR_NONE) {
680  return 1;
681  }
682 
683  giraffe_error_pop();
684 
685  }
686 
687  return 0;
688 
689 }
690 
691 
706 cxdouble*
707 giraffe_cube_get_data(const GiCube* self)
708 {
709 
710  const cxchar* const _id = "giraffe_cube_get_data";
711 
712 
713  if (self == NULL) {
714  cpl_error_set(_id, CPL_ERROR_NULL_INPUT);
715  return 0;
716  }
717 
718  return self->pixels;
719 
720 }
721 
722 
737 cxbool
738 giraffe_cube_has_xaxis(const GiCube* self)
739 {
740  return _giraffe_cube_has_axis(self, GICUBE_X);
741 }
742 
743 
758 cxbool
759 giraffe_cube_has_yaxis(const GiCube* self)
760 {
761  return _giraffe_cube_has_axis(self, GICUBE_Y);
762 }
763 
764 
779 cxbool
780 giraffe_cube_has_zaxis(const GiCube* self)
781 {
782  return _giraffe_cube_has_axis(self, GICUBE_Z);
783 }
784 
785 
800 cxbool
801 giraffe_cube_has_wcs(const GiCube* self)
802 {
803  return self->wcs != NULL;
804 }
805 
806 
827 cxint
828 giraffe_cube_get_xaxis(const GiCube* self, cxdouble* start, cxdouble* step)
829 {
830 
831  cx_assert(self != NULL);
832 
833  return _giraffe_cube_get_axis(self, GICUBE_X, start, step);
834 
835 }
836 
837 
858 cxint
859 giraffe_cube_get_yaxis(const GiCube* self, cxdouble* start, cxdouble* step)
860 {
861 
862  cx_assert(self != NULL);
863 
864  return _giraffe_cube_get_axis(self, GICUBE_Y, start, step);
865 
866 }
867 
868 
889 cxint
890 giraffe_cube_get_zaxis(const GiCube* self, cxdouble* start, cxdouble* step)
891 {
892 
893  cx_assert(self != NULL);
894 
895  return _giraffe_cube_get_axis(self, GICUBE_Z, start, step);
896 
897 }
898 
899 
915 cxint
916 giraffe_cube_set_xaxis(GiCube* self, cxdouble start, cxdouble step)
917 {
918 
919  cx_assert(self != NULL);
920 
921  return _giraffe_cube_set_axis(self, GICUBE_X, start, step);
922 
923 }
924 
925 
941 cxint
942 giraffe_cube_set_yaxis(GiCube* self, cxdouble start, cxdouble step)
943 {
944 
945  cx_assert(self != NULL);
946 
947  return _giraffe_cube_set_axis(self, GICUBE_Y, start, step);
948 
949 }
950 
951 
967 cxint
968 giraffe_cube_set_zaxis(GiCube* self, cxdouble start, cxdouble step)
969 {
970 
971  cx_assert(self != NULL);
972 
973  return _giraffe_cube_set_axis(self, GICUBE_Z, start, step);
974 
975 }
976 
977 
992 void
994 {
995 
996  if (self->wcs != NULL) {
997  _giraffe_cube_clear_wcs(self);
998  }
999 
1000  return;
1001 
1002 }
1003 
1004 
1031 cxint
1032 giraffe_cube_set_wcs(GiCube* self, const cpl_propertylist* axes,
1033  const cpl_matrix* transformation)
1034 {
1035 
1036  cx_assert(self != NULL);
1037 
1038  if ((axes == NULL) || (transformation == NULL)) {
1039  return -1;
1040  }
1041 
1042  if ((cpl_matrix_get_nrow(transformation) != GICUBE_AXES) ||
1043  (cpl_matrix_get_ncol(transformation) != GICUBE_AXES)) {
1044  return 3;
1045  }
1046 
1047  if ((cpl_propertylist_has(axes, "XORIGIN") == FALSE) ||
1048  (cpl_propertylist_has(axes, "YORIGIN") == FALSE) ||
1049  (cpl_propertylist_has(axes, "ZORIGIN") == FALSE)) {
1050  return 2;
1051  }
1052 
1053  if ((cpl_propertylist_has(axes, "XPOINT") == FALSE) ||
1054  (cpl_propertylist_has(axes, "YPOINT") == FALSE) ||
1055  (cpl_propertylist_has(axes, "ZPOINT") == FALSE)) {
1056  return 2;
1057  }
1058 
1059  if ((cpl_propertylist_has(axes, "XTYPE") == FALSE) ||
1060  (cpl_propertylist_has(axes, "YTYPE") == FALSE) ||
1061  (cpl_propertylist_has(axes, "ZTYPE") == FALSE)) {
1062  return 2;
1063  }
1064 
1065  if ((cpl_propertylist_has(axes, "XUNIT") == FALSE) ||
1066  (cpl_propertylist_has(axes, "YUNIT") == FALSE) ||
1067  (cpl_propertylist_has(axes, "ZUNIT") == FALSE)) {
1068  return 2;
1069  }
1070 
1071  _giraffe_cube_set_wcs(self, axes, transformation);
1072 
1073  return 1;
1074 }
1075 
1076 
1090 cxint
1091 giraffe_cube_sqrt(GiCube* self)
1092 {
1093 
1094  cpl_error_code status = CPL_ERROR_NONE;
1095 
1096 
1097  if (self == NULL) {
1098  return -1;
1099  }
1100 
1101  cx_assert(self->planes != NULL);
1102 
1103  status = cpl_imagelist_power(self->planes, 0.5);
1104 
1105  if (status != CPL_ERROR_NONE) {
1106  return 1;
1107  }
1108 
1109  return 0;
1110 
1111 }
1112 
1113 
1141 cpl_image*
1142 giraffe_cube_integrate(const GiCube* self, cxdouble start, cxdouble end)
1143 {
1144 
1145  cxsize depth = 0;
1146  cxsize first = (cxsize)ceil(start);
1147  cxsize last = (cxsize)floor(end);
1148 
1149  cpl_image* image = NULL;
1150 
1151 
1152  if (self == NULL) {
1153  return NULL;
1154  }
1155 
1156  depth = giraffe_cube_get_depth(self);
1157 
1158  if ((start >= end) || (start < 0.) || (end > depth)) {
1159  return NULL;
1160  }
1161 
1162 
1163  image = cpl_image_duplicate(cpl_imagelist_get(self->planes, first));
1164 
1165  if (image != NULL) {
1166 
1167  if (first == last) {
1168  cpl_image_multiply_scalar(image, (end - start));
1169  }
1170  else {
1171 
1172  cxsize i = 0;
1173 
1174  cxdouble fstart = first - start;
1175  cxdouble fend = end - last;
1176 
1177 
1178  for (i = first + 1; i < last; ++i) {
1179  cpl_image_add(image,
1180  cpl_imagelist_get_const(self->planes, i));
1181  }
1182 
1183 
1184  /*
1185  * Correct for the pixel fractions at both ends of the
1186  * integration domain.
1187  */
1188 
1189  if ((fstart > 0.) && (first > 0)) {
1190  cpl_image* tmp = cpl_imagelist_get(self->planes, first - 1);
1191 
1192  tmp = cpl_image_multiply_scalar_create(tmp, fstart);
1193  cpl_image_add(image, tmp);
1194 
1195  cpl_image_delete(tmp);
1196  tmp = NULL;
1197  }
1198 
1199  if ((fend > 0.) && (last < depth)) {
1200  cpl_image* tmp = cpl_imagelist_get(self->planes, last);
1201 
1202  tmp = cpl_image_multiply_scalar_create(tmp, fend);
1203  cpl_image_add(image, tmp);
1204 
1205  cpl_image_delete(tmp);
1206  tmp = NULL;
1207  }
1208 
1209  }
1210 
1211  }
1212 
1213  return image;
1214 
1215 }
1216 
1217 
1235 cxint
1236 giraffe_cube_save(const GiCube* self, cpl_propertylist* properties,
1237  const cxchar* filename, cxcptr data)
1238 {
1239 
1240  cxbool xaxis = FALSE;
1241  cxbool yaxis = FALSE;
1242  cxbool zaxis = FALSE;
1243 
1244  cxdouble xstart = 0.;
1245  cxdouble xstep = 0.;
1246  cxdouble ystart = 0.;
1247  cxdouble ystep = 0.;
1248  cxdouble zstart = 0.;
1249  cxdouble zstep = 0.;
1250 
1251  cxuint iomode = CPL_IO_CREATE;
1252 
1253 
1254  if (properties == NULL || filename == NULL) {
1255  return -1;
1256  }
1257 
1258 
1259  /*
1260  * If present use the cube writer configuration
1261  */
1262 
1263  if (data != NULL) {
1264  iomode = *((cxuint*)data);
1265  }
1266 
1267 
1268  if (self == NULL) {
1269 
1270  /*
1271  * If no cube has been provided, but properties and a filename
1272  * were given an empty cube is written to the file. Currently
1273  * this is restricted to creating a new cube file, to avoid
1274  * turning the property list into a valid extension header.
1275  */
1276 
1277  if (iomode != CPL_IO_CREATE) {
1278  return -2;
1279  }
1280 
1281  giraffe_error_push();
1282 
1283  cpl_propertylist_erase_regexp(properties, "CRVAL[0-9]*", 0);
1284  cpl_propertylist_erase_regexp(properties, "CRPIX[0-9]*", 0);
1285  cpl_propertylist_erase_regexp(properties, "CDELT[0-9]*", 0);
1286  cpl_propertylist_erase_regexp(properties, "CTYPE[0-9]*", 0);
1287  cpl_propertylist_erase_regexp(properties, "CUNIT[0-9]*", 0);
1288 
1289  cpl_propertylist_erase(properties, GIALIAS_BUNIT);
1290 
1291  cpl_propertylist_erase(properties, "DATAMIN");
1292  cpl_propertylist_erase(properties, "DATAMAX");
1293 
1294  cpl_propertylist_erase(properties, GIALIAS_DATAMEAN);
1295  cpl_propertylist_erase(properties, GIALIAS_DATAMEDI);
1296  cpl_propertylist_erase(properties, GIALIAS_DATASIG);
1297 
1298  cpl_propertylist_save(properties, filename, iomode);
1299 
1300  if (cpl_error_get_code() != CPL_ERROR_NONE) {
1301  return 1;
1302  }
1303 
1304  giraffe_error_pop();
1305 
1306  }
1307  else {
1308 
1309  cxsize size = 0;
1310 
1311  const cpl_array* pixels = NULL;
1312 
1313 
1314  /*
1315  * Update the data cube's properties. The world coordinates are only
1316  * written if a world coordinate system has been previously defined.
1317  * If a full world coordinate system is not present, the world
1318  * coordinates as defined by the cube's axes are used provided that
1319  * the information is present for all three axes. If this information
1320  * is missing too, no world coordinates are written.
1321  */
1322 
1323  if (giraffe_cube_get_xaxis(self, &xstart, &xstep) == 0) {
1324  xaxis = TRUE;
1325  }
1326 
1327  if (giraffe_cube_get_yaxis(self, &ystart, &ystep) == 0) {
1328  yaxis = TRUE;
1329  }
1330 
1331  if (giraffe_cube_get_zaxis(self, &zstart, &zstep) == 0) {
1332  zaxis = TRUE;
1333  }
1334 
1335 
1336  if (giraffe_cube_has_wcs(self) == TRUE) {
1337 
1338  const cxchar* ctype[GICUBE_AXES];
1339  const cxchar* cunit[GICUBE_AXES];
1340 
1341  cxint status = 0;
1342 
1343  cxdouble crpix[GICUBE_AXES];
1344  cxdouble crval[GICUBE_AXES];
1345 
1346  const cpl_matrix* cd = _giraffe_cube_get_wcs_transform(self);
1347 
1348 
1349  crpix[GICUBE_X] = _giraffe_cube_get_wcs_origin(self, GICUBE_X);
1350  crpix[GICUBE_Y] = _giraffe_cube_get_wcs_origin(self, GICUBE_Y);
1351  crpix[GICUBE_Z] = _giraffe_cube_get_wcs_origin(self, GICUBE_Z);
1352 
1353  crval[GICUBE_X] = _giraffe_cube_get_wcs_point(self, GICUBE_X);
1354  crval[GICUBE_Y] = _giraffe_cube_get_wcs_point(self, GICUBE_Y);
1355  crval[GICUBE_Z] = _giraffe_cube_get_wcs_point(self, GICUBE_Z);
1356 
1357  ctype[GICUBE_X] = _giraffe_cube_get_wcs_axistype(self, GICUBE_X);
1358  ctype[GICUBE_Y] = _giraffe_cube_get_wcs_axistype(self, GICUBE_Y);
1359  ctype[GICUBE_Z] = _giraffe_cube_get_wcs_axistype(self, GICUBE_Z);
1360 
1361  cunit[GICUBE_X] = _giraffe_cube_get_wcs_axisunit(self, GICUBE_X);
1362  cunit[GICUBE_Y] = _giraffe_cube_get_wcs_axisunit(self, GICUBE_Y);
1363  cunit[GICUBE_Z] = _giraffe_cube_get_wcs_axisunit(self, GICUBE_Z);
1364 
1365  status = giraffe_propertylist_update_wcs(properties, GICUBE_AXES,
1366  crpix, crval, ctype, cunit,
1367  cd);
1368 
1369  if (status != 0) {
1370  giraffe_propertylist_update_wcs(properties, 0, NULL, NULL, NULL,
1371  NULL, NULL);
1372  }
1373 
1374  }
1375  else if ((xaxis == TRUE) && (yaxis == TRUE) && (zaxis == TRUE)) {
1376 
1377  const cxchar* ctype[] = {"PIXEL", "PIXEL", "AWAV"};
1378  const cxchar* cunit[] = {"bin", "bin", "nm"};
1379 
1380  cxint status = 0;
1381 
1382  cxdouble crpix[] = {1., 1., 1.};
1383  cxdouble crval[] = {xstart, ystart, zstart};
1384 
1385  cpl_matrix* cd = cpl_matrix_new(3, 3);
1386 
1387  cpl_matrix_set(cd, 0, 0, xstep);
1388  cpl_matrix_set(cd, 1, 1, ystep);
1389  cpl_matrix_set(cd, 2, 2, zstep);
1390 
1391  status = giraffe_propertylist_update_wcs(properties, GICUBE_AXES,
1392  crpix, crval, ctype, cunit,
1393  cd);
1394 
1395  if (status != 0) {
1396  giraffe_propertylist_update_wcs(properties, 0, NULL, NULL, NULL,
1397  NULL, NULL);
1398  }
1399 
1400  cpl_matrix_delete(cd);
1401  cd = NULL;
1402 
1403  }
1404  else {
1405 
1406  giraffe_propertylist_update_wcs(properties, 0, NULL, NULL, NULL,
1407  NULL, NULL);
1408 
1409  }
1410 
1411 
1412  /*
1413  * Update data properties
1414  */
1415 
1416  giraffe_error_push();
1417 
1418  size = giraffe_cube_get_size(self);
1419  pixels = cpl_array_wrap_double(giraffe_cube_get_data(self), size);
1420 
1421 
1422  cpl_propertylist_update_string(properties, GIALIAS_BUNIT,
1423  "adu");
1424 
1425  cpl_propertylist_update_double(properties, GIALIAS_DATAMIN,
1426  cpl_array_get_min(pixels));
1427  cpl_propertylist_set_comment(properties, GIALIAS_DATAMIN,
1428  "Minimal pixel value");
1429 
1430  cpl_propertylist_update_double(properties, GIALIAS_DATAMAX,
1431  cpl_array_get_max(pixels));
1432  cpl_propertylist_set_comment(properties, GIALIAS_DATAMAX,
1433  "Maximum pixel value");
1434 
1435  cpl_propertylist_update_double(properties, GIALIAS_DATAMEAN,
1436  cpl_array_get_mean(pixels));
1437  cpl_propertylist_set_comment(properties, GIALIAS_DATAMEAN,
1438  "Mean of pixel values");
1439 
1440  cpl_propertylist_update_double(properties, GIALIAS_DATASIG,
1441  cpl_array_get_stdev(pixels));
1442  cpl_propertylist_set_comment(properties, GIALIAS_DATASIG,
1443  "Standard deviation of pixel values");
1444 
1445  cpl_propertylist_update_double(properties, GIALIAS_DATAMEDI,
1446  cpl_array_get_median(pixels));
1447  cpl_propertylist_set_comment(properties, GIALIAS_DATAMEDI,
1448  "Median of pixel values");
1449 
1450  cpl_array_unwrap((cpl_array*)pixels);
1451  pixels = NULL;
1452 
1453  if (cpl_error_get_code() != CPL_ERROR_NONE) {
1454  return 1;
1455  }
1456 
1457  giraffe_error_pop();
1458 
1459 
1460  /*
1461  * Write the data cube to the output file
1462  */
1463 
1464  giraffe_error_push();
1465 
1466  cpl_imagelist_save(self->planes, filename, CPL_BPP_IEEE_FLOAT,
1467  properties, iomode);
1468 
1469  if (cpl_error_get_code() != CPL_ERROR_NONE) {
1470  return 1;
1471  }
1472 
1473  giraffe_error_pop();
1474 
1475  }
1476 
1477  return 0;
1478 
1479 }
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:828
cxbool giraffe_cube_has_yaxis(const GiCube *self)
Check whether a y-axis is defined for the given cube.
Definition: gicube.c:759
cxsize giraffe_cube_get_width(const GiCube *self)
Get the width of the given data cube.
Definition: gicube.c:530
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:859
cxint giraffe_cube_set_size(GiCube *self, cxsize width, cxsize height, cxsize depth)
Set the size of a data cube.
Definition: gicube.c:627
cxsize giraffe_cube_get_depth(const GiCube *self)
Get the depth of the given data cube.
Definition: gicube.c:576
cxbool giraffe_cube_has_zaxis(const GiCube *self)
Check whether a z-axis is defined for the given cube.
Definition: gicube.c:780
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:942
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:890
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:1032
void giraffe_cube_clear_wcs(GiCube *self)
Remove the world coordinate system from the cube.
Definition: gicube.c:993
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:968
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:916
void giraffe_cube_delete(GiCube *self)
Destroys a cube object.
Definition: gicube.c:504
GiCube * giraffe_cube_new(void)
Create an empty data cube.
Definition: gicube.c:412
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:1236
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:447
cxsize giraffe_cube_get_height(const GiCube *self)
Get the height of the given data cube.
Definition: gicube.c:553
cpl_image * giraffe_cube_integrate(const GiCube *self, cxdouble start, cxdouble end)
Integrate a cube along the z-axis.
Definition: gicube.c:1142
cxint giraffe_cube_sqrt(GiCube *self)
Compute the square root of the elements of a cube.
Definition: gicube.c:1091
cxbool giraffe_cube_has_wcs(const GiCube *self)
Check whether a world coordinate system is defined for the given cube.
Definition: gicube.c:801
cxsize giraffe_cube_get_size(const GiCube *self)
Get the size of the given data cube.
Definition: gicube.c:599
cxbool giraffe_cube_has_xaxis(const GiCube *self)
Check whether an x-axis is defined for the given cube.
Definition: gicube.c:738
cxdouble * giraffe_cube_get_data(const GiCube *self)
Get a reference to the data cube's pixel buffer.
Definition: gicube.c:707

This file is part of the GIRAFFE Pipeline Reference Manual 2.16.10.
Documentation copyright © 2002-2006 European Southern Observatory.
Generated on Thu Dec 15 2022 21:18:51 by doxygen 1.9.1 written by Dimitri van Heesch, © 1997-2004