Как добиться единообразного внешнего вида в разных бэкэндах в HoloViews? - PullRequest
1 голос
/ 10 апреля 2019

Я озадачен тем, как использовать стили HoloViews для настройки графиков и достижения согласованного внешнего вида в бэкэндах.HoloViews объявляется как пакет, который обеспечивает уровень абстракции для нескольких бэкэндов, в частности, Bokeh и Matplotlib, но я полностью терплю неудачу в моих попытках получить графики, сгенерированные с использованием этих бэкэндов, чтобы они выглядели одинаково.Настройки в одном бэкэнде игнорируются другим, и у каждого бэкэнда пропущено множество (большинство) опций форматирования, поэтому необходимо прорваться через абстракцию для вызовов более низкого уровня непосредственно бэкэндам.

Я подозреваю, что я 'Я просто что-то упустил или не смог найти соответствующую документацию.

Например, приведенный ниже код (с использованием настроек, которые не пытаются создать такой же внешний вид, но раскрывают некоторые проблемы) приводит к результатам Matplotlib (правильно), что

  • игнорировать попытку достижения равномерного внешнего вида для точечного цвета точечной диаграммы,
  • игнорировать попытку переопределить цвет полос гистограммы,
  • маргинальные гистограммы с метками осей, которые явно удалены в версиях Bokeh (слева),
  • имеют маргинальные гистограммы, которые не имеют рамок и не имеют вертикальной оси, присутствующей в версии Bokeh,
  • не имеют контроляили настройки стиля осей, и
  • имеют дополнениеНа графике Боке отсутствуют метки всех вспомогательных участков.

Кроме того, существует множество дополнительных настроек для обоих графиков бэкэнда (например, линий сетки, цвета рамки), для которых я не могу найти настройки.

enter image description here

Как настроить стили в HoloViews для достижения полного и согласованного контроля над графиками, созданными Bokeh и Matplotlib?


import numpy as np
import pandas as pd
import holoviews as hv

hv.extension('bokeh', 'matplotlib')

ds = hv.Dataset({'x': np.random.randn(100), 'y1': np.random.randn(100), 'y2': np.random.randn(100), 'y3': np.random.randn(100)}, 
                ['x'],['y1', 'y2', 'y3'])


def mpl_style_hook(plot, element):
    # Settings required here are neither complete, nor do they correspond directly to the backend's naming
    # Where is the correspondence between handles and the backend's names documented?
    pass

def bok_style_hook(plot, element):
    # Such a small set of abstractions is provided, it is almost always necessary to resort to hooks
    plot.state.title.align = "center"    
    plot.handles['xaxis'].axis_label_text_color = 'red'
    plot.handles['yaxis'].axis_label_text_color = 'green'
    plot.handles['xaxis'].axis_label_text_font_style = "normal"
    plot.handles['yaxis'].axis_label_text_font_style = "normal"

# Attempt to set options that apply to both backends; but ignored by Matplotlib
hv.opts.defaults(hv.opts.Scatter(color='green'), hv.opts.Histogram(fill_color='yellow'))

# Explictily set backend to avoid warnings (`backend=` isn't sufficient)
hv.Store.current_backend = 'bokeh'
hv.opts.defaults(
    hv.opts.Scatter(line_color='orange', size=6, fill_alpha=1.0, hooks=[bok_style_hook]),    
    hv.opts.Histogram(fill_color='cyan', fill_alpha=0.9, line_width=1, line_color='gray', hooks=[bok_style_hook]),    
    backend='bokeh')

hv.Store.current_backend = 'matplotlib'
hv.opts.defaults(
    hv.opts.Scatter(hooks=[mpl_style_hook]),
    # Histogram color ignored
    hv.opts.Histogram(color='orange', hooks=[mpl_style_hook]),
    backend='matplotlib')

hv.Store.current_backend = 'bokeh'

s1 = hv.Scatter(ds, 'x', 'y1').opts(hv.opts.Scatter(labelled=[None, 'y'])).hist(num_bins=51, dimension=['x','y1'])
s2 = hv.Scatter(ds, 'x', 'y2').opts(hv.opts.Scatter(labelled=[None, 'y'])).hist(num_bins=51, dimension='y2')
s3 = hv.Scatter(ds, 'x', 'y3').hist(num_bins=51, dimension='y3')
p = (s1 + s2 + s3).opts(hv.opts.Histogram(labelled=[None, None]), hv.opts.Layout(shared_axes=True)).cols(1)

hv.save(p, '_testHV.html', backend='bokeh')
hv.save(p, '_testHV.png', backend='matplotlib')
p

1 Ответ

3 голосов
/ 11 апреля 2019

Я не думаю, что вы ничего не упустили в плане реальной поддержки программного обеспечения;что вам не хватает, так это то, что HoloViews никоим образом не обещает упростить создание графиков от разных бэкэндов до , выглядящих одинаково .Графики предназначены для того, чтобы показывать одни и те же данные примерно одинаково, но бэкэнды работают по-разному, и некоторые из этих различий фактически являются причинами выбора конкретного бэкенда вместо другого.

Есть, конечно, способы, с помощью которых HoloViews могут отобразить из абстрактного понятия стиля в детали того, как это делается в разных бэкэндах, но это удивительно сложно.И очень немногие пользователи просят об этом;большинство выбирают свой любимый бэкэнд и просто используют его, и мы бы предпочли, чтобы наше ограниченное время разработки работало над другими функциями.

При этом, если бэкенды могут создавать аналогичные сюжеты, вы должныв состоянии разработать параметры для использования с HoloViews, которые будут генерировать их в соответствующей форме.Чтобы сделать это, вы должны обработать настройки по одному бэкэнду за раз, а затем применить их к бэкэнду.Например, .opts(line_width=3, backend='bokeh').opts(linewidth=4.5, backend='matplotlib'), с соответствующей опцией, используемой, когда этот объект отображается каждым бэкэндом.Здесь эти два параметра отличаются только одним символом в своих именах, но они работают очень по-разному для такого, казалось бы, простого понятия ширины линии: matplotlib принимает ширину в «точках» (которая зависит от dpi и знания абсолютного размера в дюймах),в то время как боке принимает пиксели в пространстве экрана.Они обе ширины, но не обязательно какой-либо прямой способ сравнить два значения, поскольку это зависит от отдельных настроек, которые вы, возможно, сделали для dpi и fig_size.Вы должны быть в состоянии заставить его выглядеть одинаково с достаточными усилиями, но попытка достичь этого на всех участках за все время является огромной задачей, для достижения которой потребуются отдельное финансирование и разработчики!Тем не менее, это уже намного проще сделать в HoloViews, чем полностью переписать сюжет между Matplotlib и Bokeh, поэтому HoloViews все еще помогает, просто не решая все за вас ...

...