source: sasview/src/sas/guiframe/local_perspectives/plotting/Plotter1D.py @ a6f3613

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 a6f3613 was 090e07e, checked in by Mathieu Doucet <doucetm@…>, 10 years ago

pylint fixes

  • Property mode set to 100644
File size: 30.0 KB
RevLine 
[1bf33c1]1
[d955bf19]2################################################################################
[090e07e]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.
[d955bf19]6#
[090e07e]7# See the license text in license.txt
[d955bf19]8#
[090e07e]9# copyright 2008, University of Tennessee
[d955bf19]10################################################################################
[1bf33c1]11
12
13import wx
[4ac8556]14import sys
15import math
16import numpy
[090e07e]17import logging
[79492222]18from sas.plottools.PlotPanel import PlotPanel
[090e07e]19from sas.guiframe.events import StatusEvent
[79492222]20from sas.guiframe.events import PanelOnFocusEvent
21from sas.guiframe.utils import PanelMenu
22from sas.guiframe.panel_base import PanelBase
23from sas.guiframe.gui_style import GUIFRAME_ICON
[f8be87d]24from appearanceDialog import appearanceDialog
[8f59e95]25from graphAppearance import graphAppearance
[1bf33c1]26
[0d9dae8]27DEFAULT_QMAX = 0.05
[1bf33c1]28DEFAULT_QSTEP = 0.001
29DEFAULT_BEAM = 0.005
[32c0841]30BIN_WIDTH = 1
[940aca7]31IS_MAC = (sys.platform == 'darwin')
[0d9dae8]32
[8f59e95]33
34def find_key(dic, val):
35    """return the key of dictionary dic given the value"""
36    return [k for k, v in dic.iteritems() if v == val][0]
37
38
39
[691643c]40class ModelPanel1D(PlotPanel, PanelBase):
[1bf33c1]41    """
[d955bf19]42    Plot panel for use with the GUI manager
[1bf33c1]43    """
[090e07e]44
[1bf33c1]45    ## Internal name for the AUI manager
46    window_name = "plotpanel"
47    ## Title to appear on top of the window
[37c36d9]48    window_caption = "Graph"
[1bf33c1]49    ## Flag to tell the GUI manager that this panel is not
50    #  tied to any perspective
51    ALWAYS_ON = True
52    ## Group ID
53    group_id = None
[090e07e]54
55    def __init__(self, parent, id=-1, color=None,
[32c0841]56                 dpi=None, style=wx.NO_FULL_REPAINT_ON_RESIZE, **kwargs):
57        PlotPanel.__init__(self, parent, id=id, style=style, **kwargs)
[a45037aa]58        PanelBase.__init__(self, parent)
[1bf33c1]59        ## Reference to the parent window
60        self.parent = parent
[ae84427]61        if hasattr(parent, "parent"):
62            self.parent = self.parent.parent
[1bf33c1]63        ## Plottables
64        self.plots = {}
[ae84427]65        self.frame = None
[090e07e]66        # context menu
[52b8b74]67        self._slicerpop = None
[090e07e]68
[52b8b74]69        self._available_data = []
70        self._menu_add_ids = []
[a07e72f]71        self._symbol_labels = self.get_symbol_label()
[2636188]72        self._color_labels = self.get_color_label()
73        self.currColorIndex = ""
[36288ca]74        self._is_changed_legend_label = False
[657e52c]75        self.is_xtick = False
76        self.is_ytick = False
[090e07e]77
[a07e72f]78        self.hide_menu = None
[1bf33c1]79        ## Unique ID (from gui_manager)
80        self.uid = None
[66718a1]81        self.x_size = None
[6063b16]82        ## Default locations
[090e07e]83        # self._default_save_location = os.getcwd()
84        self.size = None
85        self.vl_ind = 0
86        ## Graph
87        # self.graph = Graph()
[1bf33c1]88        self.graph.xaxis("\\rm{Q}", 'A^{-1}')
[32c0841]89        self.graph.yaxis("\\rm{Intensity} ", "cm^{-1}")
[1bf33c1]90        self.graph.render(self)
[3e001f9]91        self.cursor_id = None
[090e07e]92
[6d727ae]93        # In resizing event
94        self.resizing = False
95        self.canvas.set_resizing(self.resizing)
96        self.Bind(wx.EVT_SIZE, self._OnReSize)
[6e75ed0]97        self.parent.SetFocus()
[090e07e]98
99
[a07e72f]100    def get_symbol_label(self):
[52b8b74]101        """
[a07e72f]102        Associates label to symbol
[52b8b74]103        """
[a07e72f]104        _labels = {}
105        i = 0
[6d727ae]106        _labels['Circle'] = i
[a07e72f]107        i += 1
[6d727ae]108        _labels['Cross X '] = i
[a07e72f]109        i += 1
110        _labels['Triangle Down'] = i
111        i += 1
112        _labels['Triangle Up'] = i
113        i += 1
114        _labels['Triangle Left'] = i
115        i += 1
116        _labels['Triangle Right'] = i
117        i += 1
[6d727ae]118        _labels['Cross +'] = i
[a07e72f]119        i += 1
120        _labels['Square'] = i
121        i += 1
[318b5bbb]122        _labels['diamond'] = i
[a07e72f]123        i += 1
124        _labels['Diamond'] = i
125        i += 1
126        _labels['Hexagon1'] = i
127        i += 1
128        _labels['Hexagon2'] = i
129        i += 1
130        _labels['Pentagon'] = i
131        i += 1
[6d727ae]132        _labels['Line'] = i
[6c4130a]133        i += 1
134        _labels['Dash'] = i
135        i += 1
136        _labels['Vline'] = i
137        i += 1
138        _labels['Step'] = i
[a07e72f]139        return _labels
[090e07e]140
[2636188]141    def get_color_label(self):
142        """
143        Associates label to a specific color
144        """
145        _labels = {}
146        i = 0
147        _labels['Blue'] = i
148        i += 1
149        _labels['Green'] = i
150        i += 1
151        _labels['Red'] = i
152        i += 1
153        _labels['Cyan'] = i
154        i += 1
155        _labels['Magenta'] = i
156        i += 1
157        _labels['Yellow'] = i
[ad019b83]158        i += 1
159        _labels['Black'] = i
[2636188]160        return _labels
[a07e72f]161
[090e07e]162
[32c0841]163    def set_data(self, list=None):
[3c44c66]164        """
165        """
166        pass
[090e07e]167
[1bf33c1]168    def _reset(self):
169        """
[d955bf19]170        Resets internal data and graph
[090e07e]171        """
[1bf33c1]172        self.graph.reset()
[090e07e]173        self.plots = {}
[cafa75f]174        self.is_zoomed = False
[090e07e]175
176    def _OnReSize(self, event):
[6d727ae]177        """
178        On response of the resize of a panel, set axes_visiable False
179        """
[66718a1]180        # It was found that wx >= 2.9.3 sends an event even if no size changed.
[294efd5]181        # So manually recode the size (=x_size) and compare here.
[940aca7]182        # Massy code to work around:<
183        if self.parent._mgr != None:
184            max_panel = self.parent._mgr.GetPane(self)
185            if max_panel.IsMaximized():
186                self.parent._mgr.RestorePane(max_panel)
187                max_panel.Maximize()
[66718a1]188        if self.x_size != None:
189            if self.x_size == self.GetSize():
[71fa9bb9]190                self.resizing = False
191                self.canvas.set_resizing(self.resizing)
[66718a1]192                return
[294efd5]193        self.x_size = self.GetSize()
194
[ad9e5e1]195        # Ready for another event
[4520830]196        # Do not remove this Skip. Otherwise it will get runtime error on wx>=2.9.
[090e07e]197        event.Skip()
[6d727ae]198        # set the resizing flag
199        self.resizing = True
200        self.canvas.set_resizing(self.resizing)
201        self.parent.set_schedule(True)
[adf44c2]202        pos_x, pos_y = self.GetPositionTuple()
203        if pos_x != 0 and pos_y != 0:
[294efd5]204            self.size, _ = self.GetClientSizeTuple()
[2b29bb4]205        self.SetSizer(self.sizer)
[090e07e]206        wx.CallAfter(self.parent.disable_app_menu, self)
207
[3e001f9]208    def on_plot_qrange(self, event=None):
209        """
210        On Qmin Qmax vertical line event
211        """
212        if event == None:
213            return
[090e07e]214        event.Skip()
[3e001f9]215        active_ctrl = event.active
216        if active_ctrl == None:
217            return
218        if event.id in self.plots.keys():
219            # Set line position and color
220            colors = ['red', 'purple']
221            self.cursor_id = event.id
222            ctrl = event.ctrl
223            if self.ly == None:
224                self.ly = []
225                for ind_ly in range(len(colors)):
[090e07e]226                    self.ly.append(self.subplot.axvline(color=colors[ind_ly],
[3e001f9]227                                                        lw=2.5, alpha=0.7))
[090e07e]228                    self.ly[ind_ly].set_rasterized(True)
[3e001f9]229            try:
230                # Display x,y in the status bar if possible
231                xval = float(active_ctrl.GetValue())
232                position = self.get_data_xy_vals(xval)
233                if position != None:
234                    wx.PostEvent(self.parent, StatusEvent(status=position))
235            except:
[090e07e]236                logging.error(sys.exc_value)
[3e001f9]237            if not event.leftdown:
[090e07e]238                # text event
[3e001f9]239                try:
240                    is_moved = False
241                    for idx in range(len(self.ly)):
242                        val = float(ctrl[idx].GetValue())
243                        # check if vline moved
244                        if self.ly[idx].get_xdata() != val:
245                            self.ly[idx].set_xdata(val)
246                            is_moved = True
247                    if is_moved:
[090e07e]248                        self.canvas.draw()
[3e001f9]249                except:
[090e07e]250                    logging.error(sys.exc_value)
251                event.Skip()
[3e001f9]252                return
253            self.q_ctrl = ctrl
[090e07e]254            pos_x_min = float(self.q_ctrl[0].GetValue())
255            pos_x_max = float(self.q_ctrl[1].GetValue())
[3e001f9]256            pos_x = [pos_x_min, pos_x_max]
257            for ind_ly in range(len(colors)):
258                self.ly[ind_ly].set_color(colors[ind_ly])
259                self.ly[ind_ly].set_xdata(pos_x[ind_ly])
260            self.canvas.draw()
261        else:
262            self.q_ctrl = None
[090e07e]263
[3e001f9]264    def get_data_xy_vals(self, xval):
265        """
266        Get x, y data values near x = x_val
267        """
268        try:
269            x_data = self.plots[self.cursor_id].x
270            y_data = self.plots[self.cursor_id].y
271            indx = self._find_nearest(x_data, xval)
272            pos_x = x_data[indx]
273            pos_y = y_data[indx]
274            position = str(pos_x), str(pos_y)
275            return position
276        except:
277            return None
[090e07e]278
[3e001f9]279    def _find_nearest(self, array, value):
280        """
281        Find and return the nearest value in array to the value.
282        Used in cusor_line()
283        :Param array: numpy array
284        :Param value: float
285        """
286        idx = (numpy.abs(array - value)).argmin()
[090e07e]287        return int(idx)  # array.flat[idx]
288
[3e001f9]289    def _check_line_positions(self, pos_x=None, nop=None):
290        """
291        Check vertical line positions
292        :Param pos_x: position of the current line [float]
293        :Param nop: number of plots [int]
294        """
295        ly = self.ly
296        ly0x = ly[0].get_xdata()
297        ly1x = ly[1].get_xdata()
298        self.q_ctrl[0].SetBackgroundColour('white')
299        self.q_ctrl[1].SetBackgroundColour('white')
300        if ly0x >= ly1x:
301            if self.vl_ind == 0:
302                ly[1].set_xdata(pos_x)
303                ly[1].set_zorder(nop)
304                self.q_ctrl[1].SetValue(str(pos_x))
305                self.q_ctrl[0].SetBackgroundColour('pink')
306            elif self.vl_ind == 1:
307                ly[0].set_xdata(pos_x)
308                ly[0].set_zorder(nop)
309                self.q_ctrl[0].SetValue(str(pos_x))
310                self.q_ctrl[1].SetBackgroundColour('pink')
[090e07e]311
[3e001f9]312    def _get_cusor_lines(self, event):
313        """
314        Revmove or switch cursor line if drawn
315        :Param event: LeftClick mouse event
[090e07e]316        """
[3e001f9]317        ax = event.inaxes
[ae84427]318        if hasattr(event, "action"):
319            dclick = event.action == 'dclick'
320            if ax == None or dclick:
321                # remove the vline
322                self._check_zoom_plot()
323                self.canvas.draw()
324                self.q_ctrl = None
[090e07e]325                return
[3e001f9]326        if self.ly != None and event.xdata != None:
327            # Selecting a new line if cursor lines are displayed already
328            dqmin = math.fabs(event.xdata - self.ly[0].get_xdata())
329            dqmax = math.fabs(event.xdata - self.ly[1].get_xdata())
330            is_qmax = dqmin > dqmax
331            if is_qmax:
332                self.vl_ind = 1
333            else:
[090e07e]334                self.vl_ind = 0
335
[3e001f9]336    def cusor_line(self, event):
337        """
338        Move the cursor line to write Q range
339        """
340        if self.q_ctrl == None:
341            return
[090e07e]342        # release a q range vline
[3e001f9]343        if self.ly != None and not self.leftdown:
344            for ly in self.ly:
345                ly.set_alpha(0.7)
346                self.canvas.draw()
347            return
348        ax = event.inaxes
349        if ax == None or not hasattr(event, 'action'):
350            return
351        end_drag = event.action != 'drag' and event.xdata != None
352        nop = len(self.plots)
[090e07e]353        pos_x, _ = float(event.xdata), float(event.ydata)
[3e001f9]354        try:
355            ly = self.ly
356            ly0x = ly[0].get_xdata()
357            ly1x = ly[1].get_xdata()
358            if ly0x == ly1x:
359                if ly[0].get_zorder() > ly[1].get_zorder():
360                    self.vl_ind = 0
361                else:
362                    self.vl_ind = 1
363            vl_ind = self.vl_ind
364            x_data = self.plots[self.cursor_id].x
365            xmin = x_data.min()
366            xmax = x_data.max()
367            indx = self._find_nearest(x_data, pos_x)
368            # Need to hold LeftButton to drag
369            if end_drag:
370                if event.button:
371                    self._check_line_positions(pos_x, nop)
[090e07e]372                return
[3e001f9]373            if indx >= len(x_data):
374                indx = len(x_data) - 1
375            pos_x = x_data[indx]
376            if xmin == ly1x:
377                vl_ind = 1
378            elif xmax == ly0x:
379                vl_ind = 0
380            else:
381                ly[vl_ind].set_xdata(pos_x)
382                ly[vl_ind].set_zorder(nop + 1)
383                self._check_line_positions(pos_x, nop)
384            ly[vl_ind].set_xdata(pos_x)
385            ly[vl_ind].set_alpha(1.0)
386            ly[vl_ind].set_zorder(nop + 1)
387            self.canvas.draw()
388            self.q_ctrl[vl_ind].SetValue(str(pos_x))
389        except:
[090e07e]390            logging.error(sys.exc_value)
391
[6d727ae]392    def set_resizing(self, resizing=False):
393        """
394        Set the resizing (True/False)
395        """
396        self.resizing = resizing
[090e07e]397        # self.canvas.set_resizing(resizing)
398
399    def schedule_full_draw(self, func='append'):
[6d727ae]400        """
401        Put self in schedule to full redraw list
402        """
403        # append/del this panel in the schedule list
404        self.parent.set_schedule_full_draw(self, func)
405
[a07e72f]406    def remove_data_by_id(self, id):
[98816c43]407        """
408            Remove data from plot
[a07e72f]409        """
410        if id in self.plots.keys():
[090e07e]411            data = self.plots[id]
[a07e72f]412            self.graph.delete(data)
413            data_manager = self._manager.parent.get_data_manager()
[df22224]414            data_list, theory_list = data_manager.get_by_id(id_list=[id])
[090e07e]415
[df22224]416            if id in data_list.keys():
417                data = data_list[id]
[248b918]418            if id in theory_list.keys():
[df22224]419                data = theory_list[id]
[090e07e]420
[a07e72f]421            del self.plots[id]
422            self.graph.render(self)
[090e07e]423            self.subplot.figure.canvas.draw_idle()
[a07e72f]424            if len(self.graph.plottables) == 0:
[090e07e]425                # onRemove: graph is empty must be the panel must be destroyed
[df22224]426                self.parent.delete_panel(self.uid)
[090e07e]427
[a07e72f]428    def plot_data(self, data):
[1bf33c1]429        """
[d955bf19]430        Data is ready to be displayed
[090e07e]431
[d955bf19]432        :param event: data event
[1bf33c1]433        """
[b837e1f]434        if data.__class__.__name__ == 'Data2D':
435            return
[6c4130a]436        plot_keys = self.plots.keys()
437        if data.id in plot_keys:
[090e07e]438            # Recover panel prop.s
[e4a703a]439            xlo, xhi = self.subplot.get_xlim()
440            ylo, yhi = self.subplot.get_ylim()
[5eede4e]441            old_data = self.plots[data.id]
[36288ca]442            if self._is_changed_legend_label:
443                data.label = old_data.label
[c9579e0]444            if old_data.__class__.__name__ == 'Data1D':
445                data.custom_color = old_data.custom_color
446                data.symbol = old_data.symbol
447                data.markersize = old_data.markersize
[6c4130a]448                data.zorder = len(plot_keys)
[e4a703a]449            # Replace data
[a07e72f]450            self.graph.replace(data)
451            self.plots[data.id] = data
[e4a703a]452            ## Set the view scale for all plots
[a4964b8e]453            try:
454                self._onEVT_FUNC_PROPERTY()
[cafa75f]455            except Exception, exc:
[090e07e]456                wx.PostEvent(self.parent,
457                             StatusEvent(status="Plotting Error: %s" % str(exc), info="error"))
[cafa75f]458            if self.is_zoomed:
[7022fdc]459                # Recover the x,y limits
[090e07e]460                self.subplot.set_xlim((xlo, xhi))
461                self.subplot.set_ylim((ylo, yhi))
[a07e72f]462        else:
463            self.plots[data.id] = data
[090e07e]464            self.graph.add(self.plots[data.id])
[6c4130a]465            data.zorder = len(plot_keys)
[e4a703a]466            ## Set the view scale for all plots
[a4964b8e]467            try:
468                self._onEVT_FUNC_PROPERTY()
[940aca7]469                if IS_MAC:
470                    # MAC: forcing to plot 2D avg
471                    self.canvas._onDrawIdle()
[090e07e]472            except Exception, exc:
[4904062]473                wx.PostEvent(self.parent, StatusEvent(status=\
[090e07e]474                    "Plotting Error: %s" % str(exc), info="error"))
[fe48fcc]475            self.toolbar.update()
[cafa75f]476            self.is_zoomed = False
[090e07e]477
[6d727ae]478    def draw_plot(self):
479        """
480        Draw plot
481        """
[090e07e]482        self.draw()
[6d727ae]483
[090e07e]484    def onLeftDown(self, event):
485        """
[d955bf19]486        left button down and ready to drag
487        Display the position of the mouse on the statusbar
[6c0568b]488        """
[090e07e]489        # self.parent.set_plot_unfocus()
[3e001f9]490        self._get_cusor_lines(event)
[e85e2bc]491        ax = event.inaxes
[3e001f9]492        PlotPanel.onLeftDown(self, event)
[e85e2bc]493        if ax != None:
[902f373]494            try:
[090e07e]495                pos_x = float(event.xdata)  # / size_x
496                pos_y = float(event.ydata)  # / size_y
497                pos_x = "%8.3g" % pos_x
498                pos_y = "%8.3g" % pos_y
[902f373]499                self.position = str(pos_x), str(pos_y)
500                wx.PostEvent(self.parent, StatusEvent(status=self.position))
501            except:
[090e07e]502                self.position = None
[0275276]503        # unfocus all
[090e07e]504        self.parent.set_plot_unfocus()
505        # post nd event to notify guiframe that this panel is on focus
[a45037aa]506        wx.PostEvent(self.parent, PanelOnFocusEvent(panel=self))
[df68da1]507
[090e07e]508
[a07e72f]509    def _ontoggle_hide_error(self, event):
510        """
511        Toggle error display to hide or show
512        """
[70ec588d]513        menu = event.GetEventObject()
[090e07e]514        event_id = event.GetId()
515        self.set_selected_from_menu(menu, event_id)
[ebf422a]516        # Check zoom
517        xlo, xhi = self.subplot.get_xlim()
518        ylo, yhi = self.subplot.get_ylim()
519
[a07e72f]520        selected_plot = self.plots[self.graph.selected_plottable]
[5637362]521        if self.hide_menu.GetText() == "Hide Error Bar":
[a07e72f]522            selected_plot.hide_error = True
523        else:
524            selected_plot.hide_error = False
525        ## increment graph color
526        self.graph.render(self)
[090e07e]527        self.subplot.figure.canvas.draw_idle()
[cafa75f]528        if self.is_zoomed:
[ebf422a]529            # Recover the x,y limits
[090e07e]530            self.subplot.set_xlim((xlo, xhi))
531            self.subplot.set_ylim((ylo, yhi))
532
[ebf422a]533
[1bf33c1]534    def _onRemove(self, event):
535        """
[090e07e]536        Remove a plottable from the graph and render the graph
537
[d955bf19]538        :param event: Menu event
[090e07e]539
[1bf33c1]540        """
[70ec588d]541        menu = event.GetEventObject()
[090e07e]542        event_id = event.GetId()
543        self.set_selected_from_menu(menu, event_id)
[6c0568b]544        ## Check if there is a selected graph to remove
[a07e72f]545        if self.graph.selected_plottable in self.plots.keys():
[090e07e]546            graph_id = self.graph.selected_plottable
547            self.remove_data_by_id(graph_id)
548
[1bf33c1]549    def onContextMenu(self, event):
550        """
[d955bf19]551        1D plot context menu
[090e07e]552
[d955bf19]553        :param event: wx context event
[090e07e]554
[1bf33c1]555        """
[52b8b74]556        self._slicerpop = PanelMenu()
557        self._slicerpop.set_plots(self.plots)
[090e07e]558        self._slicerpop.set_graph(self.graph)
559        if not self.graph.selected_plottable in self.plots:
[70ec588d]560            # Various plot options
[090e07e]561            wx_id = wx.NewId()
562            self._slicerpop.Append(wx_id, '&Save Image', 'Save image as PNG')
563            wx.EVT_MENU(self, wx_id, self.onSaveImage)
564            wx_id = wx.NewId()
565            self._slicerpop.Append(wx_id, '&Print Image', 'Print image ')
566            wx.EVT_MENU(self, wx_id, self.onPrint)
567            wx_id = wx.NewId()
568            self._slicerpop.Append(wx_id, '&Print Preview', 'Print preview')
569            wx.EVT_MENU(self, wx_id, self.onPrinterPreview)
570
571            wx_id = wx.NewId()
572            self._slicerpop.Append(wx_id, '&Copy to Clipboard',
[f866fb5]573                                   'Copy to the clipboard')
[090e07e]574            wx.EVT_MENU(self, wx_id, self.OnCopyFigureMenu)
575
[70ec588d]576            self._slicerpop.AppendSeparator()
577
578        for plot in self.plots.values():
[090e07e]579            # title = plot.title
[6d727ae]580            name = plot.name
[70ec588d]581            plot_menu = wx.Menu()
[242aff5]582            if self.graph.selected_plottable:
[4a9bce1]583                if not self.graph.selected_plottable in self.plots.keys():
584                    continue
[242aff5]585                if plot != self.plots[self.graph.selected_plottable]:
586                    continue
[090e07e]587
588            wx_id = wx.NewId()
589            plot_menu.Append(wx_id, "&DataInfo", name)
590            wx.EVT_MENU(self, wx_id, self. _onDataShow)
591            wx_id = wx.NewId()
592            plot_menu.Append(wx_id, "&Save Points as a File", name)
593            wx.EVT_MENU(self, wx_id, self._onSave)
[940aca7]594            plot_menu.AppendSeparator()
[090e07e]595
596            # add menu of other plugins
[940aca7]597            item_list = self.parent.get_current_context_menu(self)
[090e07e]598
[70ec588d]599            if (not item_list == None) and (not len(item_list) == 0):
600                for item in item_list:
[242aff5]601
[70ec588d]602                    try:
[090e07e]603                        wx_id = wx.NewId()
604                        plot_menu.Append(wx_id, item[0], name)
605                        wx.EVT_MENU(self, wx_id, item[2])
[70ec588d]606                    except:
607                        msg = "ModelPanel1D.onContextMenu: "
608                        msg += "bad menu item  %s" % sys.exc_value
609                        wx.PostEvent(self.parent, StatusEvent(status=msg))
610                plot_menu.AppendSeparator()
[090e07e]611
612            if self.parent.ClassName.count('wxDialog') == 0:
613                wx_id = wx.NewId()
614                plot_menu.Append(wx_id, '&Linear Fit', name)
615                wx.EVT_MENU(self, wx_id, self.onFitting)
[70ec588d]616                plot_menu.AppendSeparator()
[090e07e]617
618                wx_id = wx.NewId()
619                plot_menu.Append(wx_id, "Remove", name)
620                wx.EVT_MENU(self, wx_id, self._onRemove)
[a436b2e]621                if not plot.is_data:
[090e07e]622                    wx_id = wx.NewId()
623                    plot_menu.Append(wx_id, '&Freeze', name)
624                    wx.EVT_MENU(self, wx_id, self.onFreeze)
625                plot_menu.AppendSeparator()
626
[70ec588d]627                if plot.is_data:
[090e07e]628                    wx_id = wx.NewId()
629                    self.hide_menu = plot_menu.Append(wx_id, "Hide Error Bar", name)
630
[70ec588d]631                    if plot.dy is not None and plot.dy != []:
[090e07e]632                        if plot.hide_error:
[70ec588d]633                            self.hide_menu.SetText('Show Error Bar')
634                        else:
635                            self.hide_menu.SetText('Hide Error Bar')
[a436b2e]636                    else:
[70ec588d]637                        self.hide_menu.Enable(False)
[090e07e]638                    wx.EVT_MENU(self, wx_id, self._ontoggle_hide_error)
[f8be87d]639
[090e07e]640                    plot_menu.AppendSeparator()
[f8be87d]641
[090e07e]642                wx_id = wx.NewId()
643                plot_menu.Append(wx_id, '&Modify Plot Property', name)
644                wx.EVT_MENU(self, wx_id, self.createAppDialog)
645            wx_id = wx.NewId()
646            # plot_menu.SetTitle(name)
647            self._slicerpop.AppendMenu(wx_id, '&%s' % name, plot_menu)
[f866fb5]648            # Option to hide
[090e07e]649            # TODO: implement functionality to hide a plottable (legend click)
650        if not self.graph.selected_plottable in self.plots:
[70ec588d]651            self._slicerpop.AppendSeparator()
652            loc_menu = wx.Menu()
653            for label in self._loc_labels:
[090e07e]654                wx_id = wx.NewId()
655                loc_menu.Append(wx_id, str(label), str(label))
656                wx.EVT_MENU(self, wx_id, self.onChangeLegendLoc)
657
658            wx_id = wx.NewId()
659            self._slicerpop.Append(wx_id, '&Modify Graph Appearance',
[f866fb5]660                                   'Modify graph appearance')
[090e07e]661            wx.EVT_MENU(self, wx_id, self.modifyGraphAppearance)
[70ec588d]662            self._slicerpop.AppendSeparator()
[8f59e95]663
[090e07e]664
[70ec588d]665            if self.position != None:
[090e07e]666                wx_id = wx.NewId()
667                self._slicerpop.Append(wx_id, '&Add Text')
668                wx.EVT_MENU(self, wx_id, self._on_addtext)
669                wx_id = wx.NewId()
670                self._slicerpop.Append(wx_id, '&Remove Text')
671                wx.EVT_MENU(self, wx_id, self._on_removetext)
[70ec588d]672                self._slicerpop.AppendSeparator()
[090e07e]673            wx_id = wx.NewId()
674            self._slicerpop.Append(wx_id, '&Change Scale')
675            wx.EVT_MENU(self, wx_id, self._onProperties)
[857d00f]676            self._slicerpop.AppendSeparator()
[090e07e]677            wx_id = wx.NewId()
678            self._slicerpop.Append(wx_id, '&Reset Graph Range')
679            wx.EVT_MENU(self, wx_id, self.onResetGraph)
680
681            if self.parent.ClassName.count('wxDialog') == 0:
[70ec588d]682                self._slicerpop.AppendSeparator()
[090e07e]683                wx_id = wx.NewId()
684                self._slicerpop.Append(wx_id, '&Window Title')
685                wx.EVT_MENU(self, wx_id, self.onChangeCaption)
[dc51a7f]686        try:
687            pos_evt = event.GetPosition()
688            pos = self.ScreenToClient(pos_evt)
689        except:
690            pos_x, pos_y = self.toolbar.GetPositionTuple()
691            pos = (pos_x, pos_y + 5)
[52b8b74]692        self.PopupMenu(self._slicerpop, pos)
[090e07e]693
[e6a93df]694    def onFreeze(self, event):
695        """
[f866fb5]696        on Freeze data
[e6a93df]697        """
[70ec588d]698        menu = event.GetEventObject()
[090e07e]699        wx_id = event.GetId()
700        self.set_selected_from_menu(menu, wx_id)
[e6a93df]701        plot = self.plots[self.graph.selected_plottable]
702        self.parent.onfreeze([plot.id])
[090e07e]703
[1bf33c1]704    def _onSave(self, evt):
705        """
[d955bf19]706        Save a data set to a text file
[090e07e]707
[d955bf19]708        :param evt: Menu event
[090e07e]709
[1bf33c1]710        """
[70ec588d]711        menu = evt.GetEventObject()
[090e07e]712        event_id = evt.GetId()
713        self.set_selected_from_menu(menu, event_id)
[176fbf1]714        data = self.plots[self.graph.selected_plottable]
715        default_name = data.label
[c553b18]716        if default_name.count('.') > 0:
717            default_name = default_name.split('.')[0]
718        default_name += "_out"
719        if self.parent != None:
[176fbf1]720            self.parent.save_data1d(data, default_name)
[c5a769e]721
[0aca693]722    def _onDataShow(self, evt):
723        """
724        Show the data set in text
[090e07e]725
[0aca693]726        :param evt: Menu event
[090e07e]727
[0aca693]728        """
729        menu = evt.GetEventObject()
[090e07e]730        event_id = evt.GetId()
731        self.set_selected_from_menu(menu, event_id)
[0aca693]732        data = self.plots[self.graph.selected_plottable]
733        default_name = data.label
734        if default_name.count('.') > 0:
735            default_name = default_name.split('.')[0]
[090e07e]736        # default_name += "_out"
[0aca693]737        if self.parent != None:
738            self.parent.show_data1d(data, default_name)
[090e07e]739
[6e75ed0]740    def _on_hide(self, event):
741        """
742        Hides the plot when button is pressed
[090e07e]743        """
[c5a769e]744        if self.parent is not None:
[6e75ed0]745            self.parent.hide_panel(self.uid)
[f8be87d]746
[ae84427]747    def on_close(self, event):
748        """
749        On Close Event
750        """
751        ID = self.uid
752        self.parent.delete_panel(ID)
[090e07e]753
[f8be87d]754    def createAppDialog(self, event):
755        """
756        Create the custom dialog for fit appearance modification
757        """
758        menu = event.GetEventObject()
[090e07e]759        event_id = event.GetId()
760        self.set_selected_from_menu(menu, event_id)
[f866fb5]761        self.appearance_selected_plot = \
762                        self.plots[self.graph.selected_plottable]
[f8be87d]763        # find current properties
764        curr_color = self.appearance_selected_plot.custom_color
765        curr_symbol = self.appearance_selected_plot.symbol
766        curr_size = self.appearance_selected_plot.markersize
767        curr_label = self.appearance_selected_plot.label
768
769        if curr_color == None:
770            curr_color = self._color_labels['Blue']
771            curr_symbol = 13
772
[9f51c2c]773        self.appD = appearanceDialog(self, 'Modify Plot Property')
774        icon = self.parent.GetIcon()
775        self.appD.SetIcon(icon)
[090e07e]776        self.appD.set_defaults(float(curr_size), int(curr_color),
777                               str(appearanceDialog.find_key(self.get_symbol_label(),
778                                                             int(curr_symbol))), curr_label)
779        self.appD.Bind(wx.EVT_CLOSE, self.on_AppDialog_close)
[9f51c2c]780
[f866fb5]781    def on_AppDialog_close(self, event):
782        """
783        on_Modify Plot Property_close
784        """
[090e07e]785        if self.appD.okay_clicked == True:
786            info = self.appD.get_current_values()
[f866fb5]787            self.appearance_selected_plot.custom_color = \
788                        self._color_labels[info[1].encode('ascii', 'ignore')]
[9f51c2c]789
790            self.appearance_selected_plot.markersize = float(info[0])
[f866fb5]791            self.appearance_selected_plot.symbol = \
[090e07e]792                        self.get_symbol_label()[info[2]]
[9f51c2c]793            self.appearance_selected_plot.label = str(info[3])
[f8be87d]794        self.appD.Destroy()
795        self._check_zoom_plot()
[8f59e95]796
[f866fb5]797    def modifyGraphAppearance(self, event):
798        """
[090e07e]799        On Modify Graph Appearance
[f866fb5]800        """
801        self.graphApp = graphAppearance(self, 'Modify Graph Appearance')
[9f51c2c]802        icon = self.parent.GetIcon()
803        self.graphApp.SetIcon(icon)
[090e07e]804        self.graphApp.setDefaults(self.grid_on, self.legend_on,
805                                  self.xaxis_label, self.yaxis_label,
806                                  self.xaxis_unit, self.yaxis_unit,
807                                  self.xaxis_font, self.yaxis_font,
808                                  find_key(self.get_loc_label(), self.legendLoc),
809                                  self.xcolor, self.ycolor,
[657e52c]810                                  self.is_xtick, self.is_ytick)
[9f51c2c]811        self.graphApp.Bind(wx.EVT_CLOSE, self.on_graphApp_close)
[8f59e95]812
[9f51c2c]813    def on_graphApp_close(self, event):
[83d9120]814        """
815        Gets values from graph appearance dialog and sends them off
816        to modify the plot
817        """
818        graph_app = self.graphApp
819        toggle_grid = graph_app.get_togglegrid()
820        legend_loc = graph_app.get_legend_loc()
821        toggle_legend = graph_app.get_togglelegend()
[090e07e]822
823        self.onGridOnOff(toggle_grid)
[83d9120]824        self.ChangeLegendLoc(legend_loc)
825        self.onLegend(toggle_legend)
[8a687cfd]826
[83d9120]827        self.xaxis_label = graph_app.get_xlab()
828        self.yaxis_label = graph_app.get_ylab()
829        self.xaxis_unit = graph_app.get_xunit()
830        self.yaxis_unit = graph_app.get_yunit()
[657e52c]831        self.xaxis_font = graph_app.get_xfont()
832        self.yaxis_font = graph_app.get_yfont()
[090e07e]833        self.is_xtick = graph_app.get_xtick_check()
834        self.is_ytick = graph_app.get_ytick_check()
[657e52c]835        if self.is_xtick:
836            self.xaxis_tick = self.xaxis_font
837        if self.is_ytick:
838            self.yaxis_tick = self.yaxis_font
[8a687cfd]839
[090e07e]840        self.xaxis(self.xaxis_label, self.xaxis_unit,
841                   graph_app.get_xfont(), graph_app.get_xcolor(),
[657e52c]842                   self.xaxis_tick)
[090e07e]843        self.yaxis(self.yaxis_label, self.yaxis_unit,
[657e52c]844                   graph_app.get_yfont(), graph_app.get_ycolor(),
845                   self.yaxis_tick)
[8f59e95]846
[83d9120]847        graph_app.Destroy()
Note: See TracBrowser for help on using the repository browser.