Source code for schrodinger.ui.qt.matplot_widget

# Matplot widget that can be used in Qt Designer

from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure

from schrodinger.Qt import QtCore
from schrodinger.Qt import QtWidgets
from schrodinger.ui.qt.structure2d import LabeledStructureToolTip


[docs]class MatplotCanvas(FigureCanvas): """ This is the class to represent FigureCanvas widget """
[docs] def __init__(self): self.fig = Figure() self.ax = self.fig.add_subplot(111) FigureCanvas.__init__(self, self.fig) FigureCanvas.setSizePolicy(self, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) FigureCanvas.updateGeometry(self)
[docs]class MatplotWidget(QtWidgets.QWidget): """ This is a widget defined in Qt Designer """
[docs] def __init__(self, parent=None): QtWidgets.QWidget.__init__(self, parent) self.canvas = MatplotCanvas() self.vLayout = QtWidgets.QVBoxLayout() self.vLayout.addWidget(self.canvas) #self.vLayout.addWidget(self.ntb) # matplot lib toolbar on/off self.setLayout(self.vLayout)
[docs]class StructureTooltipMixin(object): """ A class that enables tooltip on matplotlib plots. Derived classes might need to re-define showToolTip(), findPoint() and addDataSet(). """ TOOLTIP_SHOW_DELAY = 300 TOOLTIP_HIDE_DELAY = 0
[docs] def __init__(self): self.tooltip = None self.tooltip_annotation = None # for project table use. self.tooltip_ds = None self.tooltip_eid = None self.tooltip_show_timer = QtCore.QTimer() self.tooltip_show_timer.setSingleShot(True) self.tooltip_show_timer.timeout.connect(self.showToolTip) self.tooltip_hide_timer = QtCore.QTimer() self.tooltip_hide_timer.setSingleShot(True) self.tooltip_hide_timer.timeout.connect(self.hideToolTip) self.data_sets = [] self.st = None self.title = ""
[docs] def showToolTip(self): """ Constructs and displays the tooltip. Should be re-defined as needed in derived classes. """ if self.st: self.tooltip = LabeledStructureToolTip(structure=self.st) if self.title: self.tooltip.addLabel(self.title) self.tooltip.show()
[docs] def hideToolTip(self): """ Hide and remove the current tooltip, stops the show timer if still running """ if self.tooltip_show_timer.isActive(): self.tooltip_show_timer.stop() if self.tooltip: self.tooltip.hide() self.tooltip = None self.tooltip_ds = None self.tooltip_eid = None
[docs] def addDataSet(self, ds): """ Adds data sets. The reason it is a list of data sets is primarily to work with projplot.PlotWindow. In the case of multiple sets, derived class should overwrite findPoint method. :param ds: Data set to add. :type ds: list of 2-element tuples. [(x1, y1), (x2, y2), ...] Derived class can use its own type of data sets. """ self.data_sets.append(ds)
[docs] def mouseMove(self, event): """ A mouse move event handler used to pick points in the plot """ if not event.inaxes: self.tooltip_hide_timer.start(self.TOOLTIP_HIDE_DELAY) return found_point = self.findPoint(event) if not found_point and self.tooltip: self.tooltip_hide_timer.start(self.TOOLTIP_HIDE_DELAY)
[docs] def findPoint(self, event): """ Takes care of all the stuff needed if the data point is found. Might need to redefine in derived classes. :param event: mouse event :type event: matplotlib.backend_bases.Event :return: Whether the point at the mouse event is found :rtype: bool """ if not self.data_sets: return False if event.xdata is None or event.ydata is None: return False ds = self.data_sets[0] # ds is a list of 2-ele tuples [(x1, y1), (x2, y2)...] x_min = min([data[0] for data in ds]) x_max = max([data[0] for data in ds]) y_min = min([data[1] for data in ds]) y_max = max([data[1] for data in ds]) if (event.xdata >= x_min and event.xdata <= x_max and event.ydata >= y_min and event.ydata <= y_max): return True else: return False