Changeset 6d05e1d in sasview


Ignore:
Timestamp:
Dec 6, 2016 3:39:24 AM (7 years ago)
Author:
Piotr Rozyczko <rozyczko@…>
Branches:
ESS_GUI, ESS_GUI_Docs, ESS_GUI_batch_fitting, ESS_GUI_bumps_abstraction, ESS_GUI_iss1116, ESS_GUI_iss879, ESS_GUI_iss959, ESS_GUI_opencl, ESS_GUI_ordering, ESS_GUI_sync_sascalc
Children:
55d89f8
Parents:
b94889a
git-author:
Piotr Rozyczko <rozyczko@…> (12/06/16 03:38:55)
git-committer:
Piotr Rozyczko <rozyczko@…> (12/06/16 03:39:24)
Message:

More functionality for quick plots + unit tests

Location:
src/sas
Files:
1 added
7 edited

Legend:

Unmodified
Added
Removed
  • src/sas/qtgui/Plotter.py

    ref01be4 r6d05e1d  
    1 import logging 
    2  
    31from PyQt4 import QtGui 
    42 
    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 # 
    9 from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas 
    10 from matplotlib.backends.backend_qt4agg import NavigationToolbar2QT as NavigationToolbar 
    113import matplotlib.pyplot as plt 
    12 import matplotlib as mpl 
    13  
    14 import sas.qtgui.PlotHelper as PlotHelper 
     4 
     5from sas.sasgui.plottools import transform 
     6from sas.sasgui.plottools.convert_units import convert_unit 
    157from sas.qtgui.PlotterBase import PlotterBase 
    168 
     
    2719        """ data setter """ 
    2820        self._data = value 
    29         self.label=value.name 
    30         self.xLabel(xlabel="%s(%s)"%(value._xaxis, value._xunit)) 
    31         self.yLabel(ylabel="%s(%s)"%(value._yaxis, value._yunit)) 
     21        self.xLabel = "%s(%s)"%(value._xaxis, value._xunit) 
     22        self.yLabel = "%s(%s)"%(value._yaxis, value._yunit) 
    3223        self.title(title=value.title) 
    3324 
     
    3627        Plot self._data 
    3728        """ 
    38         # create an axis 
     29        # Shortcut for an axis 
    3930        ax = self.ax 
    4031 
    4132        if marker == None: 
    42             marker = '*' 
     33            marker = 'o' 
    4334 
    4435        if linestyle == None: 
    4536            linestyle = '-' 
    4637 
    47         # plot data with legend 
    48         ax.plot(self._data.x, self._data.y, marker=marker, linestyle=linestyle, label=self.title) 
     38        # plot data with title 
     39        ax.plot(self._data.view.x, 
     40                self._data.view.y, 
     41                marker=marker, 
     42                linestyle=linestyle, 
     43                label=self._title) 
    4944 
    5045        # Now add the legend with some customizations. 
    5146        legend = ax.legend(loc='upper right', shadow=True) 
    5247 
     48        # Current labels for axes 
    5349        ax.set_ylabel(self.y_label) 
    5450        ax.set_xlabel(self.x_label) 
     51 
    5552        # Title only for regular charts 
    5653        if not self.quickplot: 
    57             ax.set_title(label=self.title) 
    58  
    59         ax.set_yscale('log') 
    60         ax.set_xscale('log') 
     54            ax.set_title(label=self._title) 
     55 
     56        # Include scaling (log vs. linear) 
     57        ax.set_yscale(self.xscale) 
     58        ax.set_xscale(self.xscale) 
    6159 
    6260        # refresh canvas 
    6361        self.canvas.draw() 
    6462 
     63    def contextMenuQuickPlot(self): 
     64        """ 
     65        Define context menu and associated actions for the quickplot MPL widget 
     66        """ 
     67        # Actions 
     68        self.contextMenu = QtGui.QMenu(self) 
     69        self.actionSaveImage = self.contextMenu.addAction("Save Image") 
     70        self.actionPrintImage = self.contextMenu.addAction("Print Image") 
     71        self.actionCopyToClipboard = self.contextMenu.addAction("Copy to Clipboard") 
     72        self.contextMenu.addSeparator() 
     73        self.actionToggleGrid = self.contextMenu.addAction("Toggle Grid On/Off") 
     74        self.contextMenu.addSeparator() 
     75        self.actionChangeScale = self.contextMenu.addAction("Change Scale") 
     76 
     77        # Define the callbacks 
     78        self.actionSaveImage.triggered.connect(self.onImageSave) 
     79        self.actionPrintImage.triggered.connect(self.onImagePrint) 
     80        self.actionCopyToClipboard.triggered.connect(self.onClipboardCopy) 
     81        self.actionToggleGrid.triggered.connect(self.onGridToggle) 
     82        self.actionChangeScale.triggered.connect(self.onScaleChange) 
     83 
     84    def onScaleChange(self): 
     85        """ 
     86        Show a dialog allowing axes rescaling 
     87        """ 
     88        if self.properties.exec_() == QtGui.QDialog.Accepted: 
     89            xLabel, yLabel = self.properties.getValues() 
     90            self.xyTransform(xLabel, yLabel) 
     91 
     92    def xyTransform(self, xLabel="", yLabel=""): 
     93        """ 
     94        Transforms x and y in View and set the scale 
     95        """ 
     96        # Clear the plot first 
     97        plt.cla() 
     98 
     99        # Changing the scale might be incompatible with 
     100        # currently displayed data (for instance, going 
     101        # from ln to log when all plotted values have 
     102        # negative natural logs). 
     103        # Go linear and only change the scale at the end. 
     104        self._xscale = "linear" 
     105        self._yscale = "linear" 
     106        _xscale = 'linear' 
     107        _yscale = 'linear' 
     108        # Local data is either 1D or 2D 
     109        if self.data.id == 'fit': 
     110            return 
     111 
     112        # control axis labels from the panel itself 
     113        yname, yunits = self.data.get_yaxis() 
     114        xname, xunits = self.data.get_xaxis() 
     115 
     116        # Goes through all possible scales 
     117        # self.x_label is already wrapped with Latex "$", so using the argument 
     118 
     119        # X 
     120        if xLabel == "x": 
     121            self.data.transformX(transform.toX, transform.errToX) 
     122            self.xLabel = "%s(%s)" % (xname, xunits) 
     123        if xLabel == "x^(2)": 
     124            self.data.transformX(transform.toX2, transform.errToX2) 
     125            xunits = convert_unit(2, xunits) 
     126            self.xLabel = "%s^{2}(%s)" % (xname, xunits) 
     127        if xLabel == "x^(4)": 
     128            self.data.transformX(transform.toX4, transform.errToX4) 
     129            xunits = convert_unit(4, xunits) 
     130            self.xLabel = "%s^{4}(%s)" % (xname, xunits) 
     131        if xLabel == "ln(x)": 
     132            self.data.transformX(transform.toLogX, transform.errToLogX) 
     133            self.xLabel = "\ln{(%s)}(%s)" % (xname, xunits) 
     134        if xLabel == "log10(x)": 
     135            self.data.transformX(transform.toX_pos, transform.errToX_pos) 
     136            _xscale = 'log' 
     137            self.xLabel = "%s(%s)" % (xname, xunits) 
     138        if xLabel == "log10(x^(4))": 
     139            self.data.transformX(transform.toX4, transform.errToX4) 
     140            xunits = convert_unit(4, xunits) 
     141            self.xLabel = "%s^{4}(%s)" % (xname, xunits) 
     142            _xscale = 'log' 
     143 
     144        # Y 
     145        if yLabel == "ln(y)": 
     146            self.data.transformY(transform.toLogX, transform.errToLogX) 
     147            self.yLabel = "\ln{(%s)}(%s)" % (yname, yunits) 
     148        if yLabel == "y": 
     149            self.data.transformY(transform.toX, transform.errToX) 
     150            self.yLabel = "%s(%s)" % (yname, yunits) 
     151        if yLabel == "log10(y)": 
     152            self.data.transformY(transform.toX_pos, transform.errToX_pos) 
     153            _yscale = 'log' 
     154            self.yLabel = "%s(%s)" % (yname, yunits) 
     155        if yLabel == "y^(2)": 
     156            self.data.transformY(transform.toX2, transform.errToX2) 
     157            yunits = convert_unit(2, yunits) 
     158            self.yLabel = "%s^{2}(%s)" % (yname, yunits) 
     159        if yLabel == "1/y": 
     160            self.data.transformY(transform.toOneOverX, transform.errOneOverX) 
     161            yunits = convert_unit(-1, yunits) 
     162            self.yLabel = "1/%s(%s)" % (yname, yunits) 
     163        if yLabel == "y*x^(2)": 
     164            self.data.transformY(transform.toYX2, transform.errToYX2) 
     165            xunits = convert_unit(2, xunits) 
     166            self.yLabel = "%s \ \ %s^{2}(%s%s)" % (yname, xname, yunits, xunits) 
     167        if yLabel == "y*x^(4)": 
     168            self.data.transformY(transform.toYX4, transform.errToYX4) 
     169            xunits = convert_unit(4, xunits) 
     170            self.yLabel = "%s \ \ %s^{4}(%s%s)" % (yname, xname, yunits, xunits) 
     171        if yLabel == "1/sqrt(y)": 
     172            self.data.transformY(transform.toOneOverSqrtX, 
     173                                 transform.errOneOverSqrtX) 
     174            yunits = convert_unit(-0.5, yunits) 
     175            self.yLabel = "1/\sqrt{%s}(%s)" % (yname, yunits) 
     176        if yLabel == "ln(y*x)": 
     177            self.data.transformY(transform.toLogXY, transform.errToLogXY) 
     178            self.yLabel = "\ln{(%s \ \ %s)}(%s%s)" % (yname, xname, yunits, xunits) 
     179        if yLabel == "ln(y*x^(2))": 
     180            self.data.transformY(transform.toLogYX2, transform.errToLogYX2) 
     181            xunits = convert_unit(2, xunits) 
     182            self.yLabel = "\ln (%s \ \ %s^{2})(%s%s)" % (yname, xname, yunits, xunits) 
     183        if yLabel == "ln(y*x^(4))": 
     184            self.data.transformY(transform.toLogYX4, transform.errToLogYX4) 
     185            xunits = convert_unit(4, xunits) 
     186            self.yLabel = "\ln (%s \ \ %s^{4})(%s%s)" % (yname, xname, yunits, xunits) 
     187        if yLabel == "log10(y*x^(4))": 
     188            self.data.transformY(transform.toYX4, transform.errToYX4) 
     189            xunits = convert_unit(4, xunits) 
     190            _yscale = 'log' 
     191            self.yLabel = "%s \ \ %s^{4}(%s%s)" % (yname, xname, yunits, xunits) 
     192 
     193        # Perform the transformation of data in data1d->View 
     194        self.data.transformView() 
     195 
     196        self.xscale = _xscale 
     197        self.yscale = _yscale 
     198 
     199        # Plot the updated chart 
     200        self.plot(marker='o', linestyle='') 
  • src/sas/qtgui/Plotter2D.py

    ref01be4 r6d05e1d  
    1 import logging 
    21import copy 
    32import numpy 
     
    65from PyQt4 import QtGui 
    76 
    8 # TODO: Replace the qt4agg calls below with qt5 equivalent. 
    9 # Requires some code modifications. 
    10 # https://www.boxcontrol.net/embedding-matplotlib-plot-on-pyqt5-gui.html 
    11 # 
    12 from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas 
    13 from matplotlib.backends.backend_qt4agg import NavigationToolbar2QT as NavigationToolbar 
    14 import matplotlib.pyplot as plt 
    15  
    167DEFAULT_CMAP = pylab.cm.jet 
    178 
    189import sas.qtgui.PlotUtilities as PlotUtilities 
    19 import sas.qtgui.PlotHelper as PlotHelper 
    2010from sas.qtgui.PlotterBase import PlotterBase 
    2111 
     
    4131        self.zmax=data.zmax 
    4232        self.label=data.name 
    43         self.xLabel(xlabel="%s(%s)"%(data._xaxis, data._xunit)) 
    44         self.yLabel(ylabel="%s(%s)"%(data._yaxis, data._yunit)) 
     33        self.dimension=2 
     34        self.xLabel="%s(%s)"%(data._xaxis, data._xunit) 
     35        self.yLabel="%s(%s)"%(data._yaxis, data._yunit) 
    4536        self.title(title=data.title) 
    4637 
     
    5748        # Title only for regular charts 
    5849        if not self.quickplot: 
    59             ax.set_title(label=self.title) 
     50            ax.set_title(label=self._title) 
    6051 
    6152        # Re-adjust colorbar 
     
    7566        cb = self.figure.colorbar(im, cax=cbax) 
    7667        cb.update_bruteforce(im) 
    77         cb.set_label('$' + self._scale + '$') 
     68        cb.set_label('$' + self.scale + '$') 
    7869 
    7970        # Schedule the draw for the next time the event loop is idle. 
    8071        self.canvas.draw_idle() 
     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        self.actionToggleGrid = self.contextMenu.addAction("Toggle Grid On/Off") 
     84        self.contextMenu.addSeparator() 
     85        self.actionChangeScale = self.contextMenu.addAction("Toggle Linear/Log Scale") 
     86 
     87        # Define the callbacks 
     88        self.actionSaveImage.triggered.connect(self.onImageSave) 
     89        self.actionPrintImage.triggered.connect(self.onImagePrint) 
     90        self.actionCopyToClipboard.triggered.connect(self.onClipboardCopy) 
     91        self.actionToggleGrid.triggered.connect(self.onGridToggle) 
     92        self.actionChangeScale.triggered.connect(self.onToggleScale) 
     93 
     94    def onToggleScale(self, event): 
     95        """ 
     96        Toggle axis and replot image 
     97 
     98        """ 
     99        zmin_2D_temp = self.zmin 
     100        zmax_2D_temp = self.zmax 
     101        if self.scale == 'log_{10}': 
     102            self.scale = 'linear' 
     103            if not self.zmin is None: 
     104                zmin_2D_temp = math.pow(10, self.zmin) 
     105            if not self.zmax is None: 
     106                zmax_2D_temp = math.pow(10, self.zmax) 
     107        else: 
     108            self.scale = 'log_{10}' 
     109            if not self.zmin is None: 
     110                # min log value: no log(negative) 
     111                if self.zmin <= 0: 
     112                    zmin_2D_temp = -32 
     113                else: 
     114                    zmin_2D_temp = math.log10(self.zmin) 
     115            if not self.zmax is None: 
     116                zmax_2D_temp = math.log10(self.zmax) 
     117 
     118        self.image(data=self.data.data, qx_data=self.qx_data, 
     119                   qy_data=self.qy_data, xmin=self.xmin, 
     120                   xmax=self.xmax, 
     121                   ymin=self.ymin, ymax=self.ymax, 
     122                   cmap=self.cmap, zmin=zmin_2D_temp, 
     123                   zmax=zmax_2D_temp) 
     124 
     125 
     126    def image(self, data, qx_data, qy_data, xmin, xmax, ymin, ymax, 
     127              zmin, zmax, color=0, symbol=0, markersize=0, 
     128              label='data2D', cmap=DEFAULT_CMAP): 
     129        """ 
     130        Render the current data 
     131 
     132        """ 
     133        #self.data = data 
     134        self.qx_data = qx_data 
     135        self.qy_data = qy_data 
     136        self.xmin = xmin 
     137        self.xmax = xmax 
     138        self.ymin = ymin 
     139        self.ymax = ymax 
     140        self.zmin = zmin 
     141        self.zmax = zmax 
     142        #c = self.color(color) 
     143        # If we don't have any data, skip. 
     144        if data == None: 
     145            return 
     146        if data.ndim == 1: 
     147            #output = self._build_matrix() 
     148            output = PlotUtilities.build_matrix(data, self.qx_data, self.qy_data) 
     149        else: 
     150            output = copy.deepcopy(data) 
     151 
     152        zmin_temp = self.zmin 
     153        # check scale 
     154        if self.scale == 'log_{10}': 
     155            try: 
     156                if  self.zmin <= 0  and len(output[output > 0]) > 0: 
     157                    zmin_temp = self.zmin_2D 
     158                    output[output > 0] = numpy.log10(output[output > 0]) 
     159                    #In log scale Negative values are not correct in general 
     160                    #output[output<=0] = math.log(numpy.min(output[output>0])) 
     161                elif self.zmin <= 0: 
     162                    zmin_temp = self.zmin 
     163                    output[output > 0] = numpy.zeros(len(output)) 
     164                    output[output <= 0] = -32 
     165                else: 
     166                    zmin_temp = self.zmin 
     167                    output[output > 0] = numpy.log10(output[output > 0]) 
     168                    #In log scale Negative values are not correct in general 
     169                    #output[output<=0] = math.log(numpy.min(output[output>0])) 
     170            except: 
     171                #Too many problems in 2D plot with scale 
     172                output[output > 0] = numpy.log10(output[output > 0]) 
     173                pass 
     174 
     175        self.cmap = cmap 
     176        if self.dimension != 3: 
     177            #Re-adjust colorbar 
     178            self.figure.subplots_adjust(left=0.2, right=.8, bottom=.2) 
     179 
     180            im = self.ax.imshow(output, interpolation='nearest', 
     181                                origin='lower', 
     182                                vmin=zmin_temp, vmax=self.zmax, 
     183                                cmap=self.cmap, 
     184                                extent=(self.xmin, self.xmax, 
     185                                        self.ymin, self.ymax)) 
     186 
     187            cbax = self.figure.add_axes([0.84, 0.2, 0.02, 0.7]) 
     188        else: 
     189            # clear the previous 2D from memory 
     190            # mpl is not clf, so we do 
     191            self.figure.clear() 
     192 
     193            self.figure.subplots_adjust(left=0.1, right=.8, bottom=.1) 
     194 
     195            X = self.x_bins[0:-1] 
     196            Y = self.y_bins[0:-1] 
     197            X, Y = numpy.meshgrid(X, Y) 
     198 
     199            try: 
     200                # mpl >= 1.0.0 
     201                ax = self.figure.gca(projection='3d') 
     202                #ax.disable_mouse_rotation() 
     203                cbax = self.figure.add_axes([0.84, 0.1, 0.02, 0.8]) 
     204                if len(X) > 60: 
     205                    ax.disable_mouse_rotation() 
     206            except: 
     207                # mpl < 1.0.0 
     208                try: 
     209                    from mpl_toolkits.mplot3d import Axes3D 
     210                except: 
     211                    logging.error("PlotPanel could not import Axes3D") 
     212                self.figure.clear() 
     213                ax = Axes3D(self.figure) 
     214                if len(X) > 60: 
     215                    ax.cla() 
     216                cbax = None 
     217            self.figure.canvas.resizing = False 
     218            im = ax.plot_surface(X, Y, output, rstride=1, cstride=1, cmap=cmap, 
     219                                 linewidth=0, antialiased=False) 
     220            self.set_axis_off() 
     221 
     222        if cbax == None: 
     223            ax.set_frame_on(False) 
     224            cb = self.figure.colorbar(im, shrink=0.8, aspect=20) 
     225        else: 
     226            cb = self.figure.colorbar(im, cax=cbax) 
     227        cb.update_bruteforce(im) 
     228        cb.set_label('$' + self.scale + '$') 
     229        if self.dimension != 3: 
     230            self.figure.canvas.draw_idle() 
     231        else: 
     232            self.figure.canvas.draw() 
  • src/sas/qtgui/PlotterBase.py

    ref01be4 r6d05e1d  
    1 import logging 
    2 import copy 
    3 import numpy 
    41import pylab 
    52 
    63from PyQt4 import QtGui 
    7 from PyQt4 import QtCore 
    84 
    95# TODO: Replace the qt4agg calls below with qt5 equivalent. 
     
    139from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas 
    1410from matplotlib.backends.backend_qt4agg import NavigationToolbar2QT as NavigationToolbar 
    15 from matplotlib.backend_bases import NavigationToolbar2 
    1611 
    1712import matplotlib.pyplot as plt 
     
    4540        # set the layout 
    4641        layout = QtGui.QVBoxLayout() 
     42        layout.setMargin(0) 
    4743        layout.addWidget(self.canvas) 
    4844 
    4945        # defaults 
    5046        self.current_plot = 111 
    51         self._data = [] 
     47        self._data = [] # Original 1D/2D object 
     48        self._xscale = 'log' 
     49        self._yscale = 'log' 
    5250        self.qx_data = [] 
    5351        self.qy_data = [] 
    5452        self.color=0 
    5553        self.symbol=0 
     54        self.dimension=1 
    5655        self.grid_on = False 
    5756        self.scale = 'linear' 
     57        self.x_label = "log10(x)" 
     58        self.y_label = "log10(y)" 
    5859 
    5960        # default color map 
     
    6465 
    6566        if not quickplot: 
     67            # set the layout 
    6668            layout.addWidget(self.toolbar) 
    6769            # Notify the helper 
    6870            PlotHelper.addPlot(self) 
     71            # Add the context menu 
     72            self.contextMenu() 
    6973            # Notify the listeners 
    7074            self.parent.communicator.activeGraphsSignal.emit(PlotHelper.currentPlots()) 
     
    8084    @data.setter 
    8185    def data(self, data=None): 
    82         """ data setter """ 
    83         pass 
     86        """ virtual data setter """ 
     87        raise ImportError("Data setter must be implemented in derived class.") 
    8488 
    8589    def title(self, title=""): 
    8690        """ title setter """ 
    87         self.title = title 
    88  
    89     def id(self, id=""): 
    90         """ id setter """ 
    91         self.id = id 
    92  
     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 
    93103    def xLabel(self, xlabel=""): 
    94104        """ x-label setter """ 
    95105        self.x_label = r'$%s$'% xlabel 
    96106 
     107    @property 
     108    def yLabel(self, ylabel=""): 
     109        """ y-label setter """ 
     110        return self.y_label 
     111 
     112    @yLabel.setter 
    97113    def yLabel(self, ylabel=""): 
    98114        """ y-label setter """ 
     
    102118    def yscale(self): 
    103119        """ Y-axis scale getter """ 
    104         return self.yscale 
     120        return self._yscale 
    105121 
    106122    @yscale.setter 
    107123    def yscale(self, scale='linear'): 
    108124        """ Y-axis scale setter """ 
    109         self.subplot.set_yscale(scale, nonposy='clip') 
    110         self.yscale = scale 
     125        self.ax.set_yscale(scale, nonposy='clip') 
     126        self._yscale = scale 
    111127 
    112128    @property 
    113129    def xscale(self): 
    114130        """ X-axis scale getter """ 
    115         return self.xscale 
     131        return self._xscale 
    116132 
    117133    @xscale.setter 
    118134    def xscale(self, scale='linear'): 
    119135        """ X-axis scale setter """ 
    120         self.subplot.set_xscale(scale) 
    121         self.xscale = scale 
    122  
    123     def contextMenuQuickPlot(self): 
     136        self.ax.set_xscale(scale) 
     137        self._xscale = scale 
     138 
     139    def contextMenu(self): 
    124140        """ 
    125141        Define context menu and associated actions for the MPL widget 
     
    131147        self.actionCopyToClipboard = self.contextMenu.addAction("Copy to Clipboard") 
    132148        self.contextMenu.addSeparator() 
    133         self.actionToggleGrid = self.contextMenu.addAction("Toggle Grid On/Off") 
    134         self.contextMenu.addSeparator() 
    135         self.actionChangeScale = self.contextMenu.addAction("Change Scale") 
    136149 
    137150        # Define the callbacks 
     
    139152        self.actionPrintImage.triggered.connect(self.onImagePrint) 
    140153        self.actionCopyToClipboard.triggered.connect(self.onClipboardCopy) 
    141         self.actionToggleGrid.triggered.connect(self.onGridToggle) 
    142         self.actionChangeScale.triggered.connect(self.onScaleChange) 
     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.") 
    143160 
    144161    def contextMenuEvent(self, event): 
     
    217234        self.ax.grid(self.grid_on) 
    218235        self.canvas.draw_idle() 
    219  
    220     def onScaleChange(self): 
    221         """ 
    222         Show a dialog allowing axes rescaling 
    223         """ 
    224         if self.properties.exec_() == QtGui.QDialog.Accepted: 
    225             xLabel, yLabel = self.properties.getValues() 
    226             #self.xyTransform(xLabel, yLabel) 
    227  
    228     def xyTransform(self, xLabel="", yLabel=""): 
    229         """ 
    230         Transforms x and y in View and set the scale 
    231         """ 
    232         # The logic should be in the right order 
    233         self.ly = None 
    234         self.q_ctrl = None 
    235         # Changing the scale might be incompatible with 
    236         # currently displayed data (for instance, going 
    237         # from ln to log when all plotted values have 
    238         # negative natural logs). 
    239         # Go linear and only change the scale at the end. 
    240         self.set_xscale("linear") 
    241         self.set_yscale("linear") 
    242         _xscale = 'linear' 
    243         _yscale = 'linear' 
    244         # Local data is either 1D or 2D 
    245         #for item in list: 
    246         #if item.id == 'fit': 
    247         #    continue 
    248         item.setLabel(self.xLabel, self.yLabel) 
    249         # control axis labels from the panel itself 
    250         yname, yunits = item.get_yaxis() 
    251         if self.yaxis_label != None: 
    252             yname = self.yaxis_label 
    253             yunits = self.yaxis_unit 
    254         else: 
    255             self.yaxis_label = yname 
    256             self.yaxis_unit = yunits 
    257         xname, xunits = item.get_xaxis() 
    258         if self.xaxis_label != None: 
    259             xname = self.xaxis_label 
    260             xunits = self.xaxis_unit 
    261         else: 
    262             self.xaxis_label = xname 
    263             self.xaxis_unit = xunits 
    264         # Goes through all possible scales 
    265         if self.xLabel == "x": 
    266             item.transformX(transform.toX, transform.errToX) 
    267             self.graph._xaxis_transformed("%s" % xname, "%s" % xunits) 
    268         if self.xLabel == "x^(2)": 
    269             item.transformX(transform.toX2, transform.errToX2) 
    270             xunits = convert_unit(2, xunits) 
    271             self.graph._xaxis_transformed("%s^{2}" % xname, "%s" % xunits) 
    272         if self.xLabel == "x^(4)": 
    273             item.transformX(transform.toX4, transform.errToX4) 
    274             xunits = convert_unit(4, xunits) 
    275             self.graph._xaxis_transformed("%s^{4}" % xname, "%s" % xunits) 
    276         if self.xLabel == "ln(x)": 
    277             item.transformX(transform.toLogX, transform.errToLogX) 
    278             self.graph._xaxis_transformed("\ln{(%s)}" % xname, "%s" % xunits) 
    279         if self.xLabel == "log10(x)": 
    280             item.transformX(transform.toX_pos, transform.errToX_pos) 
    281             _xscale = 'log' 
    282             self.graph._xaxis_transformed("%s" % xname, "%s" % xunits) 
    283         if self.xLabel == "log10(x^(4))": 
    284             item.transformX(transform.toX4, transform.errToX4) 
    285             xunits = convert_unit(4, xunits) 
    286             self.graph._xaxis_transformed("%s^{4}" % xname, "%s" % xunits) 
    287             _xscale = 'log' 
    288         if self.yLabel == "ln(y)": 
    289             item.transformY(transform.toLogX, transform.errToLogX) 
    290             self.graph._yaxis_transformed("\ln{(%s)}" % yname, "%s" % yunits) 
    291         if self.yLabel == "y": 
    292             item.transformY(transform.toX, transform.errToX) 
    293             self.graph._yaxis_transformed("%s" % yname, "%s" % yunits) 
    294         if self.yLabel == "log10(y)": 
    295             item.transformY(transform.toX_pos, transform.errToX_pos) 
    296             _yscale = 'log' 
    297             self.graph._yaxis_transformed("%s" % yname, "%s" % yunits) 
    298         if self.yLabel == "y^(2)": 
    299             item.transformY(transform.toX2, transform.errToX2) 
    300             yunits = convert_unit(2, yunits) 
    301             self.graph._yaxis_transformed("%s^{2}" % yname, "%s" % yunits) 
    302         if self.yLabel == "1/y": 
    303             item.transformY(transform.toOneOverX, transform.errOneOverX) 
    304             yunits = convert_unit(-1, yunits) 
    305             self.graph._yaxis_transformed("1/%s" % yname, "%s" % yunits) 
    306         if self.yLabel == "y*x^(2)": 
    307             item.transformY(transform.toYX2, transform.errToYX2) 
    308             xunits = convert_unit(2, self.xaxis_unit) 
    309             self.graph._yaxis_transformed("%s \ \ %s^{2}" % (yname, xname), 
    310                                             "%s%s" % (yunits, xunits)) 
    311         if self.yLabel == "y*x^(4)": 
    312             item.transformY(transform.toYX4, transform.errToYX4) 
    313             xunits = convert_unit(4, self.xaxis_unit) 
    314             self.graph._yaxis_transformed("%s \ \ %s^{4}" % (yname, xname), 
    315                                             "%s%s" % (yunits, xunits)) 
    316         if self.yLabel == "1/sqrt(y)": 
    317             item.transformY(transform.toOneOverSqrtX, 
    318                             transform.errOneOverSqrtX) 
    319             yunits = convert_unit(-0.5, yunits) 
    320             self.graph._yaxis_transformed("1/\sqrt{%s}" % yname, 
    321                                             "%s" % yunits) 
    322         if self.yLabel == "ln(y*x)": 
    323             item.transformY(transform.toLogXY, transform.errToLogXY) 
    324             self.graph._yaxis_transformed("\ln{(%s \ \ %s)}" % (yname, xname), 
    325                                             "%s%s" % (yunits, self.xaxis_unit)) 
    326         if self.yLabel == "ln(y*x^(2))": 
    327             item.transformY(transform.toLogYX2, transform.errToLogYX2) 
    328             xunits = convert_unit(2, self.xaxis_unit) 
    329             self.graph._yaxis_transformed("\ln (%s \ \ %s^{2})" % (yname, xname), 
    330                                             "%s%s" % (yunits, xunits)) 
    331         if self.yLabel == "ln(y*x^(4))": 
    332             item.transformY(transform.toLogYX4, transform.errToLogYX4) 
    333             xunits = convert_unit(4, self.xaxis_unit) 
    334             self.graph._yaxis_transformed("\ln (%s \ \ %s^{4})" % (yname, xname), 
    335                                             "%s%s" % (yunits, xunits)) 
    336         if self.yLabel == "log10(y*x^(4))": 
    337             item.transformY(transform.toYX4, transform.errToYX4) 
    338             xunits = convert_unit(4, self.xaxis_unit) 
    339             _yscale = 'log' 
    340             self.graph._yaxis_transformed("%s \ \ %s^{4}" % (yname, xname), 
    341                                             "%s%s" % (yunits, xunits)) 
    342             item.transformView() 
    343  
    344         # set new label and units 
    345         yname = self.graph.prop["ylabel"] 
    346         yunits = '' 
    347         xname = self.graph.prop["xlabel"] 
    348         xunits = '' 
    349  
    350         self.resetFitView() 
    351         self.prevXtrans = self.xLabel 
    352         self.prevYtrans = self.yLabel 
    353         self.graph.render(self) 
    354         self.set_xscale(_xscale) 
    355         self.set_yscale(_yscale) 
    356  
    357         self.xaxis(xname, xunits, self.xaxis_font, 
    358                    self.xaxis_color, self.xaxis_tick) 
    359         self.yaxis(yname, yunits, self.yaxis_font, 
    360                    self.yaxis_color, self.yaxis_tick) 
    361         self.subplot.texts = self.textList 
    362  
    363         self.canvas.draw_idle() 
  • src/sas/qtgui/ScaleProperties.py

    ref01be4 r6d05e1d  
    1 # global 
    2 #import sys 
    3 #import os 
    4 #from PyQt4 import QtCore 
    51from PyQt4 import QtGui 
    62 
     
    3632        # Connect combobox index change to a custom method 
    3733        self.cbView.currentIndexChanged.connect(self.viewIndexChanged) 
     34        self.cbX.currentIndexChanged.connect(self.xyIndexChanged) 
     35        self.cbY.currentIndexChanged.connect(self.xyIndexChanged) 
    3836 
    3937    def getValues(self): 
     
    4846        """ 
    4947        if index > 0: 
     48            # Disable signals so xyIndexChanged() doesn't get called 
     49            self.cbX.blockSignals(True) 
     50            self.cbY.blockSignals(True) 
     51 
     52            # Update the sub-controls 
    5053            self.cbX.setCurrentIndex(view_to_xy[view_values[index]][0]) 
    5154            self.cbY.setCurrentIndex(view_to_xy[view_values[index]][1]) 
     55            # Re-enable the signals 
     56 
     57            self.cbX.blockSignals(False) 
     58            self.cbY.blockSignals(False) 
     59 
     60    def xyIndexChanged(self, index): 
     61        """ 
     62        Update View label based on the "X" and "Y" index 
     63        """ 
     64        self.cbView.setCurrentIndex(0) 
  • src/sas/qtgui/UnitTesting/DataExplorerTest.py

    r31c5b58 r6d05e1d  
    506506        self.assertTrue(self.form.manager.add_data.called) 
    507507 
    508     def testNewPlot(self): 
     508    def testNewPlot1D(self): 
    509509        """ 
    510510        Creating new plots from Data1D/2D 
     
    521521        # get Data1D 
    522522        p_file="cyl_400_20.txt" 
     523        output_object = loader.load(p_file) 
     524        new_data = [manager.create_gui_data(output_object, p_file)] 
     525 
     526        # Mask retrieval of the data 
     527        self.form.plotsFromCheckedItems = MagicMock(return_value=new_data) 
     528 
     529        # Mask plotting 
     530        self.form.parent.workspace = MagicMock() 
     531 
     532        # Call the plotting method 
     533        self.form.newPlot() 
     534 
     535        # The plot was registered 
     536        self.assertEqual(len(PlotHelper.currentPlots()), 1) 
     537 
     538        self.assertTrue(self.form.cbgraph.isEnabled()) 
     539        self.assertTrue(self.form.cmdAppend.isEnabled()) 
     540 
     541    def testNewPlot2D(self): 
     542        """ 
     543        Creating new plots from Data1D/2D 
     544        """ 
     545        loader = Loader() 
     546        manager = DataManager() 
     547        PlotHelper.clear() 
     548        self.form.enableGraphCombo(None) 
     549 
     550        # Make sure the controls are disabled 
     551        self.assertFalse(self.form.cbgraph.isEnabled()) 
     552        self.assertFalse(self.form.cmdAppend.isEnabled()) 
     553 
     554        # get Data2D 
     555        p_file="Dec07031.ASC" 
    523556        output_object = loader.load(p_file) 
    524557        new_data = [manager.create_gui_data(output_object, p_file)] 
  • src/sas/qtgui/UnitTesting/PlotterTest.py

    • Property mode changed from 100755 to 100644
    rf721030 r6d05e1d  
     1import sys 
     2import unittest 
     3 
     4from PyQt4 import QtGui 
     5from PyQt4 import QtCore 
     6from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas 
     7from mock import MagicMock 
     8 
     9####### TEMP 
     10import LocalSetup 
     11####### 
     12from sas.sasgui.guiframe.dataFitting import Data1D 
     13from sas.sasgui.guiframe.dataFitting import Data2D 
     14from UnitTesting.TestUtils import QtSignalSpy 
     15 
     16# Tested module 
     17import sas.qtgui.Plotter as Plotter 
     18 
     19app = QtGui.QApplication(sys.argv) 
     20 
     21class PlotterTest(unittest.TestCase): 
     22    '''Test the Plotter 1D class''' 
     23    def setUp(self): 
     24        '''create''' 
     25        self.plotter = Plotter.Plotter(None, quickplot=True) 
     26        self.data = Data1D(x=[1.0, 2.0, 3.0], 
     27                           y=[10.0, 11.0, 12.0], 
     28                           dx=[0.1, 0.2, 0.3], 
     29                           dy=[0.1, 0.2, 0.3]) 
     30        self.data.title="Test data" 
     31        self.data.id = 1 
     32 
     33    def tearDown(self): 
     34        '''destroy''' 
     35        self.plotter = None 
     36 
     37    def testDataProperty(self): 
     38        """ Adding data """ 
     39        self.plotter.data = self.data 
     40 
     41        self.assertEqual(self.plotter.data, self.data) 
     42        self.assertEqual(self.plotter._title, self.data.title) 
     43        self.assertEqual(self.plotter.xLabel, "$()$") 
     44        self.assertEqual(self.plotter.yLabel, "$()$") 
     45 
     46    def testPlot(self): 
     47        """ Look at the plotting """ 
     48        self.plotter.data = self.data 
     49        self.plotter.show() 
     50        FigureCanvas.draw = MagicMock() 
     51 
     52        self.plotter.plot() 
     53 
     54        self.assertTrue(FigureCanvas.draw.called) 
     55 
     56    def testContextMenuQuickPlot(self): 
     57        """ Test the right click menu """ 
     58        actions = self.plotter.contextMenu.actions() 
     59        self.assertEqual(len(actions), 7) 
     60 
     61        # Trigger Save Image and make sure the method is called 
     62        self.assertEqual(actions[0].text(), "Save Image") 
     63        self.plotter.toolbar.save_figure = MagicMock() 
     64        actions[0].trigger() 
     65        self.assertTrue(self.plotter.toolbar.save_figure.called) 
     66 
     67        # Trigger Print Image and make sure the method is called 
     68        self.assertEqual(actions[1].text(), "Print Image") 
     69        QtGui.QPrintDialog.exec_ = MagicMock(return_value=QtGui.QDialog.Rejected) 
     70        actions[1].trigger() 
     71        self.assertTrue(QtGui.QPrintDialog.exec_.called) 
     72 
     73        # Trigger Copy to Clipboard and make sure the method is called 
     74        self.assertEqual(actions[2].text(), "Copy to Clipboard") 
     75 
     76        # Spy on cliboard's dataChanged() signal 
     77        self.clipboard_called = False 
     78        def done(): 
     79            self.clipboard_called = True 
     80        QtCore.QObject.connect(app.clipboard(), QtCore.SIGNAL("dataChanged()"), done) 
     81        actions[2].trigger() 
     82        QtGui.qApp.processEvents() 
     83        # Make sure clipboard got updated. 
     84        self.assertTrue(self.clipboard_called) 
     85 
     86        # Trigger Toggle Grid and make sure the method is called 
     87        self.assertEqual(actions[4].text(), "Toggle Grid On/Off") 
     88        self.plotter.ax.grid = MagicMock() 
     89        actions[4].trigger() 
     90        self.assertTrue(self.plotter.ax.grid.called) 
     91 
     92        # Trigger Change Scale and make sure the method is called 
     93        self.assertEqual(actions[6].text(), "Change Scale") 
     94        self.plotter.properties.exec_ = MagicMock(return_value=QtGui.QDialog.Rejected) 
     95        actions[6].trigger() 
     96        self.assertTrue(self.plotter.properties.exec_.called) 
     97 
     98    def testXYTransform(self): 
     99        """ Assure the unit/legend transformation is correct""" 
     100        self.plotter.data = self.data 
     101 
     102        self.plotter.xyTransform(xLabel="ln(x)", yLabel="ln(y)") 
     103        self.assertEqual(self.plotter.ax.get_xlabel(), "$\\ln{()}()$") 
     104        self.assertEqual(self.plotter.ax.get_ylabel(), "$\\ln{()}()$") 
     105 
     106        self.plotter.xyTransform(xLabel="ln(x)", yLabel="ln(y)") 
     107        self.assertEqual(self.plotter.ax.get_xlabel(), "$\\ln{()}()$") 
     108        self.assertEqual(self.plotter.ax.get_ylabel(), "$\\ln{()}()$") 
     109 
     110        self.plotter.xyTransform(xLabel="x^(2)", yLabel="1/sqrt(y)") 
     111        self.assertEqual(self.plotter.ax.get_xlabel(), "$^{2}(()^{2})$") 
     112        self.assertEqual(self.plotter.ax.get_ylabel(), "$1/\\sqrt{}(()^{-0.5})$") 
     113 
     114if __name__ == "__main__": 
     115    unittest.main() 
  • src/sas/sasgui/plottools/config.py

    rd7bb526 r6d05e1d  
    3535# Sort out matplotlib version 
    3636import matplotlib 
    37 try: 
    38     import pkg_resources 
    39     pkg_resources.require("matplotlib>=" + plot_version) 
    40 except: 
    41     from distutils.version import LooseVersion as Version 
    42     if Version(matplotlib.__version__) < Version(plot_version): 
    43         msg = "Matplotlib version must be %s or newer" % (plot_version, ) 
    44         raise ImportError(msg) 
     37#try: 
     38#    import pkg_resources 
     39#    pkg_resources.require("matplotlib>=" + plot_version) 
     40#except: 
     41#    from distutils.version import LooseVersion as Version 
     42#    if Version(matplotlib.__version__) < Version(plot_version): 
     43#        msg = "Matplotlib version must be %s or newer" % (plot_version, ) 
     44#        raise ImportError(msg) 
    4545 
    4646# Sort out matplotlib backend 
     
    5151elif matplotlib.get_backend() != plot_backend: 
    5252    # if a backend has already been selected, make sure it is the correct one. 
    53     raise ImportError("Matplotlib not using backend " + plot_backend) 
     53    #raise ImportError("Matplotlib not using backend " + plot_backend) 
     54    pass 
    5455 
    5556# set global plot style 
Note: See TracChangeset for help on using the changeset viewer.