source: sasview/guiframe/local_perspectives/plotting/boxSlicer.py @ 8ff3ec1

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

working on box slicer

  • Property mode set to 100644
File size: 21.4 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()
129            self.right_line.update()
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            self.bottom_line.update(xmin= self.left_line.x ,xmax= self.right_line.x)
133        if self.right_line.has_move:
134            print "right has moved"
135            self.right_line.update()
136            self.left_line.update()
137            #self.left_line.update(xmin= self.right_line.x ,xmax=-1*self.right_line.x)
138            self.top_line.update( xmin= self.left_line.x ,xmax= self.right_line.x)
139            self.bottom_line.update(xmin= self.left_line.x ,xmax= self.right_line.x)
140           
141           
142        if self.bottom_line.has_move:
143            print "bottom has moved"
144            self.bottom_line.update()
145            self.top_line.update(y= -1*self.top_line.y)
146            self.left_line.update( ymin= self.bottom_line.y ,ymax= self.top_line.y)
147            self.right_line.update(ymin= self.bottom_line.y ,ymax= self.top_line.y)
148           
149        if self.top_line.has_move:
150            print "top has moved"
151            self.top_line.update()
152            #self.bottom_line.update()xmin=None, xmax=None,y=None, mline=None):
153            self.bottom_line.update(y= -1*self.top_line.y )
154            self.left_line.update(ymin= self.bottom_line.y ,ymax= self.top_line.y)
155            self.right_line.update(ymin= self.bottom_line.y ,ymax= self.top_line.y)
156           
157   
158    def save(self, ev):
159        """
160        Remember the roughness for this layer and the next so that we
161        can restore on Esc.
162        """
163        self.base.freeze_axes()
164        self.inner_circle.save(ev)
165        self.outer_circle.save(ev)
166
167    def _post_data(self):
168        # Compute data
169        data = self.base.data2D
170        from DataLoader.manipulations import  Boxavg
171        radius = math.sqrt(math.pow(self.qmax,2)+math.pow(self.qmax,2))
172        x_min= self.left_line.x
173        x_max= self.right_line.x
174        y_min= self.bottom_line.y
175        y_max= self.top_line.y
176        box =  Boxavg (x_min=x_min, x_max=x_max, y_min=y_min, y_max=y_max)
177       
178        self.count, self.error= box(self.base.data2D)
179       
180       
181             
182                                       
183    def moveend(self, ev):
184        self.base.thaw_axes()
185       
186        # Post paramters
187        event = SlicerParameters.SlicerParameterEvent()
188        event.type = self.__class__.__name__
189        #event.params = self.get_params()
190        wx.PostEvent(self.base.parent, event)
191
192        self._post_data()
193           
194    def restore(self):
195        """
196        Restore the roughness for this layer.
197        """
198        self.inner_circle.restore()
199        self.outer_circle.restore()
200
201    def move(self, x, y, ev):
202        """
203        Process move to a new position, making sure that the move is allowed.
204        """
205        pass
206       
207    def set_cursor(self, x, y):
208        pass
209       
210    def get_params(self):
211        params = {}
212        params["x_min"] = self.left_line.x
213        params["x_max"] = self.right_line.x
214        params["y_min"] = self.bottom_line.y
215        params["y_max"] = self.top_line.y
216        params["count"] = self.count
217        params["error"] = self.error
218        params["phi"] = self.main_line.theta
219        return params
220   
221    def set_params(self, params):
222       
223        x_min = params["x_min"] 
224        x_max = params["x_max"] 
225        y_min = params["y_min"]
226        y_max = params["y_max"] 
227        theta = params["theta"]
228       
229        self.left_line.update(ymin= y_min ,ymax= y_max)
230        self.right_line.update(ymin= y_min ,ymax= y_max)
231        self.top_line.update( xmin= x_min ,xmax= xmax)
232        self.bottom_line.update(xmin= xmin ,xmax= xmax)
233        self.main_line.update(theta)
234       
235        self._post_data()
236    def freeze_axes(self):
237        self.base.freeze_axes()
238       
239    def thaw_axes(self):
240        self.base.thaw_axes()
241
242    def draw(self):
243        self.base.draw()
244
245class HorizontalLine(_BaseInteractor):
246    """
247         Select an annulus through a 2D plot
248    """
249    def __init__(self,base,axes,color='black', zorder=5, y=0.5,
250                 xmin=0.0,xmax=0.5,
251                 theta2= math.pi/3 ):
252       
253        _BaseInteractor.__init__(self, base, axes, color=color)
254        self.markers = []
255        self.axes = axes
256       
257        self.y=y
258        self.save_y=y
259       
260        self.xmin=xmin
261        self.save_xmin=xmin
262        self.xmax=xmax
263        self.save_xmax=xmax
264        self.theta2= theta2
265        self.radius1= math.sqrt(math.pow(self.xmin, 2)+ math.pow(self.y, 2))
266        self.radius2= math.sqrt(math.pow(self.xmax, 2)+ math.pow(self.y, 2))
267       
268       
269        #print "phi and theta2", math.degrees(math.atan2(self.y, self.xmax))
270       
271        self.theta_right= math.atan2(self.y,self.xmin)
272        self.theta_left= math.atan2(self.y,self.xmax)
273       
274        self.phi_left= self.theta_left - self.theta2
275        self.phi_right=  self.theta_right -  self.theta2
276        #print "phi left right", math.degrees(self.phi_left),math.degrees(self.phi_right)
277        print "theta left right ", math.degrees(self.theta_left),math.degrees(self.theta_right)
278       
279        self.line = self.axes.plot([self.xmin,self.xmax],[self.y,self.y],
280                                      linestyle='-', marker='',
281                                      color=self.color,
282                                      visible=True)[0]
283 
284
285        self.npts = 20
286        self.has_move=False
287        self.connect_markers([self.line])
288        self.update()
289
290    def set_layer(self, n):
291        self.layernum = n
292        self.update()
293       
294    def clear(self):
295        self.clear_markers()
296        try:
297           
298            self.line.remove()
299        except:
300            # Old version of matplotlib
301            for item in range(len(self.axes.lines)):
302                del self.axes.lines[0]
303       
304    def get_radius(self):
305       
306        return 0
307   
308    def update(self,xmin=None, xmax=None,y=None, mline=None):
309        """
310        Draw the new roughness on the graph.
311        """
312        #print "update main line", self.has_move
313        if xmin !=None:
314            self.xmin=xmin
315        if xmax !=None:
316            self.xmax=xmax
317        if y !=None:
318            self.y = y
319        if mline !=None:
320            self.theta2= mline.theta
321            delta = mline.get_delta_angle()
322            # rotation
323            x1 = self.radius1 * math.cos(self.phi_left +  delta)
324            y1= self.radius1 * math.sin(self.phi_left + delta)
325               
326            x2= -1*self.radius2 * math.cos( self.phi_right + delta)
327            y2= -1*self.radius2 * math.sin(self.phi_right + delta)
328           
329            self.line.set(xdata=[x1,x2], ydata=[y1,y2]) 
330            print "Horizontal: update ",math.degrees(self.phi_left +delta),math.degrees(self.phi_right+delta)
331            print x1,x2,y1,y2
332           
333        else:
334            self.line.set(xdata=[self.xmin,self.xmax], ydata=[self.y,self.y])
335     
336       
337       
338    def save(self, ev):
339        """
340        Remember the roughness for this layer and the next so that we
341        can restore on Esc.
342        """
343        self.save_xmin= self.xmin
344        self.save_xmax= self.xmax
345       
346        self.save_y= self.y
347        self.base.freeze_axes()
348
349    def moveend(self, ev):
350       
351        self.has_move=False
352        self.base.moveend(ev)
353           
354    def restore(self):
355        """
356        Restore the roughness for this layer.
357        """
358        self.ymin = self.save_ymin
359        self.ymax = self.save_ymax
360
361    def move(self, x, y, ev):
362        """
363        Process move to a new position, making sure that the move is allowed.
364        """
365        self.y=y
366       
367       
368        self.has_move=True
369        self.base.base.update()
370       
371    def set_cursor(self, x, y):
372        self.move(x, y, None)
373        self.update()
374       
375       
376    def get_params(self):
377        params = {}
378        params["radius"] = self.xmin
379        params["theta"] = self.xmax
380        return params
381   
382    def set_params(self, params):
383
384        x = params["radius"] 
385        self.set_cursor(x, self._inner_mouse_y)
386       
387
388
389
390class VerticalLine(_BaseInteractor):
391    """
392         Select an annulus through a 2D plot
393    """
394    def __init__(self,base,axes,color='black', zorder=5, ymin=0.0, 
395                 ymax=0.5,x= 0.5,
396                 theta2= math.pi/3 ):
397       
398        _BaseInteractor.__init__(self, base, axes, color=color)
399        self.markers = []
400        self.axes = axes
401        # x coordinate of the vertical line
402        self.x = x
403        self.save_x = x
404        # minimum value of y coordinate of the vertical line
405        self.ymin = ymin
406        self.save_ymin = ymin
407        # maximum value of y coordinate of the vertical line
408        self.ymax=ymax
409        self.save_ymax=ymax
410        #insure rotation
411        self.radius1= math.sqrt(math.pow(self.x, 2)+ math.pow(self.ymin, 2))
412        self.radius2= math.sqrt(math.pow(self.x, 2)+ math.pow(self.ymax, 2))
413       
414       
415        self.theta_down = math.atan2(self.ymin, self.x)
416        self.theta_up = math.atan2(self.ymax, self.x)
417        self.theta2= theta2
418       
419        self.phi_down= self.theta_down - self.theta2
420        self.phi_up= self.theta_up - self.theta2
421        print "phi up down", math.degrees(self.phi_up),math.degrees(self.phi_down)
422        print "theta up down ", math.degrees(self.theta_up),math.degrees(self.theta_down)
423        # Draw vertical line
424        self.line = self.axes.plot([self.x,self.x],[self.ymin,self.ymax],
425                                      linestyle='-', marker='',
426                                      color=self.color,
427                                      visible=True)[0]
428     
429        self.npts = 20
430        # Check vertical line motion
431        self.has_move=False
432        self.connect_markers([self.line])
433        self.update()
434
435    def set_layer(self, n):
436        self.layernum = n
437        self.update()
438       
439    def clear(self):
440        self.clear_markers()
441        try:
442           
443            self.line.remove()
444        except:
445            # Old version of matplotlib
446            for item in range(len(self.axes.lines)):
447                del self.axes.lines[0]
448       
449    def get_radius(self):
450        return 0
451   
452    def update(self,x=None,ymin=None, ymax=None, mline=None):
453        """
454        Draw the new roughness on the graph.
455        """
456        if x!=None:
457            self.x = x
458        if ymin !=None:
459            self.ymin = ymin
460        if ymax !=None:
461            self.ymax = ymax
462        if mline !=None:
463            self.theta2= mline.theta
464            delta = mline.get_delta_angle()
465            # rotation
466            x1 = self.radius1 * math.cos(self.phi_down +  delta)
467            y1= self.radius1 * math.sin(self.phi_down + delta)
468               
469            x2= -1*self.radius2 * math.cos( self.phi_up + delta)
470            y2= -1*self.radius2 * math.sin(self.phi_up + delta)
471           
472            self.line.set(xdata=[x1,x2], ydata=[y1,y2]) 
473           
474        else:
475           self.line.set(xdata=[self.x,self.x], ydata=[self.ymin,self.ymax])
476     
477       
478       
479    def save(self, ev):
480        """
481        Remember the roughness for this layer and the next so that we
482        can restore on Esc.
483        """
484        self.save_x= self.x
485        self.save_ymin= self.ymin
486        self.save_ymax= self.ymax
487       
488        self.base.freeze_axes()
489
490    def moveend(self, ev):
491       
492        self.has_move=False
493        self.base.moveend(ev)
494           
495    def restore(self):
496        """
497        Restore the roughness for this layer.
498        """
499        self.x = self.save_x
500       
501        self.ymin=self.save_ymin
502        self.ymax=self.save_ymax
503    def move(self, x, y, ev):
504        """
505        Process move to a new position, making sure that the move is allowed.
506        """
507        self.x = x
508        self.has_move=True
509        self.base.base.update()
510       
511       
512    def set_cursor(self, x, y):
513        self.move(x, y, None)
514        self.update()
515       
516       
517    def get_params(self):
518        params = {}
519        params["x"] = self.xmin
520        params["ymin"] = self.ymin
521        params["ymax"] = self.ymax
522        return params
523   
524    def set_params(self, params):
525        """
526            Draw a vertical line given some value of params
527            @param params: a dictionary containing value for x, ymin , ymax to draw
528            a vertical line
529        """
530        x = params["x"] 
531        ymin = params["ymin"] 
532        ymax = params["ymax"] 
533        #self.set_cursor(x, self._inner_mouse_y)
534        self.update(self,x =x,ymin =ymin, ymax =ymax)
535       
536
537       
538class LineInteractor(_BaseInteractor):
539    """
540         Select an annulus through a 2D plot
541    """
542    def __init__(self,base,axes,color='black', zorder=5, r=1.0,theta=math.pi/4):
543       
544        _BaseInteractor.__init__(self, base, axes, color=color)
545        self.markers = []
546        self.axes = axes
547       
548        self.save_theta = theta
549        self.theta= theta
550       
551        self.radius = r
552     
553        self.scale = 10.0
554           
555        # Inner circle
556        x1= self.radius*math.cos(self.theta)
557        y1= self.radius*math.sin(self.theta)
558        x2= -1*self.radius*math.cos(self.theta)
559        y2= -1*self.radius*math.sin(self.theta)
560       
561        self.line = self.axes.plot([x1,x2],[y1,y2],
562                                      linestyle='-', marker='',
563                                      color=self.color,
564                                      visible=True)[0]
565     
566        self.npts = 20
567        self.has_move=False
568        self.connect_markers([self.line])
569        self.update()
570
571    def set_layer(self, n):
572       
573        self.layernum = n
574        self.update()
575       
576    def clear(self):
577        """
578            Remove the line of the plot
579        """
580        self.clear_markers()
581        try:
582            self.line.remove()
583        except:
584            # Old version of matplotlib
585            for item in range(len(self.axes.lines)):
586                del self.axes.lines[0]
587       
588       
589       
590    def get_delta_angle(self):
591        """
592            return difference between initial angle and the final angle during
593            rotation
594        """
595        return self.theta - self.save_theta
596       
597    def update(self, theta=None,radius=None):
598        """
599            Draw a line given and angle relative to the x-axis and a radius
600            @param  theta: the angle realtive to the x-axis
601            @param radius: the distance between the center and one end of the line
602        """
603       
604        if theta !=None:
605            self.theta= theta
606        if radius !=None:
607            self.radius =radius
608        print "update main line", math.degrees(self.theta)
609        x1= self.radius*math.cos(self.theta)
610        y1= self.radius*math.sin(self.theta)
611        x2= -1*self.radius*math.cos(self.theta)
612        y2= -1*self.radius*math.sin(self.theta)
613     
614        self.line.set(xdata=[x1,x2], ydata=[y1,y2]) 
615     
616       
617       
618    def save(self, ev):
619        """
620        Remember the roughness for this layer and the next so that we
621        can restore on Esc.
622        """
623        self.save_theta= self.theta
624        self.base.freeze_axes()
625
626    def moveend(self, ev):
627       
628        self.has_move=False
629        self.base.moveend(ev)
630           
631    def restore(self):
632        """
633        Restore the roughness for this layer.
634        """
635        self.theta = self.save_theta
636
637    def move(self, x, y, ev):
638        """
639        Process move to a new position, making sure that the move is allowed.
640        """
641        self.theta= math.atan2(y,x)
642        #print "main_line previous theta --- next theta ",math.degrees(self.save_theta),math.degrees(self.theta)
643        self.has_move=True
644        self.base.base.update()
645       
646       
647    def set_cursor(self, x, y):
648       
649        self.move(x, y, None)
650        self.update()
651       
652       
653    def get_params(self):
654        """
655            return params a dictionary containing values of paramters necessary to draw
656            this line
657        """
658        params = {}
659        params["radius"] = self.radius
660        params["theta"] = self.theta
661        return params
662   
663    def set_params(self, params):
664        """
665            Draw the line given value contains by params
666            @param params: dictionary containing name of parameters and their values
667        """
668        radius = params["radius"]
669        theta = params["theta"]
670        self.update(x, theta= theta , radius = radius )
671       
672
673
674
675       
Note: See TracBrowser for help on using the repository browser.