source: sasview/guiframe/local_perspectives/plotting/ring.py @ 54cc36a

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 54cc36a was ffd23b5, checked in by Gervaise Alina <gervyh@…>, 15 years ago
  • Property mode set to 100644
File size: 10.8 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 config import printEVT
11from BaseInteractor import _BaseInteractor
12from copy import deepcopy
13import math
14
15from Plotter1D import AddPlotEvent
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.data2D.xmax
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.qmax
37     
38        #self.outer_circle.set_cursor(self.base.qmax/1.8, 0)
39       
40                     
41        self.update()
42        self._post_data()
43       
44        # Bind to slice parameter events
45        self.base.parent.Bind(SlicerParameters.EVT_SLICER_PARS, self._onEVT_SLICER_PARS)
46
47
48    def _onEVT_SLICER_PARS(self, event):
49        printEVT("AnnulusSlicer._onEVT_SLICER_PARS")
50        event.Skip()
51        if event.type == self.__class__.__name__:
52            self.set_params(event.params)
53            self.base.update()
54
55    def update_and_post(self):
56        self.update()
57        self._post_data()
58
59    def save_data(self, path, image, x, y):
60        output = open(path, 'w')
61       
62        data_x, data_y = self.get_data(image, x, y)
63       
64        output.write("<phi>  <average>\n")
65        for i in range(len(data_x)):
66            output.write("%g  %g\n" % (data_x[i], data_y[i]))
67        output.close()
68
69    def set_layer(self, n):
70        self.layernum = n
71        self.update()
72       
73    def clear(self):
74        self.clear_markers()
75       
76        self.inner_circle.clear()
77        #self.base.connect.disconnect()
78        self.base.parent.Unbind(SlicerParameters.EVT_SLICER_PARS)
79       
80    def update(self):
81        """
82        Respond to changes in the model by recalculating the profiles and
83        resetting the widgets.
84        """
85        # Update locations       
86        self.inner_circle.update()
87       
88       
89       
90    def get_data(self, image, x, y):
91        """
92            Return a 1D vector corresponding to the slice
93            @param image: data matrix
94            @param x: x matrix
95            @param y: y matrix
96        """
97        # If we have no data, just return
98        if image == None:
99            return       
100       
101        nbins = self.nbins
102       
103        data_x = nbins*[0]
104        data_y = nbins*[0]
105        counts = nbins*[0]
106        length = len(image)
107        print "length x , y , image", len(x), len(y), length
108       
109        for i_x in range(length):
110            for i_y in range(length):
111                       
112                q = math.sqrt(x[i_x]*x[i_x] + y[i_y]*y[i_y])
113                if (q>self.inner_circle._inner_mouse_x \
114                    and q<self.outer_circle._inner_mouse_x) \
115                    or (q<self.inner_circle._inner_mouse_x \
116                    and q>self.outer_circle._inner_mouse_x):
117                           
118                    i_bin = int(math.ceil(nbins*(math.atan2(y[i_y], x[i_x])+math.pi)/(2.0*math.pi)) - 1)
119                   
120                   
121                    #data_y[i_bin] += math.exp(image[i_x][i_y])
122                    data_y[i_bin] += image[i_y][i_x]
123                    counts[i_bin] += 1.0
124                   
125        for i in range(nbins):
126            data_x[i] = (1.0*i+0.5)*2.0*math.pi/nbins
127            if counts[i]>0:
128                data_y[i] = data_y[i]/counts[i]
129       
130        return data_x, data_y
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       
140
141    def _post_data(self):
142        # Compute data
143        data = self.base.get_corrected_data()
144        # If we have no data, just return
145        if data == None:
146            return
147
148        data_x, data_y = self.get_data(data, self.base.x, self.base.y)
149       
150        name = "Ring"
151        if hasattr(self.base, "name"):
152            name += " %s" % self.base.name
153       
154        wx.PostEvent(self.base.parent, AddPlotEvent(name=name,
155                                               x = data_x,
156                                               y = data_y,
157                                               qmin = self.inner_circle._inner_mouse_x,
158                                               qmax = self.outer_circle._inner_mouse_x,
159                                               yscale = 'log',
160                                               variable = 'ANGLE',
161                                               ylabel = "\\rm{Intensity} ",
162                                               yunits = "cm^{-1}",
163                                               xlabel = "\\rm{\phi}",
164                                               xunits = "rad",
165                                               parent = self.base.__class__.__name__))
166                                               
167       
168    def moveend(self, ev):
169        self.base.thaw_axes()
170       
171        # Post paramters
172        event = SlicerParameters.SlicerParameterEvent()
173        event.type = self.__class__.__name__
174        event.params = self.get_params()
175        wx.PostEvent(self.base.parent, event)
176
177        self._post_data()
178           
179    def restore(self):
180        """
181        Restore the roughness for this layer.
182        """
183        self.inner_circle.restore()
184     
185
186    def move(self, x, y, ev):
187        """
188        Process move to a new position, making sure that the move is allowed.
189        """
190        pass
191       
192    def set_cursor(self, x, y):
193        pass
194       
195    def get_params(self):
196        params = {}
197        params["inner_radius"] = self.inner_circle._inner_mouse_x
198       
199        params["nbins"] = self.nbins
200        return params
201   
202    def set_params(self, params):
203       
204        inner = params["inner_radius"] 
205       
206        self.nbins = int(params["nbins"])
207        self.inner_circle.set_cursor(inner, self.inner_circle._inner_mouse_y)
208       
209        self._post_data()
210       
211    def freeze_axes(self):
212        self.base.freeze_axes()
213       
214    def thaw_axes(self):
215        self.base.thaw_axes()
216
217    def draw(self):
218        self.base.draw()
219
220       
221class RingInteractor(_BaseInteractor):
222    """
223         Select an annulus through a 2D plot
224    """
225    def __init__(self,base,axes,color='black', zorder=5, r=1.0):
226       
227        _BaseInteractor.__init__(self, base, axes, color=color)
228        self.markers = []
229        self.axes = axes
230        self._inner_mouse_x = r
231        self._inner_mouse_y = 0
232        self._inner_save_x  = r
233        self._inner_save_y  = 0
234        self.scale = 10.0
235       
236        try:
237            # Inner circle marker
238            self.inner_marker = self.axes.plot([self._inner_mouse_x],[0], linestyle='',
239                                          marker='s', markersize=10,
240                                          color=self.color, alpha=0.6,
241                                          pickradius=5, label="pick", 
242                                          zorder=zorder, # Prefer this to other lines
243                                          visible=True)[0]
244        except:
245            self.inner_marker = self.axes.plot([self._inner_mouse_x],[0], linestyle='',
246                                          marker='s', markersize=10,
247                                          color=self.color, alpha=0.6,
248                                          label="pick", 
249                                          visible=True)[0]
250            message  = "\nTHIS PROTOTYPE NEEDS THE LATEST VERSION OF MATPLOTLIB\n"
251            message += "Get the SVN version that is at least as recent as June 1, 2007"
252           
253            #raise "Version error", message
254           
255        # Inner circle
256
257           
258        [self.inner_circle] = self.axes.plot([],[],
259                                      linestyle='-', marker='',
260                                      color=self.color)
261        self.npts = 20
262           
263        self.connect_markers([self.inner_marker])
264        self.update()
265
266    def set_layer(self, n):
267        self.layernum = n
268        self.update()
269       
270    def clear(self):
271        self.clear_markers()
272        try:
273            self.inner_marker.remove()
274            self.inner_circle.remove()
275        except:
276            # Old version of matplotlib
277            for item in range(len(self.axes.lines)):
278                del self.axes.lines[0]
279       
280       
281       
282    def get_radius(self):
283        return self._inner_mouse_x
284       
285    def update(self):
286        """
287        Draw the new roughness on the graph.
288        """
289        # Plot inner circle
290        x = []
291        y = []
292        for i in range(self.npts):
293            phi = 2.0*math.pi/(self.npts-1)*i
294           
295            xval = 1.0*self._inner_mouse_x*math.cos(phi) 
296            yval = 1.0*self._inner_mouse_x*math.sin(phi) 
297           
298            x.append(xval)
299            y.append(yval)
300       
301        self.inner_marker.set(xdata=[self._inner_mouse_x],ydata=[0])
302        self.inner_circle.set_data(x, y)       
303
304    def save(self, ev):
305        """
306        Remember the roughness for this layer and the next so that we
307        can restore on Esc.
308        """
309        self._inner_save_x = self._inner_mouse_x
310        self._inner_save_y = self._inner_mouse_y
311        self.base.freeze_axes()
312
313    def moveend(self, ev):
314        self.base.moveend(ev)
315           
316    def restore(self):
317        """
318        Restore the roughness for this layer.
319        """
320        self._inner_mouse_x = self._inner_save_x
321        self._inner_mouse_y = self._inner_save_y
322
323    def move(self, x, y, ev):
324        """
325        Process move to a new position, making sure that the move is allowed.
326        """
327        self._inner_mouse_x = x
328        self._inner_mouse_y = y
329        self.base.base.update()
330       
331    def set_cursor(self, x, y):
332        self.move(x, y, None)
333        self.update()
334       
335       
336    def get_params(self):
337        params = {}
338        params["radius"] = self._inner_mouse_x
339        return params
340   
341    def set_params(self, params):
342
343        x = params["radius"] 
344        self.set_cursor(x, self._inner_mouse_y)
345       
346       
Note: See TracBrowser for help on using the repository browser.