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)