source: sasview/sansguiframe/src/sans/guiframe/local_perspectives/plotting/boxSum.py @ 9ccb7e1

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 9ccb7e1 was 8c61e14, checked in by Mathieu Doucet <doucetm@…>, 12 years ago

Fixing code style problems and bugs

  • Property mode set to 100644
File size: 29.6 KB
RevLine 
[8c61e14]1"""
2    Boxsum Class: determine 2 rectangular area to compute
3    the sum of pixel of a Data.
4"""
[78ed1ad]5import math
6import wx
[eba08f1a]7from BaseInteractor import _BaseInteractor
[55a0dc1]8from sans.guiframe.events import SlicerParamUpdateEvent
9from sans.guiframe.events import EVT_SLICER_PARS
10from sans.guiframe.events import StatusEvent
[eba08f1a]11
12
[78ed1ad]13class BoxSum(_BaseInteractor):
14    """
[32c0841]15        Boxsum Class: determine 2 rectangular area to compute
16        the sum of pixel of a Data.
[eba08f1a]17        Uses PointerInteractor , VerticalDoubleLine,HorizontalDoubleLine.
18        @param zorder:  Artists with lower zorder values are drawn first.
19        @param x_min: the minimum value of the x coordinate
20        @param x_max: the maximum value of the x coordinate
21        @param y_min: the minimum value of the y coordinate
22        @param y_max: the maximum value of the y coordinate
23
[78ed1ad]24    """
[32c0841]25    def __init__(self, base, axes, color='black', zorder=3, x_min=0.008,
[eba08f1a]26                  x_max=0.008, y_min=0.0025, y_max=0.0025):
[32c0841]27        """
28        """
[78ed1ad]29        _BaseInteractor.__init__(self, base, axes, color=color)
[eba08f1a]30        ## class initialization
31        ## list of Boxsmun markers
[78ed1ad]32        self.markers = []
33        self.axes = axes
[eba08f1a]34        ## connect the artist for the motion
[78ed1ad]35        self.connect = self.base.connect
[eba08f1a]36        ## when qmax is reached the selected line is reset the its previous value
37        self.qmax = min(self.base.data2D.xmax, self.base.data2D.xmin)
38        ## Define the boxsum limits
[32c0841]39        self.xmin = -1 * 0.5 * min(math.fabs(self.base.data2D.xmax),
40                                  math.fabs(self.base.data2D.xmin))
41        self.ymin = -1 * 0.5 * min(math.fabs(self.base.data2D.xmax),
[614ce1b1]42                                  math.fabs(self.base.data2D.xmin))
[32c0841]43        self.xmax = 0.5 * min(math.fabs(self.base.data2D.xmax),
44                              math.fabs(self.base.data2D.xmin))
45        self.ymax = 0.5 * min(math.fabs(self.base.data2D.xmax),
46                              math.fabs(self.base.data2D.xmin))
[eba08f1a]47        ## center of the boxSum
[32c0841]48        self.center_x = 0.0002
49        self.center_y = 0.0003
[78ed1ad]50        ## Number of points on the plot
51        self.nbins = 20
[eba08f1a]52        ## Define initial result the summation
[32c0841]53        self.count = 0
54        self.error = 0
[eba08f1a]55        ## Flag to determine if the current figure has moved
56        ## set to False == no motion , set to True== motion
[32c0841]57        self.has_move = False
[eba08f1a]58        ## Create Boxsum edges
[8c61e14]59        self.horizontal_lines = HorizontalDoubleLine(self,
[32c0841]60                                                    self.base.subplot,
61                                                    color='blue',
[2a3a890]62                                                      zorder=zorder,
[32c0841]63                                                      y=self.ymax,
64                                                      x=self.xmax,
65                                                      center_x=self.center_x,
66                                                      center_y=self.center_y)
[2a3a890]67        self.horizontal_lines.qmax = self.qmax
[78ed1ad]68       
[8c61e14]69        self.vertical_lines = VerticalDoubleLine(self,
[32c0841]70                                                self.base.subplot,
71                                                color='black',
72                                                zorder=zorder,
73                                                y=self.ymax,
74                                                x=self.xmax,
75                                                center_x=self.center_x,
76                                                center_y=self.center_y)
[2a3a890]77        self.vertical_lines.qmax = self.qmax
[eba08f1a]78       
[8c61e14]79        self.center = PointInteractor(self,
[32c0841]80                                     self.base.subplot,color='grey',
81                                    zorder=zorder,
[2a3a890]82                                    center_x= self.center_x,
83                                    center_y= self.center_y)
[eba08f1a]84        ## Save the name of the slicer panel associate with this slicer
[32c0841]85        self.panel_name = ""   
[eba08f1a]86        ## Update and post slicer parameters 
[78ed1ad]87        self.update()
[92c2345]88        self._post_data()
[eba08f1a]89        ## Bind to slice parameter events
[18eba35]90        self.base.Bind(EVT_SLICER_PARS, self._onEVT_SLICER_PARS)
[6d920cd]91       
[0bd2cd8]92    def set_panel_name(self, name):
[eba08f1a]93        """
94            Store the name of the panel associated to this slicer
95            @param name: the name of this panel
96        """
[32c0841]97        self.panel_name = name
[6d920cd]98       
[78ed1ad]99    def _onEVT_SLICER_PARS(self, event):
[eba08f1a]100        """
101            receive an event containing parameters values to reset the slicer
102            @param event: event of type SlicerParameterEvent with params as
103            attribute
104        """
105        ## Post e message to declare what kind of event has being received
[32c0841]106        wx.PostEvent(self.base.parent,
107                     StatusEvent(status="Boxsum._onEVT_SLICER_PARS"))
[78ed1ad]108        event.Skip()
[eba08f1a]109        ## reset the slicer with the values contains the event.params dictionary
[78ed1ad]110        if event.type == self.__class__.__name__:
[92c2345]111            self.set_params(event.params)
[78ed1ad]112            self.base.update()
113
114    def set_layer(self, n):
[eba08f1a]115        """
[32c0841]116        Allow adding plot to the same panel
117        :param n: the number of layer
[eba08f1a]118        """
[78ed1ad]119        self.layernum = n
120        self.update()
121       
122    def clear(self):
[eba08f1a]123        """
[32c0841]124        Clear the slicer and all connected events related to this slicer
[eba08f1a]125        """
[78ed1ad]126        self.clear_markers()
[2a3a890]127        self.horizontal_lines.clear()
128        self.vertical_lines.clear()
129        self.center.clear()
[18eba35]130        self.base.connect.clearall()
131        self.base.Unbind(EVT_SLICER_PARS)
[78ed1ad]132       
133    def update(self):
134        """
[32c0841]135        Respond to changes in the model by recalculating the profiles and
136        resetting the widgets.
[78ed1ad]137        """
[eba08f1a]138        ## check if the center point has moved and update the figure accordingly
[2a3a890]139        if self.center.has_move:
140            self.center.update()
141            self.horizontal_lines.update( center= self.center)
142            self.vertical_lines.update( center= self.center)
[32c0841]143        ## check if the horizontal lines have moved and
144        #update the figure accordingly   
[2a3a890]145        if self.horizontal_lines.has_move:
146            self.horizontal_lines.update()
147            self.vertical_lines.update(y1=self.horizontal_lines.y1,
148                                       y2=self.horizontal_lines.y2,
[32c0841]149                                       height=self.horizontal_lines.half_height)
150        ## check if the vertical lines have moved and
151        #update the figure accordingly   
[2a3a890]152        if self.vertical_lines.has_move:
153            self.vertical_lines.update()
154            self.horizontal_lines.update(x1=self.vertical_lines.x1,
155                                         x2=self.vertical_lines.x2,
156                                         width=self.vertical_lines.half_width)
[78ed1ad]157           
158    def save(self, ev):
159        """
160        Remember the roughness for this layer and the next so that we
161        can restore on Esc.
162        """
163        self.base.freeze_axes()
[2a3a890]164        self.horizontal_lines.save(ev)
165        self.vertical_lines.save(ev)
166        self.center.save(ev)
167       
[78ed1ad]168    def _post_data(self):
[eba08f1a]169        """
[32c0841]170        Get the limits of the boxsum and compute the sum of the pixel
171        contained in that region and the error on that sum
[eba08f1a]172        """
173        ## Data 2D for which the pixel will be summed
[78ed1ad]174        data = self.base.data2D
[eba08f1a]175        ## the region of the summation
[32c0841]176        x_min = self.horizontal_lines.x2
177        x_max = self.horizontal_lines.x1
178        y_min = self.vertical_lines.y2
179        y_max = self.vertical_lines.y1
[eba08f1a]180        ##computation of the sum and its error
[db7a82e]181        from sans.dataloader.manipulations import Boxavg
[32c0841]182        box =  Boxavg(x_min=x_min, x_max=x_max, y_min=y_min, y_max=y_max)
[92c2345]183        self.count, self.error = box(self.base.data2D)
[32c0841]184       
[78ed1ad]185    def moveend(self, ev):
[eba08f1a]186        """
187            After a dragging motion this function is called to compute
188            the error and the sum of pixel of a given data 2D
189        """
[78ed1ad]190        self.base.thaw_axes()
[eba08f1a]191        ## compute error an d sum of data's pixel
[54cc36a]192        self._post_data()
[eba08f1a]193        ## Create and event ( posted to guiframe)that  set the
194        ##current slicer parameter to a panel of name self.panel_name
[32c0841]195        self.type = self.__class__.__name__
196        params = self.get_params()
197        event = SlicerParamUpdateEvent(type=self.type,
198                                       params=params,
199                                       panel_name=self.panel_name)
[0bd2cd8]200        wx.PostEvent(self.base.parent, event)
[92c2345]201       
[78ed1ad]202    def restore(self):
203        """
204        Restore the roughness for this layer.
205        """
[2a3a890]206        self.horizontal_lines.restore()
207        self.vertical_lines.restore()
208        self.center.restore()
[eba08f1a]209       
[78ed1ad]210    def move(self, x, y, ev):
211        """
212        Process move to a new position, making sure that the move is allowed.
213        """
[2a3a890]214        pass
215   
[78ed1ad]216    def set_cursor(self, x, y):
[32c0841]217        """
218        """
[78ed1ad]219        pass
220       
221    def get_params(self):
[eba08f1a]222        """
[32c0841]223        Store a copy of values of parameters of the slicer into a dictionary.
224        :return params: the dictionary created
[eba08f1a]225        """
[78ed1ad]226        params = {}
[32c0841]227        params["Width"] = math.fabs(self.vertical_lines.half_width) * 2
228        params["Height"] = math.fabs(self.horizontal_lines.half_height) * 2 
[2a3a890]229        params["center_x"] = self.center.x
[32c0841]230        params["center_y"] = self.center.y
[0f6d05f8]231        params["count"] = self.count
[32c0841]232        params["errors"] = self.error
[78ed1ad]233        return params
234   
[92c2345]235    def get_result(self):
236        """
237            return the result of box summation
238        """
[32c0841]239        result = {}
[92c2345]240        result["count"] = self.count
241        result["error"] = self.error
242        return result
243       
[78ed1ad]244    def set_params(self, params):
[eba08f1a]245        """
[32c0841]246        Receive a dictionary and reset the slicer with values contained
247        in the values of the dictionary.
248        :param params: a dictionary containing name of slicer parameters and
[eba08f1a]249            values the user assigned to the slicer.
250        """
[ee69839]251        x_max = math.fabs(params["Width"] )/2
252        y_max = math.fabs(params["Height"] )/2
[78ed1ad]253       
[32c0841]254        self.center_x = params["center_x"] 
255        self.center_y = params["center_y"]
[eba08f1a]256        #update the slicer given values of params
[32c0841]257        self.center.update(center_x=self.center_x, center_y=self.center_y)
258        self.horizontal_lines.update(center=self.center,
259                                     width=x_max, height=y_max)
260        self.vertical_lines.update(center=self.center,
261                                    width=x_max, height=y_max)
[eba08f1a]262        #compute the new error and sum given values of params
[78ed1ad]263        self._post_data()
[2a3a890]264       
[78ed1ad]265    def freeze_axes(self):
[32c0841]266        """
267        """
[78ed1ad]268        self.base.freeze_axes()
269       
270    def thaw_axes(self):
[32c0841]271        """
272        """
[78ed1ad]273        self.base.thaw_axes()
274
275    def draw(self):
[32c0841]276        """
277        """
[78ed1ad]278        self.base.draw()
[eba08f1a]279       
280       
281       
[2a3a890]282class PointInteractor(_BaseInteractor):
[78ed1ad]283    """
[32c0841]284    Draw a point that can be dragged with the marker.
285    this class controls the motion the center of the BoxSum
[78ed1ad]286    """
[32c0841]287    def __init__(self, base, axes, color='black', zorder=5, center_x=0.0,
288                 center_y=0.0):
289        """
290        """
[78ed1ad]291        _BaseInteractor.__init__(self, base, axes, color=color)
[eba08f1a]292        ## Initialization the class
[78ed1ad]293        self.markers = []
294        self.axes = axes
[eba08f1a]295        # center coordinates
[2a3a890]296        self.x = center_x
297        self.y = center_y
[eba08f1a]298        ## saved value of the center coordinates
[2a3a890]299        self.save_x = center_x
300        self.save_y = center_y
[eba08f1a]301        ## Create a marker
[2a3a890]302        try:
303            self.center_marker = self.axes.plot([self.x],[self.y], linestyle='',
304                                          marker='s', markersize=10,
305                                          color=self.color, alpha=0.6,
306                                          pickradius=5, label="pick", 
[32c0841]307                                          # Prefer this to other lines
308                                          zorder=zorder, 
[2a3a890]309                                          visible=True)[0]
310        except:
311            self.center_marker = self.axes.plot([self.x],[self.y], linestyle='',
312                                          marker='s', markersize=10,
313                                          color=self.color, alpha=0.6,
314                                          label="pick", 
315                                          visible=True)[0]
[32c0841]316            message  = "\nTHIS PROTOTYPE NEEDS THE LATEST VERSION"
317            message += " OF MATPLOTLIB.\n Get the SVN version that is "
318            message += "at least as recent as June 1, 2007"
319            owner = self.base.base.parent
320            wx.PostEvent(owner,
321                         StatusEvent(status="AnnulusSlicer: %s" % message))
[eba08f1a]322        ## Draw a point
[32c0841]323        self.center = self.axes.plot([self.x], [self.y],
[78ed1ad]324                                      linestyle='-', marker='',
325                                      color=self.color,
326                                      visible=True)[0]
[eba08f1a]327        ## Flag to determine the motion this point
[32c0841]328        self.has_move = False   
[eba08f1a]329        ## connecting the marker to allow them to move
[2a3a890]330        self.connect_markers([self.center_marker])
[eba08f1a]331        ## Update the figure
[78ed1ad]332        self.update()
[54cc36a]333   
[78ed1ad]334    def set_layer(self, n):
[eba08f1a]335        """
336            Allow adding plot to the same panel
337            @param n: the number of layer
338        """
[78ed1ad]339        self.layernum = n
340        self.update()
341       
342    def clear(self):
[eba08f1a]343        """
344            Clear this figure and its markers
345        """
[78ed1ad]346        self.clear_markers()
347        try:
[2a3a890]348            self.center.remove()
[54cc36a]349            self.center_marker.remove()
[78ed1ad]350        except:
351            # Old version of matplotlib
352            for item in range(len(self.axes.lines)):
353                del self.axes.lines[0]
[eba08f1a]354 
[2a3a890]355    def update(self, center_x=None,center_y=None):
[78ed1ad]356        """
[eba08f1a]357            Draw the new roughness on the graph.
[78ed1ad]358        """
[32c0841]359        if center_x != None:
360            self.x = center_x
361        if center_y != None:
362            self.y = center_y
[2a3a890]363        self.center_marker.set(xdata=[self.x], ydata=[self.y])
364        self.center.set(xdata=[self.x], ydata=[self.y])
365       
[78ed1ad]366    def save(self, ev):
367        """
368        Remember the roughness for this layer and the next so that we
369        can restore on Esc.
370        """
[32c0841]371        self.save_x = self.x
372        self.save_y = self.y
[78ed1ad]373        self.base.freeze_axes()
374       
[32c0841]375    def moveend(self, ev):
376        """
377        """
[78ed1ad]378        self.has_move=False
379        self.base.moveend(ev)
380           
381    def restore(self):
382        """
383        Restore the roughness for this layer.
384        """
[32c0841]385        self.y = self.save_y
386        self.x = self.save_x
387   
[78ed1ad]388    def move(self, x, y, ev):
389        """
390        Process move to a new position, making sure that the move is allowed.
391        """
[32c0841]392        self.x = x
393        self.y = y
394        self.has_move = True
[78ed1ad]395        self.base.base.update()
396       
397    def set_cursor(self, x, y):
[32c0841]398        """
399        """
[78ed1ad]400        self.move(x, y, None)
401        self.update()
402       
[eba08f1a]403class VerticalDoubleLine(_BaseInteractor):
[78ed1ad]404    """
[eba08f1a]405         Draw 2 vertical lines moving in opposite direction and centered on
406         a point (PointInteractor)
[78ed1ad]407    """
[32c0841]408    def __init__(self, base, axes, color='black', zorder=5, x=0.5,y=0.5,
409                 center_x=0.0, center_y=0.0):
410        """
411        """
[78ed1ad]412        _BaseInteractor.__init__(self, base, axes, color=color)
[eba08f1a]413        ## Initialization the class
[78ed1ad]414        self.markers = []
415        self.axes = axes
[eba08f1a]416        ## Center coordinates
[2a3a890]417        self.center_x = center_x
418        self.center_y = center_y
[eba08f1a]419        ## defined end points vertical lignes and their saved values
[32c0841]420        self.y1 = y + self.center_y
[2a3a890]421        self.save_y1= self.y1
422       
[32c0841]423        delta = self.y1 - self.center_y
424        self.y2 = self.center_y - delta
425        self.save_y2 = self.y2
[2a3a890]426       
[32c0841]427        self.x1 = x + self.center_x
[2a3a890]428        self.save_x1 = self.x1
429         
[32c0841]430        delta = self.x1 - self.center_x
431        self.x2 = self.center_x - delta
[2a3a890]432        self.save_x2 = self.x2
[eba08f1a]433        ## save the color of the line
434        self.color = color
435        ## the height of the rectangle
[32c0841]436        self.half_height = math.fabs(y)
437        self.save_half_height = math.fabs(y)
[eba08f1a]438        ## the with of the rectangle
[32c0841]439        self.half_width = math.fabs(self.x1- self.x2)/2
440        self.save_half_width = math.fabs(self.x1- self.x2)/2
[eba08f1a]441        ## Create marker
[2a3a890]442        try:
443            self.right_marker = self.axes.plot([self.x1],[0], linestyle='',
444                                          marker='s', markersize=10,
445                                          color=self.color, alpha=0.6,
446                                          pickradius=5, label="pick", 
[32c0841]447                                          # Prefer this to other lines
448                                          zorder=zorder, visible=True)[0]
[2a3a890]449        except:
450            self.right_marker = self.axes.plot([self.x1],[0], linestyle='',
451                                          marker='s', markersize=10,
452                                          color=self.color, alpha=0.6,
[32c0841]453                                          label="pick", visible=True)[0]
454            message  = "\nTHIS PROTOTYPE NEEDS THE LATEST "
455            message += "VERSION OF MATPLOTLIB\n Get the SVN version that"
456            message += " is at least as recent as June 1, 2007"
457            owner = self.base.base.parent
458            wx.PostEvent(owner,
459                         StatusEvent(status="AnnulusSlicer: %s" % message))
[2a3a890]460           
[eba08f1a]461        ## define the left and right lines of the rectangle
[32c0841]462        self.right_line = self.axes.plot([self.x1, self.x1], [self.y1, self.y2],
[78ed1ad]463                                      linestyle='-', marker='',
[32c0841]464                                      color=self.color, visible=True)[0]
465        self.left_line = self.axes.plot([self.x2, self.x2], [self.y1, self.y2],
[2a3a890]466                                      linestyle='-', marker='',
[32c0841]467                                      color=self.color, visible=True)[0]
[eba08f1a]468        ## Flag to determine if the lines have moved
[32c0841]469        self.has_move = False 
[eba08f1a]470        ## connection the marker and draw the pictures 
[2a3a890]471        self.connect_markers([self.right_marker])
[78ed1ad]472        self.update()
473
474    def set_layer(self, n):
[eba08f1a]475        """
[32c0841]476        Allow adding plot to the same panel
477        :param n: the number of layer
[eba08f1a]478        """
[78ed1ad]479        self.layernum = n
480        self.update()
481       
482    def clear(self):
[eba08f1a]483        """
[32c0841]484        Clear this slicer  and its markers
[eba08f1a]485        """
[78ed1ad]486        self.clear_markers()
487        try:
[54cc36a]488            self.right_marker.remove()
[2a3a890]489            self.right_line.remove()
490            self.left_line.remove()
[78ed1ad]491        except:
492            # Old version of matplotlib
493            for item in range(len(self.axes.lines)):
494                del self.axes.lines[0]
[eba08f1a]495   
[32c0841]496    def update(self, x1=None, x2=None, y1=None, y2=None,width=None,
497                height=None, center=None):
498        """
499        Draw the new roughness on the graph.
500        :param x1: new maximum value of x coordinates
501        :param x2: new minimum value of x coordinates
502        :param y1: new maximum value of y coordinates
503        :param y2: new minimum value of y coordinates
504        :param width: is the width of the new rectangle
505        :param height: is the height of the new rectangle
506        :param center: provided x, y  coordinates of the center point
[78ed1ad]507        """
[eba08f1a]508        ## save the new height, witdh of the rectangle if given as a param
[32c0841]509        if width != None:
510            self.half_width = width
511        if height != None:
512            self.half_height = height
[eba08f1a]513        ## If new  center coordinates are given draw the rectangle
514        ##given these value
[32c0841]515        if center != None:
516            self.center_x = center.x
517            self.center_y = center.y
[2a3a890]518            self.x1 = self.half_width + self.center_x
519            self.x2= -self.half_width + self.center_x
520            self.y1 = self.half_height + self.center_y
521            self.y2= -self.half_height + self.center_y
522         
[32c0841]523            self.right_marker.set(xdata=[self.x1], ydata=[self.center_y])
524            self.right_line.set(xdata=[self.x1, self.x1], 
525                                ydata=[self.y1, self.y2])
526            self.left_line.set(xdata=[self.x2, self.x2],
527                               ydata=[self.y1, self.y2])
[2a3a890]528            return 
[eba08f1a]529        ## if x1, y1, y2, y3 are given draw the rectangle with this value
[32c0841]530        if x1 != None: 
531            self.x1 = x1
532        if x2 != None: 
533            self.x2 = x2
534        if y1 != None: 
535            self.y1 = y1
536        if y2 != None: 
537            self.y2 = y2
[eba08f1a]538        ## Draw 2 vertical lines and a marker
[32c0841]539        self.right_marker.set(xdata=[self.x1], ydata=[self.center_y])
540        self.right_line.set(xdata=[self.x1, self.x1], ydata=[self.y1, self.y2])
541        self.left_line.set(xdata=[self.x2, self.x2], ydata=[self.y1, self.y2])
[78ed1ad]542       
543    def save(self, ev):
544        """
545        Remember the roughness for this layer and the next so that we
546        can restore on Esc.
547        """
[32c0841]548        self.save_x2 = self.x2
549        self.save_y2 = self.y2
550        self.save_x1 = self.x1
551        self.save_y1 = self.y1
552        self.save_half_height = self.half_height
[ee69839]553        self.save_half_width = self.half_width
[78ed1ad]554        self.base.freeze_axes()
555
556    def moveend(self, ev):
[eba08f1a]557        """
558            After a dragging motion reset the flag self.has_move to False
559        """
[32c0841]560        self.has_move = False
[78ed1ad]561        self.base.moveend(ev)
562           
563    def restore(self):
564        """
565        Restore the roughness for this layer.
566        """
[32c0841]567        self.y2 = self.save_y2
568        self.x2 = self.save_x2
569        self.y1 = self.save_y1
570        self.x1 = self.save_x1
571        self.half_height = self.save_half_height
572        self.half_width = self.save_half_width
[eba08f1a]573       
[78ed1ad]574    def move(self, x, y, ev):
575        """
576        Process move to a new position, making sure that the move is allowed.
577        """
[32c0841]578        self.x1 = x
579        delta = self.x1 - self.center_x
580        self.x2 = self.center_x - delta
581        self.half_width = math.fabs(self.x1 - self.x2)/2
582        self.has_move = True
[78ed1ad]583        self.base.base.update()
584       
585    def set_cursor(self, x, y):
[eba08f1a]586        """
587            Update the figure given x and y
588        """
[78ed1ad]589        self.move(x, y, None)
590        self.update()
591       
[eba08f1a]592class HorizontalDoubleLine(_BaseInteractor):
[2a3a890]593    """
594         Select an annulus through a 2D plot
595    """
[32c0841]596    def __init__(self, base, axes, color='black', zorder=5, x=0.5, y=0.5,
597                 center_x=0.0, center_y=0.0):
[2a3a890]598       
599        _BaseInteractor.__init__(self, base, axes, color=color)
[eba08f1a]600        ## Initialization the class
[2a3a890]601        self.markers = []
602        self.axes = axes
[eba08f1a]603        ## Center coordinates
[2a3a890]604        self.center_x = center_x
605        self.center_y = center_y
[32c0841]606        self.y1 = y + self.center_y
607        self.save_y1 = self.y1
608        delta = self.y1 - self.center_y
609        self.y2 = self.center_y - delta
610        self.save_y2 = self.y2
611        self.x1 = x + self.center_x
[2a3a890]612        self.save_x1 = self.x1
[32c0841]613        delta = self.x1 - self.center_x
614        self.x2 = self.center_x - delta
[2a3a890]615        self.save_x2 = self.x2
[32c0841]616        self.color = color
[2a3a890]617        self.half_height= math.fabs(y)
[32c0841]618        self.save_half_height = math.fabs(y)
619        self.half_width = math.fabs(x)
620        self.save_half_width = math.fabs(x)
[2a3a890]621        try:
[32c0841]622            self.top_marker = self.axes.plot([0], [self.y1], linestyle='',
[2a3a890]623                                          marker='s', markersize=10,
624                                          color=self.color, alpha=0.6,
[32c0841]625                                          pickradius=5, label="pick",
626                                          # Prefer this to other lines
627                                          zorder=zorder, visible=True)[0]
[2a3a890]628        except:
[32c0841]629            self.top_marker = self.axes.plot([0], [self.y1], linestyle='',
[2a3a890]630                                          marker='s', markersize=10,
631                                          color=self.color, alpha=0.6,
[32c0841]632                                          label="pick", visible=True)[0]
633            message  = "\nTHIS PROTOTYPE NEEDS THE LATEST VERSION "
634            message += "OF MATPLOTLIB\n Get the SVN version "
635            message += "that is at least as recent as June 1, 2007"
636            owner = self.base.base.parent
637            wx.PostEvent(owner,
638                         StatusEvent(status="AnnulusSlicer: %s" % message))
[2a3a890]639           
[eba08f1a]640        # Define 2 horizotnal lines
[32c0841]641        self.top_line = self.axes.plot([self.x1, -self.x1], [self.y1, self.y1],
[2a3a890]642                                      linestyle='-', marker='',
[32c0841]643                                      color=self.color, visible=True)[0]
644        self.bottom_line = self.axes.plot([self.x1, -self.x1], 
645                                          [self.y2, self.y2],
[2a3a890]646                                      linestyle='-', marker='',
[32c0841]647                                      color=self.color, visible=True)[0]
[eba08f1a]648        ## Flag to determine if the lines have moved
[32c0841]649        self.has_move = False   
[eba08f1a]650        ## connection the marker and draw the pictures
[2a3a890]651        self.connect_markers([self.top_marker])
652        self.update()
653
654    def set_layer(self, n):
[eba08f1a]655        """
656            Allow adding plot to the same panel
657            @param n: the number of layer
658        """
[2a3a890]659        self.layernum = n
660        self.update()
661       
662    def clear(self):
[eba08f1a]663        """
664            Clear this figure and its markers
665        """
[2a3a890]666        self.clear_markers()
667        try:
[54cc36a]668            self.top_marker.remove()
[2a3a890]669            self.bottom_line.remove()
670            self.top_line.remove()
671        except:
672            # Old version of matplotlib
673            for item in range(len(self.axes.lines)):
674                del self.axes.lines[0]
[eba08f1a]675   
[32c0841]676    def update(self, x1=None, x2=None, y1=None, y2=None,
677               width=None, height=None, center=None):
678        """
679        Draw the new roughness on the graph.
680        :param x1: new maximum value of x coordinates
681        :param x2: new minimum value of x coordinates
682        :param y1: new maximum value of y coordinates
683        :param y2: new minimum value of y coordinates
684        :param width: is the width of the new rectangle
685        :param height: is the height of the new rectangle
686        :param center: provided x, y  coordinates of the center point
[eba08f1a]687        """
688        ## save the new height, witdh of the rectangle if given as a param
689        if width != None:
690            self.half_width = width
691        if height!= None:
[32c0841]692            self.half_height = height
[eba08f1a]693        ## If new  center coordinates are given draw the rectangle
694        ##given these value
[32c0841]695        if center != None:
696            self.center_x = center.x
697            self.center_y = center.y
[2a3a890]698            self.x1 = self.half_width + self.center_x
[32c0841]699            self.x2 = -self.half_width + self.center_x
[2a3a890]700           
701            self.y1 = self.half_height + self.center_y
[32c0841]702            self.y2 = -self.half_height + self.center_y
[2a3a890]703           
[32c0841]704            self.top_marker.set(xdata=[self.center_x], ydata=[self.y1])
705            self.top_line.set(xdata=[self.x1, self.x2],
706                              ydata=[self.y1, self.y1])
707            self.bottom_line.set(xdata=[self.x1, self.x2],
708                                 ydata=[self.y2, self.y2])
[2a3a890]709            return 
[eba08f1a]710        ## if x1, y1, y2, y3 are given draw the rectangle with this value
[32c0841]711        if x1 != None: 
712            self.x1 = x1
713        if x2 != None: 
714            self.x2 = x2
715        if y1 != None: 
716            self.y1 = y1
717        if y2 != None: 
718            self.y2 = y2
[eba08f1a]719        ## Draw 2 vertical lines and a marker
[32c0841]720        self.top_marker.set(xdata=[self.center_x], ydata=[self.y1])
721        self.top_line.set(xdata=[self.x1, self.x2], ydata=[self.y1, self.y1])
722        self.bottom_line.set(xdata=[self.x1, self.x2], ydata=[self.y2, self.y2])
[2a3a890]723       
724    def save(self, ev):
725        """
726        Remember the roughness for this layer and the next so that we
727        can restore on Esc.
728        """
[32c0841]729        self.save_x2 = self.x2
730        self.save_y2 = self.y2
731        self.save_x1 = self.x1
732        self.save_y1 = self.y1
733        self.save_half_height = self.half_height
[2a3a890]734        self.save_half_width =  self.half_width
735        self.base.freeze_axes()
[32c0841]736       
[2a3a890]737    def moveend(self, ev):
[eba08f1a]738        """
[32c0841]739        After a dragging motion reset the flag self.has_move to False
[eba08f1a]740        """
[32c0841]741        self.has_move = False
[2a3a890]742        self.base.moveend(ev)
[eba08f1a]743           
[2a3a890]744    def restore(self):
745        """
746        Restore the roughness for this layer.
747        """
[32c0841]748        self.y2 = self.save_y2
749        self.x2 = self.save_x2
750        self.y1 = self.save_y1
751        self.x1 = self.save_x1
752        self.half_height = self.save_half_height
753        self.half_width = self.save_half_width
[eba08f1a]754       
[2a3a890]755    def move(self, x, y, ev):
756        """
757        Process move to a new position, making sure that the move is allowed.
758        """
[32c0841]759        self.y1 = y
760        delta = self.y1 - self.center_y
761        self.y2 =  self.center_y - delta
762        self.half_height = math.fabs(self.y1) - self.center_y
763        self.has_move = True
[2a3a890]764        self.base.base.update()
[32c0841]765   
[2a3a890]766    def set_cursor(self, x, y):
[eba08f1a]767        """
768            Update the figure given x and y
769        """
[2a3a890]770        self.move(x, y, None)
771        self.update()
[78ed1ad]772         
Note: See TracBrowser for help on using the repository browser.