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

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

check the existance of id before using its value on 1d event plot

  • Property mode set to 100644
File size: 12.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
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       
59        ## Unique ID (from gui_manager)
60        self.uid = None
61       
62        ## Action IDs for internal call-backs
63        self.action_ids = {}
64       
65        ## Graph       
66        self.graph = Graph()
67        self.graph.xaxis("\\rm{Q}", 'A^{-1}')
68        self.graph.yaxis("\\rm{Intensity} ","cm^{-1}")
69        self.graph.render(self)
70   
71    def _reset(self):
72        """
73            Resets internal data and graph
74        """   
75        self.graph.reset()
76        self.plots      = {}
77        self.action_ids = {}
78   
79    def _onEVT_1DREPLOT(self, event):
80        """
81            Data is ready to be displayed
82            @param event: data event
83        """
84       
85        #TODO: Check for existence of plot attribute
86
87        # Check whether this is a replot. If we ask for a replot
88        # and the plottable no longer exists, ignore the event.
89        if hasattr(event, "update") and event.update==True \
90            and event.plot.name not in self.plots.keys():
91            return
92       
93        if hasattr(event, "reset"):
94            self._reset()
95       
96        is_new = True
97        if event.plot.name in self.plots.keys():
98            # Check whether the class of plottable changed
99            if not event.plot.__class__==self.plots[event.plot.name].__class__:
100                #overwrite a plottable using the same name
101                self.graph.delete(self.plots[event.plot.name])
102            else:
103                # plottable is already draw on the panel
104                is_new = False
105       
106           
107           
108        if is_new:
109            # a new plottable overwrites a plotted one  using the same id
110            for plottable in self.plots.itervalues():
111                if hasattr(event.plot,"id"):
112                    if event.plot.id==plottable.id :
113                        self.graph.delete(plottable)
114           
115            self.plots[event.plot.name] = event.plot
116            self.graph.add(self.plots[event.plot.name])
117        else:
118            #replot the graph
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       
130        self.graph.xaxis(event.plot._xaxis, event.plot._xunit)
131           
132        #if event.plot._yunit != self.graph.prop["yunit"]:
133        self.graph.yaxis(event.plot._yaxis, event.plot._yunit)
134     
135        # Set the view scale for all plots
136       
137        self._onEVT_FUNC_PROPERTY()
138   
139        self.graph.render(self)
140        self.subplot.figure.canvas.draw_idle()
141
142    def onLeftDown(self,event): 
143        """ left button down and ready to drag"""
144           
145        PlotPanel.onLeftDown(self, event)
146        ax = event.inaxes
147        if ax != None:
148            position = "x: %8.3g    y: %8.3g" % (event.xdata, event.ydata)
149            wx.PostEvent(self.parent, StatusEvent(status=position))
150
151    def _onRemove(self, event):
152        """
153        """
154        if not self.graph.selected_plottable == None:
155            #print self.graph.selected_plottable
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           
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        slicerpop.AppendSeparator()
199        item_list = self.parent.get_context_menu(self.graph)
200        #print "item_list",item_list
201        if (not item_list==None) and (not len(item_list)==0):
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                        pass
209                        #print sys.exc_value
210                        #print RuntimeError, "View1DPanel.onContextMenu: bad menu item"
211       
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                #print "panel scale before  ",self.xLabel, self.yLabel
218                #print "cyllinder before adding error", self.plots[self.graph.selected_plottable].x
219                wx.EVT_MENU(self, id, self._on_add_errors)
220            else:
221                id = wx.NewId()
222                slicerpop.Append(id, '&Linear fit')
223                wx.EVT_MENU(self, id, self.onFitting)
224               
225        slicerpop.AppendSeparator()
226        id = wx.NewId()
227        slicerpop.Append(id, '&Change scale')
228        wx.EVT_MENU(self, id, self._onProperties)
229       
230        id = wx.NewId()
231        slicerpop.Append(id, '&Reset Graph')
232        wx.EVT_MENU(self, id, self.onResetGraph) 
233       
234        slicerpop.AppendSeparator() 
235        id = wx.NewId()
236        slicerpop.Append(id,'&Printer setup', 'Set image size')
237        wx.EVT_MENU(self, id, self.onPrinterSetup)
238       
239        id = wx.NewId()
240        slicerpop.Append(id,'&Printer Preview', 'Set image size')
241        wx.EVT_MENU(self, id, self.onPrinterPreview)
242   
243        id = wx.NewId()
244        slicerpop.Append(id,'&Print image', 'Print image ')
245        wx.EVT_MENU(self, id, self.onPrint)     
246
247        pos = event.GetPosition()
248        pos = self.ScreenToClient(pos)
249        self.PopupMenu(slicerpop, pos)
250   
251   
252    def _on_add_errors(self, evt):
253        """
254            Compute reasonable errors for a data set without
255            errors and transorm the plottable to a Data1D
256        """
257        import math
258        import numpy
259        import time
260       
261        if not self.graph.selected_plottable == None:
262            length = len(self.plots[self.graph.selected_plottable].x)
263            dy = numpy.zeros(length)
264            for i in range(length):
265                dy[i] = math.sqrt(self.plots[self.graph.selected_plottable].y[i])
266               
267            new_plot = Data1D(self.plots[self.graph.selected_plottable].x,
268                              self.plots[self.graph.selected_plottable].y,
269                              dy=dy)
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           
279            label, unit = self.plots[self.graph.selected_plottable].get_xaxis()
280            new_plot.xaxis(label, unit)
281            label, unit = self.plots[self.graph.selected_plottable].get_yaxis()
282            new_plot.yaxis(label, unit)
283            #print "panel scale ",self.xLabel, self.yLabel
284            self.graph.delete(self.plots[self.graph.selected_plottable])
285           
286            self.graph.add(new_plot)
287            # transforming the view of the new data into the same of the previous data
288            self._onEVT_FUNC_PROPERTY()
289            #print "cyllinder", self.plots[self.graph.selected_plottable].x,self.plots[self.graph.selected_plottable].view.x, new_plot.x, new_plot.view.x
290            self.plots[self.graph.selected_plottable]=new_plot
291           
292            self.graph.render(self)
293            self.subplot.figure.canvas.draw_idle()   
294   
295    def _onSave(self, evt):
296        """
297            Save a data set to a text file
298            @param evt: Menu event
299        """
300        import os
301        id = str(evt.GetId())
302        if id in self.action_ids:         
303           
304            path = None
305            dlg = wx.FileDialog(self, "Choose a file", os.getcwd(), "", "*.txt", wx.SAVE)
306            if dlg.ShowModal() == wx.ID_OK:
307                path = dlg.GetPath()
308                mypath = os.path.basename(path)
309                #print path
310            dlg.Destroy()
311           
312            if not path == None:
313                out = open(path, 'w')
314                has_errors = True
315                if self.action_ids[id].dy==None or self.action_ids[id].dy==[]:
316                    has_errors = False
317                   
318                # Sanity check
319                if has_errors:
320                    try:
321                        if len(self.action_ids[id].y) != len(self.action_ids[id].dy):
322                            #print "Y and dY have different lengths"
323                            has_errors = False
324                    except:
325                        has_errors = False
326               
327                if has_errors:
328                    out.write("<X>   <Y>   <dY>\n")
329                else:
330                    out.write("<X>   <Y>\n")
331                   
332                for i in range(len(self.action_ids[id].x)):
333                    if has_errors:
334                        out.write("%g  %g  %g\n" % (self.action_ids[id].x[i], 
335                                                    self.action_ids[id].y[i],
336                                                    self.action_ids[id].dy[i]))
337                    else:
338                        out.write("%g  %g\n" % (self.action_ids[id].x[i], 
339                                                self.action_ids[id].y[i]))
340                       
341                out.close()
342   
343 
344
345    def _onToggleScale(self, event):
346        if self.get_yscale() == 'log':
347            self.set_yscale('linear')
348        else:
349            self.set_yscale('log')
350        self.subplot.figure.canvas.draw_idle()   
351       
Note: See TracBrowser for help on using the repository browser.