diff --git a/Gaussians.ipynb b/Gaussians.ipynb index 90e4130..86a0a38 100644 --- a/Gaussians.ipynb +++ b/Gaussians.ipynb @@ -1,7 +1,7 @@ { "metadata": { "name": "", - "signature": "sha256:df50da4d6f87f1215c25b03c3c6a3aaa704a4ed1187da87af0018921ba07e577" + "signature": "sha256:9a6dc147357bb4522160e2ebc131a4f64e7a03c2500c7f1f5facd8e9dc8248cd" }, "nbformat": 3, "nbformat_minor": 0, @@ -14,6 +14,26 @@ "source": [ "#Gaussian Probabilities\n", "\n", + "Before we begin, we need to set the book's style." + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "#format the book\n", + "import book_format\n", + "book_format.load_style()" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": "" + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ "### Introduction\n", "\n", "The last chapter ended by discussing some of the drawbacks of the Discrete Bayesian filter. For many tracking and filtering problems our desire is to have a filter that is *unimodal* and *continuous*. That is, we want to model our system using floating point math (continuous) and to have only one belief represented (unimodal). For example, we want to say an aircraft is at (12.34381, -95.54321,2389.5) where that is latitude, longitude, and altidue. We do not want our filter to tell us \"it might be at (1,65,78) or at (34,656,98)\" That doesn't match our physical intuition of how the world works, and as we discussed, it is prohibitively expensive to compute.\n", diff --git a/Introduction.ipynb b/Introduction.ipynb index 5aef2ab..229485c 100644 --- a/Introduction.ipynb +++ b/Introduction.ipynb @@ -8,6 +8,26 @@ "worksheets": [ { "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Before we begin, we need to set the book's style." + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "#format the book\n", + "import book_format\n", + "book_format.load_style()" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": "" + }, { "cell_type": "markdown", "metadata": {}, diff --git a/Kalman_Filters.ipynb b/Kalman_Filters.ipynb index 44aff1f..2ebc95a 100644 --- a/Kalman_Filters.ipynb +++ b/Kalman_Filters.ipynb @@ -1,7 +1,7 @@ { "metadata": { "name": "", - "signature": "sha256:3a7b44bd3874a8149fcf6a20285e8a0855662094c0cb4dbb11f3ec3a2e1e7a3c" + "signature": "sha256:eb8fb6c7b3c058958756ae2a421b60bc30ea1fe666e553e82c7d2a8926accdee" }, "nbformat": 3, "nbformat_minor": 0, @@ -12,11 +12,27 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "#Kalman Filters\n", - "\n", - "\n", - "Now that we understand the histogram filter and Gaussians we are prepared to implement a 1D Kalman filter. We will do this exactly as we did the histogram filter - rather than going into the theory we will just develop the code step by step. \n", - "\n", + "# Kalman Filters\n", + "Now that we understand the histogram filter and Gaussians we are prepared to implement a 1D Kalman filter. We will do this exactly as we did the histogram filter - rather than going into the theory we will just develop the code step by step. But first, let's set the book style." + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "#format the book\n", + "import book_format\n", + "book_format.load_style()" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": "" + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ "#Tracking A Dog\n", "\n", "As in the histogram chapter we will be tracking a dog in a long hallway at work. However, in our latest hackathon someone created an RFID tracker that provides a reasonable accurate position for our dog. Suppose the hallway is 100m long. The sensor returns the distance of the dog from the left end of the hallway. So, 23.4 would mean the dog is 23.4 meters from the left end of the hallway.\n", @@ -52,7 +68,8 @@ ], "language": "python", "metadata": {}, - "outputs": [] + "outputs": [], + "prompt_number": "" }, { "cell_type": "markdown", @@ -72,7 +89,8 @@ ], "language": "python", "metadata": {}, - "outputs": [] + "outputs": [], + "prompt_number": "" }, { "cell_type": "markdown", @@ -90,7 +108,6 @@ "%matplotlib inline\n", "import matplotlib.pyplot as plt\n", "import matplotlib.pylab as pylab\n", - "pylab.rcParams['figure.figsize'] = 10,6\n", "\n", "dog = DogSensor (noise=0.0)\n", "xs = []\n", @@ -103,7 +120,8 @@ ], "language": "python", "metadata": {}, - "outputs": [] + "outputs": [], + "prompt_number": "" }, { "cell_type": "markdown", @@ -1376,21 +1394,6 @@ " \n", " " ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "#format the book\n", - "from IPython.core.display import HTML\n", - "def css_styling():\n", - " styles = open(\"./styles/custom2.css\", \"r\").read()\n", - " return HTML(styles)\n", - "css_styling()" - ], - "language": "python", - "metadata": {}, - "outputs": [] } ], "metadata": {} diff --git a/Multidimensional_Kalman_Filters.ipynb b/Multidimensional_Kalman_Filters.ipynb index 86cc84a..0ef772e 100644 --- a/Multidimensional_Kalman_Filters.ipynb +++ b/Multidimensional_Kalman_Filters.ipynb @@ -14,7 +14,26 @@ "source": [ "

Multidimensional

\n", "

Kalman Filters

\n", - "\n", + "Before we begin, we need to set the book's style." + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "#format the book\n", + "import book_format\n", + "book_format.load_style()" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": "" + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ "### Introduction\n", "The techniques in the last chapter are very powerful, but they only work in one dimension. The gaussians represent a mean and variance that are scalars - real numbers. They provide no way to represent multidimensional data, such as the position of a dog in a field. You may retort that you could use two Kalman filters for that case, one tracks the x coordinate and the other tracks the y coordinate. That does work in some cases, but put that thought aside, because soon you will see some enormous benefits to implementing the multidimensional case.\n", "\n", @@ -214,6 +233,8 @@ "import numpy as np\n", "\n", "pylab.rcParams['figure.figsize'] = 12,6\n", + "pylab.rcParams['axes.color_cycle'] = '348ABD, 7A68A6, A60628, 467821, CF4457, 188487, E24A33'\n", + "\n", "P = np.array([[8.,0],[0,10.]])\n", "mu = np.array([2,7])\n", "\n", diff --git a/README.md b/README.md new file mode 100644 index 0000000..8e8f326 --- /dev/null +++ b/README.md @@ -0,0 +1,24 @@ +#[Kalman Filters and Random Signals in Python][http://github.com/rlabbe/Kalman-Filters-and-Random-Signals-in-Python] + +this is a book BLAH BLAH BLAH + +Contents +----- + +[**Introduction**] foo + +[**Chapter 1: You've got me]() + tells you this and that. and the other thing. + +Reading the book +----- + + +Installation +----- + +License +----- + +Contact +----- diff --git a/Untitled0.ipynb b/Untitled0.ipynb index 4499a4a..774acd6 100644 --- a/Untitled0.ipynb +++ b/Untitled0.ipynb @@ -13,11 +13,8 @@ "collapsed": false, "input": [ "#format the book\n", - "from IPython.core.display import HTML\n", - "def css_styling():\n", - " styles = open(\"./styles/custom2.css\", \"r\").read()\n", - " return HTML(styles)\n", - "css_styling()" + "import book_format\n", + "book_format.load_style()" ], "language": "python", "metadata": {}, @@ -49,72 +46,35 @@ "input": [], "language": "python", "metadata": {}, - "outputs": [] + "outputs": [], + "prompt_number": "" }, { "cell_type": "code", "collapsed": false, "input": [ - "def to_array(x):\n", - " try:\n", - " x.shape\n", - " try:\n", - " if type(x) != numpy.ndarray:\n", - " x=asarray(x)[0]\n", - " return x\n", - " except:\n", - " pass\n", + "import ggplot_setup\n", + "%matplotlib inline\n", + "import numpy.random as random\n", + "import matplotlib.pyplot as plt\n", "\n", - " except:\n", - " return array(mat(x)).reshape(1)\n", - "\n", - "def to_cov(x,n):\n", - " try:\n", - " x.shape\n", - " return x\n", - " except:\n", - " return eye(n) * x\n", - " \n", - "def multivariate_gaussian (x, mu, cov):\n", - " \"\"\" This is designed to work the same as scipy.stats.multivariate_normal\n", - " which is available before version 0.14. You may either pass in a \n", - " multivariate set of data:\n", - " multivariate_gaussian (array([1,1]), array([3,4]), eye(2)*1.4)\n", - " or unidimensional data:\n", - " multivariate_gaussian(1, 3, 1.4)\n", - " \n", - " In the multivariate case if cov is a scalar it is interpreted as eye(n)*cov\n", - " \"\"\"\n", - " \n", - " # force all to numpy.array type\n", - " x = to_array(x)\n", - " mu = to_array(mu)\n", - " n = mu.size\n", - " cov = to_cov (cov, n)\n", - "\n", - " det = numpy.sqrt(numpy.prod(numpy.diag(cov)))\n", - " frac = (2*numpy.pi)**(-n/2.0) * (1.0/det)\n", - " fprime = x - mu\n", - " fprime **= 2\n", - " m = frac * numpy.exp(-0.5*numpy.dot(fprime, 1/numpy.diag(cov)))\n", - " return m\n", - "\n" + "xs = range(30)\n", + "ys = [i+random.randn() for i in range(30)]\n", + "plt.scatter(xs,ys)" ], "language": "python", "metadata": {}, - "outputs": [] + "outputs": [], + "prompt_number": "" }, { "cell_type": "code", "collapsed": false, - "input": [ - "print mvg (array([1,1]), array([1,1]), eye(2))\n", - "print mvg (mat([1,1]), mat([1,1]), eye(2))\n", - "print mvg (2,3,1)" - ], + "input": [], "language": "python", "metadata": {}, - "outputs": [] + "outputs": [], + "prompt_number": "" }, { "cell_type": "code", @@ -125,7 +85,8 @@ ], "language": "python", "metadata": {}, - "outputs": [] + "outputs": [], + "prompt_number": "" }, { "cell_type": "code", @@ -197,8 +158,7 @@ ], "language": "python", "metadata": {}, - "outputs": [], - "prompt_number": "" + "outputs": [] }, { "cell_type": "code", @@ -208,6 +168,207 @@ ], "language": "python", "metadata": {}, + "outputs": [] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "import math\n", + "import numpy as np\n", + "import numpy.linalg as linalg\n", + "import matplotlib.pyplot as plt\n", + "import scipy.sparse as sp\n", + "import scipy.sparse.linalg as spln\n", + "\n", + "_two_pi = 2*math.pi\n", + "\n", + "\n", + "def gaussian(x, mean, var):\n", + " \"\"\"returns normal distribution for x given a gaussian with the specified\n", + " mean and variance. All must be scalars\n", + " \"\"\"\n", + " return math.exp((-0.5*(x-mean)**2)/var) / math.sqrt(_two_pi*var)\n", + "\n", + "def mul (a_mu, a_var, b_mu, b_var):\n", + " m = (a_var*b_mu + b_var*a_mu) / (a_var + b_var)\n", + " v = 1. / (1./a_var + 1./b_var)\n", + " return (m, v)\n", + "\n", + "def add (a_mu, a_var, b_mu, b_var):\n", + " return (a_mu+b_mu, a_var+b_var)\n", + "\n", + "\n", + "def multivariate_gaussian(x, mu, cov):\n", + " \"\"\" This is designed to work the same as scipy.stats.multivariate_normal\n", + " which is not available before version 0.14. You may either pass in a\n", + " multivariate set of data:\n", + " multivariate_gaussian (array([1,1]), array([3,4]), eye(2)*1.4)\n", + " multivariate_gaussian (array([1,1,1]), array([3,4,5]), 1.4)\n", + " or unidimensional data:\n", + " multivariate_gaussian(1, 3, 1.4)\n", + "\n", + " In the multivariate case if cov is a scalar it is interpreted as eye(n)*cov\n", + "\n", + " The function gaussian() implements the 1D (univariate)case, and is much\n", + " faster than this function.\n", + " \"\"\"\n", + "\n", + " # force all to numpy.array type\n", + " x = np.array(x, copy=False, ndmin=1)\n", + " mu = np.array(mu,copy=False, ndmin=1)\n", + "\n", + " nx = len(mu)\n", + " cov = _to_cov(cov, nx)\n", + "\n", + " norm_coeff = nx*math.log(2*math.pi) + np.linalg.slogdet(cov)[1]\n", + "\n", + " err = x - mu\n", + " if (sp.issparse(cov)):\n", + " numerator = spln.spsolve(cov, err).T.dot(err)\n", + " else:\n", + " numerator = np.linalg.solve(cov, err).T.dot(err)\n", + "\n", + " return math.exp(-0.5*(norm_coeff + numerator))\n", + "\n", + "\n", + "def norm_plot(mean, var):\n", + " min_x = mean - var * 1.5\n", + " max_x = mean + var * 1.5\n", + "\n", + " xs = np.arange(min_x, max_x, 0.1)\n", + " ys = [gaussian(x,23,5) for x in xs]\n", + " plt.plot(xs,ys)\n", + "\n", + "\n", + "def sigma_ellipse(cov, x=0, y=0, sigma=1, num_pts=100):\n", + " \"\"\" Takes a 2D covariance matrix and generates an ellipse showing the\n", + " contour plot at the specified sigma value. Ellipse is centered at (x,y).\n", + " num_pts specifies how many discrete points are used to generate the\n", + " ellipse.\n", + "\n", + " Returns a tuple containing the ellipse,x, and y, in that order.\n", + " The ellipse is a 2D numpy array with shape (2, num_pts). Row 0 contains the\n", + " x components, and row 1 contains the y coordinates\n", + " \"\"\"\n", + " cov = np.asarray(cov)\n", + "\n", + " L = linalg.cholesky(cov)\n", + " t = np.linspace(0, _two_pi, num_pts)\n", + " unit_circle = np.array([np.cos(t), np.sin(t)])\n", + "\n", + " ellipse = sigma * L.dot(unit_circle)\n", + " ellipse[0] += x\n", + " ellipse[1] += y\n", + " return (ellipse,x,y)\n", + "\n", + "def sigma_ellipses(cov, x=0, y=0, sigma=[1,2], num_pts=100):\n", + " cov = np.asarray(cov)\n", + "\n", + " L = linalg.cholesky(cov)\n", + " t = np.linspace(0, _two_pi, num_pts)\n", + " unit_circle = np.array([np.cos(t), np.sin(t)])\n", + "\n", + " e_list = []\n", + " for s in sigma:\n", + " ellipse = s * L.dot(unit_circle)\n", + " ellipse[0] += x\n", + " ellipse[1] += y\n", + " e_list.append (ellipse)\n", + " return (e_list,x,y)\n", + "\n", + "def plot_covariance_ellipse (cov, x=0, y=0, sigma=1,title=None, axis_equal=True):\n", + " \"\"\" Plots the ellipse of the provided 2x2 covariance matrix.\n", + " \"\"\"\n", + " e = sigma_ellipse (cov, x, y, sigma)\n", + " plot_sigma_ellipse(e, title, axis_equal)\n", + " \n", + "\n", + "def plot_sigma_ellipse(ellipse, title=None, axis_equal=True):\n", + " \"\"\" plots the ellipse produced from sigma_ellipse.\"\"\"\n", + "\n", + " if axis_equal:\n", + " plt.axis('equal')\n", + "\n", + " e = ellipse[0]\n", + " x = ellipse[1]\n", + " y = ellipse[2]\n", + "\n", + " plt.plot(e[0], e[1],c='b')\n", + " plt.scatter(x,y,marker='+') # mark the center\n", + " if title is not None:\n", + " plt.title (title)\n", + "\n", + "def plot_sigma_ellipses(ellipses,title=None,axis_equal=True,x_lim=None,y_lim=None):\n", + " \"\"\" plots the ellipse produced from sigma_ellipse.\"\"\"\n", + "\n", + " if x_lim is not None:\n", + " axis_equal = False\n", + " plt.xlim(x_lim)\n", + "\n", + " if y_lim is not None:\n", + " axis_equal = False\n", + " plt.ylim(y_lim)\n", + "\n", + " if axis_equal:\n", + " plt.axis('equal')\n", + "\n", + " for ellipse in ellipses:\n", + " es = ellipse[0]\n", + " x = ellipse[1]\n", + " y = ellipse[2]\n", + "\n", + " for e in es:\n", + " plt.plot(e[0], e[1], c='b')\n", + "\n", + " plt.scatter(x,y,marker='+') # mark the center\n", + " if title is not None:\n", + " plt.title (title)\n", + "\n", + "\n", + "def _to_cov(x,n):\n", + " \"\"\" If x is a scalar, returns a covariance matrix generated from it\n", + " as the identity matrix multiplied by x. The dimension will be nxn.\n", + " If x is already a numpy array then it is returned unchanged.\n", + " \"\"\"\n", + " try:\n", + " x.shape\n", + " if type(x) != np.ndarray:\n", + " x = np.asarray(x)[0]\n", + " return x\n", + " except:\n", + " return np.eye(n) * x\n", + "\n", + "\n", + "if __name__ == '__main__':\n", + " from scipy.stats import norm\n", + "\n", + " # test conversion of scalar to covariance matrix\n", + " x = multivariate_gaussian(np.array([1,1]), np.array([3,4]), np.eye(2)*1.4)\n", + " x2 = multivariate_gaussian(np.array([1,1]), np.array([3,4]), 1.4)\n", + " assert x == x2\n", + "\n", + " # test univarate case\n", + " rv = norm(loc = 1., scale = np.sqrt(2.3))\n", + " x2 = multivariate_gaussian(1.2, 1., 2.3)\n", + " x3 = gaussian(1.2, 1., 2.3)\n", + "\n", + " assert rv.pdf(1.2) == x2\n", + " assert abs(x2- x3) < 0.00000001\n", + "\n", + " cov = np.array([[1,1],\n", + " [1,1.1]])\n", + "\n", + " sigma = [1,1]\n", + " ev = sigma_ellipses(cov, x=2, y=2, sigma=sigma)\n", + " plot_sigma_ellipses([ev], axis_equal=True,x_lim=[0,4],y_lim=[0,15])\n", + " #isct = plt.Circle((2,2),1,color='b',fill=False)\n", + " #plt.figure().gca().add_artist(isct)\n", + " plt.show()\n", + " print \"all tests passed\"\n" + ], + "language": "python", + "metadata": {}, "outputs": [], "prompt_number": "" }, @@ -397,7 +558,8 @@ ], "language": "python", "metadata": {}, - "outputs": [] + "outputs": [], + "prompt_number": "" }, { "cell_type": "code", @@ -425,11 +587,24 @@ "outputs": [], "prompt_number": "" }, + { + "cell_type": "code", + "collapsed": false, + "input": [], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": "" + }, { "cell_type": "code", "collapsed": false, "input": [ - "%rerun -l 2" + "def gaussian(x, mean, var):\n", + " \"\"\"returns normal distribution for x given a gaussian with the specified\n", + " mean and variance. All must be scalars\n", + " \"\"\"\n", + " return math.exp((-0.5*(x-mean)**2)/var) / math.sqrt(_two_pi*var)" ], "language": "python", "metadata": {}, @@ -448,21 +623,8 @@ ], "language": "python", "metadata": {}, - "outputs": [] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "def gaussian(x, mean, var):\n", - " \"\"\"returns normal distribution for x given a gaussian with the specified\n", - " mean and variance. All must be scalars\n", - " \"\"\"\n", - " return math.exp((-0.5*(x-mean)**2)/var) / math.sqrt(_two_pi*var)" - ], - "language": "python", - "metadata": {}, - "outputs": [] + "outputs": [], + "prompt_number": "" }, { "cell_type": "code", @@ -472,7 +634,8 @@ ], "language": "python", "metadata": {}, - "outputs": [] + "outputs": [], + "prompt_number": "" }, { "cell_type": "markdown", diff --git a/book_format.py b/book_format.py new file mode 100644 index 0000000..6c8b7b9 --- /dev/null +++ b/book_format.py @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- +from IPython.core.display import HTML +import matplotlib.pylab as pylab + +def load_style(): + styles = open("./styles/custom2.css", "r").read() + return HTML(styles) + + +pylab.rcParams['figure.figsize'] = 12,6 +pylab.rcParams['axes.color_cycle'] = '348ABD, 7A68A6, A60628, 467821, CF4457, 188487, E24A33' +pylab.rcParams['lines.linewidth'] = 1 + +pylab.rcParams['lines.antialiased'] = True +pylab.rcParams['patch.linewidth'] = 0.5 +pylab.rcParams['patch.facecolor'] = '348ABD' #blue +pylab.rcParams['patch.edgecolor'] = 'eeeeee' +pylab.rcParams['patch.antialiased'] = True +pylab.rcParams['font.family'] = 'monospace' +pylab.rcParams['font.size'] = 10.0 +pylab.rcParams['font.monospace'] = 'Andale Mono, Nimbus Mono L, Courier New, Courier, Fixed, Terminal, monospace' +pylab.rcParams['axes.facecolor'] = 'eeeeee' +pylab.rcParams['axes.edgecolor'] = 'bcbcbc' +pylab.rcParams['axes.linewidth'] = 1 +pylab.rcParams['axes.grid'] = True +pylab.rcParams['axes.titlesize'] = 'x-large' +pylab.rcParams['axes.labelsize'] = 'large' +pylab.rcParams['axes.labelcolor'] = '555555' +pylab.rcParams['axes.axisbelow'] = True +pylab.rcParams['axes.color_cycle'] = '348ABD, 7A68A6, A60628, 467821, CF4457, 188487, E24A33' +pylab.rcParams['xtick.major.pad'] = 6 +pylab.rcParams['xtick.minor.size'] = 0 +pylab.rcParams['xtick.minor.pad'] = 6 +pylab.rcParams['xtick.color'] = '555555' +pylab.rcParams['ytick.direction'] = 'in' +pylab.rcParams['legend.fancybox'] = True +pylab.rcParams['figure.facecolor'] = '0.85' +pylab.rcParams['figure.edgecolor'] = '0.50' +pylab.rcParams['figure.subplot.hspace'] = 0.5 + diff --git a/g-h_filter.ipynb b/g-h_filter.ipynb index 6c471f6..6f9892b 100644 --- a/g-h_filter.ipynb +++ b/g-h_filter.ipynb @@ -1,7 +1,7 @@ { "metadata": { "name": "", - "signature": "sha256:79e48eadc10012625737389a3259ac9df692b99636f47612d5b5a9fdde69923f" + "signature": "sha256:9ab8aab8c1f9fc795707c579ec0d6653fce8590a5adb3a019b0b88bc8101642b" }, "nbformat": 3, "nbformat_minor": 0, @@ -14,6 +14,44 @@ "source": [ "### Building Intuition via Thought Experiments\n", "\n", + "Before we begin, we need to set the book's style." + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "#format the book\n", + "import book_format\n", + "book_format.load_style()" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": "" + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + " toggle input" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ "Imagine we live in a world without scales - the devices you stand on to weigh yourself. One day at work a coworker comes running up to you and announces her invention to you. After she explains, you eagerly stand on it and announce the results: \"172 lbs\". You are estatic - for the first time in your life you know what you weigh. More importantly, dollar signs dance in your eyes as you imagine selling this device to weight loss clinics across the world! This is fantastic!\n", "\n", "Another coworker hears the commotion and walks over to find out what has you so excited. You explain the invention and once again step onto the scale, and proudly proclaim the result: \"161 lbs.\" And then you hesitate, confused.\n", @@ -448,7 +486,8 @@ ], "language": "python", "metadata": {}, - "outputs": [] + "outputs": [], + "prompt_number": "" }, { "cell_type": "markdown", @@ -488,7 +527,8 @@ ], "language": "python", "metadata": {}, - "outputs": [] + "outputs": [], + "prompt_number": "" }, { "cell_type": "markdown", @@ -522,7 +562,8 @@ ], "language": "python", "metadata": {}, - "outputs": [] + "outputs": [], + "prompt_number": "" }, { "cell_type": "code", @@ -530,7 +571,8 @@ "input": [], "language": "python", "metadata": {}, - "outputs": [] + "outputs": [], + "prompt_number": "" }, { "cell_type": "code", @@ -538,7 +580,8 @@ "input": [], "language": "python", "metadata": {}, - "outputs": [] + "outputs": [], + "prompt_number": "" }, { "cell_type": "code", @@ -546,7 +589,8 @@ "input": [], "language": "python", "metadata": {}, - "outputs": [] + "outputs": [], + "prompt_number": "" }, { "cell_type": "code", @@ -554,7 +598,8 @@ "input": [], "language": "python", "metadata": {}, - "outputs": [] + "outputs": [], + "prompt_number": "" }, { "cell_type": "markdown", @@ -578,7 +623,8 @@ "input": [], "language": "python", "metadata": {}, - "outputs": [] + "outputs": [], + "prompt_number": "" }, { "cell_type": "code", @@ -593,7 +639,8 @@ ], "language": "python", "metadata": {}, - "outputs": [] + "outputs": [], + "prompt_number": "" } ], "metadata": {} diff --git a/histogram_filter.ipynb b/histogram_filter.ipynb index 8879627..5b25b3e 100644 --- a/histogram_filter.ipynb +++ b/histogram_filter.ipynb @@ -1,19 +1,38 @@ { "metadata": { "name": "", - "signature": "sha256:ed8104ceb49f694c36a56ac93873fcef520772e80c863e6346aeb03f40798c42" + "signature": "sha256:a8af5361cea4c2e2bdc01b6a821bd8d7def5d34141cebfae64113a2a8e4e037b" }, "nbformat": 3, "nbformat_minor": 0, "worksheets": [ { "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Before we begin, we need to set the book's style." + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "#format the book\n", + "import book_format\n", + "book_format.load_style()" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": "" + }, { "cell_type": "markdown", "metadata": {}, "source": [ "#Introduction\n", - "\n", "The Kalman filter belongs to a family of filters called *bayesian filters*. Without going into" ] }, diff --git a/styles/custom2.css b/styles/custom2.css index 21e698e..ca461e7 100644 --- a/styles/custom2.css +++ b/styles/custom2.css @@ -6,7 +6,8 @@ } h1 { font-family: 'Open sans',verdana,arial,sans-serif; - } + } + div.input_area { background: #F6F6F9; border: 1px solid #586e75; @@ -17,8 +18,8 @@ font-size: 40pt; line-height: 100%; color:#c76c0c; - margin-bottom: 0em; - margin-top: 0em; + margin-bottom: 0.5em; + margin-top: 1em; display: block; white-space: nowrap; }