Skip to content

Commit e5b3114

Browse files
Fix numerical_inverse API issue (#565)
1 parent b1c9955 commit e5b3114

File tree

5 files changed

+95
-2
lines changed

5 files changed

+95
-2
lines changed

CHANGES.rst

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
0.25.0 (unreleased)
22
-------------------
33

4+
- Fix API issue with ``wcs.numerical_inverse``. [#565]
5+
46
0.24.0 (2025-02-04)
57
-------------------
68

gwcs/examples.py

+54-1
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
from astropy.time import Time
66

77
from . import coordinate_frames as cf
8+
from . import geometry, wcs
89
from . import spectroscopy as sp
9-
from . import wcs
1010

1111
# frames
1212
DETECTOR_1D_FRAME = cf.CoordinateFrame(
@@ -651,3 +651,56 @@ def gwcs_with_pipeline_celestial():
651651
]
652652

653653
return wcs.WCS(pipeline)
654+
655+
656+
def gwcs_romanisim():
657+
targ_pos = coord.SkyCoord(ra=0 * u.deg, dec=0 * u.deg)
658+
659+
ra_ref = targ_pos.ra.to(u.deg).value
660+
dec_ref = targ_pos.dec.to(u.deg).value
661+
662+
# v2_ref, v3_ref are in arcsec, but RotationSequence3D wants degrees,
663+
# so start by scaling by 3600.
664+
rot = models.RotationSequence3D([0, 0, 0, dec_ref, -ra_ref], "zyxyz")
665+
666+
# V2V3 are in arcseconds, while SphericalToCartesian expects degrees,
667+
# so again start by scaling by 3600
668+
tel2sky = (
669+
(models.Scale(1 / 3600) & models.Scale(1 / 3600))
670+
| geometry.SphericalToCartesian(wrap_lon_at=180)
671+
| rot
672+
| geometry.CartesianToSpherical(wrap_lon_at=360)
673+
)
674+
tel2sky.name = "v23tosky"
675+
676+
detector = cf.Frame2D(name="detector", axes_order=(0, 1), unit=(u.pix, u.pix))
677+
v2v3 = cf.Frame2D(
678+
name="v2v3",
679+
axes_order=(0, 1),
680+
axes_names=("v2", "v3"),
681+
unit=(u.arcsec, u.arcsec),
682+
)
683+
v2v3vacorr = cf.Frame2D(
684+
name="v2v3vacorr",
685+
axes_order=(0, 1),
686+
axes_names=("v2", "v3"),
687+
unit=(u.arcsec, u.arcsec),
688+
)
689+
world = cf.CelestialFrame(reference_frame=coord.ICRS(), name="world")
690+
691+
va_corr = models.Identity(2)
692+
zen2v2v3 = models.EulerAngleRotation(0, -90, 0, "xyz") | (
693+
models.Scale(3600) & models.Scale(3600)
694+
)
695+
tanproj = models.Pix2Sky_Gnomonic()
696+
pix2tan = models.Scale(0.11 / 3600) & models.Scale(0.11 / 3600)
697+
distortion = pix2tan | tanproj | zen2v2v3
698+
699+
pipeline = [
700+
wcs.Step(detector, distortion),
701+
wcs.Step(v2v3, va_corr),
702+
wcs.Step(v2v3vacorr, tel2sky),
703+
wcs.Step(world, None),
704+
]
705+
706+
return wcs.WCS(pipeline)

gwcs/tests/conftest.py

+5
Original file line numberDiff line numberDiff line change
@@ -156,3 +156,8 @@ def cart_to_spher():
156156
@pytest.fixture
157157
def gwcs_with_pipeline_celestial():
158158
return examples.gwcs_with_pipeline_celestial()
159+
160+
161+
@pytest.fixture
162+
def gwcs_romanisim():
163+
return examples.gwcs_romanisim()

gwcs/tests/test_wcs.py

+9
Original file line numberDiff line numberDiff line change
@@ -1804,3 +1804,12 @@ def test_bounding_box_with_units():
18041804

18051805
w_gwcs.invert(4 * u.deg, 5 * u.deg)
18061806
w_gwcs.to_fits(bounding_box=([0, 100] * u.pix, [0, 100] * u.pix))
1807+
1808+
1809+
def test_direct_numerical_inverse(gwcs_romanisim):
1810+
xy = (128, 256)
1811+
coord = gwcs_romanisim(*xy)
1812+
ra_dec = (np.radians(c) * u.rad for c in coord)
1813+
out = gwcs_romanisim.numerical_inverse(*ra_dec)
1814+
1815+
assert_allclose(xy, out)

gwcs/wcs/_wcs.py

+25-1
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,7 @@ def _call_backward(
352352
else:
353353
# Always strip units for numerical inverse
354354
args = self._remove_units_input(args, self.output_frame)
355-
result = self.numerical_inverse(
355+
result = self._numerical_inverse(
356356
*args,
357357
with_bounding_box=with_bounding_box,
358358
fill_value=fill_value,
@@ -678,6 +678,30 @@ def numerical_inverse(
678678
[2.76552923e-05 1.14789013e-05]]
679679
680680
""" # noqa: E501
681+
return self._numerical_inverse(
682+
*self._remove_units_input(args, self.output_frame),
683+
tolerance=tolerance,
684+
maxiter=maxiter,
685+
adaptive=adaptive,
686+
detect_divergence=detect_divergence,
687+
quiet=quiet,
688+
with_bounding_box=with_bounding_box,
689+
fill_value=fill_value,
690+
**kwargs,
691+
)
692+
693+
def _numerical_inverse(
694+
self,
695+
*args,
696+
tolerance=1e-5,
697+
maxiter=30,
698+
adaptive=True,
699+
detect_divergence=True,
700+
quiet=True,
701+
with_bounding_box=True,
702+
fill_value=np.nan,
703+
**kwargs,
704+
):
681705
if kwargs.pop("with_units", False):
682706
msg = (
683707
"Support for with_units in numerical_inverse has been removed, "

0 commit comments

Comments
 (0)