Skip to content

Fix contour labels and colorbar semantics [mpl compatibility] - #341

Merged
Alek99 merged 17 commits into
mainfrom
agent/contour-label-colorbar-compat
Jul 27, 2026
Merged

Fix contour labels and colorbar semantics [mpl compatibility]#341
Alek99 merged 17 commits into
mainfrom
agent/contour-label-colorbar-compat

Conversation

@sselvakumaran

@sselvakumaran sselvakumaran commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Summary

This groups the selected-gallery contour, normalization, and colorbar repairs:

  • join contour paths for one-label-per-component placement, tangent rotation, collision avoidance, manual snapping, inherited styles, and true inline gaps;
  • preserve extend, exact listed-color bands, under/over colors, and contour add_lines overlays;
  • render line-only contour colorbars as unfilled bodies with styled isolines and outlined extension triangles;
  • support multiple colorbars on one host axes without overwriting earlier bars;
  • support logarithmic imshow/pcolormesh colorbars and pcolormesh(rasterized=True);
  • honor explicit colorbar(cax=...), including correct placement without shrinking the source axes;
  • reserve automatic colorbar layout once across static renderers and browser source.

Why

The previous contour label path treated marching-square fragments independently, so labels duplicated, collided, ignored tangents, and did not create real inline gaps. Colorbars lost mappable semantics, overwrote one another, sampled explicit listed bands through a named ramp, and treated line contours as filled ramps. Log-normalized meshes and explicit cax placement were also missing.

Visual comparisons

Review-only images from immutable evidence commit a5d959e; none is part of this PR diff.

Automatic contour labels

Matplotlib / XY before / XY after

Manual contour labels

Matplotlib / XY before / XY after

Line-only contour and separate image colorbars

Matplotlib / XY before / XY after

Exact listed colors and extensions

Matplotlib / XY before / XY after

Logarithmic colorbar

Matplotlib / XY before / XY after

Explicit cax

Matplotlib / XY before / XY after

Verification

  • 208 combined focused tests passed; 3 skipped and 1 standalone-bundle-dependent HTML test deselected;
  • exact contour_demo.py, contourf_demo.py, time_series_histogram.py, and subplots_adjust.py produced 12 PNG and 12 SVG outputs;
  • all reviewed SVG outputs parsed successfully;
  • Ruff and git diff --check passed.

Remaining approximations

  • negative contour dash phase still restarts at native marching-segment boundaries; fully preserving phase requires broader native path stitching;
  • custom listed-band RGB and extremes are exact, but per-band alpha is not retained in colorbar chrome;
  • the selected contourf 2×2 title gap remains tighter than Matplotlib.

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
    • Added log normalization support for heatmaps and colorbars, including correct tick/label placement and under/over handling.
    • Enhanced colorbar placement via explicit axes, with improved padding and layout sizing.
    • Improved contour labeling (collision-aware placement, manual snapping, inline label gaps, rotation behavior) and added line-only contour colorbars with preserved band/extension colors.
  • Bug Fixes
    • Fixed rendering/layout issues for rasterized heatmaps and colorbars across browser/PNG/SVG, including explicit cax behavior and extension color handling.
  • Documentation
    • Updated compatibility docs and docstrings for the new norm="linear"/"log" behavior.

@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@sselvakumaran, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 2 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: b3bab0fa-cfb2-42d3-b11a-8a1f8c51e77e

📥 Commits

Reviewing files that changed from the base of the PR and between 4407886 and eff656b.

📒 Files selected for processing (21)
  • js/src/10_colormaps.ts
  • js/src/50_chartview.ts
  • python/xy/_raster.py
  • python/xy/_svg.py
  • python/xy/_trace.py
  • python/xy/channels.py
  • python/xy/components.py
  • python/xy/marks.py
  • python/xy/pyplot/_artists.py
  • python/xy/pyplot/_axes.py
  • python/xy/pyplot/_colors.py
  • python/xy/pyplot/_mplfig.py
  • python/xy/pyplot/_plot_types.py
  • tests/pyplot/test_axes_charts.py
  • tests/pyplot/test_color_pipeline_fixes.py
  • tests/pyplot/test_contour_label_placement.py
  • tests/pyplot/test_gallery_colorbar_options.py
  • tests/pyplot/test_gallery_log_colorbar_blockers.py
  • tests/pyplot/test_p3_option_contracts.py
  • tests/test_declarative_colorbar.py
  • tests/test_svg_export.py
📝 Walkthrough

Walkthrough

This change advances the wire protocol to v9 and adds logarithmic normalization, contour label placement, line-only and exact-color colorbars, explicit colorbar axes, updated layout behavior, cross-renderer support, compatibility documentation, and regression tests.

Changes

Matplotlib compatibility and rendering

Layer / File(s) Summary
Scalar normalization and mesh rendering
python/xy/pyplot/_colors.py, python/xy/pyplot/_axes.py, python/xy/pyplot/_plot_types.py, python/xy/pyplot/_artists.py, tests/pyplot/test_gallery_log_colorbar_blockers.py, tests/pyplot/test_p3_option_contracts.py
Linear and logarithmic scalar grids are normalized through shared helpers, converted to RGBA when needed, and retain domain, scale, and rasterization metadata.
Connected contour labels
python/xy/pyplot/_plot_types.py, tests/pyplot/test_contour_label_placement.py, tests/pyplot/test_axes_charts.py
Contour segments are joined into paths, labels use screen-space placement and snapping, and inline labels split visible contour geometry.
Colorbar API and layout orchestration
python/xy/pyplot/_mplfig.py, python/xy/pyplot/_axes.py, tests/pyplot/test_contour_label_placement.py, tests/pyplot/test_gallery_log_colorbar_blockers.py, tests/pyplot/test_pdsh_gap_features.py
Colorbars support explicit axes, inherited extensions, contour line overlays, exact band and extension colors, host-backed facades, and automatic layout sizing.
Cross-renderer colorbar output
js/src/50_chartview.ts, python/xy/_raster.py, python/xy/_svg.py
Browser, raster, and SVG renderers implement axes placement, padding, logarithmic ticks, line-only bars, exact bands, and extension geometry.
Protocol and compatibility contracts
js/src/00_header.ts, python/xy/config.py, spec/design/wire-protocol.md, spec/matplotlib/*, python/xy/pyplot/__init__.py
Protocol constants advance from v8 to v9 and documentation records the updated normalization, colorbar, contour, and compatibility behavior.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Axes as Axes.imshow/pcolormesh
  participant Figure as Figure.colorbar
  participant Renderer as SVG/Raster/ChartView renderer
  Axes->>Figure: provide normalized domain and scale metadata
  Figure->>Figure: build colorbar options and placement
  Figure->>Renderer: serialize colorbar bands, ticks, overlays, and extensions
  Renderer-->>Figure: render colorbar output
Loading

Possibly related PRs

  • reflex-dev/xy#280: Modifies the same JavaScript colorbar construction and positioning paths.
  • reflex-dev/xy#325: Modifies the SVG and raster colorbar rendering entry points.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 35.96% 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
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately summarizes the main changes to contour labels and colorbar semantics.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch agent/contour-label-colorbar-compat

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/contour-label-colorbar-compat (eff656b) with main (9fdc236)

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: 5

🧹 Nitpick comments (8)
js/src/50_chartview.ts (1)

2539-2571: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Two identical fraction closures. colorbarFraction (Line 2543) and fractionFor (Line 2569) are byte-identical; keep one so the log/linear mapping can't drift between line markers and ticks.

♻️ Proposed dedupe
-    for (const raw of tickValues) {
+    for (const raw of tickValues) {

(remove the second definition and reuse colorbarFraction at Lines 2579 / 2597)

🤖 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 `@js/src/50_chartview.ts` around lines 2539 - 2571, Remove the duplicate
fractionFor closure and reuse colorbarFraction for all subsequent tick and label
positioning calculations, including the usages near the indicated later lines.
Keep the existing log/linear mapping behavior unchanged.
python/xy/_svg.py (1)

3953-4093: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Avoid round-tripping the formatted width back through float(). Line 4068 stores _num(...) (a formatted string) in line_width and Lines 4070-4071 re-parse it to compute the dash pattern; keep the numeric value separate from its serialized form.

♻️ Proposed tweak
-        line_width = _num(max(0.5, float(line.get("width", 1.0))))
+        width_value = max(0.5, float(line.get("width", 1.0)))
+        line_width = _num(width_value)
         dash = (
-            f' stroke-dasharray="{_num(3.7 * float(line_width))} '
-            f'{_num(1.6 * float(line_width))}"'
+            f' stroke-dasharray="{_num(3.7 * width_value)} {_num(1.6 * width_value)}"'
             if line.get("dash") == "dashed"
             else ""
         )
🤖 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 `@python/xy/_svg.py` around lines 3953 - 4093, Update the line rendering loop
around line_width so the numeric width remains available for dash-pattern
calculations while its _num-formatted string is used only for the SVG
stroke-width attribute. Compute the dash values from the original numeric width,
avoiding any float() conversion of the serialized result; preserve the existing
minimum width behavior and output.
python/xy/pyplot/_mplfig.py (1)

737-747: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicate tick-candidate-selection logic.

This block re-implements the exact same "top-~10 candidates closest to zero" algorithm as the pre-existing elif levels is not None and entry.get("discrete_boundaries") is not None: branch just below (lines 748-761), differing only in the source array. Extracting a small helper (e.g. _select_colorbar_ticks(locations)) would remove the duplication and prevent the two copies from drifting if the heuristic changes later.

♻️ Proposed refactor
+def _select_colorbar_ticks(locations: np.ndarray) -> list[float]:
+    step = max(1, int(np.ceil(len(locations) / 10)))
+    candidates = [locations[offset::step] for offset in range(step)]
+    selected = min(candidates, key=lambda values: np.min(np.abs(values)))
+    zero_tolerance = np.finfo(np.float64).eps * max(1.0, float(np.max(np.abs(locations)))) * 8
+    return [0.0 if abs(float(value)) <= zero_tolerance else float(value) for value in selected]
+
 ...
         if ticks is not None:
             options["ticks"] = [float(value) for value in np.asarray(ticks).reshape(-1)]
         elif line_contour:
-            locations = np.asarray(mappable.levels, dtype=np.float64).reshape(-1)
-            step = max(1, int(np.ceil(len(locations) / 10)))
-            candidates = [locations[offset::step] for offset in range(step)]
-            selected = min(candidates, key=lambda values: np.min(np.abs(values)))
-            zero_tolerance = (
-                np.finfo(np.float64).eps * max(1.0, float(np.max(np.abs(locations)))) * 8
-            )
-            options["ticks"] = [
-                0.0 if abs(float(value)) <= zero_tolerance else float(value) for value in selected
-            ]
+            options["ticks"] = _select_colorbar_ticks(
+                np.asarray(mappable.levels, dtype=np.float64).reshape(-1)
+            )
         elif levels is not None and entry.get("discrete_boundaries") is not None:
-            locations = np.asarray(entry["discrete_boundaries"], dtype=np.float64).reshape(-1)
-            step = max(1, int(np.ceil(len(locations) / 10)))
-            candidates = [locations[offset::step] for offset in range(step)]
-            selected = min(candidates, key=lambda values: np.min(np.abs(values)))
-            zero_tolerance = (
-                np.finfo(np.float64).eps * max(1.0, float(np.max(np.abs(locations)))) * 8
-            )
-            options["ticks"] = [
-                0.0 if abs(float(value)) <= zero_tolerance else float(value) for value in selected
-            ]
+            options["ticks"] = _select_colorbar_ticks(
+                np.asarray(entry["discrete_boundaries"], dtype=np.float64).reshape(-1)
+            )
🤖 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 `@python/xy/pyplot/_mplfig.py` around lines 737 - 747, Extract the shared
“select up to ~10 colorbar ticks closest to zero” algorithm from the
line_contour branch and the following discrete_boundaries branch into a helper
such as _select_colorbar_ticks(locations). Update both branches to call the
helper with their respective source arrays, preserving the existing sampling,
zero-tolerance, and tick-value behavior.
python/xy/pyplot/_axes.py (1)

6286-6299: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Colorbar chrome constants are now duplicated verbatim in four renderers.

_colorbar_outside_room mirrors the exact numbers in _svg.layout() (44/24/62/86/18/38 + 18/16 label) and the raster/JS equivalents. The mirror is correct today, but nothing fails loudly if one side changes. Consider exporting these from a single module (e.g. alongside _svg.layout) and importing them here.

🤖 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 `@python/xy/pyplot/_axes.py` around lines 6286 - 6299, The colorbar sizing
constants in _colorbar_outside_room are duplicated across renderers and can
drift. Define shared exported constants alongside the existing _svg.layout
sizing definitions, then update _colorbar_outside_room and the raster/JS
equivalents to import and reuse them while preserving the current orientation,
placement, padding, and label calculations.
python/xy/pyplot/_colors.py (1)

503-511: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider reusing this extreme() resolver in _axes.py.

Axes.imshow's local extreme() (python/xy/pyplot/_axes.py lines 2599-2611) resolves only cmap._{name} and misses the _rgba_{name} fallback added here, so a real matplotlib.colors.Colormap with set_bad/set_under takes a different path in the has_extremes branch than in scalar_grid_rgba. Exporting this helper (or its lookup) would remove the divergence.

🤖 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 `@python/xy/pyplot/_colors.py` around lines 503 - 511, The local extreme()
resolver in Axes.imshow should reuse the shared resolver from _colors.py so it
also handles _rgba_{name} fallbacks and tuple values consistently. Export the
existing helper or its lookup, update _axes.py’s has_extremes path to call it,
and remove the duplicated local resolution logic while preserving the existing
default handling.
python/xy/pyplot/_plot_types.py (2)

821-825: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

Per-channel interpolation of straight (non-premultiplied) RGBA.

For the log path grid is truecolor RGBA where bad cells carry alpha 0 but arbitrary RGB. Interpolating R/G/B independently of A bleeds the bad cell's RGB into its neighbours as a faint halo. Premultiplying before the interpolation and dividing back afterwards avoids it. Only reachable for shading="gouraud" with masked/non-positive samples, so low priority.

🤖 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 `@python/xy/pyplot/_plot_types.py` around lines 821 - 825, Update the 3D RGBA
branch in _bilinear_grid to premultiply RGB channels by alpha before
interpolation, interpolate alpha alongside them, then unpremultiply the
resulting RGB using a safe zero-alpha guard. Preserve the existing per-channel
stack shape and behavior for non-RGBA inputs.

478-487: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value

Row-wise Python iteration over the segment array.

for xa, ya, xb, yb in segments unboxes every marching-squares segment in Python; on a dense grid with several levels this is the dominant cost of clabel(). Since the keys are just quantized integers, the whole table can be built vectorized (np.rint(segments / tolerance).astype(np.int64)) and only the adjacency dict built in Python. Optional — clabel() is off the default build path.

🤖 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 `@python/xy/pyplot/_plot_types.py` around lines 478 - 487, Update the
segment-processing block around segments to quantize all endpoint coordinates
vectorized with NumPy rather than unboxing rows through Python iteration.
Preserve the existing tolerance-based key behavior and skip degenerate segments
where both endpoint keys match, while limiting Python work to constructing
endpoints, positions, and adjacency from the resulting key arrays.
tests/pyplot/test_gallery_log_colorbar_blockers.py (1)

29-211: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a regression test for clabel() on an axes that already holds another contour.

The suite never places two contour entries on one axes before calling clabel, which is exactly the state that trips the value-based self._entries.index(source) lookup flagged in python/xy/pyplot/_plot_types.py lines 3689-3692. A contourf + contour + clabel case would pin it.

Want me to draft that test?

🤖 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_gallery_log_colorbar_blockers.py` around lines 29 - 211,
The test suite needs coverage for labeling a contour when another contour
already exists on the same axes. Add a regression test near the existing
contourf colorbar test that creates a contourf and then a separate contour on
one axes, calls clabel on the latter, and verifies the labels render or are
associated with the correct contour, exercising the ContourSet.clabel path and
preventing value-based entry lookup failures.
🤖 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/_colors.py`:
- Around line 503-511: Extract the nested extreme resolver from
scalar_grid_rgba.extreme into an exported module-level helper such as
cmap_extreme(cmap, name, default), preserving support for both _under/_over/_bad
and _rgba_under/_rgba_over/_rgba_bad attributes. Update
python/xy/pyplot/_plot_types.py lines 3150-3151 to use this helper for contour
extreme colors; the _colors.py anchor requires the resolver extraction and
export, while the sibling site requires replacing its direct getattr calls.

In `@python/xy/pyplot/_plot_types.py`:
- Around line 3150-3151: Update the colormap extreme lookup near cmap_under and
cmap_over to support matplotlib’s _rgba_under and _rgba_over attributes, while
retaining compatibility with the existing _under and _over spellings. Mirror the
fallback behavior used by scalar_grid_rgba so contour and colorbar rendering
preserve configured cap colors.
- Around line 3689-3692: Replace the value-based list.index and list.remove
calls in the generated-entry update flow with identity-based lookup and removal,
matching the approach used by Axes._remove_entry. Ensure source_index identifies
the exact source object and each generated entry is removed by object identity
before reinserting generated after the source, avoiding equality comparisons
involving NumPy arrays.
- Around line 738-742: In the piece-filtering loop, replace the data-coordinate
np.allclose(a, b) check with a scale-independent check that appends each piece
when piece_stop is greater than piece_start. Keep the existing interpolation and
result tuple construction unchanged.

In `@tests/pyplot/test_gallery_log_colorbar_blockers.py`:
- Around line 22-26: Update the autouse fixture function _clean to annotate its
yield-based return type as Iterator[None] instead of None, adding the necessary
typing import if the module does not already provide it.

---

Nitpick comments:
In `@js/src/50_chartview.ts`:
- Around line 2539-2571: Remove the duplicate fractionFor closure and reuse
colorbarFraction for all subsequent tick and label positioning calculations,
including the usages near the indicated later lines. Keep the existing
log/linear mapping behavior unchanged.

In `@python/xy/_svg.py`:
- Around line 3953-4093: Update the line rendering loop around line_width so the
numeric width remains available for dash-pattern calculations while its
_num-formatted string is used only for the SVG stroke-width attribute. Compute
the dash values from the original numeric width, avoiding any float() conversion
of the serialized result; preserve the existing minimum width behavior and
output.

In `@python/xy/pyplot/_axes.py`:
- Around line 6286-6299: The colorbar sizing constants in _colorbar_outside_room
are duplicated across renderers and can drift. Define shared exported constants
alongside the existing _svg.layout sizing definitions, then update
_colorbar_outside_room and the raster/JS equivalents to import and reuse them
while preserving the current orientation, placement, padding, and label
calculations.

In `@python/xy/pyplot/_colors.py`:
- Around line 503-511: The local extreme() resolver in Axes.imshow should reuse
the shared resolver from _colors.py so it also handles _rgba_{name} fallbacks
and tuple values consistently. Export the existing helper or its lookup, update
_axes.py’s has_extremes path to call it, and remove the duplicated local
resolution logic while preserving the existing default handling.

In `@python/xy/pyplot/_mplfig.py`:
- Around line 737-747: Extract the shared “select up to ~10 colorbar ticks
closest to zero” algorithm from the line_contour branch and the following
discrete_boundaries branch into a helper such as
_select_colorbar_ticks(locations). Update both branches to call the helper with
their respective source arrays, preserving the existing sampling,
zero-tolerance, and tick-value behavior.

In `@python/xy/pyplot/_plot_types.py`:
- Around line 821-825: Update the 3D RGBA branch in _bilinear_grid to
premultiply RGB channels by alpha before interpolation, interpolate alpha
alongside them, then unpremultiply the resulting RGB using a safe zero-alpha
guard. Preserve the existing per-channel stack shape and behavior for non-RGBA
inputs.
- Around line 478-487: Update the segment-processing block around segments to
quantize all endpoint coordinates vectorized with NumPy rather than unboxing
rows through Python iteration. Preserve the existing tolerance-based key
behavior and skip degenerate segments where both endpoint keys match, while
limiting Python work to constructing endpoints, positions, and adjacency from
the resulting key arrays.

In `@tests/pyplot/test_gallery_log_colorbar_blockers.py`:
- Around line 29-211: The test suite needs coverage for labeling a contour when
another contour already exists on the same axes. Add a regression test near the
existing contourf colorbar test that creates a contourf and then a separate
contour on one axes, calls clabel on the latter, and verifies the labels render
or are associated with the correct contour, exercising the ContourSet.clabel
path and preventing value-based entry lookup failures.
🪄 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: b088ae39-b99e-427e-91ae-61b6cd53aa2b

📥 Commits

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

📒 Files selected for processing (19)
  • js/src/00_header.ts
  • js/src/50_chartview.ts
  • python/xy/_raster.py
  • python/xy/_svg.py
  • python/xy/config.py
  • python/xy/pyplot/__init__.py
  • python/xy/pyplot/_artists.py
  • python/xy/pyplot/_axes.py
  • python/xy/pyplot/_colors.py
  • python/xy/pyplot/_mplfig.py
  • python/xy/pyplot/_plot_types.py
  • spec/design/wire-protocol.md
  • spec/matplotlib/compat-changelog.md
  • spec/matplotlib/compat.md
  • tests/pyplot/test_axes_charts.py
  • tests/pyplot/test_contour_label_placement.py
  • tests/pyplot/test_gallery_log_colorbar_blockers.py
  • tests/pyplot/test_p3_option_contracts.py
  • tests/pyplot/test_pdsh_gap_features.py

Comment thread python/xy/pyplot/_colors.py Outdated
Comment thread python/xy/pyplot/_plot_types.py Outdated
Comment thread python/xy/pyplot/_plot_types.py Outdated
Comment thread python/xy/pyplot/_plot_types.py Outdated
Comment thread tests/pyplot/test_gallery_log_colorbar_blockers.py
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.

3 participants