source: sasview/guiframe/local_perspectives/plotting/SectorSlicer.py @ 247873a

ESS_GUIESS_GUI_DocsESS_GUI_batch_fittingESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_iss879ESS_GUI_iss959ESS_GUI_openclESS_GUI_orderingESS_GUI_sync_sascalccostrafo411magnetic_scattrelease-4.1.1release-4.1.2release-4.2.2release_4.0.1ticket-1009ticket-1094-headlessticket-1242-2d-resolutionticket-1243ticket-1249ticket885unittest-saveload
Last change on this file since 247873a was fcf072d, checked in by Jae Cho <jhjcho@…>, 14 years ago

fixed all y_lable problem for residual

  • Property mode set to 100644
File size: 22.3 KB
RevLine 
[ef0c170]1
2import math
[0d9dae8]3import wx
[32c0841]4#from copy import deepcopy
[0d9dae8]5from BaseInteractor import _BaseInteractor
[55a0dc1]6from sans.guiframe.events import NewPlotEvent
7from sans.guiframe.events import StatusEvent
8from sans.guiframe.events import SlicerParameterEvent
9from sans.guiframe.events import EVT_SLICER_PARS
[4ac8556]10from sans.guiframe.dataFitting import Data1D
[ef0c170]11
[32c0841]12
[ef0c170]13class SectorInteractor(_BaseInteractor):
14    """
[d955bf19]15    Draw a sector slicer.Allow to performQ averaging on data 2D
[ef0c170]16    """
[32c0841]17    def __init__(self, base, axes, color='black', zorder=3):
[ef0c170]18       
19        _BaseInteractor.__init__(self, base, axes, color=color)
[6c0568b]20        ## Class initialization
[ef0c170]21        self.markers = []
[6c0568b]22        self.axes = axes   
23        ## connect the plot to event
[ef0c170]24        self.connect = self.base.connect
25       
[6c0568b]26        ## compute qmax limit to reset the graph     
[32c0841]27        x = math.pow(max(self.base.data2D.xmax, 
28                         math.fabs(self.base.data2D.xmin)), 2)
29        y = math.pow(max(self.base.data2D.ymax, 
30                         math.fabs(self.base.data2D.ymin)), 2)
31        self.qmax = math.sqrt(x + y)
[ef0c170]32        ## Number of points on the plot
[b783024]33        self.nbins = 20
[6c0568b]34        ## Angle of the middle line
[32c0841]35        self.theta2 = math.pi/3
[6c0568b]36        ## Absolute value of the Angle between the middle line and any side line
[32c0841]37        self.phi = math.pi/12
[6c0568b]38        ## Middle line
[32c0841]39        self.main_line = LineInteractor(self, self.base.subplot, color='blue', 
40                                        zorder=zorder, r=self.qmax,
[ef0c170]41                                           theta= self.theta2)
[2dda74ac]42        self.main_line.qmax = self.qmax
[6c0568b]43        ## Right Side line
[32c0841]44        self.right_line = SideInteractor(self, self.base.subplot, color='black',
45                                          zorder=zorder, r=self.qmax,
46                                          phi=-1*self.phi, theta2=self.theta2)
[2dda74ac]47        self.right_line.qmax = self.qmax
[6c0568b]48        ## Left Side line
[32c0841]49        self.left_line = SideInteractor(self, self.base.subplot, color='black',
50                                        zorder=zorder, r=self.qmax,
51                                           phi=self.phi, theta2=self.theta2)
[2dda74ac]52        self.left_line.qmax = self.qmax
[6c0568b]53        ## draw the sector               
[ef0c170]54        self.update()
55        self._post_data()
[6c0568b]56        ## Bind to slice parameter events
[1ce365f8]57        self.base.Bind(EVT_SLICER_PARS, self._onEVT_SLICER_PARS)
[ef0c170]58
59    def _onEVT_SLICER_PARS(self, event):
[6c0568b]60        """
[d955bf19]61        receive an event containing parameters values to reset the slicer
62       
63        :param event: event of type SlicerParameterEvent with params as
64        attribute
65       
[6c0568b]66        """
[32c0841]67        wx.PostEvent(self.base.parent,
68                     StatusEvent(status="SectorSlicer._onEVT_SLICER_PARS"))
[ef0c170]69        event.Skip()
70        if event.type == self.__class__.__name__:
71            self.set_params(event.params)
72            self.base.update()
[d955bf19]73           
[ef0c170]74    def set_layer(self, n):
[6c0568b]75        """
[d955bf19]76         Allow adding plot to the same panel
77         
78        :param n: the number of layer
79       
[6c0568b]80        """
[ef0c170]81        self.layernum = n
82        self.update()
83       
84    def clear(self):
[6c0568b]85        """
[d955bf19]86        Clear the slicer and all connected events related to this slicer
[6c0568b]87        """
[ef0c170]88        self.clear_markers()
89        self.main_line.clear()
90        self.left_line.clear()
91        self.right_line.clear()
[18eba35]92        self.base.connect.clearall()
[d468daa]93        self.base.Unbind(EVT_SLICER_PARS)
[ef0c170]94       
95    def update(self):
96        """
[d955bf19]97        Respond to changes in the model by recalculating the profiles and
98        resetting the widgets.
[ef0c170]99        """
[6c0568b]100        # Update locations 
[32c0841]101        ## Check if the middle line was dragged and
102        #update the picture accordingly     
[ef0c170]103        if self.main_line.has_move:
104            self.main_line.update()
[32c0841]105            self.right_line.update(delta=-self.left_line.phi/2,
106                                    mline=self.main_line.theta)
107            self.left_line.update(delta=self.left_line.phi/2,
108                                   mline=self.main_line.theta)
[6c0568b]109        ## Check if the left side has moved and update the slicer accordingly 
[ef0c170]110        if self.left_line.has_move:
111            self.main_line.update()
[32c0841]112            self.left_line.update(phi=None, delta=None, mline=self.main_line,
113                                  side=True, left=True)
114            self.right_line.update(phi=self.left_line.phi, delta=None,
115                                     mline=self.main_line, side=True,
116                                     left=False, right=True)
117        ## Check if the right side line has moved and
118        #update the slicer accordingly
[ef0c170]119        if self.right_line.has_move:
120            self.main_line.update()
[32c0841]121            self.right_line.update(phi=None, delta=None, mline=self.main_line,
122                                   side=True, left=False, right=True)
123            self.left_line.update(phi=self.right_line.phi, delta=None,
124                                    mline=self.main_line, side=True, left=False)
[d955bf19]125           
[ef0c170]126    def save(self, ev):
127        """
128        Remember the roughness for this layer and the next so that we
129        can restore on Esc.
130        """
131        self.base.freeze_axes()
[6c0568b]132        self.main_line.save(ev)
133        self.right_line.save(ev)
134        self.left_line.save(ev)
[ef0c170]135
136    def _post_data(self, nbins=None):
[6c0568b]137        """
[d955bf19]138        compute sector averaging of data2D into data1D
139       
140        :param nbins: the number of point to plot for the average 1D data
[6c0568b]141        """
142        ## get the data2D to average
[ef0c170]143        data = self.base.data2D
144        # If we have no data, just return
145        if data == None:
146            return
[6c0568b]147        ## Averaging
[ef0c170]148        from DataLoader.manipulations import SectorQ
[6c0568b]149        radius = self.qmax
150        phimin =  -self.left_line.phi + self.main_line.theta
151        phimax = self.left_line.phi + self.main_line.theta
[32c0841]152        if nbins == None:
[1ce365f8]153            nbins = 20
[32c0841]154        sect = SectorQ(r_min=0.0, r_max=radius,
155                        phi_min=phimin + math.pi,
156                        phi_max=phimax + math.pi, nbins=nbins)
[6c0568b]157     
[ef0c170]158        sector = sect(self.base.data2D)
[6c0568b]159        ##Create 1D data resulting from average
[4ac8556]160       
[32c0841]161        if hasattr(sector, "dxl"):
162            dxl = sector.dxl
[ef0c170]163        else:
[32c0841]164            dxl = None
165        if hasattr(sector, "dxw"):
166            dxw = sector.dxw
[ef0c170]167        else:
[32c0841]168            dxw = None
[21969a4a]169        new_plot = Data1D(x=sector.x, y=sector.y, dy=sector.dy, dx=sector.dx)
[4ac8556]170        new_plot.dxl = dxl
171        new_plot.dxw = dxw
[32c0841]172        new_plot.name = "SectorQ" + "(" + self.base.data2D.name + ")"
173        new_plot.source = self.base.data2D.source
[8b30e62]174        #new_plot.info=self.base.data2D.info
[ef0c170]175        new_plot.interactive = True
[32c0841]176        new_plot.detector = self.base.data2D.detector
[21969a4a]177        ## If the data file does not tell us what the axes are, just assume...
178        new_plot.xaxis("\\rm{Q}", "A^{-1}")
[7f59ee8e]179        new_plot.yaxis("\\rm{Intensity}", "cm^{-1}")
[fcf072d]180        if hasattr(data, "scale") and data.scale == 'linear' and \
181                self.base.data2D.name.count("Residuals") > 0:
[7f59ee8e]182            new_plot.ytransform = 'y'
183            new_plot.yaxis("\\rm{Residuals} ", "/")
184
[32c0841]185        new_plot.group_id = "SectorQ" + self.base.data2D.name
[21969a4a]186        new_plot.id = None
[32c0841]187        new_plot.is_data = True
[21969a4a]188
[ef0c170]189        wx.PostEvent(self.base.parent, NewPlotEvent(plot=new_plot,
[32c0841]190                                    title="SectorQ" + self.base.data2D.name))
[ef0c170]191       
192    def moveend(self, ev):
[6c0568b]193        """
[d955bf19]194        Called a dragging motion ends.Get slicer event
[6c0568b]195        """
[ef0c170]196        self.base.thaw_axes()
[6c0568b]197        ## Post parameters
[0d9dae8]198        event = SlicerParameterEvent()
[ef0c170]199        event.type = self.__class__.__name__
200        event.params = self.get_params()
[6c0568b]201        ## Send slicer paramers to plotter2D
[d468daa]202        wx.PostEvent(self.base, event)
[d955bf19]203       
[ef0c170]204    def restore(self):
205        """
206        Restore the roughness for this layer.
207        """
208        self.main_line.restore()
209        self.left_line.restore()
210        self.right_line.restore()
211
212    def move(self, x, y, ev):
213        """
214        Process move to a new position, making sure that the move is allowed.
215        """
216        pass
217       
218    def set_cursor(self, x, y):
[d955bf19]219        """
220        """
[ef0c170]221        pass
222       
223    def get_params(self):
[6c0568b]224        """
[d955bf19]225        Store a copy of values of parameters of the slicer into a dictionary.
226       
227        :return params: the dictionary created
228       
[6c0568b]229        """
[ef0c170]230        params = {}
[6c0568b]231        ## Always make sure that the left and the right line are at phi
232        ## angle of the middle line
[ef0c170]233        if math.fabs(self.left_line.phi) != math.fabs(self.right_line.phi):
[32c0841]234            msg = "Phi left and phi right are different"
235            msg += " %f, %f" % (self.left_line.phi, self.right_line.phi)
236            raise ValueError, msg
[6c0568b]237        params["Phi"] = self.main_line.theta
[1a6ec25]238        params["Delta_Phi"] = math.fabs(self.left_line.phi)
[ef0c170]239        params["nbins"] = self.nbins
240        return params
241   
242    def set_params(self, params):
[6c0568b]243        """
[d955bf19]244        Receive a dictionary and reset the slicer with values contained
245        in the values of the dictionary.
246       
247        :param params: a dictionary containing name of slicer parameters and
[6c0568b]248            values the user assigned to the slicer.
249        """
[1a6ec25]250        main = params["Phi"] 
[32c0841]251        phi = math.fabs(params["Delta_Phi"])
[ef0c170]252        self.nbins = int(params["nbins"])
[32c0841]253        self.main_line.theta = main
[6c0568b]254        ## Reset the slicer parameters
[ef0c170]255        self.main_line.update()
[32c0841]256        self.right_line.update(phi=phi, delta=None, mline=self.main_line,
257                               side=True, right=True)
258        self.left_line.update(phi=phi, delta=None, 
259                              mline=self.main_line, side=True)
[6c0568b]260        ## post the new corresponding data
[ef0c170]261        self._post_data(nbins=self.nbins)
262       
263    def freeze_axes(self):
[d955bf19]264        """
265        """
[ef0c170]266        self.base.freeze_axes()
[d955bf19]267   
[ef0c170]268    def thaw_axes(self):
[d955bf19]269        """
270        """
[ef0c170]271        self.base.thaw_axes()
272
273    def draw(self):
[d955bf19]274        """
275        """
[ef0c170]276        self.base.draw()
277
278       
279class SideInteractor(_BaseInteractor):
280    """
[d955bf19]281    Draw an oblique line
282   
283    :param phi: the phase between the middle line and one side line
284    :param theta2: the angle between the middle line and x- axis
285   
[ef0c170]286    """
[32c0841]287    def __init__(self, base, axes, color='black', zorder=5, r=1.0,
288                 phi=math.pi/4, theta2= math.pi/3):
289        """
290        """
[ef0c170]291        _BaseInteractor.__init__(self, base, axes, color=color)
[6c0568b]292        ## Initialize the class
[ef0c170]293        self.markers = []
294        self.axes = axes
[6c0568b]295        ## compute the value of the angle between the current line and
296        ## the x-axis 
[ef0c170]297        self.save_theta = theta2 + phi
[32c0841]298        self.theta = theta2 + phi
[6c0568b]299        ## the value of the middle line angle with respect to the x-axis
[ef0c170]300        self.theta2 = theta2
[6c0568b]301        ## Radius to find polar coordinates this line's endpoints
[ef0c170]302        self.radius = r
[6c0568b]303        ## phi is the phase between the current line and the middle line
[ef0c170]304        self.phi = phi
[6c0568b]305        ## End points polar coordinates
[32c0841]306        x1 = self.radius * math.cos(self.theta)
307        y1 = self.radius * math.sin(self.theta)
308        x2 = -1 * self.radius * math.cos(self.theta)
309        y2 = -1 * self.radius * math.sin(self.theta)
[6c0568b]310        ## defining a new marker
[7a28ba7]311        try:
[32c0841]312            self.inner_marker = self.axes.plot([x1/2.5], [y1/2.5], linestyle='',
[7a28ba7]313                                          marker='s', markersize=10,
314                                          color=self.color, alpha=0.6,
315                                          pickradius=5, label="pick", 
[32c0841]316                                          # Prefer this to other lines
317                                          zorder=zorder, visible=True)[0]
[7a28ba7]318        except:
[0c218d9]319            self.inner_marker = self.axes.plot([x1/2.5],[y1/2.5], linestyle='',
[7a28ba7]320                                          marker='s', markersize=10,
321                                          color=self.color, alpha=0.6,
[32c0841]322                                          label="pick", visible=True)[0]
323            message  = "\nTHIS PROTOTYPE NEEDS THE LATEST"
324            message += " VERSION OF MATPLOTLIB\n Get the SVN version that"
325            message += " is at least as recent as June 1, 2007"
326            owner = self.base.base.parent
327            wx.PostEvent(owner, 
328                         StatusEvent(status="sectorSlicer: %s" % message))
[6c0568b]329       
330        ## Defining the current line
[32c0841]331        self.line = self.axes.plot([x1, x2], [y1, y2],
[ef0c170]332                                      linestyle='-', marker='',
[32c0841]333                                      color=self.color, visible=True)[0]
[6c0568b]334        ## Flag to differentiate the left line from the right line motion
[32c0841]335        self.left_moving = False
[6c0568b]336        ## Flag to define a motion
[32c0841]337        self.has_move = False
[6c0568b]338        ## connecting markers and draw the picture
[7a28ba7]339        self.connect_markers([self.inner_marker, self.line])
[6c0568b]340       
[ef0c170]341    def set_layer(self, n):
[6c0568b]342        """
[d955bf19]343        Allow adding plot to the same panel
344         
345        :param n: the number of layer
346       
[6c0568b]347        """
[ef0c170]348        self.layernum = n
349        self.update()
350       
351    def clear(self):
[6c0568b]352        """
[d955bf19]353        Clear the slicer and all connected events related to this slicer
[6c0568b]354        """
[ef0c170]355        self.clear_markers()
356        try:
357            self.line.remove()
[7a28ba7]358            self.inner_marker.remove()
[ef0c170]359        except:
360            # Old version of matplotlib
361            for item in range(len(self.axes.lines)):
362                del self.axes.lines[0]
[d955bf19]363   
[6c0568b]364    def update(self, phi=None, delta=None, mline=None,
365               side=False, left= False, right=False):
[ef0c170]366        """
[d955bf19]367        Draw oblique line
368       
369        :param phi: the phase between the middle line and the current line
370        :param delta: phi/2 applied only when the mline was moved
371       
[ef0c170]372        """
373        #print "update left or right ", self.has_move
[32c0841]374        self.left_moving = left
375        theta3 = 0
376        if phi != None:
377            self.phi = phi
378        if delta == None:
[31e3298]379            delta = 0
[7a28ba7]380        if  right:
[32c0841]381            self.phi = -1 * math.fabs(self.phi)
[31e3298]382            #delta=-delta
[7a28ba7]383        else:
[32c0841]384            self.phi = math.fabs(self.phi)
[e23a20c]385        if side:
[32c0841]386            self.theta = mline.theta + self.phi
[31e3298]387                   
[32c0841]388        if mline != None :
389            if delta != 0:
390                self.theta2 = mline + delta
[31e3298]391            else:
392                self.theta2 = mline.theta
[32c0841]393        if delta == 0:
394            theta3 = self.theta + delta
[31e3298]395        else:
[32c0841]396            theta3 = self.theta2 + delta
397        x1 = self.radius * math.cos(theta3)
398        y1 = self.radius * math.sin(theta3)
399        x2 = -1 * self.radius * math.cos(theta3)
400        y2 = -1 * self.radius * math.sin(theta3)
401        self.inner_marker.set(xdata=[x1/2.5], ydata=[y1/2.5])
402        self.line.set(xdata=[x1, x2], ydata=[y1, y2]) 
[ef0c170]403       
404    def save(self, ev):
405        """
406        Remember the roughness for this layer and the next so that we
407        can restore on Esc.
408        """
[32c0841]409        self.save_theta = self.theta
[ef0c170]410        self.base.freeze_axes()
411
412    def moveend(self, ev):
[d955bf19]413        """
414        """
[32c0841]415        self.has_move = False
[ef0c170]416        self.base.moveend(ev)
417           
418    def restore(self):
419        """
420        Restore the roughness for this layer.
421        """
422        self.theta = self.save_theta
423
424    def move(self, x, y, ev):
425        """
426        Process move to a new position, making sure that the move is allowed.
427        """
[32c0841]428        self.theta = math.atan2(y, x)
429        self.has_move = True
[0c218d9]430        #ToDo: Simplify below
[7a28ba7]431        if not self.left_moving:
[32c0841]432            if  self.theta2 - self.theta <= 0 and self.theta2 > 0:
[0c218d9]433                self.restore()
434                return 
[32c0841]435            elif self.theta2 < 0 and self.theta < 0 and \
436                self.theta-self.theta2 >= 0:
[0c218d9]437                self.restore()
438                return                             
[32c0841]439            elif  self.theta2 < 0 and self.theta > 0 and \
440                (self.theta2 + 2 * math.pi - self.theta) >= math.pi/2:
[0c218d9]441                #print "my theta", self.theta
442                self.restore()
443                return 
[32c0841]444            elif  self.theta2 < 0 and self.theta < 0 and \
445                (self.theta2 - self.theta) >= math.pi/2:
[0c218d9]446                #print "my theta", self.theta
[7a28ba7]447                self.restore()
448                return 
[32c0841]449            elif self.theta2 > 0 and (self.theta2-self.theta >= math.pi/2 or \
450                (self.theta2-self.theta >= math.pi/2)):
[0c218d9]451                #print "self theta encore"
[7a28ba7]452                self.restore()
453                return 
454        else:
[0c218d9]455            #print "left move"
[32c0841]456            if  self.theta < 0 and (self.theta + math.pi*2-self.theta2) <= 0:
[7a28ba7]457                self.restore()
458                return 
[32c0841]459            elif self.theta2 < 0 and (self.theta-self.theta2) <= 0:
[0c218d9]460                self.restore()
461                return                             
[32c0841]462            elif  self.theta > 0 and self.theta-self.theta2 <= 0:
[0c218d9]463                #print "my theta", self.theta
464                self.restore()
465                return 
[32c0841]466            elif self.theta-self.theta2 >= math.pi/2 or  \
467                ((self.theta + math.pi * 2 - self.theta2) >= math.pi/2 and \
468                 self.theta < 0 and self.theta2 > 0):
[0c218d9]469                #print "self theta encore"
[7a28ba7]470                self.restore()
471                return 
[0c218d9]472           
[32c0841]473        self.phi = math.fabs(self.theta2 - self.theta)
474        if self.phi > math.pi:
475            self.phi = 2 * math.pi - math.fabs(self.theta2 - self.theta)
[ef0c170]476        self.base.base.update()
477       
478    def set_cursor(self, x, y):
[d955bf19]479        """
480        """
[ef0c170]481        self.move(x, y, None)
482        self.update()
[d955bf19]483   
[ef0c170]484    def get_params(self):
[d955bf19]485        """
486        """
[ef0c170]487        params = {}
488        params["radius"] = self.radius
489        params["theta"] = self.theta
490        return params
491   
492    def set_params(self, params):
[d955bf19]493        """
494        """
[ef0c170]495        x = params["radius"] 
496        self.set_cursor(x, self._inner_mouse_y)
497       
[d955bf19]498
[ef0c170]499class LineInteractor(_BaseInteractor):
500    """
[d955bf19]501    Select an annulus through a 2D plot
[ef0c170]502    """
[32c0841]503    def __init__(self, base, axes, color='black',
504                 zorder=5, r=1.0, theta=math.pi/4):
[d955bf19]505        """
506        """
[ef0c170]507        _BaseInteractor.__init__(self, base, axes, color=color)
[d955bf19]508       
[ef0c170]509        self.markers = []
510        self.axes = axes
511        self.save_theta = theta
512        self.theta= theta
513        self.radius = r
514        self.scale = 10.0
515        # Inner circle
[32c0841]516        x1 = self.radius * math.cos(self.theta)
517        y1 = self.radius * math.sin(self.theta)
518        x2 = -1*self.radius * math.cos(self.theta)
519        y2 = -1*self.radius * math.sin(self.theta)
[7a28ba7]520        try:
521            # Inner circle marker
[32c0841]522            self.inner_marker = self.axes.plot([x1/2.5], [y1/2.5], linestyle='',
[7a28ba7]523                                          marker='s', markersize=10,
524                                          color=self.color, alpha=0.6,
525                                          pickradius=5, label="pick", 
[32c0841]526                                          # Prefer this to other lines
527                                          zorder=zorder, 
[7a28ba7]528                                          visible=True)[0]
529        except:
[32c0841]530            self.inner_marker = self.axes.plot([x1/2.5], [y1/2.5], linestyle='',
[7a28ba7]531                                          marker='s', markersize=10,
532                                          color=self.color, alpha=0.6,
533                                          label="pick", 
534                                          visible=True)[0]
[32c0841]535            message  = "\nTHIS PROTOTYPE NEEDS THE LATEST VERSION"
536            message += " OF MATPLOTLIB\n Get the SVN version that is at"
537            message += " least as recent as June 1, 2007"
538        self.line = self.axes.plot([x1, x2], [y1, y2],
[ef0c170]539                                      linestyle='-', marker='',
[32c0841]540                                      color=self.color, visible=True)[0]
[ef0c170]541        self.npts = 20
[32c0841]542        self.has_move = False
[7a28ba7]543        self.connect_markers([self.inner_marker, self.line])
[ef0c170]544        self.update()
545
546    def set_layer(self, n):
[d955bf19]547        """
548        """
[ef0c170]549        self.layernum = n
550        self.update()
551       
552    def clear(self):
[d955bf19]553        """
554        """
[ef0c170]555        self.clear_markers()
556        try:
[7a28ba7]557            self.inner_marker.remove()
[ef0c170]558            self.line.remove()
559        except:
560            # Old version of matplotlib
561            for item in range(len(self.axes.lines)):
562                del self.axes.lines[0]
[6c0568b]563 
[ef0c170]564    def update(self, theta=None):
565        """
566        Draw the new roughness on the graph.
567        """
[6c0568b]568       
[32c0841]569        if theta != None:
570            self.theta = theta
571        x1 = self.radius * math.cos(self.theta)
572        y1 = self.radius * math.sin(self.theta)
573        x2 = -1 * self.radius * math.cos(self.theta)
574        y2 = -1 * self.radius * math.sin(self.theta)
575       
576        self.inner_marker.set(xdata=[x1/2.5], ydata=[y1/2.5])
577        self.line.set(xdata=[x1, x2], ydata=[y1, y2]) 
[d955bf19]578   
[ef0c170]579    def save(self, ev):
580        """
581        Remember the roughness for this layer and the next so that we
582        can restore on Esc.
583        """
584        self.save_theta= self.theta
585        self.base.freeze_axes()
586
587    def moveend(self, ev):
[d955bf19]588        """
589        """
[32c0841]590        self.has_move = False
[ef0c170]591        self.base.moveend(ev)
592           
593    def restore(self):
594        """
595        Restore the roughness for this layer.
596        """
597        self.theta = self.save_theta
598
599    def move(self, x, y, ev):
600        """
601        Process move to a new position, making sure that the move is allowed.
602        """
[32c0841]603        self.theta = math.atan2(y, x)
604        self.has_move = True
[ef0c170]605        self.base.base.update()
606       
607    def set_cursor(self, x, y):
[d955bf19]608        """
609        """
[ef0c170]610        self.move(x, y, None)
611        self.update()
612       
613    def get_params(self):
[d955bf19]614        """
615        """
[ef0c170]616        params = {}
617        params["radius"] = self.radius
618        params["theta"] = self.theta
619        return params
620   
621    def set_params(self, params):
[d955bf19]622        """
623        """
[ef0c170]624        x = params["radius"] 
625        self.set_cursor(x, self._inner_mouse_y)
[356aea78]626       
Note: See TracBrowser for help on using the repository browser.