source: sasview/guiframe/local_perspectives/plotting/boxSlicer.py @ 3e852ef5

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 3e852ef5 was 18eba35, checked in by Gervaise Alina <gervyh@…>, 16 years ago

small bugs fixed: clearing slicer improved

  • Property mode set to 100644
File size: 15.7 KB
RevLine 
[2d107b8]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
9# Debug printout
[38224f10]10#from config import printEVT
[2d107b8]11from BaseInteractor import _BaseInteractor
12from copy import deepcopy
[18eba35]13import math, numpy
[2d107b8]14
[0d9dae8]15from sans.guicomm.events import NewPlotEvent, StatusEvent,SlicerParameterEvent,EVT_SLICER_PARS
[2d107b8]16import SlicerParameters
17import wx
18
[0f6d05f8]19
[38224f10]20class BoxInteractor(_BaseInteractor):
[2d107b8]21    """
22         Select an annulus through a 2D plot
23    """
[18eba35]24    def __init__(self,base,axes,color='black', zorder=3):
[2d107b8]25        _BaseInteractor.__init__(self, base, axes, color=color)
[18eba35]26       
[2d107b8]27        self.markers = []
28        self.axes = axes
[18eba35]29       
[2d107b8]30        self.connect = self.base.connect
[18eba35]31       
[3b909b7]32        self.x= 0.5*min(math.fabs(self.base.data2D.xmax),math.fabs( self.base.data2D.xmin))
33        self.y= 0.5*min(math.fabs(self.base.data2D.xmax),math.fabs( self.base.data2D.xmin))       
[18eba35]34       
35        self.qmax = max(self.base.data2D.xmax,self.base.data2D.xmin,
36                        self.base.data2D.ymax,self.base.data2D.ymin )   
37       
[2d107b8]38        ## Number of points on the plot
[ffd23b5]39        self.nbins = 30
[38224f10]40        self.count=0
41        self.error=0
[ffd23b5]42        self.averager=None
[dd40217]43       
[18eba35]44        self.vertical_lines = VerticalLines(self, self.base.subplot,color='blue', 
[dd40217]45                                      zorder=zorder,
[18eba35]46                                        y= self.y ,
47                                        x= self.x)
48        self.vertical_lines.qmax = self.qmax
49       
50        self.horizontal_lines= HorizontalLines(self, self.base.subplot,color='green', 
[dd40217]51                                      zorder=zorder,
[18eba35]52                                      x= self.x,
53                                      y= self.y)
54        self.horizontal_lines.qmax= self.qmax
[dd40217]55       
[18eba35]56     
[dd40217]57       
[38224f10]58        self.update()
[0f6d05f8]59        self._post_data()
[2d107b8]60       
61        # Bind to slice parameter events
[18eba35]62        self.base.Bind(EVT_SLICER_PARS, self._onEVT_SLICER_PARS)
[2d107b8]63
64
65    def _onEVT_SLICER_PARS(self, event):
[18eba35]66        wx.PostEvent(self.base.parent, StatusEvent(status="BoxSlicer._onEVT_SLICER_PARS"))
[2d107b8]67        event.Skip()
68        if event.type == self.__class__.__name__:
[0f6d05f8]69            self.set_params(event.params)
[2d107b8]70            self.base.update()
71
72    def update_and_post(self):
73        self.update()
74        self._post_data()
75
76    def save_data(self, path, image, x, y):
77        output = open(path, 'w')
78       
79        data_x, data_y = self.get_data(image, x, y)
80       
81        output.write("<phi>  <average>\n")
82        for i in range(len(data_x)):
83            output.write("%g  %g\n" % (data_x[i], data_y[i]))
84        output.close()
85
86    def set_layer(self, n):
87        self.layernum = n
88        self.update()
89       
90    def clear(self):
[ffd23b5]91        self.averager=None
[2d107b8]92        self.clear_markers()
[18eba35]93        self.horizontal_lines.clear()
94        self.vertical_lines.clear()
95        self.base.connect.clearall()
96       
97        self.base.Unbind(EVT_SLICER_PARS)
[2d107b8]98       
99    def update(self):
100        """
101        Respond to changes in the model by recalculating the profiles and
102        resetting the widgets.
103        """
[18eba35]104        if self.horizontal_lines.has_move:
105            #print "top has moved"
106            self.horizontal_lines.update()
107            self.vertical_lines.update(y=self.horizontal_lines.y)
108        if self.vertical_lines.has_move:
109            #print "right has moved"
110            self.vertical_lines.update()
111            self.horizontal_lines.update(x=self.vertical_lines.x)
[dd40217]112           
113               
[0f6d05f8]114           
[2d107b8]115    def save(self, ev):
116        """
117        Remember the roughness for this layer and the next so that we
118        can restore on Esc.
119        """
120        self.base.freeze_axes()
[18eba35]121        self.vertical_lines.save(ev)
122        self.horizontal_lines.save(ev)
123   
[ffd23b5]124    def _post_data(self):
125        pass
126       
127   
128    def post_data(self,new_slab=None , nbins=None):
129        """ post data averaging in Q"""
[18eba35]130        x_min= -1*math.fabs(self.vertical_lines.x)
131        x_max= math.fabs(self.vertical_lines.x)
[ffd23b5]132       
[18eba35]133        y_min= -1*math.fabs(self.horizontal_lines.y)
134        y_max= math.fabs(self.horizontal_lines.y)
[ffd23b5]135       
136        if nbins !=None:
137            self.nbins
138        if self.averager==None:
139            if new_slab ==None:
140                raise ValueError,"post data:cannot average , averager is empty"
141            self.averager= new_slab
142        bin_width= (x_max + math.fabs(x_min))/self.nbins
143       
144        box = self.averager( x_min=x_min, x_max=x_max, y_min=y_min, y_max=y_max,
145                         bin_width=bin_width)
146       
147        boxavg = box(self.base.data2D)
148       
149        from sans.guiframe.dataFitting import Data1D
150        if hasattr(boxavg,"dxl"):
151            dxl= boxavg.dxl
152        else:
153            dxl= None
154        if hasattr(boxavg,"dxw"):
155            dxw=boxavg.dxw
156        else:
157            dxw= None
158       
159        new_plot = Data1D(x=boxavg.x,y=boxavg.y,dy=boxavg.dy,dxl=dxl,dxw=dxw)
160        new_plot.name = str(self.averager.__name__) +"("+ self.base.data2D.name+")"
161       
162       
[2d107b8]163
[ffd23b5]164        new_plot.source=self.base.data2D.source
165        new_plot.interactive = True
166        #print "loader output.detector",output.source
167        new_plot.detector =self.base.data2D.detector
168        # If the data file does not tell us what the axes are, just assume...
169        new_plot.xaxis("\\rm{Q}", 'rad')
170        new_plot.yaxis("\\rm{Intensity} ","cm^{-1}")
171        new_plot.group_id = str(self.averager.__name__)+self.base.data2D.name
172        new_plot.id = str(self.averager.__name__)
173        wx.PostEvent(self.base.parent, NewPlotEvent(plot=new_plot,
174                                                 title=str(self.averager.__name__) ))
[18eba35]175   
[b319def8]176             
[38224f10]177                                       
[2d107b8]178    def moveend(self, ev):
179        self.base.thaw_axes()
180       
181        # Post paramters
[0d9dae8]182        event = SlicerParameterEvent()
[2d107b8]183        event.type = self.__class__.__name__
[0f6d05f8]184        event.params = self.get_params()
[2d107b8]185        wx.PostEvent(self.base.parent, event)
186
187        self._post_data()
188           
189    def restore(self):
190        """
191        Restore the roughness for this layer.
192        """
[18eba35]193        self.horizontal_lines.restore()
194        self.vertical_lines.restore()
195       
[2d107b8]196
197    def move(self, x, y, ev):
198        """
199        Process move to a new position, making sure that the move is allowed.
200        """
201        pass
202       
203    def set_cursor(self, x, y):
204        pass
205       
206    def get_params(self):
207        params = {}
[18eba35]208        params["x_max"]= math.fabs(self.vertical_lines.x)
209        params["y_max"]= math.fabs(self.horizontal_lines.y)
[ffd23b5]210        params["nbins"]= self.nbins
[18eba35]211     
[2d107b8]212        return params
213   
214    def set_params(self, params):
[aa1b747]215       
[0f6d05f8]216        self.x = float(math.fabs(params["x_max"]))
217        self.y = float(math.fabs(params["y_max"] ))
[ffd23b5]218        self.nbins=params["nbins"]
[18eba35]219       
220        self.horizontal_lines.update(x= self.x, y=  self.y)
221        self.vertical_lines.update(x= self.x, y=  self.y)
[ffd23b5]222        self.post_data( nbins=None)
[18eba35]223       
224       
[2d107b8]225    def freeze_axes(self):
226        self.base.freeze_axes()
227       
228    def thaw_axes(self):
229        self.base.thaw_axes()
230
231    def draw(self):
232        self.base.draw()
233
[18eba35]234class HorizontalLines(_BaseInteractor):
[2d107b8]235    """
236         Select an annulus through a 2D plot
237    """
[18eba35]238    def __init__(self,base,axes,color='black', zorder=5,x=0.5, y=0.5):
[2d107b8]239       
240        _BaseInteractor.__init__(self, base, axes, color=color)
241        self.markers = []
242        self.axes = axes
[18eba35]243        self.x= x
244        self.save_x= x
[3554b99a]245       
[18eba35]246        self.y= y
247        self.save_y= y
248       
249        try:
250            # Inner circle marker
251            self.inner_marker = self.axes.plot([0],[self.y], linestyle='',
252                                          marker='s', markersize=10,
253                                          color=self.color, alpha=0.6,
254                                          pickradius=5, label="pick", 
255                                          zorder=zorder, # Prefer this to other lines
256                                          visible=True)[0]
257        except:
258            self.inner_marker = self.axes.plot([0],[self.y], linestyle='',
259                                          marker='s', markersize=10,
260                                          color=self.color, alpha=0.6,
261                                          label="pick", 
262                                          visible=True)[0]
263            message  = "\nTHIS PROTOTYPE NEEDS THE LATEST VERSION OF MATPLOTLIB\n"
264            message += "Get the SVN version that is at least as recent as June 1, 2007"
265           
266        self.top_line = self.axes.plot([self.x,-self.x],
267                                   [self.y,self.y],
268                                      linestyle='-', marker='',
269                                      color=self.color,
270                                      visible=True)[0]
271        self.bottom_line = self.axes.plot([self.x,-self.x],
272                                   [-self.y,-self.y],
[2d107b8]273                                      linestyle='-', marker='',
274                                      color=self.color,
275                                      visible=True)[0]
[c73d871]276       
[2d107b8]277        self.has_move=False
[18eba35]278        self.connect_markers([self.top_line, self.inner_marker])
[3554b99a]279        self.update()
[2d107b8]280
281    def set_layer(self, n):
282        self.layernum = n
283        self.update()
284       
285    def clear(self):
286        self.clear_markers()
287        try:
[18eba35]288            self.inner_marker.remove()
289            self.top_line.remove() 
290            self.bottom_line.remove()
[2d107b8]291        except:
292            # Old version of matplotlib
293            for item in range(len(self.axes.lines)):
294                del self.axes.lines[0]
[030873e]295   
[8ff3ec1]296   
[18eba35]297    def update(self,x=None,y=None):
[2d107b8]298        """
299        Draw the new roughness on the graph.
300        """
[18eba35]301        if x!=None:
302            self.x = numpy.sign(self.x)*math.fabs(x)
303        if y !=None:
304            self.y = numpy.sign(self.y)*math.fabs(y)
305        self.inner_marker.set(xdata=[0],ydata=[self.y])
306       
307        self.top_line.set(xdata=[self.x,-self.x],
308                       ydata=[self.y,self.y])
309        self.bottom_line.set(xdata=[self.x,-self.x],
310                       ydata=[-self.y, -self.y])
[2d107b8]311       
312       
313    def save(self, ev):
314        """
315        Remember the roughness for this layer and the next so that we
316        can restore on Esc.
317        """
[18eba35]318        self.save_x= self.x
319        self.save_y= self.y
[3554b99a]320       
[2d107b8]321        self.base.freeze_axes()
322
323    def moveend(self, ev):
[030873e]324       
[2d107b8]325        self.has_move=False
326        self.base.moveend(ev)
327           
328    def restore(self):
329        """
330        Restore the roughness for this layer.
331        """
[18eba35]332        self.x = self.save_x
333        self.y = self.save_y
[0f6d05f8]334       
[2d107b8]335
336    def move(self, x, y, ev):
337        """
338        Process move to a new position, making sure that the move is allowed.
339        """
[d468daa]340        #print "horizontal move x y "
[18eba35]341        self.y= y
[2d107b8]342        self.has_move=True
343        self.base.base.update()
344       
[18eba35]345 
[2d107b8]346       
[18eba35]347 
[2d107b8]348   
[18eba35]349class VerticalLines(_BaseInteractor):
[2d107b8]350    """
351         Select an annulus through a 2D plot
352    """
[18eba35]353    def __init__(self,base,axes,color='black',zorder=5,x=0.5, y=0.5):
[2d107b8]354       
355        _BaseInteractor.__init__(self, base, axes, color=color)
356        self.markers = []
357        self.axes = axes
[030873e]358       
[18eba35]359        self.x= math.fabs(x)
360        self.save_x= self.x
361        self.y= math.fabs(y)
362        self.save_y= y
363       
364        try:
365            # Inner circle marker
366            self.inner_marker = self.axes.plot([self.x],[0], linestyle='',
367                                          marker='s', markersize=10,
368                                          color=self.color, alpha=0.6,
369                                          pickradius=5, label="pick", 
370                                          zorder=zorder, # Prefer this to other lines
371                                          visible=True)[0]
372        except:
373            self.inner_marker = self.axes.plot([self.x],[0], linestyle='',
374                                          marker='s', markersize=10,
375                                          color=self.color, alpha=0.6,
376                                          label="pick", 
377                                          visible=True)[0]
378            message  = "\nTHIS PROTOTYPE NEEDS THE LATEST VERSION OF MATPLOTLIB\n"
379            message += "Get the SVN version that is at least as recent as June 1, 2007"
380           
381        self.right_line = self.axes.plot([self.x,self.x],[self.y,-self.y],
382                                      linestyle='-', marker='',
383                                      color=self.color,
384                                      visible=True)[0]
385        self.left_line = self.axes.plot([-self.x,-self.x],[self.y,-self.y],
[2d107b8]386                                      linestyle='-', marker='',
387                                      color=self.color,
388                                      visible=True)[0]
389     
390        self.has_move=False
[18eba35]391        self.connect_markers([self.right_line, self.inner_marker])
[2d107b8]392        self.update()
393
394    def set_layer(self, n):
395        self.layernum = n
396        self.update()
397       
398    def clear(self):
399        self.clear_markers()
400        try:
[18eba35]401            self.inner_marker.remove()
402            self.left_line.remove()
403            self.right_line.remove()
[2d107b8]404        except:
405            # Old version of matplotlib
406            for item in range(len(self.axes.lines)):
407                del self.axes.lines[0]
[18eba35]408
409    def update(self,x=None,y=None):
[2d107b8]410        """
411        Draw the new roughness on the graph.
412        """
[0f6d05f8]413
[18eba35]414        if x!=None:
415            self.x = numpy.sign(self.x)*math.fabs(x)
416        if y !=None:
417            self.y = numpy.sign(self.y)*math.fabs(y)
418           
419        self.inner_marker.set(xdata=[self.x],ydata=[0]) 
420        self.left_line.set(xdata=[-self.x,-self.x],
421                       ydata=[self.y,-self.y]) 
422        self.right_line.set(xdata=[self.x,self.x],
423                       ydata=[self.y,-self.y]) 
[0f6d05f8]424   
[3554b99a]425       
[2d107b8]426    def save(self, ev):
427        """
428        Remember the roughness for this layer and the next so that we
429        can restore on Esc.
430        """
[18eba35]431        self.save_x= self.x
432        self.save_y= self.y
[8ff3ec1]433       
[2d107b8]434        self.base.freeze_axes()
435
436    def moveend(self, ev):
[030873e]437       
[2d107b8]438        self.has_move=False
439        self.base.moveend(ev)
440           
441    def restore(self):
442        """
443        Restore the roughness for this layer.
444        """
[18eba35]445        self.x = self.save_x
446        self.y = self.save_y
[3554b99a]447     
[78ed1ad]448       
[2d107b8]449    def move(self, x, y, ev):
450        """
451        Process move to a new position, making sure that the move is allowed.
452        """
[8ff3ec1]453        self.has_move=True
[18eba35]454        self.x= x
[8ff3ec1]455        self.base.base.update()
456       
[18eba35]457   
[2d107b8]458       
[8ff3ec1]459
[ffd23b5]460class BoxInteractorX(BoxInteractor):
461    def __init__(self,base,axes,color='black', zorder=3):
462        BoxInteractor.__init__(self, base, axes, color=color)
463        self.base=base
464        self._post_data()
465    def _post_data(self):
466        from DataLoader.manipulations import SlabX
467        self.post_data(SlabX )   
468       
469
470class BoxInteractorY(BoxInteractor):
471    def __init__(self,base,axes,color='black', zorder=3):
472        BoxInteractor.__init__(self, base, axes, color=color)
473        self.base=base
474        self._post_data()
475    def _post_data(self):
476        from DataLoader.manipulations import SlabY
477        self.post_data(SlabY )   
478       
[2d107b8]479       
Note: See TracBrowser for help on using the repository browser.