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

Update 1D Profile viewer to use wcsaxes - Add slice function to 1D Profile viewer with sliders to select point #2248

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from
Draft
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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,5 @@ glue/qt/glue_qt_resources.py
.vscode
# vscode plugin
.history

.qt_for_python/
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
4 changes: 2 additions & 2 deletions glue/core/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,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 +1659,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 Down
23 changes: 23 additions & 0 deletions glue/utils/wcs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from astropy.wcs import WCS


def get_identity_wcs(naxis):
"""
Create a WCS object with an identity transform.

Parameters
----------
naxis : float
The number of axes.

Returns
-------
`astropy.wcs.WCS`
A WCS object with an identity transform.
"""
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
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
3 changes: 2 additions & 1 deletion glue/viewers/image/qt/slice_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

class MultiSliceWidgetHelper(object):

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

self.viewer_state = viewer_state

Expand Down Expand Up @@ -56,6 +56,7 @@ def sync_state_from_sliders(self, *args):
else:
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):
Expand Down
14 changes: 1 addition & 13 deletions glue/viewers/image/viewer.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import os

from astropy.wcs import WCS

from glue.core.subset import roi_to_subset_state
from glue.core.coordinates import Coordinates, LegacyCoordinates
from glue.core.coordinate_helpers import dependent_axes
Expand All @@ -12,21 +10,11 @@

from glue.viewers.image.frb_artist import imshow
from glue.viewers.image.composite_array import CompositeArray
from glue.utils.wcs import get_identity_wcs

__all__ = ['MatplotlibImageMixin']


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


EXTRA_FOOTER = """
# Set tick label size - for now tick_params (called lower down) doesn't work
# properly, but these lines won't be needed in future.
Expand Down
17 changes: 8 additions & 9 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,9 +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)

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

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

@defer_draw
Expand All @@ -51,7 +49,7 @@ def _calculate_profile_thread(self, reset=False):
warnings.simplefilter("ignore")
if reset:
self.state.reset_cache()
self.state.update_profile(update_limits=False)
self.state.update_profile(update_limits=True)

def _calculate_profile_postthread(self):

Expand Down Expand Up @@ -122,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 @@ -131,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', 'as_steps')):
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: 32 additions & 9 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,24 +35,45 @@ 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_attribute_change(self, *args):
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()
# Has to be set to None otherwise it will re-appear for other functions
self.profile_slice_helper = None

def _on_attribute_change(self, *args):
if (self.viewer_state.reference_data is None or
self.viewer_state.x_att_pixel is None or
self.viewer_state.x_att is self.viewer_state.x_att_pixel):
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 world_warning:
self.ui.text_warning.show()
self.ui.text_warning.setText(WARNING_TEXT.format(label=self.viewer_state.x_att.label))
else:
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
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