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

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 2d88fc4 was 2d88fc4, checked in by Paul Kienzle <pkienzle@…>, 9 years ago

reduce number of NewIds? used for each plot. Refs #448.

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