diff --git a/Orange/widgets/unsupervised/owdistancemap.py b/Orange/widgets/unsupervised/owdistancemap.py index a0747752a4d..400d8790cc9 100644 --- a/Orange/widgets/unsupervised/owdistancemap.py +++ b/Orange/widgets/unsupervised/owdistancemap.py @@ -27,6 +27,9 @@ from Orange.widgets.utils.widgetpreview import WidgetPreview from Orange.widgets.widget import Input, Output from Orange.widgets.utils.dendrogram import DendrogramWidget +from Orange.widgets.visualize.utils.heatmap import ( + GradientColorMap, GradientLegendWidget, +) def _remove_item(item): @@ -74,8 +77,6 @@ def __select(self, area, command): if command & self.Select: area = area.normalized() - intersects = [rect.intersects(area) - for item, rect in self.__selections] def partition(predicate, iterable): t1, t2 = itertools.tee(iterable) @@ -287,6 +288,7 @@ def __init__(self): super().__init__() self.matrix = None + self._matrix_range = 0. self._tree = None self._ordered_tree = None self._sorted_matrix = None @@ -308,12 +310,6 @@ def __init__(self): labelAlignment=Qt.AlignLeft, fieldGrowthPolicy=QFormLayout.AllNonFixedFieldsGrow ) -# form.addRow( -# "Gamma", -# gui.hSlider(box, self, "color_gamma", minValue=0.0, maxValue=1.0, -# step=0.05, ticks=True, intOnly=False, -# createLabel=False, callback=self._update_color) -# ) form.addRow( "Low:", gui.hSlider(box, self, "color_low", minValue=0.0, maxValue=1.0, @@ -344,10 +340,16 @@ def __init__(self): self.grid = QGraphicsGridLayout() self.grid_widget.setLayout(self.grid) + self.gradient_legend = GradientLegendWidget( + 0, 1, self._color_map() + ) + self.gradient_legend.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed) + self.gradient_legend.setMaximumWidth(250) + self.grid.addItem(self.gradient_legend, 0, 1) self.viewbox = pg.ViewBox(enableMouse=False, enableMenu=False) self.viewbox.setAcceptedMouseButtons(Qt.NoButton) self.viewbox.setAcceptHoverEvents(False) - self.grid.addItem(self.viewbox, 1, 1) + self.grid.addItem(self.viewbox, 2, 1) self.left_dendrogram = DendrogramWidget( self.grid_widget, orientation=DendrogramWidget.Left, @@ -365,8 +367,8 @@ def __init__(self): self.top_dendrogram.setAcceptedMouseButtons(Qt.NoButton) self.top_dendrogram.setAcceptHoverEvents(False) - self.grid.addItem(self.left_dendrogram, 1, 0) - self.grid.addItem(self.top_dendrogram, 0, 1) + self.grid.addItem(self.left_dendrogram, 2, 0) + self.grid.addItem(self.top_dendrogram, 1, 1) self.right_labels = TextList( alignment=Qt.AlignLeft | Qt.AlignVCenter, @@ -378,11 +380,12 @@ def __init__(self): sizePolicy=QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) ) - self.grid.addItem(self.right_labels, 1, 2) - self.grid.addItem(self.bottom_labels, 2, 1) + self.grid.addItem(self.right_labels, 2, 2) + self.grid.addItem(self.bottom_labels, 3, 1) self.view.setCentralItem(self.grid_widget) + self.gradient_legend.hide() self.left_dendrogram.hide() self.top_dendrogram.hide() self.right_labels.hide() @@ -391,8 +394,6 @@ def __init__(self): self.matrix_item = None self.dendrogram = None - self.grid_widget.scene().installEventFilter(self) - self.settingsAboutToBePacked.connect(self.pack_settings) def pack_settings(self): @@ -414,8 +415,10 @@ def set_distances(self, matrix): self.matrix = matrix if matrix is not None: + self._matrix_range = numpy.nanmax(matrix) self.set_items(matrix.row_items, matrix.axis) else: + self._matrix_range = 0. self.set_items(None) if matrix is not None: @@ -469,7 +472,6 @@ def set_items(self, items, axis=1): def clear(self): self.matrix = None - self.cluster = None self._tree = None self._ordered_tree = None self._sorted_matrix = None @@ -499,6 +501,7 @@ def remove(item): self._set_displayed_dendrogram(None) self._set_labels(None) + self.gradient_legend.hide() def _cluster_tree(self): if self._tree is None: @@ -607,12 +610,22 @@ def _set_labels(self, labels): self.right_labels.setMaximumWidth(constraint) self.bottom_labels.setMaximumHeight(constraint) + def _color_map(self) -> GradientColorMap: + palette = self.color_box.currentData() + return GradientColorMap( + palette.lookup_table(), + thresholds=(self.color_low, max(self.color_high, self.color_low)), + span=(0., self._matrix_range)) + def _update_color(self): palette = self.color_box.currentData() self.palette_name = palette.name if self.matrix_item: colors = palette.lookup_table(self.color_low, self.color_high) self.matrix_item.setLookupTable(colors) + self.gradient_legend.show() + self.gradient_legend.setRange(0, self._matrix_range) + self.gradient_legend.setColorMap(self._color_map()) def _invalidate_selection(self): ranges = self.matrix_item.selections() diff --git a/Orange/widgets/visualize/utils/heatmap.py b/Orange/widgets/visualize/utils/heatmap.py index ab6b2c7c302..a616fa1c5d0 100644 --- a/Orange/widgets/visualize/utils/heatmap.py +++ b/Orange/widgets/visualize/utils/heatmap.py @@ -86,7 +86,7 @@ class GradientColorMap(ColorMap): def __init__(self, colortable, thresholds=thresholds, center=None, span=None): self.colortable = np.asarray(colortable) self.thresholds = thresholds - assert thresholds[0] < thresholds[1] + assert thresholds[0] <= thresholds[1] self.center = center self.span = span @@ -1159,6 +1159,12 @@ def __init__( if parent is not None: self.setParentItem(parent) + def setRange(self, low, high): + if self.low != low or self.high != high: + self.low = low + self.high = high + self.__update() + def setColorMap(self, colormap: ColorMap) -> None: """Set the color map""" self.colormap = colormap @@ -1180,6 +1186,7 @@ def __update(self): tick_values = [low, high] tickformat = "{:.6g}".format ticks = [(val, tickformat(val)) for val in tick_values] + self.__axis.setRange(low, high) self.__axis.setTicks([ticks]) self.updateGeometry()