CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_6_1_1/src/JetMETCorrections/InterpolationTables/src/NUHistoAxis.cc

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                 // Bin center is mapped to binnum.
00117                 // Bin center of the next bin is mapped to binnum + 1.
00118                 // Bin center of the previos bin is mapped to binnum - 1.
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 }