37 #include <type_traits> 40 #include <boost/math/constants/constants.hpp> 67 template<
typename Scalar_,
typename CountType_ =
unsigned int>
94 template<
typename OtherParams
127 <<
" out of range ["<<min<<
","<<max<<
"["));
154 return min + index * (max-
min) / num_bins;
166 return min + (index+boost::math::constants::half<Scalar>()) * (max-
min) / num_bins;
179 return min + (index+1) * (max-min) /
num_bins;
207 : params(min_, max_, num_bins), bins(
Eigen::Array<CountType,
Eigen::Dynamic,1>::Zero(num_bins)),
213 template<
typename HistogramType>
215 : params(other.params), bins(other.params.
num_bins), off_chart(other.off_chart)
217 bins = other.bins.template cast<CountType>();
223 bins.
resize(params.num_bins);
237 template<
typename EigenType>
240 tomographer_assert(x.cols() == 1);
241 tomographer_assert((
std::size_t)x.rows() == params.num_bins);
242 bins = x.derived().template cast<CountType>();
243 off_chart = off_chart_;
254 template<
typename EigenType>
260 tomographer_assert(x.cols() == 1);
261 tomographer_assert((
std::size_t)x.rows() == params.num_bins);
262 bins += x.derived().template cast<CountType>();
263 off_chart += off_chart_;
274 template<
typename OtherScalar,
typename OtherCountType>
277 tomographer_assert(x.
bins.cols() == 1);
281 bins += x.
bins.template cast<CountType>();
288 return params.num_bins;
300 return params.isWithinBounds(value);
305 return params.binIndex(value);
310 return params.binLowerValue(index);
315 return params.binCenterValue(index);
320 return params.binUpperValue(index);
326 return params.binResolution();
345 const std::size_t index = params.binIndexUnsafe(value);
368 const std::size_t index = params.binIndexUnsafe(value);
369 bins(index) += weight;
392 template<
typename Scalar_,
typename CountType_ =
double>
410 static constexpr
bool HasErrorBars =
true;
418 using Base_::off_chart;
427 : Base_(params), delta(
Eigen::Array<CountType,
Eigen::Dynamic, 1>::Zero(params.
num_bins))
437 : Base_(min, max, num_bins), delta(
Eigen::Array<CountType,
Eigen::Dynamic, 1>::Zero(num_bins))
450 delta.
resize(Base_::numBins());
477 template<
typename Scalar_,
typename CountType_>
518 template<
typename HistogramType_,
typename RealAvgType =
double>
539 static constexpr
bool HasErrorBars =
true;
556 : Base_(params), num_histograms(0)
566 inline void reset(
const Params& params_)
568 Base_::params = params_;
603 TOMOGRAPHER_ENABLED_IF(!HistogramType::HasErrorBars)
604 inline
void addHistogram(const HistogramType& histogram)
609 tomographer_assert((
typename HistogramType::CountType)histogram.numBins() ==
610 (
typename HistogramType::CountType)Base_::numBins());
612 for (
std::size_t k = 0; k < histogram.numBins(); ++k) {
613 RealAvgType binvalue = histogram.count(k);
614 Base_::bins(k) += binvalue;
615 Base_::delta(k) += binvalue * binvalue;
618 Base_::off_chart += histogram.off_chart;
635 TOMOGRAPHER_ENABLED_IF(!HistogramType::HasErrorBars)
636 inline
void finalize()
638 Base_::bins /= num_histograms;
639 Base_::delta /= num_histograms;
640 Base_::off_chart /= num_histograms;
643 auto finhist2 = Base_::bins*Base_::bins;
644 Base_::delta = ( (Base_::delta - finhist2) / (num_histograms-1) ).sqrt();
665 TOMOGRAPHER_ENABLED_IF(HistogramType::HasErrorBars)
671 tomographer_assert((
typename HistogramType::CountType)histogram.numBins() == Base_::numBins());
673 for (
std::size_t k = 0; k < histogram.numBins(); ++k) {
674 RealAvgType binvalue = histogram.count(k);
675 Base_::bins(k) += binvalue;
676 RealAvgType bindelta = histogram.errorBar(k);
677 Base_::delta(k) += bindelta*bindelta;
680 Base_::off_chart += histogram.off_chart;
697 TOMOGRAPHER_ENABLED_IF(HistogramType::HasErrorBars)
698 inline
void finalize()
700 Base_::bins /= num_histograms;
701 Base_::off_chart /= num_histograms;
703 Base_::delta = Base_::delta.sqrt();
704 Base_::delta /= num_histograms;
721 namespace tomo_internal {
726 template<
typename Scalar,
typename Fn>
730 bool has_first_val =
false;
731 Scalar max_val = default_val;
733 const Scalar this_val = val_generator(k);
734 if (
std::isfinite(this_val) && (!has_first_val || this_val > max_val)) {
736 has_first_val =
true;
745 template<
typename HistogramType>
746 struct histogram_pretty_print_label
750 labels.
resize(hist.numBins());
760 template<
typename HistogramType>
763 labels.
resize(hist.numBins());
765 const double max_label_val =
std::max(hist.binCenterValue(0), hist.binCenterValue(hist.numBins()-1));
767 const int relprecision = 4;
768 const int precision = (powten > relprecision) ? 0 : (relprecision - powten - 1);
773 labels[k] = ss.
str();
777 template<
typename Scalar_,
typename CountType_>
778 struct histogram_pretty_print_label<UniformBinsHistogram<Scalar_, CountType_> >
783 histogram_get_labels_for_hist_params<HistogramType>(labels, hist);
787 template<
typename Scalar_,
typename CountType_>
788 struct histogram_pretty_print_label<UniformBinsHistogramWithErrorBars<Scalar_, CountType_> >
793 histogram_get_labels_for_hist_params<HistogramType>(labels, hist);
797 template<
typename BaseHistogramType_,
typename RealAvgType_>
798 struct histogram_pretty_print_label<AveragedHistogram<BaseHistogramType_, RealAvgType_> >
803 histogram_get_labels_for_hist_params<HistogramType>(labels, hist);
808 template<
typename HistogramType>
809 struct histogram_pretty_print_value
812 histogram_pretty_print_value(
const HistogramType & hist_) : hist(hist_) { }
814 TOMOGRAPHER_ENABLED_IF(!HistogramType::HasErrorBars)
817 svalues.
resize(hist.numBins());
819 double max_val = max_finite_value(hist.numBins(), [&](
std::size_t k) {
return hist.count(k); }, 1.0);
822 const int relprecision = 3;
823 const int precision = abs_precision_for(powten, relprecision);
824 const int w = (precision > 0) ? (precision+powten+1) : (relprecision+2);
830 svalues[k] = ss.
str();
834 TOMOGRAPHER_ENABLED_IF(HistogramType::HasErrorBars)
837 svalues.
resize(hist.numBins());
839 double max_val = max_finite_value(hist.numBins(), [&](
std::size_t k) {
return hist.count(k); }, 1.0);
842 const int relprecision = 3;
843 const int precision = abs_precision_for(powten, relprecision);
844 const int w = (precision > 0) ? (precision+powten+2) : (relprecision+2);
849 << hist.count(k) <<
" +- " 852 svalues[k] = ss.
str();
856 static inline int abs_precision_for(
const int powten,
const int relprecision)
858 return (powten > relprecision) ? 0 : (relprecision - powten - 1);
866 template<
typename HistogramType>
867 struct histogram_pretty_printer
886 histogram_pretty_printer(
const HistogramType & hist_,
const int max_width_)
887 : hist(hist_), max_width(max_width_), lsep(
" |"), rsep(
" ")
893 labels.
resize(hist.numBins());
894 svalues.
resize(hist.numBins());
896 histogram_pretty_print_label<HistogramType>::getLabels(labels, hist);
897 histogram_pretty_print_value<HistogramType>::getStrValues(svalues, hist);
899 bool has_maxval =
false;
901 const double val = maxval(k);
903 if (
std::isfinite(val) && (!has_maxval || val > max_value)) {
907 if (k == 0 || (
int)labels[k].size() > maxlabelwidth) {
908 maxlabelwidth = labels[k].
size();
910 if (k == 0 || (
int)svalues[k].size() > maxsvaluewidth) {
911 maxsvaluewidth = svalues[k].
size();
918 max_bar_width = max_width - maxlabelwidth - maxsvaluewidth - lsep.
size() - rsep.
size();
919 if (max_bar_width < 2) {
922 barscale = ((max_value > 0) ? (max_value / max_bar_width) : 1.0);
925 inline int value_to_bar_length(
double val)
const 930 int l = (int)(val/barscale+0.5);
931 if (l >= max_bar_width) {
932 return max_bar_width-1;
937 inline void fill_str_len(
std::string & s,
double valstart,
double valend,
938 char c,
char clside,
char crside)
const 940 int vs = value_to_bar_length(valstart);
941 int ve = value_to_bar_length(valend);
942 tomographer_assert(vs >= 0);
943 tomographer_assert(vs < (
int)s.
size());
944 tomographer_assert(ve >= 0);
945 tomographer_assert(ve < (
int)s.
size());
946 for (
int j = vs; j < ve; ++j) {
949 if (clside && crside && clside != crside && vs == ve) {
950 if (ve < (
int)s.
size()-1) {
971 for (k = 0; k < hist.numBins(); ++k) {
972 str <<
std::setw(maxlabelwidth) << labels[k] << lsep
973 << make_bar(k) << rsep <<
std::setw(maxsvaluewidth) << svalues[k] <<
"\n";
979 TOMOGRAPHER_ENABLED_IF(!HistogramType::HasErrorBars)
982 return (
double)hist.count(k);
984 TOMOGRAPHER_ENABLED_IF(HistogramType::HasErrorBars)
987 return (
double)(hist.count(k) + hist.errorBar(k));
990 TOMOGRAPHER_ENABLED_IF(!HistogramType::HasErrorBars)
994 fill_str_len(sbar, 0.0, hist.count(k),
'*', 0, 0);
997 TOMOGRAPHER_ENABLED_IF(HistogramType::HasErrorBars)
1001 const double binval = hist.count(k);
1002 const double binerr = hist.errorBar(k);
1003 fill_str_len(sbar, 0.0, binval - binerr,
'*',
'*',
'*');
1004 fill_str_len(sbar, binval - binerr, binval + binerr,
'-',
'|',
'|');
1009 template<
typename HistogramType>
1011 const int max_width)
1015 if (histogram.off_chart > 0) {
1016 send +=
Tools::fmts(
" [+%.1g off]", (
double)histogram.off_chart);
1019 const int maxbarwidth = max_width - s.
size() - send.size();
1020 const int numdiv = (int)(
std::ceil((
float)histogram.numBins() / maxbarwidth) + 0.5f);
1021 const int barwidth = (int)(
std::ceil((
float)histogram.numBins() / numdiv) + 0.5f);
1024 Eigen::ArrayXf veclog(barwidth);
1027 float minlogval = 0;
1028 float maxlogval = 0;
1029 for (k = 0; k < barwidth; ++k) {
1031 (
std::size_t)(histogram.bins.size()-numdiv*k))).sum();
1034 veclog(k) =
std::log((
float)vec(k));
1036 veclog(k) = (float)vec(k);
1038 if (k == 0 || minlogval > veclog(k)) {
1039 minlogval = veclog(k);
1041 if (k == 0 || maxlogval < veclog(k)) {
1042 maxlogval = veclog(k) + 1e-6f;
1051 for (k = 0; k < barwidth; ++k) {
1055 int i = (int)(chars.
size() * (veclog(k) - minlogval) / (maxlogval - minlogval));
1056 if (i < 0) { i = 0; }
1057 if (i >= (
int)chars.
size()) { i = chars.
size()-1; }
1078 template<
typename HistogramType>
1083 if (histogram.params.num_bins == 0) {
1084 str <<
"<empty histogram: no bins>\n";
1089 tomo_internal::histogram_pretty_printer<HistogramType>(histogram, max_width).pretty_print(str);
1100 template<
typename HistogramType>
1104 histogramPrettyPrint<HistogramType>(ss, histogram, max_width);
1125 template<
typename HistogramType>
1127 bool log_scale =
true,
int max_width = 0)
1134 if (histogram.params.num_bins == 0) {
1135 s =
"<empty histogram: no bins>";
1137 s = tomo_internal::histogram_short_bar_fmt<HistogramType>(histogram, log_scale, max_width);
1141 return max_width - s.
size();
1153 template<
typename HistogramType>
1158 if (histogram.params.num_bins == 0) {
1159 return "<empty histogram: no bins>";
1163 return tomo_internal::histogram_short_bar_fmt<HistogramType>(histogram, log_scale, max_width);
Utilities for formatting strings.
Combines several histograms (with same parameters) into an averaged histogram.
Base_::Params Params
The histogram parameters' type. See UniformBinsHistogramWithErrorBars::Params.
Base namespace for the Tomographer project.
int num_histograms
The number of histograms averaged.
Base_::CountType CountType
The histogram' count type. This is exactly the same as RealAvgType.
void reset()
Resets the data keeping the exisiting params.
#define streamstr(tokens)
Utility macro to format stream tokens to a std::string.
UniformBinsHistogramWithErrorBars< typename HistogramType_::Scalar, RealAvgType > Base_
Shortcut for our base class' type.
SegmentReturnType segment(Index start, Index n)
Base_::Scalar Scalar
The histogram's X-axis scalar type. See UniformBinsHistogramWithErrorBars::Scalar.
void histogramPrettyPrint(std::ostream &str, const HistogramType &histogram, int max_width=0)
pretty-print the given histogram.
Basic utilities for dealing with Eigen matrices and other types.
HistogramType_ HistogramType
Type of the individual histograms we are averaging.
Some C++ utilities, with a tad of C++11 tricks.
Managing the need for specific overrides to operator new() for some types (especially Eigen types) ...
VarValueDecoder< T >::RetType value(const Var &var)
Access the value of the given variable, as a C++ type.
void reset(const Params ¶ms_)
Resets the data and sets new params.
AveragedHistogram(const Params ¶ms=Params())
Constructs an AveragedHistogram with the given histogram parameters.
void resize(Index nbRows, Index nbCols)
int histogramShortBar(std::ostream &str, const HistogramType &histogram, bool log_scale=true, int max_width=0)
Format the histogram as a one-line bar.
Derived & setZero(Index size)