Skip to content
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

Add minor ticks on and off in Axis #22761

Merged
merged 1 commit into from
Mar 13, 2024

Conversation

n-aswin
Copy link
Contributor

@n-aswin n-aswin commented Apr 1, 2022

PR Summary

Simialar to Axes, minor ticks can be turned on or off in Axis using axis.minorticks_on() or axis.minorticks_off().

PR Checklist

Tests and Styling

  • Has pytest style unit tests (and pytest passes).
  • Is Flake 8 compliant (install flake8-docstrings and run flake8 --docstring-convention=all).

Documentation

  • New features are documented, with examples if plot related.
  • New features have an entry in doc/users/next_whats_new/ (follow instructions in README.rst there).
  • API changes documented in doc/api/next_api_changes/ (follow instructions in README.rst there).
  • Documentation is sphinx and numpydoc compliant (the docs should build without error).

Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

Thank you for opening your first PR into Matplotlib!

If you have not heard from us in a while, please feel free to ping @matplotlib/developers or anyone who has commented on the PR. Most of our reviewers are volunteers and sometimes things fall through the cracks.

You can also join us on gitter for real-time discussion.

For details on testing, writing docs, and our review process, please see the developer guide

We strive to be a welcoming and open project. Please follow our Code of Conduct.

------------------------------

Similar to Axes, minor ticks on Axis can be displayed or removed
using ``minorticks_on()`` and ``minor_ticks_off()``.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
using ``minorticks_on()`` and ``minor_ticks_off()``.
using ``minorticks_on()`` and ``minorticks_off()``.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed.

@@ -193,9 +192,9 @@ def set_default_locators_and_formatters(self, axis):
# update the minor locator for x and y axis based on rcParams
if (axis.axis_name == 'x' and mpl.rcParams['xtick.minor.visible'] or
axis.axis_name == 'y' and mpl.rcParams['ytick.minor.visible']):
axis.set_minor_locator(AutoMinorLocator())
axis.minorticks_off()
Copy link
Member

Choose a reason for hiding this comment

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

This should be "on"? Maybe add a test for this ;-). OTOH This is a change of behaviour, in that it only turns the ticks on, doesn't change then to AutoMinorLocator. I'm not sure this new behaviour is bad, but it might have ramifications for folks.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yep, my mistake; fixed it.

The definition of minorticks_off() uses AutoMinorLocator unless the scale is log or symlog. Looking at the if condition, wouldn't the logic be better located inside minorticks_on() and minorticks_off()?

Copy link
Contributor Author

@n-aswin n-aswin Apr 1, 2022

Choose a reason for hiding this comment

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

I think the (existing) test below covers minorticks_on(), but there are no tests for minorticks_off(). The code passes pytest on test_ticker.py with minorticks_on().

def test_minorticks_rc():
fig = plt.figure()
def minorticksubplot(xminor, yminor, i):
rc = {'xtick.minor.visible': xminor,
'ytick.minor.visible': yminor}
with plt.rc_context(rc=rc):
ax = fig.add_subplot(2, 2, i)
assert (len(ax.xaxis.get_minor_ticks()) > 0) == xminor
assert (len(ax.yaxis.get_minor_ticks()) > 0) == yminor
minorticksubplot(False, False, 1)
minorticksubplot(True, False, 2)
minorticksubplot(False, True, 3)
minorticksubplot(True, True, 4)

@oscargus oscargus added the status: needs workflow approval For PRs from new contributors, from which GitHub blocks workflows by default. label Apr 1, 2022
Copy link
Member

@jklymak jklymak left a comment

Choose a reason for hiding this comment

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

Don't we need to change ~.Axes.minortick_on as well?

I think overall this is a welcome addition. Lets try and leave as many breadcrumbs in the docs as possible because folks often get frustrated that the defaults interact difficultly with the more custom locators and tickers.

doc/users/next_whats_new/axis_minorticks_toggle.rst Outdated Show resolved Hide resolved
lib/matplotlib/axis.py Outdated Show resolved Hide resolved
@@ -193,9 +192,9 @@ def set_default_locators_and_formatters(self, axis):
# update the minor locator for x and y axis based on rcParams
if (axis.axis_name == 'x' and mpl.rcParams['xtick.minor.visible'] or
axis.axis_name == 'y' and mpl.rcParams['ytick.minor.visible']):
axis.set_minor_locator(AutoMinorLocator())
axis.minorticks_on()
Copy link
Member

Choose a reason for hiding this comment

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

This line still isn't being hit by the tests? Can we add a test here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think the test_minorticks_rc in test_ticker.py only covers linear scale. I can add a test.

@n-aswin
Copy link
Contributor Author

n-aswin commented Apr 2, 2022

Trying to implement a test which hits all scales; it seems like there are problems. If I understand correctly:

  • Every scale sets corresponding major and minor locators in the overridden method set_default_locators_and_formatters()
  • It does this using axis.set_major_locator() and axis.set_minor_locator() which are available through the axis argument to set_default_locators_and_formatters().
  • Prior to this pull request, toggling minorticks was available through Axes.minorticks_on(). It conditionally checked for 'log' and 'symlog' scales to set appropriate locators while rest of the scales were set to AutoMinorLocator(). This missed proper locators for other items in scales which have specific minor locators (like logit which has LogitLocator(minor=True) or asinh). This pull request only moved the problem into Axis.minorticks_on().
  • It seems like all the tests in test_ticker.py use the default linear scale and so the line inside FuncScale (mentioned above) was not covered.

Solution 1:

Add every scale name as a condition to Axis.minorticks_on(). Not a clean solution but works; may cause problems when scales added in future are not added as conditions.


Solution 2: (better?)

Add class variables in the ScaleBase class for minor locators and expose them through a ScaleBase.get_minor_locator() method. Setting the variables can be added to set_default_locators_and_formatters(). Axis already has access to scale instances through Axis._scale. Toggling minor ticks in Axis methods can then be done as:

scale = self._scale

# on
minor_locator = scale.get_minor_locator()
self.set_minor_locator(minor_locator)

# off
self.set_minor_locator(mticker.NullLocator())

This should work for scales added in future as long as they have the variables defined. Documentation for Custom Scale can be updated to set the variables.


In both cases, tests for minor ticks can be looped through matplotlib.scale.get_scale_names() (with test function arguments for FuncScale).

I am new to this codebase; let me know if I missed anything.

@jklymak
Copy link
Member

jklymak commented Apr 2, 2022

Thanks, the issues syncing up scales and default locators etc have been a pretty large pain as more scales have been added. I don't know that this PR needs to fix all the woes - if the testing you have in here is as good as the testing you had before, I think its fair enough to get this change in as an improvement, and save sorting out default scale locators and formaters for future work. Thanks a lot for looking into it!

@n-aswin
Copy link
Contributor Author

n-aswin commented Apr 3, 2022

In that case, I can:

  • Revert the changes in scale classes so that the locator information is still available there, but add conditional checking of xticks.minor.visible and yticks.minor.visible to remaining built-in scales with documented support (just like how it was implemented before for 'linear' scale).
  • Add conditional checking in Axis.minorticks_on() for built-in scales (as in Solution 1 mentioned above).
  • Instead of testing for all scales in matplotlib.scale.get_scale_names(), just test for built-in scales with comments regarding the limited behaviour in the test function.

This way, toggling minor ticks would work for built-in scales with minimum modifications toscale.py. If this sounds good I can push the changes.

@oscargus
Copy link
Contributor

oscargus commented Apr 5, 2022

Power cycling to restart the tests.

@oscargus oscargus closed this Apr 5, 2022
@oscargus oscargus reopened this Apr 5, 2022
@n-aswin
Copy link
Contributor Author

n-aswin commented Apr 11, 2022

I have amended the commit seeing that the tests were failing for many scales. Were the rcParams xticks.minor.visible and yticks.minor.visible restricted to only 'linear' and custom scales?

@n-aswin n-aswin force-pushed the axis-minorticks-toggle branch 3 times, most recently from b6283c1 to 20402e8 Compare April 12, 2022 12:26
@jklymak
Copy link
Member

jklymak commented May 18, 2022

this needs the docs fixed:

/home/circleci/project/doc/users/next_whats_new/axis_minorticks_toggle.rst:4: WARNING: more than one target found for cross-reference 'Axis': mpl_toolkits.mplot3d.axis3d.Axis, matplotlib.axis.Axis
/home/circleci/project/doc/users/next_whats_new/axis_minorticks_toggle.rst:4: WARNING: py:obj reference target not found: Axis.minorticks_on
/home/circleci/project/doc/users/next_whats_new/axis_minorticks_toggle.rst:4: WARNING: py:obj reference target not found: Axis.minorticks_off

@jklymak jklymak marked this pull request as draft May 18, 2022 09:22
@n-aswin
Copy link
Contributor Author

n-aswin commented May 26, 2022

Removed the ambiguity in Axis and added references to doc/api/axis_api.rst.

@melissawm
Copy link
Contributor

Hi @n-aswin - this needs a rebase and then I am assuming it is ready for another round of reviews?

If you need help rebasing, here's a nice guide. If you have questions, let us know!

@melissawm
Copy link
Contributor

@n-aswin is this ready for review?

@n-aswin
Copy link
Contributor Author

n-aswin commented Feb 9, 2023

Sorry, forgot to comment after the update. I have rebased the commits; should be OK now.

I had done this quite some time ago. Let me know if this needs changes.

@melissawm
Copy link
Contributor

If the PR is ready for review, can you please update it by removing the draft status using the GitHub web interface? Otherwise, it will be skipped over by maintainers, as draft PRs are considered not yet ready to review. Thanks!

@n-aswin n-aswin marked this pull request as ready for review March 10, 2023 05:48
@ksunden ksunden removed the status: needs workflow approval For PRs from new contributors, from which GitHub blocks workflows by default. label Apr 18, 2023
Copy link
Member

@jklymak jklymak left a comment

Choose a reason for hiding this comment

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

This looks good to me. Seems a useful addition and maybe we should merge soonish to see what it catches and iterate on fixes

@tacaswell tacaswell closed this Dec 12, 2023
@tacaswell tacaswell reopened this Dec 12, 2023
@tacaswell
Copy link
Member

power cycled to re-run tests against merging to current main

@QuLogic
Copy link
Member

QuLogic commented Dec 13, 2023

Looks like it just needs an addition to the type stubs to get the tests passing again.

@oscargus oscargus added this to the v3.9.0 milestone Dec 13, 2023
@QuLogic
Copy link
Member

QuLogic commented Mar 13, 2024

I rebased this, and added the missing type hints.

@tacaswell tacaswell merged commit 03a7ff0 into matplotlib:main Mar 13, 2024
42 checks passed
@tacaswell
Copy link
Member

Thank you for your work @n-aswin and congratulations on your first merged Matplotlib PR 🎉

I hope we hear from you again.

@n-aswin
Copy link
Contributor Author

n-aswin commented Mar 13, 2024

Thanks!

@n-aswin n-aswin deleted the axis-minorticks-toggle branch March 13, 2024 20:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Waiting for author
Development

Successfully merging this pull request may close these issues.

None yet

9 participants