如何在HoloViews的不同后端中实现一致的外观? [英] How do I achieve consistent appearance in different backends in HoloViews?

查看:80
本文介绍了如何在HoloViews的不同后端中实现一致的外观?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对如何使用HoloViews样式自定义图并在后端实现一致外观感到迷惑. HoloViews被标为一个软件包,它为多个后端(尤其是Bokeh和Matplotlib)提供抽象层,但是我完全失败了尝试使使用这些后端生成的图看起来相同.一个后端中的设置会被另一个后端忽略,每个后端都缺少许多(大多数)格式设置选项,因此有必要突破抽象来直接对后端进行较低级别的调用.

I'm mystified by how to use HoloViews styles to customize plots and achieve a consistent appearance across backends. HoloViews is billed as a package that provides an abstraction layer to several backends, notably Bokeh and Matplotlib, but I'm completely failing in my attempts to get plots generated using these backends to look the same. Settings in one backend are ignored by another, and each backend has many (most) formatting options missing, so that it is necessary to break through the abstraction to lower level calls directly the the backends.

我怀疑我只是缺少了一些东西,或者没有找到合适的文档.

I suspect I'm just missing something or have failed to discover the appropriate documentation.

例如,下面的代码(使用的设置不尝试产生相同的外观,但是暴露了一些问题)导致Matplotlib图形(右)显示

The code below for example (using settings that don't attempt to produce the same appearance, but expose some of the issues) results in Matplotlib figures (right) that

  • 忽略为散点图点颜色获得统一外观的尝试,
  • 忽略尝试覆盖直方图条形颜色的尝试,
  • 具有带有在Bokeh版本(左)中明确删除的轴标签的边缘直方图,
  • 具有未框架且缺少散景版本中存在的垂直轴的边缘直方图,
  • 无法控制或自定义轴的样式,并且
  • 散景图上没有其他子图标签.

此外,还有两个我无法为其设置的后端绘图(例如,网格线,框架颜色)还有许多其他自定义设置.

In addition, there are many further customizations to both backend's plots (gridlines, frame color, for example) that I can't find settings for.

如何在HoloViews中设置样式,以实现对Bokeh和Matplotlib生成的图的完全一致的控制?

How do I set styles in HoloViews to achieve full and consistent control over plots produced by Bokeh and 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

推荐答案

在实际的软件支持方面,我认为您不会丢失任何东西.您所缺少的是,HoloViews绝不保证将从不同后端绘制的图简化为相同.这些图旨在以大致相同的方式显示相同的数据,但是每个后端以不同的方式工作,而其中的一些差异实际上是选择该特定后端而不是另一个后端的原因.

I don't think you're missing anything in terms of actual software support; what you're missing is that HoloViews in no way promises to make it simple to make plots from different backends to look the same. The plots are meant to show the same data in roughly the same way, but the backends each work in different ways, and some of those differences are in fact reasons to choose that particular backend over another.

HoloViews当然可以通过多种方式从抽象的样式概念映射到在不同的后端中如何完成操作的细节,但这令人惊讶地棘手.很少有用户要求这样做;大多数人会选择他们喜欢的后端并仅使用它,而宁愿我们将有限的开发时间用于其他功能.

There are certainly ways that HoloViews could map from an abstract notion of styling into the details of how that's done in different backends, but that's surprisingly tricky. And very few users ask for that; most pick their favorite backend and just use it, and would rather we spend our limited development time working on other features.

也就是说,如果后端 可以生成类似的图,则您应该能够计算出与HoloViews一起使用的设置,这些设置将以匹配的形式生成它们.为此,您需要一次设定一个后端的设置,然后在每个后端应用它们.例如. .opts(line_width=3, backend='bokeh').opts(linewidth=4.5, backend='matplotlib'),当每个后端显示该对象时,将使用适当的选项.这两个选项的名称仅相差一个字符,但它们对于看似简单的线宽概念却工作方式却大不相同:matplotlib接受以点"为单位的宽度(取决于dpi并知道以英寸为单位的绝对大小),而bokeh则接受屏幕空间中的像素.它们都是宽度,但不一定有直接比较这两个值的方法,因为这取决于您可能对dpi和fig_size进行的单独设置.您应该能够通过足够的努力使它看起来相似,但是要一直在所有地块上实现这一目标是一项艰巨的任务,需要一些单独的资金和开发人员才能实现!不过,与完全重写Matplotlib和Bokeh本机之间的绘图相比,在HoloViews中执行此操作已经容易得多,因此HoloViews仍然可以提供很多帮助,只是不能为您解决所有问题...

That said, if the backends can produce similar plots, you should be able to work out settings for use with HoloViews that will generate them in matching form. To do this, you'd work out the settings one backend at a time, then apply them per backend. E.g. .opts(line_width=3, backend='bokeh').opts(linewidth=4.5, backend='matplotlib'), with the appropriate option being used when that object is displayed by each backend. Here the two options differ only by one character in their names, but they work very differently for such a seemingly simple concept of line width: matplotlib accepts a width in "points" (which depends on dpi and knowing the absolute size in inches), while bokeh accepts pixels in screen space. They are both widths, but there's not necessarily any direct way to compare the two values, as it depends on separate settings you may have done for dpi and fig_size. You should be able to get it to look similar with enough effort, but trying to achieve that across all plots for all time is a massive task that would need some separate funding and developers to achieve! Still, it's already much easier to do that in HoloViews than it would be to completely rewrite a plot between Matplotlib and Bokeh natively, so HoloViews is still helping a good bit, just not solving everything for you...

这篇关于如何在HoloViews的不同后端中实现一致的外观?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆