source: sasview/src/sans/guiframe/local_perspectives/plotting/Plotter2D.py @ f468791

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 f468791 was f468791, checked in by Mathieu Doucet <doucetm@…>, 11 years ago

Move plottools under sans

  • Property mode set to 100644
File size: 31.0 KB
Line 
1
2################################################################################
3#This software was developed by the University of Tennessee as part of the
4#Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
5#project funded by the US National Science Foundation.
6#
7#See the license text in license.txt
8#
9#copyright 2008, University of Tennessee
10################################################################################
11
12
13import wx
14import sys
15import math
16import numpy
17from sans.plottools.PlotPanel import PlotPanel
18from sans.plottools.plottables import Graph
19from sans.plottools.TextDialog import TextDialog
20from sans.guiframe.events import StatusEvent
21from sans.guiframe.events import NewPlotEvent
22from sans.guiframe.events import PanelOnFocusEvent
23from sans.guiframe.events import SlicerEvent
24from sans.guiframe.utils import PanelMenu
25from  sans.guiframe.local_perspectives.plotting.binder import BindArtist
26from Plotter1D import ModelPanel1D
27from sans.plottools.toolbar import NavigationToolBar
28from matplotlib.font_manager import FontProperties
29from graphAppearance import graphAppearance
30(InternalEvent, EVT_INTERNAL) = wx.lib.newevent.NewEvent()
31
32DEFAULT_QMAX = 0.05
33DEFAULT_QSTEP = 0.001
34DEFAULT_BEAM = 0.005
35BIN_WIDTH = 1.0
36
37
38def find_key(dic, val):
39    """return the key of dictionary dic given the value"""
40    return [k for k, v in dic.iteritems() if v == val][0]
41
42
43class NavigationToolBar2D(NavigationToolBar):
44    """
45    """
46    def __init__(self, canvas, parent=None):
47        NavigationToolBar.__init__(self, canvas=canvas, parent=parent)
48       
49    def delete_option(self):
50        """
51        remove default toolbar item
52        """
53        #delete reset button
54        self.DeleteToolByPos(0) 
55        #delete dragging
56        self.DeleteToolByPos(2) 
57        #delete unwanted button that configures subplot parameters
58        self.DeleteToolByPos(4)
59       
60    def add_option(self):
61        """
62        add item to the toolbar
63        """
64        #add button
65        id_context = wx.NewId()
66        context_tip = 'Graph Menu'
67        context =  wx.ArtProvider.GetBitmap(wx.ART_LIST_VIEW, wx.ART_TOOLBAR)
68        self.InsertSimpleTool(0, id_context, context, 
69                                   context_tip, context_tip)
70        wx.EVT_TOOL(self, id_context,  self.parent.onToolContextMenu)
71        self.InsertSeparator(1)
72        #add print button
73        id_print = wx.NewId()
74        print_bmp =  wx.ArtProvider.GetBitmap(wx.ART_PRINT, wx.ART_TOOLBAR)
75        self.AddSimpleTool(id_print, print_bmp,
76                           'Print', 'Activate printing')
77        wx.EVT_TOOL(self, id_print, self.on_print)
78       
79       
80class ModelPanel2D(ModelPanel1D):
81    """
82    Plot panel for use with the GUI manager
83    """
84   
85    ## Internal name for the AUI manager
86    window_name = "plotpanel"
87    ## Title to appear on top of the window
88    window_caption = "Plot Panel"
89    ## Flag to tell the GUI manager that this panel is not
90    #  tied to any perspective
91    ALWAYS_ON = True
92    ## Group ID
93    group_id = None
94   
95   
96    def __init__(self, parent, id=-1, data2d=None, color = None,
97                 dpi=None, style=wx.NO_FULL_REPAINT_ON_RESIZE, **kwargs):
98        """
99        Initialize the panel
100        """
101        ModelPanel1D.__init__(self, parent, id=id, style=style, **kwargs)
102        self.parent = parent
103        ## Reference to the parent window
104        if hasattr(parent, "parent"):
105            self.parent = self.parent.parent
106        ## Dictionary containing Plottables
107        self.plots = {}
108        ## Save reference of the current plotted
109        self.data2D = data2d
110        ## Unique ID (from gui_manager)
111        self.uid = None
112        ## Action IDs for internal call-backs
113        self.action_ids = {}
114        ## Create Artist and bind it
115        self.connect = BindArtist(self.subplot.figure)
116        ## Beam stop
117        self.beamstop_radius = DEFAULT_BEAM
118        ## to set the order of lines drawn first.
119        self.slicer_z = 5
120        ## Reference to the current slicer
121        self.slicer = None
122        ## event to send slicer info
123        self.Bind(EVT_INTERNAL, self._onEVT_INTERNAL)
124       
125        self.axes_frozen = False
126        ## panel that contains result from slicer motion (ex: Boxsum info)
127        self.panel_slicer = None
128        self.title_label = None
129        self.title_font = None
130        self.title_color = 'black'
131        ## Graph       
132        self.graph = Graph()
133        self.graph.xaxis("\\rm{Q}", 'A^{-1}')
134        self.graph.yaxis("\\rm{Intensity} ", "cm^{-1}")
135        self.graph.render(self)
136        ## store default value of zmin and zmax
137        self.default_zmin_ctl = self.zmin_2D
138        self.default_zmax_ctl = self.zmax_2D
139
140    def on_plot_qrange(self, event=None):
141        """
142        On Qmin Qmax vertical line event
143        """
144        # Not implemented
145        if event == None:
146            return
147        event.Skip() 
148                       
149    def onLeftDown(self, event): 
150        """
151        left button down and ready to drag
152       
153        """
154        # Check that the LEFT button was pressed
155        PlotPanel.onLeftDown(self, event)   
156        ax = event.inaxes
157        if ax != None:
158            # data coordinate position
159            pos_x = "%8.3g"% event.xdata
160            pos_y = "%8.3g"% event.ydata
161            position = "x: %s    y: %s" % (pos_x, pos_y)
162            wx.PostEvent(self.parent, StatusEvent(status=position))
163        self.plottable_selected(self.data2D.id)
164        self._manager.set_panel_on_focus(self)
165        wx.PostEvent(self.parent, PanelOnFocusEvent(panel=self))
166       
167    def add_toolbar(self):
168        """
169        add toolbar
170        """
171        self.enable_toolbar = True
172        self.toolbar = NavigationToolBar2D(parent=self, canvas=self.canvas)
173        self.toolbar.Realize()
174        # On Windows platform, default window size is incorrect, so set
175        # toolbar width to figure width.
176        tw, th = self.toolbar.GetSizeTuple()
177        fw, fh = self.canvas.GetSizeTuple()
178        self.toolbar.SetSize(wx.Size(fw, th))
179        self.sizer.Add(self.toolbar, 0, wx.LEFT|wx.EXPAND)
180        # update the axes menu on the toolbar
181        self.toolbar.update()
182         
183    def plot_data(self, data):
184        """
185        Data is ready to be displayed
186       
187        :TODO: this name should be changed to something more appropriate
188             Don't forget that changing this name will mean changing code
189             in plotting.py
190         
191        :param event: data event
192        """
193        xlo = None
194        xhi = None
195        ylo = None 
196        yhi = None
197        if data.__class__.__name__ == 'Data1D':
198            return
199        ## Update self.data2d with the current plot
200        self.data2D = data
201        if data.id in self.plots.keys():
202            #replace
203            xlo, xhi = self.subplot.get_xlim()
204            ylo, yhi = self.subplot.get_ylim()
205            self.graph.replace(data)
206            self.plots[data.id] = data
207        else:
208            self.plots[data.id] = data
209            self.graph.add(self.plots[data.id]) 
210            # update qmax with the new xmax of data plotted
211            self.qmax = data.xmax 
212        self.slicer = None
213        # Check axis labels
214        #TODO: Should re-factor this
215        ## render the graph with its new content   
216        #data2D: put 'Pixel (Number)' for axis title and unit in case of having no detector info and none in _units
217        if len(data.detector) < 1: 
218            if len(data._xunit) < 1 and len(data._yunit) < 1:
219                data._xaxis = '\\rm{x}'
220                data._yaxis = '\\rm{y}'
221                data._xunit = 'pixel'
222                data._yunit = 'pixel'
223        # graph properties
224        self.graph.xaxis(data._xaxis, data._xunit)
225        self.graph.yaxis(data._yaxis, data._yunit)
226        if self._is_changed_legend_label:   
227                data.label = self.title_label
228        if data.label == None:
229            data.label = data.name   
230        if not self.title_font:
231            self.graph.title(data.label)
232            self.graph.render(self)
233            # Set the axis labels on subplot
234            self._set_axis_labels()
235            self.draw_plot()
236        else:
237            self.graph.render(self)
238            self.draw_plot()
239            self.subplot.set_title(label=data.label,
240                                   fontproperties=self.title_font,
241                                   color=self.title_color)
242            self.subplot.figure.canvas.draw_idle()   
243        # Update Graph menu and help string       
244        #pos = self.parent._window_menu.FindItem(self.window_caption)
245        helpString = 'Show/Hide Graph: '
246        helpString += (' ' + str(data.label) +';')
247        #self.parent._window_menu.SetHelpString(pos, helpString)
248        ## store default value of zmin and zmax
249        self.default_zmin_ctl = self.zmin_2D
250        self.default_zmax_ctl = self.zmax_2D
251        # Check if zoomed
252        toolbar_zoomed = self.toolbar.GetToolEnabled(self.toolbar._NTB2_BACK)
253        if not self.is_zoomed and not toolbar_zoomed:
254            return
255        # Recover the x,y limits
256        if (xlo and xhi and ylo and yhi) != None:
257            if (xlo > data.xmin and xhi < data.xmax and\
258                        ylo > data.ymin and yhi < data.ymax):
259                self.subplot.set_xlim((xlo, xhi))     
260                self.subplot.set_ylim((ylo, yhi)) 
261            else: 
262                self.toolbar.update()
263                self._is_zoomed = False
264
265    def _set_axis_labels(self):
266        """
267        Set axis labels
268        """
269        data = self.data2D
270        # control axis labels from the panel itself
271        yname, yunits = data.get_yaxis()
272        if self.yaxis_label != None:
273            yname = self.yaxis_label
274            yunits = self.yaxis_unit
275        else:
276            self.yaxis_label = yname
277            self.yaxis_unit = yunits
278        xname, xunits = data.get_xaxis()
279        if self.xaxis_label != None:
280            xname = self.xaxis_label
281            xunits = self.xaxis_unit
282        else:
283            self.xaxis_label = xname
284            self.xaxis_unit = xunits
285        self.xaxis(xname, xunits, self.xaxis_font, 
286                   self.xaxis_color, self.xaxis_tick)
287        self.yaxis(yname, yunits, self.yaxis_font, 
288                   self.yaxis_color, self.yaxis_tick)
289       
290    def onContextMenu(self, event):
291        """
292        2D plot context menu
293       
294        :param event: wx context event
295       
296        """
297        slicerpop = PanelMenu()
298        slicerpop.set_plots(self.plots)
299        slicerpop.set_graph(self.graph)
300             
301        id = wx.NewId()
302        slicerpop.Append(id, '&Save Image')
303        wx.EVT_MENU(self, id, self.onSaveImage)
304       
305        id = wx.NewId()
306        slicerpop.Append(id,'&Print Image', 'Print image')
307        wx.EVT_MENU(self, id, self.onPrint)
308       
309        id = wx.NewId()
310        slicerpop.Append(id,'&Print Preview', 'Print preview')
311        wx.EVT_MENU(self, id, self.onPrinterPreview)
312
313        id = wx.NewId()
314        slicerpop.Append(id, '&Copy to Clipboard', 'Copy to the clipboard')
315        wx.EVT_MENU(self, id, self.OnCopyFigureMenu)
316        slicerpop.AppendSeparator()
317        # saving data
318        plot = self.data2D
319        id = wx.NewId()
320        name = plot.name
321        slicerpop.Append(id, "&Data Info" )
322        wx.EVT_MENU(self, id, self._onDataShow)
323
324        id = wx.NewId()
325        name = plot.name
326        slicerpop.Append(id, "&Save as a File (DAT)" )
327        self.action_ids[str(id)] = plot
328        wx.EVT_MENU(self, id, self._onSave)
329
330        slicerpop.AppendSeparator()
331        if len(self.data2D.detector) == 1:       
332           
333            item_list = self.parent.get_current_context_menu(self)
334            if (not item_list == None) and (not len(item_list) == 0) and\
335                self.data2D.name.split(" ")[0] != 'Residuals': 
336                # The line above; Not for trunk
337                for item in item_list:
338                    try:
339                        id = wx.NewId()
340                        slicerpop.Append(id, item[0], item[1])
341                        wx.EVT_MENU(self, id, item[2])
342                    except:
343                        msg = "ModelPanel1D.onContextMenu: "
344                        msg += "bad menu item  %s"%sys.exc_value
345                        wx.PostEvent(self.parent, StatusEvent(status=msg))
346                        pass
347                slicerpop.AppendSeparator()
348           
349            id = wx.NewId()
350            slicerpop.Append(id, '&Perform Circular Average')
351            wx.EVT_MENU(self, id, self.onCircular) \
352            # For Masked Data
353            if not plot.mask.all():
354                id = wx.NewId()
355                slicerpop.Append(id, '&Masked Circular Average')
356                wx.EVT_MENU(self, id, self.onMaskedCircular) 
357            id = wx.NewId()
358            slicerpop.Append(id, '&Sector [Q View]')
359            wx.EVT_MENU(self, id, self.onSectorQ) 
360            id = wx.NewId()
361            slicerpop.Append(id, '&Annulus [Phi View ]')
362            wx.EVT_MENU(self, id, self.onSectorPhi) 
363            id = wx.NewId()
364            slicerpop.Append(id, '&Box Sum')
365            wx.EVT_MENU(self, id, self.onBoxSum) 
366            id = wx.NewId()
367            slicerpop.Append(id, '&Box Averaging in Qx')
368            wx.EVT_MENU(self, id, self.onBoxavgX) 
369            id = wx.NewId()
370            slicerpop.Append(id, '&Box Averaging in Qy')
371            wx.EVT_MENU(self, id, self.onBoxavgY) 
372            if self.slicer != None:
373                id = wx.NewId()
374                slicerpop.Append(id, '&Clear Slicer')
375                wx.EVT_MENU(self, id,  self.onClearSlicer) 
376                if self.slicer.__class__.__name__  != "BoxSum":
377                    id = wx.NewId()
378                    slicerpop.Append(id, '&Edit Slicer Parameters')
379                    wx.EVT_MENU(self, id, self._onEditSlicer) 
380            slicerpop.AppendSeparator() 
381           
382        id = wx.NewId()
383        slicerpop.Append(id, '&Edit Graph Label', 'Edit Graph Label')
384        wx.EVT_MENU(self, id, self.onEditLabels)
385        slicerpop.AppendSeparator()
386       
387        # ILL mod here
388
389        id = wx.NewId()
390        slicerpop.Append(id, '&Modify graph appearance','Modify graph appearance')
391        wx.EVT_MENU(self, id, self.modifyGraphAppearance)
392        slicerpop.AppendSeparator()
393
394
395       
396        id = wx.NewId()
397        slicerpop.Append(id, '&2D Color Map')
398        wx.EVT_MENU(self, id, self._onEditDetector)
399        slicerpop.AppendSeparator()
400       
401        id = wx.NewId()
402        slicerpop.Append(id, '&Toggle Linear/Log Scale')
403        wx.EVT_MENU(self, id, self._onToggleScale) 
404       
405       
406        slicerpop.AppendSeparator()
407        id = wx.NewId()
408        slicerpop.Append(id, '&Window Title')
409        wx.EVT_MENU(self, id, self.onChangeCaption)
410       
411        try:
412            pos_evt = event.GetPosition()
413            pos = self.ScreenToClient(pos_evt)
414        except:
415            pos_x, pos_y = self.toolbar.GetPositionTuple()
416            pos = (pos_x, pos_y + 5)
417        self.PopupMenu(slicerpop, pos)
418       
419           
420    def onEditLabels(self, event):
421        """
422        Edit legend label
423        """
424        try:
425            selected_plot = self.plots[self.graph.selected_plottable]
426        except:
427            selected_plot = self.plots[self.data2D.id]
428        label = selected_plot.label
429        dial = TextDialog(None, -1, 'Change Label', label)
430        if dial.ShowModal() == wx.ID_OK:
431            try:
432                FONT = FontProperties()
433                newlabel = dial.getText()
434                font = FONT.copy()
435                font.set_size(dial.getSize())
436                font.set_family(dial.getFamily())
437                font.set_style(dial.getStyle())
438                font.set_weight(dial.getWeight())
439                colour = dial.getColor()
440                if len(newlabel) > 0:
441                    # update Label
442                    selected_plot.label = newlabel
443                    self.graph.title(newlabel)
444                    self.title_label = selected_plot.label
445                    self.title_font = font
446                    self.title_color = colour
447                    ## render the graph
448                    self.subplot.set_title(label=self.title_label,
449                                           fontproperties=self.title_font,
450                                           color=self.title_color)
451                    self._is_changed_legend_label = True
452                    self.subplot.figure.canvas.draw_idle() 
453            except:
454                if self.parent != None:
455                    from sans.guiframe.events import StatusEvent
456                    msg= "Add Text: Error. Check your property values..."
457                    wx.PostEvent(self.parent, StatusEvent(status = msg ))
458                else:
459                    raise
460        dial.Destroy()
461       
462        # Update Graph menu and help string
463        if self.title_label != None:     
464            #pos = self.parent._window_menu.FindItem(self.window_caption)
465            helpString = 'Show/Hide Graph: '
466            helpString += (' ' + str(self.title_label) +';')
467            #self.parent._window_menu.SetHelpString(pos, helpString)
468
469       
470    def _onEditDetector(self, event):
471        """
472        Allow to view and edits  detector parameters
473       
474        :param event: wx.menu event
475       
476        """
477        import detector_dialog
478        dialog = detector_dialog.DetectorDialog(self, -1,base=self.parent,
479                       reset_zmin_ctl =self.default_zmin_ctl,
480                       reset_zmax_ctl = self.default_zmax_ctl,cmap=self.cmap)
481        ## info of current detector and data2D
482        xnpts = len(self.data2D.x_bins)
483        ynpts = len(self.data2D.y_bins)
484        xmax = max(self.data2D.xmin, self.data2D.xmax)
485        ymax = max(self.data2D.ymin, self.data2D.ymax)
486        qmax = math.sqrt(math.pow(xmax, 2) + math.pow(ymax, 2))
487        beam = self.data2D.xmin
488        ## set dialog window content
489        dialog.setContent(xnpts=xnpts,ynpts=ynpts,qmax=qmax,
490                           beam=self.data2D.xmin,
491                           zmin = self.zmin_2D,
492                          zmax = self.zmax_2D)
493        if dialog.ShowModal() == wx.ID_OK:
494            evt = dialog.getContent()
495            self.zmin_2D = evt.zmin
496            self.zmax_2D = evt.zmax
497            self.cmap = evt.cmap
498        dialog.Destroy()
499        ## Redraw the current image
500        self.image(data=self.data2D.data,
501                   qx_data=self.data2D.qx_data,
502                   qy_data=self.data2D.qy_data,
503                   xmin= self.data2D.xmin,
504                   xmax= self.data2D.xmax,
505                   ymin= self.data2D.ymin,
506                   ymax= self.data2D.ymax,
507                   zmin= self.zmin_2D,
508                   zmax= self.zmax_2D,
509                   cmap= self.cmap,
510                   color=0, symbol=0, label=self.data2D.name)
511        self.subplot.figure.canvas.draw_idle()
512       
513    def freeze_axes(self):
514        """
515        """
516        self.axes_frozen = True
517       
518    def thaw_axes(self):
519        """
520        """
521        self.axes_frozen = False
522       
523    def onMouseMotion(self,event):
524        """
525        """
526        pass
527   
528    def onWheel(self, event):
529        """
530        """
531        pass 
532     
533    def update(self, draw=True):
534        """
535        Respond to changes in the model by recalculating the
536        profiles and resetting the widgets.
537        """
538        self.draw_plot()
539       
540    def _getEmptySlicerEvent(self):
541        """
542        create an empty slicervent
543        """
544        return SlicerEvent(type=None, params=None, obj_class=None)
545       
546    def _onEVT_INTERNAL(self, event):
547        """
548        Draw the slicer
549       
550        :param event: wx.lib.newevent (SlicerEvent) containing slicer
551            parameter
552           
553        """
554        self._setSlicer(event.slicer)
555           
556    def _setSlicer(self, slicer):
557        """
558        Clear the previous slicer and create a new one.Post an internal
559        event.
560       
561        :param slicer: slicer class to create
562       
563        """
564        ## Clear current slicer
565        if not self.slicer == None: 
566            self.slicer.clear()           
567        ## Create a new slicer   
568        self.slicer_z += 1
569        self.slicer = slicer(self, self.subplot, zorder=self.slicer_z)
570        self.subplot.set_ylim(self.data2D.ymin, self.data2D.ymax)
571        self.subplot.set_xlim(self.data2D.xmin, self.data2D.xmax)
572        ## Draw slicer
573        self.update()
574        self.slicer.update()
575        msg = "Plotter2D._setSlicer  %s"%self.slicer.__class__.__name__
576        wx.PostEvent(self.parent, StatusEvent(status=msg))
577        # Post slicer event
578        event = self._getEmptySlicerEvent()
579        event.type = self.slicer.__class__.__name__
580        event.obj_class = self.slicer.__class__
581        event.params = self.slicer.get_params()
582        wx.PostEvent(self, event)
583       
584    def onMaskedCircular(self, event):
585        """
586        perform circular averaging on Data2D with mask if it exists
587       
588        :param event: wx.menu event
589       
590        """
591        self.onCircular(event, True)
592       
593    def onCircular(self, event, ismask=False):
594        """
595        perform circular averaging on Data2D
596       
597        :param event: wx.menu event
598       
599        """
600        # Find the best number of bins
601        npt = math.sqrt(len(self.data2D.data[numpy.isfinite(self.data2D.data)]))
602        npt = math.floor(npt)
603        from sans.dataloader.manipulations import CircularAverage
604        ## compute the maximum radius of data2D
605        self.qmax = max(math.fabs(self.data2D.xmax), 
606                        math.fabs(self.data2D.xmin))
607        self.ymax = max(math.fabs(self.data2D.ymax),
608                        math.fabs(self.data2D.ymin))
609        self.radius = math.sqrt(math.pow(self.qmax, 2)+ math.pow(self.ymax, 2)) 
610        ##Compute beam width
611        bin_width = (self.qmax + self.qmax)/npt
612        ## Create data1D circular average of data2D
613        Circle = CircularAverage(r_min=0, r_max=self.radius, 
614                                 bin_width=bin_width)
615        circ = Circle(self.data2D, ismask=ismask)
616        from sans.guiframe.dataFitting import Data1D
617        if hasattr(circ, "dxl"):
618            dxl = circ.dxl
619        else:
620            dxl = None
621        if hasattr(circ, "dxw"):
622            dxw = circ.dxw
623        else:
624            dxw = None
625
626        new_plot = Data1D(x=circ.x, y=circ.y, dy=circ.dy, dx=circ.dx)
627        new_plot.dxl = dxl
628        new_plot.dxw = dxw
629        new_plot.name = "Circ avg " + self.data2D.name
630        new_plot.source = self.data2D.source
631        #new_plot.info = self.data2D.info
632        new_plot.interactive = True
633        new_plot.detector = self.data2D.detector
634       
635        ## If the data file does not tell us what the axes are, just assume...
636        new_plot.xaxis("\\rm{Q}", "A^{-1}")
637        if hasattr(self.data2D, "scale") and \
638                    self.data2D.scale == 'linear':
639            new_plot.ytransform = 'y'
640            new_plot.yaxis("\\rm{Residuals} ", "normalized")
641        else:
642            new_plot.yaxis("\\rm{Intensity} ", "cm^{-1}")
643
644        new_plot.group_id = "2daverage"  + self.data2D.name
645        new_plot.id = "Circ avg " + self.data2D.name
646        new_plot.is_data = True
647        self.parent.update_theory(data_id=self.data2D.id, \
648                                       theory=new_plot)
649        wx.PostEvent(self.parent, 
650                     NewPlotEvent(plot=new_plot, title=new_plot.name))
651       
652    def _onEditSlicer(self, event):
653        """
654        Is available only when a slicer is drawn.Create a dialog
655        window where the user can enter value to reset slicer
656        parameters.
657       
658        :param event: wx.menu event
659       
660        """
661        if self.slicer != None:
662            from SlicerParameters import SlicerParameterPanel
663            dialog = SlicerParameterPanel(self, -1, "Slicer Parameters")
664            dialog.set_slicer(self.slicer.__class__.__name__,
665                            self.slicer.get_params())
666            if dialog.ShowModal() == wx.ID_OK:
667                dialog.Destroy() 
668       
669    def onSectorQ(self, event):
670        """
671        Perform sector averaging on Q and draw sector slicer
672        """
673        from SectorSlicer import SectorInteractor
674        self.onClearSlicer(event)
675        wx.PostEvent(self, InternalEvent(slicer=SectorInteractor))
676       
677    def onSectorPhi(self, event):
678        """
679        Perform sector averaging on Phi and draw annulus slicer
680        """
681        from AnnulusSlicer import AnnulusInteractor
682        self.onClearSlicer(event)
683        wx.PostEvent(self, InternalEvent(slicer=AnnulusInteractor))
684       
685    def onBoxSum(self, event):
686        """
687        """
688        from sans.guiframe.gui_manager import MDIFrame
689        from boxSum import BoxSum
690        self.onClearSlicer(event)
691        self.slicer_z += 1
692        self.slicer =  BoxSum(self, self.subplot, zorder=self.slicer_z)
693        self.subplot.set_ylim(self.data2D.ymin, self.data2D.ymax)
694        self.subplot.set_xlim(self.data2D.xmin, self.data2D.xmax)
695        self.update()
696        self.slicer.update()
697        ## Value used to initially set the slicer panel
698        type = self.slicer.__class__.__name__
699        params = self.slicer.get_params()
700        ## Create a new panel to display results of summation of Data2D
701        from slicerpanel import SlicerPanel
702        win = MDIFrame(self.parent, None, 'None', (100, 200))
703        new_panel = SlicerPanel(parent=win, id=-1,
704                                    base=self, type=type,
705                                    params=params, style=wx.RAISED_BORDER)
706       
707        new_panel.window_caption = self.slicer.__class__.__name__ + " " + \
708                                    str(self.data2D.name)
709        new_panel.window_name = self.slicer.__class__.__name__+ " " + \
710                                    str(self.data2D.name)
711        ## Store a reference of the new created panel
712       
713        ## save the window_caption of the new panel in the current slicer
714        self.slicer.set_panel_name(name=new_panel.window_caption)
715        ## post slicer panel to guiframe to display it
716        from sans.guiframe.events import SlicerPanelEvent
717       
718        win.set_panel(new_panel)
719        new_panel.frame = win
720        wx.PostEvent(self.parent, SlicerPanelEvent(panel=new_panel,
721                                                    main_panel=self))
722        wx.CallAfter(new_panel.frame.Show)
723        self.panel_slicer = new_panel
724       
725    def onBoxavgX(self,event):
726        """
727        Perform 2D data averaging on Qx
728        Create a new slicer .
729       
730        :param event: wx.menu event
731        """
732        from boxSlicer import BoxInteractorX
733        self.onClearSlicer(event)
734        wx.PostEvent(self, InternalEvent(slicer=BoxInteractorX))
735       
736    def onBoxavgY(self,event):
737        """
738        Perform 2D data averaging on Qy
739        Create a new slicer .
740       
741        :param event: wx.menu event
742       
743        """
744        from boxSlicer import BoxInteractorY
745        self.onClearSlicer(event)
746        wx.PostEvent(self, InternalEvent(slicer=BoxInteractorY))
747       
748    def onClearSlicer(self, event):
749        """
750        Clear the slicer on the plot
751        """
752        if not self.slicer == None:
753            self.slicer.clear()
754            self.subplot.figure.canvas.draw()
755            self.slicer = None
756            # Post slicer None event
757            event = self._getEmptySlicerEvent()
758            wx.PostEvent(self, event)
759           
760    def _onSave(self, evt):
761        """
762        Save a data set to a dat(text) file
763       
764        :param evt: Menu event
765       
766        """
767        id = str(evt.GetId())
768        if self.parent != None:
769            self._default_save_location = self.parent._default_save_location
770        default_name = self.plots[self.graph.selected_plottable].label
771        if default_name.count('.') > 0:
772            default_name = default_name.split('.')[0]
773        default_name += "_out"
774        if id in self.action_ids:         
775            path = None
776            self.parent.save_data2d(self.data2D, default_name)
777           
778    def _onDataShow(self, evt):
779        """
780        Show the data set in text
781       
782        :param evt: Menu event
783       
784        """
785        menu = evt.GetEventObject()
786        id = evt.GetId()
787        self.set_selected_from_menu(menu, id)
788        data = self.plots[self.graph.selected_plottable]
789        default_name = data.label
790        if default_name.count('.') > 0:
791            default_name = default_name.split('.')[0]
792        #default_name += "_out"
793        if self.parent != None:
794            self.parent.show_data2d(data, default_name)
795       
796
797    def modifyGraphAppearance(self,e):
798        self.graphApp = graphAppearance(self,'Modify graph appearance',
799                                        legend=False)
800
801       
802
803        self.graphApp.setDefaults(self.grid_on,self.legend_on,
804                                  self.xaxis_label,self.yaxis_label,
805                                  self.xaxis_unit,self.yaxis_unit,
806                                  self.xaxis_font,self.yaxis_font,
807                                  find_key(self.get_loc_label(),self.legendLoc),
808                                  self.xcolor,self.ycolor,
809                                   self.is_xtick, self.is_ytick)
810        self.graphApp.Bind(wx.EVT_CLOSE, self.on_graphApp_close)
811   
812
813    def on_graphApp_close(self,e):
814        # gets values from graph appearance dialog and sends them off
815        # to modify the plot
816
817        self.onGridOnOff(self.graphApp.get_togglegrid())
818
819       
820        self.xaxis_label = self.graphApp.get_xlab()
821        self.yaxis_label = self.graphApp.get_ylab()
822        self.xaxis_unit = self.graphApp.get_xunit()
823        self.yaxis_unit = self.graphApp.get_yunit()
824        self.xaxis_font = self.graphApp.get_xfont()
825        self.yaxis_font = self.graphApp.get_yfont()
826        self.is_xtick =  self.graphApp.get_xtick_check()
827        self.is_ytick =  self.graphApp.get_ytick_check()
828        if self.is_xtick:
829            self.xaxis_tick = self.xaxis_font
830        if self.is_ytick:
831            self.yaxis_tick = self.yaxis_font
832
833        self.xaxis(self.xaxis_label, self.xaxis_unit, 
834                   self.graphApp.get_xfont(), self.graphApp.get_xcolor(), 
835                   self.xaxis_tick)
836        self.yaxis(self.yaxis_label, self.yaxis_unit, 
837                   self.graphApp.get_yfont(), self.graphApp.get_ycolor(),
838                   self.yaxis_tick)
839
840        self.graphApp.Destroy()
Note: See TracBrowser for help on using the repository browser.