00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include "Histogram.h"
00037
00038 #include <iostream>
00039 #include <fstream>
00040 #include <iomanip>
00041 #include <limits>
00042 #include <algorithm>
00043 #include <boost/format.hpp>
00044
00045 namespace PointMatcherSupport
00046 {
00047 using namespace std;
00048
00049 template<typename T>
00050 Histogram<T>::Histogram(const size_t binCount, const std::string& name, const std::string&
00051 filePrefix, const bool dumpStdErrOnExit):
00052 binCount(binCount),
00053 name(name),
00054 filePrefix(filePrefix),
00055 dumpStdErrOnExit(dumpStdErrOnExit)
00056 {
00057 }
00058
00059 template<typename T>
00060 Histogram<T>::~Histogram()
00061 {
00062 T meanV, varV, medianV, lowQt, highQt, minV, maxV;
00063 uint64_t maxBinC;
00064 if (!dumpStdErrOnExit && filePrefix.empty())
00065 return;
00066
00067 const vector<uint64_t> bins(computeStats(meanV, varV, medianV, lowQt, highQt, minV, maxV, maxBinC));
00068
00069 if (!filePrefix.empty())
00070 {
00071 std::cerr << "writing to " << (filePrefix + name) << std::endl;
00072 std::ofstream ofs((filePrefix + name).c_str());
00073 for (size_t i = 0; i < this->size(); ++i)
00074 ofs << ((*this)[i]) << "\n";
00075 }
00076
00077 if (dumpStdErrOnExit)
00078 {
00079 std::cerr.precision(4);
00080 std::cerr.fill(' ');
00081 std::cerr.flags(std::ios::left);
00082 std::cerr << "Histogram " << name << ":\n";
00083 std::cerr << " count: " << this->size() << ", mean: " << meanV << "\n";
00084 if(this->size() > 1)
00085 {
00086 for (size_t i = 0; i < binCount; ++i)
00087 {
00088 const T v(minV + i * (maxV - minV) / T(binCount));
00089 std::cerr << " " << std::setw(10) << v << " (" << std::setw(6) << bins[i] << ") : ";
00090
00091 for (size_t j = 0; j < (bins[i] * 60) / maxBinC; ++j)
00092 std::cerr << "*";
00093 std::cerr << "\n";
00094 }
00095 std::cerr << std::endl;
00096 }
00097 }
00098 }
00099
00100 template<typename T>
00101 vector<uint64_t> Histogram<T>::computeStats(T& meanV, T& varV, T& medianV, T& lowQt, T& highQt, T& minV, T& maxV, uint64_t& maxBinC)
00102 {
00103 typedef typename std::vector<T>::iterator Iterator;
00104 vector<uint64_t> bins(binCount, 0);
00105
00106
00107 if(this->size() > 0)
00108 {
00109
00110 meanV = 0;
00111 minV = std::numeric_limits<T>::max();
00112 maxV = std::numeric_limits<T>::min();
00113 for (size_t i = 0; i < this->size(); ++i)
00114 {
00115 const T v((*this)[i]);
00116 meanV += v;
00117 minV = std::min<T>(minV, v);
00118 maxV = std::max<T>(maxV, v);
00119 }
00120 meanV /= T(this->size());
00121
00122 std::fill(bins.begin(), bins.end(), uint64_t(0));
00123 maxBinC = 0;
00124 varV = 0;
00125 if (minV == maxV)
00126 {
00127 medianV = lowQt = highQt = minV;
00128 return bins;
00129 }
00130 for (size_t i = 0; i < this->size(); ++i)
00131 {
00132 const T v((*this)[i]);
00133 varV += (v - meanV)*(v - meanV);
00134 const size_t index((v - minV) * (binCount) / ((maxV - minV) * (1+std::numeric_limits<T>::epsilon()*10)));
00135
00136 ++bins[index];
00137 maxBinC = std::max<uint64_t>(maxBinC, bins[index]);
00138 }
00139 varV /= T(this->size());
00140
00141 const Iterator lowQtIt(this->begin() + (this->size() / 4));
00142 const Iterator medianIt(this->begin() + (this->size() / 2));
00143 const Iterator highQtIt(this->begin() + (3*this->size() / 4));
00144 std::nth_element(this->begin(), medianIt, this->end());
00145 medianV = *medianIt;
00146 std::nth_element(this->begin(), lowQtIt, this->end());
00147 lowQt = *lowQtIt;
00148 std::nth_element(this->begin(), highQtIt, this->end());
00149 highQt = *highQtIt;
00150 }
00151 else
00152 {
00153 meanV = std::numeric_limits<T>::quiet_NaN();
00154 varV = std::numeric_limits<T>::quiet_NaN();
00155 medianV = std::numeric_limits<T>::quiet_NaN();
00156 lowQt = std::numeric_limits<T>::quiet_NaN();
00157 highQt = std::numeric_limits<T>::quiet_NaN();
00158 minV = std::numeric_limits<T>::quiet_NaN();
00159 maxV = std::numeric_limits<T>::quiet_NaN();
00160 maxBinC = 0;
00161 }
00162 return bins;
00163 }
00164
00165 template<typename T>
00166 void Histogram<T>::dumpStats(std::ostream& os)
00167 {
00168 T meanV, varV, medianV, lowQt, highQt, minV, maxV;
00169 uint64_t maxBinC;
00170 const vector<uint64_t> bins(computeStats(meanV, varV, medianV, lowQt, highQt, minV, maxV, maxBinC));
00171 os << this->size() << ", " << meanV << ", " << varV << ", " << medianV << ", " << lowQt << ", " << highQt << ", " << minV << ", " << maxV << ", " << binCount << ", ";
00172
00173 for (size_t i = 0; i < binCount; ++i)
00174 os << bins[i] << ", ";
00175 os << maxBinC;
00176 }
00177
00178 template<typename T>
00179 void Histogram<T>::dumpStatsHeader(std::ostream& os) const
00180 {
00181 os << name + "_count, ";
00182 os << name + "_mean, ";
00183 os << name + "_var, ";
00184 os << name + "_median, ";
00185 os << name + "_low_quartile, ";
00186 os << name + "_high_quartile, ";
00187 os << name + "_min_value, ";
00188 os << name + "_max_value, ";
00189 os << name + "_bin_count, ";
00190 for (size_t i = 0; i < binCount; ++i)
00191 os << (boost::format("%1%_bin_%2%,") % name % i).str();
00192 os << name + "_max_elements_per_bin ";
00193 }
00194
00195 template struct Histogram<unsigned>;
00196 template struct Histogram<float>;
00197 template struct Histogram<double>;
00198 }