Обновления многострочного графика в реальном времени при достойной производительности - PullRequest
0 голосов
/ 30 сентября 2019

В настоящее время я использую Bokeh для представления графика multi_line, который имеет несколько статических линий и одну линию, которая обновляется в реальном времени. Это нормально работает только с несколькими линиями, но, в зависимости от разрешения линий (обычно 2000-4000 точек на линию), частота обновления значительно падает при наличии на графике более 50 линий. Загрузка процессора браузером в этот момент довольно высока.

Вот как инициализируется сюжет и запускается обновление в реальном времени:

    figure_opts = dict(plot_width=750,
                        plot_height=750,
                        x_range=(0, dset_size),
                        y_range=(0, np.iinfo(dtype).max),
                        tools='pan,wheel_zoom')

    line_opts = dict(
        line_width=5, line_color='color', line_alpha=0.6,
        hover_line_color='color', hover_line_alpha=1.0,
        source=profile_lines
    )

    profile_plot = figure(**figure_opts)
    profile_plot.toolbar.logo = None
    multi_line_plot = profile_plot.multi_line(xs='x', ys='y', **line_opts)
    profile_plot.xaxis.axis_label = "x"
    profile_plot.yaxis.axis_label = "y"

    ds = multi_line_plot.data_source

    def update_live_plot():
        random_arr = np.random.random_integers(65535 * (i % 100) / (100 + 100 / 4), 65535 * (i % 100 + 1) / 100, (2048))
        profile = random_arr.astype(np.uint16)
        if profile is not None:
            profile_lines["x"][i] = x
            profile_lines["y"][i] = profile
            profile_lines["color"][i] = Category20_20[0]
            ds.data = profile_lines

    doc.add_periodic_callback(update_live_plot, 100)

Есть ли способ сделать этолучше выступать? Можно ли, например, обновить только одну строку, которую нужно обновить, вместо ds.data = profile_lines?

Редактировать: Одна строка, которая должна быть обновлена, должнаобновляться в полном объеме. Т.е. я не транслирую данные на одном конце, но вместо этого у меня есть полный новый набор значений 2000-4000, и я хочу показать их вместо старой live строки. В настоящее время строка live является элементом i в массивах словаря profile_lines.

1 Ответ

1 голос
/ 01 октября 2019

Вам повезло, обновление одной строки всеми новыми элементами при сохранении одинаковой длины - это то, что может быть достигнуто с помощью метода CDS patch. (Потоковая передача здесь не поможет, поскольку потоковая передача до конца CDS для multi_line означает добавление всей новой строки, а другой случай потоковой передачи до конца каждой подстроки вообще не имеет хорошего решения. )

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

source.patch({ 'ys' : [([i, slice(None)], new_y)]})

Это обновит i-ю строку в source.data['ys'], пока new_yимеет ту же длину, что и старая строка.

...