source: sasview/guiframe/local_perspectives/plotting/ring.py @ 1ce365f8

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 1ce365f8 was 0d9dae8, checked in by Gervaise Alina <gervyh@…>, 16 years ago

add a new module containing common classes that I used often:
sans.guiframe.utils

remove event slicer and add it in sans.guicoom.events,
modified slicer for those events

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