Ignore:
Timestamp:
Feb 2, 2017 8:29:07 AM (6 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/sasgui/guiframe/local_perspectives/plotting/AnnulusSlicer.py

    rd85c194 r3bdbfcc  
    1 # TODO: the line slicer should listen to all 2DREFRESH events, get the data and slice it 
    2 #      before pushing a new 1D data update. 
    3  
    4 # 
    5 # TODO: NEED MAJOR REFACTOR 
    6 # 
    7  
    8 import math 
    9 import wx 
    10 # from copy import deepcopy 
    11 # Debug printout 
    12 from sas.sasgui.guiframe.events import NewPlotEvent 
    13 from sas.sasgui.guiframe.events import StatusEvent 
    14 from sas.sasgui.guiframe.events import SlicerParameterEvent 
    15 from sas.sasgui.guiframe.events import EVT_SLICER_PARS 
     1import numpy 
     2from PyQt4 import QtGui 
     3from PyQt4 import QtCore 
     4 
    165from BaseInteractor import _BaseInteractor 
    176from sas.sasgui.guiframe.dataFitting import Data1D 
    18  
    19 class AnnulusInteractor(_BaseInteractor): 
     7import sas.qtgui.GuiUtils as GuiUtils 
     8from sas.qtgui.GuiUtils import formatNumber 
     9from sas.qtgui.SlicerModel import SlicerModel 
     10 
     11class AnnulusInteractor(_BaseInteractor, SlicerModel): 
    2012    """ 
    2113    Select an annulus through a 2D plot. 
     
    2416    this class is defined by 2 Ringinterators. 
    2517    """ 
    26     def __init__(self, base, axes, color='black', zorder=3): 
     18    def __init__(self, base, axes, item=None, color='black', zorder=3): 
    2719 
    2820        _BaseInteractor.__init__(self, base, axes, color=color) 
     21        SlicerModel.__init__(self) 
     22 
    2923        self.markers = [] 
    3024        self.axes = axes 
    3125        self.base = base 
    32         self.qmax = min(math.fabs(self.base.data2D.xmax), 
    33                         math.fabs(self.base.data2D.xmin))  # must be positive 
     26        self._item = item 
     27        self.qmax = min(numpy.fabs(self.base.data.xmax), 
     28                        numpy.fabs(self.base.data.xmin))  # must be positive 
    3429        self.connect = self.base.connect 
    3530 
    36         # # Number of points on the plot 
     31        # Number of points on the plot 
    3732        self.nbins = 36 
    3833        # Cursor position of Rings (Left(-1) or Right(1)) 
    39         self.xmaxd = self.base.data2D.xmax 
    40         self.xmind = self.base.data2D.xmin 
     34        self.xmaxd = self.base.data.xmax 
     35        self.xmind = self.base.data.xmin 
    4136 
    4237        if (self.xmaxd + self.xmind) > 0: 
     
    4540            self.sign = -1 
    4641        # Inner circle 
    47         self.inner_circle = RingInteractor(self, self.base.subplot, 
     42        self.inner_circle = RingInteractor(self, self.axes, 
    4843                                           zorder=zorder, 
    4944                                           r=self.qmax / 2.0, sign=self.sign) 
    5045        self.inner_circle.qmax = self.qmax 
    51         self.outer_circle = RingInteractor(self, self.base.subplot, 
     46        self.outer_circle = RingInteractor(self, self.axes, 
    5247                                           zorder=zorder + 1, r=self.qmax / 1.8, 
    5348                                           sign=self.sign) 
     
    5651        self._post_data() 
    5752 
    58         # Bind to slice parameter events 
    59         self.base.Bind(EVT_SLICER_PARS, self._onEVT_SLICER_PARS) 
    60  
    61     def _onEVT_SLICER_PARS(self, event): 
    62         """ 
    63         receive an event containing parameters values to reset the slicer 
    64  
    65         :param event: event of type SlicerParameterEvent with params as 
    66             attribute 
    67  
    68         """ 
    69         wx.PostEvent(self.base, 
    70                      StatusEvent(status="AnnulusSlicer._onEVT_SLICER_PARS")) 
    71         event.Skip() 
    72         if event.type == self.__class__.__name__: 
    73             self.set_params(event.params) 
    74             self.base.update() 
     53        self.setModelFromParams() 
    7554 
    7655    def set_layer(self, n): 
     
    9271        self.inner_circle.clear() 
    9372        self.base.connect.clearall() 
    94         self.base.Unbind(EVT_SLICER_PARS) 
    9573 
    9674    def update(self): 
     
    10886        can restore on Esc. 
    10987        """ 
    110         self.base.freeze_axes() 
    11188        self.inner_circle.save(ev) 
    11289        self.outer_circle.save(ev) 
     
    12097        """ 
    12198        # Data to average 
    122         data = self.base.data2D 
    123         # If we have no data, just return 
    124         if data == None: 
     99        data = self.base.data 
     100        if data is None: 
    125101            return 
    126102 
    127103        from sas.sascalc.dataloader.manipulations import Ring 
    128         rmin = min(math.fabs(self.inner_circle.get_radius()), 
    129                    math.fabs(self.outer_circle.get_radius())) 
    130         rmax = max(math.fabs(self.inner_circle.get_radius()), 
    131                    math.fabs(self.outer_circle.get_radius())) 
    132         # if the user does not specify the numbers of points to plot 
     104        rmin = min(numpy.fabs(self.inner_circle.get_radius()), 
     105                   numpy.fabs(self.outer_circle.get_radius())) 
     106        rmax = max(numpy.fabs(self.inner_circle.get_radius()), 
     107                   numpy.fabs(self.outer_circle.get_radius())) 
     108        # If the user does not specify the numbers of points to plot 
    133109        # the default number will be nbins= 36 
    134         if nbins == None: 
     110        if nbins is None: 
    135111            self.nbins = 36 
    136112        else: 
    137113            self.nbins = nbins 
    138         # # create the data1D Q average of data2D 
     114        # Create the data1D Q average of data2D 
    139115        sect = Ring(r_min=rmin, r_max=rmax, nbins=self.nbins) 
    140         sector = sect(self.base.data2D) 
     116        sector = sect(self.base.data) 
    141117 
    142118        if hasattr(sector, "dxl"): 
     
    148124        else: 
    149125            dxw = None 
    150         new_plot = Data1D(x=(sector.x - math.pi) * 180 / math.pi, 
     126        new_plot = Data1D(x=(sector.x - numpy.pi) * 180 / numpy.pi, 
    151127                          y=sector.y, dy=sector.dy) 
    152128        new_plot.dxl = dxl 
    153129        new_plot.dxw = dxw 
    154         new_plot.name = "AnnulusPhi" + "(" + self.base.data2D.name + ")" 
    155  
    156         new_plot.source = self.base.data2D.source 
    157         # new_plot.info=self.base.data2D.info 
     130        new_plot.name = "AnnulusPhi" + "(" + self.base.data.name + ")" 
     131        new_plot.title = "AnnulusPhi" + "(" + self.base.data.name + ")" 
     132 
     133        new_plot.source = self.base.data.source 
    158134        new_plot.interactive = True 
    159         new_plot.detector = self.base.data2D.detector 
     135        new_plot.detector = self.base.data.detector 
    160136        # If the data file does not tell us what the axes are, just assume... 
    161137        new_plot.xaxis("\\rm{\phi}", 'degrees') 
    162138        new_plot.yaxis("\\rm{Intensity} ", "cm^{-1}") 
    163139        if hasattr(data, "scale") and data.scale == 'linear' and \ 
    164                 self.base.data2D.name.count("Residuals") > 0: 
     140                self.base.data.name.count("Residuals") > 0: 
    165141            new_plot.ytransform = 'y' 
    166142            new_plot.yaxis("\\rm{Residuals} ", "/") 
    167143 
    168         new_plot.group_id = "AnnulusPhi" + self.base.data2D.name 
    169         new_plot.id = "AnnulusPhi" + self.base.data2D.name 
     144        new_plot.group_id = "AnnulusPhi" + self.base.data.name 
     145        new_plot.id = "AnnulusPhi" + self.base.data.name 
    170146        new_plot.is_data = True 
    171147        new_plot.xtransform = "x" 
    172148        new_plot.ytransform = "y" 
    173         self.base.parent.update_theory(data_id=data.id, theory=new_plot) 
    174         wx.PostEvent(self.base.parent, NewPlotEvent(plot=new_plot, title="AnnulusPhi")) 
     149        variant_plot = QtCore.QVariant(new_plot) 
     150        GuiUtils.updateModelItemWithPlot(self._item, variant_plot, new_plot.id) 
     151 
     152        if self.update_model: 
     153            self.setModelFromParams() 
     154        self.draw() 
     155 
    175156 
    176157    def moveend(self, ev): 
    177158        """ 
    178159        Called when any dragging motion ends. 
    179         Post an event (type =SlicerParameterEvent) 
    180         to plotter 2D with a copy  slicer parameters 
    181         Call  _post_data method 
    182         """ 
    183         self.base.thaw_axes() 
    184         # Post parameters to plotter 2D 
    185         event = SlicerParameterEvent() 
    186         event.type = self.__class__.__name__ 
    187         event.params = self.get_params() 
    188         wx.PostEvent(self.base, event) 
     160        Redraw the plot with new parameters. 
     161        """ 
     162        self._post_data(self.nbins) 
    189163 
    190164    def restore(self): 
     
    204178        pass 
    205179 
    206     def get_params(self): 
     180    def getParams(self): 
    207181        """ 
    208182        Store a copy of values of parameters of the slicer into a dictionary. 
    209  
    210183        :return params: the dictionary created 
    211  
    212184        """ 
    213185        params = {} 
    214         params["inner_radius"] = math.fabs(self.inner_circle._inner_mouse_x) 
    215         params["outer_radius"] = math.fabs(self.outer_circle._inner_mouse_x) 
     186        params["inner_radius"] = numpy.fabs(self.inner_circle._inner_mouse_x) 
     187        params["outer_radius"] = numpy.fabs(self.outer_circle._inner_mouse_x) 
    216188        params["nbins"] = self.nbins 
    217189        return params 
    218190 
    219     def set_params(self, params): 
     191    def setParams(self, params): 
    220192        """ 
    221193        Receive a dictionary and reset the slicer with values contained 
     
    224196        :param params: a dictionary containing name of slicer parameters and 
    225197            values the user assigned to the slicer. 
    226  
    227         """ 
    228         inner = math.fabs(params["inner_radius"]) 
    229         outer = math.fabs(params["outer_radius"]) 
     198        """ 
     199        inner = numpy.fabs(params["inner_radius"]) 
     200        outer = numpy.fabs(params["outer_radius"]) 
    230201        self.nbins = int(params["nbins"]) 
    231         # # Update the picture 
     202        # Update the picture 
    232203        self.inner_circle.set_cursor(inner, self.inner_circle._inner_mouse_y) 
    233204        self.outer_circle.set_cursor(outer, self.outer_circle._inner_mouse_y) 
    234         # # Post the data given the nbins entered by the user 
     205        # Post the data given the nbins entered by the user 
    235206        self._post_data(self.nbins) 
    236  
    237     def freeze_axes(self): 
    238         """ 
    239         """ 
    240         self.base.freeze_axes() 
    241  
    242     def thaw_axes(self): 
    243         """ 
    244         """ 
    245         self.base.thaw_axes() 
    246207 
    247208    def draw(self): 
     
    278239        self.sign = sign 
    279240        # # Create a marker 
    280         try: 
    281             # Inner circle marker 
    282             x_value = [self.sign * math.fabs(self._inner_mouse_x)] 
    283             self.inner_marker = self.axes.plot(x_value, [0], linestyle='', 
    284                                                marker='s', markersize=10, 
    285                                                color=self.color, alpha=0.6, 
    286                                                pickradius=5, label="pick", 
    287                                                zorder=zorder, 
    288                                                visible=True)[0] 
    289         except: 
    290             x_value = [self.sign * math.fabs(self._inner_mouse_x)] 
    291             self.inner_marker = self.axes.plot(x_value, [0], linestyle='', 
    292                                                marker='s', markersize=10, 
    293                                                color=self.color, alpha=0.6, 
    294                                                label="pick", 
    295                                                visible=True)[0] 
    296             message = "\nTHIS PROTOTYPE NEEDS THE LATEST" 
    297             message += " VERSION OF MATPLOTLIB\n" 
    298             message += "Get the SVN version that is at " 
    299             message += " least as recent as June 1, 2007" 
    300  
    301             owner = self.base.base.parent 
    302             wx.PostEvent(owner, StatusEvent(status="AnnulusSlicer: %s" % message)) 
    303  
     241        # Inner circle marker 
     242        x_value = [self.sign * numpy.fabs(self._inner_mouse_x)] 
     243        self.inner_marker = self.axes.plot(x_value, [0], linestyle='', 
     244                                           marker='s', markersize=10, 
     245                                           color=self.color, alpha=0.6, 
     246                                           pickradius=5, label="pick", 
     247                                           zorder=zorder, 
     248                                           visible=True)[0] 
    304249        # Draw a circle 
    305250        [self.inner_circle] = self.axes.plot([], [], linestyle='-', marker='', color=self.color) 
    306         # the number of points that make the ring line 
     251        # The number of points that make the ring line 
    307252        self.npts = 40 
    308253 
     
    325270        """ 
    326271        self.clear_markers() 
    327         try: 
    328             self.inner_marker.remove() 
    329             self.inner_circle.remove() 
    330         except: 
    331             # Old version of matplotlib 
    332             for item in range(len(self.axes.lines)): 
    333                 del self.axes.lines[0] 
     272        self.inner_marker.remove() 
     273        self.inner_circle.remove() 
    334274 
    335275    def get_radius(self): 
     
    347287        y = [] 
    348288        for i in range(self.npts): 
    349             phi = 2.0 * math.pi / (self.npts - 1) * i 
    350  
    351             xval = 1.0 * self._inner_mouse_x * math.cos(phi) 
    352             yval = 1.0 * self._inner_mouse_x * math.sin(phi) 
     289            phi = 2.0 * numpy.pi / (self.npts - 1) * i 
     290 
     291            xval = 1.0 * self._inner_mouse_x * numpy.cos(phi) 
     292            yval = 1.0 * self._inner_mouse_x * numpy.sin(phi) 
    353293 
    354294            x.append(xval) 
    355295            y.append(yval) 
    356296 
    357         self.inner_marker.set(xdata=[self.sign * math.fabs(self._inner_mouse_x)], 
     297        self.inner_marker.set(xdata=[self.sign * numpy.fabs(self._inner_mouse_x)], 
    358298                              ydata=[0]) 
    359299        self.inner_circle.set_data(x, y) 
     
    366306        self._inner_save_x = self._inner_mouse_x 
    367307        self._inner_save_y = self._inner_mouse_y 
    368         self.base.freeze_axes() 
    369308 
    370309    def moveend(self, ev): 
     
    396335        self.update() 
    397336 
    398  
    399     def get_params(self): 
     337    def getParams(self): 
    400338        """ 
    401339        Store a copy of values of parameters of the slicer into a dictionary. 
    402  
    403340        :return params: the dictionary created 
    404  
    405341        """ 
    406342        params = {} 
    407         params["radius"] = math.fabs(self._inner_mouse_x) 
     343        params["radius"] = numpy.fabs(self._inner_mouse_x) 
    408344        return params 
    409345 
    410     def set_params(self, params): 
     346    def setParams(self, params): 
    411347        """ 
    412348        Receive a dictionary and reset the slicer with values contained 
     
    435371        self.base = base 
    436372        self.is_inside = side 
    437         self.qmax = min(math.fabs(self.base.data.xmax), 
    438                         math.fabs(self.base.data.xmin))  # must be positive 
     373        self.qmax = min(numpy.fabs(self.base.data.xmax), 
     374                        numpy.fabs(self.base.data.xmin))  # must be positive 
    439375        self.connect = self.base.connect 
    440376 
     
    448384            self.sign = -1 
    449385        # Inner circle 
    450         self.outer_circle = RingInteractor(self, self.base.subplot, 'blue', 
     386        self.outer_circle = RingInteractor(self, self.axes, 'blue', 
    451387                                           zorder=zorder + 1, r=self.qmax / 1.8, 
    452388                                           sign=self.sign) 
     
    455391        self._post_data() 
    456392 
    457         # Bind to slice parameter events 
    458         # self.base.Bind(EVT_SLICER_PARS, self._onEVT_SLICER_PARS) 
    459  
    460     def _onEVT_SLICER_PARS(self, event): 
    461         """ 
    462         receive an event containing parameters values to reset the slicer 
    463  
    464         :param event: event of type SlicerParameterEvent with params as 
    465             attribute 
    466         """ 
    467         wx.PostEvent(self.base, 
    468                      StatusEvent(status="AnnulusSlicer._onEVT_SLICER_PARS")) 
    469         event.Skip() 
    470         if event.type == self.__class__.__name__: 
    471             self.set_params(event.params) 
    472             self.base.update() 
    473  
    474393    def set_layer(self, n): 
    475394        """ 
    476395        Allow adding plot to the same panel 
    477  
    478396        :param n: the number of layer 
    479  
    480397        """ 
    481398        self.layernum = n 
     
    489406        self.outer_circle.clear() 
    490407        self.base.connect.clearall() 
    491         # self.base.Unbind(EVT_SLICER_PARS) 
    492408 
    493409    def update(self): 
     
    498414        # Update locations 
    499415        self.outer_circle.update() 
    500         # if self.is_inside != None: 
     416        self._post_data() 
    501417        out = self._post_data() 
    502418        return out 
     
    507423        can restore on Esc. 
    508424        """ 
    509         self.base.freeze_axes() 
    510425        self.outer_circle.save(ev) 
    511426 
     
    521436 
    522437        # If we have no data, just return 
    523         if data == None: 
     438        if data is None: 
    524439            return 
    525440        mask = data.mask 
     
    527442 
    528443        rmin = 0 
    529         rmax = math.fabs(self.outer_circle.get_radius()) 
    530  
    531         # # create the data1D Q average of data2D 
     444        rmax = numpy.fabs(self.outer_circle.get_radius()) 
     445 
     446        # Create the data1D Q average of data2D 
    532447        mask = Ringcut(r_min=rmin, r_max=rmax) 
    533448 
     
    536451        else: 
    537452            out = (mask(data)) 
    538         # self.base.data.mask=out 
    539453        return out 
    540454 
     
    566480        pass 
    567481 
    568     def get_params(self): 
     482    def getParams(self): 
    569483        """ 
    570484        Store a copy of values of parameters of the slicer into a dictionary. 
     
    574488        """ 
    575489        params = {} 
    576         params["outer_radius"] = math.fabs(self.outer_circle._inner_mouse_x) 
     490        params["outer_radius"] = numpy.fabs(self.outer_circle._inner_mouse_x) 
    577491        return params 
    578492 
    579     def set_params(self, params): 
     493    def setParams(self, params): 
    580494        """ 
    581495        Receive a dictionary and reset the slicer with values contained 
     
    585499            values the user assigned to the slicer. 
    586500        """ 
    587         outer = math.fabs(params["outer_radius"]) 
    588         # # Update the picture 
     501        outer = numpy.fabs(params["outer_radius"]) 
     502        # Update the picture 
    589503        self.outer_circle.set_cursor(outer, self.outer_circle._inner_mouse_y) 
    590         # # Post the data given the nbins entered by the user 
     504        # Post the data given the nbins entered by the user 
    591505        self._post_data() 
    592  
    593     def freeze_axes(self): 
    594         self.base.freeze_axes() 
    595  
    596     def thaw_axes(self): 
    597         self.base.thaw_axes() 
    598506 
    599507    def draw(self): 
Note: See TracChangeset for help on using the changeset viewer.