source: sasview/guiframe/local_perspectives/plotting/boxSlicer.py @ 54cc36a

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 54cc36a was ffd23b5, checked in by Gervaise Alina <gervyh@…>, 15 years ago
  • Property mode set to 100644
File size: 18.2 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
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= x_max
33        self.y= y_max
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(SlicerParameters.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(SlicerParameters.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.info=self.base.data2D.info
216        new_plot.interactive = True
217        #print "loader output.detector",output.source
218        new_plot.detector =self.base.data2D.detector
219        # If the data file does not tell us what the axes are, just assume...
220        new_plot.xaxis("\\rm{Q}", 'rad')
221        new_plot.yaxis("\\rm{Intensity} ","cm^{-1}")
222        new_plot.group_id = str(self.averager.__name__)+self.base.data2D.name
223        new_plot.id = str(self.averager.__name__)
224        wx.PostEvent(self.base.parent, NewPlotEvent(plot=new_plot,
225                                                 title=str(self.averager.__name__) ))
226       
227       
228    def _post_data(self):
229        # Compute data
230        data = self.base.data2D
231        from DataLoader.manipulations import  Boxavg
232        radius = math.sqrt(math.pow(self.qmax,2)+math.pow(self.qmax,2))
233        self.x= math.fabs(self.right_line.x1)
234        self.y= math.fabs(self.top_line.y1 )
235       
236        box =  Boxavg (x_min=-self.x, x_max=self.x, y_min=-self.y, y_max=self.y)
237       
238        self.count, self.error= box(self.base.data2D)
239       
240        #print "post data"
241             
242                                       
243    def moveend(self, ev):
244        self.base.thaw_axes()
245       
246        # Post paramters
247        event = SlicerParameters.SlicerParameterEvent()
248        event.type = self.__class__.__name__
249        event.params = self.get_params()
250        wx.PostEvent(self.base.parent, event)
251
252        self._post_data()
253           
254    def restore(self):
255        """
256        Restore the roughness for this layer.
257        """
258        self.left_line.restore()
259        self.right_line.restore()
260        self.top_line.restore()
261        self.bottom_line.restore()
262
263    def move(self, x, y, ev):
264        """
265        Process move to a new position, making sure that the move is allowed.
266        """
267        pass
268       
269    def set_cursor(self, x, y):
270        pass
271       
272    def get_params(self):
273        params = {}
274        params["x_max"]= math.fabs(self.right_line.x1)
275        params["y_max"]= math.fabs(self.top_line.y1)
276        params["nbins"]= self.nbins
277        params["errors"] = self.error
278        params["count"]= self.count
279        return params
280   
281    def set_params(self, params):
282       
283        self.x = float(math.fabs(params["x_max"]))
284        self.y = float(math.fabs(params["y_max"] ))
285        self.nbins=params["nbins"]
286        self.left_line.update(xmin= -1*self.x,
287                              xmax = -1*self.x,
288                              ymin= -self.y,
289                              ymax=  self.y, 
290                              )
291        self.right_line.update(xmin= self.x,
292                              xmax = self.x,
293                              ymin= -self.y,
294                              ymax=  self.y, 
295                              )
296        self.top_line.update(xmin= -1*self.x,
297                             xmax= self.x,
298                             ymin= self.y,
299                             ymax= self.y)
300        self.bottom_line.update(xmin= -1*self.x,
301                                 xmax= self.x,
302                                 ymin= -1*self.y,
303                                 ymax= -1*self.y)
304       
305        self.post_data( nbins=None)
306    def freeze_axes(self):
307        self.base.freeze_axes()
308       
309    def thaw_axes(self):
310        self.base.thaw_axes()
311
312    def draw(self):
313        self.base.draw()
314
315class HorizontalLine(_BaseInteractor):
316    """
317         Select an annulus through a 2D plot
318    """
319    def __init__(self,base,axes,color='black', zorder=5,mline=None,ymin=None, ymax=None, y=0.5,
320                 xmin=0.0,xmax=0.5):
321       
322        _BaseInteractor.__init__(self, base, axes, color=color)
323        self.markers = []
324        self.axes = axes
325        self.x1= xmax
326        self.save_x1= xmax
327       
328        self.x2= xmin
329        self.save_x2= xmin
330       
331        self.y1= ymax
332        self.save_y1= ymax
333       
334        self.y2= ymin
335        self.save_y2= ymin
336        self.mline= mline
337        self.line = self.axes.plot([self.x1,-self.x1],
338                                   [self.y1,self.y2],
339                                      linestyle='-', marker='',
340                                      color=self.color,
341                                      visible=True)[0]
342       
343        self.npts = 20
344        self.has_move=False
345        self.connect_markers([self.line])
346        self.update()
347
348    def set_layer(self, n):
349        self.layernum = n
350        self.update()
351       
352    def clear(self):
353        self.clear_markers()
354        try:
355           
356            self.line.remove()
357        except:
358            # Old version of matplotlib
359            for item in range(len(self.axes.lines)):
360                del self.axes.lines[0]
361   
362    def get_radius(self):
363       
364        return 0
365   
366    def update(self,xmin=None, xmax=None,ymin=None,ymax=None, mline=None,translation=False):
367        """
368        Draw the new roughness on the graph.
369        """
370        if xmin !=None:
371            self.x1 = xmin
372        if ymin !=None:
373            self.y1 = ymin
374        self.line.set(xdata=[self.x1,-self.x1],
375                       ydata=[self.y1,self.y1])
376   
377       
378       
379    def save(self, ev):
380        """
381        Remember the roughness for this layer and the next so that we
382        can restore on Esc.
383        """
384        self.save_x1= self.x1
385        self.save_x2= self.x2
386       
387        self.save_y1= self.y1
388        self.save_y2= self.y2
389   
390       
391        self.base.freeze_axes()
392
393    def moveend(self, ev):
394       
395        self.has_move=False
396        self.base.moveend(ev)
397           
398    def restore(self):
399        """
400        Restore the roughness for this layer.
401        """
402        self.x1 = self.save_x1
403        self.x2 = self.save_x2
404        self.y1 = self.save_y1
405        self.y2 = self.save_y2
406       
407
408    def move(self, x, y, ev):
409        """
410        Process move to a new position, making sure that the move is allowed.
411        """
412        print "horizontal move x y "
413        self.y1= y
414        self.has_move=True
415        self.base.base.update()
416       
417    def set_cursor(self, x, y):
418        self.move(x, y, None)
419        self.update()
420       
421       
422    def get_params(self):
423        params = {}
424        params["radius"] = self.x1
425        #params["theta"] = self.xmax
426        return params
427   
428    def set_params(self, params):
429
430        x = params["radius"] 
431        self.set_cursor(x, self._inner_mouse_y)
432       
433
434
435
436class VerticalLine(_BaseInteractor):
437    """
438         Select an annulus through a 2D plot
439    """
440    def __init__(self,base,axes,color='black', zorder=5, mline=None, ymin=0.0, 
441                 ymax=0.5,xmin=-0.5,xmax=0.5
442                 ):
443       
444        _BaseInteractor.__init__(self, base, axes, color=color)
445        self.markers = []
446        self.axes = axes
447       
448        self.x1= xmax
449        self.x2= xmin
450        self.y1= ymax
451        self.y2= ymin
452        self.line = self.axes.plot([self.x1,self.x2],[self.y1,self.y2],
453                                      linestyle='-', marker='',
454                                      color=self.color,
455                                      visible=True)[0]
456     
457        self.has_move=False
458        self.connect_markers([self.line])
459        self.update()
460
461    def set_layer(self, n):
462        self.layernum = n
463        self.update()
464       
465    def clear(self):
466        self.clear_markers()
467        try:
468           
469            self.line.remove()
470        except:
471            # Old version of matplotlib
472            for item in range(len(self.axes.lines)):
473                del self.axes.lines[0]
474   
475   
476    def get_radius(self):
477        return 0
478   
479    def update(self,xmin=None,xmax=None,ymin=None, ymax=None, opline=None,translation=False):
480        """
481        Draw the new roughness on the graph.
482        """
483
484   
485        if xmin!=None:
486            self.x1=xmin
487        if ymin!=None:
488            self.y1=ymin
489        self.line.set(xdata=[self.x1,self.x1],
490                       ydata=[self.y1,-self.y1]) 
491       
492   
493       
494    def save(self, ev):
495        """
496        Remember the roughness for this layer and the next so that we
497        can restore on Esc.
498        """
499        self.save_x1= self.x1
500        self.save_x2= self.x2
501        self.save_y1= self.y1
502        self.save_y2= self.y2
503       
504        self.base.freeze_axes()
505
506    def moveend(self, ev):
507       
508        self.has_move=False
509        self.base.moveend(ev)
510           
511    def restore(self):
512        """
513        Restore the roughness for this layer.
514        """
515        self.x1 = self.save_x1
516        self.x2 = self.save_x2
517        self.y1 = self.save_y1
518        self.y2= self.save_y2
519     
520       
521    def move(self, x, y, ev):
522        """
523        Process move to a new position, making sure that the move is allowed.
524        """
525        self.has_move=True
526       
527        # compute the b intercept of the vertical line
528        self.x1= x
529       
530       
531        self.base.base.update()
532       
533       
534    def set_cursor(self, x, y):
535        self.move(x, y, None)
536        self.update()
537       
538       
539    def get_params(self):
540        params = {}
541        params["x"] = self.xmin
542        params["ymin"] = self.ymin
543        params["ymax"] = self.ymax
544        return params
545   
546    def set_params(self, params):
547        """
548            Draw a vertical line given some value of params
549            @param params: a dictionary containing value for x, ymin , ymax to draw
550            a vertical line
551        """
552        x = params["x"] 
553        ymin = params["ymin"] 
554        ymax = params["ymax"] 
555        #self.set_cursor(x, self._inner_mouse_y)
556        self.update(self,x =x,ymin =ymin, ymax =ymax)
557       
558
559class BoxInteractorX(BoxInteractor):
560    def __init__(self,base,axes,color='black', zorder=3):
561        BoxInteractor.__init__(self, base, axes, color=color)
562        self.base=base
563        self._post_data()
564    def _post_data(self):
565        from DataLoader.manipulations import SlabX
566        self.post_data(SlabX )   
567       
568
569class BoxInteractorY(BoxInteractor):
570    def __init__(self,base,axes,color='black', zorder=3):
571        BoxInteractor.__init__(self, base, axes, color=color)
572        self.base=base
573        self._post_data()
574    def _post_data(self):
575        from DataLoader.manipulations import SlabY
576        self.post_data(SlabY )   
577       
578       
Note: See TracBrowser for help on using the repository browser.