source: sasview/guiframe/local_perspectives/plotting/boxSlicer.py @ 7ab9241

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

small change on annulus

  • Property mode set to 100644
File size: 23.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
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                                        x= 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                                     x=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(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(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.x
222        params["x_max"] = self.right_line.x
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        self.theta2 = theta2
274        self.radius1 = math.sqrt(math.pow(self.xmin, 2)+ math.pow(self.y, 2))
275        self.radius2 = math.sqrt(math.pow(self.xmax, 2)+ math.pow(self.y, 2))
276       
277       
278        #print "phi and theta2", math.degrees(math.atan2(self.y, self.xmax))
279       
280        self.theta_right= math.atan2(self.y,self.xmin)
281        self.theta_left= math.atan2(self.y,self.xmax)
282       
283        self.phi_left= self.theta_left - self.theta2
284        self.phi_right=  self.theta_right -  self.theta2
285        print "phi left right", math.degrees(self.phi_left),math.degrees(self.phi_right)
286        #print "theta left right ", math.degrees(self.theta_left),math.degrees(self.theta_right)
287       
288        self.line = self.axes.plot([self.xmin,self.xmax],[self.y,self.y],
289                                      linestyle='-', marker='',
290                                      color=self.color,
291                                      visible=True)[0]
292 
293
294        self.npts = 20
295        self.has_move=False
296        self.connect_markers([self.line])
297        self.update()
298
299    def set_layer(self, n):
300        self.layernum = n
301        self.update()
302       
303    def clear(self):
304        self.clear_markers()
305        try:
306           
307            self.line.remove()
308        except:
309            # Old version of matplotlib
310            for item in range(len(self.axes.lines)):
311                del self.axes.lines[0]
312       
313    def get_radius(self):
314       
315        return 0
316   
317    def update(self,xmin=None, xmax=None,y=None, mline=None,translation=False):
318        """
319        Draw the new roughness on the graph.
320        """
321        #print "update main line", self.has_move
322        if xmin !=None:
323            self.xmin=xmin
324        if xmax !=None:
325            self.xmax=xmax
326        if y !=None:
327            self.y = y
328        if mline !=None:
329            self.theta2= mline.theta
330            delta = mline.get_delta_angle()
331            # rotation
332            x1 = self.radius1 * math.cos(self.phi_left +  delta)
333            y1= self.radius1 * math.sin(self.phi_left + delta)
334               
335            x2= -1*self.radius2 * math.cos( self.phi_right + delta)
336            y2= -1*self.radius2 * math.sin(self.phi_right + delta)
337           
338            self.line.set(xdata=[x1,x2], ydata=[y1,y2]) 
339            print "Horizontal: update ",math.degrees(self.phi_left +delta),math.degrees(self.phi_right+delta)
340            print x1,x2,y1,y2
341           
342        #else:
343        #    self.line.set(xdata=[self.xmin,self.xmax], ydata=[self.y,self.y])
344     
345       
346       
347    def save(self, ev):
348        """
349        Remember the roughness for this layer and the next so that we
350        can restore on Esc.
351        """
352        self.save_xmin= self.xmin
353        self.save_xmax= self.xmax
354       
355        self.save_y= self.y
356        self.base.freeze_axes()
357
358    def moveend(self, ev):
359       
360        self.has_move=False
361        self.base.moveend(ev)
362           
363    def restore(self):
364        """
365        Restore the roughness for this layer.
366        """
367        self.ymin = self.save_ymin
368        self.ymax = self.save_ymax
369
370    def move(self, x, y, ev):
371        """
372        Process move to a new position, making sure that the move is allowed.
373        """
374        self.y=y
375        #self.radius1= math.sqrt(math.pow(self.xmin, 2)+ math.pow(self.y, 2))
376        #self.radius2= math.sqrt(math.pow(self.xmax, 2)+ math.pow(self.y, 2))
377       
378        #self.theta_right= math.atan2(self.y,self.xmin)
379        #self.theta_left= math.atan2(self.y,self.xmax)
380       
381        #self.phi_left= self.theta_left - self.theta2
382        #self.phi_right=  self.theta_right -  self.theta2
383       
384        self.has_move=True
385        self.base.base.update()
386       
387    def set_cursor(self, x, y):
388        self.move(x, y, None)
389        self.update()
390       
391       
392    def get_params(self):
393        params = {}
394        params["radius"] = self.xmin
395        params["theta"] = self.xmax
396        return params
397   
398    def set_params(self, params):
399
400        x = params["radius"] 
401        self.set_cursor(x, self._inner_mouse_y)
402       
403
404
405
406class VerticalLine(_BaseInteractor):
407    """
408         Select an annulus through a 2D plot
409    """
410    def __init__(self,base,axes,color='black', zorder=5, ymin=0.0, 
411                 ymax=0.5,x= 0.5,
412                 theta2= math.pi/3 ):
413       
414        _BaseInteractor.__init__(self, base, axes, color=color)
415        self.markers = []
416        self.axes = axes
417        # x coordinate of the vertical line
418        self.x = x
419        self.save_x = x
420        # minimum value of y coordinate of the vertical line
421        self.ymin = ymin
422        self.save_ymin = ymin
423        # maximum value of y coordinate of the vertical line
424        self.ymax=ymax
425        self.save_ymax=ymax
426        #insure rotation
427        self.radius1= math.sqrt(math.pow(self.x, 2)+ math.pow(self.ymin, 2))
428        self.radius2= math.sqrt(math.pow(self.x, 2)+ math.pow(self.ymax, 2))
429       
430       
431        self.theta_down = math.atan2(self.ymin, self.x)
432        self.theta_up = math.atan2(self.ymax, self.x)
433        self.theta2= theta2
434       
435        self.phi_down= self.theta_down - self.theta2
436        self.phi_up= self.theta_up - self.theta2
437        print "phi up down", math.degrees(self.phi_up),math.degrees(self.phi_down)
438        #print "theta up down ", math.degrees(self.theta_up),math.degrees(self.theta_down)
439        # Draw vertical line
440        self.line = self.axes.plot([self.x,self.x],[self.ymin,self.ymax],
441                                      linestyle='-', marker='',
442                                      color=self.color,
443                                      visible=True)[0]
444     
445        self.npts = 20
446        # Check vertical line motion
447        self.has_move=False
448        self.connect_markers([self.line])
449        self.update()
450
451    def set_layer(self, n):
452        self.layernum = n
453        self.update()
454       
455    def clear(self):
456        self.clear_markers()
457        try:
458           
459            self.line.remove()
460        except:
461            # Old version of matplotlib
462            for item in range(len(self.axes.lines)):
463                del self.axes.lines[0]
464       
465    def get_radius(self):
466        return 0
467   
468    def update(self,x=None,ymin=None, ymax=None, mline=None,translation=False):
469        """
470        Draw the new roughness on the graph.
471        """
472        if x!=None:
473            self.x = x
474        if ymin !=None:
475            self.ymin = ymin
476        if ymax !=None:
477            self.ymax = ymax
478        if mline !=None:
479           
480            self.theta2= mline.theta
481            delta = mline.get_delta_angle()
482            if translation:
483                delta= 0
484            # rotation
485            x1 = self.radius1 * math.cos(self.phi_down +  delta)
486            y1= self.radius1 * math.sin(self.phi_down + delta)
487               
488            x2= -1*self.radius2 * math.cos( self.phi_up + delta)
489            y2= -1*self.radius2 * math.sin(self.phi_up + delta)
490           
491            self.line.set(xdata=[x1,x2], ydata=[y1,y2]) 
492           
493        #else:
494        #   self.line.set(xdata=[self.x,self.x], ydata=[self.ymin,self.ymax])
495     
496       
497       
498    def save(self, ev):
499        """
500        Remember the roughness for this layer and the next so that we
501        can restore on Esc.
502        """
503        self.save_x= self.x
504        self.save_ymin= self.ymin
505        self.save_ymax= self.ymax
506       
507        self.base.freeze_axes()
508
509    def moveend(self, ev):
510       
511        self.has_move=False
512        self.base.moveend(ev)
513           
514    def restore(self):
515        """
516        Restore the roughness for this layer.
517        """
518        self.x = self.save_x
519       
520        self.ymin=self.save_ymin
521        self.ymax=self.save_ymax
522    def move(self, x, y, ev):
523        """
524        Process move to a new position, making sure that the move is allowed.
525        """
526        self.x = x
527        self.radius1= math.sqrt(math.pow(self.x, 2)+ math.pow(self.ymin, 2))
528        self.radius2= math.sqrt(math.pow(self.x, 2)+ math.pow(self.ymax, 2))
529       
530       
531        self.theta_down = math.atan2(self.ymin, self.x)
532        self.theta_up = math.atan2(self.ymax, self.x)
533       
534       
535        self.phi_down= self.theta_down - self.theta2
536        self.phi_up= self.theta_up - self.theta2
537       
538        self.has_move=True
539        self.base.base.update()
540       
541       
542    def set_cursor(self, x, y):
543        self.move(x, y, None)
544        self.update()
545       
546       
547    def get_params(self):
548        params = {}
549        params["x"] = self.xmin
550        params["ymin"] = self.ymin
551        params["ymax"] = self.ymax
552        return params
553   
554    def set_params(self, params):
555        """
556            Draw a vertical line given some value of params
557            @param params: a dictionary containing value for x, ymin , ymax to draw
558            a vertical line
559        """
560        x = params["x"] 
561        ymin = params["ymin"] 
562        ymax = params["ymax"] 
563        #self.set_cursor(x, self._inner_mouse_y)
564        self.update(self,x =x,ymin =ymin, ymax =ymax)
565       
566
567       
568class LineInteractor(_BaseInteractor):
569    """
570         Select an annulus through a 2D plot
571    """
572    def __init__(self,base,axes,color='black', zorder=5, r=1.0,theta=math.pi/4):
573       
574        _BaseInteractor.__init__(self, base, axes, color=color)
575        self.markers = []
576        self.axes = axes
577       
578        self.save_theta = theta
579        self.theta= theta
580       
581        self.radius = r
582     
583        self.scale = 10.0
584           
585        # Inner circle
586        x1= self.radius*math.cos(self.theta)
587        y1= self.radius*math.sin(self.theta)
588        x2= -1*self.radius*math.cos(self.theta)
589        y2= -1*self.radius*math.sin(self.theta)
590       
591        self.line = self.axes.plot([x1,x2],[y1,y2],
592                                      linestyle='-', marker='',
593                                      color=self.color,
594                                      visible=True)[0]
595     
596        self.npts = 20
597        self.has_move=False
598        self.connect_markers([self.line])
599        self.update()
600
601    def set_layer(self, n):
602       
603        self.layernum = n
604        self.update()
605       
606    def clear(self):
607        """
608            Remove the line of the plot
609        """
610        self.clear_markers()
611        try:
612            self.line.remove()
613        except:
614            # Old version of matplotlib
615            for item in range(len(self.axes.lines)):
616                del self.axes.lines[0]
617       
618       
619       
620    def get_delta_angle(self):
621        """
622            return difference between initial angle and the final angle during
623            rotation
624        """
625        return self.theta - self.save_theta
626       
627    def update(self, theta=None,radius=None):
628        """
629            Draw a line given and angle relative to the x-axis and a radius
630            @param  theta: the angle realtive to the x-axis
631            @param radius: the distance between the center and one end of the line
632        """
633       
634        if theta !=None:
635            self.theta= theta
636        if radius !=None:
637            self.radius =radius
638        print "update main line", math.degrees(self.theta)
639        x1= self.radius*math.cos(self.theta)
640        y1= self.radius*math.sin(self.theta)
641        x2= -1*self.radius*math.cos(self.theta)
642        y2= -1*self.radius*math.sin(self.theta)
643     
644        self.line.set(xdata=[x1,x2], ydata=[y1,y2]) 
645     
646       
647       
648    def save(self, ev):
649        """
650        Remember the roughness for this layer and the next so that we
651        can restore on Esc.
652        """
653        self.save_theta= self.theta
654        self.base.freeze_axes()
655
656    def moveend(self, ev):
657       
658        self.has_move=False
659        self.base.moveend(ev)
660           
661    def restore(self):
662        """
663        Restore the roughness for this layer.
664        """
665        self.theta = self.save_theta
666
667    def move(self, x, y, ev):
668        """
669        Process move to a new position, making sure that the move is allowed.
670        """
671        self.theta= math.atan2(y,x)
672        #print "main_line previous theta --- next theta ",math.degrees(self.save_theta),math.degrees(self.theta)
673        self.has_move=True
674        self.base.base.update()
675       
676       
677    def set_cursor(self, x, y):
678       
679        self.move(x, y, None)
680        self.update()
681       
682       
683    def get_params(self):
684        """
685            return params a dictionary containing values of paramters necessary to draw
686            this line
687        """
688        params = {}
689        params["radius"] = self.radius
690        params["theta"] = self.theta
691        return params
692   
693    def set_params(self, params):
694        """
695            Draw the line given value contains by params
696            @param params: dictionary containing name of parameters and their values
697        """
698        radius = params["radius"]
699        theta = params["theta"]
700        self.update(x, theta= theta , radius = radius )
701       
702
703
704
705       
Note: See TracBrowser for help on using the repository browser.