source: trunk/python/casatoolbar.py@ 1981

Last change on this file since 1981 was 1981, checked in by Kana Sugimoto, 14 years ago

New Development: Yes

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

Ready for Test: Yes

Interface Changes: Yes

What Interface Changed: Added "-" page button and page counter to the ASAP plotter

Test Programs: plot spectra and press Page: "+" and "-" button to go

back and forth between the pages

Put in Release Notes: Yes

Module(s): asapplotter and sdplot (CASA)

Description:

Added "-" page button and page counter to the ASAP plotter.
Renamed "+ page" button to "+" button.
You can plot multi-page plots and move back and forth between pages.

File size: 14.1 KB
Line 
1import os
2import matplotlib, numpy
3from asap.logging import asaplog, asaplog_post_dec
4
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
14 ### and display spectral value on the toolbar.
15 def _select_spectrum(self,event):
16 # Do not fire event when in zooming/panning mode
17 mode = self.figmgr.toolbar.mode
18 if not mode == '':
19 return
20 # When selected point is out of panels
21 if event.inaxes == None:
22 return
23 # If not left button
24 if event.button != 1:
25 return
26
27 xclick=event.xdata
28 yclick=event.ydata
29 dist2=1000.
30 pickline=None
31 # If the pannel has picable objects
32 pflag=False
33 for lin in event.inaxes.lines:
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
57 del pind, inds, xlin, ylin
58 # Spectra are Picked
59 theplot = self.plotter._plotter
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)
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
71 picked="Selected: '"+titl+"' in panel '"+titp+"'."
72 thetoolbar.set_message(picked)
73 # Generate a navigation window
74 #naviwin=Navigationwindow(titp,titl)
75 #------------------------------------------------------#
76 # Show spectrum data at mouse position
77 def spec_data(event):
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)
94 #------------------------------------------------------#
95 # Disconnect from mouse events
96 def discon(event):
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
104 #------------------------------------------------------#
105 # Show data value along with mouse movement
106 theplot.register('motion_notify',spec_data)
107 # Finish events when mouse button is released
108 theplot.register('button_release',discon)
109
110
111 ### Calculate statistics of the selected area.
112 def _single_mask(self,event):
113 # Do not fire event when in zooming/panning mode
114 if not self.figmgr.toolbar.mode == '':
115 return
116 # When selected point is out of panels
117 if event.inaxes == None:
118 return
119 if event.button ==1:
120 baseinv=True
121 elif event.button == 3:
122 baseinv=False
123 else:
124 return
125
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)
135
136 # Interactive mask definition
137 from asap.interactivemask import interactivemask
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)
147
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):
155 self.notewin.load_modmenu(event)
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
170 def _new_page(self,next=True):
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
178 self.plotter._plotter.hold()
179 if not next:
180 self._set_prevpage_counter()
181 #self.plotter._plotter.clear()
182 self.set_pagenum(self._get_pagenum())
183 self.plotter._plot(self.plotter._data)
184 self.plotter._plotter.release()
185 self.plotter._plotter.tidy()
186 self.plotter._plotter.show(hardrefresh=False)
187
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
213
214 def _get_pagenum(self):
215 maxpanel = 16
216 nextp = self.plotter._ipanel+1
217 if self.plotter._rows and self.plotter._cols:
218 ppp = self.plotter._rows*self.plotter._cols
219 else:
220 ppp = maxpanel
221 return int(nextp/ppp)+1
222
223#####################################
224## Backend dependent Classes ##
225#####################################
226### TkAgg
227if matplotlib.get_backend() == 'TkAgg':
228 import Tkinter as Tk
229 from notationwindow import NotationWindowTkAgg
230
231class CustomToolbarTkAgg(CustomToolbarCommon, Tk.Frame):
232 def __init__(self,parent):
233 from asap.asapplotter import asapplotter
234 if not isinstance(parent,asapplotter):
235 return False
236 if not parent._plotter:
237 return False
238 self._p = parent._plotter
239 self.figmgr = self._p.figmgr
240 self.canvas = self.figmgr.canvas
241 self.mode = ''
242 self.button = True
243 self.pagenum = None
244 self._add_custom_toolbar()
245 self.notewin=NotationWindowTkAgg(master=self.canvas)
246 CustomToolbarCommon.__init__(self,parent)
247
248 def _add_custom_toolbar(self):
249 Tk.Frame.__init__(self,master=self.figmgr.window)
250 #self.bSpec=self._NewButton(master=self,
251 # text='spec value',
252 # command=self.spec_show)
253 self.bNote=self._NewButton(master=self,
254 text='notation',
255 command=self.modify_note)
256
257 self.bStat=self._NewButton(master=self,
258 text='statistics',
259 command=self.stat_cal)
260 # page change oparations
261 self.lPagetitle = Tk.Label(master=self,text=' Page:',padx=5)
262 self.lPagetitle.pack(side=Tk.LEFT)
263 self.pagenum = Tk.StringVar(master=self)
264 self.lPage = Tk.Label(master=self,textvariable=self.pagenum,
265 padx=5,bg='white')
266 self.lPage.pack(side=Tk.LEFT,padx=3)
267
268 self.bNext=self._NewButton(master=self,
269 text=' + ',
270 command=self.next_page)
271 self.bPrev=self._NewButton(master=self,
272 text=' - ',
273 command=self.prev_page)
274
275 if os.uname()[0] != 'Darwin':
276 self.bPrev.config(padx=5)
277 self.bNext.config(padx=5)
278 self.bQuit=self._NewButton(master=self,
279 text='Quit',
280 command=self.quit,
281 side=Tk.RIGHT)
282 self.pack(side=Tk.BOTTOM,fill=Tk.BOTH)
283 self.pagenum.set(' ')
284
285 self.disable_button()
286 return #self
287
288 def _NewButton(self, master, text, command, side=Tk.LEFT):
289 if os.uname()[0] == 'Darwin':
290 b = Tk.Button(master=master, text=text, command=command)
291 else:
292 b = Tk.Button(master=master, text=text, padx=2, pady=2,
293 command=command)
294 b.pack(side=side)
295 return b
296
297 def spec_show(self):
298 if not self.figmgr.toolbar.mode == '' or not self.button: return
299 self.figmgr.toolbar.set_message('spec value: drag on a spec')
300 if self.mode == 'spec': return
301 #self.bStat.config(relief='raised')
302 #self.bSpec.config(relief='sunken')
303 #self.bNote.config(relief='raised')
304 self.mode='spec'
305 self.notewin.close_widgets()
306 self.__disconnect_event()
307 self._p.register('button_press',self._select_spectrum)
308
309 def stat_cal(self):
310 if not self.figmgr.toolbar.mode == '' or not self.button: return
311 self.figmgr.toolbar.set_message('statistics: select a region')
312 if self.mode == 'stat':
313 # go back to spec mode
314 self.bStat.config(relief='raised')
315 self.spec_show()
316 return
317 #self.bSpec.config(relief='raised')
318 self.bStat.config(relief='sunken')
319 self.bNote.config(relief='raised')
320 self.mode='stat'
321 self.notewin.close_widgets()
322 self.__disconnect_event()
323 self._p.register('button_press',self._single_mask)
324
325 def modify_note(self):
326 if not self.figmgr.toolbar.mode == '': return
327 self.figmgr.toolbar.set_message('text: select a position/text')
328 if self.mode == 'note':
329 self.bNote.config(relief='raised')
330 self.mode='none'
331 self.spec_show()
332 return
333 #self.bSpec.config(relief='raised')
334 self.bStat.config(relief='raised')
335 self.bNote.config(relief='sunken')
336 self.mode='note'
337 self.__disconnect_event()
338 self._p.register('button_press',self._mod_note)
339
340 def prev_page(self):
341 self.figmgr.toolbar.set_message('plotting the previous page')
342 self._new_page(next=False)
343
344 def next_page(self):
345 self.figmgr.toolbar.set_message('plotting the next page')
346 self._new_page(next=True)
347
348 def set_pagenum(self,page):
349 nwidth = int(numpy.ceil(numpy.log10(max(page,1))))+1
350 nwidth = max(nwidth,4)
351 formatstr = '%'+str(nwidth)+'d'
352 self.pagenum.set(formatstr % (page))
353
354 def quit(self):
355 self.__disconnect_event()
356 #self.delete_bar()
357 self.disable_button()
358 self.figmgr.window.wm_withdraw()
359
360 def enable_button(self):
361 if self.button: return
362 #self.bSpec.config(state=Tk.NORMAL)
363 self.bStat.config(state=Tk.NORMAL)
364 self.button=True
365 self.spec_show()
366
367 def disable_button(self):
368 if not self.button: return
369 #self.bSpec.config(relief='raised', state=Tk.DISABLED)
370 self.bStat.config(relief='raised', state=Tk.DISABLED)
371 #self.bNext.config(state=Tk.DISABLED)
372 #self.bPrev.config(state=Tk.DISABLED)
373 self.button=False
374 self.mode=''
375 self.__disconnect_event()
376
377 def enable_next(self):
378 self.bNext.config(state=Tk.NORMAL)
379
380 def disable_next(self):
381 self.bNext.config(state=Tk.DISABLED)
382
383 def enable_prev(self):
384 self.bPrev.config(state=Tk.NORMAL)
385
386 def disable_prev(self):
387 self.bPrev.config(state=Tk.DISABLED)
388
389 def delete_bar(self):
390 self.__disconnect_event()
391 self.destroy()
392
393 def __disconnect_event(self):
394 self._p.register('button_press',None)
395 self._p.register('button_release',None)
Note: See TracBrowser for help on using the repository browser.