CMS 3D CMS Logo

NUHistoAxis.cc
Go to the documentation of this file.
1 #include <cmath>
2 #include <cassert>
3 #include <climits>
5 #include <algorithm>
6 
7 #include "Alignment/Geners/interface/binaryIO.hh"
8 #include "Alignment/Geners/interface/IOException.hh"
10 
13 
14 namespace npstat {
15  NUHistoAxis::NUHistoAxis(const std::vector<double>& binEdges, const char* label)
16  : binEdges_(binEdges), nBins_(binEdges.size() - 1U), uniform_(false) {
17  if (!(binEdges_.size() > 1U && binEdges_.size() < UINT_MAX / 2U))
19  "In npstat::NUHistoAxis constructor: "
20  "number of bin edges is out of range");
21  std::sort(binEdges_.begin(), binEdges_.end());
22  min_ = binEdges_[0];
24  if (label)
26  }
27 
28  NUHistoAxis::NUHistoAxis(const unsigned nBins, const double min, const double max, const char* label)
29  : min_(min), max_(max), nBins_(nBins), uniform_(true) {
30  if (!(nBins_ && nBins_ < UINT_MAX / 2U - 1U))
32  "In npstat::NUHistoAxis constructor: "
33  "number of bins is out of range");
34  if (min_ > max_)
37  if (label)
39  }
40 
41  NUHistoAxis NUHistoAxis::rebin(const unsigned newBins) const {
42  return NUHistoAxis(newBins, min_, max_, label_.c_str());
43  }
44 
45  bool NUHistoAxis::isClose(const NUHistoAxis& r, const double tol) const {
46  if (!(closeWithinTolerance(min_, r.min_, tol) && closeWithinTolerance(max_, r.max_, tol) && label_ == r.label_ &&
47  nBins_ == r.nBins_ && uniform_ == r.uniform_))
48  return false;
49  for (unsigned i = 0; i < nBins_; ++i)
50  if (!closeWithinTolerance(binEdges_[i], r.binEdges_[i], tol))
51  return false;
52  return true;
53  }
54 
55  bool NUHistoAxis::operator==(const NUHistoAxis& r) const {
56  return min_ == r.min_ && max_ == r.max_ && label_ == r.label_ && nBins_ == r.nBins_ && binEdges_ == r.binEdges_ &&
57  uniform_ == r.uniform_;
58  }
59 
60  bool NUHistoAxis::operator!=(const NUHistoAxis& r) const { return !(*this == r); }
61 
62  int NUHistoAxis::binNumber(const double x) const {
63  const int delta = std::upper_bound(binEdges_.begin(), binEdges_.end(), x) - binEdges_.begin();
64  return delta - 1;
65  }
66 
67  double NUHistoAxis::fltBinNumber(const double x, const bool mapLeftEdgeTo0) const {
68  const int delta = std::upper_bound(binEdges_.begin(), binEdges_.end(), x) - binEdges_.begin();
69  const int binnum = delta - 1;
70 
71  if (binnum < 0) {
72  const double left = binEdges_[0];
73  const double right = binEdges_[1];
74  double bval = (x - left) / (right - left);
75  if (!mapLeftEdgeTo0)
76  bval -= 0.5;
77  if (bval < -1.0)
78  bval = -1.0;
79  return bval;
80  } else if (static_cast<unsigned>(binnum) >= nBins_) {
81  const double left = binEdges_[nBins_ - 1U];
82  const double right = binEdges_[nBins_];
83  double bval = nBins_ - 1U + (x - left) / (right - left);
84  if (!mapLeftEdgeTo0)
85  bval -= 0.5;
86  if (bval > static_cast<double>(nBins_))
87  bval = nBins_;
88  return bval;
89  } else {
90  const double left = binEdges_[binnum];
91  const double right = binEdges_[delta];
92  if (mapLeftEdgeTo0)
93  return binnum + (x - left) / (right - left);
94  else {
95  // It is not obvious what is best to do here.
96  // The following works to preserve interpolation
97  // of 0th order. The commented out snippet below
98  // would instead connect bin centers by straight
99  // lines during interpolation.
100  return binnum + (x - left) / (right - left) - 0.5;
101 
102  // Bin center is mapped to binnum.
103  // Bin center of the next bin is mapped to binnum + 1.
104  // Bin center of the previous bin is mapped to binnum - 1.
105  //
106  // const double binCenter = (left + right)/2.0;
107  // if ((binnum == 0 && x <= binCenter) ||
108  // (static_cast<unsigned>(binnum) == nBins_ - 1 && x >= binCenter))
109  // return binnum + (x - left)/(right - left) - 0.5;
110  // else if (x <= binCenter)
111  // {
112  // const double otherBinCenter = (left + binEdges_[binnum - 1])/2.0;
113  // return binnum + (x - binCenter)/(binCenter - otherBinCenter);
114  // }
115  // else
116  // {
117  // const double otherBinCenter = (right + binEdges_[binnum + 2])/2.0;
118  // return binnum + (x - binCenter)/(otherBinCenter - binCenter);
119  // }
120  }
121  }
122  }
123 
124  unsigned NUHistoAxis::closestValidBin(const double x) const {
125  const int delta = std::upper_bound(binEdges_.begin(), binEdges_.end(), x) - binEdges_.begin();
126  int binnum = delta - 1;
127  if (binnum < 0)
128  binnum = 0;
129  else if (static_cast<unsigned>(binnum) >= nBins_)
130  binnum = nBins_ - 1U;
131  return binnum;
132  }
133 
134  bool NUHistoAxis::write(std::ostream& of) const {
135  gs::write_pod_vector(of, binEdges_);
136  gs::write_pod(of, label_);
137  unsigned char c = uniform_;
138  gs::write_pod(of, c);
139  return !of.fail();
140  }
141 
142  NUHistoAxis* NUHistoAxis::read(const gs::ClassId& id, std::istream& in) {
143  static const gs::ClassId current(gs::ClassId::makeId<NUHistoAxis>());
144  current.ensureSameId(id);
145 
146  std::vector<double> binEdges;
148  unsigned char unif;
149  gs::read_pod_vector(in, &binEdges);
150  gs::read_pod(in, &label);
151  gs::read_pod(in, &unif);
152  if (in.fail())
153  throw gs::IOReadFailure(
154  "In npstat::UHistoAxis::read: "
155  "input stream failure");
156  NUHistoAxis* result = new NUHistoAxis(binEdges, label.c_str());
157  result->uniform_ = unif;
158  return result;
159  }
160 } // namespace npstat
std::vector< double > binEdges_
Definition: NUHistoAxis.h:108
NUHistoAxis rebin(unsigned newBins) const
Definition: NUHistoAxis.cc:41
unsigned closestValidBin(double x) const
Definition: NUHistoAxis.cc:124
bool closeWithinTolerance(const double &a, const double &b, const double &tol)
unsigned nBins() const
Definition: NUHistoAxis.h:43
double fltBinNumber(double x, bool mapLeftEdgeTo0=true) const
Definition: NUHistoAxis.cc:67
Histogram axis with non-uniform bin spacing.
bool write(std::ostream &of) const
Definition: NUHistoAxis.cc:134
bool operator==(const NUHistoAxis &) const
Definition: NUHistoAxis.cc:55
void swap(Association< C > &lhs, Association< C > &rhs)
Definition: Association.h:112
char const * label
Equidistant sequences of points in either linear or log space.
Exceptions for the npstat namespace.
std::string label_
Definition: NUHistoAxis.h:109
Determine if two doubles are within requested relative tolerance of each other.
int binNumber(double x) const
Definition: NUHistoAxis.cc:62
static NUHistoAxis * read(const gs::ClassId &id, std::istream &in)
Definition: NUHistoAxis.cc:142
bool operator!=(const NUHistoAxis &) const
Definition: NUHistoAxis.cc:60
const std::string & label() const
Definition: NUHistoAxis.h:45
float x
bool isClose(const NUHistoAxis &, double tol) const
Definition: NUHistoAxis.cc:45