39 #include <type_traits> 42 #include <boost/math/constants/constants.hpp> 67 template<
typename Scalar_ =
double>
79 template<
typename Params2,
81 decltype((
int)std::declval<const Params2>().
min + (
int)std::declval<const Params2>().
max 82 + std::declval<Params2>().
num_bins) dummyval = 0>
114 <<
" out of range ["<<min<<
","<<max<<
"["));
141 return min + index * (max-
min) / num_bins;
153 return min + (index+boost::math::constants::half<Scalar>()) * (max-
min) / num_bins;
166 return min + (index+1) * (max-min) /
num_bins;
181 const auto halfbinres = boost::math::constants::half<Scalar>() *
binResolution();
210 template<
typename Scalar_,
typename CountType_ =
int>
225 static constexpr
bool HasErrorBars =
false;
238 template<
typename Params2 = Params,
240 decltype((
int)std::declval<const Params2>().
min + (
int)std::declval<const Params2>().
max 241 + std::declval<Params2>().
num_bins) dummyval = 0>
250 : params(min_, max_, num_bins), bins(
Eigen::Array<CountType,
Eigen::Dynamic,1>::Zero(num_bins)),
256 template<
typename HistogramType,
257 TOMOGRAPHER_ENABLED_IF_TMPL(HistogramType::HasErrorBars == 0 || HistogramType::HasErrorBars == 1)>
259 : params(other.params), bins(other.params.
num_bins), off_chart(other.off_chart)
261 bins = other.bins.template cast<CountType>();
281 template<
typename EigenType>
284 tomographer_assert(x.cols() == 1);
286 bins = x.derived().template cast<CountType>();
287 off_chart = off_chart_;
298 template<
typename EigenType>
304 tomographer_assert(x.cols() == 1);
306 bins += x.derived().template cast<CountType>();
307 off_chart += off_chart_;
318 template<
typename OtherScalar,
typename OtherCountType>
321 tomographer_assert(x.
bins.cols() == 1);
325 bins += x.
bins.template cast<CountType>();
413 bins(index) += weight;
431 template<
typename NewCountType = decltype(Scalar(1) + CountType(1))>
436 return NewCountType(off_chart) + NewCountType(
binResolution() * bins.sum());
445 template<
typename NewCountType = Scalar>
449 const NewCountType f = normalization<NewCountType>();
450 h.
load(bins.template cast<NewCountType>() / f, NewCountType(off_chart) / f);
473 template<
typename Scalar_,
typename CountType_ =
double>
492 static constexpr
bool HasErrorBars =
true;
500 using Base_::off_chart;
509 : Base_(params), delta(
Eigen::Array<CountType,
Eigen::Dynamic, 1>::Zero(params.
num_bins))
519 : Base_(min, max, num_bins), delta(
Eigen::Array<CountType,
Eigen::Dynamic, 1>::Zero(num_bins))
532 delta.
resize(Base_::numBins());
558 template<
typename EigenType,
typename EigenType2 = EigenType>
561 CountType off_chart_ = 0)
563 Base_::load(d, off_chart_);
564 tomographer_assert(derr.cols() == 1);
566 delta = derr.derived().template cast<CountType>();
576 template<
typename NewCountType = Scalar>
580 const NewCountType f = Base_::template normalization<NewCountType>();
581 h.
load(bins.template cast<NewCountType>() / f,
582 delta.template cast<NewCountType>() / f,
583 NewCountType(off_chart) / f);
592 template<
typename... Args>
593 inline void add(Args && ... )
613 template<
typename Scalar_,
typename CountType_>
654 template<
typename HistogramType_,
typename RealAvgType =
double>
676 static constexpr
bool HasErrorBars =
true;
693 : Base_(params), num_histograms(0)
703 : Base_(min, max, num_bins), num_histograms(0)
713 inline void reset(
const Params& params_)
715 Base_::params = params_;
750 TOMOGRAPHER_ENABLED_IF(!HistogramType::HasErrorBars)
751 inline
void addHistogram(const HistogramType& histogram)
756 tomographer_assert((
typename HistogramType::CountType)histogram.numBins() ==
757 (
typename HistogramType::CountType)Base_::numBins());
759 for (
std::size_t k = 0; k < histogram.numBins(); ++k) {
760 RealAvgType binvalue = histogram.count(k);
761 Base_::bins(k) += binvalue;
762 Base_::delta(k) += binvalue * binvalue;
765 Base_::off_chart += histogram.off_chart;
782 TOMOGRAPHER_ENABLED_IF(!HistogramType::HasErrorBars)
783 inline
void finalize()
785 Base_::bins /= num_histograms;
786 Base_::delta /= num_histograms;
787 Base_::off_chart /= num_histograms;
790 auto finhist2 = Base_::bins*Base_::bins;
791 Base_::delta = ( (Base_::delta - finhist2) / (num_histograms-1) ).sqrt();
812 TOMOGRAPHER_ENABLED_IF(HistogramType::HasErrorBars)
818 tomographer_assert((
typename HistogramType::CountType)histogram.numBins() == Base_::numBins());
820 for (
std::size_t k = 0; k < histogram.numBins(); ++k) {
821 RealAvgType binvalue = histogram.count(k);
822 Base_::bins(k) += binvalue;
823 RealAvgType bindelta = histogram.errorBar(k);
824 Base_::delta(k) += bindelta*bindelta;
827 Base_::off_chart += histogram.off_chart;
844 TOMOGRAPHER_ENABLED_IF(HistogramType::HasErrorBars)
845 inline
void finalize()
847 Base_::bins /= num_histograms;
848 Base_::off_chart /= num_histograms;
850 Base_::delta = Base_::delta.sqrt();
851 Base_::delta /= num_histograms;
868 namespace tomo_internal {
873 template<
typename Scalar,
typename Fn>
874 inline Scalar max_finite_value(
const std::size_t num_items, Fn val_generator,
875 const Scalar default_val =
Scalar(1.0))
877 bool has_first_val =
false;
878 Scalar max_val = default_val;
880 const Scalar this_val = val_generator(k);
881 if (
std::isfinite(this_val) && (!has_first_val || this_val > max_val)) {
883 has_first_val =
true;
892 template<
typename HistogramType>
893 struct histogram_pretty_print_label
897 labels.
resize(hist.numBins());
907 template<
typename HistogramType>
910 labels.
resize(hist.numBins());
912 const double max_label_val =
std::max(hist.binCenterValue(0), hist.binCenterValue(hist.numBins()-1));
914 const int relprecision = 4;
915 const int precision = (powten > relprecision) ? 0 : (relprecision - powten - 1);
920 labels[k] = ss.
str();
924 template<
typename Scalar_,
typename CountType_>
925 struct histogram_pretty_print_label<UniformBinsHistogram<Scalar_, CountType_> >
930 histogram_get_labels_for_hist_params<HistogramType>(labels, hist);
934 template<
typename Scalar_,
typename CountType_>
935 struct histogram_pretty_print_label<UniformBinsHistogramWithErrorBars<Scalar_, CountType_> >
940 histogram_get_labels_for_hist_params<HistogramType>(labels, hist);
944 template<
typename BaseHistogramType_,
typename RealAvgType_>
945 struct histogram_pretty_print_label<AveragedHistogram<BaseHistogramType_, RealAvgType_> >
950 histogram_get_labels_for_hist_params<HistogramType>(labels, hist);
955 template<
typename HistogramType>
956 struct histogram_pretty_print_value
959 histogram_pretty_print_value(
const HistogramType & hist_) : hist(hist_) { }
961 TOMOGRAPHER_ENABLED_IF(!HistogramType::HasErrorBars)
964 svalues.
resize(hist.numBins());
966 double max_val = max_finite_value(hist.numBins(), [&](
std::size_t k) {
return hist.count(k); }, 1.0);
969 const int relprecision = 3;
970 const int precision = abs_precision_for(powten, relprecision);
971 const int w = (precision > 0) ? (precision+powten+1) : (relprecision+2);
977 svalues[k] = ss.
str();
981 TOMOGRAPHER_ENABLED_IF(HistogramType::HasErrorBars)
984 svalues.
resize(hist.numBins());
986 double max_val = max_finite_value(hist.numBins(), [&](
std::size_t k) {
return hist.count(k); }, 1.0);
989 const int relprecision = 3;
990 const int precision = abs_precision_for(powten, relprecision);
991 const int w = (precision > 0) ? (precision+powten+2) : (relprecision+2);
996 << hist.count(k) <<
" +- " 999 svalues[k] = ss.
str();
1003 static inline int abs_precision_for(
const int powten,
const int relprecision)
1005 return (powten >= relprecision) ? 0 : (relprecision - powten - 1);
1013 template<
typename HistogramType>
1014 struct histogram_pretty_printer
1017 const int max_width;
1033 histogram_pretty_printer(
const HistogramType & hist_,
const int max_width_)
1034 : hist(hist_), max_width(max_width_), lsep(
" |"), rsep(
" ")
1040 labels.
resize(hist.numBins());
1041 svalues.
resize(hist.numBins());
1043 histogram_pretty_print_label<HistogramType>::getLabels(labels, hist);
1044 histogram_pretty_print_value<HistogramType>::getStrValues(svalues, hist);
1046 bool has_maxval =
false;
1047 for (
std::size_t k = 0; k < hist.numBins(); ++k) {
1048 const double val = maxval(k);
1050 if (
std::isfinite(val) && (!has_maxval || val > max_value)) {
1054 if (k == 0 || (
int)labels[k].size() > maxlabelwidth) {
1055 maxlabelwidth = labels[k].
size();
1057 if (k == 0 || (
int)svalues[k].size() > maxsvaluewidth) {
1058 maxsvaluewidth = svalues[k].
size();
1065 max_bar_width = max_width - maxlabelwidth - maxsvaluewidth - lsep.
size() - rsep.
size();
1066 if (max_bar_width < 2) {
1069 barscale = ((max_value > 0) ? (max_value / max_bar_width) : 1.0);
1072 inline int value_to_bar_length(
double val)
const 1077 int l = (int)(val/barscale+0.5);
1078 if (l >= max_bar_width) {
1079 return max_bar_width-1;
1084 inline void fill_str_len(
std::string & s,
double valstart,
double valend,
1085 char c,
char clside,
char crside)
const 1087 int vs = value_to_bar_length(valstart);
1088 int ve = value_to_bar_length(valend);
1089 tomographer_assert(vs >= 0);
1090 tomographer_assert(vs < (
int)s.
size());
1091 tomographer_assert(ve >= 0);
1092 tomographer_assert(ve < (
int)s.
size());
1093 for (
int j = vs; j < ve; ++j) {
1096 if (clside && crside && clside != crside && vs == ve) {
1097 if (ve < (
int)s.
size()-1) {
1099 }
else if (vs > 1) {
1118 for (k = 0; k < hist.numBins(); ++k) {
1119 str <<
std::setw(maxlabelwidth) << labels[k] << lsep
1120 << make_bar(k) << rsep <<
std::setw(maxsvaluewidth) << svalues[k] <<
"\n";
1126 TOMOGRAPHER_ENABLED_IF(!HistogramType::HasErrorBars)
1129 return (
double)hist.count(k);
1131 TOMOGRAPHER_ENABLED_IF(HistogramType::HasErrorBars)
1134 return (
double)(hist.count(k) + hist.errorBar(k));
1137 TOMOGRAPHER_ENABLED_IF(!HistogramType::HasErrorBars)
1141 fill_str_len(sbar, 0.0, hist.count(k),
'*', 0, 0);
1144 TOMOGRAPHER_ENABLED_IF(HistogramType::HasErrorBars)
1148 const double binval = hist.count(k);
1149 const double binerr = hist.errorBar(k);
1150 fill_str_len(sbar, 0.0, binval - binerr,
'*',
'*',
'*');
1151 fill_str_len(sbar, binval - binerr, binval + binerr,
'-',
'|',
'|');
1156 template<
typename HistogramType>
1158 const int max_width)
1162 if (histogram.off_chart > 0) {
1163 send +=
Tools::fmts(
" [+%.1g off]", (
double)histogram.off_chart);
1166 const int maxbarwidth = max_width - (int)s.
size() - (int)send.size();
1167 const int numdiv = (int)(
std::ceil((
float)histogram.numBins() / maxbarwidth) + 0.5f);
1168 const int barwidth = (int)(
std::ceil((
float)histogram.numBins() / numdiv) + 0.5f);
1171 Eigen::ArrayXf veclog(barwidth);
1174 float minlogval = 0;
1175 float maxlogval = 0;
1176 for (k = 0; k < barwidth; ++k) {
1178 (
std::size_t)(histogram.bins.size()-numdiv*k))).sum();
1181 veclog(k) =
std::log((
float)vec(k));
1183 veclog(k) = (float)vec(k);
1185 if (k == 0 || minlogval > veclog(k)) {
1186 minlogval = veclog(k);
1188 if (k == 0 || maxlogval < veclog(k)) {
1189 maxlogval = veclog(k) + 1e-6f;
1198 for (k = 0; k < barwidth; ++k) {
1202 int i = (int)(chars.
size() * (veclog(k) - minlogval) / (maxlogval - minlogval));
1203 if (i < 0) { i = 0; }
1204 if (i >= (
int)chars.
size()) { i = (int)chars.
size()-1; }
1225 template<
typename HistogramType>
1230 if (histogram.params.num_bins == 0) {
1231 str <<
"<empty histogram: no bins>\n";
1236 tomo_internal::histogram_pretty_printer<HistogramType>(histogram, max_width).pretty_print(str);
1247 template<
typename HistogramType>
1251 histogramPrettyPrint<HistogramType>(ss, histogram, max_width);
1272 template<
typename HistogramType>
1274 bool log_scale =
true,
int max_width = 0)
1281 if (histogram.params.num_bins == 0) {
1282 s =
"<empty histogram: no bins>";
1284 s = tomo_internal::histogram_short_bar_fmt<HistogramType>(histogram, log_scale, max_width);
1288 return max_width - (int)s.
size();
1300 template<
typename HistogramType>
1305 if (histogram.params.num_bins == 0) {
1306 return "<empty histogram: no bins>";
1310 return tomo_internal::histogram_short_bar_fmt<HistogramType>(histogram, log_scale, max_width);
1328 template<
typename HistogramType>
1331 const HistogramType& hist,
1333 bool log_scale =
true,
1334 int full_max_width = 0)
1357 template<
typename HistogramType>
1359 const HistogramType& hist,
1361 bool log_scale =
true,
1362 int full_max_width = 0)
Utilities for formatting strings.
Base namespace for the Tomographer project.
void histogramShortBarWithInfo(std::ostream &str, std::string head, const HistogramType &hist, std::string tail, bool log_scale=true, int full_max_width=0)
Format the histogram as a one-line bar, with some surrounding info.
Base_::Scalar Scalar
The histogram's X-axis scalar type. See UniformBinsHistogramWithErrorBars::Scalar.
Base_::Params Params
The histogram parameters' type. See UniformBinsHistogramWithErrorBars::Params.
int num_histograms
The number of histograms averaged.
SegmentReturnType segment(Index start, Index n)
void reset()
Resets the data keeping the exisiting params.
AveragedHistogram(const Params ¶ms=Params())
Constructs an AveragedHistogram with the given histogram parameters.
Combines several histograms (with same parameters) into an averaged histogram.
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.
UniformBinsHistogramWithErrorBars< typename HistogramType_::Scalar, RealAvgType > Base_
Shortcut for our base class' type.
Base_::CountType CountType
The histogram' count type. This is exactly the same as RealAvgType.
Some C++ utilities, with a tad of C++11 tricks.
void reset(const Params ¶ms_)
Resets the data and sets new params.
AveragedHistogram(Scalar min, Scalar max, std::size_t num_bins)
Constructs an AveragedHistogram with the given histogram parameters.
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.
HistogramType_ HistogramType
Type of the individual histograms we are averaging.
void resize(Index nbRows, Index nbCols)
#define streamstr(tokens)
Utility macro to format stream tokens to a std::string.
int histogramShortBar(std::ostream &str, const HistogramType &histogram, bool log_scale=true, int max_width=0)
Format the histogram as a one-line bar.
T setprecision(T... args)
Derived & setZero(Index size)