write_image (via kaleido) visually distorts large square heatmaps through aliasing artifacts
@ayjayt がすでに取り組んでいます。
2025年6月3日 から。
評価
この issue はまだ評価されていません。
説明
I have a relatively large matrix that I want to plot usinggraph_objects.Heatmap. The matrix has some structure that should become immediately apparent to the viewer (i.e. it has a constant diagonal and is symmetric). However due to visual artifacts, it looks like these properties are violated in the image produced by write_image (with the kaleido backend, haven't tested orca).
It was difficult to write a simple example script to reproduce these distortions, as variations in both the matrix and output image size can affect the issue significantly (both in intensity and quality). In any case it looks to be an aliasing artifact related to the selection of heatmap cell data that results in a non-bijective map between the heatmap cells and regions within the (vector) output image.
In the script below, one output format is PDF to rule out image compression as a culprit (as there the heatmap appears to be stored as a vector image as its cells remain sharp when zoomed in). However, the issue can be reproduced also when the output format is PNG. I assume that in the vector-output case, the heatmap data is (badly) rescaled like a bitmap image whose pixels are then re-interpreted as an array of square cells, even though those cells then do not match the heatmap/data cells any more.
#!/usr/bin/env python3
import numpy as np
import plotly.graph_objects as go
import plotly.io as pio
resultions = [
# Gives very unequal cell sizes, making the result look like a mosaic:
(200, 400, 400),
# Looks almost correct, but some diagonal elements show bad values:
(400, 400, 400),
]
for n, width, height in resultions:
# Produce a random matrix with key properties (symmetric, constant
# diagonal) matching my actual data.
np.random.seed(1)
A = np.random.random(size=(n, n))
A += A.T
np.fill_diagonal(A, -1)
# Plot the matrix as a square heatmap.
fig = go.Figure()
fig.add_trace(go.Heatmap(z=A))
fig.update_layout(
autosize=False,
width=width,
height=height,
margin=dict(b=0, l=0, r=0, t=0),
yaxis1=dict(scaleanchor="x1", constrain="domain"),
yaxis2=dict(scaleanchor="x2", constrain="domain"),
)
for ext in ("pdf", "png"):
pio.write_image(fig, f"n={n}_{width}x{height}.{ext}")
The outcomes are:
PDF:
n=200_400x400.pdf
n=400_400x400.pdf
PNG (note in the first image that only the heatmap, not the text looks blurred):


- For n = 200 and a layout size of 400x400, many adjacent rows and columns appear to use the same heatmap data. As a result the diagonal looks to be composed of alternating small and large blue cells. On closer inspection you can see that there are two locations where a double row and a double column meet off-diagonal, so that the result looks asymmetric.
- For n = 400 and a layout size of 400x400, the result looks mostly correct but some main diagonal cells are not blue, i.e. they have not been sampled from the data's main diagonal.
Given that my understanding of the problem is correct, I would suggest:
- For bitmap output, use a better interpolation method to scale the heatmap image to its output size.
- For vector output, if possible, do not go the middle route of rescaling a bitmap image. Instead rescale the vector data.
- 主要言語
- Python
- スター
- 504
- フォーク
- 65
- 平均マージ
- 6日 9時間
- マージ済み PR(30日)
- 2
環境構築
このプロジェクトには開発コンテナ、Dockerfile、コントリビューションガイドがありません。まず README を読み、一般的な手順ははじめてのコントリビューションガイドを参照してください。
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
plotly/kaleido のほかの issue
-
Writing to an existing directory whose name has a dot fails with "Invalid format"対応中かも @RaphaelFakhri が 13 日前に担当しました。 オープンbug P3 size: 1
難易度 2/5 1〜3時間 初心者へのやさしさ 35/100
-
Deterministic Rendering Challenges再び着手できるかも @camdecoster が 67 日前に担当しましたが、オープン中のプルリクエストはありません。 オープンenhancement feature P2 size: 5
-
[FEATURE]: Embed custom fonts into vector exports (no system install)対応中かも @camdecoster が 124 日前に担当しました。 オープンenhancement P3 size: 3
-
enhancement feature P3 size: 5
難易度 5/5 1週間以上 初心者へのやさしさ 25/100
-
GlobalKaleidoServer is not thread-safe対応中かも @talleibman が 250 日前に担当しました。 オープン
難易度 4/5 3〜5日 初心者へのやさしさ 48/100
似ている issue
-
area:cli bug difficulty:1
難易度 1/5 1〜3時間 初心者へのやさしさ 87/100
MakazhanAlpamys/Soup#2491 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
microsoft/onnxscript#3155 ·
メンテナーはふだん 4 日以内に返信
-
IFEval nth-paragraph checker reads the wrong paragraph when a blank separator is present対応中かも @chetana1410 が今日担当しました。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 82/100
EleutherAI/lm-evaluation-harness#4530 ·
メンテナーはふだん 1 日以内に返信
-
bug
難易度 2/5 1〜3時間 初心者へのやさしさ 84/100
メンテナーはふだん 1 日以内に返信
-
sv_SE vat_id() has 14 digits: the "16" organisation number prefix is kept対応中かも @kevin9327 が今日担当しました。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
メンテナーはふだん 19 日以内に返信