source: sasview/src/sas/qtgui/Plotter2D.py @ 416fa8f

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

Initial implementation of the mask editor.
Refactored plotter base to QDialog and reimplemented as local widgets.
Fixed some unit tests.

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