From d7bbee8540d6723fb622e9ffaaddb18ef2309421 Mon Sep 17 00:00:00 2001 From: ViciousEagle03 Date: Wed, 24 Jul 2024 21:15:31 +0530 Subject: [PATCH 1/3] Add converter and schema for basic astropy.wcs.WCS objects --- asdf_astropy/converters/__init__.py | 3 +- asdf_astropy/converters/fits/__init__.py | 2 + asdf_astropy/converters/fits/fitswcs.py | 29 +++++++++++++ .../converters/fits/tests/test_fitswcs.py | 41 +++++++++++++++++++ asdf_astropy/extensions.py | 2 + .../resources/manifests/astropy-1.0.0.yaml | 5 +++ .../resources/schemas/fits/fitswcs-1.0.0.yaml | 17 ++++++++ 7 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 asdf_astropy/converters/fits/fitswcs.py create mode 100644 asdf_astropy/converters/fits/tests/test_fitswcs.py create mode 100644 asdf_astropy/resources/schemas/fits/fitswcs-1.0.0.yaml diff --git a/asdf_astropy/converters/__init__.py b/asdf_astropy/converters/__init__.py index e18b0b0a..131ff5c2 100644 --- a/asdf_astropy/converters/__init__.py +++ b/asdf_astropy/converters/__init__.py @@ -15,6 +15,7 @@ "FitsConverter", "AsdfFitsConverter", "AstropyFitsConverter", + "FitsWCSConverter", "ColumnConverter", "AstropyTableConverter", "AsdfTableConverter", @@ -51,7 +52,7 @@ SkyCoordConverter, SpectralCoordConverter, ) -from .fits import AsdfFitsConverter, AstropyFitsConverter, FitsConverter +from .fits import AsdfFitsConverter, AstropyFitsConverter, FitsConverter, FitsWCSConverter from .table import AsdfTableConverter, AstropyTableConverter, ColumnConverter, NdarrayMixinConverter from .time import TimeConverter, TimeDeltaConverter from .transform import ( diff --git a/asdf_astropy/converters/fits/__init__.py b/asdf_astropy/converters/fits/__init__.py index 4647e59c..4f915659 100644 --- a/asdf_astropy/converters/fits/__init__.py +++ b/asdf_astropy/converters/fits/__init__.py @@ -2,6 +2,8 @@ "FitsConverter", "AsdfFitsConverter", "AstropyFitsConverter", + "FitsWCSConverter", ] from .fits import AsdfFitsConverter, AstropyFitsConverter, FitsConverter +from .fitswcs import FitsWCSConverter diff --git a/asdf_astropy/converters/fits/fitswcs.py b/asdf_astropy/converters/fits/fitswcs.py new file mode 100644 index 00000000..a01fde2c --- /dev/null +++ b/asdf_astropy/converters/fits/fitswcs.py @@ -0,0 +1,29 @@ +from asdf.extension import Converter + + +class FitsWCSConverter(Converter): + """ + Converter for serializing and deserializing `astropy.wcs.WCS` objects. + + This converter currently supports the serialization of simple WCS objects + by preserving the `wcs.to_header()` data. It does not support complex WCS objects + such as tabular or distortion WCSes. + + Future work: + - Until the support for tabular and distortion WCSes is added, throw error for such WCSes when passed through in the converter + - Implement mechanisms to detect tabular and distortion WCSes and support their serialization + """ + tags = ("tag:astropy.org:astropy/fits/fitswcs-*",) + types = ("astropy.wcs.wcs.WCS", ) + + def from_yaml_tree(self, node, tag, ctx): + from astropy.wcs import WCS + + header = node["header"] + wcs = WCS(header) + return wcs + + def to_yaml_tree(self, wcs, tag, ctx): + node = {} + node["header"] = dict(wcs.to_header()) + return node diff --git a/asdf_astropy/converters/fits/tests/test_fitswcs.py b/asdf_astropy/converters/fits/tests/test_fitswcs.py new file mode 100644 index 00000000..3cedc02e --- /dev/null +++ b/asdf_astropy/converters/fits/tests/test_fitswcs.py @@ -0,0 +1,41 @@ +import asdf +import pytest +from astropy.wcs import WCS + + +def create_wcs(): + header = { + 'CTYPE1': 'TIME', + 'CUNIT1': 'min', + 'CDELT1': 0.4, + 'CRPIX1': 0, + 'CRVAL1': 0, + 'CTYPE2': 'WAVE', + 'CUNIT2': 'Angstrom', + 'CDELT2': 0.2, + 'CRPIX2': 0, + 'CRVAL2': 0, + 'CTYPE3': 'HPLT-TAN', + 'CUNIT3': 'arcsec', + 'CDELT3': 20, + 'CRPIX3': 0, + 'CRVAL3': 0, + 'CTYPE4': 'HPLN-TAN', + 'CUNIT4': 'arcsec', + 'CDELT4': 5, + 'CRPIX4': 5, + 'CRVAL4': 0, + } + return WCS(header) + +@pytest.mark.parametrize("wcs", [create_wcs()]) +def test_wcs_serialization(wcs, tmp_path): + file_path = tmp_path / "test_wcs.asdf" + with asdf.AsdfFile() as af: + af["wcs"] = wcs + af.write_to(file_path) + + with asdf.open(file_path) as af: + loaded_wcs = af["wcs"] + + assert wcs.to_header() == loaded_wcs.to_header() diff --git a/asdf_astropy/extensions.py b/asdf_astropy/extensions.py index bace370e..51ff0317 100644 --- a/asdf_astropy/extensions.py +++ b/asdf_astropy/extensions.py @@ -13,6 +13,7 @@ from .converters.coordinates.sky_coord import SkyCoordConverter from .converters.coordinates.spectral_coord import SpectralCoordConverter from .converters.fits.fits import AsdfFitsConverter, AstropyFitsConverter +from .converters.fits.fitswcs import FitsWCSConverter from .converters.table.table import AsdfTableConverter, AstropyTableConverter, ColumnConverter, NdarrayMixinConverter from .converters.time.time import TimeConverter from .converters.time.time_delta import TimeDeltaConverter @@ -482,6 +483,7 @@ AstropyTableConverter(), AstropyFitsConverter(), NdarrayMixinConverter(), + FitsWCSConverter(), ] _COORDINATES_MANIFEST_URIS = [ diff --git a/asdf_astropy/resources/manifests/astropy-1.0.0.yaml b/asdf_astropy/resources/manifests/astropy-1.0.0.yaml index 4f6d25b7..c7eba75d 100644 --- a/asdf_astropy/resources/manifests/astropy-1.0.0.yaml +++ b/asdf_astropy/resources/manifests/astropy-1.0.0.yaml @@ -28,6 +28,11 @@ tags: be accessible in its proper form in the ASDF file. Only image and binary table extensions are supported. +- tag_uri: tag:astropy.org:astropy/fits/fitswcs-1.0.0 + schema_uri: http://astropy.org/schemas/astropy/fits/fitswcs-1.0.0 + title: Represents an astropy.wcs.WCS object + description: |- + Supports serialization of the simple wcs objects header - tag_uri: tag:astropy.org:astropy/table/table-1.0.0 schema_uri: http://astropy.org/schemas/astropy/table/table-1.0.0 title: A table. diff --git a/asdf_astropy/resources/schemas/fits/fitswcs-1.0.0.yaml b/asdf_astropy/resources/schemas/fits/fitswcs-1.0.0.yaml new file mode 100644 index 00000000..86a15ad2 --- /dev/null +++ b/asdf_astropy/resources/schemas/fits/fitswcs-1.0.0.yaml @@ -0,0 +1,17 @@ +%YAML 1.1 +--- +$schema: "http://stsci.edu/schemas/yaml-schema/draft-01" +id: "http://astropy.org/schemas/astropy/fits/fitswcs-1.0.0" + +title: + Represents the fits object + +description: + Represents the fits object + +allOf: + - tag: "tag:astropy.org:astropy/fits/fitswcs-1.0.0" + - type: object + properties: + header: + type: object \ No newline at end of file From 11f1b272114570673376fb2dbdbee051fabc5bd9 Mon Sep 17 00:00:00 2001 From: ViciousEagle03 Date: Wed, 24 Jul 2024 22:15:06 +0530 Subject: [PATCH 2/3] Style Fix --- asdf_astropy/converters/fits/fitswcs.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/asdf_astropy/converters/fits/fitswcs.py b/asdf_astropy/converters/fits/fitswcs.py index a01fde2c..63a50d7c 100644 --- a/asdf_astropy/converters/fits/fitswcs.py +++ b/asdf_astropy/converters/fits/fitswcs.py @@ -10,18 +10,19 @@ class FitsWCSConverter(Converter): such as tabular or distortion WCSes. Future work: - - Until the support for tabular and distortion WCSes is added, throw error for such WCSes when passed through in the converter + - Until the support for tabular and distortion WCSes is added, + throw error for such WCSes when passed through in the converter - Implement mechanisms to detect tabular and distortion WCSes and support their serialization """ + tags = ("tag:astropy.org:astropy/fits/fitswcs-*",) - types = ("astropy.wcs.wcs.WCS", ) + types = ("astropy.wcs.wcs.WCS",) def from_yaml_tree(self, node, tag, ctx): from astropy.wcs import WCS header = node["header"] - wcs = WCS(header) - return wcs + return WCS(header) def to_yaml_tree(self, wcs, tag, ctx): node = {} From ff1c9cec95030bbdb706305ee02a5bd5892b9f20 Mon Sep 17 00:00:00 2001 From: ViciousEagle03 Date: Thu, 25 Jul 2024 00:10:07 +0530 Subject: [PATCH 3/3] remove outdated version check --- .../transform/tests/test_transform.py | 29 ++++++++----------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/asdf_astropy/converters/transform/tests/test_transform.py b/asdf_astropy/converters/transform/tests/test_transform.py index 6c7790b3..137a5ac9 100644 --- a/asdf_astropy/converters/transform/tests/test_transform.py +++ b/asdf_astropy/converters/transform/tests/test_transform.py @@ -77,24 +77,19 @@ def create_bounding_boxes(): astropy_models.Polynomial2D(1), [("x", False)], ), + CompoundBoundingBox( + {(1,): (0, 1), (2,): (2, 3)}, + astropy_models.Polynomial2D(1), + [("x", False)], + ignored=["x"], + ), + CompoundBoundingBox( + {(1,): (0, 1), (2,): (2, 3)}, + astropy_models.Polynomial2D(1), + [("x", False)], + ignored=["y"], + ), ] - if minversion("astropy", "5.1"): - compound_bounding_box.extend( - [ - CompoundBoundingBox( - {(1,): (0, 1), (2,): (2, 3)}, - astropy_models.Polynomial2D(1), - [("x", False)], - ignored=["x"], - ), - CompoundBoundingBox( - {(1,): (0, 1), (2,): (2, 3)}, - astropy_models.Polynomial2D(1), - [("x", False)], - ignored=["y"], - ), - ], - ) return model_bounding_box + compound_bounding_box