CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_6_1_2_SLHC2_patch1/src/JetMETCorrections/InterpolationTables/src/GridAxis.cc

Go to the documentation of this file.
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         // Can't have duplicate coordinates
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         // It is unlikely that this object will be written in isolation.
00147         // So, do not bother with too many checks.
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 }