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

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

add id on add_error_method for data1D with no error

  • Property mode set to 100644
File size: 12.2 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                new_plot.id = self.plots[self.graph.selected_plottable].id
270            else:
271                new_plot.group_id = str(time.time())
272                new_plot.id = str(time.time())
273           
274            label, unit = self.plots[self.graph.selected_plottable].get_xaxis()
275            new_plot.xaxis(label, unit)
276            label, unit = self.plots[self.graph.selected_plottable].get_yaxis()
277            new_plot.yaxis(label, unit)
278           
279            self.graph.delete(self.plots[self.graph.selected_plottable])
280           
281            self.graph.add(new_plot)
282            self.plots[self.graph.selected_plottable]=new_plot
283           
284            self.graph.render(self)
285            self.subplot.figure.canvas.draw_idle()   
286   
287    def _onSave(self, evt):
288        """
289            Save a data set to a text file
290            @param evt: Menu event
291        """
292        import os
293        id = str(evt.GetId())
294        if id in self.action_ids:         
295           
296            path = None
297            dlg = wx.FileDialog(self, "Choose a file", os.getcwd(), "", "*.txt", wx.SAVE)
298            if dlg.ShowModal() == wx.ID_OK:
299                path = dlg.GetPath()
300                mypath = os.path.basename(path)
301                print path
302            dlg.Destroy()
303           
304            if not path == None:
305                out = open(path, 'w')
306                has_errors = True
307                if self.action_ids[id].dy==None or self.action_ids[id].dy==[]:
308                    has_errors = False
309                   
310                # Sanity check
311                if has_errors:
312                    try:
313                        if len(self.action_ids[id].y) != len(self.action_ids[id].dy):
314                            print "Y and dY have different lengths"
315                            has_errors = False
316                    except:
317                        has_errors = False
318               
319                if has_errors:
320                    out.write("<X>   <Y>   <dY>\n")
321                else:
322                    out.write("<X>   <Y>\n")
323                   
324                for i in range(len(self.action_ids[id].x)):
325                    if has_errors:
326                        out.write("%g  %g  %g\n" % (self.action_ids[id].x[i], 
327                                                    self.action_ids[id].y[i],
328                                                    self.action_ids[id].dy[i]))
329                    else:
330                        out.write("%g  %g\n" % (self.action_ids[id].x[i], 
331                                                self.action_ids[id].y[i]))
332                       
333                out.close()
334   
335   
336    def _onToggleScale(self, event):
337        if self.get_yscale() == 'log':
338            self.set_yscale('linear')
339        else:
340            self.set_yscale('log')
341        self.subplot.figure.canvas.draw_idle()   
342       
Note: See TracBrowser for help on using the repository browser.