Fix toc, imshow default interpolation, and detail animation rendering

main
Aurélien Geron 2020-04-21 21:14:10 +12:00
parent ab97bf435b
commit 2993c68490
1 changed files with 126 additions and 57 deletions

View File

@ -16,7 +16,7 @@
}, },
"source": [ "source": [
"# Table of Contents\n", "# Table of Contents\n",
" <p><div class=\"lev1\"><a href=\"#Plotting-your-first-graph-1\"><span class=\"toc-item-num\">1&nbsp;&nbsp;</span>Plotting your first graph</a></div><div class=\"lev1\"><a href=\"#Line-style-and-color-2\"><span class=\"toc-item-num\">2&nbsp;&nbsp;</span>Line style and color</a></div><div class=\"lev1\"><a href=\"#Saving-a-figure-3\"><span class=\"toc-item-num\">3&nbsp;&nbsp;</span>Saving a figure</a></div><div class=\"lev1\"><a href=\"#Subplots-4\"><span class=\"toc-item-num\">4&nbsp;&nbsp;</span>Subplots</a></div><div class=\"lev1\"><a href=\"#Multiple-figures-5\"><span class=\"toc-item-num\">5&nbsp;&nbsp;</span>Multiple figures</a></div><div class=\"lev1\"><a href=\"#Pyplot's-state-machine:-implicit-vs-explicit-6\"><span class=\"toc-item-num\">6&nbsp;&nbsp;</span>Pyplot's state machine: implicit <em>vs</em> explicit</a></div><div class=\"lev1\"><a href=\"#Pylab-vs-Pyplot-vs-Matplotlib-7\"><span class=\"toc-item-num\">7&nbsp;&nbsp;</span>Pylab <em>vs</em> Pyplot <em>vs</em> Matplotlib</a></div><div class=\"lev1\"><a href=\"#Drawing-text-8\"><span class=\"toc-item-num\">8&nbsp;&nbsp;</span>Drawing text</a></div><div class=\"lev1\"><a href=\"#Legends-9\"><span class=\"toc-item-num\">9&nbsp;&nbsp;</span>Legends</a></div><div class=\"lev1\"><a href=\"#Non-linear-scales-10\"><span class=\"toc-item-num\">10&nbsp;&nbsp;</span>Non linear scales</a></div><div class=\"lev1\"><a href=\"#Ticks-and-tickers-11\"><span class=\"toc-item-num\">11&nbsp;&nbsp;</span>Ticks and tickers</a></div><div class=\"lev1\"><a href=\"#Polar-projection-12\"><span class=\"toc-item-num\">12&nbsp;&nbsp;</span>Polar projection</a></div><div class=\"lev1\"><a href=\"#3D-projection-13\"><span class=\"toc-item-num\">13&nbsp;&nbsp;</span>3D projection</a></div><div class=\"lev1\"><a href=\"#Scatter-plot-14\"><span class=\"toc-item-num\">14&nbsp;&nbsp;</span>Scatter plot</a></div><div class=\"lev1\"><a href=\"#Lines-15\"><span class=\"toc-item-num\">15&nbsp;&nbsp;</span>Lines</a></div><div class=\"lev1\"><a href=\"#Histograms-16\"><span class=\"toc-item-num\">16&nbsp;&nbsp;</span>Histograms</a></div><div class=\"lev1\"><a href=\"#Images-17\"><span class=\"toc-item-num\">17&nbsp;&nbsp;</span>Images</a></div><div class=\"lev1\"><a href=\"#Animations-18\"><span class=\"toc-item-num\">18&nbsp;&nbsp;</span>Animations</a></div><div class=\"lev1\"><a href=\"#Saving-animations-to-video-files-19\"><span class=\"toc-item-num\">19&nbsp;&nbsp;</span>Saving animations to video files</a></div><div class=\"lev1\"><a href=\"#What-next?-20\"><span class=\"toc-item-num\">20&nbsp;&nbsp;</span>What next?</a></div>" " <p><div class=\"lev1\"><a href=\"#Plotting-your-first-graph\"><span class=\"toc-item-num\">1&nbsp;&nbsp;</span>Plotting your first graph</a></div><div class=\"lev1\"><a href=\"#Line-style-and-color\"><span class=\"toc-item-num\">2&nbsp;&nbsp;</span>Line style and color</a></div><div class=\"lev1\"><a href=\"#Saving-a-figure\"><span class=\"toc-item-num\">3&nbsp;&nbsp;</span>Saving a figure</a></div><div class=\"lev1\"><a href=\"#Subplots\"><span class=\"toc-item-num\">4&nbsp;&nbsp;</span>Subplots</a></div><div class=\"lev1\"><a href=\"#Multiple-figures\"><span class=\"toc-item-num\">5&nbsp;&nbsp;</span>Multiple figures</a></div><div class=\"lev1\"><a href=\"#Pyplot's-state-machine:-implicit-vs-explicit\"><span class=\"toc-item-num\">6&nbsp;&nbsp;</span>Pyplot's state machine: implicit <em>vs</em> explicit</a></div><div class=\"lev1\"><a href=\"#Pylab-vs-Pyplot-vs-Matplotlib\"><span class=\"toc-item-num\">7&nbsp;&nbsp;</span>Pylab <em>vs</em> Pyplot <em>vs</em> Matplotlib</a></div><div class=\"lev1\"><a href=\"#Drawing-text\"><span class=\"toc-item-num\">8&nbsp;&nbsp;</span>Drawing text</a></div><div class=\"lev1\"><a href=\"#Legends\"><span class=\"toc-item-num\">9&nbsp;&nbsp;</span>Legends</a></div><div class=\"lev1\"><a href=\"#Non-linear-scales\"><span class=\"toc-item-num\">10&nbsp;&nbsp;</span>Non linear scales</a></div><div class=\"lev1\"><a href=\"#Ticks-and-tickers\"><span class=\"toc-item-num\">11&nbsp;&nbsp;</span>Ticks and tickers</a></div><div class=\"lev1\"><a href=\"#Polar-projection\"><span class=\"toc-item-num\">12&nbsp;&nbsp;</span>Polar projection</a></div><div class=\"lev1\"><a href=\"#3D-projection\"><span class=\"toc-item-num\">13&nbsp;&nbsp;</span>3D projection</a></div><div class=\"lev1\"><a href=\"#Scatter-plot\"><span class=\"toc-item-num\">14&nbsp;&nbsp;</span>Scatter plot</a></div><div class=\"lev1\"><a href=\"#Lines\"><span class=\"toc-item-num\">15&nbsp;&nbsp;</span>Lines</a></div><div class=\"lev1\"><a href=\"#Histograms\"><span class=\"toc-item-num\">16&nbsp;&nbsp;</span>Histograms</a></div><div class=\"lev1\"><a href=\"#Images\"><span class=\"toc-item-num\">17&nbsp;&nbsp;</span>Images</a></div><div class=\"lev1\"><a href=\"#Animations\"><span class=\"toc-item-num\">18&nbsp;&nbsp;</span>Animations</a></div><div class=\"lev1\"><a href=\"#Saving-animations-to-video-files\"><span class=\"toc-item-num\">19&nbsp;&nbsp;</span>Saving animations to video files</a></div><div class=\"lev1\"><a href=\"#What-next?\"><span class=\"toc-item-num\">20&nbsp;&nbsp;</span>What next?</a></div>"
] ]
}, },
{ {
@ -68,7 +68,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 4, "execution_count": 3,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -89,7 +89,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 5, "execution_count": 4,
"metadata": { "metadata": {
"scrolled": true "scrolled": true
}, },
@ -108,7 +108,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 6, "execution_count": 5,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -126,7 +126,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 7, "execution_count": 6,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -147,7 +147,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 8, "execution_count": 7,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -175,7 +175,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 9, "execution_count": 8,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -194,7 +194,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 10, "execution_count": 9,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -214,7 +214,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 11, "execution_count": 10,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -232,7 +232,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 12, "execution_count": 11,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -252,7 +252,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 13, "execution_count": 12,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -270,7 +270,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 14, "execution_count": 13,
"metadata": { "metadata": {
"scrolled": true "scrolled": true
}, },
@ -294,7 +294,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 15, "execution_count": 14,
"metadata": { "metadata": {
"scrolled": true "scrolled": true
}, },
@ -315,7 +315,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 16, "execution_count": 15,
"metadata": { "metadata": {
"scrolled": true "scrolled": true
}, },
@ -349,7 +349,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 17, "execution_count": 16,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -371,7 +371,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 18, "execution_count": 17,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -403,7 +403,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 19, "execution_count": 18,
"metadata": { "metadata": {
"scrolled": true "scrolled": true
}, },
@ -444,7 +444,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 20, "execution_count": 19,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -460,7 +460,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 21, "execution_count": 20,
"metadata": { "metadata": {
"scrolled": true "scrolled": true
}, },
@ -503,7 +503,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 22, "execution_count": 21,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -533,7 +533,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 23, "execution_count": 22,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -553,7 +553,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 24, "execution_count": 23,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -577,7 +577,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 25, "execution_count": 24,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -603,7 +603,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 26, "execution_count": 25,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -625,7 +625,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 27, "execution_count": 26,
"metadata": { "metadata": {
"scrolled": true "scrolled": true
}, },
@ -674,7 +674,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 28, "execution_count": 27,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -717,7 +717,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 29, "execution_count": 28,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -741,7 +741,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 30, "execution_count": 29,
"metadata": { "metadata": {
"scrolled": true "scrolled": true
}, },
@ -770,7 +770,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 31, "execution_count": 30,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -795,7 +795,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 32, "execution_count": 31,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -814,7 +814,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 33, "execution_count": 32,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -833,7 +833,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 34, "execution_count": 33,
"metadata": { "metadata": {
"scrolled": true "scrolled": true
}, },
@ -861,7 +861,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 35, "execution_count": 34,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -892,7 +892,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 36, "execution_count": 35,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -910,7 +910,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 37, "execution_count": 36,
"metadata": { "metadata": {
"scrolled": true "scrolled": true
}, },
@ -946,7 +946,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 38, "execution_count": 37,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -965,7 +965,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 39, "execution_count": 38,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -982,7 +982,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 40, "execution_count": 39,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -1000,7 +1000,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 41, "execution_count": 40,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -1019,7 +1019,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 42, "execution_count": 41,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -1036,7 +1036,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 43, "execution_count": 42,
"metadata": { "metadata": {
"scrolled": true "scrolled": true
}, },
@ -1054,17 +1054,16 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"Since the `img` array is just quite small (20x30), when the `imshow` function displays it, it grows the image to the figure's size. By default it uses [bilinear interpolation](https://en.wikipedia.org/wiki/Bilinear_interpolation) to fill the added pixels. This is why the edges look blurry.\n", "Since the `img` array is just quite small (20x30), when the `imshow` function displays it, it grows the image to the figure's size. Imagine stretching the original image, leaving blanks between the original pixels. How does imshow fill the blanks? Well, by default, it just colors each blank pixel using the color of the nearest non-blank pixel. This technique can lead to pixelated images. If you prefer, you can use a different interpolation method, such as [bilinear interpolation](https://en.wikipedia.org/wiki/Bilinear_interpolation) to fill the blank pixels. This leads to blurry edges, which many be nicer in some cases:"
"You can select another interpolation algorithm, such as copying the color of the nearest pixel:"
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 44, "execution_count": 43,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
"plt.imshow(img, interpolation=\"nearest\")\n", "plt.imshow(img, interpolation=\"bilinear\")\n",
"plt.show()" "plt.show()"
] ]
}, },
@ -1073,38 +1072,36 @@
"metadata": {}, "metadata": {},
"source": [ "source": [
"# Animations\n", "# Animations\n",
"Although matplotlib is mostly used to generate images, it is also capable of displaying animations. First, you need to import `matplotlib.animation`. Second, in a Jupyter notebook, you can either use the `nbagg` backend or run the following code." "Although matplotlib is mostly used to generate images, it is also capable of displaying animations. First, you need to import `matplotlib.animation`."
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 45, "execution_count": 44,
"metadata": { "metadata": {
"collapsed": true,
"jupyter": { "jupyter": {
"outputs_hidden": true "outputs_hidden": true
} }
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
"import matplotlib.animation as animation\n", "import matplotlib.animation as animation"
"matplotlib.rc('animation', html='jshtml')"
] ]
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"In this example, we start by creating data points, then we create an empty plot, we define the update function that will be called at every iteration of the animation, and finally we add an animation to the plot by creating a `FuncAnimation` instance.\n", "In the following example, we start by creating data points, then we create an empty plot, we define the update function that will be called at every iteration of the animation, and finally we add an animation to the plot by creating a `FuncAnimation` instance.\n",
"\n", "\n",
"The `FuncAnimation` constructor takes a figure, an update function and optional arguments. We specify that we want a 100-frame long animation, with 20ms between each frame. At each iteration, `FuncAnimation` calls our update function and passes it the frame number `num` (from 0 to 99 in our case) followed by the extra arguments that we specified with `fargs`.\n", "The `FuncAnimation` constructor takes a figure, an update function and optional arguments. We specify that we want a 50-frame long animation, with 100ms between each frame. At each iteration, `FuncAnimation` calls our update function and passes it the frame number `num` (from 0 to 49 in our case) followed by the extra arguments that we specified with `fargs`.\n",
"\n", "\n",
"Our update function simply sets the line data to be the first `num` data points (so the data gets drawn gradually), and just for fun we also add a small random number to each data point so that the line appears to wiggle." "Our update function simply sets the line data to be the first `num` data points (so the data gets drawn gradually), and just for fun we also add a small random number to each data point so that the line appears to wiggle."
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 46, "execution_count": 45,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -1124,9 +1121,81 @@
" line.set_data(data[..., :num] + np.random.rand(2, num) / 25) # we only plot the first `num` data points.\n", " line.set_data(data[..., :num] + np.random.rand(2, num) / 25) # we only plot the first `num` data points.\n",
" return line,\n", " return line,\n",
"\n", "\n",
"line_ani = animation.FuncAnimation(fig, update_line, frames=100, fargs=(data, line), interval=67)\n", "line_ani = animation.FuncAnimation(fig, update_line, frames=50, fargs=(data, line), interval=100)\n",
"plt.close()\n", "plt.close() # call close() to avoid displaying the static plot"
"line_ani" ]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Next, let's display the animation. One option is to convert it to HTML5 code (using a `<video>` tag), and render this code using `IPython.display.HTML`:"
]
},
{
"cell_type": "code",
"execution_count": 46,
"metadata": {},
"outputs": [],
"source": [
"from IPython.display import HTML\n",
"\n",
"HTML(line_ani.to_html5_video())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Alternatively, we can display the animation using a nice little HTML/Javascript interactive widget:"
]
},
{
"cell_type": "code",
"execution_count": 47,
"metadata": {},
"outputs": [],
"source": [
"HTML(line_ani.to_jshtml())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You can configure Matplotlib to use this widget by default when rendering animations:"
]
},
{
"cell_type": "code",
"execution_count": 48,
"metadata": {},
"outputs": [],
"source": [
"matplotlib.rc('animation', html='jshtml')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"After that, you don't even need to use `IPython.display.HTML` anymore:"
]
},
{
"cell_type": "code",
"execution_count": 49,
"metadata": {},
"outputs": [],
"source": [
"animation.FuncAnimation(fig, update_line, frames=50, fargs=(data, line), interval=100)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Warning:** if you save the notebook along with its outputs, then the animations will take up a lot of space."
] ]
}, },
{ {
@ -1139,7 +1208,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 47, "execution_count": 50,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [