source: sasview/sansguiframe/src/sans/guiframe/local_perspectives/plotting/masking.py @ 223a154

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 223a154 was 52e0f2d, checked in by Jae Cho <jhjcho@…>, 13 years ago

trying to fix the problem in plots on MAC

  • Property mode set to 100644
File size: 29.2 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#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################################################################################
15
16
17##Todo: cleaning up, improving the maskplotpanel initialization, and testing.
18import wx
19import sys
20import time
21import pylab
22import math
23import copy
24import numpy
25from danse.common.plottools.PlotPanel import PlotPanel
26from danse.common.plottools.plottables import Graph
27from binder import BindArtist
28from sans.guiframe.dataFitting import Data1D, Data2D
29from boxMask import BoxMask
30from sectorMask import SectorMask
31from sans.guiframe.events import SlicerEvent
32from sans.guiframe.events import StatusEvent
33(InternalEvent, EVT_INTERNAL) = wx.lib.newevent.NewEvent()
34
35DEFAULT_CMAP = pylab.cm.jet
36_BOX_WIDTH = 76
37_SCALE = 1e-6
38_STATICBOX_WIDTH = 380
39
40#SLD panel size
41if sys.platform.count("win32") > 0:
42    PANEL_SIZE = 350
43    FONT_VARIANT = 0
44else:
45    PANEL_SIZE = 300
46    FONT_VARIANT = 1
47   
48from data_util.calcthread import CalcThread
49
50class CalcPlot(CalcThread):
51    """
52    Compute Resolution
53    """
54    def __init__(self,
55                 id = -1,
56                 panel = None,
57                 image = None,
58                 completefn = None,
59                 updatefn   = None,
60                 elapsed = 0,
61                 yieldtime  = 0.01,
62                 worktime   = 0.01
63                 ):
64        """
65        """
66        CalcThread.__init__(self,completefn,
67                 updatefn,
68                 yieldtime,
69                 worktime)
70        self.starttime = 0
71        self.id = id 
72        self.panel = panel
73        self.image = image
74       
75       
76    def compute(self):
77        """
78        excuting computation
79        """
80        elapsed = time.time() - self.starttime
81       
82        self.complete(panel=self.panel, image=self.image, elapsed=elapsed)
83       
84       
85class MaskPanel(wx.Dialog):
86    """
87    Provides the Mask Editor GUI.
88    """
89    ## Internal nickname for the window, used by the AUI manager
90    window_name = "Mask Editor"
91    ## Name to appear on the window title bar
92    window_caption = "Mask Editor"
93    ## Flag to tell the AUI manager to put this panel in the center pane
94    CENTER_PANE = True
95    def __init__(self, parent=None, base=None, 
96                 data=None, id=-1, *args, **kwds):
97        kwds["style"] = wx.DEFAULT_DIALOG_STYLE
98        kwds["size"] = wx.Size(_STATICBOX_WIDTH*0.8, PANEL_SIZE) 
99        wx.Dialog.__init__(self, parent, id=id,  *args, **kwds)
100       
101        if data != None:
102            #Font size
103            kwds = []
104            self.SetWindowVariant(variant=FONT_VARIANT)
105            self.SetTitle("Mask Editor for " + data.name)
106            self.parent = base
107            self.data = data
108            self.str = self.data.__str__()
109            ## mask for 2D
110            self.mask = data.mask
111            self.default_mask = copy.deepcopy(data.mask)
112            ## masked data from GUI
113            self.slicer_mask = None
114            self.slicer = None
115            self.slicer_z = 5
116            self.data.interactive = True
117            ## when 2 data have the same id override the 1 st plotted
118            self.name = self.data.name
119            # Panel for 2D plot
120            self.plotpanel = Maskplotpanel(self, -1,
121                                           style=wx.TRANSPARENT_WINDOW)
122            self.cmap = DEFAULT_CMAP
123            ## Create Artist and bind it
124            self.subplot = self.plotpanel.subplot
125            self.connect = BindArtist(self.subplot.figure)
126            self._setup_layout()
127            self.newplot = Data2D(image=self.data.data)
128            self.newplot.setValues(self.data)
129            self.plotpanel.add_image(self.newplot) 
130            self._update_mask(self.mask)
131            self.Centre()
132            self.Layout()
133            # bind evt_close to _draw in fitpage
134            self.Bind(wx.EVT_CLOSE, self.OnClose)
135           
136    def ShowMessage(self, msg=''):
137        """
138        Show error message when mask covers whole data area
139        """
140        mssg = 'Erase, redraw or clear the mask. \n\r'
141        mssg += 'The data range can not be completely masked... \n\r'
142        mssg += msg
143        wx.MessageBox(mssg, 'Error', wx.OK | wx.ICON_ERROR)
144   
145    def _setup_layout(self):
146        """
147        Set up the layout
148        """
149        note = "Note: This masking applies\n     only to %s." % self.data.name
150        note_txt = wx.StaticText(self, -1, note) 
151        note_txt.SetForegroundColour(wx.RED)
152        shape = "Select a Shape for Masking:"
153        #  panel
154        sizer = wx.GridBagSizer(10, 10)
155        #---------inputs----------------
156        shape_txt = wx.StaticText(self, -1, shape) 
157        sizer.Add(shape_txt, (1, 1), flag=wx.TOP|wx.LEFT|wx.BOTTOM, border=5)
158        self.innersector_rb = wx.RadioButton(self, -1, "Double Wings")
159        self.Bind(wx.EVT_RADIOBUTTON, self.onInnerSectorMask,
160                  id=self.innersector_rb.GetId())
161        sizer.Add(self.innersector_rb, (2, 1), 
162                  flag=wx.RIGHT|wx.BOTTOM, border=5)
163        self.innercircle_rb = wx.RadioButton(self, -1, "Circular Disk")
164        self.Bind(wx.EVT_RADIOBUTTON, self.onInnerRingMask,
165                  id=self.innercircle_rb.GetId())
166        sizer.Add(self.innercircle_rb, (3, 1),
167                   flag=wx.RIGHT|wx.BOTTOM, border=5)
168       
169        self.innerbox_rb = wx.RadioButton(self, -1, "Rectangular Disk")
170        self.Bind(wx.EVT_RADIOBUTTON, self.onInnerBoxMask,
171                  id=self.innerbox_rb.GetId())
172        sizer.Add(self.innerbox_rb, (4, 1), flag=wx.RIGHT|wx.BOTTOM, border=5)
173
174        self.outersector_rb = wx.RadioButton(self, -1, "Double Wing Window")
175        self.Bind(wx.EVT_RADIOBUTTON, self.onOuterSectorMask, 
176                  id=self.outersector_rb.GetId())
177        sizer.Add(self.outersector_rb, (5, 1),
178                  flag=wx.RIGHT|wx.BOTTOM, border=5)
179       
180        #outersector_y_txt = wx.StaticText(self, -1, 'Outer Sector')
181        self.outercircle_rb = wx.RadioButton(self, -1, "Circular Window")
182        self.Bind(wx.EVT_RADIOBUTTON, self.onOuterRingMask,
183                  id=self.outercircle_rb.GetId())
184        sizer.Add(self.outercircle_rb, (6, 1), 
185                  flag=wx.RIGHT|wx.BOTTOM, border=5)
186        #outerbox_txt = wx.StaticText(self, -1, 'Outer Box')
187        self.outerbox_rb = wx.RadioButton(self, -1, "Rectangular Window")
188        self.Bind(wx.EVT_RADIOBUTTON, self.onOuterBoxMask, 
189                  id=self.outerbox_rb.GetId())
190        sizer.Add(self.outerbox_rb, (7, 1), flag=wx.RIGHT|wx.BOTTOM, border=5)
191        sizer.Add(note_txt, (8, 1), flag=wx.RIGHT|wx.BOTTOM, border=5)
192        self.innercircle_rb.SetValue(False)
193        self.outercircle_rb.SetValue(False)       
194        self.innerbox_rb.SetValue(False)
195        self.outerbox_rb.SetValue(False)
196        self.innersector_rb.SetValue(False)
197        self.outersector_rb.SetValue(False)
198        sizer.Add(self.plotpanel, (0, 2), (13, 13), 
199                  wx.EXPAND|wx.LEFT|wx.RIGHT, 15)
200
201        #-----Buttons------------1
202        id_button = wx.NewId()
203        button_add = wx.Button(self, id_button, "Add")
204        button_add.SetToolTipString("Add the mask drawn.")
205        button_add.Bind(wx.EVT_BUTTON, self.onAddMask, id=button_add.GetId()) 
206        sizer.Add(button_add, (13, 7))
207        id_button = wx.NewId()
208        button_erase = wx.Button(self, id_button, "Erase")
209        button_erase.SetToolTipString("Erase the mask drawn.")
210        button_erase.Bind(wx.EVT_BUTTON, self.onEraseMask,
211                          id=button_erase.GetId()) 
212        sizer.Add(button_erase, (13, 8))
213        id_button = wx.NewId()
214        button_reset = wx.Button(self, id_button, "Reset")
215        button_reset.SetToolTipString("Reset the mask.")
216        button_reset.Bind(wx.EVT_BUTTON, self.onResetMask,
217                          id=button_reset.GetId()) 
218        sizer.Add(button_reset, (13, 9), flag=wx.RIGHT|wx.BOTTOM, border=15)
219        id_button = wx.NewId()
220        button_reset = wx.Button(self, id_button, "Clear")
221        button_reset.SetToolTipString("Clear all mask.")
222        button_reset.Bind(wx.EVT_BUTTON, self.onClearMask,
223                          id=button_reset.GetId()) 
224        sizer.Add(button_reset, (13, 10), flag=wx.RIGHT|wx.BOTTOM, border=15)
225        sizer.AddGrowableCol(3)
226        sizer.AddGrowableRow(2)
227        self.SetSizerAndFit(sizer)
228        self.Centre()
229        self.Show(True)
230
231    def onInnerBoxMask(self, event=None):
232        """
233        Call Draw Box Slicer and get mask inside of the box
234        """
235        #get ready for next evt
236        event.Skip()       
237        #from boxMask import BoxMask
238        if event != None:
239            self.onClearSlicer(event)         
240        self.slicer_z += 1
241        self.slicer =  BoxMask(self, self.subplot,
242                               zorder=self.slicer_z, side=True)
243        self.subplot.set_ylim(self.data.ymin, self.data.ymax)
244        self.subplot.set_xlim(self.data.xmin, self.data.xmax)
245        self.update()
246        self.slicer_mask = self.slicer.update()
247       
248    def onOuterBoxMask(self, event=None):
249        """
250        Call Draw Box Slicer and get mask outside of the box
251        """
252        event.Skip()       
253        #from boxMask import BoxMask
254        if event != None:
255            self.onClearSlicer(event)     
256        self.slicer_z += 1
257        self.slicer =  BoxMask(self, self.subplot,
258                               zorder=self.slicer_z, side=False)
259        self.subplot.set_ylim(self.data.ymin, self.data.ymax)
260        self.subplot.set_xlim(self.data.xmin, self.data.xmax)
261        self.update()
262        self.slicer_mask = self.slicer.update()
263
264    def onInnerSectorMask(self, event=None):
265        """
266        Call Draw Sector Slicer and get mask inside of the sector
267        """
268        event.Skip()
269        from sectorMask import SectorMask
270        if event != None:
271            self.onClearSlicer(event)
272        self.slicer_z += 1
273        self.slicer =  SectorMask(self, self.subplot,
274                                  zorder=self.slicer_z, side=True)
275        self.subplot.set_ylim(self.data.ymin, self.data.ymax)
276        self.subplot.set_xlim(self.data.xmin, self.data.xmax)   
277        self.update()
278        self.slicer_mask = self.slicer.update() 
279
280    def onOuterSectorMask(self,event=None):
281        """
282        Call Draw Sector Slicer and get mask outside of the sector
283        """
284        event.Skip()
285        from sectorMask import SectorMask
286        if event != None:
287            self.onClearSlicer(event)
288        self.slicer_z += 1
289        self.slicer =  SectorMask(self, self.subplot,
290                                  zorder=self.slicer_z, side=False)
291        self.subplot.set_ylim(self.data.ymin, self.data.ymax)
292        self.subplot.set_xlim(self.data.xmin, self.data.xmax)   
293        self.update()     
294        self.slicer_mask = self.slicer.update()   
295
296    def onInnerRingMask(self, event=None):
297        """
298        Perform inner circular cut on Phi and draw circular slicer
299        """
300        event.Skip()
301        from AnnulusSlicer import CircularMask
302        if event != None:
303            self.onClearSlicer(event)
304        self.slicer_z += 1
305        self.slicer = CircularMask(self, self.subplot,
306                                   zorder=self.slicer_z, side=True)
307        self.subplot.set_ylim(self.data.ymin, self.data.ymax)
308        self.subplot.set_xlim(self.data.xmin, self.data.xmax)   
309        self.update()
310        self.slicer_mask = self.slicer.update() 
311
312    def onOuterRingMask(self, event=None):
313        """
314        Perform outer circular cut on Phi and draw circular slicer
315        """
316        event.Skip()
317        from AnnulusSlicer import CircularMask
318        if event != None:
319            self.onClearSlicer(event)
320        self.slicer_z += 1
321        self.slicer = CircularMask(self,self.subplot,
322                                   zorder=self.slicer_z, side=False)   
323        self.subplot.set_ylim(self.data.ymin, self.data.ymax)
324        self.subplot.set_xlim(self.data.xmin, self.data.xmax)
325        self.update()
326        self.slicer_mask = self.slicer.update()     
327       
328    def onAddMask(self, event):
329        """
330        Add new mask to old mask
331        """
332        if not self.slicer == None:
333            data = Data2D()
334            data = self.data
335            self.slicer_mask = self.slicer.update()
336            data.mask = self.data.mask & self.slicer_mask
337            self._check_display_mask(data.mask, event)
338           
339    def _check_display_mask(self, mask, event):
340        """
341        check if the mask valid and update the plot
342       
343        :param mask: mask data
344        """
345        ## Redraw the current image
346        self._update_mask(mask)
347
348    def onEraseMask(self, event):
349        """
350        Erase new mask from old mask
351        """
352        if not self.slicer==None:
353            self.slicer_mask = self.slicer.update()
354            mask = self.data.mask
355            mask[self.slicer_mask==False] = True
356            self._check_display_mask(mask, event)
357           
358    def onResetMask(self, event):
359        """
360        Reset mask to the original mask
361        """       
362        self.slicer_z += 1
363        self.slicer =  BoxMask(self, self.subplot, 
364                               zorder=self.slicer_z, side=True)
365        self.subplot.set_ylim(self.data.ymin, self.data.ymax)
366        self.subplot.set_xlim(self.data.xmin, self.data.xmax)   
367        mask = copy.deepcopy(self.default_mask)
368        self.data.mask = mask
369        # update mask plot
370        self._check_display_mask(mask, event)
371       
372    def onClearMask(self, event):
373        """
374        Clear mask
375        """           
376        self.slicer_z += 1
377        self.slicer =  BoxMask(self, self.subplot,
378                               zorder=self.slicer_z, side=True)
379        self.subplot.set_ylim(self.data.ymin, self.data.ymax)
380        self.subplot.set_xlim(self.data.xmin, self.data.xmax)   
381        #mask = copy.deepcopy(self.default_mask)
382        mask = numpy.ones(len(self.data.mask), dtype=bool)
383        self.data.mask = mask
384        # update mask plot
385        self._check_display_mask(mask, event)
386       
387    def onClearSlicer(self, event):
388        """
389        Clear the slicer on the plot
390        """
391        if not self.slicer == None:
392            self.slicer.clear()
393            self.subplot.figure.canvas.draw()
394            self.slicer = None
395
396    def _setSlicer(self):
397        """
398        Clear the previous slicer and create a new one.Post an internal
399        event.
400       
401        :param slicer: slicer class to create
402        """
403        ## Clear current slicer
404        if not self.slicer == None: 
405            self.slicer.clear()           
406        ## Create a new slicer   
407        self.slicer_z += 1
408        self.slicer = slicer(self, self.subplot, zorder=self.slicer_z)
409        self.subplot.set_ylim(self.data2D.ymin, self.data2D.ymax)
410        self.subplot.set_xlim(self.data2D.xmin, self.data2D.xmax)
411        ## Draw slicer
412        self.update()
413        self.slicer.update()
414        msg = "Plotter2D._setSlicer  %s"%self.slicer.__class__.__name__
415        wx.PostEvent(self.parent, StatusEvent(status=msg))
416        # Post slicer event
417        event = self._getEmptySlicerEvent()
418        event.type = self.slicer.__class__.__name__
419        event.obj_class = self.slicer.__class__
420        event.params = self.slicer.get_params()
421        wx.PostEvent(self, event)
422   
423    def update(self, draw=True):
424        """
425        Respond to changes in the model by recalculating the
426        profiles and resetting the widgets.
427        """
428        self.plotpanel.draw()
429       
430    def _set_mask(self, mask):
431        """
432        Set mask
433        """
434        self.data.mask = mask
435       
436    def set_plot_unfocus(self):
437        """
438        Not implemented
439        """
440        pass
441   
442    def _update_mask(self,mask):
443        """
444        Respond to changes in masking
445        """ 
446        # the case of liitle numbers of True points
447        if (len(mask[mask]) < 10 and self.data != None):
448            self.ShowMessage()
449            mask = copy.deepcopy(self.mask)
450            self.data.mask = mask
451        else:
452            self.mask = mask
453        # make temperary data to plot
454        temp_mask = numpy.zeros(len(mask))
455        temp_data = copy.deepcopy(self.data)
456        # temp_data default is None
457        # This method is to distinguish between masked point and data point = 0.
458        temp_mask = temp_mask/temp_mask
459        temp_mask[mask] = temp_data.data[mask]
460        # set temp_data value for self.mask==True, else still None
461        #temp_mask[mask] = temp_data[mask]
462        temp_data.data[mask==False] = temp_mask[mask==False]
463        self.plotpanel.clear()
464        if self.slicer != None:
465            self.slicer.clear()
466            self.slicer = None
467        # Post slicer None event
468        event = self._getEmptySlicerEvent()
469        wx.PostEvent(self, event)
470       
471        ##use this method
472        #set zmax and zmin to plot: Fix it w/ data.
473        if self.plotpanel.scale == 'log_{10}':
474            zmax = math.log10(max(self.data.data[self.data.data>0]))
475            zmin = math.log10(min(self.data.data[self.data.data>0]))
476        else:
477            zmax = max(self.data.data[self.data.data>0])
478            zmin = min(self.data.data[self.data.data>0])
479        #plot   
480        plot = self.plotpanel.image(data=temp_mask,
481                       qx_data=self.data.qx_data,
482                       qy_data=self.data.qy_data,
483                       xmin=self.data.xmin,
484                       xmax=self.data.xmax,
485                       ymin=self.data.ymin,
486                       ymax=self.data.ymax,
487                       zmin=zmin,
488                       zmax=zmax,
489                       cmap=self.cmap,
490                       color=0, symbol=0, label=self.data.name)
491        # axis labels
492        self.plotpanel.axes[0].set_xlabel('$\\rm{Q}_{x}(A^{-1})$')
493        self.plotpanel.axes[0].set_ylabel('$\\rm{Q}_{y}(A^{-1})$')
494        self.plotpanel.render()
495        self.plotpanel.subplot.figure.canvas.draw_idle()
496       
497    def _getEmptySlicerEvent(self):
498        """
499        create an empty slicervent
500        """
501        self.innerbox_rb.SetValue(False)
502        self.outerbox_rb.SetValue(False)
503        self.innersector_rb.SetValue(False)
504        self.outersector_rb.SetValue(False)
505        self.innercircle_rb.SetValue(False)
506        self.outercircle_rb.SetValue(False)
507        return SlicerEvent(type=None,
508                           params=None,
509                           obj_class=None) 
510             
511    def _draw_model(self, event):
512        """
513         on_close, update the model2d plot
514        """
515        pass
516       
517    def freeze_axes(self):
518        """
519        freeze axes
520        """
521        self.plotpanel.axes_frozen = True
522       
523    def thaw_axes(self):
524        """
525        thaw axes
526        """
527        self.plotpanel.axes_frozen = False       
528         
529    def onMouseMotion(self, event):
530        """
531        onMotion event
532        """
533        pass
534   
535    def onWheel(self, event):
536        """
537        on wheel event
538        """
539        pass 
540   
541    def OnClose(self, event):
542        """
543        """
544        try:
545            self.parent._draw_masked_model(event)
546        except:
547            # when called by data panel
548            event.Skip()
549            pass   
550
551class FloatPanel(wx.Dialog):
552    """
553    Provides the Mask Editor GUI.
554    """
555    ## Internal nickname for the window, used by the AUI manager
556    window_name = "Plot"
557    ## Name to appear on the window title bar
558    window_caption = "Plot"
559    ## Flag to tell the AUI manager to put this panel in the center pane
560    CENTER_PANE = False
561    ID = wx.NewId()
562    def __init__(self, parent=None, base=None, 
563                 data=None, dimension=1, id=ID, *args, **kwds):
564        kwds["style"] = wx.DEFAULT_DIALOG_STYLE
565        kwds["size"] = wx.Size(PANEL_SIZE*1.5, PANEL_SIZE*1.5) 
566        wx.Dialog.__init__(self, parent, id=id,  *args, **kwds)
567       
568        if data != None:
569            #Font size
570            kwds = []
571            self.SetWindowVariant(variant=FONT_VARIANT)
572            self.SetTitle("Plot " + data.name)
573            self.parent = base
574            self.data = data
575            self.str = self.data.__str__()
576            ## when 2 data have the same id override the 1 st plotted
577            self.name = self.data.name
578            self.dimension = dimension
579            # Panel for 2D plot
580            self.plotpanel = Maskplotpanel(self, -1, dimension,
581                                           style=wx.TRANSPARENT_WINDOW)
582            self.plotpanel._SetInitialSize()
583           
584            self.cmap = DEFAULT_CMAP
585            ## Create Artist and bind it
586            self.subplot = self.plotpanel.subplot
587            self._setup_layout()
588            if self.dimension == 1:
589                self.newplot = Data1D(x=data.x, y=data.y, 
590                                      dx=data.dx, dy=data.dy)
591                self.newplot.name = data.name
592            else:   
593                self.newplot = Data2D(image=self.data.data)
594                self.newplot.setValues(self.data)
595                    # Compute and get the image plot
596            self.get_plot()
597            #self.plotpanel.add_image(self.newplot)
598            self.Centre()
599            self.Layout()
600   
601    def get_plot(self):
602        """
603        Get Plot panel
604        """
605        cal_plot = CalcPlot(panel=self.plotpanel, 
606                                   image=self.newplot, 
607                                   completefn=self.complete)
608        cal_plot.queue()
609   
610    def complete(self, panel, image, elapsed=None):
611        """
612        Plot image
613       
614        :param image: newplot [plotpanel]
615        """
616        wx.CallAfter(panel.add_image, image) 
617       
618    def _setup_layout(self):
619        """
620        Set up the layout
621        """
622        #  panel
623        sizer = wx.GridBagSizer(10, 10)
624        if self.dimension == 3:
625            note = "Note: I am very SLOW.     Please be PATIENT...\n"
626            if len(self.data.data) > 3600:
627                note += "Rotation disabled for pixels > 60x60."
628            note_txt = wx.StaticText(self, -1, note) 
629            note_txt.SetForegroundColour(wx.RED)
630            sizer.Add(note_txt, (0, 2), flag=wx.RIGHT|wx.TOP, border=5)
631       
632        sizer.Add(self.plotpanel, (1, 0), (9, 9), 
633                  wx.EXPAND|wx.ALL, 15)
634
635        sizer.AddGrowableCol(3)
636        sizer.AddGrowableRow(2)
637       
638        self.SetSizerAndFit(sizer)
639        self.Centre()
640        self.Show(True)
641       
642    def set_plot_unfocus(self):
643        """
644        Not implemented
645        """
646        pass
647   
648
649    def _draw_model(self, event):
650        """
651         on_close, update the model2d plot
652        """
653        pass
654       
655    def freeze_axes(self):
656        """
657        freeze axes
658        """
659        self.plotpanel.axes_frozen = True
660       
661    def thaw_axes(self):
662        """
663        thaw axes
664        """
665        self.plotpanel.axes_frozen = False       
666   
667    def OnClose(self, event):
668        """
669        """
670        try:
671            self.plotpanel.subplot.figure.clf()
672            self.plotpanel.close()
673        except:
674            # when called by data panel
675            event.Skip()
676            pass
677
678               
679class Maskplotpanel(PlotPanel):
680    """
681    PlotPanel for Quick plot and masking plot
682    """
683    def __init__(self, parent, id=-1, dimension=2, color=None, 
684                                            dpi=None, **kwargs):
685        """
686        """
687        PlotPanel.__init__(self, parent, id=id, color=color, dpi=dpi, **kwargs)
688       
689        # Keep track of the parent Frame
690        self.parent = parent
691        # Internal list of plottable names (because graph
692        # doesn't have a dictionary of handles for the plottables)
693        self.dimension = dimension
694        self.plots = {}
695        self.graph = Graph()
696        #add axis labels
697        if self.dimension == 1:
698            self.graph.xaxis('\\rm{x} ', '')
699            self.graph.yaxis('\\rm{y} ', '')
700        if self.dimension == 2:
701            self.graph.xaxis('\\rm{Q}_{x} ', 'A^{-1}')
702            self.graph.yaxis('\\rm{Q}_{y} ', 'A^{-1}')
703       
704    def add_toolbar(self):
705        """
706        Add toolbar
707        """
708        # Not implemented
709        pass
710   
711    def on_set_focus(self, event):
712        """
713        send to the parenet the current panel on focus
714        """
715        if self.dimension == 3:
716            pass
717        else:
718            self.draw()   
719         
720    def add_image(self, plot):
721        """
722        Add Image
723        """
724        self.plots[plot.name] = plot
725        #init graph
726        self.gaph = Graph()
727        #add plot
728        self.graph.add(plot)
729        #add axes
730        if self.dimension == 1:
731            self.xaxis_label = '\\rm{x} '
732            self.xaxis_unit = ''
733            self.yaxis_label = '\\rm{y} '
734            self.yaxis_unit = ''
735        #draw
736        # message
737        status_type = 'progress' 
738        msg = 'Plotting...'
739        self._status_info(msg, status_type)
740        status_type = 'stop'           
741        self.graph.render(self)
742        self.subplot.figure.canvas.resizing = False
743        if self.dimension < 3:
744            self.graph.render(self)
745            self.subplot.figure.canvas.draw()
746        elif FONT_VARIANT:
747            self.subplot.figure.canvas.draw()
748        msg = 'Plotting Completed.'
749        self._status_info(msg, status_type)
750       
751    def onMouseMotion(self, event):
752        """
753        Disable dragging 2D image
754        """
755        pass
756   
757    def onWheel(self, event):
758        """
759        """
760        pass 
761     
762    def onLeftDown(self, event):
763        """
764        Disables LeftDown
765        """
766        pass
767   
768    def onPick(self, event):
769        """
770        Disables OnPick
771        """
772        pass
773   
774    def draw(self):
775        """
776        Draw
777        """
778        # message
779        status_type = 'progress' 
780        msg = 'Plotting...'
781        self._status_info(msg, status_type)
782        status_type = 'stop'           
783       
784        if self.dimension == 3:
785            pass
786        else:
787           self.subplot.figure.canvas.draw_idle() 
788       
789        msg = 'Plotting Completed.'
790        self._status_info(msg, status_type)
791       
792    def onContextMenu(self, event):
793        """
794        Default context menu for a plot panel
795        """
796        # Selective Slicer plot popup menu
797        slicerpop = wx.Menu()
798       
799        id = wx.NewId()
800        slicerpop.Append(id,'&Print Image', 'Print image')
801        wx.EVT_MENU(self, id, self.onPrint)
802
803        id = wx.NewId()
804        slicerpop.Append(id, '&Copy to Clipboard', 'Copy to the clipboard')
805        wx.EVT_MENU(self, id, self.OnCopyFigureMenu)
806       
807        if self.dimension == 1:
808            id = wx.NewId()
809            slicerpop.Append(id, '&Change Scale')
810            wx.EVT_MENU(self, id, self._onProperties)
811        else:
812            slicerpop.AppendSeparator()
813            id_cm = wx.NewId()
814            slicerpop.Append(id_cm, '&Toggle Linear/Log scale')
815            wx.EVT_MENU(self, id_cm, self._onToggleScale)
816               
817        pos = event.GetPosition()
818        pos = self.ScreenToClient(pos)
819        self.PopupMenu(slicerpop, pos)
820       
821    def _status_info(self, msg = '', type = "update"):
822        """
823        Status msg
824        """
825        if type == "stop":
826            label = "Plotting..."
827            able = True
828        else:   
829            label = "Wait..."
830            able = False
831        if self.parent.parent.parent != None:
832                wx.PostEvent(self.parent.parent.parent, 
833                             StatusEvent(status = msg, type = type ))
834
835class ViewerFrame(wx.Frame):
836    """
837    Add comment
838    """
839    def __init__(self, parent, id, title):
840        """
841        comment
842        :param parent: parent panel/container
843        """
844        # Initialize the Frame object
845        wx.Frame.__init__(self, parent, id, title,
846                          wx.DefaultPosition, wx.Size(950, 850))
847        # Panel for 1D plot
848        self.plotpanel = Maskplotpanel(self, -1, style=wx.RAISED_BORDER)
849
850class ViewApp(wx.App):
851    def OnInit(self):
852        frame = ViewerFrame(None, -1, 'testView')   
853        frame.Show(True)
854        #self.SetTopWindow(frame)
855       
856        return True
857               
858if __name__ == "__main__": 
859    app = ViewApp(0)
860    app.MainLoop()     
Note: See TracBrowser for help on using the repository browser.