Python Matplotlib更新滑块小部件范围
我试图编写一小段代码,使用matplotlib以交互方式删除图像系列中的选定切片。我创建了一个“删除”按钮,它存储了在选择“更新”按钮时要删除的一些索引。但是,我目前无法重置滑块小部件的范围,即从valmax中删除已删除切片的数量。这个问题的pythonic解决方案是什么 这是我的密码:Python Matplotlib更新滑块小部件范围,python,widget,matplotlib,slider,Python,Widget,Matplotlib,Slider,我试图编写一小段代码,使用matplotlib以交互方式删除图像系列中的选定切片。我创建了一个“删除”按钮,它存储了在选择“更新”按钮时要删除的一些索引。但是,我目前无法重置滑块小部件的范围,即从valmax中删除已删除切片的数量。这个问题的pythonic解决方案是什么 这是我的密码: import dicom import numpy as np import matplotlib.pyplot as plt from matplotlib.widgets import Slider, Bu
import dicom
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider, Button
frame = 0
#store indices of slices to be deleted
delete_list = []
def main():
data = np.random.rand(16,256,256)
nframes = data.shape[0]
raw_dicom_stack = []
for x in range (nframes):
raw_dicom_stack.append(data[x,:,:])
#yframe = 0
# Visualize it
viewer = VolumeViewer(raw_dicom_stack, nframes)
viewer.show()
class VolumeViewer(object):
def __init__(self, raw_dicom_stack, nframes):
global delete_list
self.raw_dicom_stack = raw_dicom_stack
self.nframes = nframes
self.delete_list = delete_list
# Setup the axes.
self.fig, self.ax = plt.subplots()
self.slider_ax = self.fig.add_axes([0.2, 0.03, 0.65, 0.03])
self.delete_ax = self.fig.add_axes([0.85,0.84,0.1,0.04])
self.update_ax = self.fig.add_axes([0.85,0.78,0.1,0.04])
self.register_ax = self.fig.add_axes([0.85,0.72,0.1,0.04])
self.add_ax = self.fig.add_axes([0.85,0.66,0.1,0.04])
# Make the slider
self.slider = Slider(self.slider_ax, 'Frame', 1, self.nframes,
valinit=1, valfmt='%1d/{}'.format(self.nframes))
self.slider.on_changed(self.update)
#Make the buttons
self.del_button = Button(self.delete_ax, 'Delete')
self.del_button.on_clicked(self.delete)
self.upd_button = Button(self.update_ax, 'Update')
self.upd_button.on_clicked(self.img_update)
self.reg_button = Button(self.register_ax, 'Register')
self.add_button = Button(self.add_ax, "Add")
# Plot the first slice of the image
self.im = self.ax.imshow(np.array(raw_dicom_stack[0]))
def update(self, value):
global frame
frame = int(np.round(value - 1))
# Update the image data
dat = np.array(self.raw_dicom_stack[frame])
self.im.set_data(dat)
# Reset the image scaling bounds (this may not be necessary for you)
self.im.set_clim([dat.min(), dat.max()])
# Redraw the plot
self.fig.canvas.draw()
def delete(self,event):
global frame
global delete_list
delete_list.append(frame)
print 'Frame %s has been added to list of slices to be deleted' %str(frame+1)
print 'Please click update to delete these slices and show updated image series \n'
#Remove duplicates from delete list
def img_update(self,event):
#function deletes image stacks and updates viewer
global delete_list
#Remove duplicates from list and sort into numerical order
delete_list = list(set(delete_list))
delete_list.sort()
#Make sure delete_list is not empty
if not delete_list:
print "Delete list is empty, no slices to delete"
#Loop through delete list in reverse numerical order and remove slices from series
else:
for i in reversed(delete_list):
self.raw_dicom_stack.pop(i)
print 'Slice %i removed from dicom series \n' %(i+1)
#Can now remove contents from delete_list
del delete_list[:]
#Update slider range
self.nframes = len(self.raw_dicom_stack)
def show(self):
plt.show()
if __name__ == '__main__':
main()
滑块似乎无法更新范围()。我建议将滑块的范围设置为[0,1],然后执行以下操作
frame = int(self.nframes * value)
与此相关的一点是,我会将
frame
实例变量作为数据属性,而不是全局变量()。为了更新滑块范围,您可以直接设置其最小值和最大值
slider.valmin = 3
slider.valmax = 7
为了在滑块轴中反映此变化,您需要设置轴的限制
slider.ax.set_xlim(slider.valmin,slider.valmax)
一个完整的示例,其中键入任何数字都会将滑块的valmin
更改为该值
import matplotlib.pyplot as plt
import matplotlib.widgets
fig, (ax,sliderax) = plt.subplots(nrows=2,gridspec_kw=dict(height_ratios=[1,.05]))
ax.plot(range(11))
ax.set_xlim(5,None)
ax.set_title("Type number to set minimum slider value")
def update_range(val):
ax.set_xlim(val,None)
def update_slider(evt):
print(evt.key)
try:
val = int(evt.key)
slider.valmin = val
slider.ax.set_xlim(slider.valmin,None)
if val > slider.val:
slider.val=val
update_range(val)
fig.canvas.draw_idle()
except:
pass
slider=matplotlib.widgets.Slider(sliderax,"xlim",0,10,5)
slider.on_changed(update_range)
fig.canvas.mpl_connect('key_press_event', update_slider)
plt.show()
谢谢你的回复。我仍然在学习python,但我很喜欢它。实例变量是局部变量。我只是在main函数中设置frame=0吗?
self.frame
,一个变量的值绑定到类的实例上(我把术语弄乱了一点,应该说是“数据属性”)。看见