{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Custom Display Logic Exercises" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false }, "outputs": [], "source": [ "from IPython.display import display\n", "from IPython.display import (\n", " display_png, display_html, display_latex,\n", " display_javascript, display_svg\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Circle class with custom display methods" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Write a simple `MyCircle` Python class. Here is a skeleton to get you started:\n", "\n", "```python\n", "class MyCircle(object):\n", " def __init__(self, center=(0.0,0.0), radius=1.0, color='blue'):\n", " self.center = center\n", " self.radius = radius\n", " self.color = color\n", "```\n", "\n", "Now add special display methods to this class for the following representations (remember to wrap them in Python strings):\n", "\n", "For HTML:\n", "\n", " ○\n", "\n", "For LaTeX (wrap with `$` and use a raw Python string):\n", "\n", " \\bigcirc\n", "\n", "For JavaScript:\n", "\n", " alert('I am a circle!');\n", "\n", "After you write the class, create an instance and then use `display_html`, `display_svg`, `display_latex` and `display_javascript` to display those representations." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Solution" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here is the solution to the simple `MyCircle` class:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%load soln/mycircle.py" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now create an instance and use the display methods:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "c = MyCircle()" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "display(c)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "display_html(c)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "display_latex(c)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## PNG formatter for `MyCircle`" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%matplotlib inline\n", "from matplotlib import pyplot as plt" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now let's assume that the `MyCircle` class has already been defined and add a PNG representation using a formatter display function. Here is a function that converts a `MyCircle` instance to raw PNG data." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "from IPython.core.pylabtools import print_figure\n", "\n", "def circle_to_png(circle):\n", " \"\"\"Render AnotherCircle to png data using matplotlib\"\"\"\n", " fig, ax = plt.subplots()\n", " patch = plt.Circle(circle.center,\n", " radius=circle.radius,\n", " fc=circle.color,\n", " )\n", " ax.add_patch(patch)\n", " plt.axis('scaled')\n", " data = print_figure(fig, 'png')\n", " # We MUST close the figure, otherwise IPython's display machinery\n", " # will pick it up and send it as output, resulting in a double display\n", " plt.close(fig)\n", " return data" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now use the IPython API to get the PNG formatter (`image/png`) and call the `for_type` method to register `circle_to_png` as the display function for `MyCircle`." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%load soln/mycircle_png.py" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "display_png(c)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## PNG formatter for NumPy arrays" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In this exercise, you will register a display formatter function that generates a PNG representation of a 2d NumPy array. Here is the function that uses the [Python Imaging Library (PIL)](http://www.pythonware.com/products/pil/) to generate the raw PNG data:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "from PIL import Image\n", "from io import BytesIO\n", "import numpy as np\n", "\n", "def ndarray_to_png(x):\n", " if len(x.shape) != 2: return\n", " x = np.asarray(Image.fromarray(x).resize((500, 500)))\n", " x = (x - x.min()) / (x.max() - x.min())\n", " img = Image.fromarray((x*256).astype('uint8'))\n", " img_buffer = BytesIO()\n", " img.save(img_buffer, format='png')\n", " return img_buffer.getvalue()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Use the `for_type` method of the PNG formatter to register `ndarray_to_png` as the display function for `np.ndarray`." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%load soln/ndarray_png.py" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now create a few NumPy arrays and display them. Notice that their default representation in the Notebook is PNG rather than text." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "a = np.random.rand(100,100)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "a" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can still display the plain text representation using the `display_pretty` function." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "from IPython.display import display_pretty" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "display_pretty(a)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "b = np.linspace(0,100.0, 100**2).reshape((100,100))" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "b" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.3" } }, "nbformat": 4, "nbformat_minor": 2 }