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 + "Stats.csv") << std::endl;
00072 std::ofstream ofs_stats((filePrefix + name + "Stats.csv").c_str());
00073 dumpStatsHeader(ofs_stats);
00074 ofs_stats << endl;
00075 dumpStats(ofs_stats);
00076
00077 std::cerr << "writing to " << (filePrefix + name + ".csv") << std::endl;
00078 std::ofstream ofs((filePrefix + name + ".csv").c_str());
00079 for (size_t i = 0; i < this->size(); ++i)
00080 ofs << ((*this)[i]) << "\n";
00081 }
00082
00083 if (dumpStdErrOnExit)
00084 {
00085 std::cerr.precision(4);
00086 std::cerr.fill(' ');
00087 std::cerr.flags(std::ios::left);
00088 std::cerr << "Histogram " << name << ":\n";
00089 std::cerr << " count: " << this->size() << ", mean: " << meanV << ", var: " << varV << ", median: " << medianV << ", min: " << minV << ", max: " << maxV << ", lowQt: " << lowQt << ", highQt: " << highQt << ", maxBinC: " << maxBinC << "\n";
00090 if(this->size() > 1)
00091 {
00092 for (size_t i = 0; i < binCount; ++i)
00093 {
00094 const T v(minV + i * (maxV - minV) / T(binCount));
00095 std::cerr << " " << std::setw(10) << v << " (" << std::setw(6) << bins[i] << ") : ";
00096
00097 if (maxBinC > 0) {
00098 for (size_t j = 0; j < (bins[i] * 60) / maxBinC; ++j)
00099 std::cerr << "*";
00100 }
00101 std::cerr << "\n";
00102 }
00103 std::cerr << std::endl;
00104 }
00105 }
00106 }
00107
00108 template<typename T>
00109 vector<uint64_t> Histogram<T>::computeStats(T& meanV, T& varV, T& medianV, T& lowQt, T& highQt, T& minV, T& maxV, uint64_t& maxBinC)
00110 {
00111 typedef typename std::vector<T>::iterator Iterator;
00112 vector<uint64_t> bins(binCount, 0);
00113
00114
00115 if(this->size() > 0)
00116 {
00117
00118 meanV = 0;
00119 minV = std::numeric_limits<T>::max();
00120 maxV = std::numeric_limits<T>::min();
00121 for (size_t i = 0; i < this->size(); ++i)
00122 {
00123 const T v((*this)[i]);
00124 meanV += v;
00125 minV = std::min<T>(minV, v);
00126 maxV = std::max<T>(maxV, v);
00127 }
00128 meanV /= T(this->size());
00129
00130 std::fill(bins.begin(), bins.end(), uint64_t(0));
00131 maxBinC = 0;
00132 varV = 0;
00133 if (minV == maxV)
00134 {
00135 medianV = lowQt = highQt = minV;
00136 return bins;
00137 }
00138 for (size_t i = 0; i < this->size(); ++i)
00139 {
00140 const T v((*this)[i]);
00141 varV += (v - meanV)*(v - meanV);
00142 const size_t index((v - minV) * (binCount) / ((maxV - minV) * (1+std::numeric_limits<T>::epsilon()*10)));
00143
00144 ++bins[index];
00145 maxBinC = std::max<uint64_t>(maxBinC, bins[index]);
00146 }
00147 varV /= T(this->size());
00148
00149 const Iterator lowQtIt(this->begin() + (this->size() / 4));
00150 const Iterator medianIt(this->begin() + (this->size() / 2));
00151 const Iterator highQtIt(this->begin() + (3*this->size() / 4));
00152 std::nth_element(this->begin(), medianIt, this->end());
00153 medianV = *medianIt;
00154 std::nth_element(this->begin(), lowQtIt, this->end());
00155 lowQt = *lowQtIt;
00156 std::nth_element(this->begin(), highQtIt, this->end());
00157 highQt = *highQtIt;
00158 }
00159 else
00160 {
00161 meanV = std::numeric_limits<T>::quiet_NaN();
00162 varV = std::numeric_limits<T>::quiet_NaN();
00163 medianV = std::numeric_limits<T>::quiet_NaN();
00164 lowQt = std::numeric_limits<T>::quiet_NaN();
00165 highQt = std::numeric_limits<T>::quiet_NaN();
00166 minV = std::numeric_limits<T>::quiet_NaN();
00167 maxV = std::numeric_limits<T>::quiet_NaN();
00168 maxBinC = 0;
00169 }
00170 return bins;
00171 }
00172
00173 template<typename T>
00174 void Histogram<T>::dumpStats(std::ostream& os)
00175 {
00176 T meanV, varV, medianV, lowQt, highQt, minV, maxV;
00177 uint64_t maxBinC;
00178 const vector<uint64_t> bins(computeStats(meanV, varV, medianV, lowQt, highQt, minV, maxV, maxBinC));
00179 os << this->size() << ", " << meanV << ", " << varV << ", " << medianV << ", " << lowQt << ", " << highQt << ", " << minV << ", " << maxV << ", " << binCount << ", ";
00180
00181 for (size_t i = 0; i < binCount; ++i)
00182 os << bins[i] << ", ";
00183 os << maxBinC;
00184 }
00185
00186 template<typename T>
00187 void Histogram<T>::dumpStatsHeader(std::ostream& os) const
00188 {
00189 os << name + "_count, ";
00190 os << name + "_mean, ";
00191 os << name + "_var, ";
00192 os << name + "_median, ";
00193 os << name + "_low_quartile, ";
00194 os << name + "_high_quartile, ";
00195 os << name + "_min_value, ";
00196 os << name + "_max_value, ";
00197 os << name + "_bin_count, ";
00198 for (size_t i = 0; i < binCount; ++i)
00199 os << (boost::format("%1%_bin_%2%,") % name % i).str();
00200 os << name + "_max_elements_per_bin ";
00201 }
00202
00203 template struct Histogram<unsigned>;
00204 template struct Histogram<float>;
00205 template struct Histogram<double>;
00206 }