Ejemplo n.º 1
0
    def skyoffset_to_reference(orbitskyoffset_coord, reference_frame,
                               **kwargs):
        """Convert an sky offset frame coordinate to the reference frame."""
        lon, lat, distance = inverse_track_fn(orbitskyoffset_coord, **kwargs)
        rep = SphericalRepresentation(lon=lon, lat=lat, distance=distance)

        if not hasattr(orbitskyoffset_coord, "distance"):
            rep = rep.represent_as(UnitSphericalRepresentation)

        return framecls(
            rep, representation_type=reference_frame.representation_type)
Ejemplo n.º 2
0
def test_representations_api():
    from astropy.coordinates.representation import SphericalRepresentation, \
        UnitSphericalRepresentation, PhysicsSphericalRepresentation, \
        CartesianRepresentation
    from astropy.coordinates import Angle, Longitude, Latitude, Distance

    # <-----------------Classes for representation of coordinate data-------------->
    # These classes inherit from a common base class and internally contain Quantity
    # objects, which are arrays (although they may act as scalars, like numpy's
    # length-0  "arrays")

    # They can be initialized with a variety of ways that make intuitive sense.
    # Distance is optional.
    UnitSphericalRepresentation(lon=8 * u.hour, lat=5 * u.deg)
    UnitSphericalRepresentation(lon=8 * u.hourangle, lat=5 * u.deg)
    SphericalRepresentation(lon=8 * u.hourangle,
                            lat=5 * u.deg,
                            distance=10 * u.kpc)

    # In the initial implementation, the lat/lon/distance arguments to the
    # initializer must be in order. A *possible* future change will be to allow
    # smarter guessing of the order.  E.g. `Latitude` and `Longitude` objects can be
    # given in any order.
    UnitSphericalRepresentation(Longitude(8, u.hour), Latitude(5, u.deg))
    SphericalRepresentation(Longitude(8, u.hour), Latitude(5, u.deg),
                            Distance(10, u.kpc))

    # Arrays of any of the inputs are fine
    UnitSphericalRepresentation(lon=[8, 9] * u.hourangle, lat=[5, 6] * u.deg)

    # Default is to copy arrays, but optionally, it can be a reference
    UnitSphericalRepresentation(lon=[8, 9] * u.hourangle,
                                lat=[5, 6] * u.deg,
                                copy=False)

    # strings are parsed by `Latitude` and `Longitude` constructors, so no need to
    # implement parsing in the Representation classes
    UnitSphericalRepresentation(lon=Angle('2h6m3.3s'), lat=Angle('0.1rad'))

    # Or, you can give `Quantity`s with keywords, and they will be internally
    # converted to Angle/Distance
    c1 = SphericalRepresentation(lon=8 * u.hourangle,
                                 lat=5 * u.deg,
                                 distance=10 * u.kpc)

    # Can also give another representation object with the `reprobj` keyword.
    c2 = SphericalRepresentation.from_representation(c1)

    #  distance, lat, and lon typically will just match in shape
    SphericalRepresentation(lon=[8, 9] * u.hourangle,
                            lat=[5, 6] * u.deg,
                            distance=[10, 11] * u.kpc)
    # if the inputs are not the same, if possible they will be broadcast following
    # numpy's standard broadcasting rules.
    c2 = SphericalRepresentation(lon=[8, 9] * u.hourangle,
                                 lat=[5, 6] * u.deg,
                                 distance=10 * u.kpc)
    assert len(c2.distance) == 2
    # when they can't be broadcast, it is a ValueError (same as Numpy)
    with pytest.raises(ValueError):
        c2 = UnitSphericalRepresentation(lon=[8, 9, 10] * u.hourangle,
                                         lat=[5, 6] * u.deg)

    # It's also possible to pass in scalar quantity lists with mixed units. These
    # are converted to array quantities following the same rule as `Quantity`: all
    # elements are converted to match the first element's units.
    c2 = UnitSphericalRepresentation(
        lon=Angle([8 * u.hourangle, 135 * u.deg]),
        lat=Angle([5 * u.deg, (6 * np.pi / 180) * u.rad]))
    assert c2.lat.unit == u.deg and c2.lon.unit == u.hourangle
    npt.assert_almost_equal(c2.lon[1].value, 9)

    # The Quantity initializer itself can also be used to force the unit even if the
    # first element doesn't have the right unit
    lon = u.Quantity([120 * u.deg, 135 * u.deg], u.hourangle)
    lat = u.Quantity([(5 * np.pi / 180) * u.rad, 0.4 * u.hourangle], u.deg)
    c2 = UnitSphericalRepresentation(lon, lat)

    # regardless of how input, the `lat` and `lon` come out as angle/distance
    assert isinstance(c1.lat, Angle)
    assert isinstance(
        c1.lat,
        Latitude)  # `Latitude` is an `~astropy.coordinates.Angle` subclass
    assert isinstance(c1.distance, Distance)

    # but they are read-only, as representations are immutable once created
    with pytest.raises(AttributeError):
        c1.lat = Latitude(5, u.deg)
    # Note that it is still possible to modify the array in-place, but this is not
    # sanctioned by the API, as this would prevent things like caching.
    c2.lat[:] = [0] * u.deg  # possible, but NOT SUPPORTED

    # To address the fact that there are various other conventions for how spherical
    # coordinates are defined, other conventions can be included as new classes.
    # Later there may be other conventions that we implement - for now just the
    # physics convention, as it is one of the most common cases.
    _ = PhysicsSphericalRepresentation(phi=120 * u.deg,
                                       theta=85 * u.deg,
                                       r=3 * u.kpc)

    # first dimension must be length-3 if a lone `Quantity` is passed in.
    c1 = CartesianRepresentation(np.random.randn(3, 100) * u.kpc)
    assert c1.xyz.shape[0] == 3
    assert c1.xyz.unit == u.kpc
    assert c1.x.shape[0] == 100
    assert c1.y.shape[0] == 100
    assert c1.z.shape[0] == 100
    # can also give each as separate keywords
    CartesianRepresentation(x=np.random.randn(100) * u.kpc,
                            y=np.random.randn(100) * u.kpc,
                            z=np.random.randn(100) * u.kpc)
    # if the units don't match but are all distances, they will automatically be
    # converted to match `x`
    xarr, yarr, zarr = np.random.randn(3, 100)
    c1 = CartesianRepresentation(x=xarr * u.kpc,
                                 y=yarr * u.kpc,
                                 z=zarr * u.kpc)
    c2 = CartesianRepresentation(x=xarr * u.kpc, y=yarr * u.kpc, z=zarr * u.pc)
    assert c1.xyz.unit == c2.xyz.unit == u.kpc
    assert_allclose((c1.z / 1000) - c2.z, 0 * u.kpc, atol=1e-10 * u.kpc)

    # representations convert into other representations via  `represent_as`
    srep = SphericalRepresentation(lon=90 * u.deg,
                                   lat=0 * u.deg,
                                   distance=1 * u.pc)
    crep = srep.represent_as(CartesianRepresentation)
    assert_allclose(crep.x, 0 * u.pc, atol=1e-10 * u.pc)
    assert_allclose(crep.y, 1 * u.pc, atol=1e-10 * u.pc)
    assert_allclose(crep.z, 0 * u.pc, atol=1e-10 * u.pc)
Ejemplo n.º 3
0
def test_representations_api():
    from astropy.coordinates.representation import SphericalRepresentation, \
        UnitSphericalRepresentation, PhysicsSphericalRepresentation, \
        CartesianRepresentation
    from astropy.coordinates import Angle, Longitude, Latitude, Distance

    # <-----------------Classes for representation of coordinate data-------------->
    # These classes inherit from a common base class and internally contain Quantity
    # objects, which are arrays (although they may act as scalars, like numpy's
    # length-0  "arrays")

    # They can be initialized with a variety of ways that make intuitive sense.
    # Distance is optional.
    UnitSphericalRepresentation(lon=8*u.hour, lat=5*u.deg)
    UnitSphericalRepresentation(lon=8*u.hourangle, lat=5*u.deg)
    SphericalRepresentation(lon=8*u.hourangle, lat=5*u.deg, distance=10*u.kpc)

    # In the initial implementation, the lat/lon/distance arguments to the
    # initializer must be in order. A *possible* future change will be to allow
    # smarter guessing of the order.  E.g. `Latitude` and `Longitude` objects can be
    # given in any order.
    UnitSphericalRepresentation(Longitude(8, u.hour), Latitude(5, u.deg))
    SphericalRepresentation(Longitude(8, u.hour), Latitude(5, u.deg), Distance(10, u.kpc))

    # Arrays of any of the inputs are fine
    UnitSphericalRepresentation(lon=[8, 9]*u.hourangle, lat=[5, 6]*u.deg)

    # Default is to copy arrays, but optionally, it can be a reference
    UnitSphericalRepresentation(lon=[8, 9]*u.hourangle, lat=[5, 6]*u.deg, copy=False)

    # strings are parsed by `Latitude` and `Longitude` constructors, so no need to
    # implement parsing in the Representation classes
    UnitSphericalRepresentation(lon=Angle('2h6m3.3s'), lat=Angle('0.1rad'))

    # Or, you can give `Quantity`s with keywords, and they will be internally
    # converted to Angle/Distance
    c1 = SphericalRepresentation(lon=8*u.hourangle, lat=5*u.deg, distance=10*u.kpc)

    # Can also give another representation object with the `reprobj` keyword.
    c2 = SphericalRepresentation.from_representation(c1)

    #  distance, lat, and lon typically will just match in shape
    SphericalRepresentation(lon=[8, 9]*u.hourangle, lat=[5, 6]*u.deg, distance=[10, 11]*u.kpc)
    # if the inputs are not the same, if possible they will be broadcast following
    # numpy's standard broadcasting rules.
    c2 = SphericalRepresentation(lon=[8, 9]*u.hourangle, lat=[5, 6]*u.deg, distance=10*u.kpc)
    assert len(c2.distance) == 2
    # when they can't be broadcast, it is a ValueError (same as Numpy)
    with raises(ValueError):
        c2 = UnitSphericalRepresentation(lon=[8, 9, 10]*u.hourangle, lat=[5, 6]*u.deg)

    # It's also possible to pass in scalar quantity lists with mixed units. These
    # are converted to array quantities following the same rule as `Quantity`: all
    # elements are converted to match the first element's units.
    c2 = UnitSphericalRepresentation(lon=Angle([8*u.hourangle, 135*u.deg]),
                                     lat=Angle([5*u.deg, (6*np.pi/180)*u.rad]))
    assert c2.lat.unit == u.deg and c2.lon.unit == u.hourangle
    npt.assert_almost_equal(c2.lon[1].value, 9)

    # The Quantity initializer itself can also be used to force the unit even if the
    # first element doesn't have the right unit
    lon = u.Quantity([120*u.deg, 135*u.deg], u.hourangle)
    lat = u.Quantity([(5*np.pi/180)*u.rad, 0.4*u.hourangle], u.deg)
    c2 = UnitSphericalRepresentation(lon, lat)

    # regardless of how input, the `lat` and `lon` come out as angle/distance
    assert isinstance(c1.lat, Angle)
    assert isinstance(c1.lat, Latitude)  # `Latitude` is an `Angle` subclass
    assert isinstance(c1.distance, Distance)

    # but they are read-only, as representations are immutable once created
    with raises(AttributeError):
        c1.lat = Latitude(5, u.deg)
    # Note that it is still possible to modify the array in-place, but this is not
    # sanctioned by the API, as this would prevent things like caching.
    c2.lat[:] = [0] * u.deg  # possible, but NOT SUPPORTED

    # To address the fact that there are various other conventions for how spherical
    # coordinates are defined, other conventions can be included as new classes.
    # Later there may be other conventions that we implement - for now just the
    # physics convention, as it is one of the most common cases.
    c3 = PhysicsSphericalRepresentation(phi=120*u.deg, theta=85*u.deg, r=3*u.kpc)

    # first dimension must be length-3 if a lone `Quantity` is passed in.
    c1 = CartesianRepresentation(np.random.randn(3, 100) * u.kpc)
    assert c1.xyz.shape[0] == 3
    assert c1.xyz.unit == u.kpc
    assert c1.x.shape[0] == 100
    assert c1.y.shape[0] == 100
    assert c1.z.shape[0] == 100
    # can also give each as separate keywords
    CartesianRepresentation(x=np.random.randn(100)*u.kpc,
                            y=np.random.randn(100)*u.kpc,
                            z=np.random.randn(100)*u.kpc)
    # if the units don't match but are all distances, they will automatically be
    # converted to match `x`
    xarr, yarr, zarr = np.random.randn(3, 100)
    c1 = CartesianRepresentation(x=xarr*u.kpc, y=yarr*u.kpc, z=zarr*u.kpc)
    c2 = CartesianRepresentation(x=xarr*u.kpc, y=yarr*u.kpc, z=zarr*u.pc)
    assert c1.xyz.unit == c2.xyz.unit == u.kpc
    assert_allclose((c1.z / 1000) - c2.z, 0*u.kpc, atol=1e-10*u.kpc)

    # representations convert into other representations via  `represent_as`
    srep = SphericalRepresentation(lon=90*u.deg, lat=0*u.deg, distance=1*u.pc)
    crep = srep.represent_as(CartesianRepresentation)
    assert_allclose(crep.x, 0*u.pc, atol=1e-10*u.pc)
    assert_allclose(crep.y, 1*u.pc, atol=1e-10*u.pc)
    assert_allclose(crep.z, 0*u.pc, atol=1e-10*u.pc)