source: sasview/guiframe/local_perspectives/plotting/SectorSlicer.py @ 0d9dae8

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

add a new module containing common classes that I used often:
sans.guiframe.utils

remove event slicer and add it in sans.guicoom.events,
modified slicer for those events

  • Property mode set to 100644
File size: 16.5 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
10import math
11import wx
12from copy import deepcopy
13
14from BaseInteractor import _BaseInteractor
15from sans.guicomm.events import NewPlotEvent, StatusEvent,SlicerParameterEvent,EVT_SLICER_PARS
16
17
18
19
20
21
22class SectorInteractor(_BaseInteractor):
23    """
24         Select an annulus through a 2D plot
25    """
26    def __init__(self,base,axes,color='black', zorder=3):
27       
28        _BaseInteractor.__init__(self, base, axes, color=color)
29        self.markers = []
30        self.axes = axes       
31        self.qmax = math.sqrt(math.pow(max(self.base.data2D.xmax,abs(self.base.data2D.xmin)),2)+math.pow(max(self.base.data2D.xmax,abs(self.base.data2D.xmin)),2))
32        #print "sector qmax", self.qmax
33        self.connect = self.base.connect
34       
35        ## Number of points on the plot
36        self.nbins = 20
37        self.theta1= math.pi/4
38        self.theta2= math.pi/3
39        self.phi=math.pi/12
40        #self.theta3= 2*self.theta2 -self.theta1
41        # Inner circle
42        self.main_line = LineInteractor(self, self.base.subplot,color='green', zorder=zorder, r=self.qmax,
43                                           theta= self.theta2)
44        self.main_line.qmax = self.qmax
45        #self.left_line = SectionInteractor(self, self.base.subplot, zorder=zorder+1, r=self.qmax,
46        #                                   theta1= self.theta1, theta2= self.theta2)
47        #self.left_line.qmax = self.base.qmax
48        self.right_line= SideInteractor(self, self.base.subplot,color='black', zorder=zorder,
49                                     r=self.qmax,
50                                           phi= -1*self.phi,
51                                           theta2=self.theta2)
52        self.right_line.qmax = self.qmax
53        self.left_line= SideInteractor(self, self.base.subplot,color='blue', zorder=zorder,
54                                     r=self.qmax,
55                                           phi= self.phi,
56                                           theta2=self.theta2)
57        self.left_line.qmax = self.qmax
58        #self.outer_circle.set_cursor(self.base.qmax/1.8, 0)
59       
60                     
61        self.update()
62        self._post_data()
63       
64        # Bind to slice parameter events
65        self.base.parent.Bind(EVT_SLICER_PARS, self._onEVT_SLICER_PARS)
66
67
68    def _onEVT_SLICER_PARS(self, event):
69        wx.PostEvent(self.base.parent, StatusEvent(status="SectorSlicer._onEVT_SLICER_PARS"))
70        event.Skip()
71        if event.type == self.__class__.__name__:
72            self.set_params(event.params)
73            self.base.update()
74
75    def update_and_post(self):
76        self.update()
77        #self._post_data()
78
79    def save_data(self, path, image, x, y):
80        output = open(path, 'w')
81       
82        data_x, data_y = self.get_data(image, x, y)
83       
84        output.write("<phi>  <average>\n")
85        for i in range(len(data_x)):
86            output.write("%g  %g\n" % (data_x[i], data_y[i]))
87        output.close()
88
89    def set_layer(self, n):
90        self.layernum = n
91        self.update()
92       
93    def clear(self):
94        self.clear_markers()
95        self.main_line.clear()
96        self.left_line.clear()
97        self.right_line.clear()
98        #self.base.connect.disconnect()
99        self.base.parent.Unbind(EVT_SLICER_PARS)
100       
101    def update(self):
102        """
103        Respond to changes in the model by recalculating the profiles and
104        resetting the widgets.
105        """
106        # Update locations       
107       
108        #if self.main_line.has_move:
109        #self.main_line.update()   
110        #self.right_line.update()   
111        #self.left_line.update()     
112        if self.main_line.has_move:
113            self.main_line.update()
114            self.right_line.update( delta = self.main_line.get_radius(),mline= self.main_line)
115            self.left_line.update( delta = self.main_line.get_radius() ,mline= self.main_line)
116            print "Main line has moved ---> phi right",math.degrees(self.main_line.get_radius()+self.right_line.theta)
117            print "Main line has moved ---> phi left",math.degrees(self.left_line.theta+self.main_line.get_radius())
118        if self.left_line.has_move:
119            print "left line has moved --->"
120            self.main_line.update()
121            self.left_line.update(phi=None,delta=None, mline=self.main_line,side=True, left=True)
122            #self.right_line.update(-1*delta,linem=self.main_line,linel=self.left_line)
123            self.right_line.update(phi=-1*self.left_line.phi,delta=None, mline=self.main_line,side=True, left=True)
124        if self.right_line.has_move:
125            print "right line has moved --->"
126           
127            self.main_line.update()
128            self.right_line.update(phi=None,delta=None, mline=self.main_line,side=True, right=True)
129            #self.right_line.update(-1*delta,linem=self.main_line,linel=self.left_line)
130            self.left_line.update(phi=-1*self.right_line.phi,delta=None, mline=self.main_line,side=True, left=True)
131   
132   
133   
134
135    def save(self, ev):
136        """
137        Remember the roughness for this layer and the next so that we
138        can restore on Esc.
139        """
140        self.base.freeze_axes()
141        self.inner_circle.save(ev)
142        self.outer_circle.save(ev)
143
144    def _post_data(self, nbins=None):
145        # Compute data
146        data = self.base.data2D
147        # If we have no data, just return
148        if data == None:
149            return
150
151        name = "Sector "
152        from DataLoader.manipulations import SectorQ
153        radius = self.qmax #radius=math.sqrt(math.pow(self.qmax,2)+math.pow(self.qmax,2))
154        phimin = self.right_line.theta+math.pi
155        phimax = self.left_line.theta+math.pi
156        print "sector Q", radius
157        sect = SectorQ(r_min=0.0, r_max= radius , phi_min=phimin, phi_max=phimax)
158        #sect = SectorQ(r_min=-1*radius , r_max= radius , phi_min=phimin, phi_max=phimax)
159        if nbins!=None:
160            sect.nbins = nbins
161       
162        sector = sect(self.base.data2D)
163       
164        from sans.guiframe.dataFitting import Data1D
165        if hasattr(sector,"dxl"):
166            dxl= sector.dxl
167        else:
168            dxl= None
169        if hasattr(sector,"dxw"):
170            dxw= sector.dxw
171        else:
172            dxw= None
173       
174        new_plot = Data1D(x=sector.x,y=sector.y,dy=sector.dy,dxl=dxl,dxw=dxw)
175        new_plot.name = "SectorQ" +"("+ self.base.data2D.name+")"
176       
177       
178
179        new_plot.source=self.base.data2D.source
180        #new_plot.info=self.base.data2D.info
181        new_plot.interactive = True
182        #print "loader output.detector",self.base.data2D.info,output.source,
183        new_plot.detector =self.base.data2D.detector
184        #print "loader output.detector",new_plot.detector
185        # If the data file does not tell us what the axes are, just assume...
186        new_plot.xaxis("\\rm{Q}", 'A^{-1}')
187        new_plot.yaxis("\\rm{Intensity} ","cm^{-1}")
188        new_plot.group_id = "SectorQ"+self.base.data2D.name
189        wx.PostEvent(self.base.parent, NewPlotEvent(plot=new_plot,
190                                                 title="SectorQ"+self.base.data2D.name ))
191       
192         
193       
194    def moveend(self, ev):
195        self.base.thaw_axes()
196       
197        # Post paramters
198        event = SlicerParameterEvent()
199        event.type = self.__class__.__name__
200        event.params = self.get_params()
201        wx.PostEvent(self.base.parent, event)
202        self._post_data()
203           
204    def restore(self):
205        """
206        Restore the roughness for this layer.
207        """
208        self.main_line.restore()
209        self.left_line.restore()
210        self.right_line.restore()
211
212    def move(self, x, y, ev):
213        """
214        Process move to a new position, making sure that the move is allowed.
215        """
216        pass
217       
218    def set_cursor(self, x, y):
219        pass
220       
221    def get_params(self):
222        params = {}
223        params["main_phi"] = self.main_line.theta
224        if math.fabs(self.left_line.phi) != math.fabs(self.right_line.phi):
225            raise ValueError,"Phi left and phi right are different %f, %f"%(self.left_line.phi, self.right_line.phi)
226        params["left_phi"] = math.fabs(self.left_line.phi)
227        params["nbins"] = self.nbins
228        return params
229   
230    def set_params(self, params):
231       
232        main = params["main_phi"] 
233        phi = params["left_phi"] 
234        self.nbins = int(params["nbins"])
235        self.main_line.theta= main
236       
237        self.main_line.update()
238        self.right_line.update(phi=-1*phi,delta=None, mline=self.main_line,side=True)
239        self.left_line.update(phi=phi,delta=None, mline=self.main_line,side=True)
240       
241        self._post_data(nbins=self.nbins)
242       
243    def freeze_axes(self):
244        self.base.freeze_axes()
245       
246    def thaw_axes(self):
247        self.base.thaw_axes()
248
249    def draw(self):
250        self.base.draw()
251
252       
253class SideInteractor(_BaseInteractor):
254    """
255         Select an annulus through a 2D plot
256    """
257    def __init__(self,base,axes,color='black', zorder=5, r=1.0,phi=math.pi/4, theta2= math.pi/3):
258       
259        _BaseInteractor.__init__(self, base, axes, color=color)
260        self.markers = []
261        self.axes = axes
262       
263        self.save_theta = theta2 + phi
264        self.theta=  theta2 + phi
265        self.theta2 = theta2
266        self.radius = r
267        self.phi = phi
268        self.scale = 10.0
269        #print "init for line side theta2, phi, theta",math.degrees(theta2),math.degrees(phi),math.degrees(self.theta)
270        #raise "Version error", message
271         
272        # Inner circle
273        x1= self.radius*math.cos(self.theta)
274        y1= self.radius*math.sin(self.theta)
275        x2= -1*self.radius*math.cos(self.theta)
276        y2= -1*self.radius*math.sin(self.theta)
277       
278        self.line = self.axes.plot([x1,x2],[y1,y2],
279                                      linestyle='-', marker='',
280                                      color=self.color,
281                                      visible=True)[0]
282       
283        self.npts = 20
284        self.has_move=False
285        self.connect_markers([self.line])
286        #self.update()
287
288    def set_layer(self, n):
289        self.layernum = n
290        self.update()
291       
292    def clear(self):
293        self.clear_markers()
294        try:
295           
296            self.line.remove()
297        except:
298            # Old version of matplotlib
299            for item in range(len(self.axes.lines)):
300                del self.axes.lines[0]
301       
302       
303       
304    def get_radius(self):
305       
306        return self.theta - self.save_theta
307       
308    def update(self,phi=None,delta=None, mline=None,side=False, left= False, right=False):
309        """
310        Draw the new roughness on the graph.
311        """
312        #print "update left or right ", self.has_move
313       
314        if phi !=None:
315            self.phi = phi
316        if delta==None:
317            delta = 0
318        if side:
319            self.theta=  mline.theta + self.phi
320           
321           
322        if mline!=None:
323            self.theta2 = mline.theta
324            #self.phi= math.fabs(self.theta2 - (self.theta+delta))
325        #print "U:for line side theta2, phi, theta",math.degrees(self.theta2),math.degrees(self.phi),math.degrees(self.theta)
326        #if self.theta2 >= self.theta and self.theta>=0:
327        #    print "between 0-pi",math.degrees(self.theta)
328       
329        x1= self.radius*math.cos(self.theta + delta)
330        y1= self.radius*math.sin(self.theta + delta)
331        x2= -1*self.radius*math.cos(self.theta + delta)
332        y2= -1*self.radius*math.sin(self.theta + delta)
333       
334       
335        self.line.set(xdata=[x1,x2], ydata=[y1,y2]) 
336       
337       
338       
339       
340    def save(self, ev):
341        """
342        Remember the roughness for this layer and the next so that we
343        can restore on Esc.
344        """
345        self.save_theta= self.theta
346        self.base.freeze_axes()
347
348    def moveend(self, ev):
349       
350        self.has_move=False
351        self.base.moveend(ev)
352           
353    def restore(self):
354        """
355        Restore the roughness for this layer.
356        """
357        self.theta = self.save_theta
358
359    def move(self, x, y, ev):
360        """
361        Process move to a new position, making sure that the move is allowed.
362        """
363       
364        self.theta= math.atan2(y,x)
365       
366        self.phi= math.fabs(self.theta2 - self.theta)
367       
368        print "move left or right phi ---theta--thetaM", self.phi, self.theta, self.theta2
369        self.has_move=True
370        self.base.base.update()
371       
372    def set_cursor(self, x, y):
373        self.move(x, y, None)
374        self.update()
375       
376       
377    def get_params(self):
378        params = {}
379        params["radius"] = self.radius
380        params["theta"] = self.theta
381        return params
382   
383    def set_params(self, params):
384
385        x = params["radius"] 
386        self.set_cursor(x, self._inner_mouse_y)
387       
388
389
390       
391       
392class LineInteractor(_BaseInteractor):
393    """
394         Select an annulus through a 2D plot
395    """
396    def __init__(self,base,axes,color='black', zorder=5, r=1.0,theta=math.pi/4):
397       
398        _BaseInteractor.__init__(self, base, axes, color=color)
399        self.markers = []
400        self.axes = axes
401       
402        self.save_theta = theta
403        self.theta= theta
404       
405        self.radius = r
406     
407        self.scale = 10.0
408     
409        #raise "Version error", message
410           
411        # Inner circle
412
413           
414        x1= self.radius*math.cos(self.theta)
415        y1= self.radius*math.sin(self.theta)
416        x2= -1*self.radius*math.cos(self.theta)
417        y2= -1*self.radius*math.sin(self.theta)
418       
419        self.line = self.axes.plot([x1,x2],[y1,y2],
420                                      linestyle='-', marker='',
421                                      color=self.color,
422                                      visible=True)[0]
423     
424        self.npts = 20
425        self.has_move=False
426        self.connect_markers([self.line])
427        self.update()
428
429    def set_layer(self, n):
430        self.layernum = n
431        self.update()
432       
433    def clear(self):
434        self.clear_markers()
435        try:
436           
437            self.line.remove()
438        except:
439            # Old version of matplotlib
440            for item in range(len(self.axes.lines)):
441                del self.axes.lines[0]
442       
443       
444       
445    def get_radius(self):
446       
447        return self.theta - self.save_theta
448       
449    def update(self, theta=None):
450        """
451        Draw the new roughness on the graph.
452        """
453        print "update main line", self.theta
454        if theta !=None:
455            self.theta= theta
456        x1= self.radius*math.cos(self.theta)
457        y1= self.radius*math.sin(self.theta)
458        x2= -1*self.radius*math.cos(self.theta)
459        y2= -1*self.radius*math.sin(self.theta)
460     
461        self.line.set(xdata=[x1,x2], ydata=[y1,y2]) 
462     
463       
464       
465    def save(self, ev):
466        """
467        Remember the roughness for this layer and the next so that we
468        can restore on Esc.
469        """
470        self.save_theta= self.theta
471        self.base.freeze_axes()
472
473    def moveend(self, ev):
474       
475        self.has_move=False
476        self.base.moveend(ev)
477           
478    def restore(self):
479        """
480        Restore the roughness for this layer.
481        """
482        self.theta = self.save_theta
483
484    def move(self, x, y, ev):
485        """
486        Process move to a new position, making sure that the move is allowed.
487        """
488       
489        self.theta= math.atan2(y,x)
490        print "main_line previous theta --- next theta ",math.degrees(self.save_theta),math.degrees(self.theta)
491       
492        self.has_move=True
493        self.base.base.update()
494       
495    def set_cursor(self, x, y):
496        self.move(x, y, None)
497        self.update()
498       
499       
500    def get_params(self):
501        params = {}
502        params["radius"] = self.radius
503        params["theta"] = self.theta
504        return params
505   
506    def set_params(self, params):
507
508        x = params["radius"] 
509        self.set_cursor(x, self._inner_mouse_y)
510       
511
512
513       
Note: See TracBrowser for help on using the repository browser.