source: sasview/guiframe/local_perspectives/plotting/Plotter1D.py @ 6285a79

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

hide and show error bug fixed

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