fix(points): render solid markers at small sizes - #757
Merged
Conversation
matplotlib's default scatter edge stroke (edgecolors="face", linewidths=1pt) strokes each circle marker with a fixed points-unit ring. When the fill disk goes sub-pixel (tiny `size` at high dpi) only that ring survives, so markers render as hollow "outlined" circles. Set linewidths=0 in _scatter_points so markers stay solid fills at every size; `size` now maps honestly to the fill area. Also removes the same-color ~1pt halo that silently enlarged every marker, so point markers render slightly smaller (visual baselines need regenerating). Fixes #756.
Add an explicit "import matplotlib.collections" instead of relying on pyplot's transitive import, and document that the pixel-level solid-disk appearance is covered by the CI visual baselines while this non-visual test guards the mechanism.
Markers now render as solid fills without the default 1pt edge stroke, so they are slightly smaller and match the datashader backend. Baselines regenerated from the py3.12-stable CI artifact of run 31130393033.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #757 +/- ##
=======================================
Coverage 79.59% 79.60%
=======================================
Files 17 18 +1
Lines 4641 4657 +16
Branches 1029 1032 +3
=======================================
+ Hits 3694 3707 +13
- Misses 598 599 +1
- Partials 349 351 +2
🚀 New features to boost your workflow:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Closes #756.
render_points(method="matplotlib")with a smallsizeat high dpi renders hollow "outlined" circles instead of filled dots.Root cause
_scatter_pointscalledax.scatterwithout edge parameters, so matplotlib's defaults applied:edgecolors="face"andlinewidths=1.0(points). matplotlib strokes the"o"marker path with that fixed points-unit linewidth, and the stroke of a circle is an annulus. When the fill disk goes sub-pixel (tinysize, high dpi) only the ring survives → the marker renders as a hollow outline.Confirmed empirically (saturation grid at
size=0.1, dpi=300): bright outer ring, hollow interior valley, i.e. a donut.Fix
Add
linewidths=0to the sharedax.scattercall in_scatter_points. Markers stay solid fills at every size, andsizenow maps honestly to the fill area (points²), aligning the matplotlib backend with datashader. The change also covers the shapes/labelsas_pointscentroid fast-mode, which shares this primitive.