source: sasview/guiframe/local_perspectives/plotting/boxSlicer.py @ 2d107b8

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

small changes circular averaging

  • Property mode set to 100644
File size: 15.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 config import printEVT
11from BaseInteractor import _BaseInteractor
12from copy import deepcopy
13import math
14
15from Plotter1D import AddPlotEvent
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, x_min=0.025, x_max=0.025, y_min=0.025, y_max=0.025):
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        self.xmin=xmin
31        self.ymin=ymin
32        self.xmax=xmax
33        self.ymax=ymax
34        ## Number of points on the plot
35        self.nbins = 20
36       
37        #self.theta3= 2*self.theta2 -self.theta1
38        # Inner circle
39        self.left_line = VerticalLine(self, self.base.subplot,color='blue', zorder=zorder, 
40                                        ymin=-1*self.ymin, ymax=self.ymax,
41                                        xmin=-1*self.xmin,xmax=-1*self.xmax)
42        self.left_line.qmax = self.base.qmax
43       
44        self.right_line= VerticalLine(self, self.base.subplot,color='black', zorder=zorder,
45                                     ymin=-1*self.ymin, ymax=self.ymax,
46                                     xmin=self.xmin,xmax=self.xmax)
47        self.right_line.qmax = self.base.qmax
48       
49        self.top_line= HorizontalLine(self, self.base.subplot,color='green', zorder=zorder,
50                                    ymin=self.ymax, ymax=self.ymax,
51                                    xmin=-1*self.xmax,xmax=self.xmax)
52        self.top_line.qmax = self.base.qmax
53       
54        self.bottom_line= HorizontalLine(self, self.base.subplot,color='red', zorder=zorder,
55                                    ymin=-1*self.ymin, ymax=-1*self.ymin,
56                                    xmin=-1*self.xmin,xmax=self.xmin)
57        self.bottom_line.qmax = self.base.qmax
58        #self.outer_circle.set_cursor(self.base.qmax/1.8, 0)
59       
60                     
61        #self.update()
62        self._post_data()
63       
64        # Bind to slice parameter events
65        self.base.parent.Bind(SlicerParameters.EVT_SLICER_PARS, self._onEVT_SLICER_PARS)
66
67
68    def _onEVT_SLICER_PARS(self, event):
69        printEVT("AnnulusSlicer._onEVT_SLICER_PARS")
70        event.Skip()
71        if event.type == self.__class__.__name__:
72            #self.set_params(event.params)
73            self.base.update()
74
75    def update_and_post(self):
76        self.update()
77        self._post_data()
78
79    def save_data(self, path, image, x, y):
80        output = open(path, 'w')
81       
82        data_x, data_y = self.get_data(image, x, y)
83       
84        output.write("<phi>  <average>\n")
85        for i in range(len(data_x)):
86            output.write("%g  %g\n" % (data_x[i], data_y[i]))
87        output.close()
88
89    def set_layer(self, n):
90        self.layernum = n
91        self.update()
92       
93    def clear(self):
94        self.clear_markers()
95        self.outer_circle.clear()
96        self.inner_circle.clear()
97        #self.base.connect.disconnect()
98        self.base.parent.Unbind(SlicerParameters.EVT_SLICER_PARS)
99       
100    def update(self):
101        """
102        Respond to changes in the model by recalculating the profiles and
103        resetting the widgets.
104        """
105        if self.left_line.has_move:
106            print "left has moved"
107            self.left_line.update()
108            self.right_line.update()
109            #self.right_line.update(xmin= self.left_line.x ,xmax=-1*self.left_line.x)
110            self.top_line.update( xmin= self.left_line.x ,xmax= self.right_line.x)
111            self.bottom_line.update(xmin= self.left_line.x ,xmax= self.right_line.x)
112        if self.right_line.has_move:
113            print "right has moved"
114            self.right_line.update()
115            self.left_line.update()
116            #self.left_line.update(xmin= self.right_line.x ,xmax=-1*self.right_line.x)
117            self.top_line.update( xmin= self.left_line.x ,xmax= self.right_line.x)
118            self.bottom_line.update(xmin= self.left_line.x ,xmax= self.right_line.x)
119           
120           
121        if self.bottom_line.has_move:
122            print "bottom has moved"
123            self.bottom_line.update()
124            self.top_line.update()
125            #self.top_line.update(ymin= -1*self.bottom_line.y ,ymax=-1*self.bottom_line.y)
126            self.left_line.update( ymin= self.bottom_line.y ,ymax= self.top_line.y)
127            self.right_line.update(ymin= self.bottom_line.y ,ymax= self.top_line.y)
128           
129        if self.top_line.has_move:
130            print "top has moved"
131            self.top_line.update()
132            #self.bottom_line.update()
133            self.bottom_line.update(ymin= -1*self.top_line.y ,ymax=-1*self.top_line.y)
134            self.left_line.update(ymin= self.bottom_line.y ,ymax= self.top_line.y)
135            self.right_line.update(ymin= self.bottom_line.y ,ymax= self.top_line.y)
136           
137    def get_data(self, image, x, y):
138        """
139            Return a 1D vector corresponding to the slice
140            @param image: data matrix
141            @param x: x matrix
142            @param y: y matrix
143        """
144        # If we have no data, just return
145        if image == None:
146            return       
147       
148        nbins = self.nbins
149       
150        data_x = nbins*[0]
151        data_y = nbins*[0]
152        counts = nbins*[0]
153        length = len(image)
154        print "length x , y , image", len(x), len(y), length
155       
156        for i_x in range(length):
157            for i_y in range(length):
158                       
159                q = math.sqrt(x[i_x]*x[i_x] + y[i_y]*y[i_y])
160                if (q>self.inner_circle._inner_mouse_x \
161                    and q<self.outer_circle._inner_mouse_x) \
162                    or (q<self.inner_circle._inner_mouse_x \
163                    and q>self.outer_circle._inner_mouse_x):
164                           
165                    i_bin = int(math.ceil(nbins*(math.atan2(y[i_y], x[i_x])+math.pi)/(2.0*math.pi)) - 1)
166                   
167                   
168                    #data_y[i_bin] += math.exp(image[i_x][i_y])
169                    data_y[i_bin] += image[i_y][i_x]
170                    counts[i_bin] += 1.0
171                   
172        for i in range(nbins):
173            data_x[i] = (1.0*i+0.5)*2.0*math.pi/nbins
174            if counts[i]>0:
175                data_y[i] = data_y[i]/counts[i]
176       
177        return data_x, data_y
178
179    def save(self, ev):
180        """
181        Remember the roughness for this layer and the next so that we
182        can restore on Esc.
183        """
184        self.base.freeze_axes()
185        self.inner_circle.save(ev)
186        self.outer_circle.save(ev)
187
188    def _post_data(self):
189        # Compute data
190        data = self.base.get_corrected_data()
191        # If we have no data, just return
192        if data == None:
193            return
194
195        data_x, data_y = self.get_data(data, self.base.x, self.base.y)
196       
197        name = "Ring"
198        if hasattr(self.base, "name"):
199            name += " %s" % self.base.name
200       
201        wx.PostEvent(self.base.parent, AddPlotEvent(name=name,
202                                               x = data_x,
203                                               y = data_y,
204                                               qmin = self.inner_circle._inner_mouse_x,
205                                               qmax = self.outer_circle._inner_mouse_x,
206                                               yscale = 'log',
207                                               variable = 'ANGLE',
208                                               ylabel = "\\rm{Intensity} ",
209                                               yunits = "cm^{-1}",
210                                               xlabel = "\\rm{\phi}",
211                                               xunits = "rad",
212                                               parent = self.base.__class__.__name__))
213                                               
214       
215    def moveend(self, ev):
216        self.base.thaw_axes()
217       
218        # Post paramters
219        event = SlicerParameters.SlicerParameterEvent()
220        event.type = self.__class__.__name__
221        #event.params = self.get_params()
222        wx.PostEvent(self.base.parent, event)
223
224        self._post_data()
225           
226    def restore(self):
227        """
228        Restore the roughness for this layer.
229        """
230        self.inner_circle.restore()
231        self.outer_circle.restore()
232
233    def move(self, x, y, ev):
234        """
235        Process move to a new position, making sure that the move is allowed.
236        """
237        pass
238       
239    def set_cursor(self, x, y):
240        pass
241       
242    def get_params(self):
243        params = {}
244        #params["main_phi"] = self.right_line.get_radius()
245        #params["left_phi"] = self.left_line.get_radius()
246       
247        params["nbins"] = self.nbins
248        return params
249   
250    def set_params(self, params):
251       
252        main = params["main_phi"] 
253        left = params["left_phi"] 
254       
255        self.nbins = int(params["nbins"])
256        #self.main_line.set_cursor(inner, self.inner_circle._inner_mouse_y)
257        #self.outer_circle.set_cursor(outer, self.outer_circle._inner_mouse_y)
258        self._post_data()
259       
260    def freeze_axes(self):
261        self.base.freeze_axes()
262       
263    def thaw_axes(self):
264        self.base.thaw_axes()
265
266    def draw(self):
267        self.base.draw()
268
269class HorizontalLine(_BaseInteractor):
270    """
271         Select an annulus through a 2D plot
272    """
273    def __init__(self,base,axes,color='black', zorder=5, ymin=0.0, ymax=0.5,xmin=0.0,xmax=0.5):
274       
275        _BaseInteractor.__init__(self, base, axes, color=color)
276        self.markers = []
277        self.axes = axes
278       
279        self.y=ymin
280        self.save_y=ymin
281       
282        self.xmin=xmin
283        self.save_xmin=xmin
284        self.xmax=xmax
285        self.save_xmax=xmax
286       
287        self.line = self.axes.plot([self.xmin,self.xmax],[self.y,self.y],
288                                      linestyle='-', marker='',
289                                      color=self.color,
290                                      visible=True)[0]
291     
292        self.npts = 20
293        self.has_move=False
294        self.connect_markers([self.line])
295        self.update()
296
297    def set_layer(self, n):
298        self.layernum = n
299        self.update()
300       
301    def clear(self):
302        self.clear_markers()
303        try:
304           
305            self.line.remove()
306        except:
307            # Old version of matplotlib
308            for item in range(len(self.axes.lines)):
309                del self.axes.lines[0]
310       
311       
312       
313    def get_radius(self):
314       
315        return 0
316       
317    def update(self,xmin=None, xmax=None,ymin=None, ymax=None):
318        """
319        Draw the new roughness on the graph.
320        """
321        #print "update main line", self.has_move
322        if xmin !=None:
323            self.xmin=xmin
324        if xmax !=None:
325            self.xmax=xmax
326        if ymin !=None:
327            self.y=ymin
328        if ymax !=None:
329            self.y = ymax
330        self.line.set(xdata=[self.xmin,self.xmax], ydata=[self.y,self.y])
331     
332       
333       
334    def save(self, ev):
335        """
336        Remember the roughness for this layer and the next so that we
337        can restore on Esc.
338        """
339        self.save_xmin= self.xmin
340        self.save_xmax= self.xmax
341       
342        self.save_y= self.y
343        self.base.freeze_axes()
344
345    def moveend(self, ev):
346       
347        self.has_move=False
348        self.base.moveend(ev)
349           
350    def restore(self):
351        """
352        Restore the roughness for this layer.
353        """
354        self.ymin = self.save_ymin
355        self.ymax = self.save_ymax
356
357    def move(self, x, y, ev):
358        """
359        Process move to a new position, making sure that the move is allowed.
360        """
361        self.y=y
362       
363       
364        self.has_move=True
365        self.base.base.update()
366       
367    def set_cursor(self, x, y):
368        self.move(x, y, None)
369        self.update()
370       
371       
372    def get_params(self):
373        params = {}
374        params["radius"] = self.xmin
375        params["theta"] = self.xmax
376        return params
377   
378    def set_params(self, params):
379
380        x = params["radius"] 
381        self.set_cursor(x, self._inner_mouse_y)
382       
383
384
385
386class VerticalLine(_BaseInteractor):
387    """
388         Select an annulus through a 2D plot
389    """
390    def __init__(self,base,axes,color='black', zorder=5, ymin=0.0, ymax=0.5,xmin=0.0,xmax=0.5):
391       
392        _BaseInteractor.__init__(self, base, axes, color=color)
393        self.markers = []
394        self.axes = axes
395       
396        self.x=xmin
397        self.save_x=xmin
398       
399        self.ymin=ymin
400        self.save_ymin=ymin
401        self.ymax=ymax
402        self.save_ymax=ymax
403       
404        self.line = self.axes.plot([self.x,self.x],[self.ymin,self.ymax],
405                                      linestyle='-', marker='',
406                                      color=self.color,
407                                      visible=True)[0]
408     
409        self.npts = 20
410        self.has_move=False
411        self.connect_markers([self.line])
412        self.update()
413
414    def set_layer(self, n):
415        self.layernum = n
416        self.update()
417       
418    def clear(self):
419        self.clear_markers()
420        try:
421           
422            self.line.remove()
423        except:
424            # Old version of matplotlib
425            for item in range(len(self.axes.lines)):
426                del self.axes.lines[0]
427       
428       
429       
430    def get_radius(self):
431       
432        return 0
433       
434    def update(self,xmin=None, xmax=None,ymin=None, ymax=None):
435        """
436        Draw the new roughness on the graph.
437        """
438       
439        if xmin !=None:
440            self.x=xmin
441        if xmin !=None:
442            self.x=xmax
443        if ymin !=None:
444            self.ymin=ymin
445        if ymax !=None:
446            self.ymax=ymax
447        print "update vertical line", self.has_move,[self.x,self.x], [self.ymin,self.ymax]
448        self.line.set(xdata=[self.x,self.x], ydata=[self.ymin,self.ymax])
449     
450       
451       
452    def save(self, ev):
453        """
454        Remember the roughness for this layer and the next so that we
455        can restore on Esc.
456        """
457        self.save_x= self.x
458     
459        self.save_ymin= self.ymin
460        self.save_ymax= self.ymax
461        self.base.freeze_axes()
462
463    def moveend(self, ev):
464       
465        self.has_move=False
466        self.base.moveend(ev)
467           
468    def restore(self):
469        """
470        Restore the roughness for this layer.
471        """
472        self.x = self.save_x
473       
474        self.ymin=self.save_ymin
475        self.ymax=self.save_ymax
476    def move(self, x, y, ev):
477        """
478        Process move to a new position, making sure that the move is allowed.
479        """
480        self.x=x
481       
482       
483       
484        self.has_move=True
485        self.base.base.update()
486       
487    def set_cursor(self, x, y):
488        self.move(x, y, None)
489        self.update()
490       
491       
492    def get_params(self):
493        params = {}
494        params["radius"] = self.xmin
495        params["theta"] = self.xmax
496        params["radius"] = self.xmin
497        params["theta"] = self.xmax
498        return params
499   
500    def set_params(self, params):
501
502        x = params["radius"] 
503        self.set_cursor(x, self._inner_mouse_y)
504       
505
506
507       
Note: See TracBrowser for help on using the repository browser.