From 91029f39fc059f0cde65ba312e9fb9357a256f2e Mon Sep 17 00:00:00 2001 From: devteamaegis Date: Wed, 17 Jun 2026 15:12:14 -0400 Subject: [PATCH] fix: correct symlog scale invert to be inverse of apply The symlog scaleTransform's JS invert computed sign(x)*exp(|x|-C), subtracting the constant inside the exponent. The correct inverse of apply (sign(x)*log1p(|x|)) is sign(x)*(exp(|x|)-C), matching the existing sqlInvert. Previously invert(apply(5)) returned ~2.207 instead of 5, corrupting data coordinates when inverting symlog-scaled pixel positions (e.g. plot brushing/zoom). --- packages/mosaic/sql/src/transforms/scales.ts | 2 +- packages/mosaic/sql/test/scales.test.ts | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 packages/mosaic/sql/test/scales.test.ts diff --git a/packages/mosaic/sql/src/transforms/scales.ts b/packages/mosaic/sql/src/transforms/scales.ts index 49b9ae9d4..eeed09a71 100644 --- a/packages/mosaic/sql/src/transforms/scales.ts +++ b/packages/mosaic/sql/src/transforms/scales.ts @@ -88,7 +88,7 @@ function scaleSymlog({ constant = 1 } = {}): ScaleTransform { const _ = +constant; return { apply: x => Math.sign(x) * Math.log1p(Math.abs(x)), - invert: x => Math.sign(x) * Math.exp(Math.abs(x) - _), + invert: x => Math.sign(x) * (Math.exp(Math.abs(x)) - _), sqlApply: c => (c = asNode(c), mul(sign(c), ln(add(_, abs(c))))), sqlInvert: c => mul(sign(c), sub(exp(abs(c)), _)) }; diff --git a/packages/mosaic/sql/test/scales.test.ts b/packages/mosaic/sql/test/scales.test.ts new file mode 100644 index 000000000..54c61ffdb --- /dev/null +++ b/packages/mosaic/sql/test/scales.test.ts @@ -0,0 +1,11 @@ +import { expect, describe, it } from 'vitest'; +import { scaleTransform } from '../src/index.js'; + +describe('scaleTransform', () => { + it('symlog invert is the inverse of apply', () => { + const s = scaleTransform({ type: 'symlog' }); + for (const x of [5, 10, 100, -7, 1, 0.5]) { + expect(s.invert(s.apply(x))).toBeCloseTo(x, 9); + } + }); +});