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

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

add a new module containing common classes that I used often:
sans.guiframe.utils

remove event slicer and add it in sans.guicoom.events,
modified slicer for those events

  • Property mode set to 100644
File size: 12.3 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 event.plot.id==plottable.id :
112                    self.graph.delete(plottable)
113           
114            self.plots[event.plot.name] = event.plot
115            self.graph.add(self.plots[event.plot.name])
116        else:
117            #replot the graph
118            self.plots[event.plot.name].x = event.plot.x   
119            self.plots[event.plot.name].y = event.plot.y   
120            self.plots[event.plot.name].dy = event.plot.dy 
121            if hasattr(event.plot, 'dx') and hasattr(self.plots[event.plot.name], 'dx'):
122                self.plots[event.plot.name].dx = event.plot.dx   
123 
124       
125        # Check axis labels
126        #TODO: Should re-factor this
127        #if event.plot._xunit != self.graph.prop["xunit"]:
128       
129        self.graph.xaxis(event.plot._xaxis, event.plot._xunit)
130           
131        #if event.plot._yunit != self.graph.prop["yunit"]:
132        self.graph.yaxis(event.plot._yaxis, event.plot._yunit)
133     
134        # Set the view scale for all plots
135       
136        self._onEVT_FUNC_PROPERTY()
137   
138        self.graph.render(self)
139        self.subplot.figure.canvas.draw_idle()
140
141    def onLeftDown(self,event): 
142        """ left button down and ready to drag"""
143           
144        PlotPanel.onLeftDown(self, event)
145        ax = event.inaxes
146        if ax != None:
147            position = "x: %8.3g    y: %8.3g" % (event.xdata, event.ydata)
148            wx.PostEvent(self.parent, StatusEvent(status=position))
149
150    def _onRemove(self, event):
151        """
152        """
153        if not self.graph.selected_plottable == None:
154            print self.graph.selected_plottable
155           
156           
157            self.graph.delete(self.plots[self.graph.selected_plottable])
158            del self.plots[self.graph.selected_plottable]
159            self.graph.render(self)
160            self.subplot.figure.canvas.draw_idle()   
161           
162
163    def onContextMenu(self, event):
164        """
165            1D plot context menu
166            @param event: wx context event
167        """
168        #slicerpop = wx.Menu()
169        slicerpop = PanelMenu()
170        slicerpop.set_plots(self.plots)
171        slicerpop.set_graph(self.graph)
172               
173        # Option to save the data displayed
174       
175        #for plot in self.graph.plottables:
176        if self.graph.selected_plottable in self.plots:
177            plot = self.plots[self.graph.selected_plottable]
178            id = wx.NewId()
179            name = plot.name
180            slicerpop.Append(id, "&Save %s points" % name)
181            self.action_ids[str(id)] = plot
182            wx.EVT_MENU(self, id, self._onSave)
183               
184            # Option to delete plottable
185            id = wx.NewId()
186            slicerpop.Append(id, "Remove %s curve" % name)
187            self.action_ids[str(id)] = plot
188            wx.EVT_MENU(self, id, self._onRemove)
189           
190            # Option to hide
191            #TODO: implement functionality to hide a plottable (legend click)
192            slicerpop.AppendSeparator()
193               
194        # Various plot options
195        id = wx.NewId()
196        slicerpop.Append(id,'&Save image', 'Save image as PNG')
197        wx.EVT_MENU(self, id, self.onSaveImage)
198       
199       
200        item_list = self.parent.get_context_menu(self.graph)
201        if (not item_list==None) and (not len(item_list)==0):
202                slicerpop.AppendSeparator()
203                for item in item_list:
204                    try:
205                        id = wx.NewId()
206                        slicerpop.Append(id, item[0], item[1])
207                        wx.EVT_MENU(self, id, item[2])
208                    except:
209                        print sys.exc_value
210                        print RuntimeError, "View1DPanel.onContextMenu: bad menu item"
211       
212        slicerpop.AppendSeparator()
213       
214        if self.graph.selected_plottable in self.plots:
215            if self.plots[self.graph.selected_plottable].__class__.__name__=="Theory1D":
216                id = wx.NewId()
217                slicerpop.Append(id, '&Add errors to data')
218                #print "panel scale before  ",self.xLabel, self.yLabel
219                #print "cyllinder before adding error", self.plots[self.graph.selected_plottable].x
220                wx.EVT_MENU(self, id, self._on_add_errors)
221            else:
222                id = wx.NewId()
223                slicerpop.Append(id, '&Linear fit')
224                wx.EVT_MENU(self, id, self.onFitting)
225               
226       
227
228        id = wx.NewId()
229        slicerpop.Append(id, '&Change scale')
230        wx.EVT_MENU(self, id, self._onProperties)
231       
232        id = wx.NewId()
233        #slicerpop.AppendSeparator()
234        slicerpop.Append(id, '&Reset Graph')
235        wx.EVT_MENU(self, id, self.onResetGraph)       
236
237        pos = event.GetPosition()
238        pos = self.ScreenToClient(pos)
239        self.PopupMenu(slicerpop, pos)
240   
241   
242    def _on_add_errors(self, evt):
243        """
244            Compute reasonable errors for a data set without
245            errors and transorm the plottable to a Data1D
246        """
247        import math
248        import numpy
249        import time
250       
251        if not self.graph.selected_plottable == None:
252            length = len(self.plots[self.graph.selected_plottable].x)
253            dy = numpy.zeros(length)
254            for i in range(length):
255                dy[i] = math.sqrt(self.plots[self.graph.selected_plottable].y[i])
256               
257            new_plot = Data1D(self.plots[self.graph.selected_plottable].x,
258                              self.plots[self.graph.selected_plottable].y,
259                              dy=dy)
260            new_plot.interactive = True
261            new_plot.name = self.plots[self.graph.selected_plottable].name
262            if hasattr(self.plots[self.graph.selected_plottable], "group_id"):
263                new_plot.group_id = self.plots[self.graph.selected_plottable].group_id
264                new_plot.id = self.plots[self.graph.selected_plottable].id
265            else:
266                new_plot.group_id = str(time.time())
267                new_plot.id = str(time.time())
268           
269            label, unit = self.plots[self.graph.selected_plottable].get_xaxis()
270            new_plot.xaxis(label, unit)
271            label, unit = self.plots[self.graph.selected_plottable].get_yaxis()
272            new_plot.yaxis(label, unit)
273            #print "panel scale ",self.xLabel, self.yLabel
274            self.graph.delete(self.plots[self.graph.selected_plottable])
275           
276            self.graph.add(new_plot)
277            # transforming the view of the new data into the same of the previous data
278            self._onEVT_FUNC_PROPERTY()
279            #print "cyllinder", self.plots[self.graph.selected_plottable].x,self.plots[self.graph.selected_plottable].view.x, new_plot.x, new_plot.view.x
280            self.plots[self.graph.selected_plottable]=new_plot
281           
282            self.graph.render(self)
283            self.subplot.figure.canvas.draw_idle()   
284   
285    def _onSave(self, evt):
286        """
287            Save a data set to a text file
288            @param evt: Menu event
289        """
290        import os
291        id = str(evt.GetId())
292        if id in self.action_ids:         
293           
294            path = None
295            dlg = wx.FileDialog(self, "Choose a file", os.getcwd(), "", "*.txt", wx.SAVE)
296            if dlg.ShowModal() == wx.ID_OK:
297                path = dlg.GetPath()
298                mypath = os.path.basename(path)
299                print path
300            dlg.Destroy()
301           
302            if not path == None:
303                out = open(path, 'w')
304                has_errors = True
305                if self.action_ids[id].dy==None or self.action_ids[id].dy==[]:
306                    has_errors = False
307                   
308                # Sanity check
309                if has_errors:
310                    try:
311                        if len(self.action_ids[id].y) != len(self.action_ids[id].dy):
312                            print "Y and dY have different lengths"
313                            has_errors = False
314                    except:
315                        has_errors = False
316               
317                if has_errors:
318                    out.write("<X>   <Y>   <dY>\n")
319                else:
320                    out.write("<X>   <Y>\n")
321                   
322                for i in range(len(self.action_ids[id].x)):
323                    if has_errors:
324                        out.write("%g  %g  %g\n" % (self.action_ids[id].x[i], 
325                                                    self.action_ids[id].y[i],
326                                                    self.action_ids[id].dy[i]))
327                    else:
328                        out.write("%g  %g\n" % (self.action_ids[id].x[i], 
329                                                self.action_ids[id].y[i]))
330                       
331                out.close()
332   
333   
334    def _onToggleScale(self, event):
335        if self.get_yscale() == 'log':
336            self.set_yscale('linear')
337        else:
338            self.set_yscale('log')
339        self.subplot.figure.canvas.draw_idle()   
340       
Note: See TracBrowser for help on using the repository browser.