source: sasview/guiframe/local_perspectives/plotting/Plotter2D.py @ ec489f5

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 ec489f5 was ed8ad21, checked in by Jae Cho <jhjcho@…>, 14 years ago

added 2D save as a file in context menu

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