source: sasview/guiframe/local_perspectives/plotting/Plotter2D.py @ 015d109

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 015d109 was 32c0841, checked in by Gervaise Alina <gervyh@…>, 14 years ago

working on pylint

  • Property mode set to 100644
File size: 20.8 KB
RevLine 
[1bf33c1]1
[d955bf19]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################################################################################
[1bf33c1]11
12
13import wx
[32c0841]14import sys
15import math
[0d9dae8]16import pylab
[1bf33c1]17import danse.common.plottools
18from danse.common.plottools.PlotPanel import PlotPanel
[4ac8556]19from danse.common.plottools.plottables import Graph
[0bd2cd8]20from sans.guicomm.events import EVT_NEW_PLOT
[0d9dae8]21from sans.guicomm.events import EVT_SLICER_PARS
[32c0841]22from sans.guicomm.events import StatusEvent
23from sans.guicomm.events import NewPlotEvent
24from sans.guicomm.events import SlicerEvent
[0d9dae8]25from sans.guiframe.utils import PanelMenu
[1bf33c1]26from binder import BindArtist
27from Plotter1D import ModelPanel1D
[32c0841]28from danse.common.plottools.toolbar import NavigationToolBar
[4ac8556]29from sans.guiframe.dataFitting import Data1D
[32c0841]30(InternalEvent, EVT_INTERNAL) = wx.lib.newevent.NewEvent()
[0d9dae8]31
32DEFAULT_QMAX = 0.05
[1bf33c1]33DEFAULT_QSTEP = 0.001
34DEFAULT_BEAM = 0.005
[ef0c170]35BIN_WIDTH = 1.0
[32c0841]36
[d955bf19]37
[ac8671e]38class NavigationToolBar2D(NavigationToolBar):
[d955bf19]39    """
40    """
[ac8671e]41    def __init__(self, canvas, parent=None):
42        NavigationToolBar.__init__(self, canvas=canvas, parent=parent)
43       
44    def delete_option(self):
45        """
[d955bf19]46        remove default toolbar item
[ac8671e]47        """
48        #delete reset button
49        self.DeleteToolByPos(0) 
50        #delete dragging
[88ca6db]51        self.DeleteToolByPos(2) 
[ac8671e]52        #delete unwanted button that configures subplot parameters
53        self.DeleteToolByPos(4)
54       
55    def add_option(self):
56        """
[d955bf19]57        add item to the toolbar
[ac8671e]58        """
59        #add print button
60        id_print = wx.NewId()
61        print_bmp =  wx.ArtProvider.GetBitmap(wx.ART_PRINT, wx.ART_TOOLBAR)
62        self.AddSimpleTool(id_print, print_bmp,
63                           'Print', 'Activate printing')
64        wx.EVT_TOOL(self, id_print, self.on_print)
65       
66       
67class ModelPanel2D(ModelPanel1D):
[1bf33c1]68    """
[d955bf19]69    Plot panel for use with the GUI manager
[1bf33c1]70    """
71   
72    ## Internal name for the AUI manager
73    window_name = "plotpanel"
74    ## Title to appear on top of the window
75    window_caption = "Plot Panel"
76    ## Flag to tell the GUI manager that this panel is not
77    #  tied to any perspective
78    ALWAYS_ON = True
79    ## Group ID
80    group_id = None
81   
82   
[32c0841]83    def __init__(self, parent, id=-1, data2d=None, color = None,
84                 dpi=None, style=wx.NO_FULL_REPAINT_ON_RESIZE, **kwargs):
[1bf33c1]85        """
[d955bf19]86        Initialize the panel
[1bf33c1]87        """
[32c0841]88        ModelPanel1D.__init__(self, parent, id=id, style=style, **kwargs)
[1bf33c1]89       
90        ## Reference to the parent window
91        self.parent = parent
[6c0568b]92        ## Dictionary containing Plottables
[1bf33c1]93        self.plots = {}
[6c0568b]94        ## Save reference of the current plotted
95        self.data2D = data2d
[1bf33c1]96        ## Unique ID (from gui_manager)
97        self.uid = None
98        ## Action IDs for internal call-backs
99        self.action_ids = {}
[6c0568b]100        ## Create Artist and bind it
[1bf33c1]101        self.connect = BindArtist(self.subplot.figure)
[6c0568b]102        ## Beam stop
[1bf33c1]103        self.beamstop_radius = DEFAULT_BEAM
[6c0568b]104        ## to set the order of lines drawn first.
[f15ed33]105        self.slicer_z = 5
[6c0568b]106        ## Reference to the current slicer
[1bf33c1]107        self.slicer = None
[6c0568b]108        ## event to send slicer info
[d468daa]109        self.Bind(EVT_INTERNAL, self._onEVT_INTERNAL)
[1bf33c1]110       
[6c0568b]111        self.axes_frozen = False
112        ## panel that contains result from slicer motion (ex: Boxsum info)
[32c0841]113        self.panel_slicer = None
[1bf33c1]114        ## Graph       
115        self.graph = Graph()
116        self.graph.xaxis("\\rm{Q}", 'A^{-1}')
[32c0841]117        self.graph.yaxis("\\rm{Intensity} ", "cm^{-1}")
[1bf33c1]118        self.graph.render(self)
[8dfdd20]119        ## store default value of zmin and zmax
120        self.default_zmin_ctl = self.zmin_2D
121        self.default_zmax_ctl = self.zmax_2D
[ac8671e]122       
123    def add_toolbar(self):
124        """
[d955bf19]125        add toolbar
[ac8671e]126        """
127        self.enable_toolbar = True
[32c0841]128        self.toolbar = NavigationToolBar2D(parent=self, canvas=self.canvas)
[ac8671e]129        self.toolbar.Realize()
130        # On Windows platform, default window size is incorrect, so set
131        # toolbar width to figure width.
132        tw, th = self.toolbar.GetSizeTuple()
133        fw, fh = self.canvas.GetSizeTuple()
134        self.toolbar.SetSize(wx.Size(fw, th))
[32c0841]135        self.sizer.Add(self.toolbar, 0, wx.LEFT|wx.EXPAND)
[ac8671e]136        # update the axes menu on the toolbar
137        self.toolbar.update()
138         
[1bf33c1]139    def _onEVT_1DREPLOT(self, event):
140        """
[d955bf19]141        Data is ready to be displayed
142       
143        :TODO: this name should be changed to something more appropriate
144             Don't forget that changing this name will mean changing code
145             in plotting.py
146         
147        :param event: data event
[1bf33c1]148        """
[6c0568b]149        ## Update self.data2d with the current plot
150        self.data2D = event.plot
[15550f4]151       
[1bf33c1]152        #TODO: Check for existence of plot attribute
[6c0568b]153       
[1bf33c1]154        # Check whether this is a replot. If we ask for a replot
155        # and the plottable no longer exists, ignore the event.
[32c0841]156        if hasattr(event, "update") and event.update == True \
[1bf33c1]157            and event.plot.name not in self.plots.keys():
158            return
159        if hasattr(event, "reset"):
160            self._reset()
161        is_new = True
162        if event.plot.name in self.plots.keys():
163            # Check whether the class of plottable changed
[32c0841]164            if not event.plot.__class__ == self.plots[event.plot.name].__class__:
[ab8f936]165                #overwrite a plottable using the same name
[1bf33c1]166                self.graph.delete(self.plots[event.plot.name])
167            else:
[ab8f936]168                # plottable is already draw on the panel
[1bf33c1]169                is_new = False
[ab8f936]170           
171        if is_new:
172            # a new plottable overwrites a plotted one  using the same id
173            for plottable in self.plots.itervalues():
[e48a62e]174                if hasattr(event.plot,"id"):
[32c0841]175                    if event.plot.id == plottable.id:
[e48a62e]176                        self.graph.delete(plottable)
[ab8f936]177           
178            self.plots[event.plot.name] = event.plot
179            self.graph.add(self.plots[event.plot.name])
180        else:
[4b91fd1]181            # Update the plottable with the new data
182           
183            #TODO: we should have a method to do this,
184            #      something along the lines of:
185            #      plottable1.update_data_from_plottable(plottable2)
186           
187            self.plots[event.plot.name].xmin = event.plot.xmin
188            self.plots[event.plot.name].xmax = event.plot.xmax
189            self.plots[event.plot.name].ymin = event.plot.ymin
190            self.plots[event.plot.name].ymax = event.plot.ymax
191            self.plots[event.plot.name].data = event.plot.data
[20b6760]192            self.plots[event.plot.name].qx_data = event.plot.qx_data
193            self.plots[event.plot.name].qy_data = event.plot.qy_data
[4b91fd1]194            self.plots[event.plot.name].err_data = event.plot.err_data
[ac9a5f6]195            # update qmax with the new xmax of data plotted
[32c0841]196            self.qmax = event.plot.xmax
[4b91fd1]197           
[32c0841]198        self.slicer = None
[1bf33c1]199        # Check axis labels
200        #TODO: Should re-factor this
[6c0568b]201        ## render the graph with its new content
[7fff5cd]202               
203        #data2D: put 'Pixel (Number)' for axis title and unit in case of having no detector info and none in _units
204        if len(self.data2D.detector) < 1: 
[32c0841]205            if len(event.plot._xunit) < 1 and len(event.plot._yunit) < 1:
[b03deea]206                event.plot._xaxis = '\\rm{x}'
207                event.plot._yaxis = '\\rm{y}'
208                event.plot._xunit = 'pixel'
209                event.plot._yunit = 'pixel'
[1bf33c1]210        self.graph.xaxis(event.plot._xaxis, event.plot._xunit)
211        self.graph.yaxis(event.plot._yaxis, event.plot._yunit)
[0690e1d]212        self.graph.title(self.data2D.name)
[1bf33c1]213        self.graph.render(self)
214        self.subplot.figure.canvas.draw_idle()
[8dfdd20]215        ## store default value of zmin and zmax
216        self.default_zmin_ctl = self.zmin_2D
217        self.default_zmax_ctl = self.zmax_2D
[1bf33c1]218
219    def onContextMenu(self, event):
220        """
[d955bf19]221        2D plot context menu
222       
223        :param event: wx context event
[15550f4]224       
[d955bf19]225        """
[1bf33c1]226        slicerpop = PanelMenu()
227        slicerpop.set_plots(self.plots)
228        slicerpop.set_graph(self.graph)
[9a585d0]229             
230        id = wx.NewId()
231        slicerpop.Append(id, '&Save image')
232        wx.EVT_MENU(self, id, self.onSaveImage)
233       
234        id = wx.NewId()
[32c0841]235        slicerpop.Append(id,'&Print image', 'Print image')
[9a585d0]236        wx.EVT_MENU(self, id, self.onPrint)
237       
[1ce365f8]238        id = wx.NewId()
[18eba35]239        slicerpop.Append(id,'&Print Preview', 'image preview for print')
[1ce365f8]240        wx.EVT_MENU(self, id, self.onPrinterPreview)
241       
[9a585d0]242        slicerpop.AppendSeparator()
[7fff5cd]243        if len(self.data2D.detector) == 1:       
[0e13148]244           
245            item_list = self.parent.get_context_menu(self.graph)
[32c0841]246            if (not item_list == None) and (not len(item_list) == 0):
247                for item in item_list:
248                    try:
249                        id = wx.NewId()
250                        slicerpop.Append(id, item[0], item[1])
251                        wx.EVT_MENU(self, id, item[2])
252                    except:
253                        msg = "ModelPanel1D.onContextMenu: "
254                        msg += "bad menu item  %s"%sys.exc_value
255                        wx.PostEvent(self.parent, StatusEvent(status=msg))
256                        pass
257                slicerpop.AppendSeparator()
[0e13148]258           
[15550f4]259            id = wx.NewId()
260            slicerpop.Append(id, '&Perform circular average')
261            wx.EVT_MENU(self, id, self.onCircular) 
262            id = wx.NewId()
263            slicerpop.Append(id, '&Sector [Q view]')
264            wx.EVT_MENU(self, id, self.onSectorQ) 
265            id = wx.NewId()
266            slicerpop.Append(id, '&Annulus [Phi view ]')
267            wx.EVT_MENU(self, id, self.onSectorPhi) 
[92c2345]268            id = wx.NewId()
[15550f4]269            slicerpop.Append(id, '&Box Sum')
270            wx.EVT_MENU(self, id, self.onBoxSum) 
271            id = wx.NewId()
272            slicerpop.Append(id, '&Box averaging in Qx')
273            wx.EVT_MENU(self, id, self.onBoxavgX) 
274            id = wx.NewId()
275            slicerpop.Append(id, '&Box averaging in Qy')
276            wx.EVT_MENU(self, id, self.onBoxavgY) 
[32c0841]277            if self.slicer != None:
[eba08f1a]278                id = wx.NewId()
[15550f4]279                slicerpop.Append(id, '&Clear slicer')
280                wx.EVT_MENU(self, id,  self.onClearSlicer) 
[32c0841]281                if self.slicer.__class__.__name__  != "BoxSum":
[15550f4]282                    id = wx.NewId()
283                    slicerpop.Append(id, '&Edit Slicer Parameters')
284                    wx.EVT_MENU(self, id, self._onEditSlicer) 
285            slicerpop.AppendSeparator() 
[0e13148]286        id = wx.NewId()
287        slicerpop.Append(id, '&Detector Parameters')
[32c0841]288        wx.EVT_MENU(self, id, self._onEditDetector)
[1bf33c1]289        id = wx.NewId()
290        slicerpop.Append(id, '&Toggle Linear/Log scale')
291        wx.EVT_MENU(self, id, self._onToggleScale) 
292        pos = event.GetPosition()
293        pos = self.ScreenToClient(pos)
294        self.PopupMenu(slicerpop, pos)
[8bd764d]295   
[ea290ee]296    def _onEditDetector(self, event):
[6d920cd]297        """
[d955bf19]298        Allow to view and edits  detector parameters
299       
300        :param event: wx.menu event
301       
[6d920cd]302        """
[ea290ee]303        import detector_dialog
[8dfdd20]304        dialog = detector_dialog.DetectorDialog(self, -1,base=self.parent,
305                       reset_zmin_ctl =self.default_zmin_ctl,
306                       reset_zmax_ctl = self.default_zmax_ctl,cmap=self.cmap)
[6c0568b]307        ## info of current detector and data2D
[ea290ee]308        xnpts = len(self.data2D.x_bins)
309        ynpts = len(self.data2D.y_bins)
310        xmax = max(self.data2D.xmin, self.data2D.xmax)
311        ymax = max(self.data2D.ymin, self.data2D.ymax)
[32c0841]312        qmax = math.sqrt(math.pow(xmax, 2) + math.pow(ymax, 2))
[ea290ee]313        beam = self.data2D.xmin
[6c0568b]314        ## set dialog window content
[ea290ee]315        dialog.setContent(xnpts=xnpts,ynpts=ynpts,qmax=qmax,
316                           beam=self.data2D.xmin,
317                           zmin = self.zmin_2D,
318                          zmax = self.zmax_2D)
319        if dialog.ShowModal() == wx.ID_OK:
320            evt = dialog.getContent()
321            self.zmin_2D = evt.zmin
322            self.zmax_2D = evt.zmax
[32c0841]323            self.cmap = evt.cmap
[ea290ee]324        dialog.Destroy()
[6c0568b]325        ## Redraw the current image
[32c0841]326        self.image(data=self.data2D.data,
[20b6760]327                   qx_data=self.data2D.qx_data,
328                   qy_data=self.data2D.qy_data,
[ea290ee]329                   xmin= self.data2D.xmin,
330                   xmax= self.data2D.xmax,
331                   ymin= self.data2D.ymin,
332                   ymax= self.data2D.ymax,
333                   zmin= self.zmin_2D,
334                   zmax= self.zmax_2D,
[8dfdd20]335                   cmap= self.cmap,
[32c0841]336                   color=0, symbol=0, label=self.data2D.name)
[ea290ee]337        self.subplot.figure.canvas.draw_idle()
[1bf33c1]338       
339    def freeze_axes(self):
[d955bf19]340        """
341        """
[1bf33c1]342        self.axes_frozen = True
343       
344    def thaw_axes(self):
[d955bf19]345        """
346        """
[1bf33c1]347        self.axes_frozen = False
348       
349    def onMouseMotion(self,event):
[d955bf19]350        """
351        """
[1bf33c1]352        pass
[d955bf19]353   
[1bf33c1]354    def onWheel(self, event):
[d955bf19]355        """
356        """
[6c0568b]357        pass 
358     
[1bf33c1]359    def update(self, draw=True):
360        """
[d955bf19]361        Respond to changes in the model by recalculating the
362        profiles and resetting the widgets.
[1bf33c1]363        """
364        self.draw()
365       
366    def _getEmptySlicerEvent(self):
[6c0568b]367        """
[d955bf19]368        create an empty slicervent
[6c0568b]369        """
[32c0841]370        return SlicerEvent(type=None, params=None, obj_class=None)
[d955bf19]371       
[1bf33c1]372    def _onEVT_INTERNAL(self, event):
373        """
[d955bf19]374        Draw the slicer
375       
376        :param event: wx.lib.newevent (SlicerEvent) containing slicer
[6c0568b]377            parameter
[d955bf19]378           
[1bf33c1]379        """
380        self._setSlicer(event.slicer)
381           
382    def _setSlicer(self, slicer):
[6c0568b]383        """
[d955bf19]384        Clear the previous slicer and create a new one.Post an internal
385        event.
386       
387        :param slicer: slicer class to create
388       
[6c0568b]389        """
390        ## Clear current slicer
[1bf33c1]391        if not self.slicer == None: 
392            self.slicer.clear()           
[6c0568b]393        ## Create a new slicer   
[1bf33c1]394        self.slicer_z += 1
395        self.slicer = slicer(self, self.subplot, zorder=self.slicer_z)
[240c805]396        self.subplot.set_ylim(self.data2D.ymin, self.data2D.ymax)
397        self.subplot.set_xlim(self.data2D.xmin, self.data2D.xmax)
[6c0568b]398        ## Draw slicer
[1bf33c1]399        self.update()
400        self.slicer.update()
[32c0841]401        msg = "Plotter2D._setSlicer  %s"%self.slicer.__class__.__name__
402        wx.PostEvent(self.parent, StatusEvent(status=msg))
[1bf33c1]403        # Post slicer event
404        event = self._getEmptySlicerEvent()
405        event.type = self.slicer.__class__.__name__
406        event.obj_class = self.slicer.__class__
407        event.params = self.slicer.get_params()
[d468daa]408        wx.PostEvent(self, event)
[1bf33c1]409
410    def onCircular(self, event):
411        """
[d955bf19]412        perform circular averaging on Data2D
413       
414        :param event: wx.menu event
415       
[1bf33c1]416        """
417        from DataLoader.manipulations import CircularAverage
[6c0568b]418        ## compute the maximum radius of data2D
[32c0841]419        self.qmax = max(math.fabs(self.data2D.xmax), 
420                        math.fabs(self.data2D.xmin))
421        self.ymax = max(math.fabs(self.data2D.ymax),
422                        math.fabs(self.data2D.ymin))
423        self.radius = math.sqrt(math.pow(self.qmax, 2)+ math.pow(self.ymax, 2)) 
[6c0568b]424        ##Compute beam width
[32c0841]425        bin_width = (self.qmax + self.qmax)/100
[6c0568b]426        ## Create data1D circular average of data2D
[32c0841]427        Circle = CircularAverage(r_min=0, r_max=self.radius, 
428                                 bin_width=bin_width)
[1bf33c1]429        circ = Circle(self.data2D)
430        from sans.guiframe.dataFitting import Data1D
[32c0841]431        if hasattr(circ, "dxl"):
432            dxl = circ.dxl
[1bf33c1]433        else:
[32c0841]434            dxl = None
435        if hasattr(circ, "dxw"):
436            dxw = circ.dxw
[1bf33c1]437        else:
[32c0841]438            dxw = None
439        new_plot = Data1D(x=circ.x, y=circ.y, dy=circ.dy)
440        new_plot.dxl = dxl
441        new_plot.dxw = dxw
442        new_plot.name = "Circ avg " + self.data2D.name
443        new_plot.source = self.data2D.source
444        #new_plot.info = self.data2D.info
[1bf33c1]445        new_plot.interactive = True
[32c0841]446        new_plot.detector = self.data2D.detector
[6c0568b]447        ## If the data file does not tell us what the axes are, just assume...
[32c0841]448        new_plot.xaxis("\\rm{Q}", "A^{-1}")
449        new_plot.yaxis("\\rm{Intensity} ", "cm^{-1}")
450        new_plot.group_id = "Circ avg " + self.data2D.name
451        new_plot.id = "Circ avg " + self.data2D.name
452        new_plot.is_data = True
453        wx.PostEvent(self.parent, 
454                     NewPlotEvent(plot=new_plot, title=new_plot.name))
[ef0c170]455       
[1bf33c1]456    def _onEditSlicer(self, event):
[6c0568b]457        """
[d955bf19]458        Is available only when a slicer is drawn.Create a dialog
459        window where the user can enter value to reset slicer
460        parameters.
461       
462        :param event: wx.menu event
463       
[6c0568b]464        """
[32c0841]465        if self.slicer != None:
[1bf33c1]466            from SlicerParameters import SlicerParameterPanel
[4f8a00c]467            dialog = SlicerParameterPanel(self, -1, "Slicer Parameters")
[1bf33c1]468            dialog.set_slicer(self.slicer.__class__.__name__,
469                            self.slicer.get_params())
470            if dialog.ShowModal() == wx.ID_OK:
471                dialog.Destroy() 
472       
473    def onSectorQ(self, event):
474        """
[d955bf19]475        Perform sector averaging on Q and draw sector slicer
[1bf33c1]476        """
[ef0c170]477        from SectorSlicer import SectorInteractor
[1bf33c1]478        self.onClearSlicer(event)
[32c0841]479        wx.PostEvent(self, InternalEvent(slicer=SectorInteractor))
[1bf33c1]480       
481    def onSectorPhi(self, event):
482        """
[d955bf19]483        Perform sector averaging on Phi and draw annulus slicer
[1bf33c1]484        """
[ef0c170]485        from AnnulusSlicer import AnnulusInteractor
[1bf33c1]486        self.onClearSlicer(event)
[32c0841]487        wx.PostEvent(self, InternalEvent(slicer=AnnulusInteractor))
[1bf33c1]488       
[d955bf19]489    def onBoxSum(self, event):
490        """
491        """
[7ab9241]492        from boxSum import BoxSum
493        self.onClearSlicer(event)
[54cc36a]494        self.slicer_z += 1
495        self.slicer =  BoxSum(self, self.subplot, zorder=self.slicer_z)
496        self.subplot.set_ylim(self.data2D.ymin, self.data2D.ymax)
497        self.subplot.set_xlim(self.data2D.xmin, self.data2D.xmax)
498        self.update()
499        self.slicer.update()
[6c0568b]500        ## Value used to initially set the slicer panel
501        type = self.slicer.__class__.__name__
502        params = self.slicer.get_params()
503        ## Create a new panel to display results of summation of Data2D
[8a7a21b]504        from slicerpanel import SlicerPanel
[32c0841]505        new_panel = SlicerPanel(parent=self.parent, id=-1,
506                                    base=self, type=type,
507                                    params=params, style=wx.RAISED_BORDER)
508       
509        new_panel.window_caption = self.slicer.__class__.__name__ + " " + \
510                                    str(self.data2D.name)
511        new_panel.window_name = self.slicer.__class__.__name__+ " " + \
512                                    str(self.data2D.name)
[6c0568b]513        ## Store a reference of the new created panel
[32c0841]514        self.panel_slicer = new_panel
[6c0568b]515        ## save the window_caption of the new panel in the current slicer
[32c0841]516        self.slicer.set_panel_name(name=new_panel.window_caption)
[6c0568b]517        ## post slicer panel to guiframe to display it
[54cc36a]518        from sans.guicomm.events import SlicerPanelEvent
[32c0841]519        wx.PostEvent(self.parent, SlicerPanelEvent(panel=self.panel_slicer,
520                                                    main_panel=self))
[6c0568b]521
[8a7a21b]522    def onBoxavgX(self,event):
[6c0568b]523        """
[d955bf19]524        Perform 2D data averaging on Qx
525        Create a new slicer .
526       
527        :param event: wx.menu event
[6c0568b]528        """
[8a7a21b]529        from boxSlicer import BoxInteractorX
[38224f10]530        self.onClearSlicer(event)
[32c0841]531        wx.PostEvent(self, InternalEvent(slicer=BoxInteractorX))
[d468daa]532       
[8a7a21b]533    def onBoxavgY(self,event):
[6c0568b]534        """
[d955bf19]535        Perform 2D data averaging on Qy
536        Create a new slicer .
537       
538        :param event: wx.menu event
539       
[6c0568b]540        """
[8a7a21b]541        from boxSlicer import BoxInteractorY
542        self.onClearSlicer(event)
[32c0841]543        wx.PostEvent(self, InternalEvent(slicer=BoxInteractorY))
[6c0568b]544       
[1bf33c1]545    def onClearSlicer(self, event):
546        """
[d955bf19]547        Clear the slicer on the plot
[1bf33c1]548        """
[32c0841]549        if not self.slicer == None:
[1bf33c1]550            self.slicer.clear()
551            self.subplot.figure.canvas.draw()
552            self.slicer = None
553            # Post slicer None event
554            event = self._getEmptySlicerEvent()
[d468daa]555            wx.PostEvent(self, event)
[3562fbc]556   
Note: See TracBrowser for help on using the repository browser.