source: sasview/src/sas/qtgui/Plotter2D.py @ 0532d7c1

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 0532d7c1 was c4e5400, checked in by Piotr Rozyczko <rozyczko@…>, 8 years ago

Refactored context menu setup for plots

  • Property mode set to 100644
File size: 7.2 KB
RevLine 
[49e124c]1import copy
2import numpy
3import pylab
4
5from PyQt4 import QtGui
6
[31c5b58]7DEFAULT_CMAP = pylab.cm.jet
8
9import sas.qtgui.PlotUtilities as PlotUtilities
[ef01be4]10from sas.qtgui.PlotterBase import PlotterBase
[64f1e93]11from mpl_toolkits.mplot3d import Axes3D
[49e124c]12
[fecfe28]13# Minimum value of Z for which we will present data.
14MIN_Z=-32
15
[416fa8f]16class Plotter2DWidget(PlotterBase):
[c4e5400]17    """
18    2D Plot widget for use with a QDialog
[fecfe28]19    """
[416fa8f]20    def __init__(self, parent=None, manager=None, quickplot=False, dimension=2):
[55d89f8]21        self.dimension = dimension
[416fa8f]22        super(Plotter2DWidget, self).__init__(parent, manager=manager, quickplot=quickplot)
[49e124c]23
[31c5b58]24    @property
25    def data(self):
26        return self._data
27
28    @data.setter
[49e124c]29    def data(self, data=None):
30        """ data setter """
[14d9c7b]31        self._data = data
[fecfe28]32        self.qx_data = data.qx_data
33        self.qy_data = data.qy_data
34        self.xmin = data.xmin
35        self.xmax = data.xmax
36        self.ymin = data.ymin
37        self.ymax = data.ymax
38        self.zmin = data.zmin
39        self.zmax = data.zmax
40        self.label = data.name
41        self.xLabel = "%s(%s)"%(data._xaxis, data._xunit)
42        self.yLabel = "%s(%s)"%(data._yaxis, data._yunit)
[49e124c]43        self.title(title=data.title)
44
45    def plot(self, marker=None, linestyle=None):
46        """
47        Plot 2D self._data
48        """
[64f1e93]49        # Toggle the scale
[55d89f8]50        zmin_2D_temp = self.zmin
51        zmax_2D_temp = self.zmax
[fecfe28]52        # self.scale predefined in the baseclass
[55d89f8]53        if self.scale == 'log_{10}':
54            self.scale = 'linear'
55            if not self.zmin is None:
[cad617b]56                zmin_2D_temp = numpy.power(10, self.zmin)
[55d89f8]57            if not self.zmax is None:
[cad617b]58                zmax_2D_temp = numpy.power(10, self.zmax)
[55d89f8]59        else:
60            self.scale = 'log_{10}'
61            if not self.zmin is None:
62                # min log value: no log(negative)
63                if self.zmin <= 0:
[fecfe28]64                    zmin_2D_temp = MIN_Z
[55d89f8]65                else:
66                    zmin_2D_temp = numpy.log10(self.zmin)
67            if not self.zmax is None:
68                zmax_2D_temp = numpy.log10(self.zmax)
[31c5b58]69
[64f1e93]70        # Prepare and show the plot
71        self.showPlot(data=self.data.data,
72                      qx_data=self.qx_data,
73                      qy_data=self.qy_data,
74                      xmin=self.xmin,
75                      xmax=self.xmax,
76                      ymin=self.ymin, ymax=self.ymax,
77                      cmap=self.cmap, zmin=zmin_2D_temp,
78                      zmax=zmax_2D_temp)
[6d05e1d]79
[c4e5400]80    def contextMenu(self):
81        """
82        Define common context menu and associated actions for the MPL widget
83        """
84        self.defaultContextMenu()
85
[6d05e1d]86    def contextMenuQuickPlot(self):
87        """
88        Define context menu and associated actions for the quickplot MPL widget
89        """
[c4e5400]90        self.defaultContextMenu()
91
[55d89f8]92        if self.dimension == 2:
93            self.actionToggleGrid = self.contextMenu.addAction("Toggle Grid On/Off")
94            self.contextMenu.addSeparator()
[6d05e1d]95        self.actionChangeScale = self.contextMenu.addAction("Toggle Linear/Log Scale")
96
97        # Define the callbacks
[c4e5400]98        self.actionChangeScale.triggered.connect(self.onToggleScale)
[55d89f8]99        if self.dimension == 2:
100            self.actionToggleGrid.triggered.connect(self.onGridToggle)
[6d05e1d]101
102    def onToggleScale(self, event):
103        """
104        Toggle axis and replot image
105        """
[55d89f8]106        self.plot()
[6d05e1d]107
[64f1e93]108    def showPlot(self, data, qx_data, qy_data, xmin, xmax, ymin, ymax,
109                 zmin, zmax, color=0, symbol=0, markersize=0,
110                 label='data2D', cmap=DEFAULT_CMAP):
[6d05e1d]111        """
[64f1e93]112        Render and show the current data
[6d05e1d]113        """
114        self.qx_data = qx_data
115        self.qy_data = qy_data
116        self.xmin = xmin
117        self.xmax = xmax
118        self.ymin = ymin
119        self.ymax = ymax
120        self.zmin = zmin
121        self.zmax = zmax
122        # If we don't have any data, skip.
[fecfe28]123        if data is None:
[6d05e1d]124            return
125        if data.ndim == 1:
126            output = PlotUtilities.build_matrix(data, self.qx_data, self.qy_data)
127        else:
128            output = copy.deepcopy(data)
129
130        zmin_temp = self.zmin
131        # check scale
132        if self.scale == 'log_{10}':
133            try:
134                if  self.zmin <= 0  and len(output[output > 0]) > 0:
135                    zmin_temp = self.zmin_2D
136                    output[output > 0] = numpy.log10(output[output > 0])
137                elif self.zmin <= 0:
138                    zmin_temp = self.zmin
139                    output[output > 0] = numpy.zeros(len(output))
[fecfe28]140                    output[output <= 0] = MIN_Z
[6d05e1d]141                else:
142                    zmin_temp = self.zmin
143                    output[output > 0] = numpy.log10(output[output > 0])
144            except:
145                #Too many problems in 2D plot with scale
146                output[output > 0] = numpy.log10(output[output > 0])
147                pass
148
149        self.cmap = cmap
150        if self.dimension != 3:
151            #Re-adjust colorbar
152            self.figure.subplots_adjust(left=0.2, right=.8, bottom=.2)
153
154            im = self.ax.imshow(output, interpolation='nearest',
155                                origin='lower',
156                                vmin=zmin_temp, vmax=self.zmax,
157                                cmap=self.cmap,
158                                extent=(self.xmin, self.xmax,
159                                        self.ymin, self.ymax))
160
161            cbax = self.figure.add_axes([0.84, 0.2, 0.02, 0.7])
[b4b8589]162
163            # Current labels for axes
164            self.ax.set_ylabel(self.y_label)
165            self.ax.set_xlabel(self.x_label)
166
167            # Title only for regular charts
168            if not self.quickplot:
169                self.ax.set_title(label=self._title)
170
[fecfe28]171            if cbax is None:
172                ax.set_frame_on(False)
173                cb = self.figure.colorbar(im, shrink=0.8, aspect=20)
174            else:
175                cb = self.figure.colorbar(im, cax=cbax)
176
177            cb.update_bruteforce(im)
178            cb.set_label('$' + self.scale + '$')
[b4b8589]179
[6d05e1d]180        else:
181            # clear the previous 2D from memory
182            self.figure.clear()
183
184            self.figure.subplots_adjust(left=0.1, right=.8, bottom=.1)
185
[55d89f8]186            X = self._data.x_bins[0:-1]
187            Y = self._data.y_bins[0:-1]
[6d05e1d]188            X, Y = numpy.meshgrid(X, Y)
189
[64f1e93]190            ax = Axes3D(self.figure)
[fecfe28]191            #cbax = self.figure.add_axes([0.84, 0.1, 0.02, 0.8])
[b4b8589]192
[64f1e93]193            # Disable rotation for large sets.
194            # TODO: Define "large" for a dataset
195            SET_TOO_LARGE = 500
196            if len(X) > SET_TOO_LARGE:
197                ax.disable_mouse_rotation()
198
[6d05e1d]199            self.figure.canvas.resizing = False
200            im = ax.plot_surface(X, Y, output, rstride=1, cstride=1, cmap=cmap,
201                                 linewidth=0, antialiased=False)
[55d89f8]202            self.ax.set_axis_off()
[6d05e1d]203
204        if self.dimension != 3:
205            self.figure.canvas.draw_idle()
206        else:
207            self.figure.canvas.draw()
[416fa8f]208
209class Plotter2D(QtGui.QDialog, Plotter2DWidget):
210    def __init__(self, parent=None, quickplot=False, dimension=2):
211
212        QtGui.QDialog.__init__(self)
[cad617b]213        Plotter2DWidget.__init__(self, manager=parent, quickplot=quickplot, dimension=dimension)
[c4e5400]214        icon = QtGui.QIcon()
215        icon.addPixmap(QtGui.QPixmap(":/res/ball.ico"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
216        self.setWindowIcon(icon)
Note: See TracBrowser for help on using the repository browser.