Skip to content

perf(shapes): vectorize datashader polygon scaling#740

Merged
timtreis merged 1 commit into
mainfrom
perf/scale-geometries-cleanup
Jun 22, 2026
Merged

perf(shapes): vectorize datashader polygon scaling#740
timtreis merged 1 commit into
mainfrom
perf/scale-geometries-cleanup

Conversation

@timtreis

@timtreis timtreis commented Jun 22, 2026

Copy link
Copy Markdown
Member

Vectorize datashader polygon/multipolygon scaling: the old per-geometry affinity.scale loop is pure Python and dominates large renders (~60% of a 100k-polygon render). _scale_geometries scales all coordinates about each geometry's bounding-box centre (affinity.scale's default origin) in one get_coordinates/set_coordinates pass. Only fires for scale != 1.0.

Byte-identical to affinity.scale (asymmetric shapes, multipolygons, holes; main-vs-branch render diff_px=0). Trades peak memory for speed (scale=0.6):

shape n speed peak memory
polygons 200k 15.0× 5.8× (21→123 MB)
multipolygons 200k 7.4× 11.1× (21→235 MB)

Re-land of #738 (reverted in #739); helper lives in _geometry.py next to _scale_path_around_centroid.

Re-lands #738 (accidentally merged then reverted in #739), with the code-review
cleanups applied: the helper lives in _geometry.py next to its matplotlib-Path
twin _scale_path_around_centroid (module-level shapely import, no local one).

The datashader path scaled polygons with a per-geometry affinity.scale loop — a
pure-Python loop that dominates large polygon renders (~60% of a 100k-polygon
render). _scale_geometries scales every coordinate about each geometry's
bounding-box centre (affinity.scale's default origin) in one vectorized
get_coordinates/set_coordinates pass. Byte-identical to affinity.scale incl.
asymmetric shapes, multipolygons and holes (verified main-vs-branch diff_px=0;
unit test at 1e-9); ~12x polygons / ~6.5x multipolygons. Only fires for scale != 1.0.
@codecov-commenter

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 79.33%. Comparing base (1af9398) to head (4fe6add).

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #740      +/-   ##
==========================================
+ Coverage   79.29%   79.33%   +0.03%     
==========================================
  Files          17       17              
  Lines        4599     4603       +4     
  Branches     1030     1030              
==========================================
+ Hits         3647     3652       +5     
  Misses        602      602              
+ Partials      350      349       -1     
Files with missing lines Coverage Δ
src/spatialdata_plot/pl/_geometry.py 80.18% <100.00%> (+0.45%) ⬆️
src/spatialdata_plot/pl/render.py 89.62% <100.00%> (-0.02%) ⬇️

... and 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@timtreis timtreis merged commit e454700 into main Jun 22, 2026
7 of 8 checks passed
@timtreis timtreis changed the title perf(shapes): vectorize datashader polygon scaling (re-land of #738) perf(shapes): vectorize datashader polygon scaling Jun 22, 2026
@timtreis timtreis deleted the perf/scale-geometries-cleanup branch June 22, 2026 09:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants