Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Implemented support for 'markevery' in prop_cycle #10713

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 11 commits into from
Mar 14, 2018
Merged

Implemented support for 'markevery' in prop_cycle #10713

merged 11 commits into from
Mar 14, 2018

Conversation

salindersidhu
Copy link
Contributor

@salindersidhu salindersidhu commented Mar 8, 2018

PR Summary

Closes issue #8576

This PR resolves a ValueError caused by assigning the axes.prop_cycle attribute, through rcParams, a cycler composed using a markevery value. Markevery is Line2D object property that is used to show a marker at actual data points along a plot. e.g., if markevery=[5], every 5-th marker will be plotted. Additional details about markevery and it's type constraints can be found here https://matplotlib.org/api/_as_gen/matplotlib.lines.Line2D.html#matplotlib.lines.Line2D.set_markevery

The following code replicates the ValueError mentioned above.

from cycler import cycler
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt

mpl.rcParams['axes.prop_cycle'] = cycler(markevery=[5])
t = np.arange(0.0, 1.0, 0.01)
plt.plot(t, np.sin(2*np.pi*t), marker='o')
plt.show()
ValueError: Key axes.prop_cycle: Unknown artist properties: {'markevery'}

The following picture shows the above code functioning correctly, every 5th data point on the sine curve is marked.
figure_1
I have extended rcsetup.py to include a markevery validator and the test cases for the markevery validator in test_rcparams.py. I have added the what's new entry for this fix and example code showcasing axes.prop_cycle configured through rcParams with valid use cases of markevery.

PR Checklist

  • Has Pytest style unit tests
  • Code is PEP 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 8, 2018

Just a few preliminary requests:

  • can you make the PR self contained so we don't need to look up support 'markevery' in prop_cycle #8576? And not refer to the issue number in the title?
  • The documentation is quite self-referential. I don't know what markevery is, and I can't quickly grok it from anything in this PR. You do reference where I could figure it out, but a short description of what markevery does would help the documentation.
  • does this need a test of actually using the property beyond the example?

@salindersidhu salindersidhu changed the title Fixed issue 8576 Implemented support for 'markevery' in prop_cycle Mar 8, 2018
@salindersidhu
Copy link
Contributor Author

salindersidhu commented Mar 8, 2018

Hi, thanks for the response.

I've removed the issue number from the title and made the PR self contained with enough information about markevery and the issue this PR resolves.

If I understood correctly, using the property beyond the example. The functionality for markevery is already supported within matplotlib. This PR just enables support for assigning a cycler object with markevery to axes.prop_cycle through the use of rcparams.

Let me know if anything else needs to be done.

@jklymak
Copy link
Member

jklymak commented Mar 8, 2018

@salindersidhu Thanks so much. Crystal clear now! I'll try an review when you are done. If you don't get feedback in a few days, feel free to ping...

@salindersidhu
Copy link
Contributor Author

Done, all checks have passed!

@jklymak
Copy link
Member

jklymak commented Mar 9, 2018

OK< sorry if I'm a lazy reviewer, but time is time. Is there no kwarg way to specify markevery? If not, that seems more important than an rcparam.

@salindersidhu
Copy link
Contributor Author

salindersidhu commented Mar 9, 2018

Don't think there's a kwarg way to specify markevery. Would probably need to open a new issue to request this as a feature correct?

@jklymak
Copy link
Member

jklymak commented Mar 9, 2018

I get confused about the linestyle cycles. Maybe they are only implimented via rcParams?

@salindersidhu
Copy link
Contributor Author

salindersidhu commented Mar 10, 2018

Sorry about the delay, after reading this link it turns out that we can assign markevery using set.prop_cycle in a kwarg way.

Axes.set_prop_cycle(*args, **kwargs)

I've demonstrated this using the code below.

from cycler import cycler
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt

t = np.arange(0.0, 1.0, 0.01)
ax = plt.subplot(111)
ax.set_prop_cycle(markevery=[5])
ax.plot(t, np.sin(2*np.pi*t), marker='o')
plt.show()

Upon testing this with the current stable version of matplotlib (2.2.0), I get the same ValueError as using markevery with rcparams. However, this code works using the fix from this PR.

@jklymak
Copy link
Member

jklymak commented Mar 10, 2018

Are you sure you checked all the files in? This PR doesn't touch any files to do with plotting or lines, so I don't see how it could have fixed anything... Sorry for the long process!

@salindersidhu
Copy link
Contributor Author

The answer is found in this file /master/lib/matplotlib/axes/_base.py

That file contains a class called _AxesBase which contains set_prop_cycle(self, *args, **kwarfs). This function calls a set_prop_cycle function from the _process_plot_var_args class through self._get_lines, which is an instance of _process_plot_var_args master/lib/matplotlib/axes/_base.py#L1204

The set_prop_cycle function from the _process_plot_var_args class assigns it's property cycler by calling the cycler() function here /master/lib/matplotlib/axes/_base.py#L169

We can see that this cycler function is imported from rcsetup.py here /master/lib/matplotlib/axes/_base.py#L38

The cycler function in rcsetup.py validates the keywords from a dictionary containing a keyword and it's validator. This PR added 'markevery': validate_markeverylist to _prop_validators which is used by cycler.

This is the reason why the fix in this PR works for set_prop_cycle because it uses a cycler object from rcsetup.py

@jklymak
Copy link
Member

jklymak commented Mar 11, 2018

Great detective work! Not at all obvious.

@salindersidhu
Copy link
Contributor Author

Awesome, any ETA on when this will be merged?

@jklymak
Copy link
Member

jklymak commented Mar 13, 2018

It needs two reviews

Copy link
Member

@efiring efiring left a comment

Choose a reason for hiding this comment

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

Looks nicely done.

@efiring efiring merged commit b2782e0 into matplotlib:master Mar 14, 2018
@jklymak
Copy link
Member

jklymak commented Mar 14, 2018

Thanks a lot @salindersidhu and thanks for patiently walking me through your changes!

@salindersidhu salindersidhu deleted the fixed-issue-8576 branch March 15, 2018 04:16
@QuLogic QuLogic added this to the v3.0 milestone Mar 21, 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.

4 participants