#!/usr/bin/env python # coding: utf-8 # # Custom Display Logic Exercises # In[1]: from IPython.display import display from IPython.display import ( display_png, display_html, display_latex, display_javascript, display_svg ) # ## Circle class with custom display methods # Write a simple `MyCircle` Python class. Here is a skeleton to get you started: # # ```python # class MyCircle(object): # def __init__(self, center=(0.0,0.0), radius=1.0, color='blue'): # self.center = center # self.radius = radius # self.color = color # ``` # # Now add special display methods to this class for the following representations (remember to wrap them in Python strings): # # For HTML: # # ○ # # For LaTeX (wrap with `$` and use a raw Python string): # # \bigcirc # # For JavaScript: # # alert('I am a circle!'); # # After you write the class, create an instance and then use `display_html`, `display_svg`, `display_latex` and `display_javascript` to display those representations. # ### Solution # Here is the solution to the simple `MyCircle` class: # In[ ]: get_ipython().run_line_magic('load', 'soln/mycircle.py') # Now create an instance and use the display methods: # In[ ]: c = MyCircle() # In[ ]: display(c) # In[ ]: display_html(c) # In[ ]: display_latex(c) # ## PNG formatter for `MyCircle` # In[ ]: get_ipython().run_line_magic('matplotlib', 'inline') from matplotlib import pyplot as plt # 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. # In[ ]: from IPython.core.pylabtools import print_figure def circle_to_png(circle): """Render AnotherCircle to png data using matplotlib""" fig, ax = plt.subplots() patch = plt.Circle(circle.center, radius=circle.radius, fc=circle.color, ) ax.add_patch(patch) plt.axis('scaled') data = print_figure(fig, 'png') # We MUST close the figure, otherwise IPython's display machinery # will pick it up and send it as output, resulting in a double display plt.close(fig) return data # 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`. # In[ ]: get_ipython().run_line_magic('load', 'soln/mycircle_png.py') # In[ ]: display_png(c) # ## PNG formatter for NumPy arrays # 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: # In[ ]: from PIL import Image from io import BytesIO import numpy as np def ndarray_to_png(x): if len(x.shape) != 2: return x = np.asarray(Image.fromarray(x).resize((500, 500))) x = (x - x.min()) / (x.max() - x.min()) img = Image.fromarray((x*256).astype('uint8')) img_buffer = BytesIO() img.save(img_buffer, format='png') return img_buffer.getvalue() # Use the `for_type` method of the PNG formatter to register `ndarray_to_png` as the display function for `np.ndarray`. # In[ ]: get_ipython().run_line_magic('load', 'soln/ndarray_png.py') # Now create a few NumPy arrays and display them. Notice that their default representation in the Notebook is PNG rather than text. # In[ ]: a = np.random.rand(100,100) # In[ ]: a # You can still display the plain text representation using the `display_pretty` function. # In[ ]: from IPython.display import display_pretty # In[ ]: display_pretty(a) # In[ ]: b = np.linspace(0,100.0, 100**2).reshape((100,100)) # In[ ]: b