From 0d8fb24cdce4370e5f648b8384b5f9564e4cc137 Mon Sep 17 00:00:00 2001 From: mellybinda Date: Mon, 17 Jul 2017 17:33:55 +0100 Subject: [PATCH] Add files via upload Thanks to Annarita Buonaura --- Seminar1_main.ipynb | 1015 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1015 insertions(+) create mode 100644 Seminar1_main.ipynb diff --git a/Seminar1_main.ipynb b/Seminar1_main.ipynb new file mode 100644 index 0000000..16eb485 --- /dev/null +++ b/Seminar1_main.ipynb @@ -0,0 +1,1015 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Intro to numpy\n", + "\n", + "This notebook's gonna teach you to play around with data using numpy, pandas and matplotlib.\n", + "\n", + "Let's get started!\n", + "\n", + "#### Jupyter primer:\n", + "* Those blocks below are cells. Click on cell to select. Ctrl+enter to run code from cell.\n", + "* Click topbar \"+\" button to create new cell.\n", + "* Sometimes we'll ask you to add ``" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "#execute this cell\n", + "\n", + "from __future__ import print_function\n", + "\n", + "import math" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "#type \"math.\" or \"math.s\" and press tab\n", + "" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "#type math.atan2() and press shift+tab inside the brackets\n", + "" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "del math\n", + "\n", + "#oops, i destroyed math :)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Gettin' all vectorized with Numpy" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import numpy as np\n", + "\n", + "#numpy's main object is the homogeneous multidimensional array.\n", + "a = np.array([1,2,3,4,5])\n", + "b = np.array([5,4,3,2,1])\n", + "\n", + "print (\"a = \",a)\n", + "print (\"b = \",b)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "#Arithmetic operators on arrays apply elementwise. \n", + "print (\"a+1 =\", a+1)\n", + "print (\"a*2 =\", a*2)\n", + "\n", + "#Or pairwise, etc.\n", + "print (\"a+b =\",a+b)\n", + "print (\"a*b + b**a =\",a*b + b**a)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Numpy's also rich on functions that compute all kinds of stuff" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print (\"numpy.sum(a) = \",np.sum(a))\n", + "print (\"numpy.mean(a) = \", np.mean(a))\n", + "print (\"numpy.min(a) = \", np.min(a))\n", + "print (\"numpy.argmax(a) = \", np.argmax(a)) #index of minimal element\n", + "print (\"numpy.log(b) = \",np.log(b))\n", + "print (\"numpy.arctan(b) = \",np.arctan(b))\n", + "print (\"numpy.unique(['b','c','d','c','b']) = \",np.unique(['b','c','d','c','b']))\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Wax on, wax off" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "#The basics of numpy\n", + "print (\"Difference between a and b:\", )\n", + "print (\"Sum of squares of a and b:\", )\n", + "print (\"a minus 2 divided by square root of b\", )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "print (\"difference between minimum and maximum of a\", )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print (\"mean squared error between a and b\", )" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Hello, data" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import pandas as pd\n", + "data = pd.read_csv(\"small_higgs.csv\",na_values=-999).fillna(0)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "#Data's a table, 2d array. Here's first 10 elements.\n", + "data[:10]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "#Data shapes\n", + "print (\"len(data) = \",len(data))\n", + "print (\"data.shape = \",data.shape)\n", + "print (\"data.columns = \",data.columns)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "#selecting just one row\n", + "print (data.iloc[4])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "#first 5 elements\n", + "print(data[0:5])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "#Selecting columns\n", + "print (data[\"PRI_jet_leading_eta\"])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "#Or everything at once\n", + "data[[\"Label\",\"PRI_jet_leading_phi\",\"PRI_jet_leading_eta\"]][5:10]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Column's basically an array\n", + "\n", + "You can do anything you've done before with arrays - now with actual data." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "np.cos(data[\"PRI_jet_leading_phi\"])[:5]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "phi = data[\"PRI_jet_leading_phi\"]\n", + "print (\"sin^2(phi) + cos^2(phi) = \",)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Numpy booleans and indexing" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "#Logical operations are also elementwise\n", + "print (\"a==2\", a==2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print \"Boolean ops\"\n", + "\n", + "print (\"a>2\",a>2) #suports <, !=, <=, etc.\n", + "print (\"numpy.logical_not(a>2) = \", np.logical_not(a>2))\n", + "print (\"numpy.logical_and(a>2,b>2) = \", np.logical_and(a>2,b>2))\n", + "print (\"numpy.logical_or(a>4,b<3) = \", np.logical_or(a>2,b<3))\n", + "\n", + "print \"\\nOr simpler\"\n", + "print (\"~(a>2) = \",~(a>2)) #like logical_not\n", + "print (\"(a>2)&(b>2) = \", (a>2)&(b>2)) #lk logical_and\n", + "print (\"(a>2)|(b<3) = \", (a>2)|(b<3)) #как logical_or\n", + "\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print (\"\\n\\nSelecting with booleans\")\n", + "\n", + "#Selecting elements that match boolean predicate\n", + "print (\"a = \",a)\n", + "print (\"a >= 3 =\",a>=3)\n", + "print (\"a[a>=3] =\", a[a>=3])\n", + "print (\"b[a>=3] =\", b[a>=3])\n", + "print (\"numpy.where(a>=3) =\",np.where(a>=3)) #indices where mask is True\n", + "\n", + "\n", + "print (\"\\nYou can also select elements by their index\")\n", + "print (\"a[[1,3,4]] = \", a[[1,3,4]])\n", + "print (\"a[[1,2,2,3]] = \", a[[1,2,2,3]]) #repeat a[2] twice\n", + "print (\"a[numpy.where(a%2!=0)] = \", a[np.where(a%2!=0)]) #same as a[a%2!=0]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Doing stuff" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "#Compute mean and standard deviation of PRI_jet_all_pt\n", + "#of only those events where PRI_jet_num equals 2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "#Find the data row with largest PRI_jet_all_pt among those where PRI_jet_num equals 1,\n", + "#Print that row\n", + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### More numpy\n", + "\n", + "* Full reference aka docs [[here]](https://docs.scipy.org/doc/numpy/reference/)\n", + "* Cheat sheet - [[here]](https://pbs.twimg.com/media/C23mQfaWEAAGzBn.jpg)\n", + "* Usually you can make your way with tab-ing and shift-tab-ing and following your gut feeling.\n", + " * This is likely not the most efficient way to do so." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "#More useful things in numpy:\n", + "\n", + "print(\"Special numpy array creators:\")\n", + "print(\"np.zeros(6) = \",np.zeros(6))\n", + "print(\"np.ones(6) = \",np.ones(6)) #or you could use np.zeros(7) + 1\n", + "print(\"np.zeros_like(a) = \",np.zeros_like(a))\n", + "\n", + "print(\"\\n\")\n", + "print(\"np.arange(5) = \",np.arange(5))\n", + "print(\"np.linspace(0,5,10) = \",np.linspace(0,5,num=11))\n", + "print(\"np.random.normal(0,0.1,10) = \",np.random.normal(0,0.1,size=3)) \n", + "\n", + "\n", + "print(\"Shapes\")\n", + "v = np.arange(6)\n", + "print(\"v = \",v)\n", + "print(\"np.reshape(v,[2,3]) = \\n\",np.reshape(v,[2,3]))\n", + "print(\"np.reshape(v,[2,-1]) = \\n\",np.reshape(v,[2,-1])) #means \"Figure that last dimension out by yourself\"\n", + "\n", + "print(\"np.reshape(v,[10,1]) = \\n\",np.reshape(v,[6,1]))\n", + "print(\"v[:,None] = \\n\",v[:,None])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "#Multi-dimensional arrays work exactly as 1d ones, but with more axes\n", + "mat = np.reshape(v,[3,2])\n", + "print(\"mat = \\n\",mat)\n", + "print(\"mat.shape =\",mat.shape)\n", + "print(\"mat[2,1] = \",mat[2,1]) #second row, first element, both starting from 0\n", + "print(\"mat[:,0] = \",mat[:,0]) #first column\n", + "print(\"mat[0:2,1] = \",mat[0:2,0]) #two elems of second column\n", + "\n", + "\n", + "print(\"\\nAxes:\")\n", + "print(\"np.sum(mat) = \",np.sum(mat))\n", + "print(\"np.sum(mat,axis=0) = \",np.sum(mat,axis=0))\n", + "print(\"np.sum(mat,axis=1) = \",np.sum(mat,axis=1))\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print(\"A glimpse into broadcasting\")\n", + "print(\"np.reshape(v,[6,1]) + np.reshape(v,[1,6]) = \\n\",np.reshape(v,[6,1]) + np.reshape(v,[1,6]))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "#In short, you can divide(elem-wise) matrix by a row vector \n", + "#or perform any operation when two arrays share last axes\n", + "print(\"matrix shape =\",mat.shape)\n", + "print(\"vector shape =\",np.mean(mat,axis=0).shape)\n", + "print(\"Result:\")\n", + "\n", + "print(mat / np.mean(mat,axis=0))\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "#So for example, you can't divide matrix by a column vector...\n", + "\n", + "print(\"matrix shape =\",mat.shape)\n", + "print(\"vector shape =\",np.mean(mat,axis=1).shape)\n", + "print(\"Result:\")\n", + "\n", + "print(mat / np.mean(mat,axis=1))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "#... but you can replace vector with a single-column matrix \n", + "# because the final axis is gonna be broadcasted\n", + "\n", + "print(\"matrix shape =\",mat.shape)\n", + "print(\"vector shape =\",np.mean(mat,axis=1).reshape([3,1]).shape)\n", + "print(\"Result:\")\n", + "\n", + "mat / np.mean(mat,axis=1).reshape([3,1])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# The quest" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "matrix = data[[\"DER_mass_MMC\",\"DER_mass_transverse_met_lep\",\"DER_mass_vis\",\"DER_pt_h\"]].values\n", + "matrix" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "__Normalize the matrix:__ subtract from each column its mean and divide by the standard deviation. \n", + "\n", + "I suggest np.mean, np.std with axis parameter." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "matrix_normalized = " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print(\"Sanity check, print new mean and new std for each column\")\n", + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Print for the following matrix row numbers for those rows, where row sum is greater than 1. \n", + "I suggest np.sum and np.where." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "```\n", + "\n", + "```\n", + "```\n", + "\n", + "```\n", + "```\n", + "\n", + "```\n", + "```\n", + "\n", + "```\n", + "```\n", + "\n", + "```\n", + "```\n", + "\n", + "```\n", + "```\n", + "\n", + "```\n", + "```\n", + "\n", + "```\n", + "```\n", + "\n", + "```\n", + "```\n", + "\n", + "```\n", + "```\n", + "\n", + "```\n", + "```\n", + "\n", + "```\n", + "```\n", + "\n", + "```\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Performance stuff: \"how fast is it, Harry?\"\n", + "![img](http://statics.viralizalo.com/virs/2016/02/VIR_155188_11939_harry_potter_y_el_prisionero_de_azkaban_test_solo_para_fans.jpg?cb=383)\n", + "\n", + "\n", + "Let's see if numpy is any faster than loops\n", + "\n", + "* Doing some elementwise ops\n", + "* Three options\n", + " * Pure python\n", + " * Start python, convert to numpy\n", + " * Pure numpy\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%%time\n", + "#This cell magic prints the time it took to run the cell\n", + "\n", + "\n", + "#Pure python\n", + "\n", + "arr_1 = range(1000000)\n", + "arr_2 = range(99,1000099)\n", + "\n", + "\n", + "a_sum = []\n", + "a_prod = []\n", + "sqrt_a1 = []\n", + "\n", + "#elementwise sum/prod/sqrt\n", + "for i in range(len(arr_1)):\n", + " a_sum.append(arr_1[i]+arr_2[i])\n", + " a_prod.append(arr_1[i]*arr_2[i])\n", + " a_sum.append(arr_1[i]**0.5)\n", + " \n", + "#sum of all elements of arr_1\n", + "arr_1_sum = sum(arr_1)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%%time\n", + "\n", + "#start with list, convert to numpy\n", + "arr_1 = range(1000000)\n", + "arr_2 = range(99,1000099)\n", + "\n", + "arr_1, arr_2 = np.array(arr_1) , np.array(arr_2)\n", + "\n", + "\n", + "a_sum = arr_1 + arr_2\n", + "a_prod = arr_1*arr_2\n", + "sqrt_a1 = arr_1**.5\n", + "\n", + "np.sum(arr_1)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%%time\n", + "\n", + "# Pure numpy\n", + "arr_1 = np.arange(1000000)\n", + "arr_2 = np.arange(99,1000099)\n", + "\n", + "a_sum = arr_1 + arr_2\n", + "a_prod = arr_1*arr_2\n", + "sqrt_a1 = arr_1**.5\n", + "\n", + "np.sum(arr_1)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "```\n", + "\n", + "```\n", + "```\n", + "\n", + "```\n", + "```\n", + "\n", + "```\n", + "```\n", + "\n", + "```\n", + "```\n", + "\n", + "```\n", + "```\n", + "\n", + "```\n", + "```\n", + "\n", + "```\n", + "```\n", + "\n", + "```\n", + "```\n", + "\n", + "```\n", + "```\n", + "\n", + "```\n", + "```\n", + "\n", + "```\n", + "```\n", + "\n", + "```\n", + "```\n", + "\n", + "```\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Matplotlib\n", + "\n", + "Simple and powerful plotting to make sense of data.\n", + "\n", + "![img](https://imgs.xkcd.com/comics/extrapolating.png)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "scrolled": true + }, + "outputs": [], + "source": [ + "import matplotlib.pyplot as plt\n", + "#VV This is an official \"magic\" to force plots inside your notebook\n", + "%matplotlib inline \n", + "\n", + "#line plot\n", + "plt.plot([0,1,2,3,4,5],[0,1,4,9,16,25])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "#line plot with better formatting\n", + "\n", + "plt.title(\"Super-plot\")\n", + "\n", + "plt.xlabel(\"Number of layers\")\n", + "plt.ylabel(\"Coolness\")\n", + "\n", + "plt.plot([0,1,2,3,4,5],[0,1,4,9,16,25],marker='o',label='super-curve')\n", + "\n", + "plt.legend(loc='best')\n", + "plt.grid()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "#scatter-plot\n", + "\n", + "#draw first plot\n", + "plt.scatter(np.arange(10),np.arange(10)**2) #just to show that np-arrays are allowed\n", + "\n", + "#Show it, start new plot\n", + "plt.show()\n", + "\n", + "#Draw two scatters in one plot\n", + "plt.scatter([1,1,2,3],[10,12,6,20],c = [\"red\",\"blue\",\"blue\",\"green\"],marker = \"x\")\n", + "plt.scatter([0,1,2,3,4,5],[0,1,4,9,16,25],c = \"black\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "#Histogram\n", + "plt.hist([0,1,1,1,2,2,3,3,3,3,3,4,4,5,5,5,6,7,7,8,9,10])\n", + "plt.show()\n", + "\n", + "\n", + "plt.hist([0,1,1,1,2,2,3,3,3,3,3,4,4,5,5,5,6,7,7,8,9,10],bins = 5) \n", + "\n", + "\n", + "#now gently press shift+tab+tab with cursor inside plt.hist -^^" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "#plot a histogram of PRI_jet_leading_pt\n", + "\n", + "\n", + "\n", + "#bonus: separate histograms for PRI_jet_leading_pt where PRI_jet_num equals 0,1,2 and 3 respectively\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "#make a scatter-plot of DER_mass_MMC vs DER_mass_jet_jet\n", + "\n", + "\n", + "\n", + "#bonus: make it as clear as possible with formatting" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "collapsed": false + }, + "source": [ + "### More matplotlib\n", + "\n", + "* Docs - [[url]](https://matplotlib.org/2.0.2/contents.html)\n", + "* Cheat sheet - [[url]](https://s3.amazonaws.com/assets.datacamp.com/blog_assets/Python_Matplotlib_Cheat_Sheet.pdf)\n", + "* Examples - [[url]](https://matplotlib.org/examples/)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "#Final boss - find a way to display a 2-dimensional histogram \n", + "#of DER_mass_MMC vs DER_mass_jet_jet" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "```\n", + "\n", + "```\n", + "```\n", + "\n", + "```\n", + "```\n", + "\n", + "```\n", + "```\n", + "\n", + "```\n", + "```\n", + "\n", + "```\n", + "```\n", + "\n", + "```\n", + "```\n", + "\n", + "```\n", + "```\n", + "\n", + "```\n", + "```\n", + "\n", + "```\n", + "```\n", + "\n", + "```\n", + "```\n", + "\n", + "```\n", + "```\n", + "\n", + "```\n", + "```\n", + "\n", + "```\n", + "\n", + "
You made it!
\n", + "\n", + "![img](https://pbs.twimg.com/media/CrHblh9WgAEoH1u.jpg)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 2", + "language": "python", + "name": "python2" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.13" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +}