From ef4032634cf4d942a48d2a58de90bde4df47ffd8 Mon Sep 17 00:00:00 2001 From: Andrew Conti Date: Mon, 24 Jun 2013 12:06:51 -0400 Subject: [PATCH] fixed example display error --- Central Limit Theroem.ipynb | 107408 +++++++++++++++++++++++++++++---- 1 file changed, 96725 insertions(+), 10683 deletions(-) diff --git a/Central Limit Theroem.ipynb b/Central Limit Theroem.ipynb index 81a3de5..76d9fde 100644 --- a/Central Limit Theroem.ipynb +++ b/Central Limit Theroem.ipynb @@ -11071,7 +11071,7 @@ "# http://matplotlib.sourceforge.net/api/animation_api.html\n", "#anim.save('basic_animation.mp4', fps=30, extra_args=['-vcodec', 'libx264'])\n", "\n", - "display_animation(ani)" + "display_animation(anim)" ], "language": "python", "metadata": {}, @@ -11085,7 +11085,7 @@ " this.img_id = img_id;\n", " this.slider_id = slider_id;\n", " this.loop_select_id = loop_select_id;\n", - " this.interval = 200;\n", + " this.interval = 20;\n", " this.current_frame = 0;\n", " this.direction = 0;\n", " this.timer = null;\n", @@ -11216,12 +11216,12 @@ "\n", "\n", "
\n", - " \n", + " \n", "
\n", - " \n", + " \n", "
\n", - " \n", - " \n", + " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
\n", - " Once \n", - " Loop \n", + " \n", + " \n", + " Once \n", + " Loop \n", " Reflect \n", "
\n", "
\n", @@ -11291,10920 +11291,96962 @@ "\n" + ], + "metadata": {}, + "output_type": "pyout", + "prompt_number": 8, + "text": [ + "" + ] + } + ], + "prompt_number": 8 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "###Jake Ball Animation" + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "\"\"\"\n", + "Animation of Elastic collisions with Gravity\n", + "\n", + "author: Jake Vanderplas\n", + "email: vanderplas@astro.washington.edu\n", + "website: http://jakevdp.github.com\n", + "license: BSD\n", + "Please feel free to use and modify this, but keep the above information. Thanks!\n", + "\"\"\"\n", + "import numpy as np\n", + "from scipy.spatial.distance import pdist, squareform\n", + "\n", + "import matplotlib.pyplot as plt\n", + "import scipy.integrate as integrate\n", + "import matplotlib.animation as animation\n", + "\n", + "class ParticleBox:\n", + " \"\"\"Orbits class\n", + " \n", + " init_state is an [N x 4] array, where N is the number of particles:\n", + " [[x1, y1, vx1, vy1],\n", + " [x2, y2, vx2, vy2],\n", + " ... ]\n", + "\n", + " bounds is the size of the box: [xmin, xmax, ymin, ymax]\n", + " \"\"\"\n", + " def __init__(self,\n", + " init_state = [[1, 0, 0, -1],\n", + " [-0.5, 0.5, 0.5, 0.5],\n", + " [-0.5, -0.5, -0.5, 0.5]],\n", + " bounds = [-2, 2, -2, 2],\n", + " size = 0.04,\n", + " M = 0.05,\n", + " G = 9.8):\n", + " self.init_state = np.asarray(init_state, dtype=float)\n", + " self.M = M * np.ones(self.init_state.shape[0])\n", + " self.size = size\n", + " self.state = self.init_state.copy()\n", + " self.time_elapsed = 0\n", + " self.bounds = bounds\n", + " self.G = G\n", + "\n", + " def step(self, dt):\n", + " \"\"\"step once by dt seconds\"\"\"\n", + " self.time_elapsed += dt\n", + " \n", + " # update positions\n", + " self.state[:, :2] += dt * self.state[:, 2:]\n", + "\n", + " # find pairs of particles undergoing a collision\n", + " D = squareform(pdist(self.state[:, :2]))\n", + " ind1, ind2 = np.where(D < 2 * self.size)\n", + " unique = (ind1 < ind2)\n", + " ind1 = ind1[unique]\n", + " ind2 = ind2[unique]\n", + "\n", + " # update velocities of colliding pairs\n", + " for i1, i2 in zip(ind1, ind2):\n", + " # mass\n", + " m1 = self.M[i1]\n", + " m2 = self.M[i2]\n", + "\n", + " # location vector\n", + " r1 = self.state[i1, :2]\n", + " r2 = self.state[i2, :2]\n", + "\n", + " # velocity vector\n", + " v1 = self.state[i1, 2:]\n", + " v2 = self.state[i2, 2:]\n", + "\n", + " # relative location & velocity vectors\n", + " r_rel = r1 - r2\n", + " v_rel = v1 - v2\n", + "\n", + " # momentum vector of the center of mass\n", + " v_cm = (m1 * v1 + m2 * v2) / (m1 + m2)\n", + "\n", + " # collisions of spheres reflect v_rel over r_rel\n", + " rr_rel = np.dot(r_rel, r_rel)\n", + " vr_rel = np.dot(v_rel, r_rel)\n", + " v_rel = 2 * r_rel * vr_rel / rr_rel - v_rel\n", + "\n", + " # assign new velocities\n", + " self.state[i1, 2:] = v_cm + v_rel * m2 / (m1 + m2)\n", + " self.state[i2, 2:] = v_cm - v_rel * m1 / (m1 + m2) \n", + "\n", + " # check for crossing boundary\n", + " crossed_x1 = (self.state[:, 0] < self.bounds[0] + self.size)\n", + " crossed_x2 = (self.state[:, 0] > self.bounds[1] - self.size)\n", + " crossed_y1 = (self.state[:, 1] < self.bounds[2] + self.size)\n", + " crossed_y2 = (self.state[:, 1] > self.bounds[3] - self.size)\n", + "\n", + " self.state[crossed_x1, 0] = self.bounds[0] + self.size\n", + " self.state[crossed_x2, 0] = self.bounds[1] - self.size\n", + "\n", + " self.state[crossed_y1, 1] = self.bounds[2] + self.size\n", + " self.state[crossed_y2, 1] = self.bounds[3] - self.size\n", + "\n", + " self.state[crossed_x1 | crossed_x2, 2] *= -1\n", + " self.state[crossed_y1 | crossed_y2, 3] *= -1\n", + "\n", + " # add gravity\n", + " self.state[:, 3] -= self.M * self.G * dt\n", + "\n", + "\n", + "#------------------------------------------------------------\n", + "# set up initial state\n", + "np.random.seed(0)\n", + "init_state = -0.5 + np.random.random((50, 4))\n", + "init_state[:, :2] *= 3.9\n", + "\n", + "box = ParticleBox(init_state, size=0.04)\n", + "dt = 1. / 30 # 30fps\n", + "\n", + "\n", + "#------------------------------------------------------------\n", + "# set up figure and animation\n", + "fig = plt.figure()\n", + "fig.subplots_adjust(left=0, right=1, bottom=0, top=1)\n", + "ax = fig.add_subplot(111, aspect='equal', autoscale_on=False,\n", + " xlim=(-3.2, 3.2), ylim=(-2.4, 2.4))\n", + "\n", + "# particles holds the locations of the particles\n", + "particles, = ax.plot([], [], 'bo', ms=6)\n", + "\n", + "# rect is the box edge\n", + "rect = plt.Rectangle(box.bounds[::2],\n", + " box.bounds[1] - box.bounds[0],\n", + " box.bounds[3] - box.bounds[2],\n", + " ec='none', lw=2, fc='none')\n", + "ax.add_patch(rect)\n", + "\n", + "def init():\n", + " \"\"\"initialize animation\"\"\"\n", + " global box, rect\n", + " particles.set_data([], [])\n", + " rect.set_edgecolor('none')\n", + " return particles, rect\n", + "\n", + "def animate(i):\n", + " \"\"\"perform animation step\"\"\"\n", + " global box, rect, dt, ax, fig\n", + " box.step(dt)\n", + "\n", + " ms = int(fig.dpi * 2 * box.size * fig.get_figwidth()\n", + " / np.diff(ax.get_xbound())[0])\n", + " \n", + " # update pieces of the animation\n", + " rect.set_edgecolor('k')\n", + " particles.set_data(box.state[:, 0], box.state[:, 1])\n", + " particles.set_markersize(ms)\n", + " return particles, rect\n", + "\n", + "ani = animation.FuncAnimation(fig, animate, frames=600,\n", + " interval=10, blit=True, init_func=init)\n", + "\n", + "\n", + "# save the animation as an mp4. This requires ffmpeg or mencoder to be\n", + "# installed. The extra_args ensure that the x264 codec is used, so that\n", + "# the video can be embedded in html5. You may need to adjust this for\n", + "# your system: for more information, see\n", + "# http://matplotlib.sourceforge.net/api/animation_api.html\n", + "#ani.save('particle_box.mp4', fps=30, extra_args=['-vcodec', 'libx264'])\n", + "\n", + "display_animation(ani)" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "html": [ + "\n", + "\n", + "\n", + "
\n", + " \n", + "
\n", + " \n", + "
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + " Once \n", + " Loop \n", + " Reflect \n", + "
\n", + "
\n", + "\n", + "\n", + "\n" ], "metadata": {}, "output_type": "pyout", - "prompt_number": 4, + "prompt_number": 5, "text": [ - "" - ] - }, - { - "metadata": {}, - "output_type": "display_data", - "png": "iVBORw0KGgoAAAANSUhEUgAAAX4AAAD9CAYAAAC7iRw+AAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAEvJJREFUeJzt3X9olPcBx/HPs1zGOLWNgXrK3UFgly4XG5M41/yV9sp6\nlSTLkf5g6loWNMhhUdd/9sf+akJbq6yj2Api/5irFNRVcAk0HnWjj4NKcn8YxmgEI1vmJTGHkjrU\n/pE0PPuj7Gi8y6/nuSTG7/sFgXvuvvc8Xx4e3z558lxiOY7jCABgjB+s9AQAAMuL8AOAYQg/ABiG\n8AOAYQg/ABiG8AOAYTyFP5PJ6LnnntPmzZv11FNP6YMPPig47uDBg6qsrFRtba0GBga8bBIA4JHP\ny5tLS0v1/vvvq66uTvfu3dNPf/pTxeNxRaPR3Jje3l5dv35dQ0ND6u/v1759+9TX1+d54gAAdzyd\n8W/cuFF1dXWSpLVr1yoajWpsbGzGmJ6eHrW3t0uSGhoadOfOHWWzWS+bBQB44OmM//uGh4c1MDCg\nhoaGGc+Pjo4qHA7nlkOhkEZGRhQIBHLPWZZVrGkAgFHc/PKFovxw9969e3rllVd09OhRrV27dt6J\nFQq94zh8FeHrzTffXPE5PEpf7E/258P85Zbn8E9NTenll1/Wa6+9pra2trzXg8GgMplMbnlkZETB\nYNDrZgEALnkKv+M46ujoUHV1td54442CYxKJhE6dOiVJ6uvrU1lZ2YzLPACA5eXpGv+XX36pTz75\nRFu2bFF9fb0k6dChQ7px44YkKZlMqrm5Wb29vYpEIlqzZo1OnjzpfdaYVSwWW+kpPFLYn8XF/nw4\nWI6XC0XFmoRlebpeBQAmcttOPrkLAIYh/ABgGMIPAIYh/ABgGMIPAIYh/ABgGMIPAIYh/ABgGMIP\nAIYh/ABgGMIPAIYh/ABgGMIPAIYh/ABgGMIPAIYh/ABgGMIPAIYh/ABgGMIPAIbxFP49e/YoEAio\npqam4Ou2bevxxx9XfX296uvr9fbbb3vZHACgCHxe3rx7924dOHBAv/71r2cd8+yzz6qnp8fLZgAA\nReTpjL+xsVHr16+fc4ybvwAPAFg6ns7452NZli5fvqza2loFg0G99957qq6uLji2s7Mz9zgWiykW\niy3l1ABg1bFtW7Zte16P5Xg8JR8eHlZra6v++c9/5r129+5dlZSUyO/368KFC/rNb36ja9eu5U/C\nsvjOAAAWyW07l/SunnXr1snv90uSmpqaNDU1pYmJiaXcJABgHksa/mw2m/vfKJ1Oy3EclZeXL+Um\nAQDz8HSNf9euXbp06ZJu376tcDisrq4uTU1NSZKSyaTOnTun48ePy+fzye/368yZM0WZNADAPc/X\n+IsyCa7xA8CiPZTX+AEADx/CDwCGIfwAYBjCDwCGIfwAYBjCDwCGIfwAYBjCDwCGIfwAYBjCDwCG\nIfwAYBjCDwCGIfwAYBjCDwCGIfwAYBjCDwCGIfwAYBjCDwCG8RT+PXv2KBAIqKamZtYxBw8eVGVl\npWprazUwMOBlcwCAIvAU/t27dyuVSs36em9vr65fv66hoSF99NFH2rdvn5fNAQCKwFP4GxsbtX79\n+llf7+npUXt7uySpoaFBd+7cUTab9bJJAIBHvqVc+ejoqMLhcG45FAppZGREgUAgb2xnZ2fucSwW\nUywWW8qpAcCqY9u2bNv2vJ4lDb8kOY4zY9myrILjvh9+AEC+B0+Ku7q6XK1nSe/qCQaDymQyueWR\nkREFg8Gl3CQAYB5LGv5EIqFTp05Jkvr6+lRWVlbwMg8AYPl4utSza9cuXbp0Sbdv31Y4HFZXV5em\npqYkSclkUs3Nzert7VUkEtGaNWt08uTJokwaAOCe5Tx4EX4lJmFZeT8LAADMzW07+eQuABiG8AOA\nYQg/ABiG8AOAYQg/ABiG8AOAYQg/ABiG8AOAYQg/ABiG8AOAYQg/ABiG8AOAYQg/ABiG8AOAYQg/\nABiG8AOAYQg/ABiG8AOAYQg/ABjGc/hTqZSqqqpUWVmpI0eO5L1u27Yef/xx1dfXq76+Xm+//bbX\nTQIAPPB5efP09LT279+vv/71rwoGg/rZz36mRCKhaDQ6Y9yzzz6rnp4eTxMFABSHpzP+dDqtSCSi\niooKlZaWaufOneru7s4b5+avwAMAloanM/7R0VGFw+HccigUUn9//4wxlmXp8uXLqq2tVTAY1Hvv\nvafq6uq8dXV2duYex2IxxWIxL1MDgEeObduybdvzejyF37Ksecds3bpVmUxGfr9fFy5cUFtbm65d\nu5Y37vvhBwDke/CkuKury9V6PF3qCQaDymQyueVMJqNQKDRjzLp16+T3+yVJTU1Nmpqa0sTEhJfN\nAgA88BT+bdu2aWhoSMPDw5qcnNTZs2eVSCRmjMlms7lr/Ol0Wo7jqLy83MtmAQAeeLrU4/P5dOzY\nMW3fvl3T09Pq6OhQNBrViRMnJEnJZFLnzp3T8ePH5fP55Pf7debMmaJMHADgjuU8BLfcWJbFnT8A\nsEhu28kndwHAMIQfAAxD+AHAMIQfAAxD+AHAMIQfAAxD+AHAMIQfAAxD+AHAMIQfAAxD+AHAMIQf\nAAxD+AHAMIQfAAxD+AHAMIQfAAxD+AHAMIQfAAxD+AHAMJ7Dn0qlVFVVpcrKSh05cqTgmIMHD6qy\nslK1tbUaGBjwukkAgAeewj89Pa39+/crlUppcHBQp0+f1tWrV2eM6e3t1fXr1zU0NKSPPvpI+/bt\n8zRhAIA3nsKfTqcViURUUVGh0tJS7dy5U93d3TPG9PT0qL29XZLU0NCgO3fuKJvNetksAMADn5c3\nj46OKhwO55ZDoZD6+/vnHTMyMqJAIDBjXGdnZ+5xLBZTLBbzMjUAeOTYti3btj2vx1P4Lcta0DjH\nceZ93/fDDwDI9+BJcVdXl6v1eLrUEwwGlclkcsuZTEahUGjOMSMjIwoGg142CwDwwFP4t23bpqGh\nIQ0PD2tyclJnz55VIpGYMSaRSOjUqVOSpL6+PpWVleVd5gEALB9Pl3p8Pp+OHTum7du3a3p6Wh0d\nHYpGozpx4oQkKZlMqrm5Wb29vYpEIlqzZo1OnjxZlIkDANyxnAcvwK/EJCwr7+cAAIC5uW0nn9wF\nAMMQfgAwDOEHAMMQfgAwDOEHAMMQfgAwDOEHAMMQfgAwDOEHAMMQfgAwDOEHAMMQfgAwDOEHAMMQ\nfgAwDOEHAMMQfgAwDOEHAMMQfgAwDOEHAMO4/mPrExMT2rFjh/7zn/+ooqJCf/7zn1VWVpY3rqKi\nQo899phKSkpUWlqqdDrtacIAAG9cn/EfPnxY8Xhc165d089//nMdPny44DjLsmTbtgYGBog+ADwE\nXIe/p6dH7e3tkqT29nb95S9/mXWsm78CDwBYGq4v9WSzWQUCAUlSIBBQNpstOM6yLD3//PMqKSlR\nMpnU3r17C47r7OzMPY7FYorFYm6nBgCPJNu2Zdu25/VYzhyn4/F4XOPj43nPv/POO2pvb9fXX3+d\ne668vFwTExN5Y2/evKlNmzbp1q1bisfj+vDDD9XY2DhzEpbFdwUAsEhu2znnGf/FixdnfS0QCGh8\nfFwbN27UzZs3tWHDhoLjNm3aJEl64okn9OKLLyqdTueFHwCwfFxf408kEvr4448lSR9//LHa2try\nxnzzzTe6e/euJOn+/fv6/PPPVVNT43aTAIAimPNSz1wmJib0y1/+Ujdu3JhxO+fY2Jj27t2rzz77\nTP/617/00ksvSZK+/fZbvfrqq/rd736XPwku9QDAorltp+vwFxPhB4DFc9tOPrkLAIYh/ABgGMIP\nAIYh/ABgGMIPAIYh/ABgGMIPAIYh/ABgGMIPAIYh/ABgGMIPAIYh/ABgGMIPAIYh/ABgGMIPAIYh\n/ABgGMIPAIYh/ABgGMIPAIZxHf5PP/1UmzdvVklJia5cuTLruFQqpaqqKlVWVurIkSNuNwcAKBLX\n4a+pqdH58+f1zDPPzDpmenpa+/fvVyqV0uDgoE6fPq2rV6+63SQAoAh8bt9YVVU175h0Oq1IJKKK\nigpJ0s6dO9Xd3a1oNOp2swAAj1yHfyFGR0cVDodzy6FQSP39/QXHdnZ25h7HYjHFYrGlnBoArDq2\nbcu2bc/rmTP88Xhc4+Pjec8fOnRIra2t867csqwFT+T74QcA5HvwpLirq8vVeuYM/8WLF12t9P+C\nwaAymUxuOZPJKBQKeVonAMCbotzO6ThOwee3bdumoaEhDQ8Pa3JyUmfPnlUikSjGJgEALrkO//nz\n5xUOh9XX16eWlhY1NTVJksbGxtTS0iJJ8vl8OnbsmLZv367q6mrt2LGDH+wCwAqznNlO15dzEpY1\n63cNAIDC3LaTT+4CgGEIPwAYhvADgGEIPwAYhvADgGEIPwAYhvADgGEIPwAYhvADgGEIPwAYhvAD\ngGEIPwAYhvADgGEIPwAYhvADgGEIPwAYhvADgGEIPwAYhvADgGFch//TTz/V5s2bVVJSoitXrsw6\nrqKiQlu2bFF9fb2efvppt5sDABSJz+0ba2pqdP78eSWTyTnHWZYl27ZVXl7udlMAgCJyHf6qqqoF\nj3XzV+ABAEvDdfgXyrIsPf/88yopKVEymdTevXsLjuvs7Mw9jsViisViSz01AFhVbNuWbdue12M5\nc5yOx+NxjY+P5z1/6NAhtba2SpKee+45/eEPf9DWrVsLruPmzZvatGmTbt26pXg8rg8//FCNjY0z\nJ2FZfFcAAIvktp1znvFfvHjR9YT+b9OmTZKkJ554Qi+++KLS6XRe+AEAy6cot3PO9j/ON998o7t3\n70qS7t+/r88//1w1NTXF2CQAwCXX4T9//rzC4bD6+vrU0tKipqYmSdLY2JhaWlokSePj42psbFRd\nXZ0aGhr0i1/8Qi+88EJxZg4AcGXOa/zLNgmu8QPAorltJ5/cBQDDEH4AMAzhBwDDEH4AMAzhBwDD\nEH4AMAzhBwDDEH4AMAzhBwDDEH4AMAzhBwDDEH4AMAzhBwDDEH4AMAzhBwDDEH4AMAzhBwDDEH4A\nMAzhf8TYtr3SU3iksD+Li/35cHAd/t/+9reKRqOqra3VSy+9pP/+978Fx6VSKVVVVamyslJHjhxx\nPVEsDP+wiov9WVzsz4eD6/C/8MIL+uqrr/SPf/xDTz75pN599928MdPT09q/f79SqZQGBwd1+vRp\nXb161dOEAQDeuA5/PB7XD37w3dsbGho0MjKSNyadTisSiaiiokKlpaXauXOnuru73c8WAOCZrxgr\n+eMf/6hdu3blPT86OqpwOJxbDoVC6u/vL7gOy7KKMRVI6urqWukpPFLYn8XF/lx5c4Y/Ho9rfHw8\n7/lDhw6ptbVVkvTOO+/ohz/8oX71q1/ljVtozB3HWdA4AIB3c4b/4sWLc775T3/6k3p7e/W3v/2t\n4OvBYFCZTCa3nMlkFAqFXEwTAFAsrq/xp1Ip/f73v1d3d7d+9KMfFRyzbds2DQ0NaXh4WJOTkzp7\n9qwSiYTryQIAvHMd/gMHDujevXuKx+Oqr6/X66+/LkkaGxtTS0uLJMnn8+nYsWPavn27qqurtWPH\nDkWj0eLMHADgjrOMLly44PzkJz9xIpGIc/jw4YJjDhw44EQiEWfLli3OlStXlnN6q858+/OLL75w\nHnvsMaeurs6pq6tz3nrrrRWY5eqwe/duZ8OGDc5TTz016xiOzYWZb19yXC7OjRs3nFgs5lRXVzub\nN292jh49WnDcYo7PZQv/t99+6/z4xz92/v3vfzuTk5NObW2tMzg4OGPMZ5995jQ1NTmO4zh9fX1O\nQ0PDck1v1VnI/vziiy+c1tbWFZrh6vL3v//duXLlyqyx4thcuPn2Jcfl4ty8edMZGBhwHMdx7t69\n6zz55JOe27lsv7JhIff09/T0qL29XdJ3nw24c+eOstnsck1xVVnoZyQc7phakMbGRq1fv37W1zk2\nF26+fSlxXC7Gxo0bVVdXJ0lau3atotGoxsbGZoxZ7PG5bOEvdE//6OjovGMKfTAMC9uflmXp8uXL\nqq2tVXNzswYHB5d7mo8Mjs3i4bh0b3h4WAMDA2poaJjx/GKPz6J8gGsh3N7Tzwe7ClvIftm6dasy\nmYz8fr8uXLigtrY2Xbt2bRlm92ji2CwOjkt37t27p1deeUVHjx7V2rVr815fzPG5bGf8C7mn/8Ex\nIyMjCgaDyzXFVWUh+3PdunXy+/2SpKamJk1NTWliYmJZ5/mo4NgsHo7LxZuamtLLL7+s1157TW1t\nbXmvL/b4XLbwL+Se/kQioVOnTkmS+vr6VFZWpkAgsFxTXFUWsj+z2WzuLCCdTstxHJWXl6/EdFc9\njs3i4bhcHMdx1NHRoerqar3xxhsFxyz2+Fy2Sz3fv6d/enpaHR0dikajOnHihCQpmUyqublZvb29\nikQiWrNmjU6ePLlc01t1FrI/z507p+PHj8vn88nv9+vMmTMrPOuH165du3Tp0iXdvn1b4XBYXV1d\nmpqaksSxuVjz7UuOy8X58ssv9cknn2jLli2qr6+X9N2vzblx44Ykd8en5fDjdQAwCn+BCwAMQ/gB\nwDCEHwAMQ/gBwDCEHwAMQ/gBwDD/A+g1xh3vSvESAAAAAElFTkSuQmCC\n", - "text": [ - "" + "" ] } ], - "prompt_number": "*" + "prompt_number": 5 }, { "cell_type": "markdown", "metadata": {}, "source": [ - "###Jake Ball Animation" + "###Version Control" ] }, { "cell_type": "code", "collapsed": false, "input": [ - "\"\"\"\n", - "Animation of Elastic collisions with Gravity\n", - "\n", - "author: Jake Vanderplas\n", - "email: vanderplas@astro.washington.edu\n", - "website: http://jakevdp.github.com\n", - "license: BSD\n", - "Please feel free to use and modify this, but keep the above information. Thanks!\n", - "\"\"\"\n", - "import numpy as np\n", - "from scipy.spatial.distance import pdist, squareform\n", - "\n", - "import matplotlib.pyplot as plt\n", - "import scipy.integrate as integrate\n", - "import matplotlib.animation as animation\n", - "\n", - "class ParticleBox:\n", - " \"\"\"Orbits class\n", - " \n", - " init_state is an [N x 4] array, where N is the number of particles:\n", - " [[x1, y1, vx1, vy1],\n", - " [x2, y2, vx2, vy2],\n", - " ... ]\n", - "\n", - " bounds is the size of the box: [xmin, xmax, ymin, ymax]\n", - " \"\"\"\n", - " def __init__(self,\n", - " init_state = [[1, 0, 0, -1],\n", - " [-0.5, 0.5, 0.5, 0.5],\n", - " [-0.5, -0.5, -0.5, 0.5]],\n", - " bounds = [-2, 2, -2, 2],\n", - " size = 0.04,\n", - " M = 0.05,\n", - " G = 9.8):\n", - " self.init_state = np.asarray(init_state, dtype=float)\n", - " self.M = M * np.ones(self.init_state.shape[0])\n", - " self.size = size\n", - " self.state = self.init_state.copy()\n", - " self.time_elapsed = 0\n", - " self.bounds = bounds\n", - " self.G = G\n", - "\n", - " def step(self, dt):\n", - " \"\"\"step once by dt seconds\"\"\"\n", - " self.time_elapsed += dt\n", - " \n", - " # update positions\n", - " self.state[:, :2] += dt * self.state[:, 2:]\n", - "\n", - " # find pairs of particles undergoing a collision\n", - " D = squareform(pdist(self.state[:, :2]))\n", - " ind1, ind2 = np.where(D < 2 * self.size)\n", - " unique = (ind1 < ind2)\n", - " ind1 = ind1[unique]\n", - " ind2 = ind2[unique]\n", - "\n", - " # update velocities of colliding pairs\n", - " for i1, i2 in zip(ind1, ind2):\n", - " # mass\n", - " m1 = self.M[i1]\n", - " m2 = self.M[i2]\n", - "\n", - " # location vector\n", - " r1 = self.state[i1, :2]\n", - " r2 = self.state[i2, :2]\n", - "\n", - " # velocity vector\n", - " v1 = self.state[i1, 2:]\n", - " v2 = self.state[i2, 2:]\n", - "\n", - " # relative location & velocity vectors\n", - " r_rel = r1 - r2\n", - " v_rel = v1 - v2\n", - "\n", - " # momentum vector of the center of mass\n", - " v_cm = (m1 * v1 + m2 * v2) / (m1 + m2)\n", - "\n", - " # collisions of spheres reflect v_rel over r_rel\n", - " rr_rel = np.dot(r_rel, r_rel)\n", - " vr_rel = np.dot(v_rel, r_rel)\n", - " v_rel = 2 * r_rel * vr_rel / rr_rel - v_rel\n", - "\n", - " # assign new velocities\n", - " self.state[i1, 2:] = v_cm + v_rel * m2 / (m1 + m2)\n", - " self.state[i2, 2:] = v_cm - v_rel * m1 / (m1 + m2) \n", - "\n", - " # check for crossing boundary\n", - " crossed_x1 = (self.state[:, 0] < self.bounds[0] + self.size)\n", - " crossed_x2 = (self.state[:, 0] > self.bounds[1] - self.size)\n", - " crossed_y1 = (self.state[:, 1] < self.bounds[2] + self.size)\n", - " crossed_y2 = (self.state[:, 1] > self.bounds[3] - self.size)\n", - "\n", - " self.state[crossed_x1, 0] = self.bounds[0] + self.size\n", - " self.state[crossed_x2, 0] = self.bounds[1] - self.size\n", - "\n", - " self.state[crossed_y1, 1] = self.bounds[2] + self.size\n", - " self.state[crossed_y2, 1] = self.bounds[3] - self.size\n", - "\n", - " self.state[crossed_x1 | crossed_x2, 2] *= -1\n", - " self.state[crossed_y1 | crossed_y2, 3] *= -1\n", - "\n", - " # add gravity\n", - " self.state[:, 3] -= self.M * self.G * dt\n", - "\n", - "\n", - "#------------------------------------------------------------\n", - "# set up initial state\n", - "np.random.seed(0)\n", - "init_state = -0.5 + np.random.random((50, 4))\n", - "init_state[:, :2] *= 3.9\n", - "\n", - "box = ParticleBox(init_state, size=0.04)\n", - "dt = 1. / 30 # 30fps\n", - "\n", - "\n", - "#------------------------------------------------------------\n", - "# set up figure and animation\n", - "fig = plt.figure()\n", - "fig.subplots_adjust(left=0, right=1, bottom=0, top=1)\n", - "ax = fig.add_subplot(111, aspect='equal', autoscale_on=False,\n", - " xlim=(-3.2, 3.2), ylim=(-2.4, 2.4))\n", - "\n", - "# particles holds the locations of the particles\n", - "particles, = ax.plot([], [], 'bo', ms=6)\n", - "\n", - "# rect is the box edge\n", - "rect = plt.Rectangle(box.bounds[::2],\n", - " box.bounds[1] - box.bounds[0],\n", - " box.bounds[3] - box.bounds[2],\n", - " ec='none', lw=2, fc='none')\n", - "ax.add_patch(rect)\n", - "\n", - "def init():\n", - " \"\"\"initialize animation\"\"\"\n", - " global box, rect\n", - " particles.set_data([], [])\n", - " rect.set_edgecolor('none')\n", - " return particles, rect\n", - "\n", - "def animate(i):\n", - " \"\"\"perform animation step\"\"\"\n", - " global box, rect, dt, ax, fig\n", - " box.step(dt)\n", - "\n", - " ms = int(fig.dpi * 2 * box.size * fig.get_figwidth()\n", - " / np.diff(ax.get_xbound())[0])\n", - " \n", - " # update pieces of the animation\n", - " rect.set_edgecolor('k')\n", - " particles.set_data(box.state[:, 0], box.state[:, 1])\n", - " particles.set_markersize(ms)\n", - " return particles, rect\n", - "\n", - "ani = animation.FuncAnimation(fig, animate, frames=600,\n", - " interval=10, blit=True, init_func=init)\n", - "\n", - "\n", - "# save the animation as an mp4. This requires ffmpeg or mencoder to be\n", - "# installed. The extra_args ensure that the x264 codec is used, so that\n", - "# the video can be embedded in html5. You may need to adjust this for\n", - "# your system: for more information, see\n", - "# http://matplotlib.sourceforge.net/api/animation_api.html\n", - "#ani.save('particle_box.mp4', fps=30, extra_args=['-vcodec', 'libx264'])\n", - "\n", - "display_animation(ani)" + "!git add \"Central Limit Theroem.ipynb\"" ], "language": "python", "metadata": {}, "outputs": [], - "prompt_number": "*" - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "###Version Control" - ] + "prompt_number": 9 }, { "cell_type": "code", "collapsed": false, "input": [ - "!git add \"Central Limit Theroem.ipynb\"" + "!git commit " ], "language": "python", "metadata": {}, - "outputs": [], - "prompt_number": "*" + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "# On branch master\n", + "# Untracked files:\n", + "# (use \"git add ...\" to include in what will be committed)\n", + "#\n", + "#\t.ipynb_checkpoints/\n", + "#\tMagicTriangle.ipynb\n", + "#\tOlympicAthletes.csv\n", + "#\tcentral_lim.js\n", + "#\ttmp_output_fdsahkrkdkskrt.html\n", + "nothing added to commit but untracked files present (use \"git add\" to track)\n" + ] + } + ], + "prompt_number": 10 }, { "cell_type": "code", "collapsed": false, - "input": [ - "!git commit " - ], + "input": [], "language": "python", "metadata": {}, - "outputs": [], - "prompt_number": "*" + "outputs": [] } ], "metadata": {}