Changeset 3bdbfcc in sasview for src/sas/qtgui/Plotter2D.py


Ignore:
Timestamp:
Feb 2, 2017 8:29:07 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:
965fbd8
Parents:
5d89f43
git-author:
Piotr Rozyczko <rozyczko@…> (01/23/17 09:21:03)
git-committer:
Piotr Rozyczko <rozyczko@…> (02/02/17 08:29:07)
Message:

Reimplementation of the slicer functionality

File:
1 edited

Legend:

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

    r5d89f43 r3bdbfcc  
    1111 
    1212import sas.qtgui.PlotUtilities as PlotUtilities 
     13import sas.qtgui.GuiUtils as GuiUtils 
    1314from sas.qtgui.PlotterBase import PlotterBase 
    1415from sas.qtgui.ColorMap import ColorMap 
     16from sas.sasgui.guiframe.dataFitting import Data1D 
    1517from sas.sasgui.guiframe.dataFitting import Data2D 
     18from sas.sascalc.dataloader.manipulations import CircularAverage 
     19from sas.sasgui.guiframe.local_perspectives.plotting.binder import BindArtist 
     20from sas.qtgui.BoxSum import BoxSum 
     21from sas.qtgui.GuiUtils import formatNumber 
     22from sas.qtgui.SlicerParameters import SlicerParameters 
     23from sas.sasgui.guiframe.local_perspectives.plotting.boxSlicer import BoxInteractorX 
     24from sas.sasgui.guiframe.local_perspectives.plotting.AnnulusSlicer import AnnulusInteractor 
     25from sas.sasgui.guiframe.local_perspectives.plotting.SectorSlicer import SectorInteractor 
     26from sas.sasgui.guiframe.local_perspectives.plotting.boxSum import BoxSumCalculator 
     27from sas.sasgui.guiframe.local_perspectives.plotting.boxSlicer import BoxInteractorY 
    1628 
    1729# Minimum value of Z for which we will present data. 
    18 MIN_Z=-32 
     30MIN_Z = -32 
    1931 
    2032class Plotter2DWidget(PlotterBase): 
     
    2941        # Default scale 
    3042        self.scale = 'log_{10}' 
     43        # to set the order of lines drawn first. 
     44        self.slicer_z = 5 
     45        # Reference to the current slicer 
     46        self.slicer = None 
     47        # Create Artist and bind it 
     48        self.connect = BindArtist(self.figure) 
    3149        self.vmin = None 
    3250        self.vmax = None 
     
    5371        self.title(title=data.title) 
    5472 
    55     def plot(self, data=None, marker=None, linestyle=None): 
     73    @property 
     74    def item(self): 
     75        ''' getter for this plot's QStandardItem ''' 
     76        return self._item 
     77 
     78    @item.setter 
     79    def item(self, item=None): 
     80        ''' setter for this plot's QStandardItem ''' 
     81        self._item = item 
     82 
     83    def plot(self, data=None): 
    5684        """ 
    5785        Plot 2D self._data 
     
    6189            self.data = data 
    6290 
    63         assert(self._data) 
     91        assert self._data 
    6492 
    6593        # Toggle the scale 
     
    128156        self.actionBoxAveragingY = self.contextMenu.addAction("&Box Averaging in Qy") 
    129157        self.actionBoxAveragingY.triggered.connect(self.onBoxAveragingY) 
    130         self.contextMenu.addSeparator() 
    131         self.actionEditGraphLabel = self.contextMenu.addAction("&Edit Graph Label") 
    132         self.actionEditGraphLabel.triggered.connect(self.onEditgraphLabel) 
     158        # Additional items for slicer interaction 
     159        if self.slicer: 
     160            self.actionClearSlicer = self.contextMenu.addAction("&Clear Slicer") 
     161            self.actionClearSlicer.triggered.connect(self.onClearSlicer) 
     162            self.actionEditSlicer = self.contextMenu.addAction("&Edit Slicer Parameters") 
     163            self.actionEditSlicer.triggered.connect(self.onEditSlicer) 
    133164        self.contextMenu.addSeparator() 
    134165        self.actionColorMap = self.contextMenu.addAction("&2D Color Map") 
     
    166197        self.plot() 
    167198 
     199    def onClearSlicer(self): 
     200        """ 
     201        Remove all sclicers from the chart 
     202        """ 
     203        if self.slicer: 
     204            self.slicer.clear() 
     205            self.canvas.draw() 
     206            self.slicer = None 
     207 
     208    def onEditSlicer(self): 
     209        """ 
     210        Present a small dialog for manipulating the current slicer 
     211        """ 
     212        assert self.slicer 
     213 
     214        self.param_model = self.slicer.model() 
     215         # Pass the model to the Slicer Parameters widget 
     216        self.slicer_widget = SlicerParameters(self, model=self.param_model) 
     217        self.slicer_widget.show() 
     218 
    168219    def onCircularAverage(self): 
    169220        """ 
    170         """ 
    171         pass 
     221        Perform circular averaging on Data2D 
     222        """ 
     223        # Find the best number of bins 
     224        npt = numpy.sqrt(len(self.data.data[numpy.isfinite(self.data.data)])) 
     225        npt = numpy.floor(npt) 
     226        # compute the maximum radius of data2D 
     227        self.qmax = max(numpy.fabs(self.data.xmax), 
     228                        numpy.fabs(self.data.xmin)) 
     229        self.ymax = max(numpy.fabs(self.data.ymax), 
     230                        numpy.fabs(self.data.ymin)) 
     231        self.radius = numpy.sqrt(numpy.power(self.qmax, 2) + numpy.power(self.ymax, 2)) 
     232        #Compute beam width 
     233        bin_width = (self.qmax + self.qmax) / npt 
     234        # Create data1D circular average of data2D 
     235        circle = CircularAverage(r_min=0, r_max=self.radius, bin_width=bin_width) 
     236        circ = circle(self.data) 
     237        dxl = circ.dxl if hasattr(circ, "dxl") else None 
     238        dxw = circ.dxw if hasattr(circ, "dxw") else None 
     239 
     240        new_plot = Data1D(x=circ.x, y=circ.y, dy=circ.dy, dx=circ.dx) 
     241        new_plot.dxl = dxl 
     242        new_plot.dxw = dxw 
     243        new_plot.name = new_plot.title = "Circ avg " + self.data.name 
     244        new_plot.source = self.data.source 
     245        new_plot.interactive = True 
     246        new_plot.detector = self.data.detector 
     247 
     248        # Define axes if not done yet. 
     249        new_plot.xaxis("\\rm{Q}", "A^{-1}") 
     250        if hasattr(self.data, "scale") and \ 
     251                    self.data.scale == 'linear': 
     252            new_plot.ytransform = 'y' 
     253            new_plot.yaxis("\\rm{Residuals} ", "normalized") 
     254        else: 
     255            new_plot.yaxis("\\rm{Intensity} ", "cm^{-1}") 
     256 
     257        new_plot.group_id = "2daverage" + self.data.name 
     258        new_plot.id = "Circ avg " + self.data.name 
     259        new_plot.is_data = True 
     260        variant_plot = QtCore.QVariant(new_plot) 
     261        GuiUtils.updateModelItemWithPlot(self._item, variant_plot, new_plot.id) 
     262        # TODO: force immediate display (?) 
     263 
     264    def setSlicer(self, slicer): 
     265        """ 
     266        Clear the previous slicer and create a new one. 
     267        slicer: slicer class to create 
     268        """ 
     269        # Clear current slicer 
     270        if self.slicer is not None: 
     271            self.slicer.clear() 
     272        # Create a new slicer 
     273        self.slicer_z += 1 
     274        self.slicer = slicer(self, self.ax, item=self._item, zorder=self.slicer_z) 
     275        self.ax.set_ylim(self.data.ymin, self.data.ymax) 
     276        self.ax.set_xlim(self.data.xmin, self.data.xmax) 
     277        # Draw slicer 
     278        self.figure.canvas.draw() 
     279        self.slicer.update() 
    172280 
    173281    def onSectorView(self): 
    174282        """ 
    175         """ 
    176         pass 
     283        Perform sector averaging on Q and draw sector slicer 
     284        """ 
     285        self.setSlicer(slicer=SectorInteractor) 
    177286 
    178287    def onAnnulusView(self): 
    179288        """ 
    180         """ 
    181         pass 
     289        Perform sector averaging on Phi and draw annulus slicer 
     290        """ 
     291        self.setSlicer(slicer=AnnulusInteractor) 
    182292 
    183293    def onBoxSum(self): 
    184294        """ 
    185         """ 
    186         pass 
     295        Perform 2D Data averaging Qx and Qy. 
     296        Display box slicer details. 
     297        """ 
     298        self.onClearSlicer() 
     299        self.slicer_z += 1 
     300        self.slicer = BoxSumCalculator(self, self.ax, zorder=self.slicer_z) 
     301 
     302        self.ax.set_ylim(self.data.ymin, self.data.ymax) 
     303        self.ax.set_xlim(self.data.xmin, self.data.xmax) 
     304        self.figure.canvas.draw() 
     305        self.slicer.update() 
     306 
     307        # Get the BoxSumCalculator model. 
     308        self.box_sum_model = self.slicer.model() 
     309        # Pass the BoxSumCalculator model to the BoxSum widget 
     310        self.boxwidget = BoxSum(self, model=self.box_sum_model) 
     311        # Add the plot to the workspace 
     312        self.manager.parent.workspace().addWindow(self.boxwidget) 
     313        self.boxwidget.show() 
    187314 
    188315    def onBoxAveragingX(self): 
    189316        """ 
    190         """ 
    191         pass 
     317        Perform 2D data averaging on Qx 
     318        Create a new slicer. 
     319        """ 
     320        self.setSlicer(slicer=BoxInteractorX) 
    192321 
    193322    def onBoxAveragingY(self): 
    194323        """ 
    195         """ 
    196         pass 
    197  
    198     def onEditgraphLabel(self): 
    199         """ 
    200         """ 
    201         pass 
     324        Perform 2D data averaging on Qy 
     325        Create a new slicer . 
     326        """ 
     327        self.setSlicer(slicer=BoxInteractorY) 
    202328 
    203329    def onColorMap(self): 
     
    225351 
    226352    def showPlot(self, data, qx_data, qy_data, xmin, xmax, ymin, ymax, 
    227                  zmin, zmax, color=0, symbol=0, markersize=0, 
    228                  label='data2D', cmap=DEFAULT_CMAP): 
     353                 zmin, zmax, label='data2D', cmap=DEFAULT_CMAP): 
    229354        """ 
    230355        Render and show the current data 
     
    310435            self.figure.subplots_adjust(left=0.1, right=.8, bottom=.1) 
    311436 
    312             X = self._data.x_bins[0:-1] 
    313             Y = self._data.y_bins[0:-1] 
    314             X, Y = numpy.meshgrid(X, Y) 
     437            data_x, data_y = numpy.meshgrid(self._data.x_bins[0:-1], 
     438                                            self._data.y_bins[0:-1]) 
    315439 
    316440            ax = Axes3D(self.figure) 
     
    319443            # TODO: Define "large" for a dataset 
    320444            SET_TOO_LARGE = 500 
    321             if len(X) > SET_TOO_LARGE: 
     445            if len(data_x) > SET_TOO_LARGE: 
    322446                ax.disable_mouse_rotation() 
    323447 
    324448            self.figure.canvas.resizing = False 
    325             im = ax.plot_surface(X, Y, output, rstride=1, cstride=1, cmap=cmap, 
     449            im = ax.plot_surface(data_x, data_y, output, rstride=1, 
     450                                 cstride=1, cmap=cmap, 
    326451                                 linewidth=0, antialiased=False) 
    327452            self.ax.set_axis_off() 
     
    332457            self.figure.canvas.draw() 
    333458 
     459    def update(self): 
     460        self.figure.canvas.draw() 
     461 
     462    def draw(self): 
     463        self.figure.canvas.draw() 
     464 
     465 
    334466class Plotter2D(QtGui.QDialog, Plotter2DWidget): 
     467    """ 
     468    Plotter widget implementation 
     469    """ 
    335470    def __init__(self, parent=None, quickplot=False, dimension=2): 
    336  
    337471        QtGui.QDialog.__init__(self) 
    338472        Plotter2DWidget.__init__(self, manager=parent, quickplot=quickplot, dimension=dimension) 
Note: See TracChangeset for help on using the changeset viewer.