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

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 b07ffca was ae84427, checked in by Jae Cho <jhjcho@…>, 12 years ago

mdi frames for main applications

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