source: sasview/guiframe/local_perspectives/plotting/boxSlicer.py @ 78ed1ad

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 78ed1ad was 78ed1ad, checked in by Gervaise Alina <gervyh@…>, 16 years ago

working on boxslicer

  • Property mode set to 100644
File size: 23.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
15#from Plotter1D import AddPlotEvent
16import SlicerParameters
17import wx
18
19class BoxInteractor(_BaseInteractor):
20    """
21         Select an annulus through a 2D plot
22    """
23    def __init__(self,base,axes,color='black', zorder=3, x_min=0.0025, x_max=0.0025, y_min=0.0025, y_max=0.0025):
24       
25        _BaseInteractor.__init__(self, base, axes, color=color)
26        self.markers = []
27        self.axes = axes
28        self.qmax = self.base.qmax
29        self.connect = self.base.connect
30        self.xmin= -1* x_min
31        self.ymin= -1* y_min
32        self.xmax= x_max
33        self.ymax=  y_max
34       
35        self.theta2= math.pi/2
36        ## Number of points on the plot
37        self.nbins = 20
38        self.count=0
39        self.error=0
40        self.main_line = LineInteractor(self, self.base.subplot,color='orange', zorder=zorder, r=self.qmax,
41                                           theta= self.theta2)
42        self.main_line.qmax = self.base.qmax
43       
44        self.left_line = VerticalLine(self, self.base.subplot,color='blue', zorder=zorder, 
45                                        ymin= self.ymin, ymax= self.ymax,
46                                        xmin= self.xmin,xmax= self.xmin,
47                                        theta2= self.theta2)
48        self.left_line.qmax = self.base.qmax
49       
50        self.right_line= VerticalLine(self, self.base.subplot,color='black', zorder=zorder,
51                                     ymin= self.ymin, ymax= self.ymax,
52                                     xmin=self.xmax,xmax=self.xmax,
53                                      theta2= self.theta2)
54        self.right_line.qmax = self.base.qmax
55       
56        self.top_line= HorizontalLine(self, self.base.subplot,color='green', zorder=zorder,
57                                    y= self.ymax,
58                                    xmin= self.xmin, xmax= self.xmax,
59                                     theta2= self.theta2)
60        self.top_line.qmax = self.base.qmax
61       
62        self.bottom_line= HorizontalLine(self, self.base.subplot,color='red', zorder=zorder,
63                                    y =self.ymin,
64                                    xmin= self.xmin, xmax= self.xmax,
65                                     theta2= self.theta2)
66        self.bottom_line.qmax = self.base.qmax
67        #self.outer_circle.set_cursor(self.base.qmax/1.8, 0)
68       
69                     
70        self.update()
71        #self._post_data()
72       
73        # Bind to slice parameter events
74        self.base.parent.Bind(SlicerParameters.EVT_SLICER_PARS, self._onEVT_SLICER_PARS)
75
76
77    def _onEVT_SLICER_PARS(self, event):
78        #printEVT("AnnulusSlicer._onEVT_SLICER_PARS")
79        event.Skip()
80        if event.type == self.__class__.__name__:
81            #self.set_params(event.params)
82            self.base.update()
83
84    def update_and_post(self):
85        self.update()
86        self._post_data()
87
88    def save_data(self, path, image, x, y):
89        output = open(path, 'w')
90       
91        data_x, data_y = self.get_data(image, x, y)
92       
93        output.write("<phi>  <average>\n")
94        for i in range(len(data_x)):
95            output.write("%g  %g\n" % (data_x[i], data_y[i]))
96        output.close()
97
98    def set_layer(self, n):
99        self.layernum = n
100        self.update()
101       
102    def clear(self):
103        self.clear_markers()
104        self.left_line.clear()
105        self.right_line.clear()
106        self.top_line.clear()
107        self.bottom_line.clear()
108        self.main_line.clear()
109        #self.base.connect.disconnect()
110        self.base.parent.Unbind(SlicerParameters.EVT_SLICER_PARS)
111       
112    def update(self):
113        """
114        Respond to changes in the model by recalculating the profiles and
115        resetting the widgets.
116        """
117       
118        if self.main_line.has_move:
119            print "main has move"
120            self.main_line.update()
121            self.left_line.update(mline= self.main_line)
122            self.right_line.update(mline= self.main_line)
123            self.top_line.update(mline= self.main_line)
124            self.bottom_line.update(mline= self.main_line)
125       
126        if self.left_line.has_move:
127            print "left has moved"
128            self.left_line.update(mline= self.main_line,translation=True)
129            self.right_line.update(x=-1*self.left_line.x,mline= self.main_line,translation=True)
130            #self.right_line.update(xmin= self.left_line.x ,xmax=-1*self.left_line.x)
131            self.top_line.update( xmin= self.left_line.x ,xmax= self.right_line.x,
132                                  mline= self.main_line,translation=True)
133            self.bottom_line.update(xmin= self.left_line.x ,xmax= self.right_line.x,
134                                    mline= self.main_line,translation=True)
135        if self.right_line.has_move:
136            print "right has moved"
137            self.right_line.update(mline= self.main_line,translation=True)
138            self.left_line.update(x=-1*self.right_line.x,mline= self.main_line,translation=True)
139            #self.left_line.update(xmin= self.right_line.x ,xmax=-1*self.right_line.x)
140            self.top_line.update( xmin= self.left_line.x ,xmax= self.right_line.x,
141                                  mline= self.main_line,translation=True)
142            self.bottom_line.update(xmin= self.left_line.x ,xmax= self.right_line.x,
143                                    mline= self.main_line,translation=True)
144           
145           
146        if self.bottom_line.has_move:
147            print "bottom has moved"
148            self.bottom_line.update(mline= self.main_line,translation=True)
149            self.top_line.update(y= -1*self.top_line.y,translation=True)
150            self.left_line.update( ymin= self.bottom_line.y ,ymax= self.top_line.y,
151                                   mline= self.main_line,translation=True)
152            self.right_line.update(ymin= self.bottom_line.y ,ymax= self.top_line.y,
153                                   mline= self.main_line,translation=True)
154           
155        if self.top_line.has_move:
156            print "top has moved"
157            self.top_line.update(mline= self.main_line,translation=True)
158            #self.bottom_line.update()xmin=None, xmax=None,y=None, mline=None):
159            self.bottom_line.update(y= -1*self.top_line.y,mline= self.main_line,
160                                    translation=True )
161            self.left_line.update(ymin= self.bottom_line.y ,ymax= self.top_line.y,
162                                  mline= self.main_line,translation=True)
163            self.right_line.update(ymin= self.bottom_line.y ,ymax= self.top_line.y,
164                                   mline= self.main_line,translation=True)
165           
166   
167    def save(self, ev):
168        """
169        Remember the roughness for this layer and the next so that we
170        can restore on Esc.
171        """
172        self.base.freeze_axes()
173        self.inner_circle.save(ev)
174        self.outer_circle.save(ev)
175
176    def _post_data(self):
177        # Compute data
178        data = self.base.data2D
179        from DataLoader.manipulations import  Boxavg
180        radius = math.sqrt(math.pow(self.qmax,2)+math.pow(self.qmax,2))
181        x_min= self.left_line.x
182        x_max= self.right_line.x
183        y_min= self.bottom_line.y
184        y_max= self.top_line.y
185        box =  Boxavg (x_min=x_min, x_max=x_max, y_min=y_min, y_max=y_max)
186       
187        self.count, self.error= box(self.base.data2D)
188       
189       
190             
191                                       
192    def moveend(self, ev):
193        self.base.thaw_axes()
194       
195        # Post paramters
196        event = SlicerParameters.SlicerParameterEvent()
197        event.type = self.__class__.__name__
198        #event.params = self.get_params()
199        wx.PostEvent(self.base.parent, event)
200
201        self._post_data()
202           
203    def restore(self):
204        """
205        Restore the roughness for this layer.
206        """
207        self.inner_circle.restore()
208        self.outer_circle.restore()
209
210    def move(self, x, y, ev):
211        """
212        Process move to a new position, making sure that the move is allowed.
213        """
214        pass
215       
216    def set_cursor(self, x, y):
217        pass
218       
219    def get_params(self):
220        params = {}
221        params["x_min"] = self.left_line.xmin
222        params["x_max"] = self.right_line.xmax
223        params["y_min"] = self.bottom_line.y
224        params["y_max"] = self.top_line.y
225        params["count"] = self.count
226        params["error"] = self.error
227        params["phi"] = self.main_line.theta
228        return params
229   
230    def set_params(self, params):
231       
232        x_min = params["x_min"] 
233        x_max = params["x_max"] 
234        y_min = params["y_min"]
235        y_max = params["y_max"] 
236        theta = params["theta"]
237       
238        self.left_line.update(ymin= y_min ,ymax= y_max)
239        self.right_line.update(ymin= y_min ,ymax= y_max)
240        self.top_line.update( xmin= x_min ,xmax= xmax)
241        self.bottom_line.update(xmin= xmin ,xmax= xmax)
242        self.main_line.update(theta)
243       
244        self._post_data()
245    def freeze_axes(self):
246        self.base.freeze_axes()
247       
248    def thaw_axes(self):
249        self.base.thaw_axes()
250
251    def draw(self):
252        self.base.draw()
253
254class HorizontalLine(_BaseInteractor):
255    """
256         Select an annulus through a 2D plot
257    """
258    def __init__(self,base,axes,color='black', zorder=5, y=0.5,
259                 xmin=0.0,xmax=0.5,
260                 theta2= math.pi/3 ):
261       
262        _BaseInteractor.__init__(self, base, axes, color=color)
263        self.markers = []
264        self.axes = axes
265       
266        self.y= y
267        self.save_y = y
268       
269        self.xmin = xmin
270        self.save_xmin = xmin
271        self.xmax = xmax
272        self.save_xmax = xmax
273       
274        self.theta2 = theta2
275
276       
277        x1= self.xmin*math.cos(self.theta2)- self.y*math.sin(self.theta2)
278        y1= self.xmin*math.sin(self.theta2)+ self.y*math.sin(self.theta2)
279       
280        x2= self.xmax*math.cos(self.theta2)- self.y*math.sin(self.theta2)
281        y2= self.xmax*math.sin(self.theta2)+ self.y*math.sin(self.theta2)
282        print "x1, y1", x1, y1, x2,y2
283        self.line = self.axes.plot([x1,x2],[y1,y2],
284                                      linestyle='-', marker='',
285                                      color=self.color,
286                                      visible=True)[0]
287 
288
289        self.npts = 20
290        self.has_move=False
291        self.connect_markers([self.line])
292        self.update()
293
294    def set_layer(self, n):
295        self.layernum = n
296        self.update()
297       
298    def clear(self):
299        self.clear_markers()
300        try:
301           
302            self.line.remove()
303        except:
304            # Old version of matplotlib
305            for item in range(len(self.axes.lines)):
306                del self.axes.lines[0]
307       
308    def get_radius(self):
309       
310        return 0
311   
312    def update(self,xmin=None, xmax=None,y=None, mline=None,translation=False):
313        """
314        Draw the new roughness on the graph.
315        """
316        #print "update main line", self.has_move
317        if xmin !=None:
318            self.xmin=xmin
319        if xmax !=None:
320            self.xmax=xmax
321        if y !=None:
322            self.y = y
323        if mline !=None:
324            self.theta2= mline.theta
325            delta = mline.get_delta_angle()
326           
327            x1= self.xmin*math.cos(self.theta2)- self.y*math.sin(self.theta2)
328            y1= self.xmin*math.sin(self.theta2)+ self.y*math.sin(self.theta2)
329       
330            x2= self.xmax*math.cos(self.theta2)- self.y*math.sin(self.theta2)
331            y2= self.xmax*math.sin(self.theta2)+ self.y*math.sin(self.theta2)
332           
333            self.line.set(xdata=[x1,x2], ydata=[y1,y2]) 
334            print "Horizontal: update ",math.degrees(self.phi_left +delta),math.degrees(self.phi_right+delta)
335            print x1,x2,y1,y2
336           
337        #else:
338        #    self.line.set(xdata=[self.xmin,self.xmax], ydata=[self.y,self.y])
339     
340       
341       
342    def save(self, ev):
343        """
344        Remember the roughness for this layer and the next so that we
345        can restore on Esc.
346        """
347        self.save_xmin= self.xmin
348        self.save_xmax= self.xmax
349       
350        self.save_y= self.y
351        self.base.freeze_axes()
352
353    def moveend(self, ev):
354       
355        self.has_move=False
356        self.base.moveend(ev)
357           
358    def restore(self):
359        """
360        Restore the roughness for this layer.
361        """
362        self.ymin = self.save_ymin
363        self.ymax = self.save_ymax
364
365    def move(self, x, y, ev):
366        """
367        Process move to a new position, making sure that the move is allowed.
368        """
369        self.y=y
370       
371       
372        self.has_move=True
373        self.base.base.update()
374       
375    def set_cursor(self, x, y):
376        self.move(x, y, None)
377        self.update()
378       
379       
380    def get_params(self):
381        params = {}
382        params["radius"] = self.xmin
383        params["theta"] = self.xmax
384        return params
385   
386    def set_params(self, params):
387
388        x = params["radius"] 
389        self.set_cursor(x, self._inner_mouse_y)
390       
391
392
393
394class VerticalLine(_BaseInteractor):
395    """
396         Select an annulus through a 2D plot
397    """
398    def __init__(self,base,axes,color='black', zorder=5, ymin=0.0, 
399                 ymax=0.5,xmin= 0.5,xmax=0.5,
400                 theta2= math.pi/3 ):
401       
402        _BaseInteractor.__init__(self, base, axes, color=color)
403        self.markers = []
404        self.axes = axes
405        # x coordinate of the vertical line
406        self.xmin = xmin
407        self.save_xmin = xmin
408        self.xmax = xmax
409        self.save_xmax = xmax
410        # minimum value of y coordinate of the vertical line
411        self.ymin = ymin
412        self.save_ymin = ymin
413        # maximum value of y coordinate of the vertical line
414        self.ymax=ymax
415        self.save_ymax=ymax
416        #insure rotation
417        self.radius1= math.sqrt(math.pow(self.xmin, 2)+ math.pow(self.ymin, 2))
418        self.radius2= math.sqrt(math.pow(self.xmax, 2)+ math.pow(self.ymax, 2))
419       
420       
421        self.theta_down = math.atan2(self.ymin, self.xmin)
422        self.theta_up = math.atan2(self.ymax, self.xmax)
423        self.theta2= theta2
424       
425        self.phi_down= self.theta_down - self.theta2
426        self.phi_up= self.theta_up - self.theta2
427        print "phi up down", math.degrees(self.phi_up),math.degrees(self.phi_down)
428        #print "theta up down ", math.degrees(self.theta_up),math.degrees(self.theta_down)
429        # Draw vertical line
430        self.xmin= self.xmin* math.cos(self.theta2)-self.ymin *math.sin(self.theta2)
431        self.xmax= self.xmax* math.cos(self.theta2)-self.ymax *math.sin(self.theta2)
432       
433        self.ymin= self.xmin* math.sin(self.theta2)+self.ymin *math.cos(self.theta2)
434        self.ymax= self.xmax* math.sin(self.theta2)+self.ymax *math.cos(self.theta2)
435       
436        self.line = self.axes.plot([self.xmin,self.xmax],[self.ymin,self.ymax],
437                                      linestyle='-', marker='',
438                                      color=self.color,
439                                      visible=True)[0]
440     
441        self.npts = 20
442        # Check vertical line motion
443        self.has_move=False
444        self.connect_markers([self.line])
445        self.update()
446
447    def set_layer(self, n):
448        self.layernum = n
449        self.update()
450       
451    def clear(self):
452        self.clear_markers()
453        try:
454           
455            self.line.remove()
456        except:
457            # Old version of matplotlib
458            for item in range(len(self.axes.lines)):
459                del self.axes.lines[0]
460       
461    def get_radius(self):
462        return 0
463   
464    def update(self,x=None,ymin=None, ymax=None, mline=None,translation=False):
465        """
466        Draw the new roughness on the graph.
467        """
468        if x!=None:
469            self.x = x
470        if ymin !=None:
471            self.ymin = ymin
472        if ymax !=None:
473            self.ymax = ymax
474        if mline !=None:
475           
476            self.theta2= mline.theta
477            delta = mline.get_delta_angle()
478            if translation:
479                delta= 0
480            # rotation
481            x1 = self.radius1 * math.cos(self.phi_down +  delta)
482            y1= self.radius1 * math.sin(self.phi_down + delta)
483               
484            x2= -1*self.radius2 * math.cos( self.phi_up + delta)
485            y2= -1*self.radius2 * math.sin(self.phi_up + delta)
486            self.xmin= x1
487            self.xmax=x2
488            self.ymin= y1
489            self.ymax= y2
490            self.line.set(xdata=[self.xmin,self.xmax], ydata=[self.ymin,self.ymax]) 
491           
492        #else:
493        #   self.line.set(xdata=[self.x,self.x], ydata=[self.ymin,self.ymax])
494     
495       
496       
497    def save(self, ev):
498        """
499        Remember the roughness for this layer and the next so that we
500        can restore on Esc.
501        """
502        #self.save_x= self.x
503        self.save_xmin= self.xmin
504        self.save_xmax= self.xmax
505        self.save_ymin= self.ymin
506        self.save_ymax= self.ymax
507       
508        self.base.freeze_axes()
509
510    def moveend(self, ev):
511       
512        self.has_move=False
513        self.base.moveend(ev)
514           
515    def restore(self):
516        """
517        Restore the roughness for this layer.
518        """
519        self.xmin = self.save_xmin
520        self.xmax = self.save_xmax
521        self.ymin=self.save_ymin
522        self.ymax=self.save_ymax
523       
524       
525    def move(self, x, y, ev):
526        """
527        Process move to a new position, making sure that the move is allowed.
528        """
529        delta_xmin = x- self.save_xmin
530        delta_xmax = x- self.save_xmax
531        delta_ymin = y- self.save_ymin
532        delta_ymax = y- self.save_ymax
533       
534        self.xmin= self.xmin + delta_xmin
535        self.xmax= self.xmax + delta_xmax
536       
537        self.ymin= self.ymin +delta_ymin
538        self.ymax= self.ymax +delta_ymax
539       
540       
541        self.has_move=True
542        self.base.base.update()
543       
544       
545    def set_cursor(self, x, y):
546        self.move(x, y, None)
547        self.update()
548       
549       
550    def get_params(self):
551        params = {}
552        params["x"] = self.xmin
553        params["ymin"] = self.ymin
554        params["ymax"] = self.ymax
555        return params
556   
557    def set_params(self, params):
558        """
559            Draw a vertical line given some value of params
560            @param params: a dictionary containing value for x, ymin , ymax to draw
561            a vertical line
562        """
563        x = params["x"] 
564        ymin = params["ymin"] 
565        ymax = params["ymax"] 
566        #self.set_cursor(x, self._inner_mouse_y)
567        self.update(self,x =x,ymin =ymin, ymax =ymax)
568       
569
570       
571class LineInteractor(_BaseInteractor):
572    """
573         Select an annulus through a 2D plot
574    """
575    def __init__(self,base,axes,color='black', zorder=5, r=1.0,theta=math.pi/4):
576       
577        _BaseInteractor.__init__(self, base, axes, color=color)
578        self.markers = []
579        self.axes = axes
580       
581        self.save_theta = theta
582        self.theta= theta
583       
584        self.radius = r
585     
586        self.scale = 10.0
587           
588        # Inner circle
589        x1= self.radius*math.cos(self.theta)
590        y1= self.radius*math.sin(self.theta)
591        x2= -1*self.radius*math.cos(self.theta)
592        y2= -1*self.radius*math.sin(self.theta)
593       
594        self.line = self.axes.plot([x1,x2],[y1,y2],
595                                      linestyle='-', marker='',
596                                      color=self.color,
597                                      visible=True)[0]
598     
599        self.npts = 20
600        self.has_move=False
601        self.connect_markers([self.line])
602        self.update()
603
604    def set_layer(self, n):
605       
606        self.layernum = n
607        self.update()
608       
609    def clear(self):
610        """
611            Remove the line of the plot
612        """
613        self.clear_markers()
614        try:
615            self.line.remove()
616        except:
617            # Old version of matplotlib
618            for item in range(len(self.axes.lines)):
619                del self.axes.lines[0]
620       
621       
622       
623    def get_delta_angle(self):
624        """
625            return difference between initial angle and the final angle during
626            rotation
627        """
628        return self.theta - self.save_theta
629       
630    def update(self, theta=None,radius=None):
631        """
632            Draw a line given and angle relative to the x-axis and a radius
633            @param  theta: the angle realtive to the x-axis
634            @param radius: the distance between the center and one end of the line
635        """
636       
637        if theta !=None:
638            self.theta= theta
639        if radius !=None:
640            self.radius =radius
641        print "update main line", math.degrees(self.theta)
642        x1= self.radius*math.cos(self.theta)
643        y1= self.radius*math.sin(self.theta)
644        x2= -1*self.radius*math.cos(self.theta)
645        y2= -1*self.radius*math.sin(self.theta)
646     
647        self.line.set(xdata=[x1,x2], ydata=[y1,y2]) 
648     
649       
650       
651    def save(self, ev):
652        """
653        Remember the roughness for this layer and the next so that we
654        can restore on Esc.
655        """
656        self.save_theta= self.theta
657        self.base.freeze_axes()
658
659    def moveend(self, ev):
660       
661        self.has_move=False
662        self.base.moveend(ev)
663           
664    def restore(self):
665        """
666        Restore the roughness for this layer.
667        """
668        self.theta = self.save_theta
669
670    def move(self, x, y, ev):
671        """
672        Process move to a new position, making sure that the move is allowed.
673        """
674        self.theta= math.atan2(y,x)
675        #print "main_line previous theta --- next theta ",math.degrees(self.save_theta),math.degrees(self.theta)
676        self.has_move=True
677        self.base.base.update()
678       
679       
680    def set_cursor(self, x, y):
681       
682        self.move(x, y, None)
683        self.update()
684       
685       
686    def get_params(self):
687        """
688            return params a dictionary containing values of paramters necessary to draw
689            this line
690        """
691        params = {}
692        params["radius"] = self.radius
693        params["theta"] = self.theta
694        return params
695   
696    def set_params(self, params):
697        """
698            Draw the line given value contains by params
699            @param params: dictionary containing name of parameters and their values
700        """
701        radius = params["radius"]
702        theta = params["theta"]
703        self.update(x, theta= theta , radius = radius )
704       
705
706
707
708       
Note: See TracBrowser for help on using the repository browser.