Bqplot рендеринг нового бара на каждом шаге анимации вместо перемещения исходного бара - PullRequest
0 голосов
/ 03 апреля 2019

Я пытаюсь анимировать гистограмму в Bqplot.Я хотел бы иметь возможность обновлять значения x и y для столбцов и плавно их регулировать.Код ниже ведет себя так, как и ожидалось для 2 из 3 баров на моем графике, но 3-й бар полностью перерисовывается на каждом временном шаге.

Я изначально пробовал это только с 2 барами.Первый бар вел себя как ожидалось, но второй будет перерисовываться на каждом временном шаге.Я добавил 3-й бар, чтобы попытаться решить проблему.

initialIndex = 0
idxSlider3 = IntSlider(min=0, max=20, step=1, 
    description='Index',value=initialIndex)

''' I want to update the bar chart with this function '''
def update_chart3(change):
    with bar3.hold_sync():
        bar3.x = [idxSlider3.value, 
             idxSlider3.value + 1, 
             idxSlider3.value + 2]
        bar3.y = [idxSlider3.value, idxSlider3.value, idxSlider3.value] 

idxSlider3.observe(update_chart3, 'value')  

fig3 = plt.figure(animation_duration=1000)

bar3 = plt.bar(x=[0, 1, 2], y=[1, 1, 0])

play_button3 = Play(min=0, max=20, step=1, interval=1000, initial_value=0)
jslink((play_button3, 'value'), (idxSlider3, 'value'))

VBox([HBox([idxSlider3, play_button3]), fig3])

Ответы [ 2 ]

0 голосов
/ 12 апреля 2019

Вот способ сделать анимированные «бары» красивыми в x. Это не может быть сделано с барами. Вместо этого я использовал линейные метки - это взлом. Но вы получаете гибкость. И я предпочитаю использовать Bqplot в объектной модели (а не в стиле pyplot).

enter image description here

import bqplot as bq
from ipywidgets import *
import numpy as np

initialIndex = 0
xBar=[0, 2, 4] 
yBar=[1, 1, 0]
zeroY = 0
barWidth = 1

idxSlider3 = IntSlider(min=0, max=20, step=1, 
    description='Index',value=initialIndex)

''' I want to update the bar chart with this function '''
def update_chart3(change):
    xBar = [idxSlider3.value, 
         idxSlider3.value + 2, 
         idxSlider3.value + 4]
    np.random.rand()
    yBar = [idxSlider3.value + np.random.rand()*2, idxSlider3.value + np.random.rand()*2, idxSlider3.value + np.random.rand()*2] 
    xList, yList = getLineCoordsFromBarLike(xBar, yBar)
    lines.x = xList
    lines.y = yList

idxSlider3.observe(update_chart3, 'value')  

x_sc = bq.LinearScale()
y_sc = bq.LinearScale()

x_ax1 = bq.Axis(label='', scale=x_sc, num_ticks = 3)
y_ax1 = bq.Axis(label='', scale=y_sc, orientation='vertical')

def getLineCoordsFromBarLike(xBar, yBar):
    """ Convert of single list of bar coordinates to a 2D array of line coordinates that describe the rectangular shape

    xBar: 1D list of numbers for central x position of bar chart
    yBar: 1D list of numbers for amplitudes of bar chart  (must be same length as xBar)

    retrns x cordinates 2D array, y coordinates 2D array.   
    """
    xList= []
    yList= []
    for num, x in enumerate(xBar):
        y = yBar[num] 
        xList.append([x - barWidth/2, x - barWidth/2, x + barWidth/2, x + barWidth/2,])
        yList.append([zeroY, y, y, zeroY])
    x_ax1.tick_values = xBar 
    return xList, yList

xList, yList = getLineCoordsFromBarLike(xBar, yBar)   

lines = bq.Lines(x=xList, y=yList,
    scales={'x': x_sc, 'y': y_sc},
    colors=['black'], 
    display_legend=True, 
#     tooltip=def_tt,
    stroke_width = .5,
     close_path = True,
     fill = 'inside',
    fill_colors = bq.colorschemes.CATEGORY10 * 10
    )

margins = dict(top=10, bottom=40, left=50, right=30)
fig3 = bq.Figure(marks=[lines], axes=[x_ax1, y_ax1], fig_margin=margins, animation_duration=1000)
fig3.layout.width = '600px'
fig3.layout.height = '600px'

# def_tt = bq.Tooltip(fields=['name',], formats=['',],  labels=['id', ])
play_button3 = Play(min=1, max=20, step=1, interval=1000, initial_value=0)
jslink((play_button3, 'value'), (idxSlider3, 'value'))

VBox([HBox([idxSlider3, play_button3]), fig3])
0 голосов
/ 04 апреля 2019

Когда вы говорите «отрегулировать» плавно, вы хотите, чтобы полосы сдвигались вправо, без перерисовки? Я не думаю, что bqplot так «двигает» бары. Данные для новых баров 1 и 2 уже существуют (так как они были построены как старые бары 2 и 3), поэтому они не перерисовываются. Новые данные бара 3 раньше не существовали, их нужно рисовать с нуля. Это создает видимость «движущихся» баров вокруг.

В качестве другого примера посмотрите, что происходит, когда вы перемещаете стержни на одну единицу, но они расположены на расстоянии двух единиц. Вы должны видеть, что все бары рисуются с нуля каждый раз.

from ipywidgets import *
import bqplot.pyplot as plt

initialIndex = 0
idxSlider3 = IntSlider(min=0, max=20, step=1, 
    description='Index',value=initialIndex)

''' I want to update the bar chart with this function '''
def update_chart3(change):
    with bar3.hold_sync():
        bar3.x = [idxSlider3.value, 
             idxSlider3.value + 2, 
             idxSlider3.value + 4]
        bar3.y = [idxSlider3.value, idxSlider3.value, idxSlider3.value] 

idxSlider3.observe(update_chart3, 'value')  

fig3 = plt.figure(animation_duration=1000)

bar3 = plt.bar(x=[0, 1, 2], y=[1, 1, 0])

play_button3 = Play(min=1, max=20, step=1, interval=1000, initial_value=0)
jslink((play_button3, 'value'), (idxSlider3, 'value'))

VBox([HBox([idxSlider3, play_button3]), fig3])
...