00001 #include <cmath>
00002 #include <algorithm>
00003 #include "JetMETCorrections/InterpolationTables/interface/NpstatException.h"
00004
00005 #include "Alignment/Geners/interface/binaryIO.hh"
00006 #include "Alignment/Geners/interface/IOException.hh"
00007
00008 #include "JetMETCorrections/InterpolationTables/interface/GridAxis.h"
00009 #include "JetMETCorrections/InterpolationTables/interface/closeWithinTolerance.h"
00010
00011 namespace npstat {
00012 void GridAxis::initialize()
00013 {
00014 if (npt_ <= 1U) throw npstat::NpstatInvalidArgument(
00015 "In npstat::GridAxis::initialize: insufficient number "
00016 "of coordinates (at least 2 are required)");
00017 std::sort(coords_.begin(), coords_.end());
00018 const double* c = &coords_[0];
00019 if (useLogSpace_)
00020 {
00021 logs_.reserve(npt_);
00022 for (unsigned i=0; i<npt_; ++i)
00023 {
00024 if (c[i] <= 0.0) throw npstat::NpstatInvalidArgument(
00025 "In npstat::GridAxis::initialize: in log space"
00026 "all coordinates must be positive");
00027 logs_.push_back(log(c[i]));
00028 }
00029 }
00030
00031
00032 for (unsigned i=1; i<npt_; ++i)
00033 if (c[i] <= c[i - 1U]) throw npstat::NpstatInvalidArgument(
00034 "In npstat::GridAxis::initialize: "
00035 "all coordinates must be distinct");
00036 }
00037
00038 GridAxis::GridAxis(const std::vector<double>& coords,
00039 const bool useLogSpace)
00040 : coords_(coords),
00041 npt_(coords_.size()),
00042 useLogSpace_(useLogSpace)
00043 {
00044 initialize();
00045 }
00046
00047 GridAxis::GridAxis(const std::vector<double>& coords,
00048 const char* label,
00049 const bool useLogSpace)
00050 : coords_(coords),
00051 label_(label ? label : ""),
00052 npt_(coords_.size()),
00053 useLogSpace_(useLogSpace)
00054 {
00055 initialize();
00056 }
00057
00058 std::pair<unsigned,double> GridAxis::getInterval(const double x) const
00059 {
00060 if (useLogSpace_)
00061 if (x <= 0.0) throw npstat::NpstatDomainError(
00062 "In GridAxis::getInterval: argument must be positive");
00063 const double* c = &coords_[0];
00064 if (x <= c[0])
00065 return std::pair<unsigned,double>(0U, 1.0);
00066 else if (x >= c[npt_ - 1U])
00067 return std::pair<unsigned,double>(npt_ - 2U, 0.0);
00068 else
00069 {
00070 unsigned ibnd = lower_bound
00071 (coords_.begin(), coords_.end(), x) - coords_.begin();
00072 --ibnd;
00073 if (useLogSpace_)
00074 {
00075 const double* l = &logs_[0];
00076 const double w = 1.0 - (log(x) - l[ibnd])/
00077 (l[ibnd + 1U] - l[ibnd]);
00078 return std::pair<unsigned,double>(ibnd, w);
00079 }
00080 else
00081 {
00082 const double w = 1.0 - (x - c[ibnd])/(c[ibnd + 1U] - c[ibnd]);
00083 return std::pair<unsigned,double>(ibnd, w);
00084 }
00085 }
00086 }
00087
00088 std::pair<unsigned,double> GridAxis::linearInterval(const double x) const
00089 {
00090 if (useLogSpace_)
00091 if (x <= 0.0) throw npstat::NpstatDomainError(
00092 "In GridAxis::linearInterval: argument must be positive");
00093 const double* c = &coords_[0];
00094 if (x <= c[0])
00095 {
00096 if (useLogSpace_)
00097 {
00098 const double* l = &logs_[0];
00099 const double bw = l[1] - l[0];
00100 return std::pair<unsigned,double>(0U, 1.0 - (log(x) - l[0])/bw);
00101 }
00102 else
00103 {
00104 const double bw = c[1] - c[0];
00105 return std::pair<unsigned,double>(0U, 1.0 - (x - c[0])/bw);
00106 }
00107 }
00108 else if (x >= c[npt_ - 1U])
00109 {
00110 if (useLogSpace_)
00111 {
00112 const double* l = &logs_[0];
00113 const double bw = l[npt_ - 1U] - l[npt_ - 2U];
00114 return std::pair<unsigned,double>(
00115 npt_ - 2U, (l[npt_ - 1U] - log(x))/bw);
00116 }
00117 else
00118 {
00119 const double bw = c[npt_ - 1U] - c[npt_ - 2U];
00120 return std::pair<unsigned,double>(
00121 npt_ - 2U, (c[npt_ - 1U] - x)/bw);
00122 }
00123 }
00124 else
00125 {
00126 unsigned ibnd = lower_bound
00127 (coords_.begin(), coords_.end(), x) - coords_.begin();
00128 --ibnd;
00129 if (useLogSpace_)
00130 {
00131 const double* l = &logs_[0];
00132 const double w = 1.0 - (log(x) - l[ibnd])/
00133 (l[ibnd + 1U] - l[ibnd]);
00134 return std::pair<unsigned,double>(ibnd, w);
00135 }
00136 else
00137 {
00138 const double w = 1.0 - (x - c[ibnd])/(c[ibnd + 1U] - c[ibnd]);
00139 return std::pair<unsigned,double>(ibnd, w);
00140 }
00141 }
00142 }
00143
00144 bool GridAxis::write(std::ostream& of) const
00145 {
00146
00147
00148 gs::write_pod_vector(of, coords_);
00149 gs::write_pod(of, label_);
00150 gs::write_pod(of, useLogSpace_);
00151 return !of.fail();
00152 }
00153
00154 GridAxis* GridAxis::read(const gs::ClassId& id, std::istream& in)
00155 {
00156 static const gs::ClassId current(gs::ClassId::makeId<GridAxis>());
00157 current.ensureSameId(id);
00158
00159 std::vector<double> coords;
00160 gs::read_pod_vector(in, &coords);
00161
00162 std::string label;
00163 gs::read_pod(in, &label);
00164
00165 bool useLogSpace;
00166 gs::read_pod(in, &useLogSpace);
00167
00168 if (in.fail())
00169 throw gs::IOReadFailure("In npstat::GridAxis::read: "
00170 "input stream failure");
00171 return new GridAxis(coords, label.c_str(), useLogSpace);
00172 }
00173
00174 bool GridAxis::operator==(const GridAxis& r) const
00175 {
00176 return useLogSpace_ == r.useLogSpace_ &&
00177 coords_ == r.coords_ &&
00178 label_ == r.label_;
00179 }
00180
00181 bool GridAxis::isClose(const GridAxis& r, const double tol) const
00182 {
00183 if (!(useLogSpace_ == r.useLogSpace_ &&
00184 label_ == r.label_))
00185 return false;
00186 const unsigned long n = coords_.size();
00187 if (n != r.coords_.size())
00188 return false;
00189 for (unsigned long i=0; i<n; ++i)
00190 if (!closeWithinTolerance(coords_[i], r.coords_[i], tol))
00191 return false;
00192 return true;
00193 }
00194 }