source: sasview/guiframe/local_perspectives/plotting/Plotter2D.py @ 20b482f

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 20b482f was 003fa4e, checked in by Jae Cho <jhjcho@…>, 14 years ago

Added dq in cir. averaging

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