DETMON Pipeline Reference Manual  1.3.0
irplib_hist.c
1 
2 
3 /*
4  * This file is part of the irplib package
5  * Copyright (C) 2002, 2003 European Southern Observatory
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02111-1307 USA
20  */
21 
22 /*
23  * $Author: jtaylor $
24  * $Id: irplib_hist.c,v 1.8 2013-07-04 12:10:12 jtaylor Exp $
25  * $Date: 2013-07-04 12:10:12 $
26  * $Revision: 1.8 $
27  * $Name: not supported by cvs2svn $
28  */
29 
30 #ifdef HAVE_CONFIG_H
31 #include <config.h>
32 #endif
33 
34 #include <stdlib.h>
35 #include <stdio.h>
36 
37 #include <math.h>
38 
39 #include "irplib_hist.h"
40 
41 struct _irplib_hist_
42 {
43  unsigned long * bins;
44  unsigned long nbins;
45  double start;
46  double range;
47 };
48 
49 /*
50  * Create a new empty histogram
51  */
52 
53 irplib_hist *
54 irplib_hist_new(void)
55 {
56  return (irplib_hist *) cpl_calloc(1, sizeof(irplib_hist));
57 }
58 
59 /*
60  * Delete a histogram
61  */
62 
63 void
64 irplib_hist_delete(irplib_hist * d)
65 {
66  if (d == NULL)
67  return;
68 
69  if (d -> bins)
70  cpl_free(d -> bins);
71 
72  cpl_free(d);
73 }
74 
75 /*
76  * Initialise a histogram with user-defined values
77  */
78 
79 cpl_error_code
80 irplib_hist_init(irplib_hist * hist,
81  unsigned long nbins,
82  double start,
83  double range)
84 {
85  /* Test the entries */
86  cpl_ensure_code(hist != NULL, CPL_ERROR_NULL_INPUT);
87  cpl_ensure_code(nbins > 0, CPL_ERROR_ILLEGAL_INPUT);
88  cpl_ensure_code(range > 0, CPL_ERROR_ILLEGAL_INPUT);
89  cpl_ensure_code(hist -> bins == NULL, CPL_ERROR_ILLEGAL_INPUT);
90 
91  /* Initialise the histogram structure */
92  hist -> bins = (unsigned long *) cpl_calloc(nbins, sizeof(unsigned long));
93  hist -> nbins = nbins;
94  hist -> start = start;
95  hist -> range = range;
96 
97  return cpl_error_get_code();
98 }
99 
100 /*
101  * Return the value of a histogram bin.
102  * An uninitialised histogram is considered an illegal input.
103  */
104 
105 unsigned long
106 irplib_hist_get_value(const irplib_hist * hist,
107  const unsigned long binpos)
108 {
109  cpl_ensure(hist != NULL, CPL_ERROR_NULL_INPUT, 0);
110  cpl_ensure(hist -> bins != NULL, CPL_ERROR_ILLEGAL_INPUT, 0);
111  cpl_ensure(binpos < hist -> nbins, CPL_ERROR_ILLEGAL_INPUT, 0);
112 
113  return hist -> bins[binpos];
114 }
115 
116 /*
117  * Return the number of bins in the histogram.
118  */
119 
120 unsigned long
121 irplib_hist_get_nbins(const irplib_hist * hist)
122 {
123  cpl_ensure(hist != NULL, CPL_ERROR_NULL_INPUT, 0);
124 
125  return hist -> nbins;
126 }
127 
128 /*
129  * Return the binwidth of the histogram.
130  */
131 
132 double
133 irplib_hist_get_bin_size(const irplib_hist * hist)
134 {
135  cpl_ensure(hist != NULL, CPL_ERROR_NULL_INPUT, 0);
136  cpl_ensure(hist -> bins != NULL, CPL_ERROR_ILLEGAL_INPUT, 0);
137 
138  return hist -> range / (double)(hist -> nbins - 2);
139 }
140 
141 /*
142  * Return the range covered by the histogram.
143  */
144 
145 double
146 irplib_hist_get_range(const irplib_hist * hist)
147 {
148  cpl_ensure(hist != NULL, CPL_ERROR_NULL_INPUT, 0);
149 
150  return hist -> range;
151 }
152 
153 /*
154  * Return the real value corresponding
155  * to the inferior limit of the histogram..
156  */
157 
158 double
159 irplib_hist_get_start(const irplib_hist * hist)
160 {
161  cpl_ensure(hist != NULL, CPL_ERROR_NULL_INPUT, 0);
162  cpl_ensure(hist -> bins != NULL, CPL_ERROR_ILLEGAL_INPUT, 0);
163 
164  return hist -> start;
165 }
166 
167 /*
168  * Fill a histogram for an image.
169  * If the histogram is uninitialised,
170  * the function initialises it with default values.
171  */
172 
173 cpl_error_code
174 irplib_hist_fill(irplib_hist * hist,
175  const cpl_image * image)
176 {
177  double binwidth = 1.0;
178  int nsamples;
179  int i;
180  const float * data = 0;
181  const cpl_binary* bpm_data = 0;
182  const cpl_mask* bpm = 0;
183 
184  /* Test the entries */
185  cpl_ensure_code(hist != NULL, CPL_ERROR_NULL_INPUT);
186  cpl_ensure_code(image != NULL, CPL_ERROR_NULL_INPUT);
187 
188  if (hist -> bins == NULL) {
189  const double hstart = cpl_image_get_min(image);
190  const double hrange = cpl_image_get_max(image) - hstart;
191  cpl_error_code error;
192 
193  /*
194  * Whichever function that computes an optimal binwidth
195  * should be introduced inside this if-statement, here.
196  */
197 
198  /* 2 extra-bins for possible out-of-range values */
199  const unsigned long nbins = (unsigned long) (hrange / binwidth) + 2;
200 
201  error = irplib_hist_init(hist, nbins, hstart, hrange);
202  cpl_ensure_code(!error, error);
203  } else {
204  cpl_ensure_code(hist -> range > 0, CPL_ERROR_ILLEGAL_INPUT);
205 
206  /* 2 bins reserved for possible out-of-range values */
207  binwidth = hist -> range / (double)(hist -> nbins - 2);
208  }
209 
210  nsamples = cpl_image_get_size_x(image) * cpl_image_get_size_y(image);
211  data = cpl_image_get_data_float_const(image);
212  bpm = cpl_image_get_bpm_const(image);
213  if (bpm)
214  {
215  bpm_data = cpl_mask_get_data_const(bpm); // bad pixel mask
216  }
217 
218  for (i = 0; i < nsamples; i++)
219  {
220  int pos = 0;
221  if(bpm_data && bpm_data[i] != CPL_BINARY_0)
222  {
223  continue;
224  }
225  pos = (int)((data[i] - hist -> start) / binwidth);
226  if (pos < 0)
227  {
228  hist -> bins[0]++;
229  } else if ((unsigned long) pos >= (hist -> nbins - 2))
230  {
231  hist -> bins[hist -> nbins - 1]++;
232  } else
233  {
234  hist -> bins[pos + 1]++;
235  }
236  }
237 
238  return cpl_error_get_code();
239 }
240 
241 /*
242  * Compute the maximum of a histogram.
243  * Return: the maximum value.
244  * The parameter max_where is a pointer to the position
245  * of the maximum in the histogram.
246  */
247 
248 unsigned long
249 irplib_hist_get_max(const irplib_hist * hist,
250  unsigned long * maxpos)
251 {
252  unsigned long max = 0;
253  unsigned long ui;
254 
255  cpl_ensure(hist != NULL, CPL_ERROR_NULL_INPUT, 0);
256  cpl_ensure(maxpos != NULL, CPL_ERROR_NULL_INPUT, 0);
257  cpl_ensure(hist -> bins != NULL, CPL_ERROR_ILLEGAL_INPUT, 0);
258 
259  for(ui = 0; ui < hist -> nbins; ui++) {
260  double c_value = irplib_hist_get_value(hist, ui);
261  if(c_value > max) {
262  max = c_value;
263  *maxpos = ui;
264  }
265  }
266 
267  return max;
268 }
269 
270 /*
271  * Cast a histogram into a table with a single column named "HIST"
272  */
273 
274 cpl_table *
275 irplib_hist_cast_table(const irplib_hist * hist)
276 {
277  cpl_table * table;
278  cpl_error_code error;
279 
280  cpl_ensure(hist != NULL, CPL_ERROR_NULL_INPUT, NULL);
281  cpl_ensure(hist -> bins != NULL, CPL_ERROR_ILLEGAL_INPUT, NULL);
282 
283  table = cpl_table_new(hist -> nbins);
284 
285  error = cpl_table_new_column(table, "HIST", CPL_TYPE_INT);
286  cpl_ensure(!error, error, NULL);
287 
288  error = cpl_table_copy_data_int(table, "HIST", (int *)(hist -> bins));
289  cpl_ensure(!error, error, NULL);
290 
291  return table;
292 }
293 
294 /*
295  * Collapse the histogram: add the values of all bins.
296  * Used now only for debugging purposes.
297  */
298 
299 cpl_error_code
300 irplib_hist_collapse(irplib_hist * hist,
301  unsigned long new_nbins)
302 {
303  unsigned long ui, nuj;
304  unsigned long * old_bins;
305  unsigned long old_nbins;
306  double collapse_rate;
307  cpl_error_code error;
308  unsigned long rest;
309 
310  cpl_ensure_code(hist != NULL, CPL_ERROR_NULL_INPUT);
311  cpl_ensure_code(hist -> bins != NULL, CPL_ERROR_ILLEGAL_INPUT);
312  cpl_ensure_code(new_nbins > 0, CPL_ERROR_ILLEGAL_INPUT);
313  cpl_ensure_code(new_nbins <= hist -> nbins, CPL_ERROR_ILLEGAL_INPUT);
314 
315  old_bins = hist -> bins;
316  old_nbins = hist -> nbins;
317 
318  hist -> bins = NULL;
319  error = irplib_hist_init(hist, new_nbins, hist -> start, hist -> range);
320  cpl_ensure_code(!error, error);
321 
322  collapse_rate = (double) (old_nbins - 2) / (double) (new_nbins - 2);
323 
324  /* The out-of-range values are not affected by the collapsing operation */
325  hist -> bins[0] = old_bins[0];
326  hist -> bins[new_nbins - 1] = old_bins[old_nbins - 1];
327 
328  rest = 0;
329  nuj = 1;
330 
331  for (ui = 1; ui < new_nbins - 1; ui++) {
332  unsigned long uj;
333  const double up = collapse_rate * ui;
334 
335  hist -> bins[ui] += rest;
336 
337  for (uj = nuj; uj < (unsigned long) up + 1; uj++)
338  hist -> bins[ui] += old_bins[uj];
339 
340  rest = (unsigned long)(up - (unsigned long) up) * old_bins[uj];
341  hist -> bins[ui] += rest;
342 
343  rest = old_bins[uj] - rest;
344  nuj = uj + 1;
345  }
346 
347  cpl_free(old_bins);
348 
349  return cpl_error_get_code();
350 }