如何使用多线程重置 ipywidgets?

问题描述 投票:0回答:0

使用 Google Colab,我正在尝试创建一个交互式小部件,它可以让我在音频文件中选择一个位置,然后同时播放它并同时绘制波形。多亏了无数个问题的例子,我快到了。但是,我坚持以下几点:第一次运行时,它按预期工作 - 它播放音频并为波形设置动画(耶!)。当我调整开始滑块时不起作用。我想要它做的是清除图形并开始绘制新波形。它没有。不过,它确实会在新的开始时间播放音频。所以,很明显,我很接近。但我能做什么呢?我认为它与多线程连接有关,但如果我不加入它,那么它甚至不会为初始设置设置动画。

import matplotlib.pyplot as plt
import numpy as np

from IPython.display import Audio, display
from ipywidgets import interactive,  widgets

import threading
import time

from PIL import Image
from io import StringIO

def note(frequency, length, amplitude=1, sample_rate=44100):
    time_points = np.linspace(0, length, length*sample_rate)
    data = np.sin(2*np.pi*frequency*time_points)
    data = amplitude*data
    return data

song_rate = 22050
song_amp =  np.concatenate(
             (note(440.00, 1, 1.0, song_rate),  #A 
              note(493.88, 1, 0.9, song_rate),  #B 
              note(523.25, 1, 0.8, song_rate),  #C
              note(587.33, 1, 0.7, song_rate),  #D 
              note(659.25, 1, 0.6, song_rate),  #E
              note(698.46, 1, 0.5, song_rate),  #F
              note(783.99, 1, 0.4, song_rate),  #G
              ),             
             axis=-1)

animation_frames_per_secs = 1

mygraph = display(display_id=True)
mythread = None

def animate_images(start_secs, width_secs, duration_secs):
    for tick in range(duration_secs*animation_frames_per_secs):
      curr_time = start_secs + (tick*1.0/animation_frames_per_secs)
      make_image(curr_time, width_secs)
      time.sleep(1.0/animation_frames_per_secs)

def make_image(current_time, time_window):
    global song_amp, song_rate, mythread, mygraph  
    fig = plt.figure(figsize = (10, 2))
    ax1 = fig.add_subplot(111)
    ax1.set_ylim(-1, 1)
    x = np.arange(int(current_time*song_rate),
                      int((current_time+time_window)*song_rate),
                      1)/song_rate
    y = song_amp[int(current_time*song_rate):int((current_time+time_window)*song_rate)]
    ax1.plot(x,y)
    buffer = StringIO()
    canvas = plt.get_current_fig_manager().canvas
    canvas.draw()
    image = Image.frombytes('RGB', canvas.get_width_height(), canvas.tostring_rgb())
    plt.close()
    mygraph.update(image)

def play_music(start_secs=0, width_secs=3.0/440, duration_secs=2):
    global song_amp, song_rate, mythread, mygraph
    s = song_amp[start_secs*song_rate:(start_secs + duration_secs)*song_rate]
    display(Audio(data=s, rate=song_rate,autoplay=True))
    mythread =  threading.Thread(target=animate_images, args=(start_secs,width_secs, duration_secs))
    mythread.start()
    return None

v = interactive(play_music, start_secs=(0, 14), width_secs=(0.001,1.0), duration_secs=(1,13))
display(v)
mythread.join()
ipython python-multithreading ipywidgets
© www.soinside.com 2019 - 2024. All rights reserved.