Skip to content

fix(sql): correct symlog scale invert to be the inverse of apply#1059

Open
devteamaegis wants to merge 1 commit into
uwdata:mainfrom
devteamaegis:fix/symlog-scale-invert
Open

fix(sql): correct symlog scale invert to be the inverse of apply#1059
devteamaegis wants to merge 1 commit into
uwdata:mainfrom
devteamaegis:fix/symlog-scale-invert

Conversation

@devteamaegis

Copy link
Copy Markdown

What's broken

The symlog scale's JS invert is not the inverse of its apply. With apply(x) = sign(x)·log1p(|x|), the correct inverse is sign(x)·(exp(|x|) − C), but the code computed sign(x)·exp(|x| − C) — subtracting the constant inside the exponent. So invert(apply(5)) returns ≈2.207 instead of 5. This corrupts data coordinates wherever scale.invert is used on a symlog scale, e.g. mapping pixel positions back to data values during brushing/zoom (vgplot .../interactors/util/invert.js).

Why it happens

Operator placement error: the constant is subtracted within the exponent (exp(|x|−C)) instead of after exponentiation (exp(|x|)−C). The sibling sqlInvert already used the correct form, so the JS and SQL paths disagreed.

Fix

invert: x => Math.sign(x) * (Math.exp(Math.abs(x)) - constant), matching sqlInvert.

Test

Added a symlog invert is the inverse of apply test asserting invert(apply(x)) ≈ x across several values. Fails before (≈2.207 vs 5), passes after; full sql suite green (254).

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).

@domoritz domoritz 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.

Thank you for the pull request


describe('scaleTransform', () => {
it('symlog invert is the inverse of apply', () => {
const s = scaleTransform<number>({ type: 'symlog' });

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.

Should we test this across constants?

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)), _))

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.

Can we test that the sql and js versions are consistent?

@domoritz

Copy link
Copy Markdown
Member

Let's fix this after #1046 is merged.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants