source: sasview/guiframe/local_perspectives/plotting/boxSlicer.py @ 1a6ec25

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 1a6ec25 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
Line 
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
10#from config import printEVT
11from BaseInteractor import _BaseInteractor
12from copy import deepcopy
13import math, numpy
14
15from sans.guicomm.events import NewPlotEvent, StatusEvent,SlicerParameterEvent,EVT_SLICER_PARS
16import SlicerParameters
17import wx
18
19
20class BoxInteractor(_BaseInteractor):
21    """
22         Select an annulus through a 2D plot
23    """
24    def __init__(self,base,axes,color='black', zorder=3):
25        _BaseInteractor.__init__(self, base, axes, color=color)
26       
27        self.markers = []
28        self.axes = axes
29       
30        self.connect = self.base.connect
31       
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))       
34       
35        self.qmax = max(self.base.data2D.xmax,self.base.data2D.xmin,
36                        self.base.data2D.ymax,self.base.data2D.ymin )   
37       
38        ## Number of points on the plot
39        self.nbins = 30
40        self.count=0
41        self.error=0
42        self.averager=None
43       
44        self.vertical_lines = VerticalLines(self, self.base.subplot,color='blue', 
45                                      zorder=zorder,
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', 
51                                      zorder=zorder,
52                                      x= self.x,
53                                      y= self.y)
54        self.horizontal_lines.qmax= self.qmax
55       
56     
57       
58        self.update()
59        self._post_data()
60       
61        # Bind to slice parameter events
62        self.base.Bind(EVT_SLICER_PARS, self._onEVT_SLICER_PARS)
63
64
65    def _onEVT_SLICER_PARS(self, event):
66        wx.PostEvent(self.base.parent, StatusEvent(status="BoxSlicer._onEVT_SLICER_PARS"))
67        event.Skip()
68        if event.type == self.__class__.__name__:
69            self.set_params(event.params)
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):
91        self.averager=None
92        self.clear_markers()
93        self.horizontal_lines.clear()
94        self.vertical_lines.clear()
95        self.base.connect.clearall()
96       
97        self.base.Unbind(EVT_SLICER_PARS)
98       
99    def update(self):
100        """
101        Respond to changes in the model by recalculating the profiles and
102        resetting the widgets.
103        """
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)
112           
113               
114           
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()
121        self.vertical_lines.save(ev)
122        self.horizontal_lines.save(ev)
123   
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"""
130        x_min= -1*math.fabs(self.vertical_lines.x)
131        x_max= math.fabs(self.vertical_lines.x)
132       
133        y_min= -1*math.fabs(self.horizontal_lines.y)
134        y_max= math.fabs(self.horizontal_lines.y)
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       
163
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__) ))
175   
176             
177                                       
178    def moveend(self, ev):
179        self.base.thaw_axes()
180       
181        # Post paramters
182        event = SlicerParameterEvent()
183        event.type = self.__class__.__name__
184        event.params = self.get_params()
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        """
193        self.horizontal_lines.restore()
194        self.vertical_lines.restore()
195       
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 = {}
208        params["x_max"]= math.fabs(self.vertical_lines.x)
209        params["y_max"]= math.fabs(self.horizontal_lines.y)
210        params["nbins"]= self.nbins
211     
212        return params
213   
214    def set_params(self, params):
215       
216        self.x = float(math.fabs(params["x_max"]))
217        self.y = float(math.fabs(params["y_max"] ))
218        self.nbins=params["nbins"]
219       
220        self.horizontal_lines.update(x= self.x, y=  self.y)
221        self.vertical_lines.update(x= self.x, y=  self.y)
222        self.post_data( nbins=None)
223       
224       
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
234class HorizontalLines(_BaseInteractor):
235    """
236         Select an annulus through a 2D plot
237    """
238    def __init__(self,base,axes,color='black', zorder=5,x=0.5, y=0.5):
239       
240        _BaseInteractor.__init__(self, base, axes, color=color)
241        self.markers = []
242        self.axes = axes
243        self.x= x
244        self.save_x= x
245       
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],
273                                      linestyle='-', marker='',
274                                      color=self.color,
275                                      visible=True)[0]
276       
277        self.has_move=False
278        self.connect_markers([self.top_line, self.inner_marker])
279        self.update()
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:
288            self.inner_marker.remove()
289            self.top_line.remove() 
290            self.bottom_line.remove()
291        except:
292            # Old version of matplotlib
293            for item in range(len(self.axes.lines)):
294                del self.axes.lines[0]
295   
296   
297    def update(self,x=None,y=None):
298        """
299        Draw the new roughness on the graph.
300        """
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])
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        """
318        self.save_x= self.x
319        self.save_y= self.y
320       
321        self.base.freeze_axes()
322
323    def moveend(self, ev):
324       
325        self.has_move=False
326        self.base.moveend(ev)
327           
328    def restore(self):
329        """
330        Restore the roughness for this layer.
331        """
332        self.x = self.save_x
333        self.y = self.save_y
334       
335
336    def move(self, x, y, ev):
337        """
338        Process move to a new position, making sure that the move is allowed.
339        """
340        #print "horizontal move x y "
341        self.y= y
342        self.has_move=True
343        self.base.base.update()
344       
345 
346       
347 
348   
349class VerticalLines(_BaseInteractor):
350    """
351         Select an annulus through a 2D plot
352    """
353    def __init__(self,base,axes,color='black',zorder=5,x=0.5, y=0.5):
354       
355        _BaseInteractor.__init__(self, base, axes, color=color)
356        self.markers = []
357        self.axes = axes
358       
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],
386                                      linestyle='-', marker='',
387                                      color=self.color,
388                                      visible=True)[0]
389     
390        self.has_move=False
391        self.connect_markers([self.right_line, self.inner_marker])
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:
401            self.inner_marker.remove()
402            self.left_line.remove()
403            self.right_line.remove()
404        except:
405            # Old version of matplotlib
406            for item in range(len(self.axes.lines)):
407                del self.axes.lines[0]
408
409    def update(self,x=None,y=None):
410        """
411        Draw the new roughness on the graph.
412        """
413
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]) 
424   
425       
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        """
431        self.save_x= self.x
432        self.save_y= self.y
433       
434        self.base.freeze_axes()
435
436    def moveend(self, ev):
437       
438        self.has_move=False
439        self.base.moveend(ev)
440           
441    def restore(self):
442        """
443        Restore the roughness for this layer.
444        """
445        self.x = self.save_x
446        self.y = self.save_y
447     
448       
449    def move(self, x, y, ev):
450        """
451        Process move to a new position, making sure that the move is allowed.
452        """
453        self.has_move=True
454        self.x= x
455        self.base.base.update()
456       
457   
458       
459
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       
479       
Note: See TracBrowser for help on using the repository browser.