{ "metadata": { "name": "" }, "nbformat": 3, "nbformat_minor": 0, "worksheets": [ { "cells": [ { "cell_type": "heading", "level": 1, "metadata": {}, "source": [ "Fourier reconstruction of elephant in complex plane" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "###Hypothesis: \n", "- \"With four parameters I can fit an elephant, and with five I can make him wiggle his trunk\" --John von Neumann\n", "\n", "###Solution:\n", "- \"Drawing an elephant with four complex parameters\", Mayer et al, 2010\n", "\n", "- Available here: http://java-srv1.mpi-cbg.de/publications/getDocument.html?id=ff8080812daff75c012dc1b7bc10000c\n", "\n", "###Implementation of solution\n", "- Based on code from here: http://www.johndcook.com/blog/2011/06/21/how-to-fit-an-elephant/\n", "\n", "- Modified to make JavaScript animation possible (worker function needed)" ] }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "Functions for elephant reconstruction based on four complex numbers" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "... plus one complex number to wiggle the trunk and to add the elephant's eye" ] }, { "cell_type": "code", "collapsed": false, "input": [ "\"\"\"\n", "Author: Piotr A. Zolnierczuk (zolnierczukp at ornl dot gov)\n", " \n", "Based on a paper by:\n", "Drawing an elephant with four complex parameters\n", "Jurgen Mayer, Khaled Khairy, and Jonathon Howard,\n", "Am. J. Phys. 78, 648 (2010), DOI:10.1119/1.3254017\n", "\"\"\"\n", "import numpy as np\n", " \n", "# elephant parameters\n", "p1, p2, p3, p4 = (50 - 30j, 18 + 8j, 12 - 10j, -14 - 60j )\n", "p5 = 40 + 20j # wiggle factor and eyepiece\n", " \n", "def fourier(t, C):\n", " f = np.zeros(t.shape)\n", " A, B = C.real, C.imag\n", " for k in range(len(C)):\n", " f = f + A[k]*np.cos(k*t) + B[k]*np.sin(k*t)\n", " return f\n", " \n", "def elephant(t, p1, p2, p3, p4, p5):\n", " npar = 6\n", " Cx = np.zeros((npar,), dtype='complex')\n", " Cy = np.zeros((npar,), dtype='complex')\n", " \n", " Cx[1] = p1.real*1j\n", " Cx[2] = p2.real*1j\n", " Cx[3] = p3.real\n", " Cx[5] = p4.real\n", " \n", " Cy[1] = p4.imag + p1.imag*1j\n", " Cy[2] = p2.imag*1j\n", " Cy[3] = p3.imag*1j\n", " \n", " x = np.append(fourier(t,Cx), [-p5.imag])\n", " y = np.append(fourier(t,Cy), [p5.imag])\n", " \n", " # wiggle the trunk (\n", " trunk_i = y>40\n", " x_trunk = x[trunk_i]\n", " N_trunk = len(x_trunk)\n", "# x[trunk_i] = x_trunk * concatenate([linspace(1,p5.real,floor(N_trunk/2.0)), \n", "# linspace(p5.real,1,ceil(N_trunk/2.0))])\n", " x[trunk_i] = x_trunk + concatenate([linspace(0,p5.real,floor(N_trunk/2.0)), \n", " linspace(p5.real,0,ceil(N_trunk/2.0))])\n", " return x,y" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 1 }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "Worker function for JavaScript animation widget: Calculates elephant's $x$ and $y$ and plots it " ] }, { "cell_type": "code", "collapsed": false, "input": [ "def plot_elephant(wiggle=40, p4_real=14, t_p=1.0):\n", " p1, p2, p3, p4 = (50 - 30j, 18 + 8j, 12 - 10j, - p4_real - 60j )\n", " p5 = wiggle + 20j\n", " t = np.linspace(0,2*np.pi,1000)\n", " x, y = elephant(t, p1, p2, p3, p4, p5)\n", " \n", " fig, ax = plt.subplots(figsize=(10, 7))\n", " ax.plot(y,-x,'.')\n", " \n", " #x_p, y_p = elephant(array(t_p/1000.0*2*pi), p1, p2, p3, p4, p5)\n", " #ax.plot(y_p,-x_p,'ro')\n", " \n", " ax.set_xlim(-80, 100)\n", " ax.set_ylim(-80, 100)\n", " fig.suptitle('elephant with wiggle parameter = ' + str(wiggle))\n", " return fig\n", "\n", "#fig = plot_elephant(wiggle=0.5)\n", "#plot_elephant(wiggle=10, p4_real=10)" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 6 }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "Make static JavaScript animation widget" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ipywidgets can be downloaded from here: https://github.com/jakevdp/ipywidgets" ] }, { "cell_type": "code", "collapsed": false, "input": [ "from ipywidgets import StaticInteract, RangeWidget, RadioWidget\n", "StaticInteract(plot_elephant, wiggle=RangeWidget(0,40,5))" ], "language": "python", "metadata": {}, "outputs": [ { "html": [ "\n", " \n", " \n", "
\n", " \n", "
\n", " \n", "
\n", " \n", "
\n", " \n", "
\n", " \n", "
\n", " \n", "
\n", " \n", "
\n", " \n", "
\n", " \n", "
\n", " \n", "
\n", " \n", "
\n", " \n", "
\n", " \n", "
\n", " \n", "
\n", " \n", "
\n", " \n", "
\n", " \n", "
\n", " \n", "
\n", " \n", " \n", "
\n", " " ], "metadata": {}, "output_type": "pyout", "prompt_number": 7, "text": [ "" ] } ], "prompt_number": 7 }, { "cell_type": "heading", "level": 1, "metadata": {}, "source": [ "use slider to wiggle the trunk!" ] } ], "metadata": {} } ] }