<jupyter_start><jupyter_text>Introduction to Python for Bioinformatics - available at https://github.com/kipkurui/Python4Bioinformatics. Introduction to BiopythonBiopython is a set of tools or python packages for Computational Biology. Since some of the tasks are common and repetitive, these tools help reduce wheel reinvention, especially when parsing file formats. Bipython is an example of an open source project, developed by a team of international collaborators and hosted in GitHub:  https://github.com/biopython/biopython. In this lecture, we introduce Biopython and demonstrate how some we can utilize in Bioinformatics data analysis.  First we install BiopythonFor this, we use the conda package manager`conda install biopython` Learning ResourcesThe focus of this lecture is to give you an overview of what you can do with Biopython, and whet your appetite to learn further. At this stage of your learning, I encourage you to write your own scripts for genomic sequence parsing for better learning. When you are ready to dive deeper, here are some resources you will find useful:1. [Biopython documentation](https://biopython.org/wiki/Documentation)2. [Biopython cookbook](http://biopython.org/DIST/docs/tutorial/Tutorial.html)Then we can test if the package was successfully installed:<jupyter_code>import Bio
Bio.__version__<jupyter_output><empty_output><jupyter_text>AlphabetWith the latest version installed, now we can explore some of the cool packages available in Biopython. Let's start with the basics for dealing with genomic alphabet.<jupyter_code>import Bio.Alphabet 
Bio.Alphabet.ThreeLetterProtein.letters<jupyter_output><empty_output><jupyter_text>We can easily check the alphabet form the IUPAC module, which stores the internationally defined and accepted alphabet for genomic analysis.<jupyter_code>from Bio.Alphabet import IUPAC
IUPAC.ambiguous_dna.letters
IUPAC.unambiguous_dna.letters
IUPAC.extended_protein.letters

from Bio.Alphabet import IUPAC<jupyter_output><empty_output><jupyter_text>Getting data from EntrenzWe can download data from Entrenz using the Biopython modules. Frist we import the tool we'll need.<jupyter_code>from Bio import Entrez, Seq, SeqIO
Entrez.email = "<EMAIL>" 
hdl = Entrez.efetch(db='nucleotide', id=['NM_002299'], rettype='fasta')  # Lactase gene
#for l in hdl:
#    print l
seq = SeqIO.read(hdl, 'fasta') # we can read the downloaded data into a seq object<jupyter_output><empty_output><jupyter_text>The SeqRecord `seq` object holds a sequence and information about it.The Seq object also provides some biological methods, such as complement, reverse_complement, transcribe, back_transcribe and translate (which are not applicable to sequences with a protein alphabet).<jupyter_code>w_seq = seq[11:5795]
w_seq<jupyter_output><empty_output><jupyter_text>Write the sequence to fasta fileNow we can use the `SeqIO.write` function to save the file for later use. Remember, you always have to specify the write format.<jupyter_code>with open('../Data/example.fasta', 'w') as w_hdl:
    SeqIO.write([w_seq], w_hdl, 'fasta')
recs = SeqIO.parse('../Data/example.fasta', 'fasta')
for rec in recs:
    print(type(rec))
    seq = rec.seq
    print(rec.description)
    print(seq[:10])
    print(seq.alphabet)
recs = SeqIO.parse('../Data/example.fasta', 'fasta')
for rec in recs:
    print(rec.seq)<jupyter_output>GAAAATGGAGCTGTCTTGGCATGTAGTCTTTATTGCCCTGCTAAGTTTTTCATGCTGGGGGTCAGACTGGGAGTCTGATAGAAATTTCATTTCCACCGCTGGTCCTCTAACCAATGACTTGCTGCACAACCTGAGTGGTCTCCTGGGAGACCAGAGTTCTAACTTTGTAGCAGGGGACAAAGACATGTATGTTTGTCACCAGCCACTGCCCACTTTCCTGCCAGAATACTTCAGCAGTCTCCATGCCAGTCAGATCACCCATTATAAGGTATTTCTGTCATGGGCACAGCTCCTCCCAGCAGGAAGCACCCAGAATCCAGACGAGAAAACAGTGCAGTGCTACCGGCGACTCCTCAAGGCCCTCAAGACTGCACGGCTTCAGCCCATGGTCATCCTGCACCACCAGACCCTCCCTGCCAGCACCCTCCGGAGAACCGAAGCCTTTGCTGACCTCTTCGCCGACTATGCCACATTCGCCTTCCACTCCTTCGGGGACCTAGTTGGGATCTGGTTCACCTTCAGTGACTTGGAGGAAGTGATCAAGGAGCTTCCCCACCAGGAATCAAGAGCGTCACAACTCCAGACCCTCAGTGATGCCCACAGAAAAGCCTATGAGATTTACCACGAAAGCTATGCTTTTCAGGGCGGAAAACTCTCTGTTGTCCTGCGAGCTGAAGATATCCCGGAGCTCCTGCTAGAACCACCCATATCTGCGCTTGCCCAGGACACGGTCGATTTCCTCTCTCTTGATTTGTCTTATGAATGCCAAAATGAGGCAAGTCTGCGGCAGAAGCTGAGTAAATTGCAGACCATTGAGCCAAAAGTGAAAGTTTTCATCTTCAACCTAAAACTCCCAGACTGCCCCTCCACCATGAAGAACCCAGCCAGTCTGCTCTTCAGCCTTTTTGAAGCCATAAATAAAGACCAAGTGCTCACCATTGGGTTTGATATTAATGAGTTTCTGAGTTGTTCATCAAGTTCCAAGAAAAGCATGTCTTGT[...]<jupyter_text>Now, let's explore a genbank file<jupyter_code>records = SeqIO.parse('../Data/Streptomyces_coelicolor.gbk', 'genbank')
for record in records:
    print(record)
for record in records:
    coelicolor = record<jupyter_output><empty_output><jupyter_text>SeqIO.parse() returns a generator function, not a listAs you can see abovem when you run the previous loop again, you do not get any output. This is because the return value of `SeqIO.parse()` is a generator function. It genrates the results on the fly. This is beneficial for large input files where you don’t want to keep the whole file in memory.You have used generator functions before: range() is a generator function as well.<jupyter_code>records = list(SeqIO.parse('../Data/Streptomyces_coelicolor.gbk', 'genbank'))<jupyter_output><empty_output><jupyter_text>Every record has an id, a name, and a description, though they might be set to “unknown”. Additionally, the annotations attribute contains a dictionary of further annotations.<jupyter_code>coelicolor = records[0]
coelicolor.id
coelicolor.seq<jupyter_output><empty_output><jupyter_text>Records can also contain featuresFeatures are sequence features annotated in the record file, if present.<jupyter_code>coelicolor.features[:10]<jupyter_output><empty_output><jupyter_text>Sequence features have multiple typesIn theory, the allowed feature types are limited, in practice a lot of tools invent new types on the fly.<jupyter_code>for feature in coelicolor.features[:10]:
    print(feature.type)<jupyter_output>source
misc_feature
regulatory
gene
CDS
regulatory
gene
CDS
gene
CDS<jupyter_text>Features have qualifiers<jupyter_code>for feature in coelicolor.features[:10]:
    if feature.type == 'CDS':
        break
print('Type:', feature.type)
print('Qualifiers:', feature.qualifiers)<jupyter_output>Type: CDS
Qualifiers: OrderedDict([('locus_tag', ['SCO0001']), ('gene_synonym', ['SCEND.02c']), ('note', ['SCEND.02c, unknown, doubtful CDS, len: 225aa']), ('codon_start', ['1']), ('transl_table', ['11']), ('product', ['hypothetical protein']), ('protein_id', ['NP_624362.1']), ('db_xref', ['GI:21218583', 'GeneID:1095448']), ('translation', ['MTGHHESTGPGTALSSDSTCRVTQYQTAGVNARLRLFALLERRACPRARRTTWWPGRSARWWSWTAWRRLLGVCCVRGRLGRRRDGGERGPGGHRGPGLATARRRSGGATELAVHCADVRQRERADLVRLEGFVRESVLPRAHPHTTARRRVLEVLGEAGSLCTARTVNSDEDYILCTLGVGHYDPDDQPPFKDGKPGWQRAGASIWNGSGAACIPHAAIEGPRK'])])<jupyter_text>Qualifiers are listsEven if qualifiers only exist once per feature, Biopython always treats them as lists<jupyter_code>print(type(feature.qualifiers['locus_tag']))
tropica = list(SeqIO.parse('../Data/Salinispora_tropica_CNB_440.gbk', 'genbank'))[0]
for feature in tropica.features[:10]:
    if feature.type != 'CDS':
        continue
    protein_seq = feature.extract(tropica.seq)
    print('>' + feature.qualifiers['locus_tag'][0])
    print(protein_seq)<jupyter_output>>STROP_RS00005
GTGACGGATACAACCGACCTCGCCGCGGTGTGGACGGCAACGACCGACGAGTTGGCCGACGAGATCGTCTCTGCCCAGCAGCGGGCCTATCTGCGACTGACCCGCCTCCGCGCCATCGTCGAGGACACCGCGCTCGTCTCCGTCCCGGACGCCTTCACCCGAGATGTCATCGAGTCCCGGCTCCGCCCGGCGATCACCGAGGCCCTCACCCGCCGGCTGGGGCGCCCCATCCAGGTGGCGGTCACGGTGCGAGCACCGGAAGACGCCCCCGGCCGCCCGGCCGGCACCATCTACCACAGCGCCCCGAGCCCGGAGACCGGCGCGTTGCCCGGCGACACCACCGACCGCGCCGCGGGAGGGGGCCCGGACGACGGCGTGGACCACAGGTTCCCGCTGATCCCCGGGCAGGCCCAACCGGAGCGCCGCACTGCGGCGCCCGCTGGTTCGTACGGCGAGCAGACGACGCCGATGTCCCGGGACAGCCAGGAGCCGTTGTTCAGCTCCGCCTTCGCCGGGCCGCCCCGAGGCGAGCGTCACGATGTTGACGAGCAGGCCCGGCTGGGCCCACCGGTGACCGAACGCCCGTTCGAGGCCCACTACCGAGCAGAGGGGGCGGACCAGCACGGGGGGCGGGCCCTGCCCCGGGAACTCGGCACCGACAGCGGGCCGGGGAGGGTGGACCACCGACCGGGTGGCCGCGAGGACCGTCGGCCACCGGCACCCGCCGACGGCGGCGGCAACCGGCTCAACCCGAAGTACATGTTCGAGACGTTCGTTATCGGTTCGTCGAACCGATTCGCCCACGCGGCTTCGGTGGCGGTCGCCGAGTCACCGGCGAAGGCGTACAACCCGCTGTTCATCTACGGCAGCTCAGGGCTGGGCAAGACGCACTTGCTGCACGCGATCGGCCACTACGCCACGACGCTCGGCAACGCCAACTCGGTCCGGTACGTCTCGACCGAGGAGTTCACCAACGACTTCATCA[...]
{'fraction_non_alphanumeric': 0.07200774537093066, 'fraction_numerical': 0.008713542296986567, 'mean_word_length': 8.676814988290397, 'pattern_counts': {'":': 0, '<': 50, '<?xml version=': 0, '>': 52, 'https://': 3, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '13', 'dir': 'jupyter-structured-clean-dedup', 'id': '434401', 'license': 'CC-BY-3.0', 'n_tokens_mistral': 3178, 'n_tokens_neox': 2821, 'n_words': 615, 'path': 'Notebooks/10.ipynb', 'repo_name': 'Namikelwa/Python4Bioinformatics2019', 'size': '8275'}