Skip to content

Commit

Permalink
expose zoom_to_selected in catalogs plugin api
Browse files Browse the repository at this point in the history
  • Loading branch information
cshanahan1 committed Dec 20, 2024
1 parent 0693231 commit 2082f32
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 8 deletions.
48 changes: 41 additions & 7 deletions jdaviz/configs/imviz/plugins/catalogs/catalogs.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ class Catalogs(PluginTemplateMixin, ViewerSelectMixin, HasFileImportSelect, Tabl
* :meth:`~jdaviz.core.template_mixin.PluginTemplateMixin.show`
* :meth:`~jdaviz.core.template_mixin.PluginTemplateMixin.open_in_tray`
* :meth:`~jdaviz.core.template_mixin.PluginTemplateMixin.close_in_tray`
* :meth:`~jdaviz.core.template_mixin.PluginTemplateMixin.clear_table`
* :meth:`~jdaviz.core.template_mixin.PluginTemplateMixin.export_table`
* :meth:`~jdaviz.core.template_mixin.PluginTemplateMixin.zoom_to_selected`
"""
template_file = __file__, "catalogs.vue"
uses_active_status = Bool(True).tag(sync=True)
Expand All @@ -49,7 +52,8 @@ class Catalogs(PluginTemplateMixin, ViewerSelectMixin, HasFileImportSelect, Tabl

@property
def user_api(self):
return PluginUserApi(self, expose=('clear_table', 'export_table',))
return PluginUserApi(self, expose=('clear_table', 'export_table',
'zoom_to_selected'))

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
Expand Down Expand Up @@ -324,23 +328,53 @@ def plot_selected_points(self):
getattr(y, 'value', y))

def vue_zoom_in(self, *args, **kwargs):
"""This function will zoom into the image based on the selected points"""

self.zoom_to_selected(return_bounding_box=True)

def zoom_to_selected(self, padding=50, return_bounding_box=False):
"""
Zoom to a region containing the currently selected points in the catalog.
Parameters
----------
padding : int, optional
The total padding added to the bounding box of the selected points
to define the zoom region, in pixels. This value is added to both
the minimum and maximum coordinates along each axis. Defaults to 50.
return_bounding_box : bool, optional
If True, returns the bounding box of the zoomed region as
((x_min, x_max), (y_min, y_max)). Defaults to False.
Returns
-------
tuple of tuple, optional
If there are activley selected rows, and `return_bounding_box` is
True, returns a tuple containing the bounding
box coordinates: ((x_min, x_max), (y_min, y_max)).
Otherwise, returns None.
"""

selected_rows = self.table.selected_rows

if not len(selected_rows):
return

x = [float(coord['x_coord']) for coord in selected_rows]
y = [float(coord['y_coord']) for coord in selected_rows]

# this works with single selected points
# zooming when the range is too large is not performing correctly
x_min = min(x) - 50
x_max = max(x) + 50
y_min = min(y) - 50
y_max = max(y) + 50
x_min = min(x) - padding
x_max = max(x) + padding
y_min = min(y) - padding
y_max = max(y) + padding

self.app._jdaviz_helper._default_viewer.set_limits(
x_min=x_min, x_max=x_max, y_min=y_min, y_max=y_max)

return (x_min, x_max), (y_min, y_max)
if return_bounding_box:
return (x_min, x_max), (y_min, y_max)

def import_catalog(self, catalog):
"""
Expand Down
65 changes: 64 additions & 1 deletion jdaviz/configs/imviz/tests/test_catalogs.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,12 @@
'''

import numpy as np
from numpy.testing import assert_allclose
import pytest

from astropy.coordinates import SkyCoord
from astropy.io import fits
from astropy.nddata import NDData
from astropy.coordinates import SkyCoord
from astropy.table import Table, QTable


Expand Down Expand Up @@ -257,3 +258,65 @@ def test_offline_ecsv_catalog(imviz_helper, image_2d_wcs, tmp_path):
assert imviz_helper.viewers['imviz-0']._obj.state.x_max == 50.00034
assert imviz_helper.viewers['imviz-0']._obj.state.y_min == -48.99999
assert imviz_helper.viewers['imviz-0']._obj.state.y_max == 51.00001


def test_zoom_to_selected(imviz_helper, image_2d_wcs, tmp_path):

arr = np.ones((500, 500))
ndd = NDData(arr, wcs=image_2d_wcs)
imviz_helper.load_data(ndd)

# write out catalog to file so we can read it back in
# todo: if tables can be loaded directly at some point, do that

# sources at pixel coords ~(100, 100), ~(200, 200)
sky_coord = SkyCoord(ra=[337.49056532, 337.46086081],
dec=[-20.80555273, -20.7777673], unit='deg')
tbl = Table({'sky_centroid': [sky_coord],
'label': ['Source_1', 'Source_2']})
tbl_file = str(tmp_path / 'test_catalog.ecsv')
tbl.write(tbl_file, overwrite=True)

catalogs_plugin = imviz_helper.plugins['Catalog Search']

catalogs_plugin._obj.from_file = tbl_file

catalogs_plugin._obj.search()

# select both sources
catalogs_plugin._obj.table.selected_rows = catalogs_plugin._obj.table.items

# check viewer limits before zoom
xmin, xmax, ymin, ymax = imviz_helper.app._jdaviz_helper._default_viewer.get_limits()
assert xmin == ymin == -0.5
assert xmax == ymax == 499.5

# zoom to selected sources
catalogs_plugin.zoom_to_selected()

# make sure the viewer bounds reflect the zoom, which, in pixel coords,
# should be centered at roughly pixel coords (150, 150)
xmin, xmax, ymin, ymax = imviz_helper.app._jdaviz_helper._default_viewer.get_limits()

assert_allclose((xmin + xmax) / 2, 150., atol=0.1)
assert_allclose((ymin + ymax) / 2, 150., atol=0.1)

# and the zoom box size should reflect the default padding of 50 pixels
# added to/subtracted from x(y) min(max)
assert_allclose(xmax - xmin, 200., atol=0.1)
assert_allclose(ymax - ymin, 200., atol=0.1)

# select one source now
catalogs_plugin._obj.table.selected_rows = catalogs_plugin._obj.table.items[0:1]

# zoom to single selected source, using a new value for 'padding'
catalogs_plugin.zoom_to_selected(padding=25)

# check that zoom window is centered correctly
xmin, xmax, ymin, ymax = imviz_helper.app._jdaviz_helper._default_viewer.get_limits()
assert_allclose((xmin + xmax) / 2, 100., atol=0.1)
assert_allclose((ymin + ymax) / 2, 100., atol=0.1)

# and that the the window size corresponds to the 'padding' chosen
assert_allclose(xmax - xmin, 50., atol=0.1)
assert_allclose(ymax - ymin, 50., atol=0.1)

0 comments on commit 2082f32

Please sign in to comment.