From a254b5cb90eebef3a54177df1c7c36afac79cb2c Mon Sep 17 00:00:00 2001 From: Andrew Straw Date: Fri, 18 Oct 2024 09:44:25 +0200 Subject: [PATCH] lecture 1 --- ...hon Basics - Variables and Functions.ipynb | 813 ++++++++++++++++++ .../1 - Course Introduction-checkpoint.ipynb | 126 +++ ... - Deconstructing blockly-checkpoint.ipynb | 80 ++ ...yter notebook environment-checkpoint.ipynb | 155 ++++ ...Python programming basics-checkpoint.ipynb | 395 +++++++++ .../lecture-01/1 - Course Introduction.ipynb | 126 +++ .../2 - Deconstructing blockly.ipynb | 80 ++ .../3 - Jupyter notebook environment.ipynb | 155 ++++ .../4 - Python programming basics.ipynb | 395 +++++++++ lectures/lecture-01/blockly-bird.png | Bin 0 -> 45255 bytes lectures/lecture-01/blockly.png | Bin 0 -> 28391 bytes nbgrader_config.py | 0 release | 1 + source | 1 + 14 files changed, 2327 insertions(+) create mode 100644 exercises/release/exercise-02/1 - Python Basics - Variables and Functions.ipynb create mode 100644 lectures/lecture-01/.ipynb_checkpoints/1 - Course Introduction-checkpoint.ipynb create mode 100644 lectures/lecture-01/.ipynb_checkpoints/2 - Deconstructing blockly-checkpoint.ipynb create mode 100644 lectures/lecture-01/.ipynb_checkpoints/3 - Jupyter notebook environment-checkpoint.ipynb create mode 100644 lectures/lecture-01/.ipynb_checkpoints/4 - Python programming basics-checkpoint.ipynb create mode 100644 lectures/lecture-01/1 - Course Introduction.ipynb create mode 100644 lectures/lecture-01/2 - Deconstructing blockly.ipynb create mode 100644 lectures/lecture-01/3 - Jupyter notebook environment.ipynb create mode 100644 lectures/lecture-01/4 - Python programming basics.ipynb create mode 100644 lectures/lecture-01/blockly-bird.png create mode 100644 lectures/lecture-01/blockly.png create mode 100644 nbgrader_config.py create mode 120000 release create mode 120000 source diff --git a/exercises/release/exercise-02/1 - Python Basics - Variables and Functions.ipynb b/exercises/release/exercise-02/1 - Python Basics - Variables and Functions.ipynb new file mode 100644 index 0000000..284a5f9 --- /dev/null +++ b/exercises/release/exercise-02/1 - Python Basics - Variables and Functions.ipynb @@ -0,0 +1,813 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "markdown", + "checksum": "cf3408d1e3a45641f78d7858696864a8", + "grade": false, + "grade_id": "cell-d3917cf691ff056c", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "source": [ + "# Python Basics - Variables and Functions" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "e17d31bcc816f46ee2121754064627e0", + "grade": false, + "grade_id": "cell-4367d53c03c57930", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "outputs": [], + "source": [ + "# You must run this cell, but you can ignore its contents.\n", + "\n", + "import hashlib\n", + "\n", + "def ads_hash(ty):\n", + " \"\"\"Return a unique string for input\"\"\"\n", + " ty_str = str(ty).encode()\n", + " m = hashlib.sha256()\n", + " m.update(ty_str)\n", + " return m.hexdigest()[:10]" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "markdown", + "checksum": "52c8b1602d2996fad0fdad39dc324ae8", + "grade": false, + "grade_id": "cell-a396e1b67f65db5a", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "source": [ + "## Problem 1 - variable assignment\n", + "\n", + "Assign a value of 42 to the variable named `x`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "d33600594c70d12cb316c58380f0b8ed", + "grade": false, + "grade_id": "cell-ae28d599cff14ed6", + "locked": false, + "schema_version": 3, + "solution": true, + "task": false + } + }, + "outputs": [], + "source": [ + "# YOUR CODE HERE\n", + "raise NotImplementedError()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "25e2fa08766780c594f2fba09876024a", + "grade": true, + "grade_id": "cell-0e037ae0dbd9b1ad", + "locked": true, + "points": 1, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "outputs": [], + "source": [ + "# This checks that the above worked\n", + "assert ads_hash(x)=='73475cb40a'" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "markdown", + "checksum": "cb9fba32ae4ca338a285fb3649117521", + "grade": false, + "grade_id": "cell-c4b55ac9cdc77304", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "source": [ + "## Problem 2 - solving exceptions\n", + "\n", + "Modify the following so that it runs without an \"exception\" (an error in Python):\n", + "\n", + "\n", + "```python\n", + "y = 2 plus 2\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "7077eeea6fd5b76898892e27fb049ac2", + "grade": false, + "grade_id": "cell-c4b1b65a81fbe0ae", + "locked": false, + "schema_version": 3, + "solution": true, + "task": false + } + }, + "outputs": [], + "source": [ + "# YOUR CODE HERE\n", + "raise NotImplementedError()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "417459c798e32bb2c978ee95ba027cf5", + "grade": true, + "grade_id": "cell-f25ca0617c9fefdf", + "locked": true, + "points": 1, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "outputs": [], + "source": [ + "# This checks that the above worked\n", + "assert ads_hash(y)=='4b227777d4'" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "markdown", + "checksum": "f014700590c215a3ddf78e557914afca", + "grade": false, + "grade_id": "cell-d2ec8851f4e990e5", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "source": [ + "## Problem 3 - using the Python Tutor\n", + "\n", + "Run the following code at the [Python Tutor](http://pythontutor.com/).\n", + "\n", + "1. Click on \"Visualize your code and get live help now\" in the Python Tutor website.\n", + "2. Copy this code into your clipboard:\n", + "```python\n", + "x = 42\n", + "y = x + 42\n", + "```\n", + "3. Paste it into the edit window of the Python Tutor.\n", + "4. Click the \"Visualize Execution\" button of the Python Tutor.\n", + "5. Click the \"Next button\" until all steps are done.\n", + "\n", + "**For great insight, run all the problems in this exercise in the Python Tutor and carefully watch what is happening. This will be a massive help for you understand what your programs are doing**\n", + "\n", + "How many variables are in the global frame? Assign the answer to the variable named `answer`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "ff50dbf79b87fb3bdf4e72670e6fb7a6", + "grade": false, + "grade_id": "cell-c90583224070d298", + "locked": false, + "schema_version": 3, + "solution": true, + "task": false + } + }, + "outputs": [], + "source": [ + "# YOUR CODE HERE\n", + "raise NotImplementedError()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "de43ead478c6cead06e44632c52cf9e1", + "grade": true, + "grade_id": "cell-4a36c43c001f4d04", + "locked": true, + "points": 1, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "outputs": [], + "source": [ + "# This checks that the above worked\n", + "assert ads_hash(answer)=='d4735e3a26'" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "markdown", + "checksum": "bc190a7c395423c80634e904355187af", + "grade": false, + "grade_id": "cell-a8185ffe231c0ce4", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "source": [ + "## Problem 4 - functions\n", + "\n", + "Here is an example function named `double` that has one input named `x` and returns `x*2` (`x` times two).\n", + "\n", + "```python\n", + "def double(x):\n", + " return x*2\n", + "```\n", + "\n", + "Remember that all functions in python are defined with the `def` word, then the name of the function, then zero, one, two, or more arguments in parentheses, then a colon. The body of the function must be in a block - a group of lines with the same indentation.\n", + "\n", + "Now, make a function named `triple` that has one input named `x` and returns `x*3`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "60b9c24367737189ce8c2299aca2c1e6", + "grade": false, + "grade_id": "cell-69c4b1cf7dfd376f", + "locked": false, + "schema_version": 3, + "solution": true, + "task": false + } + }, + "outputs": [], + "source": [ + "# YOUR CODE HERE\n", + "raise NotImplementedError()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "8853c152f9aa1854369cec5bb45c5901", + "grade": true, + "grade_id": "cell-c2eb28444382a954", + "locked": true, + "points": 1, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "outputs": [], + "source": [ + "# This checks that the above worked\n", + "assert ads_hash(triple(3))=='19581e27de' \n", + "assert ads_hash(triple(4))=='6b51d431df'\n", + "assert ads_hash(triple(5))=='e629fa6598'" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "markdown", + "checksum": "af02828c7a0a1d4c68a2cfd266af5a66", + "grade": false, + "grade_id": "cell-5c7cd3a6ef33c261", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "source": [ + "## Problem 5 - functions with multiple arguments\n", + "\n", + "Here is an example function named `my_func` that takes two inputs, `x` and `y` and does a bit of math on the inputs:\n", + "\n", + "```python\n", + "def my_func(x,y):\n", + " return x + 2*y\n", + "```\n", + "\n", + "Make a function named `foo` which returns five times the first argument plus three times the second argument." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "df02e7e195e3beeb14dd0ac6b5743704", + "grade": false, + "grade_id": "cell-a7218905d3eb7d0d", + "locked": false, + "schema_version": 3, + "solution": true, + "task": false + } + }, + "outputs": [], + "source": [ + "# YOUR CODE HERE\n", + "raise NotImplementedError()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "5145a593d8183cf9a25132c733778575", + "grade": true, + "grade_id": "cell-a417fcd5f3319f27", + "locked": true, + "points": 1, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "outputs": [], + "source": [ + "# This checks that the above worked\n", + "assert ads_hash(foo(3,10))=='811786ad1a'\n", + "assert ads_hash(foo(10,3))=='3e1e967e9b'\n", + "assert ads_hash(foo(13,2302))=='5f7635b6a1'" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "markdown", + "checksum": "719f7021bb84ce24b25e4ef01dd7824e", + "grade": false, + "grade_id": "cell-8f0143cd8208922f", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "source": [ + "## Problem 6 - calling functions from functions\n", + "\n", + "We can call functions from within functions.\n", + "\n", + "Here are two example functions named `double` and `double_twice`\n", + "\n", + "```python\n", + "def double(x):\n", + " return x*2\n", + "\n", + "def double_twice(x):\n", + " y = double(x)\n", + " z = double(y)\n", + " return z\n", + "```\n", + "\n", + "Re-use your function `triple` from above and make a function named `triple_thrice` which calls `triple` three times repeatedly on its input value." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "62c5724a2440f89dfb9624ab5ce8703e", + "grade": false, + "grade_id": "cell-aa0cfdb16d440f6b", + "locked": false, + "schema_version": 3, + "solution": true, + "task": false + } + }, + "outputs": [], + "source": [ + "# YOUR CODE HERE\n", + "raise NotImplementedError()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "38e9e8e38f32f83d67593876817efb0f", + "grade": true, + "grade_id": "cell-ee28ca6d0fc146ee", + "locked": true, + "points": 1, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "outputs": [], + "source": [ + "assert ads_hash(triple_thrice(3))=='5316ca1c5d'\n", + "assert ads_hash(triple_thrice(4))=='9537f32ec7'" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "markdown", + "checksum": "bb89f7b73ee210cd1f35300adf30f4e2", + "grade": false, + "grade_id": "cell-66fac9b6dafd5cd6", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "source": [ + "## Problem 7 - variable scopes\n", + "\n", + "Functions are also useful because they let you \"hide\" variables so they do not \"pollute\" other parts of your code. In other words, functions let you make modular pieces of code which do not affect each other.\n", + "\n", + "Consider this piece of code, and think about the value of `x` throughout the code.\n", + "\n", + "```python\n", + "x = 43\n", + "\n", + "def blah(x):\n", + " x = x - 26\n", + " return x\n", + "\n", + "blah(2)\n", + "\n", + "x\n", + "```\n", + "\n", + "In the very last line, what is the value of `x`?\n", + "\n", + "In the very last line, `x` has a value of `43`. However, inside the function there is a *local* variable, also named `x`, which can have a different value. Changes to this local variable `x` in the function do not affect the `x` in the *global frame*. (This could also be called the *global scope*. \"Frame\" and \"scope\" are synonyms.)\n", + "\n", + "Inside a function, variable from the outside frame can be *read* if there is no local variable in the function with the same name. Consider this code. Here we will read the variable `x` inside the function because we have no argument or other local variable named `x`.\n", + "\n", + "```python\n", + "x = 43\n", + "\n", + "def blah(y):\n", + " z = x - y\n", + " return z\n", + "\n", + "q = blah(2)\n", + "```\n", + "\n", + "What is the value of `q`?\n", + "\n", + "The value of `q` here will be 41.\n", + "\n", + "*Advanced*: Frames can be nested - for example if you call a function named `function2` from another function named `function1`, the frame of `function2` will be created while the frame of `function1` continues to exist.\n", + "\n", + "In this second example, `y` is defined only inside the function. What is it's value in the function? Assign your answer to the variable `y`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "aea2a9a276437e340a4e8af8453970b8", + "grade": false, + "grade_id": "cell-cdc1a3f2940f028c", + "locked": false, + "schema_version": 3, + "solution": true, + "task": false + } + }, + "outputs": [], + "source": [ + "# YOUR CODE HERE\n", + "raise NotImplementedError()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "20fab6e2c79881c84c4178dc942a9952", + "grade": true, + "grade_id": "cell-93d460ecce09dcfd", + "locked": true, + "points": 1, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "outputs": [], + "source": [ + "assert ads_hash(y)=='d4735e3a26'" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "markdown", + "checksum": "b1e7c21f388151f457c9477ed79325ab", + "grade": false, + "grade_id": "cell-56a56e248a2320f1", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "source": [ + "## Problem 8 - return values of functions\n", + "\n", + "To return a value, a function must use the keyword `return`. Otherwise, the special python type `None` is returned. Check these two functions out:\n", + "\n", + "```python\n", + "def func_one(x):\n", + " return x*10\n", + "\n", + "def func_two(x):\n", + " x*10\n", + "```\n", + "\n", + "What is the result of `func_one(10)`? It is `100`. What is the result of `func_two(10)`? It is `None`, a special type in Python which means \"nothing\".\n", + "\n", + "Taking this as a starting point, fix the `my_triple` function so that it returns the value of `x*3`.\n", + "\n", + "```\n", + "def my_triple(x):\n", + " x*3\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "8d35a4922df3598cb1e8da453a64cd51", + "grade": false, + "grade_id": "cell-3d76a38f83df69ce", + "locked": false, + "schema_version": 3, + "solution": true, + "task": false + } + }, + "outputs": [], + "source": [ + "# YOUR CODE HERE\n", + "raise NotImplementedError()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "1f975aebc553039503e03b7480621d48", + "grade": true, + "grade_id": "cell-f70296c24b543ae5", + "locked": true, + "points": 1, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "outputs": [], + "source": [ + "assert ads_hash(my_triple(100))=='983bd614bb'" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "markdown", + "checksum": "184af9b260021fe31f91b6eb4893ec11", + "grade": false, + "grade_id": "cell-0748880c1c3a5b6f", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "source": [ + "## Problem 9 - `print()` is not return\n", + "\n", + "One thing that can be confusing is the difference between the return value of a cell in Jupyter notebook - which gets displayed automatically and the use of the built-in `print()` function.\n", + "\n", + "```python\n", + "print(1234)\n", + "```\n", + "\n", + "Will print `1234` but has no return value. This can be tricky in functions.\n", + "\n", + "Consider this function\n", + "\n", + "```python\n", + "def my_great_function(a):\n", + " print(a*30)\n", + "```\n", + "\n", + "What does this function return?\n", + "\n", + "It returns `None`.\n", + "\n", + "Now make a function called `my_even_better_function` which returns the value of its input times thirty." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "3be3337b633051d62badc2ed20bec9ff", + "grade": false, + "grade_id": "cell-25d97b85b08d5a2c", + "locked": false, + "schema_version": 3, + "solution": true, + "task": false + } + }, + "outputs": [], + "source": [ + "# YOUR CODE HERE\n", + "raise NotImplementedError()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "ce83ca5daaf52deb49f7124b31ceafe2", + "grade": true, + "grade_id": "cell-b2fc619e60513768", + "locked": true, + "points": 1, + "schema_version": 3, + "solution": false, + "task": false + }, + "tags": [] + }, + "outputs": [], + "source": [ + "assert ads_hash(my_even_better_function(32))=='7f5642cd0c'" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.8" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/lectures/lecture-01/.ipynb_checkpoints/1 - Course Introduction-checkpoint.ipynb b/lectures/lecture-01/.ipynb_checkpoints/1 - Course Introduction-checkpoint.ipynb new file mode 100644 index 0000000..b1f5048 --- /dev/null +++ b/lectures/lecture-01/.ipynb_checkpoints/1 - Course Introduction-checkpoint.ipynb @@ -0,0 +1,126 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# PM-21 Python für die Biowissenschaften / Python for the Biosciences\n", + "\n", + "- Instructors: Andrew Straw\n", + "- Tutor: Michael Harrap\n", + "\n", + "## Course content\n", + "\n", + " - Basics of Python programming\n", + " - Introduction to version control and command line\n", + " - Introduction to key data science concepts\n", + " - Introduction to biological sequence analysis" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Who am I (what do I know about programming, data science, and bioinformatics)?\n", + "\n", + "[strawlab.org](https://strawlab.org/)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Course format\n", + "\n", + "This course will be done in person but can be followed remotely. Lectures will be recorded and uploaded to Ilias shortly after class. Discussion and live particiaption will be encouraged. Friday lectures will start at 10:15. The exercises are self-paced and the tutor will available during our exercise time - Monday afternoons starting at 14:15 to 18:00 - to discuss." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Feedback\n", + "\n", + "We would like to make this course as productive as possible for you. Therefore, we encourage any feedback. This can come after the course is over as part of the official Uni Freiburg course feedback. Additionally, we would be happy to get suggestions and ideas as the course is ongoing." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Communication with instructors and tutors during the course\n", + "\n", + "We have started a forum room on Ilias. For questions, use this, or ask during the lecture. This lets other students see them and learn from the answers. Almost certainly you will not be the only one with a particular question!\n", + "\n", + "If you email us, unless the content is very personal, we may re-post the question into the forum room so everyone has a chance to benefit from the communication." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Team work\n", + "\n", + "We highly encourage teamwork during this course! You are welcome to discuss any aspect of the course with your colleagues. If you have any ideas how to better support teamwork, please let us know." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Grading\n", + "\n", + "To pass the course, you must actively participate. This will be checked by verifying that you did the exercise assignments. We have a threshold of 80% of assignments submitted to receive a pass grade." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Assignments\n", + "\n", + "Around the time of each lecture, there will be a new assignment posted on Ilias. We expect that you should be able to finish the exercise by Monday at 18:00, but the exercises will be due Wednesday at 23:55. We use https://strawlab-rp2.zoologie.uni-freiburg.de to handle distributing and collecting work. This runs software called [forgejo](https://forgejo.org) which approximates other sites such as [GitHub](https://github.com) and is widely used in the software world." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Anaconda and Python installation\n", + "\n", + "We would like to you to run Python on your own device if possible. Therefore, we recommend that you install Anaconda on your own computer. A demonstration video is available [here](https://uni-freiburg.cloud.panopto.eu/Panopto/Pages/Viewer.aspx?id=1691f1da-2f9a-4cd3-acb2-b20d006d1a2f) and we can offer further help during the tutorials." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## [Ten simple rules for biologists learning to program](https://journals.plos.org/ploscompbiol/article?id=10.1371/journal.pcbi.1005871)" + ] + } + ], + "metadata": { + "interpreter": { + "hash": "ccf25074823ae812a85d1e93a88d7cc1917c9d66a77f4dbdd42f55ca58b1eefe" + }, + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.8" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/lectures/lecture-01/.ipynb_checkpoints/2 - Deconstructing blockly-checkpoint.ipynb b/lectures/lecture-01/.ipynb_checkpoints/2 - Deconstructing blockly-checkpoint.ipynb new file mode 100644 index 0000000..9a63e99 --- /dev/null +++ b/lectures/lecture-01/.ipynb_checkpoints/2 - Deconstructing blockly-checkpoint.ipynb @@ -0,0 +1,80 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Blockly deconstructed\n", + "\n", + "Consider this [blockly program](https://blockly.games/bird?lang=en&level=2#562ubo).\n", + "\n", + "![blockly-bird](blockly-bird.png)\n", + "\n", + "This is actually a full computer program! When you succesfully complete it, you can see the automatic translation to Javascript. (Javascript is obviously a different programming language than Python, but the important points we can discuss anyway.)\n", + "\n", + "```\n", + "if (noWorm()) {\n", + " heading(0);\n", + "} else {\n", + " heading(90);\n", + "}\n", + "```\n", + "\n", + "if we would re-write this in Python, it would be:\n", + "\n", + "```\n", + "if noWorm():\n", + " heading(0)\n", + "else:\n", + " heading(90)\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's discuss what is going on here.\n", + "\n", + "(Discussion of computer program, computer, operating system, external world.)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Consider this [blockly program](https://blockly.games/music?lang=en&level=3#juok8w).\n", + "\n", + "![blockly](blockly.png)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The main conceptual new thing is the use of **functions**." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.8" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/lectures/lecture-01/.ipynb_checkpoints/3 - Jupyter notebook environment-checkpoint.ipynb b/lectures/lecture-01/.ipynb_checkpoints/3 - Jupyter notebook environment-checkpoint.ipynb new file mode 100644 index 0000000..b8fb72a --- /dev/null +++ b/lectures/lecture-01/.ipynb_checkpoints/3 - Jupyter notebook environment-checkpoint.ipynb @@ -0,0 +1,155 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## The Jupyter notebook environment (formerly IPython notebooks)\n", + "\n", + "Articles:\n", + "\n", + "- https://www.dataquest.io/blog/jupyter-notebook-tutorial/" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Jupyter notebooks let you execute Python code in a browser.\n", + "\n", + "They have advantages and disadvantages compared to other ways of running Python code. We will start with them in this class to rapidly get programming.\n", + "\n", + "In this course, we encourage you to install and run [Anaconda Python](https://www.anaconda.com/products/distribution) on your own computer." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# this is a comment" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "a = 4" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The result of the last line is displayed in the notebook environment." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "a" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "a = 5" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "a" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Good practice - \"restart are run all\" in your notebooks\n", + "\n", + "It is good practice to \"Kernel -> restart and run all\" prior to finishing work on a Jupyter notebook. This ensures that your notebook can execute code from top to bottom, as it is displayed.\n", + "\n", + "## Automatic tests\n", + "\n", + "In this course, we have a number of automatic tests such as the following. These allow you to check that your answer is correct before moving on." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "nbgrader": { + "grade": true, + "grade_id": "cell-2ff2ea3096b36c93", + "locked": true, + "points": 1, + "schema_version": 3, + "solution": false, + "task": false + }, + "tags": [] + }, + "outputs": [], + "source": [ + "# This is an automatic test.\n", + "\n", + "assert a==5" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Jupyter Lab\n", + "\n", + "Files side bar.\n", + "\n", + "Server runs in your computer. Your browser connects to \"Localhost\"." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Further reading - success of jupyter notebooks\n", + " \n", + "- http://nbviewer.jupyter.org/github/parente/nbestimate/blob/master/estimate.ipynb" + ] + } + ], + "metadata": { + "celltoolbar": "Create Assignment", + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.8" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/lectures/lecture-01/.ipynb_checkpoints/4 - Python programming basics-checkpoint.ipynb b/lectures/lecture-01/.ipynb_checkpoints/4 - Python programming basics-checkpoint.ipynb new file mode 100644 index 0000000..f491eb5 --- /dev/null +++ b/lectures/lecture-01/.ipynb_checkpoints/4 - Python programming basics-checkpoint.ipynb @@ -0,0 +1,395 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Python programming basics\n", + "\n", + "Here are some basic examples of concepts that we will learn in the class. We will also run these at http://pythontutor.com/visualize.html" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Built-in names\n", + "\n", + "Python has several words which are \"built in\" and do special things. When we start, we will use a lot of these. As we get further along, we will start using our own names and names we *imported* more and more." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(\"hello world\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Variables\n", + "\n", + "Another building block of programming are **variables**. These are names given to hold values. Each variable has a type, such as a string (like \"hello\" -- note the quotation marks) or integer (like 42)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "x=\"hello world\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(x)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(\"x\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "x" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "type(x)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "x=42" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(x)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(42)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "x" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "type(x)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(print)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "type(print)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(type)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "type" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "type(type)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "type(type(x))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Assignment\n", + "\n", + "The process of setting a variable is called **assignment**. This is done with the equals (`=`) symbol." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "x = \"my new string\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "x" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "x = -1" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "x" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "x = x + 1" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "x" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's look at these in the Python Tutor..." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Functions\n", + "\n", + "A building block of programming are **functions**. These are pieces of code that are called (also known as executed) with input and return output. They may also have side-effects.\n", + "\n", + "Let's look at a function definition:\n", + "\n", + "```python\n", + "def my_function_name(argument1, argument2):\n", + " variable1 = argument1 + argument2\n", + " print(\"hello from my function\") # this is a \"side-effect\"\n", + " return variable1\n", + "```\n", + "\n", + "Above, we created a function named `my_function_name`. This function takes two inputs (called arguments). There are several steps performed in the function. First, we add `argument1` to `argument2` and store the result in `variable1`. Then we print something. Then we return `variable1` as the output of our function.\n", + "\n", + "The indentation (spaces) at the beginning of the lines in the function tell Python which lines of code are part of the function. Everything with the same level if indentation is a \"block\".\n", + "\n", + "Above, we called the built in function `print()`.\n", + "\n", + "The `print()` function takes any number of arguments as input, returns nothing, and as a side-effect prints the arguments to the screen." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Errors (\"exceptions\")\n", + "\n", + "Python errors are called \"exceptions\". An important part of programming is figuring out why you got a particular error. Read the error message very carefully - it contains type of error, a description of the error, and a \"traceback\" that shows where the error came from." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "1/0" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "x = variable_does_not_exist + 4" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "defx asdlkfj39:\n", + " adsk..{" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Doing the assignments\n", + "\n", + "We use automatic tests in this course. This way you can check most of your own work. Below is an example of how this works." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example Problem\n", + "\n", + "Assign a value of 2 to the variable named `x`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Write your answer here\n", + "x = 2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "nbgrader": { + "grade": true, + "grade_id": "cell-a83e7ba665c8308e", + "locked": true, + "points": 1, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "outputs": [], + "source": [ + "assert x==2" + ] + } + ], + "metadata": { + "celltoolbar": "Create Assignment", + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.8" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/lectures/lecture-01/1 - Course Introduction.ipynb b/lectures/lecture-01/1 - Course Introduction.ipynb new file mode 100644 index 0000000..b1f5048 --- /dev/null +++ b/lectures/lecture-01/1 - Course Introduction.ipynb @@ -0,0 +1,126 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# PM-21 Python für die Biowissenschaften / Python for the Biosciences\n", + "\n", + "- Instructors: Andrew Straw\n", + "- Tutor: Michael Harrap\n", + "\n", + "## Course content\n", + "\n", + " - Basics of Python programming\n", + " - Introduction to version control and command line\n", + " - Introduction to key data science concepts\n", + " - Introduction to biological sequence analysis" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Who am I (what do I know about programming, data science, and bioinformatics)?\n", + "\n", + "[strawlab.org](https://strawlab.org/)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Course format\n", + "\n", + "This course will be done in person but can be followed remotely. Lectures will be recorded and uploaded to Ilias shortly after class. Discussion and live particiaption will be encouraged. Friday lectures will start at 10:15. The exercises are self-paced and the tutor will available during our exercise time - Monday afternoons starting at 14:15 to 18:00 - to discuss." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Feedback\n", + "\n", + "We would like to make this course as productive as possible for you. Therefore, we encourage any feedback. This can come after the course is over as part of the official Uni Freiburg course feedback. Additionally, we would be happy to get suggestions and ideas as the course is ongoing." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Communication with instructors and tutors during the course\n", + "\n", + "We have started a forum room on Ilias. For questions, use this, or ask during the lecture. This lets other students see them and learn from the answers. Almost certainly you will not be the only one with a particular question!\n", + "\n", + "If you email us, unless the content is very personal, we may re-post the question into the forum room so everyone has a chance to benefit from the communication." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Team work\n", + "\n", + "We highly encourage teamwork during this course! You are welcome to discuss any aspect of the course with your colleagues. If you have any ideas how to better support teamwork, please let us know." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Grading\n", + "\n", + "To pass the course, you must actively participate. This will be checked by verifying that you did the exercise assignments. We have a threshold of 80% of assignments submitted to receive a pass grade." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Assignments\n", + "\n", + "Around the time of each lecture, there will be a new assignment posted on Ilias. We expect that you should be able to finish the exercise by Monday at 18:00, but the exercises will be due Wednesday at 23:55. We use https://strawlab-rp2.zoologie.uni-freiburg.de to handle distributing and collecting work. This runs software called [forgejo](https://forgejo.org) which approximates other sites such as [GitHub](https://github.com) and is widely used in the software world." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Anaconda and Python installation\n", + "\n", + "We would like to you to run Python on your own device if possible. Therefore, we recommend that you install Anaconda on your own computer. A demonstration video is available [here](https://uni-freiburg.cloud.panopto.eu/Panopto/Pages/Viewer.aspx?id=1691f1da-2f9a-4cd3-acb2-b20d006d1a2f) and we can offer further help during the tutorials." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## [Ten simple rules for biologists learning to program](https://journals.plos.org/ploscompbiol/article?id=10.1371/journal.pcbi.1005871)" + ] + } + ], + "metadata": { + "interpreter": { + "hash": "ccf25074823ae812a85d1e93a88d7cc1917c9d66a77f4dbdd42f55ca58b1eefe" + }, + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.8" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/lectures/lecture-01/2 - Deconstructing blockly.ipynb b/lectures/lecture-01/2 - Deconstructing blockly.ipynb new file mode 100644 index 0000000..9a63e99 --- /dev/null +++ b/lectures/lecture-01/2 - Deconstructing blockly.ipynb @@ -0,0 +1,80 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Blockly deconstructed\n", + "\n", + "Consider this [blockly program](https://blockly.games/bird?lang=en&level=2#562ubo).\n", + "\n", + "![blockly-bird](blockly-bird.png)\n", + "\n", + "This is actually a full computer program! When you succesfully complete it, you can see the automatic translation to Javascript. (Javascript is obviously a different programming language than Python, but the important points we can discuss anyway.)\n", + "\n", + "```\n", + "if (noWorm()) {\n", + " heading(0);\n", + "} else {\n", + " heading(90);\n", + "}\n", + "```\n", + "\n", + "if we would re-write this in Python, it would be:\n", + "\n", + "```\n", + "if noWorm():\n", + " heading(0)\n", + "else:\n", + " heading(90)\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's discuss what is going on here.\n", + "\n", + "(Discussion of computer program, computer, operating system, external world.)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Consider this [blockly program](https://blockly.games/music?lang=en&level=3#juok8w).\n", + "\n", + "![blockly](blockly.png)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The main conceptual new thing is the use of **functions**." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.8" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/lectures/lecture-01/3 - Jupyter notebook environment.ipynb b/lectures/lecture-01/3 - Jupyter notebook environment.ipynb new file mode 100644 index 0000000..b8fb72a --- /dev/null +++ b/lectures/lecture-01/3 - Jupyter notebook environment.ipynb @@ -0,0 +1,155 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## The Jupyter notebook environment (formerly IPython notebooks)\n", + "\n", + "Articles:\n", + "\n", + "- https://www.dataquest.io/blog/jupyter-notebook-tutorial/" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Jupyter notebooks let you execute Python code in a browser.\n", + "\n", + "They have advantages and disadvantages compared to other ways of running Python code. We will start with them in this class to rapidly get programming.\n", + "\n", + "In this course, we encourage you to install and run [Anaconda Python](https://www.anaconda.com/products/distribution) on your own computer." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# this is a comment" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "a = 4" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The result of the last line is displayed in the notebook environment." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "a" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "a = 5" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "a" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Good practice - \"restart are run all\" in your notebooks\n", + "\n", + "It is good practice to \"Kernel -> restart and run all\" prior to finishing work on a Jupyter notebook. This ensures that your notebook can execute code from top to bottom, as it is displayed.\n", + "\n", + "## Automatic tests\n", + "\n", + "In this course, we have a number of automatic tests such as the following. These allow you to check that your answer is correct before moving on." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "nbgrader": { + "grade": true, + "grade_id": "cell-2ff2ea3096b36c93", + "locked": true, + "points": 1, + "schema_version": 3, + "solution": false, + "task": false + }, + "tags": [] + }, + "outputs": [], + "source": [ + "# This is an automatic test.\n", + "\n", + "assert a==5" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Jupyter Lab\n", + "\n", + "Files side bar.\n", + "\n", + "Server runs in your computer. Your browser connects to \"Localhost\"." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Further reading - success of jupyter notebooks\n", + " \n", + "- http://nbviewer.jupyter.org/github/parente/nbestimate/blob/master/estimate.ipynb" + ] + } + ], + "metadata": { + "celltoolbar": "Create Assignment", + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.8" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/lectures/lecture-01/4 - Python programming basics.ipynb b/lectures/lecture-01/4 - Python programming basics.ipynb new file mode 100644 index 0000000..f491eb5 --- /dev/null +++ b/lectures/lecture-01/4 - Python programming basics.ipynb @@ -0,0 +1,395 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Python programming basics\n", + "\n", + "Here are some basic examples of concepts that we will learn in the class. We will also run these at http://pythontutor.com/visualize.html" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Built-in names\n", + "\n", + "Python has several words which are \"built in\" and do special things. When we start, we will use a lot of these. As we get further along, we will start using our own names and names we *imported* more and more." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(\"hello world\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Variables\n", + "\n", + "Another building block of programming are **variables**. These are names given to hold values. Each variable has a type, such as a string (like \"hello\" -- note the quotation marks) or integer (like 42)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "x=\"hello world\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(x)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(\"x\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "x" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "type(x)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "x=42" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(x)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(42)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "x" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "type(x)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(print)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "type(print)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(type)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "type" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "type(type)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "type(type(x))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Assignment\n", + "\n", + "The process of setting a variable is called **assignment**. This is done with the equals (`=`) symbol." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "x = \"my new string\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "x" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "x = -1" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "x" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "x = x + 1" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "x" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's look at these in the Python Tutor..." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Functions\n", + "\n", + "A building block of programming are **functions**. These are pieces of code that are called (also known as executed) with input and return output. They may also have side-effects.\n", + "\n", + "Let's look at a function definition:\n", + "\n", + "```python\n", + "def my_function_name(argument1, argument2):\n", + " variable1 = argument1 + argument2\n", + " print(\"hello from my function\") # this is a \"side-effect\"\n", + " return variable1\n", + "```\n", + "\n", + "Above, we created a function named `my_function_name`. This function takes two inputs (called arguments). There are several steps performed in the function. First, we add `argument1` to `argument2` and store the result in `variable1`. Then we print something. Then we return `variable1` as the output of our function.\n", + "\n", + "The indentation (spaces) at the beginning of the lines in the function tell Python which lines of code are part of the function. Everything with the same level if indentation is a \"block\".\n", + "\n", + "Above, we called the built in function `print()`.\n", + "\n", + "The `print()` function takes any number of arguments as input, returns nothing, and as a side-effect prints the arguments to the screen." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Errors (\"exceptions\")\n", + "\n", + "Python errors are called \"exceptions\". An important part of programming is figuring out why you got a particular error. Read the error message very carefully - it contains type of error, a description of the error, and a \"traceback\" that shows where the error came from." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "1/0" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "x = variable_does_not_exist + 4" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "defx asdlkfj39:\n", + " adsk..{" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Doing the assignments\n", + "\n", + "We use automatic tests in this course. This way you can check most of your own work. Below is an example of how this works." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example Problem\n", + "\n", + "Assign a value of 2 to the variable named `x`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Write your answer here\n", + "x = 2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "nbgrader": { + "grade": true, + "grade_id": "cell-a83e7ba665c8308e", + "locked": true, + "points": 1, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "outputs": [], + "source": [ + "assert x==2" + ] + } + ], + "metadata": { + "celltoolbar": "Create Assignment", + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.8" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/lectures/lecture-01/blockly-bird.png b/lectures/lecture-01/blockly-bird.png new file mode 100644 index 0000000000000000000000000000000000000000..3fa289eb5b1f6c56f1b630f44b7a4d4926f030b7 GIT binary patch literal 45255 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 literal 0 HcmV?d00001 diff --git a/lectures/lecture-01/blockly.png b/lectures/lecture-01/blockly.png new file mode 100644 index 0000000000000000000000000000000000000000..92cc93acc0a8be08763e9f986f6431be4c84de81 GIT binary patch literal 28391 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 literal 0 HcmV?d00001 diff --git a/nbgrader_config.py b/nbgrader_config.py new file mode 100644 index 0000000..e69de29 diff --git a/release b/release new file mode 120000 index 0000000..e6a7459 --- /dev/null +++ b/release @@ -0,0 +1 @@ +exercises/release \ No newline at end of file diff --git a/source b/source new file mode 120000 index 0000000..478e94e --- /dev/null +++ b/source @@ -0,0 +1 @@ +exercises/source \ No newline at end of file