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

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 b9f6d83 was b9f6d83, checked in by Mathieu Doucet <doucetm@…>, 10 years ago

Re #216 Merging wx30 branch

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