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

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 f89fa84 was 79492222, checked in by krzywon, 10 years ago

Changed the file and folder names to remove all SANS references.

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