source: sasview/guiframe/local_perspectives/plotting/Plotter1D.py @ 18eba35

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

small bugs fixed: clearing slicer improved

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