00001
00007 #ifndef __HISTOGRAM_H__
00008 #define __HISTOGRAM_H__
00009
00010
00011 #include <iterator>
00012 #include <functional>
00013 #include <vector>
00014 #include <numeric>
00015 #include <complex>
00016
00017 #include "../src/index_iterator.h"
00018 #include "../src/genericalgs.h"
00019 #include "../src/generic_stdlib.h"
00020 #include "../src/bounded.h"
00021 #include "../src/mathconstants.h"
00022
00023
00024 namespace Histo {
00025
00026
00036 template<class Count=int, class Value=double>
00037 class OneDBinList {
00038 protected:
00039 std::vector<Count> counts;
00040 std::vector<Value> values;
00041 Count total_c;
00042 Value total_v;
00043
00044 template<class C, class V>
00045 friend OneDBinList<C,V> operator-(const OneDBinList<C,V> &A, const OneDBinList<C,V> &B);
00046
00047 private:
00048 typedef Generic::index_iterator< std::vector<Value>, Scale::Linear<Value> > index_i;
00049 typedef Scale::Linear<Value> ScaleType;
00050
00051 public:
00052 typedef typename std::vector<Value>::size_type size_type;
00053 typedef Value value_type;
00054
00056 typedef Bounded::Magnitude Magnitude;
00057
00060 typedef std::complex<Value> Vector;
00061
00062 static size_type num_bins_default;
00063
00066 OneDBinList(const size_type num_bins=num_bins_default)
00067 : counts(num_bins), values(num_bins), total_c(0), total_v(0),
00068 cached_vector_sum_count(0), cached_vector_sum(0,0),
00069 cached_sum_value_count(0), cached_sum_value(0)
00070 { assert(num_bins>0); }
00071
00072
00074
00075 OneDBinList& add(size_type bin, Value val=1){
00076 total_c++;
00077 total_v+=val;
00078 counts[bin]++;
00079 values[bin]+=val;
00080 return *this;
00081 }
00082
00093 OneDBinList& keep_peak(size_type bin, Value val) {
00094 total_c++;
00095 total_v+=val;
00096 counts[bin]++;
00097 if (val > values[bin]) values[bin]=val;
00098 return *this;
00099 }
00100
00106 inline size_type num_bins() const { return counts.size(); }
00107
00116 inline Value sum_value() const {
00117 if (total_count() != cached_sum_value_count) {
00118 cached_sum_value = std::accumulate(ISEQ(values),Value(0));
00119 cached_sum_value_count = total_count();
00120 }
00121 return cached_sum_value;
00122 }
00123
00125 inline Count sum_count() const { return std::accumulate(ISEQ(counts),Count(0)); }
00126
00128 inline Value average_value()const { return sum_value()/Value(num_bins()); }
00129
00131 Value max_value() const { return *(std::max_element(ISEQ(values))); }
00132 Value min_value() const { return *(std::min_element(ISEQ(values))); }
00133 Count max_count() const { return *(std::max_element(ISEQ(counts))); }
00134 Count min_count() const { return *(std::min_element(ISEQ(counts))); }
00135
00137 size_type max_value_bin() const
00138 { return std::max_element(ISEQ(values))-values.begin(); }
00139
00141
00142
00155 inline Magnitude relative_selectivity() const {
00156
00157
00158 if (num_bins()<=1) return 1.0;
00159 const Magnitude proportion = safe_divide(value(max_value_bin()),sum_value());
00160 const Magnitude offset = 1.0/num_bins();
00161 const Magnitude scaled = (proportion-offset)/(1.0-offset);
00162
00163
00164 return Generic::crop(Magnitude(0.0),Magnitude(1.0),scaled);
00165 return scaled;
00166 }
00167
00169 Value weighted_sum() const
00170 { return std::inner_product(ISEQ(values),index_i(values.begin()),Value(0)); }
00171
00177 inline Magnitude weighted_average() const
00178 { return safe_divide((safe_divide(weighted_sum(),sum_value())),Value(num_bins()-1)); }
00179
00180
00186 inline static size_type undefined_values() { return undefined_vals; }
00187 inline static void undefined_values_reset(size_type val=0) { undefined_vals=val; }
00188
00192 inline Value total_value() const { return total_v; }
00193
00198 inline Count total_count() const { return total_c; }
00199
00201
00202
00203
00220 Vector vector_sum() const {
00221 if (total_count() != cached_vector_sum_count) {
00222 cached_vector_sum = std::inner_product
00223 (ISEQ(values), index_i(values.begin(),ScaleType(2*(Math::pi)/Value(num_bins()))),
00224 Vector(0,0),
00225
00226
00227 #if (__GNUC__ && (__GNUC__ < 3))
00228 plus<Vector>(),
00229 #else
00230 std::plus<Vector>(),
00231 #endif
00232
00233 Generic::Polar<Value>());
00234 cached_vector_sum_count = total_count();
00235 }
00236
00237 return cached_vector_sum;
00238 }
00239
00242 inline Vector vector_average() const { return vector_sum()/Value(num_bins()); }
00243
00260 inline Magnitude vector_direction() const {
00261 if (std::abs(vector_sum())==0) undefined_vals++;
00262 return Generic::wrap(0.0,1.0,std::arg(vector_sum())/(2*(Math::pi)));
00263 }
00264
00281 inline Magnitude vector_selectivity() const
00282 { return safe_divide(std::abs(vector_sum()),sum_value()); }
00284
00285
00286
00293 inline Value value(size_type i) const { return values[i]; }
00294 inline Count count(size_type i) const { return counts[i]; }
00295 inline Magnitude value_mag(size_type i) const { return safe_divide(values[i]*1.0,total_value()); }
00296 inline Magnitude count_mag(size_type i) const { return safe_divide(Magnitude(counts[i]),Magnitude(total_count())); }
00297
00298
00306 Magnitude relative_value(size_type bin) const
00307 { return safe_divide(value(bin),sum_value()); }
00309
00310
00329 size_type bin_number(Magnitude binmag) {
00330 return Generic::crop(size_type(0),size_type(num_bins())-size_type(1),
00331 size_type(binmag*num_bins()+float_adjust));
00332 }
00333
00334
00339 size_type bin_number_inclusive(Magnitude binmag) {
00340 return Generic::crop(size_type(0),size_type(num_bins()),
00341 size_type(binmag*(num_bins()-1)+float_adjust));
00342 }
00343
00344
00347 Magnitude bin_mag(size_type bin) { return Magnitude(bin)/Magnitude(num_bins()); }
00349
00350 private:
00351
00355 template <class T>
00356 inline T safe_divide(const T numerator, const T denominator) const
00357 { return (denominator==0? undefined_vals++, 0 : numerator/denominator); }
00358
00359 static size_type undefined_vals;
00360
00364 mutable Count cached_vector_sum_count;
00365 mutable Vector cached_vector_sum;
00366 mutable Count cached_sum_value_count;
00367 mutable Value cached_sum_value;
00369
00370 static const value_type float_adjust;
00371 };
00372
00373
00374
00375
00376 template<class Count, class Value> typename OneDBinList<Count,Value>::size_type
00377 OneDBinList<Count,Value>::num_bins_default=1;
00378 template<class Count, class Value> typename OneDBinList<Count,Value>::size_type
00379 OneDBinList<Count,Value>::undefined_vals=0;
00380
00384 template<class Count, class Value> const typename OneDBinList<Count,Value>::value_type
00385 OneDBinList<Count,Value>::float_adjust=1E-14;
00386
00387
00393 template<class Count, class Value>
00394 OneDBinList<Count,Value> operator-(const OneDBinList<Count,Value> &A, const OneDBinList<Count,Value> &B)
00395 {
00396 typename OneDBinList<Count,Value>::size_type N = A.num_bins();
00397 assert(N==B.num_bins());
00398
00399 OneDBinList<Count,Value> tmp(N);
00400
00401 for (typename OneDBinList<Count,Value>::size_type i=0; i<N; i++) {
00402 tmp.values[i] = A.values[i] - B.values[i];
00403 tmp.counts[i] = A.counts[i] - B.counts[i];
00404 }
00405
00406 tmp.total_v = A.total_v + B.total_v;
00407 tmp.total_c = A.total_c + B.total_c;
00408
00409 return tmp;
00410 }
00411
00412
00413
00423 template<class Count=int, class Value=double>
00424 class OneDHistogram : public OneDBinList<Count,Value> {
00425 public:
00426 typedef typename OneDBinList<Count,Value>::size_type size_type;
00427 OneDHistogram(const size_type num_bins)
00428 : OneDBinList<Count,Value>(num_bins) { }
00429 };
00430
00431
00432
00434 template<class Count=int, class Value=double>
00435 class OneDHistogramDifference : public OneDBinList<Count,Value> {
00436 public:
00437 OneDHistogramDifference(const OneDBinList<Count,Value> &A,
00438 const OneDBinList<Count,Value> &B)
00439 : OneDBinList<Count,Value>(A-B) { }
00440 };
00441
00442
00443
00444 }
00445 #endif