From 123125ce537ed47d800e2705208568b9557fadbb Mon Sep 17 00:00:00 2001
From: Pierre Raybaut
Date: Mon, 9 Oct 2023 14:44:40 +0200
Subject: [PATCH] Fixed another plotpy V1 regression (thx to guiqwt)
Fixes aspect ratio issue when doing autoscale
---
plotpy/plot/base.py | 51 ++++++++++++++++++++-------------------------
1 file changed, 23 insertions(+), 28 deletions(-)
diff --git a/plotpy/plot/base.py b/plotpy/plot/base.py
index 5ed9b55..4c0a933 100644
--- a/plotpy/plot/base.py
+++ b/plotpy/plot/base.py
@@ -396,23 +396,6 @@ def __init__(
self.set_aspect_ratio(options.aspect_ratio, options.lock_aspect_ratio)
self.replot() # Workaround for the empty image widget bug
- def replot(self) -> None:
- """
- Redraw the plot
-
- If the `autoReplot` option is not set (which is the default)
- or if any curves are attached to raw data, the plot has to
- be refreshed explicitly in order to make changes visible.
-
- .. seealso::
-
- :py:meth:`qwt.plot.QwtPlot.updateAxes`,
- :py:meth:`qwt.plot.QwtPlot.setAutoReplot`
- """
- super().replot()
- if self.lock_aspect_ratio:
- self.apply_aspect_ratio()
-
# ---- Private API ----------------------------------------------------------
def __del__(self):
# Sometimes, an obscure exception happens when we quit an application
@@ -1937,11 +1920,9 @@ def do_autoscale(self, replot: bool = True, axis_id: int | None = None) -> None:
vmax = 10 ** (np.log10(vmax) + 0.002 * dv)
self.set_axis_limits(axis_id, vmin, vmax)
self.setAutoReplot(auto)
-
self.updateAxes()
- # if self.lock_aspect_ratio:
- # self.replot()
- # self.apply_aspect_ratio(full_scale=True)
+ if self.lock_aspect_ratio:
+ self.apply_aspect_ratio(full_scale=True)
if replot:
self.replot()
self.SIG_PLOT_AXIS_CHANGED.emit(self)
@@ -2185,6 +2166,9 @@ def apply_aspect_ratio(self, full_scale: bool = False) -> None:
Args:
full_scale: if True, the aspect ratio is applied to the full scale
+ (this argument is True only when doing autoscale, i.e. in method
+ :py:meth:`do_autoscale`: it is necessary to ensure that the whole
+ image items are visible after autoscale, whatever their aspect ratio)
"""
if not self.isVisible():
return
@@ -2206,19 +2190,30 @@ def apply_aspect_ratio(self, full_scale: bool = False) -> None:
if w == 0 or h == 0:
return # avoid division by zero
+ # Compute new Y limits, keeping the same X limits and aspect ratio
dy2 = (h * dx1) / (w * self.__aspect_ratio)
- dx2 = (w * dy1 * self.__aspect_ratio) / h
- fix_yaxis = not full_scale or dy2 > dy1
+ # Compute new X limits, keeping the same Y limits and aspect ratio
+ dx2 = (w * dy1 * self.__aspect_ratio) / h
- if fix_yaxis:
- delta_y = 0.5 * (dy2 - dy1)
- y0 -= delta_y
- y1 += delta_y
- else:
+ if full_scale and dy2 <= dy1:
+ # If the new Y limits are smaller than the current ones,
+ # *and* if we are doing autoscale, we keep the current Y limits.
+ # Why? Because, if the new Y limits are smaller than the current ones,
+ # it means that the image items would not be entirely visible after
+ # autoscale, and we don't want that.
delta_x = 0.5 * (dx2 - dx1)
x0 -= delta_x
x1 += delta_x
+ else:
+ # If we are not doing autoscale, then we only change the Y limits (that
+ # is a choice, we could also change the X limits).
+ # If we are doing autoscale, then we change the Y limits only if the
+ # new Y limits are larger than the current ones, in order to ensure
+ # that the image items are entirely visible after autoscale.
+ delta_y = 0.5 * (dy2 - dy1)
+ y0 -= delta_y
+ y1 += delta_y
self.set_plot_limits(x0, x1, y0, y1)