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>
228 static constexpr
bool HasErrorBars =
false;
241 template<
typename Params2 = Params,
243 decltype((
int)std::declval<const Params2>().
min + (
int)std::declval<const Params2>().
max 244 + std::declval<Params2>().
num_bins) dummyval = 0>
253 : params(min_, max_, num_bins), bins(
Eigen::Array<CountType,
Eigen::Dynamic,1>::Zero(num_bins)),
259 template<
typename HistogramType,
260 TOMOGRAPHER_ENABLED_IF_TMPL(HistogramType::HasErrorBars == 0 || HistogramType::HasErrorBars == 1)>
262 : params(other.params), bins(other.params.
num_bins), off_chart(other.off_chart)
264 bins = other.bins.template cast<CountType>();
284 template<
typename EigenType>
289 bins = x.derived().template cast<CountType>();
290 off_chart = off_chart_;
301 template<
typename EigenType>
309 bins += x.derived().template cast<CountType>();
310 off_chart += off_chart_;
321 template<
typename OtherScalar,
typename OtherCountType>
328 bins += x.
bins.template cast<CountType>();
416 bins(index) += weight;
434 template<
typename NewCountType = decltype(Scalar(1) + CountType(1))>
439 return NewCountType(off_chart) + NewCountType(
binResolution() * bins.sum());
448 template<
typename NewCountType = Scalar>
452 const NewCountType f = normalization<NewCountType>();
453 h.
load(bins.template cast<NewCountType>() / f, NewCountType(off_chart) / f);
476 template<
typename Scalar_,
typename CountType_ =
double>
495 static constexpr
bool HasErrorBars =
true;
503 using Base_::off_chart;
512 : Base_(params), delta(
Eigen::Array<CountType,
Eigen::Dynamic, 1>::Zero(params.
num_bins))
522 : Base_(min, max, num_bins), delta(
Eigen::Array<CountType,
Eigen::Dynamic, 1>::Zero(num_bins))
535 delta.
resize(Base_::numBins());
561 template<
typename EigenType,
typename EigenType2 = EigenType>
564 CountType off_chart_ = 0)
566 Base_::load(d, off_chart_);
569 delta = derr.derived().template cast<CountType>();
579 template<
typename NewCountType = Scalar>
583 const NewCountType f = Base_::template normalization<NewCountType>();
584 h.
load(bins.template cast<NewCountType>() / f,
585 delta.template cast<NewCountType>() / f,
586 NewCountType(off_chart) / f);
595 template<
typename... Args>
596 inline void add(Args && ... )
616 template<
typename Scalar_,
typename CountType_>
657 template<
typename HistogramType_,
typename RealAvgType =
double>
679 static constexpr
bool HasErrorBars =
true;
696 : Base_(params), num_histograms(0)
706 : Base_(min, max, num_bins), num_histograms(0)
716 inline void reset(
const Params& params_)
718 Base_::params = params_;
753 TOMOGRAPHER_ENABLED_IF(!HistogramType::HasErrorBars)
754 inline
void addHistogram(const HistogramType& histogram)
760 (
typename HistogramType::CountType)Base_::numBins());
762 for (
std::size_t k = 0; k < histogram.numBins(); ++k) {
763 RealAvgType binvalue = histogram.count(k);
764 Base_::bins(k) += binvalue;
765 Base_::delta(k) += binvalue * binvalue;
768 Base_::off_chart += histogram.off_chart;
785 TOMOGRAPHER_ENABLED_IF(!HistogramType::HasErrorBars)
786 inline
void finalize()
788 Base_::bins /= num_histograms;
789 Base_::delta /= num_histograms;
790 Base_::off_chart /= num_histograms;
793 auto finhist2 = Base_::bins*Base_::bins;
794 Base_::delta = ( (Base_::delta - finhist2) / (num_histograms-1) ).sqrt();
815 TOMOGRAPHER_ENABLED_IF(HistogramType::HasErrorBars)
821 tomographer_assert((
typename HistogramType::CountType)histogram.numBins() == Base_::numBins());
823 for (
std::size_t k = 0; k < histogram.numBins(); ++k) {
824 RealAvgType binvalue = histogram.count(k);
825 Base_::bins(k) += binvalue;
826 RealAvgType bindelta = histogram.errorBar(k);
827 Base_::delta(k) += bindelta*bindelta;
830 Base_::off_chart += histogram.off_chart;
847 TOMOGRAPHER_ENABLED_IF(HistogramType::HasErrorBars)
848 inline
void finalize()
850 Base_::bins /= num_histograms;
851 Base_::off_chart /= num_histograms;
853 Base_::delta = Base_::delta.sqrt();
854 Base_::delta /= num_histograms;
871 namespace tomo_internal {
876 template<
typename Scalar,
typename Fn>
877 inline Scalar max_finite_value(
const std::size_t num_items, Fn val_generator,
878 const Scalar default_val =
Scalar(1.0))
880 bool has_first_val =
false;
881 Scalar max_val = default_val;
883 const Scalar this_val = val_generator(k);
884 if (
std::isfinite(this_val) && (!has_first_val || this_val > max_val)) {
886 has_first_val =
true;
895 template<
typename HistogramType>
896 struct histogram_pretty_print_label
900 labels.
resize(hist.numBins());
910 template<
typename HistogramType>
913 labels.
resize(hist.numBins());
915 const double max_label_val =
std::max(hist.binCenterValue(0), hist.binCenterValue(hist.numBins()-1));
917 const int relprecision = 4;
918 const int precision = (powten > relprecision) ? 0 : (relprecision - powten - 1);
923 labels[k] = ss.
str();
927 template<
typename Scalar_,
typename CountType_>
928 struct histogram_pretty_print_label<UniformBinsHistogram<Scalar_, CountType_> >
933 histogram_get_labels_for_hist_params<HistogramType>(labels, hist);
937 template<
typename Scalar_,
typename CountType_>
938 struct histogram_pretty_print_label<UniformBinsHistogramWithErrorBars<Scalar_, CountType_> >
943 histogram_get_labels_for_hist_params<HistogramType>(labels, hist);
947 template<
typename BaseHistogramType_,
typename RealAvgType_>
948 struct histogram_pretty_print_label<AveragedHistogram<BaseHistogramType_, RealAvgType_> >
953 histogram_get_labels_for_hist_params<HistogramType>(labels, hist);
958 template<
typename HistogramType>
959 struct histogram_pretty_print_value
962 histogram_pretty_print_value(
const HistogramType & hist_) : hist(hist_) { }
964 TOMOGRAPHER_ENABLED_IF(!HistogramType::HasErrorBars)
967 svalues.
resize(hist.numBins());
969 double max_val = max_finite_value(hist.numBins(), [&](
std::size_t k) {
return hist.count(k); }, 1.0);
972 const int relprecision = 3;
973 const int precision = abs_precision_for(powten, relprecision);
974 const int w = (precision > 0) ? (precision+powten+1) : (relprecision+2);
980 svalues[k] = ss.
str();
984 TOMOGRAPHER_ENABLED_IF(HistogramType::HasErrorBars)
987 svalues.
resize(hist.numBins());
989 double max_val = max_finite_value(hist.numBins(), [&](
std::size_t k) {
return hist.count(k); }, 1.0);
992 const int relprecision = 3;
993 const int precision = abs_precision_for(powten, relprecision);
994 const int w = (precision > 0) ? (precision+powten+2) : (relprecision+2);
999 << hist.count(k) <<
" +- " 1001 << hist.errorBar(k);
1002 svalues[k] = ss.
str();
1006 static inline int abs_precision_for(
const int powten,
const int relprecision)
1008 return (powten >= relprecision) ? 0 : (relprecision - powten - 1);
1016 template<
typename HistogramType>
1017 struct histogram_pretty_printer
1020 const int max_width;
1036 histogram_pretty_printer(
const HistogramType & hist_,
const int max_width_)
1037 : hist(hist_), max_width(max_width_), lsep(
" |"), rsep(
" ")
1043 labels.
resize(hist.numBins());
1044 svalues.
resize(hist.numBins());
1046 histogram_pretty_print_label<HistogramType>::getLabels(labels, hist);
1047 histogram_pretty_print_value<HistogramType>::getStrValues(svalues, hist);
1049 bool has_maxval =
false;
1050 for (
std::size_t k = 0; k < hist.numBins(); ++k) {
1051 const double val = maxval(k);
1053 if (
std::isfinite(val) && (!has_maxval || val > max_value)) {
1057 if (k == 0 || (
int)labels[k].size() > maxlabelwidth) {
1058 maxlabelwidth = (int)labels[k].size();
1060 if (k == 0 || (
int)svalues[k].
size() > maxsvaluewidth) {
1061 maxsvaluewidth = (int)svalues[k].size();
1068 max_bar_width = max_width - maxlabelwidth - maxsvaluewidth - (int)lsep.
size() - (int)rsep.
size();
1069 if (max_bar_width < 2) {
1072 barscale = ((max_value > 0) ? (max_value / max_bar_width) : 1.0);
1075 inline int value_to_bar_length(
double val)
const 1080 int l = (int)(val/barscale+0.5);
1081 if (l >= max_bar_width) {
1082 return max_bar_width-1;
1087 inline void fill_str_len(
std::string & s,
double valstart,
double valend,
1088 char c,
char clside,
char crside)
const 1090 int vs = value_to_bar_length(valstart);
1091 int ve = value_to_bar_length(valend);
1096 for (
int j = vs; j < ve; ++j) {
1099 if (clside && crside && clside != crside && vs == ve) {
1100 if (ve < (
int)s.
size()-1) {
1102 }
else if (vs > 1) {
1121 for (k = 0; k < hist.numBins(); ++k) {
1122 str <<
std::setw(maxlabelwidth) << labels[k] << lsep
1123 << make_bar(k) << rsep <<
std::setw(maxsvaluewidth) << svalues[k] <<
"\n";
1129 TOMOGRAPHER_ENABLED_IF(!HistogramType::HasErrorBars)
1132 return (
double)hist.count(k);
1134 TOMOGRAPHER_ENABLED_IF(HistogramType::HasErrorBars)
1137 return (
double)(hist.count(k) + hist.errorBar(k));
1140 TOMOGRAPHER_ENABLED_IF(!HistogramType::HasErrorBars)
1144 fill_str_len(sbar, 0.0, hist.count(k),
'*', 0, 0);
1147 TOMOGRAPHER_ENABLED_IF(HistogramType::HasErrorBars)
1151 const double binval = hist.count(k);
1152 const double binerr = hist.errorBar(k);
1153 fill_str_len(sbar, 0.0, binval - binerr,
'*',
'*',
'*');
1154 fill_str_len(sbar, binval - binerr, binval + binerr,
'-',
'|',
'|');
1159 template<
typename HistogramType>
1161 const int max_width)
1165 if (histogram.off_chart > 0) {
1166 send +=
Tools::fmts(
" [+%.1g off]", (
double)histogram.off_chart);
1169 const int maxbarwidth = max_width - (int)s.
size() - (int)send.size();
1170 const int numdiv = (int)(
std::ceil((
float)histogram.numBins() / maxbarwidth) + 0.5f);
1171 const int barwidth = (int)(
std::ceil((
float)histogram.numBins() / numdiv) + 0.5f);
1174 Eigen::ArrayXf veclog(barwidth);
1177 float minlogval = 0;
1178 float maxlogval = 0;
1179 for (k = 0; k < barwidth; ++k) {
1181 (
std::size_t)(histogram.bins.size()-numdiv*k))).sum();
1184 veclog(k) =
std::log((
float)vec(k));
1186 veclog(k) = (float)vec(k);
1188 if (k == 0 || minlogval > veclog(k)) {
1189 minlogval = veclog(k);
1191 if (k == 0 || maxlogval < veclog(k)) {
1192 maxlogval = veclog(k) + 1e-6f;
1201 for (k = 0; k < barwidth; ++k) {
1205 int i = (int)(chars.
size() * (veclog(k) - minlogval) / (maxlogval - minlogval));
1206 if (i < 0) { i = 0; }
1207 if (i >= (
int)chars.
size()) { i = (int)chars.
size()-1; }
1228 template<
typename HistogramType>
1233 if (histogram.params.num_bins == 0) {
1234 str <<
"<empty histogram: no bins>\n";
1239 tomo_internal::histogram_pretty_printer<HistogramType>(histogram, max_width).pretty_print(str);
1250 template<
typename HistogramType>
1254 histogramPrettyPrint<HistogramType>(ss, histogram, max_width);
1275 template<
typename HistogramType>
1277 bool log_scale =
true,
int max_width = 0)
1284 if (histogram.params.num_bins == 0) {
1285 s =
"<empty histogram: no bins>";
1287 s = tomo_internal::histogram_short_bar_fmt<HistogramType>(histogram, log_scale, max_width);
1291 return max_width - (int)s.
size();
1303 template<
typename HistogramType>
1308 if (histogram.params.num_bins == 0) {
1309 return "<empty histogram: no bins>";
1313 return tomo_internal::histogram_short_bar_fmt<HistogramType>(histogram, log_scale, max_width);
1331 template<
typename HistogramType>
1334 const HistogramType& hist,
1336 bool log_scale =
true,
1337 int full_max_width = 0)
1342 const int w =
histogramShortBar(str, hist, log_scale, full_max_width - (
int)head.size() - (int)tail.
size());
1360 template<
typename HistogramType>
1362 const HistogramType& hist,
1364 bool log_scale =
true,
1365 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)
#define tomographer_assert(...)
Assertion test macro.
Derived & setZero(Index size)