Skip to content

Commit

Permalink
Update 1D Profile viewer to use wcsaxes for plotting and add sliders
Browse files Browse the repository at this point in the history
  • Loading branch information
Kris Stern authored and nabobalis committed Feb 7, 2022
1 parent 2d64631 commit 7775633
Show file tree
Hide file tree
Showing 17 changed files with 331 additions and 66 deletions.
4 changes: 2 additions & 2 deletions glue/app/qt/layer_tree_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,14 +197,14 @@ class DeleteAction(LayerAction):

def _can_trigger(self):
selection = self.selected_layers()
return all(isinstance(s, (core.Data, core.SubsetGroup))
return all(isinstance(s, (core.BaseData, core.SubsetGroup))
for s in selection)

def _do_action(self):
assert self._can_trigger()
selection = self.selected_layers()
for s in selection:
if isinstance(s, core.Data):
if isinstance(s, core.BaseData):
self._layer_tree.data_collection.remove(s)
else:
assert isinstance(s, core.SubsetGroup)
Expand Down
8 changes: 5 additions & 3 deletions glue/core/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@
from glue.core.contracts import contract
from glue.core.joins import get_mask_with_key_joins
from glue.config import settings, data_translator, subset_state_translator
from glue.utils import (compute_statistic, unbroadcast, iterate_chunks,
from glue.utils import (compute_statistic,
unbroadcast, iterate_chunks,
datetime64_to_mpl, broadcast_to, categorical_ndarray,
format_choices, random_views_for_dask_array)
from glue.core.coordinate_helpers import axis_label
Expand Down Expand Up @@ -241,7 +242,7 @@ def add_subset(self, subset, label=None):
if subset.data is not self:
subset.do_broadcast(False)
subset.data = self
subset.label = subset.label # hacky. disambiguates name if needed
subset.label = subset.label # hacky, disambiguates name if needed

if self.hub is not None:
msg = SubsetCreateMessage(subset)
Expand Down Expand Up @@ -1659,7 +1660,7 @@ def compute_statistic(self, statistic, cid, subset_state=None, axis=None,
# from glue.core.link_manager import pixel_cid_to_pixel_cid_matrix
# for att in subset_state.attributes:
# # TODO: in principle we cold still deal with non-pixel
# # componnet IDs, so this should be fixed.
# # component IDs, so this should be fixed.
# if not isinstance(att, PixelComponentID):
# break
# matrix = pixel_cid_to_pixel_cid_matrix(att.parent, self)
Expand All @@ -1686,6 +1687,7 @@ def compute_statistic(self, statistic, cid, subset_state=None, axis=None,
values = self.compute_statistic(statistic, cid, subset_state=subset_state,
axis=axis, finite=finite, positive=positive,
percentile=percentile, view=chunk_view)

result[chunk_view[axis_index]] = values

return result
Expand Down
12 changes: 12 additions & 0 deletions glue/utils/wcs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from astropy.wcs import WCS


def get_identity_wcs(naxis):

wcs = WCS(naxis=naxis)
wcs.wcs.ctype = ['X'] * naxis
wcs.wcs.crval = [0.] * naxis
wcs.wcs.crpix = [1.] * naxis
wcs.wcs.cdelt = [1.] * naxis

return wcs
3 changes: 2 additions & 1 deletion glue/viewers/common/qt/data_slice_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def __init__(self, label='', world=None, lo=0, hi=10,
parent=None, world_unit=None,
world_warning=False):

super(SliceWidget, self).__init__(parent)
super(SliceWidget, self).__init__(parent=parent)

self.state = SliceState()
self.state.label = label
Expand Down Expand Up @@ -109,6 +109,7 @@ def __init__(self, label='', world=None, lo=0, hi=10,

def set_label_from_slider(self):
value = self.state.slice_center

if self.state.use_world:
value = self._world[value]
if self._world_warning:
Expand Down
3 changes: 2 additions & 1 deletion glue/viewers/image/qt/data_viewer.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ class ImageViewer(MatplotlibImageMixin, MatplotlibDataViewer):

tools = ['select:rectangle', 'select:xrange',
'select:yrange', 'select:circle',
'select:polygon', 'image:point_selection', 'image:contrast_bias',
'select:polygon', 'image:point_selection',
'image:contrast_bias',
'profile-viewer']

def __init__(self, session, parent=None, state=None):
Expand Down
4 changes: 3 additions & 1 deletion glue/viewers/image/qt/options_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,12 @@ def __init__(self, viewer_state, session, parent=None):

self.viewer_state = viewer_state

self.session = session

self.slice_helper = MultiSliceWidgetHelper(viewer_state=self.viewer_state,
session=self.session,
layout=self.ui.layout_slices)

self.session = session
self.ui.axes_editor.button_apply_all.clicked.connect(self._apply_all_viewers)

def _apply_all_viewers(self):
Expand Down
1 change: 0 additions & 1 deletion glue/viewers/image/qt/profile_viewer_tool.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ def activate(self):
# be a pixel attribute or world attribute depending on what information
# is available in the coordinates, so we need to be careful about that.

x_att = profile_viewer.state.x_att
reference_data = self.viewer.state.reference_data

if isinstance(profile_viewer.state.x_att, PixelComponentID):
Expand Down
8 changes: 6 additions & 2 deletions glue/viewers/image/qt/slice_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@
from glue.viewers.image.state import AggregateSlice
from glue.utils.decorators import avoid_circular


__all__ = ['MultiSliceWidgetHelper']


class MultiSliceWidgetHelper(object):

def __init__(self, viewer_state=None, layout=None):
def __init__(self, viewer_state=None, layout=None, *args, **kwargs):

self.viewer_state = viewer_state

Expand Down Expand Up @@ -57,9 +58,10 @@ def sync_state_from_sliders(self, *args):
slices.append(self.viewer_state.slices[i])
self.viewer_state.slices = tuple(slices)

self._reference_data = self.viewer_state.reference_data

@avoid_circular
def sync_sliders_from_state(self, *args):

if self.data is None or self.viewer_state.x_att is None or self.viewer_state.y_att is None:
return

Expand Down Expand Up @@ -94,6 +96,7 @@ def sync_sliders_from_state(self, *args):
pixel_axis=world_axis_index,
world_axis=world_axis_index)
world_unit = self.data.coords.world_axis_units[world_axis_index]

world_warning = len(dependent_axes(self.data.coords, i)) > 1
world_label = self.data.world_component_ids[i].label
else:
Expand All @@ -107,6 +110,7 @@ def sync_sliders_from_state(self, *args):
world_unit=world_unit, world_warning=world_warning)

self.slider_state = slider.state

self.slider_state.add_callback('slice_center', self.sync_state_from_sliders)
self._sliders.append(slider)
self.layout.addWidget(slider)
Expand Down
15 changes: 8 additions & 7 deletions glue/viewers/profile/layer_artist.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

from matplotlib.lines import Line2D


from glue.core import BaseData
from glue.utils import defer_draw
from glue.viewers.profile.state import ProfileLayerState
Expand All @@ -27,8 +26,8 @@ def __init__(self, axes, viewer_state, layer_state=None, layer=None):
self._viewer_state.add_global_callback(self._update_profile)
self.state.add_global_callback(self._update_profile)

self.plot_artist = self.axes.plot([1, 2, 3], [3, 4, 5], 'k-', drawstyle='steps-mid')[0]

self.plot_artist = self.axes.plot([1, 2, 3], [3, 4, 5], 'k-', drawstyle='steps-mid',
color=self.state.layer.style.color)[0]
self.mpl_artists = [self.plot_artist]

@defer_draw
Expand All @@ -46,6 +45,7 @@ def _calculate_profile_thread(self, reset=False):
# otherwise the thread tries to send these to the glue logger (which
# uses Qt), which then results in this kind of error:
# QObject::connect: Cannot queue arguments of type 'QTextCursor'

with warnings.catch_warnings():
warnings.simplefilter("ignore")
if reset:
Expand Down Expand Up @@ -120,7 +120,7 @@ def _update_visual_attributes(self):

def _update_profile(self, force=False, **kwargs):

if (self._viewer_state.x_att is None or
if (self._viewer_state.x_att_pixel is None or
self.state.attribute is None or
self.state.layer is None):
return
Expand All @@ -129,9 +129,10 @@ def _update_profile(self, force=False, **kwargs):
# of updated properties is up to date after this method has been called.
changed = self.pop_changed_properties()

if force or any(prop in changed for prop in ('layer', 'x_att', 'attribute', 'function', 'normalize', 'v_min', 'v_max', 'visible')):
self._calculate_profile(reset=force)
force = True
if force or any(prop in changed for prop in ('layer', 'slices', 'x_att', 'x_att_pixel', 'attribute',
'function', 'normalize', 'v_min', 'v_max', 'visible')):
self._update_visual_attributes()
self._calculate_profile(reset=True)

if force or any(prop in changed for prop in ('alpha', 'color', 'zorder', 'linewidth')):
self._update_visual_attributes()
Expand Down
2 changes: 1 addition & 1 deletion glue/viewers/profile/qt/data_viewer.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,5 @@ class ProfileViewer(MatplotlibProfileMixin, MatplotlibDataViewer):
tools = ['select:xrange', 'profile-analysis']

def __init__(self, session, parent=None, state=None):
MatplotlibDataViewer.__init__(self, session, parent=parent, state=state)
MatplotlibDataViewer.__init__(self, session, parent=parent, wcs=True, state=state)
MatplotlibProfileMixin.setup_callbacks(self)
41 changes: 34 additions & 7 deletions glue/viewers/profile/qt/options_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
from glue.core.coordinate_helpers import dependent_axes
from echo.qt import autoconnect_callbacks_to_qt
from glue.utils.qt import load_ui, fix_tab_widget_fontsize
from glue.viewers.profile.qt.slice_widget import ProfileMultiSliceWidgetHelper
from glue.viewers.matplotlib.state import MatplotlibDataViewerState

__all__ = ['ProfileOptionsWidget']

Expand Down Expand Up @@ -33,10 +35,28 @@ def __init__(self, viewer_state, session, parent=None):

self.session = session

self.profile_slice_helper = None

self.viewer_state.add_callback('function', self._on_function_change)
self.viewer_state.add_callback('x_att', self._on_attribute_change)

self.ui.text_warning.hide()

self.ui.axes_editor.button_apply_all.clicked.connect(self._apply_all_viewers)

def _on_function_change(self, *args):

if self.viewer_state.function == 'slice':
self.profile_slice_helper = ProfileMultiSliceWidgetHelper(viewer_state=self.viewer_state,
session=self.session,
layout=self.ui.layout_slices)
self.ui.text_warning.hide()
self.ui.text_warning.setText('')

else:
if self.profile_slice_helper:
self.profile_slice_helper.remove()

def _on_attribute_change(self, *args):

if (self.viewer_state.reference_data is None or
Expand All @@ -45,12 +65,19 @@ def _on_attribute_change(self, *args):
self.ui.text_warning.hide()
return

world_warning = len(dependent_axes(self.viewer_state.reference_data.coords,
self.viewer_state.x_att_pixel.axis)) > 1
if self.viewer_state.function != 'slice':

world_warning = len(dependent_axes(self.viewer_state.reference_data.coords,
self.viewer_state.x_att_pixel.axis)) > 1

if world_warning:
self.ui.text_warning.show()
self.ui.text_warning.setText(WARNING_TEXT.format(label=self.viewer_state.x_att.label))
else:
self.ui.text_warning.hide()
self.ui.text_warning.setText('')

if world_warning:
self.ui.text_warning.show()
self.ui.text_warning.setText(WARNING_TEXT.format(label=self.viewer_state.x_att.label))

def _apply_all_viewers(self):
for tab in self.session.application.viewers:
for viewer in tab:
if isinstance(viewer.state, MatplotlibDataViewerState):
viewer.state.update_axes_settings_from(self.viewer_state)
6 changes: 6 additions & 0 deletions glue/viewers/profile/qt/options_widget.ui
Original file line number Diff line number Diff line change
Expand Up @@ -167,13 +167,19 @@
</property>
</widget>
</item>

<item row="6" column="0" colspan="3">
<layout class="QVBoxLayout" name="layout_slices"/>
</item>

<item row="1" column="1" colspan="2">
<widget class="QComboBox" name="combosel_reference_data">
<property name="sizeAdjustPolicy">
<enum>QComboBox::AdjustToMinimumContentsLength</enum>
</property>
</widget>
</item>

<item row="6" column="0">
<spacer name="verticalSpacer_2">
<property name="orientation">
Expand Down
Loading

0 comments on commit 7775633

Please sign in to comment.