diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index dec00a0..9a9c6df 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,21 +1,21 @@ repos: - repo: https://github.com/asottile/pyupgrade - rev: v2.7.4 + rev: v2.29.0 hooks: - id: pyupgrade args: ["--py36-plus"] - repo: https://github.com/psf/black - rev: stable + rev: 21.9b0 hooks: - id: black - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v3.3.0 + rev: v4.0.1 hooks: - id: trailing-whitespace - id: end-of-file-fixer - id: mixed-line-ending - repo: https://gitlab.com/pycqa/flake8 - rev: '3.8.4' + rev: '3.9.2' hooks: - id: flake8 additional_dependencies: diff --git a/orangecontrib/survival_analysis/widgets/owranksurvivalfeatures.py b/orangecontrib/survival_analysis/widgets/owranksurvivalfeatures.py index 4a065c9..2e2993d 100644 --- a/orangecontrib/survival_analysis/widgets/owranksurvivalfeatures.py +++ b/orangecontrib/survival_analysis/widgets/owranksurvivalfeatures.py @@ -71,7 +71,6 @@ def worker(table: Table, covariates: List, time_var: str, event_var: str, state: results = stacked_result[:, 1:].astype(float) _, pvals_corrected = fdrcorrection(results[:, -1], is_sorted=False) results = np.hstack((results, pvals_corrected.reshape(pvals_corrected.shape[0], -1))) - return covariate_names, results @@ -105,6 +104,7 @@ def __init__(self): self.data: Optional[Table] = None self.attr_name_to_variable: Optional[Table] = None + self.covariates_from_worker_result = None time_var_model = DomainModel(valid_types=(ContinuousVariable,), order=(4,)) box = gui.vBox(self.controlArea, 'Time', margin=0) @@ -150,7 +150,7 @@ def button(text, buttonid, toolTip=None): self.commit_button = gui.auto_commit(self.buttonsArea, self, 'auto_commit', '&Commit', box=False) # Main area - self.model = PyTableModel() + self.model = PyTableModel(parent=self) self.table_view = TableView(parent=self) self.table_view.setModel(self.model) self.model.setHorizontalHeaderLabels(['Log-Likelihood', 'Log-Likelihood Ratio', f'{"p".center(13)}', 'FDR']) @@ -175,6 +175,7 @@ def covariates(self) -> Optional[List[str]]: def set_data(self, data: Table): self.closeContext() self.selected_attrs = [] + self.covariates_from_worker_result = [] self.model.clear() self.model.resetSorting() @@ -229,6 +230,9 @@ def on_done(self, worker_result): # wrap everything except covariate names self.model.wrap(results.tolist()) + # this is temp solution because covariate orders gets mixed when using multiprocessing + self.covariates_from_worker_result = covariate_names.tolist() + # match covariate names to domain variables and set vertical header self.model.setVerticalHeaderLabels([self.attr_name_to_variable[name] for name in covariate_names]) self.table_view.setVHeaderFixedWidthFromLabel(max((a.name for a in self.data.domain.attributes), key=len)) @@ -260,7 +264,7 @@ def auto_select(self): else: selection = QItemSelection() if self.selected_attrs is not None: - attr_indices = [self.data.domain.attributes.index(var) for var in self.selected_attrs] + attr_indices = [self.covariates_from_worker_result.index(var.name) for var in self.selected_attrs] for row in self.model.mapFromSourceRows(attr_indices): selection.append( QItemSelectionRange(self.model.index(row, 0), self.model.index(row, column_count - 1)) @@ -272,7 +276,7 @@ def on_select(self): selected_rows = self.table_view.selectionModel().selectedRows(0) row_indices = [i.row() for i in selected_rows] attr_indices = self.model.mapToSourceRows(row_indices) - self.selected_attrs = [self.data.domain[idx] for idx in attr_indices] + self.selected_attrs = [self.model._headers[Qt.Vertical][row] for row in attr_indices] self.commit() diff --git a/orangecontrib/survival_analysis/widgets/tests/test_owkaplanmeier.py b/orangecontrib/survival_analysis/widgets/tests/test_owkaplanmeier.py index 8ab1222..c01701e 100644 --- a/orangecontrib/survival_analysis/widgets/tests/test_owkaplanmeier.py +++ b/orangecontrib/survival_analysis/widgets/tests/test_owkaplanmeier.py @@ -1,14 +1,39 @@ import pyqtgraph as pg -from pyqtgraph.tests import mouseMove, mousePress, mouseRelease, mouseClick from pyqtgraph.graphicsItems.LegendItem import LabelItem -from pyqtgraph.Qt import QtTest from Orange.data.table import Table, Domain, StringVariable, ContinuousVariable, DiscreteVariable -from orangewidget.tests.base import WidgetTest +from Orange.widgets.tests.base import WidgetTest from orangecontrib.survival_analysis.widgets.owkaplanmeier import OWKaplanMeier -from AnyQt.QtCore import Qt +from AnyQt.QtCore import Qt, QEvent +from AnyQt.QtGui import QMouseEvent +from AnyQt.QtWidgets import QApplication, QGraphicsView +from AnyQt.QtTest import QTest + + +def mouse_press_and_hold(widget, pos, mouse_button=Qt.LeftButton): + if isinstance(widget, QGraphicsView): + widget = widget.viewport() + + event = QMouseEvent(QEvent.MouseButtonPress, pos, mouse_button, Qt.NoButton, Qt.NoModifier) + QApplication.sendEvent(widget, event) + + +def mouse_release(widget, pos, mouse_button=Qt.LeftButton): + if isinstance(widget, QGraphicsView): + widget = widget.viewport() + + event = QMouseEvent(QEvent.MouseButtonRelease, pos, mouse_button, Qt.NoButton, Qt.NoModifier) + QApplication.sendEvent(widget, event) + + +def mouse_move(widget, pos, buttons=Qt.NoButton): + if isinstance(widget, QGraphicsView): + widget = widget.viewport() + + event = QMouseEvent(QEvent.MouseMove, pos, Qt.NoButton, buttons, Qt.NoModifier) + QApplication.sendEvent(widget, event) class TestOWKaplanMeier(WidgetTest): @@ -54,12 +79,17 @@ def simulate_mouse_drag(self, start: tuple, end: tuple): start = self.widget.graph.view_box.mapViewToScene(pg.Point(start[0], start[1])).toPoint() end = self.widget.graph.view_box.mapViewToScene(pg.Point(end[0], end[1])).toPoint() - mouseMove(self.widget.graph, start) - QtTest.QTest.qWait(100) - mousePress(self.widget.graph, start, Qt.LeftButton) - mouseMove(self.widget.graph, end, Qt.LeftButton) - mouseRelease(self.widget.graph, end, Qt.LeftButton) - QtTest.QTest.qWait(100) + mouse_move(self.widget.graph, start) + # this is somehow not respected in KaplanMeierViewBox.mouseDragEvent so we do it here manualy + self.widget.graph.plotItem.scene().blockSignals(True) + + QTest.qWait(100) + mouse_press_and_hold(self.widget.graph, start) + mouse_move(self.widget.graph, end, Qt.LeftButton) + QTest.qWait(100) + mouse_release(self.widget.graph, end) + + self.widget.graph.plotItem.scene().blockSignals(False) def test_group_variable(self): # we expect only one curve @@ -98,14 +128,14 @@ def test_curve_highlight(self): self.widget.on_controls_changed() pos = self.widget.graph.view_box.mapViewToScene(pg.Point(1.5, 0.5)).toPoint() - mouseMove(self.widget.graph, pos) + mouse_move(self.widget.graph, pos) # We need to wait for events to process - QtTest.QTest.qWait(100) + QTest.qWait(100) self.assertTrue(self.widget.graph.highlighted_curve == 1) pos = self.widget.graph.view_box.mapViewToScene(pg.Point(1.5, 0.85)).toPoint() - mouseMove(self.widget.graph, pos) - QtTest.QTest.qWait(100) + mouse_move(self.widget.graph, pos) + QTest.qWait(100) self.assertTrue(self.widget.graph.highlighted_curve == 0) def test_selection(self): @@ -163,8 +193,8 @@ def test_selection(self): # reset selection pos = self.widget.graph.view_box.mapViewToScene(pg.Point(0, 0)).toPoint() - mouseClick(self.widget.graph, pos, Qt.LeftButton) - QtTest.QTest.qWait(100) + QTest.mouseClick(self.widget.graph.viewport(), Qt.LeftButton, pos=pos) + QTest.qWait(100) selected_data = self.get_output(self.widget.Outputs.selected_data) self.assertIsNone(selected_data) diff --git a/setup.cfg b/setup.cfg index 2319735..5fb1234 100644 --- a/setup.cfg +++ b/setup.cfg @@ -27,6 +27,7 @@ setup_requires = install_requires = Orange3 lifelines + statsmodels [options.extras_require] doc =