Skip to content

Commit 2cba5ea

Browse files
committed
Add tests for set/get viewport
1 parent d95fc67 commit 2cba5ea

File tree

1 file changed

+145
-24
lines changed

1 file changed

+145
-24
lines changed

src/astro_image_display_api/widget_api_test.py

Lines changed: 145 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -92,38 +92,159 @@ def test_load(self, data, tmp_path, load_type):
9292

9393
self.image.load_image(load_arg)
9494

95-
def test_center_on(self):
96-
self.image.center_on((10, 10)) # X, Y
95+
def test_set_get_center_xy(self, data):
96+
self.image.load_image(data, image_label='test')
97+
self.image.set_viewport(center=(10, 10), image_label='test') # X, Y
98+
vport = self.image.get_viewport(image_label='test')
99+
assert vport['center'] == (10, 10)
100+
assert vport['image_label'] == 'test'
101+
102+
def test_set_get_center_world(self, data, wcs):
103+
self.image.load_image(NDData(data=data, wcs=wcs), image_label='test')
104+
self.image.set_viewport(center=SkyCoord(*wcs.crval, unit='deg'), image_label='test')
105+
106+
vport = self.image.get_viewport(image_label='test')
107+
assert isinstance(vport['center'], SkyCoord)
108+
assert vport['center'].ra.deg == pytest.approx(wcs.crval[0])
109+
assert vport['center'].dec.deg == pytest.approx(wcs.crval[1])
110+
111+
def test_set_get_fov_pixel(self, data):
112+
# Set data first, since that is needed to determine zoom level
113+
self.image.load_image(data, image_label='test')
97114

98-
def test_offset_by(self, data, wcs):
99-
self.image.offset_by(10, 10) # dX, dY
115+
self.image.set_viewport(fov=100, image_label='test')
116+
vport = self.image.get_viewport(image_label='test')
117+
assert vport['fov'] == 100
118+
assert vport['image_label'] == 'test'
100119

101-
# Testing offset by WCS requires a WCS. The viewer will (or ought to
102-
# have) taken care of setting up the WCS internally if initialized with
103-
# an NDData that has a WCS.
104-
ndd = NDData(data=data, wcs=wcs)
105-
self.image.load_image(ndd)
120+
def test_set_get_fov_world(self, data, wcs):
121+
# Set data first, since that is needed to determine zoom level
122+
self.image.load_image(NDData(data=data, wcs=wcs), image_label='test')
106123

107-
self.image.offset_by(10 * u.arcmin, 10 * u.arcmin)
124+
# Set the FOV in world coordinates
125+
self.image.set_viewport(fov=0.1 * u.deg, image_label='test')
126+
vport = self.image.get_viewport(image_label='test')
127+
assert isinstance(vport['fov'], SkyCoord)
128+
assert vport['fov'].deg == pytest.approx(0.1)
108129

109-
# A mix of pixel and sky should produce an error
110-
with pytest.raises(u.UnitConversionError, match='are not convertible'):
111-
self.image.offset_by(10 * u.arcmin, 10)
130+
def test_set_get_viewport_errors(self, data, wcs):
131+
self.image.load_image(NDData(data=data, wcs=wcs), image_label='test')
112132

113-
# A mix of inconsistent units should produce an error
114-
with pytest.raises(u.UnitConversionError, match='are not convertible'):
115-
self.image.offset_by(1 * u.arcsec, 1 * u.AA)
133+
# fov can be float or an angular Qunatity
134+
with pytest.raises(u.UnitTypeError, match='[Ii]ncorrect unit for fov'):
135+
self.image.set_viewport(fov=100 * u.meter, image_label='test')
116136

117-
def test_zoom_level(self, data):
118-
# Set data first, since that is needed to determine zoom level
137+
# try an fov that is completely the wrong type
138+
with pytest.raises(TypeError, match='[Ii]nvalid value for fov'):
139+
self.image.set_viewport(fov='not a valid value', image_label='test')
140+
141+
# center can be a SkyCoord or a tuple of floats. Try a value that is neither
142+
with pytest.raises(TypeError, match='[Ii]nvalid value for center'):
143+
self.image.set_viewport(center='not a valid value', image_label='test')
144+
145+
# Check that an error is raised if a label is provided that does not
146+
# match an image that is loaded.
147+
with pytest.raises(ValueError, match='[Ii]mage label.*not found'):
148+
self.image.set_viewport(center=(10, 10), fov=100, image_label='not a valid label')
149+
150+
# Getting a viewport for an image_label that does not exist should raise an error
151+
with pytest.raises(ValueError, match='[Ii]mage label.*not found'):
152+
self.image.get_viewport(image_label='not a valid label')
153+
154+
# If there are multiple images loaded, the image_label must be provided
155+
self.image.load_image(data, image_label='another test')
156+
157+
with pytest.raises(ValueError, match='[Ii]mage label.*not provided'):
158+
self.image.get_viewport()
159+
160+
def test_set_get_view_port_no_image_label(self, data):
161+
# If there is only one image, the viewport should be able to be set
162+
# and retrieved without an image label.
163+
164+
# Add an image without an image label
119165
self.image.load_image(data)
120-
self.image.zoom_level = 5
121-
assert self.image.zoom_level == 5
122166

123-
def test_zoom(self):
124-
self.image.zoom_level = 3
125-
self.image.zoom(2)
126-
assert self.image.zoom_level == 6 # 3 x 2
167+
# Getting the viewport should not fail...
168+
vport = self.image.get_viewport()
169+
assert 'center' in vport
170+
assert 'fov' in vport
171+
assert 'image_label' in vport
172+
assert vport['image_label'] is None
173+
174+
# Set the viewport without an image label
175+
self.image.set_viewport(center=(10, 10), fov=100)
176+
177+
# Getting the viewport again should return the same values
178+
vport = self.image.get_viewport()
179+
assert vport['center'] == (10, 10)
180+
assert vport['fov'] == 100
181+
assert vport['image_label'] is None
182+
183+
def test_set_get_viewport_single_label(self, data):
184+
# If there is only one image, the viewport should be able to be set
185+
# and retrieved with an image label.
186+
187+
# Add an image with an image label
188+
self.image.load_image(data, image_label='test')
189+
190+
# Getting the viewport should not fail...
191+
vport = self.image.get_viewport(image_label='test')
192+
assert 'center' in vport
193+
assert 'fov' in vport
194+
assert 'image_label' in vport
195+
assert vport['image_label'] == 'test'
196+
197+
# Set the viewport with an image label
198+
self.image.set_viewport(center=(10, 10), fov=100, image_label='test')
199+
200+
# Getting the viewport again should return the same values
201+
vport = self.image.get_viewport(image_label='test')
202+
assert vport['center'] == (10, 10)
203+
assert vport['fov'] == 100
204+
assert vport['image_label'] == 'test'
205+
206+
def test_get_viewport_sky_or_pixel(self, data, wcs):
207+
# Check that the viewport can be retrieved in both pixel and world
208+
# coordinates, depending on the WCS of the image.
209+
210+
# Load the data with a WCS
211+
self.image.load_image(NDData(data=data, wcs=wcs), image_label='test')
212+
213+
input_center = SkyCoord(*wcs.val, unit='deg')
214+
input_fov = 2 * u.arcmin
215+
self.image.set_viewport(center=input_center, fov=input_fov, image_label='test')
216+
217+
# Get the viewport in pixel coordinates
218+
vport_pixel = self.image.get_viewport(image_label='test', sky_or_pixel='pixel')
219+
assert vport_pixel['center'] == wcs.crpix
220+
# tbh, not at all sure what the fov should be in pixel coordinates,
221+
# so just check that it is a float.
222+
assert isinstance(vport_pixel['fov'], float)
223+
224+
# Get the viewport in world coordinates
225+
vport_world = self.image.get_viewport(image_label='test', sky_or_pixel='sky')
226+
assert vport_world['center'] == input_center
227+
assert vport_world['fov'] == input_fov
228+
229+
@pytest.mark.parametrize("sky_or_pixel", ['sky', 'pixel'])
230+
def test_get_viewport_no_sky_or_pixel(self, data, wcs, sky_or_pixel):
231+
# Check that get_viewport returns the correct "default" sky_or_pixel
232+
# value when the result ought to be unambiguous.
233+
if sky_or_pixel == 'sky':
234+
use_wcs = wcs
235+
else:
236+
use_wcs = None
237+
238+
self.image.load_image(NDData(data=data, wcs=use_wcs), image_label='test')
239+
240+
vport = self.image.get_viewport(image_label='test')
241+
match sky_or_pixel:
242+
case 'sky':
243+
assert isinstance(vport['center'], SkyCoord)
244+
assert vport['fov'].unit.physical_type == "angle"
245+
case 'pixel':
246+
assert isinstance(vport['center'], tuple)
247+
assert isinstance(vport['fov'], float)
127248

128249
def test_marker_properties(self):
129250
# Set the marker style

0 commit comments

Comments
 (0)