00001
00002
00003 #include "common.h"
00004 #include "histogram.h"
00005
00006 static char const rcsid[] = "$Id: histogram.c,v 1.4 2004/09/14 23:43:58 hiram Exp $";
00007
00008 static unsigned autoScale(float *values, size_t N, float *binSize,
00009 unsigned *binCount, float *minValue, float *min, float *max)
00010
00011
00012
00013
00014
00015
00016
00017
00018 {
00019 float minFound = INFINITY;
00020 float maxFound = -1.0 * INFINITY;
00021 float range = 0.0;
00022 unsigned count = 0;
00023 unsigned bins = DEFAULT_BIN_COUNT;
00024 size_t i;
00025 boolean findMinMax = FALSE;
00026
00027 if ( (*min == 0.0) && (*max == 0.0) )
00028 findMinMax = TRUE;
00029 else
00030 {
00031 minFound = *min;
00032 maxFound = *max;
00033 }
00034
00035 if (isnan(*minValue))
00036 {
00037 for (i = 0; i < N; ++i)
00038 {
00039 if (!isnan(values[i]))
00040 {
00041 if (findMinMax)
00042 {
00043 ++count;
00044 if (values[i] < minFound) minFound = values[i];
00045 if (values[i] > maxFound) maxFound = values[i];
00046 }
00047 else
00048 {
00049 if ( (values[i] < *max) && (values[i] > *min) ) ++count;
00050 }
00051 }
00052 }
00053 }
00054 else
00055 {
00056 minFound = *minValue;
00057 for (i = 0; i < N; ++i)
00058 {
00059 if ((!isnan(values[i])) && (values[i] >= minFound))
00060 {
00061 if (findMinMax)
00062 {
00063 ++count;
00064 if (values[i] > maxFound) maxFound = values[i];
00065 }
00066 else
00067 {
00068 if ( (values[i] < *max) && (values[i] > *min) ) ++count;
00069 }
00070 }
00071
00072 }
00073 }
00074
00075 if (count > 0)
00076 {
00077
00078 if (findMinMax)
00079 {
00080 *min = minFound;
00081 *max = maxFound;
00082 }
00083
00084
00085 if (isnan(*minValue))
00086 *minValue = minFound;
00087
00088 range = maxFound - minFound;
00089
00090
00091 if (*binCount > 0)
00092 bins = *binCount;
00093 else
00094 *binCount = bins;
00095
00096 if ( (range > 0.0) && (bins > 1))
00097 {
00098
00099
00100
00101
00102 if (isnan(*binSize))
00103 *binSize = range / (bins - 1);
00104
00105 if (*binSize > 0.0)
00106 return count;
00107 else
00108 return 0;
00109 }
00110 }
00111 return 0;
00112 }
00113
00114 void freeHistoGram(struct histoResult **histoResults)
00115
00116 {
00117 if (histoResults && *histoResults)
00118 {
00119 struct histoResult *hr, *next;
00120
00121 for (hr = *histoResults; hr; hr = next)
00122 {
00123 next = hr->next;
00124 freeMem(hr->binCounts);
00125 freeMem(hr->pValues);
00126 freeMem(hr);
00127 }
00128 *histoResults = NULL;
00129 }
00130 }
00131
00132 struct histoResult *histoGram(float *values, size_t N, float binSize,
00133 unsigned binCount, float minValue, float min, float max,
00134 struct histoResult *accumHisto)
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153 {
00154 float autoBinSize = NAN;
00155 float autoMinValue = NAN;
00156 float range = 0.0;
00157 unsigned autoBinCount = 0;
00158 unsigned autoValueCount = 0;
00159 boolean autoScaling = FALSE;
00160 unsigned valueCount = 0;
00161 unsigned i;
00162 struct histoResult *hr;
00163 unsigned missed = 0;
00164
00165 if (N == 0)
00166 return NULL;
00167
00168 if (accumHisto)
00169 {
00170 autoBinCount = accumHisto->binCount;
00171 autoBinSize = accumHisto->binSize;
00172 autoMinValue = accumHisto->binZero;
00173 autoScaling = FALSE;
00174 range = autoBinSize * (autoBinCount - 1);
00175 valueCount = accumHisto->count;
00176 }
00177 else
00178 {
00179
00180 if ( (0.0 == min) && (0.0 == max) )
00181 autoScaling = TRUE;
00182 else
00183 {
00184 range = max - min;
00185 if (range == 0.0)
00186 return NULL;
00187 }
00188
00189
00190 if (binCount > 1)
00191 autoBinCount = binCount;
00192 else if (!autoScaling)
00193 autoBinCount = DEFAULT_BIN_COUNT;
00194
00195 if (!isnan(binSize))
00196 autoBinSize = binSize;
00197 else if (!autoScaling)
00198 autoBinSize = range / (autoBinCount - 1);
00199
00200 if (!isnan(minValue))
00201 autoMinValue = minValue;
00202 else if (!autoScaling)
00203 autoMinValue = min;
00204
00205 if (autoScaling)
00206 {
00207 autoValueCount = autoScale(values, N, &autoBinSize,
00208 &autoBinCount, &autoMinValue, &min, &max);
00209 if (autoValueCount == 0)
00210 return NULL;
00211 }
00212 else
00213 autoValueCount = N;
00214 }
00215
00216 if (accumHisto)
00217 hr = accumHisto;
00218 else
00219 {
00220 AllocVar(hr);
00221 AllocArray(hr->binCounts,autoBinCount);
00222 AllocArray(hr->pValues,autoBinCount);
00223 }
00224
00225 for (i = 0; i < N; ++i)
00226 {
00227 if (!isnan(values[i]) && (values[i] >= autoMinValue))
00228 {
00229 if ( (values[i] <= max) && (values[i] >= min) )
00230 {
00231 float f = values[i] - autoMinValue;
00232 int inx = (int) floor(f / autoBinSize);
00233
00234 if ( (inx >= 0) && (inx < autoBinCount))
00235 {
00236 ++valueCount;
00237 ++hr->binCounts[inx];
00238 }
00239 else
00240 ++missed;
00241 }
00242 else
00243 ++missed;
00244 }
00245 else
00246 ++missed;
00247 }
00248
00249 if (accumHisto)
00250 hr->count = valueCount;
00251 else
00252 {
00253 hr->binSize = autoBinSize;
00254 hr->binCount = autoBinCount;
00255 hr->count = valueCount;
00256 hr->binZero = autoMinValue;
00257 }
00258
00259 for (i = 0; i < autoBinCount; ++i)
00260 {
00261 if (hr->binCounts[i] > 0)
00262 hr->pValues[i] = (float) hr->binCounts[i] / (float) valueCount;
00263 else
00264 hr->pValues[i] = 0.0;
00265 }
00266
00267 return hr;
00268 }