2012-11-21 7 views
2

matplotlib를 사용하여 이미지 시리즈에서 선택한 슬라이스를 대화식으로 삭제하는 작은 코드를 작성하려고합니다. 나는 'update'버튼이 선택되었을 때 삭제 될 인덱스의 수를 저장하는 'delete'버튼을 만들었습니다. 그러나 현재는 슬라이더 위젯 범위를 재설정 할 수 없습니다. 즉, 삭제 된 슬라이스 수를 valmax에서 제거 할 수 없습니다. 이 문제의 파이썬 솔루션은 무엇입니까?Matplotlib Updating slider widget range

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() 

답변

1

슬라이더가 범위 (api)를 업데이트 할 수있는 방법이없는 것 같습니다 :

여기 내 코드입니다. I (나는 frame 대신 전역 변수의 데이터 속성 변수 인스턴스 만든 것, 슬라이더의 범위 [0,1]로 설정하고, 어느 정도 관련 메모에서

frame = int(self.nframes * value) 

하 제안 tutorial). 만약 축의 제한을 설정할 필요가 축 슬라이더의 변화를 반영하기 위하여는 분 직접 그것의 최대 값을 설정할 수있는 슬라이더 범위를 업데이트하기 위해

+0

답장을 보내 주셔서 감사합니다. 나는 여전히 파이썬을 이해하고 즐기고 있지만 즐기고있다. 인스턴스 변수가 로컬 변수입니까? main 함수 내에서 frame = 0으로 설정 했습니까? – moadeep

+1

'self.frame'은 값이 클래스의 인스턴스에 묶여있는 변수입니다. (용어를 엉망으로 만들었고, '데이터 속성'이라고 말해야합니다.) http://docs.python.org/2/tutorial/classes.html#instance-objects를 참조하십시오. – tacaswell

0

,

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()