35 #include "boost/format.hpp" 
   42 namespace ex = pex::exceptions;
 
   47         : _style(style), _orderX(
orderX), _orderY(orderY < 0 ? 
orderX : orderY), _weighting(weighting) {
 
   48     if (_orderX != _orderY) {
 
   51                                             "due to a limitation in math::Chebyshev1Function2") %
 
   60 template <
typename PixelT>
 
   61 class ApproximateChebyshev : 
public Approximate<PixelT> {
 
   70     ~ApproximateChebyshev() 
override;
 
   79             int orderX, 
int orderY) 
const override;
 
   81             int orderX, 
int orderY) 
const override;
 
   87 inline void solveMatrix_Eigen(Eigen::MatrixXd& 
a, Eigen::VectorXd& 
b, Eigen::Map<Eigen::VectorXd>& c) {
 
   88     Eigen::PartialPivLU<Eigen::MatrixXd> lu(
a);
 
   96 template <
typename PixelT>
 
   97 ApproximateChebyshev<PixelT>::ApproximateChebyshev(
 
  102         ApproximateControl 
const& ctrl         
 
  104         : Approximate<
PixelT>(xVec, yVec, 
bbox, ctrl),
 
  105           _poly(math::Chebyshev1Function2<double>(ctrl.getOrderX(), 
lsst::
geom::Box2D(
bbox))) {
 
  113     int const nTerm = _poly.getNParameters();          
 
  127     for (
int i = 0; i != nTerm; ++i) {
 
  128         termCoeffs[i].reserve(nData);
 
  131     for (
int iy = 0; iy != im.
getHeight(); ++iy) {
 
  132         double const y = yVec[iy];
 
  134         for (
int ix = 0; ix != im.
getWidth(); ++ix) {
 
  135             double const x = xVec[ix];
 
  137             for (
int i = 0; i != nTerm; ++i) {
 
  138                 _poly.setParameter(i, 1.0);
 
  139                 termCoeffs[i].push_back(_poly(
x, 
y));
 
  140                 _poly.setParameter(i, 0.0);
 
  146     A.setZero(nTerm, nTerm);  
 
  153     for (
int iy = 0; iy != im.
getHeight(); ++iy) {
 
  157             double const val = 
ptr.image();
 
  158             double const ivar = ctrl.getWeighting() ? 1 / 
ptr.variance() : 1.0;
 
  163             for (
int i = 0; i != nTerm; ++i) {
 
  164                 double const c_i = termCoeffs[i][alpha];
 
  165                 double const tmp = c_i * ivar;
 
  167                 A(i, i) += c_i * tmp;
 
  168                 for (
int j = 0; j < i; ++j) {
 
  169                     double const c_j = termCoeffs[j][alpha];
 
  170                     A(i, j) += c_j * tmp;
 
  176         if (ctrl.getWeighting()) {
 
  178                               "No valid points to fit. Variance is likely zero. Try weighting=False");
 
  181                               "No valid points to fit (even though weighting is False). " 
  182                               "Check that binSize & approxOrderX settings are appropriate for image size.");
 
  186     for (
int j = 0; j != nTerm; ++j) {
 
  187         for (
int i = j + 1; i != nTerm; ++i) {
 
  195     Eigen::Map<Eigen::VectorXd> c(&cvec[0], nTerm);  
 
  197     solveMatrix_Eigen(A, 
b, c);
 
  199     _poly.setParameters(cvec);
 
  203 template <
typename PixelT>
 
  204 ApproximateChebyshev<PixelT>::~ApproximateChebyshev() {}
 
  216 template <
typename PixelT>
 
  218 ApproximateChebyshev<PixelT>::doGetImage(
int orderX, 
int orderY)
 const {
 
  230     for (
int iy = 0; iy != im->
getHeight(); ++iy) {
 
  254 template <
typename PixelT>
 
  256 ApproximateChebyshev<PixelT>::doGetMaskedImage(
int orderX, 
int orderY)
 const {
 
  262     for (
int iy = 0; iy != im->getHeight(); ++iy) {
 
  266         for (
typename MImageT::Image::x_iterator 
ptr = im->row_begin(iy), 
end = im->row_end(iy); 
ptr != 
end;
 
  278 template <
typename PixelT>
 
  287                     new ApproximateChebyshev<PixelT>(
x, 
y, im, 
bbox, ctrl));
 
  298 #define INSTANTIATE(PIXEL_T)                                                      \ 
  299     template std::shared_ptr<Approximate<PIXEL_T>> makeApproximate(               \ 
  300             std::vector<double> const& x, std::vector<double> const& y,           \ 
  301             image::MaskedImage<PIXEL_T> const& im, lsst::geom::Box2I const& bbox, \ 
  302             ApproximateControl const& ctrl)