source: sasview/guiframe/local_perspectives/plotting/SectorSlicer.py @ 343fdb6

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 343fdb6 was d955bf19, checked in by Gervaise Alina <gervyh@…>, 15 years ago

working on documentation

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