24 #include "boost/make_shared.hpp"
35 namespace lsst {
namespace afw {
namespace math {
62 _toChebyshevRange(makeChebyshevRangeTransform(geom::Box2D(bbox))),
63 _coefficients(coefficients)
69 _toChebyshevRange(makeChebyshevRangeTransform(geom::Box2D(bbox)))
91 for (
int i = 2; i < n; ++i) {
92 t[i] = 2.0*x*t[i-1] - t[i-2];
104 Packer
const & packer,
107 int const nPoints = x.
getSize<0>();
113 for (
int p = 0; p < nPoints; ++p) {
115 evaluateBasis1d(tx, sxy.getX());
116 evaluateBasis1d(ty, sxy.getY());
117 packer.pack(out[p], tx, ty);
129 Packer
const & packer,
151 for (
int j = 0; j < bbox.
getWidth(); ++j, ++outIter) {
153 packer.pack(*outIter, tx[j], ty);
162 afw::geom::Box2I const & bbox,
163 ndarray::Array<
double const,1> const & x,
164 ndarray::Array<
double const,1> const & y,
165 ndarray::Array<
double const,1> const & z,
172 Packer
const packer(ctrl);
178 result->_coefficients = packer.unpack(lstsq.
getSolution());
183 afw::geom::Box2I const & bbox,
184 ndarray::Array<
double const,1> const & x,
185 ndarray::Array<
double const,1> const & y,
186 ndarray::Array<
double const,1> const & z,
187 ndarray::Array<
double const,1> const &
w,
194 Packer
const packer(ctrl);
199 matrix.
asEigen<Eigen::ArrayXpr>().colwise() *= w.asEigen<Eigen::ArrayXpr>();
201 wz.asEigen<Eigen::ArrayXpr>() *= w.asEigen<Eigen::ArrayXpr>();
205 result->_coefficients = packer.unpack(lstsq.
getSolution());
209 template <
typename T>
211 image::Image<T> const & img,
219 Packer
const packer(ctrl);
223 imgCopy.
deep() = img.getArray();
228 result->_coefficients = packer.unpack(lstsq.getSolution());
235 if (ctrl.orderX >= _coefficients.getSize<1>()) {
237 pex::exceptions::LengthError,
239 % ctrl.orderX % (_coefficients.getSize<1>() - 1)).str()
242 if (ctrl.orderY >= _coefficients.getSize<0>()) {
244 pex::exceptions::LengthError,
246 % ctrl.orderY % (_coefficients.getSize<0>() - 1)).str()
251 = _coefficients[
ndarray::view(0, ctrl.orderY + 1)(0, ctrl.orderX + 1)];
252 if (ctrl.triangular) {
255 packer.pack(packed, coefficients);
256 packer.unpack(coefficients, packed);
258 return boost::make_shared<ChebyshevBoundedField>(getBBox(),
coefficients);
262 return boost::make_shared<ChebyshevBoundedField>(bbox, _coefficients);
274 template <
typename CoeffGetter>
275 double evaluateFunction1d(
280 double b_kp2=0.0, b_kp1=0.0;
281 for (
int k = (size - 1); k > 0; --k) {
282 double b_k = g[k] + 2*x*b_kp1 - b_kp2;
286 return g[0] + x*b_kp1 - b_kp2;
294 struct RecursionArrayImitator {
296 double operator[](
int i)
const {
312 return evaluateFunction1d(RecursionArrayImitator(
_coefficients, p.getX()),
320 struct PersistenceHelper {
327 PersistenceHelper(
int nx,
int ny) :
329 orderX(
schema.addField<int>(
"order_x",
"maximum Chebyshev function order in x")),
330 bboxMin(table::PointKey<int>::addFields(
331 schema,
"bbox_min",
"lower-left corner of bounding box",
"pixels")),
332 bboxMax(table::PointKey<int>::addFields(
333 schema,
"bbox_max",
"upper-right corner of bounding box",
"pixels")),
335 schema.addField< table::Array<double> >(
336 "coefficients",
"Chebyshev function coefficients, ordered by y then x", nx*ny
341 PersistenceHelper(table::Schema
const & s) :
351 class ChebyshevBoundedFieldFactory :
public table::io::PersistableFactory {
354 virtual PTR(table::io::Persistable)
355 read(InputArchive const & archive, CatalogVector const & catalogs)
const {
358 table::BaseRecord
const & record = catalogs.front().front();
359 PersistenceHelper
const keys(record.getSchema());
360 geom::Box2I bbox(record.get(keys.bboxMin), record.get(keys.bboxMax));
361 int nx = record.get(keys.orderX) + 1;
362 int ny = keys.coefficients.getSize() / nx;
365 ndarray::flatten<1>(
coefficients) = record.get(keys.coefficients);
366 return boost::make_shared<ChebyshevBoundedField>(bbox,
coefficients);
369 ChebyshevBoundedFieldFactory(std::string
const &
name) : afw::table::io::PersistableFactory(name) {}
373 std::string getChebyshevBoundedFieldPersistenceName() {
return "ChebyshevBoundedField"; }
375 ChebyshevBoundedFieldFactory registration(getChebyshevBoundedFieldPersistenceName());
380 return getChebyshevBoundedFieldPersistenceName();
384 return "lsst.afw.math";
392 record->set(keys.bboxMin,
getBBox().getMin());
393 record->set(keys.bboxMax,
getBBox().getMax());
394 (*record)[keys.coefficients].deep() = ndarray::flatten<1>(
_coefficients);
399 return boost::make_shared<ChebyshevBoundedField>(getBBox(),
ndarray::copy(getCoefficients()*scale));
406 #define INSTANTIATE(T) \
407 template PTR(ChebyshevBoundedField) ChebyshevBoundedField::fit( \
408 image::Image<T> const & image, \
409 Control const & ctrl \
Extent< int, N > truncate(Extent< double, N > const &input)
View< boost::fusion::vector1< index::Full > > view()
Start a view definition that includes the entire first dimension.
int computeSize() const
Return the number of nonzero coefficients in the Chebyshev function defined by this object...
static LeastSquares fromDesignMatrix(ndarray::Array< T1, 2, C1 > const &design, ndarray::Array< T2, 1, C2 > const &data, Factorization factorization=NORMAL_EIGENSYSTEM)
Initialize from the design matrix and data vector given as ndarrays.
table::Key< std::string > name
BaseCatalog makeCatalog(Schema const &schema)
Return a new, empty catalog with the given schema.
Eigen matrix objects that present a view into an ndarray::Array.
An object passed to Persistable::write to allow it to persist itself.
#define LSST_ARCHIVE_ASSERT(EXPR)
An assertion macro used to validate the structure of an InputArchive.
virtual std::string getPersistenceName() const
Return the unique name used to persist this object and look up its factory.
ChebyshevBoundedField(afw::geom::Box2I const &bbox, ndarray::Array< double const, 2, 2 > const &coefficients)
Initialize the field from its bounding box an coefficients.
A custom container class for records, based on std::vector.
A control object used when fitting ChebyshevBoundedField to data (see ChebyshevBoundedField::fit) ...
SelectEigenView< T >::Type copy(Eigen::EigenBase< T > const &other)
Copy an arbitrary Eigen expression into a new EigenView.
EigenView< Element, ND::value, RMC::value, XprKind, Rows, Cols > asEigen() const
Solver for linear least-squares problems.
geom::AffineTransform _toChebyshevRange
int getSize() const
Return the size of a specific dimension.
boost::shared_ptr< RecordT > addNew()
Create a new record, add it to the end of the catalog, and return a pointer to it.
An integer coordinate rectangle.
table::Key< table::Array< Kernel::Pixel > > image
double getCenterX() const
virtual void write(OutputArchiveHandle &handle) const
Write the object to one or more catalogs.
geom::Box2I getBBox() const
virtual double evaluate(geom::Point2D const &position) const
detail::SimpleInitializer< N > allocate(Vector< int, N > const &shape)
Create an expression that allocates uninitialized memory for an array.
#define LSST_EXCEPT(type,...)
tbl::PointKey< int > bboxMax
Deep const deep() const
Return an ArrayRef view to this.
Base class for all records.
A BoundedField based on 2-d Chebyshev polynomials of the first kind.
Use the normal equations with a symmetric Eigensystem decomposition.
An abstract base class for 2-d functions defined on an integer bounding boxes.
ndarray::Array< double const, 2, 2 > _coefficients
double getCenterY() const
ExpressionTraits< Derived >::Iterator Iterator
Nested expression or element iterator.
A floating-point coordinate rectangle geometry.
ndarray::Array< double const, 2, 2 > coefficients
virtual std::string getPythonModule() const
Return the fully-qualified Python module that should be imported to guarantee that its factory is reg...
void saveCatalog(BaseCatalog const &catalog)
Save a catalog in the archive.
ndarray::Array< double const, 1, 1 > getSolution()
Return the vector solution to the least squares problem.
Iterator begin() const
Return an Iterator to the beginning of the array.
tbl::PointKey< int > bboxMin