In class work on testing/program design.
authorMatt Davis <jiffyclub@gmail.com>
Sat, 11 May 2013 05:06:14 +0000 (22:06 -0700)
committerW. Trevor King <wking@tremily.us>
Sat, 9 Nov 2013 17:58:06 +0000 (09:58 -0800)
python/sw_engineering/instructor_notebook.ipynb
python/sw_engineering/mean_animals.ipynb [new file with mode: 0644]
python/sw_engineering/meananimals.py [new file with mode: 0644]
python/sw_engineering/research.ipynb [new file with mode: 0644]

index f2bca2d445b2592331404783e13d09d3149d1d1a..06a8d89b391a0e9774b003d32776257b038e6f0d 100644 (file)
  "worksheets": [
   {
    "cells": [
+    {
+     "cell_type": "markdown",
+     "metadata": {},
+     "source": [
+      "# Software Engineering Unit at LBL\n",
+      "\n",
+      "Goal:\n",
+      "    \n",
+      "Write a utility that returns the mean number of a particular animal seen per sighting of that animal.\n",
+      "\n",
+      "    def mean_animal(filename, species)\n",
+      "        ...\n",
+      "        return mean_animal_per_sighting"
+     ]
+    },
+    {
+     "cell_type": "code",
+     "collapsed": false,
+     "input": [
+      "ls"
+     ],
+     "language": "python",
+     "metadata": {},
+     "outputs": [
+      {
+       "output_type": "stream",
+       "stream": "stdout",
+       "text": [
+        "README.md                  instructor_notebook.ipynb\r\n",
+        "animals.txt                ipython_nose.py\r\n",
+        "big_animals.txt            macguffin_animals.txt\r\n",
+        "dev_notes.md               merida_animals.txt\r\n",
+        "dingwall_animals.txt       student_notebook.ipynb\r\n",
+        "fergus_animals.txt\r\n"
+       ]
+      }
+     ],
+     "prompt_number": 1
+    },
+    {
+     "cell_type": "code",
+     "collapsed": false,
+     "input": [
+      "cat animals.txt"
+     ],
+     "language": "python",
+     "metadata": {},
+     "outputs": [
+      {
+       "output_type": "stream",
+       "stream": "stdout",
+       "text": [
+        "2011-04-22 21:06 Grizzly 36\r\n",
+        "2011-04-23 14:12 Elk 25\r\n",
+        "2011-04-23 10:24 Elk 26\r\n",
+        "2011-04-23 20:08 Wolverine 31\r\n",
+        "2011-04-23 18:46 Muskox 20\r\n"
+       ]
+      }
+     ],
+     "prompt_number": 2
+    },
+    {
+     "cell_type": "code",
+     "collapsed": false,
+     "input": [
+      "def read_file(ifile):\n",
+      "    open_file = open(ifile, 'r')\n",
+      "    \n",
+      "    time = []\n",
+      "    date = []\n",
+      "    animal = []\n",
+      "    count = []\n",
+      "    \n",
+      "    for iline in open_file:\n",
+      "        s = iline.split()\n",
+      "        date.append(s[0])\n",
+      "        time.append(s[1])\n",
+      "        animal.append(s[2])\n",
+      "        count.append(int(s[3]))\n",
+      "    \n",
+      "    open_file.close()\n",
+      "    \n",
+      "    return date, time, animal, count"
+     ],
+     "language": "python",
+     "metadata": {},
+     "outputs": [],
+     "prompt_number": 15
+    },
+    {
+     "cell_type": "code",
+     "collapsed": false,
+     "input": [
+      "read_file('animals.txt')"
+     ],
+     "language": "python",
+     "metadata": {},
+     "outputs": [
+      {
+       "output_type": "pyout",
+       "prompt_number": 7,
+       "text": [
+        "(['2011-04-22', '2011-04-23', '2011-04-23', '2011-04-23', '2011-04-23'],\n",
+        " ['21:06', '14:12', '10:24', '20:08', '18:46'],\n",
+        " ['Grizzly', 'Elk', 'Elk', 'Wolverine', 'Muskox'],\n",
+        " [36, 25, 26, 31, 20])"
+       ]
+      }
+     ],
+     "prompt_number": 7
+    },
+    {
+     "cell_type": "code",
+     "collapsed": false,
+     "input": [
+      "def test_read_animals():\n",
+      "    date, time, animal, count = read_file('animals.txt')\n",
+      "    ref_date = ['2011-04-22', '2011-04-23', '2011-04-23', '2011-04-23', '2011-04-23']\n",
+      "    ref_time = ['21:06', '14:12', '10:24', '20:08', '18:46']\n",
+      "    ref_animal = ['Grizzly', 'Elk', 'Elk', 'Wolverine', 'Muskox']\n",
+      "    ref_count = [36, 25, 26, 31, 20]\n",
+      "    \n",
+      "    assert date == ref_date, 'Dates do not match!'\n",
+      "    assert time == ref_time, 'Times do not match!'\n",
+      "    assert animal == ref_animal, 'Animals do not match!'\n",
+      "    assert count == ref_count, 'Counts do not match!'"
+     ],
+     "language": "python",
+     "metadata": {},
+     "outputs": [],
+     "prompt_number": 24
+    },
+    {
+     "cell_type": "code",
+     "collapsed": false,
+     "input": [
+      "test_read_animals()"
+     ],
+     "language": "python",
+     "metadata": {},
+     "outputs": [],
+     "prompt_number": 19
+    },
+    {
+     "cell_type": "code",
+     "collapsed": false,
+     "input": [
+      "%load_ext ipython_nose"
+     ],
+     "language": "python",
+     "metadata": {},
+     "outputs": [
+      {
+       "output_type": "stream",
+       "stream": "stderr",
+       "text": [
+        "/Users/mrdavis/.homebrew/Cellar/python/2.7.3/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/nose/plugins/manager.py:418: UserWarning: Module argparse was already imported from /Users/mrdavis/.homebrew/Cellar/python/2.7.3/Frameworks/Python.framework/Versions/2.7/lib/python2.7/argparse.pyc, but /usr/local/lib/python2.7/site-packages is being added to sys.path\n",
+        "  import pkg_resources\n"
+       ]
+      }
+     ],
+     "prompt_number": 20
+    },
+    {
+     "cell_type": "code",
+     "collapsed": false,
+     "input": [
+      "%nose"
+     ],
+     "language": "python",
+     "metadata": {},
+     "outputs": [
+      {
+       "html": [
+        "<div id=\"ipython_nose_6f9af703139c456f96a60b847ccf532d\"></div>"
+       ],
+       "output_type": "display_data"
+      },
+      {
+       "javascript": [
+        "document.ipython_nose_6f9af703139c456f96a60b847ccf532d = $(\"#ipython_nose_6f9af703139c456f96a60b847ccf532d\");"
+       ],
+       "output_type": "display_data"
+      },
+      {
+       "javascript": [
+        "document.ipython_nose_6f9af703139c456f96a60b847ccf532d.append($(\"<span>.</span>\"));"
+       ],
+       "output_type": "display_data"
+      },
+      {
+       "javascript": [
+        "delete document.ipython_nose_6f9af703139c456f96a60b847ccf532d;"
+       ],
+       "output_type": "display_data"
+      },
+      {
+       "html": [
+        "    <style type=\"text/css\">\n",
+        "        span.nosefailedfunc {\n",
+        "            font-family: monospace;\n",
+        "            font-weight: bold;\n",
+        "        }\n",
+        "        div.noseresults {\n",
+        "            width: 100%;\n",
+        "        }\n",
+        "        div.nosebar {\n",
+        "            float: left;\n",
+        "            padding: 1ex 0px 1ex 0px;\n",
+        "        }\n",
+        "        div.nosebar.fail {\n",
+        "            background: #ff3019; /* Old browsers */\n",
+        "            /* FF3.6+ */\n",
+        "            background: -moz-linear-gradient(top, #ff3019 0%, #cf0404 100%);\n",
+        "            /* Chrome,Safari4+ */\n",
+        "            background: -webkit-gradient(linear, left top, left bottom,\n",
+        "                                         color-stop(0%,#ff3019),\n",
+        "                                         color-stop(100%,#cf0404));\n",
+        "            /* Chrome10+,Safari5.1+ */\n",
+        "            background: -webkit-linear-gradient(top, #ff3019 0%,#cf0404 100%);\n",
+        "            /* Opera 11.10+ */\n",
+        "            background: -o-linear-gradient(top, #ff3019 0%,#cf0404 100%);\n",
+        "            /* IE10+ */\n",
+        "            background: -ms-linear-gradient(top, #ff3019 0%,#cf0404 100%);\n",
+        "            /* W3C */\n",
+        "            background: linear-gradient(to bottom, #ff3019 0%,#cf0404 100%);\n",
+        "        }\n",
+        "        div.nosebar.pass {\n",
+        "            background: #52b152;\n",
+        "            background: -moz-linear-gradient(top, #52b152 1%, #008a00 100%);\n",
+        "            background: -webkit-gradient(linear, left top, left bottom,\n",
+        "                                         color-stop(1%,#52b152),\n",
+        "                                         color-stop(100%,#008a00));\n",
+        "            background: -webkit-linear-gradient(top, #52b152 1%,#008a00 100%);\n",
+        "            background: -o-linear-gradient(top, #52b152 1%,#008a00 100%);\n",
+        "            background: -ms-linear-gradient(top, #52b152 1%,#008a00 100%);\n",
+        "            background: linear-gradient(to bottom, #52b152 1%,#008a00 100%);\n",
+        "        }\n",
+        "        div.nosebar.skip {\n",
+        "            background: #f1e767;\n",
+        "            background: -moz-linear-gradient(top, #f1e767 0%, #feb645 100%);\n",
+        "            background: -webkit-gradient(linear, left top, left bottom,\n",
+        "                                         color-stop(0%,#f1e767),\n",
+        "                                         color-stop(100%,#feb645));\n",
+        "            background: -webkit-linear-gradient(top, #f1e767 0%,#feb645 100%);\n",
+        "            background: -o-linear-gradient(top, #f1e767 0%,#feb645 100%);\n",
+        "            background: -ms-linear-gradient(top, #f1e767 0%,#feb645 100%);\n",
+        "            background: linear-gradient(to bottom, #f1e767 0%,#feb645 100%);\n",
+        "        }\n",
+        "        div.nosebar.leftmost {\n",
+        "            border-radius: 4px 0 0 4px;\n",
+        "        }\n",
+        "        div.nosebar.rightmost {\n",
+        "            border-radius: 0 4px 4px 0;\n",
+        "        }\n",
+        "        div.nosefailbanner {\n",
+        "            border-radius: 4px 0 0 4px;\n",
+        "            border-left: 10px solid #cf0404;\n",
+        "            padding: 0.5ex 0em 0.5ex 1em;\n",
+        "            margin-top: 1ex;\n",
+        "            margin-bottom: 0px;\n",
+        "        }\n",
+        "        div.nosefailbanner.expanded {\n",
+        "            border-radius: 4px 4px 0 0;\n",
+        "            border-top: 10px solid #cf0404;\n",
+        "        }\n",
+        "        pre.nosetraceback {\n",
+        "            border-radius: 0 4px 4px 4px;\n",
+        "            border-left: 10px solid #cf0404;\n",
+        "            padding: 1em;\n",
+        "            margin-left: 0px;\n",
+        "            margin-top: 0px;\n",
+        "            display: none;\n",
+        "        }\n",
+        "    </style>\n",
+        "    \n",
+        "    <script>\n",
+        "        setTimeout(function () {\n",
+        "            $('.nosefailtoggle').bind(\n",
+        "                'click',\n",
+        "                function () {\n",
+        "                    $(\n",
+        "                        $(this)\n",
+        "                            .parent().toggleClass('expanded')\n",
+        "                            .parent()\n",
+        "                            .children()\n",
+        "                            .filter('.nosetraceback')\n",
+        "                    ).toggle();\n",
+        "                }\n",
+        "            );},\n",
+        "            0);\n",
+        "    </script>\n",
+        "    \n",
+        "    <div class=\"noseresults\">\n",
+        "      <div class=\"nosebar fail leftmost\" style=\"width: 0%\">\n",
+        "          &nbsp;\n",
+        "      </div>\n",
+        "      <div class=\"nosebar skip\" style=\"width: 0%\">\n",
+        "          &nbsp;\n",
+        "      </div>\n",
+        "      <div class=\"nosebar pass rightmost\" style=\"width: 100%\">\n",
+        "          &nbsp;\n",
+        "      </div>\n",
+        "      1/1 tests passed\n",
+        "    </div>\n",
+        "    "
+       ],
+       "output_type": "pyout",
+       "prompt_number": 25,
+       "text": [
+        "1/1 tests passed\n"
+       ]
+      }
+     ],
+     "prompt_number": 25
+    },
+    {
+     "cell_type": "code",
+     "collapsed": false,
+     "input": [
+      "def calc_mean(ilist):\n",
+      "    '''\n",
+      "    returns the mean of input list\n",
+      "    '''\n",
+      "    if len(ilist) == 0:\n",
+      "        raise ValueError('Input is empty.')\n",
+      "        \n",
+      "    total = 0.0\n",
+      "    for num in ilist:\n",
+      "        total = total + num\n",
+      "    return total/float(len(ilist))"
+     ],
+     "language": "python",
+     "metadata": {},
+     "outputs": [],
+     "prompt_number": 30
+    },
+    {
+     "cell_type": "code",
+     "collapsed": false,
+     "input": [
+      "import nose.tools as nt"
+     ],
+     "language": "python",
+     "metadata": {},
+     "outputs": [],
+     "prompt_number": 27
+    },
+    {
+     "cell_type": "code",
+     "collapsed": false,
+     "input": [
+      "def test_mean1():\n",
+      "    m = calc_mean([1, 2, 3])\n",
+      "    assert m == 2\n",
+      "    \n",
+      "def test_mean2():\n",
+      "    m = calc_mean([1])\n",
+      "    assert m == 1\n",
+      "\n",
+      "def test_mean3():\n",
+      "    m = calc_mean([3.4, 3.5, 3.6])\n",
+      "    assert m == 3.5\n",
+      "\n",
+      "@nt.raises(ValueError)\n",
+      "def test_mean4():\n",
+      "    m = calc_mean([])"
+     ],
+     "language": "python",
+     "metadata": {},
+     "outputs": [],
+     "prompt_number": 28
+    },
+    {
+     "cell_type": "code",
+     "collapsed": false,
+     "input": [
+      "%nose"
+     ],
+     "language": "python",
+     "metadata": {},
+     "outputs": [
+      {
+       "html": [
+        "<div id=\"ipython_nose_78c80018c7cf4f79834c36da78624ba0\"></div>"
+       ],
+       "output_type": "display_data"
+      },
+      {
+       "javascript": [
+        "document.ipython_nose_78c80018c7cf4f79834c36da78624ba0 = $(\"#ipython_nose_78c80018c7cf4f79834c36da78624ba0\");"
+       ],
+       "output_type": "display_data"
+      },
+      {
+       "javascript": [
+        "document.ipython_nose_78c80018c7cf4f79834c36da78624ba0.append($(\"<span>.</span>\"));"
+       ],
+       "output_type": "display_data"
+      },
+      {
+       "javascript": [
+        "document.ipython_nose_78c80018c7cf4f79834c36da78624ba0.append($(\"<span>.</span>\"));"
+       ],
+       "output_type": "display_data"
+      },
+      {
+       "javascript": [
+        "document.ipython_nose_78c80018c7cf4f79834c36da78624ba0.append($(\"<span>.</span>\"));"
+       ],
+       "output_type": "display_data"
+      },
+      {
+       "javascript": [
+        "document.ipython_nose_78c80018c7cf4f79834c36da78624ba0.append($(\"<span>.</span>\"));"
+       ],
+       "output_type": "display_data"
+      },
+      {
+       "javascript": [
+        "document.ipython_nose_78c80018c7cf4f79834c36da78624ba0.append($(\"<span>.</span>\"));"
+       ],
+       "output_type": "display_data"
+      },
+      {
+       "javascript": [
+        "delete document.ipython_nose_78c80018c7cf4f79834c36da78624ba0;"
+       ],
+       "output_type": "display_data"
+      },
+      {
+       "html": [
+        "    <style type=\"text/css\">\n",
+        "        span.nosefailedfunc {\n",
+        "            font-family: monospace;\n",
+        "            font-weight: bold;\n",
+        "        }\n",
+        "        div.noseresults {\n",
+        "            width: 100%;\n",
+        "        }\n",
+        "        div.nosebar {\n",
+        "            float: left;\n",
+        "            padding: 1ex 0px 1ex 0px;\n",
+        "        }\n",
+        "        div.nosebar.fail {\n",
+        "            background: #ff3019; /* Old browsers */\n",
+        "            /* FF3.6+ */\n",
+        "            background: -moz-linear-gradient(top, #ff3019 0%, #cf0404 100%);\n",
+        "            /* Chrome,Safari4+ */\n",
+        "            background: -webkit-gradient(linear, left top, left bottom,\n",
+        "                                         color-stop(0%,#ff3019),\n",
+        "                                         color-stop(100%,#cf0404));\n",
+        "            /* Chrome10+,Safari5.1+ */\n",
+        "            background: -webkit-linear-gradient(top, #ff3019 0%,#cf0404 100%);\n",
+        "            /* Opera 11.10+ */\n",
+        "            background: -o-linear-gradient(top, #ff3019 0%,#cf0404 100%);\n",
+        "            /* IE10+ */\n",
+        "            background: -ms-linear-gradient(top, #ff3019 0%,#cf0404 100%);\n",
+        "            /* W3C */\n",
+        "            background: linear-gradient(to bottom, #ff3019 0%,#cf0404 100%);\n",
+        "        }\n",
+        "        div.nosebar.pass {\n",
+        "            background: #52b152;\n",
+        "            background: -moz-linear-gradient(top, #52b152 1%, #008a00 100%);\n",
+        "            background: -webkit-gradient(linear, left top, left bottom,\n",
+        "                                         color-stop(1%,#52b152),\n",
+        "                                         color-stop(100%,#008a00));\n",
+        "            background: -webkit-linear-gradient(top, #52b152 1%,#008a00 100%);\n",
+        "            background: -o-linear-gradient(top, #52b152 1%,#008a00 100%);\n",
+        "            background: -ms-linear-gradient(top, #52b152 1%,#008a00 100%);\n",
+        "            background: linear-gradient(to bottom, #52b152 1%,#008a00 100%);\n",
+        "        }\n",
+        "        div.nosebar.skip {\n",
+        "            background: #f1e767;\n",
+        "            background: -moz-linear-gradient(top, #f1e767 0%, #feb645 100%);\n",
+        "            background: -webkit-gradient(linear, left top, left bottom,\n",
+        "                                         color-stop(0%,#f1e767),\n",
+        "                                         color-stop(100%,#feb645));\n",
+        "            background: -webkit-linear-gradient(top, #f1e767 0%,#feb645 100%);\n",
+        "            background: -o-linear-gradient(top, #f1e767 0%,#feb645 100%);\n",
+        "            background: -ms-linear-gradient(top, #f1e767 0%,#feb645 100%);\n",
+        "            background: linear-gradient(to bottom, #f1e767 0%,#feb645 100%);\n",
+        "        }\n",
+        "        div.nosebar.leftmost {\n",
+        "            border-radius: 4px 0 0 4px;\n",
+        "        }\n",
+        "        div.nosebar.rightmost {\n",
+        "            border-radius: 0 4px 4px 0;\n",
+        "        }\n",
+        "        div.nosefailbanner {\n",
+        "            border-radius: 4px 0 0 4px;\n",
+        "            border-left: 10px solid #cf0404;\n",
+        "            padding: 0.5ex 0em 0.5ex 1em;\n",
+        "            margin-top: 1ex;\n",
+        "            margin-bottom: 0px;\n",
+        "        }\n",
+        "        div.nosefailbanner.expanded {\n",
+        "            border-radius: 4px 4px 0 0;\n",
+        "            border-top: 10px solid #cf0404;\n",
+        "        }\n",
+        "        pre.nosetraceback {\n",
+        "            border-radius: 0 4px 4px 4px;\n",
+        "            border-left: 10px solid #cf0404;\n",
+        "            padding: 1em;\n",
+        "            margin-left: 0px;\n",
+        "            margin-top: 0px;\n",
+        "            display: none;\n",
+        "        }\n",
+        "    </style>\n",
+        "    \n",
+        "    <script>\n",
+        "        setTimeout(function () {\n",
+        "            $('.nosefailtoggle').bind(\n",
+        "                'click',\n",
+        "                function () {\n",
+        "                    $(\n",
+        "                        $(this)\n",
+        "                            .parent().toggleClass('expanded')\n",
+        "                            .parent()\n",
+        "                            .children()\n",
+        "                            .filter('.nosetraceback')\n",
+        "                    ).toggle();\n",
+        "                }\n",
+        "            );},\n",
+        "            0);\n",
+        "    </script>\n",
+        "    \n",
+        "    <div class=\"noseresults\">\n",
+        "      <div class=\"nosebar fail leftmost\" style=\"width: 0%\">\n",
+        "          &nbsp;\n",
+        "      </div>\n",
+        "      <div class=\"nosebar skip\" style=\"width: 0%\">\n",
+        "          &nbsp;\n",
+        "      </div>\n",
+        "      <div class=\"nosebar pass rightmost\" style=\"width: 100%\">\n",
+        "          &nbsp;\n",
+        "      </div>\n",
+        "      5/5 tests passed\n",
+        "    </div>\n",
+        "    "
+       ],
+       "output_type": "pyout",
+       "prompt_number": 31,
+       "text": [
+        "5/5 tests passed\n"
+       ]
+      }
+     ],
+     "prompt_number": 31
+    },
+    {
+     "cell_type": "code",
+     "collapsed": false,
+     "input": [
+      "def filter_animals(species, date, time, animal, count):\n",
+      "    \"\"\"\n",
+      "    Given a particular species, filter out the data for just that species.\n",
+      "\n",
+      "    Returns four lists: date, time, animal, count.\n",
+      "    \"\"\"\n",
+      "    fdate = []\n",
+      "    ftime = []\n",
+      "    fanimal = []\n",
+      "    fcount = []\n",
+      "    \n",
+      "    for d, t, a, c in zip(date, time, animal, count):\n",
+      "        if a == species:\n",
+      "            fdate.append(d)\n",
+      "            ftime.append(t)\n",
+      "            fanimal.append(a)\n",
+      "            fcount.append(c)\n",
+      "    \n",
+      "    return fdate, ftime, fanimal, fcount"
+     ],
+     "language": "python",
+     "metadata": {},
+     "outputs": [],
+     "prompt_number": 36
+    },
+    {
+     "cell_type": "code",
+     "collapsed": false,
+     "input": [
+      "cat animals.txt"
+     ],
+     "language": "python",
+     "metadata": {},
+     "outputs": [
+      {
+       "output_type": "stream",
+       "stream": "stdout",
+       "text": [
+        "2011-04-22 21:06 Grizzly 36\r\n",
+        "2011-04-23 14:12 Elk 25\r\n",
+        "2011-04-23 10:24 Elk 26\r\n",
+        "2011-04-23 20:08 Wolverine 31\r\n",
+        "2011-04-23 18:46 Muskox 20\r\n"
+       ]
+      }
+     ],
+     "prompt_number": 33
+    },
+    {
+     "cell_type": "code",
+     "collapsed": false,
+     "input": [
+      "def test_filter_animals1():\n",
+      "    date, time, animal, count = read_file('animals.txt')\n",
+      "    fdate, ftime, fanimal, fcount = filter_animals('Elk', date, time, animal, count)\n",
+      "    \n",
+      "    assert fdate == ['2011-04-23', '2011-04-23']\n",
+      "    assert ftime == ['14:12', '10:24']\n",
+      "    assert fanimal == ['Elk', 'Elk']\n",
+      "    assert fcount == [25, 26]"
+     ],
+     "language": "python",
+     "metadata": {},
+     "outputs": [],
+     "prompt_number": 37
+    },
+    {
+     "cell_type": "code",
+     "collapsed": false,
+     "input": [
+      "%nose"
+     ],
+     "language": "python",
+     "metadata": {},
+     "outputs": [
+      {
+       "html": [
+        "<div id=\"ipython_nose_d965cb31197d482394af98b11319a703\"></div>"
+       ],
+       "output_type": "display_data"
+      },
+      {
+       "javascript": [
+        "document.ipython_nose_d965cb31197d482394af98b11319a703 = $(\"#ipython_nose_d965cb31197d482394af98b11319a703\");"
+       ],
+       "output_type": "display_data"
+      },
+      {
+       "javascript": [
+        "document.ipython_nose_d965cb31197d482394af98b11319a703.append($(\"<span>.</span>\"));"
+       ],
+       "output_type": "display_data"
+      },
+      {
+       "javascript": [
+        "document.ipython_nose_d965cb31197d482394af98b11319a703.append($(\"<span>.</span>\"));"
+       ],
+       "output_type": "display_data"
+      },
+      {
+       "javascript": [
+        "document.ipython_nose_d965cb31197d482394af98b11319a703.append($(\"<span>.</span>\"));"
+       ],
+       "output_type": "display_data"
+      },
+      {
+       "javascript": [
+        "document.ipython_nose_d965cb31197d482394af98b11319a703.append($(\"<span>.</span>\"));"
+       ],
+       "output_type": "display_data"
+      },
+      {
+       "javascript": [
+        "document.ipython_nose_d965cb31197d482394af98b11319a703.append($(\"<span>.</span>\"));"
+       ],
+       "output_type": "display_data"
+      },
+      {
+       "javascript": [
+        "document.ipython_nose_d965cb31197d482394af98b11319a703.append($(\"<span>.</span>\"));"
+       ],
+       "output_type": "display_data"
+      },
+      {
+       "javascript": [
+        "delete document.ipython_nose_d965cb31197d482394af98b11319a703;"
+       ],
+       "output_type": "display_data"
+      },
+      {
+       "html": [
+        "    <style type=\"text/css\">\n",
+        "        span.nosefailedfunc {\n",
+        "            font-family: monospace;\n",
+        "            font-weight: bold;\n",
+        "        }\n",
+        "        div.noseresults {\n",
+        "            width: 100%;\n",
+        "        }\n",
+        "        div.nosebar {\n",
+        "            float: left;\n",
+        "            padding: 1ex 0px 1ex 0px;\n",
+        "        }\n",
+        "        div.nosebar.fail {\n",
+        "            background: #ff3019; /* Old browsers */\n",
+        "            /* FF3.6+ */\n",
+        "            background: -moz-linear-gradient(top, #ff3019 0%, #cf0404 100%);\n",
+        "            /* Chrome,Safari4+ */\n",
+        "            background: -webkit-gradient(linear, left top, left bottom,\n",
+        "                                         color-stop(0%,#ff3019),\n",
+        "                                         color-stop(100%,#cf0404));\n",
+        "            /* Chrome10+,Safari5.1+ */\n",
+        "            background: -webkit-linear-gradient(top, #ff3019 0%,#cf0404 100%);\n",
+        "            /* Opera 11.10+ */\n",
+        "            background: -o-linear-gradient(top, #ff3019 0%,#cf0404 100%);\n",
+        "            /* IE10+ */\n",
+        "            background: -ms-linear-gradient(top, #ff3019 0%,#cf0404 100%);\n",
+        "            /* W3C */\n",
+        "            background: linear-gradient(to bottom, #ff3019 0%,#cf0404 100%);\n",
+        "        }\n",
+        "        div.nosebar.pass {\n",
+        "            background: #52b152;\n",
+        "            background: -moz-linear-gradient(top, #52b152 1%, #008a00 100%);\n",
+        "            background: -webkit-gradient(linear, left top, left bottom,\n",
+        "                                         color-stop(1%,#52b152),\n",
+        "                                         color-stop(100%,#008a00));\n",
+        "            background: -webkit-linear-gradient(top, #52b152 1%,#008a00 100%);\n",
+        "            background: -o-linear-gradient(top, #52b152 1%,#008a00 100%);\n",
+        "            background: -ms-linear-gradient(top, #52b152 1%,#008a00 100%);\n",
+        "            background: linear-gradient(to bottom, #52b152 1%,#008a00 100%);\n",
+        "        }\n",
+        "        div.nosebar.skip {\n",
+        "            background: #f1e767;\n",
+        "            background: -moz-linear-gradient(top, #f1e767 0%, #feb645 100%);\n",
+        "            background: -webkit-gradient(linear, left top, left bottom,\n",
+        "                                         color-stop(0%,#f1e767),\n",
+        "                                         color-stop(100%,#feb645));\n",
+        "            background: -webkit-linear-gradient(top, #f1e767 0%,#feb645 100%);\n",
+        "            background: -o-linear-gradient(top, #f1e767 0%,#feb645 100%);\n",
+        "            background: -ms-linear-gradient(top, #f1e767 0%,#feb645 100%);\n",
+        "            background: linear-gradient(to bottom, #f1e767 0%,#feb645 100%);\n",
+        "        }\n",
+        "        div.nosebar.leftmost {\n",
+        "            border-radius: 4px 0 0 4px;\n",
+        "        }\n",
+        "        div.nosebar.rightmost {\n",
+        "            border-radius: 0 4px 4px 0;\n",
+        "        }\n",
+        "        div.nosefailbanner {\n",
+        "            border-radius: 4px 0 0 4px;\n",
+        "            border-left: 10px solid #cf0404;\n",
+        "            padding: 0.5ex 0em 0.5ex 1em;\n",
+        "            margin-top: 1ex;\n",
+        "            margin-bottom: 0px;\n",
+        "        }\n",
+        "        div.nosefailbanner.expanded {\n",
+        "            border-radius: 4px 4px 0 0;\n",
+        "            border-top: 10px solid #cf0404;\n",
+        "        }\n",
+        "        pre.nosetraceback {\n",
+        "            border-radius: 0 4px 4px 4px;\n",
+        "            border-left: 10px solid #cf0404;\n",
+        "            padding: 1em;\n",
+        "            margin-left: 0px;\n",
+        "            margin-top: 0px;\n",
+        "            display: none;\n",
+        "        }\n",
+        "    </style>\n",
+        "    \n",
+        "    <script>\n",
+        "        setTimeout(function () {\n",
+        "            $('.nosefailtoggle').bind(\n",
+        "                'click',\n",
+        "                function () {\n",
+        "                    $(\n",
+        "                        $(this)\n",
+        "                            .parent().toggleClass('expanded')\n",
+        "                            .parent()\n",
+        "                            .children()\n",
+        "                            .filter('.nosetraceback')\n",
+        "                    ).toggle();\n",
+        "                }\n",
+        "            );},\n",
+        "            0);\n",
+        "    </script>\n",
+        "    \n",
+        "    <div class=\"noseresults\">\n",
+        "      <div class=\"nosebar fail leftmost\" style=\"width: 0%\">\n",
+        "          &nbsp;\n",
+        "      </div>\n",
+        "      <div class=\"nosebar skip\" style=\"width: 0%\">\n",
+        "          &nbsp;\n",
+        "      </div>\n",
+        "      <div class=\"nosebar pass rightmost\" style=\"width: 100%\">\n",
+        "          &nbsp;\n",
+        "      </div>\n",
+        "      6/6 tests passed\n",
+        "    </div>\n",
+        "    "
+       ],
+       "output_type": "pyout",
+       "prompt_number": 38,
+       "text": [
+        "6/6 tests passed\n"
+       ]
+      }
+     ],
+     "prompt_number": 38
+    },
+    {
+     "cell_type": "code",
+     "collapsed": false,
+     "input": [
+      "d, t, a, c = read_file('animals.txt')\n",
+      "filter_animals('Grizzly', d, t, a, c)"
+     ],
+     "language": "python",
+     "metadata": {},
+     "outputs": [
+      {
+       "output_type": "pyout",
+       "prompt_number": 40,
+       "text": [
+        "(['2011-04-22'], ['21:06'], ['Grizzly'], [36])"
+       ]
+      }
+     ],
+     "prompt_number": 40
+    },
+    {
+     "cell_type": "code",
+     "collapsed": false,
+     "input": [
+      "def mean_animals(filename, species):\n",
+      "    d, t, a, c = read_file(filename)\n",
+      "    d, t, a, c = filter_animals(species, d, t, a, c)\n",
+      "    return calc_mean(c)"
+     ],
+     "language": "python",
+     "metadata": {},
+     "outputs": [],
+     "prompt_number": 41
+    },
+    {
+     "cell_type": "code",
+     "collapsed": false,
+     "input": [
+      "def test_mean_animals1():\n",
+      "    m = mean_animals('animals.txt', 'Elk')\n",
+      "    assert m == 25.5\n",
+      "\n",
+      "def test_mean_animals2():\n",
+      "    m = mean_animals('animals.txt', 'Grizzly')\n",
+      "    assert m == 36"
+     ],
+     "language": "python",
+     "metadata": {},
+     "outputs": [],
+     "prompt_number": 42
+    },
+    {
+     "cell_type": "code",
+     "collapsed": false,
+     "input": [
+      "%nose"
+     ],
+     "language": "python",
+     "metadata": {},
+     "outputs": [
+      {
+       "html": [
+        "<div id=\"ipython_nose_237eee0b04e94196a101b786319e18c1\"></div>"
+       ],
+       "output_type": "display_data"
+      },
+      {
+       "javascript": [
+        "document.ipython_nose_237eee0b04e94196a101b786319e18c1 = $(\"#ipython_nose_237eee0b04e94196a101b786319e18c1\");"
+       ],
+       "output_type": "display_data"
+      },
+      {
+       "javascript": [
+        "document.ipython_nose_237eee0b04e94196a101b786319e18c1.append($(\"<span>.</span>\"));"
+       ],
+       "output_type": "display_data"
+      },
+      {
+       "javascript": [
+        "document.ipython_nose_237eee0b04e94196a101b786319e18c1.append($(\"<span>.</span>\"));"
+       ],
+       "output_type": "display_data"
+      },
+      {
+       "javascript": [
+        "document.ipython_nose_237eee0b04e94196a101b786319e18c1.append($(\"<span>.</span>\"));"
+       ],
+       "output_type": "display_data"
+      },
+      {
+       "javascript": [
+        "document.ipython_nose_237eee0b04e94196a101b786319e18c1.append($(\"<span>.</span>\"));"
+       ],
+       "output_type": "display_data"
+      },
+      {
+       "javascript": [
+        "document.ipython_nose_237eee0b04e94196a101b786319e18c1.append($(\"<span>.</span>\"));"
+       ],
+       "output_type": "display_data"
+      },
+      {
+       "javascript": [
+        "document.ipython_nose_237eee0b04e94196a101b786319e18c1.append($(\"<span>.</span>\"));"
+       ],
+       "output_type": "display_data"
+      },
+      {
+       "javascript": [
+        "document.ipython_nose_237eee0b04e94196a101b786319e18c1.append($(\"<span>.</span>\"));"
+       ],
+       "output_type": "display_data"
+      },
+      {
+       "javascript": [
+        "document.ipython_nose_237eee0b04e94196a101b786319e18c1.append($(\"<span>.</span>\"));"
+       ],
+       "output_type": "display_data"
+      },
+      {
+       "javascript": [
+        "delete document.ipython_nose_237eee0b04e94196a101b786319e18c1;"
+       ],
+       "output_type": "display_data"
+      },
+      {
+       "html": [
+        "    <style type=\"text/css\">\n",
+        "        span.nosefailedfunc {\n",
+        "            font-family: monospace;\n",
+        "            font-weight: bold;\n",
+        "        }\n",
+        "        div.noseresults {\n",
+        "            width: 100%;\n",
+        "        }\n",
+        "        div.nosebar {\n",
+        "            float: left;\n",
+        "            padding: 1ex 0px 1ex 0px;\n",
+        "        }\n",
+        "        div.nosebar.fail {\n",
+        "            background: #ff3019; /* Old browsers */\n",
+        "            /* FF3.6+ */\n",
+        "            background: -moz-linear-gradient(top, #ff3019 0%, #cf0404 100%);\n",
+        "            /* Chrome,Safari4+ */\n",
+        "            background: -webkit-gradient(linear, left top, left bottom,\n",
+        "                                         color-stop(0%,#ff3019),\n",
+        "                                         color-stop(100%,#cf0404));\n",
+        "            /* Chrome10+,Safari5.1+ */\n",
+        "            background: -webkit-linear-gradient(top, #ff3019 0%,#cf0404 100%);\n",
+        "            /* Opera 11.10+ */\n",
+        "            background: -o-linear-gradient(top, #ff3019 0%,#cf0404 100%);\n",
+        "            /* IE10+ */\n",
+        "            background: -ms-linear-gradient(top, #ff3019 0%,#cf0404 100%);\n",
+        "            /* W3C */\n",
+        "            background: linear-gradient(to bottom, #ff3019 0%,#cf0404 100%);\n",
+        "        }\n",
+        "        div.nosebar.pass {\n",
+        "            background: #52b152;\n",
+        "            background: -moz-linear-gradient(top, #52b152 1%, #008a00 100%);\n",
+        "            background: -webkit-gradient(linear, left top, left bottom,\n",
+        "                                         color-stop(1%,#52b152),\n",
+        "                                         color-stop(100%,#008a00));\n",
+        "            background: -webkit-linear-gradient(top, #52b152 1%,#008a00 100%);\n",
+        "            background: -o-linear-gradient(top, #52b152 1%,#008a00 100%);\n",
+        "            background: -ms-linear-gradient(top, #52b152 1%,#008a00 100%);\n",
+        "            background: linear-gradient(to bottom, #52b152 1%,#008a00 100%);\n",
+        "        }\n",
+        "        div.nosebar.skip {\n",
+        "            background: #f1e767;\n",
+        "            background: -moz-linear-gradient(top, #f1e767 0%, #feb645 100%);\n",
+        "            background: -webkit-gradient(linear, left top, left bottom,\n",
+        "                                         color-stop(0%,#f1e767),\n",
+        "                                         color-stop(100%,#feb645));\n",
+        "            background: -webkit-linear-gradient(top, #f1e767 0%,#feb645 100%);\n",
+        "            background: -o-linear-gradient(top, #f1e767 0%,#feb645 100%);\n",
+        "            background: -ms-linear-gradient(top, #f1e767 0%,#feb645 100%);\n",
+        "            background: linear-gradient(to bottom, #f1e767 0%,#feb645 100%);\n",
+        "        }\n",
+        "        div.nosebar.leftmost {\n",
+        "            border-radius: 4px 0 0 4px;\n",
+        "        }\n",
+        "        div.nosebar.rightmost {\n",
+        "            border-radius: 0 4px 4px 0;\n",
+        "        }\n",
+        "        div.nosefailbanner {\n",
+        "            border-radius: 4px 0 0 4px;\n",
+        "            border-left: 10px solid #cf0404;\n",
+        "            padding: 0.5ex 0em 0.5ex 1em;\n",
+        "            margin-top: 1ex;\n",
+        "            margin-bottom: 0px;\n",
+        "        }\n",
+        "        div.nosefailbanner.expanded {\n",
+        "            border-radius: 4px 4px 0 0;\n",
+        "            border-top: 10px solid #cf0404;\n",
+        "        }\n",
+        "        pre.nosetraceback {\n",
+        "            border-radius: 0 4px 4px 4px;\n",
+        "            border-left: 10px solid #cf0404;\n",
+        "            padding: 1em;\n",
+        "            margin-left: 0px;\n",
+        "            margin-top: 0px;\n",
+        "            display: none;\n",
+        "        }\n",
+        "    </style>\n",
+        "    \n",
+        "    <script>\n",
+        "        setTimeout(function () {\n",
+        "            $('.nosefailtoggle').bind(\n",
+        "                'click',\n",
+        "                function () {\n",
+        "                    $(\n",
+        "                        $(this)\n",
+        "                            .parent().toggleClass('expanded')\n",
+        "                            .parent()\n",
+        "                            .children()\n",
+        "                            .filter('.nosetraceback')\n",
+        "                    ).toggle();\n",
+        "                }\n",
+        "            );},\n",
+        "            0);\n",
+        "    </script>\n",
+        "    \n",
+        "    <div class=\"noseresults\">\n",
+        "      <div class=\"nosebar fail leftmost\" style=\"width: 0%\">\n",
+        "          &nbsp;\n",
+        "      </div>\n",
+        "      <div class=\"nosebar skip\" style=\"width: 0%\">\n",
+        "          &nbsp;\n",
+        "      </div>\n",
+        "      <div class=\"nosebar pass rightmost\" style=\"width: 100%\">\n",
+        "          &nbsp;\n",
+        "      </div>\n",
+        "      8/8 tests passed\n",
+        "    </div>\n",
+        "    "
+       ],
+       "output_type": "pyout",
+       "prompt_number": 43,
+       "text": [
+        "8/8 tests passed\n"
+       ]
+      }
+     ],
+     "prompt_number": 43
+    },
     {
      "cell_type": "code",
      "collapsed": false,
diff --git a/python/sw_engineering/mean_animals.ipynb b/python/sw_engineering/mean_animals.ipynb
new file mode 100644 (file)
index 0000000..2cbbae4
--- /dev/null
@@ -0,0 +1,96 @@
+{
+ "metadata": {
+  "name": "mean_animals"
+ },
+ "nbformat": 3,
+ "nbformat_minor": 0,
+ "worksheets": [
+  {
+   "cells": [
+    {
+     "cell_type": "code",
+     "collapsed": false,
+     "input": [
+      "%%file meananimals.py\n",
+      "def read_file(ifile):\n",
+      "    open_file = open(ifile, 'r')\n",
+      "    \n",
+      "    time = []\n",
+      "    date = []\n",
+      "    animal = []\n",
+      "    count = []\n",
+      "    \n",
+      "    for iline in open_file:\n",
+      "        s = iline.split()\n",
+      "        date.append(s[0])\n",
+      "        time.append(s[1])\n",
+      "        animal.append(s[2])\n",
+      "        count.append(int(s[3]))\n",
+      "    \n",
+      "    open_file.close()\n",
+      "    \n",
+      "    return date, time, animal, count\n",
+      "\n",
+      "def calc_mean(ilist):\n",
+      "    '''\n",
+      "    returns the mean of input list\n",
+      "    '''\n",
+      "    if len(ilist) == 0:\n",
+      "        raise ValueError('Input is empty.')\n",
+      "        \n",
+      "    total = 0.0\n",
+      "    for num in ilist:\n",
+      "        total = total + num\n",
+      "    return total/float(len(ilist))\n",
+      "\n",
+      "def filter_animals(species, date, time, animal, count):\n",
+      "    \"\"\"\n",
+      "    Given a particular species, filter out the data for just that species.\n",
+      "\n",
+      "    Returns four lists: date, time, animal, count.\n",
+      "    \"\"\"\n",
+      "    fdate = []\n",
+      "    ftime = []\n",
+      "    fanimal = []\n",
+      "    fcount = []\n",
+      "    \n",
+      "    for d, t, a, c in zip(date, time, animal, count):\n",
+      "        if a == species:\n",
+      "            fdate.append(d)\n",
+      "            ftime.append(t)\n",
+      "            fanimal.append(a)\n",
+      "            fcount.append(c)\n",
+      "    \n",
+      "    return fdate, ftime, fanimal, fcount\n",
+      "\n",
+      "def mean_animals(filename, species):\n",
+      "    d, t, a, c = read_file(filename)\n",
+      "    d, t, a, c = filter_animals(species, d, t, a, c)\n",
+      "    return calc_mean(c)"
+     ],
+     "language": "python",
+     "metadata": {},
+     "outputs": [
+      {
+       "output_type": "stream",
+       "stream": "stdout",
+       "text": [
+        "Writing meananimals.py\n"
+       ]
+      }
+     ],
+     "prompt_number": 1
+    },
+    {
+     "cell_type": "code",
+     "collapsed": false,
+     "input": [],
+     "language": "python",
+     "metadata": {},
+     "outputs": []
+    }
+   ],
+   "metadata": {}
+  }
+ ]
+}
\ No newline at end of file
diff --git a/python/sw_engineering/meananimals.py b/python/sw_engineering/meananimals.py
new file mode 100644 (file)
index 0000000..22bce35
--- /dev/null
@@ -0,0 +1,55 @@
+def read_file(ifile):
+    open_file = open(ifile, 'r')
+    
+    time = []
+    date = []
+    animal = []
+    count = []
+    
+    for iline in open_file:
+        s = iline.split()
+        date.append(s[0])
+        time.append(s[1])
+        animal.append(s[2])
+        count.append(int(s[3]))
+    
+    open_file.close()
+    
+    return date, time, animal, count
+
+def calc_mean(ilist):
+    '''
+    returns the mean of input list
+    '''
+    if len(ilist) == 0:
+        raise ValueError('Input is empty.')
+        
+    total = 0.0
+    for num in ilist:
+        total = total + num
+    return total/float(len(ilist))
+
+def filter_animals(species, date, time, animal, count):
+    """
+    Given a particular species, filter out the data for just that species.
+
+    Returns four lists: date, time, animal, count.
+    """
+    fdate = []
+    ftime = []
+    fanimal = []
+    fcount = []
+    
+    for d, t, a, c in zip(date, time, animal, count):
+        if a == species:
+            fdate.append(d)
+            ftime.append(t)
+            fanimal.append(a)
+            fcount.append(c)
+    
+    return fdate, ftime, fanimal, fcount
+
+def mean_animals(filename, species):
+    d, t, a, c = read_file(filename)
+    d, t, a, c = filter_animals(species, d, t, a, c)
+    return calc_mean(c)
\ No newline at end of file
diff --git a/python/sw_engineering/research.ipynb b/python/sw_engineering/research.ipynb
new file mode 100644 (file)
index 0000000..fd98307
--- /dev/null
@@ -0,0 +1,90 @@
+{
+ "metadata": {
+  "name": "research"
+ },
+ "nbformat": 3,
+ "nbformat_minor": 0,
+ "worksheets": [
+  {
+   "cells": [
+    {
+     "cell_type": "code",
+     "collapsed": false,
+     "input": [
+      "import meananimals"
+     ],
+     "language": "python",
+     "metadata": {},
+     "outputs": [],
+     "prompt_number": 1
+    },
+    {
+     "cell_type": "code",
+     "collapsed": false,
+     "input": [
+      "meananimals.mean_animals('animals.txt', 'Elk')"
+     ],
+     "language": "python",
+     "metadata": {},
+     "outputs": [
+      {
+       "output_type": "pyout",
+       "prompt_number": 2,
+       "text": [
+        "25.5"
+       ]
+      }
+     ],
+     "prompt_number": 2
+    },
+    {
+     "cell_type": "code",
+     "collapsed": false,
+     "input": [
+      "meananimals.mean_animals('big_animals.txt', 'Elk')"
+     ],
+     "language": "python",
+     "metadata": {},
+     "outputs": [
+      {
+       "output_type": "pyout",
+       "prompt_number": 3,
+       "text": [
+        "24.22222222222222"
+       ]
+      }
+     ],
+     "prompt_number": 3
+    },
+    {
+     "cell_type": "code",
+     "collapsed": false,
+     "input": [
+      "!wc -l big_animals.txt"
+     ],
+     "language": "python",
+     "metadata": {},
+     "outputs": [
+      {
+       "output_type": "stream",
+       "stream": "stdout",
+       "text": [
+        "     100 big_animals.txt\r\n"
+       ]
+      }
+     ],
+     "prompt_number": 4
+    },
+    {
+     "cell_type": "code",
+     "collapsed": false,
+     "input": [],
+     "language": "python",
+     "metadata": {},
+     "outputs": []
+    }
+   ],
+   "metadata": {}
+  }
+ ]
+}
\ No newline at end of file