source: sasview/src/sas/qtgui/PlotterBase.py @ 55d89f8

ESS_GUIESS_GUI_DocsESS_GUI_batch_fittingESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_iss879ESS_GUI_iss959ESS_GUI_openclESS_GUI_orderingESS_GUI_sync_sascalc
Last change on this file since 55d89f8 was 55d89f8, checked in by Piotr Rozyczko <rozyczko@…>, 7 years ago

Context menu 3D plotting

  • Property mode set to 100644
File size: 6.7 KB
Line 
1import pylab
2
3from PyQt4 import QtGui
4
5# TODO: Replace the qt4agg calls below with qt5 equivalent.
6# Requires some code modifications.
7# https://www.boxcontrol.net/embedding-matplotlib-plot-on-pyqt5-gui.html
8#
9from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
10from matplotlib.backends.backend_qt4agg import NavigationToolbar2QT as NavigationToolbar
11
12import matplotlib.pyplot as plt
13
14DEFAULT_CMAP = pylab.cm.jet
15from sas.qtgui.ScaleProperties import ScaleProperties
16import sas.qtgui.PlotUtilities as PlotUtilities
17import sas.qtgui.PlotHelper as PlotHelper
18
19class PlotterBase(QtGui.QDialog):
20    def __init__(self, parent=None, quickplot=False):
21        super(PlotterBase, self).__init__(parent)
22
23        # Required for the communicator
24        self.parent = parent
25        self.quickplot = quickplot
26
27        # a figure instance to plot on
28        self.figure = plt.figure()
29
30        # this is the Canvas Widget that displays the `figure`
31        # it takes the `figure` instance as a parameter to __init__
32        self.canvas = FigureCanvas(self.figure)
33
34        # this is the Navigation widget
35        # it takes the Canvas widget and a parent
36        self.toolbar = NavigationToolbar(self.canvas, self)
37
38        self.properties = ScaleProperties(self)
39
40        # set the layout
41        layout = QtGui.QVBoxLayout()
42        layout.setMargin(0)
43        layout.addWidget(self.canvas)
44
45        # defaults
46        self.current_plot = 111
47        self._data = [] # Original 1D/2D object
48        self._xscale = 'log'
49        self._yscale = 'log'
50        self.qx_data = []
51        self.qy_data = []
52        self.color=0
53        self.symbol=0
54        self.grid_on = False
55        self.scale = 'linear'
56        self.x_label = "log10(x)"
57        self.y_label = "log10(y)"
58
59        # default color map
60        self.cmap = DEFAULT_CMAP
61
62        self.ax = self.figure.add_subplot(self.current_plot)
63        self.canvas.figure.set_facecolor('#FFFFFF')
64
65        if not quickplot:
66            # set the layout
67            layout.addWidget(self.toolbar)
68            # Notify the helper
69            PlotHelper.addPlot(self)
70            # Add the context menu
71            self.contextMenu()
72            # Notify the listeners
73            self.parent.communicator.activeGraphsSignal.emit(PlotHelper.currentPlots())
74        else:
75            self.contextMenuQuickPlot()
76
77        self.setLayout(layout)
78
79    @property
80    def data(self):
81        return self._data
82
83    @data.setter
84    def data(self, data=None):
85        """ virtual data setter """
86        raise ImportError("Data setter must be implemented in derived class.")
87
88    def title(self, title=""):
89        """ title setter """
90        self._title = title
91
92    #def id(self, id=""):
93    #    """ id setter """
94    #    self.id = id
95
96    @property
97    def xLabel(self, xlabel=""):
98        """ x-label setter """
99        return self.x_label
100
101    @xLabel.setter
102    def xLabel(self, xlabel=""):
103        """ x-label setter """
104        self.x_label = r'$%s$'% xlabel
105
106    @property
107    def yLabel(self, ylabel=""):
108        """ y-label setter """
109        return self.y_label
110
111    @yLabel.setter
112    def yLabel(self, ylabel=""):
113        """ y-label setter """
114        self.y_label = r'$%s$'% ylabel
115
116    @property
117    def yscale(self):
118        """ Y-axis scale getter """
119        return self._yscale
120
121    @yscale.setter
122    def yscale(self, scale='linear'):
123        """ Y-axis scale setter """
124        self.ax.set_yscale(scale, nonposy='clip')
125        self._yscale = scale
126
127    @property
128    def xscale(self):
129        """ X-axis scale getter """
130        return self._xscale
131
132    @xscale.setter
133    def xscale(self, scale='linear'):
134        """ X-axis scale setter """
135        self.ax.set_xscale(scale)
136        self._xscale = scale
137
138    def contextMenu(self):
139        """
140        Define context menu and associated actions for the MPL widget
141        """
142        # Actions
143        self.contextMenu = QtGui.QMenu(self)
144        self.actionSaveImage = self.contextMenu.addAction("Save Image")
145        self.actionPrintImage = self.contextMenu.addAction("Print Image")
146        self.actionCopyToClipboard = self.contextMenu.addAction("Copy to Clipboard")
147        self.contextMenu.addSeparator()
148
149        # Define the callbacks
150        self.actionSaveImage.triggered.connect(self.onImageSave)
151        self.actionPrintImage.triggered.connect(self.onImagePrint)
152        self.actionCopyToClipboard.triggered.connect(self.onClipboardCopy)
153
154    def contextMenuQuickPlot(self):
155        """
156        Define context menu and associated actions for the quickplot MPL widget
157        """
158        raise ImportError("Context menu method must be implemented in derived class.")
159
160    def contextMenuEvent(self, event):
161        """
162        Display the context menu
163        """
164        self.contextMenu.exec_( self.canvas.mapToGlobal(event.pos()) )
165
166    def clean(self):
167        """
168        Redraw the graph
169        """
170        self.figure.delaxes(self.ax)
171        self.ax = self.figure.add_subplot(self.current_plot)
172
173    def plot(self, marker=None, linestyle=None):
174        """
175        VIRTUAL
176        Plot the content of self._data
177        """
178        raise ImportError("Plot method must be implemented in derived class.")
179
180    def closeEvent(self, event):
181        """
182        Overwrite the close event adding helper notification
183        """
184        # Please remove me from your database.
185        PlotHelper.deletePlot(PlotHelper.idOfPlot(self))
186        # Notify the listeners
187        self.parent.communicator.activeGraphsSignal.emit(PlotHelper.currentPlots())
188        event.accept()
189
190    def onImageSave(self):
191        """
192        Use the internal MPL method for saving to file
193        """
194        self.toolbar.save_figure()
195
196    def onImagePrint(self):
197        """
198        Display printer dialog and print the MPL widget area
199        """
200        # Define the printer
201        printer = QtGui.QPrinter()
202
203        # Display the print dialog
204        dialog = QtGui.QPrintDialog(printer)
205        dialog.setModal(True)
206        dialog.setWindowTitle("Print")
207        if(dialog.exec_() != QtGui.QDialog.Accepted):
208            return
209
210        painter = QtGui.QPainter(printer)
211        # Create a label with pixmap drawn
212        pmap = QtGui.QPixmap.grabWidget(self)
213        printLabel = QtGui.QLabel()
214        printLabel.setPixmap(pmap)
215
216        # Print the label
217        printLabel.render(painter)
218        painter.end()
219
220    def onClipboardCopy(self):
221        """
222        Copy MPL widget area to buffer
223        """
224        bmp = QtGui.QApplication.clipboard()
225        pixmap = QtGui.QPixmap.grabWidget(self.canvas)
226        bmp.setPixmap(pixmap)
227
228    def onGridToggle(self):
229        """
230        Add/remove grid lines from MPL plot
231        """
232        self.grid_on = (not self.grid_on)
233        self.ax.grid(self.grid_on)
234        self.canvas.draw_idle()
Note: See TracBrowser for help on using the repository browser.