Skip to content

Commit

Permalink
Change SpherePointEndpoint to IcrsCoordEndpoint
Browse files Browse the repository at this point in the history
Also change `SkyWcs` to use `IcrsCoord` instead of `SpherePoint`.
  • Loading branch information
r-owen committed Jun 21, 2017
1 parent be04815 commit 45a5db4
Show file tree
Hide file tree
Showing 23 changed files with 255 additions and 178 deletions.
56 changes: 31 additions & 25 deletions include/lsst/afw/geom/Endpoint.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@
#include "astshim.h"
#include "ndarray.h"

#include "lsst/afw/coord/Coord.h"
#include "lsst/afw/geom/Point.h"
#include "lsst/afw/geom/SpherePoint.h"

namespace lsst {
namespace afw {
Expand All @@ -41,10 +41,10 @@ namespace geom {
Virtual base class for endpoints, which are helper classes for Transform
Endpoints transform points and lists of points from LSST-specific data types,
such as Point2D and SpherePoint, to a form accepted by ast::Mapping.tran.
such as Point2D and IcrsCoord, to a form accepted by ast::Mapping.tran.
Each type of endpoint is used for a particular LSST data type, for example:
- Point2Endpoint is used for Point2D data
- SpherePointEndpoint for SpherePoint data
- IcrsCoordEndpoint for IcrsCoord data
- GenericEndpoint is used when no other form will do; its LSST data type
is identical to the type used for ast::Mapping.applyForward.
Expand Down Expand Up @@ -164,7 +164,7 @@ class BaseEndpoint {
/**
Base class for endpoints with Array = std::vector<Point> where Point has 2 dimensions
@note Subclasses must provide `arrayFromData`
@note Subclasses must provide `dataFromPoint`, `dataFromArray`, `pointFromData` and `arrayFromData`
*/
template <typename PointT>
class BaseVectorEndpoint : public BaseEndpoint<PointT, std::vector<PointT>> {
Expand All @@ -179,13 +179,7 @@ class BaseVectorEndpoint : public BaseEndpoint<PointT, std::vector<PointT>> {

virtual ~BaseVectorEndpoint(){};

virtual int getNPoints(Array const &arr) const override { return arr.size(); }

virtual std::vector<double> dataFromPoint(Point const &point) const override;

virtual ndarray::Array<double, 2, 2> dataFromArray(Array const &arr) const override;

virtual Point pointFromData(std::vector<double> const &data) const override;
virtual int getNPoints(Array const &arr) const override;

protected:
/**
Expand Down Expand Up @@ -262,6 +256,12 @@ class Point2Endpoint : public BaseVectorEndpoint<Point2D> {

virtual ~Point2Endpoint(){};

virtual std::vector<double> dataFromPoint(Point const &point) const override;

virtual ndarray::Array<double, 2, 2> dataFromArray(Array const &arr) const override;

virtual Point pointFromData(std::vector<double> const &data) const override;

virtual Array arrayFromData(ndarray::Array<double, 2, 2> const &data) const override;

/**
Expand All @@ -277,24 +277,24 @@ class Point2Endpoint : public BaseVectorEndpoint<Point2D> {
};

/**
An endpoint for SpherePoint
An endpoint for IcrsCoord
A SpherePointEndpoint always has 2 axes: longitude, latitude
A IcrsCoordEndpoint always has 2 axes: RA, Dec
*/
class SpherePointEndpoint : public BaseVectorEndpoint<SpherePoint> {
class IcrsCoordEndpoint : public BaseVectorEndpoint<coord::IcrsCoord> {
public:
SpherePointEndpoint(SpherePointEndpoint const &) = default;
SpherePointEndpoint(SpherePointEndpoint &&) = default;
SpherePointEndpoint &operator=(SpherePointEndpoint const &) = delete;
SpherePointEndpoint &operator=(SpherePointEndpoint &&) = delete;
IcrsCoordEndpoint(IcrsCoordEndpoint const &) = default;
IcrsCoordEndpoint(IcrsCoordEndpoint &&) = default;
IcrsCoordEndpoint &operator=(IcrsCoordEndpoint const &) = delete;
IcrsCoordEndpoint &operator=(IcrsCoordEndpoint &&) = delete;

/**
Construct a SpherePointEndpoint
Construct a IcrsCoordEndpoint
*/
explicit SpherePointEndpoint() : BaseVectorEndpoint(2) {}
explicit IcrsCoordEndpoint() : BaseVectorEndpoint(2) {}

/**
Construct a SpherePointEndpoint with nAxes specified; nAxes must equal 2
Construct a IcrsCoordEndpoint with nAxes specified; nAxes must equal 2
This constructor is primarily used by Transform; other users are encouraged
to use the default constructor.
Expand All @@ -303,9 +303,15 @@ class SpherePointEndpoint : public BaseVectorEndpoint<SpherePoint> {
@throws lsst.pex.exceptions.InvalidParameterError if nAxes != 2
*/
explicit SpherePointEndpoint(int nAxes);
explicit IcrsCoordEndpoint(int nAxes);

virtual ~SpherePointEndpoint(){};
virtual ~IcrsCoordEndpoint(){};

virtual std::vector<double> dataFromPoint(Point const &point) const override;

virtual ndarray::Array<double, 2, 2> dataFromArray(Array const &arr) const override;

virtual Point pointFromData(std::vector<double> const &data) const override;

virtual Array arrayFromData(ndarray::Array<double, 2, 2> const &data) const override;

Expand All @@ -328,8 +334,8 @@ std::ostream &operator<<(std::ostream &os, GenericEndpoint const &endpoint);
/// Print "Point2Endpoint()" to the ostream
std::ostream &operator<<(std::ostream &os, Point2Endpoint const &endpoint);

/// Print "SpherePointEndpoint()" to the ostream
std::ostream &operator<<(std::ostream &os, SpherePointEndpoint const &endpoint);
/// Print "IcrsCoordEndpoint()" to the ostream
std::ostream &operator<<(std::ostream &os, IcrsCoordEndpoint const &endpoint);

} // namespace geom
} // namespace afw
Expand Down
18 changes: 10 additions & 8 deletions include/lsst/afw/geom/SkyWcs.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@
#include "astshim.h"
#include "ndarray.h"

#include "lsst/afw/coord/Coord.h"
#include "lsst/afw/geom/Angle.h"
#include "lsst/afw/geom/Point.h"
#include "lsst/afw/geom/SpherePoint.h"
#include "lsst/afw/geom/Endpoint.h"
#include "lsst/afw/geom/Transform.h"
#include "lsst/daf/base/PropertyList.h"
Expand Down Expand Up @@ -94,7 +94,7 @@ Constructors must set the following properties of the contained ast::FrameSet:
SkyWcs uses this to look up CRVAL; "Ignored" is required to prevent CRVAL from being used as an offset
from the desired WCS.
*/
class SkyWcs : public Transform<Point2Endpoint, SpherePointEndpoint> {
class SkyWcs : public Transform<Point2Endpoint, IcrsCoordEndpoint> {
public:
SkyWcs(SkyWcs const &) = default;
SkyWcs(SkyWcs &&) = default;
Expand All @@ -110,7 +110,7 @@ class SkyWcs : public Transform<Point2Endpoint, SpherePointEndpoint> {
@param[in] cdMatrix CD matrix, where element (i-1, j-1) corresponds to FITS keyword CDi_j
and i, j have range [1, 2]. May be computed by calling makeCdMatrix.
*/
explicit SkyWcs(Point2D const &crpix, SpherePoint const &crval, Eigen::Matrix2d const &cdMatrix);
explicit SkyWcs(Point2D const &crpix, coord::IcrsCoord const &crval, Eigen::Matrix2d const &cdMatrix);

/**
Construct a WCS from FITS keywords
Expand Down Expand Up @@ -160,7 +160,7 @@ class SkyWcs : public Transform<Point2Endpoint, SpherePointEndpoint> {
/**
Get CRVAL, the sky origin or celestial fiducial point
*/
SpherePoint getSkyOrigin() const;
coord::IcrsCoord getSkyOrigin() const;

/**
Get the 2x2 CD matrix at the specified pixel position
Expand Down Expand Up @@ -189,8 +189,8 @@ class SkyWcs : public Transform<Point2Endpoint, SpherePointEndpoint> {
*/
//@{
std::pair<Angle, Angle> pixelToSky(double x, double y) const;
SpherePoint pixelToSky(Point2D const &pixel) const { return applyForward(pixel); };
std::vector<SpherePoint> pixelToSky(std::vector<Point2D> const &pixels) const {
coord::IcrsCoord pixelToSky(Point2D const &pixel) const { return applyForward(pixel); };
std::vector<coord::IcrsCoord> pixelToSky(std::vector<Point2D> const &pixels) const {
return applyForward(pixels);
}
//@}
Expand All @@ -202,8 +202,10 @@ class SkyWcs : public Transform<Point2Endpoint, SpherePointEndpoint> {
*/
//@{
std::pair<double, double> skyToPixel(Angle const &ra, Angle const &dec) const;
Point2D skyToPixel(SpherePoint const &sky) const { return applyInverse(sky); }
std::vector<Point2D> skyToPixel(std::vector<SpherePoint> const &sky) const { return applyInverse(sky); }
Point2D skyToPixel(coord::IcrsCoord const &sky) const { return applyInverse(sky); }
std::vector<Point2D> skyToPixel(std::vector<coord::IcrsCoord> const &sky) const {
return applyInverse(sky);
}
//@}

private:
Expand Down
5 changes: 2 additions & 3 deletions include/lsst/afw/geom/Transform.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ namespace afw {
namespace geom {

/**
Transform LSST spatial data, such as Point2D and SpherePoint, using an AST transform.
Transform LSST spatial data, such as Point2D and IcrsCoord, using an AST transform.
This class contains two Endpoints, to specify the "from" and "to" LSST data type,
and an ast::FrameSet or ast::Mapping to specify the transformation.
Expand Down Expand Up @@ -216,8 +216,7 @@ class Transform {
* auto pixelsToSky = pixelsToFP.then(fpToPupil).then(pupilToSky);
*/
template <class NextToEndpoint>
Transform<FromEndpoint, NextToEndpoint> then(
Transform<ToEndpoint, NextToEndpoint> const &next) const;
Transform<FromEndpoint, NextToEndpoint> then(Transform<ToEndpoint, NextToEndpoint> const &next) const;

protected:
/**
Expand Down
4 changes: 3 additions & 1 deletion include/lsst/afw/geom/detail/frameSetUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "astshim.h"
#include "ndarray.h"

#include "lsst/afw/coord/Coord.h"
#include "lsst/afw/geom/Endpoint.h"
#include "lsst/afw/geom/Transform.h"
#include "lsst/daf/base/PropertyList.h"
Expand Down Expand Up @@ -60,7 +61,8 @@ Make FITS metadata for a pure tangent WCS
@param[in] cdMatrix CD matrix where element (i-1, j-1) corresponds to FITS keyword CDi_j
and i, j have range [1, 2]
*/
std::shared_ptr<daf::base::PropertyList> makeTanWcsMetadata(Point2D const& crpix, SpherePoint const& crval,
std::shared_ptr<daf::base::PropertyList> makeTanWcsMetadata(Point2D const& crpix,
coord::IcrsCoord const& crval,
Eigen::Matrix2d const& cdMatrix);

/**
Expand Down
12 changes: 6 additions & 6 deletions include/lsst/afw/geom/transformFactory.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,19 +55,19 @@ Transform<FromEndpoint, ToEndpoint> linearizeTransform(
typename Transform<FromEndpoint, ToEndpoint>::FromPoint const &point);

/*
* The correct behavior for linearization is unclear where SpherePoints are involved (see discussion on
* The correct behavior for linearization is unclear where IcrsCoords are involved (see discussion on
* DM-10542). Forbid usage until somebody needs it. Note to maintainers: the template specializations MUST
* be deleted in the header for compilers to complain correctly.
*/
#define DISABLE(From, To) \
template <> \
Transform<From, To> linearizeTransform<From, To>(Transform<From, To> const &, \
Transform<From, To>::FromPoint const &) = delete;
DISABLE(GenericEndpoint, SpherePointEndpoint);
DISABLE(Point2Endpoint, SpherePointEndpoint);
DISABLE(SpherePointEndpoint, GenericEndpoint);
DISABLE(SpherePointEndpoint, Point2Endpoint);
DISABLE(SpherePointEndpoint, SpherePointEndpoint);
DISABLE(GenericEndpoint, IcrsCoordEndpoint);
DISABLE(Point2Endpoint, IcrsCoordEndpoint);
DISABLE(IcrsCoordEndpoint, GenericEndpoint);
DISABLE(IcrsCoordEndpoint, Point2Endpoint);
DISABLE(IcrsCoordEndpoint, IcrsCoordEndpoint);
#undef DISABLE

} // namespace geom
Expand Down
27 changes: 27 additions & 0 deletions python/lsst/afw/coord/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@

import warnings

import numpy as np

import lsst.utils.tests
import lsst.afw.geom as afwGeom

Expand All @@ -54,6 +56,31 @@ def assertCoordsAlmostEqual(testCase, coord0, coord1, maxDiff=0.001*afwGeom.arcs
(msg, measDiff.asArcseconds(), maxDiff.asArcseconds()))


@lsst.utils.tests.inTestCase
def assertCoordListsAlmostEqual(testCase, coordlist0, coordlist1, maxDiff=0.001*afwGeom.arcseconds, msg=None):
"""!Assert that two lists of IcrsCoords represent almost the same point on the sky
@warning the coordinate systems are not compared; instead both sets of angles are converted to ICRS
and the angular separation measured.
@param[in] testCase unittest.TestCase instance the test is part of;
an object supporting one method: fail(self, msgStr)
@param[in] coordlist0 list of IcrsCoords 0
@param[in] coordlist1 list of IcrsCoords 1
@param[in] maxDiff maximum angular separation, an lsst.afw.geom.Angle
@param[in] msg exception message prefix; details of the error are appended after ": "
"""
testCase.assertEqual(len(coordlist0), len(coordlist1), msg=msg)
sepArr = np.array([sp0.toIcrs().angularSeparation(sp1.toIcrs())
for sp0, sp1 in zip(coordlist0, coordlist1)])
badArr = sepArr > maxDiff
if np.any(badArr):
maxInd = np.argmax(sepArr)
testCase.fail("%s: IcrsCoordLists differ in %s places; max separation is at %s: %s\" > %s\"%s" %
(msg, np.sum(badArr), maxInd, sepArr[maxInd].asArcseconds(),
maxDiff.asArcseconds()))


@lsst.utils.tests.inTestCase
def assertCoordsNearlyEqual(*args, **kwargs):
warnings.warn("Deprecated. Use assertCoordsAlmostEqual",
Expand Down
1 change: 0 additions & 1 deletion python/lsst/afw/geom/detail/frameSetUtils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
#include "lsst/daf/base.h"
#include "lsst/afw/geom/Angle.h"
#include "lsst/afw/geom/Point.h"
#include "lsst/afw/geom/SpherePoint.h"
#include "lsst/afw/geom/detail/frameSetUtils.h"

namespace py = pybind11;
Expand Down
22 changes: 12 additions & 10 deletions python/lsst/afw/geom/endpoint.cc
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@
#include "numpy/arrayobject.h"
#include "ndarray/pybind11.h"

#include "lsst/afw/coord/Coord.h"
#include "lsst/afw/geom/Point.h"
#include "lsst/afw/geom/SpherePoint.h"
#include "lsst/afw/geom/Endpoint.h"

namespace py = pybind11;
Expand All @@ -45,7 +45,7 @@ namespace {
Add `__str__` and `__repr__` methods to an Endpoint pybind11 wrapper
str(self) = "GenericEndpoint(_nAxes_)" for GenericEndpoint, e.g. "GenericEndpoint(4)";
"_typeName_()" for all other Endpoint classes, e.g. "SpherePointEndpoint()",
"_typeName_()" for all other Endpoint classes, e.g. "IcrsCoordEndpoint()",
repr(self) = "lsst.afw.geom." + str(self), e.g. "lsst.afw.geom.GenericEndpoint(4)"
*/
template <typename PyClass>
Expand Down Expand Up @@ -108,7 +108,7 @@ template <typename SelfClass, typename PyClass>
void addAllEquals(PyClass& cls) {
addEquals<SelfClass, GenericEndpoint>(cls);
addEquals<SelfClass, Point2Endpoint>(cls);
addEquals<SelfClass, SpherePointEndpoint>(cls);
addEquals<SelfClass, IcrsCoordEndpoint>(cls);
}

/*
Expand Down Expand Up @@ -177,14 +177,14 @@ void declarePoint2Endpoint(py::module& mod) {
addStrAndRepr(cls);
}

/// @internal declare SpherePointEndpoint and all subclasses
void declareSpherePointEndpoint(py::module& mod) {
using Class = SpherePointEndpoint;
/// @internal declare IcrsCoordEndpoint and all subclasses
void declareIcrsCoordEndpoint(py::module& mod) {
using Class = IcrsCoordEndpoint;
using Point = typename Class::Point;

declareBaseVectorEndpoint<Point>(mod, "SpherePoint");
declareBaseVectorEndpoint<Point>(mod, "IcrsCoord");

py::class_<Class, std::shared_ptr<Class>, BaseVectorEndpoint<Point>> cls(mod, "SpherePointEndpoint");
py::class_<Class, std::shared_ptr<Class>, BaseVectorEndpoint<Point>> cls(mod, "IcrsCoordEndpoint");

cls.def(py::init<>());
// do not wrap the constructor that takes nAxes; it is an implementation detail
Expand All @@ -198,7 +198,9 @@ PYBIND11_PLUGIN(endpoint) {
py::module mod("endpoint");

py::module::import("lsst.afw.geom.coordinates");
py::module::import("lsst.afw.geom.spherePoint");
// The following import causes a circular import. Uncomment or delete once DM-10999 is fixed.
// Until then a user must manually `import lsst.afw.coord` before using `IcrsEndpoint`
// py::module::import("lsst.afw.coord.coord");

// Need to import numpy for ndarray and eigen conversions
if (_import_array() < 0) {
Expand All @@ -208,7 +210,7 @@ PYBIND11_PLUGIN(endpoint) {

declareGenericEndpoint(mod);
declarePoint2Endpoint(mod);
declareSpherePointEndpoint(mod);
declareIcrsCoordEndpoint(mod);

return mod.ptr();
}
Expand Down
6 changes: 3 additions & 3 deletions python/lsst/afw/geom/python/transform.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@
and subclasses, such as lsst::afw::geom::SkyWcs.
In Python the templated Transform classes have names such as
`lsst.afw.geom.TransformSpherePointToPoint2` for
`lsst::afw::geom::Transform<SpherePointEndpoint, Point2Endpoint>`
`lsst.afw.geom.TransformIcrsCoordToPoint2` for
`lsst::afw::geom::Transform<IcrsCoordEndpoint, Point2Endpoint>`
"""

from __future__ import absolute_import, division, print_function
Expand Down Expand Up @@ -86,7 +86,7 @@ def addTransformMethods(cls):
----------
cls : :ref:`_pybind11_transform_classes`
A Transform class or subclass, e.g.
`lsst.afw.geom.TransformPoint2ToSpherePoint`
`lsst.afw.geom.TransformPoint2ToIcrsCoord`
"""
global transformRegistry
className = cls.__name__
Expand Down

0 comments on commit 45a5db4

Please sign in to comment.