Tomographer  v2.0
Tomographer C++ Framework Documentation
histogram.h
Go to the documentation of this file.
1 /* This file is part of the Tomographer project, which is distributed under the
2  * terms of the MIT license.
3  *
4  * The MIT License (MIT)
5  *
6  * Copyright (c) 2015 ETH Zurich, Institute for Theoretical Physics, Philippe Faist
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a copy
9  * of this software and associated documentation files (the "Software"), to deal
10  * in the Software without restriction, including without limitation the rights
11  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12  * copies of the Software, and to permit persons to whom the Software is
13  * furnished to do so, subject to the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be included in
16  * all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24  * SOFTWARE.
25  */
26 
27 #ifndef HISTOGRAM_H
28 #define HISTOGRAM_H
29 
30 #include <cmath>
31 #include <cstdlib>
32 
33 #include <iostream>
34 #include <iomanip> // std::setprecision
35 #include <sstream> // std::stringstream
36 #include <stdexcept> // std::out_of_range
37 #include <type_traits> // std::enable_if
38 #include <algorithm> // std::max
39 
40 #include <boost/math/constants/constants.hpp>
41 
42 #include <Eigen/Core>
43 
44 #include <tomographer2/tools/fmt.h>
46 #include <tomographer2/tools/cxxutil.h> // TOMOGRAPHER_ENABLED_IF, tomographer_assert(), getWidthForTerminalOutput
48 
49 
57 namespace Tomographer {
58 
59 
67 template<typename Scalar_, typename CountType_ = unsigned int>
69  // inheriting from this has some advantages over EIGEN_MAKE_ALIGNED_OPERATOR_NEW, such
70  // as not needing to explicitly declare the specialization
71  // NeedOwnOperatorNew<UniformBinsHistogram>:
73 {
75  typedef Scalar_ Scalar;
76 
78  typedef CountType_ CountType;
79 
81  static constexpr bool HasErrorBars = false;
82 
87  struct Params {
89  Params(Scalar min_ = 0.0, Scalar max_ = 1.0, std::size_t num_bins_ = 50)
90  : min(min_), max(max_), num_bins(num_bins_)
91  {
92  }
94  template<typename OtherParams/*,
95  typename std::enable_if<(tomo_internal::is_histogram_params_type<OtherParams>::value), bool>::type
96  dummy2 = true*/>
97  Params(const OtherParams& other)
98  : min(other.min), max(other.max), num_bins(other.num_bins)
99  {
100  }
101 
103  Scalar min;
105  Scalar max;
108 
114  inline bool isWithinBounds(Scalar value) const
115  {
116  return std::isfinite(value) && value >= min && value < max;
117  }
123  inline std::size_t binIndex(Scalar value) const
124  {
125  if ( !isWithinBounds(value) ) {
126  throw std::out_of_range(streamstr("UniformBinsHistogram::Params: Value "<<value
127  <<" out of range ["<<min<<","<<max<<"["));
128  }
129  return binIndexUnsafe(value);
130  }
139  inline std::size_t binIndexUnsafe(Scalar value) const
140  {
141  return (std::size_t)((value-min) / (max-min) * num_bins);
142  }
151  inline Scalar binLowerValue(std::size_t index) const
152  {
153  tomographer_assert(Tools::isPositive(index) && (std::size_t)index < num_bins);
154  return min + index * (max-min) / num_bins;
155  }
163  inline Scalar binCenterValue(std::size_t index) const
164  {
165  tomographer_assert(Tools::isPositive(index) && (std::size_t)index < num_bins);
166  return min + (index+boost::math::constants::half<Scalar>()) * (max-min) / num_bins;
167  }
176  inline Scalar binUpperValue(std::size_t index) const
177  {
178  tomographer_assert(Tools::isPositive(index) && (std::size_t)index < num_bins);
179  return min + (index+1) * (max-min) / num_bins;
180  }
185  inline Scalar binResolution() const
186  {
187  return (max - min) / num_bins;
188  }
189  };
190 
196  CountType off_chart;
197 
200  : params(p), bins(Eigen::Array<CountType,Eigen::Dynamic,1>::Zero(p.num_bins)),
201  off_chart(0)
202  {
203  }
204 
206  UniformBinsHistogram(Scalar min_, Scalar max_, std::size_t num_bins)
207  : params(min_, max_, num_bins), bins(Eigen::Array<CountType,Eigen::Dynamic,1>::Zero(num_bins)),
208  off_chart(0)
209  {
210  }
211 
213  template<typename HistogramType>
214  UniformBinsHistogram(const HistogramType & other)
215  : params(other.params), bins(other.params.num_bins), off_chart(other.off_chart)
216  {
217  bins = other.bins.template cast<CountType>();
218  }
219 
221  inline void reset()
222  {
223  bins.resize(params.num_bins);
224  bins.setZero();
225  off_chart = 0;
226  }
227 
237  template<typename EigenType>
238  inline void load(const Eigen::DenseBase<EigenType> & x, CountType off_chart_ = 0)
239  {
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_;
244  }
245 
254  template<typename EigenType>
255  inline void add(const Eigen::ArrayBase<EigenType> & x, CountType off_chart_ = 0)
256  {
257  // the argument must be of ArrayBase type (as opposed to load() where we can
258  // also accept MatrixBase types) because Eigen doesn't allow operator+=
259  // between Arrays and Matrices, but has an operator= .
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_;
264  }
265 
274  template<typename OtherScalar, typename OtherCountType>
276  {
277  tomographer_assert(x.bins.cols() == 1);
278  tomographer_assert((std::size_t)x.bins.rows() == params.num_bins);
279  tomographer_assert(std::fabs(x.params.min - params.min) < 1e-8);
280  tomographer_assert(std::fabs(x.params.max - params.max) < 1e-8);
281  bins += x.bins.template cast<CountType>();
282  off_chart += x.off_chart;
283  }
284 
286  inline std::size_t numBins() const
287  {
288  return params.num_bins;
289  }
290 
292  inline CountType count(std::size_t i) const
293  {
294  return bins(i);
295  }
296 
298  inline bool isWithinBounds(Scalar value) const
299  {
300  return params.isWithinBounds(value);
301  }
303  inline std::size_t binIndex(Scalar value) const
304  {
305  return params.binIndex(value);
306  }
308  inline Scalar binLowerValue(int index) const
309  {
310  return params.binLowerValue(index);
311  }
313  inline Scalar binCenterValue(std::size_t index) const
314  {
315  return params.binCenterValue(index);
316  }
318  inline Scalar binUpperValue(std::size_t index) const
319  {
320  return params.binUpperValue(index);
321  }
322 
324  inline Scalar binResolution() const
325  {
326  return params.binResolution();
327  }
328 
338  inline std::size_t record(Scalar value)
339  {
340  if ( !isWithinBounds(value) ) {
341  ++off_chart;
343  }
344  // calling bin_index_unsafe because we have already checked that value is in range.
345  const std::size_t index = params.binIndexUnsafe(value);
346  ++bins( index );
347  return index;
348  }
349 
360  inline std::size_t record(Scalar value, CountType weight)
361  {
362  if ( !isWithinBounds(value) ) {
363  off_chart += weight;
365  }
366  // calling bin_index_unsafe is safe here because we have already checked that value is
367  // in range.
368  const std::size_t index = params.binIndexUnsafe(value);
369  bins(index) += weight;
370  return index;
371  }
372 
377  inline std::string prettyPrint(int max_width = 0) const
378  {
379  return histogramPrettyPrint(*this, max_width);
380  }
381 
382 };
383 
384 
385 
386 
392 template<typename Scalar_, typename CountType_ = double>
394  : public UniformBinsHistogram<Scalar_, CountType_>,
396 {
398  typedef Scalar_ Scalar;
400  typedef CountType_ CountType;
401 
407  typedef typename Base_::Params Params;
408 
410  static constexpr bool HasErrorBars = true;
411 
414 
415  // make these accessible without having to use the "Base_::member" syntax all the time
416  using Base_::params;
417  using Base_::bins;
418  using Base_::off_chart;
419 
420 
427  : Base_(params), delta(Eigen::Array<CountType, Eigen::Dynamic, 1>::Zero(params.num_bins))
428  {
429  }
430 
437  : Base_(min, max, num_bins), delta(Eigen::Array<CountType, Eigen::Dynamic, 1>::Zero(num_bins))
438  {
439  }
440 
447  inline void reset()
448  {
449  Base_::reset();
450  delta.resize(Base_::numBins());
451  delta.setZero();
452  }
453 
458  inline CountType errorBar(std::size_t i) const
459  {
460  return delta(i);
461  }
462 
470  std::string prettyPrint(int max_width = 0) const
471  {
472  return histogramPrettyPrint(*this, max_width);
473  }
474 
475 };
476 // static members:
477 template<typename Scalar_, typename CountType_>
479 
480 
481 
482 
483 
484 
518 template<typename HistogramType_, typename RealAvgType = double>
520  : public UniformBinsHistogramWithErrorBars<typename HistogramType_::Scalar, RealAvgType>
521 {
527  typedef HistogramType_ HistogramType;
530 
532  typedef typename Base_::Params Params;
534  typedef typename Base_::Scalar Scalar;
536  typedef typename Base_::CountType CountType;
537 
539  static constexpr bool HasErrorBars = true;
540 
547 
548 
555  AveragedHistogram(const Params& params = Params())
556  : Base_(params), num_histograms(0)
557  {
558  }
559 
566  inline void reset(const Params& params_)
567  {
568  Base_::params = params_;
569  Base_::reset();
570  num_histograms = 0;
571  }
572 
579  inline void reset()
580  {
581  Base_::reset();
582  num_histograms = 0;
583  }
584 
585  // ---------------------------------------------------------------------------
586  // Implementation in case the added histograms don't have their own error bars
587  // ---------------------------------------------------------------------------
588 
603  TOMOGRAPHER_ENABLED_IF(!HistogramType::HasErrorBars)
604  inline void addHistogram(const HistogramType& histogram)
605  {
606  // bins collects the sum of the histograms
607  // delta for now collects the sum of squares. delta will be normalized in finalize().
608 
609  tomographer_assert((typename HistogramType::CountType)histogram.numBins() ==
610  (typename HistogramType::CountType)Base_::numBins());
611 
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;
616  }
617 
618  Base_::off_chart += histogram.off_chart;
619  ++num_histograms;
620  }
635  TOMOGRAPHER_ENABLED_IF(!HistogramType::HasErrorBars)
636  inline void finalize()
637  {
638  Base_::bins /= num_histograms;
639  Base_::delta /= num_histograms;
640  Base_::off_chart /= num_histograms;
641 
642  // delta = sqrt(< X^2 > - < X >^2) / sqrt(Nrepeats-1)
643  auto finhist2 = Base_::bins*Base_::bins; // for array, this is c-wise product
644  Base_::delta = ( (Base_::delta - finhist2) / (num_histograms-1) ).sqrt();
645  }
646 
647  // ---------------------------------------------------------------------------
648  // Implementation in case the added histograms do have their own error bars
649  // ---------------------------------------------------------------------------
650 
665  TOMOGRAPHER_ENABLED_IF(HistogramType::HasErrorBars)
666  inline void addHistogram(const HistogramType& histogram)
667  {
668  // bins collects the sum of the histograms
669  // delta for now collects the sum of squares. delta will be normalized in finished().
670 
671  tomographer_assert((typename HistogramType::CountType)histogram.numBins() == Base_::numBins());
672 
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;
678  }
679 
680  Base_::off_chart += histogram.off_chart;
681  ++num_histograms;
682  }
697  TOMOGRAPHER_ENABLED_IF(HistogramType::HasErrorBars)
698  inline void finalize()
699  {
700  Base_::bins /= num_histograms;
701  Base_::off_chart /= num_histograms;
702 
703  Base_::delta = Base_::delta.sqrt();
704  Base_::delta /= num_histograms;
705  }
706 
707 };
708 
709 
710 
711 
712 
713 
714 
715 // -----------------------------------------------------------------------------
716 // Pretty Print Histogram Utilities
717 // -----------------------------------------------------------------------------
718 
719 
720 
721 namespace tomo_internal {
722 // internal helpers
723 //
724 // find maximum value in the list only among those values which are finite (not inf or nan)
725 //
726 template<typename Scalar, typename Fn>
727 inline Scalar max_finite_value(const std::size_t num_items, Fn val_generator,
728  const Scalar default_val = Scalar(1.0))
729 {
730  bool has_first_val = false;
731  Scalar max_val = default_val;
732  for (std::size_t k = 0; k < num_items; ++k) {
733  const Scalar this_val = val_generator(k);
734  if (std::isfinite(this_val) && (!has_first_val || this_val > max_val)) {
735  max_val = this_val;
736  has_first_val = true;
737  }
738  }
739  return max_val;
740 }
741 
742 //
743 // get labels left of histogram (generic HistogramType interface: no information, just bin #)
744 //
745 template<typename HistogramType>
746 struct histogram_pretty_print_label
747 {
748  static inline void getLabels(std::vector<std::string> & labels, const HistogramType & hist)
749  {
750  labels.resize(hist.numBins());
751  for (std::size_t k = 0; k < hist.numBins(); ++k) {
752  labels[k] = std::to_string(k);
753  }
754  }
755 };
756 // get labels left of histogram (for the family of histograms with 'Params':
757 // UniformBinsHistogram, UniformBinsHistogramWithErrorBars etc.)
758 //
759 // common code for several specializations of histogram_pretty_print_label
760 template<typename HistogramType>
761 inline void histogram_get_labels_for_hist_params(std::vector<std::string> & labels, const HistogramType& hist)
762 {
763  labels.resize(hist.numBins());
764 
765  const double max_label_val = std::max(hist.binCenterValue(0), hist.binCenterValue(hist.numBins()-1));
766  const int powten = (int)std::floor(std::log10(max_label_val));
767  const int relprecision = 4;
768  const int precision = (powten > relprecision) ? 0 : (relprecision - powten - 1);
769 
770  for (std::size_t k = 0; k < hist.numBins(); ++k) {
772  ss << std::fixed << std::setprecision(precision) << std::right << hist.binCenterValue(k);
773  labels[k] = ss.str();
774  }
775 }
776 // specialize histogram pretty-print labels using the code above
777 template<typename Scalar_, typename CountType_>
778 struct histogram_pretty_print_label<UniformBinsHistogram<Scalar_, CountType_> >
779 {
781  static inline void getLabels(std::vector<std::string> & labels, const HistogramType & hist)
782  {
783  histogram_get_labels_for_hist_params<HistogramType>(labels, hist);
784  }
785 };
786 // specialize histogram pretty-print labels using the code above
787 template<typename Scalar_, typename CountType_>
788 struct histogram_pretty_print_label<UniformBinsHistogramWithErrorBars<Scalar_, CountType_> >
789 {
791  static inline void getLabels(std::vector<std::string> & labels, const HistogramType & hist)
792  {
793  histogram_get_labels_for_hist_params<HistogramType>(labels, hist);
794  }
795 };
796 // specialize histogram pretty-print labels using the code above
797 template<typename BaseHistogramType_, typename RealAvgType_>
798 struct histogram_pretty_print_label<AveragedHistogram<BaseHistogramType_, RealAvgType_> >
799 {
801  static inline void getLabels(std::vector<std::string> & labels, const HistogramType & hist)
802  {
803  histogram_get_labels_for_hist_params<HistogramType>(labels, hist);
804  }
805 };
806 
807 // format bin counts nicely
808 template<typename HistogramType>
809 struct histogram_pretty_print_value
810 {
811  const HistogramType & hist;
812  histogram_pretty_print_value(const HistogramType & hist_) : hist(hist_) { }
813 
814  TOMOGRAPHER_ENABLED_IF(!HistogramType::HasErrorBars)
815  static inline void getStrValues(std::vector<std::string> & svalues, const HistogramType & hist)
816  {
817  svalues.resize(hist.numBins());
818 
819  double max_val = max_finite_value(hist.numBins(), [&](std::size_t k) { return hist.count(k); }, 1.0);
820 
821  const int powten = (int)std::floor(std::log10(max_val));
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);
825 
826  for (std::size_t k = 0; k < hist.numBins(); ++k) {
828  ss << std::setprecision(precision) << std::fixed << std::right << std::setw(w)
829  << hist.count(k);
830  svalues[k] = ss.str();
831  }
832  }
833 
834  TOMOGRAPHER_ENABLED_IF(HistogramType::HasErrorBars)
835  static inline void getStrValues(std::vector<std::string> & svalues, const HistogramType & hist)
836  {
837  svalues.resize(hist.numBins());
838 
839  double max_val = max_finite_value(hist.numBins(), [&](std::size_t k) { return hist.count(k); }, 1.0);
840 
841  const int powten = (int)std::floor(std::log10(max_val)); // floor of log_{10}(...)
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);
845 
846  for (std::size_t k = 0; k < hist.numBins(); ++k) {
848  ss << std::setprecision(precision) << std::fixed << std::right << std::setw(w)
849  << hist.count(k) << " +- "
850  << std::setprecision(abs_precision_for(powten-1, relprecision-1)) << std::setw(w)
851  << hist.errorBar(k);
852  svalues[k] = ss.str();
853  }
854  }
855 private:
856  static inline int abs_precision_for(const int powten, const int relprecision)
857  {
858  return (powten > relprecision) ? 0 : (relprecision - powten - 1);
859  }
860 };
861 
863 //
864 // access this with public API using histogram_pretty_print().
865 //
866 template<typename HistogramType>
867 struct histogram_pretty_printer
868 {
869  const HistogramType & hist;
870  const int max_width;
871 
872  const std::string lsep;
873  const std::string rsep;
874 
876  int maxlabelwidth;
877 
878  std::vector<std::string> svalues;
879  int maxsvaluewidth;
880 
881  double max_value;
882 
883  int max_bar_width;
884  double barscale;
885 
886  histogram_pretty_printer(const HistogramType & hist_, const int max_width_)
887  : hist(hist_), max_width(max_width_), lsep(" |"), rsep(" ")
888  {
889  // first pass:
890  // - determine the maximum value attained in the histogram
891  // - determine maximum width of formatted label & value fields.
892 
893  labels.resize(hist.numBins());
894  svalues.resize(hist.numBins());
895 
896  histogram_pretty_print_label<HistogramType>::getLabels(labels, hist);
897  histogram_pretty_print_value<HistogramType>::getStrValues(svalues, hist);
898 
899  bool has_maxval = false;
900  for (std::size_t k = 0; k < hist.numBins(); ++k) {
901  const double val = maxval(k);
902 
903  if (std::isfinite(val) && (!has_maxval || val > max_value)) {
904  max_value = val;
905  has_maxval = true;
906  }
907  if (k == 0 || (int)labels[k].size() > maxlabelwidth) {
908  maxlabelwidth = labels[k].size();
909  }
910  if (k == 0 || (int)svalues[k].size() > maxsvaluewidth) {
911  maxsvaluewidth = svalues[k].size();
912  }
913  }
914  if (!has_maxval) {
915  max_value = 1.0;
916  }
917 
918  max_bar_width = max_width - maxlabelwidth - maxsvaluewidth - lsep.size() - rsep.size();
919  if (max_bar_width < 2) {
920  max_bar_width = 2;
921  }
922  barscale = ((max_value > 0) ? (max_value / max_bar_width) : 1.0);
923  }
924 
925  inline int value_to_bar_length(double val) const
926  {
927  if (val < 0 || !std::isfinite(val)) {
928  val = 0;
929  }
930  int l = (int)(val/barscale+0.5);
931  if (l >= max_bar_width) {
932  return max_bar_width-1;
933  }
934  return l;
935  }
936 
937  inline void fill_str_len(std::string & s, double valstart, double valend,
938  char c, char clside, char crside) const
939  {
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) {
947  s[j] = c;
948  }
949  if (clside && crside && clside != crside && vs == ve) {
950  if (ve < (int)s.size()-1) {
951  ++ve;
952  } else if (vs > 1) {
953  --vs;
954  }
955  }
956  if (clside) {
957  s[vs] = clside;
958  }
959  if (crside) {
960  s[ve] = crside;
961  }
962  }
963 
964  inline void pretty_print(std::ostream & str) const
965  {
966  // perform now second pass:
967  // - display the histogram line by line, with the calculated widths.
968 
969  std::size_t k;
970 
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";
974  }
975  }
976 
977 private:
978  // maxval(k): how much this bar may extend in length
979  TOMOGRAPHER_ENABLED_IF(!HistogramType::HasErrorBars)
980  inline double maxval(const std::size_t k) const
981  {
982  return (double)hist.count(k);
983  }
984  TOMOGRAPHER_ENABLED_IF(HistogramType::HasErrorBars)
985  inline double maxval(const std::size_t k) const
986  {
987  return (double)(hist.count(k) + hist.errorBar(k));
988  }
989  // make_bar(k): produce the histogram bar in characters...
990  TOMOGRAPHER_ENABLED_IF(!HistogramType::HasErrorBars)
991  inline std::string make_bar(std::size_t k) const
992  {
993  std::string sbar(max_bar_width, ' ');
994  fill_str_len(sbar, 0.0, hist.count(k), '*', 0, 0);
995  return sbar;
996  }
997  TOMOGRAPHER_ENABLED_IF(HistogramType::HasErrorBars)
998  inline std::string make_bar(std::size_t k) const
999  {
1000  std::string sbar(max_bar_width, ' ');
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, '-', '|', '|');
1005  return sbar;
1006  }
1007 };
1008 
1009 template<typename HistogramType>
1010 inline std::string histogram_short_bar_fmt(const HistogramType & histogram, const bool log_scale,
1011  const int max_width)
1012 {
1013  std::string s = Tools::fmts("%.2g|", (double)histogram.binLowerValue(0));
1014  std::string send = Tools::fmts("|%.2g", (double)histogram.binUpperValue(histogram.numBins()-1));
1015  if (histogram.off_chart > 0) {
1016  send += Tools::fmts(" [+%.1g off]", (double)histogram.off_chart);
1017  }
1018 
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);
1022 
1024  Eigen::ArrayXf veclog(barwidth);
1025 
1026  int k;
1027  float minlogval = 0;
1028  float maxlogval = 0;
1029  for (k = 0; k < barwidth; ++k) {
1030  vec(k) = histogram.bins.segment(numdiv*k, std::min((std::size_t)numdiv,
1031  (std::size_t)(histogram.bins.size()-numdiv*k))).sum();
1032  if (vec(k) > 0) {
1033  if (log_scale) {
1034  veclog(k) = std::log((float)vec(k));
1035  } else {
1036  veclog(k) = (float)vec(k);
1037  }
1038  if (k == 0 || minlogval > veclog(k)) {
1039  minlogval = veclog(k);
1040  }
1041  if (k == 0 || maxlogval < veclog(k)) {
1042  maxlogval = veclog(k) + 1e-6f;
1043  }
1044  } else {
1045  veclog(k) = 0.f;
1046  }
1047  }
1048 
1049  // now, prepare string
1050  const std::string chars = ".-+ox%#";
1051  for (k = 0; k < barwidth; ++k) {
1052  if (vec(k) <= 0) {
1053  s += ' ';
1054  } else {
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; }
1058  s += chars[i];
1059  }
1060  }
1061 
1062  s += send;
1063 
1064  return s;
1065 }
1066 
1067 } // namespace tomo_internal
1068 
1069 
1078 template<typename HistogramType>
1079 inline void histogramPrettyPrint(std::ostream & str, const HistogramType & histogram, int max_width = 0)
1080 {
1081  tomographer_assert(Tools::isPositive(histogram.params.num_bins));
1082 
1083  if (histogram.params.num_bins == 0) {
1084  str << "<empty histogram: no bins>\n";
1085  return;
1086  }
1087 
1088  max_width = Tools::getWidthForTerminalOutput(max_width);
1089  tomo_internal::histogram_pretty_printer<HistogramType>(histogram, max_width).pretty_print(str);
1090 }
1091 
1100 template<typename HistogramType>
1101 inline std::string histogramPrettyPrint(const HistogramType & histogram, int max_width = 0)
1102 {
1103  std::ostringstream ss;
1104  histogramPrettyPrint<HistogramType>(ss, histogram, max_width);
1105  return ss.str();
1106 }
1107 
1125 template<typename HistogramType>
1126 inline int histogramShortBar(std::ostream & str, const HistogramType & histogram,
1127  bool log_scale = true, int max_width = 0)
1128 {
1129  tomographer_assert(Tools::isPositive(histogram.params.num_bins));
1130 
1131  max_width = Tools::getWidthForTerminalOutput(max_width);
1132 
1133  std::string s;
1134  if (histogram.params.num_bins == 0) {
1135  s = "<empty histogram: no bins>";
1136  } else {
1137  s = tomo_internal::histogram_short_bar_fmt<HistogramType>(histogram, log_scale, max_width);
1138  }
1139 
1140  str << s;
1141  return max_width - s.size();
1142 }
1153 template<typename HistogramType>
1154 inline std::string histogramShortBar(const HistogramType & histogram, bool log_scale = true, int max_width = 0)
1155 {
1156  tomographer_assert(Tools::isPositive(histogram.params.num_bins));
1157 
1158  if (histogram.params.num_bins == 0) {
1159  return "<empty histogram: no bins>";
1160  }
1161 
1162  max_width = Tools::getWidthForTerminalOutput(max_width);
1163  return tomo_internal::histogram_short_bar_fmt<HistogramType>(histogram, log_scale, max_width);
1164 }
1165 
1166 
1167 
1168 
1169 
1170 } // namespace Tomographer
1171 
1172 
1173 
1174 
1175 #endif
Utilities for formatting strings.
Params params
Parameters of this histogram (range and # of bins)
Definition: histogram.h:192
UniformBinsHistogram(Params p=Params())
Constructor: stores the parameters and initializes the histogram to zero counts everywhere.
Definition: histogram.h:199
CountType count(std::size_t i) const
Shorthand for bins(i)
Definition: histogram.h:292
Eigen::Array< CountType, Eigen::Dynamic, 1 > bins
The counts for each bin.
Definition: histogram.h:194
Scalar binCenterValue(std::size_t index) const
Shorthand for Params::binCenterValue()
Definition: histogram.h:313
Combines several histograms (with same parameters) into an averaged histogram.
Definition: histogram.h:519
Base_::Params Params
The histogram parameters&#39; type. See UniformBinsHistogramWithErrorBars::Params.
Definition: histogram.h:532
Provides correct operator-new implementation for Eigen types via the NeedOwnOperatorNew mechanism...
Base namespace for the Tomographer project.
Definition: densellh.h:44
Scalar binUpperValue(std::size_t index) const
Returns the value which a given bin index represents (upper bin value limit)
Definition: histogram.h:176
T ceil(T...args)
std::string prettyPrint(int max_width=0) const
Print the histogram in human readable form.
Definition: histogram.h:470
Scalar binResolution() const
Returns the width of a bin.
Definition: histogram.h:185
void add(const UniformBinsHistogram< OtherScalar, OtherCountType > &x)
Add data to the histogram.
Definition: histogram.h:275
int num_histograms
The number of histograms averaged.
Definition: histogram.h:546
T log(T...args)
Base_::CountType CountType
The histogram&#39; count type. This is exactly the same as RealAvgType.
Definition: histogram.h:536
Stores a histogram along with error bars.
Definition: histogram.h:393
Scalar min
Lower range value.
Definition: histogram.h:103
T to_string(T...args)
void reset()
Resets the histogram to zero counts everywhere.
Definition: histogram.h:221
bool isWithinBounds(Scalar value) const
Shorthand for Params::isWithinBounds()
Definition: histogram.h:298
T right(T...args)
std::size_t binIndex(Scalar value) const
Shorthand for Params::binIndex()
Definition: histogram.h:303
CountType_ CountType
The type that serves to count how many hits in each bin.
Definition: histogram.h:78
Eigen::Array< CountType, Eigen::Dynamic, 1 > delta
The error bars associated with each histogram bin.
Definition: histogram.h:413
void reset()
Resets the data keeping the exisiting params.
Definition: histogram.h:579
Scalar binLowerValue(int index) const
Shorthand for Params::binLowerValue()
Definition: histogram.h:308
T floor(T...args)
#define streamstr(tokens)
Utility macro to format stream tokens to a std::string.
Definition: fmt.h:145
T log10(T...args)
UniformBinsHistogramWithErrorBars< typename HistogramType_::Scalar, RealAvgType > Base_
Shortcut for our base class&#39; type.
Definition: histogram.h:529
std::string prettyPrint(int max_width=0) const
Pretty-print the histogram and return it as a string with horizontal bars.
Definition: histogram.h:377
SegmentReturnType segment(Index start, Index n)
T setw(T...args)
T resize(T...args)
std::size_t binIndex(Scalar value) const
Returns which bin this value should be counted in (index in bins array)
Definition: histogram.h:123
STL class.
T min(T...args)
Base_::Scalar Scalar
The histogram&#39;s X-axis scalar type. See UniformBinsHistogramWithErrorBars::Scalar.
Definition: histogram.h:534
The parameters of a UniformBinsHistogram.
Definition: histogram.h:87
std::size_t num_bins
Number of bins to split the range into.
Definition: histogram.h:107
void histogramPrettyPrint(std::ostream &str, const HistogramType &histogram, int max_width=0)
pretty-print the given histogram.
Definition: histogram.h:1079
UniformBinsHistogramWithErrorBars(Scalar min, Scalar max, std::size_t num_bins)
Constructor, with given histogram parameters.
Definition: histogram.h:436
Basic utilities for dealing with Eigen matrices and other types.
CountType_ CountType
The Type used to keep track of counts. See UniformBinsHistogram::CountType.
Definition: histogram.h:400
Scalar binCenterValue(std::size_t index) const
Returns the value which a given bin index represents (center bin value)
Definition: histogram.h:163
std::enable_if< std::is_unsigned< X >::value, bool >::type isPositive(const X)
Test whether the given value is positive or zero.
Definition: cxxutil.h:376
Scalar binResolution() const
Shorthand for Params::binResolution()
Definition: histogram.h:324
Scalar_ Scalar
The Scalar (X-axis) Type. See UniformBinsHistogram::Scalar.
Definition: histogram.h:398
HistogramType_ HistogramType
Type of the individual histograms we are averaging.
Definition: histogram.h:527
std::size_t binIndexUnsafe(Scalar value) const
Returns which bin this value should be counted in.
Definition: histogram.h:139
UniformBinsHistogram(Scalar min_, Scalar max_, std::size_t num_bins)
Constructor: stores the parameters and initializes the histogram to zero counts everywhere.
Definition: histogram.h:206
static constexpr bool HasErrorBars
This histogram type does not provide error bars (see Histogram Interface)
Definition: histogram.h:81
T isfinite(T...args)
Some C++ utilities, with a tad of C++11 tricks.
T fabs(T...args)
std::size_t record(Scalar value)
Record a new value in the histogram.
Definition: histogram.h:338
Params(const OtherParams &other)
Copy constructor, from any other UniformBinsHistogram::Params type.
Definition: histogram.h:97
T fixed(T...args)
void load(const Eigen::DenseBase< EigenType > &x, CountType off_chart_=0)
Load data for the histogram. Uses current histogram parameters, just sets the bin counts...
Definition: histogram.h:238
Managing the need for specific overrides to operator new() for some types (especially Eigen types) ...
Scalar max
Upper range value.
Definition: histogram.h:105
T size(T...args)
UniformBinsHistogramWithErrorBars(Params params=Params())
Constructor, with given histogram parameters.
Definition: histogram.h:426
CountType off_chart
The number of points that fell outside of the given range.
Definition: histogram.h:196
std::string fmts(const char *fmt,...)
printf- format to a std::string
Definition: fmt.h:124
STL class.
Base_::Params Params
Shortcut for our base class&#39; histogram parameters. See UniformBinsHistogram::Params.
Definition: histogram.h:407
void add(const Eigen::ArrayBase< EigenType > &x, CountType off_chart_=0)
Add data to the histogram.
Definition: histogram.h:255
VarValueDecoder< T >::RetType value(const Var &var)
Access the value of the given variable, as a C++ type.
Definition: ezmatio.h:854
std::size_t record(Scalar value, CountType weight)
Record a new value in the histogram, with a certain weight.
Definition: histogram.h:360
UniformBinsHistogram(const HistogramType &other)
Constructor: copy another histogram type.
Definition: histogram.h:214
std::size_t numBins() const
Shorthand for params.num_bins
Definition: histogram.h:286
int getWidthForTerminalOutput(int max_width=0)
Return a suitable width for displaying stuff on the standard output.
Definition: cxxutil.h:489
void reset(const Params &params_)
Resets the data and sets new params.
Definition: histogram.h:566
AveragedHistogram(const Params &params=Params())
Constructs an AveragedHistogram with the given histogram parameters.
Definition: histogram.h:555
Stores a histogram.
Definition: histogram.h:68
void reset()
Resets the histogram to zero counts everywhere, and zero error bars.
Definition: histogram.h:447
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.
Definition: histogram.h:1126
Scalar binLowerValue(std::size_t index) const
Returns the value which a given bin index represents (lower bin value limit)
Definition: histogram.h:151
Params(Scalar min_=0.0, Scalar max_=1.0, std::size_t num_bins_=50)
The obvious constructor.
Definition: histogram.h:89
T setprecision(T...args)
STL class.
UniformBinsHistogram< Scalar_, CountType_ > Base_
Shortcut for our base class type.
Definition: histogram.h:403
Scalar binUpperValue(std::size_t index) const
Shorthand for Params::binUpperValue()
Definition: histogram.h:318
Scalar_ Scalar
The scalar type of the "X"-axis of the histogram (usually double)
Definition: histogram.h:75
bool isWithinBounds(Scalar value) const
Tests whether the given value is in the range of the histogram.
Definition: histogram.h:114
CountType errorBar(std::size_t i) const
For the Histogram Interface. Get error bar for bin number i.
Definition: histogram.h:458
Derived & setZero(Index size)