irplib_hist.c

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

Generated on Fri Apr 18 14:11:41 2008 for UVES Pipeline Reference Manual by  doxygen 1.5.1