diff --git a/CHANGES.rst b/CHANGES.rst index c0c8b653e7e..6630298d6f7 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -35,6 +35,8 @@ astropy.io.ascii astropy.io.misc ^^^^^^^^^^^^^^^ +Added support for saving all representation classes and many coordinate frames to the asdf format. [#7079] + astropy.io.fits ^^^^^^^^^^^^^^^ diff --git a/astropy/coordinates/attributes.py b/astropy/coordinates/attributes.py index 887fbafaca8..ae2ca8353d2 100644 --- a/astropy/coordinates/attributes.py +++ b/astropy/coordinates/attributes.py @@ -318,6 +318,7 @@ def convert_input(self, value): converted = oldvalue is not value return value, converted + class EarthLocationAttribute(Attribute): """ A frame attribute that can act as a `~astropy.coordinates.EarthLocation`. @@ -498,6 +499,7 @@ def __init__(self, *args, **kwargs): AstropyDeprecationWarning) super().__init__(*args, **kwargs) + class TimeFrameAttribute(TimeAttribute): def __init__(self, *args, **kwargs): @@ -505,6 +507,7 @@ def __init__(self, *args, **kwargs): AstropyDeprecationWarning) super().__init__(*args, **kwargs) + class QuantityFrameAttribute(QuantityAttribute): def __init__(self, *args, **kwargs): @@ -512,6 +515,7 @@ def __init__(self, *args, **kwargs): "QuantityAttribute.", AstropyDeprecationWarning) super().__init__(*args, **kwargs) + class CartesianRepresentationFrameAttribute(CartesianRepresentationAttribute): def __init__(self, *args, **kwargs): diff --git a/astropy/io/misc/asdf/extension.py b/astropy/io/misc/asdf/extension.py index 46c31d28464..aaa66528150 100644 --- a/astropy/io/misc/asdf/extension.py +++ b/astropy/io/misc/asdf/extension.py @@ -11,6 +11,8 @@ # the extension class so that _astropy_asdf_types is populated correctly. We # could do this using __init__ files, except it causes pytest import errors in # the case that asdf is not installed. +from .tags.coordinates.angle import * +from .tags.coordinates.representation import * from .tags.coordinates.frames import * from .tags.fits.fits import * from .tags.table.table import * diff --git a/astropy/io/misc/asdf/schemas/astropy.org/astropy/coordinates/angle-1.0.0.yaml b/astropy/io/misc/asdf/schemas/astropy.org/astropy/coordinates/angle-1.0.0.yaml new file mode 100644 index 00000000000..898d7545064 --- /dev/null +++ b/astropy/io/misc/asdf/schemas/astropy.org/astropy/coordinates/angle-1.0.0.yaml @@ -0,0 +1,35 @@ +%YAML 1.1 +--- +$schema: "http://stsci.edu/schemas/yaml-schema/draft-01" +id: "http://astropy.org/schemas/astropy/coordinates/angle-1.0.0" +tag: "tag:astropy.org:astropy/coordinates/angle-1.0.0" + +title: | + Represents an Angle. + +description: + This object represents a subtype of Quantity which has units equivalent to + radians or degrees. + +examples: + - + - An Angle object in Degrees + - | + ! + unit: !unit/unit-1.0.0 deg + value: 10.0 + +type: object +properties: + value: + description: | + A vector of one or more values + anyOf: + - type: number + - $ref: "tag:stsci.edu:asdf/core/ndarray-1.0.0" + unit: + description: | + The unit corresponding to the values + $ref: "tag:stsci.edu:asdf/unit/unit-1.0.0" +required: [value, unit] +... diff --git a/astropy/io/misc/asdf/schemas/astropy.org/astropy/coordinates/frames/baseframe-1.0.0.yaml b/astropy/io/misc/asdf/schemas/astropy.org/astropy/coordinates/frames/baseframe-1.0.0.yaml new file mode 100644 index 00000000000..09788310584 --- /dev/null +++ b/astropy/io/misc/asdf/schemas/astropy.org/astropy/coordinates/frames/baseframe-1.0.0.yaml @@ -0,0 +1,27 @@ +%YAML 1.1 +--- +$schema: "http://stsci.edu/schemas/yaml-schema/draft-01" +id: "http://astropy.org/schemas/astropy/coordinates/baseframe-1.0.0" + +title: | + Represents a coordinate frame object from astropy + +description: + This schema is designed to be extended by other schemas to restrict the + allowable frame_attributes. + +type: object +properties: + data: + description: | + The representation object holding any data associated with the frame. + $ref: "./representation-1.0.0" + frame_attributes: + description: | + Attributes on the coordinate frame. + type: object + + +additionalProperties: false +required: [frame_attributes] +... diff --git a/astropy/io/misc/asdf/schemas/astropy.org/astropy/coordinates/frames/cirs-1.0.0.yaml b/astropy/io/misc/asdf/schemas/astropy.org/astropy/coordinates/frames/cirs-1.0.0.yaml new file mode 100644 index 00000000000..cf8f24833d2 --- /dev/null +++ b/astropy/io/misc/asdf/schemas/astropy.org/astropy/coordinates/frames/cirs-1.0.0.yaml @@ -0,0 +1,43 @@ +%YAML 1.1 +--- +$schema: "http://stsci.edu/schemas/yaml-schema/draft-01" +id: "http://astropy.org/schemas/astropy/coordinates/frames/cirs-1.0.0" +tag: "tag:astropy.org:astropy/coordinates/frames/cirs-1.0.0" + +title: | + Represents a CIRS coordinate object from astropy + +examples: + - + - A CIRS frame without data + - | + ! + frame_attributes: + obstime: !time/time-1.1.0 {scale: tai, value: B1950.000} + - + - A CIRS frame with data + - | + ! + data: ! + components: + lat: ! {unit: !unit/unit-1.0.0 deg, + value: 10.0} + lon: ! + unit: !unit/unit-1.0.0 deg + value: 120.0 + wrap_angle: ! {unit: !unit/unit-1.0.0 deg, + value: 360.0} + type: UnitSphericalRepresentation + frame_attributes: + obstime: !time/time-1.1.0 {scale: tai, value: B1950.000} + +allOf: + - $ref: baseframe-1.0.0 + - properties: + frame_attributes: + type: object + properties: + obstime: + $ref: "tag:stsci.edu:asdf/time/time-1.1.0" + required: [obstime] +... diff --git a/astropy/io/misc/asdf/schemas/astropy.org/astropy/coordinates/frames/fk4-1.0.0.yaml b/astropy/io/misc/asdf/schemas/astropy.org/astropy/coordinates/frames/fk4-1.0.0.yaml new file mode 100644 index 00000000000..2fad22bf1d0 --- /dev/null +++ b/astropy/io/misc/asdf/schemas/astropy.org/astropy/coordinates/frames/fk4-1.0.0.yaml @@ -0,0 +1,47 @@ +%YAML 1.1 +--- +$schema: "http://stsci.edu/schemas/yaml-schema/draft-01" +id: "http://astropy.org/schemas/astropy/coordinates/frames/fk4-1.0.0" +tag: "tag:astropy.org:astropy/coordinates/frames/fk4-1.0.0" + +title: | + Represents a FK4 coordinate object from astropy + +examples: + - + - A FK4 frame without data + - | + ! + frame_attributes: + equinox: !time/time-1.1.0 {scale: tai, value: B1950.000} + obstime: !time/time-1.1.0 {scale: tai, value: B1950.000} + - + - A FK4 frame with data + - | + ! + data: ! + components: + lat: ! {unit: !unit/unit-1.0.0 deg, + value: 10.0} + lon: ! + unit: !unit/unit-1.0.0 deg + value: 120.0 + wrap_angle: ! {unit: !unit/unit-1.0.0 deg, + value: 360.0} + type: UnitSphericalRepresentation + frame_attributes: + equinox: !time/time-1.1.0 {scale: tai, value: B1950.000} + obstime: !time/time-1.1.0 {scale: tai, value: B1950.000} + +allOf: + - $ref: baseframe-1.0.0 + - properties: + frame_attributes: + type: object + properties: + equinox: + $ref: "tag:stsci.edu:asdf/time/time-1.1.0" + obstime: + $ref: "tag:stsci.edu:asdf/time/time-1.1.0" + required: [equinox] +... diff --git a/astropy/io/misc/asdf/schemas/astropy.org/astropy/coordinates/frames/fk4noeterms-1.0.0.yaml b/astropy/io/misc/asdf/schemas/astropy.org/astropy/coordinates/frames/fk4noeterms-1.0.0.yaml new file mode 100644 index 00000000000..2258f941f7f --- /dev/null +++ b/astropy/io/misc/asdf/schemas/astropy.org/astropy/coordinates/frames/fk4noeterms-1.0.0.yaml @@ -0,0 +1,47 @@ +%YAML 1.1 +--- +$schema: "http://stsci.edu/schemas/yaml-schema/draft-01" +id: "http://astropy.org/schemas/astropy/coordinates/frames/fk4noeterms-1.0.0" +tag: "tag:astropy.org:astropy/coordinates/frames/fk4noeterms-1.0.0" + +title: | + Represents a FK4NoETerms coordinate object from astropy + +examples: + - + - A FK4NoETerms frame without data + - | + ! + frame_attributes: + equinox: !time/time-1.1.0 {scale: tai, value: B1950.000} + obstime: !time/time-1.1.0 {scale: tai, value: B1950.000} + - + - A FK4NoETerms frame with data + - | + ! + data: ! + components: + lat: ! {unit: !unit/unit-1.0.0 deg, + value: 10.0} + lon: ! + unit: !unit/unit-1.0.0 deg + value: 120.0 + wrap_angle: ! {unit: !unit/unit-1.0.0 deg, + value: 360.0} + type: UnitSphericalRepresentation + frame_attributes: + equinox: !time/time-1.1.0 {scale: tai, value: B1950.000} + obstime: !time/time-1.1.0 {scale: tai, value: B1950.000} + +allOf: + - $ref: baseframe-1.0.0 + - properties: + frame_attributes: + type: object + properties: + equinox: + $ref: "tag:stsci.edu:asdf/time/time-1.1.0" + obstime: + $ref: "tag:stsci.edu:asdf/time/time-1.1.0" + required: [equinox] +... diff --git a/astropy/io/misc/asdf/schemas/astropy.org/astropy/coordinates/frames/fk5-1.0.0.yaml b/astropy/io/misc/asdf/schemas/astropy.org/astropy/coordinates/frames/fk5-1.0.0.yaml new file mode 100644 index 00000000000..6a7886841a2 --- /dev/null +++ b/astropy/io/misc/asdf/schemas/astropy.org/astropy/coordinates/frames/fk5-1.0.0.yaml @@ -0,0 +1,41 @@ +%YAML 1.1 +--- +$schema: "http://stsci.edu/schemas/yaml-schema/draft-01" +id: "http://astropy.org/schemas/astropy/coordinates/frames/fk5-1.0.0" +tag: "tag:astropy.org:astropy/coordinates/frames/fk5-1.0.0" + +title: | + Represents a FK5 coordinate object from astropy + +examples: + - + - A FK5 frame without data with a custom equinox + - | + ! + frame_attributes: {equinox: !time/time-1.1.0 '2011-01-02 00:00:00.000'} + - + - A FK5 frame with data + - | + ! + data: ! + components: + lat: ! {unit: !unit/unit-1.0.0 deg, + value: 10.0} + lon: ! + unit: !unit/unit-1.0.0 deg + value: 120.0 + wrap_angle: ! {unit: !unit/unit-1.0.0 deg, + value: 360.0} + type: UnitSphericalRepresentation + frame_attributes: {equinox: !time/time-1.1.0 J2000.000} + +allOf: + - $ref: baseframe-1.0.0 + - properties: + frame_attributes: + type: object + properties: + equinox: + $ref: "tag:stsci.edu:asdf/time/time-1.1.0" + required: [equinox] +... diff --git a/astropy/io/misc/asdf/schemas/astropy.org/astropy/coordinates/frames/galactic-1.0.0.yaml b/astropy/io/misc/asdf/schemas/astropy.org/astropy/coordinates/frames/galactic-1.0.0.yaml new file mode 100644 index 00000000000..041c81d7cbc --- /dev/null +++ b/astropy/io/misc/asdf/schemas/astropy.org/astropy/coordinates/frames/galactic-1.0.0.yaml @@ -0,0 +1,37 @@ +%YAML 1.1 +--- +$schema: "http://stsci.edu/schemas/yaml-schema/draft-01" +id: "http://astropy.org/schemas/astropy/coordinates/frames/galactic-1.0.0" +tag: "tag:astropy.org:astropy/coordinates/frames/galactic-1.0.0" + +title: | + Represents an Galactic coordinate object from astropy. + +examples: + - + - An Galactic frame without data + - | + ! + frame_attributes: {} + - + - An Galactic frame with data + - | + ! + data: ! + components: + lat: ! {unit: !unit/unit-1.0.0 deg, + value: 2.0} + lon: ! + unit: !unit/unit-1.0.0 deg + value: 1.0 + wrap_angle: ! {unit: !unit/unit-1.0.0 deg, + value: 360.0} + type: UnitSphericalRepresentation + frame_attributes: {} + + + + +allOf: + - $ref: baseframe-1.0.0 +... diff --git a/astropy/io/misc/asdf/schemas/astropy.org/astropy/coordinates/frames/galactocentric-1.0.0.yaml b/astropy/io/misc/asdf/schemas/astropy.org/astropy/coordinates/frames/galactocentric-1.0.0.yaml new file mode 100644 index 00000000000..2475517f1a4 --- /dev/null +++ b/astropy/io/misc/asdf/schemas/astropy.org/astropy/coordinates/frames/galactocentric-1.0.0.yaml @@ -0,0 +1,56 @@ +%YAML 1.1 +--- +$schema: "http://stsci.edu/schemas/yaml-schema/draft-01" +id: "http://astropy.org/schemas/astropy/coordinates/frames/galactocentric-1.0.0" +tag: "tag:astropy.org:astropy/coordinates/frames/galactocentric-1.0.0" + +title: | + Represents an galactocentric coordinate object from astropy + +examples: + - + - A Galactocentric frame without data + - | + ! + frame_attributes: + galcen_coord: ! + data: ! + components: + lat: ! {unit: !unit/unit-1.0.0 deg, + value: -28.936175} + lon: ! + unit: !unit/unit-1.0.0 deg + value: 266.4051 + wrap_angle: ! {unit: !unit/unit-1.0.0 deg, + value: 360.0} + type: UnitSphericalRepresentation + frame_attributes: {} + galcen_distance: !unit/quantity-1.1.0 {unit: !unit/unit-1.0.0 kpc, value: 8.3} + galcen_v_sun: ! + components: + d_x: !unit/quantity-1.1.0 {unit: !unit/unit-1.0.0 km s-1, value: 11.1} + d_y: !unit/quantity-1.1.0 {unit: !unit/unit-1.0.0 km s-1, value: 232.24} + d_z: !unit/quantity-1.1.0 {unit: !unit/unit-1.0.0 km s-1, value: 7.25} + type: CartesianDifferential + roll: !unit/quantity-1.1.0 {unit: !unit/unit-1.0.0 deg, value: 0.0} + z_sun: !unit/quantity-1.1.0 {unit: !unit/unit-1.0.0 pc, value: 27.0} + +allOf: + - $ref: baseframe-1.0.0 + - properties: + frame_attributes: + type: object + properties: + galacen_coord: + $ref: "icrs-1.1.0" + galcen_distance: + $ref: "tag:stsci.edu:asdf/unit/quantity-1.1.0" + galcen_v_sun: + $ref: "../representation-1.0.0" + z_sun: + $ref: "tag:stsci.edu:asdf/unit/quantity-1.1.0" + roll: + $ref: "tag:stsci.edu:asdf/unit/quantity-1.1.0" + + required: [galcen_coord, galcen_distance, galcen_v_sun, z_sun, roll] +... diff --git a/astropy/io/misc/asdf/schemas/astropy.org/astropy/coordinates/frames/gcrs-1.0.0.yaml b/astropy/io/misc/asdf/schemas/astropy.org/astropy/coordinates/frames/gcrs-1.0.0.yaml new file mode 100644 index 00000000000..374a493bc1e --- /dev/null +++ b/astropy/io/misc/asdf/schemas/astropy.org/astropy/coordinates/frames/gcrs-1.0.0.yaml @@ -0,0 +1,70 @@ +%YAML 1.1 +--- +$schema: "http://stsci.edu/schemas/yaml-schema/draft-01" +id: "http://astropy.org/schemas/astropy/coordinates/frames/gcrs-1.0.0" +tag: "tag:astropy.org:astropy/coordinates/frames/gcrs-1.0.0" + +title: | + Represents a GCRS coordinate object from astropy + +examples: + - + - A GCRS frame without data + - | + ! + frame_attributes: + obsgeoloc: ! + components: + x: !unit/quantity-1.1.0 {unit: !unit/unit-1.0.0 m, value: 0.0} + y: !unit/quantity-1.1.0 {unit: !unit/unit-1.0.0 m, value: 0.0} + z: !unit/quantity-1.1.0 {unit: !unit/unit-1.0.0 m, value: 0.0} + type: CartesianRepresentation + obsgeovel: ! + components: + x: !unit/quantity-1.1.0 {unit: !unit/unit-1.0.0 m s-1, value: 0.0} + y: !unit/quantity-1.1.0 {unit: !unit/unit-1.0.0 m s-1, value: 0.0} + z: !unit/quantity-1.1.0 {unit: !unit/unit-1.0.0 m s-1, value: 0.0} + type: CartesianRepresentation + obstime: !time/time-1.1.0 J2000.000 + - + - A GCRS frame with data + - | + ! + data: ! + components: + lat: ! {unit: !unit/unit-1.0.0 deg, + value: 2.0} + lon: ! + unit: !unit/unit-1.0.0 deg + value: 1.0 + wrap_angle: ! {unit: !unit/unit-1.0.0 deg, + value: 360.0} + type: UnitSphericalRepresentation + frame_attributes: + obsgeoloc: ! + components: + x: !unit/quantity-1.1.0 {unit: !unit/unit-1.0.0 m, value: 0.0} + y: !unit/quantity-1.1.0 {unit: !unit/unit-1.0.0 m, value: 0.0} + z: !unit/quantity-1.1.0 {unit: !unit/unit-1.0.0 m, value: 0.0} + type: CartesianRepresentation + obsgeovel: ! + components: + x: !unit/quantity-1.1.0 {unit: !unit/unit-1.0.0 m s-1, value: 0.0} + y: !unit/quantity-1.1.0 {unit: !unit/unit-1.0.0 m s-1, value: 0.0} + z: !unit/quantity-1.1.0 {unit: !unit/unit-1.0.0 m s-1, value: 0.0} + type: CartesianRepresentation + obstime: !time/time-1.1.0 J2000.000 + +allOf: + - $ref: baseframe-1.0.0 + - properties: + frame_attributes: + type: object + properties: + obstime: + $ref: "tag:stsci.edu:asdf/time/time-1.1.0" + obsgeoloc: + $ref: "../representation-1.0.0" + obsgeovel: + $ref: "../representation-1.0.0" +... diff --git a/astropy/io/misc/asdf/schemas/astropy.org/astropy/coordinates/frames/icrs-1.1.0.yaml b/astropy/io/misc/asdf/schemas/astropy.org/astropy/coordinates/frames/icrs-1.1.0.yaml new file mode 100644 index 00000000000..830dc204471 --- /dev/null +++ b/astropy/io/misc/asdf/schemas/astropy.org/astropy/coordinates/frames/icrs-1.1.0.yaml @@ -0,0 +1,36 @@ +%YAML 1.1 +--- +$schema: "http://stsci.edu/schemas/yaml-schema/draft-01" +id: "http://astropy.org/schemas/astropy/coordinates/frames/icrs-1.1.0" +tag: "tag:astropy.org:astropy/coordinates/frames/icrs-1.1.0" + +title: | + Represents an ICRS coordinate object from astropy. + +examples: + - + - An ICRS frame without data + - | + ! + frame_attributes: {} + - + - An ICRS frame with data + - | + ! + data: ! + components: + lat: ! {unit: !unit/unit-1.0.0 deg, + value: 10.0} + lon: ! + unit: !unit/unit-1.0.0 deg + value: 120.0 + wrap_angle: ! {unit: !unit/unit-1.0.0 deg, + value: 360.0} + type: UnitSphericalRepresentation + frame_attributes: {} + + + +allOf: + - $ref: baseframe-1.0.0 +... diff --git a/astropy/io/misc/asdf/schemas/astropy.org/astropy/coordinates/frames/itrs-1.0.0.yaml b/astropy/io/misc/asdf/schemas/astropy.org/astropy/coordinates/frames/itrs-1.0.0.yaml new file mode 100644 index 00000000000..e5d2f386db5 --- /dev/null +++ b/astropy/io/misc/asdf/schemas/astropy.org/astropy/coordinates/frames/itrs-1.0.0.yaml @@ -0,0 +1,43 @@ +%YAML 1.1 +--- +$schema: "http://stsci.edu/schemas/yaml-schema/draft-01" +id: "http://astropy.org/schemas/astropy/coordinates/frames/itrs-1.0.0" +tag: "tag:astropy.org:astropy/coordinates/frames/itrs-1.0.0" + +title: | + Represents a ITRS coordinate object from astropy + +examples: + - + - A ITRS frame without data + - | + ! + frame_attributes: + obstime: !time/time-1.1.0 {scale: tai, value: B1950.000} + - + - A ITRS frame with data + - | + ! + data: ! + components: + lat: ! {unit: !unit/unit-1.0.0 deg, + value: 10.0} + lon: ! + unit: !unit/unit-1.0.0 deg + value: 120.0 + wrap_angle: ! {unit: !unit/unit-1.0.0 deg, + value: 360.0} + type: UnitSphericalRepresentation + frame_attributes: + obstime: !time/time-1.1.0 {scale: tai, value: B1950.000} + +allOf: + - $ref: baseframe-1.0.0 + - properties: + frame_attributes: + type: object + properties: + obstime: + $ref: "tag:stsci.edu:asdf/time/time-1.1.0" + required: [obstime] +... diff --git a/astropy/io/misc/asdf/schemas/astropy.org/astropy/coordinates/frames/precessedgeocentric-1.0.0.yaml b/astropy/io/misc/asdf/schemas/astropy.org/astropy/coordinates/frames/precessedgeocentric-1.0.0.yaml new file mode 100644 index 00000000000..b9d1df7b468 --- /dev/null +++ b/astropy/io/misc/asdf/schemas/astropy.org/astropy/coordinates/frames/precessedgeocentric-1.0.0.yaml @@ -0,0 +1,74 @@ +%YAML 1.1 +--- +$schema: "http://stsci.edu/schemas/yaml-schema/draft-01" +id: "http://astropy.org/schemas/astropy/coordinates/frames/precessedgeocentric-1.0.0" +tag: "tag:astropy.org:astropy/coordinates/frames/precessedgeocentric-1.0.0" + +title: | + Represents a PrecessedGeocentric coordinate object from astropy + +examples: + - + - A PrecessedGeocentric frame without data + - | + ! + frame_attributes: + equinox: !time/time-1.1.0 J2000.000 + obsgeoloc: ! + components: + x: !unit/quantity-1.1.0 {unit: !unit/unit-1.0.0 m, value: 0.0} + y: !unit/quantity-1.1.0 {unit: !unit/unit-1.0.0 m, value: 0.0} + z: !unit/quantity-1.1.0 {unit: !unit/unit-1.0.0 m, value: 0.0} + type: CartesianRepresentation + obsgeovel: ! + components: + x: !unit/quantity-1.1.0 {unit: !unit/unit-1.0.0 m s-1, value: 0.0} + y: !unit/quantity-1.1.0 {unit: !unit/unit-1.0.0 m s-1, value: 0.0} + z: !unit/quantity-1.1.0 {unit: !unit/unit-1.0.0 m s-1, value: 0.0} + type: CartesianRepresentation + obstime: !time/time-1.1.0 J2000.000 + - + - A PrecessedGeocentric frame with data + - | + ! + data: ! + components: + lat: ! {unit: !unit/unit-1.0.0 deg, + value: 1.0} + lon: ! + unit: !unit/unit-1.0.0 deg + value: 1.0 + wrap_angle: ! {unit: !unit/unit-1.0.0 deg, + value: 360.0} + type: UnitSphericalRepresentation + frame_attributes: + equinox: !time/time-1.1.0 J2000.000 + obsgeoloc: ! + components: + x: !unit/quantity-1.1.0 {unit: !unit/unit-1.0.0 m, value: 0.0} + y: !unit/quantity-1.1.0 {unit: !unit/unit-1.0.0 m, value: 0.0} + z: !unit/quantity-1.1.0 {unit: !unit/unit-1.0.0 m, value: 0.0} + type: CartesianRepresentation + obsgeovel: ! + components: + x: !unit/quantity-1.1.0 {unit: !unit/unit-1.0.0 m s-1, value: 0.0} + y: !unit/quantity-1.1.0 {unit: !unit/unit-1.0.0 m s-1, value: 0.0} + z: !unit/quantity-1.1.0 {unit: !unit/unit-1.0.0 m s-1, value: 0.0} + type: CartesianRepresentation + obstime: !time/time-1.1.0 J2000.000 + +allOf: + - $ref: baseframe-1.0.0 + - properties: + frame_attributes: + type: object + properties: + equinox: + $ref: "tag:stsci.edu:asdf/time/time-1.1.0" + obstime: + $ref: "tag:stsci.edu:asdf/time/time-1.1.0" + obsgeoloc: + $ref: "../representation-1.0.0" + obsgeovel: + $ref: "../representation-1.0.0" +... diff --git a/astropy/io/misc/asdf/schemas/astropy.org/astropy/coordinates/latitude-1.0.0.yaml b/astropy/io/misc/asdf/schemas/astropy.org/astropy/coordinates/latitude-1.0.0.yaml new file mode 100644 index 00000000000..823056636b0 --- /dev/null +++ b/astropy/io/misc/asdf/schemas/astropy.org/astropy/coordinates/latitude-1.0.0.yaml @@ -0,0 +1,34 @@ +%YAML 1.1 +--- +$schema: "http://stsci.edu/schemas/yaml-schema/draft-01" +id: "http://astropy.org/schemas/astropy/coordinates/latitude-1.0.0" +tag: "tag:astropy.org:astropy/coordinates/latitude-1.0.0" + +title: | + Represents latitude-like angles. + +description: + Represents latitude-like angle(s) which must be in the range -90 to +90 deg. + +examples: + - + - A Latitude object in Degrees + - | + ! + unit: !unit/unit-1.0.0 deg + value: 10.0 + +type: object +properties: + value: + description: | + A vector of one or more values + anyOf: + - type: number + - $ref: "tag:stsci.edu:asdf/core/ndarray-1.0.0" + unit: + description: | + The unit corresponding to the values + $ref: "tag:stsci.edu:asdf/unit/unit-1.0.0" +required: [value, unit] +... diff --git a/astropy/io/misc/asdf/schemas/astropy.org/astropy/coordinates/longitude-1.0.0.yaml b/astropy/io/misc/asdf/schemas/astropy.org/astropy/coordinates/longitude-1.0.0.yaml new file mode 100644 index 00000000000..1e1971d3146 --- /dev/null +++ b/astropy/io/misc/asdf/schemas/astropy.org/astropy/coordinates/longitude-1.0.0.yaml @@ -0,0 +1,42 @@ +%YAML 1.1 +--- +$schema: "http://stsci.edu/schemas/yaml-schema/draft-01" +id: "http://astropy.org/schemas/astropy/coordinates/longitude-1.0.0" +tag: "tag:astropy.org:astropy/coordinates/longitude-1.0.0" + +title: | + Represents longitude-like angles. + +description: + Longitude-like angle(s) which are wrapped within a contiguous 360 degree range. + +examples: + - + - A Longitude object in Degrees + - | + ! + unit: !unit/unit-1.0.0 deg + value: 10.0 + wrap_angle: ! + unit: !unit/unit-1.0.0 deg + value: 180.0 + +type: object +properties: + value: + description: | + A vector of one or more values + anyOf: + - type: number + - $ref: "tag:stsci.edu:asdf/core/ndarray-1.0.0" + unit: + description: | + The unit corresponding to the values + $ref: "tag:stsci.edu:asdf/unit/unit-1.0.0" + wrap_angle: + description: | + Angle at which to wrap back to ``wrap_angle - 360 deg``. + $ref: "angle-1.0.0" + +required: [value, unit, wrap_angle] +... diff --git a/astropy/io/misc/asdf/schemas/astropy.org/astropy/coordinates/representation-1.0.0.yaml b/astropy/io/misc/asdf/schemas/astropy.org/astropy/coordinates/representation-1.0.0.yaml new file mode 100644 index 00000000000..cb1b44323bb --- /dev/null +++ b/astropy/io/misc/asdf/schemas/astropy.org/astropy/coordinates/representation-1.0.0.yaml @@ -0,0 +1,207 @@ +%YAML 1.1 +--- +$schema: "http://stsci.edu/schemas/yaml-schema/draft-01" +id: "http://astropy.org/schemas/astropy/coordinates/representation-1.0.0" +tag: "tag:astropy.org:astropy/coordinates/representation-1.0.0" + +title: | + Representation of points or differentials in two or three dimensional space. + +description: + Representation of points or differentials in two or three dimensional space. + +examples: + - + - A SphericalRepresentation + - | + ! + components: + distance: !unit/quantity-1.1.0 {unit: !unit/unit-1.0.0 AU, value: 1.0} + lat: ! {unit: !unit/unit-1.0.0 deg, + value: 10.0} + lon: ! + unit: !unit/unit-1.0.0 deg + value: 10.0 + wrap_angle: ! {unit: !unit/unit-1.0.0 deg, + value: 360.0} + type: SphericalRepresentation + - + - A CartesianDifferential + - | + ! + components: + d_x: !unit/quantity-1.1.0 {unit: !unit/unit-1.0.0 km s-1, value: 100.0} + d_y: !unit/quantity-1.1.0 {unit: !unit/unit-1.0.0 km s-1, value: 200.0} + d_z: !unit/quantity-1.1.0 {unit: !unit/unit-1.0.0 km s-1, value: 3141.0} + type: CartesianDifferential + +type: object +properties: + type: + type: string + enum: + - CartesianRepresentation + - SphericalRepresentation + - UnitSphericalRepresentation + - RadialRepresentation + - PhysicsSphericalRepresentation + - CylindricalRepresentation + - CartesianDifferential + - SphericalDifferential + - UnitSphericalCosLatDifferential + - UnitSphericalDifferential + - SphericalCosLatDifferential + - RadialDifferential + - PhysicsSphericalDifferential + - CylindricalDifferential + + components: + anyOf: + # CartesianRepresentation + - type: object + properties: + x: + $ref: "tag:stsci.edu:asdf/unit/quantity-1.1.0" + y: + $ref: "tag:stsci.edu:asdf/unit/quantity-1.1.0" + z: + $ref: "tag:stsci.edu:asdf/unit/quantity-1.1.0" + + # SphericalRepresentation + - type: object + properties: + lat: + $ref: "latitude-1.0.0" + lon: + $ref: "longitude-1.0.0" + distance: + $ref: "tag:stsci.edu:asdf/unit/quantity-1.1.0" + + # UnitSphericalRepresentation + - type: object + properties: + lat: + $ref: "latitude-1.0.0" + lon: + $ref: "longitude-1.0.0" + + # RadialRepresentation + - type: object + properties: + distance: + $ref: "tag:stsci.edu:asdf/unit/quantity-1.1.0" + + # PhysicsSphericalRepresentation + - type: object + properties: + phi: + $ref: "angle-1.0.0" + theta: + $ref: "angle-1.0.0" + r: + $ref: "tag:stsci.edu:asdf/unit/quantity-1.1.0" + + # CylindricalRepresentation + - type: object + properties: + rho: + $ref: "tag:stsci.edu:asdf/unit/quantity-1.1.0" + phi: + $ref: "angle-1.0.0" + z: + $ref: "tag:stsci.edu:asdf/unit/quantity-1.1.0" + + # CartesianDifferential + - type: object + properties: + d_x: + $ref: "tag:stsci.edu:asdf/unit/quantity-1.1.0" + d_y: + $ref: "tag:stsci.edu:asdf/unit/quantity-1.1.0" + d_z: + $ref: "tag:stsci.edu:asdf/unit/quantity-1.1.0" + + # SphericalDifferential + - type: object + properties: + d_lon: + $ref: "tag:stsci.edu:asdf/unit/quantity-1.1.0" + d_lat: + $ref: "tag:stsci.edu:asdf/unit/quantity-1.1.0" + d_distance: + $ref: "tag:stsci.edu:asdf/unit/quantity-1.1.0" + + # UnitSphericalCosLatDifferential + - type: object + properties: + d_lon_coslat: + $ref: "tag:stsci.edu:asdf/unit/quantity-1.1.0" + d_lat: + $ref: "tag:stsci.edu:asdf/unit/quantity-1.1.0" + + # UnitSphericalDifferential + - type: object + properties: + d_lon: + $ref: "tag:stsci.edu:asdf/unit/quantity-1.1.0" + d_lat: + $ref: "tag:stsci.edu:asdf/unit/quantity-1.1.0" + + # SphericalCosLatDifferential + - type: object + properties: + d_lon_coslat: + $ref: "tag:stsci.edu:asdf/unit/quantity-1.1.0" + d_lat: + $ref: "tag:stsci.edu:asdf/unit/quantity-1.1.0" + d_distance: + $ref: "tag:stsci.edu:asdf/unit/quantity-1.1.0" + + # SphericalDifferential + - type: object + properties: + d_lon: + $ref: "tag:stsci.edu:asdf/unit/quantity-1.1.0" + d_lat: + $ref: "tag:stsci.edu:asdf/unit/quantity-1.1.0" + d_distance: + $ref: "tag:stsci.edu:asdf/unit/quantity-1.1.0" + + # RadialDifferential + - type: object + properties: + d_phi: + $ref: "tag:stsci.edu:asdf/unit/quantity-1.1.0" + d_theta: + $ref: "tag:stsci.edu:asdf/unit/quantity-1.1.0" + d_r: + $ref: "tag:stsci.edu:asdf/unit/quantity-1.1.0" + + # PhysicsSphericalDifferential + - type: object + properties: + d_phi: + $ref: "tag:stsci.edu:asdf/unit/quantity-1.1.0" + d_theta: + $ref: "tag:stsci.edu:asdf/unit/quantity-1.1.0" + d_r: + $ref: "tag:stsci.edu:asdf/unit/quantity-1.1.0" + + # RadialDifferential + - type: object + properties: + d_distance: + $ref: "tag:stsci.edu:asdf/unit/quantity-1.1.0" + + # CylindricalDifferential + - type: object + properties: + d_rho: + $ref: "tag:stsci.edu:asdf/unit/quantity-1.1.0" + d_phi: + $ref: "tag:stsci.edu:asdf/unit/quantity-1.1.0" + d_z: + $ref: "tag:stsci.edu:asdf/unit/quantity-1.1.0" + +required: [type, components] +... diff --git a/astropy/io/misc/asdf/tags/coordinates/angle.py b/astropy/io/misc/asdf/tags/coordinates/angle.py new file mode 100644 index 00000000000..09ad631f32b --- /dev/null +++ b/astropy/io/misc/asdf/tags/coordinates/angle.py @@ -0,0 +1,49 @@ +# Licensed under a 3-clause BSD style license - see LICENSE.rst +# -*- coding: utf-8 -*- + +from asdf.yamlutil import custom_tree_to_tagged_tree +from astropy.coordinates import Angle, Latitude, Longitude + +from ..unit.quantity import QuantityType + + +__all__ = ['AngleType', 'LatitudeType', 'LongitudeType'] + + +class AngleType(QuantityType): + name = "coordinates/angle" + types = [Angle] + requires = ['astropy'] + version = "1.0.0" + organization = 'astropy.org' + standard = 'astropy' + + @classmethod + def from_tree(cls, node, ctx): + return Angle(super().from_tree(node, ctx)) + + +class LatitudeType(AngleType): + name = "coordinates/latitude" + types = [Latitude] + + @classmethod + def from_tree(cls, node, ctx): + return Latitude(super().from_tree(node, ctx)) + + +class LongitudeType(AngleType): + name = "coordinates/longitude" + types = [Longitude] + + @classmethod + def from_tree(cls, node, ctx): + wrap_angle = node['wrap_angle'] + return Longitude(super().from_tree(node, ctx), wrap_angle=wrap_angle) + + @classmethod + def to_tree(cls, longitude, ctx): + tree = super().to_tree(longitude, ctx) + tree['wrap_angle'] = custom_tree_to_tagged_tree(longitude.wrap_angle, ctx) + + return tree diff --git a/astropy/io/misc/asdf/tags/coordinates/frames.py b/astropy/io/misc/asdf/tags/coordinates/frames.py index 61cec2895c6..be1aba761f3 100644 --- a/astropy/io/misc/asdf/tags/coordinates/frames.py +++ b/astropy/io/misc/asdf/tags/coordinates/frames.py @@ -1,22 +1,128 @@ # Licensed under a 3-clause BSD style license - see LICENSE.rst # -*- coding: utf-8 -*- +import os +import glob +from asdf import tagged from asdf.yamlutil import custom_tree_to_tagged_tree +import astropy.coordinates +from astropy.coordinates.baseframe import frame_transform_graph +from astropy.tests.helper import assert_quantity_allclose from astropy.units import Quantity from astropy.coordinates import ICRS, Longitude, Latitude, Angle -from astropy.tests.helper import assert_quantity_allclose -from ...types import AstropyType from ..unit.quantity import QuantityType +from ...types import AstropyType + + +__all__ = ['CoordType'] + +SCHEMA_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), + '..', '..', + 'schemas', + 'astropy.org', + 'astropy')) + + +def _get_frames(): + """ + By reading the schema files, get the list of all the frames we can + save/load. + """ + search = os.path.join(SCHEMA_PATH, 'coordinates', 'frames', '*.yaml') + files = glob.glob(search) + + names = [] + for fpath in files: + path, fname = os.path.split(fpath) + frame, _ = fname.split('-') + # Skip baseframe because we cannot directly save / load it. + # Skip icrs because we have an explicit tag for it because there are + # two versions. + if frame not in ['baseframe', 'icrs']: + names.append(frame) + + return names + + +class BaseCoordType: + """ + This defines the base methods for coordinates, without defining anything + related to asdf types. This allows subclasses with different types and + schemas to use this without confusing the metaclass machinery. + """ + @staticmethod + def _tag_to_frame(tag): + """ + Extract the frame name from the tag. + """ + tag = tag[tag.rfind('/')+1:] + tag = tag[:tag.rfind('-')] + return frame_transform_graph.lookup_name(tag) + + @classmethod + def _frame_name_to_tag(cls, frame_name): + return cls.make_yaml_tag(cls._tag_prefix + frame_name) + + @classmethod + def from_tree_tagged(cls, node, ctx): + frame = cls._tag_to_frame(node._tag) -__all__ = ['ICRSCoordType'] + data = node.get('data', None) + if data is not None: + return frame(node['data'], **node['frame_attributes']) + return frame(**node['frame_attributes']) -class ICRSCoordType(AstropyType): + @classmethod + def to_tree_tagged(cls, frame, ctx): + if type(frame) not in frame_transform_graph.frame_set: + raise ValueError("Can only save frames that are registered with the " + "transformation graph.") + + node = {} + if frame.has_data: + node['data'] = custom_tree_to_tagged_tree(frame.data, ctx) + frame_attributes = {} + for attr in frame.frame_attributes.keys(): + value = getattr(frame, attr, None) + if value is not None: + frame_attributes[attr] = value + node['frame_attributes'] = custom_tree_to_tagged_tree(frame_attributes, ctx) + + return tagged.tag_object(cls._frame_name_to_tag(frame.name), node, ctx=ctx) + + @classmethod + def assert_equal(cls, old, new): + assert isinstance(new, type(old)) + if new.has_data: + assert_quantity_allclose(new.data.lon, old.data.lon) + assert_quantity_allclose(new.data.lat, old.data.lat) + + +class CoordType(BaseCoordType, AstropyType): + _tag_prefix = "coordinates/frames/" + name = ["coordinates/frames/" + f for f in _get_frames()] + types = [astropy.coordinates.BaseCoordinateFrame] + handle_dynamic_subclasses = True + requires = ['astropy'] + version = "1.0.0" + + +class ICRSType(CoordType): + """ + Define a special tag for ICRS so we can make it version 1.1.0. + """ name = "coordinates/frames/icrs" types = ['astropy.coordinates.ICRS'] + version = "1.1.0" + + +class ICRSType10(AstropyType): + name = "coordinates/frames/icrs" + types = [astropy.coordinates.ICRS] requires = ['astropy'] version = "1.0.0" diff --git a/astropy/io/misc/asdf/tags/coordinates/representation.py b/astropy/io/misc/asdf/tags/coordinates/representation.py new file mode 100644 index 00000000000..bfc4ff46e45 --- /dev/null +++ b/astropy/io/misc/asdf/tags/coordinates/representation.py @@ -0,0 +1,46 @@ +from asdf.yamlutil import custom_tree_to_tagged_tree + +import astropy.coordinates.representation +from astropy.coordinates.representation import BaseRepresentationOrDifferential +from astropy.tests.helper import assert_quantity_allclose + +from ...types import AstropyType + + +class RepresentationType(AstropyType): + name = "coordinates/representation" + types = [BaseRepresentationOrDifferential] + version = "1.0.0" + + _representation_module = astropy.coordinates.representation + + @classmethod + def to_tree(cls, representation, ctx): + comps = representation.components + components = {} + for c in comps: + value = getattr(representation, '_' + c, None) + if value is not None: + components[c] = value + + t = type(representation) + + node = {} + node['type'] = t.__name__ + node['components'] = custom_tree_to_tagged_tree(components, ctx) + + return node + + @classmethod + def from_tree(cls, node, ctx): + rep_type = getattr(cls._representation_module, node['type']) + return rep_type(**node['components']) + + @classmethod + def assert_equal(cls, old, new): + assert isinstance(new, type(old)) + assert new.components == old.components + for comp in new.components: + nc = getattr(new, comp) + oc = getattr(old, comp) + assert_quantity_allclose(nc, oc) diff --git a/astropy/io/misc/asdf/tags/coordinates/tests/test_angle.py b/astropy/io/misc/asdf/tags/coordinates/tests/test_angle.py new file mode 100644 index 00000000000..904f17da155 --- /dev/null +++ b/astropy/io/misc/asdf/tags/coordinates/tests/test_angle.py @@ -0,0 +1,29 @@ +# Licensed under a 3-clause BSD style license - see LICENSE.rst +# -*- coding: utf-8 -*- + +import pytest + +asdf = pytest.importorskip('asdf') + +import astropy.units as u + +from asdf.tests.helpers import assert_roundtrip_tree + +from astropy.coordinates import Longitude, Latitude, Angle + +from ....extension import AstropyExtension + + +def test_angle(tmpdir): + tree = {'angle': Angle(100, u.deg)} + assert_roundtrip_tree(tree, tmpdir) + + +def test_latitude(tmpdir): + tree = {'angle': Latitude(10, u.deg)} + assert_roundtrip_tree(tree, tmpdir) + + +def test_longitude(tmpdir): + tree = {'angle': Longitude(-100, u.deg, wrap_angle=180*u.deg)} + assert_roundtrip_tree(tree, tmpdir) diff --git a/astropy/io/misc/asdf/tags/coordinates/tests/test_coords.py b/astropy/io/misc/asdf/tags/coordinates/tests/test_frames.py similarity index 56% rename from astropy/io/misc/asdf/tags/coordinates/tests/test_coords.py rename to astropy/io/misc/asdf/tags/coordinates/tests/test_frames.py index 9dbcd8a6cb2..467aa2f4bb3 100644 --- a/astropy/io/misc/asdf/tags/coordinates/tests/test_coords.py +++ b/astropy/io/misc/asdf/tags/coordinates/tests/test_frames.py @@ -7,11 +7,20 @@ from asdf.tests.helpers import assert_roundtrip_tree from astropy import units -from astropy.coordinates import ICRS, Longitude, Latitude, Angle +from astropy.coordinates import ICRS, FK5, Longitude, Latitude, Angle from ....extension import AstropyExtension +def test_hcrs_basic(tmpdir): + ra = Longitude(25, unit=units.deg) + dec = Latitude(45, unit=units.deg) + + tree = {'coord': ICRS(ra=ra, dec=dec)} + + assert_roundtrip_tree(tree, tmpdir, extensions=AstropyExtension()) + + def test_icrs_basic(tmpdir): wrap_angle = Angle(1.5, unit=units.rad) ra = Longitude(25, unit=units.deg, wrap_angle=wrap_angle) @@ -22,8 +31,12 @@ def test_icrs_basic(tmpdir): assert_roundtrip_tree(tree, tmpdir, extensions=AstropyExtension()) -@pytest.mark.xfail( - reason="Compound ICRS coordinates have not been implemented for ASDF yet") +def test_icrs_nodata(tmpdir): + tree = {'coord': ICRS()} + + assert_roundtrip_tree(tree, tmpdir, extensions=AstropyExtension()) + + def test_icrs_compound(tmpdir): icrs = ICRS(ra=[0, 1, 2]*units.deg, dec=[3, 4, 5]*units.deg) @@ -31,3 +44,10 @@ def test_icrs_compound(tmpdir): tree = {'coord': icrs} assert_roundtrip_tree(tree, tmpdir, extensions=AstropyExtension()) + + +def test_fk5_time(tmpdir): + + tree = {'coord': FK5(equinox="2011-01-01T00:00:00")} + + assert_roundtrip_tree(tree, tmpdir, extensions=AstropyExtension()) diff --git a/astropy/io/misc/asdf/tags/coordinates/tests/test_representation.py b/astropy/io/misc/asdf/tags/coordinates/tests/test_representation.py new file mode 100644 index 00000000000..ae638ef3494 --- /dev/null +++ b/astropy/io/misc/asdf/tags/coordinates/tests/test_representation.py @@ -0,0 +1,38 @@ +# Licensed under a 3-clause BSD style license - see LICENSE.rst +# -*- coding: utf-8 -*- +import pytest + +from numpy.random import random, randint + +import astropy.units as u + +from astropy.coordinates import Angle +import astropy.coordinates.representation as r + +asdf = pytest.importorskip('asdf') +from asdf.tests.helpers import assert_roundtrip_tree + + +@pytest.fixture(params=filter(lambda x: "Base" not in x, r.__all__)) +def representation(request): + rep = getattr(r, request.param) + + angle_unit = u.deg + other_unit = u.km + + kwargs = {} + arr_len = randint(1, 100) + for aname, atype in rep.attr_classes.items(): + if issubclass(atype, Angle): + value = ([random()] * arr_len) * angle_unit + else: + value = ([random()] * arr_len) * other_unit + + kwargs[aname] = value + + return rep(**kwargs) + + +def test_representations(tmpdir, representation): + tree = {'representation': representation} + assert_roundtrip_tree(tree, tmpdir)