Go to the documentation of this file.00001 #include <cmath>
00002 #include <climits>
00003 #include <algorithm>
00004 #include "JetMETCorrections/InterpolationTables/interface/NpstatException.h"
00005
00006 #include "Alignment/Geners/interface/binaryIO.hh"
00007 #include "Alignment/Geners/interface/IOException.hh"
00008
00009 #include "JetMETCorrections/InterpolationTables/interface/closeWithinTolerance.h"
00010 #include "JetMETCorrections/InterpolationTables/interface/HistoAxis.h"
00011
00012 namespace npstat {
00013 HistoAxis::HistoAxis(const unsigned nbins, const double min,
00014 const double max, const char* label)
00015 : min_(min), max_(max), label_(label ? label : ""), nBins_(nbins)
00016 {
00017 if (!(nBins_ && nBins_ < UINT_MAX/2U - 1U))
00018 throw npstat::NpstatInvalidArgument("In npstat::HistoAxis constructor: "
00019 "number of bins is out of range");
00020 if (min_ > max_)
00021 std::swap(min_, max_);
00022 bw_ = (max_ - min_)/nBins_;
00023 }
00024
00025 bool HistoAxis::isClose(const HistoAxis& r, const double tol) const
00026 {
00027 return closeWithinTolerance(min_, r.min_, tol) &&
00028 closeWithinTolerance(max_, r.max_, tol) &&
00029 label_ == r.label_ &&
00030 nBins_ == r.nBins_;
00031 }
00032
00033 bool HistoAxis::operator==(const HistoAxis& r) const
00034 {
00035 return min_ == r.min_ &&
00036 max_ == r.max_ &&
00037 label_ == r.label_ &&
00038 nBins_ == r.nBins_;
00039 }
00040
00041 bool HistoAxis::operator!=(const HistoAxis& r) const
00042 {
00043 return !(*this == r);
00044 }
00045
00046 int HistoAxis::binNumber(const double x) const
00047 {
00048 if (bw_)
00049 {
00050 int binnum = static_cast<int>(floor((x - min_)/bw_));
00051 if (x >= max_)
00052 {
00053 if (binnum < static_cast<int>(nBins_))
00054 binnum = nBins_;
00055 }
00056 else
00057 {
00058 if (binnum >= static_cast<int>(nBins_))
00059 binnum = nBins_ - 1U;
00060 }
00061 return binnum;
00062 }
00063 else
00064 {
00065 if (x < min_)
00066 return -1;
00067 else
00068 return nBins_;
00069 }
00070 }
00071
00072 unsigned HistoAxis::closestValidBin(const double x) const
00073 {
00074 if (x <= min_)
00075 return 0U;
00076 else if (bw_ && x < max_)
00077 {
00078 const unsigned binnum = static_cast<unsigned>(floor((x-min_)/bw_));
00079 if (binnum < nBins_)
00080 return binnum;
00081 }
00082 return nBins_ - 1U;
00083 }
00084
00085 LinearMapper1d HistoAxis::binNumberMapper(const bool mapLeftEdgeTo0) const
00086 {
00087 if (!bw_) throw npstat::NpstatDomainError(
00088 "In npstat::HistoAxis::binNumberMapper: "
00089 "bin width is zero. Mapper can not be constructed.");
00090 const double base = mapLeftEdgeTo0 ? min_/bw_ : min_/bw_ + 0.5;
00091 return LinearMapper1d(1.0/bw_, -base);
00092 }
00093
00094 CircularMapper1d HistoAxis::kernelScanMapper(const bool doubleRange) const
00095 {
00096 if (!bw_) throw npstat::NpstatDomainError(
00097 "In npstat::HistoAxis::kernelScanMapper: "
00098 "bin width is zero. Mapper can not be constructed.");
00099 double range = max_ - min_;
00100 if (doubleRange)
00101 range *= 2.0;
00102 return CircularMapper1d(bw_, 0.0, range);
00103 }
00104
00105 unsigned HistoAxis::overflowIndexWeighted(
00106 const double x, unsigned* binNumber, double *weight) const
00107 {
00108 if (x < min_)
00109 return 0U;
00110 else if (x >= max_)
00111 return 2U;
00112 else
00113 {
00114 if (nBins_ <= 1U) throw npstat::NpstatInvalidArgument(
00115 "In npstat::HistoAxis::overflowIndexWeighted: "
00116 "must have more than one bin");
00117 const double dbin = (x - min_)/bw_;
00118 if (dbin <= 0.5)
00119 {
00120 *binNumber = 0;
00121 *weight = 1.0;
00122 }
00123 else if (dbin >= nBins_ - 0.5)
00124 {
00125 *binNumber = nBins_ - 2;
00126 *weight = 0.0;
00127 }
00128 else
00129 {
00130 const unsigned bin = static_cast<unsigned>(dbin - 0.5);
00131 *binNumber = bin >= nBins_ - 1U ? nBins_ - 2U : bin;
00132 *weight = 1.0 - (dbin - 0.5 - *binNumber);
00133 }
00134 return 1U;
00135 }
00136 }
00137
00138 bool HistoAxis::write(std::ostream& of) const
00139 {
00140 gs::write_pod(of, min_);
00141 gs::write_pod(of, max_);
00142 gs::write_pod(of, label_);
00143 gs::write_pod(of, nBins_);
00144 return !of.fail();
00145 }
00146
00147 HistoAxis* HistoAxis::read(const gs::ClassId& id, std::istream& in)
00148 {
00149 static const gs::ClassId current(gs::ClassId::makeId<HistoAxis>());
00150 current.ensureSameId(id);
00151
00152 double min = 0.0, max = 0.0;
00153 std::string label;
00154 unsigned nBins = 0;
00155
00156 gs::read_pod(in, &min);
00157 gs::read_pod(in, &max);
00158 gs::read_pod(in, &label);
00159 gs::read_pod(in, &nBins);
00160
00161 if (!in.fail())
00162 return new HistoAxis(nBins, min, max, label.c_str());
00163 else
00164 throw gs::IOReadFailure("In npstat::HistoAxis::read: "
00165 "input stream failure");
00166 }
00167 }