source: sasview/guiframe/local_perspectives/plotting/Plotter1D.py @ 8f274b11

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 8f274b11 was 9a585d0, checked in by Gervaise Alina <gervyh@…>, 15 years ago

make plotter1D and plotter2D context menu in the same order

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