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

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

sector averaging

  • Property mode set to 100644
File size: 8.3 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
10
11from BaseInteractor import _BaseInteractor
12from copy import deepcopy
13import math
14
15
16import SlicerParameters
17import wx
18
19class SectorInteractor(_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        theta1=math.pi/8
34        theta2=math.pi/2
35        r1=self.qmax/2.0
36        r2=self.qmax/1.8
37        # Inner circle
38        from Arc import ArcInteractor
39        self.inner_circle = ArcInteractor(self, self.base.subplot, zorder=zorder, r=self.qmax/2.0,theta1= theta1,
40                                           theta2=theta2)
41        self.inner_circle.qmax = self.base.qmax
42        self.outer_circle = ArcInteractor(self, self.base.subplot, zorder=zorder+1, r=self.qmax/1.8,theta1= theta1,
43                                           theta2=theta2)
44        self.outer_circle.qmax = self.base.qmax*1.2
45        #self.outer_circle.set_cursor(self.base.qmax/1.8, 0)
46        from Edge import RadiusInteractor
47        self.inner_radius= RadiusInteractor(self, self.base.subplot, zorder=zorder+1,
48                                             arc1=self.inner_circle,
49                                             arc2=self.outer_circle,
50                                            theta=math.pi/8)
51        self.outer_radius= RadiusInteractor(self, self.base.subplot, zorder=zorder+1,
52                                             arc1=self.inner_circle,
53                                             arc2=self.outer_circle,
54                                            theta=math.pi/2)
55        self.update()
56        #self._post_data()
57       
58        # Bind to slice parameter events
59        #self.base.parent.Bind(SlicerParameters.EVT_SLICER_PARS, self._onEVT_SLICER_PARS)
60
61
62    def _onEVT_SLICER_PARS(self, event):
63        #printEVT("AnnulusSlicer._onEVT_SLICER_PARS")
64        event.Skip()
65        if event.type == self.__class__.__name__:
66            self.set_params(event.params)
67            self.base.update()
68
69    def update_and_post(self):
70        self.update()
71        self._post_data()
72
73    def save_data(self, path, image, x, y):
74        output = open(path, 'w')
75       
76        data_x, data_y = self.get_data(image, x, y)
77       
78        output.write("<phi>  <average>\n")
79        for i in range(len(data_x)):
80            output.write("%g  %g\n" % (data_x[i], data_y[i]))
81        output.close()
82
83    def set_layer(self, n):
84        self.layernum = n
85        self.update()
86       
87    def clear(self):
88        self.clear_markers()
89        #self.outer_circle.clear()
90        self.inner_circle.clear()
91        #self.base.connect.disconnect()
92        self.base.parent.Unbind(SlicerParameters.EVT_SLICER_PARS)
93       
94    def update(self):
95        """
96        Respond to changes in the model by recalculating the profiles and
97        resetting the widgets.
98        """
99        # Update locations       
100        self.inner_circle.update()
101        self.outer_circle.update()
102        r1=self.inner_circle.get_radius()
103        r2=self.outer_circle.get_radius()
104        print"annulus update",r1, r2
105        if self.inner_radius.update(r1,r2)==1:
106            print "went here"
107            self.inner_circle.update(theta1=self.inner_radius.get_radius(), theta2=None)
108            self.outer_circle.update(theta1=self.inner_radius.get_radius(),theta2=None)
109        if self.outer_radius.update(r1,r2)==1:
110             #self.outer_circle.update(self.outer_radius.get_radius())
111             self.inner_circle.update(theta1=None, theta2=self.outer_radius.get_radius())
112             self.outer_circle.update(theta1=None,theta2=self.outer_radius.get_radius())
113    def get_data(self, image, x, y):
114        """
115            Return a 1D vector corresponding to the slice
116            @param image: data matrix
117            @param x: x matrix
118            @param y: y matrix
119        """
120        # If we have no data, just return
121        if image == None:
122            return       
123       
124        nbins = self.nbins
125       
126        data_x = nbins*[0]
127        data_y = nbins*[0]
128        counts = nbins*[0]
129        length = len(image)
130       
131       
132        for i_x in range(length):
133            for i_y in range(length):
134                       
135                q = math.sqrt(x[i_x]*x[i_x] + y[i_y]*y[i_y])
136                if (q>self.inner_circle._inner_mouse_x \
137                    and q<self.outer_circle._inner_mouse_x) \
138                    or (q<self.inner_circle._inner_mouse_x \
139                    and q>self.outer_circle._inner_mouse_x):
140                           
141                    i_bin = int(math.ceil(nbins*(math.atan2(y[i_y], x[i_x])+math.pi)/(2.0*math.pi)) - 1)
142                   
143                   
144                    #data_y[i_bin] += math.exp(image[i_x][i_y])
145                    data_y[i_bin] += image[i_y][i_x]
146                    counts[i_bin] += 1.0
147                   
148        for i in range(nbins):
149            data_x[i] = (1.0*i+0.5)*2.0*math.pi/nbins
150            if counts[i]>0:
151                data_y[i] = data_y[i]/counts[i]
152       
153        return data_x, data_y
154
155    def save(self, ev):
156        """
157        Remember the roughness for this layer and the next so that we
158        can restore on Esc.
159        """
160        self.base.freeze_axes()
161        self.inner_circle.save(ev)
162        #self.outer_circle.save(ev)
163
164    def _post_data(self):
165        # Compute data
166        data = self.base.get_corrected_data()
167        # If we have no data, just return
168        if data == None:
169            return
170
171        data_x, data_y = self.get_data(data, self.base.x, self.base.y)
172       
173        name = "Ring"
174        if hasattr(self.base, "name"):
175            name += " %s" % self.base.name
176       
177        wx.PostEvent(self.base.parent, AddPlotEvent(name=name,
178                                               x = data_x,
179                                               y = data_y,
180                                               qmin = self.inner_circle._inner_mouse_x,
181                                               qmax = self.outer_circle._inner_mouse_x,
182                                               yscale = 'log',
183                                               variable = 'ANGLE',
184                                               ylabel = "\\rm{Intensity} ",
185                                               yunits = "cm^{-1}",
186                                               xlabel = "\\rm{\phi}",
187                                               xunits = "rad",
188                                               parent = self.base.__class__.__name__))
189                                               
190       
191    def moveend(self, ev):
192        self.base.thaw_axes()
193       
194        # Post paramters
195        event = SlicerParameters.SlicerParameterEvent()
196        event.type = self.__class__.__name__
197        event.params = self.get_params()
198        wx.PostEvent(self.base.parent, event)
199
200        self._post_data()
201           
202    def restore(self):
203        """
204        Restore the roughness for this layer.
205        """
206        self.inner_circle.restore()
207        #self.outer_circle.restore()
208
209    def move(self, x, y, ev):
210        """
211        Process move to a new position, making sure that the move is allowed.
212        """
213        pass
214       
215    def set_cursor(self, x, y):
216        pass
217       
218    def get_params(self):
219        params = {}
220        params["inner_radius"] = self.inner_circle._inner_mouse_x
221        #params["outer_radius"] = self.outer_circle._inner_mouse_x
222        params["nbins"] = self.nbins
223        return params
224   
225    def set_params(self, params):
226       
227        inner = params["inner_radius"] 
228        #outer = params["outer_radius"]
229        self.nbins = int(params["nbins"])
230        self.inner_circle.set_cursor(inner, self.inner_circle._inner_mouse_y)
231        #self.outer_circle.set_cursor(outer, self.outer_circle._inner_mouse_y)
232        self._post_data()
233       
234    def freeze_axes(self):
235        self.base.freeze_axes()
236       
237    def thaw_axes(self):
238        self.base.thaw_axes()
239
240    def draw(self):
241        self.base.draw()
242
243   
Note: See TracBrowser for help on using the repository browser.