Skip to content

Commit

Permalink
applying changes
Browse files Browse the repository at this point in the history
  • Loading branch information
cshanahan1 committed Nov 20, 2023
1 parent c32ad0e commit 1d62999
Show file tree
Hide file tree
Showing 4 changed files with 446 additions and 57 deletions.
20 changes: 15 additions & 5 deletions jdaviz/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -1014,6 +1014,17 @@ def get_subsets_from_viewer(self, viewer_reference, data_label=None, subset_type

return regions

def _get_wcs_from_subset(self, subset_state):
""" Usually WCS is subset.parent.coords, except special cuebviz case."""

if self.config == 'cubeviz':
parent_data = subset_state.attributes[0].parent
wcs = parent_data.meta.get("_orig_spatial_wcs", None)
else:
wcs = subset_state.xatt.parent.coords

return wcs

def get_subsets(self, subset_name=None, spectral_only=False,
spatial_only=False, object_only=False,
simplify_spectral=True, use_display_units=False,
Expand Down Expand Up @@ -1200,13 +1211,12 @@ def _get_roi_subset_definition(self, subset_state, to_sky=False):
# pixel region
roi_as_region = roi_subset_state_to_region(subset_state)

# pixel region
roi_as_region = roi_subset_state_to_region(subset_state)

wcs = None
if to_sky:
if self.config == 'cubeviz':
parent_data = subset_state.attributes[0].parent
wcs = parent_data.meta.get("_orig_spatial_wcs", None)
else:
wcs = subset_state.xatt.parent.coords # imviz, try getting WCS from subset data
wcs = self._get_wcs_from_subset(subset_state)

# if no spatial wcs on subset, we have to skip computing sky region for this subset
# but want to do so without raising an error (since many subsets could be requested)
Expand Down
156 changes: 105 additions & 51 deletions jdaviz/configs/default/plugins/subset_plugin/subset_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,15 @@
from glue_jupyter.common.toolbar_vuetify import read_icon
from traitlets import Any, List, Unicode, Bool, observe

from jdaviz.core.events import SnackbarMessage, GlobalDisplayUnitChanged
from jdaviz.core.events import SnackbarMessage, GlobalDisplayUnitChanged, LinkUpdatedMessage
from jdaviz.core.registries import tray_registry
from jdaviz.core.template_mixin import PluginTemplateMixin, DatasetSelectMixin, SubsetSelect
from jdaviz.core.tools import ICON_DIR
from jdaviz.utils import MultiMaskSubsetState

from jdaviz.configs.default.plugins.subset_plugin import utils


__all__ = ['SubsetPlugin']

SUBSET_MODES = {
Expand Down Expand Up @@ -76,6 +79,8 @@ def __init__(self, *args, **kwargs):
handler=self._on_subset_update)
self.session.hub.subscribe(self, GlobalDisplayUnitChanged,
handler=self._on_display_unit_changed)
self.session.hub.subscribe(self, LinkUpdatedMessage,
handler=self._on_link_update)

self.subset_select = SubsetSelect(self,
'subset_items',
Expand All @@ -85,6 +90,23 @@ def __init__(self, *args, **kwargs):
self.subset_states = []
self.spectral_display_unit = None

if self.multiselect:
self.display_sky_coordinates = False
else:
self.display_sky_coordinates = (self.app._link_type == 'wcs' if hasattr(self.app, '_link_type') else False)

def _on_link_update(self, *args):
"""When linking is changed pixels<>wcs, change display units of the
subset plugin from pixel (for pixel linking) to sky (for wcs linking).
If there is an active selection in the subset plugin, push this change
to the UI upon link change by calling _get_subset_definition, which
will re-determine how to display subset information."""

self.display_sky_coordinates = (self.app._link_type == 'wcs')

if self.subset_selected != self.subset_select.default_text:
self._get_subset_definition(*args)

def _sync_selected_from_state(self, *args):
if not hasattr(self, 'subset_select') or self.multiselect:
# during initial init, this can trigger before the component is initialized
Expand Down Expand Up @@ -145,7 +167,9 @@ def _unpack_get_subsets_for_ui(self):

subset_information = self.app.get_subsets(self.subset_selected,
simplify_spectral=False,
use_display_units=True)
use_display_units=True,
include_sky_region=True)

_around_decimals = 6 # Avoid 30 degrees from coming back as 29.999999999999996
if not subset_information:
return
Expand All @@ -159,60 +183,69 @@ def _unpack_get_subsets_for_ui(self):
self.is_centerable = False

for spec in subset_information:

subset_definition = []
subset_type = ''
subset_state = spec["subset_state"]
glue_state = spec["glue_state"]

if isinstance(subset_state, RoiSubsetState):
subset_definition.append({
"name": "Parent", "att": "parent",
"value": subset_state.xatt.parent.label,
"orig": subset_state.xatt.parent.label})

if isinstance(subset_state.roi, CircularROI):
x, y = subset_state.roi.center()
r = subset_state.roi.radius
subset_definition += [
{"name": "X Center", "att": "xc", "value": x, "orig": x},
{"name": "Y Center", "att": "yc", "value": y, "orig": y},
{"name": "Radius", "att": "radius", "value": r, "orig": r}]

elif isinstance(subset_state.roi, RectangularROI):
for att in ("Xmin", "Xmax", "Ymin", "Ymax"):
real_att = att.lower()
val = getattr(subset_state.roi, real_att)
subset_definition.append(
{"name": att, "att": real_att, "value": val, "orig": val})
theta = np.around(np.degrees(subset_state.roi.theta), decimals=_around_decimals)
subset_definition.append(
{"name": "Angle", "att": "theta", "value": theta, "orig": theta})

elif isinstance(subset_state.roi, EllipticalROI):
xc, yc = subset_state.roi.center()
rx = subset_state.roi.radius_x
ry = subset_state.roi.radius_y
theta = np.around(np.degrees(subset_state.roi.theta), decimals=_around_decimals)
subset_definition += [
{"name": "X Center", "att": "xc", "value": xc, "orig": xc},
{"name": "Y Center", "att": "yc", "value": yc, "orig": yc},
{"name": "X Radius", "att": "radius_x", "value": rx, "orig": rx},
{"name": "Y Radius", "att": "radius_y", "value": ry, "orig": ry},
{"name": "Angle", "att": "theta", "value": theta, "orig": theta}]

elif isinstance(subset_state.roi, CircularAnnulusROI):
x, y = subset_state.roi.center()
inner_r = subset_state.roi.inner_radius
outer_r = subset_state.roi.outer_radius
subset_definition += [{"name": "X Center", "att": "xc", "value": x, "orig": x},
{"name": "Y Center", "att": "yc", "value": y, "orig": y},
{"name": "Inner radius", "att": "inner_radius",
"value": inner_r, "orig": inner_r},
{"name": "Outer radius", "att": "outer_radius",
"value": outer_r, "orig": outer_r}]
sky_region = spec['sky_region']
if self.display_sky_coordinates and (sky_region is not None):
subset_definition += utils._sky_region_to_subset_def(sky_region)

else:
if isinstance(subset_state.roi, CircularROI):
x, y = subset_state.roi.center()
r = subset_state.roi.radius
subset_definition += [
{"name": "X Center (pixels)", "att": "xc", "value": x, "orig": x},
{"name": "Y Center (pixels)", "att": "yc", "value": y, "orig": y},
{"name": "Radius (pixels)", "att": "radius", "value": r, "orig": r}]

if isinstance(subset_state.roi, RectangularROI):
for att in ("Xmin", "Xmax", "Ymin", "Ymax"):
real_att = att.lower()
val = getattr(subset_state.roi, real_att)
subset_definition.append(
{"name": att + " (pixels)", "att": real_att, "value": val, "orig": val})

theta = np.around(np.degrees(subset_state.roi.theta), decimals=_around_decimals)
subset_definition.append({"name": "Angle", "att": "theta", "value": theta, "orig": theta})

if isinstance(subset_state.roi, EllipticalROI):
xc, yc = subset_state.roi.center()
rx = subset_state.roi.radius_x
ry = subset_state.roi.radius_y
theta = np.around(np.degrees(subset_state.roi.theta), decimals=_around_decimals)

subset_definition += [
{"name": "X Center (pixels)", "att": "xc", "value": xc, "orig": xc},
{"name": "Y Center (pixels)", "att": "yc", "value": yc, "orig": yc},
{"name": "X Radius (pixels)", "att": "radius_x", "value": rx, "orig": rx},
{"name": "Y Radius (pixels)", "att": "radius_y", "value": ry, "orig": ry},
{"name": "Angle", "att": "theta", "value": theta, "orig": theta}]

if isinstance(subset_state.roi, CircularAnnulusROI):
xc, yc = subset_state.roi.center()
inner_r = subset_state.roi.inner_radius
outer_r = subset_state.roi.outer_radius
display_labels = '(pixels)'
subset_definition += [{"name": "X Center (pixels)", "att": "xc", "value": xc, "orig": xc},
{"name": "Y Center (pixels)", "att": "yc", "value": yc, "orig": yc},
{"name": "Inner Radius (pixels)", "att": "inner_radius",
"value": inner_r, "orig": inner_r},
{"name": "Outer Radius (pixels)", "att": "outer_radius",
"value": outer_r, "orig": outer_r}]

subset_type = subset_state.roi.__class__.__name__

elif isinstance(subset_state, RangeSubsetState):
if isinstance(subset_state, RangeSubsetState):
region = spec['region']
if isinstance(region, Time):
lo = region.min()
Expand All @@ -230,7 +263,7 @@ def _unpack_get_subsets_for_ui(self):
"orig": hi.value, "unit": str(hi.unit)}]
subset_type = "Range"

elif isinstance(subset_state, MultiMaskSubsetState):
if isinstance(subset_state, MultiMaskSubsetState):
total_masked = subset_state.total_masked_first_data()
subset_definition = [{"name": "Masked values", "att": "masked",
"value": total_masked,
Expand Down Expand Up @@ -303,12 +336,11 @@ def _on_display_unit_changed(self, msg):
self._get_subset_definition(self.subset_selected)

def vue_update_subset(self, *args):

if self.multiselect:
self.hub.broadcast(SnackbarMessage("Cannot update subset "
"when multiselect is active", color='warning',
sender=self))
return

status, reason = self._check_input()
if not status:
self.hub.broadcast(SnackbarMessage(reason, color='error', sender=self))
Expand All @@ -318,12 +350,34 @@ def vue_update_subset(self, *args):
if len(self.subset_states) <= index:
return
sub_states = self.subset_states[index]

# we need to push updates to subset in pixels. to do this when wcs
# linked, convert the new input subset parameters from sky to pix
wcs = None

if self.display_sky_coordinates:
wcs = self.app._get_wcs_from_subset(sub_states)

if wcs is not None:
# convert newly entered sky coords to pixel
print(f'self.subset_types[index] is {self.subset_types[index]}!!!')
skyregion = utils._subset_def_to_region(self.subset_types[index], sub)
new = utils._get_pixregion_params_in_dict(skyregion.to_pixel(wcs))
# convert previous entered sky coords to pixel
new_orig_skyregion = utils._subset_def_to_region(self.subset_types[index], sub, val='orig')
new_orig = utils._get_pixregion_params_in_dict(new_orig_skyregion.to_pixel(wcs))

for d_att in sub:
if d_att["att"] == 'parent': # Read-only
continue

if d_att["att"] == 'theta': # Humans use degrees but glue uses radians
d_val = np.radians(d_att["value"])
if self.display_sky_coordinates and (wcs is not None):
d_att["value"] = new[d_att["att"]]
d_att["orig"] = new_orig[d_att["att"]]

if (d_att["att"] == 'theta') and (self.display_sky_coordinates is False):
# Humans use degrees but glue uses radians
# We've already enforced this in wcs linking in _get_pixregion_params_in_dict
d_val = (d_att["value"]*u.deg).to(u.rad).value
else:
d_val = float(d_att["value"])

Expand All @@ -342,6 +396,7 @@ def vue_update_subset(self, *args):
setattr(sub_states, d_att["att"], d_val)
else:
setattr(sub_states.roi, d_att["att"], d_val)

self._push_update_to_ui()

def _push_update_to_ui(self, subset_name=None):
Expand Down Expand Up @@ -422,7 +477,7 @@ def vue_recenter_subset(self, *args):

def _do_recentering(subset, subset_state):
try:
reg = _get_region_from_spatial_subset(self, subset_state) # noqa
reg = _get_region_from_spatial_subset(self, subset_state) # noqa
aperture = regions2aperture(reg)
data = self.dataset.selected_dc_item
comp = data.get_component(data.main_components[0])
Expand All @@ -439,7 +494,6 @@ def _do_recentering(subset, subset_state):
subset_state.xatt.parent.coords,
phot_aperstats.xcentroid,
phot_aperstats.ycentroid)

else:
x = phot_aperstats.xcentroid
y = phot_aperstats.ycentroid
Expand Down
Loading

0 comments on commit 1d62999

Please sign in to comment.