source: sasview/sansmodels/PlotPanel.py @ f03b027

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 f03b027 was c510183, checked in by Gervaise Alina <gervyh@…>, 17 years ago
  • Property mode set to 100644
File size: 8.6 KB
Line 
1import wx
2import matplotlib
3matplotlib.interactive(False)
4#Use the WxAgg back end. The Wx one takes too long to render
5matplotlib.use('WXAgg')
6from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg
7from matplotlib.figure import Figure
8import os
9
10#from canvas import FigureCanvas
11#TODO: make the plottables interactive
12
13def show_tree(obj,d=0):
14    """Handy function for displaying a tree of graph objects"""
15    print "%s%s" % ("-"*d,obj.__class__.__name__)
16    if 'get_children' in dir(obj):
17        for a in obj.get_children(): show_tree(a,d+1)
18
19class PlotPanel(wx.Panel):
20    """
21    The PlotPanel has a Figure and a Canvas. OnSize events simply set a
22    flag, and the actually redrawing of the
23    figure is triggered by an Idle event.
24    """
25    def __init__(self, parent, id = -1, color = None,\
26        dpi = None, **kwargs):
27        wx.Panel.__init__(self, parent, id = id, **kwargs)
28
29        self.figure = Figure(None, dpi)
30        self.canvas = FigureCanvasWxAgg(self, -1, self.figure)
31        self.SetColor(color)
32        self._resizeflag = True
33        self._SetSize()
34        self.subplot = self.figure.add_subplot(111)
35        self.figure.subplots_adjust(left=.2, bottom=.2)
36        self.yscale = 'linear'
37        self.xscale = 'linear'
38        sizer = wx.BoxSizer(wx.VERTICAL)
39        sizer.Add(self.canvas,1,wx.EXPAND)
40        self.SetSizer(sizer)
41
42
43       
44        self.Bind(wx.EVT_CONTEXT_MENU, self.onContextMenu)
45
46        # Define some constants
47        self.colorlist = ['b','g','r','c','m','y']
48        self.symbollist = ['o','x','^','v','<','>','+','s','d','D','h','H','p']
49
50    def set_yscale(self, scale='linear'):
51        self.subplot.set_yscale(scale)
52        self.yscale = scale.lower()
53       
54    def get_yscale(self):
55        return self.yscale
56   
57    def set_xscale(self, scale='linear'):
58       
59        if scale.lower()=='squared':
60            self.subplot.set_xscale('linear')
61        else:
62            self.subplot.set_xscale(scale)
63           
64        self.xscale = scale.lower()
65       
66    def get_xscale(self):
67        return self.xscale
68    def SetColor(self, rgbtuple):
69        """Set figure and canvas colours to be the same"""
70        if not rgbtuple:
71            rgbtuple = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE).Get()
72        col = [c/255.0 for c in rgbtuple]
73        self.figure.set_facecolor(col)
74        self.figure.set_edgecolor(col)
75        self.canvas.SetBackgroundColour(wx.Colour(*rgbtuple))
76
77    def _onSize(self, event):
78        self._resizeflag = True
79
80    def _onIdle(self, evt):
81        if self._resizeflag:
82            self._resizeflag = False
83            self._SetSize()
84            self.draw()
85
86    def _SetSize(self, pixels = None):
87        """
88        This method can be called to force the Plot to be a desired size, which defaults to
89        the ClientSize of the panel
90        """
91        if not pixels:
92            pixels = self.GetClientSize()
93        self.canvas.SetSize(pixels)
94        self.figure.set_size_inches(pixels[0]/self.figure.get_dpi(),
95        pixels[1]/self.figure.get_dpi())
96
97    def draw(self):
98        """Where the actual drawing happens"""
99        self.figure.canvas.draw_idle()
100
101    def onSaveImage(self, evt):
102        #figure.savefig
103        print "Save image not implemented"
104        path = None
105        dlg = wx.FileDialog(self, "Choose a file", os.getcwd(), "", "*.png", wx.SAVE)
106        if dlg.ShowModal() == wx.ID_OK:
107            path = dlg.GetPath()
108            mypath = os.path.basename(path)
109            print path
110        dlg.Destroy()
111        if not path == None:
112            self.subplot.figure.savefig(path,dpi=300, facecolor='w', edgecolor='w',
113                                        orentation='portrait', papertype=None, format='png')
114       
115    def onContextMenu(self, event):
116        """
117            Default context menu for a plot panel
118        """
119        # Slicer plot popup menu
120        slicerpop = wx.Menu()
121        slicerpop.Append(313,'&Save image', 'Save image as PNG')
122        wx.EVT_MENU(self, 313, self.onSaveImage)
123
124        pos = event.GetPosition()
125        pos = self.ScreenToClient(pos)
126        self.PopupMenu(slicerpop, pos)
127       
128   
129    ## The following is plottable functionality
130
131
132    def properties(self,prop):
133        """Set some properties of the graph.
134       
135        The set of properties is not yet determined.
136        """
137        # The particulars of how they are stored and manipulated (e.g., do
138        # we want an inventory internally) is not settled.  I've used a
139        # property dictionary for now.
140        #
141        # How these properties interact with a user defined style file is
142        # even less clear.
143
144        # Properties defined by plot
145        self.subplot.set_xlabel(r"$%s$" % prop["xlabel"])
146        self.subplot.set_ylabel(r"$%s$" % prop["ylabel"])
147        self.subplot.set_title(prop["title"])
148
149        # Properties defined by user
150        #self.axes.grid(True)
151
152    def clear(self):
153        """Reset the plot"""
154       
155        # TODO: Redraw is brutal.  Render to a backing store and swap in
156        # TODO: rather than redrawing on the fly.
157        self.subplot.clear()
158        self.subplot.hold(True)
159
160
161    def render(self):
162        """Commit the plot after all objects are drawn"""
163        # TODO: this is when the backing store should be swapped in.
164        from matplotlib.font_manager import FontProperties
165        self.subplot.legend(prop=FontProperties(size=10))
166        #self.subplot.legend()
167        pass
168
169    def xaxis(self,label,units):
170        """xaxis label and units.
171       
172        Axis labels know about units.
173       
174        We need to do this so that we can detect when axes are not
175        commesurate.  Currently this is ignored other than for formatting
176        purposes.
177        """
178        if units != "": label = label + " (" + units + ")"
179        self.subplot.set_xlabel(label)
180        pass
181   
182    def yaxis(self,label,units):
183        """yaxis label and units."""
184        if units != "": label = label + " (" + units + ")"
185        self.subplot.set_ylabel(label)
186        pass
187
188    #def connect(self,trigger,callback):
189    #    print "PlotPanel.connect???"
190    #    if trigger == 'xlim': self._connect_to_xlim(callback)
191
192    def points(self,x,y,dx=None,dy=None,color=0,symbol=0,label=None):
193        """Draw markers with error bars"""
194        # Convert tuple (lo,hi) to array [(x-lo),(hi-x)]
195        import numpy as nx
196        if dx != None and type(dx) == type(()):
197            dx = nx.vstack((x-dx[0],dx[1]-x)).transpose()
198        if dy != None and type(dy) == type(()):
199            dy = nx.vstack((y-dy[0],dy[1]-y)).transpose()
200
201        if True or dx is None and dy is None:
202            h = self.subplot.plot(x,y,color=self._color(color),
203                                   marker=self._symbol(symbol))
204        else:
205            h,hcap,hbar = self.subplot.errorbar(x,y,dy,color=self._color(color),
206                                             marker=self._symbol(symbol), 
207                                             linestyle='None',
208                                             label=label,picker=5)
209
210    def curve(self,x,y,dy=None,color=0,symbol=0,label=None):
211        """Draw a line on a graph, possibly with confidence intervals."""
212        c = self._color(color)
213        self.subplot.set_yscale('linear')
214        self.subplot.set_xscale('linear')
215       
216        x_tmp = x
217        if self.xscale == 'squared':
218            x_tmp = []
219            for x_i in x:
220                x_tmp.append(x_i*x_i)
221       
222        hlist = self.subplot.plot(x_tmp,y,color=c,marker='',linestyle='-',label=label)
223       
224        self.subplot.set_yscale(self.yscale)
225        if not self.xscale == 'squared':
226            self.subplot.set_xscale(self.xscale)
227       
228        if False and dy != None:
229            if type(dy) == type(()):
230                self.subplot.plot(x,dy[0],color=c,
231                               marker='',linestyle='--',label='_nolegend_')
232                self.subplot.plot(x,dy[1],color=c,
233                               marker='',linestyle='--',label='_nolegend_')
234            elif len(dy)==len(y):
235                upper = []
236                lower = []
237                for i in range(len(y)):
238                    lower.append(y[i]-dy[i])
239                    upper.append(y[i]+dy[i])
240               
241                self.subplot.plot(x,upper,color=c,
242                               marker='',linestyle='--',label='_nolegend_')
243                self.subplot.plot(x,lower,color=c,
244                               marker='',linestyle='--',label='_nolegend_')
245
246    def _color(self,c):
247        """Return a particular colour"""
248        return self.colorlist[c%len(self.colorlist)]
249
250    def _symbol(self,s):
251        """Return a particular symbol"""
252        return self.symbollist[s%len(self.symbollist)]
253
Note: See TracBrowser for help on using the repository browser.