diff --git a/CHANGES.md b/CHANGES.md index 653b1754c..38919d6a9 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -6,6 +6,9 @@ v0.6 (unreleased) * Added a GUI plugin manager in the 'Plugins' menu. [#682] +* Added an option to specify whether to use an automatic aspect ratio for image + data or whether to enforce square pixels. [#717] + * Data factories can now be given priorities to determine which ones should take precedence in ambiguous cases. The ``set_default_factory`` and ``get_default_factory`` functions are now deprecated since it is possible to diff --git a/glue/clients/image_client.py b/glue/clients/image_client.py index 8f8260e53..d52a72f2a 100644 --- a/glue/clients/image_client.py +++ b/glue/clients/image_client.py @@ -36,8 +36,10 @@ def result(*args, **kwargs): class ImageClient(VizClient): + display_data = CallbackProperty(None) display_attribute = CallbackProperty(None) + display_aspect = CallbackProperty(None) def __init__(self, data, artist_container=None): @@ -327,14 +329,17 @@ def _update_data_plot(self, relim=False, force=False): self._view = view for a in list(self.artists): - if (not isinstance(a, ScatterLayerBase)) and \ - a.layer.data is not self.display_data: + if (not isinstance(a, ScatterLayerBase) and + a.layer.data is not self.display_data): self.artists.remove(a) else: - a.update(view, transpose) + if isinstance(a, ScatterLayerBase): + a.update(view, transpose) + else: + a.update(view, transpose, aspect=self.display_aspect) for a in self.artists[self.display_data]: meth = a.update if not force else a.force_update - meth(view, transpose=transpose) + meth(view, transpose=transpose, aspect=self.display_aspect) def _update_subset_single(self, s, redraw=False, force=False): """ @@ -464,6 +469,10 @@ def rgb_mode(self, enable=None): self._redraw() return result + def update_aspect(self): + self._update_data_plot(relim=True) + self._redraw() + def add_layer(self, layer): if layer in self.artists: return self.artists[layer][0] diff --git a/glue/clients/layer_artist.py b/glue/clients/layer_artist.py index d61cfab22..d9a5e2b94 100644 --- a/glue/clients/layer_artist.py +++ b/glue/clients/layer_artist.py @@ -452,7 +452,11 @@ def _update_clip(self, att): data = small_view_array(self._override_image) self.norm.update_clip(data) - def update(self, view, transpose=False): + def update(self, view, transpose=False, aspect=None): + + if aspect is None: + aspect = 'equal' + self.clear() views = view_cascade(self.layer, view) artists = [] @@ -470,7 +474,7 @@ def update(self, view, transpose=False): interpolation='nearest', origin='lower', extent=extent, zorder=0)) - self._axes.set_aspect('equal', adjustable='datalim') + self._axes.set_aspect(aspect, adjustable='datalim') self.artists = artists self._sync_style() @@ -541,8 +545,13 @@ def set_norm(self, *args, **kwargs): self.norm = self.bnorm self.bnorm = spr(*args, **kwargs) - def update(self, view=None, transpose=False): + def update(self, view=None, transpose=False, aspect=None): + self.clear() + + if aspect is None: + aspect = 'equal' + if self.r is None or self.g is None or self.b is None: return @@ -591,7 +600,7 @@ def update(self, view=None, transpose=False): interpolation='nearest', origin='lower', extent=extent, zorder=0)) - self._axes.set_aspect('equal', adjustable='datalim') + self._axes.set_aspect(aspect, adjustable='datalim') self.artists = artists self._sync_style() diff --git a/glue/qt/ui/imagewidget.ui b/glue/qt/ui/imagewidget.ui index b1037d1dd..923fef2d9 100644 --- a/glue/qt/ui/imagewidget.ui +++ b/glue/qt/ui/imagewidget.ui @@ -6,8 +6,8 @@ 0 0 - 299 - 331 + 351 + 279 @@ -51,18 +51,15 @@ 10 - - - 2 - - - + + + - Data + Attribute - + @@ -78,10 +75,56 @@ + + + + + 0 + 0 + + + + Set which attribute of the data to display + + + QComboBox::AdjustToMinimumContentsLength + + + + + + + Data + + + + + + + Aspect + + + + + + - + + + + + Qt::Horizontal + + + + 40 + 20 + + + + @@ -105,38 +148,24 @@ - - - - - - 2 - - - - - Attribute - - - - - - - 0 - 0 - + + + Qt::Horizontal - - Set which attribute of the data to display + + + 40 + 20 + - - QComboBox::AdjustToMinimumContentsLength - - + + + + @@ -144,22 +173,6 @@ - - - - - - - Qt::Vertical - - - - 5 - 5 - - - - diff --git a/glue/qt/widgets/image_widget.py b/glue/qt/widgets/image_widget.py index 75af8e86f..fcef7229c 100644 --- a/glue/qt/widgets/image_widget.py +++ b/glue/qt/widgets/image_widget.py @@ -48,6 +48,8 @@ class ImageWidgetBase(DataViewer): 'Current attribute') data = CurrentComboProperty('ui.displayDataCombo', 'Current data') + aspect_ratio = CurrentComboProperty('ui.aspectCombo', + 'Aspect ratio for image') rgb_mode = ButtonProperty('ui.rgb', 'RGB Mode?') rgb_viz = Pointer('ui.rgb_options.rgb_visible') @@ -74,6 +76,9 @@ def _setup_widgets(self): self.ui.slice_layout.addWidget(self.ui.slice) self._tweak_geometry() + self.ui.aspectCombo.addItem("Square Pixels", userData='equal') + self.ui.aspectCombo.addItem("Automatic", userData='auto') + def make_client(self): """ Instantiate and return an ImageClient subclass """ raise NotImplementedError() @@ -215,10 +220,12 @@ def _connect(self): # sync window title to data/attribute add_callback(self.client, 'display_data', nonpartial(self.update_window_title)) add_callback(self.client, 'display_attribute', nonpartial(self.update_window_title)) + add_callback(self.client, 'display_aspect', nonpartial(self.client.update_aspect)) # sync data/attribute combos with client properties connect_current_combo(self.client, 'display_data', self.ui.displayDataCombo) connect_current_combo(self.client, 'display_attribute', self.ui.attributeComboBox) + connect_current_combo(self.client, 'display_aspect', self.ui.aspectCombo) @defer_draw def _update_rgb_console(self, is_monochrome):