Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Subsets tools API hints #3325

Merged
merged 5 commits into from
Dec 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ API Changes
-----------
- Removed API access to plugins that have passed the deprecation period: Links Control, Canvas Rotation, Export Plot. [#3270]

- Subset Tools plugin now exposes the ``subset``, ``combination_mode``, ``get_center``, and ``set_center`` in the user API. [#3293, #3304]
- Subset Tools plugin now exposes the ``subset``, ``combination_mode``, ``recenter_dataset``,
``recenter``, ``get_center``, and ``set_center`` in the user API. [#3293, #3304, #3325]

- Metadata plugin: ``metadata_plugin.metadata`` API has been deprecated; use
``metadata_plugin.meta`` instead, which will return a Python dictionary instead of
Expand Down
30 changes: 25 additions & 5 deletions jdaviz/configs/default/plugins/subset_tools/subset_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
from jdaviz.core.region_translators import regions2roi, aperture2regions
from jdaviz.core.events import SnackbarMessage, GlobalDisplayUnitChanged, LinkUpdatedMessage
from jdaviz.core.registries import tray_registry
from jdaviz.core.template_mixin import (PluginTemplateMixin, DatasetSelectMixin,
from jdaviz.core.template_mixin import (PluginTemplateMixin, DatasetSelect,
SubsetSelect, SelectPluginComponent)
from jdaviz.core.tools import ICON_DIR
from jdaviz.core.user_api import PluginUserApi
Expand Down Expand Up @@ -63,7 +63,7 @@


@tray_registry('g-subset-tools', label="Subset Tools")
class SubsetTools(PluginTemplateMixin, DatasetSelectMixin):
class SubsetTools(PluginTemplateMixin):
"""
See the :ref:`Subset Tools <imviz-subset-plugin>` for more details.

Expand All @@ -77,6 +77,9 @@
Manages subset selection and creation
* ``combination_mode`` (:class:`~jdaviz.core.template_mixin.SelectPluginComponent`):
Allows selection of combination modes for subsets
* ``recenter_dataset`` (:class:`~jdaviz.core.template_mixin.DatasetSelect`):
Data used for recentering.
* :meth:`recenter`
* :meth:`get_center`
* :meth:`set_center`
* :meth:`import_region`
Expand All @@ -93,6 +96,9 @@
glue_state_types = List([]).tag(sync=True)
has_subset_details = Bool(False).tag(sync=True)

recenter_dataset_items = List().tag(sync=True)
recenter_dataset_selected = Unicode().tag(sync=True)

subplugins_opened = Any().tag(sync=True)

multiselect = Bool(False).tag(sync=True) # multiselect only for subset
Expand Down Expand Up @@ -148,14 +154,21 @@
align_by = getattr(self.app, '_align_by', None)
self.display_sky_coordinates = (align_by == 'wcs' and not self.multiselect)

self.recenter_dataset = DatasetSelect(self, 'recenter_dataset_items',
'recenter_dataset_selected',
multiselect=None)

self.combination_mode = SelectPluginComponent(self,
items='combination_items',
selected='combination_selected',
manual_options=COMBO_OPTIONS)

@property
def user_api(self):
expose = ['subset', 'combination_mode', 'get_center', 'set_center', 'import_region']
expose = ['subset', 'combination_mode',
'recenter_dataset', 'recenter',
'get_center', 'set_center',
'import_region']
return PluginUserApi(self, expose)

def _on_link_update(self, *args):
Expand Down Expand Up @@ -556,7 +569,11 @@

return status, reason

def vue_recenter_subset(self, *args):
def recenter(self):
"""
Recenter the selected subset on the centroid of the region of the current subset
in the selected data layer.
"""
# Composite region cannot be centered. This only works for Imviz.
if not self.is_centerable or self.config != 'imviz': # no-op
raise NotImplementedError(
Expand All @@ -570,7 +587,7 @@
try:
reg = _get_region_from_spatial_subset(self, subset_state)
aperture = regions2aperture(reg)
data = self.dataset.selected_dc_item
data = self.recenter_dataset.selected_dc_item
comp = data.get_component(data.main_components[0])
comp_data = comp.data
phot_aperstats = ApertureStats(comp_data, aperture, wcs=data.coords)
Expand Down Expand Up @@ -613,6 +630,9 @@
f"composite subset {sub}",
color='error', sender=self))

def vue_recenter_subset(self, *args):
self.recenter()

Check warning on line 634 in jdaviz/configs/default/plugins/subset_tools/subset_tools.py

View check run for this annotation

Codecov / codecov/patch

jdaviz/configs/default/plugins/subset_tools/subset_tools.py#L634

Added line #L634 was not covered by tests

def _get_subset_state(self, subset_name=None):
if self.multiselect and not subset_name:
raise ValueError("Please include subset_name in when in multiselect mode")
Expand Down
51 changes: 48 additions & 3 deletions jdaviz/configs/default/plugins/subset_tools/subset_tools.vue
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
<template>
<j-tray-plugin
:config="config"
plugin_key="Subset Tools"
:api_hints_enabled.sync="api_hints_enabled"
:description="docs_description"
:link="docs_link || 'https://jdaviz.readthedocs.io/en/'+vdocs+'/'+config+'/plugins.html#subset-tools'"
:popout_button="popout_button"
:scroll_to.sync="scroll_to">

<v-row v-if="api_hints_enabled && config === 'imviz'">
<span class="api-hint">
plg.subset.multiselect = {{ boolToString(multiselect) }}
</span>
</v-row>
<v-row v-if="config === 'imviz'">
<div style="width: calc(100% - 32px)">
</div>
Expand All @@ -29,6 +37,8 @@
:multiselect="multiselect"
:show_if_single_entry="true"
label="Subset"
api_hint="plg.subset ="
:api_hints_enabled="api_hints_enabled"
hint="Select subset to edit."
/>
</v-col>
Expand All @@ -40,6 +50,12 @@
</v-col>
</v-row>

<v-row v-if="api_hints_enabled" style="margin-top: -32px">
<span class="api-hint">
plg.combination_mode = '{{ combination_selected }}'
</span>
</v-row>

<!-- Sub-plugin for recentering of spatial subset (Imviz only) -->
<v-row v-if="config=='imviz' && is_centerable">
<v-expansion-panels accordion v-model="subplugins_opened">
Expand All @@ -49,14 +65,29 @@
</v-expansion-panel-header>
<v-expansion-panel-content class="plugin-expansion-panel-content">
<plugin-dataset-select
:items="dataset_items"
:selected.sync="dataset_selected"
:items="recenter_dataset_items"
:selected.sync="recenter_dataset_selected"
:show_if_single_entry="true"
label="Data"
api_hint="plg.recenter_dataset ="
:api_hints_enabled="api_hints_enabled"
hint="Select the data for centroiding."
/>
<v-row justify="end" no-gutters>
<v-btn color="primary" text @click="recenter_subset">Recenter</v-btn>
<j-tooltip tooltipcontent="Recenter subset to centroid of selected data">
<v-btn
color="primary"
text
@click="recenter_subset"
:class="api_hints_enabled ? 'api-hint' : null"
>
{{ api_hints_enabled ?
'plg.recenter()'
:
'Recenter'
}}
</v-btn>
</j-tooltip>
</v-row>
</v-expansion-panel-content>
</v-expansion-panel>
Expand Down Expand Up @@ -146,3 +177,17 @@
</v-row>
</j-tray-plugin>
</template>

<script>
module.exports = {
methods: {
boolToString(b) {
if (b) {
return 'True'
} else {
return 'False'
}
},
}
}
</script>
38 changes: 19 additions & 19 deletions jdaviz/configs/imviz/tests/test_subset_centroid.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,26 +9,26 @@
class TestImvizSpatialSubsetCentroidPixelLinked(BaseImviz_WCS_GWCS):
def test_centroiding_pixel(self):
reg = CirclePixelRegion(PixCoord(2, 2), 3)
plg = self.imviz.plugins['Subset Tools']._obj
plg = self.imviz.plugins['Subset Tools']
plg.import_region(reg)

plg.subset_selected = 'Subset 1'
plg.subset = 'Subset 1'

# Since they are linked by pixels, the bright corner pixel aligns
# and nothing should change.
for data_label in ('fits_wcs[DATA]', 'gwcs[DATA]'):
plg.dataset_selected = data_label
plg.recenter_dataset = data_label
plg.set_center((2, 2), update=True) # Move the Subset back first.
plg.vue_recenter_subset()
plg.recenter()

# Calculate and move to centroid.
for key in ("X Center (pixels)", "Y Center (pixels)"):
assert plg._get_value_from_subset_definition(0, key, "value") == -1
assert plg._get_value_from_subset_definition(0, key, "orig") == -1
assert plg._obj._get_value_from_subset_definition(0, key, "value") == -1
assert plg._obj._get_value_from_subset_definition(0, key, "orig") == -1

# Radius will not be touched.
for key in ("value", "orig"):
assert plg._get_value_from_subset_definition(0, "Radius (pixels)", key) == 3
assert plg._obj._get_value_from_subset_definition(0, "Radius (pixels)", key) == 3

assert plg.get_center() == (-1, -1)

Expand All @@ -40,34 +40,34 @@ def test_centroiding_wcs(self):
self.imviz.link_data(align_by='wcs')

reg = CirclePixelRegion(PixCoord(2, 2), 3).to_sky(self.wcs_1)
plg = self.imviz.plugins['Subset Tools']._obj
plg = self.imviz.plugins['Subset Tools']
plg.import_region(reg)

plg.subset_selected = 'Subset 1'
plg.dataset_selected = 'fits_wcs[DATA]'
plg.vue_recenter_subset()
plg.subset = 'Subset 1'
plg.recenter_dataset = 'fits_wcs[DATA]'
plg.recenter()

# Pixel value is now w.r.t. fake WCS layer, not the selected data.
for key in ("value", "orig"):
# subset definition is now in sky coordinates. get RA and Dec and convert back to pixel
# to compare with expected recentered position.
ra = plg._get_value_from_subset_definition(0, "RA Center (degrees)", key) * u.deg
dec = plg._get_value_from_subset_definition(0, "Dec Center (degrees)", key) * u.deg
ra = plg._obj._get_value_from_subset_definition(0, "RA Center (degrees)", key) * u.deg
dec = plg._obj._get_value_from_subset_definition(0, "Dec Center (degrees)", key) * u.deg
x, y = SkyCoord(ra, dec).to_pixel(self.wcs_1)
assert_allclose((x, y), -1)

# GWCS does not extrapolate and this Subset is out of bounds,
# so will get NaNs and enter the exception handling logic.
plg.dataset_selected = 'gwcs[DATA]'
plg.recenter_dataset = 'gwcs[DATA]'
plg.set_center((2.6836, 1.6332), update=True) # Move the Subset back first.
plg.vue_recenter_subset()
plg.recenter()
subsets = self.imviz.app.get_subsets(include_sky_region=True)
subsets_sky = subsets['Subset 1'][0]['sky_region']
subsets_pix = subsets['Subset 1'][0]['region']
assert_allclose((subsets_pix.center.x, subsets_pix.center.y), (2.6836, 1.6332))
for key in ("value", "orig"):
ra = plg._get_value_from_subset_definition(0, "RA Center (degrees)", key)
dec = plg._get_value_from_subset_definition(0, "Dec Center (degrees)", key)
ra = plg._obj._get_value_from_subset_definition(0, "RA Center (degrees)", key)
dec = plg._obj._get_value_from_subset_definition(0, "Dec Center (degrees)", key)

# make sure what is in subset_definitions matches what is returned by get_subsets
assert_allclose((ra, dec), (subsets_sky.center.ra.deg, subsets_sky.center.dec.deg))
Expand All @@ -77,8 +77,8 @@ def test_centroiding_wcs(self):
# vue_update_subset is called.
plg.set_center((2, 2), update=False)
for key in ("value", "orig"):
ra = plg._get_value_from_subset_definition(0, "RA Center (degrees)", key)
dec = plg._get_value_from_subset_definition(0, "Dec Center (degrees)", key)
ra = plg._obj._get_value_from_subset_definition(0, "RA Center (degrees)", key)
dec = plg._obj._get_value_from_subset_definition(0, "Dec Center (degrees)", key)
# here 'ra' and 'dec' should remain unchanged from when they were defined, since
# vue_update_subset hasn't run
assert_allclose((ra, dec), (subsets_sky.center.ra.deg, subsets_sky.center.dec.deg))
12 changes: 6 additions & 6 deletions jdaviz/tests/test_subsets.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def test_region_from_subset_2d(cubeviz_helper):
assert_allclose(reg.height, 6.6)
assert_allclose(reg.angle.value, 0)

assert subset_plugin._obj.subset_selected == "Subset 1"
assert subset_plugin.subset == "Subset 1"
assert subset_plugin._obj.subset_types == ["EllipticalROI"]
assert subset_plugin._obj.is_centerable
for key in ("orig", "value"):
Expand All @@ -52,7 +52,7 @@ def test_region_from_subset_2d(cubeviz_helper):

# Recenter GUI should not be exposed, but API call would raise exception.
with pytest.raises(NotImplementedError, match='Cannot recenter'):
subset_plugin._obj.vue_recenter_subset()
subset_plugin.recenter()


def test_region_from_subset_3d(cubeviz_helper):
Expand Down Expand Up @@ -430,12 +430,12 @@ def test_recenter_linked_by_wcs(imviz_helper):
RectanglePixelRegion(center=PixCoord(x=229, y=152), width=17, height=7).to_sky(w))

subset_plugin = imviz_helper.plugins['Subset Tools']
subset_plugin._obj.subset_selected = "Subset 1"
subset_plugin._obj.dataset_selected = "gauss100_fits_wcs_block_reduced[PRIMARY,1]"
subset_plugin.subset = "Subset 1"
subset_plugin.recenter_dataset = "gauss100_fits_wcs_block_reduced[PRIMARY,1]"

# Do it a few times to converge.
for _ in range(5):
subset_plugin._obj.vue_recenter_subset()
subset_plugin.recenter()

# If handled correctly, it won't change much.
# But if not, it move down by 7 pix or so (229.05, 145.92) and fails the test.
Expand All @@ -453,7 +453,7 @@ def test_recenter_linked_by_wcs(imviz_helper):

# Do it a few times to converge.
for _ in range(5):
subset_plugin._obj.vue_recenter_subset()
subset_plugin._obj.recenter()

xy = imviz_helper.default_viewer._obj._get_real_xy(
imviz_helper.app.data_collection[0], *subset_plugin.get_center("Subset 2"))[:2]
Expand Down
Loading