Changeset 87cc73a in sasview


Ignore:
Timestamp:
Jan 11, 2017 7:31:58 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:
db5cd8d
Parents:
b46f285
Message:

Added Modify Plot Properties functionality. SASVIEW-169

Location:
src/sas/qtgui
Files:
4 added
9 edited

Legend:

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

    raadf0af1 r87cc73a  
    769769        new_plot = globals()[method_name](self, quickplot=True) 
    770770        new_plot.data = data 
    771         new_plot.plot(marker='o', linestyle='') 
     771        new_plot.plot(marker='o') 
    772772 
    773773        # Update the global plot counter 
  • src/sas/qtgui/GUITests.py

    rb46f285 r87cc73a  
    2121from UnitTesting import SetGraphRangeTest 
    2222from UnitTesting import LinearFitTest 
     23from UnitTesting import PlotPropertiesTest 
     24from UnitTesting import PlotUtilitiesTest 
    2325 
    2426def suite(): 
     
    4446        unittest.makeSuite(SetGraphRangeTest.SetGraphRangeTest, 'test'), 
    4547        unittest.makeSuite(LinearFitTest.LinearFitTest, 'test'), 
     48        unittest.makeSuite(PlotPropertiesTest.PlotPropertiesTest, 'test'), 
     49        unittest.makeSuite(PlotUtilitiesTest.PlotUtilitiesTest, 'test'), 
    4650    ) 
    4751    return unittest.TestSuite(suites) 
  • src/sas/qtgui/LinearFit.py

    rb46f285 r87cc73a  
    259259            return numpy.sqrt(numpy.sqrt(numpy.power(10, x))) 
    260260        return x 
     261 
     262 
  • src/sas/qtgui/PlotUtilities.py

    r9290b1a r87cc73a  
    11import sys 
    22import numpy 
    3  
     3from collections import OrderedDict 
     4 
     5SHAPES = OrderedDict([ 
     6        ('Circle' , 'o'), 
     7        ('Point' , '.'), 
     8        ('Pixel' , ','), 
     9        ('Triangle Down' , 'v'), 
     10        ('Triangle Up' , '^'), 
     11        ('Triangle Left' , '<'), 
     12        ('Triangle Right' , '>'), 
     13        ('Octagon' , '8'), 
     14        ('Square' , 's'), 
     15        ('Pentagon' , 'p'), 
     16        ('Star' , '*'), 
     17        ('Hexagon1' , 'h'), 
     18        ('Hexagon2' , 'H'), 
     19        ('Cross +' , 'p'), 
     20        ('Cross X ' , 'x'), 
     21        ('Diamond' , 'D'), 
     22        ('Thin Diamond' , 'd'), 
     23        ('Line' , '-'), 
     24        ('Dash' , '--'), 
     25        ('Vline' , 'vline'), 
     26        ('Step' , 'step'), 
     27]) 
     28 
     29COLORS = OrderedDict([ 
     30        ('Blue', 'b'), 
     31        ('Green', 'g'), 
     32        ('Red', 'r'), 
     33        ('Cyan', 'c'), 
     34        ('Magenta', 'm'), 
     35        ('Yellow', 'y'), 
     36        ('Black', 'k'), 
     37        ('Custom', 'x'), 
     38]) 
    439 
    540def build_matrix(data, qx_data, qy_data): 
     
    5792        if loop >= max_loop:  # this protects never-ending loop 
    5893            break 
    59         image = fillup_pixels(image=image, weights=weights) 
     94        image = fillupPixels(image=image, weights=weights) 
    6095        loop += 1 
    6196 
     
    108143    return x_bins, y_bins 
    109144 
    110 def fillup_pixels(image=None, weights=None): 
     145def fillupPixels(image=None, weights=None): 
    111146    """ 
    112147    Fill z values of the empty cells of 2d image matrix 
     
    221256    return (lo, hi) 
    222257 
     258def getValidColor(color): 
     259    ''' 
     260    Returns a valid matplotlib color 
     261    ''' 
     262 
     263    if color is not None: 
     264        # Check if it's an int 
     265        if isinstance(color, int): 
     266            # Check if it's within the range 
     267            if 0 <= color <=6: 
     268                color = COLORS.values()[color] 
     269        # Check if it's an RGB string 
     270        elif isinstance(color, str): 
     271            # Assure the correctnes of the string 
     272            assert(color[0]=="#" and len(color) == 7) 
     273            import string 
     274            assert(all(c in string.hexdigits for c in color[1:])) 
     275        else: 
     276            raise AttributeError 
     277 
     278    return color 
  • src/sas/qtgui/Plotter.py

    rb46f285 r87cc73a  
    1313from sas.qtgui.SetGraphRange import SetGraphRange 
    1414from sas.qtgui.LinearFit import LinearFit 
     15from sas.qtgui.PlotProperties import PlotProperties 
     16import sas.qtgui.PlotUtilities as PlotUtilities 
    1517 
    1618class PlotterWidget(PlotterBase): 
     
    5961        self.title(title=value.name) 
    6062 
    61     def plot(self, data=None, marker=None, linestyle=None, hide_error=False): 
     63    def plot(self, data=None, color=None, marker=None, hide_error=False): 
    6264        """ 
    6365        Add a new plot of self._data to the chart. 
     
    6870        assert(self._data) 
    6971 
    70         is_fit = (self._data.id=="fit") 
    71  
    72         # Shortcut for the current axis 
     72        is_fit = (self.data.id=="fit") 
     73 
     74        # Shortcuts 
    7375        ax = self.ax 
    74  
    75         if marker == None: 
    76             marker = 'o' 
    77  
    78         if linestyle == None: 
    79             linestyle = '' 
    80  
    81         if not self._title: 
    82             self.title(title=self.data.name) 
    83  
    84         # plot data with/without errorbars 
    85         if hide_error: 
    86             line = ax.plot(self._data.view.x, self._data.view.y, 
    87                     marker=marker, 
    88                     linestyle=linestyle, 
    89                     label=self._title, 
    90                     picker=True) 
     76        x = self._data.view.x 
     77        y = self._data.view.y 
     78 
     79        # Marker symbol. Passed marker is one of matplotlib.markers characters 
     80        # Alternatively, picked up from Data1D as an int index of PlotUtilities.SHAPES dict 
     81        if marker is None: 
     82            marker = self.data.symbol 
     83            marker = PlotUtilities.SHAPES.values()[marker] 
     84 
     85        # Plot name 
     86        self.title(title=self.data.title) 
     87 
     88        # Error marker toggle 
     89        if hide_error is None: 
     90            hide_error = self.data.hide_error 
     91 
     92        # Plot color 
     93        if color is None: 
     94            color = self.data.custom_color 
     95 
     96        color = PlotUtilities.getValidColor(color) 
     97 
     98        markersize = self._data.markersize 
     99 
     100        # Draw non-standard markers 
     101        l_width = markersize * 0.4 
     102        if marker == '-' or marker == '--': 
     103            line = self.ax.plot(x, y, color=color, lw=l_width, marker='', 
     104                             linestyle=marker, label=self._title, zorder=10)[0] 
     105 
     106        elif marker == 'vline': 
     107            y_min = min(y)*9.0/10.0 if min(y) < 0 else 0.0 
     108            line = self.ax.vlines(x=x, ymin=y_min, ymax=y, color=color, 
     109                            linestyle='-', label=self._title, lw=l_width, zorder=1) 
     110 
     111        elif marker == 'step': 
     112            line = self.ax.step(x, y, color=color, marker='', linestyle='-', 
     113                                label=self._title, lw=l_width, zorder=1)[0] 
     114 
    91115        else: 
    92             line = ax.errorbar(self._data.view.x, self._data.view.y, 
    93                         yerr=self._data.view.dy, xerr=None, 
    94                         capsize=2, linestyle='', 
    95                         barsabove=False, 
    96                         marker=marker, 
    97                         lolims=False, uplims=False, 
    98                         xlolims=False, xuplims=False, 
    99                         label=self._title, 
    100                         picker=True) 
     116            # plot data with/without errorbars 
     117            if hide_error: 
     118                line = ax.plot(x, y, marker=marker, color=color, markersize=markersize, 
     119                        linestyle='', label=self._title, picker=True) 
     120            else: 
     121                line = ax.errorbar(x, y, 
     122                            yerr=self._data.view.dy, xerr=None, 
     123                            capsize=2, linestyle='', 
     124                            barsabove=False, 
     125                            color=color, 
     126                            marker=marker, 
     127                            markersize=markersize, 
     128                            lolims=False, uplims=False, 
     129                            xlolims=False, xuplims=False, 
     130                            label=self._title, 
     131                            picker=True) 
    101132 
    102133        # Update the list of data sets (plots) in chart 
     
    112143        if self.x_label and not is_fit: 
    113144            ax.set_xlabel(self.x_label) 
    114  
    115         # Title only for regular charts 
    116         if not self.quickplot and not is_fit: 
    117             ax.set_title(label=self._title) 
    118145 
    119146        # Include scaling (log vs. linear) 
     
    170197        for id in self.plot_dict.keys(): 
    171198            plot = self.plot_dict[id] 
    172             name = plot.name 
     199            #name = plot.name 
     200            name = plot.title 
    173201            plot_menu = self.contextMenu.addMenu('&%s' % name) 
    174202 
     
    210238 
    211239            self.actionModifyPlot = plot_menu.addAction('&Modify Plot Property') 
    212             self.actionModifyPlot.triggered.connect(self.onModifyPlot) 
     240            self.actionModifyPlot.triggered.connect( 
     241                                functools.partial(self.onModifyPlot, id)) 
    213242 
    214243    def createContextMenuQuick(self): 
     
    361390            return 
    362391 
     392    def replacePlot(self, id, new_plot): 
     393        """ 
     394        Remove plot 'id' and add 'new_plot' to the chart. 
     395        This effectlvely refreshes the chart with changes to one of its plots 
     396        """ 
     397        self.removePlot(id) 
     398        self.plot(data=new_plot) 
     399 
    363400    def onRemovePlot(self, id): 
    364401        """ 
     
    407444        self.manager.add_data(data_list=[plot]) 
    408445 
    409     def onModifyPlot(self): 
     446    def onModifyPlot(self, id): 
    410447        """ 
    411448        Allows for MPL modifications to the selected plot 
    412449        """ 
    413         pass 
     450        selected_plot = self.plot_dict[id] 
     451        current = selected_plot.hide_error 
     452 
     453        # Old style color - single integer for enum color 
     454        # New style color - #hhhhhh 
     455        color = selected_plot.custom_color 
     456        # marker symbol and size 
     457        marker = selected_plot.symbol 
     458        marker_size = selected_plot.markersize 
     459        # plot name 
     460        legend = selected_plot.title 
     461 
     462        plotPropertiesWidget = PlotProperties(self, 
     463                                color=color, 
     464                                marker=marker, 
     465                                marker_size=marker_size, 
     466                                legend=legend) 
     467        if plotPropertiesWidget.exec_() == QtGui.QDialog.Accepted: 
     468            marker = plotPropertiesWidget.marker() 
     469            marker_size = plotPropertiesWidget.markersize() 
     470            color = plotPropertiesWidget.color() 
     471            legend = plotPropertiesWidget.legend() 
     472 
     473            # Update Data1d 
     474            selected_plot.markersize = marker_size 
     475            selected_plot.custom_color = color 
     476            selected_plot.symbol = marker 
     477            selected_plot.title = legend 
     478 
     479            # Redraw the plot 
     480            self.replacePlot(id, selected_plot) 
    414481 
    415482    def onToggleHideError(self, id): 
     
    461528            # Directly overwrite the data to avoid label reassignment 
    462529            self._data = current_plot 
    463             self.plot(marker='o', linestyle='') 
     530            self.plot() 
    464531 
    465532        pass # debug hook 
     
    491558 
    492559        # Plot the line 
    493         self.plot(data=self.fit_result, marker='', linestyle='solid', hide_error=True) 
     560        self.plot(data=self.fit_result, marker='-', hide_error=True) 
    494561 
    495562 
  • src/sas/qtgui/UnitTesting/PlotterTest.py

    rb46f285 r87cc73a  
    1313from sas.sasgui.guiframe.dataFitting import Data1D 
    1414from sas.sasgui.guiframe.dataFitting import Data2D 
    15 from UnitTesting.TestUtils import QtSignalSpy 
     15from UnitTesting.TestUtils import WarningNotImplemented 
    1616 
    1717# Tested module 
     
    1919 
    2020app = QtGui.QApplication(sys.argv) 
     21 
    2122 
    2223class PlotterTest(unittest.TestCase): 
     
    223224    def testOnLinearFit(self): 
    224225        """ Checks the response to LinearFit call """ 
    225         pass 
     226        WarningNotImplemented(sys._getframe().f_code.co_name) 
    226227 
    227228    def testOnRemovePlot(self): 
    228229        """ Assure plots get removed when requested """ 
    229         pass 
     230        WarningNotImplemented(sys._getframe().f_code.co_name) 
    230231 
    231232    def testRemovePlot(self): 
    232233        """ Test plot removal """ 
    233         pass 
     234        WarningNotImplemented(sys._getframe().f_code.co_name) 
    234235 
    235236    def testOnToggleHideError(self): 
    236237        """ Test the error bar toggle on plots """ 
    237         pass 
     238        WarningNotImplemented(sys._getframe().f_code.co_name) 
    238239 
    239240    def testOnFitDisplay(self): 
    240241        """ Test the fit line display on the chart """ 
    241         pass 
     242        WarningNotImplemented(sys._getframe().f_code.co_name) 
     243 
     244    def testReplacePlot(self): 
     245        """ Test the plot refresh functionality """ 
     246        WarningNotImplemented(sys._getframe().f_code.co_name) 
     247 
     248    def testReplacePlot(self): 
     249        """ Test the plot refresh functionality """ 
     250        WarningNotImplemented(sys._getframe().f_code.co_name) 
     251 
     252    def testOnModifyPlot(self): 
     253        """ Test the functionality for changing plot properties """ 
     254        WarningNotImplemented(sys._getframe().f_code.co_name) 
    242255 
    243256if __name__ == "__main__": 
  • src/sas/qtgui/UnitTesting/TestUtils.py

    • Property mode changed from 100755 to 100644
    r5032ea68 r87cc73a  
    22from PyQt4.QtGui import * 
    33from PyQt4.QtTest import * 
     4 
     5def WarningNotImplemented(method_name): 
     6    """ Prints warning about a non-implemented test """ 
     7    print("\nWARNING: %s needs implementing!"%method_name) 
    48 
    59class QtSignalSpy(QObject): 
  • src/sas/qtgui/run_tests.bat

    • Property mode changed from 100755 to 100644
    rb46f285 r87cc73a  
    2020python -m UnitTesting.SetGraphRangeTest 
    2121python -m UnitTesting.LinearFitTest 
     22python -m UnitTesting.PlotPropertiesTest 
     23python -m UnitTesting.PlotUtilitiesTest 
  • src/sas/qtgui/run_tests.sh

    • Property mode changed from 100755 to 100644
    rb46f285 r87cc73a  
    1919python -m UnitTesting.SetGraphRangeTest 
    2020python -m UnitTesting.LinearFitTest 
     21python -m UnitTesting.PlotPropertiesTest 
     22python -m UnitTesting.PlotUtilitiesTest 
Note: See TracChangeset for help on using the changeset viewer.