Skip to content

Instantly share code, notes, and snippets.

@biomadeira
Last active January 11, 2023 11:21
Show Gist options
  • Select an option

  • Save biomadeira/fbc52b3f13483990feee13076da79083 to your computer and use it in GitHub Desktop.

Select an option

Save biomadeira/fbc52b3f13483990feee13076da79083 to your computer and use it in GitHub Desktop.
Example code snippets
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"id": "2229f17b",
"metadata": {},
"source": [
"# Best coding pratices\n",
"Here are some best practices, tips, and tricks written in Python.\n"
]
},
{
"cell_type": "markdown",
"id": "54b1e013",
"metadata": {},
"source": [
"## Presentation code snippets\n",
"\n",
"These are a collection of snippets used in the \"code development and code release - best practices\" training presentation.\n",
"\n",
"The presentation is available online from [Google Docs](https://docs.google.com/presentation/d/1l9Gm9_jywRbvdqf4yiXU2RfngVtShcZCoWy5EWVcWEM/edit?usp=sharing).\n",
"\n",
"### The importance of UNIX skills\n",
"```bash\n",
"# present work directory\n",
"pwd\n",
"# change directories\n",
"cd directory\n",
"cd ../\n",
"cd /Users/username/directory\n",
"\n",
"# list files using wildcards\n",
"ls -lh sequence*.fasta\n",
"\n",
"# concatenating (opening) a file to view its contents\n",
"cat sequence.fasta\n",
"# other useful commands to interacting with the file\n",
"head sequence.fasta # view the top 10 lines\n",
"tail sequence.fasta # view the last 10 lines\n",
"more sequence.fasta # open file for viewing \n",
"less sequence.fasta # open file for viewing (alternative)\n",
"most sequence.fasta # open file for viewing (alternative)\n",
"\n",
"# installing a python module\n",
"pip install biopython\n",
"\n",
"# other features such as piping and string replacing \n",
"cut -f1 results.txt | grep -v \"miRNA\" | sed s/T/U/ > outfile.txt\n",
"\n",
"# cloning a git repository from GitHub\n",
"git clone https://github.com/ebi-jdispatcher/taxonomy-resolver.git\n",
"\n",
"# running a command line tool such as blastp\n",
"blastp -query sequence.fasta -db bacteria.proteins.fasta -evalue 1e-6 \\\n",
"-num_threads 4 -out blastp.txt\n",
"```\n",
"\n",
"### Naming conventions\n",
"\n",
"Numbered filenames should be padded with zeros:\n",
"\n",
"```bash\n",
"file_01.csv\n",
"file_02.csv\n",
"…\n",
"file_10.csv\n",
"file_11.csv\n",
"```\n",
"\n",
"Classes and Exceptions should use mixed case or “CamelCase”\n",
"```python\n",
"class SequenceCoords:\n",
" coords: Tuple[int, int]\n",
"```\n",
"\n",
"Private variables/methods - start with underscore\n",
"```python\n",
"_single_leading_underscore = 'value'\n",
"```\n",
"\n",
"Avoid conflicts with language keywords - end with underscore\n",
"```python\n",
"tkinter.Toplevel(master, class_='ClassName')\n",
"```\n",
"\n",
"Constants and globals - capital letters (with underscores)\n",
"```python\n",
"MAX_OVERFLOW = 1000\n",
"```\n",
"\n",
"### Code style\n",
"\n",
"Module imports\n",
"```python\n",
"# Wrong:\n",
"import sys, os\n",
"\n",
"# Correct:\n",
"import os\n",
"import sys\n",
"\n",
"# Correct:\n",
"from subprocess import Popen, PIPE\n",
"\n",
"```\n",
"\n",
"Whitespace\n",
"```python\n",
"# Wrong:\n",
"spam( ham[ 1 ], { eggs: 2 } )\n",
"\n",
"# Correct:\n",
"spam(ham[1], {eggs: 2})\n",
"\n",
"# Wrong:\n",
"if x == 4 : print(x , y) ; x , y = y , x\n",
"\n",
"# Correct:\n",
"if x == 4: print(x, y); x, y = y, x\n",
" \n",
"```\n",
"\n",
"Line break before binary operators\n",
"```python\n",
"# Correct:\n",
"# easy to match operators with operands\n",
"income = (gross_wages\n",
" + taxable_interest\n",
" + (dividends - qualified_dividends)\n",
" - ira_deduction\n",
" - student_loan_interest)\n",
"```"
]
},
{
"cell_type": "markdown",
"id": "b02fe589",
"metadata": {},
"source": [
"## Live demo code snippets"
]
},
{
"cell_type": "markdown",
"id": "a44e733f",
"metadata": {},
"source": [
"### Naming conventions"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "123c686c",
"metadata": {},
"outputs": [],
"source": [
"# Variable names should be lowercase and separate words by underscores. \n",
"age = 30\n",
"name = \"Alice\"\n",
"\n",
"# Function names should be lowercase and separate words by underscores.\n",
"def say_hello(name):\n",
" print(f\"Hello, {name}!\")\n",
"\n",
"# Class names should be capitalized and use CamelCase\n",
"class Person:\n",
" def __init__(self, name, age):\n",
" self.name = name\n",
" self.age = age\n",
" \n",
"# Constants should be in all uppercase, separated by underscores\n",
"PI = 3.14\n",
"GRAVITY = 9.8"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "5c90063c",
"metadata": {},
"outputs": [],
"source": [
"# imports\n",
"import math\n",
"import random\n",
"\n",
"# common abbreviations\n",
"import pandas as pd\n",
"import numpy as np\n",
"\n",
"from Bio import SeqIO"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "0fa06fda",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"'missing_file.txt' is not available!\n"
]
}
],
"source": [
"filename = \"missing_file.txt\"\n",
"# tries to open the txt file\n",
"try:\n",
" with open(filename, 'r') as filehandle:\n",
" for line in filehandle:\n",
" print(line)\n",
"except FileNotFoundError as e:\n",
" print(f\"'{filename}' is not available!\")\n",
" pass"
]
},
{
"cell_type": "markdown",
"id": "4e2b3f5e",
"metadata": {},
"source": [
"### Comments and self-documenting code"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "14ac9482",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"6.7"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def calculate_average(numbers):\n",
" \"\"\"\n",
" Calculates the average of a list of numbers.\n",
" \"\"\"\n",
" total = sum(numbers)\n",
" count = len(numbers)\n",
" return total / count\n",
"\n",
"# get the average\n",
"calculate_average([1,4,3,5,16,3,4,2,6,23])"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "bae0d721",
"metadata": {},
"outputs": [],
"source": [
"import pathlib\n",
"import typing\n",
"\n",
"pathlike = typing.Union[str, pathlib.Path]\n",
"\n",
"def parse_ncbiblast_output(outfile: pathlike, stype: str = \"protein\") -> dict:\n",
" \"\"\"\n",
" Parses (some lines of) the BLAST output format file.\n",
"\n",
" :param blastoutfile: (str or pathlib.Path) path to file \n",
" :param stype: (str) sequence type\n",
" :return: (dict) parsed output object\n",
" \"\"\"\n",
" some_dict = {}\n",
" # do something useful...\n",
" return some_dict"
]
},
{
"cell_type": "markdown",
"id": "890832ca",
"metadata": {},
"source": [
"### List comprehensions\n",
"A list comprehension can replace for loops used to fill a list."
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "9363b570",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\n"
]
}
],
"source": [
"mylist = [i for i in range(10)]\n",
"print(mylist)"
]
},
{
"cell_type": "markdown",
"id": "f91ff94a",
"metadata": {},
"source": [
"And because you can use an expression, you can also do some math:"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "dcec5548",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]\n"
]
}
],
"source": [
"squares = [x**2 for x in range(10)]\n",
"print(squares)\n",
"# [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "e614da4e",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[0, 4, 16, 36, 64]\n"
]
}
],
"source": [
"even_squares = [x**2 for x in range(10) if not x % 2]\n",
"print(even_squares)"
]
},
{
"cell_type": "markdown",
"id": "81f27a7d",
"metadata": {},
"source": [
"We can even use a function"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "94b80ff1",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 5.5, 6.0, 6.5, 7.0]\n"
]
}
],
"source": [
"def some_function(a):\n",
" return (a + 5) / 2\n",
" \n",
"my_formula = [some_function(i) for i in range(10)]\n",
"print(my_formula)\n",
"# [2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 5.5, 6.0, 6.5, 7.0]"
]
},
{
"cell_type": "markdown",
"id": "04e20fbc",
"metadata": {},
"source": [
"### Returning multiple values\n",
"Functions in Python can return more than one variable without the need for a dictionary, a list or a class. It works like this:"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "d17b32ad",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Foo Bar\n",
"01/01/2000\n"
]
}
],
"source": [
"def get_user(id):\n",
" # fetch user from database\n",
" name = \"Foo Bar\"\n",
" birthdate = \"01/01/2000\"\n",
" return name, birthdate\n",
"\n",
"name, birthdate = get_user(4)\n",
"print(name)\n",
"print(birthdate)"
]
},
{
"cell_type": "markdown",
"id": "e23ff8b2",
"metadata": {},
"source": [
"### Merging dictionaries"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "5914c751",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{'a': 1, 'b': 3, 'c': 4}\n"
]
}
],
"source": [
"dict1 = { 'a': 1, 'b': 2 }\n",
"dict2 = { 'b': 3, 'c': 4 }\n",
"dict1.update(dict2)\n",
"print(dict1)"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "b06b2730",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{'a': 1, 'b': 3, 'c': 4}\n"
]
}
],
"source": [
"dict1 = { 'a': 1, 'b': 2 }\n",
"dict2 = { 'b': 3, 'c': 4 }\n",
"merged = { **dict1, **dict2 }\n",
"print (merged)"
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "e98dfd03",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{'a': 1, 'b': 3, 'c': 4}\n"
]
}
],
"source": [
"# Python >= 3.9 only\n",
"merged = dict1 | dict2\n",
"print (merged)"
]
},
{
"cell_type": "markdown",
"id": "ab5b2748",
"metadata": {},
"source": [
"### String split and string join"
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "6137b2b1",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"['The', 'quick', 'brown', 'fox']\n"
]
}
],
"source": [
"mystring = \"The quick brown fox\"\n",
"mylist = mystring.split(' ')\n",
"print(mylist)"
]
},
{
"cell_type": "code",
"execution_count": 15,
"id": "50aaf188",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"The quick brown fox\n"
]
}
],
"source": [
"mystring = \" \".join(mylist)\n",
"print(mystring)"
]
},
{
"cell_type": "markdown",
"id": "d277ba23",
"metadata": {},
"source": [
"### String to CamelCase"
]
},
{
"cell_type": "code",
"execution_count": 16,
"id": "de28b096",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"The Quick Brown Fox\n"
]
}
],
"source": [
"print(mystring.title())"
]
},
{
"cell_type": "markdown",
"id": "39a4130e",
"metadata": {},
"source": [
"### Data slicing\n",
"The basic syntax of list slicing is `a[start:stop:step]`"
]
},
{
"cell_type": "code",
"execution_count": 17,
"id": "2f994ffd",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[1, 2]\n"
]
}
],
"source": [
"first_two = [1, 2, 3, 4, 5][0:2]\n",
"print(first_two)"
]
},
{
"cell_type": "code",
"execution_count": 18,
"id": "07420f4c",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[1, 3, 5]\n"
]
}
],
"source": [
"steps = [1, 2, 3, 4, 5][0:5:2]\n",
"print(steps)"
]
},
{
"cell_type": "code",
"execution_count": 19,
"id": "2094d138",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"aced it\n"
]
}
],
"source": [
"mystring = \"abcdefdn nimt\"[::2]\n",
"print(mystring)"
]
},
{
"cell_type": "code",
"execution_count": 20,
"id": "8b6f3c86",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"tmin ndfedcba\n"
]
}
],
"source": [
"mystring = \"abcdefdn nimt\"[::-1]\n",
"print(mystring)"
]
},
{
"cell_type": "markdown",
"id": "3f0fe5eb",
"metadata": {},
"source": [
"### Using map()\n",
"One of Python’s built-in functions is called map(). The syntax for map() is:\n",
"\n",
"`map(function, something_iterable)`\n",
"\n",
"So you give it a function to execute, and something to execute on. This can be anything that’s iterable. In the examples below I’ll use a list."
]
},
{
"cell_type": "code",
"execution_count": 21,
"id": "cd8b0062",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"['SENTENCE', 'FRAGMENT']\n"
]
}
],
"source": [
"def upper(s):\n",
" return s.upper()\n",
" \n",
"mylist = list(map(upper, ['sentence', 'fragment']))\n",
"print(mylist)"
]
},
{
"cell_type": "code",
"execution_count": 22,
"id": "696aa557",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[1, 2, 3, 4, 5, 6, 7]\n"
]
}
],
"source": [
"list_of_ints = list(map(int, \"1234567\"))\n",
"print(list_of_ints)"
]
},
{
"cell_type": "markdown",
"id": "065cfd5b",
"metadata": {},
"source": [
"### Get unique elements from a list or string\n",
"By creating a set with the set() function, you get all the unique elements from a list or list-like object:"
]
},
{
"cell_type": "code",
"execution_count": 23,
"id": "647d1fcf",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{1, 2, 3, 4, 5, 6}\n"
]
}
],
"source": [
"mylist = [1, 1, 2, 3, 4, 5, 5, 5, 6, 6]\n",
"print (set(mylist))"
]
},
{
"cell_type": "code",
"execution_count": 24,
"id": "023c55fc",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"['a', 'b', 'c', 'd', 'e', 'f', 'i', 'v']\n"
]
}
],
"source": [
"print(sorted(set(\"fffaaabbbiiiiccceeeedddeeefffvvveee\")))"
]
},
{
"cell_type": "markdown",
"id": "52753581",
"metadata": {},
"source": [
"### Find the most frequently occurring value\n",
"To find the most frequently occurring value in a list or string:"
]
},
{
"cell_type": "code",
"execution_count": 25,
"id": "4c92931d",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"4\n"
]
}
],
"source": [
"test = [1, 2, 3, 4, 2, 2, 3, 1, 4, 4, 4]\n",
"print(max(set(test), key = test.count))"
]
},
{
"cell_type": "markdown",
"id": "cce32ac1",
"metadata": {},
"source": [
"Counting occurrences using Counter from the collections library"
]
},
{
"cell_type": "code",
"execution_count": 26,
"id": "ba577c7f",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Counter({4: 4, 2: 3, 1: 2, 3: 2})\n"
]
}
],
"source": [
"from collections import Counter\n",
"\n",
"test = [1, 2, 3, 4, 2, 2, 3, 1, 4, 4, 4]\n",
"c = Counter(test)\n",
"print(c)"
]
},
{
"cell_type": "markdown",
"id": "248ae962",
"metadata": {},
"source": [
"### Ternary operator for conditional assignment\n",
"This is another one of those ways to make your code more concise while still keeping it readable:"
]
},
{
"cell_type": "code",
"execution_count": 27,
"id": "c0fe4173",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Success!\n"
]
}
],
"source": [
"x = 2\n",
"y = \"Success!\" if (x == 2) else \"Failed!\"\n",
"print(y)"
]
},
{
"cell_type": "markdown",
"id": "118d4b44",
"metadata": {},
"source": [
"### Chaining of comparison operators\n",
"You can chain comparison operators in Python, creating more readable and concise code:"
]
},
{
"cell_type": "code",
"execution_count": 28,
"id": "27f45529",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Yes\n",
"Yes\n"
]
}
],
"source": [
"x = 10\n",
"\n",
"# Instead of:\n",
"if x > 5 and x < 15:\n",
" print(\"Yes\")\n",
"\n",
"# You can also write:\n",
"if 5 < x < 15:\n",
" print(\"Yes\")"
]
},
{
"cell_type": "markdown",
"id": "f4d94222",
"metadata": {},
"source": [
"### Dataclass\n",
"Since version 3.7, Python offers data classes. There are several advantages over regular classes or other alternatives like returning multiple values or dictionaries:\n",
"\n",
"- a data class requires a minimal amount of code\n",
"- you can compare data classes because `__eq__` is implemented for you\n",
"- you can easily print a data class for debugging because `__repr__` is implemented as well\n",
"- data classes require type hints, reduced the chances of bugs\n",
"\n",
"Here’s an example of a data class at work:"
]
},
{
"cell_type": "code",
"execution_count": 29,
"id": "5165cd5f",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Card(rank='Q', suit='hearts')\n"
]
}
],
"source": [
"from dataclasses import dataclass\n",
"\n",
"@dataclass\n",
"class Card:\n",
" rank: str\n",
" suit: str\n",
" \n",
"card = Card(\"Q\", \"hearts\")\n",
"print(card)\n"
]
},
{
"cell_type": "code",
"execution_count": 30,
"id": "8cd18195",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Q\n",
"hearts\n"
]
}
],
"source": [
"print(card.rank)\n",
"print(card.suit)"
]
},
{
"cell_type": "markdown",
"id": "f9f8f00a",
"metadata": {},
"source": [
"### Defensive programming\n",
"Program defensively, i.e., assume that errors are going to arise, and write code to detect them when they do.\n",
"Put assertions in programs to check their state as they run, and to help readers understand how those programs are supposed to work."
]
},
{
"cell_type": "code",
"execution_count": 31,
"id": "a1a89916",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Data should only contain positive values\n"
]
}
],
"source": [
"numbers = [1.5, 2.3, 0.7, -0.001, 4.4]\n",
"total = 0.0\n",
"try:\n",
" for num in numbers:\n",
" assert num > 0.0, 'Data should only contain positive values'\n",
" total += num\n",
" print('total is:', total)\n",
"except AssertionError as e:\n",
" print(e)\n",
" # handle this issue appropriately"
]
},
{
"cell_type": "markdown",
"id": "e59d69d7",
"metadata": {},
"source": [
"How to retry after an exception?"
]
},
{
"cell_type": "code",
"execution_count": 32,
"id": "d52a32e7",
"metadata": {},
"outputs": [],
"source": [
"# break only when the block succeeds\n",
"while True:\n",
" try:\n",
" pass\n",
" # do something\n",
" except SomeSpecificException: \n",
" continue\n",
" break"
]
},
{
"cell_type": "markdown",
"id": "2572b438",
"metadata": {},
"source": [
"### Programming paradigms\n",
"- Object-Oriented Programming (OOP): OOP is a programming paradigm that is based on the concept of \"objects\", which have properties (attributes) and methods. \n",
"- Functional Programming (FP): FP is a programming paradigm that is based on the concept of \"functions\" that take input(s) and return output(s) without modifying the state of variables outside the function.\n",
"- Procedural Programming (PP): PP is a programming paradigm that is based on the concept of a \"procedure\", which is a set of instructions that are executed in a specific order to perform a task.\n",
"- Asynchronous Programming (AP): AP is a programming paradigm that allows the programmer to write non-blocking code. It helps to avoid waiting for a specific task and continue to execute other codes."
]
},
{
"cell_type": "markdown",
"id": "e9f5c106",
"metadata": {},
"source": [
"#### Object-Oriented Programming"
]
},
{
"cell_type": "code",
"execution_count": 33,
"id": "08e72ca0",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Hello, my name is Alice and I am 30 years old.\n"
]
}
],
"source": [
"class Person:\n",
" def __init__(self, name, age):\n",
" self.name = name\n",
" self.age = age\n",
" \n",
" def say_hello(self):\n",
" print(f\"Hello, my name is {self.name} and I am {self.age} years old.\")\n",
"\n",
"p = Person(\"Alice\", 30)\n",
"p.say_hello()"
]
},
{
"cell_type": "markdown",
"id": "abb4a60e",
"metadata": {},
"source": [
"In the following example we:\n",
"\n",
"- Keep the `__init__` method clean\n",
"- Use `@property` and `@property_name.setter` decorators: These decorators allow you to define methods that are used to get and set the value of a class property, respectively. This allows you to add additional logic to your getters and setters, such as validation, without changing the way that the property is accessed from outside the class."
]
},
{
"cell_type": "code",
"execution_count": 34,
"id": "c0828762",
"metadata": {},
"outputs": [],
"source": [
"class MyClass:\n",
" def __init__(self, value):\n",
" self._value = value\n",
" self._private_value = \"This is private\"\n",
" self.initialize_extra_values()\n",
" \n",
" def initialize_extra_values(self):\n",
" self.extra_value = \"extra\"\n",
"\n",
" @property\n",
" def value(self):\n",
" return self._value\n",
"\n",
" @value.setter\n",
" def value(self, new_value):\n",
" if isinstance(new_value, int) and new_value > 0:\n",
" self._value = new_value\n",
" else:\n",
" raise ValueError(\"Value must be a positive integer.\")"
]
},
{
"cell_type": "markdown",
"id": "a18887a3",
"metadata": {},
"source": [
"#### Using inheritance and polymorphism"
]
},
{
"cell_type": "code",
"execution_count": 35,
"id": "f1f16592",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"200\n",
"78.5\n",
"375\n",
"200.96\n"
]
}
],
"source": [
"class Shape:\n",
" def area(self):\n",
" pass\n",
" \n",
"class Rectangle(Shape):\n",
" def __init__(self, width, height):\n",
" self.width = width\n",
" self.height = height\n",
"\n",
" def area(self):\n",
" return self.width * self.height\n",
" \n",
"class Circle(Shape):\n",
" def __init__(self, radius):\n",
" self.radius = radius\n",
"\n",
" def area(self):\n",
" return 3.14 * self.radius ** 2\n",
"\n",
"shapes = [Rectangle(10,20), Circle(5), Rectangle(15,25), Circle(8)]\n",
"for shape in shapes:\n",
" print(shape.area())\n"
]
},
{
"cell_type": "markdown",
"id": "ce57bf64",
"metadata": {},
"source": [
"#### Using descriptor classes"
]
},
{
"cell_type": "code",
"execution_count": 36,
"id": "6e7c6484",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"10\n",
"20\n"
]
}
],
"source": [
"# descriptor class with 'setters and getters'\n",
"class Quantity:\n",
" # method called in the background by Python\n",
" def __set_name__(self, owner, name):\n",
" self.var_name = name\n",
" \n",
" def __set__(self, instance, value):\n",
" instance.__dict__[self.var_name] = value\n",
" \n",
" def __get__(self, instance, owner):\n",
" return instance.__dict__[self.var_name]\n",
" \n",
"class Rectangle:\n",
" width = Quantity()\n",
" height = Quantity()\n",
" \n",
"rect = Rectangle()\n",
"rect.width = 10\n",
"rect.height = 20\n",
"\n",
"print(rect.width)\n",
"print(rect.height)"
]
},
{
"cell_type": "markdown",
"id": "2b8ae0f0",
"metadata": {},
"source": [
"#### Functional Programming"
]
},
{
"cell_type": "code",
"execution_count": 37,
"id": "2c9b361d",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[4, 16, 36, 64, 100]\n"
]
}
],
"source": [
"numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\n",
"filtered_numbers = filter(lambda x: x % 2 == 0, numbers)\n",
"squared_numbers = map(lambda x: x ** 2, filtered_numbers)\n",
"print(list(squared_numbers)) # prints [4, 16, 36, 64, 100]"
]
},
{
"cell_type": "markdown",
"id": "eacb88fc",
"metadata": {},
"source": [
"#### Asynchronous Programming"
]
},
{
"cell_type": "code",
"execution_count": 38,
"id": "638e9a72",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Running in foo\n",
"Explicit context to bar\n",
"Explicit context switch to foo again\n",
"Implicit context switch back to bar\n"
]
}
],
"source": [
"import asyncio\n",
"\n",
"async def foo():\n",
" print(\"Running in foo\")\n",
" await asyncio.sleep(0)\n",
" print(\"Explicit context switch to foo again\")\n",
"\n",
"async def bar():\n",
" print(\"Explicit context to bar\")\n",
" await asyncio.sleep(0)\n",
" print(\"Implicit context switch back to bar\")\n",
"\n",
"async def main():\n",
" task1 = asyncio.create_task(foo())\n",
" task2 = asyncio.create_task(bar())\n",
" await task1\n",
" await task2\n",
"\n",
"await main()"
]
},
{
"cell_type": "markdown",
"id": "f599dd7e",
"metadata": {},
"source": [
"### Parsing a FASTA sequence"
]
},
{
"cell_type": "markdown",
"id": "6b2b7925",
"metadata": {},
"source": [
"Example sequences:\n",
"```\n",
">SEQUENCE_1\n",
"MTEITAAMVKELRESTGAGMMDCKNALSETNGDFDKAVQLLREKGLGKAAKKADRLAAEG\n",
"LVSVKVSDDFTIAAMRPSYLSYEDLDMTFVENEYKALVAELEKENEERRRLKDPNKPEHK\n",
"IPQFASRKQLSDAILKEAEEKIKEELKAQGKPEKIWDNIIPGKMNSFIADNSQLDSKLTL\n",
"MGQFYVMDDKKTVEQVIAEKEKEFGGKIKIVEFICFEVGEGLEKKTEDFAAEVAAQL\n",
">SEQUENCE_2\n",
"SATVSEINSETDFVAKNDQFIALTKDTTAHIQSNSLQSVEELHSSTINGVKFEEYLKSQI\n",
"ATIGENLVVRRFATLKAGANGVVNGYIHTNGRVGVVIAAACDSAEVASKSRDLLRQICMH\n",
"```"
]
},
{
"cell_type": "markdown",
"id": "ee48833c",
"metadata": {},
"source": [
"Although FASTA format is not particularly difficult to parse, it is better to use an open source module such as Biopython."
]
},
{
"cell_type": "code",
"execution_count": 39,
"id": "0edc8e1f",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"['>SEQUENCE_1\\n', 'MTEITAAMVKELRESTGAGMMDCKNALSETNGDFDKAVQLLREKGLGKAAKKADRLAAEG\\n', 'LVSVKVSDDFTIAAMRPSYLSYEDLDMTFVENEYKALVAELEKENEERRRLKDPNKPEHK\\n', 'IPQFASRKQLSDAILKEAEEKIKEELKAQGKPEKIWDNIIPGKMNSFIADNSQLDSKLTL\\n', 'MGQFYVMDDKKTVEQVIAEKEKEFGGKIKIVEFICFEVGEGLEKKTEDFAAEVAAQL\\n', '>SEQUENCE_2\\n', 'SATVSEINSETDFVAKNDQFIALTKDTTAHIQSNSLQSVEELHSSTINGVKFEEYLKSQI\\n', 'ATIGENLVVRRFATLKAGANGVVNGYIHTNGRVGVVIAAACDSAEVASKSRDLLRQICM\\n']\n"
]
}
],
"source": [
"fasta_file = \"test.fasta\"\n",
"\n",
"def parse_fasta(filename):\n",
" contents = []\n",
" with open(filename, \"r\") as filehandle:\n",
" for line in filehandle:\n",
" contents.append(line)\n",
" return contents\n",
"\n",
"fasta = parse_fasta(fasta_file)\n",
"print(fasta)"
]
},
{
"cell_type": "code",
"execution_count": 40,
"id": "b0d2607f",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"SEQUENCE_1\n",
"MTEITAAMVKELRESTGAGMMDCKNALSETNGDFDKAVQLLREKGLGKAAKKADRLAAEGLVSVKVSDDFTIAAMRPSYLSYEDLDMTFVENEYKALVAELEKENEERRRLKDPNKPEHKIPQFASRKQLSDAILKEAEEKIKEELKAQGKPEKIWDNIIPGKMNSFIADNSQLDSKLTLMGQFYVMDDKKTVEQVIAEKEKEFGGKIKIVEFICFEVGEGLEKKTEDFAAEVAAQL\n",
"237\n",
"SEQUENCE_2\n",
"SATVSEINSETDFVAKNDQFIALTKDTTAHIQSNSLQSVEELHSSTINGVKFEEYLKSQIATIGENLVVRRFATLKAGANGVVNGYIHTNGRVGVVIAAACDSAEVASKSRDLLRQICM\n",
"119\n"
]
}
],
"source": [
"from Bio import SeqIO\n",
"\n",
"records = []\n",
"for seq_record in SeqIO.parse(\"test.fasta\", \"fasta\"):\n",
" records.append(seq_record)\n",
" print(seq_record.id)\n",
" print(seq_record.seq)\n",
" print(len(seq_record))"
]
},
{
"cell_type": "code",
"execution_count": 41,
"id": "1a633c0b",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"ID: SEQUENCE_1\n",
"Name: SEQUENCE_1\n",
"Description: SEQUENCE_1\n",
"Number of features: 0\n",
"Seq('MTEITAAMVKELRESTGAGMMDCKNALSETNGDFDKAVQLLREKGLGKAAKKAD...AQL')\n"
]
}
],
"source": [
"print(records[0])"
]
},
{
"cell_type": "markdown",
"id": "b1c92fd3",
"metadata": {},
"source": [
"#### Sequence operations"
]
},
{
"cell_type": "code",
"execution_count": 42,
"id": "1dfae8ca",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"AGTACACTGGT\n",
"TCATGTGACCA\n",
"ACCAGTGTACT\n"
]
}
],
"source": [
"from Bio.Seq import Seq\n",
"my_seq = Seq(\"AGTACACTGGT\")\n",
"print(my_seq)\n",
"print(my_seq.complement())\n",
"print(my_seq.reverse_complement())"
]
},
{
"cell_type": "markdown",
"id": "1c37dd9e",
"metadata": {},
"source": [
"### Importing data from a CSV file\n",
"Based on the Python lessons in Software Carpentry:\n",
"https://swcarpentry.github.io/python-novice-inflammation\n",
"\n",
"Data downloaded from:\n",
"https://swcarpentry.github.io/python-novice-inflammation/data/python-novice-inflammation-data.zip"
]
},
{
"cell_type": "code",
"execution_count": 43,
"id": "fae0e737",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"--2023-01-11 11:19:44-- https://swcarpentry.github.io/python-novice-inflammation/data/python-novice-inflammation-data.zip\n",
"Resolving swcarpentry.github.io (swcarpentry.github.io)... 185.199.110.153, 185.199.108.153, 185.199.111.153, ...\n",
"Connecting to swcarpentry.github.io (swcarpentry.github.io)|185.199.110.153|:443... connected.\n",
"HTTP request sent, awaiting response... 200 OK\n",
"Length: 22554 (22K) [application/zip]\n",
"Saving to: 'python-novice-inflammation-data.zip'\n",
"\n",
"python-novice-infla 100%[===================>] 22.03K --.-KB/s in 0.003s \n",
"\n",
"2023-01-11 11:19:44 (8.02 MB/s) - 'python-novice-inflammation-data.zip' saved [22554/22554]\n",
"\n"
]
}
],
"source": [
"!wget https://swcarpentry.github.io/python-novice-inflammation/data/python-novice-inflammation-data.zip"
]
},
{
"cell_type": "code",
"execution_count": 44,
"id": "f2334df0",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Archive: python-novice-inflammation-data.zip\r\n",
" creating: data/\r\n",
" inflating: data/inflammation-01.csv \r\n",
" inflating: data/inflammation-02.csv \r\n",
" inflating: data/inflammation-03.csv \r\n",
" inflating: data/inflammation-04.csv \r\n",
" inflating: data/inflammation-05.csv \r\n",
" inflating: data/inflammation-06.csv \r\n",
" inflating: data/inflammation-07.csv \r\n",
" inflating: data/inflammation-08.csv \r\n",
" inflating: data/inflammation-09.csv \r\n",
" inflating: data/inflammation-10.csv \r\n",
" inflating: data/inflammation-11.csv \r\n",
" inflating: data/inflammation-12.csv \r\n",
" extracting: data/small-01.csv \r\n",
" extracting: data/small-02.csv \r\n",
" extracting: data/small-03.csv \r\n"
]
}
],
"source": [
"!unzip python-novice-inflammation-data.zip"
]
},
{
"cell_type": "code",
"execution_count": 45,
"id": "aa43c6b9",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"['0', '0', '1']\n",
"['0', '1', '2']\n"
]
}
],
"source": [
"with open('data/small-01.csv', 'r') as csvlines:\n",
" for line in csvlines:\n",
" print(line.rstrip('\\n').split(','))"
]
},
{
"cell_type": "code",
"execution_count": 46,
"id": "a1aad356",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"['0', '0', '1']\n",
"['0', '1', '2']\n"
]
}
],
"source": [
"import csv\n",
"with open('data/small-01.csv', newline='') as csvfile:\n",
" csvreader = csv.reader(csvfile, delimiter=',', quotechar='|')\n",
" for row in csvreader:\n",
" print(row)"
]
},
{
"cell_type": "code",
"execution_count": 47,
"id": "52a52ea2",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([[0., 0., 1., ..., 3., 0., 0.],\n",
" [0., 1., 2., ..., 1., 0., 1.],\n",
" [0., 1., 1., ..., 2., 1., 1.],\n",
" ...,\n",
" [0., 1., 1., ..., 1., 1., 1.],\n",
" [0., 0., 0., ..., 0., 2., 0.],\n",
" [0., 0., 1., ..., 1., 1., 0.]])"
]
},
"execution_count": 47,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import numpy as np \n",
"np.loadtxt(fname='data/inflammation-01.csv', delimiter=',')"
]
},
{
"cell_type": "code",
"execution_count": 48,
"id": "54e2428c",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" 0 0.1 1 3 1.1 2 4 7 8 3.1 ... 4.3 4.4 5.1 7.6 3.4 4.5 \\\n",
"0 0 1 2 1 2 1 3 2 2 6 ... 3 5 4 4 5 5 \n",
"1 0 1 1 3 3 2 6 2 5 9 ... 10 5 4 2 2 3 \n",
"2 0 0 2 0 4 2 2 1 6 7 ... 3 5 6 3 3 4 \n",
"3 0 1 1 3 3 1 3 5 2 4 ... 9 6 3 2 2 4 \n",
"4 0 0 1 2 2 4 2 1 6 4 ... 8 4 7 3 5 4 \n",
"5 0 0 2 2 4 2 2 5 5 8 ... 8 8 4 2 3 5 \n",
"6 0 0 1 2 3 1 2 3 5 3 ... 4 9 3 5 2 5 \n",
"7 0 0 0 3 1 5 6 5 5 8 ... 4 6 4 7 6 3 \n",
"8 0 1 1 2 1 3 5 3 5 8 ... 2 5 4 5 1 4 \n",
"9 0 1 0 0 4 3 3 5 5 4 ... 4 3 4 5 5 3 \n",
"10 0 1 0 0 3 4 2 7 8 5 ... 8 3 5 4 5 5 \n",
"11 0 0 2 1 4 3 6 4 6 7 ... 5 4 7 3 5 4 \n",
"12 0 0 0 0 1 3 1 6 6 5 ... 5 8 7 4 6 4 \n",
"13 0 1 2 1 1 1 4 1 5 2 ... 8 2 5 1 3 4 \n",
"14 0 1 1 0 1 2 4 3 6 4 ... 10 9 5 6 5 3 \n",
"15 0 0 0 0 2 3 6 5 7 4 ... 9 8 7 5 3 1 \n",
"16 0 0 0 1 2 1 4 3 6 7 ... 2 3 6 5 4 2 \n",
"17 0 0 2 1 2 5 4 2 7 8 ... 6 9 2 1 1 2 \n",
"18 0 1 2 0 1 4 3 2 2 7 ... 6 6 6 1 1 2 \n",
"19 0 1 1 3 1 4 4 1 8 2 ... 3 2 4 3 1 5 \n",
"20 0 0 2 3 2 3 2 6 3 8 ... 8 5 6 6 1 4 \n",
"21 0 0 0 3 4 5 1 7 7 8 ... 4 4 8 2 6 5 \n",
"22 0 1 1 1 1 3 3 2 6 3 ... 5 3 5 1 1 4 \n",
"23 0 1 1 1 2 3 5 3 6 3 ... 5 5 6 1 1 1 \n",
"24 0 0 2 1 3 3 2 7 4 4 ... 8 5 7 2 2 4 \n",
"25 0 0 1 2 4 2 2 3 5 7 ... 7 4 8 2 2 1 \n",
"26 0 0 1 1 1 5 1 5 2 2 ... 9 4 5 3 2 5 \n",
"27 0 0 2 2 3 4 6 3 7 6 ... 7 7 8 3 5 4 \n",
"28 0 0 0 1 4 4 6 3 8 6 ... 6 9 5 5 2 5 \n",
"29 0 1 1 0 3 2 4 6 8 6 ... 10 4 2 6 5 5 \n",
"30 0 0 2 3 3 4 5 3 6 7 ... 3 6 6 4 5 2 \n",
"31 0 1 2 2 2 3 6 6 6 7 ... 5 8 5 2 5 5 \n",
"32 0 0 2 1 3 5 6 7 5 8 ... 2 9 7 2 4 2 \n",
"33 0 0 1 2 4 1 5 5 2 3 ... 5 6 6 2 3 5 \n",
"34 0 0 0 3 1 3 6 4 3 4 ... 3 9 5 1 6 5 \n",
"35 0 1 2 2 2 5 5 1 4 6 ... 6 4 5 4 6 3 \n",
"36 0 1 1 2 3 1 5 1 2 2 ... 9 9 5 4 4 2 \n",
"37 0 1 0 3 2 4 1 1 5 9 ... 5 5 2 1 1 1 \n",
"38 0 1 1 3 1 1 5 5 3 7 ... 2 3 6 3 3 5 \n",
"39 0 0 0 2 2 1 3 4 5 5 ... 2 9 6 2 2 5 \n",
"40 0 0 1 3 3 1 2 1 8 9 ... 4 8 2 6 6 4 \n",
"41 0 1 1 3 4 5 2 1 3 7 ... 5 8 5 5 6 1 \n",
"42 0 0 1 3 1 4 3 6 7 8 ... 10 2 5 1 5 4 \n",
"43 0 1 1 3 3 4 4 6 3 4 ... 10 6 8 7 2 5 \n",
"44 0 1 2 2 4 3 1 4 8 9 ... 5 8 4 4 5 2 \n",
"45 0 0 2 3 4 5 4 6 2 9 ... 6 7 6 5 1 3 \n",
"46 0 1 1 3 1 4 6 2 8 2 ... 6 9 5 6 1 1 \n",
"47 0 0 1 3 2 5 1 2 7 6 ... 10 7 6 3 1 5 \n",
"48 0 0 1 2 3 4 5 7 5 4 ... 4 6 2 4 1 4 \n",
"49 0 1 2 1 1 3 5 3 6 3 ... 7 9 3 3 6 3 \n",
"50 0 1 2 2 3 5 2 4 5 6 ... 8 5 4 1 3 2 \n",
"51 0 0 0 2 4 4 5 3 3 3 ... 10 8 7 5 2 2 \n",
"52 0 0 2 1 1 4 4 7 2 9 ... 7 6 5 4 1 4 \n",
"53 0 1 2 1 1 4 5 4 4 5 ... 4 5 5 2 2 5 \n",
"54 0 0 1 3 2 3 6 4 5 7 ... 3 5 3 5 4 5 \n",
"55 0 1 1 2 2 5 1 7 4 2 ... 7 7 5 6 3 4 \n",
"56 0 1 1 1 4 1 6 4 6 3 ... 8 6 6 4 3 5 \n",
"57 0 0 0 1 4 5 6 3 8 7 ... 10 8 8 6 5 5 \n",
"58 0 0 1 0 3 2 5 4 8 2 ... 8 5 3 5 4 1 \n",
"\n",
" 2.1 3.5 0.2 0.3 \n",
"0 1 1 0 1 \n",
"1 2 2 1 1 \n",
"2 2 3 2 1 \n",
"3 2 0 1 1 \n",
"4 4 3 2 1 \n",
"5 4 1 1 1 \n",
"6 3 2 2 1 \n",
"7 2 1 0 0 \n",
"8 1 2 0 0 \n",
"9 3 2 2 1 \n",
"10 4 0 1 1 \n",
"11 2 3 0 1 \n",
"12 1 3 0 0 \n",
"13 2 0 2 0 \n",
"14 4 2 2 0 \n",
"15 4 0 2 1 \n",
"16 3 0 1 0 \n",
"17 2 0 1 0 \n",
"18 4 3 1 1 \n",
"19 4 2 2 0 \n",
"20 3 0 2 0 \n",
"21 1 0 1 0 \n",
"22 4 1 2 0 \n",
"23 1 0 2 1 \n",
"24 1 1 1 0 \n",
"25 3 0 1 1 \n",
"26 4 3 2 1 \n",
"27 1 3 1 0 \n",
"28 2 1 0 1 \n",
"29 2 3 2 1 \n",
"30 2 3 0 0 \n",
"31 2 0 2 1 \n",
"32 1 2 1 1 \n",
"33 2 1 1 1 \n",
"34 4 2 2 0 \n",
"35 4 3 2 1 \n",
"36 1 0 1 0 \n",
"37 1 3 0 1 \n",
"38 4 3 2 1 \n",
"39 3 0 0 1 \n",
"40 2 2 0 0 \n",
"41 2 1 2 0 \n",
"42 2 1 0 1 \n",
"43 4 3 1 1 \n",
"44 4 1 1 0 \n",
"45 1 0 0 0 \n",
"46 2 1 2 1 \n",
"47 4 3 0 0 \n",
"48 2 2 2 1 \n",
"49 4 1 2 0 \n",
"50 1 3 1 0 \n",
"51 4 1 2 1 \n",
"52 2 2 2 1 \n",
"53 1 0 0 1 \n",
"54 3 3 0 1 \n",
"55 2 2 1 1 \n",
"56 2 1 1 1 \n",
"57 2 0 2 0 \n",
"58 3 1 1 0 \n",
"\n",
"[59 rows x 40 columns]\n"
]
}
],
"source": [
"import pandas as pd\n",
"\n",
"df = pd.read_csv(r'data/inflammation-01.csv')\n",
"print(df)"
]
},
{
"cell_type": "code",
"execution_count": 49,
"id": "2223ef6b",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" 1 2 4 7 8\n",
"0 2 1 3 2 2\n",
"1 1 2 6 2 5\n",
"2 2 2 2 1 6\n",
"3 1 1 3 5 2\n",
"4 1 4 2 1 6\n"
]
}
],
"source": [
"ndf = pd.DataFrame(df, columns=['1', '2', '4', '7', '8']).head()\n",
"print(ndf)"
]
},
{
"cell_type": "code",
"execution_count": 50,
"id": "16e2e180",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"<class 'pandas.core.frame.DataFrame'>\n",
"RangeIndex: 5 entries, 0 to 4\n",
"Data columns (total 5 columns):\n",
" # Column Non-Null Count Dtype\n",
"--- ------ -------------- -----\n",
" 0 1 5 non-null int64\n",
" 1 2 5 non-null int64\n",
" 2 4 5 non-null int64\n",
" 3 7 5 non-null int64\n",
" 4 8 5 non-null int64\n",
"dtypes: int64(5)\n",
"memory usage: 328.0 bytes\n"
]
}
],
"source": [
"ndf.info()"
]
},
{
"cell_type": "code",
"execution_count": 51,
"id": "ae578c3a",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>1</th>\n",
" <th>2</th>\n",
" <th>4</th>\n",
" <th>7</th>\n",
" <th>8</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>count</th>\n",
" <td>5.000000</td>\n",
" <td>5.000000</td>\n",
" <td>5.000000</td>\n",
" <td>5.000000</td>\n",
" <td>5.00000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>mean</th>\n",
" <td>1.400000</td>\n",
" <td>2.000000</td>\n",
" <td>3.200000</td>\n",
" <td>2.200000</td>\n",
" <td>4.20000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>std</th>\n",
" <td>0.547723</td>\n",
" <td>1.224745</td>\n",
" <td>1.643168</td>\n",
" <td>1.643168</td>\n",
" <td>2.04939</td>\n",
" </tr>\n",
" <tr>\n",
" <th>min</th>\n",
" <td>1.000000</td>\n",
" <td>1.000000</td>\n",
" <td>2.000000</td>\n",
" <td>1.000000</td>\n",
" <td>2.00000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>25%</th>\n",
" <td>1.000000</td>\n",
" <td>1.000000</td>\n",
" <td>2.000000</td>\n",
" <td>1.000000</td>\n",
" <td>2.00000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>50%</th>\n",
" <td>1.000000</td>\n",
" <td>2.000000</td>\n",
" <td>3.000000</td>\n",
" <td>2.000000</td>\n",
" <td>5.00000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>75%</th>\n",
" <td>2.000000</td>\n",
" <td>2.000000</td>\n",
" <td>3.000000</td>\n",
" <td>2.000000</td>\n",
" <td>6.00000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>max</th>\n",
" <td>2.000000</td>\n",
" <td>4.000000</td>\n",
" <td>6.000000</td>\n",
" <td>5.000000</td>\n",
" <td>6.00000</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" 1 2 4 7 8\n",
"count 5.000000 5.000000 5.000000 5.000000 5.00000\n",
"mean 1.400000 2.000000 3.200000 2.200000 4.20000\n",
"std 0.547723 1.224745 1.643168 1.643168 2.04939\n",
"min 1.000000 1.000000 2.000000 1.000000 2.00000\n",
"25% 1.000000 1.000000 2.000000 1.000000 2.00000\n",
"50% 1.000000 2.000000 3.000000 2.000000 5.00000\n",
"75% 2.000000 2.000000 3.000000 2.000000 6.00000\n",
"max 2.000000 4.000000 6.000000 5.000000 6.00000"
]
},
"execution_count": 51,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ndf.describe()"
]
},
{
"cell_type": "code",
"execution_count": 52,
"id": "37852d1c",
"metadata": {},
"outputs": [],
"source": [
"%matplotlib inline"
]
},
{
"cell_type": "code",
"execution_count": 53,
"id": "6fc9e710",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<AxesSubplot: >"
]
},
"execution_count": 53,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"ndf.plot()"
]
}
],
"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.9.7"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
>SEQUENCE_1
MTEITAAMVKELRESTGAGMMDCKNALSETNGDFDKAVQLLREKGLGKAAKKADRLAAEG
LVSVKVSDDFTIAAMRPSYLSYEDLDMTFVENEYKALVAELEKENEERRRLKDPNKPEHK
IPQFASRKQLSDAILKEAEEKIKEELKAQGKPEKIWDNIIPGKMNSFIADNSQLDSKLTL
MGQFYVMDDKKTVEQVIAEKEKEFGGKIKIVEFICFEVGEGLEKKTEDFAAEVAAQL
>SEQUENCE_2
SATVSEINSETDFVAKNDQFIALTKDTTAHIQSNSLQSVEELHSSTINGVKFEEYLKSQI
ATIGENLVVRRFATLKAGANGVVNGYIHTNGRVGVVIAAACDSAEVASKSRDLLRQICM
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment