source: sasview/src/sas/qtgui/Plotter2D.py @ 9290b1a

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

Added AddText? to plot, enabled legend drag - SASVIEW-378

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