CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/JetMETCorrections/InterpolationTables/src/HistoAxis.cc

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 }