source: sasview/src/sas/qtgui/PlotterBase.py @ 6d05e1d

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 6d05e1d was 6d05e1d, checked in by Piotr Rozyczko <rozyczko@…>, 7 years ago

More functionality for quick plots + unit tests

  • Property mode set to 100755
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.dimension=1
55        self.grid_on = False
56        self.scale = 'linear'
57        self.x_label = "log10(x)"
58        self.y_label = "log10(y)"
59
60        # default color map
61        self.cmap = DEFAULT_CMAP
62
63        self.ax = self.figure.add_subplot(self.current_plot)
64        self.canvas.figure.set_facecolor('#FFFFFF')
65
66        if not quickplot:
67            # set the layout
68            layout.addWidget(self.toolbar)
69            # Notify the helper
70            PlotHelper.addPlot(self)
71            # Add the context menu
72            self.contextMenu()
73            # Notify the listeners
74            self.parent.communicator.activeGraphsSignal.emit(PlotHelper.currentPlots())
75        else:
76            self.contextMenuQuickPlot()
77
78        self.setLayout(layout)
79
80    @property
81    def data(self):
82        return self._data
83
84    @data.setter
85    def data(self, data=None):
86        """ virtual data setter """
87        raise ImportError("Data setter must be implemented in derived class.")
88
89    def title(self, title=""):
90        """ title setter """
91        self._title = title
92
93    #def id(self, id=""):
94    #    """ id setter """
95    #    self.id = id
96
97    @property
98    def xLabel(self, xlabel=""):
99        """ x-label setter """
100        return self.x_label
101
102    @xLabel.setter
103    def xLabel(self, xlabel=""):
104        """ x-label setter """
105        self.x_label = r'$%s$'% xlabel
106
107    @property
108    def yLabel(self, ylabel=""):
109        """ y-label setter """
110        return self.y_label
111
112    @yLabel.setter
113    def yLabel(self, ylabel=""):
114        """ y-label setter """
115        self.y_label = r'$%s$'% ylabel
116
117    @property
118    def yscale(self):
119        """ Y-axis scale getter """
120        return self._yscale
121
122    @yscale.setter
123    def yscale(self, scale='linear'):
124        """ Y-axis scale setter """
125        self.ax.set_yscale(scale, nonposy='clip')
126        self._yscale = scale
127
128    @property
129    def xscale(self):
130        """ X-axis scale getter """
131        return self._xscale
132
133    @xscale.setter
134    def xscale(self, scale='linear'):
135        """ X-axis scale setter """
136        self.ax.set_xscale(scale)
137        self._xscale = scale
138
139    def contextMenu(self):
140        """
141        Define context menu and associated actions for the MPL widget
142        """
143        # Actions
144        self.contextMenu = QtGui.QMenu(self)
145        self.actionSaveImage = self.contextMenu.addAction("Save Image")
146        self.actionPrintImage = self.contextMenu.addAction("Print Image")
147        self.actionCopyToClipboard = self.contextMenu.addAction("Copy to Clipboard")
148        self.contextMenu.addSeparator()
149
150        # Define the callbacks
151        self.actionSaveImage.triggered.connect(self.onImageSave)
152        self.actionPrintImage.triggered.connect(self.onImagePrint)
153        self.actionCopyToClipboard.triggered.connect(self.onClipboardCopy)
154
155    def contextMenuQuickPlot(self):
156        """
157        Define context menu and associated actions for the quickplot MPL widget
158        """
159        raise ImportError("Context menu method must be implemented in derived class.")
160
161    def contextMenuEvent(self, event):
162        """
163        Display the context menu
164        """
165        self.contextMenu.exec_( self.canvas.mapToGlobal(event.pos()) )
166
167    def clean(self):
168        """
169        Redraw the graph
170        """
171        self.figure.delaxes(self.ax)
172        self.ax = self.figure.add_subplot(self.current_plot)
173
174    def plot(self, marker=None, linestyle=None):
175        """
176        VIRTUAL
177        Plot the content of self._data
178        """
179        raise ImportError("Plot method must be implemented in derived class.")
180
181    def closeEvent(self, event):
182        """
183        Overwrite the close event adding helper notification
184        """
185        # Please remove me from your database.
186        PlotHelper.deletePlot(PlotHelper.idOfPlot(self))
187        # Notify the listeners
188        self.parent.communicator.activeGraphsSignal.emit(PlotHelper.currentPlots())
189        event.accept()
190
191    def onImageSave(self):
192        """
193        Use the internal MPL method for saving to file
194        """
195        self.toolbar.save_figure()
196
197    def onImagePrint(self):
198        """
199        Display printer dialog and print the MPL widget area
200        """
201        # Define the printer
202        printer = QtGui.QPrinter()
203
204        # Display the print dialog
205        dialog = QtGui.QPrintDialog(printer)
206        dialog.setModal(True)
207        dialog.setWindowTitle("Print")
208        if(dialog.exec_() != QtGui.QDialog.Accepted):
209            return
210
211        painter = QtGui.QPainter(printer)
212        # Create a label with pixmap drawn
213        pmap = QtGui.QPixmap.grabWidget(self)
214        printLabel = QtGui.QLabel()
215        printLabel.setPixmap(pmap)
216
217        # Print the label
218        printLabel.render(painter)
219        painter.end()
220
221    def onClipboardCopy(self):
222        """
223        Copy MPL widget area to buffer
224        """
225        bmp = QtGui.QApplication.clipboard()
226        pixmap = QtGui.QPixmap.grabWidget(self.canvas)
227        bmp.setPixmap(pixmap)
228
229    def onGridToggle(self):
230        """
231        Add/remove grid lines from MPL plot
232        """
233        self.grid_on = (not self.grid_on)
234        self.ax.grid(self.grid_on)
235        self.canvas.draw_idle()
Note: See TracBrowser for help on using the repository browser.