Skip to content

Commit 68cbfdb

Browse files
authored
Merge pull request #5207 from markotoplak/fix-pg-test-0.11.1
Fix pyqtgraph==0.11.1 test failures
2 parents 516d3d9 + 5ed8816 commit 68cbfdb

File tree

8 files changed

+87
-52
lines changed

8 files changed

+87
-52
lines changed

Orange/widgets/visualize/owscatterplotgraph.py

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,27 @@ def setZ(self, z):
226226
self._z_mapping = np.argsort(z)
227227
self._inv_mapping = np.argsort(self._z_mapping)
228228

229+
def setCoordinates(self, x, y):
230+
"""
231+
Change the coordinates of points while keeping other properties.
232+
233+
Asserts that the number of points stays the same.
234+
235+
Note. Pyqtgraph does not offer a method for this: setting coordinates
236+
invalidates other data. We therefore retrieve the data to set it
237+
together with the coordinates. Pyqtgraph also does not offer a
238+
(documented) method for retrieving the data, yet using
239+
data[prop]` looks reasonably safe.
240+
241+
The alternative, updating the whole scatterplot from the Orange Table,
242+
is too slow.
243+
"""
244+
assert len(self.data) == len(x) == len(y)
245+
data = dict(x=x, y=y)
246+
for prop in ('pen', 'brush', 'size', 'symbol', 'data'):
247+
data[prop] = self.data[prop]
248+
self.setData(**data)
249+
229250
def updateSpots(self, dataSet=None): # pylint: disable=unused-argument
230251
self._update_spots_in_paint = True
231252
self.update()
@@ -662,8 +683,8 @@ def update_jittering(self):
662683
x, y = self.get_coordinates()
663684
if x is None or len(x) == 0 or self.scatterplot_item is None:
664685
return
665-
self._update_plot_coordinates(self.scatterplot_item, x, y)
666-
self._update_plot_coordinates(self.scatterplot_item_sel, x, y)
686+
self.scatterplot_item.setCoordinates(x, y)
687+
self.scatterplot_item_sel.setCoordinates(x, y)
667688
self.update_labels()
668689

669690
# TODO: Rename to remove_plot_items
@@ -843,27 +864,6 @@ def _jitter_data(self, x, y, span_x=None, span_y=None):
843864
return (x + magnitude * span_x * rs * np.cos(phis),
844865
y + magnitude * span_y * rs * np.sin(phis))
845866

846-
def _update_plot_coordinates(self, plot, x, y):
847-
"""
848-
Change the coordinates of points while keeping other properites.
849-
850-
Asserts that the number of points stays the same.
851-
852-
Note. Pyqtgraph does not offer a method for this: setting coordinates
853-
invalidates other data. We therefore retrieve the data to set it
854-
together with the coordinates. Pyqtgraph also does not offer a
855-
(documented) method for retrieving the data, yet using
856-
`plot.data[prop]` looks reasonably safe. The alternative, calling
857-
update for every property would essentially reset the graph, which
858-
can be time consuming.
859-
"""
860-
assert self.n_shown == len(x) == len(y)
861-
data = dict(x=x, y=y)
862-
for prop in ('pen', 'brush', 'size', 'symbol', 'data',
863-
'sourceRect', 'targetRect'):
864-
data[prop] = plot.data[prop]
865-
plot.setData(**data)
866-
867867
def update_coordinates(self):
868868
"""
869869
Trigger the update of coordinates while keeping other features intact.
@@ -891,8 +891,8 @@ def update_coordinates(self):
891891
self.plot_widget.addItem(self.scatterplot_item_sel)
892892
self.plot_widget.addItem(self.scatterplot_item)
893893
else:
894-
self._update_plot_coordinates(self.scatterplot_item, x, y)
895-
self._update_plot_coordinates(self.scatterplot_item_sel, x, y)
894+
self.scatterplot_item.setCoordinates(x, y)
895+
self.scatterplot_item_sel.setCoordinates(x, y)
896896
self.update_labels()
897897

898898
self.update_density() # Todo: doesn't work: try MDS with density on

Orange/widgets/visualize/tests/test_owlineplot.py

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from AnyQt.QtCore import Qt, QPointF
1111
from AnyQt.QtGui import QFont
1212

13+
import pyqtgraph
1314
from pyqtgraph import PlotCurveItem
1415
from pyqtgraph.Point import Point
1516

@@ -154,8 +155,19 @@ def test_selection_line(self):
154155
self.send_signal(self.widget.Inputs.data, self.data)
155156

156157
# set view-dependent click coordinates
157-
event.buttonDownPos.return_value = QPointF(2.38, 4.84)
158-
event.pos.return_value = QPointF(3.58, 4.76)
158+
pos_down, pos_up = QPointF(2.38, 4.84), QPointF(3.58, 4.76)
159+
mapToParent = self.widget.graph.view_box.childGroup.mapToParent
160+
161+
# On pyqtgraph < 0.11.1 mapping does not work unless the widget is shown
162+
# Delete when Orange stops supporting pyqtgraph < 0.11.1,
163+
to_and_back = self.widget.graph.view_box.childGroup.mapFromParent(
164+
mapToParent(pos_down))
165+
successful_mapping = (to_and_back - pos_down).manhattanLength() < 0.001
166+
if not successful_mapping: # on pyqtgraph < 0.11.1
167+
mapToParent = lambda x: x
168+
169+
event.buttonDownPos.return_value = mapToParent(pos_down)
170+
event.pos.return_value = mapToParent(pos_up)
159171

160172
self.widget.graph.view_box.mouseDragEvent(event)
161173
line = self.widget.graph.view_box.selection_line
@@ -166,6 +178,12 @@ def test_selection_line(self):
166178
self.widget.graph.view_box.mouseClickEvent(event)
167179
self.assertListEqual(self.widget.selection, [])
168180

181+
def test_remove_old_pyqtgraph_support(self):
182+
# When 0.11.2 is released there is probably time to drop support
183+
# for pyqtgraph <= 0.11.0:
184+
# - remove test_selection_line workaround for 0.11.0
185+
self.assertLess(pyqtgraph.__version__, "0.11.2")
186+
169187
@patch("Orange.widgets.visualize.owlineplot.SEL_MAX_INSTANCES", 100)
170188
def test_select_lines_enabled(self):
171189
self.send_signal(self.widget.Inputs.data, self.data[::2])

Orange/widgets/visualize/tests/test_owscatterplotbase.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from AnyQt.QtGui import QColor
99
from AnyQt.QtTest import QSignalSpy
1010

11-
from pyqtgraph import mkPen
11+
from pyqtgraph import mkPen, mkBrush
1212

1313
from orangewidget.tests.base import GuiTest
1414
from Orange.widgets.settings import SettingProvider
@@ -103,7 +103,7 @@ def test_update_coordinates(self):
103103
scatterplot_item.setSize([5, 6])
104104
scatterplot_item.setSymbol([7, 8])
105105
scatterplot_item.setPen([mkPen(9), mkPen(10)])
106-
scatterplot_item.setBrush([11, 12])
106+
scatterplot_item.setBrush([mkBrush(11), mkBrush(12)])
107107
data["data"] = np.array([13, 14])
108108

109109
xy[0][0] = 0
@@ -118,7 +118,8 @@ def test_update_coordinates(self):
118118
np.testing.assert_almost_equal(data["symbol"], [7, 8])
119119
self.assertEqual(data["pen"][0], mkPen(9))
120120
self.assertEqual(data["pen"][1], mkPen(10))
121-
np.testing.assert_almost_equal(data["brush"], [11, 12])
121+
self.assertEqual(data["brush"][0], mkBrush(11))
122+
self.assertEqual(data["brush"][1], mkBrush(12))
122123
np.testing.assert_almost_equal(data["data"], [13, 14])
123124

124125
def test_update_coordinates_and_labels(self):
@@ -1532,7 +1533,11 @@ def test_hiding_too_many_labels(self):
15321533
def test_no_needless_buildatlas(self):
15331534
graph = self.graph
15341535
graph.reset_graph()
1535-
self.assertIsNone(graph.scatterplot_item.fragmentAtlas.atlas)
1536+
atlas = graph.scatterplot_item.fragmentAtlas
1537+
if hasattr(atlas, "atlas"): # pyqtgraph < 0.11.1
1538+
self.assertIsNone(atlas.atlas)
1539+
else:
1540+
self.assertFalse(atlas)
15361541

15371542

15381543
class TestScatterPlotItem(GuiTest):

Orange/widgets/visualize/utils/customizableplot.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ def plot_title_resize(title_item):
115115

116116
@staticmethod
117117
def update_axis_title_text(item: pg.AxisItem, text: str):
118-
item.setLabel(text)
118+
item.setLabel(text, item.labelUnits, item.labelUnitPrefix)
119119
item.resizeEvent(None)
120120

121121
@staticmethod
@@ -128,7 +128,8 @@ def update_axes_titles_font(items: List[pg.AxisItem],
128128
style = {"font-size": f"{font.pointSize()}pt",
129129
"font-family": f"{font.family()}",
130130
"font-style": f"{fstyle}"}
131-
item.setLabel(None, None, None, **style)
131+
item.setLabel(item.labelText, item.labelUnits,
132+
item.labelUnitPrefix, **style)
132133

133134
@staticmethod
134135
def update_axes_ticks_font(items: List[pg.AxisItem],
@@ -143,6 +144,11 @@ def update_axes_ticks_font(items: List[pg.AxisItem],
143144
def update_legend_font(items: Iterable[_LegendItemType],
144145
**settings: _SettingType):
145146
for sample, label in items:
147+
if "size" in label.opts:
148+
# pyqtgraph added html-like support for size in 0.11.1, which
149+
# overrides our QFont property
150+
label.opts.pop("size")
151+
label.setText(label.text)
146152
sample.setFixedHeight(sample.height())
147153
sample.setFixedWidth(sample.width())
148154
label.item.setFont(Updater.change_font(label.item.font(), settings))

Orange/widgets/visualize/utils/plotutils.py

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -508,10 +508,12 @@ def setRotateTicks(self, rotate):
508508
self.prepareGeometryChange()
509509
self.update()
510510

511-
def generateDrawSpecs(self, p):
512-
if self.style["tickFont"]:
513-
p.setFont(self.style["tickFont"])
514-
return super().generateDrawSpecs(p)
511+
# remove after Orange requires pyqtgraph >= 0.11.1
512+
if pg.__version__ <= "0.11.0":
513+
def generateDrawSpecs(self, p):
514+
if self.style["tickFont"]:
515+
p.setFont(self.style["tickFont"])
516+
return super().generateDrawSpecs(p)
515517

516518
def drawPicture(self, p, axisSpec, tickSpecs, textSpecs):
517519
if self.orientation in ["bottom", "top"] and self.style["rotateTicks"]:
@@ -549,12 +551,14 @@ def drawPicture(self, p, axisSpec, tickSpecs, textSpecs):
549551
else:
550552
super().drawPicture(p, axisSpec, tickSpecs, textSpecs)
551553

552-
def _updateMaxTextSize(self, x):
553-
if self.orientation in ["left", "right"]:
554-
self.textWidth = x
555-
if self.style["autoExpandTextSpace"] is True:
556-
self._updateWidth()
557-
else:
558-
self.textHeight = x
559-
if self.style["autoExpandTextSpace"] is True:
560-
self._updateHeight()
554+
# remove after Orange requires pyqtgraph >= 0.11.1
555+
if pg.__version__ <= "0.11.0":
556+
def _updateMaxTextSize(self, x):
557+
if self.orientation in ["left", "right"]:
558+
self.textWidth = x
559+
if self.style["autoExpandTextSpace"] is True:
560+
self._updateWidth()
561+
else:
562+
self.textHeight = x
563+
if self.style["autoExpandTextSpace"] is True:
564+
self._updateHeight()

Orange/widgets/visualize/utils/tests/test_plotutils.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@
22

33

44
class TestAxisItem(unittest.TestCase):
5-
def test_scalable_axis_item(self):
5+
def test_remove_old_pyqtgraph_support(self):
66
from pyqtgraph import __version__
7-
# When upgraded to 0.11.1 (or bigger) check if resizing AxisItem font
8-
# works and overwritten functions generateDrawSpecs and
9-
# _updateMaxTextSize are no longer needed.
10-
self.assertLess(__version__, "0.11.1")
7+
# When 0.11.2 is released there is probably time to drop support
8+
# for pyqtgraph <= 0.11.0:
9+
# - remove AxisItem.generateDrawSpecs
10+
# - remove AxisItem._updateMaxTextSize
11+
self.assertLess(__version__, "0.11.2")
1112

1213

1314
if __name__ == '__main__':

requirements-gui.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@ PyQt5>=5.12,!=5.15.1 # 5.15.1 skipped because of QTBUG-87057 - affects select c
55
PyQtWebEngine>=5.12
66
AnyQt>=0.0.11
77

8-
pyqtgraph==0.11.0
8+
pyqtgraph>=0.11.0
99
matplotlib>=2.0.0

tox.ini

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ commands =
3939
[testenv:future_compatibility]
4040
deps =
4141
{[testenv]deps}
42+
git+git://github.com/pyqtgraph/pyqtgraph.git#egg=pyqtgraph
4243
git+git://github.com/biolab/orange-canvas-core.git#egg=orange-canvas-core
4344
git+git://github.com/biolab/orange-widget-base.git#egg=orange-widget-base
4445

0 commit comments

Comments
 (0)