Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- A crosshair toggle option has been added in mantidplots
42 changes: 38 additions & 4 deletions qt/applications/workbench/workbench/plotting/figuremanager.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,10 +232,13 @@ def __init__(self, canvas, num):
self.toolbar.sig_waterfall_conversion.connect(self.update_toolbar_waterfall_plot)
self.toolbar.sig_change_line_collection_colour_triggered.connect(self.change_line_collection_colour)
self.toolbar.sig_hide_plot_triggered.connect(self.hide_plot)
self.toolbar.sig_crosshair_toggle_triggered.connect(self.crosshair_toggle)
self.toolbar.setFloatable(False)
tbs_height = self.toolbar.sizeHint().height()
else:
tbs_height = 0
# canvas.mpl_connect("motion_notify_event", self.crosshair)
# self.crosshair_toggle(False)

# resize the main window so it will display the canvas with the
# requested size:
Expand All @@ -251,9 +254,7 @@ def __init__(self, canvas, num):
self.window.addDockWidget(Qt.LeftDockWidgetArea, self.fit_browser)

self.superplot = None

self.fit_browser.hide()

if matplotlib.is_interactive():
self.window.show()
canvas.draw_idle()
Expand All @@ -264,11 +265,9 @@ def notify_axes_change(fig):
self.toolbar.update()

canvas.figure.add_axobserver(notify_axes_change)

# Register canvas observers
self._fig_interaction = FigureInteraction(self)
self._ads_observer = FigureManagerADSObserver(self)

self.window.raise_()

def full_screen_toggle(self):
Expand Down Expand Up @@ -603,6 +602,41 @@ def _reverse_axis_lines(ax):
line.remove()
ax.add_line(line)

def crosshair_toggle(self, on):
cid = self.canvas.mpl_connect("motion_notify_event", self.crosshair)
if not on:
self.canvas.mpl_disconnect(cid)

def crosshair(self, event):
axes = self.canvas.figure.gca()

# create a crosshair made from horizontal and verticle lines.
self.horizontal_line = axes.axhline(color="r", lw=1.0, ls="-")
self.vertical_line = axes.axvline(color="r", lw=1.0, ls="-")

def set_cross_hair_visible(visible):
need_redraw = self.horizontal_line.get_visible() != visible
self.horizontal_line.set_visible(visible)
self.vertical_line.set_visible(visible)
return need_redraw

# if event is out-of-bound we update
if not event.inaxes:
need_redraw = set_cross_hair_visible(False)
if need_redraw:
axes.figure.canvas.draw()

else:
set_cross_hair_visible(True)
x, y = event.xdata, event.ydata
self.horizontal_line.set_ydata([y])
self.vertical_line.set_xdata([x])
self.canvas.draw()

# after update we remove
self.horizontal_line.remove()
self.vertical_line.remove()


# -----------------------------------------------------------------------------
# Figure control
Expand Down
22 changes: 22 additions & 0 deletions qt/applications/workbench/workbench/plotting/test/test_toolbar.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,15 @@ def test_button_checked_for_plot_with_grid(self, mock_qappthread):
# Grid button should be ON because we enabled the grid.
self.assertTrue(self._is_grid_button_checked(fig))

@patch("workbench.plotting.figuremanager.QAppThreadCall")
def test_button_checked_for_plot_with_no_crosshair(self, mock_qappthread):
mock_qappthread.return_value = mock_qappthread

fig, axes = plt.subplots(subplot_kw={"projection": "mantid"})
axes.plot([-10, 10], [1, 2])
# Grid button should be OFF because we have not enabled the crosshair.
self.assertFalse(self._is_crosshair_button_checked(fig))

@patch("workbench.plotting.figuremanager.QAppThreadCall")
def test_button_checked_for_plot_with_grid_using_kwargs(self, mock_qappthread):
mock_qappthread.return_value = mock_qappthread
Expand Down Expand Up @@ -266,6 +275,19 @@ def _is_button_enabled(cls, fig, button):
fig_manager.toolbar.set_buttons_visibility(fig)
return fig_manager.toolbar._actions[button].isEnabled()

@classmethod
def _is_crosshair_button_checked(cls, fig):
"""
Create the figure manager and check whether its toolbar is toggled on or off for the given figure.
We have to explicitly call set_button_visibility() here, which would otherwise be called within the show()
function.
"""
canvas = MantidFigureCanvas(fig)
fig_manager = FigureManagerWorkbench(canvas, 1)
# This is only called when show() is called on the figure manager, so we have to manually call it here.
fig_manager.toolbar.set_buttons_visibility(fig)
return fig_manager.toolbar._actions["toggle_crosshair"].isChecked()


if __name__ == "__main__":
unittest.main()
9 changes: 9 additions & 0 deletions qt/applications/workbench/workbench/plotting/toolbar.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ def _create_script_action(self, text, tooltip_text, mdi_icon, *args):
class WorkbenchNavigationToolbar(MantidNavigationToolbar):
sig_home_clicked = QtCore.Signal()
sig_grid_toggle_triggered = QtCore.Signal(bool)
sig_crosshair_toggle_triggered = QtCore.Signal(bool)
sig_active_triggered = QtCore.Signal()
sig_hold_triggered = QtCore.Signal()
sig_toggle_fit_triggered = QtCore.Signal()
Expand Down Expand Up @@ -83,6 +84,7 @@ class WorkbenchNavigationToolbar(MantidNavigationToolbar):
MantidNavigationTool("Fill Area", "Fill area under curves", "mdi.format-color-fill", "waterfall_fill_area", None),
MantidStandardNavigationTools.SEPARATOR,
MantidNavigationTool("Help", "Open plotting help documentation", "mdi.help", "launch_plot_help", None),
MantidNavigationTool("Crosshair", "Toggle crosshair", "mdi.plus", "toggle_crosshair", False),
MantidNavigationTool("Hide", "Hide the plot", "mdi.eye", "hide_plot", None),
)

Expand All @@ -93,6 +95,13 @@ def __init__(self, canvas, parent, coordinates=True):
dpi_ratio = QtWidgets.QApplication.instance().desktop().physicalDpiX() / 100
self.setIconSize(QtCore.QSize(int(24 * dpi_ratio), int(24 * dpi_ratio)))

def toggle_crosshair(self, enable=None):
if enable is None:
enable = self._actions["toggle_crosshair"].isChecked()
else:
self._actions["toggle_crosshair"].setChecked(enable)
self.sig_crosshair_toggle_triggered.emit(enable)

def hide_plot(self):
self.sig_hide_plot_triggered.emit()

Expand Down
Loading