netscout-mthorn opened a new pull request, #21646:
URL: https://github.com/apache/echarts/pull/21646

   ## Brief Information
   
   This pull request is in the type of:
   
   - [ ] bug fixing
   - [x] new feature
   - [ ] others
   
   
   
   ### What does this PR do?
   
   Adds a `logMapping: 'asinh' | 'symlog'` option to the `log` axis type, 
enabling logarithmic
   axes that correctly handle zero and negative values via symmetric transform 
functions.
   
   ### Fixed issues
   
   - #15558: Display negative value in Logarithmic axis
   - #17459: [Feature] Support negative and zero when axis type is 'log'
   
   ## Details
   
   ### Before: What was the problem?
   
   The `log` axis type requires all data values to be strictly positive. Zero 
and negative
   values are filtered out by `getFilter()` and rejected by `setExtent()`. 
There is no
   supported way to display mixed-sign data or data containing zero on a 
logarithmic axis.
   
   Previous attempts (#16547, #20872) addressed this by auto-detecting negative 
data or
   implementing a "negative log" transform, but reviewer `100pah` identified 
these
   approaches as fragile and mathematically unsound for the general case
   (see the "Summary of Reviewer Feedback" section in #20872).
   
   ### After: How does it behave after the fixing?
   A new axis option `logMapping` is added to the `log` axis type:
   
   ```ts
   yAxis: {
       type: 'log',
       logBase: 10,          // unchanged, controls tick spacing
       logMapping: 'asinh'   // new, enables the asinh transform (or 'symlog')
   }
   ```
   
   When `logMapping: 'asinh'` is set:
   
   - The forward transform uses `asinh(x / a0) * a0` instead of `log_b(x)`, 
where `a0`
     is controlled by `logLinearWidth` (default `1`, matching d3/matplotlib 
conventions).
     This function is defined for all real numbers, passes smoothly through 
zero, and
     behaves like `log` for large `|x|`.
   - Zero and negative data values are accepted and rendered correctly.
   - The axis is odd-symmetric: `f(-x) = -f(x)`, so negative data produces a 
mirrored
     log-like axis.
   - Tick marks at `0, +-a0, +-b*a0, +-b^2*a0, ...` (where `a0 = 
logLinearWidth`, `b = logBase`) appear naturally.
   
   When `logMapping: 'symlog'` is set:
   
   - The forward transform uses `sign(x) * ln(1 + |x|/C)`, where `C` is the 
linear
     threshold controlled by `logLinearWidth` (same option, default `1`). This
     is the symlog transform familiar to matplotlib and d3 users.
   - Behaviour is otherwise identical to `'asinh'`: zero and negatives accepted,
     odd-symmetric axis, tick marks at `0, +-C, +-b*C, ...`
   
   When `logMapping` is absent or `'none'`, behaviour is **identical to 
before**. The
   standard log transform is used and all existing constraints apply. There are 
no
   breaking changes.
   
   <img width="951" height="344" alt="Screenshot 2026-06-10 at 9 43 53 AM" 
src="https://github.com/user-attachments/assets/ae8041d0-c3be-411f-b79a-5b9e21fdb080";
 />
   
   ## Document Info
   
   One of the following should be checked.
   
   - [ ] This PR doesn't relate to document changes
   - [x] The document should be updated later
   - [ ] The document changes have been made in apache/echarts-doc#xxx
   
   ## Misc
   
   ### Security Checking
   
   - [ ] This PR uses security-sensitive Web APIs.
   
   ### ZRender Changes
   
   - [ ] This PR depends on ZRender changes (ecomfe/zrender#xxx).
   
   ### Related test cases or examples to use the new APIs
   
   - `test/log-mapping.html`: visual test covering positive-only, mixed-sign, 
all-negative,
     logBase:2, and symlog comparison scenarios
   - `test/ut/spec/scale/log.test.ts`: Jest unit tests covering standard log
     (regression), `logMapping: 'asinh'`, and `logMapping: 'symlog'` behaviour
   
   ### Merging options
   
   - [x] Please squash the commits into a single one when merging.
   
   ### Other information
   
   **Design note: `asinh` and `symlog`**
   
   Both transforms are provided as equals. Neither is preferred over the other 
in this PR.
   The right choice depends on the user's data and familiarity with each 
transform.
   
   `asinh` (`asinh(x / a0) * a0`):
   - Infinitely differentiable everywhere including zero, with no curvature 
kink.
   - Named in the ECharts `scaleMapper.ts` source as an anticipated extension.
   - `Math.asinh` / `Math.sinh` are ES2015 built-ins with no polyfill needed.
   
   `symlog` (`sign(x) * ln(1 + |x|/C)`):
   - Familiar to users of matplotlib's `SymmetricalLogScale` and d3's 
`scaleSymlog`.
   - The linear threshold `C` (`logLinearWidth`) has a more concrete geometric 
meaning
     than `a0` for users who want explicit control over the transition point.
   - `Math.log1p` / `Math.expm1` are ES2015 built-ins with no polyfill needed.
   
   Both reviewer `100pah` (in the review of #20872) and matplotlib name both 
transforms
   as valid solutions to the negative/zero log problem. Both use the same 
`logLinearWidth`
   parameter and the same tick generation strategy.
   
   **Design note: `logMapping: 'none'` as the explicit default**
   
   The type is `'none' | 'asinh' | 'symlog'` rather than just `'asinh' | 
'symlog' | undefined`. This follows
   the ECharts convention for mode-selection options: `sampling` uses `'none'` 
for its
   default, as does `graph.layout`.
   **Relationship to #20872**
   
   This PR supersedes #20872. It takes a different approach (opt-in 
`logMapping` option
   with `asinh` and `symlog` transforms) rather than the `negative log` method 
implemented
   there, in direct response to `100pah`'s review feedback on that PR.
   
   ### Files changed
   
   - `src/coord/axisCommonTypes.ts`
   - `src/coord/axisDefault.ts`
   - `src/coord/axisHelper.ts`
   - `src/coord/axisNiceTicks.ts`
   - `src/coord/axisAlignTicks.ts`
   - `src/scale/Log.ts`
   - `src/scale/helper.ts`
   - `test/ut/spec/scale/log.test.ts` (new)
   - `test/log-mapping.html` (new)


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to