source: trunk/python/casatoolbar.py @ 1982

Last change on this file since 1982 was 1982, checked in by Kana Sugimoto, 13 years ago

New Development: No

JIRA Issue: Yes (CAS-1822/ASAP-204)

Ready for Test: Yes

Interface Changes: No

What Interface Changed:

Test Programs: plot spectra and move among pages

Put in Release Notes: No

Module(s): asapplotter and sdplot

Description: a little bit of fix of page counter


File size: 14.2 KB
RevLine 
[1724]1import os
[1981]2import matplotlib, numpy
3from asap.logging import asaplog, asaplog_post_dec
[1884]4
[1724]5######################################
6##    Add CASA custom toolbar       ##
7######################################
8class CustomToolbarCommon:
9    def __init__(self,parent):
10        self.plotter=parent
11        #self.figmgr=self.plotter._plotter.figmgr
12
13    ### select the nearest spectrum in pick radius
[1826]14    ###    and display spectral value on the toolbar.
[1724]15    def _select_spectrum(self,event):
16        # Do not fire event when in zooming/panning mode
17        mode = self.figmgr.toolbar.mode
[1826]18        if not mode == '':
19            return
20            # When selected point is out of panels
[1724]21        if event.inaxes == None:
[1826]22            return
[1724]23        # If not left button
24        if event.button != 1:
[1826]25            return
[1724]26
27        xclick=event.xdata
28        yclick=event.ydata
29        dist2=1000.
30        pickline=None
[1826]31        # If the pannel has picable objects
32        pflag=False
[1724]33        for lin in event.inaxes.lines:
[1826]34            if not lin.pickable():
35                continue
36            pflag=True
37            flag,pind = lin.contains(event)
38            if not flag:
39                continue
40            # Get nearest point
41            inds = pind['ind']
42            xlin = lin.get_xdata()
43            ylin = lin.get_ydata()
44            for i in inds:
45                d2=(xlin[i]-xclick)**2+(ylin[i]-yclick)**2
46                if dist2 >= d2:
47                    dist2 = d2
48                    pickline = lin
49        # No pickcable line in the pannel
50        if not pflag:
51            return
52        # Pickable but too far from mouse position
53        elif pickline is None:
54            picked='No line selected.'
55            self.figmgr.toolbar.set_message(picked)
56            return
[1724]57        del pind, inds, xlin, ylin
[1826]58        # Spectra are Picked
[1724]59        theplot = self.plotter._plotter
[1826]60        thetoolbar = self.figmgr.toolbar
61        thecanvas = self.figmgr.canvas
62        # Disconnect the default motion notify event
63        # Notice! the other buttons are also diabled!!!
64        thecanvas.mpl_disconnect(thetoolbar._idDrag)
[1724]65        # Get picked spectrum
66        xdata = pickline.get_xdata()
67        ydata = pickline.get_ydata()
68        titl=pickline.get_label()
69        titp=event.inaxes.title.get_text()
70        panel0=event.inaxes
[1826]71        picked="Selected: '"+titl+"' in panel '"+titp+"'."
72        thetoolbar.set_message(picked)
73        # Generate a navigation window
[1724]74        #naviwin=Navigationwindow(titp,titl)
75        #------------------------------------------------------#
76        # Show spectrum data at mouse position
77        def spec_data(event):
[1826]78            # Getting spectrum data of neiboring point
79            xclick=event.xdata
80            if event.inaxes != panel0:
81                return
82            ipoint=len(xdata)-1
83            for i in range(len(xdata)-1):
84                xl=xclick-xdata[i]
85                xr=xclick-xdata[i+1]
86                if xl*xr <= 0.:
87                    ipoint = i
88                    break
89            # Output spectral value on the navigation window
90            posi='[ %s, %s ]:  x = %.2f   value = %.2f'\
91                  %(titl,titp,xdata[ipoint],ydata[ipoint])
92            #naviwin.posi.set(posi)
93            thetoolbar.set_message(posi)
[1724]94        #------------------------------------------------------#
95        # Disconnect from mouse events
96        def discon(event):
[1826]97            #naviwin.window.destroy()
98            theplot.register('motion_notify',None)
99            # Re-activate the default motion_notify_event
100            thetoolbar._idDrag=thecanvas.mpl_connect('motion_notify_event',
101                                                     thetoolbar.mouse_move)
102            theplot.register('button_release',None)
103            return
[1724]104        #------------------------------------------------------#
105        # Show data value along with mouse movement
[1826]106        theplot.register('motion_notify',spec_data)
[1724]107        # Finish events when mouse button is released
108        theplot.register('button_release',discon)
109
110
[1826]111    ### Calculate statistics of the selected area.
[1724]112    def _single_mask(self,event):
113        # Do not fire event when in zooming/panning mode
[1826]114        if not self.figmgr.toolbar.mode == '':
115            return
[1724]116        # When selected point is out of panels
117        if event.inaxes == None:
[1826]118            return
119        if event.button ==1:
120            baseinv=True
121        elif event.button == 3:
122            baseinv=False
123        else:
124            return
[1724]125
[1826]126        def _calc_stats():
127            msk=mymask.get_mask()
128            mymask.scan.stats(stat='max',mask=msk)
129            mymask.scan.stats(stat='min',mask=msk)
130            mymask.scan.stats(stat='sum',mask=msk)
131            mymask.scan.stats(stat='mean',mask=msk)
132            mymask.scan.stats(stat='median',mask=msk)
133            mymask.scan.stats(stat='rms',mask=msk)
134            mymask.scan.stats(stat='stddev',mask=msk)
[1724]135
[1826]136        # Interactive mask definition
[1724]137        from asap.interactivemask import interactivemask
[1826]138        mymask=interactivemask(plotter=self.plotter,scan=self.plotter._data)
139        # Create initial mask
140        mymask.set_basemask(invert=baseinv)
141        # Inherit event
142        mymask.set_startevent(event)
143        # Set callback func
144        mymask.set_callback(_calc_stats)
145        # Selected mask
146        mymask.select_mask(once=True,showmask=False)
[1724]147
[1884]148    def _mod_note(self,event):
149        # Do not fire event when in zooming/panning mode
150        if not self.figmgr.toolbar.mode == '':
151            return
152        if event.button ==1:
153            self.notewin.load_textwindow(event)
154        elif event.button == 3 and self._note_picked(event):
[1885]155            self.notewin.load_modmenu(event)
[1884]156        return
157
158    def _note_picked(self,event):
159        # just briefly check if any texts are picked
160        for textobj in self.canvas.figure.texts:
161            if textobj.contains(event)[0]:
162                return True
163        for ax in self.canvas.figure.axes:
164            for textobj in ax.texts:
165                if textobj.contains(event)[0]:
166                    return True
167        #print "No text picked"
168        return False
169
[1913]170    def _new_page(self,next=True):
[1981]171        if self.plotter._startrow <= 0:
172            msg = "The page counter is reset due to chages of plot settings. "
173            msg += "Plotting from the first page."
174            asaplog.push(msg)
175            asaplog.post('WARN')
176            next = True
177           
[1913]178        self.plotter._plotter.hold()
[1981]179        if not next:
180            self._set_prevpage_counter()
[1945]181        #self.plotter._plotter.clear()
[1982]182        self.plotter._plot(self.plotter._data)
[1981]183        self.set_pagenum(self._get_pagenum())
[1913]184        self.plotter._plotter.release()
185        self.plotter._plotter.tidy()
186        self.plotter._plotter.show(hardrefresh=False)
187
[1981]188    def _set_prevpage_counter(self):
189        # set row and panel counters to those of the 1st panel of previous page
190        maxpanel = 16
191        # the ID of the last panel in current plot
192        lastpanel = self.plotter._ipanel
193        # the number of current subplots
194        currpnum = len(self.plotter._plotter.subplots)
195        # the nuber of previous subplots
196        prevpnum = None
197        if self.plotter._rows and self.plotter._cols:
198            # when user set layout
199            prevpnum = self.plotter._rows*self.plotter._cols
200        else:
201            # no user specification
202            prevpnum = maxpanel
203           
204        start_ipanel = max(lastpanel-currpnum-prevpnum+1, 0)
205        # set the pannel ID of the last panel of prev-prev page
206        self.plotter._ipanel = start_ipanel-1
207        if self.plotter._panelling == 'r':
208            self.plotter._startrow = start_ipanel
209        else:
210            # the start row number of the next panel
211            self.plotter._startrow = self.plotter._panelrows[start_ipanel]
212        del lastpanel,currpnum,prevpnum,start_ipanel
[1979]213
[1981]214    def _get_pagenum(self):
215        maxpanel = 16
[1982]216        # get the ID of last panel in the current page
217        idlastpanel = self.plotter._ipanel
[1981]218        if self.plotter._rows and self.plotter._cols:
219            ppp = self.plotter._rows*self.plotter._cols
220        else:
221            ppp = maxpanel
[1982]222        return int(idlastpanel/ppp)+1
[1981]223
[1724]224#####################################
225##    Backend dependent Classes    ##
226#####################################
227### TkAgg
[1826]228if matplotlib.get_backend() == 'TkAgg':
229    import Tkinter as Tk
[1884]230    from notationwindow import NotationWindowTkAgg
[1826]231
[1768]232class CustomToolbarTkAgg(CustomToolbarCommon, Tk.Frame):
[1724]233    def __init__(self,parent):
234        from asap.asapplotter import asapplotter
[1826]235        if not isinstance(parent,asapplotter):
236            return False
237        if not parent._plotter:
238            return False
[1981]239        self._p = parent._plotter
240        self.figmgr = self._p.figmgr
241        self.canvas = self.figmgr.canvas
242        self.mode = ''
243        self.button = True
244        self.pagenum = None
[1724]245        self._add_custom_toolbar()
[1884]246        self.notewin=NotationWindowTkAgg(master=self.canvas)
[1724]247        CustomToolbarCommon.__init__(self,parent)
248
249    def _add_custom_toolbar(self):
[1768]250        Tk.Frame.__init__(self,master=self.figmgr.window)
[1979]251        #self.bSpec=self._NewButton(master=self,
252        #                           text='spec value',
253        #                           command=self.spec_show)
[1981]254        self.bNote=self._NewButton(master=self,
255                                   text='notation',
256                                   command=self.modify_note)
257
[1768]258        self.bStat=self._NewButton(master=self,
[1724]259                                   text='statistics',
260                                   command=self.stat_cal)
[1981]261        # page change oparations
262        self.lPagetitle = Tk.Label(master=self,text='   Page:',padx=5)
263        self.lPagetitle.pack(side=Tk.LEFT)
264        self.pagenum = Tk.StringVar(master=self)
265        self.lPage = Tk.Label(master=self,textvariable=self.pagenum,
266                              padx=5,bg='white')
267        self.lPage.pack(side=Tk.LEFT,padx=3)
268       
[1913]269        self.bNext=self._NewButton(master=self,
[1981]270                                   text=' + ',
[1913]271                                   command=self.next_page)
[1981]272        self.bPrev=self._NewButton(master=self,
273                                   text=' - ',
274                                   command=self.prev_page)
275
[1914]276        if os.uname()[0] != 'Darwin':
[1981]277            self.bPrev.config(padx=5)
[1914]278            self.bNext.config(padx=5)
[1768]279        self.bQuit=self._NewButton(master=self,
[1724]280                                   text='Quit',
281                                   command=self.quit,
282                                   side=Tk.RIGHT)
[1768]283        self.pack(side=Tk.BOTTOM,fill=Tk.BOTH)
[1981]284        self.pagenum.set('    ')
[1768]285
[1724]286        self.disable_button()
[1768]287        return #self
[1724]288
289    def _NewButton(self, master, text, command, side=Tk.LEFT):
[1826]290        if os.uname()[0] == 'Darwin':
[1724]291            b = Tk.Button(master=master, text=text, command=command)
292        else:
[1826]293            b = Tk.Button(master=master, text=text, padx=2, pady=2,
294                          command=command)
[1724]295        b.pack(side=side)
296        return b
[1826]297
[1724]298    def spec_show(self):
299        if not self.figmgr.toolbar.mode == '' or not self.button: return
300        self.figmgr.toolbar.set_message('spec value: drag on a spec')
301        if self.mode == 'spec': return
[1979]302        #self.bStat.config(relief='raised')
303        #self.bSpec.config(relief='sunken')
304        #self.bNote.config(relief='raised')
[1724]305        self.mode='spec'
[1885]306        self.notewin.close_widgets()
[1724]307        self.__disconnect_event()
308        self._p.register('button_press',self._select_spectrum)
309
310    def stat_cal(self):
311        if not self.figmgr.toolbar.mode == '' or not self.button: return
312        self.figmgr.toolbar.set_message('statistics: select a region')
[1979]313        if self.mode == 'stat':
314            # go back to spec mode
315            self.bStat.config(relief='raised')
316            self.spec_show()
317            return
318        #self.bSpec.config(relief='raised')
[1724]319        self.bStat.config(relief='sunken')
[1884]320        self.bNote.config(relief='raised')
[1724]321        self.mode='stat'
[1885]322        self.notewin.close_widgets()
[1724]323        self.__disconnect_event()
324        self._p.register('button_press',self._single_mask)
325
[1884]326    def modify_note(self):
[1890]327        if not self.figmgr.toolbar.mode == '': return
[1884]328        self.figmgr.toolbar.set_message('text: select a position/text')
[1979]329        if self.mode == 'note':
330            self.bNote.config(relief='raised')
331            self.mode='none'
332            self.spec_show()
333            return
334        #self.bSpec.config(relief='raised')
[1884]335        self.bStat.config(relief='raised')
336        self.bNote.config(relief='sunken')
337        self.mode='note'
338        self.__disconnect_event()
339        self._p.register('button_press',self._mod_note)
340
[1913]341    def prev_page(self):
342        self.figmgr.toolbar.set_message('plotting the previous page')
343        self._new_page(next=False)
344
345    def next_page(self):
346        self.figmgr.toolbar.set_message('plotting the next page')
347        self._new_page(next=True)
348
[1981]349    def set_pagenum(self,page):
350        nwidth = int(numpy.ceil(numpy.log10(max(page,1))))+1
351        nwidth = max(nwidth,4)
352        formatstr = '%'+str(nwidth)+'d'
353        self.pagenum.set(formatstr % (page))
354
[1724]355    def quit(self):
356        self.__disconnect_event()
[1765]357        #self.delete_bar()
358        self.disable_button()
[1724]359        self.figmgr.window.wm_withdraw()
360
361    def enable_button(self):
362        if self.button: return
[1979]363        #self.bSpec.config(state=Tk.NORMAL)
[1724]364        self.bStat.config(state=Tk.NORMAL)
365        self.button=True
366        self.spec_show()
[1826]367
[1724]368    def disable_button(self):
369        if not self.button: return
[1981]370        #self.bSpec.config(relief='raised', state=Tk.DISABLED)
[1826]371        self.bStat.config(relief='raised', state=Tk.DISABLED)
[1981]372        #self.bNext.config(state=Tk.DISABLED)
[1921]373        #self.bPrev.config(state=Tk.DISABLED)
[1724]374        self.button=False
375        self.mode=''
376        self.__disconnect_event()
377
[1913]378    def enable_next(self):
379        self.bNext.config(state=Tk.NORMAL)
380
381    def disable_next(self):
382        self.bNext.config(state=Tk.DISABLED)
383
384    def enable_prev(self):
[1981]385        self.bPrev.config(state=Tk.NORMAL)
[1913]386
387    def disable_prev(self):
[1981]388        self.bPrev.config(state=Tk.DISABLED)
[1913]389
[1724]390    def delete_bar(self):
391        self.__disconnect_event()
[1768]392        self.destroy()
[1724]393
394    def __disconnect_event(self):
395        self._p.register('button_press',None)
396        self._p.register('button_release',None)
Note: See TracBrowser for help on using the repository browser.