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

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

small bugs fixed: clearing slicer improved

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