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

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

working on history panel

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