source: sasview/sansguiframe/src/sans/guiframe/local_perspectives/plotting/Plotter2D.py @ 53cf669

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 53cf669 was 53cf669, checked in by Jae Cho <jhjcho@…>, 13 years ago

Can change plotpanel 1D 2D title and set Graph as default: update datapanel cb and menu_graph accordingly

  • Property mode set to 100644
File size: 28.6 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 os
16import math
17import numpy
18import pylab
19import danse.common.plottools
20from danse.common.plottools.PlotPanel import PlotPanel
21from danse.common.plottools.plottables import Graph
22from danse.common.plottools.TextDialog import TextDialog
23from sans.guiframe.events import EVT_NEW_PLOT
24from sans.guiframe.events import EVT_SLICER_PARS
25from sans.guiframe.events import StatusEvent
26from sans.guiframe.events import NewPlotEvent
27from sans.guiframe.events import PanelOnFocusEvent
28from sans.guiframe.events import SlicerEvent
29from sans.guiframe.utils import PanelMenu
30from binder import BindArtist
31from Plotter1D import ModelPanel1D
32from danse.common.plottools.toolbar import NavigationToolBar
33from sans.guiframe.dataFitting import Data1D
34from matplotlib.font_manager import FontProperties
35(InternalEvent, EVT_INTERNAL) = wx.lib.newevent.NewEvent()
36
37DEFAULT_QMAX = 0.05
38DEFAULT_QSTEP = 0.001
39DEFAULT_BEAM = 0.005
40BIN_WIDTH = 1.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       
103        ## Reference to the parent window
104        self.parent = parent
105        ## Dictionary containing Plottables
106        self.plots = {}
107        ## Save reference of the current plotted
108        self.data2D = data2d
109        ## Unique ID (from gui_manager)
110        self.uid = None
111        ## Action IDs for internal call-backs
112        self.action_ids = {}
113        ## Create Artist and bind it
114        self.connect = BindArtist(self.subplot.figure)
115        ## Beam stop
116        self.beamstop_radius = DEFAULT_BEAM
117        ## to set the order of lines drawn first.
118        self.slicer_z = 5
119        ## Reference to the current slicer
120        self.slicer = None
121        ## event to send slicer info
122        self.Bind(EVT_INTERNAL, self._onEVT_INTERNAL)
123       
124        self.axes_frozen = False
125        ## panel that contains result from slicer motion (ex: Boxsum info)
126        self.panel_slicer = None
127        self.title_label = None
128        self.title_font = None
129        self.title_color = 'black'
130        ## Graph       
131        self.graph = Graph()
132        self.graph.xaxis("\\rm{Q}", 'A^{-1}')
133        self.graph.yaxis("\\rm{Intensity} ", "cm^{-1}")
134        self.graph.render(self)
135        ## store default value of zmin and zmax
136        self.default_zmin_ctl = self.zmin_2D
137        self.default_zmax_ctl = self.zmax_2D
138       
139    def onLeftDown(self, event): 
140        """
141        left button down and ready to drag
142       
143        """
144        # Check that the LEFT button was pressed
145        PlotPanel.onLeftDown(self, event)   
146         
147        self.plottable_selected(self.data2D.id)
148        self._manager.set_panel_on_focus(self)
149        wx.PostEvent(self.parent, PanelOnFocusEvent(panel=self))
150       
151    def add_toolbar(self):
152        """
153        add toolbar
154        """
155        self.enable_toolbar = True
156        self.toolbar = NavigationToolBar2D(parent=self, canvas=self.canvas)
157        self.toolbar.Realize()
158        # On Windows platform, default window size is incorrect, so set
159        # toolbar width to figure width.
160        tw, th = self.toolbar.GetSizeTuple()
161        fw, fh = self.canvas.GetSizeTuple()
162        self.toolbar.SetSize(wx.Size(fw, th))
163        self.sizer.Add(self.toolbar, 0, wx.LEFT|wx.EXPAND)
164        # update the axes menu on the toolbar
165        self.toolbar.update()
166         
167    def plot_data(self, data):
168        """
169        Data is ready to be displayed
170       
171        :TODO: this name should be changed to something more appropriate
172             Don't forget that changing this name will mean changing code
173             in plotting.py
174         
175        :param event: data event
176        """
177        xlo = None
178        xhi = None
179        ylo = None 
180        yhi = None
181        ## Update self.data2d with the current plot
182        self.data2D = data
183        if data.id in self.plots.keys():
184            #replace
185            xlo, xhi = self.subplot.get_xlim()
186            ylo, yhi = self.subplot.get_ylim()
187            self.graph.replace(data)
188            self.plots[data.id] = data
189        else:
190            self.plots[data.id] = data
191            self.graph.add(self.plots[data.id]) 
192            # update qmax with the new xmax of data plotted
193            self.qmax = data.xmax
194           
195        self.slicer = None
196        # Check axis labels
197        #TODO: Should re-factor this
198        ## render the graph with its new content
199               
200        #data2D: put 'Pixel (Number)' for axis title and unit in case of having no detector info and none in _units
201        if len(data.detector) < 1: 
202            if len(data._xunit) < 1 and len(data._yunit) < 1:
203                data._xaxis = '\\rm{x}'
204                data._yaxis = '\\rm{y}'
205                data._xunit = 'pixel'
206                data._yunit = 'pixel'
207       
208        # graph properties
209        self.graph.xaxis(data._xaxis, data._xunit)
210        self.graph.yaxis(data._yaxis, data._yunit)
211           
212        data.label = self.title_label
213       
214        if data.label == None:
215            data.label = data.name
216           
217        if not self.title_font:
218            self.graph.title(data.label)
219            self.graph.render(self)
220            # Set the axis labels on subplot
221            self._set_axis_labels()
222            self.draw_plot()
223        else:
224            self.graph.render(self)
225            self.draw_plot()
226            self.subplot.set_title(label=data.label,
227                                   fontproperties=self.title_font,
228                                   color=self.title_color)
229            self.subplot.figure.canvas.draw_idle() 
230       
231       
232        ## store default value of zmin and zmax
233        self.default_zmin_ctl = self.zmin_2D
234        self.default_zmax_ctl = self.zmax_2D
235        # Check if zoomed
236        toolbar_zoomed = self.toolbar.GetToolEnabled(self.toolbar._NTB2_BACK)
237        if not self.is_zoomed and not toolbar_zoomed:
238            return
239       
240        # Recover the x,y limits
241        if (xlo and xhi and ylo and yhi) != None:
242            if (xlo > data.xmin and xhi < data.xmax and\
243                        ylo > data.ymin and yhi < data.ymax):
244                self.subplot.set_xlim((xlo, xhi))     
245                self.subplot.set_ylim((ylo, yhi)) 
246            else: 
247                self.toolbar.update()
248                self._is_zoomed = False
249               
250        # Update Graph menu and help string       
251        pos = self.parent._window_menu.FindItem(self.window_caption)
252        helpString = 'Show/Hide Graph: '
253        helpString += (' ' + data.label +';')
254        self.parent._window_menu.SetHelpString(pos, helpString)
255       
256    def _set_axis_labels(self):
257        """
258        Set axis labels
259        """
260        data = self.data2D
261        # control axis labels from the panel itself
262        yname, yunits = data.get_yaxis()
263        if self.yaxis_label != None:
264            yname = self.yaxis_label
265            yunits = self.yaxis_unit
266        else:
267            self.yaxis_label = yname
268            self.yaxis_unit = yunits
269        xname, xunits = data.get_xaxis()
270        if self.xaxis_label != None:
271            xname = self.xaxis_label
272            xunits = self.xaxis_unit
273        else:
274            self.xaxis_label = xname
275            self.xaxis_unit = xunits
276        self.xaxis(xname, xunits, self.xaxis_font, self.xaxis_color)
277        self.yaxis(yname, yunits, self.yaxis_font, self.yaxis_color)
278       
279    def onContextMenu(self, event):
280        """
281        2D plot context menu
282       
283        :param event: wx context event
284       
285        """
286        slicerpop = PanelMenu()
287        slicerpop.set_plots(self.plots)
288        slicerpop.set_graph(self.graph)
289             
290        id = wx.NewId()
291        slicerpop.Append(id, '&Save Image')
292        wx.EVT_MENU(self, id, self.onSaveImage)
293       
294        id = wx.NewId()
295        slicerpop.Append(id,'&Print Image', 'Print image')
296        wx.EVT_MENU(self, id, self.onPrint)
297       
298        id = wx.NewId()
299        slicerpop.Append(id,'&Print Preview', 'Print preview')
300        wx.EVT_MENU(self, id, self.onPrinterPreview)
301
302        id = wx.NewId()
303        slicerpop.Append(id, '&Copy to Clipboard', 'Copy to the clipboard')
304        wx.EVT_MENU(self, id, self.OnCopyFigureMenu)
305        slicerpop.AppendSeparator()
306        # saving data
307        plot = self.data2D
308        id = wx.NewId()
309        name = plot.name
310        slicerpop.Append(id, "&Save as a File (DAT)" )
311        self.action_ids[str(id)] = plot
312        wx.EVT_MENU(self, id, self._onSave)
313
314        slicerpop.AppendSeparator()
315        if len(self.data2D.detector) == 1:       
316           
317            item_list = self.parent.get_context_menu(self)
318            if (not item_list == None) and (not len(item_list) == 0) and\
319                self.data2D.name.split(" ")[0] != 'Residuals': 
320                # The line above; Not for trunk
321                for item in item_list:
322                    try:
323                        id = wx.NewId()
324                        slicerpop.Append(id, item[0], item[1])
325                        wx.EVT_MENU(self, id, item[2])
326                    except:
327                        msg = "ModelPanel1D.onContextMenu: "
328                        msg += "bad menu item  %s"%sys.exc_value
329                        wx.PostEvent(self.parent, StatusEvent(status=msg))
330                        pass
331                slicerpop.AppendSeparator()
332           
333            id = wx.NewId()
334            slicerpop.Append(id, '&Perform Circular Average')
335            wx.EVT_MENU(self, id, self.onCircular) \
336            # For Masked Data
337            if not plot.mask.all():
338                id = wx.NewId()
339                slicerpop.Append(id, '&Masked Circular Average')
340                wx.EVT_MENU(self, id, self.onMaskedCircular) 
341            id = wx.NewId()
342            slicerpop.Append(id, '&Sector [Q View]')
343            wx.EVT_MENU(self, id, self.onSectorQ) 
344            id = wx.NewId()
345            slicerpop.Append(id, '&Annulus [Phi View ]')
346            wx.EVT_MENU(self, id, self.onSectorPhi) 
347            id = wx.NewId()
348            slicerpop.Append(id, '&Box Sum')
349            wx.EVT_MENU(self, id, self.onBoxSum) 
350            id = wx.NewId()
351            slicerpop.Append(id, '&Box Averaging in Qx')
352            wx.EVT_MENU(self, id, self.onBoxavgX) 
353            id = wx.NewId()
354            slicerpop.Append(id, '&Box Averaging in Qy')
355            wx.EVT_MENU(self, id, self.onBoxavgY) 
356            if self.slicer != None:
357                id = wx.NewId()
358                slicerpop.Append(id, '&Clear Slicer')
359                wx.EVT_MENU(self, id,  self.onClearSlicer) 
360                if self.slicer.__class__.__name__  != "BoxSum":
361                    id = wx.NewId()
362                    slicerpop.Append(id, '&Edit Slicer Parameters')
363                    wx.EVT_MENU(self, id, self._onEditSlicer) 
364            slicerpop.AppendSeparator() 
365           
366        id = wx.NewId()
367        slicerpop.Append(id, '&Edit Graph Label', 'Edit Graph Label')
368        wx.EVT_MENU(self, id, self.onEditLabels)
369        slicerpop.AppendSeparator()
370       
371        id = wx.NewId()
372        slicerpop.Append(id, '&Modify Y Axis Label')
373        wx.EVT_MENU(self, id, self._on_yaxis_label)     
374        id = wx.NewId()
375        slicerpop.Append(id, '&Modify X Axis Label')
376        wx.EVT_MENU(self, id, self._on_xaxis_label)
377        slicerpop.AppendSeparator()
378       
379        id = wx.NewId()
380        slicerpop.Append(id, '&2D Color Map')
381        wx.EVT_MENU(self, id, self._onEditDetector)
382        slicerpop.AppendSeparator()
383       
384        id = wx.NewId()
385        slicerpop.Append(id, '&Toggle Linear/Log Scale')
386        wx.EVT_MENU(self, id, self._onToggleScale) 
387       
388       
389        slicerpop.AppendSeparator()
390        id = wx.NewId()
391        slicerpop.Append(id, '&Window Title')
392        wx.EVT_MENU(self, id, self.onChangeCaption)
393       
394        try:
395            pos_evt = event.GetPosition()
396            pos = self.ScreenToClient(pos_evt)
397        except:
398            pos_x, pos_y = self.toolbar.GetPositionTuple()
399            pos = (pos_x, pos_y + 5)
400        self.PopupMenu(slicerpop, pos)
401       
402           
403    def onEditLabels(self, event):
404        """
405        Edit legend label
406        """
407        selected_plot = self.plots[self.graph.selected_plottable]
408        label = selected_plot.label
409        dial = TextDialog(None, -1, 'Change Label', label)
410        if dial.ShowModal() == wx.ID_OK:
411            try:
412                FONT = FontProperties()
413                newlabel = dial.getText()
414                font = FONT.copy()
415                font.set_size(dial.getSize())
416                font.set_family(dial.getFamily())
417                font.set_style(dial.getStyle())
418                font.set_weight(dial.getWeight())
419                colour = dial.getColor()
420                if len(newlabel) > 0:
421                    # update Label
422                    selected_plot.label = newlabel
423                    self.graph.title(newlabel)
424                    self.title_label = selected_plot.label
425                    self.title_font = font
426                    self.title_color = colour
427                    ## render the graph
428                    self.subplot.set_title(label=self.title_label,
429                                           fontproperties=self.title_font,
430                                           color=self.title_color)
431                    self.subplot.figure.canvas.draw_idle() 
432            except:
433                if self.parent != None:
434                    from sans.guiframe.events import StatusEvent
435                    msg= "Add Text: Error. Check your property values..."
436                    wx.PostEvent(self.parent, StatusEvent(status = msg ))
437                else:
438                    raise
439        dial.Destroy()
440       
441        # Update Graph menu and help string
442        if self.title_label != None:     
443            pos = self.parent._window_menu.FindItem(self.window_caption)
444            helpString = 'Show/Hide Graph: '
445            helpString += (' ' + self.title_label +';')
446            self.parent._window_menu.SetHelpString(pos, helpString)
447
448       
449    def _onEditDetector(self, event):
450        """
451        Allow to view and edits  detector parameters
452       
453        :param event: wx.menu event
454       
455        """
456        import detector_dialog
457        dialog = detector_dialog.DetectorDialog(self, -1,base=self.parent,
458                       reset_zmin_ctl =self.default_zmin_ctl,
459                       reset_zmax_ctl = self.default_zmax_ctl,cmap=self.cmap)
460        ## info of current detector and data2D
461        xnpts = len(self.data2D.x_bins)
462        ynpts = len(self.data2D.y_bins)
463        xmax = max(self.data2D.xmin, self.data2D.xmax)
464        ymax = max(self.data2D.ymin, self.data2D.ymax)
465        qmax = math.sqrt(math.pow(xmax, 2) + math.pow(ymax, 2))
466        beam = self.data2D.xmin
467        ## set dialog window content
468        dialog.setContent(xnpts=xnpts,ynpts=ynpts,qmax=qmax,
469                           beam=self.data2D.xmin,
470                           zmin = self.zmin_2D,
471                          zmax = self.zmax_2D)
472        if dialog.ShowModal() == wx.ID_OK:
473            evt = dialog.getContent()
474            self.zmin_2D = evt.zmin
475            self.zmax_2D = evt.zmax
476            self.cmap = evt.cmap
477        dialog.Destroy()
478        ## Redraw the current image
479        self.image(data=self.data2D.data,
480                   qx_data=self.data2D.qx_data,
481                   qy_data=self.data2D.qy_data,
482                   xmin= self.data2D.xmin,
483                   xmax= self.data2D.xmax,
484                   ymin= self.data2D.ymin,
485                   ymax= self.data2D.ymax,
486                   zmin= self.zmin_2D,
487                   zmax= self.zmax_2D,
488                   cmap= self.cmap,
489                   color=0, symbol=0, label=self.data2D.name)
490        self.subplot.figure.canvas.draw_idle()
491       
492    def freeze_axes(self):
493        """
494        """
495        self.axes_frozen = True
496       
497    def thaw_axes(self):
498        """
499        """
500        self.axes_frozen = False
501       
502    def onMouseMotion(self,event):
503        """
504        """
505        pass
506   
507    def onWheel(self, event):
508        """
509        """
510        pass 
511     
512    def update(self, draw=True):
513        """
514        Respond to changes in the model by recalculating the
515        profiles and resetting the widgets.
516        """
517        self.draw_plot()
518       
519    def _getEmptySlicerEvent(self):
520        """
521        create an empty slicervent
522        """
523        return SlicerEvent(type=None, params=None, obj_class=None)
524       
525    def _onEVT_INTERNAL(self, event):
526        """
527        Draw the slicer
528       
529        :param event: wx.lib.newevent (SlicerEvent) containing slicer
530            parameter
531           
532        """
533        self._setSlicer(event.slicer)
534           
535    def _setSlicer(self, slicer):
536        """
537        Clear the previous slicer and create a new one.Post an internal
538        event.
539       
540        :param slicer: slicer class to create
541       
542        """
543        ## Clear current slicer
544        if not self.slicer == None: 
545            self.slicer.clear()           
546        ## Create a new slicer   
547        self.slicer_z += 1
548        self.slicer = slicer(self, self.subplot, zorder=self.slicer_z)
549        self.subplot.set_ylim(self.data2D.ymin, self.data2D.ymax)
550        self.subplot.set_xlim(self.data2D.xmin, self.data2D.xmax)
551        ## Draw slicer
552        self.update()
553        self.slicer.update()
554        msg = "Plotter2D._setSlicer  %s"%self.slicer.__class__.__name__
555        wx.PostEvent(self.parent, StatusEvent(status=msg))
556        # Post slicer event
557        event = self._getEmptySlicerEvent()
558        event.type = self.slicer.__class__.__name__
559        event.obj_class = self.slicer.__class__
560        event.params = self.slicer.get_params()
561        wx.PostEvent(self, event)
562       
563    def onMaskedCircular(self, event):
564        """
565        perform circular averaging on Data2D with mask if it exists
566       
567        :param event: wx.menu event
568       
569        """
570        self.onCircular(event, True)
571       
572    def onCircular(self, event, ismask=False):
573        """
574        perform circular averaging on Data2D
575       
576        :param event: wx.menu event
577       
578        """
579        # Find the best number of bins
580        npt = math.sqrt(len(self.data2D.data[numpy.isfinite(self.data2D.data)]))
581        npt = math.floor(npt)
582        from sans.dataloader.manipulations import CircularAverage
583        ## compute the maximum radius of data2D
584        self.qmax = max(math.fabs(self.data2D.xmax), 
585                        math.fabs(self.data2D.xmin))
586        self.ymax = max(math.fabs(self.data2D.ymax),
587                        math.fabs(self.data2D.ymin))
588        self.radius = math.sqrt(math.pow(self.qmax, 2)+ math.pow(self.ymax, 2)) 
589        ##Compute beam width
590        bin_width = (self.qmax + self.qmax)/npt
591        ## Create data1D circular average of data2D
592        Circle = CircularAverage(r_min=0, r_max=self.radius, 
593                                 bin_width=bin_width)
594        circ = Circle(self.data2D, ismask=ismask)
595        from sans.guiframe.dataFitting import Data1D
596        if hasattr(circ, "dxl"):
597            dxl = circ.dxl
598        else:
599            dxl = None
600        if hasattr(circ, "dxw"):
601            dxw = circ.dxw
602        else:
603            dxw = None
604
605        new_plot = Data1D(x=circ.x, y=circ.y, dy=circ.dy, dx=circ.dx)
606        new_plot.dxl = dxl
607        new_plot.dxw = dxw
608        new_plot.name = "Circ avg " + self.data2D.name
609        new_plot.source = self.data2D.source
610        #new_plot.info = self.data2D.info
611        new_plot.interactive = True
612        new_plot.detector = self.data2D.detector
613       
614        ## If the data file does not tell us what the axes are, just assume...
615        new_plot.xaxis("\\rm{Q}", "A^{-1}")
616        if hasattr(self.data2D, "scale") and \
617                    self.data2D.scale == 'linear':
618            new_plot.ytransform = 'y'
619            new_plot.yaxis("\\rm{Residuals} ", "normalized")
620        else:
621            new_plot.yaxis("\\rm{Intensity} ", "cm^{-1}")
622
623        new_plot.group_id = "Circ avg " + self.data2D.name
624        new_plot.id = "Circ avg " + self.data2D.name
625        new_plot.is_data = True
626        wx.PostEvent(self.parent, 
627                     NewPlotEvent(plot=new_plot, title=new_plot.name))
628       
629    def _onEditSlicer(self, event):
630        """
631        Is available only when a slicer is drawn.Create a dialog
632        window where the user can enter value to reset slicer
633        parameters.
634       
635        :param event: wx.menu event
636       
637        """
638        if self.slicer != None:
639            from SlicerParameters import SlicerParameterPanel
640            dialog = SlicerParameterPanel(self, -1, "Slicer Parameters")
641            dialog.set_slicer(self.slicer.__class__.__name__,
642                            self.slicer.get_params())
643            if dialog.ShowModal() == wx.ID_OK:
644                dialog.Destroy() 
645       
646    def onSectorQ(self, event):
647        """
648        Perform sector averaging on Q and draw sector slicer
649        """
650        from SectorSlicer import SectorInteractor
651        self.onClearSlicer(event)
652        wx.PostEvent(self, InternalEvent(slicer=SectorInteractor))
653       
654    def onSectorPhi(self, event):
655        """
656        Perform sector averaging on Phi and draw annulus slicer
657        """
658        from AnnulusSlicer import AnnulusInteractor
659        self.onClearSlicer(event)
660        wx.PostEvent(self, InternalEvent(slicer=AnnulusInteractor))
661       
662    def onBoxSum(self, event):
663        """
664        """
665        from boxSum import BoxSum
666        self.onClearSlicer(event)
667        self.slicer_z += 1
668        self.slicer =  BoxSum(self, self.subplot, zorder=self.slicer_z)
669        self.subplot.set_ylim(self.data2D.ymin, self.data2D.ymax)
670        self.subplot.set_xlim(self.data2D.xmin, self.data2D.xmax)
671        self.update()
672        self.slicer.update()
673        ## Value used to initially set the slicer panel
674        type = self.slicer.__class__.__name__
675        params = self.slicer.get_params()
676        ## Create a new panel to display results of summation of Data2D
677        from slicerpanel import SlicerPanel
678        new_panel = SlicerPanel(parent=self.parent, id=-1,
679                                    base=self, type=type,
680                                    params=params, style=wx.RAISED_BORDER)
681       
682        new_panel.window_caption = self.slicer.__class__.__name__ + " " + \
683                                    str(self.data2D.name)
684        new_panel.window_name = self.slicer.__class__.__name__+ " " + \
685                                    str(self.data2D.name)
686        ## Store a reference of the new created panel
687        self.panel_slicer = new_panel
688        ## save the window_caption of the new panel in the current slicer
689        self.slicer.set_panel_name(name=new_panel.window_caption)
690        ## post slicer panel to guiframe to display it
691        from sans.guiframe.events import SlicerPanelEvent
692        wx.PostEvent(self.parent, SlicerPanelEvent(panel=self.panel_slicer,
693                                                    main_panel=self))
694
695    def onBoxavgX(self,event):
696        """
697        Perform 2D data averaging on Qx
698        Create a new slicer .
699       
700        :param event: wx.menu event
701        """
702        from boxSlicer import BoxInteractorX
703        self.onClearSlicer(event)
704        wx.PostEvent(self, InternalEvent(slicer=BoxInteractorX))
705       
706    def onBoxavgY(self,event):
707        """
708        Perform 2D data averaging on Qy
709        Create a new slicer .
710       
711        :param event: wx.menu event
712       
713        """
714        from boxSlicer import BoxInteractorY
715        self.onClearSlicer(event)
716        wx.PostEvent(self, InternalEvent(slicer=BoxInteractorY))
717       
718    def onClearSlicer(self, event):
719        """
720        Clear the slicer on the plot
721        """
722        if not self.slicer == None:
723            self.slicer.clear()
724            self.subplot.figure.canvas.draw()
725            self.slicer = None
726            # Post slicer None event
727            event = self._getEmptySlicerEvent()
728            wx.PostEvent(self, event)
729           
730    def _onSave(self, evt):
731        """
732        Save a data set to a dat(text) file
733       
734        :param evt: Menu event
735       
736        """
737        id = str(evt.GetId())
738        if id in self.action_ids:         
739           
740            path = None
741            wildcard = "IGOR/DAT 2D file in Q_map (*.dat)|*.DAT"
742            dlg = wx.FileDialog(self, "Choose a file",
743                                self._default_save_location,
744                                 "", wildcard , wx.SAVE)
745           
746            if dlg.ShowModal() == wx.ID_OK:
747                path = dlg.GetPath()
748                # ext_num = 0 for .txt, ext_num = 1 for .xml
749                # This is MAC Fix
750                ext_num = dlg.GetFilterIndex()
751                if ext_num == 0:
752                    format = '.dat'
753                else:
754                    format = ''
755                path = os.path.splitext(path)[0] + format
756                mypath = os.path.basename(path)
757               
758                #TODO: This is bad design. The DataLoader is designed
759                #to recognize extensions.
760                # It should be a simple matter of calling the .
761                #save(file, data, '.xml') method
762                # of the DataLoader.loader.Loader class.
763                from sans.dataloader.loader import  Loader
764                #Instantiate a loader
765                loader = Loader() 
766                data = self.data2D
767
768                format = ".dat"
769                if os.path.splitext(mypath)[1].lower() == format:
770                    # Make sure the ext included in the file name
771                    # especially on MAC
772                    fName = os.path.splitext(path)[0] + format
773                    loader.save(fName, data, format)
774                try:
775                    self._default_save_location = os.path.dirname(path)
776                except:
777                    pass   
778            dlg.Destroy()
Note: See TracBrowser for help on using the repository browser.