irplib_hist.c

00001 
00002 
00003 /*
00004  * This file is part of the irplib package
00005  * Copyright (C) 2002, 2003 European Southern Observatory
00006  *
00007  * This program is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License as published by
00009  * the Free Software Foundation; either version 2 of the License, or
00010  * (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02111-1307 USA
00020  */
00021 
00022 /*
00023  * $Author: kmirny $
00024  * $Id: irplib_hist.c,v 1.7 2009/10/15 14:02:18 kmirny Exp $
00025  * $Date: 2009/10/15 14:02:18 $
00026  * $Revision: 1.7 $
00027  * $Name: uves-5_0_0 $
00028  */
00029 
00030 #ifdef HAVE_CONFIG_H
00031 #include <config.h>
00032 #endif
00033 
00034 #include <stdlib.h>
00035 #include <stdio.h>
00036 
00037 #include <math.h>
00038 
00039 #include "irplib_hist.h"
00040 
00041 struct _irplib_hist_
00042 {
00043     unsigned long * bins;
00044     unsigned long   nbins;
00045     double          start;
00046     double          range;
00047 };
00048 
00049 /*
00050  * Create a new empty histogram
00051  */
00052 
00053 irplib_hist *
00054 irplib_hist_new(void)
00055 {
00056     return (irplib_hist *) cpl_calloc(1, sizeof(irplib_hist));
00057 }
00058 
00059 /*
00060  * Delete a histogram
00061  */
00062 
00063 void
00064 irplib_hist_delete(irplib_hist * d)
00065 {
00066     if (d == NULL)
00067     return;
00068 
00069     if (d -> bins)
00070     cpl_free(d -> bins);
00071 
00072     cpl_free(d);
00073 }
00074 
00075 /*
00076  * Initialise a histogram with user-defined values
00077  */
00078 
00079 cpl_error_code
00080 irplib_hist_init(irplib_hist   * hist,
00081                  unsigned long   nbins,
00082                  double          start,
00083                  double          range)
00084 {
00085     /* Test the entries */
00086     cpl_ensure_code(hist         != NULL, CPL_ERROR_NULL_INPUT);
00087     cpl_ensure_code(nbins        >  0,    CPL_ERROR_ILLEGAL_INPUT);
00088     cpl_ensure_code(range        >  0,    CPL_ERROR_ILLEGAL_INPUT);
00089     cpl_ensure_code(hist -> bins == NULL, CPL_ERROR_ILLEGAL_INPUT);
00090 
00091     /* Initialise the histogram structure */
00092     hist -> bins  = (unsigned long *) cpl_calloc(nbins, sizeof(unsigned long));
00093     hist -> nbins = nbins;
00094     hist -> start = start;
00095     hist -> range = range;
00096 
00097     return cpl_error_get_code();
00098 }
00099 
00100 /*
00101  * Return the value of a histogram bin.
00102  * An uninitialised histogram is considered an illegal input.
00103  */
00104 
00105 unsigned long
00106 irplib_hist_get_value(const irplib_hist * hist,
00107                       const unsigned long binpos)
00108 {
00109     cpl_ensure(hist         != NULL,          CPL_ERROR_NULL_INPUT, 0);
00110     cpl_ensure(hist -> bins != NULL,          CPL_ERROR_ILLEGAL_INPUT, 0);
00111     cpl_ensure(binpos       <  hist -> nbins, CPL_ERROR_ILLEGAL_INPUT, 0);
00112 
00113     return hist -> bins[binpos];
00114 }
00115 
00116 /*
00117  * Return the number of bins in the histogram.
00118  */
00119 
00120 unsigned long
00121 irplib_hist_get_nbins(const irplib_hist * hist)
00122 {
00123     cpl_ensure(hist != NULL, CPL_ERROR_NULL_INPUT, 0);
00124 
00125     return hist -> nbins;
00126 }
00127 
00128 /*
00129  * Return the binwidth of the histogram.
00130  */
00131 
00132 double
00133 irplib_hist_get_bin_size(const irplib_hist * hist)
00134 {
00135     cpl_ensure(hist         != NULL, CPL_ERROR_NULL_INPUT, 0);
00136     cpl_ensure(hist -> bins != NULL, CPL_ERROR_ILLEGAL_INPUT, 0);
00137 
00138     return hist -> range / (double)(hist -> nbins - 2);
00139 }
00140 
00141 /*
00142  * Return the range covered by the histogram.
00143  */
00144 
00145 double
00146 irplib_hist_get_range(const irplib_hist * hist)
00147 {
00148     cpl_ensure(hist != NULL, CPL_ERROR_NULL_INPUT, 0);
00149 
00150     return hist -> range;
00151 }
00152 
00153 /*
00154  * Return the real value corresponding
00155  * to the inferior limit of the histogram..
00156  */
00157 
00158 double
00159 irplib_hist_get_start(const irplib_hist * hist)
00160 {
00161     cpl_ensure(hist         != NULL, CPL_ERROR_NULL_INPUT, 0);
00162     cpl_ensure(hist -> bins != NULL, CPL_ERROR_ILLEGAL_INPUT, 0);
00163 
00164     return hist -> start;
00165 }
00166 
00167 /*
00168  * Fill a histogram for an image.
00169  * If the histogram is uninitialised,
00170  * the function initialises it with default values.
00171  */
00172 
00173 cpl_error_code
00174 irplib_hist_fill(irplib_hist     * hist,
00175                  const cpl_image * image)
00176 {
00177     double           binwidth = 1.0;
00178     int              nsamples;
00179     int              i;
00180     const float    * data = 0;
00181     const cpl_binary*  bpm_data = 0;
00182     const cpl_mask* bpm = 0;
00183     cpl_error_code   error;
00184 
00185     /* Test the entries */
00186     cpl_ensure_code(hist  != NULL, CPL_ERROR_NULL_INPUT);
00187     cpl_ensure_code(image != NULL, CPL_ERROR_NULL_INPUT);
00188 
00189     if (hist -> bins == NULL) {
00190     const double        hstart = cpl_image_get_min(image);
00191     const double        hrange = cpl_image_get_max(image) - hstart;
00192 
00193     /*
00194          * Whichever function that computes an optimal binwidth
00195          * should be introduced inside this if-statement, here.
00196          */
00197 
00198     /* 2 extra-bins for possible out-of-range values */
00199     const unsigned long nbins  = (unsigned long) (hrange / binwidth) + 2;
00200 
00201     error = irplib_hist_init(hist, nbins, hstart, hrange);
00202     cpl_ensure_code(!error, error);
00203     } else {
00204     cpl_ensure_code(hist -> range > 0, CPL_ERROR_ILLEGAL_INPUT);
00205 
00206     /* 2 bins reserved for possible out-of-range values */
00207         binwidth = hist -> range / (double)(hist -> nbins - 2);
00208     }
00209 
00210     nsamples = cpl_image_get_size_x(image) * cpl_image_get_size_y(image);
00211     data     = cpl_image_get_data_float_const(image);
00212     bpm      = cpl_image_get_bpm_const(image);
00213     if (bpm)
00214     {
00215         bpm_data     = cpl_mask_get_data_const(bpm); // bad pixel mask
00216     }
00217 
00218     for (i = 0; i < nsamples; i++)
00219     {
00220         int pos = 0;
00221         if(bpm_data && bpm_data[i] == CPL_BINARY_1)
00222         {
00223             continue;
00224         }
00225         pos = (int)((data[i] - hist -> start) / binwidth);
00226         if (pos <  0)
00227         {
00228             hist -> bins[0]++;
00229         } else if ((unsigned long) pos >= (hist -> nbins - 2))
00230         {
00231             hist -> bins[hist -> nbins - 1]++;
00232         } else
00233         {
00234             hist -> bins[pos + 1]++;
00235         }
00236     }
00237 
00238     return cpl_error_get_code();
00239 }
00240 
00241 /*
00242  * Compute the maximum of a histogram.
00243  * Return: the maximum value.
00244  * The parameter max_where is a pointer to the position
00245  * of the maximum in the histogram.
00246  */
00247 
00248 unsigned long
00249 irplib_hist_get_max(const irplib_hist * hist,
00250                     unsigned long     * maxpos)
00251 {
00252     unsigned long max = 0;
00253     unsigned long ui;
00254 
00255     cpl_ensure(hist         != NULL, CPL_ERROR_NULL_INPUT, 0);
00256     cpl_ensure(maxpos       != NULL, CPL_ERROR_NULL_INPUT, 0);
00257     cpl_ensure(hist -> bins != NULL, CPL_ERROR_ILLEGAL_INPUT, 0);
00258 
00259     for(ui = 0; ui < hist -> nbins; ui++) {
00260     double c_value = irplib_hist_get_value(hist, ui);
00261     if(c_value > max) {
00262         max     = c_value;
00263         *maxpos = ui;
00264     }
00265     }
00266 
00267     return max;
00268 }
00269 
00270 /*
00271  * Cast a histogram into a table with a single column named "HIST"
00272  */
00273 
00274 cpl_table *
00275 irplib_hist_cast_table(const irplib_hist * hist)
00276 {
00277     cpl_table      * table;
00278     cpl_error_code   error;
00279 
00280     cpl_ensure(hist         != NULL, CPL_ERROR_NULL_INPUT, NULL);
00281     cpl_ensure(hist -> bins != NULL, CPL_ERROR_ILLEGAL_INPUT, NULL);
00282 
00283     table = cpl_table_new(hist -> nbins);
00284 
00285     error = cpl_table_new_column(table, "HIST", CPL_TYPE_INT);
00286     cpl_ensure(!error, error, NULL);
00287 
00288     error = cpl_table_copy_data_int(table, "HIST", (int *)(hist -> bins));
00289     cpl_ensure(!error, error, NULL);
00290 
00291     return table;
00292 }
00293 
00294 /*
00295  * Collapse the histogram: add the values of all bins.
00296  * Used now only for debugging purposes.
00297  */
00298 
00299 cpl_error_code
00300 irplib_hist_collapse(irplib_hist * hist,
00301                      unsigned long new_nbins)
00302 {
00303     unsigned long   ui, nuj;
00304     unsigned long * old_bins;
00305     unsigned long   old_nbins;
00306     double          collapse_rate;
00307     cpl_error_code  error;
00308     unsigned long   rest;
00309 
00310     cpl_ensure_code(hist         != NULL,          CPL_ERROR_NULL_INPUT);
00311     cpl_ensure_code(hist -> bins != NULL,          CPL_ERROR_ILLEGAL_INPUT);
00312     cpl_ensure_code(new_nbins    >  0,             CPL_ERROR_ILLEGAL_INPUT);
00313     cpl_ensure_code(new_nbins    <= hist -> nbins, CPL_ERROR_ILLEGAL_INPUT);
00314 
00315     old_bins  = hist -> bins;
00316     old_nbins = hist -> nbins;
00317 
00318     hist -> bins = NULL;
00319     error = irplib_hist_init(hist, new_nbins, hist -> start, hist -> range);
00320     cpl_ensure_code(!error, error);
00321 
00322     collapse_rate = (double) (old_nbins - 2) / (double) (new_nbins - 2);
00323 
00324     /* The out-of-range values are not affected by the collapsing operation */
00325     hist -> bins[0]             = old_bins[0];
00326     hist -> bins[new_nbins - 1] = old_bins[old_nbins - 1];
00327 
00328     rest = 0;
00329     nuj  = 1;
00330 
00331     for (ui = 1; ui < new_nbins - 1; ui++) {
00332     unsigned long uj;
00333     const double  up  = collapse_rate *  ui;
00334 
00335     hist -> bins[ui] += rest;
00336 
00337     for (uj = nuj; uj < (unsigned long) up + 1; uj++)
00338         hist -> bins[ui] +=  old_bins[uj];
00339 
00340     rest = (unsigned long)(up - (unsigned long) up) * old_bins[uj];
00341     hist -> bins[ui] += rest;
00342 
00343     rest = old_bins[uj] - rest;
00344     nuj = uj + 1;
00345     }
00346 
00347     cpl_free(old_bins);
00348 
00349     return cpl_error_get_code();
00350 }

Generated on 9 Mar 2012 for UVES Pipeline Reference Manual by  doxygen 1.6.1