source: sasview/src/sas/guiframe/local_perspectives/plotting/Plotter2D.py @ b699768

ESS_GUIESS_GUI_DocsESS_GUI_batch_fittingESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_iss879ESS_GUI_iss959ESS_GUI_openclESS_GUI_orderingESS_GUI_sync_sascalccostrafo411magnetic_scattrelease-4.1.1release-4.1.2release-4.2.2release_4.0.1ticket-1009ticket-1094-headlessticket-1242-2d-resolutionticket-1243ticket-1249ticket885unittest-saveload
Last change on this file since b699768 was b699768, checked in by Piotr Rozyczko <piotr.rozyczko@…>, 8 years ago

Initial commit of the refactored SasCalc? module.

  • 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
17import logging
18from sas.plottools.PlotPanel import PlotPanel
19from sas.plottools.plottables import Graph
20from sas.plottools.TextDialog import TextDialog
21from sas.guiframe.events import StatusEvent
22from sas.guiframe.events import NewPlotEvent
23from sas.guiframe.events import PanelOnFocusEvent
24from sas.guiframe.events import SlicerEvent
25from sas.guiframe.utils import PanelMenu
26from  sas.guiframe.local_perspectives.plotting.binder import BindArtist
27from Plotter1D import ModelPanel1D
28from sas.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')
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                # The line above; Not for trunk
323                # Note: reusing menu ids for the sub-menus.  See Plotter1D.
324                for item, wx_id in zip(item_list, self._menu_ids):
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 != 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                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
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[numpy.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.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 != 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.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.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 not self.slicer == 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 != 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 != 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.