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.
table::PointKey< int > bboxMax
table::Key< std::string > name
Eigen matrix objects that present a view into an ndarray::Array.
ndarray::Array< double const, 2, 2 > _coefficients
An object passed to Persistable::write to allow it to persist itself.
A custom container class for records, based on std::vector.
afw::table::Schema schema
virtual std::string getPythonModule() const
Return the fully-qualified Python module that should be imported to guarantee that its factory is reg...
#define INSTANTIATE(MATCH)
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
virtual void write(OutputArchiveHandle &handle) const
Write the object to one or more catalogs.
Solver for linear least-squares problems.
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.
int computeSize() const
Return the number of nonzero coefficients in the Chebyshev function defined by this object...
int getSize() const
Return the size of a specific dimension.
geom::Box2I getBBox() const
An integer coordinate rectangle.
table::Key< table::Array< Kernel::Pixel > > image
geom::AffineTransform _toChebyshevRange
Use the normal equations with a symmetric Eigensystem decomposition.
double getCenterX() const
double getCenterY() const
virtual double evaluate(geom::Point2D const &position) const
table::PointKey< int > bboxMin
#define LSST_ARCHIVE_ASSERT(EXPR)
An assertion macro used to validate the structure of an InputArchive.
BaseCatalog makeCatalog(Schema const &schema)
Return a new, empty catalog with the given schema.
virtual std::string getPersistenceName() const
Return the unique name used to persist this object and look up its factory.
detail::SimpleInitializer< N > allocate(Vector< int, N > const &shape)
Create an expression that allocates uninitialized memory for an array.
#define LSST_EXCEPT(type,...)
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.
ChebyshevBoundedField(afw::geom::Box2I const &bbox, ndarray::Array< double const, 2, 2 > const &coefficients)
Initialize the field from its bounding box an coefficients.
boost::shared_ptr< RecordT > addNew()
Create a new record, add it to the end of the catalog, and return a pointer to it.
An abstract base class for 2-d functions defined on an integer bounding boxes.
ndarray::Array< double const, 1, 1 > getSolution()
Return the vector solution to the least squares problem.
ExpressionTraits< Derived >::Iterator Iterator
Nested expression or element iterator.
void saveCatalog(BaseCatalog const &catalog)
Save a catalog in the archive.
A floating-point coordinate rectangle geometry.
ndarray::Array< double const, 2, 2 > coefficients
Iterator begin() const
Return an Iterator to the beginning of the array.