source: sasview/sansguiframe/src/sans/guiframe/local_perspectives/plotting/Plotter1D.py @ 79b550a

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 79b550a was b07ffca, checked in by Jae Cho <jhjcho@…>, 12 years ago

minor fixes in focusing graph name in combobox:Data Panel

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