{ "cells": [ { "cell_type": "markdown", "id": "9965f1b0", "metadata": { "nbgrader": { "grade": false, "grade_id": "cell-3b587ecf818e3119", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "# Exercises\n", "\n", "Each exercise carries the difficulty level indication:\n", "- [*] Easy\n", "- [**] Moderate\n", "- [***] Advanced\n", "\n", "The highest difficulty level is meant for students who wish to challenge themselves and/or have previous experience in programming." ] }, { "cell_type": "markdown", "id": "7f9e7a67", "metadata": {}, "source": [ "`````{exercise} [*] Basics of NumPy\n", ":class: dropdown\n", "{download}`Download this exercise.<../Coding_exercises/Week_2/Johan/07_NumPy.py>`\n", "\n", "**Note**: this exercise contains an introduction, which is absent from the downloadable exercise (`.py`) file.\n", "\n", "````{admonition} Introduction\n", ":class: note, dropdown\n", "\n", "**NumPy and arrays**\n", "\n", "NumPy is a general numeric handling library.\n", "It is mostly useful for arrays (called `ndarrays`) and array handling.\n", "\n", "**`ndarray` vs. `lists`**\n", "\n", "Underneath, a Python `list` is actually a C array of pointers to values somewhere else in the memory.\n", "\n", "An `ndarray` is a block of memory - just an array storing values.\n", "However, it is not directly an array, instead storing the distance between\n", "each element (stride) and where the memory block starts, plus some other things needed to work with\n", "the array.\n", "\n", "Typically, it will be faster to do operations on NumPy arrays, especially computational ones.\n", "\n", "\n", "**Defining a NumPy array**\n", "\n", "Several options exist:\n", "* `x = np.zeros()` - defines an array of zeros of the desired dimensions\n", "* `x = np.array()` - define your array, manually, with the elements of your choice \n", "* `x = np.linspace()` - make an evenly spaced array over a user-defined range\n", "* `x = np.arange()` - make an array over a given range with a specific step size\n", "* `x = np.asarray()` - given input that looks like an array, converts it into a NumPy array\n", "\n", "Many more can be found in the documentation, but these are some of the basic ones.\n", "\n", "**Working with NumPy arrays**\n", "\n", "*Computation*\n", "\n", "You can use NumPy arrays into your normal mathematical operators.\n", "It will typically try to do element-wise operations to the entire `ndarray`.\n", "\n", "### Functions\n", "NumPy is great in that many functions are built into it (that are fast because they're written in a normal programming language).\n", "Say for example you want to take a mean (average) of an array.\n", "Instead of having to write a whole for loop, you can call `np.mean`, feed it an array (or an array-like variable)\n", "and it will make an attempt to calculate it.\n", "\n", "*Indexing*\n", "The same construction is used for indexing NumPy arrays as lists or other sequnces in Python.\n", "Slice indexing can also be used.\n", "\n", "```\n", "# Some valid constructions\n", "test_ar = np.linspace(1, 50)\n", "val = test_ar[10]\n", "vals = test_ar[30:50]\n", "more_vals = test_ar[::30]\n", "```\n", "\n", "(You can also feed Boolean NumPy arrays as indices.)\n", "\n", "One thing to note is how NumPy will handle copying data, and the unintended side effects of it.\n", "\n", "```\n", "x = np.linspace(1, 10, 10)\t# Making a numpy array\n", "y = x\t\t\t# \"Copying\" it to a new variable to do something with it\n", "y[1] = 100\t\t# Want to change a value directly\n", "\n", "print(x)\n", "print(y)\n", "```\n", "Try running this in VS Code.\n", "The issue here is that both `x` and `y` are looking at the same block of data fundamentally, so any direct\n", "change to a value will be seen by both.\n", "It's not actually defining a new set of values for `y` to look at.\n", "This can cause debugging headaches.\n", "\n", "\n", "*Other resources*\n", "\n", "If interested, here are some links with additional information about NumPy:\n", "* https://numpy.org\n", "* https://arxiv.org/pdf/1102.1523\n", "\n", "````\n", "\n", "This exercise contains a number of simple things to try to get familiar with \n", "NumPy.\n", "\n", "Hint: Functions (probably) exist for most of these. \n", "\n", "Use the NumPy documentation at numpy.org - try not to be too intimidated, \n", "it's easier than it seems.\n", "\n", "Google is also your friend.\n", "\n", "```\n", "import numpy as np\n", "```\n", " \n", "**Exercise A**\n", "\n", "Define `x_ar` so that it is an array of 124 elements ranging from 2.3 to \n", "1776.343, evenly spaced on a logarithmic scale.\n", "\n", "Hint: There is a function to do this.\n", "\n", "```\n", "x_ar = # Your code here\n", "```\n", "\n", "**Exercise B**\n", "\n", "Reshape `x_ar` to two-dimensional array (pick the lengths you'd like).\n", "\n", "```\n", "# Your code here\n", "```\n", "\n", "**Exercise C**\n", "\n", "Add 10 to every value in the array. \n", "\n", "Hint: you don't need any loops to do so.\n", "\n", "```\n", "# Your code here\n", "```\n", "\n", "**Exercise D**\n", "\n", "Reshape `x_ar` to a one-dimensional array again.\n", "Define a new array `y_ar` as a linear space of 10 values from 23.4 to 1006.2 \n", "and add it to the end of `x_ar`.\n", "\n", "```\n", "# Your code here\n", "```\n", "\n", "**Exercise E**\n", "\n", "Print every tenth value from the new combined `x_ar`. You should be able to do \n", "this without loops.\n", "\n", "```\n", "# Your code here\n", "```\n", "\n", "**Exercise F**\n", "\n", "Test this code. Try to describe what you see and understand what is going\n", "on before running it.\n", "\n", "```\n", "test_ar = np.linspace(1, 50)\n", "mask_ar = test_ar >= 25\n", "new_ar = test_ar[mask_ar]\n", "print(new_ar)\n", "```\n", "\n", "**Exercise G**\n", "\n", "Now find the average for every value above 100 in the combined `x_ar`.\n", "You should be able to do this without loops.\n", "\n", "```\n", "# Your code here\n", "```\n", "\n", "`````" ] }, { "cell_type": "markdown", "id": "99809349", "metadata": {}, "source": [ "`````{exercise} [*] List with the highest mean\n", ":class: dropdown\n", "{download}`Download this exercise.<../Coding_exercises/Week_2/Nina/01_Max_mean.py>`\n", "\n", "Find the list which has the highest mean and the value of that mean. Inform\n", "the user about your findings using print statements.\n", "\n", "Start with writing pseudocode.\n", "\n", "Hints: \n", "- Which NumPy function could come in handy here?\n", "- Use a `for` loop and track the highest mean.\n", "\n", "```\n", "list1 = [3, 5, 7, 9, 2, 4, 6, 8, 10, 1, 3, 5]\n", "list2 = [7, 9, 2, 4, 7, 5, 3, 1, 8, 6]\n", "list3 = [2, 4, 6, 9, 10, 3, 5, 6, 9]\n", "list4 = [1, 3, 5, 7, 9, 1, 3, 5, 7, 2, 4, 6, 8, 10]\n", "list5 = [4, 6, 8, 10, 2, 4, 6, 8, 10, 1, 3, 5, 7, 9]\n", "\n", "# Your code here\n", "```\n", "\n", "`````" ] }, { "cell_type": "markdown", "id": "14b28393", "metadata": {}, "source": [ "`````{exercise} [*] How many ways to the same array?\n", ":class: dropdown\n", "{download}`Download this exercise.<../Coding_exercises/Week_2/Nina/02_Arrays.py>`\n", "\n", "In each of the exercises below, you will receive an array. There is typically more than one way to define an array in NumPy. Therefore, for each of the arrays below, try to think of at least two (and if possible more) ways to define them using NumPy's functions and write the corresponding Python code. If you feel like it, make it a competition with your fellow students, or a competition between student groups! Feel free to use NumPy documentation.\n", "\n", "**Exercise A**:\n", "\n", "$$ A = \\begin{pmatrix} 0 & 1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 & 9 & 10 \\end{pmatrix} $$\n", "\n", "**Exercise B**:\n", "\n", "$$ B = \\begin{pmatrix} 1 & 1 & 1 & 1 & 1 & 1 \\end{pmatrix} $$\n", "\n", "**Exercise C**:\n", "\n", "$$ C = \\begin{pmatrix} 0 & 0 & 0 & 0 \\\\ 0 & 0 & 0 & 0 \\end{pmatrix} $$\n", "\n", "**Exercise D**:\n", "\n", "$$ D = \\begin{pmatrix} 2 & 0 & 0 \\\\ 0 & 2 & 0 \\\\ 0 & 0 & 2 \\end{pmatrix} $$\n", "\n", "**Exercise E**:\n", "\n", "$$ E = \\begin{pmatrix} 5 & 0 & 0 \\\\ 5 & 5 & 0 \\\\ 5 & 5 & 5 \\end{pmatrix} $$\n", "\n", "**Exercise F**:\n", "\n", "$$ F = \\begin{pmatrix} 1 & 1 & 1 \\\\ 1 & 1 & 1 \\\\ 1 & 1 & 1 \\end{pmatrix} $$\n", "\n", "**Exercise G**:\n", "\n", "$$ G = \\begin{pmatrix} 2 & 4 & 6 & 8 & 10 & 12 & 14 & 16 & 18 & 20 \\end{pmatrix} $$\n", "\n", "**Exercise H**:\n", "\n", "$$ H = \\begin{pmatrix} 1 & 0 & 0 & 0 \\\\ 0 & 5 & 0 & 0 \\\\ 0 & 0 & -9 & 0 \\\\ 0 & 0 & 0 & -2 \\end{pmatrix} $$\n", "\n", "`````" ] }, { "cell_type": "markdown", "id": "0e3a86b7", "metadata": {}, "source": [ "`````{exercise} [**] Kinetic energy\n", ":class: dropdown\n", "{download}`Download this exercise.<../Coding_exercises/Week_2/Nina/03_Kinetic_energy.py>`\n", "\n", "Given a NumPy array of masses, calculate the kinetic energy of objects using\n", " \n", "$$\n", "E = \\frac{1}{2} m {v}^2\n", "$$\n", "\n", "where $m$ is mass and $v$ = 10 nm/s is velocity.\n", "\n", "Use these masses (given in micrograms): [1.5, 2.0, 2.5, 3.0, 3.5, 50, 100].\n", "\n", "```\n", "# Your code here\n", "```\n", "\n", "`````" ] }, { "cell_type": "markdown", "id": "d76e3ff2", "metadata": {}, "source": [ "`````{exercise} [**] Protein concentration\n", ":class: dropdown\n", "{download}`Download this exercise.<../Coding_exercises/Week_2/Nina/06_Protein_concentration.py>`\n", "\n", "A biologist has measured the concentration of their favourite protein in cell lysates over time, recorded in 10-minute intervals over a 24-hour period. The concentrations are stored in a 1D NumPy array.\n", "\n", "```\n", "import numpy as np\n", "\n", "np.random.seed(0) # Setting seed for random number generation for reproducibility\n", "time_points = np.arange(0, 1440, 10) # Time in minutes\n", "protein_concentration = np.random.uniform(0.1, 1.0, len(time_points)) # Concentrations in nmol/L\n", "```\n", "\n", "**Exercise A**: Extract the concentrations between the sixth and tenth hours and print them.\n", "\n", "```\n", "# Your code here\n", "```\n", "\n", "**Exercise B**: Get concentrations measured at every full hour and print them.\n", "\n", "```\n", "# Your code here\n", "```\n", "\n", "**Exercise C**: Extract the concentrations from the last three hours and print them.\n", "\n", "```\n", "# Your code here\n", "```\n", "\n", "`````" ] }, { "cell_type": "markdown", "id": "bc09b9e0", "metadata": {}, "source": [ "`````{exercise} [**] Bacterial growth\n", ":class: dropdown\n", "{download}`Download this exercise.<../Coding_exercises/Week_2/Nina/04_Bacterial_growth.py>`\n", "\n", "A bacterial population grows exponentially according to this equation: \n", "\n", "$N(t) = N_0 \\cdot e^{rt}$\n", "\n", "where $N(t)$ is number of bacteria in time $t$, $N_0$ is initial number of bacteria, $r$ is growth rate, and $t$ is time.\n", "\n", "**Exercise A**: Population size\n", "\n", "Given $N_0$ = 1,000 and $r$ = 0.2 per hour, calculate the bacterial population size every hour for time ranging from 0 to 48 hours. Use NumPy arrays.\n", "\n", "```\n", "# Your code here\n", "```\n", "\n", "**Exercise B**: Induction of protein expression\n", "\n", "In the lab, you're growing a culture of 100 mL of *Escherichia coli* that you transformed with a plasmid containing your favourite protein-coding gene. The initial number of cells is $2 \\cdot 10^6$. You want to grow *E. coli* until the culture reaches an optical density ($OD_{600}$) of 0.6. This value indicates an exponential growth phase and is the optimal time for induction of protein expression.\n", "\n", "Knowing that for *E. coli* $1 OD_{600}$ = $5 \\cdot 10^8$ cells/mL and that it grows with a rate of 0.3 per hour, calculate how much time you need to grow *E. coli* before induction.\n", "\n", "```\n", "# Your code here\n", "```\n", "\n", "`````" ] }, { "cell_type": "markdown", "id": "4d3931f5", "metadata": {}, "source": [ "`````{exercise} [**] Heat distribution in a metal plate\n", ":class: dropdown\n", "{download}`Download this exercise.<../Coding_exercises/Week_2/Nina/07_Metal_plate.py>`\n", "\n", "A 9x9 grid represents a metal plate where each cell indicates the temperature at that point. The temperature is stored in a 2D NumPy array.\n", "\n", "```\n", "import numpy as np\n", "\n", "# Heat distribution across a 9x9 metal plate\n", "np.random.seed(0) # Setting seed for random number generation for reproducibility\n", "heat_distribution = np.random.uniform(20, 100, (9, 9)) # Degrees Celsius\n", "```\n", "\n", "**Exercise A**: Extract the temperatures from the top-left 3x3 corner of the plate.\n", "\n", "```\n", "# Your code here\n", "```\n", "\n", "**Exercise B**: Extract the middle row and the middle column and print them.\n", "\n", "```\n", "# Your code here\n", "```\n", "\n", "**Exercise C**: Get the temperatures along the diagonal of the plate and print them.\n", "\n", "```\n", "# Your code here\n", "```\n", "\n", "**Exercise D**: You can imagine your 9x9 plate consisting of nine 3x3 subplates (similar to when you're solving Sudoku puzzles).\n", "Calculate which of the nine 3x3 subplates has the highest average temperature and print the result.\n", "\n", "```\n", "# Your code here\n", "```\n", "\n", "`````" ] }, { "cell_type": "markdown", "id": "30c15920", "metadata": {}, "source": [ "`````{exercise} [**] Social network for epidemic modelling\n", ":class: dropdown\n", "{download}`Download this exercise.<../Coding_exercises/Week_2/Nina/05_Social_network.py>`\n", "\n", "As you might imagine from the experience in recent years, modelling an epidemic spread is rather useful. One of the possible models is the so-called \"probabilistic network model\", in which we model pathogen spread in the group via a network of social contacts. As it turns out, a social network can conveniently be represented by a matrix $W$. Let's look at an example:\n", "\n", "$$ W = \\begin{pmatrix} 1 & 1 & 0 \\\\ 1 & 1 & 1 \\\\ 0 & 1 & 1 \\end{pmatrix} $$\n", "\n", "You can imagine each row and each column representing a person. Our example matrix $W$ therefore outlines a social network of three people. When two individuals know each other, the corresponding element in the matrix is 1. In matrix terminology, we can say that element $w_{ij}$ = 1 when persons $i$ and $j$ know each other. The matrix is also symmetrical, i.e., $w_{ij}$ = $w_{ji}$. If $w_{ii}$ = 1, then $i$ abides by Socrate's advice: \"know thyself\".\n", "\n", "*Remember*: in $w_{ij}$, $i$ denotes the row and $j$ the column.\n", "\n", "Below we give you a social network matrix $W$ to use in the exercises. We also offer some general hints to keep in mind:\n", "- The matrix is **symmetric**, so make sure not to count the same contact twice.\n", "- When looking at contacts between different individuals, you can exclude elements from the matrix **diagonal** (i.e., the \"know thyself\" elements).\n", "- Remember good coding practices and **avoid hardcoding**. Your code should work for any social network matrix.\n", "\n", "```\n", "import numpy as np\n", "\n", "# Define social network matrix\n", "num_people = 20 # Matrix of 20 people\n", "np.random.seed(0) # Setting seed for random number generation for reproducibility\n", "W = np.random.choice([0, 1], size=(num_people, num_people), p=[0.6, 0.4])\n", "np.fill_diagonal(W, 1) # Set diagonal elements to 1\n", "```\n", "\n", "**Exercise A**: Person number 5\n", "\n", "How many contacts does person number 5 have? Use Python to find the answer and print it.\n", "\n", "Hint: How does counting in Python work?\n", "\n", "```\n", "# Your code here\n", "```\n", "\n", "**Exercise B**: The influencer\n", "\n", "Find out which person in your social network has the most contacts (i.e., who's the influencer)? Make a print statement about it.\n", "\n", "```\n", "# Your code here\n", "```\n", "\n", "**Exercise C**: Interconnectedness\n", "\n", "How many social contacts in total are represented in $W$? Calculate and make a print statement.\n", "\n", "```\n", "# Your code here\n", "```\n", "\n", "**Exercise D**: A new friendship\n", "\n", "Two people have met at a party, so now they also know each other. Make a new social network matrix $W_{new}$ that also contains this contact.\n", "In practice, identify two people in your matrix $W$ that don't know each other ($w_{ij}$ = 0) and turn the corresponding matrix element(s) to 1.\n", "\n", "Is the influencer still the same person? You can reuse your code from above to find out.\n", "\n", "```\n", "# Your code here\n", "```\n", "\n", "`````\n" ] } ], "metadata": { "jupytext": { "formats": "ipynb,md" }, "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" } }, "nbformat": 4, "nbformat_minor": 5 }