{
 "metadata": {
  "name": "",
  "signature": "sha256:3ae92794f0349f8a429e1449741a97a12adf741c2c6d41c15056be5d20e5608a"
 },
 "nbformat": 3,
 "nbformat_minor": 0,
 "worksheets": [
  {
   "cells": [
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "This notebook illustrates amassing a medium-sized dataset (1 second of 32- or 64-bit float mono audio, essentially \u2013 a simple sine wave) using the `record_history` decorator, and then using the `stats.history_as_DataFrame` attribute to obtain that dataset as a Pandas DataFrame.\n",
      "\n",
      "After that basic (and naive) example, we compare the performance of this approach to one that uses numpy's ability to vectorize the same computation, and conclude that *if you can vectorize, certainly you should do so*. (The example is naive precisely because no one would call the function `f` below in a `for` loop when it's possible to use `numpy` universal functions (*ufunc*s). When that alternative is unavailable, however, `record_history` can come in handy.)"
     ]
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "# Using the `stats.history_as_DataFrame` attribute"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "%matplotlib inline\n",
      "import numpy as np\n",
      "import pandas as pd\n",
      "import matplotlib.pyplot as plt\n",
      "\n",
      "from log_calls import record_history"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 54
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "@record_history()\n",
      "def f(freq, t):\n",
      "    return np.sin(freq * 2 * np.pi * t)"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 55
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "ran_t = np.arange(0.0, 1.0, 1/44100, dtype=np.float32)\n",
      "ran_t"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 56,
       "text": [
        "array([  0.00000000e+00,   2.26757365e-05,   4.53514731e-05, ...,\n",
        "         9.99931931e-01,   9.99954641e-01,   9.99977291e-01], dtype=float32)"
       ]
      }
     ],
     "prompt_number": 56
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "**Now, naively, call f 44,100 times in a `for` loop, and obtain its call history as a `Pandas` `DataFrame`:**"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "#f.stats.clear_history()\n",
      "for t in ran_t: \n",
      "    f(17, t)\n",
      "df = f.stats.history_as_DataFrame"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 57
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "**Examine and do stuff with it:**"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "df.info()"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "<class 'pandas.core.frame.DataFrame'>\n",
        "Int64Index: 44100 entries, 1 to 44100\n",
        "Data columns (total 7 columns):\n",
        "freq              44100 non-null int64\n",
        "t                 44100 non-null float64\n",
        "retval            44100 non-null float64\n",
        "elapsed_secs      44100 non-null float64\n",
        "timestamp         44100 non-null object\n",
        "prefixed_fname    44100 non-null object\n",
        "caller_chain      44100 non-null object\n",
        "dtypes: float64(3), int64(1), object(3)\n",
        "memory usage: 2.7 MB\n"
       ]
      }
     ],
     "prompt_number": 60
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "from IPython.display import display\n",
      "display(df.head())\n",
      "display(df.tail())"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "html": [
        "<div style=\"max-height:1000px;max-width:1500px;overflow:auto;\">\n",
        "<table border=\"1\" class=\"dataframe\">\n",
        "  <thead>\n",
        "    <tr style=\"text-align: right;\">\n",
        "      <th></th>\n",
        "      <th>freq</th>\n",
        "      <th>t</th>\n",
        "      <th>retval</th>\n",
        "      <th>elapsed_secs</th>\n",
        "      <th>timestamp</th>\n",
        "      <th>prefixed_fname</th>\n",
        "      <th>caller_chain</th>\n",
        "    </tr>\n",
        "    <tr>\n",
        "      <th>call_num</th>\n",
        "      <th></th>\n",
        "      <th></th>\n",
        "      <th></th>\n",
        "      <th></th>\n",
        "      <th></th>\n",
        "      <th></th>\n",
        "      <th></th>\n",
        "    </tr>\n",
        "  </thead>\n",
        "  <tbody>\n",
        "    <tr>\n",
        "      <th>1</th>\n",
        "      <td> 17</td>\n",
        "      <td> 0.000000</td>\n",
        "      <td> 0.000000</td>\n",
        "      <td> 0.000040</td>\n",
        "      <td> 11/10/14 01:51:47.257050</td>\n",
        "      <td> 'f'</td>\n",
        "      <td> ['&lt;module&gt;']</td>\n",
        "    </tr>\n",
        "    <tr>\n",
        "      <th>2</th>\n",
        "      <td> 17</td>\n",
        "      <td> 0.000023</td>\n",
        "      <td> 0.002422</td>\n",
        "      <td> 0.000016</td>\n",
        "      <td> 11/10/14 01:51:47.257338</td>\n",
        "      <td> 'f'</td>\n",
        "      <td> ['&lt;module&gt;']</td>\n",
        "    </tr>\n",
        "    <tr>\n",
        "      <th>3</th>\n",
        "      <td> 17</td>\n",
        "      <td> 0.000045</td>\n",
        "      <td> 0.004844</td>\n",
        "      <td> 0.000016</td>\n",
        "      <td> 11/10/14 01:51:47.257570</td>\n",
        "      <td> 'f'</td>\n",
        "      <td> ['&lt;module&gt;']</td>\n",
        "    </tr>\n",
        "    <tr>\n",
        "      <th>4</th>\n",
        "      <td> 17</td>\n",
        "      <td> 0.000068</td>\n",
        "      <td> 0.007266</td>\n",
        "      <td> 0.000016</td>\n",
        "      <td> 11/10/14 01:51:47.257812</td>\n",
        "      <td> 'f'</td>\n",
        "      <td> ['&lt;module&gt;']</td>\n",
        "    </tr>\n",
        "    <tr>\n",
        "      <th>5</th>\n",
        "      <td> 17</td>\n",
        "      <td> 0.000091</td>\n",
        "      <td> 0.009688</td>\n",
        "      <td> 0.000015</td>\n",
        "      <td> 11/10/14 01:51:47.258043</td>\n",
        "      <td> 'f'</td>\n",
        "      <td> ['&lt;module&gt;']</td>\n",
        "    </tr>\n",
        "  </tbody>\n",
        "</table>\n",
        "</div>"
       ],
       "metadata": {},
       "output_type": "display_data",
       "text": [
        "          freq         t    retval  elapsed_secs                 timestamp  \\\n",
        "call_num                                                                     \n",
        "1           17  0.000000  0.000000      0.000040  11/10/14 01:51:47.257050   \n",
        "2           17  0.000023  0.002422      0.000016  11/10/14 01:51:47.257338   \n",
        "3           17  0.000045  0.004844      0.000016  11/10/14 01:51:47.257570   \n",
        "4           17  0.000068  0.007266      0.000016  11/10/14 01:51:47.257812   \n",
        "5           17  0.000091  0.009688      0.000015  11/10/14 01:51:47.258043   \n",
        "\n",
        "         prefixed_fname  caller_chain  \n",
        "call_num                               \n",
        "1                   'f'  ['<module>']  \n",
        "2                   'f'  ['<module>']  \n",
        "3                   'f'  ['<module>']  \n",
        "4                   'f'  ['<module>']  \n",
        "5                   'f'  ['<module>']  "
       ]
      },
      {
       "html": [
        "<div style=\"max-height:1000px;max-width:1500px;overflow:auto;\">\n",
        "<table border=\"1\" class=\"dataframe\">\n",
        "  <thead>\n",
        "    <tr style=\"text-align: right;\">\n",
        "      <th></th>\n",
        "      <th>freq</th>\n",
        "      <th>t</th>\n",
        "      <th>retval</th>\n",
        "      <th>elapsed_secs</th>\n",
        "      <th>timestamp</th>\n",
        "      <th>prefixed_fname</th>\n",
        "      <th>caller_chain</th>\n",
        "    </tr>\n",
        "    <tr>\n",
        "      <th>call_num</th>\n",
        "      <th></th>\n",
        "      <th></th>\n",
        "      <th></th>\n",
        "      <th></th>\n",
        "      <th></th>\n",
        "      <th></th>\n",
        "      <th></th>\n",
        "    </tr>\n",
        "  </thead>\n",
        "  <tbody>\n",
        "    <tr>\n",
        "      <th>44096</th>\n",
        "      <td> 17</td>\n",
        "      <td> 0.999887</td>\n",
        "      <td>-0.012109</td>\n",
        "      <td> 0.000014</td>\n",
        "      <td> 11/10/14 01:51:57.920550</td>\n",
        "      <td> 'f'</td>\n",
        "      <td> ['&lt;module&gt;']</td>\n",
        "    </tr>\n",
        "    <tr>\n",
        "      <th>44097</th>\n",
        "      <td> 17</td>\n",
        "      <td> 0.999909</td>\n",
        "      <td>-0.009690</td>\n",
        "      <td> 0.000014</td>\n",
        "      <td> 11/10/14 01:51:57.920767</td>\n",
        "      <td> 'f'</td>\n",
        "      <td> ['&lt;module&gt;']</td>\n",
        "    </tr>\n",
        "    <tr>\n",
        "      <th>44098</th>\n",
        "      <td> 17</td>\n",
        "      <td> 0.999932</td>\n",
        "      <td>-0.007271</td>\n",
        "      <td> 0.000014</td>\n",
        "      <td> 11/10/14 01:51:57.920979</td>\n",
        "      <td> 'f'</td>\n",
        "      <td> ['&lt;module&gt;']</td>\n",
        "    </tr>\n",
        "    <tr>\n",
        "      <th>44099</th>\n",
        "      <td> 17</td>\n",
        "      <td> 0.999955</td>\n",
        "      <td>-0.004845</td>\n",
        "      <td> 0.000014</td>\n",
        "      <td> 11/10/14 01:51:57.921190</td>\n",
        "      <td> 'f'</td>\n",
        "      <td> ['&lt;module&gt;']</td>\n",
        "    </tr>\n",
        "    <tr>\n",
        "      <th>44100</th>\n",
        "      <td> 17</td>\n",
        "      <td> 0.999977</td>\n",
        "      <td>-0.002426</td>\n",
        "      <td> 0.000013</td>\n",
        "      <td> 11/10/14 01:51:57.921411</td>\n",
        "      <td> 'f'</td>\n",
        "      <td> ['&lt;module&gt;']</td>\n",
        "    </tr>\n",
        "  </tbody>\n",
        "</table>\n",
        "</div>"
       ],
       "metadata": {},
       "output_type": "display_data",
       "text": [
        "          freq         t    retval  elapsed_secs                 timestamp  \\\n",
        "call_num                                                                     \n",
        "44096       17  0.999887 -0.012109      0.000014  11/10/14 01:51:57.920550   \n",
        "44097       17  0.999909 -0.009690      0.000014  11/10/14 01:51:57.920767   \n",
        "44098       17  0.999932 -0.007271      0.000014  11/10/14 01:51:57.920979   \n",
        "44099       17  0.999955 -0.004845      0.000014  11/10/14 01:51:57.921190   \n",
        "44100       17  0.999977 -0.002426      0.000013  11/10/14 01:51:57.921411   \n",
        "\n",
        "         prefixed_fname  caller_chain  \n",
        "call_num                               \n",
        "44096               'f'  ['<module>']  \n",
        "44097               'f'  ['<module>']  \n",
        "44098               'f'  ['<module>']  \n",
        "44099               'f'  ['<module>']  \n",
        "44100               'f'  ['<module>']  "
       ]
      }
     ],
     "prompt_number": 61
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "len(f.stats.history)"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 62,
       "text": [
        "44100"
       ]
      }
     ],
     "prompt_number": 62
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "df[['t', 'retval']].head()"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "html": [
        "<div style=\"max-height:1000px;max-width:1500px;overflow:auto;\">\n",
        "<table border=\"1\" class=\"dataframe\">\n",
        "  <thead>\n",
        "    <tr style=\"text-align: right;\">\n",
        "      <th></th>\n",
        "      <th>t</th>\n",
        "      <th>retval</th>\n",
        "    </tr>\n",
        "    <tr>\n",
        "      <th>call_num</th>\n",
        "      <th></th>\n",
        "      <th></th>\n",
        "    </tr>\n",
        "  </thead>\n",
        "  <tbody>\n",
        "    <tr>\n",
        "      <th>1</th>\n",
        "      <td> 0.000000</td>\n",
        "      <td> 0.000000</td>\n",
        "    </tr>\n",
        "    <tr>\n",
        "      <th>2</th>\n",
        "      <td> 0.000023</td>\n",
        "      <td> 0.002422</td>\n",
        "    </tr>\n",
        "    <tr>\n",
        "      <th>3</th>\n",
        "      <td> 0.000045</td>\n",
        "      <td> 0.004844</td>\n",
        "    </tr>\n",
        "    <tr>\n",
        "      <th>4</th>\n",
        "      <td> 0.000068</td>\n",
        "      <td> 0.007266</td>\n",
        "    </tr>\n",
        "    <tr>\n",
        "      <th>5</th>\n",
        "      <td> 0.000091</td>\n",
        "      <td> 0.009688</td>\n",
        "    </tr>\n",
        "  </tbody>\n",
        "</table>\n",
        "</div>"
       ],
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 63,
       "text": [
        "                 t    retval\n",
        "call_num                    \n",
        "1         0.000000  0.000000\n",
        "2         0.000023  0.002422\n",
        "3         0.000045  0.004844\n",
        "4         0.000068  0.007266\n",
        "5         0.000091  0.009688"
       ]
      }
     ],
     "prompt_number": 63
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "plt.plot(df.t, df.retval);"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "display_data",
       "png": "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\n",
       "text": [
        "<matplotlib.figure.Figure at 0x11401d4a8>"
       ]
      }
     ],
     "prompt_number": 64
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "---"
     ]
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "#Comparing performance: `record_history` *vs* vectorization with numpy *ufunc*s"
     ]
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "##(1) No decorator"
     ]
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "###*With no decorator, it's ~2.8 orders of magnitude faster to use a function as a numpy ufunc than to call it in a for loop (looping through ran_t)*"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "def g(freq, t):\n",
      "    return np.sin(freq * 2 * np.pi * t)"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 72
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "####Vectorized:"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "nodeco_vectorized_secs = %timeit -o Hz_17 = g(17, ran_t)\n",
      "nodeco_vectorized_secs.best"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "1000 loops, best of 3: 448 \u00b5s per loop\n"
       ]
      },
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 89,
       "text": [
        "0.0004476831200008746"
       ]
      }
     ],
     "prompt_number": 89
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "Hz_17"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 90,
       "text": [
        "array([ 0.        ,  0.00242209,  0.00484416, ..., -0.00727302,\n",
        "       -0.00484692, -0.00242842], dtype=float32)"
       ]
      }
     ],
     "prompt_number": 90
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "plt.plot(Hz_17);"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "display_data",
       "png": "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\n",
       "text": [
        "<matplotlib.figure.Figure at 0x110142630>"
       ]
      }
     ],
     "prompt_number": 91
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "####With a `for` loop:"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "nodeco_loop_secs = %timeit -o for t in ran_t: g(7, t)\n",
      "nodeco_loop_secs.best"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "1 loops, best of 3: 278 ms per loop\n"
       ]
      },
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 92,
       "text": [
        "0.2777122740226332"
       ]
      }
     ],
     "prompt_number": 92
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "def comparison(slower, faster):\n",
      "    'slower, faster: seconds'\n",
      "    ratio = slower/faster\n",
      "    order_of_magnitude = np.log10(ratio)\n",
      "    return ratio, order_of_magnitude"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 93
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "print(\"With record_history disabled:\\n\"\n",
      "      \"Vectorized approach is %d times (about %.1f orders of magnitude) faster\" \n",
      "      % comparison(slower=loop_secs.best, faster=vectorized_secs.best))"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "With record_history disabled:\n",
        "Vectorized approach is 619 times (about 2.8 orders of magnitude) faster\n"
       ]
      }
     ],
     "prompt_number": 94
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "**Now let's compare the performance of the `record_history`-decorated version (`f`) of the same function**"
     ]
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "##(2) `record_history` disabled"
     ]
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "### *With record_history disabled, it's ~3.6 orders of magnitude faster to use a function as a numpy ufunc than to call it in a for loop (looping through ran_t)*"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "f.stats.clear_history()\n",
      "f.record_history_settings.enabled = False"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 83
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "####Vectorized:"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "vectorized_secs_rh_disabled = %timeit -o Hz_17 = f(17, ran_t)\n",
      "vectorized_secs_rh_disabled.best"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "1000 loops, best of 3: 489 \u00b5s per loop\n"
       ]
      },
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 84,
       "text": [
        "0.0004893772610230371"
       ]
      }
     ],
     "prompt_number": 84
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "####With a `for` loop:"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "loop_secs_rh_disabled = %timeit -o for t in ran_t: f(7, t)\n",
      "loop_secs_rh_disabled.best"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "1 loops, best of 3: 1.98 s per loop\n"
       ]
      },
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 87,
       "text": [
        "1.9756690169742797"
       ]
      }
     ],
     "prompt_number": 87
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "print(\"With record_history disabled:\\n\"\n",
      "      \"Vectorized approach is %d times (about %.1f orders of magnitude) faster\" \n",
      "      % comparison(slower=loop_secs_rh_disabled.best, faster=vectorized_secs_rh_disabled.best))"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "With record_history disabled:\n",
        "Vectorized approach is 4037 times (about 3.6 orders of magnitude) faster\n"
       ]
      }
     ],
     "prompt_number": 95
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "###Decorator overhead: about 7x slower (~0.9 orders of magnitude)"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "print(\"Called in a for-loop, the no-decorator version is %d times (about %.1f orders of magnitude) faster\" \n",
      "      % comparison(slower=loop_secs_rh_disabled.best, faster=nodeco_loop_secs.best))"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "Called in a for-loop, the no-decorator version is 7 times (about 0.9 orders of magnitude) faster\n"
       ]
      }
     ],
     "prompt_number": 99
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "##(3) `record_history` enabled"
     ]
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "### *With record_history enabled, it's ~4.2 orders of magnitude faster to use a function as a numpy ufunc than to call it in a for loop (looping through ran_t)*"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "f.record_history_settings.enabled = True\n",
      "f.stats.clear_history()"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 100
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "####Vectorized:"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "vectorized_secs_rh_enabled = %timeit -o f.stats.clear_history(); Hz_17 = f(17, ran_t)\n",
      "vectorized_secs_rh_enabled.best"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "1000 loops, best of 3: 705 \u00b5s per loop\n"
       ]
      },
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 106,
       "text": [
        "0.0007048069210140966"
       ]
      }
     ],
     "prompt_number": 106
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "len(f.stats.history)"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 107,
       "text": [
        "1"
       ]
      }
     ],
     "prompt_number": 107
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "def size_of_t_for_row(row):\n",
      "    return f.stats.history[row].argvals[1].size\n",
      "\n",
      "size_of_t_for_row(0)"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 108,
       "text": [
        "44100"
       ]
      }
     ],
     "prompt_number": 108
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "f.stats.history[0].retval.size"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 109,
       "text": [
        "44100"
       ]
      }
     ],
     "prompt_number": 109
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "f.stats.history"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 110,
       "text": [
        "(CallRecord(call_num=1, argnames=['freq', 't'], argvals=(17, array([  0.00000000e+00,   2.26757365e-05,   4.53514731e-05, ...,\n",
        "         9.99931931e-01,   9.99954641e-01,   9.99977291e-01], dtype=float32)), varargs=(), explicit_kwargs=OrderedDict(), defaulted_kwargs=OrderedDict(), implicit_kwargs={}, retval=array([ 0.        ,  0.00242209,  0.00484416, ..., -0.00727302,\n",
        "       -0.00484692, -0.00242842], dtype=float32), elapsed_secs=0.00045490264892578125, timestamp='11/10/14 02:05:01.410089', prefixed_func_name='f', caller_chain=['inner']),)"
       ]
      }
     ],
     "prompt_number": 110
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "f.stats.clear_history()"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 111
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "####With a `for` loop:"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "loop_secs_rh_enabled = %timeit -o for t in ran_t: f(7, t); f.stats.clear_history()\n",
      "loop_secs_rh_enabled.best"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "1 loops, best of 3: 10.6 s per loop\n"
       ]
      },
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 112,
       "text": [
        "10.644794539985014"
       ]
      }
     ],
     "prompt_number": 112
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "print(\"With record_history enabled:\\n\"\n",
      "      \"Vectorized approach is %d times (about %.1f orders of magnitude) faster\" \n",
      "      % comparison(slower=loop_secs_rh_enabled.best, faster=vectorized_secs_rh_enabled.best))"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "With record_history enabled:\n",
        "Vectorized approach is 15103 times (about 4.2 orders of magnitude) faster\n"
       ]
      }
     ],
     "prompt_number": 113
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "---"
     ]
    }
   ],
   "metadata": {}
  }
 ]
}