/* $Id: cpl_stats.c,v 1.30 2007/07/17 13:54:22 llundin Exp $ * * This file is part of the ESO Common Pipeline Library * Copyright (C) 2001-2004 European Southern Observatory * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * $Author: llundin $ * $Date: 2007/07/17 13:54:22 $ * $Revision: 1.30 $ * $Name: $ */ #ifdef HAVE_CONFIG_H #include #endif /*----------------------------------------------------------------------------- Includes -----------------------------------------------------------------------------*/ #include #include #include #include #include #include #include #include "cpl_memory.h" #include "cpl_stats.h" #include "cpl_image_bpm.h" #include "cpl_image_stats.h" #include "cpl_mask.h" #include "cpl_tools.h" #include "cpl_image_defs.h" /*----------------------------------------------------------------------------- Defines -----------------------------------------------------------------------------*/ #define CPL_IMAGE_STATS_MINMAX 1 #define CPL_IMAGE_STATS_MEAN 2 #define CPL_IMAGE_STATS_MEANMINMAX 3 #define CPL_IMAGE_STATS_VARIANCE 4 #define CPL_IMAGE_STATS_CENTROID 5 /*----------------------------------------------------------------------------*/ /** * @defgroup cpl_stats Statistics * * This module provides functions to handle the cpl_stats object. * This object can contain the statistics that have been computed from * different CPL objects. Currently, only the function that computes * statistics on images (or images windows) is provided. * * @par Synopsis: * @code * #include "cpl_stats.h" * @endcode */ /*----------------------------------------------------------------------------*/ /**@{*/ /*----------------------------------------------------------------------------- Type definition -----------------------------------------------------------------------------*/ struct _cpl_stats_ { double min ; double max ; double mean ; double med ; double stdev ; double flux ; double absflux ; double sqflux ; double xcentroid ; double ycentroid ; int min_x ; int min_y ; int max_x ; int max_y ; int npix ; unsigned bitmask; } ; /*----------------------------------------------------------------------------- Function codes -----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/ /** @brief Get the minimum from a cpl_stats object @param in the cpl_stats object @return the minimum value The call that created the cpl_stats object must have determined the minimum value. In case of error, the #_cpl_error_code_ code is set, and the returned double is undefined. Possible #_cpl_error_code_ set in this function: - CPL_ERROR_NULL_INPUT if (one of) the input pointer(s) is NULL - CPL_ERROR_ILLEGAL_INPUT if the requested stat has not been computed in in */ /*----------------------------------------------------------------------------*/ double cpl_stats_get_min(const cpl_stats * in) { cpl_ensure(in!=NULL, CPL_ERROR_NULL_INPUT, 0.0) ; cpl_ensure(in->bitmask & (CPL_STATS_MIN | CPL_STATS_MINPOS), CPL_ERROR_ILLEGAL_INPUT, 0); return in->min ; } /*----------------------------------------------------------------------------*/ /** @brief Get the maximum from a cpl_stats object @param in the cpl_stats object @return the maximum value @see cpl_stats_get_min() */ /*----------------------------------------------------------------------------*/ double cpl_stats_get_max(const cpl_stats * in) { cpl_ensure(in!=NULL, CPL_ERROR_NULL_INPUT, 0.0) ; cpl_ensure(in->bitmask & (CPL_STATS_MAX | CPL_STATS_MAXPOS), CPL_ERROR_ILLEGAL_INPUT, 0); return in->max ; } /*----------------------------------------------------------------------------*/ /** @brief Get the mean from a cpl_stats object @param in the cpl_stats object @return the mean value @see cpl_stats_get_min() */ /*----------------------------------------------------------------------------*/ double cpl_stats_get_mean(const cpl_stats * in) { cpl_ensure(in!=NULL, CPL_ERROR_NULL_INPUT, 0.0) ; cpl_ensure(in->bitmask & CPL_STATS_MEAN, CPL_ERROR_ILLEGAL_INPUT, 0); return in->mean ; } /*----------------------------------------------------------------------------*/ /** @brief Get the median from a cpl_stats object @param in the cpl_stats object @return the median value @see cpl_stats_get_min() */ /*----------------------------------------------------------------------------*/ double cpl_stats_get_median(const cpl_stats * in) { cpl_ensure(in!=NULL, CPL_ERROR_NULL_INPUT, 0.0) ; cpl_ensure(in->bitmask & CPL_STATS_MEDIAN, CPL_ERROR_ILLEGAL_INPUT, 0); return in->med ; } /*----------------------------------------------------------------------------*/ /** @brief Get the std. dev. from a cpl_stats object @param in the cpl_stats object @return the standard deviation @see cpl_stats_get_min() */ /*----------------------------------------------------------------------------*/ double cpl_stats_get_stdev(const cpl_stats * in) { cpl_ensure(in!=NULL, CPL_ERROR_NULL_INPUT, -1) ; cpl_ensure(in->bitmask & CPL_STATS_STDEV, CPL_ERROR_ILLEGAL_INPUT, 0); return in->stdev ; } /*----------------------------------------------------------------------------*/ /** @brief Get the flux from a cpl_stats object @param in the cpl_stats object @return the flux @see cpl_stats_get_min() */ /*----------------------------------------------------------------------------*/ double cpl_stats_get_flux(const cpl_stats * in) { cpl_ensure(in!=NULL, CPL_ERROR_NULL_INPUT, 0.0) ; cpl_ensure(in->bitmask & CPL_STATS_FLUX, CPL_ERROR_ILLEGAL_INPUT, 0); return in->flux ; } /*----------------------------------------------------------------------------*/ /** @brief Get the absolute flux from a cpl_stats object @param in the cpl_stats object @return The absolute flux, or a negative number on error @see cpl_stats_get_min() */ /*----------------------------------------------------------------------------*/ double cpl_stats_get_absflux(const cpl_stats * in) { cpl_ensure(in!=NULL, CPL_ERROR_NULL_INPUT, -1) ; cpl_ensure(in->bitmask & CPL_STATS_ABSFLUX, CPL_ERROR_ILLEGAL_INPUT, -2); return in->absflux ; } /*----------------------------------------------------------------------------*/ /** @brief Get the sum of the squared values from a cpl_stats object @param in the cpl_stats object @return the square flux, or a negative number on error @see cpl_stats_get_min() */ /*----------------------------------------------------------------------------*/ double cpl_stats_get_sqflux(const cpl_stats * in) { cpl_ensure(in!=NULL, CPL_ERROR_NULL_INPUT, -1) ; cpl_ensure(in->bitmask & CPL_STATS_SQFLUX, CPL_ERROR_ILLEGAL_INPUT, -2); return in->sqflux ; } /*----------------------------------------------------------------------------*/ /** @brief Get the x centroid position from a cpl_stats object @param in the cpl_stats object @return the x centroid @see cpl_stats_get_min() */ /*----------------------------------------------------------------------------*/ double cpl_stats_get_centroid_x(const cpl_stats * in) { cpl_ensure(in!=NULL, CPL_ERROR_NULL_INPUT, 0.0) ; cpl_ensure(in->bitmask & CPL_STATS_CENTROID, CPL_ERROR_ILLEGAL_INPUT, 0); return in->xcentroid ; } /*----------------------------------------------------------------------------*/ /** @brief Get the y centroid position from a cpl_stats object @param in the cpl_stats object @return the y centroid @see cpl_stats_get_min() */ /*----------------------------------------------------------------------------*/ double cpl_stats_get_centroid_y(const cpl_stats * in) { cpl_ensure(in!=NULL, CPL_ERROR_NULL_INPUT, 0.0) ; cpl_ensure(in->bitmask & CPL_STATS_CENTROID, CPL_ERROR_ILLEGAL_INPUT, 0); return in->ycentroid ; } /*----------------------------------------------------------------------------*/ /** @brief Get the minimum x position from a cpl_stats object @param in the cpl_stats object @return the x position (1 for the first pixel), non-positive on error. Possible #_cpl_error_code_ set in this function: - CPL_ERROR_NULL_INPUT if (one of) the input pointer(s) is NULL */ /*----------------------------------------------------------------------------*/ int cpl_stats_get_min_x(const cpl_stats * in) { cpl_ensure(in!=NULL, CPL_ERROR_NULL_INPUT, -1) ; cpl_ensure(in->bitmask & (CPL_STATS_MIN | CPL_STATS_MINPOS), CPL_ERROR_ILLEGAL_INPUT, 0); return in->min_x ; } /*----------------------------------------------------------------------------*/ /** @brief Get the minimum y position from a cpl_stats object @param in the cpl_stats object @return the y position (1 for the first pixel), non-positive on error. Possible #_cpl_error_code_ set in this function: - CPL_ERROR_NULL_INPUT if (one of) the input pointer(s) is NULL */ /*----------------------------------------------------------------------------*/ int cpl_stats_get_min_y(const cpl_stats * in) { cpl_ensure(in!=NULL, CPL_ERROR_NULL_INPUT, -1) ; cpl_ensure(in->bitmask & (CPL_STATS_MIN | CPL_STATS_MINPOS), CPL_ERROR_ILLEGAL_INPUT, 0); return in->min_y ; } /*----------------------------------------------------------------------------*/ /** @brief Get the maximum x position from a cpl_stats object @param in the cpl_stats object @return the x position (1 for the first pixel), non-positive on error. Possible #_cpl_error_code_ set in this function: - CPL_ERROR_NULL_INPUT if (one of) the input pointer(s) is NULL */ /*----------------------------------------------------------------------------*/ int cpl_stats_get_max_x(const cpl_stats * in) { cpl_ensure(in!=NULL, CPL_ERROR_NULL_INPUT, -1) ; cpl_ensure(in->bitmask & (CPL_STATS_MAX | CPL_STATS_MAXPOS), CPL_ERROR_ILLEGAL_INPUT, 0); return in->max_x ; } /*----------------------------------------------------------------------------*/ /** @brief Get the maximum y position from a cpl_stats object @param in the cpl_stats object @return the y position (1 for the first pixel), non-positive on error. Possible #_cpl_error_code_ set in this function: - CPL_ERROR_NULL_INPUT if (one of) the input pointer(s) is NULL */ /*----------------------------------------------------------------------------*/ int cpl_stats_get_max_y(const cpl_stats * in) { cpl_ensure(in!=NULL, CPL_ERROR_NULL_INPUT, -1) ; cpl_ensure(in->bitmask & (CPL_STATS_MAX | CPL_STATS_MAXPOS), CPL_ERROR_ILLEGAL_INPUT, 0); return in->max_y ; } /*----------------------------------------------------------------------------*/ /** @brief Get the number of pixels from a cpl_stats object @param in the cpl_stats object @return the number of pixels, -1 in error case. The creation of a cpl_stats object always causes the number of pixels to be determined. Possible #_cpl_error_code_ set in this function: - CPL_ERROR_NULL_INPUT if (one of) the input pointer(s) is NULL */ /*----------------------------------------------------------------------------*/ int cpl_stats_get_npix(const cpl_stats * in) { cpl_ensure(in!=NULL, CPL_ERROR_NULL_INPUT, -1) ; return in->npix ; } /*----------------------------------------------------------------------------*/ /** @brief Free memory associated to an cpl_stats object. @param stats the object to delete @return void Frees all memory associated to a cpl_stats object. */ /*----------------------------------------------------------------------------*/ void cpl_stats_delete(cpl_stats * stats) { if (stats == NULL) return ; cpl_free(stats) ; } /*----------------------------------------------------------------------------*/ /** @brief Compute various statistics of an image sub-window. @param image Input image. @param bitmask Defines which parameters have to be computed @param llx Lower left x position (FITS convention) @param lly Lower left y position (FITS convention) @param urx Upper right x position (FITS convention) @param ury Upper right y position (FITS convention) @return 1 newly allocated cpl_stats structure or NULL in error case Compute various images statistics. The specified bounds are included in the specified region. The user specifies the statistics he wants to get with a bitmask. Possible requested values are: - CPL_STATS_MIN - CPL_STATS_MAX - CPL_STATS_MEAN - CPL_STATS_MEDIAN - CPL_STATS_STDEV - CPL_STATS_FLUX - CPL_STATS_ABSFLUX - CPL_STATS_SQFLUX - CPL_STATS_CENTROID - CPL_STATS_MINPOS - CPL_STATS_MAXPOS - CPL_STATS_ALL or any bitwise combination of these. E.g. the bitmask would be CPL_STATS_MIN | CPL_STATS_MEDIAN in order to get the minimum and the median of the image. In the case of CPL_STATS_MIN and CPL_STATS_MAX where more than one set of coordinates share the extremum it is undefined which of those coordinates will be returned. Images can be CPL_TYPE_DOUBLE, CPL_TYPE_FLOAT, CPL_TYPE_INT. For the CPL_STATS_CENTROID computation, if there are negative pixels, the minimum value is added to all the pixels in order to have all pixels with positive values for computation. The returned object must be deallocated using cpl_stats_delete(). Possible #_cpl_error_code_ set in this function: - CPL_ERROR_NULL_INPUT if (one of) the input pointer(s) is NULL - CPL_ERROR_ILLEGAL_INPUT if the defined window is not in the image - CPL_ERROR_DATA_NOT_FOUND if all the pixels are bad - CPL_ERROR_TYPE_MISMATCH if the passed image type is not supported - CPL_ERROR_INVALID_TYPE if bitmask is 1, e.g. due to a logical or (||) of the allowed options. - CPL_ERROR_UNSUPPORTED_MODE if bitmask is otherwise different from the allowed options. */ /*----------------------------------------------------------------------------*/ cpl_stats * cpl_stats_new_from_image_window( const cpl_image * image, unsigned bitmask, int llx, int lly, int urx, int ury) { double min_pix_tmp, pix_sum, sqr_sum, abs_sum ; double max_pix = DBL_MAX; /* Avoid (false) uninit warning */ double min_pix = DBL_MAX; /* Avoid (false) uninit warning */ int max_pos = -1; /* Avoid (false) uninit warning */ int min_pos = -1; /* Avoid (false) uninit warning */ cpl_stats * stats ; int npix ; int pos ; int minmax_cat, mean_cat ; /* Index of 1st good pixel - used for initialization */ int firstgoodpos; /* The number of bad pixels inside the subwindow */ int nbadpix; /* A map of the the bad pixels in the input */ const cpl_binary * badmap ; int i, j ; /* Test inputs */ cpl_ensure(image, CPL_ERROR_NULL_INPUT, NULL) ; cpl_ensure(llx > 0 && llx <= image->nx && urx > 0 && urx <= image->nx && urx >= llx, CPL_ERROR_ILLEGAL_INPUT, NULL); cpl_ensure(lly>0 && lly <= image->ny && ury > 0 && ury <= image->ny && ury >= lly, CPL_ERROR_ILLEGAL_INPUT, NULL); cpl_ensure(bitmask != 1, CPL_ERROR_INVALID_TYPE, NULL); cpl_ensure(bitmask > 0, CPL_ERROR_UNSUPPORTED_MODE, NULL); cpl_ensure(bitmask <= CPL_STATS_ALL, CPL_ERROR_UNSUPPORTED_MODE, NULL); /* Get the bad pixels map */ badmap = image->bpm == NULL ? NULL : cpl_mask_get_data(image->bpm); npix = (urx-llx+1) * (ury-lly+1) ; /* Get the first good pixel and the number of bad pixels */ nbadpix = 0 ; if (badmap != NULL) { firstgoodpos = -1 ; for (j=lly ; j<=ury ; j++) { for (i=llx ; i<=urx ; i++) { pos = (i-1)+(j-1)*image->nx ; if (badmap[pos] == CPL_BINARY_1) nbadpix ++ ; if (firstgoodpos < 0) if (badmap[pos] == CPL_BINARY_0) firstgoodpos = pos ; } } } else { firstgoodpos = (llx-1)+(lly-1)*image->nx ; } /* There are no good pixels */ cpl_ensure(firstgoodpos>=0, CPL_ERROR_DATA_NOT_FOUND, NULL); /* Initialize */ pix_sum = sqr_sum = abs_sum = 0.0 ; /* Two statistics computation categories defined here */ minmax_cat = (CPL_STATS_MIN|CPL_STATS_MAX|CPL_STATS_MINPOS| CPL_STATS_MAXPOS|CPL_STATS_CENTROID) & bitmask ; mean_cat = (CPL_STATS_MEAN|CPL_STATS_STDEV|CPL_STATS_FLUX| CPL_STATS_ABSFLUX|CPL_STATS_SQFLUX) & bitmask ; /* Code duplication not avoidable for performance reasons */ /* The tests should stay outside the loops */ if (minmax_cat && !mean_cat) { /* Switch on image type */ switch (image->type) { #define CPL_OPERATION CPL_IMAGE_STATS_MINMAX #define CPL_CLASS CPL_CLASS_DOUBLE #include "cpl_stats_body.h" #undef CPL_CLASS #define CPL_CLASS CPL_CLASS_FLOAT #include "cpl_stats_body.h" #undef CPL_CLASS #define CPL_CLASS CPL_CLASS_INT #include "cpl_stats_body.h" #undef CPL_CLASS #undef CPL_OPERATION default: cpl_ensure(0, CPL_ERROR_TYPE_MISMATCH, NULL) ; } } else if (mean_cat && !minmax_cat) { /* Switch on image type */ switch (image->type) { #define CPL_OPERATION CPL_IMAGE_STATS_MEAN #define CPL_CLASS CPL_CLASS_DOUBLE #include "cpl_stats_body.h" #undef CPL_CLASS #define CPL_CLASS CPL_CLASS_FLOAT #include "cpl_stats_body.h" #undef CPL_CLASS #define CPL_CLASS CPL_CLASS_INT #include "cpl_stats_body.h" #undef CPL_CLASS #undef CPL_OPERATION default: cpl_ensure(0, CPL_ERROR_TYPE_MISMATCH, NULL) ; } } else if (mean_cat && minmax_cat) { /* Switch on image type */ switch (image->type) { #define CPL_OPERATION CPL_IMAGE_STATS_MEANMINMAX #define CPL_CLASS CPL_CLASS_DOUBLE #include "cpl_stats_body.h" #undef CPL_CLASS #define CPL_CLASS CPL_CLASS_FLOAT #include "cpl_stats_body.h" #undef CPL_CLASS #define CPL_CLASS CPL_CLASS_INT #include "cpl_stats_body.h" #undef CPL_CLASS #undef CPL_OPERATION default: cpl_ensure(0, CPL_ERROR_TYPE_MISMATCH, NULL) ; } } else { /* Only median is requested : do nothing here */ } /* Allocate stat object */ stats = cpl_malloc(sizeof(cpl_stats)) ; /* Fill stats object */ /* When a member of the struct is accessed check that it was initialized */ stats->bitmask = bitmask; stats->npix = npix - nbadpix ; if (minmax_cat) stats->min = min_pix ; if (minmax_cat) stats->max = max_pix ; if (mean_cat) stats->mean = pix_sum / stats->npix; if (bitmask&CPL_STATS_MEDIAN) stats->med = cpl_image_get_median_window(image, llx, lly, urx, ury); if (bitmask&CPL_STATS_STDEV) { double variance = 0; switch (image->type) { #define CPL_OPERATION CPL_IMAGE_STATS_VARIANCE #define CPL_CLASS CPL_CLASS_DOUBLE #include "cpl_stats_body.h" #undef CPL_CLASS #define CPL_CLASS CPL_CLASS_FLOAT #include "cpl_stats_body.h" #undef CPL_CLASS #define CPL_CLASS CPL_CLASS_INT #include "cpl_stats_body.h" #undef CPL_CLASS #undef CPL_OPERATION default: break ; /* Cannot reach this point */ } /* Compute the bias-corrected standard deviation. - With the recurrence relation rounding can likely not cause the variance to become negative, but check just to be safe */ if (stats->npix<2) stats->stdev = 0 ; else stats->stdev = variance > 0 ? sqrt(variance*stats->npix/(double)(stats->npix-1)) : 0; } if (bitmask&CPL_STATS_CENTROID) { double sum_xz, sum_yz, sum_z, sum_x, sum_y, sum_pix ; sum_xz = sum_yz = sum_z = sum_x = sum_y = sum_pix = 0.0 ; switch (image->type) { #define CPL_OPERATION CPL_IMAGE_STATS_CENTROID #define CPL_CLASS CPL_CLASS_DOUBLE #include "cpl_stats_body.h" #undef CPL_CLASS #define CPL_CLASS CPL_CLASS_FLOAT #include "cpl_stats_body.h" #undef CPL_CLASS #define CPL_CLASS CPL_CLASS_INT #include "cpl_stats_body.h" #undef CPL_CLASS #undef CPL_OPERATION default: break ; /* Cannot reach this point */ } if (sum_z > 0) { stats->xcentroid = sum_xz / sum_z; stats->ycentroid = sum_yz / sum_z; } else { stats->xcentroid = sum_x / sum_pix ; stats->ycentroid = sum_y / sum_pix ; } /* The centroid has to be inside the provided sub-window */ /* It can only fail to be that due to round-off, for example due to compiler optimization (apparently because sum_z is made into a register variable) */ /* The round-off is especially likely to happen on a 1D-image, e.g. when lly == ury */ if (stats->xcentroid < llx) { assert( llx - stats->xcentroid < FLT_EPSILON ); stats->xcentroid = llx; } else if (stats->xcentroid > urx) { assert( stats->xcentroid - urx < FLT_EPSILON ); stats->xcentroid = urx; } if (stats->ycentroid < lly) { assert( lly - stats->ycentroid < FLT_EPSILON ); stats->ycentroid = lly; } else if (stats->ycentroid > ury) { assert( stats->ycentroid - ury < FLT_EPSILON ); stats->ycentroid = ury; } } if (bitmask&CPL_STATS_FLUX) stats->flux = pix_sum ; if (bitmask&CPL_STATS_ABSFLUX) stats->absflux = abs_sum ; if (bitmask&CPL_STATS_SQFLUX) stats->sqflux = sqr_sum ; if (bitmask&CPL_STATS_MINPOS) { stats->min_x = 1 + min_pos % image->nx ; stats->min_y = 1 + min_pos / image->nx ; } if (bitmask&CPL_STATS_MAXPOS) { stats->max_x = 1 + max_pos % image->nx ; stats->max_y = 1 + max_pos / image->nx ; } return stats ; } /*----------------------------------------------------------------------------*/ /** @brief Compute various statistics of an image. @param image input image. @param bitmask Defines which parameters have to be computed @return 1 newly allocated cpl_stats structure or NULL in error case @see cpl_stats_new_from_image_window() */ /*----------------------------------------------------------------------------*/ cpl_stats * cpl_stats_new_from_image( const cpl_image * image, unsigned bitmask) { cpl_ensure(image, CPL_ERROR_NULL_INPUT, NULL); return cpl_stats_new_from_image_window(image, bitmask, 1, 1, image->nx, image->ny) ; } /*----------------------------------------------------------------------------*/ /** @brief Dump a cpl_stats object @param stats cpl_stats object. @param bitmask Defines which parameters have to be dumped. @param stream Where the output goes @return CPL_ERROR_NONE or the relevant the #_cpl_error_code_ @see cpl_stats_new_from_image_window() It is an error to request parameters that have not been set. Possible #_cpl_error_code_ set in this function: - CPL_ERROR_NULL_INPUT if (one of) the input pointer(s) is NULL - CPL_ERROR_ILLEGAL_INPUT if bitmask specifies stats that have not been computed in stats - CPL_ERROR_FILE_IO if there is a problem writing in stream */ /*----------------------------------------------------------------------------*/ cpl_error_code cpl_stats_dump( const cpl_stats * stats, unsigned bitmask, FILE * stream) { cpl_ensure_code(stats, CPL_ERROR_NULL_INPUT); cpl_ensure_code((bitmask & ~stats->bitmask) == 0, CPL_ERROR_ILLEGAL_INPUT); cpl_ensure_code( fprintf(stream, "\t\tNb pix: %d\n", stats->npix) > 0, CPL_ERROR_FILE_IO); if (bitmask&CPL_STATS_MIN) cpl_ensure_code( fprintf(stream, "\t\tMin: %.8g\n", stats->min) >0, CPL_ERROR_FILE_IO); if (bitmask&CPL_STATS_MAX) cpl_ensure_code( fprintf(stream, "\t\tMax: %.8g\n", stats->max) >0, CPL_ERROR_FILE_IO); if (bitmask&CPL_STATS_MEAN) cpl_ensure_code( fprintf(stream, "\t\tMean: %.8g\n", stats->mean) >0, CPL_ERROR_FILE_IO); if (bitmask&CPL_STATS_MEDIAN) cpl_ensure_code( fprintf(stream, "\t\tMedian: %.8g\n", stats->med), CPL_ERROR_FILE_IO); if (bitmask&CPL_STATS_STDEV) cpl_ensure_code( fprintf(stream, "\t\tStd. dev: %.8g\n", stats->stdev), CPL_ERROR_FILE_IO); if (bitmask&CPL_STATS_FLUX) cpl_ensure_code( fprintf(stream, "\t\tFlux: %.8g\n", stats->flux), CPL_ERROR_FILE_IO); if (bitmask&CPL_STATS_ABSFLUX) cpl_ensure_code( fprintf(stream, "\t\tAbs flux: %.8g\n", stats->absflux), CPL_ERROR_FILE_IO); if (bitmask&CPL_STATS_SQFLUX) cpl_ensure_code( fprintf(stream, "\t\tSq flux: %.8g\n", stats->sqflux), CPL_ERROR_FILE_IO); if (bitmask&CPL_STATS_CENTROID) cpl_ensure_code( fprintf(stream, "\t\tX centroid: %g\n", stats->xcentroid), CPL_ERROR_FILE_IO); if (bitmask&CPL_STATS_CENTROID) cpl_ensure_code( fprintf(stream, "\t\tY centroid: %.8g\n", stats->ycentroid), CPL_ERROR_FILE_IO); if (bitmask&CPL_STATS_MINPOS) cpl_ensure_code( fprintf(stream, "\t\tMin. x pos.: %d\n", stats->min_x), CPL_ERROR_FILE_IO); if (bitmask&CPL_STATS_MINPOS) cpl_ensure_code( fprintf(stream, "\t\tMin. y pos.: %d\n", stats->min_y), CPL_ERROR_FILE_IO); if (bitmask&CPL_STATS_MAXPOS) cpl_ensure_code( fprintf(stream, "\t\tMax. x pox.: %d\n", stats->max_x), CPL_ERROR_FILE_IO); if (bitmask&CPL_STATS_MAXPOS) cpl_ensure_code( fprintf(stream, "\t\tMax. y pos.: %d\n", stats->max_y), CPL_ERROR_FILE_IO); return CPL_ERROR_NONE ; } /**@}*/