Skip to content

Fix px.imshow drawing the next animation frame in empty facet_col_wrap cells - #5783

Open
breken-ai wants to merge 2 commits into
plotly:mainfrom
breken-ai:fix/imshow-wrap-animation-extra-trace
Open

breken-ai wants to merge 2 commits into
plotly:mainfrom
breken-ai:fix/imshow-wrap-animation-extra-trace

Conversation

@breken-ai

Copy link
Copy Markdown

Link to issue

No existing issue that I could find (searched open and closed issues and PRs for imshow facet_col_wrap and imshow animation facet). I'm happy to open one first if you'd like it tracked separately.

Description of change

px.imshow with both animation_frame and facet_col_wrap draws the wrong image when the facets don't fill the wrapped grid. The loop that builds fig.data kept every trace with index < nrows * ncols. With 5 facets wrapped at 2 columns that is 6, so trace 5, which is facet 0 of the second animation frame, went into the empty sixth cell. Frames only update the first 5 traces, so that extra image stays there for the whole animation, with no facet title. The check now uses nslices_facets, the number of facets in one frame.

Demo

import numpy as np
import plotly.express as px

img = np.arange(2 * 5 * 3 * 4).reshape(2, 5, 3, 4).astype(float)  # 2 frames x 5 facets
fig = px.imshow(img, animation_frame=0, facet_col=1, facet_col_wrap=2)
print(len(fig.data), [(t.name, t.xaxis, t.z[0][0]) for t in fig.data][-1])

Before: 6 ('5', 'x2', 60.0). Frame 1's first facet (values starting at 60) is drawn in the bottom-right cell, which should be empty.
After: 5 ('4', 'x', 48.0). Only frame 0's five facets are drawn, and the sixth cell is empty.

Testing strategy

I added test_animation_and_facet_col_wrap_incomplete_grid to tests/test_optional/test_px/test_imshow.py, covering both binary_string=False (Heatmap) and True (Image). Both cases fail on main (6 traces instead of 5) and pass with this change. The full test_imshow.py passes (92 tests), and ruff format --check is clean.

Additional information (optional)

Without animation there is only one frame's worth of traces, so the old bound had no effect. With facet_row, or facet_col without wrapping, nrows * ncols already equals the facet count, so only the wrapped layout with an incomplete last row was affected. I found this bug and wrote the fix with the help of an AI coding assistant, and I checked the change and the test output myself.

Guidelines

breken-ai and others added 2 commits September 29, 2026 20:48
…p cells

With animation_frame and facet_col_wrap, fig.data kept every trace whose
index was below nrows * ncols. When the facets do not fill the wrapped grid,
the first facet of the second animation frame was drawn in the empty cell
and stayed there during the animation. Only the first frame's facets are
added to fig.data now.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant