{ "metadata": { "name": "", "signature": "sha256:e4e78f24b1b22af6ae3fed829557185e9d70dc69fd1edaa2bcb23649aa5fa834" }, "nbformat": 3, "nbformat_minor": 0, "worksheets": [ { "cells": [ { "cell_type": "code", "collapsed": false, "input": [ "# - compatibility with Python 3\n", "from __future__ import print_function # print('me') instead of print 'me'\n", "from __future__ import division # 1/2 == 0.5, not 0" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 1 }, { "cell_type": "code", "collapsed": false, "input": [ "# - show figures inside the notebook\n", "%matplotlib inline" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 2 }, { "cell_type": "code", "collapsed": false, "input": [ "# - import common modules\n", "import numpy as np # the Python array package\n", "import matplotlib.pyplot as plt # the Python plotting package" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 3 }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Stuff you need for the tutorial" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Methods vs functions in numpy" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Many things are implemented in numpy as both *functions* and *methods. For example, there is a `np.sum` function, that adds up all the elements:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "arr = np.array([1, 2, 0, 1])\n", "np.sum(arr)" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 4, "text": [ "4" ] } ], "prompt_number": 4 }, { "cell_type": "markdown", "metadata": {}, "source": [ "There is also a `sum` method of the numpy `array` object:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "type(arr)" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 5, "text": [ "numpy.ndarray" ] } ], "prompt_number": 5 }, { "cell_type": "code", "collapsed": false, "input": [ "arr.sum()" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 6, "text": [ "4" ] } ], "prompt_number": 6 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Nearly all the method versions do the same thing as the function versions. Examples are `mean`, `min`, `max`, `sum`, `reshape`. Choosing the method or the function will usually depend on which one is easier to read." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Reshape arrays" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The obvious example - making an array flat (1D):" ] }, { "cell_type": "code", "collapsed": false, "input": [ "arr = np.array([[0, 1, 2, 3, 4, 5], [6, 7, 8, 9, 10, 11]])\n", "arr" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 7, "text": [ "array([[ 0, 1, 2, 3, 4, 5],\n", " [ 6, 7, 8, 9, 10, 11]])" ] } ], "prompt_number": 7 }, { "cell_type": "code", "collapsed": false, "input": [ "arr_1d = arr.reshape(12)\n", "arr_1d" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 8, "text": [ "array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])" ] } ], "prompt_number": 8 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Notice what happened. Numpy first makes an output array shape `(12,)`. It then proceeds along the *last* axis, element by element, taking the element and putting it into the output array. When it has finished each line on the last axis, it continues to the next line (on the second-to-last axis)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can reverse the process, like this:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "arr_1d.reshape((2, 6))" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 9, "text": [ "array([[ 0, 1, 2, 3, 4, 5],\n", " [ 6, 7, 8, 9, 10, 11]])" ] } ], "prompt_number": 9 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Making an N-D array into a 1D array is very common, so numpy has a short-cut for that:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "arr.ravel()" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 10, "text": [ "array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])" ] } ], "prompt_number": 10 }, { "cell_type": "markdown", "metadata": {}, "source": [ "For a 3D array, there are three axes. In this case numpy first proceeds along the lines over the third axis. When it reaches the end of the line it moves to the next line on the *second* axis, and when it gets to the end of the second axis it goes to the first axis." ] }, { "cell_type": "code", "collapsed": false, "input": [ "arr_3d = np.array([ # now define first of 2 2D arrays (arr_3d[0, :, :])\n", " [[0, 1, 2, 3],\n", " [4, 5, 6, 7],\n", " [8, 9, 10, 11]],\n", " # define second of 2 2D arrays (arr_3d[1, :, :])\n", " [[12, 13, 14, 15],\n", " [16, 17, 18, 19],\n", " [20, 21, 22, 23]]\n", " ])\n", "arr_3d" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 11, "text": [ "array([[[ 0, 1, 2, 3],\n", " [ 4, 5, 6, 7],\n", " [ 8, 9, 10, 11]],\n", "\n", " [[12, 13, 14, 15],\n", " [16, 17, 18, 19],\n", " [20, 21, 22, 23]]])" ] } ], "prompt_number": 11 }, { "cell_type": "code", "collapsed": false, "input": [ "n_elements = 2 * 3 * 4\n", "arr_3d.reshape(n_elements)" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 12, "text": [ "array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,\n", " 17, 18, 19, 20, 21, 22, 23])" ] } ], "prompt_number": 12 }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can reshape to any shape. For example, you might want to reshape only the first two dimensions, leaving the last the same. This will take you from an array of shape (2, 3, 4), to an array of shape (6, 4). The procedure is the same in numpy. It makes an output array shape (6, 4), then takes each element over the last dimension in the input, and fills the last dimension of the output, moves one across on the second dimension of the input, then fills a line in the first dimension of the output, and so on." ] }, { "cell_type": "code", "collapsed": false, "input": [ "arr_2d = arr_3d.reshape(6, 4)\n", "arr_2d.shape" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 13, "text": [ "(6, 4)" ] } ], "prompt_number": 13 }, { "cell_type": "code", "collapsed": false, "input": [ "arr_2d" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 14, "text": [ "array([[ 0, 1, 2, 3],\n", " [ 4, 5, 6, 7],\n", " [ 8, 9, 10, 11],\n", " [12, 13, 14, 15],\n", " [16, 17, 18, 19],\n", " [20, 21, 22, 23]])" ] } ], "prompt_number": 14 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Of course we can do this with image data arrays:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "import nibabel as nib\n", "img = nib.load('ds114_sub009_t2r1.nii')\n", "data = img.get_data()\n", "data.shape" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 15, "text": [ "(64, 64, 30, 173)" ] } ], "prompt_number": 15 }, { "cell_type": "code", "collapsed": false, "input": [ "vol_shape = data.shape[:-1]\n", "vol_shape" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 16, "text": [ "(64, 64, 30)" ] } ], "prompt_number": 16 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here I am using the `np.prod` function, which is like `np.sum`, but instead of adding the elements, it multiplies them:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "n_voxels = np.prod(vol_shape)\n", "n_voxels" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 17, "text": [ "122880" ] } ], "prompt_number": 17 }, { "cell_type": "code", "collapsed": false, "input": [ "voxel_by_time = data.reshape(n_voxels, data.shape[-1])\n", "voxel_by_time.shape" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 18, "text": [ "(122880, 173)" ] } ], "prompt_number": 18 }, { "cell_type": "markdown", "metadata": {}, "source": [ "### The outer product" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can use the rules of matrix multiplication for row vectors and column vectors." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A row vector is a 2D vector where the first dimension is length 1." ] }, { "cell_type": "code", "collapsed": false, "input": [ "row_vector = np.array([[1, 3, 2]])\n", "row_vector" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 19, "text": [ "array([[1, 3, 2]])" ] } ], "prompt_number": 19 }, { "cell_type": "markdown", "metadata": {}, "source": [ "A column vector is a 2D vector where the second dimension is length 1." ] }, { "cell_type": "code", "collapsed": false, "input": [ "col_vector = np.array([[2], [0], [1]])\n", "col_vector" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 20, "text": [ "array([[2],\n", " [0],\n", " [1]])" ] } ], "prompt_number": 20 }, { "cell_type": "markdown", "metadata": {}, "source": [ "We know what will happen if we matrix multiply the row vector and the column vector:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "row_vector.dot(col_vector)" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 21, "text": [ "array([[4]])" ] } ], "prompt_number": 21 }, { "cell_type": "markdown", "metadata": {}, "source": [ "What happens with we matrix multiply the column vector by the row vector? We know this will work because we are multiplying a 3 by 1 array by a 1 by 3 array, so this should generate a 3 by 3 array: " ] }, { "cell_type": "code", "collapsed": false, "input": [ "col_vector.dot(row_vector)" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 22, "text": [ "array([[2, 6, 4],\n", " [0, 0, 0],\n", " [1, 3, 2]])" ] } ], "prompt_number": 22 }, { "cell_type": "markdown", "metadata": {}, "source": [ "This arises from the rules of matrix multiplication, except there is only one row * value pair for each dot product making up the rows and columns:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "print(col_vector[0] * row_vector)\n", "print(col_vector[1] * row_vector)\n", "print(col_vector[2] * row_vector)" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "[[2 6 4]]\n", "[[0 0 0]]\n", "[[1 3 2]]\n" ] } ], "prompt_number": 23 }, { "cell_type": "markdown", "metadata": {}, "source": [ "This (M by 1) vector matrix multiply with a (1 by N) vector is also called the *outer product* of two vectors. We can generate the same thing from 1D vectors, by using the numpy `np.outer` function:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "np.outer(col_vector.ravel(), row_vector.ravel())" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 24, "text": [ "array([[2, 6, 4],\n", " [0, 0, 0],\n", " [1, 3, 2]])" ] } ], "prompt_number": 24 }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Subtracting the mean" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We often want to do operations like subtract the mean from the columns or rows of a 2D array. For example, here is a 4 by 3 array:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "arr = np.array([[3., 1, 4], [1, 5, 9], [2, 6, 5], [3, 5, 8]])\n", "arr" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 25, "text": [ "array([[ 3., 1., 4.],\n", " [ 1., 5., 9.],\n", " [ 2., 6., 5.],\n", " [ 3., 5., 8.]])" ] } ], "prompt_number": 25 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's say I wanted to remove the mean across the columns (the row mean). Here is the row mean:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "row_means = np.mean(arr, axis=1) # mean across the second (column) axis\n", "row_means" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 26, "text": [ "array([ 2.66666667, 5. , 4.33333333, 5.33333333])" ] } ], "prompt_number": 26 }, { "cell_type": "markdown", "metadata": {}, "source": [ "This is a 1D array:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "row_means.shape" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 27, "text": [ "(4,)" ] } ], "prompt_number": 27 }, { "cell_type": "markdown", "metadata": {}, "source": [ "I want do something like the following, but in a neater and faster way:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "de_meaned = arr.copy()\n", "for i in range(arr.shape[0]): # iterate over rows\n", " de_meaned[i] = de_meaned[i] - row_means[i]\n", "# The rows now have very near 0 mean\n", "de_meaned.mean(axis=1)" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 28, "text": [ "array([ 1.48029737e-16, 0.00000000e+00, 2.96059473e-16,\n", " 2.96059473e-16])" ] } ], "prompt_number": 28 }, { "cell_type": "markdown", "metadata": {}, "source": [ "One way of doing this, is expanding 1D shape (4,) mean vector out to a shape (3, 4) array, where the new columns are all the same as the (4,) mean vector. In fact you can do this with `np.outer` and a vector of ones:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "means_expanded = np.outer(row_means, np.ones(3))\n", "means_expanded" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 29, "text": [ "array([[ 2.66666667, 2.66666667, 2.66666667],\n", " [ 5. , 5. , 5. ],\n", " [ 4.33333333, 4.33333333, 4.33333333],\n", " [ 5.33333333, 5.33333333, 5.33333333]])" ] } ], "prompt_number": 29 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now we can subtract this expanded array to remove the row means:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "re_de_meaned = arr - means_expanded\n", "# The row means are now very close to zero\n", "re_de_meaned.mean(axis=1)" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 30, "text": [ "array([ 1.48029737e-16, 0.00000000e+00, 2.96059473e-16,\n", " 2.96059473e-16])" ] } ], "prompt_number": 30 }, { "cell_type": "markdown", "metadata": {}, "source": [ "This is an example of *vectorizing*. We worked out a way of doing the operation we wanted by using arrays, rather than having to loop over the rows of the matrix." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We'll see later that there are even neater ways to do this, using a technique called *broadcasting*." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Subplots and axes" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We often want to do several plots on the same figure.\n", "\n", "We've already seen examples of doing this with the matplotlib `subplots` command.\n", "\n", "The standard input arguments to `subplots` are the number of rows and the number of columns you want in your grid of axes. For example, if you want two plots underneath each other you would call `subplots(2, 1)` for two rows and one column.\n", "\n", "`subplots` returns a `figure` object, that is an object representing the figure containing the axes. It also returns a list of `axes`. The axes are objects represting the axes on which we can plot. The axis objects have methods like `plot` and `imshow` that allow us to plot on the given axes:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "x = np.arange(0, np.pi * 2, 0.1)\n", "fig, axes = plt.subplots(2, 1)\n", "axes[0].plot(x, np.sin(x))\n", "axes[1].plot(x, np.cos(x))" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 31, "text": [ "[]" ] }, { "metadata": {}, "output_type": "display_data", "png": "iVBORw0KGgoAAAANSUhEUgAAAXoAAAEACAYAAAC9Gb03AAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzt3Xuc1XP+wPHXuymlC7GodFFSFHa7kJRqulEuuZfc7aLV\nymVdklvTLku7lhUtoYiQdSkpuqmprC2hKBUpUSR+KSSrqXn//nif0WhnpnPmzMznfM95Px+P8+ic\nme8533fT9D6f8/5+Pu+PqCrOOefSV6XQATjnnCtfnuidcy7NeaJ3zrk054neOefSnCd655xLc57o\nnXMuzSWd6EVkjIhsEJElJRwzQkRWish7ItI62XM655yLX1mM6B8HehX3TRE5EThEVZsBlwMPlcE5\nnXPOxSnpRK+q84BNJRzSBxgbO3YBUFtE6iR7Xuecc/GpiBp9fWBtocfrgAYVcF7nnHNU3MVY2eWx\n911wzrkKUrkCzvE50LDQ4waxr/2CiHjyd865UlDVXQfTv1ARI/pJwIUAItIe2KyqG4o6UFUjexs6\ndGhcx23bprz2mnLJJcq++ypHHqlccYUybpzyySdKfn7ysfz3v8qiRcro0Ur//nae3/xGuflm5c03\n//cc8caeqjeP3+PP5PjjkfSIXkSeBboA+4nIWmAoUCWWuEep6qsicqKIfAz8AFyS7DmjRhX+/W94\n/HF4+WVo3hz69oVhw6Bhw90/P1FVq0KrVnb77W9h+3aYPx9efRV+9zvIy4NLL4WLLoK6dcv+/M65\n1JJ0olfV/nEcc2Wy54min36C8ePh/vthyxYYMACGDoVGjSo2jsqV4bjj7HbnnbBgATz2GLRoAV27\nQvXq9mYkJX74c85Fla+MLSPZ2dk/39+40RL6QQfBM8/AHXfAihVw3XUVn+R3JQLt21ui//RT6N0b\n3nwzm7Zt4aWXID8/bHylUfhnH0Uef1hRjz8eEm+Np7yJiKZKLKW1ZQvcd5+N4E8/Hf74Rxs1p7r8\nfHjlFfjzn+1TyK23wllnQVZW6Micc7sjIuhuLsZ6oi8DP/0EDz8Md90F3btb7f2QQ0JHlThVmDrV\nEv7338M//mF/H+dc6vJEXwEmTYKrr4YjjrD6969/HTqi5KnCxIlWamrVCu65Bw4+OHRUzrmixJPo\nvUZfSp99BqedBjfeCKNHW+kjHZI8WB3/9NNh2TI46iho1w5uucVKU8656PFEn6C8PPjb36BNG0uC\n770H3bqFjqp8VKsGN99sf8dPP7U3stmzQ0flnEuUl24SsHQpnH8+1KkDI0dGsw6fjClTbIroqafC\n8OFQs2boiJxzXropI/n5Npuma1e46iq7YJlpSR7gpJNgyRLYutVH985FiY/od2PdOrj4YvjxR3jq\nKb8oWaBgdH/OOTbbqEqV0BE5l5l8RJ+kF1+Etm1tJD9njif5wk46CRYvtoVgnTrBmjWhI3LOFccT\nfRHy8mxq4fXXw+TJNuOkckX0+YyY/faz6aVnn20zcyZODB2Rc64oXrrZxfr10K8f1KplpZp99w0d\nUTTMn29lnFNPtVlJe+wROiLnMoOXbhI0d65NmezZ0+bFe5KPX/v2sGgRrF5tP7+vvw4dkXOugCf6\nmAcftNbBY8bAbbdBJf/JJGyffax807GjlXLeey90RM458NIN27fDNdfYVMHJk6FJkwoPIS2NHw+D\nBlkPoDPPDB2Nc+krntJNRl9i/PZbG8WLwJtvwt57h44ofZxzjm2wctppNvd+6FDvd+9cKBlboFi9\nGjp0gGbNbCTvSb7stWkDCxfCa6/ZWoRt20JH5FxmSjrRi0gvEVkhIitFZHAR388WkW9FZFHsdmuy\n50zWggVWR77iCqvN+9TJ8lOnDsyaBZs22dz7b78NHZFzmSepRC8iWcCDQC+gJdBfRIraamOOqraO\n3e5I5pzJeu01OPlkePRRuDIjNziseDVqwIQJ9umpc2f4/PPQETmXWZId0bcDPlbVNaqaB4wHTi3i\nuJSozj75pJUQJk2yZO8qTlaWNYI791wrmS1dGjoi5zJHsom+PrC20ON1sa8VpkAHEXlPRF4VkZZJ\nnjNhqraI57bbIDcXjj22oiNwYBdjBw/euRPX/PmhI3IuMyRbnY5nPuS7QENV3SoivYGJQPOiDszJ\nyfn5fnZ2dpls2qtqrQymTYN//xsaNEj6JV2Szj3X5tz36WObp/foEToi56IjNzeX3NzchJ6T1Dx6\nEWkP5Khqr9jjIUC+qg4v4TmfAG1V9Ztdvl7m8+h37IDf/97KBK++asnFpY5582yO/ahRtqOVcy5x\nFTGP/m2gmYg0Br4A+gH9dwmiDvCVqqqItMPeXL7Z9YXKWl6e1ePXr4cZM3yTjFTUqZP19i+YjXPx\nxaEjci49JZXoVXW7iFwJTAOygNGqulxEBsS+Pwo4C7hCRLYDW4Fzkox5t376yRqT5eVZ3/Q99yzv\nM7rSatPGViUff7ztSeszoZwre2nXAmHrVisD1Kpl9V/vohgNa9bY3ruDBsG114aOxrnoyLgWCD/8\nYGWARo2sOZkvhIqOxo1tc5du3eyT2I03ho7IufSRNqlwyxZL8occYouhvPtk9DRsaNNfC5L9LbeE\njsi59JAWiX7LFjjxRGui9cgjnuSjrH59S/bdu1uy92ZoziUv8om+IMkfeqhN0/MkH3316tkF2u7d\n7XGh5RXOuVKIdKL//ntL8i1aWN9zT/Lpo04deP1125g9K8tWNTvnSieyib7gwqsn+fRV0PkyO9su\nrA8ZEjoi56Ipkon+xx9t+XzTpp7k013dur9M9jfcEDoi56Incon+v/+1efJ168Jjj3mSzwQHHmg1\n+y5dLNn7PHvnEhOpRL9tG5x9ti2GGjvWarcuM9SvvzPZV60KAweGjsi56IhMot++Hfr3t+T+zDO+\nGCoTNWwIM2daGad6de+N41y8IpEud+yAiy6y2vyECVClSuiIXCgHH2xN6rp2hWrVbBNy51zJUj7R\nq1qr4S++sFbDVauGjsiFduihtr9Az56W7E87LXREzqW2lE70qnbhbelSmD7du1C6nY480jqT9u5t\nyb5Xr9AROZe6UnrOyu23W6Or116zC7DOFda2LUycCBdeCHPnho7GudSVson+7rvhpZdsJF+7duho\nXKrq0AGefRbOOgsWLgwdjXOpKSUT/ciRNkd+xgzYf//Q0bhU1707jB4Np5xiZT7n3C8lnehFpJeI\nrBCRlSIyuJhjRsS+/56ItC7p9caOheHDbRrdgQcmG53LFKecAvfdByecACtXho7GudSS1MVYEckC\nHgR6AJ8DC0VkkqouL3TMicAhqtpMRI4BHgLaF/V6L74IN91kC2MaN04mMpeJ+ve3Hkg9e1rNvlGj\n0BE5lxqSnXXTDvhYVdcAiMh44FRgeaFj+gBjAVR1gYjUFpE6qrph1xcbONA2iz7ssCSjchnr0kut\nq2mPHjBvnjVGcy7TJVu6qQ+sLfR4XexruzumQVEvNmECtC6xsOPc7l17LZx3nm04vmlT6GicCy/Z\nEX28u3nvukdQkc+bPj2H6dPtfnZ2NtnZ2aUOzGW222+Hb7+1/QpmzICaNUNH5FzZyM3NJTc3N6Hn\niGq8ubqIJ4u0B3JUtVfs8RAgX1WHFzrmYSBXVcfHHq8AuuxauhERTSYW53alCpddBp98YourqlUL\n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\nAAAAAElFTkSuQmCC\n", "text": [ "" ] } ], "prompt_number": 31 } ], "metadata": {} } ] }