source: sasview/guiframe/local_perspectives/plotting/Plotter1D.py @ c48060c

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

plotter1d and plotter2d file created

  • Property mode set to 100644
File size: 11.8 KB
Line 
1"""
2This software was developed by the University of Tennessee as part of the
3Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
4project funded by the US National Science Foundation.
5
6See the license text in license.txt
7
8copyright 2008, University of Tennessee
9"""
10
11
12import wx
13import sys
14import danse.common.plottools
15from danse.common.plottools.PlotPanel import PlotPanel
16from danse.common.plottools.plottables import Graph,Data1D
17from sans.guicomm.events import EVT_NEW_PLOT
18from sans.guicomm.events import StatusEvent ,NewPlotEvent
19
20
21from SlicerParameters import SlicerEvent
22from binder import BindArtist
23(InternalEvent, EVT_INTERNAL)   = wx.lib.newevent.NewEvent()
24#from SlicerParameters import SlicerEvent
25#(InternalEvent, EVT_INTERNAL)   = wx.lib.newevent.NewEvent()
26DEFAULT_QMAX = 0.05
27
28DEFAULT_QSTEP = 0.001
29DEFAULT_BEAM = 0.005
30BIN_WIDTH =1
31import pylab
32
33class PanelMenu(wx.Menu):
34    plots = None
35    graph = None
36   
37    def set_plots(self, plots):
38        self.plots = plots
39   
40    def set_graph(self, graph):
41        self.graph = graph
42class ModelPanel1D(PlotPanel):
43    """
44        Plot panel for use with the GUI manager
45    """
46   
47    ## Internal name for the AUI manager
48    window_name = "plotpanel"
49    ## Title to appear on top of the window
50    window_caption = "Plot Panel"
51    ## Flag to tell the GUI manager that this panel is not
52    #  tied to any perspective
53    ALWAYS_ON = True
54    ## Group ID
55    group_id = None
56   
57    def __init__(self, parent, id = -1, color = None,\
58        dpi = None, style = wx.NO_FULL_REPAINT_ON_RESIZE, **kwargs):
59        """
60            Initialize the panel
61        """
62        PlotPanel.__init__(self, parent, id = id, style = style, **kwargs)
63       
64        ## Reference to the parent window
65        self.parent = parent
66        ## Plottables
67        self.plots = {}
68       
69        ## Unique ID (from gui_manager)
70        self.uid = None
71       
72        ## Action IDs for internal call-backs
73        self.action_ids = {}
74       
75        ## Graph       
76        self.graph = Graph()
77        self.graph.xaxis("\\rm{Q}", 'A^{-1}')
78        self.graph.yaxis("\\rm{Intensity} ","cm^{-1}")
79        self.graph.render(self)
80   
81    def _reset(self):
82        """
83            Resets internal data and graph
84        """   
85        self.graph.reset()
86        self.plots      = {}
87        self.action_ids = {}
88   
89    def _onEVT_1DREPLOT(self, event):
90        """
91            Data is ready to be displayed
92            @param event: data event
93        """
94        #TODO: Check for existence of plot attribute
95
96        # Check whether this is a replot. If we ask for a replot
97        # and the plottable no longer exists, ignore the event.
98        if hasattr(event, "update") and event.update==True \
99            and event.plot.name not in self.plots.keys():
100            return
101       
102        if hasattr(event, "reset"):
103            self._reset()
104       
105        is_new = True
106        #print "model panel name",event.plot.name
107        if event.plot.name in self.plots.keys():
108            # Check whether the class of plottable changed
109            #print "model panel",event.plot.name,event.plot.__class__
110            if not event.plot.__class__==self.plots[event.plot.name].__class__:
111                self.graph.delete(self.plots[event.plot.name])
112            else:
113                is_new = False
114       
115        if is_new:
116            self.plots[event.plot.name] = event.plot
117            self.graph.add(self.plots[event.plot.name])
118        else:
119            self.plots[event.plot.name].x = event.plot.x   
120            self.plots[event.plot.name].y = event.plot.y   
121            self.plots[event.plot.name].dy = event.plot.dy 
122            if hasattr(event.plot, 'dx') and hasattr(self.plots[event.plot.name], 'dx'):
123                self.plots[event.plot.name].dx = event.plot.dx   
124 
125       
126        # Check axis labels
127        #TODO: Should re-factor this
128        #if event.plot._xunit != self.graph.prop["xunit"]:
129        self.graph.xaxis(event.plot._xaxis, event.plot._xunit)
130           
131        #if event.plot._yunit != self.graph.prop["yunit"]:
132        self.graph.yaxis(event.plot._yaxis, event.plot._yunit)
133     
134        # Set the view scale for all plots
135        self._onEVT_FUNC_PROPERTY()
136     
137        self.graph.render(self)
138        self.subplot.figure.canvas.draw_idle()
139
140    def onLeftDown(self,event): 
141        """ left button down and ready to drag"""
142           
143        PlotPanel.onLeftDown(self, event)
144        ax = event.inaxes
145        if ax != None:
146            position = "x: %8.3g    y: %8.3g" % (event.xdata, event.ydata)
147            wx.PostEvent(self.parent, StatusEvent(status=position))
148
149    def _onRemove(self, event):
150        """
151        """
152        if not self.graph.selected_plottable == None:
153            print self.graph.selected_plottable
154           
155           
156            self.graph.delete(self.plots[self.graph.selected_plottable])
157            del self.plots[self.graph.selected_plottable]
158            self.graph.render(self)
159            self.subplot.figure.canvas.draw_idle()   
160           
161
162    def onContextMenu(self, event):
163        """
164            1D plot context menu
165            @param event: wx context event
166        """
167        #slicerpop = wx.Menu()
168        slicerpop = PanelMenu()
169        slicerpop.set_plots(self.plots)
170        slicerpop.set_graph(self.graph)
171               
172        # Option to save the data displayed
173       
174        #for plot in self.graph.plottables:
175        if self.graph.selected_plottable in self.plots:
176            plot = self.plots[self.graph.selected_plottable]
177            id = wx.NewId()
178            name = plot.name
179            slicerpop.Append(id, "&Save %s points" % name)
180            self.action_ids[str(id)] = plot
181            wx.EVT_MENU(self, id, self._onSave)
182               
183            # Option to delete plottable
184            id = wx.NewId()
185            slicerpop.Append(id, "Remove %s curve" % name)
186            self.action_ids[str(id)] = plot
187            wx.EVT_MENU(self, id, self._onRemove)
188           
189            # Option to hide
190            #TODO: implement functionality to hide a plottable (legend click)
191            slicerpop.AppendSeparator()
192               
193        # Various plot options
194        id = wx.NewId()
195        slicerpop.Append(id,'&Save image', 'Save image as PNG')
196        wx.EVT_MENU(self, id, self.onSaveImage)
197       
198       
199        item_list = self.parent.get_context_menu(self.graph)
200        if (not item_list==None) and (not len(item_list)==0):
201                slicerpop.AppendSeparator()
202                for item in item_list:
203                    try:
204                        id = wx.NewId()
205                        slicerpop.Append(id, item[0], item[1])
206                        wx.EVT_MENU(self, id, item[2])
207                    except:
208                        print sys.exc_value
209                        print RuntimeError, "View1DPanel.onContextMenu: bad menu item"
210       
211        slicerpop.AppendSeparator()
212       
213        if self.graph.selected_plottable in self.plots:
214            if self.plots[self.graph.selected_plottable].__class__.__name__=="Theory1D":
215                id = wx.NewId()
216                slicerpop.Append(id, '&Add errors to data')
217                wx.EVT_MENU(self, id, self._on_add_errors)
218            else:
219                id = wx.NewId()
220                slicerpop.Append(id, '&Linear fit')
221                wx.EVT_MENU(self, id, self.onFitting)
222               
223       
224
225        id = wx.NewId()
226        slicerpop.Append(id, '&Change scale')
227        wx.EVT_MENU(self, id, self._onProperties)
228       
229        id = wx.NewId()
230        #slicerpop.AppendSeparator()
231        slicerpop.Append(id, '&Reset Graph')
232        wx.EVT_MENU(self, id, self.onResetGraph)       
233
234        pos = event.GetPosition()
235        pos = self.ScreenToClient(pos)
236        self.PopupMenu(slicerpop, pos)
237   
238   
239    def _on_add_errors(self, evt):
240        """
241            Compute reasonable errors for a data set without
242            errors and transorm the plottable to a Data1D
243        """
244        import math
245        import numpy
246        import time
247       
248        if not self.graph.selected_plottable == None:
249            length = len(self.plots[self.graph.selected_plottable].x)
250            dy = numpy.zeros(length)
251            for i in range(length):
252                dy[i] = math.sqrt(self.plots[self.graph.selected_plottable].y[i])
253               
254            new_plot = Data1D(self.plots[self.graph.selected_plottable].x,
255                              self.plots[self.graph.selected_plottable].y,
256                              dy=dy)
257            new_plot.interactive = True
258            new_plot.name = self.plots[self.graph.selected_plottable].name
259            if hasattr(self.plots[self.graph.selected_plottable], "group_id"):
260                new_plot.group_id = self.plots[self.graph.selected_plottable].group_id
261            else:
262                new_plot.group_id = str(time.time())
263           
264            label, unit = self.plots[self.graph.selected_plottable].get_xaxis()
265            new_plot.xaxis(label, unit)
266            label, unit = self.plots[self.graph.selected_plottable].get_yaxis()
267            new_plot.yaxis(label, unit)
268           
269            self.graph.delete(self.plots[self.graph.selected_plottable])
270           
271            self.graph.add(new_plot)
272            self.plots[self.graph.selected_plottable]=new_plot
273           
274            self.graph.render(self)
275            self.subplot.figure.canvas.draw_idle()   
276   
277    def _onSave(self, evt):
278        """
279            Save a data set to a text file
280            @param evt: Menu event
281        """
282        import os
283        id = str(evt.GetId())
284        if id in self.action_ids:         
285           
286            path = None
287            dlg = wx.FileDialog(self, "Choose a file", os.getcwd(), "", "*.txt", wx.SAVE)
288            if dlg.ShowModal() == wx.ID_OK:
289                path = dlg.GetPath()
290                mypath = os.path.basename(path)
291                print path
292            dlg.Destroy()
293           
294            if not path == None:
295                out = open(path, 'w')
296                has_errors = True
297                if self.action_ids[id].dy==None or self.action_ids[id].dy==[]:
298                    has_errors = False
299                   
300                # Sanity check
301                if has_errors:
302                    try:
303                        if len(self.action_ids[id].y) != len(self.action_ids[id].dy):
304                            print "Y and dY have different lengths"
305                            has_errors = False
306                    except:
307                        has_errors = False
308               
309                if has_errors:
310                    out.write("<X>   <Y>   <dY>\n")
311                else:
312                    out.write("<X>   <Y>\n")
313                   
314                for i in range(len(self.action_ids[id].x)):
315                    if has_errors:
316                        out.write("%g  %g  %g\n" % (self.action_ids[id].x[i], 
317                                                    self.action_ids[id].y[i],
318                                                    self.action_ids[id].dy[i]))
319                    else:
320                        out.write("%g  %g\n" % (self.action_ids[id].x[i], 
321                                                self.action_ids[id].y[i]))
322                       
323                out.close()
324   
325   
326    def _onToggleScale(self, event):
327        if self.get_yscale() == 'log':
328            self.set_yscale('linear')
329        else:
330            self.set_yscale('log')
331        self.subplot.figure.canvas.draw_idle()   
332       
Note: See TracBrowser for help on using the repository browser.