gpt4 book ai didi

python - 如何破解这个 Bokeh HexTile 图来修复坐标、标签位置和轴?

转载 作者:行者123 更新时间:2023-11-30 21:54:31 30 4
gpt4 key购买 nike

下面是 Bokeh 1.4.0 代码,它尝试绘制带有轴的输入数据帧的 HexTile map ,并尝试在每个十六进制上放置标签。我已经坚持了两天了,阅读 Bokeh 文档、示例和 github 已知问题,SO,Bokeh DiscourseRed Blob Games's superb tutorial on Hexagonal Grids ,并尝试代码。 (我对提出 future 的 Bokeh 问题不太感兴趣,而对已知限制的实用解决方法更感兴趣,以便让我的 map 代码今天正常工作。)图如下,代码在底部。

以下是这些问题,按重要性的粗略递减顺序排列(由于 Bokeh 处理字形的方式,不可能分离根本原因并说出哪个原因导致哪个原因。如果我应用一个比例因子或坐标变换,它会修复一组问题,但破坏了另一个“打地鼠”效果):

  1. 标签放置显然是错误的,但我似乎无法破解 (x,y) 坐标或 (q,r) 坐标的任何变体来工作。 (我尝试了 figure(..., match_aspect=True)) 的组合,我尝试了 1/sqrt(2) 缩放(x,y)坐标,我尝试了 Hextile(... size, scale) 按照 redblobgames 的参数,例如 size = 1/sqrt(3) ~ 0.57735)。
  2. Bokeh 强制原点位于左上角,y 坐标随着向下而增加,但默认轴标签将 y 或 r 显示为负。我发现我仍然必须使用 p.text(q, -r, ... 。我想我必须手动修补自动提供的 yaxis 标签或 TickFormatter 才能为正值。
  3. 我使用np.mgrid生成坐标网格,但我仍然似乎必须从右到左分配 q 坐标: np.mgrid[0:8, (4+1):0:-1] 。尽管如此,无论我做什么,六角形都会从左到右翻转
    • (注意:空“”县是获得所需形状的占位符,因此网格坐标上有 bool 掩码 [counties!='']。这工作正常,我想保持原样)
  4. 六角形的源 (q,r) 坐标是整数,我使用“奇数-r”偏移坐标(不是轴向或六边形坐标)。 无论如何HexTile(..., size, scale)我使用的 args,图中的一个或两个维度都是错误的或被压扁的。或者我是否包括 1/sqrt(2)坐标变换中的因素。
    • 我的 +q 轴是东,我的 +r 轴应该是 120° SSE
  5. 理想情况下,我希望我的原点位于左下角(数学绘图样式,而不是计算机图形)。但 Bokeh 显然不支持这一点,没有它我也可以生活。然而,默认 y 轴标签为负数,同时需要正负坐标的混合,这是令人困惑的。不管怎样,如何以最小的痛苦来自动修复这个问题呢? (手册p.yrange = Range1d(?, ?)?)
  6. Bokeh 将(十六进制)字形附加到绘图的方法是一种很难使用的习惯用法。理想情况下,我只是想在六角形、标签、轴的任何地方引用 (q,r) 坐标。我从来不想看到 (x,y)-坐标出现在轴、标签坐标、刻度线等上,但似乎 Bokeh 不允许。我想你以后必须手动修改轴和刻度。此外,plot<->glyph 接口(interface)不允许您公开 (q,r) <-> (x,y) 坐标变换函数,当然不是双向函数。
  7. 默认轴似乎没有任何访问器来自动查找其当前范围/限制; p.yaxis.start/end除非您指定,否则均为空。结果来自p.yaxis.major_tick_in , p.yaxis.major_tick_out也是错误的,对于这个图,它给出了 x 和 y 的 (2,6),似乎将它们剪裁为 2(?) 的内部倍数。 如何自动获取坐标区的范围?

我当前的情节:

Bad HexTile plot

我的代码:

import pandas as pd
import numpy as np
from math import sqrt
from bokeh.plotting import figure
from bokeh.models import ColumnDataSource
from bokeh.models.glyphs import HexTile
from bokeh.io import show

# Data source is a list of county abbreviations, in (q,r) coords...
counties = np.array([
['TE','DY','AM','DN', ''],
['DL','FM','MN','AH', ''],
['SO','LM','CN','LH', ''],
['MO','RN','LD','WH','MH'],
['GA','OY','KE','D', ''],
['', 'CE','LS','WW', ''],
['LC','TA','KK','CW', ''],
['KY','CR','WF','WX', ''],
])
#counties = counties[::-1] # UNUSED: flip so origin is at bottom-left

# (q,r) Coordinate system is “odd/even-r” horizontal Offset coords
r, q = np.mgrid[0:8, (4+1):0:-1]
q = q[counties!='']
r = r[counties!='']

sqrt3 = sqrt(3)
# Try to transform odd-r (q,r) offset coords -> (x,y). Per Red Blob Games' tutorial.
x = q - (r//2) # this may be slightly dubious
y = r

counties_df = pd.DataFrame({'q': q, 'r': r, 'abbrev': counties[counties!=''], 'x': x, 'y': y })
counties_ds = ColumnDataSource(ColumnDataSource.from_df(counties_df)) # ({'q': q, 'r': r, 'abbrev': counties[counties != '']})

p = figure(tools='save,crosshair') # match_aspect=True?

glyph = HexTile(orientation='pointytop', q='x', r='y', size=0.76, fill_color='#f6f699', line_color='black') # q,r,size,scale=??!?!!? size=0.76 is an empirical hack.
p.add_glyph(counties_ds, glyph)

p.xaxis.minor_tick_line_color = None
p.yaxis.minor_tick_line_color = None

print(f'Axes: x={p.xaxis.major_tick_in}:{p.xaxis.major_tick_out} y={p.yaxis.major_tick_in}:{p.yaxis.major_tick_out}')

# Now can't manage to get the right coords for text labels
p.text(q, -r, text=["(%d, %d)" % (q,r) for (q, r) in zip(q, r)], text_baseline="middle", text_align="center")
# Ideally I ultimately want to fix this and plot `abbrev` column as the text label

show(p)

最佳答案

  1. 有一个 axial_to_cartesian函数只会为您计算六角形中心。然后,您可以以各种方向附加标签并从中锚定。

  2. Bokeh 不会强制原点在任何地方。 Bokeh 使用一种轴到笛卡尔映射,正是 axial_to_cartesian 给出的。 。六角图 block 的位置(以及轴显示的笛卡尔坐标)由此得出。如果您想要不同的刻度,Bokeh 在刻度位置和刻度标签上提供了大量控制点。

  3. 轴向坐标有不止一种约定。 Bokeh 选择了具有“向上和向左”r 轴图 block 的那个,即此处明确显示的那个:

    https://docs.bokeh.org/en/latest/docs/user_guide/plotting.html#hex-tiles

  4. Bokeh 需要从上到左的轴向坐标。您需要将您拥有的任何坐标系转换为该坐标系。对于“挤压”,您需要设置 match_aspect=True 以确保“数据空间”长宽比与“像素空间”长宽比 1-1 匹配。

    或者,如果您不或无法使用自动调整范围,则需要仔细设置绘图大小,并使用 min_border_left 等控制边框大小,以确保边框始终足够大以容纳您拥有的任何刻度标签(这样内部区域就不会调整大小)

  5. 我不太明白这个问题,但无论底层的刻度数据如何,您都可以绝对控制在视觉上显示的刻度。除了内置格式化程序之外,还有 FuncTickFormatter它允许您使用一段 JS 代码片段以任何您想要的方式格式化刻度。 [1](如果您愿意,您还可以控制刻度线的位置。)

    [1] 请注意,CoffeeScript 和 from_py_func 选项均已弃用,并将在下一个 2.0 版本中删除。

  6. 同样,您需要使用 axial_to_cartesian放置除六角形瓷砖以外的任何东西。 Bokeh 中没有其他字形能够理解轴坐标(这就是我们提供转换函数的原因)。

  7. 您误解了 major_tick_inmajor_tick_out 的用途。它们实际上是刻度在图框内部和外部视觉上延伸的距离,以像素为单位

    自动调整范围(使用 DataRange1d)仅在浏览器中的 JavaScript 中计算,这就是为什么开始/结束在“Python”端不可用。如果您需要知道开始/结束,您需要自己显式设置开始/结束。但请注意,match_aspect=True 仅适用于 DataRange1d。如果您手动明确设置开始/结束,Bokeh 会假设您知道自己想要什么,并且会尊重您的要求,无论它对方面有何影响。

关于python - 如何破解这个 Bokeh HexTile 图来修复坐标、标签位置和轴?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59004218/

30 4 0