Skip to content

Commit

Permalink
Merge pull request #11 from VesnaT/wheel_zoom
Browse files Browse the repository at this point in the history
[ENH] Explain Prediction: Wheel zoom
  • Loading branch information
PrimozGodec committed Jan 12, 2021
2 parents 4081fbe + 0e7f2cd commit 0c3a850
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 6 deletions.
36 changes: 30 additions & 6 deletions orangecontrib/explain/widgets/owexplainprediction.py
Expand Up @@ -3,8 +3,9 @@

import numpy as np

from AnyQt.QtCore import Qt, QRectF, QSizeF, QSize, QPointF
from AnyQt.QtGui import QColor, QPen, QBrush, QPainter, QPainterPath, QPolygonF
from AnyQt.QtCore import Qt, QRectF, QSizeF, QSize, QPointF, Signal
from AnyQt.QtGui import QColor, QPen, QBrush, QPainter, QPainterPath, \
QPolygonF, QWheelEvent
from AnyQt.QtWidgets import QGraphicsItemGroup, QGraphicsLineItem, \
QGraphicsScene, QGraphicsWidget, QGraphicsLinearLayout, QGraphicsView, \
QGraphicsSimpleTextItem, QGraphicsRectItem, QGraphicsPathItem, \
Expand Down Expand Up @@ -357,7 +358,7 @@ def _set_parts_pos(self, height: float, y: float, diff: float,
y_delta = height * item.norm_value * diff

y_text = y + y_delta / 2 - item.value_height / 2
visible = y_delta > item.value_height + 8
visible = bool(y_delta > item.value_height + 8)

y_test_adj = y_text + adjust_y(i)
y_mid = height * (self.__range[1] - self.__model_output)
Expand Down Expand Up @@ -465,6 +466,19 @@ def sizeHint(self, *_) -> QSizeF:
self.height + self.VMARGIN * 2)


class GraphicsView(QGraphicsView):
zoomChanged = Signal(float)

def wheelEvent(self, event: QWheelEvent):
if event.modifiers() & Qt.ControlModifier \
and event.buttons() == Qt.NoButton:
self.zoomChanged.emit(event.angleDelta().y())
event.accept()
else:
super().wheelEvent(event)



class OWExplainPrediction(OWWidget, ConcurrentWidgetMixin):
name = "Explain Prediction"
description = "Prediction explanation widget."
Expand Down Expand Up @@ -516,7 +530,8 @@ def setup_gui(self):

def _add_plot(self):
self.scene = QGraphicsScene()
self.view = QGraphicsView(self.scene)
self.view = GraphicsView(self.scene)
self.view.zoomChanged.connect(self.__zoom_changed)
self.view.setRenderHint(QPainter.Antialiasing, True)
self.view.setAlignment(Qt.AlignVCenter | Qt.AlignLeft)
self.mainArea.layout().addWidget(self.view)
Expand All @@ -528,8 +543,10 @@ def _add_controls(self):
contentsLength=12)

box = gui.hBox(self.controlArea, "Zoom")
gui.hSlider(box, self, "stripe_len", None, minValue=1, maxValue=500,
createLabel=False, callback=self.__size_slider_changed)
self._size_slider = gui.hSlider(
box, self, "stripe_len", None, minValue=1, maxValue=500,
createLabel=False, callback=self.__size_slider_changed
)

gui.rubber(self.controlArea)

Expand All @@ -545,6 +562,13 @@ def __size_slider_changed(self):
if self._stripe_plot is not None:
self._stripe_plot.set_height(self.stripe_len)

def __zoom_changed(self, delta: float):
self.stripe_len = max(min(self.stripe_len + delta,
self._size_slider.maximum()),
self._size_slider.minimum())
self._size_slider.setValue(self.stripe_len)
self.__size_slider_changed()

@Inputs.data
@check_sql_input
def set_data(self, data: Optional[Table]):
Expand Down
25 changes: 25 additions & 0 deletions orangecontrib/explain/widgets/tests/test_owexplainprediction.py
Expand Up @@ -172,6 +172,31 @@ def test_multiple_instances_info(self):
self.send_signal(self.widget.Inputs.data, None)
self.assertFalse(self.widget.Information.multiple_instances.is_shown())

def test_mouse_wheel_zoom_changed(self):
self.send_signal(self.widget.Inputs.data, self.iris[:1])
self.send_signal(self.widget.Inputs.background_data, self.iris)
self.send_signal(self.widget.Inputs.model, self.rf_cls)
self.wait_until_finished()

self.assertEqual(self.widget._stripe_plot.height, 500)
self.assertEqual(self.widget._size_slider.value(), 10)
self.assertEqual(self.widget.stripe_len, 10)

self.widget.view.zoomChanged.emit(10)
self.assertEqual(self.widget._stripe_plot.height, 600)
self.assertEqual(self.widget._size_slider.value(), 20)
self.assertEqual(self.widget.stripe_len, 20)

self.widget.view.zoomChanged.emit(-30)
self.assertEqual(self.widget._stripe_plot.height, 410)
self.assertEqual(self.widget._size_slider.value(), 1)
self.assertEqual(self.widget.stripe_len, 1)

self.widget.view.zoomChanged.emit(1000)
self.assertEqual(self.widget._stripe_plot.height, 5400)
self.assertEqual(self.widget._size_slider.value(), 500)
self.assertEqual(self.widget.stripe_len, 500)

def test_send_report(self):
self.widget.send_report()
self.send_signal(self.widget.Inputs.data, self.iris[:1])
Expand Down

0 comments on commit 0c3a850

Please sign in to comment.