Skip to content

fix the filtering of non-integer ticks in maxNlocator with *integer = True* #12087

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 2 commits into from

Conversation

dabana
Copy link
Contributor

@dabana dabana commented Sep 11, 2018

Reference to issue #12072

PR Summary

Handling of the integer keyword does not seem right

   *integer*
     If True, ticks will take only integer values, provided
     at least `min_n_ticks` integers are found within the
     view limits.

When True it is supposed to provide only integer values for tick label. Here is the outputs printed out at different steps in the code. We first start by the list of possible tick spacing, self.extended_steps:

self._extended_steps = [ 0.1   0.15  0.2   0.25  0.3   0.4   0.5   0.6   0.8   1.    1.5   2.
  2.5   3.    4.    5.    6.    8.   10.   15.  ]

Then we multiply it by scale:

scale = 1000000000.0
steps = self._extended_steps * scale
steps = [1.0e+08 1.5e+08 2.0e+08 2.5e+08 3.0e+08 4.0e+08 5.0e+08 6.0e+08 8.0e+08 1.0e+09 1.5e+09 2.0e+09 2.5e+09 3.0e+09 4.0e+09 5.0e+09 6.0e+09 8.0e+09
 1.0e+10 1.5e+10]

Then comes the two lines of code that are supposed to filter the ticks < 1 and keep only integer ticks.

        if self._integer:
            # For steps > 1, keep only integer values.
            igood = (steps < 1) | (np.abs(steps - np.round(steps)) < 0.001)
            steps = steps[igood]

The result of this filtering is:

steps = [1.0e+08 1.5e+08 2.0e+08 2.5e+08 3.0e+08 4.0e+08 5.0e+08 6.0e+08 8.0e+08
 1.0e+09 1.5e+09 2.0e+09 2.5e+09 3.0e+09 4.0e+09 5.0e+09 6.0e+09 8.0e+09
 1.0e+10 1.5e+10]

This does not seem correct. The following PR suggest changes to the code that produces the following output:

self._extended_steps = [ 0.1   0.15  0.2   0.25  0.3   0.4   0.5   0.6   0.8   1.    1.5   2.
  2.5   3.    4.    5.    6.    8.   10.   15.  ]

FIRST, filtering of non-integer ticks:

steps = [ 1.  2.  3.  4.  5.  6.  8. 10. 15.]

THEN, multiplication by scale

scale = 1000000000.0
steps = self._extended_steps * scale 
steps = [1.0e+09 2.0e+09 3.0e+09 4.0e+09 5.0e+09 6.0e+09 8.0e+09 1.0e+10 1.5e+10]

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

@QuLogic QuLogic requested a review from efiring September 11, 2018 01:33
@efiring
Copy link
Member

efiring commented Sep 11, 2018

I don't understand the point of this PR; I think the existing code is doing what it is intended to do, as described by the docstring. Can you supply a minimal example of a plot where using "integer=True" does something other than what the docstring says?

@dabana
Copy link
Contributor Author

dabana commented Sep 11, 2018

import matplotlib.pyplot as plt
import matplotlib.ticker as ticker

sci_nums = [10**9, 8*10**9]
fig, (axl, axr) = plt.subplots(1,2)
      
axl.scatter(range(len(sci_nums)), sci_nums)
axl.yaxis.set_major_locator(ticker.MaxNLocator(4, integer = True))
axl.set_title('with integer = True\n')

axr.scatter(range(len(sci_nums)), sci_nums)
axr.yaxis.set_major_locator(ticker.MaxNLocator(4, integer = False))
axr.set_title('with integer = False\n')

Output is:

issue12072

@dabana
Copy link
Contributor Author

dabana commented Sep 11, 2018

I guess I am confused with what the integer keyword is supposed to do. I thought all the tick labels would end-up greater than 1 without decimals (like 1, 2, 3 ... or 3, 6, 9, etc...).

By reading the code, I understand than only the tick labels greater than 1 will be integer.

        if self._integer:
            # For steps > 1, keep only integer values.
            igood = (steps < 1) | (np.abs(steps - np.round(steps)) < 0.001)
            steps = steps[igood]

If this is the correct behavior it might be worth rewording the doc_string to make this clear. For exemple:

integer
If True, ticks greater than 1 will take only integer values, provided
at least min_n_ticks integers are found within the
view limits.

@dabana
Copy link
Contributor Author

dabana commented Sep 11, 2018

I am closing this PR and moving the conversation to issue #12072

@dabana dabana closed this Sep 11, 2018
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