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

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

working on slicer

  • Property mode set to 100644
File size: 12.0 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        if event.plot.name in self.plots.keys():
107            # Check whether the class of plottable changed
108            if not event.plot.__class__==self.plots[event.plot.name].__class__:
109                #overwrite a plottable using the same name
110                self.graph.delete(self.plots[event.plot.name])
111            else:
112                # plottable is already draw on the panel
113                is_new = False
114
115           
116        if is_new:
117            # a new plottable overwrites a plotted one  using the same id
118            for plottable in self.plots.itervalues():
119                if event.plot.id==plottable.id :
120                    self.graph.delete(plottable)
121           
122            self.plots[event.plot.name] = event.plot
123            self.graph.add(self.plots[event.plot.name])
124        else:
125            #replot the graph
126            self.plots[event.plot.name].x = event.plot.x   
127            self.plots[event.plot.name].y = event.plot.y   
128            self.plots[event.plot.name].dy = event.plot.dy 
129            if hasattr(event.plot, 'dx') and hasattr(self.plots[event.plot.name], 'dx'):
130                self.plots[event.plot.name].dx = event.plot.dx   
131 
132       
133        # Check axis labels
134        #TODO: Should re-factor this
135        #if event.plot._xunit != self.graph.prop["xunit"]:
136        self.graph.xaxis(event.plot._xaxis, event.plot._xunit)
137           
138        #if event.plot._yunit != self.graph.prop["yunit"]:
139        self.graph.yaxis(event.plot._yaxis, event.plot._yunit)
140     
141        # Set the view scale for all plots
142       
143        self._onEVT_FUNC_PROPERTY()
144   
145        self.graph.render(self)
146        self.subplot.figure.canvas.draw_idle()
147
148    def onLeftDown(self,event): 
149        """ left button down and ready to drag"""
150           
151        PlotPanel.onLeftDown(self, event)
152        ax = event.inaxes
153        if ax != None:
154            position = "x: %8.3g    y: %8.3g" % (event.xdata, event.ydata)
155            wx.PostEvent(self.parent, StatusEvent(status=position))
156
157    def _onRemove(self, event):
158        """
159        """
160        if not self.graph.selected_plottable == None:
161            print self.graph.selected_plottable
162           
163           
164            self.graph.delete(self.plots[self.graph.selected_plottable])
165            del self.plots[self.graph.selected_plottable]
166            self.graph.render(self)
167            self.subplot.figure.canvas.draw_idle()   
168           
169
170    def onContextMenu(self, event):
171        """
172            1D plot context menu
173            @param event: wx context event
174        """
175        #slicerpop = wx.Menu()
176        slicerpop = PanelMenu()
177        slicerpop.set_plots(self.plots)
178        slicerpop.set_graph(self.graph)
179               
180        # Option to save the data displayed
181       
182        #for plot in self.graph.plottables:
183        if self.graph.selected_plottable in self.plots:
184            plot = self.plots[self.graph.selected_plottable]
185            id = wx.NewId()
186            name = plot.name
187            slicerpop.Append(id, "&Save %s points" % name)
188            self.action_ids[str(id)] = plot
189            wx.EVT_MENU(self, id, self._onSave)
190               
191            # Option to delete plottable
192            id = wx.NewId()
193            slicerpop.Append(id, "Remove %s curve" % name)
194            self.action_ids[str(id)] = plot
195            wx.EVT_MENU(self, id, self._onRemove)
196           
197            # Option to hide
198            #TODO: implement functionality to hide a plottable (legend click)
199            slicerpop.AppendSeparator()
200               
201        # Various plot options
202        id = wx.NewId()
203        slicerpop.Append(id,'&Save image', 'Save image as PNG')
204        wx.EVT_MENU(self, id, self.onSaveImage)
205       
206       
207        item_list = self.parent.get_context_menu(self.graph)
208        if (not item_list==None) and (not len(item_list)==0):
209                slicerpop.AppendSeparator()
210                for item in item_list:
211                    try:
212                        id = wx.NewId()
213                        slicerpop.Append(id, item[0], item[1])
214                        wx.EVT_MENU(self, id, item[2])
215                    except:
216                        print sys.exc_value
217                        print RuntimeError, "View1DPanel.onContextMenu: bad menu item"
218       
219        slicerpop.AppendSeparator()
220       
221        if self.graph.selected_plottable in self.plots:
222            if self.plots[self.graph.selected_plottable].__class__.__name__=="Theory1D":
223                id = wx.NewId()
224                slicerpop.Append(id, '&Add errors to data')
225                wx.EVT_MENU(self, id, self._on_add_errors)
226            else:
227                id = wx.NewId()
228                slicerpop.Append(id, '&Linear fit')
229                wx.EVT_MENU(self, id, self.onFitting)
230               
231       
232
233        id = wx.NewId()
234        slicerpop.Append(id, '&Change scale')
235        wx.EVT_MENU(self, id, self._onProperties)
236       
237        id = wx.NewId()
238        #slicerpop.AppendSeparator()
239        slicerpop.Append(id, '&Reset Graph')
240        wx.EVT_MENU(self, id, self.onResetGraph)       
241
242        pos = event.GetPosition()
243        pos = self.ScreenToClient(pos)
244        self.PopupMenu(slicerpop, pos)
245   
246   
247    def _on_add_errors(self, evt):
248        """
249            Compute reasonable errors for a data set without
250            errors and transorm the plottable to a Data1D
251        """
252        import math
253        import numpy
254        import time
255       
256        if not self.graph.selected_plottable == None:
257            length = len(self.plots[self.graph.selected_plottable].x)
258            dy = numpy.zeros(length)
259            for i in range(length):
260                dy[i] = math.sqrt(self.plots[self.graph.selected_plottable].y[i])
261               
262            new_plot = Data1D(self.plots[self.graph.selected_plottable].x,
263                              self.plots[self.graph.selected_plottable].y,
264                              dy=dy)
265            new_plot.interactive = True
266            new_plot.name = self.plots[self.graph.selected_plottable].name
267            if hasattr(self.plots[self.graph.selected_plottable], "group_id"):
268                new_plot.group_id = self.plots[self.graph.selected_plottable].group_id
269            else:
270                new_plot.group_id = str(time.time())
271           
272            label, unit = self.plots[self.graph.selected_plottable].get_xaxis()
273            new_plot.xaxis(label, unit)
274            label, unit = self.plots[self.graph.selected_plottable].get_yaxis()
275            new_plot.yaxis(label, unit)
276           
277            self.graph.delete(self.plots[self.graph.selected_plottable])
278           
279            self.graph.add(new_plot)
280            self.plots[self.graph.selected_plottable]=new_plot
281           
282            self.graph.render(self)
283            self.subplot.figure.canvas.draw_idle()   
284   
285    def _onSave(self, evt):
286        """
287            Save a data set to a text file
288            @param evt: Menu event
289        """
290        import os
291        id = str(evt.GetId())
292        if id in self.action_ids:         
293           
294            path = None
295            dlg = wx.FileDialog(self, "Choose a file", os.getcwd(), "", "*.txt", wx.SAVE)
296            if dlg.ShowModal() == wx.ID_OK:
297                path = dlg.GetPath()
298                mypath = os.path.basename(path)
299                print path
300            dlg.Destroy()
301           
302            if not path == None:
303                out = open(path, 'w')
304                has_errors = True
305                if self.action_ids[id].dy==None or self.action_ids[id].dy==[]:
306                    has_errors = False
307                   
308                # Sanity check
309                if has_errors:
310                    try:
311                        if len(self.action_ids[id].y) != len(self.action_ids[id].dy):
312                            print "Y and dY have different lengths"
313                            has_errors = False
314                    except:
315                        has_errors = False
316               
317                if has_errors:
318                    out.write("<X>   <Y>   <dY>\n")
319                else:
320                    out.write("<X>   <Y>\n")
321                   
322                for i in range(len(self.action_ids[id].x)):
323                    if has_errors:
324                        out.write("%g  %g  %g\n" % (self.action_ids[id].x[i], 
325                                                    self.action_ids[id].y[i],
326                                                    self.action_ids[id].dy[i]))
327                    else:
328                        out.write("%g  %g\n" % (self.action_ids[id].x[i], 
329                                                self.action_ids[id].y[i]))
330                       
331                out.close()
332   
333   
334    def _onToggleScale(self, event):
335        if self.get_yscale() == 'log':
336            self.set_yscale('linear')
337        else:
338            self.set_yscale('log')
339        self.subplot.figure.canvas.draw_idle()   
340       
Note: See TracBrowser for help on using the repository browser.