{ "metadata": { }, "nbformat": 4, "nbformat_minor": 5, "cells": [ { "id": "metadata", "cell_type": "markdown", "source": "
\n\n# Python - Introductory Graduation\n\nby [Helena Rasche](https://training.galaxyproject.org/hall-of-fame/hexylena/), [Donny Vrins](https://training.galaxyproject.org/hall-of-fame/dirowa/), [Bazante Sanders](https://training.galaxyproject.org/hall-of-fame/bazante1/)\n\nCC-BY licensed content from the [Galaxy Training Network](https://training.galaxyproject.org/)\n\n**Objectives**\n\n- What all did I learn up until now?\n\n**Objectives**\n\n- Recap all previous modules.\n- Use exercises to ensure that all previous knowledge is sufficiently covered.\n\n**Time Estimation: 1H30M**\n
\n", "metadata": { "editable": false, "collapsed": false } }, { "id": "cell-0", "source": "

This module provide something like a recap of everything covered by the modular Python Introductory level curriculum. This serves as something of a graduation into the Intermediate tutorials which cover more advanced topics.

\n
\n

Agenda

\n

In this tutorial, we will cover:

\n
    \n
  1. Review
      \n
    1. Math
    2. \n
    \n
  2. \n
\n
\n

Review

\n

This recapitulates the main points from all of the previous modular tutorials

\n

Math

\n

Math in python works a lot like math in real life (from algebra onwards). Variables can be assigned, and worked with in the place of numbers

\n", "cell_type": "markdown", "metadata": { "editable": false, "collapsed": false } }, { "id": "cell-1", "source": [ "x = 1\n", "y = 2\n", "z = x * y" ], "cell_type": "code", "execution_count": null, "outputs": [ ], "metadata": { "attributes": { "classes": [ "python" ], "id": "" } } }, { "id": "cell-2", "source": "

We can use familiar math operators:

\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
OperatorOperation
+Addition
-Subtraction
*Multiplication
/Division (// for rounded, integer division)
\n

And some familiar operations require the use of the math module:

\n", "cell_type": "markdown", "metadata": { "editable": false, "collapsed": false } }, { "id": "cell-3", "source": [ "import math\n", "print(math.pow(2, 8))\n", "print(math.sqrt(9))" ], "cell_type": "code", "execution_count": null, "outputs": [ ], "metadata": { "attributes": { "classes": [ "python" ], "id": "" } } }, { "id": "cell-4", "source": "

Functions

\n

Functions were similarly analogous to algebra and mathematics, we can express f(x) = x * 3 in python as:

\n", "cell_type": "markdown", "metadata": { "editable": false, "collapsed": false } }, { "id": "cell-5", "source": [ "def f(x, y=3):\n", " z = y * 2\n", " return x * z" ], "cell_type": "code", "execution_count": null, "outputs": [ ], "metadata": { "attributes": { "classes": [ "python" ], "id": "" } } }, { "id": "cell-6", "source": "

There are a few basic parts of a function:

\n\n

And we know we can nest functions, using functional composition, just like in math. In math functional composition was written f(g(x)) and in python it’s exactly the same:

\n", "cell_type": "markdown", "metadata": { "editable": false, "collapsed": false } }, { "id": "cell-7", "source": [ "print(math.sqrt(math.pow(2, 4)))" ], "cell_type": "code", "execution_count": null, "outputs": [ ], "metadata": { "attributes": { "classes": [ "python" ], "id": "" } } }, { "id": "cell-8", "source": "

Here we’ve nested three different functions (print is a function!). To read this we start in the middle (math.pow) and move outwards (math.sqrt, print).

\n

Types

\n

There are lots of different datatypes in Python! The basic types are bool, int, float, str. Then we have more complex datatypes like list and dict which can contain the basic types (as well as other lists/dicts nested.)

\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
Data typeExamplesWhen to use itWhen not to use it
Boolean (bool)True, FalseIf there are only two possible states, true or falseIf your data is not binary
Integer (int)1, 0, -1023, 42Countable, singular items. How many patients are there, how many events did you record, how many variants are there in the sequenceIf doubling or halving the value would not make sense: do not use for e.g. patient IDs, or phone numbers. If these are integers you might accidentally do math on the value.
Float (float)123.49, 3.14159, -3.33334If you need more precision or partial values. Recording distance between places, height, mass, etc. 
Strings (str)‘patient_12312’, ‘Jane Doe’, ‘火锅’To store free text, identifiers, sequence IDs, etc.If it’s truly a numeric value you can do calculations with, like adding or subtracting or doing statistics.
List / Array (list)['A', 1, 3.4, ['Nested']]If you need to store a list of items, like sequences from a file. Especially if you’re reading in a table of data from a file.If you want to retrieve individual values, and there are clear identifiers it might be better as a dict.
Dictionary / Associative Array / map (dict){\"weight\": 3.4, \"age\": 12, \"name\": \"Fluffy\"}When you have identifiers for your data, and want to look them up by that value. E.g. looking up sequences by an identifier, or data about students based on their name. Counting values.If you just have a list of items without identifiers, it makes more sense to just use a list.
\n

There are a couple more datatypes we didn’t cover in detail: sets, tuple, None, enum, byte, all of which can be read about in Python’s documentation.

\n

Comparators

\n

We have a couple of comparators available to use specifically for numeric values:

\n\n

And a couple that can be used with numbers and strings (or other values!)

\n\n

Iterables

\n

TODO

\n

Flow Control

\n

Basic flow control looks like if, elif, else:

\n", "cell_type": "markdown", "metadata": { "editable": false, "collapsed": false } }, { "id": "cell-9", "source": [ "blood_oxygen_saturation = 92.3\n", "altitude = 0\n", "\n", "if blood_oxygen_saturation > 96 and altitude == 0:\n", " print(\"Healthy individual at sea level\")\n", "elif blood_oxygen_saturation > 92 and altitude >= 1000:\n", " print(\"Healthy value above sea level\")\n", "elif blood_oxygen_saturation == 0:\n", " print(\"Monitor failure\")\n", "else:\n", " print(\"Not good\")" ], "cell_type": "code", "execution_count": null, "outputs": [ ], "metadata": { "attributes": { "classes": [ "python" ], "id": "" } } }, { "id": "cell-10", "source": "

We must start with an if, then we can have one or more elifs, and 0 or 1 else to end our clause. If there is no else, it’s like nothing happens, we just check the if and elifs and if none match, nothing happens by default.

\n

We could use and to check if both conditions are true, and or to check if one condition is true.

\n", "cell_type": "markdown", "metadata": { "editable": false, "collapsed": false } }, { "id": "cell-11", "source": [ "# And\n", "for i in (True, False):\n", " for j in (True, False):\n", " print(f\"{i} AND {j} => {i and j}\")\n", "# Or\n", "for i in (True, False):\n", " for j in (True, False):\n", " print(f\"{i} OR {j} => {i or j}\")" ], "cell_type": "code", "execution_count": null, "outputs": [ ], "metadata": { "attributes": { "classes": [ "python" ], "id": "" } } }, { "id": "cell-12", "source": "

And if we needed, we can invert conditions with not.

\n", "cell_type": "markdown", "metadata": { "editable": false, "collapsed": false } }, { "id": "cell-13", "source": [ "# Not\n", "for i in (True, False):\n", " print(f\"NOT {i} => {not i}\")" ], "cell_type": "code", "execution_count": null, "outputs": [ ], "metadata": { "attributes": { "classes": [ "python" ], "id": "" } } }, { "id": "cell-14", "source": "

All of these components (if/elif/else, and, or, not, numerical and value comparators) let us build up

\n

Loops

\n

Loops let us loop over the contents of something iterable (a string, a list, lines in a file). We write

\n
for loopVariable in myIterable:\n    # Do something\n    print(loopVariable)\n
\n

Each loop has:

\n\n", "cell_type": "markdown", "metadata": { "editable": false, "collapsed": false } }, { "id": "cell-15", "source": [ "a = 0\n", "c = 0\n", "t = 0\n", "g = 0\n", "\n", "for base in 'ACTGATGCYGGCA':\n", " if base == 'A':\n", " a = a + 1\n", " elif base == 'C':\n", " c = c + 1\n", " elif base == 'T':\n", " t = t + 1\n", " elif base == 'G':\n", " g = g + 1\n", " else:\n", " print(\"Unexpected base!\")\n", "\n", "print(f\"a={a} c={c} t={t} g={g}\")" ], "cell_type": "code", "execution_count": null, "outputs": [ ], "metadata": { "attributes": { "classes": [ "python" ], "id": "" } } }, { "id": "cell-16", "source": "

Files

\n

In python you must open() a file handle, using one of the three modes (read, write, or append). Normally you must also later close() that file, but your life can be a bit

\n", "cell_type": "markdown", "metadata": { "editable": false, "collapsed": false } }, { "id": "cell-17", "source": [ "with open('out.txt', 'w') as handle:\n", " handle.write(\"Здравствуйте \")\n", " handle.write(\"世界!\\n\")\n", " handle.write(\"Welcome!\\n\")\n", "\n", "# Can no longer handle.write(), once we've exited the with block, the file is automatically closed for us." ], "cell_type": "code", "execution_count": null, "outputs": [ ], "metadata": { "attributes": { "classes": [ "python" ], "id": "" } } }, { "id": "cell-18", "source": "

There are several basic parts

\n\n

Additionally if you need a newline in your file, you must write it yourself with a \\n.

\n

The above code is equivalent to this, but it is not recommended, it’s a bit harder to read, and it is very very common to forget to close files which is not ideal.

\n
handle = open('out.txt', 'w')\nhandle.write(\"Здравствуйте \")\nhandle.write(\"世界!\\n\")\nhandle.write(\"Welcome!\\n\")\nhandle.close()\n\n# Can no longer write.\n
\n

You can also read from a file:

\n", "cell_type": "markdown", "metadata": { "editable": false, "collapsed": false } }, { "id": "cell-19", "source": [ "# Read the entire file as one giant string\n", "with open('out.txt', 'r') as handle:\n", " print(handle.read())\n", "\n", "# Or read it as separate lines.\n", "with open('out.txt', 'r') as handle:\n", " print(handle.readlines())" ], "cell_type": "code", "execution_count": null, "outputs": [ ], "metadata": { "attributes": { "classes": [ "python" ], "id": "" } } }, { "id": "cell-20", "source": "

Exceptions

\n

Sometimes things go wrong!

\n\n

If you expect that something will go wrong you can guard against it with a try/except

\n", "cell_type": "markdown", "metadata": { "editable": false, "collapsed": false } }, { "id": "cell-21", "source": [ "try:\n", " print(1 / 0)\n", "except ZeroDivisionError:\n", " print(\"Nope! I expected that!\")" ], "cell_type": "code", "execution_count": null, "outputs": [ ], "metadata": { "attributes": { "classes": [ "python" ], "id": "" } } }, { "id": "cell-22", "source": "

Some of the most common reasons to do this are when you’re processing user input data. Users often input invalid data, unfortunately.

\n

Exercises

\n

Series Approximation

\n

Write a program that computes the sum of an alternating series where each element of the series is an expression of the form

\n\n\\[4\\cdot\\sum_{k=1}^{N} \\dfrac{(-1)^{k+1}}{2 * k-1}\\]\n

Use that expression and calculate the sum for various values of N like 10, 1000, 1000000

\n", "cell_type": "markdown", "metadata": { "editable": false, "collapsed": false } }, { "id": "cell-23", "source": [ "# Write your approximation here!\n", "def calculate_sum(N):\n", " # for values in the range [1, N] (inclusive!)\n", " # calculate the expression (the bit after the Sigma)\n", " # sum up all of those numbers!\n", " return value\n", "\n", "print(calculate_sum(10))" ], "cell_type": "code", "execution_count": null, "outputs": [ ], "metadata": { "attributes": { "classes": [ "python" ], "id": "" } } }, { "id": "cell-24", "source": "

Monte Carlo Simulation

\n

You can use a monte carlo simulation to calculate the value of π. The easy way to do this is to take the region x = [0, 1], y = [0, 1], and fill it with random points. For each point, calculate the distance to the origin. Calculate the ratio of the inside points to the total points, and multiply the value by 4 to estimate π.

\n

You can use the random module to generate random values:

\n", "cell_type": "markdown", "metadata": { "editable": false, "collapsed": false } }, { "id": "cell-25", "source": [ "import random\n", "\n", "print(random.random())\n", "print(random.random())\n", "print(random.random())" ], "cell_type": "code", "execution_count": null, "outputs": [ ], "metadata": { "attributes": { "classes": [ "python" ], "id": "" } } }, { "id": "cell-26", "source": "

Using the random.random() to generate x and y coordinates, write a function that:

\n\n
\"Gif
Figure 1: Gif from the Wikipedia Article for Monte Carlo Method
\n", "cell_type": "markdown", "metadata": { "editable": false, "collapsed": false } }, { "id": "cell-27", "source": [ "# Write your code here!\n", "import math\n", "\n", "# Just a suggestion: write a function to calculate the distance to origin.\n", "#\n", "def distance(x, y):\n", " # ...\n", " return\n", "\n", "def generate_random_point():\n", " # ....\n", " return [x, y]\n", "\n", "def approximate(N=1000):\n", " # For every point in the range [0, N]\n", " # check if it's distance is great than 1\n", "\n", " # Find the ratio of how many are distance<=1\n", " # and return 4 times that ratio.\n", " return 4 * x\n", "\n", "# Try it with a couple N values like 1, 100, 100000,\n", "n = 10000\n", "# Since we're using a random number function, the result is different every\n", "# time we run the simulation.\n", "print(approximate(n))\n", "print(approximate(n))\n", "print(approximate(n))" ], "cell_type": "code", "execution_count": null, "outputs": [ ], "metadata": { "attributes": { "classes": [ "python" ], "id": "" } } }, { "id": "cell-28", "source": "

Sixpack

\n

Sixpack is an old EMBOSS program which takes in a DNA sequence, and then for every frame, for both strands, emits every Open Reading Frame (ORF) that it sees.

\n
  G  R  G  F  W  C  L  G  G  K  A  A  K  N  Y  R  E  K  S  V  D  V  A  G  Y  D  X   F1\n   G  V  A  S  G  A  W  A  V  K  R  Q  K  T  T  V  K  S  R  W  M  W  R  V  M  M     F2\n    A  W  L  L  V  P  G  R  *  S  G  K  K  L  P  *  K  V  G  G  C  G  G  L  *  X    F3\n1 GGGCGTGGCTTCTGGTGCCTGGGCGGTAAAGCGGCAAAAAACTACCGTGAAAAGTCGGTGGATGTGGCGGGTTATGATG 79\n  ----:----|----:----|----:----|----:----|----:----|----:----|----:----|----:----\n1 CCCGCACCGAAGACCACGGACCCGCCATTTCGCCGTTTTTTGATGGCACTTTTCAGCCACCTACACCGCCCAATACTAC 79\n   P  R  P  K  Q  H  R  P  P  L  A  A  F  F  *  R  S  F  D  T  S  T  A  P  *  S     F6\n  X  A  H  S  R  T  G  P  R  Y  L  P  L  F  S  G  H  F  T  P  P  H  P  P  N  H  H   F5\n    P  T  A  E  P  A  Q  A  T  F  R  C  F  V  V  T  F  L  R  H  I  H  R  T  I  I    F4\n
\n

Here we see a DNA sequence GGGCGTGGCTTCTGGTGCCTGGGCGGTAAAGCGGCAAAAAACTACCGTGAAAAGTCGGTGGATGTGGCGGGTTATGATG which you’ll use as input. Above is the translation of the sequence to protein, for each of the three frames (F1-6). Below is the reverse complement of the sequence, and the three frame translation again.

\n

What sixpack does is:

\n
orfs = []\n\nfor sequence in [forward, reverse_complement(forward)]:\n    for frame in [sequence, sequence[1:], sequence[2:]]:\n        # Remembering\n        for potential start_codon:\n            # accumulate until it sees a stop codon\n            # and append it to the orfs array once it does.\n
\n

Here are some variables for your convenience:

\n", "cell_type": "markdown", "metadata": { "editable": false, "collapsed": false } }, { "id": "cell-29", "source": [ "start_codons = ['TTG', 'CTG', 'ATG']\n", "stop_codons = ['TAA', 'TAG', 'TGA']\n", "\n", "# And some convenience functions\n", "def is_start_codon(codon):\n", " return codon in start_codons\n", "\n", "def is_stop_codon(codon):\n", " return codon in stop_codons" ], "cell_type": "code", "execution_count": null, "outputs": [ ], "metadata": { "attributes": { "classes": [ "python" ], "id": "" } } }, { "id": "cell-30", "source": "

It’s a good exercise to rewrite sixpack in a very simplified version without most of the features in sixpack:

\n", "cell_type": "markdown", "metadata": { "editable": false, "collapsed": false } }, { "id": "cell-31", "source": [ "# Write your code here!\n", "\n", "# Some recommendations:\n", "def reverse_complement(sequence):\n", " return ...\n", "\n", "orfs = []\n", "\n", "for sequence in [forward, reverse_complement(forward)]:\n", " for frame in [sequence, sequence[1:], sequence[2:]]:\n", " # Remembering\n", " for potential start_codon:\n", " # accumulate until it sees a stop codon\n", " # and append it to the orfs array once it does." ], "cell_type": "code", "execution_count": null, "outputs": [ ], "metadata": { "attributes": { "classes": [ "python" ], "id": "" } } }, { "id": "cell-32", "source": "\n", "cell_type": "markdown", "metadata": { "editable": false, "collapsed": false } }, { "cell_type": "markdown", "id": "final-ending-cell", "metadata": { "editable": false, "collapsed": false }, "source": [ "# Key Points\n\n", "\n# Congratulations on successfully completing this tutorial!\n\n", "Please [fill out the feedback on the GTN website](https://training.galaxyproject.org/training-material/topics/data-science/tutorials/python-basics-recap/tutorial.html#feedback) and check there for further resources!\n" ] } ] }