From d7bbee8540d6723fb622e9ffaaddb18ef2309421 Mon Sep 17 00:00:00 2001 From: ViciousEagle03 Date: Wed, 24 Jul 2024 21:15:31 +0530 Subject: [PATCH 01/17] 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 02/17] 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 faa868056c71ae896599b18738526e623d17867d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 4 Aug 2024 19:46:39 +0000 Subject: [PATCH 03/17] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- .../converters/fits/tests/test_fitswcs.py | 41 ++++++++++--------- .../resources/schemas/fits/fitswcs-1.0.0.yaml | 2 +- 2 files changed, 22 insertions(+), 21 deletions(-) diff --git a/asdf_astropy/converters/fits/tests/test_fitswcs.py b/asdf_astropy/converters/fits/tests/test_fitswcs.py index 3cedc02e..7d08fbee 100644 --- a/asdf_astropy/converters/fits/tests/test_fitswcs.py +++ b/asdf_astropy/converters/fits/tests/test_fitswcs.py @@ -5,29 +5,30 @@ 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, + "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" diff --git a/asdf_astropy/resources/schemas/fits/fitswcs-1.0.0.yaml b/asdf_astropy/resources/schemas/fits/fitswcs-1.0.0.yaml index 86a15ad2..4f020b08 100644 --- a/asdf_astropy/resources/schemas/fits/fitswcs-1.0.0.yaml +++ b/asdf_astropy/resources/schemas/fits/fitswcs-1.0.0.yaml @@ -14,4 +14,4 @@ allOf: - type: object properties: header: - type: object \ No newline at end of file + type: object From 5e830f1127799baa30f95f958e77cae9f3fe92dc Mon Sep 17 00:00:00 2001 From: ViciousEagle03 Date: Wed, 7 Aug 2024 21:54:13 +0530 Subject: [PATCH 04/17] Add SlicedLowLevelWCS serialization logic --- asdf_astropy/converters/slicedwcs/__init__.py | 5 +++ .../converters/slicedwcs/slicedwcs.py | 36 +++++++++++++++++++ .../converters/slicedwcs/test/__init__.py | 0 .../slicedwcs/test/test_slicedwcs.py | 34 ++++++++++++++++++ asdf_astropy/extensions.py | 2 ++ .../resources/manifests/astropy-1.0.0.yaml | 5 +++ .../schemas/slicedwcs/slicedwcs-1.0.0.yaml | 19 ++++++++++ 7 files changed, 101 insertions(+) create mode 100644 asdf_astropy/converters/slicedwcs/__init__.py create mode 100644 asdf_astropy/converters/slicedwcs/slicedwcs.py create mode 100644 asdf_astropy/converters/slicedwcs/test/__init__.py create mode 100644 asdf_astropy/converters/slicedwcs/test/test_slicedwcs.py create mode 100644 asdf_astropy/resources/schemas/slicedwcs/slicedwcs-1.0.0.yaml diff --git a/asdf_astropy/converters/slicedwcs/__init__.py b/asdf_astropy/converters/slicedwcs/__init__.py new file mode 100644 index 00000000..8473b67e --- /dev/null +++ b/asdf_astropy/converters/slicedwcs/__init__.py @@ -0,0 +1,5 @@ +__all__ = [ + "SlicedWCSConverter", +] + +from .slicedwcs import SlicedWCSConverter diff --git a/asdf_astropy/converters/slicedwcs/slicedwcs.py b/asdf_astropy/converters/slicedwcs/slicedwcs.py new file mode 100644 index 00000000..e4745211 --- /dev/null +++ b/asdf_astropy/converters/slicedwcs/slicedwcs.py @@ -0,0 +1,36 @@ +import ast + +from asdf.extension import Converter + + +class SlicedWCSConverter(Converter): + tags = ("tag:astropy.org:astropy/slicedwcs/slicedwcs-*",) + types = ("astropy.wcs.wcsapi.wrappers.sliced_wcs.SlicedLowLevelWCS",) + + def parse_slice_string(self, slice_str): + if slice_str.isdigit(): + return int(ast.literal_eval(slice_str)) + slice_str = slice_str[len("slice(") : -1] + parts = slice_str.split(",") + start = ast.literal_eval(parts[0].strip()) + stop = ast.literal_eval(parts[1].strip()) + step = ast.literal_eval(parts[2].strip()) + return slice(start, stop, step) + + def from_yaml_tree(self, node, tag, ctx): + from astropy.wcs.wcsapi.wrappers.sliced_wcs import SlicedLowLevelWCS + + wcs = node["wcs"] + slice_array = node["slices_array"] + slice_array = [self.parse_slice_string(s) for s in slice_array] + + return SlicedLowLevelWCS(wcs, slice_array) + + def to_yaml_tree(self, sl, tag, ctx): + import astropy + + node = {} + if isinstance(sl._wcs, astropy.wcs.WCS): + node["wcs"] = sl._wcs + node["slices_array"] = [str(item) for item in sl._slices_array] + return node diff --git a/asdf_astropy/converters/slicedwcs/test/__init__.py b/asdf_astropy/converters/slicedwcs/test/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/asdf_astropy/converters/slicedwcs/test/test_slicedwcs.py b/asdf_astropy/converters/slicedwcs/test/test_slicedwcs.py new file mode 100644 index 00000000..3106c622 --- /dev/null +++ b/asdf_astropy/converters/slicedwcs/test/test_slicedwcs.py @@ -0,0 +1,34 @@ +import asdf +import numpy as np +import pytest +from astropy.wcs import WCS +from astropy.wcs.wcsapi.wrappers.sliced_wcs import SlicedLowLevelWCS + + +def create_wcs(): + wcs = WCS(naxis=4) + wcs.wcs.ctype = "RA---CAR", "DEC--CAR", "FREQ", "TIME" + wcs.wcs.cunit = "deg", "deg", "Hz", "s" + wcs.wcs.cdelt = -2.0, 2.0, 3.0e9, 1 + wcs.wcs.crval = 4.0, 0.0, 4.0e9, 3 + wcs.wcs.crpix = 6.0, 7.0, 11.0, 11.0 + wcs.wcs.cname = "Right Ascension", "Declination", "Frequency", "Time" + wcs0 = SlicedLowLevelWCS(wcs, 1) + wcs1 = SlicedLowLevelWCS(wcs, [slice(None), slice(None), slice(None), 10]) + wcs3 = SlicedLowLevelWCS(SlicedLowLevelWCS(wcs, slice(None)), [slice(3), slice(None), slice(None), 10]) + wcs_ellipsis = SlicedLowLevelWCS(wcs, [Ellipsis, slice(5, 10)]) + wcs2 = SlicedLowLevelWCS(wcs, np.s_[:, 2, 3, :]) + return [wcs0, wcs1, wcs2, wcs_ellipsis, wcs3] + + +@pytest.mark.parametrize("sl_wcs", create_wcs()) +def test_sliced_wcs_serialization(sl_wcs, tmp_path): + file_path = tmp_path / "test_slicedwcs.asdf" + with asdf.AsdfFile() as af: + af["sl_wcs"] = sl_wcs + af.write_to(file_path) + + with asdf.open(file_path) as af: + loaded_sl_wcs = af["sl_wcs"] + assert sl_wcs._wcs.to_header() == loaded_sl_wcs._wcs.to_header() + assert sl_wcs._slices_array == loaded_sl_wcs._slices_array diff --git a/asdf_astropy/extensions.py b/asdf_astropy/extensions.py index 51ff0317..71504673 100644 --- a/asdf_astropy/extensions.py +++ b/asdf_astropy/extensions.py @@ -14,6 +14,7 @@ from .converters.coordinates.spectral_coord import SpectralCoordConverter from .converters.fits.fits import AsdfFitsConverter, AstropyFitsConverter from .converters.fits.fitswcs import FitsWCSConverter +from .converters.slicedwcs.slicedwcs import SlicedWCSConverter from .converters.table.table import AsdfTableConverter, AstropyTableConverter, ColumnConverter, NdarrayMixinConverter from .converters.time.time import TimeConverter from .converters.time.time_delta import TimeDeltaConverter @@ -484,6 +485,7 @@ AstropyFitsConverter(), NdarrayMixinConverter(), FitsWCSConverter(), + SlicedWCSConverter(), ] _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 c7eba75d..2c37a76d 100644 --- a/asdf_astropy/resources/manifests/astropy-1.0.0.yaml +++ b/asdf_astropy/resources/manifests/astropy-1.0.0.yaml @@ -33,6 +33,11 @@ tags: title: Represents an astropy.wcs.WCS object description: |- Supports serialization of the simple wcs objects header +- tag_uri: tag:astropy.org:astropy/slicedwcs/slicedwcs-1.0.0 + schema_uri: http://astropy.org/schemas/astropy/slicedwcs/slicedwcs-1.0.0 + title: Represents a SlicedLowLevelWCS object + description: |- + Supports serialization of the sliced_wcs objects - 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/slicedwcs/slicedwcs-1.0.0.yaml b/asdf_astropy/resources/schemas/slicedwcs/slicedwcs-1.0.0.yaml new file mode 100644 index 00000000..622f9a0d --- /dev/null +++ b/asdf_astropy/resources/schemas/slicedwcs/slicedwcs-1.0.0.yaml @@ -0,0 +1,19 @@ +%YAML 1.1 +--- +$schema: "http://stsci.edu/schemas/yaml-schema/draft-01" +id: "http://astropy.org/schemas/astropy/slicedwcs/slicedwcs-1.0.0" + +title: + Represents the SlicedLowLevelWCS object + +description: + Represents the SlicedLowLevelWCS object + +allOf: + - tag: "tag:astropy.org:astropy/slicedwcs/slicedwcs-1.0.0" + - type: object + properties: + wcs: + tag: "tag:astropy.org:astropy/fits/fitswcs-1.0.0" + slices_array: + type: array From 9d27051a62d54e6569507934d53f3ab78884fc7f Mon Sep 17 00:00:00 2001 From: ViciousEagle03 Date: Wed, 7 Aug 2024 22:04:53 +0530 Subject: [PATCH 05/17] Remove unnecessary check --- asdf_astropy/converters/slicedwcs/slicedwcs.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/asdf_astropy/converters/slicedwcs/slicedwcs.py b/asdf_astropy/converters/slicedwcs/slicedwcs.py index e4745211..d3ee5e6c 100644 --- a/asdf_astropy/converters/slicedwcs/slicedwcs.py +++ b/asdf_astropy/converters/slicedwcs/slicedwcs.py @@ -27,10 +27,7 @@ def from_yaml_tree(self, node, tag, ctx): return SlicedLowLevelWCS(wcs, slice_array) def to_yaml_tree(self, sl, tag, ctx): - import astropy - node = {} - if isinstance(sl._wcs, astropy.wcs.WCS): - node["wcs"] = sl._wcs + node["wcs"] = sl._wcs node["slices_array"] = [str(item) for item in sl._slices_array] return node From 66904fc1de9617660a75c0f77c176b74930c6583 Mon Sep 17 00:00:00 2001 From: ViciousEagle03 Date: Sat, 24 Aug 2024 04:56:30 +0530 Subject: [PATCH 06/17] Apply suggestions from code review --- asdf_astropy/converters/fits/fitswcs.py | 19 ++----- .../converters/fits/tests/test_fitswcs.py | 51 ++++++++----------- .../converters/slicedwcs/slicedwcs.py | 33 ++++++------ .../slicedwcs/test/test_slicedwcs.py | 17 ++++--- .../resources/manifests/astropy-1.0.0.yaml | 10 ---- .../resources/manifests/astropy-1.1.0.yaml | 17 +++++++ .../resources/schemas/fits/fitswcs-1.0.0.yaml | 5 +- .../schemas/slicedwcs/slicedwcs-1.0.0.yaml | 6 +++ 8 files changed, 77 insertions(+), 81 deletions(-) diff --git a/asdf_astropy/converters/fits/fitswcs.py b/asdf_astropy/converters/fits/fitswcs.py index 63a50d7c..2db29661 100644 --- a/asdf_astropy/converters/fits/fitswcs.py +++ b/asdf_astropy/converters/fits/fitswcs.py @@ -2,29 +2,16 @@ 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"] - return WCS(header) + primary_hdu = node["Hdu"][0] + return WCS(primary_hdu.header) def to_yaml_tree(self, wcs, tag, ctx): node = {} - node["header"] = dict(wcs.to_header()) + node["Hdu"] = wcs.to_fits() return node diff --git a/asdf_astropy/converters/fits/tests/test_fitswcs.py b/asdf_astropy/converters/fits/tests/test_fitswcs.py index 7d08fbee..69dd9624 100644 --- a/asdf_astropy/converters/fits/tests/test_fitswcs.py +++ b/asdf_astropy/converters/fits/tests/test_fitswcs.py @@ -1,42 +1,33 @@ +import warnings + import asdf import pytest -from astropy.wcs import WCS +from astropy.io import fits +from astropy.utils.data import download_file +from astropy.wcs import WCS, FITSFixedWarning 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) + urls = [ + "http://data.astropy.org/tutorials/FITS-cubes/reduced_TAN_C14.fits", + "http://data.astropy.org/tutorials/FITS-images/HorseHead.fits", + ] + + with warnings.catch_warnings(): + warnings.simplefilter("ignore", FITSFixedWarning) + return [WCS(fits.open(download_file(url, cache=True))[0].header) for url in urls] -@pytest.mark.parametrize("wcs", [create_wcs()]) +@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: + with asdf.AsdfFile() as af, warnings.catch_warnings(): + warnings.simplefilter("ignore", FITSFixedWarning) 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() + with warnings.catch_warnings(): + warnings.simplefilter("ignore", FITSFixedWarning) + with asdf.open(file_path) as af: + loaded_wcs = af["wcs"] + assert wcs.to_header() == loaded_wcs.to_header() diff --git a/asdf_astropy/converters/slicedwcs/slicedwcs.py b/asdf_astropy/converters/slicedwcs/slicedwcs.py index d3ee5e6c..404a6d3d 100644 --- a/asdf_astropy/converters/slicedwcs/slicedwcs.py +++ b/asdf_astropy/converters/slicedwcs/slicedwcs.py @@ -1,5 +1,3 @@ -import ast - from asdf.extension import Converter @@ -7,27 +5,30 @@ class SlicedWCSConverter(Converter): tags = ("tag:astropy.org:astropy/slicedwcs/slicedwcs-*",) types = ("astropy.wcs.wcsapi.wrappers.sliced_wcs.SlicedLowLevelWCS",) - def parse_slice_string(self, slice_str): - if slice_str.isdigit(): - return int(ast.literal_eval(slice_str)) - slice_str = slice_str[len("slice(") : -1] - parts = slice_str.split(",") - start = ast.literal_eval(parts[0].strip()) - stop = ast.literal_eval(parts[1].strip()) - step = ast.literal_eval(parts[2].strip()) - return slice(start, stop, step) - def from_yaml_tree(self, node, tag, ctx): from astropy.wcs.wcsapi.wrappers.sliced_wcs import SlicedLowLevelWCS wcs = node["wcs"] - slice_array = node["slices_array"] - slice_array = [self.parse_slice_string(s) for s in slice_array] - + slice_array = [] + slice_array = [ + s if isinstance(s, int) else slice(s["start"], s["stop"], s["step"]) for s in node["slices_array"] + ] return SlicedLowLevelWCS(wcs, slice_array) def to_yaml_tree(self, sl, tag, ctx): node = {} node["wcs"] = sl._wcs - node["slices_array"] = [str(item) for item in sl._slices_array] + node["slices_array"] = [] + + for s in sl._slices_array: + if isinstance(s, slice): + node["slices_array"].append( + { + "start": s.start if s.start is not None else None, + "stop": s.stop if s.stop is not None else None, + "step": s.step if s.step is not None else None, + }, + ) + else: + node["slices_array"].append(s) return node diff --git a/asdf_astropy/converters/slicedwcs/test/test_slicedwcs.py b/asdf_astropy/converters/slicedwcs/test/test_slicedwcs.py index 3106c622..f5d5d046 100644 --- a/asdf_astropy/converters/slicedwcs/test/test_slicedwcs.py +++ b/asdf_astropy/converters/slicedwcs/test/test_slicedwcs.py @@ -1,7 +1,9 @@ +import warnings + import asdf import numpy as np import pytest -from astropy.wcs import WCS +from astropy.wcs import WCS, FITSFixedWarning from astropy.wcs.wcsapi.wrappers.sliced_wcs import SlicedLowLevelWCS @@ -24,11 +26,14 @@ def create_wcs(): @pytest.mark.parametrize("sl_wcs", create_wcs()) def test_sliced_wcs_serialization(sl_wcs, tmp_path): file_path = tmp_path / "test_slicedwcs.asdf" - with asdf.AsdfFile() as af: + with asdf.AsdfFile() as af, warnings.catch_warnings(): + warnings.simplefilter("ignore", FITSFixedWarning) af["sl_wcs"] = sl_wcs af.write_to(file_path) - with asdf.open(file_path) as af: - loaded_sl_wcs = af["sl_wcs"] - assert sl_wcs._wcs.to_header() == loaded_sl_wcs._wcs.to_header() - assert sl_wcs._slices_array == loaded_sl_wcs._slices_array + with warnings.catch_warnings(): + warnings.simplefilter("ignore", FITSFixedWarning) + with asdf.open(file_path) as af: + loaded_sl_wcs = af["sl_wcs"] + assert sl_wcs._wcs.to_header() == loaded_sl_wcs._wcs.to_header() + assert sl_wcs._slices_array == loaded_sl_wcs._slices_array diff --git a/asdf_astropy/resources/manifests/astropy-1.0.0.yaml b/asdf_astropy/resources/manifests/astropy-1.0.0.yaml index 2c37a76d..4f6d25b7 100644 --- a/asdf_astropy/resources/manifests/astropy-1.0.0.yaml +++ b/asdf_astropy/resources/manifests/astropy-1.0.0.yaml @@ -28,16 +28,6 @@ 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/slicedwcs/slicedwcs-1.0.0 - schema_uri: http://astropy.org/schemas/astropy/slicedwcs/slicedwcs-1.0.0 - title: Represents a SlicedLowLevelWCS object - description: |- - Supports serialization of the sliced_wcs objects - 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/manifests/astropy-1.1.0.yaml b/asdf_astropy/resources/manifests/astropy-1.1.0.yaml index 9e8094a9..49e26253 100644 --- a/asdf_astropy/resources/manifests/astropy-1.1.0.yaml +++ b/asdf_astropy/resources/manifests/astropy-1.1.0.yaml @@ -54,3 +54,20 @@ tags: title: NdarrayMixin column. description: |- Represents an astropy.table.NdarrayMixin instance. +- tag_uri: tag:astropy.org:astropy/slicedwcs/slicedwcs-1.0.0 + schema_uri: http://astropy.org/schemas/astropy/slicedwcs/slicedwcs-1.0.0 + title: Represents an instance of SlicedLowLevelWCS + description: |- + The SlicedLowLevelWCS class is a wrapper class for WCS that applies slices + to the WCS, allowing certain pixel and world dimensions to be retained or + dropped. + + It manages the slicing and coordinate transformations while preserving + the underlying WCS object. +- tag_uri: tag:astropy.org:astropy/fits/fitswcs-1.0.0 + schema_uri: http://astropy.org/schemas/astropy/fits/fitswcs-1.0.0 + title: FITS WCS (World Coordinate System) Converter + description: |- + Represents the FITS WCS object, the HDUlist of the FITS header is preserved + during serialization and during deserialization the WCS object is recreated + from the HDUlist. diff --git a/asdf_astropy/resources/schemas/fits/fitswcs-1.0.0.yaml b/asdf_astropy/resources/schemas/fits/fitswcs-1.0.0.yaml index 4f020b08..32617c40 100644 --- a/asdf_astropy/resources/schemas/fits/fitswcs-1.0.0.yaml +++ b/asdf_astropy/resources/schemas/fits/fitswcs-1.0.0.yaml @@ -10,8 +10,7 @@ description: Represents the fits object allOf: - - tag: "tag:astropy.org:astropy/fits/fitswcs-1.0.0" - type: object properties: - header: - type: object + hdu: + tag: "tag:stsci.edu:asdf/fits/fits-*" diff --git a/asdf_astropy/resources/schemas/slicedwcs/slicedwcs-1.0.0.yaml b/asdf_astropy/resources/schemas/slicedwcs/slicedwcs-1.0.0.yaml index 622f9a0d..8db22487 100644 --- a/asdf_astropy/resources/schemas/slicedwcs/slicedwcs-1.0.0.yaml +++ b/asdf_astropy/resources/schemas/slicedwcs/slicedwcs-1.0.0.yaml @@ -17,3 +17,9 @@ allOf: tag: "tag:astropy.org:astropy/fits/fitswcs-1.0.0" slices_array: type: array + items: + - oneOf: + - type: integer + - type: object + + required: ["wcs", "slices_array"] From a6efc4f045dbf80267a4090fa0c91bbbbfaf748f Mon Sep 17 00:00:00 2001 From: ViciousEagle03 Date: Sat, 24 Aug 2024 05:17:18 +0530 Subject: [PATCH 07/17] Update schema for fitswcs and slicedwcs instance --- asdf_astropy/resources/schemas/fits/fitswcs-1.0.0.yaml | 2 ++ .../resources/schemas/slicedwcs/slicedwcs-1.0.0.yaml | 5 ++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/asdf_astropy/resources/schemas/fits/fitswcs-1.0.0.yaml b/asdf_astropy/resources/schemas/fits/fitswcs-1.0.0.yaml index 32617c40..08827d9f 100644 --- a/asdf_astropy/resources/schemas/fits/fitswcs-1.0.0.yaml +++ b/asdf_astropy/resources/schemas/fits/fitswcs-1.0.0.yaml @@ -14,3 +14,5 @@ allOf: properties: hdu: tag: "tag:stsci.edu:asdf/fits/fits-*" + + required: ["hdu"] diff --git a/asdf_astropy/resources/schemas/slicedwcs/slicedwcs-1.0.0.yaml b/asdf_astropy/resources/schemas/slicedwcs/slicedwcs-1.0.0.yaml index 8db22487..8116c865 100644 --- a/asdf_astropy/resources/schemas/slicedwcs/slicedwcs-1.0.0.yaml +++ b/asdf_astropy/resources/schemas/slicedwcs/slicedwcs-1.0.0.yaml @@ -10,11 +10,10 @@ description: Represents the SlicedLowLevelWCS object allOf: - - tag: "tag:astropy.org:astropy/slicedwcs/slicedwcs-1.0.0" - type: object properties: wcs: - tag: "tag:astropy.org:astropy/fits/fitswcs-1.0.0" + tag: "tag:astropy.org:astropy/fits/fitswcs-1*" slices_array: type: array items: @@ -22,4 +21,4 @@ allOf: - type: integer - type: object - required: ["wcs", "slices_array"] + required: ["wcs", "slices_array"] From 1f492ac477f67fcb878e6526a9493d4a992e1be6 Mon Sep 17 00:00:00 2001 From: ViciousEagle03 Date: Sun, 25 Aug 2024 15:12:34 +0530 Subject: [PATCH 08/17] Fix tests and schema --- asdf_astropy/converters/fits/fitswcs.py | 4 ++-- .../converters/fits/tests/test_fitswcs.py | 12 +++++------- .../slicedwcs/test/test_slicedwcs.py | 18 +++++++----------- .../resources/schemas/fits/fitswcs-1.0.0.yaml | 4 ++-- .../schemas/slicedwcs/slicedwcs-1.0.0.yaml | 2 +- 5 files changed, 17 insertions(+), 23 deletions(-) diff --git a/asdf_astropy/converters/fits/fitswcs.py b/asdf_astropy/converters/fits/fitswcs.py index 2db29661..403af7bd 100644 --- a/asdf_astropy/converters/fits/fitswcs.py +++ b/asdf_astropy/converters/fits/fitswcs.py @@ -8,10 +8,10 @@ class FitsWCSConverter(Converter): def from_yaml_tree(self, node, tag, ctx): from astropy.wcs import WCS - primary_hdu = node["Hdu"][0] + primary_hdu = node["hdu"][0] return WCS(primary_hdu.header) def to_yaml_tree(self, wcs, tag, ctx): node = {} - node["Hdu"] = wcs.to_fits() + node["hdu"] = wcs.to_fits() return node diff --git a/asdf_astropy/converters/fits/tests/test_fitswcs.py b/asdf_astropy/converters/fits/tests/test_fitswcs.py index 69dd9624..70c183ef 100644 --- a/asdf_astropy/converters/fits/tests/test_fitswcs.py +++ b/asdf_astropy/converters/fits/tests/test_fitswcs.py @@ -18,16 +18,14 @@ def create_wcs(): return [WCS(fits.open(download_file(url, cache=True))[0].header) for url in urls] +@pytest.mark.filterwarnings("ignore::astropy.wcs.wcs.FITSFixedWarning") @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, warnings.catch_warnings(): - warnings.simplefilter("ignore", FITSFixedWarning) + with asdf.AsdfFile() as af: af["wcs"] = wcs af.write_to(file_path) - with warnings.catch_warnings(): - warnings.simplefilter("ignore", FITSFixedWarning) - with asdf.open(file_path) as af: - loaded_wcs = af["wcs"] - assert wcs.to_header() == loaded_wcs.to_header() + with asdf.open(file_path) as af: + loaded_wcs = af["wcs"] + assert wcs.to_header() == loaded_wcs.to_header() diff --git a/asdf_astropy/converters/slicedwcs/test/test_slicedwcs.py b/asdf_astropy/converters/slicedwcs/test/test_slicedwcs.py index f5d5d046..5b09c375 100644 --- a/asdf_astropy/converters/slicedwcs/test/test_slicedwcs.py +++ b/asdf_astropy/converters/slicedwcs/test/test_slicedwcs.py @@ -1,9 +1,7 @@ -import warnings - import asdf import numpy as np import pytest -from astropy.wcs import WCS, FITSFixedWarning +from astropy.wcs import WCS from astropy.wcs.wcsapi.wrappers.sliced_wcs import SlicedLowLevelWCS @@ -23,17 +21,15 @@ def create_wcs(): return [wcs0, wcs1, wcs2, wcs_ellipsis, wcs3] +@pytest.mark.filterwarnings("ignore::astropy.wcs.wcs.FITSFixedWarning") @pytest.mark.parametrize("sl_wcs", create_wcs()) def test_sliced_wcs_serialization(sl_wcs, tmp_path): file_path = tmp_path / "test_slicedwcs.asdf" - with asdf.AsdfFile() as af, warnings.catch_warnings(): - warnings.simplefilter("ignore", FITSFixedWarning) + with asdf.AsdfFile() as af: af["sl_wcs"] = sl_wcs af.write_to(file_path) - with warnings.catch_warnings(): - warnings.simplefilter("ignore", FITSFixedWarning) - with asdf.open(file_path) as af: - loaded_sl_wcs = af["sl_wcs"] - assert sl_wcs._wcs.to_header() == loaded_sl_wcs._wcs.to_header() - assert sl_wcs._slices_array == loaded_sl_wcs._slices_array + with asdf.open(file_path) as af: + loaded_sl_wcs = af["sl_wcs"] + assert sl_wcs._wcs.to_header() == loaded_sl_wcs._wcs.to_header() + assert sl_wcs._slices_array == loaded_sl_wcs._slices_array diff --git a/asdf_astropy/resources/schemas/fits/fitswcs-1.0.0.yaml b/asdf_astropy/resources/schemas/fits/fitswcs-1.0.0.yaml index 08827d9f..8147aea0 100644 --- a/asdf_astropy/resources/schemas/fits/fitswcs-1.0.0.yaml +++ b/asdf_astropy/resources/schemas/fits/fitswcs-1.0.0.yaml @@ -13,6 +13,6 @@ allOf: - type: object properties: hdu: - tag: "tag:stsci.edu:asdf/fits/fits-*" + tag: "tag:astropy.org:astropy/fits/fits-*" - required: ["hdu"] + required: ["hdu"] diff --git a/asdf_astropy/resources/schemas/slicedwcs/slicedwcs-1.0.0.yaml b/asdf_astropy/resources/schemas/slicedwcs/slicedwcs-1.0.0.yaml index 8116c865..4215b6a5 100644 --- a/asdf_astropy/resources/schemas/slicedwcs/slicedwcs-1.0.0.yaml +++ b/asdf_astropy/resources/schemas/slicedwcs/slicedwcs-1.0.0.yaml @@ -21,4 +21,4 @@ allOf: - type: integer - type: object - required: ["wcs", "slices_array"] + required: ["wcs", "slices_array"] From 4f786807f28e68f6a1c5b7f11102ddfc4adaa266 Mon Sep 17 00:00:00 2001 From: ViciousEagle03 Date: Sun, 25 Aug 2024 15:25:15 +0530 Subject: [PATCH 09/17] Add changelog --- CHANGES.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index e038477c..bbbca7e8 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -8,6 +8,8 @@ - replace usages of ``copy_arrays`` with ``memmap`` [#230] +- Add support for astropy.wcs.WCS and astropy.wcs.wcsapi.SlicedLowLevelWCS [##235] + 0.6.1 (2024-04-05) ------------------ From de41f5186a3274a34dbeee08b34013bbbebd8a00 Mon Sep 17 00:00:00 2001 From: ViciousEagle03 Date: Sun, 25 Aug 2024 15:38:19 +0530 Subject: [PATCH 10/17] Revert small change --- CHANGES.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.rst b/CHANGES.rst index bbbca7e8..50bcd067 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -8,7 +8,7 @@ - replace usages of ``copy_arrays`` with ``memmap`` [#230] -- Add support for astropy.wcs.WCS and astropy.wcs.wcsapi.SlicedLowLevelWCS [##235] +- Add support for astropy.wcs.WCS and astropy.wcs.wcsapi.SlicedLowLevelWCS [#235] 0.6.1 (2024-04-05) ------------------ From 21062b55ec52c318ae2c7f7c051fa98118255ab6 Mon Sep 17 00:00:00 2001 From: ViciousEagle03 Date: Wed, 28 Aug 2024 19:37:03 +0530 Subject: [PATCH 11/17] Apply review suggestion --- asdf_astropy/converters/fits/fitswcs.py | 8 +- .../converters/fits/tests/test_fitswcs.py | 77 +++++++++++++++---- .../slicedwcs/test/test_slicedwcs.py | 1 + .../resources/schemas/fits/fitswcs-1.0.0.yaml | 8 +- .../schemas/slicedwcs/slicedwcs-1.0.0.yaml | 10 ++- 5 files changed, 79 insertions(+), 25 deletions(-) diff --git a/asdf_astropy/converters/fits/fitswcs.py b/asdf_astropy/converters/fits/fitswcs.py index 403af7bd..aecec738 100644 --- a/asdf_astropy/converters/fits/fitswcs.py +++ b/asdf_astropy/converters/fits/fitswcs.py @@ -8,10 +8,12 @@ class FitsWCSConverter(Converter): def from_yaml_tree(self, node, tag, ctx): from astropy.wcs import WCS - primary_hdu = node["hdu"][0] - return WCS(primary_hdu.header) + return WCS(node["hdu"][0].header, fobj=node["hdu"]) def to_yaml_tree(self, wcs, tag, ctx): node = {} - node["hdu"] = wcs.to_fits() + if wcs.sip is not None: + node["hdu"] = wcs.to_fits(relax=True) + else: + node["hdu"] = wcs.to_fits() return node diff --git a/asdf_astropy/converters/fits/tests/test_fitswcs.py b/asdf_astropy/converters/fits/tests/test_fitswcs.py index 70c183ef..af9fddf5 100644 --- a/asdf_astropy/converters/fits/tests/test_fitswcs.py +++ b/asdf_astropy/converters/fits/tests/test_fitswcs.py @@ -1,25 +1,62 @@ -import warnings - import asdf +import numpy as np import pytest -from astropy.io import fits -from astropy.utils.data import download_file -from astropy.wcs import WCS, FITSFixedWarning +from astropy import wcs + + +def create_sip_wcs(): + rng = np.random.default_rng() + twcs = wcs.WCS(naxis=2) + twcs.wcs.crval = [251.29, 57.58] + twcs.wcs.cdelt = [1, 1] + twcs.wcs.crpix = [507, 507] + twcs.wcs.pc = np.array([[7.7e-6, 3.3e-5], [3.7e-5, -6.8e-6]]) + twcs._naxis = [1014, 1014] + twcs.wcs.ctype = ["RA---TAN-SIP", "DEC--TAN-SIP"] + + # Generate random SIP coefficients + a = rng.uniform(low=-1e-5, high=1e-5, size=(5, 5)) + b = rng.uniform(low=-1e-5, high=1e-5, size=(5, 5)) + # Assign SIP coefficients + twcs.sip = wcs.Sip(a, b, None, None, twcs.wcs.crpix) + twcs.wcs.set() -def create_wcs(): - urls = [ - "http://data.astropy.org/tutorials/FITS-cubes/reduced_TAN_C14.fits", - "http://data.astropy.org/tutorials/FITS-images/HorseHead.fits", - ] + # Creates a WCS object with distortion lookup tables + img_world_wcs = wcs.WCS(naxis=2) + img_world_wcs.wcs.crpix = 1, 1 + img_world_wcs.wcs.crval = 0, 0 + img_world_wcs.wcs.cdelt = 1, 1 - with warnings.catch_warnings(): - warnings.simplefilter("ignore", FITSFixedWarning) - return [WCS(fits.open(download_file(url, cache=True))[0].header) for url in urls] + # Create maps with zero distortion except at one particular pixel + x_dist_array = np.zeros((25, 25)) + x_dist_array[10, 20] = 0.5 + map_x = wcs.DistortionLookupTable( + x_dist_array.astype(np.float32), + (5, 10), + (10, 20), + (2, 2), + ) + y_dist_array = np.zeros((25, 25)) + y_dist_array[10, 5] = 0.7 + map_y = wcs.DistortionLookupTable( + y_dist_array.astype(np.float32), + (5, 10), + (10, 20), + (3, 3), + ) + img_world_wcs.cpdis1 = map_x + img_world_wcs.cpdis2 = map_y + return (twcs, img_world_wcs) + + +@pytest.mark.parametrize("wcs", create_sip_wcs()) @pytest.mark.filterwarnings("ignore::astropy.wcs.wcs.FITSFixedWarning") -@pytest.mark.parametrize("wcs", create_wcs()) +@pytest.mark.filterwarnings( + "ignore:Some non-standard WCS keywords were excluded:astropy.utils.exceptions.AstropyWarning", +) def test_wcs_serialization(wcs, tmp_path): file_path = tmp_path / "test_wcs.asdf" with asdf.AsdfFile() as af: @@ -29,3 +66,15 @@ def test_wcs_serialization(wcs, tmp_path): with asdf.open(file_path) as af: loaded_wcs = af["wcs"] assert wcs.to_header() == loaded_wcs.to_header() + + +@pytest.mark.xfail(reason="Tabular WCS serialization is currently not supported") +def test_tabular_wcs_serialization(tab_wcs_2di, tmp_path): + file_path = tmp_path / "test_wcs.asdf" + with asdf.AsdfFile() as af: + af["wcs"] = tab_wcs_2di + af.write_to(file_path) + + with asdf.open(file_path) as af: + loaded_wcs = af["wcs"] + assert tab_wcs_2di.to_header() == loaded_wcs.to_header() diff --git a/asdf_astropy/converters/slicedwcs/test/test_slicedwcs.py b/asdf_astropy/converters/slicedwcs/test/test_slicedwcs.py index 5b09c375..8d661377 100644 --- a/asdf_astropy/converters/slicedwcs/test/test_slicedwcs.py +++ b/asdf_astropy/converters/slicedwcs/test/test_slicedwcs.py @@ -13,6 +13,7 @@ def create_wcs(): wcs.wcs.crval = 4.0, 0.0, 4.0e9, 3 wcs.wcs.crpix = 6.0, 7.0, 11.0, 11.0 wcs.wcs.cname = "Right Ascension", "Declination", "Frequency", "Time" + wcs0 = SlicedLowLevelWCS(wcs, 1) wcs1 = SlicedLowLevelWCS(wcs, [slice(None), slice(None), slice(None), 10]) wcs3 = SlicedLowLevelWCS(SlicedLowLevelWCS(wcs, slice(None)), [slice(3), slice(None), slice(None), 10]) diff --git a/asdf_astropy/resources/schemas/fits/fitswcs-1.0.0.yaml b/asdf_astropy/resources/schemas/fits/fitswcs-1.0.0.yaml index 8147aea0..220ac616 100644 --- a/asdf_astropy/resources/schemas/fits/fitswcs-1.0.0.yaml +++ b/asdf_astropy/resources/schemas/fits/fitswcs-1.0.0.yaml @@ -3,11 +3,11 @@ $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 +title: Represents the fits object -description: - Represents the fits object +description: Represents the FITS WCS object, the HDUlist of the FITS header is preserved + during serialization and during deserialization the WCS object is recreated + from the HDUlist. allOf: - type: object diff --git a/asdf_astropy/resources/schemas/slicedwcs/slicedwcs-1.0.0.yaml b/asdf_astropy/resources/schemas/slicedwcs/slicedwcs-1.0.0.yaml index 4215b6a5..942f6343 100644 --- a/asdf_astropy/resources/schemas/slicedwcs/slicedwcs-1.0.0.yaml +++ b/asdf_astropy/resources/schemas/slicedwcs/slicedwcs-1.0.0.yaml @@ -3,11 +3,13 @@ $schema: "http://stsci.edu/schemas/yaml-schema/draft-01" id: "http://astropy.org/schemas/astropy/slicedwcs/slicedwcs-1.0.0" -title: - Represents the SlicedLowLevelWCS object +title: Represents the SlicedLowLevelWCS object -description: - Represents the SlicedLowLevelWCS object +description: The SlicedLowLevelWCS class is a wrapper class for WCS that applies slices + to the WCS, allowing certain pixel and world dimensions to be retained or + dropped. + It manages the slicing and coordinate transformations while preserving + the underlying WCS object. allOf: - type: object From 0d31b030a1200d4493e01f5f08709bbd5b36b190 Mon Sep 17 00:00:00 2001 From: ViciousEagle03 Date: Wed, 28 Aug 2024 21:22:00 +0530 Subject: [PATCH 12/17] Add to a manifest and register it as a new extension --- asdf_astropy/extensions.py | 1 + .../resources/manifests/astropy-1.1.0.yaml | 17 ----- .../resources/manifests/astropy-1.3.0.yaml | 73 +++++++++++++++++++ 3 files changed, 74 insertions(+), 17 deletions(-) create mode 100644 asdf_astropy/resources/manifests/astropy-1.3.0.yaml diff --git a/asdf_astropy/extensions.py b/asdf_astropy/extensions.py index 71504673..4afba924 100644 --- a/asdf_astropy/extensions.py +++ b/asdf_astropy/extensions.py @@ -503,6 +503,7 @@ _ASTROPY_EXTENSION_MANIFEST_URIS = [ + "asdf://astropy.org/astropy/manifests/astropy-1.3.0", "asdf://astropy.org/astropy/manifests/astropy-1.2.0", "asdf://astropy.org/astropy/manifests/astropy-1.1.0", "asdf://astropy.org/astropy/manifests/astropy-1.0.0", diff --git a/asdf_astropy/resources/manifests/astropy-1.1.0.yaml b/asdf_astropy/resources/manifests/astropy-1.1.0.yaml index 49e26253..9e8094a9 100644 --- a/asdf_astropy/resources/manifests/astropy-1.1.0.yaml +++ b/asdf_astropy/resources/manifests/astropy-1.1.0.yaml @@ -54,20 +54,3 @@ tags: title: NdarrayMixin column. description: |- Represents an astropy.table.NdarrayMixin instance. -- tag_uri: tag:astropy.org:astropy/slicedwcs/slicedwcs-1.0.0 - schema_uri: http://astropy.org/schemas/astropy/slicedwcs/slicedwcs-1.0.0 - title: Represents an instance of SlicedLowLevelWCS - description: |- - The SlicedLowLevelWCS class is a wrapper class for WCS that applies slices - to the WCS, allowing certain pixel and world dimensions to be retained or - dropped. - - It manages the slicing and coordinate transformations while preserving - the underlying WCS object. -- tag_uri: tag:astropy.org:astropy/fits/fitswcs-1.0.0 - schema_uri: http://astropy.org/schemas/astropy/fits/fitswcs-1.0.0 - title: FITS WCS (World Coordinate System) Converter - description: |- - Represents the FITS WCS object, the HDUlist of the FITS header is preserved - during serialization and during deserialization the WCS object is recreated - from the HDUlist. diff --git a/asdf_astropy/resources/manifests/astropy-1.3.0.yaml b/asdf_astropy/resources/manifests/astropy-1.3.0.yaml new file mode 100644 index 00000000..5d7a4068 --- /dev/null +++ b/asdf_astropy/resources/manifests/astropy-1.3.0.yaml @@ -0,0 +1,73 @@ +id: asdf://astropy.org/astropy/manifests/astropy-1.3.0 +extension_uri: asdf://astropy.org/astropy/extensions/astropy-1.3.0 +title: Astropy extension 1.3.0 +description: |- + A set of tags for serializing astropy objects. This does not include most + model classes, which are handled by an implementation of the ASDF + transform extension. +asdf_standard_requirement: + gte: 1.5.0 +tags: +- tag_uri: tag:astropy.org:astropy/time/timedelta-1.0.0 + schema_uri: http://astropy.org/schemas/astropy/time/timedelta-1.0.0 + title: Represents an instance of TimeDelta from astropy + description: |- + Represents the time difference between two times. +- tag_uri: tag:astropy.org:astropy/fits/fits-1.0.0 + schema_uri: http://astropy.org/schemas/astropy/fits/fits-1.0.0 + title: A FITS file inside of an ASDF file. + description: |- + This schema is useful for distributing ASDF files that can + automatically be converted to FITS files by specifying the exact + content of the resulting FITS file. + + Not all kinds of data in FITS are directly representable in ASDF. + For example, applying an offset and scale to the data using the + `BZERO` and `BSCALE` keywords. In these cases, it will not be + possible to store the data in the native format from FITS and also + be accessible in its proper form in the ASDF file. + + Only image and binary table extensions are supported. +- tag_uri: tag:astropy.org:astropy/table/table-1.1.0 + schema_uri: http://astropy.org/schemas/astropy/table/table-1.1.0 + title: A table. + description: |- + A table is represented as a list of columns, where each entry is a + [column](ref:http://stsci.edu/schemas/asdf/core/column-1.0.0) + object, containing the data and some additional information. + + The data itself may be stored inline as text, or in binary in either + row- or column-major order by use of the `strides` property on the + individual column arrays. + + Each column in the table must have the same first (slowest moving) + dimension. +- tag_uri: tag:astropy.org:astropy/transform/units_mapping-1.0.0 + schema_uri: http://astropy.org/schemas/astropy/transform/units_mapping-1.0.0 + title: Mapper that operates on the units of the input. + description: |- + This transform operates on the units of the input, first converting to + the expected input units, then assigning replacement output units without + further conversion. +- tag_uri: tag:astropy.org:astropy/table/ndarraymixin-1.0.0 + schema_uri: http://astropy.org/schemas/astropy/table/ndarraymixin-1.0.0 + title: NdarrayMixin column. + description: |- + Represents an astropy.table.NdarrayMixin instance. +- tag_uri: tag:astropy.org:astropy/slicedwcs/slicedwcs-1.0.0 + schema_uri: http://astropy.org/schemas/astropy/slicedwcs/slicedwcs-1.0.0 + title: Represents an instance of SlicedLowLevelWCS + description: |- + The SlicedLowLevelWCS class is a wrapper class for WCS that applies slices + to the WCS, allowing certain pixel and world dimensions to be retained or + dropped. + + It manages the slicing and coordinate transformations while preserving + the underlying WCS object. +- tag_uri: tag:astropy.org:astropy/fits/fitswcs-1.0.0 + schema_uri: http://astropy.org/schemas/astropy/fits/fitswcs-1.0.0 + title: FITS WCS (World Coordinate System) Converter + description: |- + Represents the FITS WCS object, the HDUlist of the FITS header is preserved + during serialization and during deserialization the WCS object is recreated + from the HDUlist. From 091914298e29764d9a00343e6062601726bb511b Mon Sep 17 00:00:00 2001 From: ViciousEagle03 Date: Wed, 28 Aug 2024 21:25:33 +0530 Subject: [PATCH 13/17] Small change --- asdf_astropy/converters/fits/tests/test_fitswcs.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/asdf_astropy/converters/fits/tests/test_fitswcs.py b/asdf_astropy/converters/fits/tests/test_fitswcs.py index af9fddf5..fb885171 100644 --- a/asdf_astropy/converters/fits/tests/test_fitswcs.py +++ b/asdf_astropy/converters/fits/tests/test_fitswcs.py @@ -4,7 +4,7 @@ from astropy import wcs -def create_sip_wcs(): +def create_sip_distortion_wcs(): rng = np.random.default_rng() twcs = wcs.WCS(naxis=2) twcs.wcs.crval = [251.29, 57.58] @@ -52,7 +52,7 @@ def create_sip_wcs(): return (twcs, img_world_wcs) -@pytest.mark.parametrize("wcs", create_sip_wcs()) +@pytest.mark.parametrize("wcs", create_sip_distortion_wcs()) @pytest.mark.filterwarnings("ignore::astropy.wcs.wcs.FITSFixedWarning") @pytest.mark.filterwarnings( "ignore:Some non-standard WCS keywords were excluded:astropy.utils.exceptions.AstropyWarning", From 6b24fe1bdc0b175574e99525f497d92369087dcb Mon Sep 17 00:00:00 2001 From: ViciousEagle03 Date: Sun, 1 Sep 2024 23:28:36 +0530 Subject: [PATCH 14/17] Correct the test suite of table lookup distortion wcs --- .../converters/fits/tests/test_fitswcs.py | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/asdf_astropy/converters/fits/tests/test_fitswcs.py b/asdf_astropy/converters/fits/tests/test_fitswcs.py index fb885171..19cd1835 100644 --- a/asdf_astropy/converters/fits/tests/test_fitswcs.py +++ b/asdf_astropy/converters/fits/tests/test_fitswcs.py @@ -4,7 +4,7 @@ from astropy import wcs -def create_sip_distortion_wcs(): +def create_sip_distortion_and_tabular_wcs(): rng = np.random.default_rng() twcs = wcs.WCS(naxis=2) twcs.wcs.crval = [251.29, 57.58] @@ -52,7 +52,7 @@ def create_sip_distortion_wcs(): return (twcs, img_world_wcs) -@pytest.mark.parametrize("wcs", create_sip_distortion_wcs()) +@pytest.mark.parametrize("wcs", create_sip_distortion_and_tabular_wcs()) @pytest.mark.filterwarnings("ignore::astropy.wcs.wcs.FITSFixedWarning") @pytest.mark.filterwarnings( "ignore:Some non-standard WCS keywords were excluded:astropy.utils.exceptions.AstropyWarning", @@ -66,15 +66,3 @@ def test_wcs_serialization(wcs, tmp_path): with asdf.open(file_path) as af: loaded_wcs = af["wcs"] assert wcs.to_header() == loaded_wcs.to_header() - - -@pytest.mark.xfail(reason="Tabular WCS serialization is currently not supported") -def test_tabular_wcs_serialization(tab_wcs_2di, tmp_path): - file_path = tmp_path / "test_wcs.asdf" - with asdf.AsdfFile() as af: - af["wcs"] = tab_wcs_2di - af.write_to(file_path) - - with asdf.open(file_path) as af: - loaded_wcs = af["wcs"] - assert tab_wcs_2di.to_header() == loaded_wcs.to_header() From 5b1d4cfa66ae7510f03678be9ce96f0b92c03e29 Mon Sep 17 00:00:00 2001 From: ViciousEagle03 Date: Thu, 19 Sep 2024 03:22:48 +0530 Subject: [PATCH 15/17] Apply code suggestions --- .../converters/fits/tests/test_fitswcs.py | 34 ++++++++++++++++--- .../converters/slicedwcs/slicedwcs.py | 6 ++-- .../slicedwcs/test/test_slicedwcs.py | 4 ++- .../resources/manifests/astropy-1.3.0.yaml | 2 +- .../schemas/slicedwcs/slicedwcs-1.0.0.yaml | 14 ++++++++ 5 files changed, 50 insertions(+), 10 deletions(-) diff --git a/asdf_astropy/converters/fits/tests/test_fitswcs.py b/asdf_astropy/converters/fits/tests/test_fitswcs.py index 19cd1835..d36f3552 100644 --- a/asdf_astropy/converters/fits/tests/test_fitswcs.py +++ b/asdf_astropy/converters/fits/tests/test_fitswcs.py @@ -3,9 +3,11 @@ import pytest from astropy import wcs +from asdf_astropy.testing.helpers import assert_hdu_list_equal -def create_sip_distortion_and_tabular_wcs(): - rng = np.random.default_rng() + +def create_sip_distortion_wcs(): + rng = np.random.default_rng(42) twcs = wcs.WCS(naxis=2) twcs.wcs.crval = [251.29, 57.58] twcs.wcs.cdelt = [1, 1] @@ -22,6 +24,27 @@ def create_sip_distortion_and_tabular_wcs(): twcs.sip = wcs.Sip(a, b, None, None, twcs.wcs.crpix) twcs.wcs.set() + return (twcs,) + + +@pytest.mark.xfail(reason="Fails due to normalization differences when using wcs.to_fits().") +@pytest.mark.parametrize("wcs", create_sip_distortion_wcs()) +@pytest.mark.filterwarnings("ignore::astropy.wcs.wcs.FITSFixedWarning") +@pytest.mark.filterwarnings( + "ignore:Some non-standard WCS keywords were excluded:astropy.utils.exceptions.AstropyWarning", +) +def test_sip_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_hdu_list_equal(wcs.to_fits(relax=True), loaded_wcs.to_fits(relax=True)) + + +def create_tabular_wcs(): # Creates a WCS object with distortion lookup tables img_world_wcs = wcs.WCS(naxis=2) img_world_wcs.wcs.crpix = 1, 1 @@ -49,15 +72,15 @@ def create_sip_distortion_and_tabular_wcs(): img_world_wcs.cpdis1 = map_x img_world_wcs.cpdis2 = map_y - return (twcs, img_world_wcs) + return (img_world_wcs,) -@pytest.mark.parametrize("wcs", create_sip_distortion_and_tabular_wcs()) +@pytest.mark.parametrize("wcs", create_tabular_wcs()) @pytest.mark.filterwarnings("ignore::astropy.wcs.wcs.FITSFixedWarning") @pytest.mark.filterwarnings( "ignore:Some non-standard WCS keywords were excluded:astropy.utils.exceptions.AstropyWarning", ) -def test_wcs_serialization(wcs, tmp_path): +def test_twcs_serialization(wcs, tmp_path): file_path = tmp_path / "test_wcs.asdf" with asdf.AsdfFile() as af: af["wcs"] = wcs @@ -66,3 +89,4 @@ def test_wcs_serialization(wcs, tmp_path): with asdf.open(file_path) as af: loaded_wcs = af["wcs"] assert wcs.to_header() == loaded_wcs.to_header() + assert_hdu_list_equal(wcs.to_fits(), loaded_wcs.to_fits()) diff --git a/asdf_astropy/converters/slicedwcs/slicedwcs.py b/asdf_astropy/converters/slicedwcs/slicedwcs.py index 404a6d3d..d45a1d77 100644 --- a/asdf_astropy/converters/slicedwcs/slicedwcs.py +++ b/asdf_astropy/converters/slicedwcs/slicedwcs.py @@ -24,9 +24,9 @@ def to_yaml_tree(self, sl, tag, ctx): if isinstance(s, slice): node["slices_array"].append( { - "start": s.start if s.start is not None else None, - "stop": s.stop if s.stop is not None else None, - "step": s.step if s.step is not None else None, + "start": s.start, + "stop": s.stop, + "step": s.step, }, ) else: diff --git a/asdf_astropy/converters/slicedwcs/test/test_slicedwcs.py b/asdf_astropy/converters/slicedwcs/test/test_slicedwcs.py index 8d661377..6d3f1cef 100644 --- a/asdf_astropy/converters/slicedwcs/test/test_slicedwcs.py +++ b/asdf_astropy/converters/slicedwcs/test/test_slicedwcs.py @@ -4,6 +4,8 @@ from astropy.wcs import WCS from astropy.wcs.wcsapi.wrappers.sliced_wcs import SlicedLowLevelWCS +from asdf_astropy.testing.helpers import assert_hdu_list_equal + def create_wcs(): wcs = WCS(naxis=4) @@ -32,5 +34,5 @@ def test_sliced_wcs_serialization(sl_wcs, tmp_path): with asdf.open(file_path) as af: loaded_sl_wcs = af["sl_wcs"] - assert sl_wcs._wcs.to_header() == loaded_sl_wcs._wcs.to_header() + assert_hdu_list_equal(sl_wcs._wcs.to_fits(), loaded_sl_wcs._wcs.to_fits()) assert sl_wcs._slices_array == loaded_sl_wcs._slices_array diff --git a/asdf_astropy/resources/manifests/astropy-1.3.0.yaml b/asdf_astropy/resources/manifests/astropy-1.3.0.yaml index 5d7a4068..910a2dad 100644 --- a/asdf_astropy/resources/manifests/astropy-1.3.0.yaml +++ b/asdf_astropy/resources/manifests/astropy-1.3.0.yaml @@ -6,7 +6,7 @@ description: |- model classes, which are handled by an implementation of the ASDF transform extension. asdf_standard_requirement: - gte: 1.5.0 + gte: 1.6.0 tags: - tag_uri: tag:astropy.org:astropy/time/timedelta-1.0.0 schema_uri: http://astropy.org/schemas/astropy/time/timedelta-1.0.0 diff --git a/asdf_astropy/resources/schemas/slicedwcs/slicedwcs-1.0.0.yaml b/asdf_astropy/resources/schemas/slicedwcs/slicedwcs-1.0.0.yaml index 942f6343..f4f08ff4 100644 --- a/asdf_astropy/resources/schemas/slicedwcs/slicedwcs-1.0.0.yaml +++ b/asdf_astropy/resources/schemas/slicedwcs/slicedwcs-1.0.0.yaml @@ -22,5 +22,19 @@ allOf: - oneOf: - type: integer - type: object + properties: + start: + anyOf: + - type: integer + - type: "null" + stop: + anyOf: + - type: integer + - type: "null" + step: + anyOf: + - type: integer + - type: "null" + required: ["wcs", "slices_array"] From 53df278e6a9b5ff32bdaae1cc9674d7083a59dd2 Mon Sep 17 00:00:00 2001 From: ViciousEagle03 Date: Thu, 19 Sep 2024 03:55:43 +0530 Subject: [PATCH 16/17] correct the standard version --- asdf_astropy/resources/manifests/astropy-1.3.0.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/asdf_astropy/resources/manifests/astropy-1.3.0.yaml b/asdf_astropy/resources/manifests/astropy-1.3.0.yaml index 910a2dad..5d7a4068 100644 --- a/asdf_astropy/resources/manifests/astropy-1.3.0.yaml +++ b/asdf_astropy/resources/manifests/astropy-1.3.0.yaml @@ -6,7 +6,7 @@ description: |- model classes, which are handled by an implementation of the ASDF transform extension. asdf_standard_requirement: - gte: 1.6.0 + gte: 1.5.0 tags: - tag_uri: tag:astropy.org:astropy/time/timedelta-1.0.0 schema_uri: http://astropy.org/schemas/astropy/time/timedelta-1.0.0 From a016e2ba3f8d0acfddf96fae10478f9e966d4d96 Mon Sep 17 00:00:00 2001 From: ViciousEagle03 Date: Fri, 20 Sep 2024 02:10:02 +0530 Subject: [PATCH 17/17] move fitswcs and sliced_wcs converters to wcs submodule --- asdf_astropy/converters/__init__.py | 4 +++- asdf_astropy/converters/fits/__init__.py | 2 -- asdf_astropy/converters/{slicedwcs => wcs}/__init__.py | 3 ++- asdf_astropy/converters/{fits => wcs}/fitswcs.py | 0 asdf_astropy/converters/{slicedwcs => wcs}/slicedwcs.py | 0 .../converters/{slicedwcs/test => wcs/tests}/__init__.py | 0 asdf_astropy/converters/{fits => wcs}/tests/test_fitswcs.py | 3 --- .../{slicedwcs/test => wcs/tests}/test_slicedwcs.py | 0 asdf_astropy/extensions.py | 4 ++-- 9 files changed, 7 insertions(+), 9 deletions(-) rename asdf_astropy/converters/{slicedwcs => wcs}/__init__.py (56%) rename asdf_astropy/converters/{fits => wcs}/fitswcs.py (100%) rename asdf_astropy/converters/{slicedwcs => wcs}/slicedwcs.py (100%) rename asdf_astropy/converters/{slicedwcs/test => wcs/tests}/__init__.py (100%) rename asdf_astropy/converters/{fits => wcs}/tests/test_fitswcs.py (95%) rename asdf_astropy/converters/{slicedwcs/test => wcs/tests}/test_slicedwcs.py (100%) diff --git a/asdf_astropy/converters/__init__.py b/asdf_astropy/converters/__init__.py index 131ff5c2..fb9a0dcf 100644 --- a/asdf_astropy/converters/__init__.py +++ b/asdf_astropy/converters/__init__.py @@ -16,6 +16,7 @@ "AsdfFitsConverter", "AstropyFitsConverter", "FitsWCSConverter", + "SlicedWCSConverter", "ColumnConverter", "AstropyTableConverter", "AsdfTableConverter", @@ -52,7 +53,7 @@ SkyCoordConverter, SpectralCoordConverter, ) -from .fits import AsdfFitsConverter, AstropyFitsConverter, FitsConverter, FitsWCSConverter +from .fits import AsdfFitsConverter, AstropyFitsConverter, FitsConverter from .table import AsdfTableConverter, AstropyTableConverter, ColumnConverter, NdarrayMixinConverter from .time import TimeConverter, TimeDeltaConverter from .transform import ( @@ -75,3 +76,4 @@ UnitsMappingConverter, ) from .unit import EquivalencyConverter, MagUnitConverter, QuantityConverter, UnitConverter +from .wcs import FitsWCSConverter, SlicedWCSConverter diff --git a/asdf_astropy/converters/fits/__init__.py b/asdf_astropy/converters/fits/__init__.py index 4f915659..4647e59c 100644 --- a/asdf_astropy/converters/fits/__init__.py +++ b/asdf_astropy/converters/fits/__init__.py @@ -2,8 +2,6 @@ "FitsConverter", "AsdfFitsConverter", "AstropyFitsConverter", - "FitsWCSConverter", ] from .fits import AsdfFitsConverter, AstropyFitsConverter, FitsConverter -from .fitswcs import FitsWCSConverter diff --git a/asdf_astropy/converters/slicedwcs/__init__.py b/asdf_astropy/converters/wcs/__init__.py similarity index 56% rename from asdf_astropy/converters/slicedwcs/__init__.py rename to asdf_astropy/converters/wcs/__init__.py index 8473b67e..e8034fcc 100644 --- a/asdf_astropy/converters/slicedwcs/__init__.py +++ b/asdf_astropy/converters/wcs/__init__.py @@ -1,5 +1,6 @@ __all__ = [ + "FitsWCSConverter", "SlicedWCSConverter", ] - +from .fitswcs import FitsWCSConverter from .slicedwcs import SlicedWCSConverter diff --git a/asdf_astropy/converters/fits/fitswcs.py b/asdf_astropy/converters/wcs/fitswcs.py similarity index 100% rename from asdf_astropy/converters/fits/fitswcs.py rename to asdf_astropy/converters/wcs/fitswcs.py diff --git a/asdf_astropy/converters/slicedwcs/slicedwcs.py b/asdf_astropy/converters/wcs/slicedwcs.py similarity index 100% rename from asdf_astropy/converters/slicedwcs/slicedwcs.py rename to asdf_astropy/converters/wcs/slicedwcs.py diff --git a/asdf_astropy/converters/slicedwcs/test/__init__.py b/asdf_astropy/converters/wcs/tests/__init__.py similarity index 100% rename from asdf_astropy/converters/slicedwcs/test/__init__.py rename to asdf_astropy/converters/wcs/tests/__init__.py diff --git a/asdf_astropy/converters/fits/tests/test_fitswcs.py b/asdf_astropy/converters/wcs/tests/test_fitswcs.py similarity index 95% rename from asdf_astropy/converters/fits/tests/test_fitswcs.py rename to asdf_astropy/converters/wcs/tests/test_fitswcs.py index d36f3552..52d9c2e4 100644 --- a/asdf_astropy/converters/fits/tests/test_fitswcs.py +++ b/asdf_astropy/converters/wcs/tests/test_fitswcs.py @@ -77,9 +77,6 @@ def create_tabular_wcs(): @pytest.mark.parametrize("wcs", create_tabular_wcs()) @pytest.mark.filterwarnings("ignore::astropy.wcs.wcs.FITSFixedWarning") -@pytest.mark.filterwarnings( - "ignore:Some non-standard WCS keywords were excluded:astropy.utils.exceptions.AstropyWarning", -) def test_twcs_serialization(wcs, tmp_path): file_path = tmp_path / "test_wcs.asdf" with asdf.AsdfFile() as af: diff --git a/asdf_astropy/converters/slicedwcs/test/test_slicedwcs.py b/asdf_astropy/converters/wcs/tests/test_slicedwcs.py similarity index 100% rename from asdf_astropy/converters/slicedwcs/test/test_slicedwcs.py rename to asdf_astropy/converters/wcs/tests/test_slicedwcs.py diff --git a/asdf_astropy/extensions.py b/asdf_astropy/extensions.py index 4afba924..613c5802 100644 --- a/asdf_astropy/extensions.py +++ b/asdf_astropy/extensions.py @@ -13,8 +13,6 @@ 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.slicedwcs.slicedwcs import SlicedWCSConverter from .converters.table.table import AsdfTableConverter, AstropyTableConverter, ColumnConverter, NdarrayMixinConverter from .converters.time.time import TimeConverter from .converters.time.time_delta import TimeDeltaConverter @@ -33,6 +31,8 @@ from .converters.unit.magunit import MagUnitConverter from .converters.unit.quantity import QuantityConverter from .converters.unit.unit import UnitConverter +from .converters.wcs.fitswcs import FitsWCSConverter +from .converters.wcs.slicedwcs import SlicedWCSConverter __all__ = [ "TRANSFORM_CONVERTERS",