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

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

qmax redefined for sector

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