source: sasview/guiframe/local_perspectives/plotting/masking.py @ 4c01978

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 4c01978 was 55a0dc1, checked in by Gervaise Alina <gervyh@…>, 14 years ago

remove reference to guicomm in guiframe

  • Property mode set to 100644
File size: 21.4 KB
RevLine 
[c5874f2]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#If you use DANSE applications to do scientific research that leads to
8#publication, we ask that you acknowledge the use of the software with the
9#following sentence:
10#
11#"This work benefited from DANSE software developed under NSF award DMR-0520547."
12#
13#copyright 2008, University of Tennessee
14################################################################################
[c5874f2]15
16
[a5ca7ef]17##Todo: cleaning up, improving the maskplotpanel initialization, and testing.
[c5874f2]18import wx
19import sys
[32c0841]20import pylab
21from pylab import gca
22from pylab import gcf
23import math
24import re
25import copy
26import numpy
[c5874f2]27from danse.common.plottools.PlotPanel import PlotPanel
[a5ca7ef]28from danse.common.plottools.plottables import Graph
[c5874f2]29from binder import BindArtist
30from sans.guiframe.dataFitting import Data2D
31from boxMask import BoxMask
32from sectorMask import SectorMask
[55a0dc1]33from sans.guiframe.events import SlicerEvent
34from sans.guiframe.events import StatusEvent
[32c0841]35(InternalEvent, EVT_INTERNAL) = wx.lib.newevent.NewEvent()
[c5874f2]36
[32c0841]37DEFAULT_CMAP = pylab.cm.jet
[c5874f2]38_BOX_WIDTH = 76
39_STATICBOX_WIDTH = 400
40_SCALE = 1e-6
41
42#SLD panel size
[32c0841]43if sys.platform.count("win32") > 0:
[c5874f2]44    _STATICBOX_WIDTH = 380
45    PANEL_SIZE = 420
46    FONT_VARIANT = 0
47else:
48    _STATICBOX_WIDTH = 410
49    PANEL_SIZE = 450
50    FONT_VARIANT = 1
51   
52
53class MaskPanel(wx.Dialog):
54    """
[d955bf19]55    Provides the Mask Editor GUI.
[c5874f2]56    """
57    ## Internal nickname for the window, used by the AUI manager
58    window_name = "Mask Editor"
59    ## Name to appear on the window title bar
60    window_caption = "Mask Editor"
61    ## Flag to tell the AUI manager to put this panel in the center pane
62    CENTER_PANE = True
[32c0841]63    def __init__(self, parent=None, base=None, 
64                 data=None, id=-1, *args, **kwds):
[c5874f2]65        kwds["style"] = wx.DEFAULT_DIALOG_STYLE
[32c0841]66        kwds["size"] = wx.Size(_STATICBOX_WIDTH * 2, PANEL_SIZE) 
67        wx.Dialog.__init__(self, parent, id=id,  *args, **kwds)
68       
[c5874f2]69        if data != None:
70            #Font size
[32c0841]71            kwds = []
[c5874f2]72            self.SetWindowVariant(variant=FONT_VARIANT)
[32c0841]73            self.SetTitle("Mask Editor for " + data.name)
[c5874f2]74            self.parent = base
75            self.data = data
76            self.str = self.data.__str__()
77            ## mask for 2D
78            self.mask = data.mask
79            self.default_mask = copy.deepcopy(data.mask)
80            ## masked data from GUI
81            self.slicer_mask = None
82            self.slicer = None
83            self.slicer_z = 5
84            self.data.interactive = True
85            ## when 2 data have the same id override the 1 st plotted
86            self.name = self.data.name
87            # Panel for 2D plot
[32c0841]88            self.plotpanel = Maskplotpanel(self, -1,
89                                           style=wx.TRANSPARENT_WINDOW)
[c5874f2]90            self.cmap = DEFAULT_CMAP
91            ## Create Artist and bind it
92            self.subplot = self.plotpanel.subplot
93            self.connect = BindArtist(self.subplot.figure)
94            self._setup_layout()
[32c0841]95            self.newplot = Data2D(image=self.data.data)
[c5874f2]96            self.newplot.setValues(self.data)
97            self.plotpanel.add_image(self.newplot) 
98            self._update_mask(self.mask)
99            self.Centre()
100            self.Layout()
101            # bind evt_close to _draw in fitpage
102            self.Bind(wx.EVT_CLOSE, self._draw_model)
103           
104    def ShowMessage(self, msg=''):
105        """
[d955bf19]106        Show error message when mask covers whole data area
[c5874f2]107        """
108        mssg = 'Erase, redraw or clear the mask. \n\r'
109        mssg += 'The data range can not be completely masked... \n\r'
110        mssg += msg
[32c0841]111        wx.MessageBox(mssg, 'Error', wx.OK | wx.ICON_ERROR)
[c5874f2]112   
113    def _setup_layout(self):
114        """
[d955bf19]115        Set up the layout
[c5874f2]116        """
117        shape = "Select a Shape for Masking:"
118        #  panel
[32c0841]119        sizer = wx.GridBagSizer(10, 10)
[c5874f2]120        #---------inputs----------------
121        #inputbox = wx.StaticBox(self, -1, "Draw Mask")
122        shape_txt = wx.StaticText(self, -1, shape) 
[32c0841]123        sizer.Add(shape_txt, (1, 1), flag=wx.TOP|wx.LEFT|wx.BOTTOM, border=5)
[c5874f2]124        #innersector_x_txt = wx.StaticText(self, -1, 'Inner Sector')
[32c0841]125        self.innersector_rb = wx.RadioButton(self, -1, "Double Wings")
126        self.Bind(wx.EVT_RADIOBUTTON, self.onInnerSectorMask,
127                  id=self.innersector_rb.GetId())
128        sizer.Add(self.innersector_rb, (2, 1), 
129                  flag=wx.RIGHT|wx.BOTTOM, border=5)
[c5874f2]130        #innersector_x_txt = wx.StaticText(self, -1, 'Inner Sector')
[32c0841]131        self.innercircle_rb = wx.RadioButton(self, -1, "Circular Disk")
132        self.Bind(wx.EVT_RADIOBUTTON, self.onInnerRingMask,
133                  id=self.innercircle_rb.GetId())
134        sizer.Add(self.innercircle_rb, (3, 1),
135                   flag=wx.RIGHT|wx.BOTTOM, border=5)
136       
137        self.innerbox_rb = wx.RadioButton(self, -1, "Rectangular Disk")
138        self.Bind(wx.EVT_RADIOBUTTON, self.onInnerBoxMask,
139                  id=self.innerbox_rb.GetId())
140        sizer.Add(self.innerbox_rb, (4, 1), flag=wx.RIGHT|wx.BOTTOM, border=5)
[c5874f2]141        #outersector_y_txt = wx.StaticText(self, -1, 'Outer Sector')
[32c0841]142        self.outersector_rb = wx.RadioButton(self, -1, "Double Wing Window")
143        self.Bind(wx.EVT_RADIOBUTTON, self.onOuterSectorMask, 
144                  id=self.outersector_rb.GetId())
145        sizer.Add(self.outersector_rb, (5, 1),
146                  flag=wx.RIGHT|wx.BOTTOM, border=5)
[c5874f2]147       
148        #outersector_y_txt = wx.StaticText(self, -1, 'Outer Sector')
[32c0841]149        self.outercircle_rb = wx.RadioButton(self, -1, "Circular Window")
150        self.Bind(wx.EVT_RADIOBUTTON, self.onOuterRingMask,
151                  id=self.outercircle_rb.GetId())
152        sizer.Add(self.outercircle_rb, (6, 1), 
153                  flag=wx.RIGHT|wx.BOTTOM, border=5)
[c5874f2]154        #outerbox_txt = wx.StaticText(self, -1, 'Outer Box')
[32c0841]155        self.outerbox_rb = wx.RadioButton(self, -1, "Rectangular Window")
156        self.Bind(wx.EVT_RADIOBUTTON, self.onOuterBoxMask, 
157                  id=self.outerbox_rb.GetId())
158        sizer.Add(self.outerbox_rb, (7, 1), flag=wx.RIGHT|wx.BOTTOM, border=5)
[c5874f2]159        self.innercircle_rb.SetValue(False)
160        self.outercircle_rb.SetValue(False)       
161        self.innerbox_rb.SetValue(False)
162        self.outerbox_rb.SetValue(False)
163        self.innersector_rb.SetValue(False)
164        self.outersector_rb.SetValue(False)
[32c0841]165        sizer.Add(self.plotpanel, (0, 2), (13, 13), 
166                  wx.EXPAND|wx.LEFT|wx.RIGHT, 15)
[c5874f2]167
168        #-----Buttons------------1
169        id = wx.NewId()
170        button_add = wx.Button(self, id, "Add")
171        button_add.SetToolTipString("Add the mask drawn.")
[32c0841]172        button_add.Bind(wx.EVT_BUTTON, self.onAddMask, id=button_add.GetId()) 
[c5874f2]173        sizer.Add(button_add, (13, 7))
174        id = wx.NewId()
175        button_erase = wx.Button(self, id, "Erase")
176        button_erase.SetToolTipString("Erase the mask drawn.")
[32c0841]177        button_erase.Bind(wx.EVT_BUTTON, self.onEraseMask,
178                          id=button_erase.GetId()) 
[c5874f2]179        sizer.Add(button_erase, (13, 8))
180        id = wx.NewId()
181        button_reset = wx.Button(self, id, "Reset")
182        button_reset.SetToolTipString("Reset the mask.")
[32c0841]183        button_reset.Bind(wx.EVT_BUTTON, self.onResetMask,
184                          id=button_reset.GetId()) 
185        sizer.Add(button_reset, (13, 9), flag=wx.RIGHT|wx.BOTTOM, border=15)
[c5874f2]186        id = wx.NewId()
187        button_reset = wx.Button(self, id, "Clear")
188        button_reset.SetToolTipString("Clear all mask.")
[32c0841]189        button_reset.Bind(wx.EVT_BUTTON, self.onClearMask,
190                          id=button_reset.GetId()) 
191        sizer.Add(button_reset, (13, 10), flag=wx.RIGHT|wx.BOTTOM, border=15)
[c5874f2]192        sizer.AddGrowableCol(3)
193        sizer.AddGrowableRow(2)
194        self.SetSizerAndFit(sizer)
195        self.Centre()
196        self.Show(True)
197
[32c0841]198    def onInnerBoxMask(self, event=None):
[c5874f2]199        """
[d955bf19]200        Call Draw Box Slicer and get mask inside of the box
[c5874f2]201        """
202        #get ready for next evt
203        event.Skip()       
[32c0841]204        #from boxMask import BoxMask
205        if event != None:
206            self.onClearSlicer(event)         
[c5874f2]207        self.slicer_z += 1
[32c0841]208        self.slicer =  BoxMask(self, self.subplot,
209                               zorder=self.slicer_z, side=True)
[c5874f2]210        self.subplot.set_ylim(self.data.ymin, self.data.ymax)
211        self.subplot.set_xlim(self.data.xmin, self.data.xmax)
212        self.update()
213        self.slicer_mask = self.slicer.update()
214       
[32c0841]215    def onOuterBoxMask(self, event=None):
[c5874f2]216        """
[d955bf19]217        Call Draw Box Slicer and get mask outside of the box
[c5874f2]218        """
219        event.Skip()       
[32c0841]220        #from boxMask import BoxMask
221        if event != None:
222            self.onClearSlicer(event)     
[c5874f2]223        self.slicer_z += 1
[32c0841]224        self.slicer =  BoxMask(self, self.subplot,
225                               zorder=self.slicer_z, side=False)
[c5874f2]226        self.subplot.set_ylim(self.data.ymin, self.data.ymax)
227        self.subplot.set_xlim(self.data.xmin, self.data.xmax)
228        self.update()
229        self.slicer_mask = self.slicer.update()
230
[32c0841]231    def onInnerSectorMask(self, event=None):
[c5874f2]232        """
[d955bf19]233        Call Draw Sector Slicer and get mask inside of the sector
[c5874f2]234        """
235        event.Skip()
236        from sectorMask import SectorMask
[32c0841]237        if event != None:
[c5874f2]238            self.onClearSlicer(event)
239        self.slicer_z += 1
[32c0841]240        self.slicer =  SectorMask(self, self.subplot,
241                                  zorder=self.slicer_z, side=True)
[c5874f2]242        self.subplot.set_ylim(self.data.ymin, self.data.ymax)
243        self.subplot.set_xlim(self.data.xmin, self.data.xmax)   
244        self.update()
245        self.slicer_mask = self.slicer.update() 
[a5ca7ef]246
[c5874f2]247    def onOuterSectorMask(self,event=None):
248        """
[d955bf19]249        Call Draw Sector Slicer and get mask outside of the sector
[c5874f2]250        """
251        event.Skip()
252        from sectorMask import SectorMask
[32c0841]253        if event != None:
[c5874f2]254            self.onClearSlicer(event)
255        self.slicer_z += 1
[32c0841]256        self.slicer =  SectorMask(self, self.subplot,
257                                  zorder=self.slicer_z, side=False)
[c5874f2]258        self.subplot.set_ylim(self.data.ymin, self.data.ymax)
259        self.subplot.set_xlim(self.data.xmin, self.data.xmax)   
260        self.update()     
261        self.slicer_mask = self.slicer.update()   
[a5ca7ef]262
[c5874f2]263    def onInnerRingMask(self, event=None):
264        """
[d955bf19]265        Perform inner circular cut on Phi and draw circular slicer
[c5874f2]266        """
267        event.Skip()
268        from AnnulusSlicer import CircularMask
[32c0841]269        if event != None:
[c5874f2]270            self.onClearSlicer(event)
271        self.slicer_z += 1
[32c0841]272        self.slicer = CircularMask(self,self.subplot,
273                                   zorder=self.slicer_z, side=True)
[c5874f2]274        self.subplot.set_ylim(self.data.ymin, self.data.ymax)
275        self.subplot.set_xlim(self.data.xmin, self.data.xmax)   
276        self.update()
277        self.slicer_mask = self.slicer.update() 
[a5ca7ef]278
[c5874f2]279    def onOuterRingMask(self, event=None):
280        """
[d955bf19]281        Perform outer circular cut on Phi and draw circular slicer
[c5874f2]282        """
283        event.Skip()
284        from AnnulusSlicer import CircularMask
[32c0841]285        if event != None:
[c5874f2]286            self.onClearSlicer(event)
287        self.slicer_z += 1
[32c0841]288        self.slicer = CircularMask(self,self.subplot,
289                                   zorder=self.slicer_z, side=False)   
[c5874f2]290        self.subplot.set_ylim(self.data.ymin, self.data.ymax)
291        self.subplot.set_xlim(self.data.xmin, self.data.xmax)
292        self.update()
293        self.slicer_mask = self.slicer.update()     
294       
295    def onAddMask(self, event):
296        """
[d955bf19]297        Add new mask to old mask
[c5874f2]298        """
[32c0841]299        if not self.slicer == None:
[c5874f2]300            data = Data2D()
301            data = self.data
302            self.slicer_mask = self.slicer.update()
303            data.mask = self.data.mask & self.slicer_mask
304            self._check_display_mask(data.mask, event)
305           
306    def _check_display_mask(self, mask, event):
307        """
[d955bf19]308        check if the mask valid and update the plot
309       
310        :param mask: mask data
311       
[c5874f2]312        """
313        ## Redraw the current image
314        self._update_mask(mask)
315
316    def onEraseMask(self, event):
317        """
[d955bf19]318        Erase new mask from old mask
[c5874f2]319        """
320        if not self.slicer==None:
321            self.slicer_mask = self.slicer.update()
322            mask = self.data.mask
323            mask[self.slicer_mask==False] = True
324            self._check_display_mask(mask, event)
325           
326    def onResetMask(self, event):
327        """
[d955bf19]328        Reset mask to the original mask
329        """       
[c5874f2]330        self.slicer_z += 1
[32c0841]331        self.slicer =  BoxMask(self, self.subplot, 
332                               zorder=self.slicer_z, side=True)
[c5874f2]333        self.subplot.set_ylim(self.data.ymin, self.data.ymax)
334        self.subplot.set_xlim(self.data.xmin, self.data.xmax)   
335        mask = copy.deepcopy(self.default_mask)
336        self.data.mask = mask
337        # update mask plot
338        self._check_display_mask(mask, event)
339       
340    def onClearMask(self, event):
341        """
[d955bf19]342        Clear mask
[c5874f2]343        """           
344        self.slicer_z += 1
[32c0841]345        self.slicer =  BoxMask(self, self.subplot,
346                               zorder=self.slicer_z, side=True)
[c5874f2]347        self.subplot.set_ylim(self.data.ymin, self.data.ymax)
348        self.subplot.set_xlim(self.data.xmin, self.data.xmax)   
349        #mask = copy.deepcopy(self.default_mask)
350        mask = numpy.ones(len(self.data.mask), dtype=bool)
351        self.data.mask = mask
352        # update mask plot
353        self._check_display_mask(mask, event)
354       
355    def onClearSlicer(self, event):
356        """
[d955bf19]357        Clear the slicer on the plot
[c5874f2]358        """
[32c0841]359        if not self.slicer == None:
[c5874f2]360            self.slicer.clear()
361            self.subplot.figure.canvas.draw()
362            self.slicer = None
363
364    def _setSlicer(self):
365        """
[d955bf19]366        Clear the previous slicer and create a new one.Post an internal
367        event.
368       
369        :param slicer: slicer class to create
[c5874f2]370       
[d955bf19]371        """
[c5874f2]372        ## Clear current slicer
373        if not self.slicer == None: 
374            self.slicer.clear()           
375        ## Create a new slicer   
376        self.slicer_z += 1
377        self.slicer = slicer(self, self.subplot, zorder=self.slicer_z)
378        self.subplot.set_ylim(self.data2D.ymin, self.data2D.ymax)
379        self.subplot.set_xlim(self.data2D.xmin, self.data2D.xmax)
380        ## Draw slicer
381        self.update()
382        self.slicer.update()
[32c0841]383        msg = "Plotter2D._setSlicer  %s"%self.slicer.__class__.__name__
384        wx.PostEvent(self.parent, StatusEvent(status=msg))
[c5874f2]385        # Post slicer event
386        event = self._getEmptySlicerEvent()
387        event.type = self.slicer.__class__.__name__
388        event.obj_class = self.slicer.__class__
389        event.params = self.slicer.get_params()
390        wx.PostEvent(self, event)
391   
392    def update(self, draw=True):
393        """
[d955bf19]394        Respond to changes in the model by recalculating the
395        profiles and resetting the widgets.
[c5874f2]396        """
397        self.plotpanel.draw()
398       
399    def _set_mask(self, mask):
400        """
[d955bf19]401        Set mask
[c5874f2]402        """
403        self.data.mask = mask
404       
405    def _update_mask(self,mask):
406        """
[d955bf19]407        Respond to changes in masking
[c5874f2]408        """ 
409        # the case of liitle numbers of True points
[32c0841]410        if (len(mask[mask]) < 10 and self.data != None):
[c5874f2]411            self.ShowMessage()
412            mask = copy.deepcopy(self.mask)
413            self.data.mask = mask
414        else:
415            self.mask = mask
416        # make temperary data to plot
417        temp_mask = numpy.zeros(len(mask))
418        temp_data = copy.deepcopy(self.data)
419        # temp_data default is None
420        # This method is to distinguish between masked point and data point = 0.
421        temp_mask = temp_mask/temp_mask
422        temp_mask[mask] = temp_data.data[mask]
423        # set temp_data value for self.mask==True, else still None
424        #temp_mask[mask] = temp_data[mask]
425        temp_data.data[mask==False] = temp_mask[mask==False]
426        self.plotpanel.clear()
427        if self.slicer != None:
428            self.slicer.clear()
429            self.slicer = None
430        # Post slicer None event
431        event = self._getEmptySlicerEvent()
432        wx.PostEvent(self, event)
[9266c66]433       
[ca6c17e8]434        ##use this method
[e306b96e]435        #set zmax and zmin to plot: Fix it w/ data.
436        if self.plotpanel.scale == 'log':
437            zmax = math.log(max(self.data.data[self.data.data>0]))
[c1d2af4]438            zmin = math.log(min(self.data.data[self.data.data>0]))
[e306b96e]439        else:
440            zmax = max(self.data.data[self.data.data>0])
441            zmin = min(self.data.data[self.data.data>0])
[ca6c17e8]442        #plot   
[32c0841]443        plot = self.plotpanel.image(data=temp_mask,
[c5874f2]444                       qx_data=self.data.qx_data,
445                       qy_data=self.data.qy_data,
[32c0841]446                       xmin=self.data.xmin,
447                       xmax=self.data.xmax,
448                       ymin=self.data.ymin,
449                       ymax=self.data.ymax,
450                       zmin=zmin,
451                       zmax=zmax,
452                       cmap=self.cmap,
453                       color=0, symbol=0, label=self.data.name)
[54180f9]454        # axis labels
[0aee80d]455        self.plotpanel.axes[0].set_xlabel('$\\rm{Q}_{x}(A^{-1})$')
456        self.plotpanel.axes[0].set_ylabel('$\\rm{Q}_{y}(A^{-1})$')
[c5874f2]457        self.plotpanel.render()
458        self.plotpanel.subplot.figure.canvas.draw_idle()
459       
460    def _getEmptySlicerEvent(self):
461        """
[d955bf19]462        create an empty slicervent
[c5874f2]463        """
464        self.innerbox_rb.SetValue(False)
465        self.outerbox_rb.SetValue(False)
466        self.innersector_rb.SetValue(False)
467        self.outersector_rb.SetValue(False)
468        self.innercircle_rb.SetValue(False)
469        self.outercircle_rb.SetValue(False)
470        return SlicerEvent(type=None,
471                           params=None,
472                           obj_class=None) 
473             
[32c0841]474    def _draw_model(self, event):
[c5874f2]475        """
[d955bf19]476         on_close, update the model2d plot
[c5874f2]477        """
478        pass
479       
480    def freeze_axes(self):
[d955bf19]481        """
482        """
[c5874f2]483        self.plotpanel.axes_frozen = True
[d955bf19]484       
[c5874f2]485    def thaw_axes(self):
[d955bf19]486        """
487        """
488        self.plotpanel.axes_frozen = False       
489         
[32c0841]490    def onMouseMotion(self, event):
[d955bf19]491        """
492        """
[c5874f2]493        pass
[d955bf19]494   
[c5874f2]495    def onWheel(self, event):
[d955bf19]496        """
497        """
[c5874f2]498        pass 
499           
[a5ca7ef]500class Maskplotpanel(PlotPanel):
[d955bf19]501    """
502    """
[32c0841]503    def __init__(self, parent, id=-1, color=None, dpi=None, **kwargs):
[d955bf19]504        """
505        """
[c5874f2]506        PlotPanel.__init__(self, parent, id=id, color=color, dpi=dpi, **kwargs)
507       
508        # Keep track of the parent Frame
509        self.parent = parent
510        # Internal list of plottable names (because graph
511        # doesn't have a dictionary of handles for the plottables)
512        self.plots = {}
[a5ca7ef]513        self.graph = Graph()
[c5874f2]514       
515    def add_toolbar(self):
516        """
[d955bf19]517        Add toolbar
[c5874f2]518        """
519        # Not implemented
520        pass
521    def on_set_focus(self, event):
522        """
[d955bf19]523        send to the parenet the current panel on focus
[c5874f2]524        """
525        #change the panel background
526        #self.SetColor((170, 202, 255))
527        self.draw()   
528         
529    def add_image(self, plot):
[d955bf19]530        """
531        """
[c5874f2]532        self.plots[plot.name] = plot
[a5ca7ef]533        #init graph
534        self.gaph = Graph()
535        #add plot
[c5874f2]536        self.graph.add(plot)
[a5ca7ef]537        #add axes
[c5874f2]538        self.graph.xaxis('\\rm{Q}_{x} ', 'A^{-1}')
539        self.graph.yaxis('\\rm{Q}_{y} ', 'A^{-1}')
[a5ca7ef]540        #draw
[c5874f2]541        self.graph.render(self)
542        self.subplot.figure.canvas.draw_idle()
[a5ca7ef]543       
[c5874f2]544    def onMouseMotion(self, event):
545        """
[d955bf19]546        Disable dragging 2D image
[c5874f2]547        """
548        pass
549   
550    def onContextMenu(self, event):
551        """
[d955bf19]552        Default context menu for a plot panel
[c5874f2]553        """
554        # Slicer plot popup menu
[b40439d9]555        slicerpop = wx.Menu()
[c5874f2]556        #id = wx.NewId()
557        #slicerpop.Append(id,'&Save image', 'Save image as PNG')
558        #wx.EVT_MENU(self, id, self.onSaveImage)
559       
560        id = wx.NewId()
561        slicerpop.Append(id, '&Toggle Linear/Log scale')
562        wx.EVT_MENU(self, id, self._onToggleScale)
563               
564        pos = event.GetPosition()
565        pos = self.ScreenToClient(pos)
566        self.PopupMenu(slicerpop, pos)
567
[e306b96e]568class ViewerFrame(wx.Frame):
569    """
[d955bf19]570    Add comment
[e306b96e]571    """
572    def __init__(self, parent, id, title):
573        """
[d955bf19]574        comment
575        :param parent: parent panel/container
[e306b96e]576        """
577        # Initialize the Frame object
[32c0841]578        wx.Frame.__init__(self, parent, id, title,
579                          wx.DefaultPosition, wx.Size(950, 850))
[e306b96e]580        # Panel for 1D plot
[32c0841]581        self.plotpanel = Maskplotpanel(self, -1, style=wx.RAISED_BORDER)
[c5874f2]582
[e306b96e]583class ViewApp(wx.App):
584    def OnInit(self):
585        frame = ViewerFrame(None, -1, 'testView')   
586        frame.Show(True)
587        self.SetTopWindow(frame)
588       
589        return True
590               
[c5874f2]591if __name__ == "__main__": 
592    app = ViewApp(0)
593    app.MainLoop()     
Note: See TracBrowser for help on using the repository browser.