Skip to content

DOC: add more tutorial to text/text_intro #9827

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
Nov 24, 2017

Conversation

jklymak
Copy link
Member

@jklymak jklymak commented Nov 21, 2017

PR Summary

Working on the default DateLocators I noted that I couldn't really find a good place where Locators are explained. tutorials/text/text_intro.py seems like a good place to explain these things.

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


* :func:`~matplotlib.pyplot.text` - add text at an arbitrary location to the ``Axes``;
:meth:`matplotlib.axes.Axes.text` in the API.
* `pyplot.text` - add text at an arbitrary location to the ``Axes``;
Copy link
Contributor

Choose a reason for hiding this comment

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

single backquotes for Axes/Figure

# Terminology
# ~~~~~~~~~~~
#
# *Axes* (typically) have an `axis.xaxis` and `axis.yaxis` object that
Copy link
Contributor

Choose a reason for hiding this comment

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

I think the normal convention is to call a single Axes object "ax" instead of "axis" in order to avoid confusion with Axis. So "ax.xaxis" and "ax.yaxis".

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, that was a typo (darn auto-correct). I changed to Axes.xaxis to actually point to the objects. I think that works.

#
# The axis API is explained in detail in the `axis_api` section.

# An axis object has major and minor ticks. The axis has a *major_locator*
Copy link
Contributor

Choose a reason for hiding this comment

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

An Axis (capital) (to emphasize the difference with Axes).

# Simple ticks
# ~~~~~~~~~~~~
#
# While "discouraged", if can be very convenient to simply define the
Copy link
Contributor

@anntzer anntzer Nov 21, 2017

Choose a reason for hiding this comment

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

I think we should always say why things are discouraged, rather than just handwaving it. In this case, I'd say it's because 1) they are not recomputed during interactive navigation, and 2) this prevents the data cursor (in the status bar) from working.

Edit: didn't notice it was clarified below, but I would still mention the above points.

typo below: overriding

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Instead of making a list of all the tickalbels, we could have
# used a `ticker.FormatStrFormatter` and passed it to the `axis.xaxis`
Copy link
Contributor

Choose a reason for hiding this comment

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

ax.xaxis (as above, and throughout)

axs[1].plot(x1, y1)
ticks = np.arange(0., 8.1, 2.)
# list comprehension to get all tick labels...
formatter = matplotlib.ticker.FormatStrFormatter('%1.1f')
Copy link
Contributor

@anntzer anntzer Nov 21, 2017

Choose a reason for hiding this comment

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

I would perhaps(?) rather push forward StrMethodFormatter (i.e. using str.format), as old-style format strings are, well, old-style.

ticker.StrMethodFormatter("{x:1.1f}")

In fact I tend to just pass a bound method to FuncFormatter:

ticker.FuncFormatter("{:1.1f}".format)

which covers all use cases rather than having to invoke a specific class in each case.

Copy link
Member Author

Choose a reason for hiding this comment

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

Ha, ok. I just suck at the new format. I’ll change!

Copy link
Contributor

Choose a reason for hiding this comment

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

tbh I don't really like ticker.StrMethodFormatter("{x:1.1f}") either (IMO FuncFormatter is really the clearest) but I'm likely not be the best judge for what's best in a tutorial!

Copy link
Member Author

Choose a reason for hiding this comment

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

I give an example of func formatter below. Your use above is clever, but a bit obscure ;-)


plt.show()

############################################################################## Finally, we can secify functions for the formatter using
Copy link
Contributor

@anntzer anntzer Nov 21, 2017

Choose a reason for hiding this comment

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

newline missing?
specify

# `ticker.FuncFormatter`.

def formatoddticks(x, pos):
""" Format odd tick positions
Copy link
Contributor

Choose a reason for hiding this comment

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

extra space

* :func:`~matplotlib.pyplot.text` - add text at an arbitrary location to the ``Axes``;
:meth:`matplotlib.axes.Axes.text` in the API.
* `pyplot.text` - add text at an arbitrary location to the `Axes`;
`Axes.text` in the API.
Copy link
Member Author

Choose a reason for hiding this comment

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

@anntzer or others who understand: I am still not getting the sphinx auto-resolution. What is the proper way to make these links? Do I have to do matplotlib.Axes.text?

See: https://3893-1385122-gh.circle-artifacts.com/0/home/circleci/project/doc/build/html/tutorials/text/text_intro.html#sphx-glr-tutorials-text-text-intro-py

Copy link
Contributor

Choose a reason for hiding this comment

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

~.Axes.text

or

.Axes.text

should work, I think(?) (the leading dot means "search in other namespaces"; the tilde means "don't write the prefix in the rendered docs http://www.sphinx-doc.org/en/stable/domains.html#role-py:obj).

Copy link
Member Author

Choose a reason for hiding this comment

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

Ok thanks a lot. Hopefully that makes it into @dstansby doc on docs.

@jklymak jklymak force-pushed the doc_label_plots branch 2 times, most recently from e216346 to 4144e38 Compare November 22, 2017 05:25
=================
========================
Text in Matplotlib Plots
========================
Copy link
Contributor

Choose a reason for hiding this comment

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

remove subtitle just below, or merge with title

Copy link
Contributor

Choose a reason for hiding this comment

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

replace matplotlib by Matplotlib when in text, throughout.

Copy link
Member Author

Choose a reason for hiding this comment

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

The first line shows up in a hover-over in the docs, so I think thats why the "subtitle" is there.

* :func:`~matplotlib.pyplot.figtext` - add text at an arbitrary location to the ``Figure``;
:meth:`matplotlib.figure.Figure.text` in the API.
* `matplotlib.pyplot.figtext` - add text at an arbitrary location to the
Figure; `matplotlib.Figure.text` in the API.
Copy link
Contributor

@anntzer anntzer Nov 22, 2017

Choose a reason for hiding this comment

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

* :func:`~matplotlib.pyplot.annotate` - add an annotation, with
optional arrow, to the ``Axes`` ; :meth:`matplotlib.axes.Axes.annotate`
* `matplotlib.pyplot.annotate` - add an annotation, with
optional arrow, to the `~matplotlib.axes.Axes` ; `matplotlib.axes.Axes.annotate`
Copy link
Contributor

Choose a reason for hiding this comment

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

overindented here too

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed the indents (I hope)

@@ -31,36 +32,38 @@
===================

The following commands are used to create text in the pyplot
interface
interface and the object-oriented API:
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this would be better presented as a 3-column table (pyplot, oo, explanation).

Copy link
Member Author

Choose a reason for hiding this comment

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

I agree, but making a table that will fit is not trivial for someone w/ my rst skills. I think the list is OK.

"""

import matplotlib
Copy link
Contributor

Choose a reason for hiding this comment

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

below (unicode example): replace \374 with either the proper unicode character or "\N{LATIN SMALL LETTER U WITH DIAERESIS}" which is much more self-explanatory I think (if a bit lengthy)... (see unicodedata.name).

fig.subplots_adjust(bottom=0.2, left=0.2)
ax.plot(x1, np.cumsum(y1**2))
ax.set_xlabel('time [s] \n This was a long experiment')
ax.set_ylabel('$\int\ Y^2\ dt\ \ [V^2 s]$')
Copy link
Contributor

Choose a reason for hiding this comment

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

needs to be a raw string (otherwise the backslash escapes are invalid)

Copy link
Member Author

Choose a reason for hiding this comment

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

? They render fine.

Copy link
Contributor

Choose a reason for hiding this comment

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

https://docs.python.org/3/reference/lexical_analysis.html#string-and-bytes-literals

Changed in version 3.6: Unrecognized escape sequences produce a DeprecationWarning. In some future version of Python they will be a SyntaxError.

(run with python -Wd to see the deprecation warnings)

# Terminology
# ~~~~~~~~~~~
#
# *Axes* (typically) have an `matplotlib.axis` object for the ``ax.xaxis``
Copy link
Contributor

Choose a reason for hiding this comment

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

why typically?

Copy link
Member Author

Choose a reason for hiding this comment

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

3-D axes, not sure how polar axes work....

Copy link
Contributor

Choose a reason for hiding this comment

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

Actually it's a matplotlib.axis.Axis object. 3D axes have xaxis/yaxis/zaxis which also inherit from Axis. Polar axes have, for the better or (mostly?) the worse, also an xaxis (theta) and a yaxis (r) attributes.

fig, axs = plt.subplots(2, 1, figsize=(5, 3), tight_layout=True)
axs[0].plot(x1, y1)
axs[1].plot(x1, y1)
axs[1].xaxis.set_ticks(np.arange(0., 8.1, 2.))
Copy link
Contributor

@anntzer anntzer Nov 22, 2017

Choose a reason for hiding this comment

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

The "8.1" is a bit ugh. In this specific case I'd just write [0, 2, 4, 6, 8] explicitly (or even stop at 6, which is enough for the example).
Same below.

Copy link
Member Author

Choose a reason for hiding this comment

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

I did 8.1 on purpose so show the bad side effect of using set_ticks. I uses arange because thats just something I typically do to get ticks.

#############################################################################
# The default formatter is the `matplotlib.ticker.MaxNLocator` called as
# ``ticker.MaxNLocator(self, nbins='auto', steps=[1, 2, 2.5, 5, 10])``
# The *steps* keyword is acceptable multiples that can be used for
Copy link
Contributor

Choose a reason for hiding this comment

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

"is acceptable" typo

axs[1].xaxis.set_major_locator(locator)
axs[1].xaxis.set_major_formatter(formatter)

formatter = matplotlib.ticker.FormatStrFormatter('%1.5f')
Copy link
Contributor

Choose a reason for hiding this comment

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

%1.4f would avoid overlapping labels

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, but the overlapping labels are the point!

# `matplotlib.ticker.FuncFormatter`.


def formatoddticks(x, pos):
Copy link
Contributor

Choose a reason for hiding this comment

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

ternaries for the win: return '%1.2f' % x if x % 2 else ''

Copy link
Member Author

Choose a reason for hiding this comment

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

Lets save that for the Advanced Python Tricks guide. I want to be able to read this thing when its done ;-)

# order to help, dates have spectial Locators and Formatters,
# defined in the `matplotlib.dates` module.
#
# A simple exmample is as follows. Note how we have to rotate the
Copy link
Contributor

Choose a reason for hiding this comment

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

pyto

##############################################################################
# Maybe the format of the labels above is acceptable, but the choices is
# rather idiosyncratic. We can make the ticks fall on the start of the month
# by very lightly modifying `matplotlib.dates.AutoDateLocator`
Copy link
Contributor

Choose a reason for hiding this comment

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

lightly? slightly?

Copy link
Member Author

Choose a reason for hiding this comment

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

struck "very lightly"

plt.show()

##############################################################################
# Oddly, this changes the labels! The easiest fix is to pass a format to
Copy link
Contributor

Choose a reason for hiding this comment

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

While the behavior may be "odd" I think we should not say it as such in the official docs... (a brief explaination why (I guess locators and formatters are coupled) would be nicer)

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, I'm not sure why. Seems like a bug. But for now its a good excuse to introduce the formatter...

Copy link
Member Author

Choose a reason for hiding this comment

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

struck inflamatory language for: However, this changes the tick labels.

# Legends and Annotations
# =======================
#
# - Legends: :ref:`sphx_glr_tutorials_intermediate_legend_guide.py`
Copy link
Contributor

Choose a reason for hiding this comment

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

I tend to prefer

:doc:`/tutorials/intermediate/legend_guide`

which links to the page itself rather than an html anchor, and is also shorter to type.

@jklymak jklymak force-pushed the doc_label_plots branch 2 times, most recently from 1e4b476 to d8a3c96 Compare November 22, 2017 20:20
@jklymak jklymak added this to the v2.2 milestone Nov 22, 2017
@jklymak
Copy link
Member Author

jklymak commented Nov 22, 2017

Milestoning against 2.2 because this requires the pad argument in ax.title, which is on master, but not in 2.1. I could take that out if folks want to see this added sooner...

@jklymak jklymak changed the title WIP: DOC: add more tutorial to text/text_intro DOC: add more tutorial to text/text_intro Nov 22, 2017
@jklymak
Copy link
Member Author

jklymak commented Nov 22, 2017

For further review: https://3926-1385122-gh.circle-artifacts.com/0/home/circleci/project/doc/build/html/tutorials/text/text_intro.html#sphx-glr-tutorials-text-text-intro-py

Question: Is there a way to order the tutorials? Currently they are alphabetical, which isn't necessarily sensible.

@anntzer
Copy link
Contributor

anntzer commented Nov 23, 2017

@jklymak
Copy link
Member Author

jklymak commented Nov 23, 2017

@anntzer I'm not too concerned w/ the order of the folders, but the order of the tutorials inside each folder. However, I take it back about them being alphabetical. I'm not sure how they are ordered:

http://matplotlib.org/tutorials/index.html#introductory

@anntzer
Copy link
Contributor

anntzer commented Nov 23, 2017

No idea, but if that's not in the s-g docs perhaps you should open an issue there?

@NelleV
Copy link
Member

NelleV commented Nov 24, 2017

Thanks a lot @jklymak for this contribution!

As for ordering tutorial, maybe open an issue, although my 2 cents is that tutorials should be rst, not sphinx-gallery based, and thus can be ordered naturally.

@NelleV NelleV merged commit 4fc36df into matplotlib:master Nov 24, 2017
@jklymak
Copy link
Member Author

jklymak commented Nov 24, 2017

Thanks @NelleV. I did look up whats happening. They are are ordered by lines of code! You can change it to alphabetical, and a few other things, but I don't see where you can set it manually. I guess we could rename the tutorial files 1_this_tutorial, 2_that_tutorial if we care about the order (and we stick w/ sphinx-gallery)

@QuLogic QuLogic modified the milestones: needs sorting, v2.2.0 Feb 12, 2018
@jklymak jklymak deleted the doc_label_plots branch March 5, 2019 16:09
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.

5 participants