silx.gui.plot.PlotWidget: fix resetting zoom for curves/scatters to take the visible data in the X-range into acount#4633
Conversation
e34a910 to
a92f32f
Compare
7e37d0c to
689467a
Compare
95fb656 to
8b9cc2e
Compare
ab9f584 to
dbe4a71
Compare
|
Another example for BoundRect (not sure how to visualize) import sys
from silx.gui import qt
from silx.gui.plot import PlotWindow
from silx.gui.plot.items.shape import BoundingRect
app = qt.QApplication(sys.argv)
plot = PlotWindow()
# Visible bounding region
rect_visible = BoundingRect()
rect_visible.setBounds((45, 55, 10, 20))
plot.addItem(rect_visible)
# Hidden bounding region
rect_hidden = BoundingRect()
rect_hidden.setBounds((80, 90, 100, 200))
plot.addItem(rect_hidden)
plot.show()
print("")
print("=== BOUNDINGRECT RESETZOOM TEST ===")
print("1. Zoom X to [40, 60]")
print("2. Disable X autoscale")
print("3. Click Reset Zoom")
print("")
print("EXPECTED:")
print("- Y limits become [10, 20]")
print("- BoundingRect at x=[80,90] must not contribute")
print("")
sys.exit(app.exec()) |
|
Another example for axis extents (not sure how to visualize) import sys
from silx.gui import qt
from silx.gui.plot import PlotWindow
from silx.gui.plot.items import XAxisExtent, YAxisExtent
app = qt.QApplication(sys.argv)
plot = PlotWindow()
# Visible extents
x_visible = XAxisExtent()
x_visible.setRange(45, 55)
plot.addItem(x_visible)
y_visible = YAxisExtent()
y_visible.setRange(45, 55)
plot.addItem(y_visible)
# Hidden extents
x_hidden = XAxisExtent()
x_hidden.setRange(80, 90)
plot.addItem(x_hidden)
y_hidden = YAxisExtent()
y_hidden.setRange(80, 90)
plot.addItem(y_hidden)
plot.show()
print("")
print("=== EXTENT RESETZOOM TEST ===")
print("")
print("CASE A: X fixed")
print("1. Zoom X to [40, 60]")
print("2. Disable X autoscale")
print("3. Click Reset Zoom")
print("")
print("EXPECTED:")
print("- Y limits become [45, 55]")
print("- YAxisExtent [80,90] ignored")
print("")
print("CASE B: Y fixed")
print("1. Zoom Y to [40, 60]")
print("2. Disable Y autoscale")
print("3. Click Reset Zoom")
print("")
print("EXPECTED:")
print("- X limits become [45, 55]")
print("- XAxisExtent [80,90] ignored")
print("")
sys.exit(app.exec()) |
7e1fcf9 to
28184a2
Compare
|
@t20100 @payno The When resetting the zoom we now call class BackendBase:
def setLimits(self, xmin, xmax, ymin, ymax, y2min=None, y2max=None):In this case it seems that instead of I can either do this: uncomment https://github.com/silx-kit/silx/pull/4633/changes#diff-73bf8890a30feb0887556785fbfd8cbdc73ea4aca5e81db9de86907c4e42dd3bR942-R943 Or |
70f5b48 to
2461225
Compare
How it's done in silx/src/silx/gui/plot/PlotWidget.py Line 841 in 71cb9b8 pack, so I would go this way.
BTW, it should be possible to put some code in common between |
… getResetBounds and introduce Bounds tuple
2461225 to
ebe8a90
Compare
836de55 to
1abc23b
Compare
b3d4e97 to
1abc23b
Compare
| ): | ||
| """Reset the plot limits to the bounds of the data and redraw the plot. | ||
|
|
||
| This method forces a reset zoom and does not check axis autoscale. |
There was a problem hiding this comment.
This is no longer true, we do take autoscale into account.
The difference between resetZoom and _forceResetZoom is not really clear from the docstrings. I'm not entirely sure about the original purpose either. As far as I understand
- When at least one axis is autoscaling,
resetZoomcalls_forceResetZoomand afterwards forces limits, except if both are autoscaling. Weird. - When none of the axes are autoscaling,
resetZoomdoes nothing.
There was a problem hiding this comment.
If I were to describe the new behavior of _forceResetZoom it would be this
Reset the plot limits and redraw the plot.
The plot limits after a reset depend on whether axes have
- fixed limits (autoscale=False) or
- auto-scaling limits (autoscale=True).
See :meth:`getXAxis`, :meth:`getYAxis` and :meth:`Axis.setAutoScale`.
Axes that have fixed limits keep their limits after a reset.
Axes that have auto-scaling limits will have new limits determined by
- the data range within the limits of the axes with fixed limits or
- the full data range if all axes have auto-scaling limits.
Extra margins can be added around the data inside the plot area
(see :meth:`setDataMargins`).
Margins are given as one ratio of the data range per limit of the
data (xMin, xMax, yMin and yMax limits).
For log scale, extra margins are applied in log10 of the data.
This is exactly the same for resetZoom except that when non of the axes are auto-scaling, nothing happens. It also does a thing related to log-scale an limits >=0. I'm wondering whether this should not go to _forceResetZoom or even Item.getResetBounds().
There was a problem hiding this comment.
I would be inclined to just have
def resetZoom(self, dataMargins = None):
return self._resetZoom(dataMargins=dataMargins, force=False)
def _resetZoom(self, dataMargins = None, force = True):
...and all the logic happens in _resetZoom (currently _forceResetZoom), including to forcing and log-scale handling.
There was a problem hiding this comment.
I'm not sure why force would not always be True.
When all axes have autoscale=False we could just skip for performance reasons. But since "force" exists there must be other things that could influence the resetting even when autoscale=False for all. Something related to changing the aspect ratio fixing.
There was a problem hiding this comment.
Ok these is also _notifyLimitsChanged. This code is really convoluted.
…tead implementating it in Item._getResetBounds()



<Module or Topic>: <Action> <Summary>(see contributing guidelines)PR summary
Item.getBounds()now returns a named tupleBoundsinstead oftupleItem.getResetBounds()introduced for the bounds used when resetting the zoom (current axes autoscale and limits properties have an effect on the returnsBounds)AI Disclosure
Before this PR: reset zoom takes entire X-range to determine Y-range
After this PR: reset zoom takes current X-range to determine Y-range
Code for the example