Tomographer  v1.0a
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 
39 #include <boost/math/constants/constants.hpp>
40 
41 #include <Eigen/Core>
42 
43 #include <tomographer/tools/fmt.h>
44 #include <tomographer/qit/util.h>
45 
46 
54 namespace Tomographer {
55 
56 
64 template<typename Scalar_, typename CountType_ = unsigned int>
66 {
68  typedef Scalar_ Scalar;
69 
71  typedef CountType_ CountType;
72 
74  static constexpr bool HasErrorBars = false;
75 
80  struct Params {
82  Params(Scalar min_ = 0.0, Scalar max_ = 1.0, std::size_t num_bins_ = 50)
83  : min(min_), max(max_), num_bins(num_bins_)
84  {
85  }
87  template<typename OtherParams/*,
88  typename std::enable_if<(tomo_internal::is_histogram_params_type<OtherParams>::value), bool>::type
89  dummy2 = true*/>
90  Params(const OtherParams& other)
91  : min(other.min), max(other.max), num_bins(other.num_bins)
92  {
93  }
94 
96  Scalar min;
98  Scalar max;
101 
107  inline bool is_within_bounds(Scalar value) const
108  {
109  return std::isfinite(value) && value >= min && value < max;
110  }
116  inline std::size_t bin_index(Scalar value) const
117  {
118  if ( !is_within_bounds(value) ) {
119  throw std::out_of_range(streamstr("UniformBinsHistogram::Params: Value "<<value
120  <<" out of range ["<<min<<","<<max<<"["));
121  }
122  return bin_index_unsafe(value);
123  }
132  inline std::size_t bin_index_unsafe(Scalar value) const
133  {
134  return (std::size_t)((value-min) / (max-min) * num_bins);
135  }
144  inline Scalar bin_lower_value(std::size_t index) const
145  {
146  eigen_assert(Tools::is_positive(index) && (std::size_t)index < num_bins);
147  return min + index * (max-min) / num_bins;
148  }
156  inline Scalar bin_center_value(std::size_t index) const
157  {
158  eigen_assert(Tools::is_positive(index) && (std::size_t)index < num_bins);
159  return min + (index+boost::math::constants::half<Scalar>()) * (max-min) / num_bins;
160  }
169  inline Scalar bin_upper_value(std::size_t index) const
170  {
171  eigen_assert(Tools::is_positive(index) && (std::size_t)index < num_bins);
172  return min + (index+1) * (max-min) / num_bins;
173  }
178  inline Scalar bin_resolution() const
179  {
180  return (max - min) / num_bins;
181  }
182  };
183 
185  Params params;
189  CountType off_chart;
190 
192  UniformBinsHistogram(Params p = Params())
193  : params(p), bins(Eigen::Array<CountType,Eigen::Dynamic,1>::Zero(p.num_bins)),
194  off_chart(0)
195  {
196  }
197 
199  UniformBinsHistogram(Scalar min_, Scalar max_, std::size_t num_bins)
200  : params(min_, max_, num_bins), bins(Eigen::Array<CountType,Eigen::Dynamic,1>::Zero(num_bins)),
201  off_chart(0)
202  {
203  }
204 
206  template<typename HistogramType>
207  UniformBinsHistogram(const HistogramType & other)
208  : params(other.params), bins(other.params.num_bins), off_chart(other.off_chart)
209  {
210  bins = other.bins.template cast<CountType>();
211  }
212 
214  inline void reset()
215  {
216  bins.resize(params.num_bins);
217  bins.setZero();
218  off_chart = 0;
219  }
220 
230  template<typename EigenType>
231  inline void load(const Eigen::DenseBase<EigenType> & x, CountType off_chart_ = 0)
232  {
233  eigen_assert(x.cols() == 1);
234  eigen_assert((std::size_t)x.rows() == params.num_bins);
235  bins = x.derived().template cast<CountType>();
236  off_chart = off_chart_;
237  }
238 
247  template<typename EigenType>
248  inline void add(const Eigen::ArrayBase<EigenType> & x, CountType off_chart_ = 0)
249  {
250  // the argument must be of ArrayBase type (as opposed to load() where we can
251  // also accept MatrixBase types) because Eigen doesn't allow operator+=
252  // between Arrays and Matrices, but has an operator= .
253  eigen_assert(x.cols() == 1);
254  eigen_assert((std::size_t)x.rows() == params.num_bins);
255  bins += x.derived().template cast<CountType>();
256  off_chart += off_chart_;
257  }
258 
267  template<typename OtherScalar, typename OtherCountType>
269  {
270  eigen_assert(x.bins.cols() == 1);
271  eigen_assert((std::size_t)x.bins.rows() == params.num_bins);
272  eigen_assert(std::fabs(x.params.min - params.min) < 1e-8);
273  eigen_assert(std::fabs(x.params.max - params.max) < 1e-8);
274  bins += x.bins.template cast<CountType>();
275  off_chart += x.off_chart;
276  }
277 
279  inline std::size_t num_bins() const
280  {
281  return params.num_bins;
282  }
283 
285  inline CountType count(std::size_t i) const
286  {
287  return bins(i);
288  }
289 
291  inline bool is_within_bounds(Scalar value) const
292  {
293  return params.is_within_bounds(value);
294  }
296  inline std::size_t bin_index(Scalar value) const
297  {
298  return params.bin_index(value);
299  }
301  inline Scalar bin_lower_value(int index) const
302  {
303  return params.bin_lower_value(index);
304  }
306  inline Scalar bin_center_value(std::size_t index) const
307  {
308  return params.bin_center_value(index);
309  }
311  inline Scalar bin_upper_value(std::size_t index) const
312  {
313  return params.bin_upper_value(index);
314  }
315 
317  inline Scalar bin_resolution() const
318  {
319  return params.bin_resolution();
320  }
321 
331  inline std::size_t record(Scalar value)
332  {
333  if ( !is_within_bounds(value) ) {
334  ++off_chart;
336  }
337  // calling bin_index_unsafe because we have already checked that value is in range.
338  const std::size_t index = params.bin_index_unsafe(value);
339  ++bins( index );
340  return index;
341  }
342 
353  inline std::size_t record(Scalar value, CountType weight)
354  {
355  if ( !is_within_bounds(value) ) {
356  off_chart += weight;
358  }
359  // calling bin_index_unsafe is safe here because we have already checked that value is
360  // in range.
361  const std::size_t index = params.bin_index_unsafe(value);
362  bins(index) += weight;
363  return index;
364  }
365 
370  inline std::string pretty_print(int max_width = 0) const
371  {
372  return histogram_pretty_print(*this, max_width);
373  }
374 
375 };
376 
377 
378 
384 template<typename Scalar_, typename CountType_ = double>
385 struct UniformBinsHistogramWithErrorBars : public UniformBinsHistogram<Scalar_, CountType_>
386 {
388  typedef Scalar_ Scalar;
390  typedef CountType_ CountType;
391 
396  typedef typename Base_::Params Params;
397 
399  static constexpr bool HasErrorBars = true;
400 
403 
404  // make these accessible without having to use the "Base_::member" syntax all the time
405  using Base_::params;
406  using Base_::bins;
407  using Base_::off_chart;
408 
409 
416  : Base_(params), delta(Eigen::Array<CountType, Eigen::Dynamic, 1>::Zero(params.num_bins))
417  {
418  }
419 
426  : Base_(min, max, num_bins), delta(Eigen::Array<CountType, Eigen::Dynamic, 1>::Zero(num_bins))
427  {
428  }
429 
436  inline void reset()
437  {
438  Base_::reset();
439  delta.resize(Base_::num_bins());
440  delta.setZero();
441  }
442 
447  inline CountType errorbar(std::size_t i) const
448  {
449  return delta(i);
450  }
451 
459  std::string pretty_print(int max_width = 0) const
460  {
461  return histogram_pretty_print(*this, max_width);
462  }
463 
464 };
465 
466 
467 
468 
469 
470 
471 
505 template<typename HistogramType_, typename RealAvgType = double>
507  : public UniformBinsHistogramWithErrorBars<typename HistogramType_::Scalar, RealAvgType>
508 {
514  typedef HistogramType_ HistogramType;
517 
519  typedef typename Base_::Params Params;
521  typedef typename Base_::Scalar Scalar;
523  typedef typename Base_::CountType CountType;
524 
526  static constexpr bool HasErrorBars = true;
527 
534 
535 
542  AveragedHistogram(const Params& params = Params())
543  : Base_(params), num_histograms(0)
544  {
545  }
546 
553  inline void reset(const Params& params_)
554  {
555  Base_::params = params_;
556  Base_::reset();
557  num_histograms = 0;
558  }
559 
566  inline void reset()
567  {
568  Base_::reset();
569  num_histograms = 0;
570  }
571 
572  // ---------------------------------------------------------------------------
573  // Implementation in case the added histograms don't have their own error bars
574  // ---------------------------------------------------------------------------
575 
576  template<bool dummy = true,
578  inline void add_histogram(const HistogramType& histogram)
579  {
580  // bins collects the sum of the histograms
581  // delta for now collects the sum of squares. delta will be normalized in run_finished().
582 
583  eigen_assert((typename HistogramType::CountType)histogram.num_bins() ==
584  (typename HistogramType::CountType)Base_::num_bins());
585 
586  for (std::size_t k = 0; k < histogram.num_bins(); ++k) {
587  RealAvgType binvalue = histogram.count(k);
588  Base_::bins(k) += binvalue;
589  Base_::delta(k) += binvalue * binvalue;
590  }
591 
592  Base_::off_chart += histogram.off_chart;
593  ++num_histograms;
594  }
595  template<bool dummy = true,
597  inline void finalize()
598  {
602 
603  // delta = sqrt(< X^2 > - < X >^2) / sqrt(Nrepeats-1)
604  auto finhist2 = Base_::bins*Base_::bins; // for array, this is c-wise product
605  Base_::delta = ( (Base_::delta - finhist2) / (num_histograms-1) ).sqrt();
606  }
607 
608  // ---------------------------------------------------------------------------
609  // Implementation in case the added histograms do have their own error bars
610  // ---------------------------------------------------------------------------
611 
612  template<bool dummy = true,
614  inline void add_histogram(const HistogramType& histogram)
615  {
616  // bins collects the sum of the histograms
617  // delta for now collects the sum of squares. delta will be normalized in run_finished().
618 
619  eigen_assert((typename HistogramType::CountType)histogram.num_bins() == Base_::num_bins());
620 
621  for (std::size_t k = 0; k < histogram.num_bins(); ++k) {
622  RealAvgType binvalue = histogram.count(k);
623  Base_::bins(k) += binvalue;
624  RealAvgType bindelta = histogram.errorbar(k);
625  Base_::delta(k) += bindelta*bindelta;
626  }
627 
628  Base_::off_chart += histogram.off_chart;
629  ++num_histograms;
630  }
631  template<bool dummy = true,
633  inline void finalize()
634  {
635  Base_::bins /= num_histograms;
637 
640  }
641 
642 };
643 
644 
645 
646 
647 
648 namespace tomo_internal {
649 // internal helpers
650 //
651 // get labels left of histogram (generic HistogramType interface: no information, just bin #)
652 template<typename HistogramType>
653 struct histogram_pretty_print_label
654 {
655  static inline void getLabels(std::vector<std::string> & labels, const HistogramType & hist)
656  {
657  labels.resize(hist.num_bins());
658  for (std::size_t k = 0; k < hist.num_bins(); ++k) {
659  labels[k] = std::to_string(k);
660  }
661  }
662 };
663 // get labels left of histogram (for the family of histograms with 'Params':
664 // UniformBinsHistogram, UniformBinsHistogramWithErrorBars etc.)
665 //
666 // common code for several specializations of histogram_pretty_print_label
667 template<typename HistogramType>
668 inline void histogram_get_labels_for_hist_params(std::vector<std::string> & labels, const HistogramType& hist)
669 {
670  labels.resize(hist.num_bins());
671 
672  const double max_label_val = std::max(hist.bin_center_value(0), hist.bin_center_value(hist.num_bins()-1));
673  const int powten = (int)std::floor(std::log10(max_label_val));
674  const int relprecision = 4;
675  const int precision = (powten > relprecision) ? 0 : (relprecision - powten - 1);
676 
677  for (std::size_t k = 0; k < hist.num_bins(); ++k) {
679  ss << std::fixed << std::setprecision(precision) << std::right << hist.bin_center_value(k);
680  labels[k] = ss.str();
681  }
682 }
683 // specialize histogram pretty-print labels using the code above
684 template<typename Scalar_, typename CountType_>
685 struct histogram_pretty_print_label<UniformBinsHistogram<Scalar_, CountType_> >
686 {
687  typedef UniformBinsHistogram<Scalar_, CountType_> HistogramType;
688  static inline void getLabels(std::vector<std::string> & labels, const HistogramType & hist)
689  {
690  histogram_get_labels_for_hist_params<HistogramType>(labels, hist);
691  }
692 };
693 // specialize histogram pretty-print labels using the code above
694 template<typename Scalar_, typename CountType_>
695 struct histogram_pretty_print_label<UniformBinsHistogramWithErrorBars<Scalar_, CountType_> >
696 {
697  typedef UniformBinsHistogramWithErrorBars<Scalar_, CountType_> HistogramType;
698  static inline void getLabels(std::vector<std::string> & labels, const HistogramType & hist)
699  {
700  histogram_get_labels_for_hist_params<HistogramType>(labels, hist);
701  }
702 };
703 // specialize histogram pretty-print labels using the code above
704 template<typename BaseHistogramType_, typename RealAvgType_>
705 struct histogram_pretty_print_label<AveragedHistogram<BaseHistogramType_, RealAvgType_> >
706 {
707  typedef AveragedHistogram<BaseHistogramType_, RealAvgType_> HistogramType;
708  static inline void getLabels(std::vector<std::string> & labels, const HistogramType & hist)
709  {
710  histogram_get_labels_for_hist_params<HistogramType>(labels, hist);
711  }
712 };
713 
714 // format bin counts nicely
715 template<typename HistogramType>
716 struct histogram_pretty_print_value
717 {
718  const HistogramType & hist;
719  histogram_pretty_print_value(const HistogramType & hist_) : hist(hist_) { }
720 
721  template<bool dummy = true,
723  static inline void getStrValues(std::vector<std::string> & svalues, const HistogramType & hist)
724  {
725  svalues.resize(hist.num_bins());
726 
727  std::size_t k;
728  double max_val = 1.0;
729  for (k = 0; k < hist.num_bins(); ++k) {
730  if (k == 0 || hist.count(k) > max_val) {
731  max_val = hist.count(k);
732  }
733  }
734 
735  const int powten = (int)std::floor(std::log10(max_val));
736  const int relprecision = 3;
737  const int precision = abs_precision_for(powten, relprecision);
738  const int w = (precision > 0) ? (precision+powten+1) : (relprecision+2);
739 
740  for (std::size_t k = 0; k < hist.num_bins(); ++k) {
742  ss << std::setprecision(precision) << std::fixed << std::right << std::setw(w)
743  << hist.count(k);
744  svalues[k] = ss.str();
745  }
746  }
747  template<bool dummy = true,
749  static inline void getStrValues(std::vector<std::string> & svalues, const HistogramType & hist)
750  {
751  svalues.resize(hist.num_bins());
752 
753  std::size_t k;
754  double max_val = 1.0;
755  for (k = 0; k < hist.num_bins(); ++k) {
756  if (k == 0 || hist.count(k) > max_val) {
757  max_val = hist.count(k);
758  }
759  }
760 
761  const int powten = (int)std::floor(std::log10(max_val)); // floor of log_{10}(...)
762  const int relprecision = 3;
763  const int precision = abs_precision_for(powten, relprecision);
764  const int w = (precision > 0) ? (precision+powten+1) : (relprecision+2);
765 
766  for (k = 0; k < hist.num_bins(); ++k) {
768  ss << std::setprecision(precision) << std::fixed << std::right << std::setw(w)
769  << hist.count(k)
770  << " +- "
771  << std::setprecision(abs_precision_for(powten-1, relprecision-1)) << std::setw(w)
772  << hist.errorbar(k);
773  svalues[k] = ss.str();
774  }
775  }
776 private:
777  static inline int abs_precision_for(const int powten, const int relprecision)
778  {
779  return (powten > relprecision) ? 0 : (relprecision - powten - 1);
780  }
781 };
782 
784 //
785 // access this with public API using histogram_pretty_print().
786 //
787 template<typename HistogramType>
788 struct histogram_pretty_printer
789 {
790  const HistogramType & hist;
791  const int max_width;
792 
793  const std::string lsep;
794  const std::string rsep;
795 
797  int maxlabelwidth;
798 
799  std::vector<std::string> svalues;
800  int maxsvaluewidth;
801 
802  double max_value;
803 
804  int max_bar_width;
805  double barscale;
806 
807  histogram_pretty_printer(const HistogramType & hist_, const int max_width_)
808  : hist(hist_), max_width(max_width_), lsep(" |"), rsep(" ")
809  {
810  // first pass:
811  // - determine the maximum value attained in the histogram
812  // - determine maximum width of formatted label & value fields.
813 
814  labels.resize(hist.num_bins());
815  svalues.resize(hist.num_bins());
816 
817  histogram_pretty_print_label<HistogramType>::getLabels(labels, hist);
818  histogram_pretty_print_value<HistogramType>::getStrValues(svalues, hist);
819 
820  std::size_t k;
821  for (k = 0; k < hist.num_bins(); ++k) {
822  double val = maxval(k);
823 
824  if (k == 0 || val > max_value) {
825  max_value = val;
826  }
827  if (k == 0 || (int)labels[k].size() > maxlabelwidth) {
828  maxlabelwidth = labels[k].size();
829  }
830  if (k == 0 || (int)svalues[k].size() > maxsvaluewidth) {
831  maxsvaluewidth = svalues[k].size();
832  }
833  }
834 
835  max_bar_width = max_width - maxlabelwidth - maxsvaluewidth - lsep.size() - rsep.size();
836  if (max_bar_width < 2) {
837  max_bar_width = 2;
838  }
839  barscale = ((max_value > 0) ? (max_value / max_bar_width) : 1.0);
840  }
841 
842  inline int value_to_bar_length(double val) const
843  {
844  if (val < 0) {
845  val = 0;
846  }
847  int l = (int)(val/barscale+0.5);
848  if (l >= max_bar_width) {
849  return max_bar_width-1;
850  }
851  return l;
852  }
853 
854  inline void fill_str_len(std::string & s, double valstart, double valend,
855  char c, char clside, char crside) const
856  {
857  int vs = value_to_bar_length(valstart);
858  int ve = value_to_bar_length(valend);
859  eigen_assert(vs >= 0);
860  eigen_assert(vs < (int)s.size());
861  eigen_assert(ve >= 0);
862  eigen_assert(ve < (int)s.size());
863  for (int j = vs; j < ve; ++j) {
864  s[j] = c;
865  }
866  if (clside && crside && clside != crside && vs == ve) {
867  if (ve < (int)s.size()-1) {
868  ++ve;
869  } else if (vs > 1) {
870  --vs;
871  }
872  }
873  if (clside) {
874  s[vs] = clside;
875  }
876  if (crside) {
877  s[ve] = crside;
878  }
879  }
880 
881  inline void pretty_print(std::ostream & str) const
882  {
883  // perform now second pass:
884  // - display the histogram line by line, with the calculated widths.
885 
886  std::size_t k;
887 
888  for (k = 0; k < hist.num_bins(); ++k) {
889  str << std::setw(maxlabelwidth) << labels[k] << lsep
890  << make_bar(k) << rsep << std::setw(maxsvaluewidth) << svalues[k] << "\n";
891  }
892  }
893 
894 private:
895  // maxval(k): how much this bar may extend in length
896  template<bool dummy = true,
898  inline double maxval(const std::size_t k) const
899  {
900  return (double)hist.count(k);
901  }
902  template<bool dummy = true,
904  inline double maxval(const std::size_t k) const
905  {
906  return (double)(hist.count(k) + hist.errorbar(k));
907  }
908  // make_bar(k): produce the histogram bar in characters...
909  template<bool dummy = true,
911  inline std::string make_bar(std::size_t k) const
912  {
913  std::string sbar(max_bar_width, ' ');
914  fill_str_len(sbar, 0.0, hist.count(k), '*', 0, 0);
915  return sbar;
916  }
917  template<bool dummy = true,
919  inline std::string make_bar(std::size_t k) const
920  {
921  std::string sbar(max_bar_width, ' ');
922  const double binval = hist.count(k);
923  const double binerr = hist.errorbar(k);
924  fill_str_len(sbar, 0.0, binval - binerr, '*', '*', '*');
925  fill_str_len(sbar, binval - binerr, binval + binerr, '-', '|', '|');
926  return sbar;
927  }
928 };
929 
930 template<typename HistogramType>
931 inline std::string histogram_short_bar_fmt(const HistogramType & histogram, const bool log_scale,
932  const int max_width)
933 {
934  std::string s = Tools::fmts("%.2g|", (double)histogram.bin_lower_value(0));
935  std::string send = Tools::fmts("|%.2g", (double)histogram.bin_upper_value(histogram.num_bins()-1));
936  if (histogram.off_chart > 0) {
937  send += Tools::fmts(" [+%.1g off]", (double)histogram.off_chart);
938  }
939 
940  const int maxbarwidth = max_width - s.size() - send.size();
941  const int numdiv = (int)(std::ceil((float)histogram.num_bins() / maxbarwidth) + 0.5f);
942  const int barwidth = (int)(std::ceil((float)histogram.num_bins() / numdiv) + 0.5f);
943 
945  Eigen::ArrayXf veclog(barwidth);
946 
947  int k;
948  float minlogval = 0;
949  float maxlogval = 0;
950  for (k = 0; k < barwidth; ++k) {
951  vec(k) = histogram.bins.segment(numdiv*k, std::min((std::size_t)numdiv,
952  (std::size_t)(histogram.bins.size()-numdiv*k))).sum();
953  if (vec(k) > 0) {
954  if (log_scale) {
955  veclog(k) = std::log((float)vec(k));
956  } else {
957  veclog(k) = (float)vec(k);
958  }
959  if (k == 0 || minlogval > veclog(k)) {
960  minlogval = veclog(k);
961  }
962  if (k == 0 || maxlogval < veclog(k)) {
963  maxlogval = veclog(k) + 1e-6f;
964  }
965  } else {
966  veclog(k) = 0.f;
967  }
968  }
969 
970  // now, prepare string
971  const std::string chars = ".-+ox%#";
972  for (k = 0; k < barwidth; ++k) {
973  if (vec(k) <= 0) {
974  s += ' ';
975  } else {
976  int i = (int)(chars.size() * (veclog(k) - minlogval) / (maxlogval - minlogval));
977  if (i < 0) { i = 0; }
978  if (i >= (int)chars.size()) { i = chars.size()-1; }
979  s += chars[i];
980  }
981  }
982 
983  s += send;
984 
985  return s;
986 }
987 
996 int maybe_default_col_width(int max_width = 0)
997 {
998  if (max_width <= 0) {
999  const int offset = max_width;
1000  // decide of a maximum width to display
1001  max_width = 100; // default maximum width
1002  // If the user provided a value for the terminal width, use it. Note that $COLUMNS is
1003  // not in the environment usually, so you have to set it manually with e.g.
1004  // shell> export COLUMNS=$COLUMNS
1005  const char * cols_s = std::getenv("COLUMNS");
1006  if (cols_s != NULL) {
1007  max_width = std::atoi(cols_s);
1008  }
1009  max_width += offset; // if we had given, e.g. maxwidth=-4
1010  }
1011  return max_width;
1012 }
1013 
1014 } // namespace tomo_internal
1015 
1016 
1025 template<typename HistogramType>
1026 inline void histogram_pretty_print(std::ostream & str, const HistogramType & histogram, int max_width = 0)
1027 {
1028  eigen_assert(Tools::is_positive(histogram.params.num_bins));
1029 
1030  if (histogram.params.num_bins == 0) {
1031  str << "<empty histogram: no bins>\n";
1032  return;
1033  }
1034 
1035  max_width = tomo_internal::maybe_default_col_width(max_width);
1036  tomo_internal::histogram_pretty_printer<HistogramType>(histogram, max_width).pretty_print(str);
1037 }
1038 
1047 template<typename HistogramType>
1048 inline std::string histogram_pretty_print(const HistogramType & histogram, int max_width = 0)
1049 {
1050  std::ostringstream ss;
1051  histogram_pretty_print<HistogramType>(ss, histogram, max_width);
1052  return ss.str();
1053 }
1054 
1072 template<typename HistogramType>
1073 inline int histogram_short_bar(std::ostream & str, const HistogramType & histogram,
1074  bool log_scale = true, int max_width = 0)
1075 {
1076  eigen_assert(Tools::is_positive(histogram.params.num_bins));
1077 
1078  max_width = tomo_internal::maybe_default_col_width(max_width);
1079 
1080  std::string s;
1081  if (histogram.params.num_bins == 0) {
1082  s = "<empty histogram: no bins>";
1083  } else {
1084  s = tomo_internal::histogram_short_bar_fmt<HistogramType>(histogram, log_scale, max_width);
1085  }
1086 
1087  str << s;
1088  return max_width - s.size();
1089 }
1100 template<typename HistogramType>
1101 inline std::string histogram_short_bar(const HistogramType & histogram, bool log_scale = true, int max_width = 0)
1102 {
1103  eigen_assert(Tools::is_positive(histogram.params.num_bins));
1104 
1105  if (histogram.params.num_bins == 0) {
1106  return "<empty histogram: no bins>";
1107  }
1108 
1109  max_width = tomo_internal::maybe_default_col_width(max_width);
1110  return tomo_internal::histogram_short_bar_fmt<HistogramType>(histogram, log_scale, max_width);
1111 }
1112 
1113 
1114 
1115 
1116 
1117 
1118 } // namespace Tomographer
1119 
1120 
1121 
1122 
1123 #endif
Utilities for formatting strings.
Params params
Parameters of this histogram (range and # of bins)
Definition: histogram.h:185
UniformBinsHistogram(Params p=Params())
Constructor: stores the parameters and initializes the histogram to zero counts everywhere.
Definition: histogram.h:192
CountType count(std::size_t i) const
Shorthand for bins(i)
Definition: histogram.h:285
T atoi(T...args)
Scalar bin_lower_value(int index) const
Shorthand for params.bin_lower_value(index)
Definition: histogram.h:301
Eigen::Array< CountType, Eigen::Dynamic, 1 > bins
The counts for each bin.
Definition: histogram.h:187
Combines several histograms (with same parameters) into an averaged histogram.
Definition: histogram.h:506
Base_::Params Params
The histogram parameters' type. See UniformBinsHistogramWithErrorBars::Params.
Definition: histogram.h:519
Base namespace for the Tomographer project.
Definition: dmmhrw.h:51
T ceil(T...args)
std::string pretty_print(int max_width=0) const
Print the histogram in human readable form.
Definition: histogram.h:459
void add(const UniformBinsHistogram< OtherScalar, OtherCountType > &x)
Add data to the histogram.
Definition: histogram.h:268
int num_histograms
The number of histograms averaged.
Definition: histogram.h:533
T log(T...args)
Base_::CountType CountType
The histogram' count type. This is exactly the same as RealAvgType.
Definition: histogram.h:523
Stores a histogram along with error bars.
Definition: histogram.h:385
Scalar min
Lower range value.
Definition: histogram.h:96
T to_string(T...args)
void reset()
Resets the histogram to zero counts everywhere.
Definition: histogram.h:214
T right(T...args)
std::enable_if< std::is_unsigned< X >::value, bool >::type is_positive(const X)
Test whether the given value is positive or zero.
Definition: util.h:96
CountType_ CountType
The type that serves to count how many hits in each bin.
Definition: histogram.h:71
Eigen::Array< CountType, Eigen::Dynamic, 1 > delta
The error bars associated with each histogram bin.
Definition: histogram.h:402
void reset()
Resets the data keeping the exisiting params.
Definition: histogram.h:566
T floor(T...args)
T log10(T...args)
UniformBinsHistogramWithErrorBars< typename HistogramType_::Scalar, RealAvgType > Base_
Shortcut for our base class' type.
Definition: histogram.h:516
Scalar bin_center_value(std::size_t index) const
Returns the value which a given bin index represents (center bin value)
Definition: histogram.h:156
T setw(T...args)
int histogram_short_bar(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:1073
T resize(T...args)
STL class.
std::size_t num_bins() const
Shorthand for params.num_bins
Definition: histogram.h:279
T getenv(T...args)
T min(T...args)
Base_::Scalar Scalar
The histogram's X-axis scalar type. See UniformBinsHistogramWithErrorBars::Scalar.
Definition: histogram.h:521
The parameters of a UniformBinsHistogram.
Definition: histogram.h:80
std::size_t num_bins
Number of bins to split the range into.
Definition: histogram.h:100
std::string pretty_print(int max_width=0) const
Pretty-print the histogram and return it as a string with horizontal bars.
Definition: histogram.h:370
UniformBinsHistogramWithErrorBars(Scalar min, Scalar max, std::size_t num_bins)
Constructor, with given histogram parameters.
Definition: histogram.h:425
CountType errorbar(std::size_t i) const
For the Histogram Interface. Get error bar for bin number i.
Definition: histogram.h:447
CountType_ CountType
The Type used to keep track of counts. See UniformBinsHistogram::CountType.
Definition: histogram.h:390
std::size_t bin_index(Scalar value) const
Returns which bin this value should be counted in (index in bins array)
Definition: histogram.h:116
Scalar bin_resolution() const
Returns the width of a bin.
Definition: histogram.h:178
Scalar bin_upper_value(std::size_t index) const
Returns the value which a given bin index represents (upper bin value limit)
Definition: histogram.h:169
void histogram_pretty_print(std::ostream &str, const HistogramType &histogram, int max_width=0)
pretty-print the given histogram.
Definition: histogram.h:1026
Scalar_ Scalar
The Scalar (X-axis) Type. See UniformBinsHistogram::Scalar.
Definition: histogram.h:388
HistogramType_ HistogramType
Type of the individual histograms we are averaging.
Definition: histogram.h:514
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:199
Scalar bin_upper_value(std::size_t index) const
Shorthand for params.bin_upper_value(index)
Definition: histogram.h:311
static constexpr bool HasErrorBars
This histogram type does not provide error bars (see Histogram Interface)
Definition: histogram.h:74
T isfinite(T...args)
bool is_within_bounds(Scalar value) const
Shorthand for params.is_within_bounds(value)
Definition: histogram.h:291
Scalar bin_lower_value(std::size_t index) const
Returns the value which a given bin index represents (lower bin value limit)
Definition: histogram.h:144
T fabs(T...args)
std::size_t record(Scalar value)
Record a new value in the histogram.
Definition: histogram.h:331
Params(const OtherParams &other)
Copy constructor, from any other UniformBinsHistogram::Params type.
Definition: histogram.h:90
Scalar bin_resolution() const
Shorthand for params.bin_resolution()
Definition: histogram.h:317
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:231
Scalar max
Upper range value.
Definition: histogram.h:98
T size(T...args)
UniformBinsHistogramWithErrorBars(Params params=Params())
Constructor, with given histogram parameters.
Definition: histogram.h:415
CountType off_chart
The number of points that fell outside of the given range.
Definition: histogram.h:189
std::string fmts(const char *fmt,...)
printf- format to a std::string
Definition: fmt.h:122
STL class.
Base_::Params Params
Shortcut for our base class' histogram parameters. See UniformBinsHistogram
Definition: histogram.h:396
void add(const Eigen::ArrayBase< EigenType > &x, CountType off_chart_=0)
Add data to the histogram.
Definition: histogram.h:248
std::size_t record(Scalar value, CountType weight)
Record a new value in the histogram, with a certain weight.
Definition: histogram.h:353
UniformBinsHistogram(const HistogramType &other)
Constructor: copy another histogram type.
Definition: histogram.h:207
const CwiseUnaryOp< internal::scalar_sqrt_op< Scalar >, const Array< _Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols > > sqrt() const
Scalar bin_center_value(std::size_t index) const
Shorthand for params.bin_center_value(index)
Definition: histogram.h:306
std::size_t bin_index(Scalar value) const
Shorthand for params.bin_index(value)
Definition: histogram.h:296
void reset(const Params &params_)
Resets the data and sets new params.
Definition: histogram.h:553
AveragedHistogram(const Params &params=Params())
Constructs an AveragedHistogram with the given histogram parameters.
Definition: histogram.h:542
T sqrt(T...args)
Stores a histogram.
Definition: histogram.h:65
void reset()
Resets the histogram to zero counts everywhere, and zero error bars.
Definition: histogram.h:436
void resize(Index nbRows, Index nbCols)
#define streamstr(tokens)
Utility macro to format stream tokens to a std::string.
Definition: fmt.h:143
Params(Scalar min_=0.0, Scalar max_=1.0, std::size_t num_bins_=50)
obvious constructor
Definition: histogram.h:82
bool is_within_bounds(Scalar value) const
Tests whether the given value is in the range of the histogram.
Definition: histogram.h:107
T setprecision(T...args)
STL class.
std::size_t bin_index_unsafe(Scalar value) const
Returns which bin this value should be counted in.
Definition: histogram.h:132
UniformBinsHistogram< Scalar_, CountType_ > Base_
Shortcut for our base class type.
Definition: histogram.h:393
Scalar_ Scalar
The scalar type of the "X"-axis of the histogram (usually double)
Definition: histogram.h:68
Basic utilities for dealing with Eigen matrices and other types.
Derived & setZero(Index size)