Skip to content

DOC: MaxNLocator and contour/contourf doc update (replaces #16428) #16534

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

Merged
merged 1 commit into from
Mar 2, 2020
Merged

DOC: MaxNLocator and contour/contourf doc update (replaces #16428) #16534

merged 1 commit into from
Mar 2, 2020

Conversation

pharshalp
Copy link
Contributor

@pharshalp pharshalp commented Feb 16, 2020

PR Summary

closes #12729

I messed my github matplotlib repo settings (and not github doesn't recognize my old branch... it says pharshalp wants to merge 1 commit into matplotlib:master from **unknown repository**) so closed the older PR and recreated it here.
Sorry for the noise!
Please see #16428 the reviewers' comments, suggestions and discussion.


MaxNLocator's docs were incorrect (please see the details described in #12729).

Here is a numerical experiment that I ran to determine the difference between the number of tick locations returned by MaxNLocator and the argument nbins.

import matplotlib.ticker as mticker
import numpy as np

steps = np.linspace(1, 10, 37)   # Overkill -- 1.  ,  1.25,  1.5 ,  1.75,  2.... , 10
vmax_arr = np.linspace(0, 1, 1001)[1:]  # Overkill

# number of ticks - number of bins
nticks_minus_nbins = np.zeros((1001, 40, 3), dtype=np.int64)
for vmax_ind, vmax in enumerate(vmax_arr):
    for nbins in range(1, 40+1):
        locator = mticker.MaxNLocator(nbins, steps=steps, min_n_ticks=1)
        nticks_minus_nbins[vmax_ind, nbins-1, 0] = len(locator.tick_values(0, vmax))-nbins
        nticks_minus_nbins[vmax_ind, nbins-1, 1] = len(locator.tick_values(-vmax, 0))-nbins
        nticks_minus_nbins[vmax_ind, nbins-1, 2] = len(locator.tick_values(-vmax, vmax))-nbins
print(np.max(nticks_minus_nbins))  # returns 2

It turns out (as was shown in the original issue) that MaxNLocator returns at most nbins+2 tick locations (nbins+1 intervals).

Since contour/contourf uses MaxNLocator (as pointed out in the original issue) updated their docs as well.

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

Copy link
Member

@tacaswell tacaswell left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not think this documentation change is correct, and if it is it is showing a major bug in the locator code.

Per #16428 (comment) I think the N needs to be qualified to be within the view limit and that it make return additional ticks outside of the view limit.

@efiring
Copy link
Member

efiring commented Feb 16, 2020

The following test shows that it selects no more than N ticks within the view limits, inclusive on the left and exclusive on the right. It has to provide up to 2 more so that it can be used for autoscaling in "classic" mode.

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import MaxNLocator

Ntargets = np.arange(3, 20)
vmins = np.linspace(1, 10, 50)
spans = np.linspace(1, 10, 50)

shape = len(Ntargets), len(vmins), len(spans)
nticks_inside = np.zeros(shape, dtype=int)
nticks = np.zeros(shape, dtype=int)

for i, N in enumerate(Ntargets):
    locator = MaxNLocator(N)
    for j, vmin in enumerate(vmins):
        for k, span in enumerate(spans):
            vmax = vmin + span
            ticks = locator.tick_values(vmin, vmax)
            nticks[i, j, k] = len(ticks)
            clipped = ticks[(ticks < vmax) & (ticks >= vmin)]
            nticks_inside[i, j, k] = len(clipped)

print(Ntargets - nticks_inside.max(axis=-1).max(axis=-1))

Run it:

In [7]: run test_MaxN
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]

@tacaswell tacaswell added this to the v3.3.0 milestone Feb 16, 2020
@pharshalp
Copy link
Contributor Author

pharshalp commented Feb 16, 2020

@tacaswell and @efiring Thanks for (patiently) explaining the point about the view limits. Pushed a change as suggested.

@efiring efiring merged commit 76c764c into matplotlib:master Mar 2, 2020
@efiring
Copy link
Member

efiring commented Mar 2, 2020

Thank you, @pharshalp.

@pharshalp pharshalp deleted the maxnlocator_contourf_contour_doc branch March 2, 2020 23:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Docs for contour levels argument is incorrect
4 participants