def scale_time(title='Time scaling', size=(400, 400), animated=False): frames = 50 scale = 2*np.pi m = max(1, scale) + 0.5 t = np.linspace(-m*2, m*2, 256) y = np.sin(2 * np.pi * t) sig1 = Signal(t, y) sig1.remove_view('spans') fig = sig1.get_fig(title=title, size=size, scale='2pi') marker_source = ColumnDataSource({'x':[1, 1], 'y': [0, 1]}) marker_ref = fig.line(x=[1,1], y=[0,1], line_width=2, line_color='purple', line_dash='dashed') marker = fig.line(x='x', y='y', source=marker_source, line_width=2, line_color='purple') label = Label(x=1, y=1, text='1 second marker', render_mode='css') fig.add_layout(label) handle = show(fig, notebook_handle=True) if animated: def gen_marker_frame(frame_value): return {'x': [frame_value, frame_value]} def gen_sig_frame(frame_value): return {'x': t * frame_value} frame_values = np.linspace(1, scale, frames) a1 = FrameAnimation(marker_source, gen_marker_frame, frame_values) a2 = FrameAnimation(sig1.data_source(), gen_sig_frame, frame_values) aset = AnimationSet([a1, a2]) AnimateSets([aset], handle, fps=25).run() else: ones = np.asarray([1, 1]) def update(scale=1): marker_update = { 'x' : ones * scale } signal_update = { 'x' : t * scale } marker_source.data.update(marker_update) sig1.update(signal_update) push_notebook(handle=handle) interact(update, scale=(-1*np.pi, 2*np.pi))