source: sasview/guiframe/local_perspectives/plotting/SectorSlicer2.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 768656e, checked in by Gervaise Alina <gervyh@…>, 16 years ago

fixe plotting more than2 data at the same time from xml file
add another interactor not connect to code yet

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