source: sasview/src/sas/sasgui/guiframe/local_perspectives/plotting/Plotter2D.py @ 2f6d340

ESS_GUIESS_GUI_DocsESS_GUI_batch_fittingESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_iss879ESS_GUI_iss959ESS_GUI_openclESS_GUI_orderingESS_GUI_sync_sascalcmagnetic_scattrelease-4.2.2ticket-1009ticket-1094-headlessticket-1242-2d-resolutionticket-1243ticket-1249ticket885unittest-saveload
Last change on this file since 2f6d340 was 7432acb, checked in by andyfaff, 8 years ago

MAINT: search+replace '!= None' by 'is not None'

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