source: sasview/src/sas/sasgui/guiframe/local_perspectives/plotting/Plotter2D.py @ 0d8ee36

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.2.2ticket-1009ticket-1094-headlessticket-1242-2d-resolutionticket-1243ticket-1249ticket885unittest-saveload
Last change on this file since 0d8ee36 was 0d8ee36, checked in by krzywon, 7 years ago

Merge branch 'master' into batch_slicer

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