Skip to content

Commit f73f4e5

Browse files
committed
fix(render_points): scope resolved norm to matplotlib, keep datashader autoscaling
d5a811a routed continuous points through _resolve_continuous_norm, but the resolved norm was passed to BOTH backends. For datashader the displayed value is the per-pixel aggregate (count/sum/reduction), whose range differs from the per-point color vector — applying a color-vector-derived vmin/vmax mis-scaled the colorbar and painted empty pixels (purple background) instead of leaving them transparent. Scope the resolved norm to the matplotlib backend (where each point is colored by its own value); datashader keeps the un-scaled fresh_norm so _apply_ds_norm autoscales to the aggregate (honoring any explicit vmin/vmax) — the pre-d5a811a behavior. Reverts the datashader point baselines regenerated in error.
1 parent 17ebd6e commit f73f4e5

14 files changed

Lines changed: 13 additions & 9 deletions

src/spatialdata_plot/pl/render.py

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1415,15 +1415,6 @@ def _render_points(
14151415

14161416
trans, trans_data = _prepare_transformation(sdata.points[element], coordinate_system, ax)
14171417

1418-
# Continuous points resolve their norm through the shared resolver so the fill and colorbar match
1419-
# the shapes/labels treatment (degenerate [0, 1] reset, LogNorm/PowerNorm preserved) instead of
1420-
# letting ax.scatter autoscale a fresh linear norm. Non-continuous keeps the un-scaled fresh norm.
1421-
norm = (
1422-
_resolve_continuous_norm(color_spec.color_vector, render_params.cmap_params)
1423-
if color_spec.is_continuous
1424-
else render_params.cmap_params.fresh_norm()
1425-
)
1426-
14271418
method = render_params.method
14281419

14291420
if render_params.density:
@@ -1435,6 +1426,11 @@ def _render_points(
14351426
_default_reduction: _DsReduction = "sum"
14361427

14371428
if method == "datashader":
1429+
# datashader colors the per-pixel AGGREGATE (count/sum/reduction), whose range differs from
1430+
# the per-point color vector. Pass an un-resolved norm so _apply_ds_norm autoscales to the
1431+
# aggregate (honoring any explicit vmin/vmax) — resolving from the color vector would mis-scale
1432+
# reductions and paint empty pixels.
1433+
norm = render_params.cmap_params.fresh_norm()
14381434
_log_datashader_method(method, render_params.ds_reduction, _default_reduction)
14391435

14401436
# Apply transformations and materialize to pandas immediately so
@@ -1471,6 +1467,14 @@ def _render_points(
14711467
color_spec = color_spec.evolve(source_vector=csv, color_vector=cv)
14721468

14731469
elif method == "matplotlib":
1470+
# matplotlib colors each point by its own value, so resolve the norm (degenerate [0, 1] reset,
1471+
# LogNorm/PowerNorm preserved) to match the shapes/labels treatment instead of letting
1472+
# ax.scatter autoscale a fresh linear norm. Non-continuous keeps the un-scaled fresh norm.
1473+
norm = (
1474+
_resolve_continuous_norm(color_spec.color_vector, render_params.cmap_params)
1475+
if color_spec.is_continuous
1476+
else render_params.cmap_params.fresh_norm()
1477+
)
14741478
# update axis limits if plot was empty before (necessary if datashader comes after)
14751479
update_parameters = not _mpl_ax_contains_elements(ax)
14761480
cax = _scatter_points(
1.44 KB
Loading
-1.49 KB
Loading
-1.85 KB
Loading
1.67 KB
Loading
24 KB
Loading
2.41 KB
Loading
3.21 KB
Loading
617 Bytes
Loading
2.41 KB
Loading

0 commit comments

Comments
 (0)