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
52enum GiCubeAxes {
53 GICUBE_X = 0,
54 GICUBE_Y = 1,
55 GICUBE_Z = 2,
56 GICUBE_AXES
57};
58
59typedef enum GiCubeAxes GiCubeAxes;
60
61
62struct GiCubeAxis {
63 cxdouble start;
64 cxdouble step;
65};
66
67typedef struct GiCubeAxis GiCubeAxis;
68
69
70struct 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
80typedef struct GiCubeWCS GiCubeWCS;
81
82
83struct 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
100inline 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
131inline 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
180inline static cxdouble
181_giraffe_cube_get_wcs_origin(const GiCube* self, GiCubeAxes axis)
182{
183 return self->wcs->origin[axis];
184}
185
186
187inline static cxdouble
188_giraffe_cube_get_wcs_point(const GiCube* self, GiCubeAxes axis)
189{
190 return self->wcs->point[axis];
191}
192
193
194inline 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
201inline 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
208inline static const cpl_matrix*
209_giraffe_cube_get_wcs_transform(const GiCube* self)
210{
211 return self->wcs->transform;
212}
213
214
215inline 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
231inline 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
256inline 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
288inline 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
313inline 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
348inline static cxbool
349_giraffe_cube_has_axis(const GiCube* self, GiCubeAxes axis)
350{
351 return (self->axes[axis] == NULL) ? FALSE : TRUE;
352}
353
354
355inline 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
380inline 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
411GiCube*
413{
414
415 return _giraffe_cube_new();
416
417}
418
419
446GiCube*
447giraffe_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
503void
505{
506
507 if (self != NULL) {
508 _giraffe_cube_delete(self);
509 }
510
511 return;
512
513}
514
515
529cxsize
530giraffe_cube_get_width(const GiCube* self)
531{
532
533 cx_assert(self != NULL);
534 return self->width;
535
536}
537
538
552cxsize
553giraffe_cube_get_height(const GiCube* self)
554{
555
556 cx_assert(self != NULL);
557 return self->height;
558
559}
560
561
575cxsize
576giraffe_cube_get_depth(const GiCube* self)
577{
578
579 cx_assert(self != NULL);
580 return self->depth;
581
582}
583
584
598cxsize
599giraffe_cube_get_size(const GiCube* self)
600{
601
602 cx_assert(self != NULL);
603 return self->size;
604
605}
606
607
626cxint
627giraffe_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
706cxdouble*
707giraffe_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
737cxbool
738giraffe_cube_has_xaxis(const GiCube* self)
739{
740 return _giraffe_cube_has_axis(self, GICUBE_X);
741}
742
743
758cxbool
759giraffe_cube_has_yaxis(const GiCube* self)
760{
761 return _giraffe_cube_has_axis(self, GICUBE_Y);
762}
763
764
779cxbool
780giraffe_cube_has_zaxis(const GiCube* self)
781{
782 return _giraffe_cube_has_axis(self, GICUBE_Z);
783}
784
785
800cxbool
801giraffe_cube_has_wcs(const GiCube* self)
802{
803 return self->wcs != NULL;
804}
805
806
827cxint
828giraffe_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
858cxint
859giraffe_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
889cxint
890giraffe_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
915cxint
916giraffe_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
941cxint
942giraffe_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
967cxint
968giraffe_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
992void
994{
995
996 if (self->wcs != NULL) {
997 _giraffe_cube_clear_wcs(self);
998 }
999
1000 return;
1001
1002}
1003
1004
1031cxint
1032giraffe_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
1090cxint
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
1141cpl_image*
1142giraffe_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
1235cxint
1236giraffe_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
cpl_image * giraffe_cube_integrate(const GiCube *self, cxdouble start, cxdouble end)
Integrate a cube along the z-axis.
Definition: gicube.c:1142
GiCube * giraffe_cube_new(void)
Create an empty data cube.
Definition: gicube.c:412
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
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
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
cxdouble * giraffe_cube_get_data(const GiCube *self)
Get a reference to the data cube's pixel buffer.
Definition: gicube.c:707
void giraffe_cube_delete(GiCube *self)
Destroys a cube object.
Definition: gicube.c:504
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
cxsize giraffe_cube_get_height(const GiCube *self)
Get the height of the given data cube.
Definition: gicube.c:553
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

This file is part of the GIRAFFE Pipeline Reference Manual 2.16.11.
Documentation copyright © 2002-2006 European Southern Observatory.
Generated on Wed Apr 17 2024 20:21:54 by doxygen 1.9.6 written by Dimitri van Heesch, © 1997-2004