{
 "metadata": {
  "name": "",
  "signature": "sha256:bc50d15e4618afafc7cbb3feab475a110d7e039ac562addd73b3cc9d6a5b1137"
 },
 "nbformat": 3,
 "nbformat_minor": 0,
 "worksheets": [
  {
   "cells": [
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "# More Python Goodness (1)\n",
      "***\n",
      "\n",
      "[Wibowo Arindrarto](mailto:w.arindrarto@lumc.nl), [Sequencing Analysis Support Core, Leiden University Medical Center](http://sasc.lumc.nl)\n",
      "\n",
      "[Martijn Vermaat](mailto:m.vermaat.hg@lumc.nl), [Department of Human Genetics, Leiden University Medical Center](http://humgen.nl)\n",
      "\n",
      "License: [Creative Commons Attribution 3.0 License (CC-by)](http://creativecommons.org/licenses/by/3.0)"
     ]
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "## Table of contents\n",
      "\n",
      "1. [Working with scripts](#scripts)\n",
      "2. [The standard library](#stdlib)\n",
      "3. [String methods](#stringmethods)\n",
      "4. [Comments and docstrings](#docstrings)\n",
      "5. [Detour: PEP8 and other PEPs](#peps)\n",
      "6. [Errors and exceptions](#exceptions)\n",
      "7. Working with modules\n",
      "8. Examples from the standard library\n",
      "9. Reading and writing files\n",
      "10. Assignment: Finding the most common 7-mer in a FASTA file\n",
      "11. Further reading"
     ]
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "<a id=\"scripts\"></a>\n",
      "## Working with scripts\n",
      "\n",
      "Interpreters are great for *prototyping*, but not really suitable if you want to **share** or **release** code. To do so, we write our Python commands in scripts (and later, modules).\n",
      "\n",
      "A **script** is a simple text file containing Python instructions to execute."
     ]
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "### Executing scripts\n",
      "\n",
      "There are two common ways to execute a script:\n",
      "\n",
      "1. As an argument of the Python interpreter command.\n",
      "2. As a standalone executable (with the appropriate shebang line & file mode).\n",
      "\n",
      "IPython gives you a third option:\n",
      "\n",
      "<ol start=\"3\">\n",
      "  <li>As an argument of the `%run` magic.\n",
      "</ol>"
     ]
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "### Writing your script\n",
      "\n",
      "Let's start with a simple GC calculator. Open your text editor, and write the following Python statements (remember your indentations):\n",
      "\n",
      "    def calc_gc_percent(seq):\n",
      "        at_count, gc_count = 0, 0\n",
      "        for char in seq:\n",
      "            if char in ('A', 'T'):\n",
      "                at_count += 1\n",
      "            elif char in ('G', 'C'):\n",
      "                gc_count += 1\n",
      "                \n",
      "        return gc_count * 100.0 / (gc_count + at_count)       \n",
      "\n",
      "    print \"The sequence 'CAGG' has a %GC of {:.2f}\".format(\n",
      "              calc_gc_percent(\"CAGG\"))\n",
      "\n",
      "Save the file as `seq_toolbox.py` (you can use any other name if you like) and go to your shell."
     ]
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "### Running the script\n",
      "\n",
      "Let's try the first method: using your script as an argument:\n",
      "\n",
      "    $ python seq_toolbox.py\n",
      "\n",
      "Is the output as you expect?\n",
      "\n",
      "For the second method, we need to do two more things:\n",
      "\n",
      "1. Open the script in your editor and add the following line to the very top:\n",
      "\n",
      "        #!/usr/bin/env python\n",
      "\n",
      "2. Save the file, go back to the shell, and allow the file to be executed:\n",
      "\n",
      "        $ chmod +x seq_toolbox.py\n",
      "\n",
      "You can now execute the file directly:\n",
      "\n",
      "    $ ./seq_toolbox.py\n",
      "\n",
      "Is the output the same as the previous method?\n",
      "\n",
      "Finally, try out the third method. Open an IPython interpreter session and do:\n",
      "\n",
      "    %run seq_toolbox.py"
     ]
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "<a id=\"stdlib\"></a>\n",
      "## The standard library\n",
      "\n",
      "Our script is nice and dandy, but we don't want to edit the source file everytime we calculate a sequence's GC.\n",
      "\n",
      "The **standard library** is a collection of Python modules (or functions, for now) that comes packaged with a default Python installation. They're not part of the language per se, more like a *batteries included* thing."
     ]
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "### Our first standard library module: `sys`\n",
      "\n",
      "We'll start by using the simple `sys` module to make our script more flexible.\n",
      "\n",
      "Standard library (and other modules, as we'll see later) can be used via the `import` statement, for example:"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "import sys"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 1
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "Like other objects so far, we can peek into the documentation of these modules using `help`, or the IPython `?` shortcut. For example:"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "sys?"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 2
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "### The `sys.argv` list\n",
      "\n",
      "The `sys` module provides a way to capture command line arguments with its `argv` object. This is a list of arguments supplied when invoking the current Python session. Not really useful for an interpreter session, but very handy for scripts."
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "sys.argv"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 3,
       "text": [
        "['-c',\n",
        " '-f',\n",
        " '/home/martijn/.ipython/profile_default/security/kernel-9535cbe5-e69a-4c48-91f2-80a022c362b9.json',\n",
        " \"--IPKernelApp.parent_appname='ipython-notebook'\",\n",
        " '--profile-dir',\n",
        " '/home/martijn/.ipython/profile_default',\n",
        " '--parent=1']"
       ]
      }
     ],
     "prompt_number": 3
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "sys.argv[:3]"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 4,
       "text": [
        "['-c',\n",
        " '-f',\n",
        " '/home/martijn/.ipython/profile_default/security/kernel-9535cbe5-e69a-4c48-91f2-80a022c362b9.json']"
       ]
      }
     ],
     "prompt_number": 4
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "### Improving our script with `sys.argv`\n",
      "\n",
      "To use `sys.argv` in our script, open a text editor and edit the script by adding an import statement, capturing the `sys.argv` value, and editing our last `print` line:\n",
      "\n",
      "    #!/usr/bin/env python\n",
      "    import sys\n",
      "\n",
      "    def calc_gc_percent(seq):\n",
      "        at_count, gc_count = 0, 0\n",
      "        for char in seq:\n",
      "            if char in ('A', 'T'):\n",
      "                at_count += 1\n",
      "            elif char in ('G', 'C'):\n",
      "                gc_count += 1\n",
      "\n",
      "        return gc_count * 100.0 / (gc_count + at_count)       \n",
      "\n",
      "    input_seq = sys.argv[1]\n",
      "    print \"The sequence '{}' has a %GC of {:.2f}\".format(\n",
      "              input_seq, calc_gc_percent(input_seq))\n",
      "\n",
      "To test it, you can run the following command in your shell:\n",
      "\n",
      "    $ python seq_toolbox.py CAGG\n",
      "\n",
      "Try it with `./seq_toolbox.py` instead. What happens?"
     ]
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "<a id=\"stringmethods\"></a>\n",
      "## String methods\n",
      "\n",
      "Try running the script with `'cagg'` as the input sequence. What happens?\n",
      "\n",
      "As we saw earlier, many objects, like those of type `list`, `dict`, or `str`, have useful methods defined on them. One way to squash this potential bug is by using Python's string method `upper`. Let's first check out some commonly used string functions.\n"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "my_str = 'Hello again, ipython!'"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 5
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "my_str.upper()"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 6,
       "text": [
        "'HELLO AGAIN, IPYTHON!'"
       ]
      }
     ],
     "prompt_number": 6
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "my_str.lower()"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 7,
       "text": [
        "'hello again, ipython!'"
       ]
      }
     ],
     "prompt_number": 7
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "my_str.title()"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 8,
       "text": [
        "'Hello Again, Ipython!'"
       ]
      }
     ],
     "prompt_number": 8
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "my_str.startswith('H')"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 9,
       "text": [
        "True"
       ]
      }
     ],
     "prompt_number": 9
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "my_str.startswith('h')"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 10,
       "text": [
        "False"
       ]
      }
     ],
     "prompt_number": 10
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "my_str.split(',')"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 11,
       "text": [
        "['Hello again', ' ipython!']"
       ]
      }
     ],
     "prompt_number": 11
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "my_str.replace('ipython', 'lumc')"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 12,
       "text": [
        "'Hello again, lumc!'"
       ]
      }
     ],
     "prompt_number": 12
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "my_str.count('n')"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 13,
       "text": [
        "2"
       ]
      }
     ],
     "prompt_number": 13
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "### Improving our script with `upper()`\n",
      "\n",
      "Let's use `upper()` to fortify our function. It should now look something like this:\n",
      "\n",
      "    def calc_gc_percent(seq):\n",
      "        at_count, gc_count = 0, 0\n",
      "        for char in seq.upper():\n",
      "            if char in ('A', 'T'):\n",
      "                at_count += 1\n",
      "            elif char in ('G', 'C'):\n",
      "                gc_count += 1\n",
      "\n",
      "        return gc_count * 100.0 / (gc_count + at_count)       \n",
      "\n",
      "And run it (in whichever way you prefer). Do you get the expected output?"
     ]
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "<a id=\"docstrings\"></a>\n",
      "## Comments and docstrings\n",
      "\n",
      "There's a golden rule in programming: write code for humans (this includes you in 6 months).  Python provides two ways to accomplish this: comments and docstrings.\n",
      "\n",
      "### Comments\n",
      "\n",
      "Any lines prepended with `#` are **comments**, making them ignored by the interpreter. Comments can be freeform text; anything that helps in understanding the code\n",
      "\n",
      "### Docstrings\n",
      "\n",
      "**Docstrings** are Python's way of attaching proper documentation to objects. Officially, the first string literal that occurs in a module, function, class, or method definition is used as that object's docstring.\n",
      "\n",
      "In practice, *triple-quoted strings* are used, to handle newlines easier.\n",
      "\n",
      "Remember how we used the `help` function (or IPython's `?` shortcut) to get information about an object, function, or module? This actually prints that object's docstring."
     ]
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "### Improving our script with comments and docstrings\n",
      "\n",
      "Open your script again in a text editor, and add the following comments and docstrings: \n",
      "\n",
      "    #!/usr/bin/env python\n",
      "    import sys\n",
      "\n",
      "    def calc_gc_percent(seq):\n",
      "        \"\"\"\n",
      "        Calculates the GC percentage of the given sequence.\n",
      "\n",
      "        Arguments:\n",
      "            - seq - the input sequence (string).\n",
      "\n",
      "        Returns:\n",
      "            - GC percentage (float).\n",
      "\n",
      "        The returned value is always <= 100.0\n",
      "        \"\"\"\n",
      "        at_count, gc_count = 0, 0\n",
      "        # Change input to all caps to allow for non-capital\n",
      "        # input sequence.\n",
      "        for char in seq.upper():\n",
      "            if char in ('A', 'T'):\n",
      "                at_count += 1\n",
      "            elif char in ('G', 'C'):\n",
      "                gc_count += 1\n",
      "\n",
      "        return gc_count * 100.0 / (gc_count + at_count)       \n",
      "\n",
      "    input_seq = sys.argv[1]\n",
      "    print \"The sequence '{}' has a %GC of {:.2f}\".format(\n",
      "              input_seq, calc_gc_percent(input_seq))"
     ]
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "<a id=\"peps\"></a>\n",
      "## Detour: PEP8 and other PEPs\n",
      "\n",
      "Since comments and docstrings are basically free-form text, whether it's useful or not depends heavily on the developer. To mitigate this, the Python community has come up with practical conventions. They are documented in a document called **PEP8**.\n",
      "\n",
      "Complementary to PEP8, there is **PEP257** which is for docstrings specifically. It's not a must to follow these conventions, but *very* encouraged to do so.\n",
      "\n",
      "Python Enhancement Proposals, or **PEP**s, are how Python grows. There are hundreds of them now, all have to be approved by our BDFL.\n",
      "\n",
      "> [PEP8: Style Guide for Python Code](http://www.python.org/dev/peps/pep-0008/)\n",
      "\n",
      "> [PEP257: Docstring Conventions](http://www.python.org/dev/peps/pep-0257/)"
     ]
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "<a id=\"exceptions\"></a>\n",
      "## Errors and exceptions\n",
      "\n",
      "Try running the script with `ACTG123` as the argument. What happens? Is this acceptable behavior?\n",
      "\n",
      "Sometimes we want to put safeguards to handle invalid inputs. In this case we only accept `ACTG`, all other characters are invalid.\n",
      "\n",
      "Python provides a way to break out of the normal execution flow, by raising what's called as an **exception**. We can raise exceptions ourselves as well, by using the `raise` statement."
     ]
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "### The `ValueError` built-in exception\n",
      "\n",
      "One of the most often used exceptions is the builtin exception `ValueError`. It is used on occasions where inappropriate argument values are used, for example when trying to convert the string `A` to an integer:"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "int('A')"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "ename": "ValueError",
       "evalue": "invalid literal for int() with base 10: 'A'",
       "output_type": "pyerr",
       "traceback": [
        "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[1;31mValueError\u001b[0m                                Traceback (most recent call last)",
        "\u001b[1;32m<ipython-input-14-0da6d315d7ad>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'A'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
        "\u001b[1;31mValueError\u001b[0m: invalid literal for int() with base 10: 'A'"
       ]
      }
     ],
     "prompt_number": 14
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "`ValueError` is the appropriate exception to raise when your function is called with argument values it cannot handle."
     ]
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "### Improving our script by handling invalid inputs\n",
      "\n",
      "Open your script, and edit the `if` clause to add our exception:\n",
      "\n",
      "    def calc_gc_percent(seq):\n",
      "        \"\"\"\n",
      "        Calculates the GC percentage of the given sequence.\n",
      "\n",
      "        Arguments:\n",
      "            - seq - the input sequence (string).\n",
      "\n",
      "        Returns:\n",
      "            - GC percentage (float).\n",
      "\n",
      "        The returned value is always <= 100.0\n",
      "        \"\"\"\n",
      "        at_count, gc_count = 0, 0\n",
      "        # Change input to all caps to allow for non-capital\n",
      "        # input sequence.\n",
      "        for char in seq.upper():\n",
      "            if char in ('A', 'T'):\n",
      "                at_count += 1\n",
      "            elif char in ('G', 'C'):\n",
      "                gc_count += 1\n",
      "            else:\n",
      "                raise ValueError(\n",
      "                    \"Unexpeced character found: {}. Only \"\n",
      "                    \"ACTGs are allowed.\".format(char))\n",
      "             \n",
      "        return gc_count * 100.0 / (gc_count + at_count)\n",
      "\n",
      "Try running the script again with `ACTG123` as the argument. What happens now?"
     ]
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "### Handling corner cases\n",
      "\n",
      "Try running the script with `''` (two quote signs) as the argument. What happens? Why? Is this a valid input?\n",
      "\n",
      "We don't always want to let exceptions stop program flow, sometimes we want to provide alternative flow. The `try ... except` block allows you to do this.\n",
      "\n",
      "The syntax is:\n",
      "\n",
      "    try:\n",
      "        # Statements that may raise exceptions.\n",
      "        # [...]\n",
      "    except {exception type}:\n",
      "        # What to do when the exceptionis raised.\n",
      "        # [...]"
     ]
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "### Improving our script by handling corner cases\n",
      "\n",
      "Let's change our script by adding a `try ... except` block:\n",
      "\n",
      "    def calc_gc_percent(seq):\n",
      "        \"\"\"\n",
      "        Calculates the GC percentage of the given sequence.\n",
      "\n",
      "        Arguments:\n",
      "            - seq - the input sequence (string).\n",
      "\n",
      "        Returns:\n",
      "            - GC percentage (float).\n",
      "\n",
      "        The returned value is always <= 100.0\n",
      "        \"\"\"\n",
      "        at_count, gc_count = 0, 0\n",
      "        # Change input to all caps to allow for non-capital\n",
      "        # input sequence.\n",
      "        for char in seq.upper():\n",
      "            if char in ('A', 'T'):\n",
      "                at_count += 1\n",
      "            elif char in ('G', 'C'):\n",
      "                gc_count += 1\n",
      "            else:\n",
      "                raise ValueError(\n",
      "                    \"Unexpeced character found: {}. Only \"\n",
      "                    \"ACTGs are allowed.\".format(char))\n",
      "\n",
      "        # Corner case handling: empty input sequence.\n",
      "        try:\n",
      "            return gc_count * 100.0 / (gc_count + at_count)\n",
      "        except ZeroDivisionError:\n",
      "            return 0.0"
     ]
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "### Detour: Exception handling best practices\n",
      "\n",
      "#### Aim for a minimal `try` block\n",
      "\n",
      "We want to be able to pinpoint the statements that may raise the exceptions so we can tailor our handling.\n",
      "\n",
      "Example of code that violates this principle:\n",
      "\n",
      "    try:\n",
      "        my_function()\n",
      "        my_other_function()\n",
      "    except ValueError:\n",
      "        my_fallback_function()\n",
      "\n",
      "A better way would be:\n",
      "\n",
      "    try:\n",
      "        my_function()\n",
      "    except ValueError:\n",
      "        my_fallback_function()\n",
      "    my_other_function()"
     ]
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "#### Be specific when handling exceptions\n",
      "\n",
      "The following code is syntactically valid, but *never* use it in your real scripts / programs:\n",
      "\n",
      "    try:\n",
      "        my_function()\n",
      "    except:\n",
      "        my_fallback_function()\n",
      "\n",
      "*Always* use the full exception name when handling exceptions, to make for a much cleaner code:\n",
      "\n",
      "    try:\n",
      "        my_function()\n",
      "    except ValueError:\n",
      "        my_fallback_function()\n",
      "    except TypeError:\n",
      "        my_other_fallback_function()\n",
      "    except IndexError:\n",
      "        my_final_function()"
     ]
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "#### Look Before You Leap (LBYL) vs Easier to Ask for Apology (EAFP)\n",
      " \n",
      "We could have written our last exception block like so:\n",
      "\n",
      "    if gc_count + at_count == 0:\n",
      "        return 0.0\n",
      "    return gc_count * 100.0 / (gc_count + at_count)\n",
      "\n",
      "Both approaches are correct and have their own plus and minuses in general. However in this case, I would argue that EAFP is better since it makes the code more readable."
     ]
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "### Improving our script by handling more corner cases\n",
      "\n",
      "Now try running your script without any arguments at all. What happens?\n",
      "\n",
      "Armed with what you now know, how would you handle this situation?"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "from IPython.core.display import HTML\n",
      "def custom_style():\n",
      "    style = open('styles/notebook.css', 'r').read()\n",
      "    return HTML('<style>' + style + '</style>')\n",
      "def custom_script():\n",
      "    script = open('styles/notebook.js', 'r').read()\n",
      "    return HTML('<script>' + script + '</script>')"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 15
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "custom_style()"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "html": [
        "<style>/*\n",
        "  https://github.com/CamDavidsonPilon/Probabilistic-Programming-and-Bayesian-Methods-for-Hackers\n",
        "*/\n",
        "@font-face {\n",
        "    font-family: \"Computer Modern\";\n",
        "    src: url('http://mirrors.ctan.org/fonts/cm-unicode/fonts/otf/cmunss.otf');\n",
        "}\n",
        "div.cell{\n",
        "    width:800px;\n",
        "    margin-left:16% !important;\n",
        "    margin-right:auto;\n",
        "}\n",
        "h1 {\n",
        "    font-family: Helvetica, serif;\n",
        "}\n",
        "h4{\n",
        "    margin-top:12px;\n",
        "    margin-bottom: 3px;\n",
        "   }\n",
        "div.text_cell_render{\n",
        "    font-family: Computer Modern, \"Helvetica Neue\", Arial, Helvetica, Geneva, sans-serif;\n",
        "    line-height: 145%;\n",
        "    font-size: 130%;\n",
        "    width:800px;\n",
        "    margin-left:auto;\n",
        "    margin-right:auto;\n",
        "}\n",
        ".CodeMirror{\n",
        "        font-family: \"Source Code Pro\", source-code-pro,Consolas, monospace;\n",
        "}\n",
        ".prompt{\n",
        "    display: None;\n",
        "}\n",
        ".text_cell_render .exercise {\n",
        "    font-weight: 300;\n",
        "    /*font-size: 22pt;*/\n",
        "    color: #4057A1;\n",
        "    font-style: italic;\n",
        "    /*margin-bottom: .5em;\n",
        "    margin-top: 0.5em;\n",
        "    display: block;*/\n",
        "}\n",
        ".text_cell_render .example {\n",
        "    font-weight: 300;\n",
        "    color: #40A157;\n",
        "    font-style: italic;\n",
        "}\n",
        "\n",
        ".warning{\n",
        "    color: rgb( 240, 20, 20 )\n",
        "}\n",
        "</style>"
       ],
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 16,
       "text": [
        "<IPython.core.display.HTML at 0x2ceccd0>"
       ]
      }
     ],
     "prompt_number": 16
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "custom_script()"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "html": [
        "<script>// https://github.com/CamDavidsonPilon/Probabilistic-Programming-and-Bayesian-Methods-for-Hackers\n",
        "MathJax.Hub.Config({\n",
        "                    TeX: {\n",
        "                       extensions: [\"AMSmath.js\"]\n",
        "                       },\n",
        "            tex2jax: {\n",
        "                inlineMath: [ ['$','$'], [\"\\\\(\",\"\\\\)\"] ],\n",
        "                displayMath: [ ['$$','$$'], [\"\\\\[\",\"\\\\]\"] ]\n",
        "            },\n",
        "            displayAlign: 'center', // Change this to 'center' to center equations.\n",
        "            \"HTML-CSS\": {\n",
        "                styles: {'.MathJax_Display': {\"margin\": 4}}\n",
        "            }\n",
        "    });\n",
        "</script>"
       ],
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 17,
       "text": [
        "<IPython.core.display.HTML at 0x2cecdd0>"
       ]
      }
     ],
     "prompt_number": 17
    }
   ],
   "metadata": {}
  }
 ]
}