00001 #ifndef CCTBX_MAPTBX_STATISTICS_H
00002 #define CCTBX_MAPTBX_STATISTICS_H
00003
00004 #include <scitbx/array_family/accessors/flex_grid.h>
00005 #include <scitbx/array_family/loops.h>
00006 #include <scitbx/math/utils.h>
00007 #include <scitbx/math/accumulators.h>
00008 #include <cctbx/error.h>
00009 #include <cctbx/import_scitbx_af.h>
00010
00011 namespace cctbx { namespace maptbx {
00012
00013 namespace details {
00014 template <class AccumulatorType>
00015 struct generic_statistics
00016 {
00017 generic_statistics() : accumulator(0) {}
00018
00019 template <typename FloatType>
00020 generic_statistics(af::const_ref<FloatType, af::flex_grid<> > const& map)
00021 : accumulator(0)
00022 {
00023 CCTBX_ASSERT(map.accessor().focus_size_1d() > 0);
00024 if (!map.accessor().is_padded()) {
00025 accumulator = AccumulatorType(map[0]);
00026 for(std::size_t i=1; i < map.size(); ++i) accumulator(map[i]);
00027 }
00028 else {
00029 typedef typename af::flex_grid<>::index_type index_type;
00030 af::flex_grid<> zero_based = map.accessor().shift_origin();
00031 af::nested_loop<index_type> iter(zero_based.focus());
00032 accumulator = AccumulatorType(map[zero_based(iter())]);
00033 while (iter.incr()) accumulator(map[zero_based(iter())]);
00034 }
00035 }
00036
00037 AccumulatorType accumulator;
00038 };
00039
00040 template <class AccumulatorType>
00041 struct generic_statistical_moments
00042 {
00043 generic_statistical_moments() : accumulator(0,1) {}
00044
00045 template <typename FloatType, typename OtherFloatType>
00046 generic_statistical_moments(
00047 af::const_ref<OtherFloatType, af::flex_grid<> > const& map,
00048 FloatType about, FloatType width
00049 )
00050 : accumulator(about, width)
00051 {
00052 CCTBX_ASSERT(map.accessor().focus_size_1d() > 0);
00053 if (width == 0) return;
00054 if (!map.accessor().is_padded()) {
00055 for(std::size_t i=0; i < map.size(); ++i) accumulator(map[i]);
00056 }
00057 else {
00058 typedef typename af::flex_grid<>::index_type index_type;
00059 af::flex_grid<> zero_based = map.accessor().shift_origin();
00060 for(af::nested_loop<index_type> iter(zero_based.focus());
00061 !iter.over(); iter.incr()) accumulator(map[zero_based(iter())]);
00062 }
00063 }
00064
00065 AccumulatorType accumulator;
00066 };
00067
00068 using namespace scitbx::math::accumulator;
00069
00070 template <typename FloatType = double>
00071 struct statistics_traits {
00072 typedef generic_statistics<
00073 min_max_accumulator<FloatType,
00074 mean_variance_accumulator<FloatType,
00075 enumerated_accumulator<FloatType> > > >
00076 basic_statistics_t;
00077 typedef generic_statistical_moments<
00078 skewness_accumulator<FloatType,
00079 kurtosis_accumulator<FloatType,
00080 normalised_deviation_accumulator<FloatType> > > >
00081 extra_statistics_t;
00082 };
00083 }
00084
00086 template <typename FloatType = double>
00087 class statistics
00088 {
00089 public:
00091 statistics() : basic_stats() {}
00092
00094 template <typename OtherFloatType>
00095 statistics(af::const_ref<OtherFloatType, af::flex_grid<> > const& map)
00096 : basic_stats(map)
00097 {}
00098
00099 FloatType
00100 min() const { return basic_stats.accumulator.min(); }
00101
00102 FloatType
00103 max() const { return basic_stats.accumulator.max(); }
00104
00105 FloatType
00106 mean() const { return basic_stats.accumulator.mean(); }
00107
00108 FloatType
00109 mean_sq() const { return basic_stats.accumulator.mean_squares(); }
00110
00111 FloatType
00112 sigma() const {
00113 return basic_stats.accumulator.biased_standard_deviation();
00114 }
00115
00116 private:
00117 typedef typename details::statistics_traits<FloatType>::basic_statistics_t
00118 basic_statistics_t;
00119 basic_statistics_t basic_stats;
00120 };
00121
00122
00124 template <typename FloatType = double>
00125 class more_statistics : public statistics<FloatType>
00126 {
00127 public:
00129 more_statistics() : statistics<FloatType>(), extra_stats() {}
00130
00132 template <typename OtherFloatType>
00133 more_statistics(af::const_ref<OtherFloatType, af::flex_grid<> > const& map)
00134 : statistics<FloatType>(map),
00135 extra_stats(map, this->mean(), this->sigma())
00136 {}
00137
00138 FloatType
00139 skewness() const { return extra_stats.accumulator.skewness(); }
00140
00141 FloatType
00142 kurtosis() const { return extra_stats.accumulator.kurtosis(); }
00143
00144 private:
00145 typedef typename details::statistics_traits<FloatType>::extra_statistics_t
00146 extra_statistics_t;
00147 extra_statistics_t extra_stats;
00148 };
00149
00150 }}
00151
00152 #endif // CCTBX_MAPTBX_STATISTICS_H