Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor ImagePlot to be more adaptable #744

Merged
merged 2 commits into from
Sep 24, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
152 changes: 89 additions & 63 deletions orangecontrib/spectroscopy/widgets/owhyper.py
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,31 @@ def color_palette_model(palettes, iconsize=QSize(64, 16)):
return model


class AxesSettingsMixin:

def __init__(self):
self.xy_model = DomainModel(DomainModel.METAS | DomainModel.CLASSES,
valid_types=DomainModel.PRIMITIVE)

def setup_axes_settings_box(self):
box = gui.vBox(self)

common_options = {
"labelWidth": 50,
"orientation": Qt.Horizontal,
"sendSelectedValue": True
}

cb_attr_x = gui.comboBox(
box, self, "attr_x", label="Axis x:", callback=self.update_attr,
model=self.xy_model, **common_options)
gui.comboBox(
box, self, "attr_y", label="Axis y:", callback=self.update_attr,
model=self.xy_model, **common_options)
box.setFocusProxy(cb_attr_x)
return box


class ImageColorSettingMixin:
threshold_low = Setting(0.0, schema_only=True)
threshold_high = Setting(1.0, schema_only=True)
Expand Down Expand Up @@ -529,6 +554,53 @@ def add_zoom_actions(self, menu):
menu.addAction(zoom_fit)


class ImageSelectionMixin:

def add_selection_actions(self, menu):

select_square = QAction(
"Select (square)", self, triggered=self.plot.vb.set_mode_select_square,
)
select_square.setShortcuts([Qt.Key_S])
select_square.setShortcutContext(Qt.WidgetWithChildrenShortcut)
self.addAction(select_square)
if menu:
menu.addAction(select_square)

select_polygon = QAction(
"Select (polygon)", self, triggered=self.plot.vb.set_mode_select_polygon,
)
select_polygon.setShortcuts([Qt.Key_P])
select_polygon.setShortcutContext(Qt.WidgetWithChildrenShortcut)
self.addAction(select_polygon)
if menu:
menu.addAction(select_polygon)

def select_square(self, p1, p2):
""" Select elements within a square drawn by the user.
A selection needs to contain whole pixels """
x1, y1 = p1.x(), p1.y()
x2, y2 = p2.x(), p2.y()
polygon = [QPointF(x1, y1), QPointF(x2, y1), QPointF(x2, y2), QPointF(x1, y2), QPointF(x1, y1)]
self.select_polygon(polygon)

def select_polygon(self, polygon):
""" Select by a polygon which has to contain whole pixels. """
if self.data and self.lsx and self.lsy:
polygon = [(p.x(), p.y()) for p in polygon]
# a polygon should contain all pixel
shiftx = _shift(self.lsx)
shifty = _shift(self.lsy)
points_edges = [self.data_points + [[shiftx, shifty]],
self.data_points + [[-shiftx, shifty]],
self.data_points + [[shiftx, -shifty]],
self.data_points + [[-shiftx, -shifty]]]
inp = in_polygon(points_edges[0], polygon)
for p in points_edges[1:]:
inp *= in_polygon(p, polygon)
self.make_selection(inp)


class ImageColorLegend(GraphicsWidget):

def __init__(self):
Expand Down Expand Up @@ -622,12 +694,11 @@ def legend_items(self):
return []


class ImagePlot(QWidget, OWComponent, SelectionGroupMixin,
ImageColorSettingMixin, ImageRGBSettingMixin,
ImageZoomMixin, ConcurrentMixin):
class BasicImagePlot(QWidget, OWComponent, SelectionGroupMixin,
AxesSettingsMixin, ImageSelectionMixin,
ImageColorSettingMixin, ImageRGBSettingMixin,
ImageZoomMixin, ConcurrentMixin):

attr_x = ContextSetting(None, exclude_attributes=True)
attr_y = ContextSetting(None, exclude_attributes=True)
gamma = Setting(0)

selection_changed = Signal()
Expand All @@ -637,6 +708,8 @@ def __init__(self, parent):
QWidget.__init__(self)
OWComponent.__init__(self, parent)
SelectionGroupMixin.__init__(self)
AxesSettingsMixin.__init__(self)
ImageSelectionMixin.__init__(self)
ImageColorSettingMixin.__init__(self)
ImageZoomMixin.__init__(self)
ConcurrentMixin.__init__(self)
Expand Down Expand Up @@ -694,56 +767,28 @@ def __init__(self, parent):
# prepare interface according to the new context
self.parent.contextAboutToBeOpened.connect(lambda x: self.init_interface_data(x[0]))

actions = []

self.add_zoom_actions(view_menu)

select_square = QAction(
"Select (square)", self, triggered=self.plot.vb.set_mode_select_square,
)
select_square.setShortcuts([Qt.Key_S])
select_square.setShortcutContext(Qt.WidgetWithChildrenShortcut)
actions.append(select_square)

select_polygon = QAction(
"Select (polygon)", self, triggered=self.plot.vb.set_mode_select_polygon,
)
select_polygon.setShortcuts([Qt.Key_P])
select_polygon.setShortcutContext(Qt.WidgetWithChildrenShortcut)
actions.append(select_polygon)
self.add_selection_actions(view_menu)

if self.saving_enabled:
save_graph = QAction(
"Save graph", self, triggered=self.save_graph,
)
save_graph.setShortcuts([QKeySequence(Qt.ControlModifier | Qt.Key_I)])
actions.append(save_graph)

view_menu.addActions(actions)
self.addActions(actions)
for a in actions:
a.setShortcutVisibleInContextMenu(True)

common_options = dict(
labelWidth=50, orientation=Qt.Horizontal, sendSelectedValue=True)
self.addAction(save_graph)
view_menu.addAction(save_graph)
save_graph.setShortcutVisibleInContextMenu(True)

choose_xy = QWidgetAction(self)
box = gui.vBox(self)
box.setContentsMargins(10, 0, 10, 0)
box.setFocusPolicy(Qt.TabFocus)
self.xy_model = DomainModel(DomainModel.METAS | DomainModel.CLASSES,
valid_types=DomainModel.PRIMITIVE)
self.cb_attr_x = gui.comboBox(
box, self, "attr_x", label="Axis x:", callback=self.update_attr,
model=self.xy_model, **common_options)
self.cb_attr_y = gui.comboBox(
box, self, "attr_y", label="Axis y:", callback=self.update_attr,
model=self.xy_model, **common_options)
box.setFocusProxy(self.cb_attr_x)

self.axes_settings_box = self.setup_axes_settings_box()
self.color_settings_box = self.setup_color_settings_box()
self.rgb_settings_box = self.setup_rgb_settings_box()

box.layout().addWidget(self.axes_settings_box)
box.layout().addWidget(self.color_settings_box)
box.layout().addWidget(self.rgb_settings_box)

Expand Down Expand Up @@ -830,30 +875,6 @@ def make_selection(self, selected):
self.prepare_settings_for_saving()
self.selection_changed.emit()

def select_square(self, p1, p2):
""" Select elements within a square drawn by the user.
A selection needs to contain whole pixels """
x1, y1 = p1.x(), p1.y()
x2, y2 = p2.x(), p2.y()
polygon = [QPointF(x1, y1), QPointF(x2, y1), QPointF(x2, y2), QPointF(x1, y2), QPointF(x1, y1)]
self.select_polygon(polygon)

def select_polygon(self, polygon):
""" Select by a polygon which has to contain whole pixels. """
if self.data and self.lsx and self.lsy:
polygon = [(p.x(), p.y()) for p in polygon]
# a polygon should contain all pixel
shiftx = _shift(self.lsx)
shifty = _shift(self.lsy)
points_edges = [self.data_points + [[shiftx, shifty]],
self.data_points + [[-shiftx, shifty]],
self.data_points + [[shiftx, -shifty]],
self.data_points + [[-shiftx, -shifty]]]
inp = in_polygon(points_edges[0], polygon)
for p in points_edges[1:]:
inp *= in_polygon(p, polygon)
self.make_selection(inp)

def _points_at_pos(self, pos):
if self.data and self.lsx and self.lsy:
x, y = pos.x(), pos.y()
Expand Down Expand Up @@ -1020,6 +1041,11 @@ def on_exception(self, ex: Exception):
raise ex


class ImagePlot(BasicImagePlot):
attr_x = ContextSetting(None, exclude_attributes=True)
attr_y = ContextSetting(None, exclude_attributes=True)


class CurvePlotHyper(CurvePlot):
viewtype = Setting(AVERAGE) # average view by default

Expand Down
Loading