Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

SymmetricalLogLocator adds extra erroneous major ticks due to floating-point precision error #18757

Open
@JS3xton

Description

@JS3xton

Bug summary:

SymmetricalLogLocator appears to suffer a floating-point precision error in calculating the boundaries of the log regions of asymlog plot, which results in the addition of extra major ticks in the linear region of the plot.


Code reproducing the issue:

importnumpyasnpimportmatplotlib.pyplotasplt# v3.2.2x=y=np.linspace(-1e5,1e5,100)plt.plot(x,y)plt.xscale('symlog',linthreshx=1e3,subsx=[2,3,4,5,6,7,8,9])

(OS=Windows 10, Python=3.8.3, Anaconda=2020.07)


Output (with error highlighted in red):


Discussion:

Major ticks generated bySymmetricalLogLocator sometimes include an extra tick in the linear region:

>>>locator=mpl.ticker.SymmetricalLogLocator(linthresh=1e3,base=10)>>>locator.tick_values(vmin=0,vmax=1e6)# array([0.e+00, 1.e+02, 1.e+03, 1.e+04, 1.e+05, 1.e+06])    <-- 1.e+02 is in the linear region

SymmetricalLogLocatorcalculates the inner (towards zero) boundaries of the log regions via the following base-agnostic logarithm:

lo=np.floor(np.log(linthresh)/np.log(base))

However, whenbase=10, some power-of-ten thresholds cause floating-point precision problems:

>>>base=10>>> [np.log(linthresh)/np.log(base)forlinthreshinbase**np.arange(10)]# [0.0, 1.0, 2.0, 2.9999999999999996, 4.0, 5.0, 5.999999999999999, 7.0, 8.0, 8.999999999999998]

With thenp.floor() calculation, this introduces an additional erroneous innermost major tick.


@dstansby proposed a possible fix to a related issue in#14309, which changesnp.floor() tonp.ceil(). This looks like it would work with the precision errors I identified above, which all err towards zero, but it would fail with bases that err away from zero, e.g.,base=5:

>>>base=5>>> [np.log(linthresh)/np.log(base)forlinthreshinbase**np.arange(10)]# [0.0, 1.0, 2.0, 3.0000000000000004, 4.0, 5.0, 6.000000000000001, 7.0, 8.0, 9.0]

Other possible solutions I can think of: (1) rounding tobase within a certain proximity, or (2) adding a special case whenbase=10 whereinnp.log10() is used instead ofnp.log()/np.log(base).

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions


      [8]ページ先頭

      ©2009-2025 Movatter.jp