source: sasview/src/sas/sasgui/guiframe/local_perspectives/plotting/Plotter2D.py @ 39f0bf4

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 39f0bf4 was 39f0bf4, checked in by krzywon, 3 years ago

Modified slicer parameter panel to incorporate batch slicing. Added slicer combobox to slicer panel. Renamed files to be more explicit.

  • Property mode set to 100644
File size: 29.5 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
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        self.batch_slicer = None
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        _, th = self.toolbar.GetSizeTuple()
177        fw, _ = 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        ## store default value of zmin and zmax
244        self.default_zmin_ctl = self.zmin_2D
245        self.default_zmax_ctl = self.zmax_2D
246        if not self.is_zoomed:
247            return
248        # Recover the x,y limits
249        if xlo and xhi and ylo and yhi:
250            if xlo > data.xmin and xhi < data.xmax and \
251                        ylo > data.ymin and yhi < data.ymax:
252                self.subplot.set_xlim((xlo, xhi))
253                self.subplot.set_ylim((ylo, yhi))
254            else:
255                self.toolbar.update()
256                self.is_zoomed = False
257
258    def _set_axis_labels(self):
259        """
260        Set axis labels
261        """
262        data = self.data2D
263        # control axis labels from the panel itself
264        yname, yunits = data.get_yaxis()
265        if self.yaxis_label != None:
266            yname = self.yaxis_label
267            yunits = self.yaxis_unit
268        else:
269            self.yaxis_label = yname
270            self.yaxis_unit = yunits
271        xname, xunits = data.get_xaxis()
272        if self.xaxis_label != None:
273            xname = self.xaxis_label
274            xunits = self.xaxis_unit
275        else:
276            self.xaxis_label = xname
277            self.xaxis_unit = xunits
278        self.xaxis(xname, xunits, self.xaxis_font,
279                   self.xaxis_color, self.xaxis_tick)
280        self.yaxis(yname, yunits, self.yaxis_font,
281                   self.yaxis_color, self.yaxis_tick)
282
283    def onContextMenu(self, event):
284        """
285        2D plot context menu
286
287        :param event: wx context event
288
289        """
290        ids = iter(self._menu_ids)
291        slicerpop = PanelMenu()
292        slicerpop.set_plots(self.plots)
293        slicerpop.set_graph(self.graph)
294
295        wx_id = ids.next()
296        slicerpop.Append(wx_id, '&Save Image', 'Save image as png')
297        wx.EVT_MENU(self, wx_id, self.onSaveImage)
298
299        wx_id = ids.next()
300        slicerpop.Append(wx_id, '&Print Image', 'Print image')
301        wx.EVT_MENU(self, wx_id, self.onPrint)
302
303        wx_id = ids.next()
304        slicerpop.Append(wx_id, '&Copy to Clipboard', 'Copy to the clipboard')
305        wx.EVT_MENU(self, wx_id, self.OnCopyFigureMenu)
306        slicerpop.AppendSeparator()
307        # saving data
308        plot = self.data2D
309        wx_id = ids.next()
310        slicerpop.Append(wx_id, "&Data Info")
311        wx.EVT_MENU(self, wx_id, self._onDataShow)
312
313        wx_id = ids.next()
314        slicerpop.Append(wx_id, "&Save as a File (DAT)")
315        self.action_ids[str(wx_id)] = plot
316        wx.EVT_MENU(self, wx_id, self._onSave)
317
318        slicerpop.AppendSeparator()
319        if len(self.data2D.detector) <= 1:
320            item_list = self.parent.get_current_context_menu(self)
321            if (not item_list == None) and (not len(item_list) == 0) and\
322                self.data2D.name.split(" ")[0] != 'Residuals':
323                for item, wx_id in zip(item_list, [ids.next() for i in range(len(item_list))]):
324                    try:
325                        slicerpop.Append(wx_id, item[0], item[1])
326                        wx.EVT_MENU(self, wx_id, item[2])
327                    except:
328                        msg = "ModelPanel1D.onContextMenu: "
329                        msg += "bad menu item  %s" % sys.exc_value
330                        wx.PostEvent(self.parent, StatusEvent(status=msg))
331                slicerpop.AppendSeparator()
332
333            wx_id = ids.next()
334            slicerpop.Append(wx_id, '&Perform Circular Average')
335            wx.EVT_MENU(self, wx_id, self.onCircular) \
336            # For Masked Data
337            if not plot.mask.all():
338                wx_id = ids.next()
339                slicerpop.Append(wx_id, '&Masked Circular Average')
340                wx.EVT_MENU(self, wx_id, self.onMaskedCircular)
341            wx_id = ids.next()
342            slicerpop.Append(wx_id, '&Sector [Q View]')
343            wx.EVT_MENU(self, wx_id, self.onSectorQ)
344            wx_id = ids.next()
345            slicerpop.Append(wx_id, '&Annulus [Phi View ]')
346            wx.EVT_MENU(self, wx_id, self.onSectorPhi)
347            wx_id = ids.next()
348            slicerpop.Append(wx_id, '&Box Sum')
349            wx.EVT_MENU(self, wx_id, self.onBoxSum)
350            wx_id = ids.next()
351            slicerpop.Append(wx_id, '&Box Averaging in Qx')
352            wx.EVT_MENU(self, wx_id, self.onBoxavgX)
353            wx_id = ids.next()
354            slicerpop.Append(wx_id, '&Box Averaging in Qy')
355            wx.EVT_MENU(self, wx_id, self.onBoxavgY)
356            if self.slicer != None:
357                wx_id = ids.next()
358                slicerpop.Append(wx_id, '&Clear Slicer')
359                wx.EVT_MENU(self, wx_id, self.onClearSlicer)
360                if self.slicer.__class__.__name__ != "BoxSum":
361                    wx_id = ids.next()
362                    name = '&Edit Slicer Parameters and Batch Slicing'
363                    slicerpop.Append(wx_id, name)
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                logging.error(msg)
437                if self.parent != 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 not self.slicer == 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    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[numpy.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, \
617                                       theory=new_plot)
618        wx.PostEvent(self.parent,
619                     NewPlotEvent(plot=new_plot, title=new_plot.name))
620
621    def _onEditSlicer(self, event):
622        """
623        Is available only when a slicer is drawn.Create a dialog
624        window where the user can enter value to reset slicer
625        parameters.
626
627        :param event: wx.menu event
628
629        """
630        if self.slicer != None:
631            from parameters_panel_slicer import SlicerParameterPanel
632            dialog = SlicerParameterPanel(self, -1, "Slicer Parameters")
633            dialog.set_slicer(self.slicer.__class__.__name__,
634                              self.slicer.get_params())
635            if dialog.ShowModal() == wx.ID_OK:
636                dialog.Destroy()
637
638    def onSectorQ(self, event):
639        """
640        Perform sector averaging on Q and draw sector slicer
641        """
642        from SectorSlicer import SectorInteractor
643        self.onClearSlicer(event)
644        wx.PostEvent(self, InternalEvent(slicer=SectorInteractor))
645
646    def onSectorPhi(self, event):
647        """
648        Perform sector averaging on Phi and draw annulus slicer
649        """
650        from AnnulusSlicer import AnnulusInteractor
651        self.onClearSlicer(event)
652        wx.PostEvent(self, InternalEvent(slicer=AnnulusInteractor))
653
654    def onBoxSum(self, event):
655        """
656        """
657        from sas.sasgui.guiframe.gui_manager import MDIFrame
658        from boxSum import BoxSum
659        self.onClearSlicer(event)
660        self.slicer_z += 1
661        self.slicer = BoxSum(self, self.subplot, zorder=self.slicer_z)
662        self.subplot.set_ylim(self.data2D.ymin, self.data2D.ymax)
663        self.subplot.set_xlim(self.data2D.xmin, self.data2D.xmax)
664        self.update()
665        self.slicer.update()
666        ## Value used to initially set the slicer panel
667        params = self.slicer.get_params()
668        ## Create a new panel to display results of summation of Data2D
669        from parameters_panel_boxsum import SlicerPanel
670        win = MDIFrame(self.parent, None, 'None', (100, 200))
671        new_panel = SlicerPanel(parent=win, id=-1,
672                                base=self, type=self.slicer.__class__.__name__,
673                                params=params, style=wx.RAISED_BORDER)
674
675        new_panel.window_caption = self.slicer.__class__.__name__ + " " + \
676                                    str(self.data2D.name)
677        new_panel.window_name = self.slicer.__class__.__name__ + " " + \
678                                    str(self.data2D.name)
679        ## Store a reference of the new created panel
680
681        ## save the window_caption of the new panel in the current slicer
682        self.slicer.set_panel_name(name=new_panel.window_caption)
683        ## post slicer panel to guiframe to display it
684        from sas.sasgui.guiframe.events import SlicerPanelEvent
685
686        win.set_panel(new_panel)
687        new_panel.frame = win
688        wx.PostEvent(self.parent, SlicerPanelEvent(panel=new_panel,
689                                                   main_panel=self))
690        wx.CallAfter(new_panel.frame.Show)
691        self.panel_slicer = new_panel
692
693    def onBoxavgX(self, event):
694        """
695        Perform 2D data averaging on Qx
696        Create a new slicer .
697
698        :param event: wx.menu event
699        """
700        from boxSlicer import BoxInteractorX
701        self.onClearSlicer(event)
702        wx.PostEvent(self, InternalEvent(slicer=BoxInteractorX))
703
704    def onBoxavgY(self, event):
705        """
706        Perform 2D data averaging on Qy
707        Create a new slicer .
708
709        :param event: wx.menu event
710
711        """
712        from boxSlicer import BoxInteractorY
713        self.onClearSlicer(event)
714        wx.PostEvent(self, InternalEvent(slicer=BoxInteractorY))
715
716    def onClearSlicer(self, event):
717        """
718        Clear the slicer on the plot
719        """
720        if not self.slicer == None:
721            self.slicer.clear()
722            self.subplot.figure.canvas.draw()
723            self.slicer = None
724            # Post slicer None event
725            event = self._getEmptySlicerEvent()
726            wx.PostEvent(self, event)
727
728    def _onSave(self, evt):
729        """
730        Save a data set to a dat(text) file
731
732        :param evt: Menu event
733
734        """
735        event_id = str(evt.GetId())
736        if self.parent != None:
737            self._default_save_location = self.parent._default_save_location
738        default_name = self.plots[self.graph.selected_plottable].label
739        if default_name.count('.') > 0:
740            default_name = default_name.split('.')[0]
741        default_name += "_out"
742        if event_id in self.action_ids:
743            self.parent.save_data2d(self.data2D, default_name)
744
745    def _onDataShow(self, evt):
746        """
747        Show the data set in text
748
749        :param evt: Menu event
750
751        """
752        menu = evt.GetEventObject()
753        event_id = evt.GetId()
754        self.set_selected_from_menu(menu, event_id)
755        data = self.plots[self.graph.selected_plottable]
756        default_name = data.label
757        if default_name.count('.') > 0:
758            default_name = default_name.split('.')[0]
759        #default_name += "_out"
760        if self.parent != None:
761            self.parent.show_data2d(data, default_name)
762
763    def modifyGraphAppearance(self, e):
764        self.graphApp = graphAppearance(self, 'Modify graph appearance', legend=False)
765        self.graphApp.setDefaults(self.grid_on, self.legend_on,
766                                  self.xaxis_label, self.yaxis_label,
767                                  self.xaxis_unit, self.yaxis_unit,
768                                  self.xaxis_font, self.yaxis_font,
769                                  find_key(self.get_loc_label(), self.legendLoc),
770                                  self.xcolor, self.ycolor,
771                                  self.is_xtick, self.is_ytick)
772        self.graphApp.Bind(wx.EVT_CLOSE, self.on_graphApp_close)
773
774    def on_graphApp_close(self, e):
775        """
776            Gets values from graph appearance dialog and sends them off
777            to modify the plot
778        """
779        self.onGridOnOff(self.graphApp.get_togglegrid())
780        self.xaxis_label = self.graphApp.get_xlab()
781        self.yaxis_label = self.graphApp.get_ylab()
782        self.xaxis_unit = self.graphApp.get_xunit()
783        self.yaxis_unit = self.graphApp.get_yunit()
784        self.xaxis_font = self.graphApp.get_xfont()
785        self.yaxis_font = self.graphApp.get_yfont()
786        self.is_xtick = self.graphApp.get_xtick_check()
787        self.is_ytick = self.graphApp.get_ytick_check()
788        if self.is_xtick:
789            self.xaxis_tick = self.xaxis_font
790        if self.is_ytick:
791            self.yaxis_tick = self.yaxis_font
792
793        self.xaxis(self.xaxis_label, self.xaxis_unit,
794                   self.graphApp.get_xfont(), self.graphApp.get_xcolor(),
795                   self.xaxis_tick)
796        self.yaxis(self.yaxis_label, self.yaxis_unit,
797                   self.graphApp.get_yfont(), self.graphApp.get_ycolor(),
798                   self.yaxis_tick)
799
800        self.graphApp.Destroy()
Note: See TracBrowser for help on using the repository browser.