{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# COMP 364: Sequence Handling with BioPython\n", "\n", "\n", "## Warmup: OOP Practice\n", "\n", "Write a class that representas a Student with two attributes: name, and grade. Next, write a class called Course that represents the students in the course with two initial attribute: course name, and a list of Students, a max capacity (class attribute). The Course class can also compute the average of all the students grades and add a student to the course." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import statistics\n", "\n", "class Student:\n", " def __init__(self, name, grade):\n", " self.name = name\n", " self.grade = grade\n", "class Course:\n", " max_capacity = 3\n", " def __init__(self, name):\n", " self.course_name = name\n", " self.students = []\n", " def add_student(self, student_name, grade):\n", " if len(self.students) + 1 > Course.max_capacity:\n", " print(\"Class is full\")\n", " else:\n", " self.students.append(Student(student_name, grade))\n", " def class_avg(self):\n", " return statistics.mean([s.grade for s in self.students])\n", "\n", "\n", "\n", "c = Course(\"COMP 364\")\n", "print(c.course_name)\n", "print(c.students)\n", "\n", "c.add_student(\"Carlos\", 3.4)\n", "c.add_student(\"Chris\", 4.0)\n", "c.class_avg()\n", "\n", "b = Course(\"COMP 202\")\n", "b.add_student(\"Carlos\", 1.2)\n", "\n", "print([student.name for student in b.students])\n", "print([student.name for student in c.students])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# BioPython\n", "\n", "BioPython is a very popular third party Python package for handling biological data.\n", "\n", "In order to install:\n", "\n", "```\n", "conda install biopython\n", "```\n", "\n", "BioPython has three major functionalities:\n", "\n", "* Sequence Handling\n", "* 3D Structure\n", "* Population Genetics\n", "\n", "Today we'll cover sequence handling and next time we will do 3D structure handling, and if there is time we may do some Population Genetics.\n", "\n", "Some useful references: [tutorial](http://biopython.org/DIST/docs/tutorial/Tutorial.html), [website](http://biopython.org/), [wiki](http://biopython.org/wiki/Category%3AWiki_Documentation) (most of my examples are coming from these sources).\n", " \n", "# `BioPython.Seq`\n", "\n", "The main object we'll be dealing with are sequences. This is handled by the `Seq` class.\n", "\n", "As we know, we can have DNA, RNA, and Protein sequences.\n", "\n", "BioPython helps us cleanly distinguish and do different things with different kinds of sequences." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#let's make a generic sequence\n", "\n", "from Bio.Seq import Seq\n", "\n", "my_seq = Seq(\"CCCGGAGAGA\")\n", "print(type(my_seq))\n", "#let's see what attributes this object has\n", "attributes = [a for a in dir(my_seq) if not a.startswith(\"_\")]\n", "print(attributes)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "It seems like there is a lot we can do with this object.\n", "\n", "The problem is at this point Python doesn't know what kind of sequence this is (DNA, RNA, Protein).\n", "\n", "We have to specify what kind of \"Alphabet\" the sequence belongs to." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#right now it has just a generic alphabet\n", "print(my_seq.alphabet)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "from Bio.Alphabet import generic_dna, generic_protein, generic_rna\n", "\n", "my_dna = Seq(\"CCCGGAGAG\", generic_dna)\n", "my_rna = Seq(\"ACCCGUUGU\", generic_rna)\n", "my_protein = Seq(\"AKKKGGGUUULL\", generic_protein)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Biopython will now know the difference for example between a DNA base `A` for adenine and the protein residue `A` for alanine.\n", "\n", "Now we can do some cool things.\n", "\n", "We can perform the main actions of the central dogma: transcribe and translate." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "my_gene = Seq(\"ACTAGCAGCGGA\", generic_dna)\n", "\n", "#get the mRNA\n", "\n", "my_transcript = my_gene.transcribe()\n", "print(my_transcript)\n", "print(my_transcript.alphabet)\n", "\n", "\n", "#get the protein from the mRNA\n", "my_protein = my_transcript.translate()\n", "print(my_protein)\n", "print(my_protein.alphabet)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can also go straight from the DNA to the protein." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "coding_dna = Seq(\"ATGGCCATTGTAATGGGCCGCTGAAAGGGTGCCCGATAG\", generic_dna)\n", "myprot = coding_dna.translate()\n", "print(myprot)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As you can see, we got some STOP codons represented as `*` and translation continued.\n", "\n", "We can get translation to actually stop when it encounters a STOP codon." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "myprot = coding_dna.translate(to_stop=True)\n", "print(myprot)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can be even more realistic and only allow translation of valid genes (i.e. with a valid start and stop codon and proper number of bases).\n", "\n", "This is done by setting the `cds=True` keyword argument, which stands for \"coding sequence\".\n", "\n", "If we don't have a valid coding sequence, we get an exception." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "myprot = coding_dna.translate(cds=True)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "gene = Seq(\"ATGGCCATTGTAATGTAG\", generic_dna)\n", "gene.translate(cds=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### General sequence methods\n", "\n", "There are some convenient operations for dealing with sequences." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can concatenate sequences if they are of matching type." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "seq1 = Seq(\"AAACGGA\", generic_dna)\n", "seq2 = Seq(\"GGAGAT\", generic_dna)\n", "\n", "seq1 + seq2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can also index and slice as though we had strings." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "seq1[:2] + seq2[-1]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`Seq` objects are immutable, just like strings." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "seq1[2] = \"G\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "There is another type of object called a `MutableSeq`. If we want to support mutability we can convert a `Seq` object to a `MutableSeq` object quite easily." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "mut_seq = seq1.tomutable()\n", "mut_seq" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "mut_seq[0] = \"G\"\n", "print(mut_seq)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can also do searching inside sequences." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "myseq = Seq(\"CCAGAAACCCGGAA\", generic_dna)\n", "\n", "#find the first occurence of the pattern\n", "print(myseq.find(\"GAA\"))\n", "\n", "#find the number of non-overlapping occurrences of a pattern\n", "print(myseq.count(\"GAA\"))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Database Searching\n", "\n", "Say you isolated some piece of DNA in the lab and obtained its sequence.\n", "\n", "You now want to find out which organism that sequence belongs to.\n", "\n", "You ask a biologist and they tell you to just \"BLAST it\".\n", "\n", "As you may know already, this is essentially the same as \"Google it\" for biologists.\n", "\n", "BLAST is an alignment algorithm that searches for your sequence of interest in a huge database of sequences whose origins are known.\n", "\n", "If you didn't know BioPython, you would take your sequence `AAAAGGAGAGAGAGTTTATA` and go to the [NCBI BLAST web server](https://blast.ncbi.nlm.nih.gov/Blast.cgi?PROGRAM=blastn&PAGE_TYPE=BlastSearch&LINK_LOC=blasthome) and click on buttons like a monkey.\n", "\n", "Thanks to BioPython we can do this programatically!\n", "\n", "The `qblast` method from the `Bio.Blast.NCBIWWW` module essentially sends our sequence to the BLAST web server.\n", "\n", "Here we are using the \"nucleotice BLAST\" algorithm so we say `blastn` and we are using it on the database of all nucleotide sequences, called `nt`.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "from Bio.Blast import NCBIWWW\n", "\n", "result_handle = NCBIWWW.qblast(\"blastn\", \"nt\", Seq(\"AAAAGGAGAGAGAGTTTATA\", generic_dna))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We wait a few seconds and get a `result_handle` which is like a temporary open file that we can read from.\n", "\n", "The format of this file is in XML so not easy to read, thankfully BioPython has an XML parser that extracts all the information for us." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "from Bio.Blast import NCBIXML\n", "blast_records = NCBIXML.parse(result_handle)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We get an \"iterator\" of BLAST record objects, or \"search results\". We can now loop over each of our search results and print some information.\n", "\n", "Here I am looping over all the results which each have an attribute `alignments` which are the alignments of our query sequence to some organism in the database.\n", "\n", "The `alignment` attribute itself has other attributes like the `query` sequence, the `length` and `title` of the matching organism.." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "for b in blast_records:\n", " for alignment in b.alignments:\n", " for hsp in alignment.hsps:\n", " print('****Alignment****')\n", " print('sequence:', alignment.title)\n", " print('length:', alignment.length)\n", " print('e value:', hsp.expect)\n", " print(hsp.query[0:75] + '...')\n", " print(hsp.match[0:75] + '...')\n", " print(hsp.sbjct[0:75] + '...')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# `SeqRecord` and `SeqIO`\n", "\n", "Often, sequences have some additional information associated to them. \n", "\n", "A good example was the BLAST exercise which gave us sequences associated to specific organisms, and genomic locations.\n", "\n", "Ideally we would want to be able to keep this information along with our `Seq` if we have it.\n", "\n", "BioPython lets us do this with the `SeqRecord` and `SeqIO` classes.\n", "\n", "\n", "## Parsing with `SeqIO`\n", "\n", "The `SeqIO` class which stands for Sequence Input/Output lets us read and write from various sequence annotation file formats which are common in biological databases.\n", "\n", "I went to the [GenBank](https://www.ncbi.nlm.nih.gov/genbank/) sequence database and looked for some sequence related to the Bubonic Plague (Yersinia Pestis bacteria) [here](https://www.ncbi.nlm.nih.gov/nuccore/NZ_ADRZ01000932.1?report=fasta).\n", "\n", "![](https://www.nationalgeographic.com/content/dam/science/photos/000/033/3338.ngsversion.1492437604403.adapt.676.1.jpg)\n", "(\"The Triumph of Death by Pieter Bruegel)\n", "\n", "We get a `fasta` file which is very common for sequence annotations so BioPython can parse it for us automatically.\n", "\n", "The annotation for a FASTA sequence is typically held in the header:\n", "\n", "```\n", ">NZ_ADRZ01000932.1 Yersinia pestis biovar Antiqua str. E1979001 Contig_E1979001_19275, whole genome shotgun sequence\n", "```\n", "\n", "The `SeqIO.parse` takes a path to a file and a format, in this case \"fasta\" and produces an iteratror over each entry in the fasta file.\n", "\n", "Each item produced by the iterator is a `SeqRecords` object.\n" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "['annotations', 'dbxrefs', 'description', 'features', 'format', 'id', 'letter_annotations', 'lower', 'name', 'reverse_complement', 'seq', 'upper']\n", "\n", "['annotations', 'dbxrefs', 'description', 'features', 'format', 'id', 'letter_annotations', 'lower', 'name', 'reverse_complement', 'seq', 'upper']\n" ] } ], "source": [ "from Bio import SeqIO\n", "\n", "records = SeqIO.parse(\"plague.fa\", \"fasta\")\n", "for r in records:\n", " print(type(r))\n", " print([a for a in dir(r) if not a.startswith(\"_\")])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### `SeqRecord` Objects\n", "\n", "If you have a file with a single fasta record, you can use the `SeqIO.read()` function.\n" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": true }, "outputs": [], "source": [ "record = SeqIO.read(\"single_plague.fa\", \"fasta\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The `SeqRecords` object has some useful attributes.\n", "\n", "The object contains a `Seq` object witih the sequence info." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ID: NZ_ADRZ01000932.1\n", "Name: NZ_ADRZ01000932.1\n", "Description: NZ_ADRZ01000932.1 Yersinia pestis biovar Antiqua str. E1979001 Contig_E1979001_19275, whole genome shotgun sequence\n", "Number of features: 0\n", "Seq('CTCTCCCAGCTGAGCTATAGCCCCAATGCGCACATAATAAATCGTGTGAACGGG...AGC', SingleLetterAlphabet())\n" ] } ], "source": [ "print(record)" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "CTCTCCCAGCTGAGCTATAGCCCCAATGCGCACATAATAAATCGTGTGAACGGGGCGCATGATATGAGACCCCCGAAACTGTGTCAACGGCTAAATCGATTTCTCGTGTTAAGCGCTGAAAAAGCGGCCAAATCAGCCTGCAAATAACATAATAAGTGGAATGATGTTCACAAATTTGTTGTCACACCGCTGCTGTTATCAAATATAATAAATATCCTCCGGCATAGC\n" ] } ], "source": [ "print(record.seq)" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "NZ_ADRZ01000932.1\n" ] } ], "source": [ "print(record.id)" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "NZ_ADRZ01000932.1 Yersinia pestis biovar Antiqua str. E1979001 Contig_E1979001_19275, whole genome shotgun sequence\n" ] } ], "source": [ "print(record.description)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can also create our own `SeqRecord` objects." ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ID: YP_025292.1\n", "Name: HokC\n", "Description: toxic membrane protein, small\n", "Number of features: 0\n", "Seq('MKQHKAMIVALIVICITAVVAALVTRKDLCEVHIRTGQTEVAVF', IUPACProtein())\n" ] } ], "source": [ "from Bio.Seq import Seq\n", "from Bio.SeqRecord import SeqRecord\n", "from Bio.Alphabet import IUPAC\n", "record = SeqRecord(Seq(\"MKQHKAMIVALIVICITAVVAALVTRKDLCEVHIRTGQTEVAVF\",\n", " IUPAC.protein),\n", " id=\"YP_025292.1\", name=\"HokC\",\n", " description=\"toxic membrane protein, small\")\n", "print(record)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Then we can write it to FASTA format." ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'>YP_025292.1 toxic membrane protein, small\\nMKQHKAMIVALIVICITAVVAALVTRKDLCEVHIRTGQTEVAVF\\n'" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "record.format(\"fasta\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "And then store it in a file. \n", "\n", "So now we know how to read sequence information, as well as produce our own sequence records and store them." ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "collapsed": true }, "outputs": [], "source": [ "with open(\"myfasta.fa\", \"w\") as f:\n", " f.write(record.format(\"fasta\"))\n", " " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Making Multiple Sequence Alignments and Phylogenetic Trees\n", "\n", "Another thing biologists like to do is align (essentially, compare) sequences.\n", "\n", "If we line up two sequences on top of each other, we can look at the parts where they are different and infer many useful pieces of information.\n", "\n", "One of these pieces of information is the phylogeny.\n", "\n", "i.e. we can take a guess at how evolution took place to explain a particular set of observed sequences.\n", "\n", "\n", "\n", "### Step 1: Obtain some sequences and align them" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[SeqRecord(seq=Seq('AACCGTCAGAAGAGAGCTTTATGCAC', Alphabet()), id='0', name='', description='', dbxrefs=[]), SeqRecord(seq=Seq('ATCCGTCAGGATAGAGTTTTATTCTC', Alphabet()), id='1', name='', description='', dbxrefs=[]), SeqRecord(seq=Seq('AACCGTCCGAATCGAGCATTATTCTC', Alphabet()), id='2', name='', description='', dbxrefs=[]), SeqRecord(seq=Seq('AACCGTCCGAATAGCCCTTTATTCTC', Alphabet()), id='3', name='', description='', dbxrefs=[]), SeqRecord(seq=Seq('ATCGGTACGAATAGAGCTTTATTCTC', Alphabet()), id='4', name='', description='', dbxrefs=[]), SeqRecord(seq=Seq('AACCGTCGGAAAAGAGCTTTAGTCTC', Alphabet()), id='5', name='', description='', dbxrefs=[]), SeqRecord(seq=Seq('AACCGTCCGTGTACAGCTTTATTCGG', Alphabet()), id='6', name='', description='', dbxrefs=[]), SeqRecord(seq=Seq('AACCGGCATTACGGAGCTTTATTCTC', Alphabet()), id='7', name='', description='', dbxrefs=[]), SeqRecord(seq=Seq('AACCGTCCGAATAGATTTTTACTCTG', Alphabet()), id='8', name='', description='', dbxrefs=[]), SeqRecord(seq=Seq('GACCGGCCGAATAGAGATTTATTCTC', Alphabet()), id='9', name='', description='', dbxrefs=[]), SeqRecord(seq=Seq('ACCGATCCGTATAGAGCATTAGTCTC', Alphabet()), id='10', name='', description='', dbxrefs=[]), SeqRecord(seq=Seq('AACCGTCCGAACAGACCTTTATTCTC', Alphabet()), id='11', name='', description='', dbxrefs=[]), SeqRecord(seq=Seq('AACCGTCCGAAGAGAGCTTTCCGCTC', Alphabet()), id='12', name='', description='', dbxrefs=[]), SeqRecord(seq=Seq('CACCGTCCTAATAGACCTGTATCCTC', Alphabet()), id='13', name='', description='', dbxrefs=[]), SeqRecord(seq=Seq('AACCGTCCGAAAAGAGCTTTATTCTC', Alphabet()), id='14', name='', description='', dbxrefs=[]), SeqRecord(seq=Seq('ACCCGTCCGAATAGAGCTTTATTCTC', Alphabet()), id='15', name='', description='', dbxrefs=[]), SeqRecord(seq=Seq('AACCGGCTGAAGAGAGCTTTATTCGC', Alphabet()), id='16', name='', description='', dbxrefs=[]), SeqRecord(seq=Seq('AATCGTCCGAAGAGAGCTTTATACTC', Alphabet()), id='17', name='', description='', dbxrefs=[]), SeqRecord(seq=Seq('ATCCGCCAGAATAGAGCTTTGCTCTC', Alphabet()), id='18', name='', description='', dbxrefs=[]), SeqRecord(seq=Seq('AACCGTCTGGATAGAGTTTGATTCGC', Alphabet()), id='19', name='', description='', dbxrefs=[])]\n" ] } ], "source": [ "import random\n", "\n", "#generate some random sequences based on a random seed sequence\n", "mut = 0.1\n", "BASES = {\"A\", \"C\", \"G\", \"T\"}\n", "seqs = []\n", "seed = \"\".join([random.choice(list(BASES)) for _ in range(25 + random.choice([-1, 0, 1]))])\n", "\n", "seq_records = []\n", "\n", "for i in range(20):\n", " new_seq = \"\".join([b if random.random() > mut else random.choice(list(BASES - {b}))\\\n", " for b in seed])\n", " #create a seq record\n", " seq_records.append(SeqRecord(Seq(new_seq), id=str(i)))\n", " \n", "print(seq_records)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now that we have `SeqRecord` objects we can align them.\n", "\n", "To do so, we need to put them in a `fasta` file.\n", "\n", "### Step 2: Align the sequences" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "collapsed": true }, "outputs": [], "source": [ "#write our sequences to fasta format\n", "with open(\"seqs.fasta\", \"w\") as f:\n", " SeqIO.write(seq_records, f, \"fasta\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The next step is to actually align these sequences.\n", "\n", "BioPython has its own alignment functionalities but it requires some more installations.\n", "\n", "So let's just use an [online tool](https://www.ebi.ac.uk/Tools/msa/muscle/) which takes a input a `fasta` file which we just created.\n", "\n", "### Step 3: Load the resulting alignment" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "collapsed": true }, "outputs": [], "source": [ "#open the alignmnent file\n", "from Bio import AlignIO\n", "with open(\"aln.clustal\", \"r\") as aln:\n", " #use AlignIO to read the alignment file in 'clustal' format\n", " alignment = AlignIO.read(aln, \"clustal\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can parse the alignment with the `AlignIO` module from BioPython.\n", "\n", "I won't go into detail on this module but it has a lot of useful funcionality for dealing with sequence alignments.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Step 4: Use the alignment to obtain a \"distance\" between all pairs of sequences\n", "\n", "Using the parsed alignment, we can get the distance (or difference) between all the sequences.\n", "\n", "This just tells us, for each pair of sequences, how different they are." ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "18\t0\n", "4\t0.36\t0\n", "7\t0.36\t0.24\t0\n", "16\t0.31999999999999995\t0.28\t0.24\t0\n", "15\t0.24\t0.31999999999999995\t0.31999999999999995\t0.28\t0\n", "12\t0.31999999999999995\t0.31999999999999995\t0.31999999999999995\t0.28\t0.31999999999999995\t0\n", "14\t0.31999999999999995\t0.24\t0.24\t0.24\t0.28\t0.28\t0\n", "0\t0.31999999999999995\t0.28\t0.28\t0.24\t0.28\t0.24\t0.19999999999999996\t0\n", "3\t0.28\t0.24\t0.24\t0.19999999999999996\t0.24\t0.24\t0.16000000000000003\t0.040000000000000036\t0\n", "11\t0.28\t0.24\t0.24\t0.16000000000000003\t0.19999999999999996\t0.24\t0.19999999999999996\t0.19999999999999996\t0.16000000000000003\t0\n", "17\t0.19999999999999996\t0.24\t0.24\t0.19999999999999996\t0.24\t0.24\t0.19999999999999996\t0.19999999999999996\t0.16000000000000003\t0.16000000000000003\t0\n", "19\t0.24\t0.19999999999999996\t0.19999999999999996\t0.16000000000000003\t0.19999999999999996\t0.19999999999999996\t0.16000000000000003\t0.16000000000000003\t0.12\t0.12\t0.12\t0\n", "6\t0.16000000000000003\t0.19999999999999996\t0.19999999999999996\t0.16000000000000003\t0.12\t0.19999999999999996\t0.16000000000000003\t0.16000000000000003\t0.12\t0.12\t0.12\t0.07999999999999996\t0\n", "10\t0.24\t0.19999999999999996\t0.19999999999999996\t0.16000000000000003\t0.12\t0.19999999999999996\t0.16000000000000003\t0.16000000000000003\t0.12\t0.12\t0.12\t0.07999999999999996\t0.07999999999999996\t0\n", "5\t0.24\t0.19999999999999996\t0.19999999999999996\t0.16000000000000003\t0.19999999999999996\t0.19999999999999996\t0.12\t0.12\t0.07999999999999996\t0.12\t0.12\t0.07999999999999996\t0.07999999999999996\t0.07999999999999996\t0\n", "9\t0.24\t0.19999999999999996\t0.19999999999999996\t0.16000000000000003\t0.19999999999999996\t0.12\t0.16000000000000003\t0.12\t0.12\t0.12\t0.12\t0.07999999999999996\t0.07999999999999996\t0.07999999999999996\t0.07999999999999996\t0\n", "13\t0.16000000000000003\t0.19999999999999996\t0.19999999999999996\t0.16000000000000003\t0.16000000000000003\t0.19999999999999996\t0.16000000000000003\t0.16000000000000003\t0.12\t0.12\t0.12\t0.07999999999999996\t0.07999999999999996\t0.07999999999999996\t0.07999999999999996\t0.07999999999999996\t0\n", "8\t0.19999999999999996\t0.16000000000000003\t0.16000000000000003\t0.12\t0.16000000000000003\t0.16000000000000003\t0.12\t0.12\t0.07999999999999996\t0.07999999999999996\t0.07999999999999996\t0.040000000000000036\t0.040000000000000036\t0.040000000000000036\t0.040000000000000036\t0.040000000000000036\t0.040000000000000036\t0\n", "1\t0.28\t0.24\t0.19999999999999996\t0.12\t0.24\t0.24\t0.19999999999999996\t0.19999999999999996\t0.16000000000000003\t0.16000000000000003\t0.16000000000000003\t0.07999999999999996\t0.12\t0.12\t0.12\t0.12\t0.12\t0.07999999999999996\t0\n", "2\t0.24\t0.19999999999999996\t0.19999999999999996\t0.16000000000000003\t0.19999999999999996\t0.19999999999999996\t0.16000000000000003\t0.16000000000000003\t0.12\t0.12\t0.12\t0.040000000000000036\t0.07999999999999996\t0.07999999999999996\t0.07999999999999996\t0.07999999999999996\t0.07999999999999996\t0.040000000000000036\t0.040000000000000036\t0\n", "\t18\t4\t7\t16\t15\t12\t14\t0\t3\t11\t17\t19\t6\t10\t5\t9\t13\t8\t1\t2\n" ] } ], "source": [ "from Bio.Phylo.TreeConstruction import DistanceCalculator\n", "\n", "#calculate the distance matrix\n", "calculator = DistanceCalculator('identity')\n", "#adds distance matrix to the calculator object and returns it\n", "dm = calculator.get_distance(alignment)\n", "print(dm)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Step 5: Construct a tree from the set of distances\n", "\n", "And finally, we can construct a phylogenetic tree from the pairwise distances between all the sequences." ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "collapsed": true }, "outputs": [], "source": [ "from Bio.Phylo.TreeConstruction import DistanceTreeConstructor\n", "\n", "#initialize a DistanceTreeConstructor object based on our distance calculator object\n", "constructor = DistanceTreeConstructor(calculator)\n", "\n", "#build the tree\n", "upgma_tree = constructor.build_tree(alignment)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "And let's use the `Phylo` module to visualize the result!" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from Bio import Phylo\n", "import pylab\n", "#draw the tree\n", "Phylo.draw(upgma_tree)" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "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.6.2" } }, "nbformat": 4, "nbformat_minor": 2 }