Skip to content

Changing the symlog function to use arcsinh(x/2). #16639

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from

Conversation

greglucas
Copy link
Contributor

PR Summary

Changing the SymLogTransform math function to be
f(x) = arcsinh(x/2) = ln(x/2 + sqrt(x/2 + 1))

Reasoning: This has a well-defined mathematical function over the entire real number line and a simple inverse. It was mentioned elsewhere that most people using SymLog are using it in a qualitative sense (myself included), and this allows for a nice qualitative plot, along with a reproducible mathematical function underlying it if you want to reproduce the data.

This is a follow-on to a lot of the recent discussion about SymLog changes. See: #16280, #16376, #16391, #16392

I have only updated the SymLogTransform here because of #16457 which I think is the right way to build Norm's, which will inherently change SymLogNorm if it gets put in. This will then allow one place for all of the SymLog math to be consistent.

Before going too far down the path of updating everything, I wanted to push this up and get feedback on whether people think this is a good idea to change the underlying function or not. Pinging @dstansby, @jklymak since you two have been doing most of the recent updates with the SymLog work.

Implications

  • It removes the linscale argument that allows stretching/shrinking the linear region.
  • There is a smooth transition region where the function is neither linear nor logarithmic.
  • Deprecations may get a little messy due to the other SymLog changes taking place in the various versions.

TODOs

  • Update deprecation and warnings
  • Update documentation and API changes
  • Update test_scales SymLog figures

PR Checklist

  • Has Pytest style unit tests
  • Code is Flake 8 compliant
  • New features are documented, with examples if plot related
  • Documentation is sphinx and numpydoc compliant
  • Added an entry to doc/users/next_whats_new/ if major new feature (follow instructions in README.rst there)
  • Documented in doc/api/api_changes.rst if API changed in a backward-incompatible way

@jklymak
Copy link
Member

jklymak commented Mar 3, 2020

@greglucas, I suspect this will just need to be its own scale and norm rather than taking over symlog. You will want to take advantage of @anntzer's PR that allows scales to define norms.

I think you can change the relative "linear" part of the scale by changing the power of the arcsinh.

@greglucas
Copy link
Contributor Author

Honestly, I have no particular desire for this function to be a separate scale/norm. Someone could already implement this using the FuncScale class. The real benefit I see from this being used in SymLog is maintainability and explainability going forward.

I agree that I could do some function stretching and manipulation, but I really think simplicity is the way to go. Stretching it just muddies the waters of "What do you mean the linear region takes up 3 decades of the log region" or was it "b-ades", or... With this implementation, you simply get the quasi-linear region being mapped to +/- 1, and then how many ever b-ades are in your data beyond that maps appropriately to the following integers.

Personally, I just found it a nice simple solution to the SymLog problem rather than stitching together multiple functions and having to map them properly to the different regions.

@tacaswell
Copy link
Member

Attn @Tillsten

We need to get input from users who use this on a regular basis before we make any drastic changes. I have deep concerns about changing tools used in contexts that those making the changes do not fully understand.

@Tillsten
Copy link
Contributor

Tillsten commented Mar 4, 2020

Please don't unnecessary change a scale which is in matplolib for over ten years. The current symlog behavior is very easy grok when looking at a plot with an appropriate scale. The change will break plots in almost all my publications. The same is properly true for other people. While simplicity is fine in some cases, other cases need the customize-ability of the current symlog scale, e.g. being able to set both the linear range and its relative scale. All mentioned issues are mostly documentation issues, the scale itself has less than 200 lines, hence I don't see the big maintenance burden.

<oldmeme>Leave SymlogScale alone!</oldmeme>

@greglucas
Copy link
Contributor Author

Sounds good, @Tillsten, I'm convinced, my apologies for proposing the wholesale math change. Thanks for the speedy responses, everyone!

As a note, the reason I went down this path was because of the issues with differences between the scale/norm. So, I really do think #16457 is important to get in.

@greglucas greglucas closed this Mar 4, 2020
@ImportanceOfBeingErnest
Copy link
Member

The idea of using f(x) = arcsinh(x/2) as scale as an alternative to the inbuilt symlog scale has value. While I totally see the point of not changing the existing scale, it might still be useful to tell users about an alternative. I could think of the
Scales example or the Symlog example as a good place to show people something like

ax.set_yscale("function", functions=(lambda x: np.arcsinh(x/2),  lambda x: 2*np.sinh(x)))

@jklymak
Copy link
Member

jklymak commented Mar 4, 2020

As a note, the reason I went down this path was because of the issues with differences between the scale/norm.

Right, this is beyond a documentation problem....

@rwpenney
Copy link
Contributor

rwpenney commented Sep 26, 2021

I'd like to propose that we revisit this issue, and I have been working on a prototype axis-scale that may address some of the issues raised above.

Like others, I find the mathematical cleanliness of arcsinh much more appealing than the grafting together of linear and logarithmic segments as used by "symlog". As one can see from the attached plot (left-hand pane), even a graph as simple as y=x produces a very obvious gradient-discontinuity on the transition between these linear and logarithmic regions.
symlog-asinh

The right-hand pane in this image shows a prototype solution for an axis-scaling that uses numpy's arcsinh function, which is obviously asymptotically logarithmic for large values, and has a linear trend near zero, but is completely differentiable. The subtle bit, obviously, is getting axis labels to be sensible. The approach I've taken involves various forwards-and-backwards mappings via the sinh function, but produces some reasonably well-spaced axis ticks as well as intuitively rounded tick values.

If others are interested in this functionality, I'll be happy to continue to evolve this prototype into a pull-request that may be of use to a wider community alongside "symlog".

@jklymak
Copy link
Member

jklymak commented Sep 26, 2021

@rwpenney I think a PR with an alternate scale would be OK.

One thing to consider is the transform to allow base-10 from the sinh rather than base-e. I think that most folks who want symbol want the decade behaviour.

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.

6 participants