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

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

small change on annulus

  • Property mode set to 100644
File size: 9.9 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        sect = SectorPhi(r_min=rmin , r_max= rmax, phi_min=-1*math.pi, phi_max=math.pi)
113        if nbins!=None:
114            sect.nbins = nbins
115       
116        sector = sect(self.base.data2D)
117       
118        from sans.guiframe.dataFitting import Data1D
119        if hasattr(sector,"dxl"):
120            dxl= sector.dxl
121        else:
122            dxl= None
123        if hasattr(sector,"dxw"):
124            dxw= sector.dxw
125        else:
126            dxw= None
127       
128        new_plot = Data1D(x=sector.x,y=sector.y,dy=sector.dy,dxl=dxl,dxw=dxw)
129        new_plot.name = "SectorPhi" +"("+ self.base.data2D.name+")"
130       
131       
132
133        new_plot.source=self.base.data2D.source
134        new_plot.info=self.base.data2D.info
135        new_plot.interactive = True
136        #print "loader output.detector",output.source
137        new_plot.detector =self.base.data2D.detector
138        # If the data file does not tell us what the axes are, just assume...
139        new_plot.xaxis("\\rm{Q}", 'rad')
140        new_plot.yaxis("\\rm{Intensity} ","cm^{-1}")
141        new_plot.group_id = "SectorPhi"+self.base.data2D.name
142        wx.PostEvent(self.base.parent, NewPlotEvent(plot=new_plot,
143                                                 title="SectorPhi" ))
144       
145         
146       
147       
148    def moveend(self, ev):
149        self.base.thaw_axes()
150       
151        # Post paramters
152        event = SlicerParameters.SlicerParameterEvent()
153        event.type = self.__class__.__name__
154        event.params = self.get_params()
155        wx.PostEvent(self.base.parent, event)
156
157        self._post_data()
158           
159    def restore(self):
160        """
161        Restore the roughness for this layer.
162        """
163        self.inner_circle.restore()
164        self.outer_circle.restore()
165
166    def move(self, x, y, ev):
167        """
168        Process move to a new position, making sure that the move is allowed.
169        """
170        pass
171       
172    def set_cursor(self, x, y):
173        pass
174       
175    def get_params(self):
176        params = {}
177        params["inner_radius"] = self.inner_circle._inner_mouse_x
178        params["outer_radius"] = self.outer_circle._inner_mouse_x
179        params["nbins"] = self.nbins
180        return params
181   
182    def set_params(self, params):
183       
184        inner = params["inner_radius"] 
185        outer = params["outer_radius"] 
186        self.nbins = int(params["nbins"])
187        self.inner_circle.set_cursor(inner, self.inner_circle._inner_mouse_y)
188        self.outer_circle.set_cursor(outer, self.outer_circle._inner_mouse_y)
189        self._post_data(self.nbins)
190       
191    def freeze_axes(self):
192        self.base.freeze_axes()
193       
194    def thaw_axes(self):
195        self.base.thaw_axes()
196
197    def draw(self):
198        self.base.draw()
199
200       
201class RingInteractor(_BaseInteractor):
202    """
203         Select an annulus through a 2D plot
204    """
205    def __init__(self,base,axes,color='black', zorder=5, r=1.0):
206       
207        _BaseInteractor.__init__(self, base, axes, color=color)
208        self.markers = []
209        self.axes = axes
210        self._inner_mouse_x = r
211        self._inner_mouse_y = 0
212        self._inner_save_x  = r
213        self._inner_save_y  = 0
214        self.scale = 10.0
215       
216        try:
217            # Inner circle marker
218            self.inner_marker = self.axes.plot([self._inner_mouse_x],[0], linestyle='',
219                                          marker='s', markersize=10,
220                                          color=self.color, alpha=0.6,
221                                          pickradius=5, label="pick", 
222                                          zorder=zorder, # Prefer this to other lines
223                                          visible=True)[0]
224        except:
225            self.inner_marker = self.axes.plot([self._inner_mouse_x],[0], linestyle='',
226                                          marker='s', markersize=10,
227                                          color=self.color, alpha=0.6,
228                                          label="pick", 
229                                          visible=True)[0]
230            message  = "\nTHIS PROTOTYPE NEEDS THE LATEST VERSION OF MATPLOTLIB\n"
231            message += "Get the SVN version that is at least as recent as June 1, 2007"
232           
233            #raise "Version error", message
234           
235        # Inner circle
236
237           
238        [self.inner_circle] = self.axes.plot([],[],
239                                      linestyle='-', marker='',
240                                      color=self.color)
241        self.npts = 20
242           
243        self.connect_markers([self.inner_marker])
244        self.update()
245
246    def set_layer(self, n):
247        self.layernum = n
248        self.update()
249       
250    def clear(self):
251        self.clear_markers()
252        try:
253            self.inner_marker.remove()
254            self.inner_circle.remove()
255        except:
256            # Old version of matplotlib
257            for item in range(len(self.axes.lines)):
258                del self.axes.lines[0]
259       
260       
261       
262    def get_radius(self):
263        return self._inner_mouse_x
264       
265    def update(self):
266        """
267        Draw the new roughness on the graph.
268        """
269        # Plot inner circle
270        x = []
271        y = []
272        for i in range(self.npts):
273            phi = 2.0*math.pi/(self.npts-1)*i
274           
275            xval = 1.0*self._inner_mouse_x*math.cos(phi) 
276            yval = 1.0*self._inner_mouse_x*math.sin(phi) 
277           
278            x.append(xval)
279            y.append(yval)
280       
281        self.inner_marker.set(xdata=[self._inner_mouse_x],ydata=[0])
282        self.inner_circle.set_data(x, y)       
283
284    def save(self, ev):
285        """
286        Remember the roughness for this layer and the next so that we
287        can restore on Esc.
288        """
289        self._inner_save_x = self._inner_mouse_x
290        self._inner_save_y = self._inner_mouse_y
291        self.base.freeze_axes()
292
293    def moveend(self, ev):
294        self.base.moveend(ev)
295           
296    def restore(self):
297        """
298        Restore the roughness for this layer.
299        """
300        self._inner_mouse_x = self._inner_save_x
301        self._inner_mouse_y = self._inner_save_y
302
303    def move(self, x, y, ev):
304        """
305        Process move to a new position, making sure that the move is allowed.
306        """
307        self._inner_mouse_x = x
308        self._inner_mouse_y = y
309        self.base.base.update()
310       
311    def set_cursor(self, x, y):
312        self.move(x, y, None)
313        self.update()
314       
315       
316    def get_params(self):
317        params = {}
318        params["radius"] = self._inner_mouse_x
319        return params
320   
321    def set_params(self, params):
322
323        x = params["radius"] 
324        self.set_cursor(x, self._inner_mouse_y)
325       
326       
Note: See TracBrowser for help on using the repository browser.