Go to the documentation of this file.00001 #include <cmath>
00002 #include <cassert>
00003 #include <climits>
00004 #include "JetMETCorrections/InterpolationTables/interface/NpstatException.h"
00005 #include <algorithm>
00006
00007 #include "Alignment/Geners/interface/binaryIO.hh"
00008 #include "Alignment/Geners/interface/IOException.hh"
00009 #include "JetMETCorrections/InterpolationTables/interface/NUHistoAxis.h"
00010
00011 #include "JetMETCorrections/InterpolationTables/interface/EquidistantSequence.h"
00012 #include "JetMETCorrections/InterpolationTables/interface/closeWithinTolerance.h"
00013
00014 namespace npstat {
00015 NUHistoAxis::NUHistoAxis(const std::vector<double>& binEdges,
00016 const char* label)
00017 : binEdges_(binEdges), nBins_(binEdges.size() - 1U), uniform_(false)
00018 {
00019 if (!(binEdges_.size() > 1U && binEdges_.size() < UINT_MAX/2U))
00020 throw npstat::NpstatInvalidArgument("In npstat::NUHistoAxis constructor: "
00021 "number of bin edges is out of range");
00022 std::sort(binEdges_.begin(), binEdges_.end());
00023 min_ = binEdges_[0];
00024 max_ = binEdges_[nBins_];
00025 if (label)
00026 label_ = std::string(label);
00027 }
00028
00029 NUHistoAxis::NUHistoAxis(const unsigned nBins,
00030 const double min, const double max,
00031 const char* label)
00032 : min_(min), max_(max), nBins_(nBins), uniform_(true)
00033 {
00034 if (!(nBins_ && nBins_ < UINT_MAX/2U - 1U))
00035 throw npstat::NpstatInvalidArgument("In npstat::NUHistoAxis constructor: "
00036 "number of bins is out of range");
00037 if (min_ > max_)
00038 std::swap(min_, max_);
00039 binEdges_ = EquidistantInLinearSpace(min_, max_, nBins+1U);
00040 if (label)
00041 label_ = std::string(label);
00042 }
00043
00044 bool NUHistoAxis::isClose(const NUHistoAxis& r, const double tol) const
00045 {
00046 if (!(closeWithinTolerance(min_, r.min_, tol) &&
00047 closeWithinTolerance(max_, r.max_, tol) &&
00048 label_ == r.label_ &&
00049 nBins_ == r.nBins_ &&
00050 uniform_ == r.uniform_))
00051 return false;
00052 for (unsigned i=0; i<nBins_; ++i)
00053 if (!closeWithinTolerance(binEdges_[i], r.binEdges_[i], tol))
00054 return false;
00055 return true;
00056 }
00057
00058 bool NUHistoAxis::operator==(const NUHistoAxis& r) const
00059 {
00060 return min_ == r.min_ &&
00061 max_ == r.max_ &&
00062 label_ == r.label_ &&
00063 nBins_ == r.nBins_ &&
00064 binEdges_ == r.binEdges_ &&
00065 uniform_ == r.uniform_;
00066 }
00067
00068 bool NUHistoAxis::operator!=(const NUHistoAxis& r) const
00069 {
00070 return !(*this == r);
00071 }
00072
00073 int NUHistoAxis::binNumber(const double x) const
00074 {
00075 const int delta = std::upper_bound(binEdges_.begin(), binEdges_.end(), x) -
00076 binEdges_.begin();
00077 return delta - 1;
00078 }
00079
00080 double NUHistoAxis::fltBinNumber(const double x, const bool mapLeftEdgeTo0) const
00081 {
00082 const int delta = std::upper_bound(binEdges_.begin(), binEdges_.end(), x) -
00083 binEdges_.begin();
00084 const int binnum = delta - 1;
00085
00086 if (binnum < 0)
00087 {
00088 const double left = binEdges_[0];
00089 const double right = binEdges_[1];
00090 double bval = (x - left)/(right - left);
00091 if (!mapLeftEdgeTo0)
00092 bval -= 0.5;
00093 if (bval < -1.0)
00094 bval = -1.0;
00095 return bval;
00096 }
00097 else if (static_cast<unsigned>(binnum) >= nBins_)
00098 {
00099 const double left = binEdges_[nBins_ - 1U];
00100 const double right = binEdges_[nBins_];
00101 double bval = nBins_ - 1U + (x - left)/(right - left);
00102 if (!mapLeftEdgeTo0)
00103 bval -= 0.5;
00104 if (bval > static_cast<double>(nBins_))
00105 bval = nBins_;
00106 return bval;
00107 }
00108 else
00109 {
00110 const double left = binEdges_[binnum];
00111 const double right = binEdges_[delta];
00112 if (mapLeftEdgeTo0)
00113 return binnum + (x - left)/(right - left);
00114 else
00115 {
00116
00117
00118
00119 const double binCenter = (left + right)/2.0;
00120 if ((binnum == 0 && x <= binCenter) ||
00121 (static_cast<unsigned>(binnum) == nBins_ - 1 && x >= binCenter))
00122 return binnum + (x - left)/(right - left) - 0.5;
00123 else if (x <= binCenter)
00124 {
00125 const double otherBinCenter = (left + binEdges_[binnum - 1])/2.0;
00126 return binnum + (x - binCenter)/(binCenter - otherBinCenter);
00127 }
00128 else
00129 {
00130 const double otherBinCenter = (right + binEdges_[binnum + 1])/2.0;
00131 return binnum + (x - binCenter)/(otherBinCenter - binCenter);
00132 }
00133 }
00134 }
00135 }
00136
00137 unsigned NUHistoAxis::closestValidBin(const double x) const
00138 {
00139 const int delta = std::upper_bound(binEdges_.begin(), binEdges_.end(), x) -
00140 binEdges_.begin();
00141 int binnum = delta - 1;
00142 if (binnum < 0)
00143 binnum = 0;
00144 else if (static_cast<unsigned>(binnum) >= nBins_)
00145 binnum = nBins_ - 1U;
00146 return binnum;
00147 }
00148
00149 bool NUHistoAxis::write(std::ostream& of) const
00150 {
00151 gs::write_pod_vector(of, binEdges_);
00152 gs::write_pod(of, label_);
00153 unsigned char c = uniform_;
00154 gs::write_pod(of, c);
00155 return !of.fail();
00156 }
00157
00158 NUHistoAxis* NUHistoAxis::read(const gs::ClassId& id, std::istream& in)
00159 {
00160 static const gs::ClassId current(gs::ClassId::makeId<NUHistoAxis>());
00161 current.ensureSameId(id);
00162
00163 std::vector<double> binEdges;
00164 std::string label;
00165 unsigned char unif;
00166 gs::read_pod_vector(in, &binEdges);
00167 gs::read_pod(in, &label);
00168 gs::read_pod(in, &unif);
00169 if (in.fail())
00170 throw gs::IOReadFailure("In npstat::UHistoAxis::read: "
00171 "input stream failure");
00172 NUHistoAxis* result = new NUHistoAxis(binEdges, label.c_str());
00173 result->uniform_ = unif;
00174 return result;
00175 }
00176 }