source: sasview/guiframe/local_perspectives/plotting/SectorSlicer.py @ a5aaec9

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 a5aaec9 was e23a20c, checked in by Jae Cho <jhjcho@…>, 16 years ago

Some bugs in SectorSlicer?.py are removed.
: fixed update problem when the sector lines move below the horizon.
: fixed the unit of x-axis.
: fixed error when moving left (right)lines every other times.
: made the sector lines longer enough to cover whole region of 2D data (in q space).

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