source: sasview/guiframe/local_perspectives/plotting/masking.py @ b92cbf61

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 b92cbf61 was 21969a4a, checked in by Jae Cho <jhjcho@…>, 13 years ago

moving fixes from branch

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