在函数和 return 用户输入中使用 Matplotlib Plot 和 Widgets
Use Matplotlib Plot and Widgets in function and return user input
我的问题如下:
我创建了一个 Matplotlib 图,其中包含一些小部件滑块和一个关闭图的按钮。这行得通。我该怎么做才能在 returns 例如的函数中使用此代码单击 "close figure" 按钮后幻灯片的值?
这是代码(im3d 是一个 3d 图像 numpy 数组):
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider, Button
class IndexTracker(object):
def __init__(self, ax, data3d, title):
self.ax = ax
ax.set_title(title)
self.data3d = data3d
rows, cols, self.slices = data3d.shape
self.ind = self.slices//2
self.im = ax.imshow(self.data3d[:, :, self.ind])
self.update()
def update(self):
self.im.set_data(self.data3d[:, :, self.ind])
ax.set_ylabel('slice %s' % self.ind)
self.im.axes.figure.canvas.draw()
#
fig = plt.figure(figsize=(18, 8), dpi=80, facecolor='w', edgecolor='b')
ax = fig.add_subplot(1,2,1)
ax2 = fig.add_subplot(1,2,2)
tracker1 = IndexTracker(ax, im3d, 'Select First Image')
tracker2 = IndexTracker(ax2, im3d, 'Select Last Image')
def slider_changed(value, tracker):
numb = int(round(value))
tracker.ind = numb
tracker.update()
max0 = im3d.shape[2] -1
ax_start = fig.add_axes([0.1, 0.85, 0.35, 0.03])
sl_start = Slider(ax_start, 'START', 0, max0, valinit=0, valfmt="%i")
ax_end = fig.add_axes([0.6, 0.85, 0.35, 0.03])
sl_end = Slider(ax_end, 'END', 0, max0, valinit=0, valfmt="%i")
def sl_start_changed(val):
slider_changed(sl_start.val,tracker1)
def sl_end_changed(val):
slider_changed(sl_end.val,tracker2)
sl_start.on_changed(sl_start_changed)
sl_end.on_changed(sl_end_changed)
class Index(object):
def close_figure(self, event):
plt.close(fig)
callback = Index()
ax_button = fig.add_axes([0.7, 0.06, 0.15, 0.075])
button = Button(ax_button, 'DONE')
button.on_clicked(callback.close_figure)
fig.canvas.manager.window.raise_()
plt.plot()
我的第一个想法是在 plt.plot() 之后 运行 一个 while 循环,像这样:
while not_done:
time.sleep(0.5)
并在函数 close_figure 中将 not_done 更改为 False。但是在这种情况下,情节没有显示。
关闭图形后滑块仍然可用。因此,您可以在关闭图形
后访问其 val
属性
fig, ax = plt.subplots()
slider = Slider(...)
# .. callbacks
plt.show() # you may use plt.show(block=True) when this is run in interactive mode
print(slider.val)
澄清后编辑:
您是 运行ning spyder 并使用其中的 IPython 控制台。这有几个含义。
- 您需要关闭交互模式,
plt.ioff()
- 您需要为 matplotlib
停用 "support"
然后下面的代码 运行 没问题,只在图形关闭后打印值。
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider, Button
plt.ioff()
im3d = np.random.rand(20,20,10)
class IndexTracker(object):
def __init__(self, ax, data3d, title):
self.ax = ax
ax.set_title(title)
self.data3d = data3d
rows, cols, self.slices = data3d.shape
self.ind = self.slices//2
self.im = ax.imshow(self.data3d[:, :, self.ind])
self.update()
def update(self):
self.im.set_data(self.data3d[:, :, self.ind])
ax.set_ylabel('slice %s' % self.ind)
self.im.axes.figure.canvas.draw()
#
fig = plt.figure(figsize=(18, 8), dpi=80, facecolor='w', edgecolor='b')
ax = fig.add_subplot(1,2,1)
ax2 = fig.add_subplot(1,2,2)
tracker1 = IndexTracker(ax, im3d, 'Select First Image')
tracker2 = IndexTracker(ax2, im3d, 'Select Last Image')
def slider_changed(value, tracker):
numb = int(round(value))
tracker.ind = numb
tracker.update()
max0 = im3d.shape[2] -1
ax_start = fig.add_axes([0.1, 0.85, 0.35, 0.03])
sl_start = Slider(ax_start, 'START', 0, max0, valinit=0, valfmt="%i")
ax_end = fig.add_axes([0.6, 0.85, 0.35, 0.03])
sl_end = Slider(ax_end, 'END', 0, max0, valinit=0, valfmt="%i")
def sl_start_changed(val):
slider_changed(sl_start.val,tracker1)
def sl_end_changed(val):
slider_changed(sl_end.val,tracker2)
sl_start.on_changed(sl_start_changed)
sl_end.on_changed(sl_end_changed)
class Index(object):
def close_figure(self, event):
plt.close(fig)
callback = Index()
ax_button = fig.add_axes([0.7, 0.06, 0.15, 0.075])
button = Button(ax_button, 'DONE')
button.on_clicked(callback.close_figure)
fig.canvas.manager.window.raise_()
plt.show()
print(sl_start.val, sl_end.val)
或者,您可以 运行 外部命令行中的完整代码,而不需要 plt.ioff()
我的问题如下:
我创建了一个 Matplotlib 图,其中包含一些小部件滑块和一个关闭图的按钮。这行得通。我该怎么做才能在 returns 例如的函数中使用此代码单击 "close figure" 按钮后幻灯片的值?
这是代码(im3d 是一个 3d 图像 numpy 数组):
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider, Button
class IndexTracker(object):
def __init__(self, ax, data3d, title):
self.ax = ax
ax.set_title(title)
self.data3d = data3d
rows, cols, self.slices = data3d.shape
self.ind = self.slices//2
self.im = ax.imshow(self.data3d[:, :, self.ind])
self.update()
def update(self):
self.im.set_data(self.data3d[:, :, self.ind])
ax.set_ylabel('slice %s' % self.ind)
self.im.axes.figure.canvas.draw()
#
fig = plt.figure(figsize=(18, 8), dpi=80, facecolor='w', edgecolor='b')
ax = fig.add_subplot(1,2,1)
ax2 = fig.add_subplot(1,2,2)
tracker1 = IndexTracker(ax, im3d, 'Select First Image')
tracker2 = IndexTracker(ax2, im3d, 'Select Last Image')
def slider_changed(value, tracker):
numb = int(round(value))
tracker.ind = numb
tracker.update()
max0 = im3d.shape[2] -1
ax_start = fig.add_axes([0.1, 0.85, 0.35, 0.03])
sl_start = Slider(ax_start, 'START', 0, max0, valinit=0, valfmt="%i")
ax_end = fig.add_axes([0.6, 0.85, 0.35, 0.03])
sl_end = Slider(ax_end, 'END', 0, max0, valinit=0, valfmt="%i")
def sl_start_changed(val):
slider_changed(sl_start.val,tracker1)
def sl_end_changed(val):
slider_changed(sl_end.val,tracker2)
sl_start.on_changed(sl_start_changed)
sl_end.on_changed(sl_end_changed)
class Index(object):
def close_figure(self, event):
plt.close(fig)
callback = Index()
ax_button = fig.add_axes([0.7, 0.06, 0.15, 0.075])
button = Button(ax_button, 'DONE')
button.on_clicked(callback.close_figure)
fig.canvas.manager.window.raise_()
plt.plot()
我的第一个想法是在 plt.plot() 之后 运行 一个 while 循环,像这样:
while not_done:
time.sleep(0.5)
并在函数 close_figure 中将 not_done 更改为 False。但是在这种情况下,情节没有显示。
关闭图形后滑块仍然可用。因此,您可以在关闭图形
后访问其val
属性
fig, ax = plt.subplots()
slider = Slider(...)
# .. callbacks
plt.show() # you may use plt.show(block=True) when this is run in interactive mode
print(slider.val)
澄清后编辑:
您是 运行ning spyder 并使用其中的 IPython 控制台。这有几个含义。
- 您需要关闭交互模式,
plt.ioff()
- 您需要为 matplotlib 停用 "support"
然后下面的代码 运行 没问题,只在图形关闭后打印值。
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider, Button
plt.ioff()
im3d = np.random.rand(20,20,10)
class IndexTracker(object):
def __init__(self, ax, data3d, title):
self.ax = ax
ax.set_title(title)
self.data3d = data3d
rows, cols, self.slices = data3d.shape
self.ind = self.slices//2
self.im = ax.imshow(self.data3d[:, :, self.ind])
self.update()
def update(self):
self.im.set_data(self.data3d[:, :, self.ind])
ax.set_ylabel('slice %s' % self.ind)
self.im.axes.figure.canvas.draw()
#
fig = plt.figure(figsize=(18, 8), dpi=80, facecolor='w', edgecolor='b')
ax = fig.add_subplot(1,2,1)
ax2 = fig.add_subplot(1,2,2)
tracker1 = IndexTracker(ax, im3d, 'Select First Image')
tracker2 = IndexTracker(ax2, im3d, 'Select Last Image')
def slider_changed(value, tracker):
numb = int(round(value))
tracker.ind = numb
tracker.update()
max0 = im3d.shape[2] -1
ax_start = fig.add_axes([0.1, 0.85, 0.35, 0.03])
sl_start = Slider(ax_start, 'START', 0, max0, valinit=0, valfmt="%i")
ax_end = fig.add_axes([0.6, 0.85, 0.35, 0.03])
sl_end = Slider(ax_end, 'END', 0, max0, valinit=0, valfmt="%i")
def sl_start_changed(val):
slider_changed(sl_start.val,tracker1)
def sl_end_changed(val):
slider_changed(sl_end.val,tracker2)
sl_start.on_changed(sl_start_changed)
sl_end.on_changed(sl_end_changed)
class Index(object):
def close_figure(self, event):
plt.close(fig)
callback = Index()
ax_button = fig.add_axes([0.7, 0.06, 0.15, 0.075])
button = Button(ax_button, 'DONE')
button.on_clicked(callback.close_figure)
fig.canvas.manager.window.raise_()
plt.show()
print(sl_start.val, sl_end.val)
或者,您可以 运行 外部命令行中的完整代码,而不需要 plt.ioff()