26 #include "ndarray/eigen.h" 
   54                                  -(2.0 * 
bbox.getCenterY()) / 
bbox.getHeight()));
 
   62           _toChebyshevRange(makeChebyshevRangeTransform(
lsst::
geom::Box2D(
bbox))),
 
   77 using Packer = detail::TrapezoidalPacker;
 
   80 void evaluateBasis1d(ndarray::Array<double, 1, 1> 
const& t, 
double x) {
 
   81     int const n = t.getSize<0>();
 
   88     for (
int i = 2; i < n; ++i) {
 
   89         t[i] = 2.0 * 
x * t[i - 1] - t[i - 2];
 
   97 ndarray::Array<double, 2, 2> makeMatrix(ndarray::Array<double const, 1> 
const& 
x,
 
   98                                         ndarray::Array<double const, 1> 
const& 
y,
 
  100                                         Packer 
const& packer, 
Control const& ctrl) {
 
  101     int const nPoints = 
x.getSize<0>();
 
  102     ndarray::Array<double, 1, 1> tx = ndarray::allocate(packer.nx);
 
  103     ndarray::Array<double, 1, 1> ty = ndarray::allocate(packer.ny);
 
  104     ndarray::Array<double, 2, 2> out = ndarray::allocate(nPoints, packer.size);
 
  107     for (
int p = 0; p < nPoints; ++p) {
 
  109         evaluateBasis1d(tx, sxy.getX());
 
  110         evaluateBasis1d(ty, sxy.getY());
 
  111         packer.pack(out[p], tx, ty);  
 
  122                                         Packer 
const& packer, 
Control const& ctrl) {
 
  124     ndarray::Array<double, 2, 2> tx = ndarray::allocate(
bbox.getWidth(), packer.nx);
 
  125     for (
int x = 
bbox.getBeginX(), p = 0; p < 
bbox.getWidth(); ++p, ++
x) {
 
  132     ndarray::Array<double, 2, 2> out = ndarray::allocate(
bbox.getArea(), packer.size);
 
  134     ndarray::Array<double, 1, 1> ty = ndarray::allocate(ctrl.orderY + 1);
 
  135     for (
int y = 
bbox.getBeginY(), i = 0; i < 
bbox.getHeight(); ++i, ++
y) {
 
  138         for (
int j = 0; j < 
bbox.getWidth(); ++j, ++outIter) {
 
  140             packer.pack(*outIter, tx[j], ty);
 
  149                                                                   ndarray::Array<double const, 1> 
const& 
x,
 
  150                                                                   ndarray::Array<double const, 1> 
const& 
y,
 
  151                                                                   ndarray::Array<double const, 1> 
const& 
z,
 
  157     Packer 
const packer(ctrl);
 
  159     ndarray::Array<double, 2, 2> matrix = makeMatrix(
x, 
y, 
result->_toChebyshevRange, packer, ctrl);
 
  168                                                                   ndarray::Array<double const, 1> 
const& 
x,
 
  169                                                                   ndarray::Array<double const, 1> 
const& 
y,
 
  170                                                                   ndarray::Array<double const, 1> 
const& 
z,
 
  171                                                                   ndarray::Array<double const, 1> 
const& 
w,
 
  177     Packer 
const packer(ctrl);
 
  179     ndarray::Array<double, 2, 2> matrix = makeMatrix(
x, 
y, 
result->_toChebyshevRange, packer, ctrl);
 
  182     ndarray::asEigenArray(matrix).colwise() *= ndarray::asEigenArray(
w);
 
  183     ndarray::Array<double, 1, 1> wz = ndarray::copy(
z);
 
  184     ndarray::asEigenArray(wz) *= ndarray::asEigenArray(
w);
 
  192 template <
typename T>
 
  200     Packer 
const packer(ctrl);
 
  201     ndarray::Array<double, 2, 2> matrix = makeMatrix(
bbox, 
result->_toChebyshevRange, packer, ctrl);
 
  203     ndarray::Array<double, 2, 2> imgCopy = ndarray::allocate(img.
getArray().getShape());
 
  205     ndarray::Array<double const, 1, 1> 
z = ndarray::flatten<1>(imgCopy);
 
  219                            (_coefficients.getSize<1>() - 1))
 
  225                            (_coefficients.getSize<0>() - 1))
 
  232         ndarray::Array<double, 1, 1> packed = ndarray::allocate(packer.size);
 
  240     return std::make_shared<ChebyshevBoundedField>(
bbox, _coefficients);
 
  251 template <
typename CoeffGetter>
 
  252 double evaluateFunction1d(CoeffGetter g, 
double x, 
int size) {
 
  253     double b_kp2 = 0.0, b_kp1 = 0.0;
 
  254     for (
int k = (size - 1); k > 0; --k) {
 
  255         double b_k = g[k] + 2 * 
x * b_kp1 - b_kp2;
 
  259     return g[0] + 
x * b_kp1 - b_kp2;
 
  267 struct RecursionArrayImitator {
 
  268     double operator[](
int i)
 const {
 
  272     RecursionArrayImitator(ndarray::Array<double const, 2, 2> 
const& coefficients_, 
double x_)
 
  283     return evaluateFunction1d(RecursionArrayImitator(_coefficients, p.getX()), p.getY(),
 
  284                               _coefficients.getSize<0>());
 
  293         return 2.0 / (1.0 - double(n * n));
 
  299     for (ndarray::Size j = 0; j < _coefficients.getSize<0>(); j++) {
 
  300         for (ndarray::Size i = 0; i < _coefficients.getSize<1>(); i++) {
 
  304     return result * determinant;
 
  313 struct PersistenceHelper {
 
  319     PersistenceHelper(
int nx, 
int ny)
 
  321               orderX(
schema.addField<int>(
"order_x", 
"maximum Chebyshev function order in x")),
 
  324                       "coefficients", 
"Chebyshev function coefficients, ordered by y then x", nx * ny)) {}
 
  326     PersistenceHelper(table::Schema 
const& s)
 
  330 class ChebyshevBoundedFieldFactory : 
public table::io::PersistableFactory {
 
  333             : 
afw::table::io::PersistableFactory(
name) {}
 
  336                                                  CatalogVector 
const& catalogs)
 const override {
 
  339         table::BaseRecord 
const& record = catalogs.front().front();
 
  340         PersistenceHelper 
const keys(record.getSchema());
 
  345         ndarray::Array<double, 2, 2> 
coefficients = ndarray::allocate(ny, nx);
 
  351 std::string getChebyshevBoundedFieldPersistenceName() { 
return "ChebyshevBoundedField"; }
 
  353 ChebyshevBoundedFieldFactory registration(getChebyshevBoundedFieldPersistenceName());
 
  358     return getChebyshevBoundedFieldPersistenceName();
 
  364     PersistenceHelper 
const keys(_coefficients.getSize<1>(), _coefficients.getSize<0>());
 
  367     record->set(
keys.orderX, _coefficients.getSize<1>() - 1);
 
  369     (*record)[
keys.coefficients].deep() = ndarray::flatten<1>(_coefficients);
 
  381     if (!rhsCasted) 
return false;
 
  383     return (
getBBox() == rhsCasted->getBBox()) &&
 
  384            (_coefficients.getShape() == rhsCasted->_coefficients.getShape()) &&
 
  385            all(equal(_coefficients, rhsCasted->_coefficients));
 
  388 std::string ChebyshevBoundedField::toString()
 const {
 
  390     os << 
"ChebyshevBoundedField (" << _coefficients.getShape() << 
" coefficients in y,x)";
 
  398 #define INSTANTIATE(T)                                                                                       \ 
  399     template std::shared_ptr<ChebyshevBoundedField> ChebyshevBoundedField::fit(image::Image<T> const& image, \ 
table::Key< std::string > name
 
ndarray::Array< double const, 2, 2 > coefficients
 
#define INSTANTIATE(FROMSYS, TOSYS)
 
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
 
#define LSST_ARCHIVE_ASSERT(EXPR)
An assertion macro used to validate the structure of an InputArchive.
 
lsst::geom::Box2I getBBox(ImageOrigin origin=PARENT) const
 
A class to represent a 2-dimensional array of pixels.
 
An abstract base class for 2-d functions defined on an integer bounding boxes.
 
lsst::geom::Box2I getBBox() const
Return the bounding box that defines the region where the field is valid.
 
A control object used when fitting ChebyshevBoundedField to data (see ChebyshevBoundedField::fit)
 
int computeSize() const
Return the number of nonzero coefficients in the Chebyshev function defined by this object.
 
bool triangular
"if true, only include terms where the sum of the x and y order " "is less than or equal to max(order...
 
int orderY
"maximum Chebyshev function order in y" ;
 
int orderX
"maximum Chebyshev function order in x" ;
 
A BoundedField based on 2-d Chebyshev polynomials of the first kind.
 
static std::shared_ptr< ChebyshevBoundedField > fit(lsst::geom::Box2I const &bbox, ndarray::Array< double const, 1 > const &x, ndarray::Array< double const, 1 > const &y, ndarray::Array< double const, 1 > const &z, Control const &ctrl)
Fit a Chebyshev approximation to non-gridded data with equal weights.
 
std::shared_ptr< ChebyshevBoundedField > relocate(lsst::geom::Box2I const &bbox) const
Return a new ChebyshevBoundedField with domain set to the given bounding box.
 
bool operator==(BoundedField const &rhs) const override
BoundedFields (of the same sublcass) are equal if their bounding boxes and parameters are equal.
 
std::shared_ptr< BoundedField > operator*(double const scale) const override
Return a scaled BoundedField.
 
ChebyshevBoundedFieldControl Control
 
void write(OutputArchiveHandle &handle) const override
Write the object to one or more catalogs.
 
std::string getPythonModule() const override
Return the fully-qualified Python module that should be imported to guarantee that its factory is reg...
 
double mean() const override
Compute the mean of this function over its bounding-box.
 
~ChebyshevBoundedField() override
 
ndarray::Array< double const, 2, 2 > getCoefficients() const
Return the coefficient matrix.
 
std::shared_ptr< ChebyshevBoundedField > truncate(Control const &ctrl) const
Return a new ChebyshevBoudedField with maximum orders set by the given control object.
 
std::string getPersistenceName() const override
Return the unique name used to persist this object and look up its factory.
 
ChebyshevBoundedField(lsst::geom::Box2I const &bbox, ndarray::Array< double const, 2, 2 > const &coefficients)
Initialize the field from its bounding box an coefficients.
 
double integrate() const override
Compute the integral of this function over its bounding-box.
 
virtual double evaluate(lsst::geom::Point2D const &position) const=0
Evaluate the field at the given point.
 
Solver for linear least-squares problems.
 
ndarray::Array< double const, 1, 1 > getSolution()
Return the vector solution to the least squares problem.
 
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.
 
@ NORMAL_EIGENSYSTEM
Use the normal equations with a symmetric Eigensystem decomposition.
 
std::shared_ptr< RecordT > addNew()
Create a new record, add it to the end of the catalog, and return a pointer to it.
 
An object passed to Persistable::write to allow it to persist itself.
 
void saveCatalog(BaseCatalog const &catalog)
Save a catalog in the archive.
 
BaseCatalog makeCatalog(Schema const &schema)
Return a new, empty catalog with the given schema.
 
A floating-point coordinate rectangle geometry.
 
An integer coordinate rectangle.
 
Reports attempts to exceed implementation-defined length limits for some classes.
 
def scale(algorithm, min, max=None, frame=None)
 
double integrateTn(int n)
 
BoxKey< lsst::geom::Box2I > Box2IKey
 
bool all(CoordinateExpr< N > const &expr) noexcept
Return true if all elements are true.
 
FastFinder::Iterator Iterator
 
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
 
A base class for image defects.
 
A helper class ChebyshevBoundedField, for mapping trapezoidal matrices to 1-d arrays.
 
std::shared_ptr< table::io::Persistable > read(table::io::InputArchive const &archive, table::io::CatalogVector const &catalogs) const override