GIRAFFE Pipeline Reference Manual

gicube.c

00001 /* $Id: gicube.c,v 1.3 2009/05/29 09:59:47 rpalsa Exp $
00002  *
00003  * This file is part of the GIRAFFE Pipeline
00004  * Copyright (C) 2002-2007 European Southern Observatory
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00019  */
00020 
00021 /*
00022  * $Author: rpalsa $
00023  * $Date: 2009/05/29 09:59:47 $
00024  * $Revision: 1.3 $
00025  * $Name: giraffe-2_9 $
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 
00038 #include <cpl_error.h>
00039 #include <cpl_array.h>
00040 #include <cpl_image.h>
00041 #include <cpl_imagelist.h>
00042 #include <cpl_propertylist.h>
00043 
00044 #include "gialias.h"
00045 #include "gierror.h"
00046 #include "gicube.h"
00047 #include "giutils.h"
00048 
00049 
00058 enum GiCubeAxes {
00059     GICUBE_X = 0,
00060     GICUBE_Y = 1,
00061     GICUBE_Z = 2,
00062     GICUBE_AXES
00063 };
00064 
00065 typedef enum GiCubeAxes GiCubeAxes;
00066 
00067 
00068 struct GiCubeAxis {
00069     cxdouble start;
00070     cxdouble step;
00071 };
00072 
00073 typedef struct GiCubeAxis GiCubeAxis;
00074 
00075 
00076 struct GiCube {
00077     cxsize width;
00078     cxsize height;
00079     cxsize depth;
00080     cxsize size;
00081 
00082     GiCubeAxis* axes[GICUBE_AXES];
00083 
00084     cxdouble* pixels;
00085 
00086     cpl_imagelist* planes;
00087 };
00088 
00089 
00090 inline static void
00091 _giraffe_cube_set_size(GiCube* self, cxsize width, cxsize height,
00092                        cxsize depth)
00093 {
00094 
00095     self->width = width;
00096     self->height = height;
00097     self->depth = depth;
00098 
00099     self->size = self->width * self->height * self->depth;
00100 
00101     return;
00102 
00103 }
00104 
00105 
00106 inline static GiCube*
00107 _giraffe_cube_new(void)
00108 {
00109 
00110     GiCube* self = cx_malloc(sizeof *self);
00111 
00112 
00113     if (self != NULL) {
00114         _giraffe_cube_set_size(self, 0, 0, 0);
00115 
00116         self->axes[GICUBE_X] = NULL;
00117         self->axes[GICUBE_Y] = NULL;
00118         self->axes[GICUBE_Z] = NULL;
00119 
00120         self->pixels = NULL;
00121         self->planes = NULL;
00122     }
00123 
00124     return self;
00125 
00126 }
00127 
00128 
00129 inline static cxint
00130 _giraffe_cube_init_planes(GiCube* self)
00131 {
00132 
00133     register cxsize i = 0;
00134 
00135     register cxdouble* base = NULL;
00136 
00137 
00138     self->planes = cpl_imagelist_new();
00139     cx_assert(self->planes != NULL);
00140 
00141 
00142     base = self->pixels;
00143 
00144     for (i = 0; i < self->depth; i++) {
00145 
00146         cpl_image* plane = cpl_image_wrap_double(self->width, self->height,
00147                                                  base);
00148 
00149         cx_assert(plane != NULL);
00150         cpl_imagelist_set(self->planes, plane, i);
00151 
00152         base += self->width * self->height;
00153 
00154     }
00155 
00156     return 0;
00157 
00158 }
00159 
00160 
00161 inline static void
00162 _giraffe_cube_clear_planes(GiCube* self)
00163 {
00164 
00165     register cxsize i = 0;
00166 
00167 
00168     for (i = 0; i < self->depth; i++) {
00169 
00170         cpl_image* plane = cpl_imagelist_unset(self->planes, 0);
00171 
00172         cpl_image_unwrap(plane);
00173 
00174     }
00175 
00176     cx_assert(cpl_imagelist_get_size(self->planes) == 0);
00177 
00178     cpl_imagelist_delete(self->planes);
00179     self->planes =NULL;
00180 
00181     return;
00182 
00183 }
00184 
00185 
00186 inline static void
00187 _giraffe_cube_delete(GiCube* self)
00188 {
00189 
00190     register cxint i = 0;
00191 
00192     for (i = 0; i < GICUBE_AXES; i++) {
00193         if (self->axes[i] != NULL) {
00194             cx_free(self->axes[i]);
00195             self->axes[i] = NULL;
00196         }
00197     }
00198 
00199     if (self->planes != NULL) {
00200         _giraffe_cube_clear_planes(self);
00201         self->planes = NULL;
00202     }
00203 
00204     if (self->pixels != NULL) {
00205         cx_free(self->pixels);
00206         self->pixels = NULL;
00207     }
00208 
00209     cx_free(self);
00210 
00211     return;
00212 
00213 }
00214 
00215 
00216 inline static cxbool
00217 _giraffe_cube_has_axis(const GiCube* self, GiCubeAxes axis)
00218 {
00219     return (self->axes[axis] == NULL) ? FALSE : TRUE;
00220 }
00221 
00222 
00223 inline static cxint
00224 _giraffe_cube_get_axis(const GiCube* self, GiCubeAxes axis, cxdouble* start,
00225                        cxdouble* step)
00226 {
00227 
00228     if (self->axes[axis] == NULL) {
00229         return 1;
00230     }
00231     else {
00232 
00233         if (start != NULL) {
00234             *start = self->axes[axis]->start;
00235         }
00236 
00237         if (step != NULL) {
00238             *step = self->axes[axis]->step;
00239         }
00240 
00241     }
00242 
00243     return 0;
00244 
00245 }
00246 
00247 
00248 inline static cxint
00249 _giraffe_cube_set_axis(GiCube* self, GiCubeAxes axis, cxdouble start,
00250                        cxdouble step)
00251 {
00252 
00253     if (self->axes[axis] == NULL) {
00254         self->axes[axis] = cx_calloc(1, sizeof(GiCubeAxis));
00255     }
00256 
00257     cx_assert(self->axes[axis] != NULL);
00258 
00259     self->axes[axis]->start = start;
00260     self->axes[axis]->step = step;
00261 
00262     return 0;
00263 
00264 }
00265 
00266 
00279 GiCube*
00280 giraffe_cube_new(void)
00281 {
00282 
00283     return _giraffe_cube_new();
00284 
00285 }
00286 
00287 
00314 GiCube*
00315 giraffe_cube_create(cxsize width, cxsize height, cxsize depth, cxdouble* data)
00316 {
00317 
00318     GiCube* self = _giraffe_cube_new();
00319 
00320 
00321     _giraffe_cube_set_size(self, width, height, depth);
00322 
00323     if (self->size == 0) {
00324         _giraffe_cube_delete(self);
00325         return NULL;
00326     }
00327 
00328     if (data != NULL) {
00329         self->pixels = data;
00330     }
00331     else {
00332         self->pixels = cx_calloc(self->size, sizeof(cxdouble));
00333     }
00334 
00335     cx_assert(self->pixels != NULL);
00336 
00337 
00338     /*
00339      * Create the image list object for accessing the cube plane by plane.
00340      * It is also needed (for the time being) to save a cube to disk.
00341      */
00342 
00343     giraffe_error_push();
00344 
00345     _giraffe_cube_init_planes(self);
00346 
00347     if (cpl_error_get_code() != CPL_ERROR_NONE) {
00348         _giraffe_cube_delete(self);
00349         return NULL;
00350     }
00351 
00352     giraffe_error_pop();
00353 
00354     return self;
00355 
00356 }
00357 
00358 
00371 void
00372 giraffe_cube_delete(GiCube* self)
00373 {
00374 
00375     if (self != NULL) {
00376         _giraffe_cube_delete(self);
00377     }
00378 
00379     return;
00380 
00381 }
00382 
00383 
00397 cxsize
00398 giraffe_cube_get_width(const GiCube* self)
00399 {
00400 
00401     cx_assert(self != NULL);
00402     return self->width;
00403 
00404 }
00405 
00406 
00420 cxsize
00421 giraffe_cube_get_height(const GiCube* self)
00422 {
00423 
00424     cx_assert(self != NULL);
00425     return self->height;
00426 
00427 }
00428 
00429 
00443 cxsize
00444 giraffe_cube_get_depth(const GiCube* self)
00445 {
00446 
00447     cx_assert(self != NULL);
00448     return self->depth;
00449 
00450 }
00451 
00452 
00466 cxsize
00467 giraffe_cube_get_size(const GiCube* self)
00468 {
00469 
00470     cx_assert(self != NULL);
00471     return self->size;
00472 
00473 }
00474 
00475 
00494 cxint
00495 giraffe_cube_set_size(GiCube* self, cxsize width, cxsize height, cxsize depth)
00496 {
00497 
00498     const cxchar* const _id = "giraffe_cube_set_size";
00499 
00500 
00501     cx_assert(self != NULL);
00502 
00503     if ((width == 0) || (height == 0) || (depth == 0)) {
00504         cpl_error_set(_id, CPL_ERROR_ILLEGAL_INPUT);
00505         return 1;
00506     }
00507 
00508     if ((self->width == width) && (self->height == height) &&
00509         (self->depth == depth)) {
00510         memset(self->pixels, 0, self->size * sizeof(cxdouble));
00511     }
00512     else {
00513 
00514         /*
00515          * Clear the list of planes and destroy the old pixel buffer
00516          */
00517 
00518         if (self->planes != NULL) {
00519             _giraffe_cube_clear_planes(self);
00520         }
00521 
00522         if (self->pixels != NULL) {
00523             cx_free(self->pixels);
00524         }
00525 
00526 
00527         /*
00528          * Set the new sizes
00529          */
00530 
00531         _giraffe_cube_set_size(self, width, height, depth);
00532 
00533 
00534         /*
00535          * Re-create the pixel buffer and the list of planes from the updated
00536          * size specifications.
00537          */
00538 
00539         self->pixels = cx_calloc(self->size, sizeof(cxdouble));
00540         cx_assert(self->pixels);
00541 
00542 
00543         giraffe_error_push();
00544 
00545         _giraffe_cube_init_planes(self);
00546 
00547         if (cpl_error_get_code() != CPL_ERROR_NONE) {
00548             return 1;
00549         }
00550 
00551         giraffe_error_pop();
00552 
00553     }
00554 
00555     return 0;
00556 
00557 }
00558 
00559 
00574 cxdouble*
00575 giraffe_cube_get_data(const GiCube* self)
00576 {
00577 
00578     const cxchar* const _id = "giraffe_cube_get_data";
00579 
00580 
00581     if (self == NULL) {
00582         cpl_error_set(_id, CPL_ERROR_NULL_INPUT);
00583         return 0;
00584     }
00585 
00586     return self->pixels;
00587 
00588 }
00589 
00590 
00605 cxbool
00606 giraffe_cube_has_xaxis(const GiCube* self)
00607 {
00608     return _giraffe_cube_has_axis(self, GICUBE_X);
00609 }
00610 
00611 
00626 cxbool
00627 giraffe_cube_has_yaxis(const GiCube* self)
00628 {
00629     return _giraffe_cube_has_axis(self, GICUBE_Y);
00630 }
00631 
00632 
00647 cxbool
00648 giraffe_cube_has_zaxis(const GiCube* self)
00649 {
00650     return _giraffe_cube_has_axis(self, GICUBE_Z);
00651 }
00652 
00653 
00674 cxint
00675 giraffe_cube_get_xaxis(const GiCube* self, cxdouble* start, cxdouble* step)
00676 {
00677 
00678     cx_assert(self != NULL);
00679 
00680     return _giraffe_cube_get_axis(self, GICUBE_X, start, step);
00681 
00682 }
00683 
00684 
00705 cxint
00706 giraffe_cube_get_yaxis(const GiCube* self, cxdouble* start, cxdouble* step)
00707 {
00708 
00709     cx_assert(self != NULL);
00710 
00711     return _giraffe_cube_get_axis(self, GICUBE_Y, start, step);
00712 
00713 }
00714 
00715 
00736 cxint
00737 giraffe_cube_get_zaxis(const GiCube* self, cxdouble* start, cxdouble* step)
00738 {
00739 
00740     cx_assert(self != NULL);
00741 
00742     return _giraffe_cube_get_axis(self, GICUBE_Z, start, step);
00743 
00744 }
00745 
00746 
00762 cxint
00763 giraffe_cube_set_xaxis(GiCube* self, cxdouble start, cxdouble step)
00764 {
00765 
00766     cx_assert(self != NULL);
00767 
00768     return _giraffe_cube_set_axis(self, GICUBE_X, start, step);
00769 
00770 }
00771 
00772 
00788 cxint
00789 giraffe_cube_set_yaxis(GiCube* self, cxdouble start, cxdouble step)
00790 {
00791 
00792     cx_assert(self != NULL);
00793 
00794     return _giraffe_cube_set_axis(self, GICUBE_Y, start, step);
00795 
00796 }
00797 
00798 
00814 cxint
00815 giraffe_cube_set_zaxis(GiCube* self, cxdouble start, cxdouble step)
00816 {
00817 
00818     cx_assert(self != NULL);
00819 
00820     return _giraffe_cube_set_axis(self, GICUBE_Z, start, step);
00821 
00822 }
00823 
00824 
00838 cxint
00839 giraffe_cube_sqrt(GiCube* self)
00840 {
00841 
00842     cpl_error_code status = CPL_ERROR_NONE;
00843 
00844 
00845     if (self == NULL) {
00846         return -1;
00847     }
00848 
00849     cx_assert(self->planes != NULL);
00850 
00851     status = cpl_imagelist_power(self->planes, 0.5);
00852 
00853     if (status != CPL_ERROR_NONE) {
00854         return 1;
00855     }
00856 
00857     return 0;
00858 
00859 }
00860 
00861 
00889 cpl_image*
00890 giraffe_cube_integrate(const GiCube* self, cxdouble start, cxdouble end)
00891 {
00892 
00893     cxsize depth = 0;
00894     cxsize first = (cxsize)ceil(start);
00895     cxsize last  = (cxsize)floor(end);
00896 
00897     cpl_image* image = NULL;
00898 
00899 
00900     if (self == NULL) {
00901         return NULL;
00902     }
00903 
00904     depth = giraffe_cube_get_depth(self);
00905 
00906     if ((start >= end) || (start < 0.) || (end > depth)) {
00907         return NULL;
00908     }
00909 
00910 
00911     image = cpl_image_duplicate(cpl_imagelist_get(self->planes, first));
00912 
00913     if (image != NULL) {
00914 
00915         if (first == last) {
00916             cpl_image_multiply_scalar(image, (end - start));
00917         }
00918         else {
00919 
00920             cxsize i = 0;
00921 
00922             cxdouble fstart = first - start;
00923             cxdouble fend   = end - last;
00924 
00925 
00926             for (i = first + 1; i < last; ++i) {
00927                 cpl_image_add(image,
00928                               cpl_imagelist_get_const(self->planes, i));
00929             }
00930 
00931 
00932             /*
00933              * Correct for the pixel fractions at both ends of the
00934              * integration domain.
00935              */
00936 
00937             if ((fstart > 0.) && (first > 0)) {
00938                 cpl_image* tmp = cpl_imagelist_get(self->planes, first - 1);
00939 
00940                 tmp = cpl_image_multiply_scalar_create(tmp, fstart);
00941                 cpl_image_add(image, tmp);
00942 
00943                 cpl_image_delete(tmp);
00944                 tmp = NULL;
00945             }
00946 
00947             if ((fend > 0.) && (last < depth)) {
00948                 cpl_image* tmp = cpl_imagelist_get(self->planes, last);
00949 
00950                 tmp = cpl_image_multiply_scalar_create(tmp, fend);
00951                 cpl_image_add(image, tmp);
00952 
00953                 cpl_image_delete(tmp);
00954                 tmp = NULL;
00955             }
00956 
00957         }
00958 
00959     }
00960 
00961     return image;
00962 
00963 }
00964 
00965 
00983 cxint
00984 giraffe_cube_save(const GiCube* self, cpl_propertylist* properties,
00985                   const cxchar* filename, cxcptr data)
00986 {
00987 
00988     cxbool xaxis = FALSE;
00989     cxbool yaxis = FALSE;
00990     cxbool zaxis = FALSE;
00991 
00992     cxdouble xstart = 0.;
00993     cxdouble xstep  = 0.;
00994     cxdouble ystart = 0.;
00995     cxdouble ystep  = 0.;
00996     cxdouble zstart = 0.;
00997     cxdouble zstep  = 0.;
00998 
00999     cxuint iomode = CPL_IO_CREATE;
01000 
01001 
01002     if (properties == NULL || filename == NULL) {
01003         return -1;
01004     }
01005 
01006 
01007     /*
01008      * If present use the cube writer configuration
01009      */
01010 
01011     if (data != NULL) {
01012         iomode = *((cxuint*)data);
01013     }
01014 
01015 
01016     if (self == NULL) {
01017 
01018         /*
01019          * If no cube has been provided, but properties and a filename
01020          * were given and empty cube is written to the file. Currently
01021          * this is restricted to creating a new cube file, to avoid
01022          * turning the property list into a valid extension header.
01023          */
01024 
01025         if (iomode != CPL_IO_CREATE) {
01026             return -2;
01027         }
01028 
01029         giraffe_error_push();
01030 
01031         cpl_propertylist_erase_regexp(properties, "CRVAL[0-9]*", 0);
01032         cpl_propertylist_erase_regexp(properties, "CRPIX[0-9]*", 0);
01033         cpl_propertylist_erase_regexp(properties, "CDELT[0-9]*", 0);
01034         cpl_propertylist_erase_regexp(properties, "CTYPE[0-9]*", 0);
01035 
01036         cpl_propertylist_erase(properties, "DATAMIN");
01037         cpl_propertylist_erase(properties, "DATAMAX");
01038 
01039         cpl_propertylist_erase(properties, GIALIAS_DATAMEAN);
01040         cpl_propertylist_erase(properties, GIALIAS_DATAMEDI);
01041         cpl_propertylist_erase(properties, GIALIAS_DATASIG);
01042 
01043         cpl_propertylist_save(properties, filename, iomode);
01044 
01045         if (cpl_error_get_code() != CPL_ERROR_NONE) {
01046             return 1;
01047         }
01048 
01049         giraffe_error_pop();
01050 
01051     }
01052     else {
01053 
01054         cxsize size = 0;
01055 
01056         const cpl_array* pixels = NULL;
01057 
01058 
01059         /*
01060          * Update the data cube's properties. The world coordinates are only
01061          * written if the information is present for all three axes.
01062          */
01063 
01064         if (giraffe_cube_get_xaxis(self, &xstart, &xstep) == 0) {
01065             xaxis = TRUE;
01066         }
01067 
01068         if (giraffe_cube_get_yaxis(self, &ystart, &ystep) == 0) {
01069             yaxis = TRUE;
01070         }
01071 
01072         if (giraffe_cube_get_zaxis(self, &zstart, &zstep) == 0) {
01073             zaxis = TRUE;
01074         }
01075 
01076 
01077         if ((xaxis == TRUE) && (yaxis == TRUE) && (zaxis == TRUE)) {
01078 
01079             const cxchar* ctype[] = {"PIXEL", "PIXEL", "WAVE"};
01080             const cxchar* cunit[] = {"pixel", "pixel", "nm"};
01081 
01082             cxint status = 0;
01083 
01084             cxdouble crpix[] = {1., 1., 1.};
01085             cxdouble crval[] = {xstart, ystart, zstart};
01086 
01087             cpl_matrix* cd = cpl_matrix_new(3, 3);
01088 
01089             cpl_matrix_set(cd, 0, 0, xstep);
01090             cpl_matrix_set(cd, 1, 1, ystep);
01091             cpl_matrix_set(cd, 2, 2, zstep);
01092 
01093             status = giraffe_propertylist_update_wcs(properties, 3, crpix, crval,
01094                                                      ctype, cunit, cd);
01095 
01096             if (status != 0) {
01097                 giraffe_propertylist_update_wcs(properties, 0, NULL, NULL, NULL,
01098                                                 NULL, NULL);
01099             }
01100 
01101             cpl_matrix_delete(cd);
01102             cd = NULL;
01103 
01104         }
01105         else {
01106 
01107             giraffe_propertylist_update_wcs(properties, 0, NULL, NULL, NULL,
01108                                             NULL, NULL);
01109 
01110         }
01111 
01112 
01113         /*
01114          * Update data properties
01115          */
01116 
01117         giraffe_error_push();
01118 
01119         size = giraffe_cube_get_size(self);
01120         pixels = cpl_array_wrap_double(giraffe_cube_get_data(self), size);
01121 
01122 
01123         cpl_propertylist_update_double(properties, GIALIAS_DATAMIN,
01124                                        cpl_array_get_min(pixels));
01125         cpl_propertylist_set_comment(properties, GIALIAS_DATAMIN,
01126                                      "Minimal pixel value");
01127 
01128         cpl_propertylist_update_double(properties, GIALIAS_DATAMAX,
01129                                        cpl_array_get_max(pixels));
01130         cpl_propertylist_set_comment(properties, GIALIAS_DATAMAX,
01131                                      "Maximum pixel value");
01132 
01133         cpl_propertylist_update_double(properties, GIALIAS_DATAMEAN,
01134                                        cpl_array_get_mean(pixels));
01135         cpl_propertylist_set_comment(properties, GIALIAS_DATAMEAN,
01136                                      "Mean of pixel values");
01137 
01138         cpl_propertylist_update_double(properties, GIALIAS_DATASIG,
01139                                        cpl_array_get_stdev(pixels));
01140         cpl_propertylist_set_comment(properties, GIALIAS_DATASIG,
01141                                      "Standard deviation of pixel values");
01142 
01143         cpl_propertylist_update_double(properties, GIALIAS_DATAMEDI,
01144                                        cpl_array_get_median(pixels));
01145         cpl_propertylist_set_comment(properties, GIALIAS_DATAMEDI,
01146                                      "Median of pixel values");
01147 
01148         cpl_array_unwrap((cpl_array*)pixels);
01149         pixels = NULL;
01150 
01151         if (cpl_error_get_code() != CPL_ERROR_NONE) {
01152             return 1;
01153         }
01154 
01155         giraffe_error_pop();
01156 
01157 
01158         /*
01159          * Write the data cube to the output file
01160          */
01161 
01162         giraffe_error_push();
01163 
01164         cpl_imagelist_save(self->planes, filename, CPL_BPP_IEEE_FLOAT,
01165                            properties, iomode);
01166 
01167         if (cpl_error_get_code() != CPL_ERROR_NONE) {
01168             return 1;
01169         }
01170 
01171         giraffe_error_pop();
01172 
01173     }
01174 
01175     return 0;
01176 
01177 }

This file is part of the GIRAFFE Pipeline Reference Manual 2.9.0.
Documentation copyright © 2002-2006 European Southern Observatory.
Generated on Thu Jan 26 14:20:27 2012 by doxygen 1.6.3 written by Dimitri van Heesch, © 1997-2004