【发布时间】:2016-10-14 21:39:59
【问题描述】:
我有一个脚本,它打开一个文件并通过嵌入在 Tkinter 中的 matplotlib 图绘制它。 我希望能够在该图中选择一个区域并检索角值。 我的脚本正在打开文件并绘制数据,还有一个工作示例(taken from this question),您可以在其中选择图表上的一个区域,但我正在努力将它们组合起来。
我读取和绘制数据的脚本:
import numpy as np
import matplotlib
matplotlib.use('TkAgg')
from matplotlib.figure import *
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
import matplotlib.pyplot as plt
from matplotlib.colors import LogNorm
from matplotlib.ticker import LogFormatter
from matplotlib import gridspec
from matplotlib.ticker import MultipleLocator, FormatStrFormatter
import tkFileDialog
import tkMessageBox
import Tkinter as tk
from ncdump_file import ncdump
from netCDF4 import Dataset
class CustomToolbar(NavigationToolbar2TkAgg):
def __init__(self,canvas_,parent_):
NavigationToolbar2TkAgg.__init__(self,canvas_,parent_)
class simpleapp_tk(tk.Tk):
def __init__(self, parent):
tk.Tk.__init__(self, parent)
self.parent=parent
self.initialize()
def initialize(self):
button = tk.Button(self, text="Open file", command=self.onOpen)
button.pack()
button = tk.Button(self, text="Plot data", command=self.plot)
button.pack()
button = tk.Button(self, text="Quit", command=self.quit)
button.pack()
self.labelVariable = tk.StringVar()
label = tk.Label(self, textvariable=self.labelVariable, anchor = "w", fg = 'white', bg = 'blue')
label.pack()
self.labelVariable.set("Data Browser")
self.resizable(True, True)
def onOpen(self):
ftypes = [('Netcdf files', '*.nc'), ('All files', '*.*')]
dlg = tkFileDialog.Open(filetypes = ftypes)
fl = dlg.show()
if fl != '': # Reading ncfile and dumping data
nc_file = Dataset(fl, 'r')
global time_bnds
global para_beta
global perp_beta
global altitude
time_bnds = nc_file.variables['time_bnds'][:]
altitude = nc_file.variables['altitude'][:]
para_beta = np.swapaxes((nc_file.variables['para_beta'][:]), 0, 1)
perp_beta = np.swapaxes((nc_file.variables['perp_beta'][:]), 0, 1)
para_beta[np.isnan(para_beta)]=0
perp_beta[np.isnan(perp_beta)]=0
#ncdump(nc_file)
def plot (self):
try:
fig = plt.figure('Input para+perp ATB')
gs = gridspec.GridSpec(4, 6)
lvls = np.logspace(-5,5,num=20) # sets range and frequency of tick labels
l_f = LogFormatter(10, labelOnlyBase=False)
xaxis_majorLocator = MultipleLocator(2.0)
xaxis_majorFormatter = FormatStrFormatter('%1.1f')
xaxis_minorLocator = MultipleLocator(1.0)
ax1 = fig.add_subplot(gs[0:4, 0:5])
ax1.plot([10, 12, 14, 16], [0, 1, 2, 3]) # added so that it can run without netcdf file
#im = ax1.imshow(para_beta, extent =(time_bnds.min(), time_bnds.max(), altitude.min(), altitude.max()), aspect = 'auto', cmap = 'jet', interpolation = 'none', origin = 'lowest', norm=LogNorm(vmin=1e-5, vmax = None))
ax1.set_ylim([0, 10])
ax1.set_ylabel('Height (km)')
ax1.xaxis.set_major_locator(xaxis_majorLocator)
ax1.xaxis.set_major_formatter(plt.NullFormatter())
ax1.xaxis.set_minor_locator(xaxis_minorLocator)
plt.title('Parallel')
#cax = fig.add_subplot(gs[1:3, 5:6])
#fig.colorbar(im, label = 'Atten Beta [$km^{-1}\,sr^{-1}$]', cax = cax, format=l_f, ticks = lvls)
#im.set_clim(1e-5, 1e-1) # changes the bounds of the colour bar, irrespective of ticks
plt.subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=None, hspace=0.5)
canvas = FigureCanvasTkAgg(fig, master=self)
canvas.show()
canvas.get_tk_widget().pack()
toolbar = NavigationToolbar2TkAgg(canvas, self)
toolbar.update()
canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=True)
except SyntaxError:
tkMessageBox.showinfo("No file selected", "Please select a file")
def quit():
root.destroy()
if __name__ == "__main__":
app = simpleapp_tk(None)
app.title('Data Browser')
app.mainloop()
工作示例:
from Tkinter import *
from matplotlib.figure import *
import matplotlib
matplotlib.use('TkAgg')
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
root = Tk()
graph = Figure(figsize=(5,4), dpi=100)
ax = graph.add_subplot(111)
plot = ax.plot([1,2,3,4],[5,6,2,8])
canvas = FigureCanvasTkAgg(graph, master=root)
canvas.show()
canvas.get_tk_widget().grid(column=2, row=1, rowspan=2, sticky=(N, S, E, W))
class Zoom(object):
def __init__(self):
self.graph = Figure(figsize=(5,4), dpi=100)
self.ax = graph.add_subplot(111)
# should be Rectangle((0,0),0,0)
self.rect = Rectangle((10,10),100,100)
self.ax.add_patch(self.rect)
self.ax.plot([1,2,3,4],[5,6,2,8])
self.is_pressed = False
self.x0 = 0.0
self.y0 = 0.0
self.x1 = 0.0
self.y1 = 0.0
self.aid = graph.canvas.mpl_connect('button_press_event', self.on_press)
self.bid = graph.canvas.mpl_connect('button_release_event', self.on_release)
self.cid = graph.canvas.mpl_connect('motion_notify_event', self.on_motion)
def on_press(self, event):
self.is_pressed = True
if event.xdata is not None and event.ydata is not None:
self.x0, self.y0 = event.xdata, event.ydata
print 'press:', self.x0, self.y0
# only remove old rectangle
self.rect.set_width(0)
self.rect.set_height(0)
self.rect.set_xy((self.x0, self.y0))
self.ax.figure.canvas.draw()
# color and linestyle for future motion
self.rect.set_facecolor('red')
self.rect.set_linestyle('dashed')
def on_motion(self, event):
if self.is_pressed:
if event.xdata is not None and event.ydata is not None:
self.x1, self.y1 = event.xdata, event.ydata
self.rect.set_width(self.x1 - self.x0)
self.rect.set_height(self.y1 - self.y0)
self.rect.set_xy((self.x0, self.y0))
self.ax.figure.canvas.draw()
print 'rect:', self.x0, self.y0, self.x1, self.y1, (self.x1-self.x0), (self.y1-self.y0)
def on_release(self, event):
self.is_pressed = False
print 'release:', event.xdata, event.ydata
# change only color and linestyle
#self.rect.set_width(self.x1 - self.x0)
#self.rect.set_height(self.y1 - self.y0)
#self.rect.set_xy((self.x0, self.y0))
self.rect.set_facecolor('blue')
self.rect.set_linestyle('solid')
self.ax.figure.canvas.draw()
my_object = Zoom()
root.mainloop()
我应该在脚本的哪个部分介绍选择功能以及如何介绍?我曾尝试在我的函数图中定义 on_press 函数等,但我得到了各种 AttributeErrors。我还尝试在课堂之外全局定义它们,但这也没有用。
【问题讨论】:
标签: python matplotlib tkinter tkinter-canvas