source: sasview/guiframe/local_perspectives/plotting/Plotter1D.py @ 869c368

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

allows removing or adding errors

  • Property mode set to 100644
File size: 15.7 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        #for plot in self.graph.plottables:
178        if self.graph.selected_plottable in self.plots:
179            plot = self.plots[self.graph.selected_plottable]
180            id = wx.NewId()
181            name = plot.name
182            slicerpop.Append(id, "&Save %s points" % name)
183            self.action_ids[str(id)] = plot
184            wx.EVT_MENU(self, id, self._onSave)
185               
186            # Option to delete plottable
187            id = wx.NewId()
188            slicerpop.Append(id, "Remove %s curve" % name)
189            self.action_ids[str(id)] = plot
190            wx.EVT_MENU(self, id, self._onRemove)
191           
192            # Option to hide
193            #TODO: implement functionality to hide a plottable (legend click)
194           
195               
196        # Various plot options
197        id = wx.NewId()
198        slicerpop.Append(id,'&Save image', 'Save image as PNG')
199        wx.EVT_MENU(self, id, self.onSaveImage)
200       
201        slicerpop.AppendSeparator()
202        item_list = self.parent.get_context_menu(self.graph)
203        #print "item_list",item_list
204        if (not item_list==None) and (not len(item_list)==0):
205                for item in item_list:
206                    try:
207                        id = wx.NewId()
208                        slicerpop.Append(id, item[0], item[1])
209                        wx.EVT_MENU(self, id, item[2])
210                    except:
211                        pass
212                        #print sys.exc_value
213                        #print RuntimeError, "View1DPanel.onContextMenu: bad menu item"
214       
215       
216        if self.graph.selected_plottable in self.plots:
217            if self.plots[self.graph.selected_plottable].__class__.__name__=="Theory1D":
218                id = wx.NewId()
219                slicerpop.Append(id, '&Add errors to data')
220                #print "panel scale before  ",self.xLabel, self.yLabel
221                #print "cyllinder before adding error", self.plots[self.graph.selected_plottable].x
222                wx.EVT_MENU(self, id, self._on_add_errors)
223            elif self.plots[self.graph.selected_plottable].__class__.__name__=="Data1D":
224                id = wx.NewId()
225                slicerpop.Append(id, '&Remove errors to data')
226                #print "panel scale before  ",self.xLabel, self.yLabel
227                #print "cyllinder before adding error", self.plots[self.graph.selected_plottable].x
228                wx.EVT_MENU(self, id, self._on_remove_errors)
229            else:
230                id = wx.NewId()
231                slicerpop.Append(id, '&Linear fit')
232                wx.EVT_MENU(self, id, self.onFitting)
233               
234        slicerpop.AppendSeparator()
235        id = wx.NewId()
236        slicerpop.Append(id, '&Change scale')
237        wx.EVT_MENU(self, id, self._onProperties)
238       
239        id = wx.NewId()
240        slicerpop.Append(id, '&Reset Graph')
241        wx.EVT_MENU(self, id, self.onResetGraph) 
242       
243        slicerpop.AppendSeparator() 
244        id = wx.NewId()
245        slicerpop.Append(id,'&Printer setup', 'Set image size')
246        wx.EVT_MENU(self, id, self.onPrinterSetup)
247       
248        id = wx.NewId()
249        slicerpop.Append(id,'&Printer Preview', 'Set image size')
250        wx.EVT_MENU(self, id, self.onPrinterPreview)
251   
252        id = wx.NewId()
253        slicerpop.Append(id,'&Print image', 'Print image ')
254        wx.EVT_MENU(self, id, self.onPrint)     
255
256        pos = event.GetPosition()
257        pos = self.ScreenToClient(pos)
258        self.PopupMenu(slicerpop, pos)
259    def _on_remove_errors(self, evt):
260        if not self.graph.selected_plottable == None:
261            name =self.plots[self.graph.selected_plottable].name
262            dy = self.plots[self.graph.selected_plottable].dy
263            self.err_dy[name]= dy
264            new_plot = Theory1D(self.plots[self.graph.selected_plottable].x,
265                              self.plots[self.graph.selected_plottable].y,
266                              dy=None)
267            new_plot.interactive = True
268            new_plot.name = self.plots[self.graph.selected_plottable].name
269            if hasattr(self.plots[self.graph.selected_plottable], "group_id"):
270                new_plot.group_id = self.plots[self.graph.selected_plottable].group_id
271                new_plot.id = self.plots[self.graph.selected_plottable].id
272            else:
273                new_plot.group_id = str(time.time())
274                new_plot.id = str(time.time())
275            label, unit = self.plots[self.graph.selected_plottable].get_xaxis()
276            new_plot.xaxis(label, unit)
277            label, unit = self.plots[self.graph.selected_plottable].get_yaxis()
278            new_plot.yaxis(label, unit)
279            #print "panel scale ",self.xLabel, self.yLabel
280            print "color",self.graph.plottables[self.plots[self.graph.selected_plottable]]
281            color=self.graph.plottables[self.plots[self.graph.selected_plottable]]
282            self.graph.delete_plottable(self.plots[self.graph.selected_plottable])
283           
284            self.graph.add_plottable(new_plot,color)
285            # transforming the view of the new data into the same of the previous data
286            self._onEVT_FUNC_PROPERTY()
287            #print "cyllinder", self.plots[self.graph.selected_plottable].x,self.plots[self.graph.selected_plottable].view.x, new_plot.x, new_plot.view.x
288            self.plots[self.graph.selected_plottable]=new_plot
289           
290            self.graph.render(self)
291            self.subplot.figure.canvas.draw_idle() 
292   
293    def _on_add_errors(self, evt):
294        """
295            Compute reasonable errors for a data set without
296            errors and transorm the plottable to a Data1D
297        """
298        import math
299        import numpy
300        import time
301       
302        if not self.graph.selected_plottable == None:
303            length = len(self.plots[self.graph.selected_plottable].x)
304            dy = numpy.zeros(length)
305            selected_plot= self.plots[self.graph.selected_plottable]
306            try:
307                dy = self.err_dy[selected_plot.name]
308            except:
309                for i in range(length):
310                    dy[i] = math.sqrt(self.plots[self.graph.selected_plottable].y[i])     
311            #for i in range(length):
312            #    dy[i] = math.sqrt(self.plots[self.graph.selected_plottable].y[i])
313               
314            new_plot = Data1D(self.plots[self.graph.selected_plottable].x,
315                              self.plots[self.graph.selected_plottable].y,
316                              dy=dy)
317            new_plot.interactive = True
318            new_plot.name = self.plots[self.graph.selected_plottable].name
319            if hasattr(self.plots[self.graph.selected_plottable], "group_id"):
320                new_plot.group_id = self.plots[self.graph.selected_plottable].group_id
321                new_plot.id = self.plots[self.graph.selected_plottable].id
322            else:
323                new_plot.group_id = str(time.time())
324                new_plot.id = str(time.time())
325           
326            label, unit = self.plots[self.graph.selected_plottable].get_xaxis()
327            new_plot.xaxis(label, unit)
328            label, unit = self.plots[self.graph.selected_plottable].get_yaxis()
329            new_plot.yaxis(label, unit)
330            #print "panel scale ",self.xLabel, self.yLabel
331            color=self.graph.plottables[self.plots[self.graph.selected_plottable]]
332            self.graph.delete_plottable(self.plots[self.graph.selected_plottable])
333            self.graph.add_plottable(new_plot, color)
334            #self.graph.add(new_plot)
335            # transforming the view of the new data into the same of the previous data
336            self._onEVT_FUNC_PROPERTY()
337            #print "cyllinder", self.plots[self.graph.selected_plottable].x,self.plots[self.graph.selected_plottable].view.x, new_plot.x, new_plot.view.x
338            self.plots[self.graph.selected_plottable]=new_plot
339           
340            self.graph.render(self)
341            self.subplot.figure.canvas.draw_idle()   
342   
343    def _onSave(self, evt):
344        """
345            Save a data set to a text file
346            @param evt: Menu event
347        """
348        import os
349        id = str(evt.GetId())
350        if id in self.action_ids:         
351           
352            path = None
353            dlg = wx.FileDialog(self, "Choose a file", os.getcwd(), "", "*.txt", wx.SAVE)
354            if dlg.ShowModal() == wx.ID_OK:
355                path = dlg.GetPath()
356                mypath = os.path.basename(path)
357                #print path
358            dlg.Destroy()
359           
360            if not path == None:
361                out = open(path, 'w')
362                has_errors = True
363                if self.action_ids[id].dy==None or self.action_ids[id].dy==[]:
364                    has_errors = False
365                   
366                # Sanity check
367                if has_errors:
368                    try:
369                        if len(self.action_ids[id].y) != len(self.action_ids[id].dy):
370                            #print "Y and dY have different lengths"
371                            has_errors = False
372                    except:
373                        has_errors = False
374               
375                if has_errors:
376                    out.write("<X>   <Y>   <dY>\n")
377                else:
378                    out.write("<X>   <Y>\n")
379                   
380                for i in range(len(self.action_ids[id].x)):
381                    if has_errors:
382                        out.write("%g  %g  %g\n" % (self.action_ids[id].x[i], 
383                                                    self.action_ids[id].y[i],
384                                                    self.action_ids[id].dy[i]))
385                    else:
386                        out.write("%g  %g\n" % (self.action_ids[id].x[i], 
387                                                self.action_ids[id].y[i]))
388                       
389                out.close()
390   
391 
392
393    def _onToggleScale(self, event):
394        if self.get_yscale() == 'log':
395            self.set_yscale('linear')
396        else:
397            self.set_yscale('log')
398        self.subplot.figure.canvas.draw_idle()   
399       
Note: See TracBrowser for help on using the repository browser.