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