Skip to content

Add native zero-inclusive symlog axis scale#109

Open
FarhanAliRaza wants to merge 2 commits into
mainfrom
codex/add-zero-inclusive-long-tail-axis-scale
Open

Add native zero-inclusive symlog axis scale#109
FarhanAliRaza wants to merge 2 commits into
mainfrom
codex/add-zero-inclusive-long-tail-axis-scale

Conversation

@FarhanAliRaza

@FarhanAliRaza FarhanAliRaza commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Motivation

  • Long-tailed numeric measures commonly include valid zeros which a log axis cannot represent while a linear axis compresses the tail, so a zero-inclusive long-tail scale (symmetric log / symlog) is needed.
  • The goal is to provide a native axis type that preserves original data-space values for ticks, hover, selection, pan/zoom, density rendering, and payloads without leaking display transforms into application logic.

Description

  • Add symlog as an accepted axis type_ and a constant parameter to x_axis()/y_axis() and Figure.set_axis() to configure the linear region width around zero, including validation of a positive constant. (python/xy/components.py, python/xy/_figure.py)
  • Serialize scale: "symlog" and constant into axis payloads and ensure Figure._axis_spec emits scale/constant while preserving existing semantics for linear/log. (python/xy/_figure.py)
  • Implement symmetric-log transforms in the static PNG/SVG pipeline via _Scale and tick generation that produce ticks in original data units (including zero). (python/xy/_svg.py)
  • Wire symlog through the browser-side code: add symlog branch to axis mapping, implement JS coordinate transform and inverse, propagate a per-axis constant uniform into GLSL, and update shader map/calls so WebGL rendering, density, hit/pick, and interaction layers operate using the symlog transform consistently. (python/xy/static/index.js, python/xy/static/standalone.js)
  • Add documentation for the zero-inclusive long-tail scale and an integration test exercising API, payloads, static transforms, and ticks. (docs/core-concepts/axes-and-scales.md, tests/test_symlog_axis.py)

Testing

  • Ran focused and integrated Python tests: PYTHONPATH=python python -m pytest tests/test_symlog_axis.py -q (8 passed) and PYTHONPATH=python python -m pytest tests/test_figure.py tests/test_svg_export.py tests/test_png_export.py -q (212 passed, 1 skipped), and PYTHONPATH=python python -m pytest tests/test_components.py -q (76 passed).
  • Static JavaScript validation succeeded with node --check python/xy/static/index.js and node --check python/xy/static/standalone.js and git diff --check reported no issues.
  • Browser conformance / screenshot smoke could not be run here because Playwright’s Chromium executable is not installed in this environment (so end-to-end screenshot verification was not executed).

Closes #83

@codspeed-hq

codspeed-hq Bot commented Jul 20, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 94 untouched benchmarks
⏩ 1 skipped benchmark1


Comparing codex/add-zero-inclusive-long-tail-axis-scale (7e6e73c) with main (b283b10)

Open in CodSpeed

Footnotes

  1. 1 benchmark was skipped, so the baseline result was used instead. If it was deleted from the codebase, click here and archive it to remove it from the performance reports.

@FarhanAliRaza

Copy link
Copy Markdown
Contributor Author
image without vs

with
image

@FarhanAliRaza FarhanAliRaza added valid Issue is validated. This pr actually fixes the issue. Needs Code Review. and removed codex labels Jul 20, 2026

@Alek99 Alek99 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Review findings:

  • [P1] js/src/40_gl.js:76-78: symlog is applied after decoding offset-encoded f32 coordinates. With x=[0, 1, 1e12] and constant=1, 0 and 1 collapse to the same decoded value even though symlog should visibly separate them. Encode geometry in scale coordinates or retain sufficient precision before the transform.
  • [P1] js/src/40_gl.js:348: density aggregation remains uniform in raw data space. Clusters at x=1 and x=1000 can land in the same raw grid cell even though they are far apart in symlog display space. Bin/decimate in scale coordinates.
  • [P2] python/xy/_svg.py:2260: static heatmap/density grids are stretched only between transformed endpoints, so internal cells are not symlog-transformed. PNG follows the same pattern.
  • [P2] python/xy/_figure.py:993: scale="symlog" changes renderer semantics but the protocol remains 3; an older client will silently treat it as linear. Bump the protocol and regenerate bundles.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

valid Issue is validated. This pr actually fixes the issue. Needs Code Review.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add a native zero-inclusive long-tail axis scale

2 participants