source: sasview/guiframe/local_perspectives/plotting/AnnulusSlicer.py @ e4032d64

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

phi added on axis label

  • Property mode set to 100644
File size: 10.0 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
16import SlicerParameters
17import wx
18
19class AnnulusInteractor(_BaseInteractor):
20    """
21         Select an annulus through a 2D plot
22    """
23    def __init__(self,base,axes,color='black', zorder=3):
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       
31        ## Number of points on the plot
32        self.nbins = 20
33
34        # Inner circle
35        self.inner_circle = RingInteractor(self, self.base.subplot, zorder=zorder, r=self.qmax/2.0)
36        self.inner_circle.qmax = self.base.qmax
37        self.outer_circle = RingInteractor(self, self.base.subplot, zorder=zorder+1, r=self.qmax/1.8)
38        self.outer_circle.qmax = self.base.qmax*1.2
39        #self.outer_circle.set_cursor(self.base.qmax/1.8, 0)
40       
41                     
42        self.update()
43        self._post_data()
44       
45        # Bind to slice parameter events
46        self.base.parent.Bind(SlicerParameters.EVT_SLICER_PARS, self._onEVT_SLICER_PARS)
47
48
49    def _onEVT_SLICER_PARS(self, event):
50        wx.PostEvent(self.base.parent, StatusEvent(status="AnnulusSlicer._onEVT_SLICER_PARS"))
51        event.Skip()
52        if event.type == self.__class__.__name__:
53            self.set_params(event.params)
54            self.base.update()
55
56    def update_and_post(self):
57        self.update()
58        self._post_data()
59
60    def save_data(self, path, image, x, y):
61        output = open(path, 'w')
62       
63        data_x, data_y = self.get_data(image, x, y)
64       
65        output.write("<phi>  <average>\n")
66        for i in range(len(data_x)):
67            output.write("%g  %g\n" % (data_x[i], data_y[i]))
68        output.close()
69
70    def set_layer(self, n):
71        self.layernum = n
72        self.update()
73       
74    def clear(self):
75        self.clear_markers()
76        self.outer_circle.clear()
77        self.inner_circle.clear()
78        #self.base.connect.disconnect()
79        self.base.parent.Unbind(SlicerParameters.EVT_SLICER_PARS)
80       
81    def update(self):
82        """
83        Respond to changes in the model by recalculating the profiles and
84        resetting the widgets.
85        """
86        # Update locations       
87        self.inner_circle.update()
88        self.outer_circle.update()
89       
90 
91
92    def save(self, ev):
93        """
94        Remember the roughness for this layer and the next so that we
95        can restore on Esc.
96        """
97        self.base.freeze_axes()
98        self.inner_circle.save(ev)
99        self.outer_circle.save(ev)
100
101    def _post_data(self,nbins=None):
102         # Compute data
103        data = self.base.data2D
104        # If we have no data, just return
105        if data == None:
106            return
107       
108        from DataLoader.manipulations import SectorPhi
109        radius = math.sqrt(math.pow(self.qmax,2)+math.pow(self.qmax,2))
110        rmin= self.inner_circle.get_radius()
111        rmax = self.outer_circle.get_radius()
112        phi_min=-math.pi
113        phi_max=math.pi
114        phimi=phi_min+math.pi
115        phima=phi_max+math.pi
116        sect = SectorPhi(r_min=rmin , r_max= rmax, phi_min=phimi, phi_max=phima)
117        if nbins!=None:
118            sect.nbins = nbins
119       
120        sector = sect(self.base.data2D)
121       
122        from sans.guiframe.dataFitting import Data1D
123        if hasattr(sector,"dxl"):
124            dxl= sector.dxl
125        else:
126            dxl= None
127        if hasattr(sector,"dxw"):
128            dxw= sector.dxw
129        else:
130            dxw= None
131       
132        new_plot = Data1D(x=sector.x,y=sector.y,dy=sector.dy,dxl=dxl,dxw=dxw)
133        new_plot.name = "SectorPhi" +"("+ self.base.data2D.name+")"
134       
135       
136       
137        new_plot.source=self.base.data2D.source
138        #new_plot.info=self.base.data2D.info
139        new_plot.interactive = True
140        #print "loader output.detector",output.source
141        new_plot.detector =self.base.data2D.detector
142        # If the data file does not tell us what the axes are, just assume...
143        new_plot.xaxis("\\rm{\phi}", 'rad')
144        new_plot.yaxis("\\rm{Intensity} ","cm^{-1}")
145        new_plot.group_id = "SectorPhi"+self.base.data2D.name
146       
147        wx.PostEvent(self.base.parent, NewPlotEvent(plot=new_plot,
148                                                 title="SectorPhi" ))
149       
150         
151       
152       
153    def moveend(self, ev):
154        self.base.thaw_axes()
155       
156        # Post paramters
157        event = SlicerParameters.SlicerParameterEvent()
158        event.type = self.__class__.__name__
159        event.params = self.get_params()
160        wx.PostEvent(self.base.parent, event)
161
162        self._post_data()
163           
164    def restore(self):
165        """
166        Restore the roughness for this layer.
167        """
168        self.inner_circle.restore()
169        self.outer_circle.restore()
170
171    def move(self, x, y, ev):
172        """
173        Process move to a new position, making sure that the move is allowed.
174        """
175        pass
176       
177    def set_cursor(self, x, y):
178        pass
179       
180    def get_params(self):
181        params = {}
182        params["inner_radius"] = self.inner_circle._inner_mouse_x
183        params["outer_radius"] = self.outer_circle._inner_mouse_x
184        params["nbins"] = self.nbins
185        return params
186   
187    def set_params(self, params):
188       
189        inner = params["inner_radius"] 
190        outer = params["outer_radius"] 
191        self.nbins = int(params["nbins"])
192        self.inner_circle.set_cursor(inner, self.inner_circle._inner_mouse_y)
193        self.outer_circle.set_cursor(outer, self.outer_circle._inner_mouse_y)
194        self._post_data(self.nbins)
195       
196    def freeze_axes(self):
197        self.base.freeze_axes()
198       
199    def thaw_axes(self):
200        self.base.thaw_axes()
201
202    def draw(self):
203        self.base.draw()
204
205       
206class RingInteractor(_BaseInteractor):
207    """
208         Select an annulus through a 2D plot
209    """
210    def __init__(self,base,axes,color='black', zorder=5, r=1.0):
211       
212        _BaseInteractor.__init__(self, base, axes, color=color)
213        self.markers = []
214        self.axes = axes
215        self._inner_mouse_x = r
216        self._inner_mouse_y = 0
217        self._inner_save_x  = r
218        self._inner_save_y  = 0
219        self.scale = 10.0
220       
221        try:
222            # Inner circle marker
223            self.inner_marker = self.axes.plot([self._inner_mouse_x],[0], linestyle='',
224                                          marker='s', markersize=10,
225                                          color=self.color, alpha=0.6,
226                                          pickradius=5, label="pick", 
227                                          zorder=zorder, # Prefer this to other lines
228                                          visible=True)[0]
229        except:
230            self.inner_marker = self.axes.plot([self._inner_mouse_x],[0], linestyle='',
231                                          marker='s', markersize=10,
232                                          color=self.color, alpha=0.6,
233                                          label="pick", 
234                                          visible=True)[0]
235            message  = "\nTHIS PROTOTYPE NEEDS THE LATEST VERSION OF MATPLOTLIB\n"
236            message += "Get the SVN version that is at least as recent as June 1, 2007"
237           
238            #raise "Version error", message
239           
240        # Inner circle
241
242           
243        [self.inner_circle] = self.axes.plot([],[],
244                                      linestyle='-', marker='',
245                                      color=self.color)
246        self.npts = 40
247           
248        self.connect_markers([self.inner_marker])
249        self.update()
250
251    def set_layer(self, n):
252        self.layernum = n
253        self.update()
254       
255    def clear(self):
256        self.clear_markers()
257        try:
258            self.inner_marker.remove()
259            self.inner_circle.remove()
260        except:
261            # Old version of matplotlib
262            for item in range(len(self.axes.lines)):
263                del self.axes.lines[0]
264       
265       
266       
267    def get_radius(self):
268        return self._inner_mouse_x
269       
270    def update(self):
271        """
272        Draw the new roughness on the graph.
273        """
274        # Plot inner circle
275        x = []
276        y = []
277        for i in range(self.npts):
278            phi = 2.0*math.pi/(self.npts-1)*i
279           
280            xval = 1.0*self._inner_mouse_x*math.cos(phi) 
281            yval = 1.0*self._inner_mouse_x*math.sin(phi) 
282           
283            x.append(xval)
284            y.append(yval)
285       
286        self.inner_marker.set(xdata=[self._inner_mouse_x],ydata=[0])
287        self.inner_circle.set_data(x, y)       
288
289    def save(self, ev):
290        """
291        Remember the roughness for this layer and the next so that we
292        can restore on Esc.
293        """
294        self._inner_save_x = self._inner_mouse_x
295        self._inner_save_y = self._inner_mouse_y
296        self.base.freeze_axes()
297
298    def moveend(self, ev):
299        self.base.moveend(ev)
300           
301    def restore(self):
302        """
303        Restore the roughness for this layer.
304        """
305        self._inner_mouse_x = self._inner_save_x
306        self._inner_mouse_y = self._inner_save_y
307
308    def move(self, x, y, ev):
309        """
310        Process move to a new position, making sure that the move is allowed.
311        """
312        self._inner_mouse_x = x
313        self._inner_mouse_y = y
314        self.base.base.update()
315       
316    def set_cursor(self, x, y):
317        self.move(x, y, None)
318        self.update()
319       
320       
321    def get_params(self):
322        params = {}
323        params["radius"] = self._inner_mouse_x
324        return params
325   
326    def set_params(self, params):
327
328        x = params["radius"] 
329        self.set_cursor(x, self._inner_mouse_y)
330       
331       
Note: See TracBrowser for help on using the repository browser.