00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifdef HAVE_CONFIG_H
00029 # include <config.h>
00030 #endif
00031
00032 #include <string.h>
00033 #include <math.h>
00034
00035 #include <cxmemory.h>
00036 #include <cxmessages.h>
00037 #include <cxstrutils.h>
00038
00039 #include <cpl_error.h>
00040 #include <cpl_array.h>
00041 #include <cpl_matrix.h>
00042 #include <cpl_image.h>
00043 #include <cpl_imagelist.h>
00044 #include <cpl_propertylist.h>
00045
00046 #include "gialias.h"
00047 #include "gierror.h"
00048 #include "gicube.h"
00049 #include "giutils.h"
00050
00051
00060 enum GiCubeAxes {
00061 GICUBE_X = 0,
00062 GICUBE_Y = 1,
00063 GICUBE_Z = 2,
00064 GICUBE_AXES
00065 };
00066
00067 typedef enum GiCubeAxes GiCubeAxes;
00068
00069
00070 struct GiCubeAxis {
00071 cxdouble start;
00072 cxdouble step;
00073 };
00074
00075 typedef struct GiCubeAxis GiCubeAxis;
00076
00077
00078 struct GiCubeWCS {
00079 cxdouble origin[GICUBE_AXES];
00080 cxdouble point[GICUBE_AXES];
00081
00082 cxchar* axis_type[GICUBE_AXES];
00083 cxchar* axis_unit[GICUBE_AXES];
00084
00085 cpl_matrix* transform;
00086 };
00087
00088 typedef struct GiCubeWCS GiCubeWCS;
00089
00090
00091 struct GiCube {
00092 cxsize width;
00093 cxsize height;
00094 cxsize depth;
00095 cxsize size;
00096
00097 GiCubeAxis* axes[GICUBE_AXES];
00098
00099 GiCubeWCS* wcs;
00100
00101 cxdouble* pixels;
00102
00103 cpl_imagelist* planes;
00104 };
00105
00106
00107
00108 inline static void
00109 _giraffe_cube_clear_wcs(GiCube* self)
00110 {
00111
00112 register cxsize axis = 0;
00113
00114 for (axis = 0; axis < GICUBE_AXES; ++axis) {
00115
00116 if (self->wcs->axis_type[axis] != NULL) {
00117 cx_free(self->wcs->axis_type[axis]);
00118 self->wcs->axis_type[axis] = NULL;
00119 }
00120
00121 if (self->wcs->axis_unit[axis] != NULL) {
00122 cx_free(self->wcs->axis_unit[axis]);
00123 self->wcs->axis_unit[axis] = NULL;
00124 }
00125
00126 }
00127
00128 cpl_matrix_delete(self->wcs->transform);
00129 self->wcs->transform = NULL;
00130
00131 cx_free(self->wcs);
00132 self->wcs = NULL;
00133
00134 return;
00135
00136 }
00137
00138
00139 inline static void
00140 _giraffe_cube_set_wcs(GiCube* self, const cpl_propertylist* axes,
00141 const cpl_matrix* transform)
00142 {
00143
00144 GiCubeWCS* wcs = NULL;
00145
00146 cx_assert(self != NULL);
00147 cx_assert(axes != NULL);
00148 cx_assert(transform != NULL);
00149
00150 wcs = cx_malloc(sizeof *self->wcs);
00151
00152 wcs->transform = cpl_matrix_duplicate(transform);
00153
00154 wcs->origin[GICUBE_X] = cpl_propertylist_get_double(axes, "XORIGIN");
00155 wcs->origin[GICUBE_Y] = cpl_propertylist_get_double(axes, "YORIGIN");
00156 wcs->origin[GICUBE_Z] = cpl_propertylist_get_double(axes, "ZORIGIN");
00157
00158 wcs->point[GICUBE_X] = cpl_propertylist_get_double(axes, "XPOINT");
00159 wcs->point[GICUBE_Y] = cpl_propertylist_get_double(axes, "YPOINT");
00160 wcs->point[GICUBE_Z] = cpl_propertylist_get_double(axes, "ZPOINT");
00161
00162 wcs->axis_type[GICUBE_X] =
00163 cx_strdup(cpl_propertylist_get_string(axes, "XTYPE"));
00164 wcs->axis_type[GICUBE_Y] =
00165 cx_strdup(cpl_propertylist_get_string(axes, "YTYPE"));
00166 wcs->axis_type[GICUBE_Z] =
00167 cx_strdup(cpl_propertylist_get_string(axes, "ZTYPE"));
00168
00169 wcs->axis_unit[GICUBE_X] =
00170 cx_strdup(cpl_propertylist_get_string(axes, "XUNIT"));
00171 wcs->axis_unit[GICUBE_Y] =
00172 cx_strdup(cpl_propertylist_get_string(axes, "YUNIT"));
00173 wcs->axis_unit[GICUBE_Z] =
00174 cx_strdup(cpl_propertylist_get_string(axes, "ZUNIT"));
00175
00176
00177 if (self->wcs != NULL) {
00178 _giraffe_cube_clear_wcs(self);
00179 }
00180
00181 self->wcs = wcs;
00182
00183 return;
00184
00185 }
00186
00187
00188 inline static cxdouble
00189 _giraffe_cube_get_wcs_origin(const GiCube* self, GiCubeAxes axis)
00190 {
00191 return self->wcs->origin[axis];
00192 }
00193
00194
00195 inline static cxdouble
00196 _giraffe_cube_get_wcs_point(const GiCube* self, GiCubeAxes axis)
00197 {
00198 return self->wcs->point[axis];
00199 }
00200
00201
00202 inline static const cxchar*
00203 _giraffe_cube_get_wcs_axistype(const GiCube* self, GiCubeAxes axis)
00204 {
00205 return self->wcs->axis_type[axis];
00206 }
00207
00208
00209 inline static const cxchar*
00210 _giraffe_cube_get_wcs_axisunit(const GiCube* self, GiCubeAxes axis)
00211 {
00212 return self->wcs->axis_unit[axis];
00213 }
00214
00215
00216 inline static const cpl_matrix*
00217 _giraffe_cube_get_wcs_transform(const GiCube* self)
00218 {
00219 return self->wcs->transform;
00220 }
00221
00222
00223 inline static void
00224 _giraffe_cube_set_size(GiCube* self, cxsize width, cxsize height,
00225 cxsize depth)
00226 {
00227
00228 self->width = width;
00229 self->height = height;
00230 self->depth = depth;
00231
00232 self->size = self->width * self->height * self->depth;
00233
00234 return;
00235
00236 }
00237
00238
00239 inline static GiCube*
00240 _giraffe_cube_new(void)
00241 {
00242
00243 GiCube* self = cx_malloc(sizeof *self);
00244
00245
00246 if (self != NULL) {
00247 _giraffe_cube_set_size(self, 0, 0, 0);
00248
00249 self->axes[GICUBE_X] = NULL;
00250 self->axes[GICUBE_Y] = NULL;
00251 self->axes[GICUBE_Z] = NULL;
00252
00253 self->wcs = NULL;
00254
00255 self->pixels = NULL;
00256 self->planes = NULL;
00257 }
00258
00259 return self;
00260
00261 }
00262
00263
00264 inline static cxint
00265 _giraffe_cube_init_planes(GiCube* self)
00266 {
00267
00268 register cxsize i = 0;
00269
00270 register cxdouble* base = NULL;
00271
00272
00273 self->planes = cpl_imagelist_new();
00274 cx_assert(self->planes != NULL);
00275
00276
00277 base = self->pixels;
00278
00279 for (i = 0; i < self->depth; i++) {
00280
00281 cpl_image* plane = cpl_image_wrap_double(self->width, self->height,
00282 base);
00283
00284 cx_assert(plane != NULL);
00285 cpl_imagelist_set(self->planes, plane, i);
00286
00287 base += self->width * self->height;
00288
00289 }
00290
00291 return 0;
00292
00293 }
00294
00295
00296 inline static void
00297 _giraffe_cube_clear_planes(GiCube* self)
00298 {
00299
00300 register cxsize i = 0;
00301
00302
00303 for (i = 0; i < self->depth; i++) {
00304
00305 cpl_image* plane = cpl_imagelist_unset(self->planes, 0);
00306
00307 cpl_image_unwrap(plane);
00308
00309 }
00310
00311 cx_assert(cpl_imagelist_get_size(self->planes) == 0);
00312
00313 cpl_imagelist_delete(self->planes);
00314 self->planes =NULL;
00315
00316 return;
00317
00318 }
00319
00320
00321 inline static void
00322 _giraffe_cube_delete(GiCube* self)
00323 {
00324
00325 register cxint i = 0;
00326
00327 for (i = 0; i < GICUBE_AXES; i++) {
00328 if (self->axes[i] != NULL) {
00329 cx_free(self->axes[i]);
00330 self->axes[i] = NULL;
00331 }
00332 }
00333
00334 if (self->wcs != NULL) {
00335 _giraffe_cube_clear_wcs(self);
00336 self->wcs = NULL;
00337 }
00338
00339 if (self->planes != NULL) {
00340 _giraffe_cube_clear_planes(self);
00341 self->planes = NULL;
00342 }
00343
00344 if (self->pixels != NULL) {
00345 cx_free(self->pixels);
00346 self->pixels = NULL;
00347 }
00348
00349 cx_free(self);
00350
00351 return;
00352
00353 }
00354
00355
00356 inline static cxbool
00357 _giraffe_cube_has_axis(const GiCube* self, GiCubeAxes axis)
00358 {
00359 return (self->axes[axis] == NULL) ? FALSE : TRUE;
00360 }
00361
00362
00363 inline static cxint
00364 _giraffe_cube_get_axis(const GiCube* self, GiCubeAxes axis, cxdouble* start,
00365 cxdouble* step)
00366 {
00367
00368 if (self->axes[axis] == NULL) {
00369 return 1;
00370 }
00371 else {
00372
00373 if (start != NULL) {
00374 *start = self->axes[axis]->start;
00375 }
00376
00377 if (step != NULL) {
00378 *step = self->axes[axis]->step;
00379 }
00380
00381 }
00382
00383 return 0;
00384
00385 }
00386
00387
00388 inline static cxint
00389 _giraffe_cube_set_axis(GiCube* self, GiCubeAxes axis, cxdouble start,
00390 cxdouble step)
00391 {
00392
00393 if (self->axes[axis] == NULL) {
00394 self->axes[axis] = cx_calloc(1, sizeof(GiCubeAxis));
00395 }
00396
00397 cx_assert(self->axes[axis] != NULL);
00398
00399 self->axes[axis]->start = start;
00400 self->axes[axis]->step = step;
00401
00402 return 0;
00403
00404 }
00405
00406
00419 GiCube*
00420 giraffe_cube_new(void)
00421 {
00422
00423 return _giraffe_cube_new();
00424
00425 }
00426
00427
00454 GiCube*
00455 giraffe_cube_create(cxsize width, cxsize height, cxsize depth, cxdouble* data)
00456 {
00457
00458 GiCube* self = _giraffe_cube_new();
00459
00460
00461 _giraffe_cube_set_size(self, width, height, depth);
00462
00463 if (self->size == 0) {
00464 _giraffe_cube_delete(self);
00465 return NULL;
00466 }
00467
00468 if (data != NULL) {
00469 self->pixels = data;
00470 }
00471 else {
00472 self->pixels = cx_calloc(self->size, sizeof(cxdouble));
00473 }
00474
00475 cx_assert(self->pixels != NULL);
00476
00477
00478
00479
00480
00481
00482
00483 giraffe_error_push();
00484
00485 _giraffe_cube_init_planes(self);
00486
00487 if (cpl_error_get_code() != CPL_ERROR_NONE) {
00488 _giraffe_cube_delete(self);
00489 return NULL;
00490 }
00491
00492 giraffe_error_pop();
00493
00494 return self;
00495
00496 }
00497
00498
00511 void
00512 giraffe_cube_delete(GiCube* self)
00513 {
00514
00515 if (self != NULL) {
00516 _giraffe_cube_delete(self);
00517 }
00518
00519 return;
00520
00521 }
00522
00523
00537 cxsize
00538 giraffe_cube_get_width(const GiCube* self)
00539 {
00540
00541 cx_assert(self != NULL);
00542 return self->width;
00543
00544 }
00545
00546
00560 cxsize
00561 giraffe_cube_get_height(const GiCube* self)
00562 {
00563
00564 cx_assert(self != NULL);
00565 return self->height;
00566
00567 }
00568
00569
00583 cxsize
00584 giraffe_cube_get_depth(const GiCube* self)
00585 {
00586
00587 cx_assert(self != NULL);
00588 return self->depth;
00589
00590 }
00591
00592
00606 cxsize
00607 giraffe_cube_get_size(const GiCube* self)
00608 {
00609
00610 cx_assert(self != NULL);
00611 return self->size;
00612
00613 }
00614
00615
00634 cxint
00635 giraffe_cube_set_size(GiCube* self, cxsize width, cxsize height, cxsize depth)
00636 {
00637
00638 const cxchar* const _id = "giraffe_cube_set_size";
00639
00640
00641 cx_assert(self != NULL);
00642
00643 if ((width == 0) || (height == 0) || (depth == 0)) {
00644 cpl_error_set(_id, CPL_ERROR_ILLEGAL_INPUT);
00645 return 1;
00646 }
00647
00648 if ((self->width == width) && (self->height == height) &&
00649 (self->depth == depth)) {
00650 memset(self->pixels, 0, self->size * sizeof(cxdouble));
00651 }
00652 else {
00653
00654
00655
00656
00657
00658 if (self->planes != NULL) {
00659 _giraffe_cube_clear_planes(self);
00660 }
00661
00662 if (self->pixels != NULL) {
00663 cx_free(self->pixels);
00664 }
00665
00666
00667
00668
00669
00670
00671 _giraffe_cube_set_size(self, width, height, depth);
00672
00673
00674
00675
00676
00677
00678
00679 self->pixels = cx_calloc(self->size, sizeof(cxdouble));
00680 cx_assert(self->pixels);
00681
00682
00683 giraffe_error_push();
00684
00685 _giraffe_cube_init_planes(self);
00686
00687 if (cpl_error_get_code() != CPL_ERROR_NONE) {
00688 return 1;
00689 }
00690
00691 giraffe_error_pop();
00692
00693 }
00694
00695 return 0;
00696
00697 }
00698
00699
00714 cxdouble*
00715 giraffe_cube_get_data(const GiCube* self)
00716 {
00717
00718 const cxchar* const _id = "giraffe_cube_get_data";
00719
00720
00721 if (self == NULL) {
00722 cpl_error_set(_id, CPL_ERROR_NULL_INPUT);
00723 return 0;
00724 }
00725
00726 return self->pixels;
00727
00728 }
00729
00730
00745 cxbool
00746 giraffe_cube_has_xaxis(const GiCube* self)
00747 {
00748 return _giraffe_cube_has_axis(self, GICUBE_X);
00749 }
00750
00751
00766 cxbool
00767 giraffe_cube_has_yaxis(const GiCube* self)
00768 {
00769 return _giraffe_cube_has_axis(self, GICUBE_Y);
00770 }
00771
00772
00787 cxbool
00788 giraffe_cube_has_zaxis(const GiCube* self)
00789 {
00790 return _giraffe_cube_has_axis(self, GICUBE_Z);
00791 }
00792
00793
00808 cxbool
00809 giraffe_cube_has_wcs(const GiCube* self)
00810 {
00811 return self->wcs != NULL;
00812 }
00813
00814
00835 cxint
00836 giraffe_cube_get_xaxis(const GiCube* self, cxdouble* start, cxdouble* step)
00837 {
00838
00839 cx_assert(self != NULL);
00840
00841 return _giraffe_cube_get_axis(self, GICUBE_X, start, step);
00842
00843 }
00844
00845
00866 cxint
00867 giraffe_cube_get_yaxis(const GiCube* self, cxdouble* start, cxdouble* step)
00868 {
00869
00870 cx_assert(self != NULL);
00871
00872 return _giraffe_cube_get_axis(self, GICUBE_Y, start, step);
00873
00874 }
00875
00876
00897 cxint
00898 giraffe_cube_get_zaxis(const GiCube* self, cxdouble* start, cxdouble* step)
00899 {
00900
00901 cx_assert(self != NULL);
00902
00903 return _giraffe_cube_get_axis(self, GICUBE_Z, start, step);
00904
00905 }
00906
00907
00923 cxint
00924 giraffe_cube_set_xaxis(GiCube* self, cxdouble start, cxdouble step)
00925 {
00926
00927 cx_assert(self != NULL);
00928
00929 return _giraffe_cube_set_axis(self, GICUBE_X, start, step);
00930
00931 }
00932
00933
00949 cxint
00950 giraffe_cube_set_yaxis(GiCube* self, cxdouble start, cxdouble step)
00951 {
00952
00953 cx_assert(self != NULL);
00954
00955 return _giraffe_cube_set_axis(self, GICUBE_Y, start, step);
00956
00957 }
00958
00959
00975 cxint
00976 giraffe_cube_set_zaxis(GiCube* self, cxdouble start, cxdouble step)
00977 {
00978
00979 cx_assert(self != NULL);
00980
00981 return _giraffe_cube_set_axis(self, GICUBE_Z, start, step);
00982
00983 }
00984
00985
01000 void
01001 giraffe_cube_clear_wcs(GiCube* self)
01002 {
01003
01004 if (self->wcs != NULL) {
01005 _giraffe_cube_clear_wcs(self);
01006 }
01007
01008 return;
01009
01010 }
01011
01012
01039 cxint
01040 giraffe_cube_set_wcs(GiCube* self, const cpl_propertylist* axes,
01041 const cpl_matrix* transformation)
01042 {
01043
01044 cx_assert(self != NULL);
01045
01046 if ((axes == NULL) || (transformation == NULL)) {
01047 return -1;
01048 }
01049
01050 if ((cpl_matrix_get_nrow(transformation) != GICUBE_AXES) ||
01051 (cpl_matrix_get_ncol(transformation) != GICUBE_AXES)) {
01052 return 3;
01053 }
01054
01055 if ((cpl_propertylist_has(axes, "XORIGIN") == FALSE) ||
01056 (cpl_propertylist_has(axes, "YORIGIN") == FALSE) ||
01057 (cpl_propertylist_has(axes, "ZORIGIN") == FALSE)) {
01058 return 2;
01059 }
01060
01061 if ((cpl_propertylist_has(axes, "XPOINT") == FALSE) ||
01062 (cpl_propertylist_has(axes, "YPOINT") == FALSE) ||
01063 (cpl_propertylist_has(axes, "ZPOINT") == FALSE)) {
01064 return 2;
01065 }
01066
01067 if ((cpl_propertylist_has(axes, "XTYPE") == FALSE) ||
01068 (cpl_propertylist_has(axes, "YTYPE") == FALSE) ||
01069 (cpl_propertylist_has(axes, "ZTYPE") == FALSE)) {
01070 return 2;
01071 }
01072
01073 if ((cpl_propertylist_has(axes, "XUNIT") == FALSE) ||
01074 (cpl_propertylist_has(axes, "YUNIT") == FALSE) ||
01075 (cpl_propertylist_has(axes, "ZUNIT") == FALSE)) {
01076 return 2;
01077 }
01078
01079 _giraffe_cube_set_wcs(self, axes, transformation);
01080
01081 return 1;
01082 }
01083
01084
01098 cxint
01099 giraffe_cube_sqrt(GiCube* self)
01100 {
01101
01102 cpl_error_code status = CPL_ERROR_NONE;
01103
01104
01105 if (self == NULL) {
01106 return -1;
01107 }
01108
01109 cx_assert(self->planes != NULL);
01110
01111 status = cpl_imagelist_power(self->planes, 0.5);
01112
01113 if (status != CPL_ERROR_NONE) {
01114 return 1;
01115 }
01116
01117 return 0;
01118
01119 }
01120
01121
01149 cpl_image*
01150 giraffe_cube_integrate(const GiCube* self, cxdouble start, cxdouble end)
01151 {
01152
01153 cxsize depth = 0;
01154 cxsize first = (cxsize)ceil(start);
01155 cxsize last = (cxsize)floor(end);
01156
01157 cpl_image* image = NULL;
01158
01159
01160 if (self == NULL) {
01161 return NULL;
01162 }
01163
01164 depth = giraffe_cube_get_depth(self);
01165
01166 if ((start >= end) || (start < 0.) || (end > depth)) {
01167 return NULL;
01168 }
01169
01170
01171 image = cpl_image_duplicate(cpl_imagelist_get(self->planes, first));
01172
01173 if (image != NULL) {
01174
01175 if (first == last) {
01176 cpl_image_multiply_scalar(image, (end - start));
01177 }
01178 else {
01179
01180 cxsize i = 0;
01181
01182 cxdouble fstart = first - start;
01183 cxdouble fend = end - last;
01184
01185
01186 for (i = first + 1; i < last; ++i) {
01187 cpl_image_add(image,
01188 cpl_imagelist_get_const(self->planes, i));
01189 }
01190
01191
01192
01193
01194
01195
01196
01197 if ((fstart > 0.) && (first > 0)) {
01198 cpl_image* tmp = cpl_imagelist_get(self->planes, first - 1);
01199
01200 tmp = cpl_image_multiply_scalar_create(tmp, fstart);
01201 cpl_image_add(image, tmp);
01202
01203 cpl_image_delete(tmp);
01204 tmp = NULL;
01205 }
01206
01207 if ((fend > 0.) && (last < depth)) {
01208 cpl_image* tmp = cpl_imagelist_get(self->planes, last);
01209
01210 tmp = cpl_image_multiply_scalar_create(tmp, fend);
01211 cpl_image_add(image, tmp);
01212
01213 cpl_image_delete(tmp);
01214 tmp = NULL;
01215 }
01216
01217 }
01218
01219 }
01220
01221 return image;
01222
01223 }
01224
01225
01243 cxint
01244 giraffe_cube_save(const GiCube* self, cpl_propertylist* properties,
01245 const cxchar* filename, cxcptr data)
01246 {
01247
01248 cxbool xaxis = FALSE;
01249 cxbool yaxis = FALSE;
01250 cxbool zaxis = FALSE;
01251
01252 cxdouble xstart = 0.;
01253 cxdouble xstep = 0.;
01254 cxdouble ystart = 0.;
01255 cxdouble ystep = 0.;
01256 cxdouble zstart = 0.;
01257 cxdouble zstep = 0.;
01258
01259 cxuint iomode = CPL_IO_CREATE;
01260
01261
01262 if (properties == NULL || filename == NULL) {
01263 return -1;
01264 }
01265
01266
01267
01268
01269
01270
01271 if (data != NULL) {
01272 iomode = *((cxuint*)data);
01273 }
01274
01275
01276 if (self == NULL) {
01277
01278
01279
01280
01281
01282
01283
01284
01285 if (iomode != CPL_IO_CREATE) {
01286 return -2;
01287 }
01288
01289 giraffe_error_push();
01290
01291 cpl_propertylist_erase_regexp(properties, "CRVAL[0-9]*", 0);
01292 cpl_propertylist_erase_regexp(properties, "CRPIX[0-9]*", 0);
01293 cpl_propertylist_erase_regexp(properties, "CDELT[0-9]*", 0);
01294 cpl_propertylist_erase_regexp(properties, "CTYPE[0-9]*", 0);
01295 cpl_propertylist_erase_regexp(properties, "CUNIT[0-9]*", 0);
01296
01297 cpl_propertylist_erase(properties, GIALIAS_BUNIT);
01298
01299 cpl_propertylist_erase(properties, "DATAMIN");
01300 cpl_propertylist_erase(properties, "DATAMAX");
01301
01302 cpl_propertylist_erase(properties, GIALIAS_DATAMEAN);
01303 cpl_propertylist_erase(properties, GIALIAS_DATAMEDI);
01304 cpl_propertylist_erase(properties, GIALIAS_DATASIG);
01305
01306 cpl_propertylist_save(properties, filename, iomode);
01307
01308 if (cpl_error_get_code() != CPL_ERROR_NONE) {
01309 return 1;
01310 }
01311
01312 giraffe_error_pop();
01313
01314 }
01315 else {
01316
01317 cxsize size = 0;
01318
01319 const cpl_array* pixels = NULL;
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331 if (giraffe_cube_get_xaxis(self, &xstart, &xstep) == 0) {
01332 xaxis = TRUE;
01333 }
01334
01335 if (giraffe_cube_get_yaxis(self, &ystart, &ystep) == 0) {
01336 yaxis = TRUE;
01337 }
01338
01339 if (giraffe_cube_get_zaxis(self, &zstart, &zstep) == 0) {
01340 zaxis = TRUE;
01341 }
01342
01343
01344 if (giraffe_cube_has_wcs(self) == TRUE) {
01345
01346 const cxchar* ctype[GICUBE_AXES];
01347 const cxchar* cunit[GICUBE_AXES];
01348
01349 cxint status = 0;
01350
01351 cxdouble crpix[GICUBE_AXES];
01352 cxdouble crval[GICUBE_AXES];
01353
01354 const cpl_matrix* cd = _giraffe_cube_get_wcs_transform(self);
01355
01356
01357 crpix[GICUBE_X] = _giraffe_cube_get_wcs_origin(self, GICUBE_X);
01358 crpix[GICUBE_Y] = _giraffe_cube_get_wcs_origin(self, GICUBE_Y);
01359 crpix[GICUBE_Z] = _giraffe_cube_get_wcs_origin(self, GICUBE_Z);
01360
01361 crval[GICUBE_X] = _giraffe_cube_get_wcs_point(self, GICUBE_X);
01362 crval[GICUBE_Y] = _giraffe_cube_get_wcs_point(self, GICUBE_Y);
01363 crval[GICUBE_Z] = _giraffe_cube_get_wcs_point(self, GICUBE_Z);
01364
01365 ctype[GICUBE_X] = _giraffe_cube_get_wcs_axistype(self, GICUBE_X);
01366 ctype[GICUBE_Y] = _giraffe_cube_get_wcs_axistype(self, GICUBE_Y);
01367 ctype[GICUBE_Z] = _giraffe_cube_get_wcs_axistype(self, GICUBE_Z);
01368
01369 cunit[GICUBE_X] = _giraffe_cube_get_wcs_axisunit(self, GICUBE_X);
01370 cunit[GICUBE_Y] = _giraffe_cube_get_wcs_axisunit(self, GICUBE_Y);
01371 cunit[GICUBE_Z] = _giraffe_cube_get_wcs_axisunit(self, GICUBE_Z);
01372
01373 status = giraffe_propertylist_update_wcs(properties, GICUBE_AXES,
01374 crpix, crval, ctype, cunit,
01375 cd);
01376
01377 if (status != 0) {
01378 giraffe_propertylist_update_wcs(properties, 0, NULL, NULL, NULL,
01379 NULL, NULL);
01380 }
01381
01382 }
01383 else if ((xaxis == TRUE) && (yaxis == TRUE) && (zaxis == TRUE)) {
01384
01385 const cxchar* ctype[] = {"PIXEL", "PIXEL", "AWAV"};
01386 const cxchar* cunit[] = {"bin", "bin", "nm"};
01387
01388 cxint status = 0;
01389
01390 cxdouble crpix[] = {1., 1., 1.};
01391 cxdouble crval[] = {xstart, ystart, zstart};
01392
01393 cpl_matrix* cd = cpl_matrix_new(3, 3);
01394
01395 cpl_matrix_set(cd, 0, 0, xstep);
01396 cpl_matrix_set(cd, 1, 1, ystep);
01397 cpl_matrix_set(cd, 2, 2, zstep);
01398
01399 status = giraffe_propertylist_update_wcs(properties, GICUBE_AXES,
01400 crpix, crval, ctype, cunit,
01401 cd);
01402
01403 if (status != 0) {
01404 giraffe_propertylist_update_wcs(properties, 0, NULL, NULL, NULL,
01405 NULL, NULL);
01406 }
01407
01408 cpl_matrix_delete(cd);
01409 cd = NULL;
01410
01411 }
01412 else {
01413
01414 giraffe_propertylist_update_wcs(properties, 0, NULL, NULL, NULL,
01415 NULL, NULL);
01416
01417 }
01418
01419
01420
01421
01422
01423
01424 giraffe_error_push();
01425
01426 size = giraffe_cube_get_size(self);
01427 pixels = cpl_array_wrap_double(giraffe_cube_get_data(self), size);
01428
01429
01430 cpl_propertylist_update_string(properties, GIALIAS_BUNIT,
01431 "adu");
01432
01433 cpl_propertylist_update_double(properties, GIALIAS_DATAMIN,
01434 cpl_array_get_min(pixels));
01435 cpl_propertylist_set_comment(properties, GIALIAS_DATAMIN,
01436 "Minimal pixel value");
01437
01438 cpl_propertylist_update_double(properties, GIALIAS_DATAMAX,
01439 cpl_array_get_max(pixels));
01440 cpl_propertylist_set_comment(properties, GIALIAS_DATAMAX,
01441 "Maximum pixel value");
01442
01443 cpl_propertylist_update_double(properties, GIALIAS_DATAMEAN,
01444 cpl_array_get_mean(pixels));
01445 cpl_propertylist_set_comment(properties, GIALIAS_DATAMEAN,
01446 "Mean of pixel values");
01447
01448 cpl_propertylist_update_double(properties, GIALIAS_DATASIG,
01449 cpl_array_get_stdev(pixels));
01450 cpl_propertylist_set_comment(properties, GIALIAS_DATASIG,
01451 "Standard deviation of pixel values");
01452
01453 cpl_propertylist_update_double(properties, GIALIAS_DATAMEDI,
01454 cpl_array_get_median(pixels));
01455 cpl_propertylist_set_comment(properties, GIALIAS_DATAMEDI,
01456 "Median of pixel values");
01457
01458 cpl_array_unwrap((cpl_array*)pixels);
01459 pixels = NULL;
01460
01461 if (cpl_error_get_code() != CPL_ERROR_NONE) {
01462 return 1;
01463 }
01464
01465 giraffe_error_pop();
01466
01467
01468
01469
01470
01471
01472 giraffe_error_push();
01473
01474 cpl_imagelist_save(self->planes, filename, CPL_BPP_IEEE_FLOAT,
01475 properties, iomode);
01476
01477 if (cpl_error_get_code() != CPL_ERROR_NONE) {
01478 return 1;
01479 }
01480
01481 giraffe_error_pop();
01482
01483 }
01484
01485 return 0;
01486
01487 }