diff --git a/astropy/wcs/tests/test_utils.py b/astropy/wcs/tests/test_utils.py index 36a851dcaea..ead7aac6cb2 100644 --- a/astropy/wcs/tests/test_utils.py +++ b/astropy/wcs/tests/test_utils.py @@ -29,6 +29,8 @@ from astropy.utils.exceptions import AstropyUserWarning from astropy.wcs import _wcs from astropy.wcs.utils import ( + FRAME_WCS_MAPPINGS, + WCS_FRAME_MAPPINGS, _pixel_to_pixel_correlation_matrix, _pixel_to_world_correlation_matrix, _split_matrix, @@ -417,7 +419,10 @@ def test_wcs_to_body_frame(): unknown_wcs = WCS(naxis=2) unknown_wcs.wcs.ctype = ["UTLN-TAN", "UTLT-TAN"] - with pytest.raises(KeyError, match="unknown solar system object abbreviation UT"): + with pytest.raises( + ValueError, + match="Could not determine celestial frame corresponding to the specified WCS object", + ): frame = wcs_to_celestial_frame(unknown_wcs) triaxial_wcs = WCS(naxis=2) @@ -1593,3 +1598,40 @@ def test_obsgeo_infinite(dkist_location): def test_obsgeo_invalid(obsgeo): with pytest.raises(ValueError): obsgeo_to_frame(obsgeo, None) + + +def test_custom_wcs_to_from_frame(): + # See https://github.com/astropy/astropy/issues/15625 + # test from Sam van Kooten + + class CustomFrame(BaseCoordinateFrame): + obstime = Time("2017-08-17T12:41:04.43") + + def custom_wcs_frame_mapping(wcs): + ctypes = {c[:4] for c in wcs.wcs.ctype} + if not ({"CSLN", "CSLT"} <= ctypes): + return None + + dateobs = wcs.wcs.dateavg or wcs.wcs.dateobs or None + custom_frame = CustomFrame() + return custom_frame + + def custom_frame_wcs_mapping(frame, projection="TAN"): + if not isinstance(frame, CustomFrame): + return None + wcs = WCS(naxis=2) + wcs.wcs.ctype = [f"CSLN-{projection}", f"CSLT-{projection}"] + return wcs + + WCS_FRAME_MAPPINGS.append([custom_wcs_frame_mapping]) + FRAME_WCS_MAPPINGS.append([custom_frame_wcs_mapping]) + + mywcs = WCS(naxis=2) + mywcs.wcs.ctype = ["CSLN-TAN", "CSLT-TAN"] + custom_frame = custom_wcs_frame_mapping(mywcs) + assert isinstance(custom_frame, CustomFrame) + + custom_wcs = custom_frame_wcs_mapping(custom_frame) + print(custom_wcs.wcs.ctype) + assert custom_wcs.wcs.ctype[0] == "CSLN-TAN" + assert custom_wcs.wcs.ctype[1] == "CSLT-TAN" diff --git a/astropy/wcs/utils.py b/astropy/wcs/utils.py index a7149fe16a5..ed98fc4e41a 100644 --- a/astropy/wcs/utils.py +++ b/astropy/wcs/utils.py @@ -158,13 +158,11 @@ def _wcs_to_celestial_frame_builtin(wcs): representation_type=SphericalRepresentation, obstime=wcs.wcs.dateobs or None, ) - elif xcoord[2:4] in ("LN", "LT") and "H" not in xcoord and "CR" not in xcoord: + elif xcoord[2:4] in ("LN", "LT") and xcoord[:2] in SOLAR_SYSTEM_OBJ_DICT.keys(): # Coordinates on a planetary body, as defined in # https://agupubs.onlinelibrary.wiley.com/doi/10.1029/2018EA000388 object_name = SOLAR_SYSTEM_OBJ_DICT.get(xcoord[:2]) - if object_name is None: - raise KeyError(f"unknown solar system object abbreviation {xcoord[:2]}") a_radius = wcs.wcs.aux.a_radius b_radius = wcs.wcs.aux.b_radius diff --git a/docs/changes/wcs/15630.bugfix.rst b/docs/changes/wcs/15630.bugfix.rst new file mode 100644 index 00000000000..35ff04bd494 --- /dev/null +++ b/docs/changes/wcs/15630.bugfix.rst @@ -0,0 +1,2 @@ +Fix a regression in custom WCS mapping due to the recent introduction of +Solar System frames.