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

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

status bar changed—-removed error from data remove

  • 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                """
229                elif self.plots[self.graph.selected_plottable].__class__.__name__=="Data1D":
230                    id = wx.NewId()
231                    slicerpop.Append(id, '&Remove errors From data')
232                    #print "panel scale before  ",self.xLabel, self.yLabel
233                    #print "cyllinder before adding error", self.plots[self.graph.selected_plottable].x
234                    wx.EVT_MENU(self, id, self._on_remove_errors)
235                """
236            else:
237                id = wx.NewId()
238                slicerpop.Append(id, '&Linear fit')
239                wx.EVT_MENU(self, id, self.onFitting)
240               
241            slicerpop.AppendSeparator()
242        id = wx.NewId()
243        slicerpop.Append(id, '&Change scale')
244        wx.EVT_MENU(self, id, self._onProperties)
245       
246        id = wx.NewId()
247        slicerpop.Append(id, '&Reset Graph')
248        wx.EVT_MENU(self, id, self.onResetGraph) 
249        """
250        slicerpop.AppendSeparator()
251        id = wx.NewId()
252        slicerpop.Append(id,'&Printer setup', 'Set image size')
253        wx.EVT_MENU(self, id, self.onPrinterSetup)
254       
255        id = wx.NewId()
256        slicerpop.Append(id,'&Printer Preview', 'Set image size')
257        wx.EVT_MENU(self, id, self.onPrinterPreview)
258        """
259       
260
261        pos = event.GetPosition()
262        pos = self.ScreenToClient(pos)
263        self.PopupMenu(slicerpop, pos)
264    def _on_remove_errors(self, evt):
265        if not self.graph.selected_plottable == None:
266            name =self.plots[self.graph.selected_plottable].name
267            dy = self.plots[self.graph.selected_plottable].dy
268            self.err_dy[name]= dy
269            new_plot = Theory1D(self.plots[self.graph.selected_plottable].x,
270                              self.plots[self.graph.selected_plottable].y,
271                              dy=None)
272            new_plot.interactive = True
273            new_plot.name = self.plots[self.graph.selected_plottable].name
274            if hasattr(self.plots[self.graph.selected_plottable], "group_id"):
275                new_plot.group_id = self.plots[self.graph.selected_plottable].group_id
276                new_plot.id = self.plots[self.graph.selected_plottable].id
277            else:
278                new_plot.group_id = str(time.time())
279                new_plot.id = str(time.time())
280            label, unit = self.plots[self.graph.selected_plottable].get_xaxis()
281            new_plot.xaxis(label, unit)
282            label, unit = self.plots[self.graph.selected_plottable].get_yaxis()
283            new_plot.yaxis(label, unit)
284            #print "panel scale ",self.xLabel, self.yLabel
285            print "color",self.graph.plottables[self.plots[self.graph.selected_plottable]]
286            color=self.graph.plottables[self.plots[self.graph.selected_plottable]]
287            self.graph.delete_plottable(self.plots[self.graph.selected_plottable])
288           
289            self.graph.add(new_plot,color)
290            # transforming the view of the new data into the same of the previous data
291            self._onEVT_FUNC_PROPERTY()
292            #print "cyllinder", self.plots[self.graph.selected_plottable].x,self.plots[self.graph.selected_plottable].view.x, new_plot.x, new_plot.view.x
293            self.plots[self.graph.selected_plottable]=new_plot
294           
295            self.graph.render(self)
296            self.subplot.figure.canvas.draw_idle() 
297   
298    def _on_add_errors(self, evt):
299        """
300            Compute reasonable errors for a data set without
301            errors and transorm the plottable to a Data1D
302        """
303        import math
304        import numpy
305        import time
306       
307        if not self.graph.selected_plottable == None:
308            length = len(self.plots[self.graph.selected_plottable].x)
309            dy = numpy.zeros(length)
310            selected_plot= self.plots[self.graph.selected_plottable]
311            try:
312                dy = self.err_dy[selected_plot.name]
313            except:
314                for i in range(length):
315                    dy[i] = math.sqrt(self.plots[self.graph.selected_plottable].y[i])     
316            #for i in range(length):
317            #    dy[i] = math.sqrt(self.plots[self.graph.selected_plottable].y[i])
318               
319            new_plot = Data1D(self.plots[self.graph.selected_plottable].x,
320                              self.plots[self.graph.selected_plottable].y,
321                              dy=dy)
322            new_plot.interactive = True
323            new_plot.name = self.plots[self.graph.selected_plottable].name
324            if hasattr(self.plots[self.graph.selected_plottable], "group_id"):
325                new_plot.group_id = self.plots[self.graph.selected_plottable].group_id
326                new_plot.id = self.plots[self.graph.selected_plottable].id
327            else:
328                new_plot.group_id = str(time.time())
329                new_plot.id = str(time.time())
330           
331            label, unit = self.plots[self.graph.selected_plottable].get_xaxis()
332            new_plot.xaxis(label, unit)
333            label, unit = self.plots[self.graph.selected_plottable].get_yaxis()
334            new_plot.yaxis(label, unit)
335            #print "panel scale ",self.xLabel, self.yLabel
336            #color=self.graph.plottables[self.plots[self.graph.selected_plottable]]
337            self.graph.delete_plottable(self.plots[self.graph.selected_plottable])
338            #self.graph.add_plottable(new_plot, color)
339            self.graph.add(new_plot)
340            # transforming the view of the new data into the same of the previous data
341            self._onEVT_FUNC_PROPERTY()
342            #print "cyllinder", self.plots[self.graph.selected_plottable].x,self.plots[self.graph.selected_plottable].view.x, new_plot.x, new_plot.view.x
343            self.plots[self.graph.selected_plottable]=new_plot
344           
345            self.graph.render(self)
346            self.subplot.figure.canvas.draw_idle()   
347   
348    def _onSave(self, evt):
349        """
350            Save a data set to a text file
351            @param evt: Menu event
352        """
353        import os
354        id = str(evt.GetId())
355        if id in self.action_ids:         
356           
357            path = None
358            dlg = wx.FileDialog(self, "Choose a file", os.getcwd(), "", "*.txt", wx.SAVE)
359            if dlg.ShowModal() == wx.ID_OK:
360                path = dlg.GetPath()
361                mypath = os.path.basename(path)
362                #print path
363            dlg.Destroy()
364           
365            if not path == None:
366                out = open(path, 'w')
367                has_errors = True
368                if self.action_ids[id].dy==None or self.action_ids[id].dy==[]:
369                    has_errors = False
370                   
371                # Sanity check
372                if has_errors:
373                    try:
374                        if len(self.action_ids[id].y) != len(self.action_ids[id].dy):
375                            #print "Y and dY have different lengths"
376                            has_errors = False
377                    except:
378                        has_errors = False
379               
380                if has_errors:
381                    out.write("<X>   <Y>   <dY>\n")
382                else:
383                    out.write("<X>   <Y>\n")
384                   
385                for i in range(len(self.action_ids[id].x)):
386                    if has_errors:
387                        out.write("%g  %g  %g\n" % (self.action_ids[id].x[i], 
388                                                    self.action_ids[id].y[i],
389                                                    self.action_ids[id].dy[i]))
390                    else:
391                        out.write("%g  %g\n" % (self.action_ids[id].x[i], 
392                                                self.action_ids[id].y[i]))
393                       
394                out.close()
395   
396 
397
398    def _onToggleScale(self, event):
399        if self.get_yscale() == 'log':
400            self.set_yscale('linear')
401        else:
402            self.set_yscale('log')
403        self.subplot.figure.canvas.draw_idle()   
404       
Note: See TracBrowser for help on using the repository browser.