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

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 1ce365f8 was 3b909b7, checked in by Gervaise Alina <gervyh@…>, 16 years ago

allow annulus to plot no matter the order of the circle
boxslicer draw given data boundaries

  • Property mode set to 100644
File size: 18.3 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
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                  x_min=0.0025, x_max=0.0025, y_min=0.0025, y_max=0.0025):
26       
27        _BaseInteractor.__init__(self, base, axes, color=color)
28        self.markers = []
29        self.axes = axes
30        self.qmax = self.base.data2D.xmax
31        self.connect = self.base.connect
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.theta2= math.pi/3
36        ## Number of points on the plot
37        self.nbins = 30
38        self.count=0
39        self.error=0
40        self.averager=None
41        self.left_line = VerticalLine(self, self.base.subplot,color='blue', 
42                                      zorder=zorder,
43                                        ymin= -self.y , 
44                                        ymax= self.y ,
45                                        xmin= -self.x,
46                                        xmax= -self.x)
47        self.left_line.qmax = self.qmax
48       
49        self.right_line= VerticalLine(self, self.base.subplot,color='black', 
50                                      zorder=zorder,
51                                     ymin= -self.y , 
52                                     ymax= self.y,
53                                     xmin= self.x,
54                                     xmax= self.x)
55        self.right_line.qmax = self.qmax
56       
57        self.top_line= HorizontalLine(self, self.base.subplot,color='green', 
58                                      zorder=zorder,
59                                      xmin= -self.x,
60                                      xmax= self.x,
61                                      ymin= self.y,
62                                      ymax= self.y)
63        self.top_line.qmax= self.qmax
64       
65        self.bottom_line= HorizontalLine(self, self.base.subplot,color='gray', 
66                                      zorder=zorder,
67                                      xmin= -self.x,
68                                      xmax= self.x,
69                                      ymin= -self.y,
70                                      ymax= -self.y)
71        self.bottom_line.qmax= self.qmax
72       
73        self.update()
74        self._post_data()
75       
76        # Bind to slice parameter events
77        self.base.parent.Bind(EVT_SLICER_PARS, self._onEVT_SLICER_PARS)
78
79
80    def _onEVT_SLICER_PARS(self, event):
81        #printEVT("AnnulusSlicer._onEVT_SLICER_PARS")
82        event.Skip()
83        if event.type == self.__class__.__name__:
84            self.set_params(event.params)
85            self.base.update()
86
87    def update_and_post(self):
88        self.update()
89        self._post_data()
90
91    def save_data(self, path, image, x, y):
92        output = open(path, 'w')
93       
94        data_x, data_y = self.get_data(image, x, y)
95       
96        output.write("<phi>  <average>\n")
97        for i in range(len(data_x)):
98            output.write("%g  %g\n" % (data_x[i], data_y[i]))
99        output.close()
100
101    def set_layer(self, n):
102        self.layernum = n
103        self.update()
104       
105    def clear(self):
106        self.averager=None
107        self.clear_markers()
108        self.left_line.clear()
109        self.right_line.clear()
110        self.top_line.clear()
111        self.bottom_line.clear()
112        #self.base.connect.disconnect()
113        self.base.parent.Unbind(EVT_SLICER_PARS)
114       
115    def update(self):
116        """
117        Respond to changes in the model by recalculating the profiles and
118        resetting the widgets.
119        """
120       
121        if self.top_line.has_move:
122            #print"top has moved"
123            self.top_line.update()
124            self.bottom_line.update(ymin= -self.top_line.y1,
125                                    ymax= -self.top_line.y2)
126            self.left_line.update(ymin= -self.top_line.y1,
127                                    ymax= -self.top_line.y2)
128            self.right_line.update(ymin= -self.top_line.y1,
129                                    ymax= -self.top_line.y2)
130           
131        if self.bottom_line.has_move:
132            #print "bottom has move"
133            self.bottom_line.update()
134            self.top_line.update(ymin= -self.bottom_line.y1,
135                                    ymax= -self.bottom_line.y2)
136            self.left_line.update(ymin= self.bottom_line.y1,
137                                    ymax= self.top_line.y1)
138            self.right_line.update(ymin= self.bottom_line.y1,
139                                    ymax=self.top_line.y1)
140           
141        if self.left_line.has_move:
142           
143            self.left_line.update()
144            self.right_line.update(xmin = - self.left_line.x1,
145                                   xmax = - self.left_line.x1)
146            self.bottom_line.update(xmin=  self.left_line.x1,
147                                     xmax= self.right_line.x1)
148            self.top_line.update(xmin= self.left_line.x1,
149                                    xmax= self.right_line.x1)
150           
151        if self.right_line.has_move:
152           
153            self.right_line.update()
154            self.left_line.update(xmin = -self.right_line.x1,
155                                   xmax = -self.right_line.x1)
156           
157            self.bottom_line.update(xmin= self.left_line.x1,
158                                 xmax= self.right_line.x1)
159           
160            self.top_line.update(xmin= self.left_line.x1,
161                                    xmax= self.right_line.x1)
162               
163           
164    def save(self, ev):
165        """
166        Remember the roughness for this layer and the next so that we
167        can restore on Esc.
168        """
169        self.base.freeze_axes()
170        self.left_line.save(ev)
171        self.right_line.save(ev)
172        self.top_line.save(ev)
173        self.bottom_line.save(ev)
174    def _post_data(self):
175        pass
176       
177   
178    def post_data(self,new_slab=None , nbins=None):
179        """ post data averaging in Q"""
180        x_min= min(self.left_line.x1, self.right_line.x1)
181        x_max= max(self.left_line.x1, self.right_line.x1)
182       
183        y_min= min(self.top_line.y1, self.bottom_line.y1)
184        y_max= max(self.top_line.y1, self.bottom_line.y1) 
185       
186        if nbins !=None:
187            self.nbins
188        if self.averager==None:
189            if new_slab ==None:
190                raise ValueError,"post data:cannot average , averager is empty"
191            self.averager= new_slab
192        bin_width= (x_max + math.fabs(x_min))/self.nbins
193       
194        box = self.averager( x_min=x_min, x_max=x_max, y_min=y_min, y_max=y_max,
195                         bin_width=bin_width)
196       
197        boxavg = box(self.base.data2D)
198       
199        from sans.guiframe.dataFitting import Data1D
200        if hasattr(boxavg,"dxl"):
201            dxl= boxavg.dxl
202        else:
203            dxl= None
204        if hasattr(boxavg,"dxw"):
205            dxw=boxavg.dxw
206        else:
207            dxw= None
208       
209        new_plot = Data1D(x=boxavg.x,y=boxavg.y,dy=boxavg.dy,dxl=dxl,dxw=dxw)
210        new_plot.name = str(self.averager.__name__) +"("+ self.base.data2D.name+")"
211       
212       
213
214        new_plot.source=self.base.data2D.source
215        new_plot.interactive = True
216        #print "loader output.detector",output.source
217        new_plot.detector =self.base.data2D.detector
218        # If the data file does not tell us what the axes are, just assume...
219        new_plot.xaxis("\\rm{Q}", 'rad')
220        new_plot.yaxis("\\rm{Intensity} ","cm^{-1}")
221        new_plot.group_id = str(self.averager.__name__)+self.base.data2D.name
222        new_plot.id = str(self.averager.__name__)
223        wx.PostEvent(self.base.parent, NewPlotEvent(plot=new_plot,
224                                                 title=str(self.averager.__name__) ))
225       
226       
227    def _post_data(self):
228        # Compute data
229        data = self.base.data2D
230        from DataLoader.manipulations import  Boxavg
231        radius = math.sqrt(math.pow(self.qmax,2)+math.pow(self.qmax,2))
232        self.x= math.fabs(self.right_line.x1)
233        self.y= math.fabs(self.top_line.y1 )
234       
235        box =  Boxavg (x_min=-self.x, x_max=self.x, y_min=-self.y, y_max=self.y)
236       
237        self.count, self.error= box(self.base.data2D)
238       
239        #print "post data"
240             
241                                       
242    def moveend(self, ev):
243        self.base.thaw_axes()
244       
245        # Post paramters
246        event = SlicerParameterEvent()
247        event.type = self.__class__.__name__
248        event.params = self.get_params()
249        wx.PostEvent(self.base.parent, event)
250
251        self._post_data()
252           
253    def restore(self):
254        """
255        Restore the roughness for this layer.
256        """
257        self.left_line.restore()
258        self.right_line.restore()
259        self.top_line.restore()
260        self.bottom_line.restore()
261
262    def move(self, x, y, ev):
263        """
264        Process move to a new position, making sure that the move is allowed.
265        """
266        pass
267       
268    def set_cursor(self, x, y):
269        pass
270       
271    def get_params(self):
272        params = {}
273        params["x_max"]= math.fabs(self.right_line.x1)
274        params["y_max"]= math.fabs(self.top_line.y1)
275        params["nbins"]= self.nbins
276        params["errors"] = self.error
277        params["count"]= self.count
278        return params
279   
280    def set_params(self, params):
281       
282        self.x = float(math.fabs(params["x_max"]))
283        self.y = float(math.fabs(params["y_max"] ))
284        self.nbins=params["nbins"]
285        self.left_line.update(xmin= -1*self.x,
286                              xmax = -1*self.x,
287                              ymin= -self.y,
288                              ymax=  self.y, 
289                              )
290        self.right_line.update(xmin= self.x,
291                              xmax = self.x,
292                              ymin= -self.y,
293                              ymax=  self.y, 
294                              )
295        self.top_line.update(xmin= -1*self.x,
296                             xmax= self.x,
297                             ymin= self.y,
298                             ymax= self.y)
299        self.bottom_line.update(xmin= -1*self.x,
300                                 xmax= self.x,
301                                 ymin= -1*self.y,
302                                 ymax= -1*self.y)
303       
304        self.post_data( nbins=None)
305    def freeze_axes(self):
306        self.base.freeze_axes()
307       
308    def thaw_axes(self):
309        self.base.thaw_axes()
310
311    def draw(self):
312        self.base.draw()
313
314class HorizontalLine(_BaseInteractor):
315    """
316         Select an annulus through a 2D plot
317    """
318    def __init__(self,base,axes,color='black', zorder=5,mline=None,ymin=None, ymax=None, y=0.5,
319                 xmin=0.0,xmax=0.5):
320       
321        _BaseInteractor.__init__(self, base, axes, color=color)
322        self.markers = []
323        self.axes = axes
324        self.x1= xmax
325        self.save_x1= xmax
326       
327        self.x2= xmin
328        self.save_x2= xmin
329       
330        self.y1= ymax
331        self.save_y1= ymax
332       
333        self.y2= ymin
334        self.save_y2= ymin
335        self.mline= mline
336        self.line = self.axes.plot([self.x1,-self.x1],
337                                   [self.y1,self.y2],
338                                      linestyle='-', marker='',
339                                      color=self.color,
340                                      visible=True)[0]
341       
342        self.npts = 20
343        self.has_move=False
344        self.connect_markers([self.line])
345        self.update()
346
347    def set_layer(self, n):
348        self.layernum = n
349        self.update()
350       
351    def clear(self):
352        self.clear_markers()
353        try:
354           
355            self.line.remove()
356        except:
357            # Old version of matplotlib
358            for item in range(len(self.axes.lines)):
359                del self.axes.lines[0]
360   
361    def get_radius(self):
362       
363        return 0
364   
365    def update(self,xmin=None, xmax=None,ymin=None,ymax=None, mline=None,translation=False):
366        """
367        Draw the new roughness on the graph.
368        """
369        if xmin !=None:
370            self.x1 = xmin
371        if ymin !=None:
372            self.y1 = ymin
373        self.line.set(xdata=[self.x1,-self.x1],
374                       ydata=[self.y1,self.y1])
375   
376       
377       
378    def save(self, ev):
379        """
380        Remember the roughness for this layer and the next so that we
381        can restore on Esc.
382        """
383        self.save_x1= self.x1
384        self.save_x2= self.x2
385       
386        self.save_y1= self.y1
387        self.save_y2= self.y2
388   
389       
390        self.base.freeze_axes()
391
392    def moveend(self, ev):
393       
394        self.has_move=False
395        self.base.moveend(ev)
396           
397    def restore(self):
398        """
399        Restore the roughness for this layer.
400        """
401        self.x1 = self.save_x1
402        self.x2 = self.save_x2
403        self.y1 = self.save_y1
404        self.y2 = self.save_y2
405       
406
407    def move(self, x, y, ev):
408        """
409        Process move to a new position, making sure that the move is allowed.
410        """
411        #print "horizontal move x y "
412        self.y1= y
413        self.has_move=True
414        self.base.base.update()
415       
416    def set_cursor(self, x, y):
417        self.move(x, y, None)
418        self.update()
419       
420       
421    def get_params(self):
422        params = {}
423        params["radius"] = self.x1
424        #params["theta"] = self.xmax
425        return params
426   
427    def set_params(self, params):
428
429        x = params["radius"] 
430        self.set_cursor(x, self._inner_mouse_y)
431       
432
433
434
435class VerticalLine(_BaseInteractor):
436    """
437         Select an annulus through a 2D plot
438    """
439    def __init__(self,base,axes,color='black', zorder=5, mline=None, ymin=0.0, 
440                 ymax=0.5,xmin=-0.5,xmax=0.5
441                 ):
442       
443        _BaseInteractor.__init__(self, base, axes, color=color)
444        self.markers = []
445        self.axes = axes
446       
447        self.x1= xmax
448        self.x2= xmin
449        self.y1= ymax
450        self.y2= ymin
451        self.line = self.axes.plot([self.x1,self.x2],[self.y1,self.y2],
452                                      linestyle='-', marker='',
453                                      color=self.color,
454                                      visible=True)[0]
455     
456        self.has_move=False
457        self.connect_markers([self.line])
458        self.update()
459
460    def set_layer(self, n):
461        self.layernum = n
462        self.update()
463       
464    def clear(self):
465        self.clear_markers()
466        try:
467           
468            self.line.remove()
469        except:
470            # Old version of matplotlib
471            for item in range(len(self.axes.lines)):
472                del self.axes.lines[0]
473   
474   
475    def get_radius(self):
476        return 0
477   
478    def update(self,xmin=None,xmax=None,ymin=None, ymax=None, opline=None,translation=False):
479        """
480        Draw the new roughness on the graph.
481        """
482
483   
484        if xmin!=None:
485            self.x1=xmin
486        if ymin!=None:
487            self.y1=ymin
488        self.line.set(xdata=[self.x1,self.x1],
489                       ydata=[self.y1,-self.y1]) 
490       
491   
492       
493    def save(self, ev):
494        """
495        Remember the roughness for this layer and the next so that we
496        can restore on Esc.
497        """
498        self.save_x1= self.x1
499        self.save_x2= self.x2
500        self.save_y1= self.y1
501        self.save_y2= self.y2
502       
503        self.base.freeze_axes()
504
505    def moveend(self, ev):
506       
507        self.has_move=False
508        self.base.moveend(ev)
509           
510    def restore(self):
511        """
512        Restore the roughness for this layer.
513        """
514        self.x1 = self.save_x1
515        self.x2 = self.save_x2
516        self.y1 = self.save_y1
517        self.y2= self.save_y2
518     
519       
520    def move(self, x, y, ev):
521        """
522        Process move to a new position, making sure that the move is allowed.
523        """
524        self.has_move=True
525       
526        # compute the b intercept of the vertical line
527        self.x1= x
528       
529       
530        self.base.base.update()
531       
532       
533    def set_cursor(self, x, y):
534        self.move(x, y, None)
535        self.update()
536       
537       
538    def get_params(self):
539        params = {}
540        params["x"] = self.xmin
541        params["ymin"] = self.ymin
542        params["ymax"] = self.ymax
543        return params
544   
545    def set_params(self, params):
546        """
547            Draw a vertical line given some value of params
548            @param params: a dictionary containing value for x, ymin , ymax to draw
549            a vertical line
550        """
551        x = params["x"] 
552        ymin = params["ymin"] 
553        ymax = params["ymax"] 
554        #self.set_cursor(x, self._inner_mouse_y)
555        self.update(self,x =x,ymin =ymin, ymax =ymax)
556       
557
558class BoxInteractorX(BoxInteractor):
559    def __init__(self,base,axes,color='black', zorder=3):
560        BoxInteractor.__init__(self, base, axes, color=color)
561        self.base=base
562        self._post_data()
563    def _post_data(self):
564        from DataLoader.manipulations import SlabX
565        self.post_data(SlabX )   
566       
567
568class BoxInteractorY(BoxInteractor):
569    def __init__(self,base,axes,color='black', zorder=3):
570        BoxInteractor.__init__(self, base, axes, color=color)
571        self.base=base
572        self._post_data()
573    def _post_data(self):
574        from DataLoader.manipulations import SlabY
575        self.post_data(SlabY )   
576       
577       
Note: See TracBrowser for help on using the repository browser.