Skip to content

Fix quiver and streamplot geometry [mpl compatibility] - #339

Merged
Alek99 merged 8 commits into
agent/pie-annotation-round2from
agent/quiver-display-invariants
Jul 27, 2026
Merged

Fix quiver and streamplot geometry [mpl compatibility]#339
Alek99 merged 8 commits into
agent/pie-annotation-round2from
agent/quiver-display-invariants

Conversation

@sselvakumaran

@sselvakumaran sselvakumaran commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Summary

This groups the selected-gallery vector-field fixes:

  • resolve quiver angles, scale, units, width, and keys against the live axes/figure transform and DPI;
  • distinguish display-relative angles="uv" from data-transform angles="xy", including inverted axes;
  • preserve streamplot trajectory identity and place num_arrows by cumulative trajectory distance;
  • retain masked topology and per-segment/per-arrow linewidths;
  • reject incomplete native cell fragments below Matplotlib's minlength and continue automatic seeding through the bounded adaptive integrator.

Why

The prior quiver path validated Matplotlib options but ignored several of them during geometry generation, used a nominal 500×370 axes, and interpreted quiver keys in data space. The native streamplot path flattened trajectories into short segments, guessed arrow counts globally, and quantized linewidths; exact arrow placement exposed that many native fragments were below Matplotlib's minimum trajectory length.

Visual comparisons

Review-only images from immutable evidence commit 2ee619a; they are not part of this PR diff.

Quiver gallery

Matplotlib / XY before / XY after

Streamplot gallery

Matplotlib / XY before / XY after

The streamplot after image restores continuous bodies in the varying-color, varying-linewidth, multi-arrow, and masked panels instead of rendering mostly isolated arrowheads.

Verification

  • 30 combined focused vector-field tests passed;
  • 1 separate Matplotlib-backed reference-semantics test passed;
  • exact quiver_demo.py, quiver_simple_demo.py, and plot_streamplot.py produced 18 PNG and 18 SVG outputs with no execution/count failures;
  • all pre-commit hooks, Ruff, formatting, and SVG validation passed.

Remaining approximations

  • quiver uses a three-stroke arrow glyph rather than Matplotlib's filled polygon and short-vector head rules;
  • streamplot produces slightly different trajectory density/sampling and triangle-mesh arrowheads;
  • when the current native occupancy output consists only of incomplete fragments, pyplot uses the existing bounded adaptive Python integrator rather than changing the Rust kernel in this PR.

These differences remain visibly readable and technically bounded, but automated pixel metrics remain divergent. No local browser, native build, or full suite was run under the low-resource verification policy; GitHub CI is the final integrated gate.

Summary by CodeRabbit

  • New Features
    • Improved quiver/quiverkey rendering to better match Matplotlib for angles, scaling/units, axis inversion, figure resizing, and autoscaling.
    • Enhanced native streamplot handling with more faithful trajectory reconstruction, arrow selection/placement, and per-segment linewidth/color sampling.
    • Quiver rendering now defers geometry materialization to use the live axes/figure geometry before chart construction.
  • Documentation
    • Expanded compatibility notes and changelog entries covering quiver/quiverkey and streamplot invariants.
  • Tests
    • Added display invariants tests for quiver/quiverkey and native streamplot coverage; updated expectations for streamplot segment output.

@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 3a38b8b7-99f2-4df2-97a1-bf108a2a8127

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Quiver and quiverkey geometry now materialize from live axes and figure transforms. Streamplot adapts native trajectories with Matplotlib-compatible filtering, arrow placement, and sampled styling. Tests and compatibility documentation cover the updated vector-field behavior.

Changes

Vector-field rendering

Layer / File(s) Summary
Deferred quiver and quiverkey geometry
python/xy/pyplot/_plot_types.py, python/xy/pyplot/_axes.py, tests/pyplot/test_quiver_display_invariants.py, tests/pyplot/test_p3_option_contracts.py, spec/matplotlib/compat-changelog.md
Quiver and quiverkey inputs are stored as deferred recipes and materialized using live axes, view, subplot, and DPI geometry; autoscaling handles arrows and keys separately.
Native streamplot trajectory handling
python/xy/pyplot/_plot_types.py, tests/pyplot/test_axes_charts.py, tests/pyplot/test_p3_option_contracts.py, tests/pyplot/test_launch_compat.py, spec/matplotlib/compat.md, spec/matplotlib/shim-todo.md, spec/matplotlib/compat-changelog.md
Native streamline fragments are reconstructed, minlength-filtered, and optionally replaced by adaptive integration; arrows use cumulative-distance selection, midpoint placement, and per-segment widths and colors.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Axes
  participant QuiverRecipe
  participant LiveTransforms
  Axes->>QuiverRecipe: store vector and key parameters
  Axes->>LiveTransforms: request current axes bbox, view, and DPI
  LiveTransforms-->>QuiverRecipe: provide display-space metrics
  QuiverRecipe-->>Axes: materialize segments, widths, and labels
Loading
sequenceDiagram
  participant streamplot
  participant kernels.streamlines
  participant AdaptiveIntegrator
  streamplot->>kernels.streamlines: submit normalized velocity fields
  kernels.streamlines-->>streamplot: return native trajectory fragments
  streamplot->>AdaptiveIntegrator: integrate when fragments fail minlength
  AdaptiveIntegrator-->>streamplot: return renderable trajectories
Loading

Suggested reviewers: farhanaliraza

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 31.82% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main changes: quiver and streamplot geometry fixes for Matplotlib compatibility.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch agent/quiver-display-invariants

Comment @coderabbitai help to get the list of available commands.

@codspeed-hq

codspeed-hq Bot commented Jul 27, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 103 untouched benchmarks
⏩ 2 skipped benchmarks1


Comparing agent/quiver-display-invariants (b3710ca) with agent/pie-annotation-round2 (c853f94)

Open in CodSpeed

Footnotes

  1. 2 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (2)
spec/matplotlib/compat-changelog.md (1)

30-36: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Native streamplot bullet lands under the older 2026-07-24 heading.

These trajectory/minlength/arrow-placement changes ship with the same work as the new "Quiver display-space invariants — 2026-07-26" section above. Filing them under the earlier date makes the changelog read as if they were released then. Consider moving this bullet into the 2026-07-26 section.

As per coding guidelines, "Keep the entire spec/ directory current with every relevant code, configuration, build, and release change".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@spec/matplotlib/compat-changelog.md` around lines 30 - 36, Move the “Native
streamplot output” bullet from the 2026-07-24 section into the newer “Quiver
display-space invariants — 2026-07-26” changelog section, preserving its text
and ordering the dated entries consistently.

Source: Coding guidelines

tests/pyplot/test_quiver_display_invariants.py (1)

236-291: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider covering the remaining coordinates branches.

_materialize_quiver_geometry grew four coordinate paths (axes, figure, inches, data) plus a log-scale conversion path (_quiver_render_to_raw), but only axes and figure are exercised here. A case each for coordinates="data"/"inches" and one quiver on a log axis would lock the inversion helpers.

As per path instructions, "Enforce pyplot compatibility and boundaries using the corpus and boundary tests".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/pyplot/test_quiver_display_invariants.py` around lines 236 - 291, Add
tests alongside the existing quiverkey coordinate tests to cover the remaining
_materialize_quiver_geometry branches: verify quiverkey placement with
coordinates="data" and coordinates="inches", and add a quiver on a log-scaled
axis that exercises _quiver_render_to_raw. Assert the resulting geometry against
the expected transformed positions, preserving the existing axes and figure
coverage.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@python/xy/pyplot/_plot_types.py`:
- Around line 5099-5121: Synchronize segment colors with geometry in the
_vector_field materialization path by applying the _quiver_valid mask returned
by _quiver_segment_arrays to the colormapped color values before repeating each
color for three segments. Preserve the existing author-time validity filtering
while ensuring arrows removed by the display-space length check contribute no
color entries.

In `@spec/matplotlib/shim-todo.md`:
- Around line 359-361: Update the checked-off quiver bullet in
spec/matplotlib/shim-todo.md to remove the claim of supported norm, z-order, and
scalar-mappable behavior, and match the streamplot bullet’s wording by
explicitly stating that these options fail loudly. Keep the other verified
quiver capabilities unchanged.

In `@tests/pyplot/test_axes_charts.py`:
- Around line 533-537: Strengthen the arrow assertion in the test around
ax._entries so it requires arrow_entry["args"][0] to contain at least one
element in addition to having an even length. Preserve the existing even-count
validation.

---

Nitpick comments:
In `@spec/matplotlib/compat-changelog.md`:
- Around line 30-36: Move the “Native streamplot output” bullet from the
2026-07-24 section into the newer “Quiver display-space invariants — 2026-07-26”
changelog section, preserving its text and ordering the dated entries
consistently.

In `@tests/pyplot/test_quiver_display_invariants.py`:
- Around line 236-291: Add tests alongside the existing quiverkey coordinate
tests to cover the remaining _materialize_quiver_geometry branches: verify
quiverkey placement with coordinates="data" and coordinates="inches", and add a
quiver on a log-scaled axis that exercises _quiver_render_to_raw. Assert the
resulting geometry against the expected transformed positions, preserving the
existing axes and figure coverage.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 94b5fd9d-ed2c-4ca3-b168-44a18ffd19a5

📥 Commits

Reviewing files that changed from the base of the PR and between a2ac10e and 6c748bf.

📒 Files selected for processing (8)
  • python/xy/pyplot/_axes.py
  • python/xy/pyplot/_plot_types.py
  • spec/matplotlib/compat-changelog.md
  • spec/matplotlib/compat.md
  • spec/matplotlib/shim-todo.md
  • tests/pyplot/test_axes_charts.py
  • tests/pyplot/test_p3_option_contracts.py
  • tests/pyplot/test_quiver_display_invariants.py

Comment thread python/xy/pyplot/_plot_types.py
Comment thread spec/matplotlib/shim-todo.md Outdated
Comment thread tests/pyplot/test_axes_charts.py

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/pyplot/test_launch_compat.py`:
- Around line 277-281: Update the assertion logic around has_matplotlib in
test_launch_compat.py so both branches validate the sampled per-segment color
values from entry["kwargs"]["color"] using the same np.ptp(np.asarray(...)) > 0
check. Remove the no-Matplotlib key-presence-only assertion while preserving the
existing Matplotlib-gated structure.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 99c0e9b0-8566-4d7f-bd60-5de561831e90

📥 Commits

Reviewing files that changed from the base of the PR and between 6c748bf and d138a94.

📒 Files selected for processing (1)
  • tests/pyplot/test_launch_compat.py

Comment thread tests/pyplot/test_launch_compat.py Outdated
Alek99 added 3 commits July 27, 2026 06:33
…invariants

# Conflicts:
#	spec/matplotlib/compat-changelog.md
…o agent/quiver-display-invariants

# Conflicts:
#	python/xy/pyplot/_axes.py
@sselvakumaran
sselvakumaran changed the base branch from main to agent/pie-annotation-round2 July 27, 2026 19:31
@Alek99
Alek99 merged commit 8e72282 into agent/pie-annotation-round2 Jul 27, 2026
23 checks passed
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.

2 participants