Você está na página 1de 73

Bioinformática

Índice

Sequências biológicas............................................................................................................4
Transcrição...............................................................................................................................5
Complemento Inverso.............................................................................................................5
Tradução.......................................................................................................................................6
Open Reading Frames – ORFs............................................................................................8

Alinhamento de Sequências Biológicas......................................................................10


Função objetivo/mérito....................................................................................................11
Matrizes de pontos.............................................................................................................14
Algoritmo de Needleman/Wunsch...................................................................................15
Algoritmo de Smith/Waterman........................................................................................18
Métodos Heurísticos - BLAST........................................................................................20

Expressões Regulares............................................................................................................21
MOTIF............................................................................................................................................23

Classes...........................................................................................................................................25
Classe MySeq...........................................................................................................................26
Classe SubstMatrix.............................................................................................................31
Classe MyAlign......................................................................................................................33

BioPython......................................................................................................................................36
Alfabetos..................................................................................................................................37
Manipulação de sequências............................................................................................38
Complemento (ADN)...............................................................................................................39
Transcrição e Tradução (ADN).....................................................................................40
Tradução (RNA)......................................................................................................................40
Tabelas de Tradução...........................................................................................................41
Anotação de sequências: objecto SeqRecord.......................................................41
Formatos de sequências: objeto SeqIO...................................................................42
Função read: Ficheiro Fasta....................................................................................43
Função read: Ficheiro Genbank...............................................................................43

2
Parse........................................................................................................................................44
Sequências retiradas da net....................................................................................46
Escrita de sequências..................................................................................................47
Conversão de Formatos..................................................................................................48
Objetos SeqFeature.............................................................................................................49
Localização..........................................................................................................................50
Features: Ficheiro Genbank......................................................................................51

Alinhamento Múltiplo de Sequências...........................................................................51


Programação Dinâmica........................................................................................................52
Algoritmos Progressivos.................................................................................................53
CLUSTAL-W..............................................................................................................................56

BLAST com Biopython...............................................................................................................56


Executar Blast pela Web.................................................................................................57
Parsing dos resultados do Blast..............................................................................57
Classe BlastRecord.............................................................................................................58
Representação de Alinhamentos...................................................................................59
Objeto AlignIO......................................................................................................................60
Conversão de Formatos......................................................................................................63
Manipulação dos Alinhamentos.....................................................................................64
Módulo Bio.pairwise2........................................................................................................65

Análise de Dados Ómicos.....................................................................................................67


Estrutura..................................................................................................................................68
Dados de expressão genética........................................................................................69
Pré-tratamento dos dados brutos..............................................................................69
Pré-processamento dos dados........................................................................................69
Transformação logarítmica.........................................................................................70
Filtros de “flat patterns”......................................................................................70
Standardização entre diferentes amostras.....................................................70
Análise de dados..................................................................................................................71
Expressão diferencial..................................................................................................71

3
Clustering............................................................................................................................72

Sequências biológicas

Computacionalmente, assumiremos que as sequências biológicas são


representadas como strings (sequências de caracteres).
O ADN e o RNA são constituídos por um alfabeto de 4 letras: A, C, G e
T para o ADN e A, C, G e U para o RNA.
As proteínas são representadas por um alfabeto de 20 letras, cada uma
representando um aminoácido.

import re

def validaDNA (adn):


'''Diz se uma sequência é válida ou não'''
ADN = adn.upper()
for c in ADN:
if c not in "ACGT":
return False
return True

def validaDNAcomER (seq):


'''Diz se seq é válida através de Expressões Regulares (+ à frente) '''
if re.search ("[^ACTGactg]", seq) != None:
# match com qualquer carater diferente de ACTG/actg
return (False)
else:
return (True)

Transcrição
Representa a conversão de uma sequência de ADN numa sequência de RNA.
Como todas as sequências de ADN guardadas nas bases de dados são de
sequências de ADN lidas na direção 5’-> 3’, basta alterar todos os T’s
para U’s.

4
def transcricao (adn):
return (adn.upper (). replace ('T', 'U'))

Complemento Inverso
Para se obter a sequência complementar de uma sequência de ADN devem-
se fazer as seguintes conversões, posição a posição: A-> T; T-> A; C-> G e
G-> C. Para manter a leitura na mesma direção a sequência complementar
deverá ser invertida, obtendo-se assim o complemento inverso. Este
processo permite verificar qual será a outra banda do ADN, a que não está
guardada nas bases de dados, ou seja, a banda do ADN lida na direção 3’->
5’.

def complemento (adn):


comp = ''
for c in adn.upper ():
if c == 'A':
comp = 'T' + comp
elif c == 'T':
comp = 'A' + comp
elif c == 'G':
comp = 'C' + comp
elif c == 'C':
comp = 'G' + comp
return (comp)

5
Tradução
Consiste na conversão de uma sequência de mRNA numa sequência de
aminoácidos. O processo passa por identificar cada codão, converte-lo no
aminoácido respetivo e juntar os aminoácidos resultantes pela ordem dada.

def traduzcodao (cod):


'''Converte cada codão no aminoácido correspondente'''
tc = {'GCT':'A', 'GCC':'A', 'GCA':'A', 'GCG':'A', 'TGT':'C', 'TGC':'C',
'GAT':'D', 'GAC':'D', 'GAA':'E', 'GAG':'E', 'TTT':'F', 'TTC':'F',
'GGT':'G', 'GGC':'G', 'GGA':'G', 'GGG':'G', 'CAT':'H', 'CAC':'H',
'ATA':'I', 'ATT':'I', 'ATC':'I', 'AAA':'K', 'AAG':'K', 'TTA':'L',
'TTG':'L', 'CTT':'L', 'CTC':'L', 'CTA':'L', 'CTG':'L', 'ATG':'M',
'AAT':'N', 'ACC':'N', 'CCT':'P', 'CCC':'P', 'CCA':'P', 'CCG':'P',
'CAA':'Q', 'CAG':'Q', 'CGT':'R', 'CGC':'R', 'CGA':'R', 'CGG':'R',
'AGA':'R', 'AGG':'R', 'TCT':'S', 'TCC':'S', 'TCA':'S', 'TCG':'S',
'AGT':'S', 'AGC':'S', 'ACT':'T', 'ACC':'T', 'ACA':'T', 'ACG':'T',
'GTT':'V', 'GTC':'V', 'GTA':'V', 'GTG':'V', 'TGG':'W', 'TAT':'Y',
'TAC':'Y', 'TAA':'_', 'TAG':'_', 'TGA':'_'}
cod = cod.upper ()
if cod in tc: aa = tc [cod]

6
else: aa = 'X' #X = erro
return (aa)
def traduzseq (adn, iniPos = 0):
ADN = adn.upper ()
AA = ''
for pos in range (0, len (ADN) - 2, 3):
'''range (0, len (ADN) - 1, 3) - seleciona o 1º nucleótido dos codões.
Tem de se subtrair menos 1 porque nas strings começa-se a contar do 0.
Se o tamanho da sequência não for múltiplo de 3, ex: ACT GT, o método
anterior selecionaria A e G, no entanto, GT não é um codão, pelo que se
tem de usar range (0, len (ADN) - 2, 3), para desta forma não se
seleccionarem nucleótidos que não representem o início de um codão'''
codao = ADN [pos: pos + 3] # seleciona os codões
AA += traduzcodao (codao)
return (AA)

7
Open Reading Frames – ORFs
Cada sequência de ADN poderá ter 6 frames de leitura, na procura de
possíveis proteínas codificadas:
 Na sequência original podemos começar a ler nas posições 1, 2 ou
3, tendo assim 3 sequências distintas de aminoácidos
 Na sequência complementar inversa podemos começar a ler nas
posições 1, 2 ou 3
Assim de uma sequência de ADN podem extrair-se 6 possíveis sequências
de aminoácidos.

def orfs (adn):


res = []
res.append (traduzseq (adn, 0))
res.append (traduzseq (adn, 1))
res.append (traduzseq (adn, 2))
compinv = complemento (adn)
res.append (traduzseq (compinv, 0))
res.append (traduzseq (compinv, 1))
res.append (traduzseq (compinv, 2))
return (res)

8
Todas as possíveis proteínas iniciam-se pelo aminoácido Metionina (M)
e terminam com stop (representado por_): M……_. O stop não pode ocorrer no
interior de uma proteína; a Metionina por sua vez pode ocorrer dentro de
uma proteína.

def todasproteinas (seqAA):


'''Identifica todas as proteínas da sequência de aminoácidos'''
seqAA = seqAA.upper()
protatuais = []
proteinas = []
for aa in seqAA:
if aa == '_': # Quando aparece o codão stop, a proteína acaba
if protatuais:
for p in protatuais:
# Adiciona-se a proteína atual à lista de proteínas
proteinas.append (p)
protatuais = [] # apaga-se a proteína atual, para nova procura
else:
if aa == 'M': # A proteína começa com o aminoácido M
protatuais.append ('')
for i in range (len (protatuais)):
'''Enquanto não aparecer o codão stop (_), continuam-se a
acrescentar-se aminoácidos a proteína'''
protatuais [i] += aa
return (proteinas)

9
Alinhamento de Sequências Biológicas

O alinhamento de sequências é um procedimento de comparação de duas


ou mais sequências, procurando séries de carateres individuais que se
encontrem na mesma ordem nas sequências, podendo introduzir-se
espaçamentos em cada uma delas. Um bom alinhamento de duas sequências
implica que estas são similares e que poderão ter uma ascendência comum.
As sequências são similares se o número de carateres idênticos
(emparelhados durante o alinhamento) é elevado. Duas sequências similares
têm uma probabilidade mais alta de terem estruturas e funções semelhantes.
Não é possível comparar sequências biológicas sem realizar o seu
alinhamento dada a existência de mutações. O alinhamento de uma sequência
com outra de função/estrutura conhecida pode trazer informações valiosas
sobre a função/estrutura da primeira.

O alinhamento pode ser Global ou Local.


No alinhamento global tentam-se alinhar ambas as sequências na
totalidade (assumindo tamanhos semelhantes). Podendo-se identificar genes/
proteínas com estruturas globais e funções semelhantes
No alinhamento local tentam-se alinhar segmentos das sequências.
Podem identificar zonas conservadas ao longo da evolução que configurem,
por ex., zonas funcionais ativas de proteínas.

Quantos possíveis alinhamentos existem entre duas sequências de


tamanho n?

10
Função objetivo/mérito
Permite avaliar a “qualidade” de um alinhamento, atribuindo-lhe um
valor numérico.
Tipicamente, a função objectivo adotada é aditiva, isto é,
corresponde à soma dos termos associados a cada par de carateres ou
espaçamentos, sendo definida a partir de:

 Função de penalização para a ocorrência de espaçamentos:


P = g + rx
- P: penalidade do espaçamento
- g: penalidade por início de um espaçamento
- r: penalidade pela extensão do espaçamento por mais um caráter
- x: número de caracteres do espaçamento

 Matriz de substituição para a co-corrência de carateres: são


tabelas que definem a pontuação a adicionar à função de mérito,
para cada par de caracteres. Ex: Matriz blosum62.

11
Os valores correspondem ao logaritmo da divisão das
probabilidades de substituição em sequências relacionadas, sobre
a probabilidade de substituição em sequências não relacionadas
(logaritmos tornam coerente a sua soma na função objetivo;

valores são multiplicados por 10 e arredondados).

Vamos assumir que temos 1000 pares de aminoácidos retirados


de “bons” alinhamentos. Nos 1000, o par de aminoácidos SS aparece
32 vezes; se a probabilidade do aminoácido S for de 10%,
deveríamos ter um valor esperado de 10%x10%x1000 = 10 ocorrências
deste par. O score do par SS seria então de 10xlog10(32/10) = 5.
No caso do par SL teríamos 9 casos; se a probabilidade de L
é de 15%, o valor esperado do par seria de 15 ocorrências. O
score do par SL seria: 10xlog10(9/15) = -2.

Usaremos um dicionário para guardar a matriz, em que as


chaves são os pares de letras (juntas) a serem comparados e os
valores os scores para esse par:

def matrizSubs (match, mismatch, alfabeto):


'''Cria uma Matriz de substituição'''
sm = {}
for c1 in alfabeto:
for c2 in alfabeto:
if c1 == c2: sm [c1 + c2] = match
else: sm [c1 + c2] = mismatch
return (sm)

s1 = 'ATGAAGG'
s2 = 'AAGAGAG'
sm = matrizSubs (1, 0, 'ACTG')
print (sm)

12
No caso da matriz de substituição estiver num ficheiro tem
de se ler esse ficheiro, pelo que utiliza-se outro algoritmo:

def readFile (filename):


sm = {}
f = open (filename, 'r') # 'r'= read
line = f.readline ()
tokens = line.split ('\t') # lista com os carateres da 1ª linha, inclui '\
n'
ns = len (tokens)
alfabeto = [] # lista com os carateres da 1ª linha, sem '\n'
for i in range (0, ns):
alfabeto.append (tokens [i][0])
for i in range (0, ns):
line = f.readline () # lê as restantes linhas
tokens = line.split ('\t') # cria uma lista para cada linha
for j in range (0, len (tokens)):
k = alfabeto [i] + alfabeto [j]
# k => todas as combinações de letras possíveis
sm [k] = int (tokens [j]) # valores das combinações
return (sm)

sm = readFile ('blosum62.mat')
s1 = 'LGPS-GC'
s2 = 'TGPSGG-'
print (sm)

def scorePos (c1, c2, sm, g):


'''Score de uma posição par de letras'''
if c1 =='-' or c2 =='-': return (g)
else: return (sm [c1 + c2])

def scoreAlign (seq1, seq2, sm, g):


'''Score de um alinhamento'''
res = 0
for i in range (len (seq1)):
res += scorePos (seq1[i], seq2[i], sm, g)

13
return (res)

Matrizes de pontos
Método para comparar duas sequências de forma visual, o que permite
procurar zonas de alinhamento e repetições de carateres (diretas ou
invertidas), para além de zonas complementares.
Representa as duas sequências, uma na horizontal (colunas) e outra na
vertical (linhas).
Os pontos representam caracteres coincidentes e as diagonais
representam regiões de similaridade nas sequências.

def createMat (seq1, seq2):


mat = []
for i in range (len (seq1)):
mat.append ([])
for j in range (len (seq2)):
mat[i].append(0)
return mat

def dotplot (seq1, seq2):


mat = createMat (seq1, seq2)
for i in range (len (seq1)):
for j in range (len (seq2)):
if seq1[i] == seq2[j]:
mat[i][j] = 1
else:
mat[i][j] = 0
return mat

14
Algoritmo de Needleman/Wunsch
É um método de Programação Dinâmica (PD), método exato que garante
solução óptima. Faz o alinhamento global de duas sequências A e B.
Define-se uma matriz S, onde os elementos de A são colocados nas
linhas (i) e os de B são colocados nas colunas (j). Os elementos da matriz
S representam o mérito do melhor alinhamento percorrendo a sequência A até
à posição i e a sequência B até à posição j:

S ( i, j ) =max [S ( i−1 , j −1 )+ score ( ai ,b j ) ¿ , S ( i−1 , j )+ g , S ( i , j−1 ) + g] ¿, sendo


score ( a i , b j) o valor na matriz de substituição usada para o par de
caracteres ( a i , b j ) e g a penalização assumida por um espaçamento constante.

O mérito do melhor alinhamento é dado pelo valor do canto inferior direito


da matriz.
O alinhamento óptimo é construído de forma inversa, isto é, por trace-back,
como indicado pelas setas. Para construir o alinhamento, começa-se pela célula do
canto inferior direito. Utilizaremos a orientação das setas para construir o
alinhamento. Se a seta for:
- Diagonal, então as duas sequências recebem caracteres.
- Horizontal, coloca-se o carater na seqA e uma lacuna (gap) na seqB
- Vertical, coloca-se uma lacuna (gap) na seqA e o carater na seqB

15
def max3t (v1, v2, v3):
'''Direção das setas'''
if v1 > v2:
if v1 > v3:
return (1) # se s1 for o valor máximo a seta é diagonal
else:
return (3) # se s3 for o valor máximo a seta é horizontal
else:
if v2 > v3:
return (2) # se s2 for o valor máximo a seta é vertical
else:
return (3)

def needlemanWunsh (seq1, seq2, sm, g):


S = [[0]] # seq1 = linhas e seq2 = colunas
T = [[0]] # 0 = posição (0,0); 1 = diagonal, 2 = vertical e 3 = horizontal
for j in range (1, len (seq2) + 1): # linha 0
S[0].append (g*j)
T[0].append (3)
for i in range (1, len (seq1) + 1): # coluna 0
S.append ([g*i])
T.append ([2])
for i in range (0, len (seq1)): #resto da matriz
for j in range (len (seq2)):
''' i e j começam um ponto antes, (0,0) em vez de (1,1),
pelo que na formula se soma +1'''
s1 = S[i][j] + scorePos (seq1[i], seq2[j], sm, g)
s2 = S[i][j+1] + g
s3 = S[i+1][j] + g
S[i+1].append (max (s1, s2, s3))
T[i+1].append (max3t (s1, s2, s3))
return (S, T)
'''Dá a transposta, cada linha destas matrizes corresponde as colunas da
matriz score e trace back'''

16
def recoverAlign (T, seq1, seq2):
'''Alinhamento global de duas sequências'''
res = ['', '']
i = len (seq1)
j = len (seq2)
while i > 0 or j >0:
if T [i][j] == 1: # diagonal
res [0] = seq1 [i-1] + res[0]
res [1] = seq2 [j-1] + res[1]
i -= 1
j -= 1
elif T[i][j] == 3: # horizontal -> vertical na transposta
res [0] = '-' + res[0]
res [1] = seq2 [j-1] + res[1]
j -= 1
else: # vertical -> horizontal na transposta
res [0] = seq1 [i-1] + res[0]
res [1] = '-' + res[1]
i -= 1
return (res)

def aglobal ():


from Matrizes import printMat
seq1 = 'HGWAG'
seq2 = 'PHSWG'
sm = readFile ('blosum62.mat')
res = needlemanWunsh(seq1, seq2, sm, -8)
S = res [0]
T = res [1]
printMat (S)
print ('O mérito do melhor alinhamento é ', S [len (seq1)][len (seq2)])
print ('')
alin = recoverAlign (T, seq1, seq2)
print (alin [0])
print (alin [1])

17
Algoritmo de Smith/Waterman
É um método de Programação Dinâmica (PD), método exato que garante
solução óptima. Faz o alinhamento local de duas sequências.
Difere do algoritmo anterior no cálculo de S (i, j), pois quando o
valor obtido é negativo, substituiu-se por zero, neste caso, o alinhamento
é reiniciado: S ( i, j ) =max [S ( i−1 , j−1 )+ score ( ai ,b j ) ¿ , S ( i−1 , j )+ g , S ( i , j−1 ) + g , 0]¿.
O melhor alinhamento é obtido pelo maior valor em toda a matriz.

Todos os elementos da primeira


linha e coluna são iguais a zero.

def smithWaterman (seq1, seq2, sm, g):


S = [[0]] # seq1 = linhas e seq2 = colunas
T = [[0]] # 0 = posição (0,0); 1 = diagonal, 2 = vertical e 3 = horizontal
maxscore = 0
for j in range (1, len (seq2) + 1): # linha 0
S[0].append (0)
T[0].append (0)
for i in range (1, len (seq1) + 1): # coluna 0
S.append ([0])
T.append ([0])
for i in range (0, len (seq1)): #resto da matriz
for j in range (len (seq2)):
''' i e j começam em (0,0) em vez de (1,1), pelo que se soma +1'''
s1 = S[i][j] + scorePos (seq1[i], seq2[j], sm, g)
s2 = S[i][j+1] + g
s3 = S[i+1][j] + g
b = max3t (s1, s2, s3)
if b <= 0:
S [i+1].append (0)
T [i+1].append (0)

18
else:
S [i+1].append (b)
T [i+1].append (max (s1, s2, s3))
if b > maxscore:
maxscore = b
return (S, T, maxscore)

def recoverAlignLocal (S, T, seq1, seq2):


'''Alinhamento local de duas sequencias'''
from Matrizes import maxMat
res = ['', '']
i, j = maxMat (S)
while T [i][j] > 0:
if T [i][j] == 1: # diagonal
res [0] = seq1 [i-1] + res[0]
res [1] = seq2 [j-1] + res[1]
i -= 1
j -= 1
elif T[i][j] == 3: # horizontal -> vertical na transposta
res [0] = '-' + res[0]
res [1] = seq2 [j-1] + res[1]
j -= 1
else: # vertical -> horizontal na transposta
res [0] = seq1 [i-1] + res[0]
res [1] = '-' + res[1]
i -= 1
return (res)

def alocal ():


seq1 = 'HGWAG'
seq2 = 'PHSWG'
sm = readFile ('blosum62.mat')
res = smithWaterman (seq1, seq2, sm, -8)
print ('O mérito do melhor alinhamento é ', res [2])
alin = recoverAlignLocal (res [0], res [1], seq1, seq2)
print (alin [0]+ '\n'+ alin [1])

19
Métodos Heurísticos - BLAST
São rápidos que os algoritmos de Programação Dinâmica, mas não
garantem solução ótima. São ideais para comparar sequências similares.
Se as sequências a comparar forem pouco similares, o ideal será
utilizar a PD, pois tem maior sensibilidade.
O BLAST procura bons alinhamentos locais entre uma sequência query e
sequências de uma base de dados definida. Usa pequenas “palavras”, por
exemplo, 3 aminoácidos, ou 5-15 bases de DNA.O match entre as “palavras”
comuns formam a base de um alinhamento local que é posteriormente
estendido nas duas direções. A extensão ocorre até o alinhamento baixar de
um score pré-definido.

20
Expressões Regulares

São strings usadas como padrões usadas para procura noutras strings.
Permitem definir de uma forma flexível padrões que se podem procurar em
sequências.
O resultado de um processo de procura (match) pode consistir apenas
num valor lógico (existe ou não), a posição da primeira ocorrência ou
todas as ocorrências.
Para além dos caraters “normais”, as expressões regulares incluem um
conjunto de “meta-carateres” com significados especiais.

Meta-carateres Descrição

* Zero ou mais repetições do padrão ao qual se aplica

+ Uma ou mais repetições do padrão ao qual se aplica

? Zero ou uma ocorrência do padrão ao qual se aplica

{n} Exactamente n repetições do padrão ao qual se aplica

{m,n} Entre m e n repetições do padrão ao qual se aplica

. Qualquer caratere

$ Final da linha

^ Início da linha

| Disjunção (ab | bc – ab ou bc)

\s Espaços, newlines, tabs, …, “white space”

\S Não white space

\d Dígitos

\D Não digito

(…) Faz match com o que estiver dentro dos parenteses

21
Funções de procura em Python – Package re
 re.search (padrao, seq): verifica se o padrão faz match na string
seq; apenas retorna o resultado da primeira ocorrência
 group (): retorna o padrão que fez match
 span (): retorna as posições onde ocorreu o match
 re.match (padrao, seq): faz match se o padrão estiver no início da
seq
 re.findall (padrao, seq): retorna os resultados de todas as
ocorrências
 re.finditer (padrao, seq): retorna um iterador que permite recorrer
os resultados

def procuraPadrao (seq, pad):


'''Se encontrar o padrão, retorna a posição da primeira ocorrência'''
mo = re.search (pad, seq)
if mo != None:
return (mo.span()[0])
'''mo.span () - retorna a primeira e ultima posição
mo.span ()[0] - retorna a primeira posição'''
else:
return (-1)

def procuraTodasOcorrencias (seq, pad):


'''Retorna as posições de todas as ocorrências'''
mos = re.finditer (pad, seq)
res = []
for x in mos:
res.append (x.span () [0])
return (res)

22
MOTIF
Designa um padrão existente numa sequência biológica e que é
partilhado por várias sequências dada a função biológica associada.
Exemplos de motifs em sequências de ADN incluem, entre muitos outros,
locais de ligação de proteínas (ou outros elementos) regulatórios ao DNA,
controlando a transcrição.
Exemplos em RNA inclui, entre outros, a representação de padrões de
microRNas.
Exemplos de motifs em sequências de proteínas incluem, entre outros,
representação de domínios conservados de proteínas com funções biológicas
determinadas (e.g. locais de ligação de enzimas a substratos ou outras
moléculas).

Existem vários tipos de padrões: perfis, patterns, blocos ou motifs.

23
Os Patterns são expressões regulares que representam zonas
conservadas de proteínas. O domínio “Zinc finger RING-type signature”
(PS00518) da Prosite é representado pela expressão: "C-x-H-x-[LIVMFY]-C-
x(2)-C-[LIVMYA]". Em que:
- x: representa qualquer aminoácido
- []: representa lista de aminoácidos alternativos
- x (2): representa dois aa’s quaisquer
- os “-” são usados para separar as várias posições

def findZincFinger (seq):


'''Procura o domínio Zinc Finger numa proteína com sequência seq'''
regexp = 'C.H.[LIVMFY]C.{2}C[LIVMYA]'
mo = re.search (regexp, seq)
if mo != None:
return (mo.span() [0])
else:
return (-1)

def findProsite (seq, profile):


'''Converte os domínios da prosite em expressões regulares
E procura o domínio (profile) na sequência (seq)
Ex: findProsite (seq, 'C-x-H-x-[LIVMFY]-C-x(2)-C-[LIVMYA]')'''
regexp = profile.replace ('-', '')
regexp = regexp.replace ('x', '.')
regexp = regexp.replace ('(', '{')
regexp = regexp.replace (')', '}')
mo = re.search (regexp, seq)
if mo != None:
return (mo.span() [0])
else:
return (-1)

24
Classes

É um protótipo de um objecto que define:


 Um conjunto de atributos que caracterizam objectos dessa
classe, sendo que cada atributo terá valores independentes
para instâncias distintas de objectos da classe
 Funções que definem o comportamento dos objectos da
classe; são definidos ao nível da classe e partilhados por
todas as suas instâncias

class Funcionario:
'Classe para guardar informação de funcionários -> Documentação opcional'

#Corpo da Classe: inclui atributos e definição dos métodos


def __init__(self, nome, salario):
'''Construtor: método que cria objetos da classe
self representa o objeto da classe sobre a qual o método é chamado'''
self.nome = nome
self.salario = salario

def mostrarInformacao (self):


print ('Nome:', self.nome, ', Salário:', self.salario)

# Criando objetos da classe Funcionario


emp1 = Funcionario ('Sara', 2000)
emp2 = Funcionario ('Maria', 5000)

# Usando objetos
emp1.mostrarInformacao ()
emp2.mostrarInformacao ()

# Criando/Modificando objetos
emp1.idade = 20
emp2.salario = 4500
del emp1.idade

25
Classe MySeq
import re

class MySeq:
def __init__(self, seq, tipo = "dna"):
self.seq = seq.upper()
self.tipo = tipo

def __len__(self):
'''Aplicação da função len sobre um objetos desta classe'''
return (len (self.seq))

def __getitem__ (self, n):


'''Aplica o operador [] sobre um objeto desta classe'''
return (self.seq [n])

def __getslice__ (self, i, j):


'''Determina o comportamento no caso de se usar splicing [i:j}'''
return (self.seq [i:j])

def __str__ (self):


'''Determina a representação do objeto como uma string'''
return (self.tipo + ': ' + self.seq)

def printseq(self):
print (self.seq)

def alfabeto (self):


if self.tipo == "dna": return ("ACGT")
elif self.tipo == "rna": return ("ACGU")
elif self.tipo == "protein": return ("ACDEFGHIKLMNPQRSTVWY")
else: return None

def valida (self):


alf = self.alfabeto ()
res = True
i = 0
while i < len (self.seq) and res:
if self.seq[i] not in alf: res = False

26
else: i += 1
return (res)
def validaER (self):
if self.tipo == "dna":
if re.search ("[^ACTGactg]", self.seq) != None: return False
else: return True
elif self.tipo == "rna":
if re.search ("[^ACUGacug]", self.seq) != None: return False
else: return True
elif self.tipo == "protein":
if re.search ("[^ACDEFGHIKLMNPQRSTVWY_acdefghiklmnpqrstvwy]", self.seq) !=
None:
return False
else: return True
else: return False

def compInverso(self):
if self.tipo != "dna":
return None
comp = ""
for c in self.seq:
if (c == 'A'): comp = "T" + comp
elif (c == "T"): comp = "A" + comp
elif (c == "G"): comp = "C" + comp
elif (c== "C"): comp = "G" + comp
return (MySeq(comp))

def transcricao (self):


if self.tipo == "dna":
return (MySeq (self.seq.replace ("T","U"), "rna"))
else: return None

def traduzSeq (self, iniPos= 0):


if self.tipo != "dna":
return None
seqAA = ""

27
for pos in range (iniPos, len (self.seq) - 2, 3):
cod = self.seq [pos : pos + 3]
seqAA += self.traduzCodao (cod)
return (MySeq (seqAA, "protein"))
def traduzCodao (self, cod):
tc = {'GCT':'A', 'GCC':'A', 'GCA':'A', 'GCG':'A', 'TGT':'C', 'TGC':'C',
'GAT':'D', 'GAC':'D', 'GAA':'E', 'GAG':'E', 'TTT':'F', 'TTC':'F',
'GGT':'G', 'GGC':'G', 'GGA':'G', 'GGG':'G', 'CAT':'H', 'CAC':'H',
'ATA':'I', 'ATT':'I', 'ATC':'I', 'AAA':'K', 'AAG':'K', 'TTA':'L',
'TTG':'L', 'CTT':'L', 'CTC':'L', 'CTA':'L', 'CTG':'L', 'ATG':'M',
'AAT':'N', 'ACC':'N', 'CCT':'P', 'CCC':'P', 'CGA':'R', 'CGG':'R',
'AGA':'R', 'AGG':'R', 'TCT':'S', 'TCC':'S', 'TCA':'S', 'TCG':'S',
'AGT':'S', 'AGC':'S', 'ACT':'T', 'ACC':'T', 'ACA':'T', 'ACG':'T',
'GTT':'V', 'GTC':'V', 'GTA':'V', 'GTG':'V', 'TGG':'W', 'TAT':'Y',
'TAC':'Y', 'TAA':'_', 'TAG':'_', 'TGA':'_'}
cod = cod.upper ()
if cod in tc: aa = tc [cod]
else: aa = 'X' #X = erro
return (aa)

def traduzCodaoER (self,cod):


if re.search("GC.", cod): aa = "A"
elif re.search("TG[TC]", cod): aa = "C"
elif re.search("GA[TC]", cod): aa = "D"
elif re.search("GA[AG]", cod): aa = "E"
elif re.search("TT[TC]", cod): aa = "F"
elif re.search("GG.", cod): aa = "G"
elif re.search("CA[TC]", cod): aa = "H"
elif re.search("AT[TCA]", cod): aa = "I"
elif re.search("AA[AG]", cod): aa = "K"
elif re.search("TT[AG]|CT.", cod): aa = "L"
elif re.search("ATG", cod): aa = "M"
elif re.search("AA[TC]", cod): aa = "N"
elif re.search("CC.", cod): aa = "P"
elif re.search("CA[AG]", cod): aa = "Q"
elif re.search("CG.|AG[AG]", cod): aa = "R"
elif re.search("TC.|AG[TC]", cod): aa = "S"
elif re.search("AC.", cod): aa = "T"
elif re.search("GT.", cod): aa = "V"
elif re.search("TGG", cod): aa = "W"

28
elif re.search("TA[TC]", cod): aa = "Y"
elif re.search("TA[AG]|TGA", cod): aa = "_";
else: aa = None
return (aa)
def orfs (self):
if self.tipo != "dna": return None
res = []
res.append(self.traduzSeq(0))
res.append(self.traduzSeq(1))
res.append(self.traduzSeq(2))
compinv = self.compInverso()
res.append(compinv.traduzSeq(0))
res.append(compinv.traduzSeq(1))
res.append(compinv.traduzSeq(2))
return (res)

def maiorProteina (self):


if self.tipo != "protein": return None
seqAA = self.seq
protAtual = ""
maiorprot = ""
for aa in seqAA:
if aa == "_":
if len (protAtual) > len (maiorprot): maiorprot = protAtual
protAtual = ""
else:
if len (protAtual) > 0 or aa == "M": protAtual += aa
return (MySeq (maiorprot, "protein"))

def maiorProteinaER (self):


if self.tipo != "protein": return None
mos = re.finditer ("M[^_]*_", self.seq)
sizem = 0
lprot = ""
for x in mos:
ini = x.span()[0]
fin = x.span()[1]
s = fin - ini + 1

29
if s > sizem:
lprot = x.group()
sizem = s
return (MySeq (lprot, "protein"))
def todasProteinas (self):
if self.tipo != "protein": return None
seqAA = self.seq
protsAtuais = []
proteinas = []
for aa in seqAA:
if aa == "_":
if protsAtuais:
for p in protsAtuais: proteinas.append (MySeq (p, "protein"))
protsAtuais = []
else:
if aa == "M": protsAtuais.append ("")
for i in range (len (protsAtuais)): protsAtuais[i] += aa
return (proteinas)

def maiorProteinaORFs (self):


if self.tipo != "dna": return None
larg = MySeq ("", "protein")
for orf in self.orfs ():
prot = orf.maiorProteinaER ()
if len (prot.seq) > len (larg.seq): larg = prot
return (larg)

def teste():
seq_dna = input ("Sequencia:") # ATAATGATAGATAGATGAT
s1 = MySeq (seq_dna.upper ())
if s1.validaER():
print ("Sequencia valida")
print ("Transcricao: ")
s1.transcricao().printseq()
print("Complemento inverso:")
s1.compInverso().printseq()
print("Traducao: ")
s1.traduzSeq().printseq()
print("ORFs:")

30
for orf in s1.orfs(): orf.printseq()
print("Maior proteina nas ORFs:")
s1.maiorProteinaORFs().printseq()
else: print("Sequencia invalida")

Classe SubstMatrix
class SubstMatrix:

def __init__(self):
self.alphabet = ""
self.sm = {}

def loadFromFile (self, filename, sep):


f = open (filename, "r")
line = f.readline ()
tokens = line.split (sep)
ns = len (tokens)
self.alphabet = ""
for i in range (0, ns):
self.alphabet += tokens[i][0]
for i in range (0, ns):
line = f.readline ();
tokens = line.split (sep);
for j in range (0, len (tokens)):
k = self.alphabet[i] + self.alphabet[j]
self.sm[k] = int (tokens[j])
f.close()
return None

def createFromMatchPars (self, match, mismatch, alphabet):


self.alphabet = alphabet
for c1 in alphabet:
for c2 in alphabet:
if c1 == c2: self.sm[c1 + c2] = match
else: self.sm[c1 + c2] = mismatch
return None

31
def scorePair (self, c1, c2):
if c1 not in self.alphabet or c2 not in self.alphabet: return None
return (self.sm [c1 + c2])

def __getitem__(self, ij):


i, j = ij
return (self.scorePair (i, j))

def test1 ():


sm = SubstMatrix ()
sm.loadFromFile ("blosum62.mat", "\t")
print (sm.alphabet) # ARNDCQEGHILKMFPSTWYV
print (sm.scorePair ("G", "M")) # -3
print (sm.scorePair ("W", "W")) # 11
print (sm.scorePair ("A", "S")) # 1
print (sm.scorePair ("X", "X")) # None
print (sm ["G", "K"]) # -2
print (sm ["T", "T"]) # 5

def test2 ():


sm = SubstMatrix ()
sm.createFromMatchPars (3, -1, "ACGU")
print (sm.alphabet) # ACGU
print (sm.scorePair ("A", "A")) # 3
print (sm.scorePair ("A", "U")) # -1
print (sm.scorePair ("T", "T")) # None
print (sm ["G", "G"]) # 3

32
Classe MyAlign
class MyAlign:

def __init__(self, lseqs, tipo = "protein"):


self.listseqs = lseqs
self.tipo = tipo

def __len__(self): # número de colunas


return (len (self.listseqs [0]))

def __getitem__(self, n):


'''Se n for um tuplo, retorna o símbolo na sequência i e posição j'''
if type(n) is tuple and len(n) == 2:
i, j = n
return (self.listseqs[i][j])
elif type(n) is int:
return (self.listseqs[n])
return None

def __str__(self):
'''Define como se imprime o alinhamento'''
res = ""
for seq in self.listseqs:
res += "\n" + seq
return (res)

def addGap (self, seq, pos):


self.listseqs[seq] = self.listseqs[seq][:pos] + "-" + self.listseqs[seq][pos:]

33
def removeGap (self, seq, pos):
self.listseqs[seq] = self.listseqs[seq][:pos] + self.listseqs[seq][pos+1:]

def consensus (self):


cons = ""
for i in range (len (self)):
cont = {}
for k in range (len (self.listseqs)):
c = self.listseqs[k][i]
'''Cria linhas com os elementos das sequências
- Primeira linha: primeiro carater da primeira sequência
- Segunda linha: primeiro elemento da segunda sequência'''
if c in cont:
cont[c] = cont[c] + 1
#Se os elementos das duas sequências forem iguais, imprime 2
else:
cont[c] = 1
#Se os elementos forem diferentes, imprime 1
'''cont = {'elemento da primeira sequencia': cont [c]'''

maximum = 0
cmax = None
for ke in cont.keys():
# ke: A,| T, A,| -, G,| A,| T, -,| A, -|
# cont.keys (): pares de elementos das sequencias'''

if ke != "-" and cont[ke] > maximum:


maximum = cont[ke]
cmax = ke
# cont [ke] = 1 se cont.keys sao diferentes
# cont [ke] = 2 se cont.keys sao iguais

cons = cons + cmax


return (cons) # AAGATA

34
def column (self, indice):
'''Lista com simbolos da coluna indice'''
res = []
for k in range (len (self.listseqs)):
res.append (self.listseqs[k][indice])
return (res)
def scoreColumn (self, charsCol, alignpars):
sc = 0;
for i in range (len (charsCol)):
for j in range (i + 1, len (charsCol)):
if charsCol[i] != '-' or charsCol[j] != '-':
sc += alignpars.scorePos (charsCol[i], charsCol[j])
return (sc)

if __name__ == "__main__":
alig = MyAlign (["ATGA-A","AA-AT-"], "dna")
print (alig)
# ATGA-A
# AA-AT-
print (len (alig)) # 6
print (alig.column (2)) # ['G', '-']
print (alig [1, 1]) # A
print (alig [0, 2]) # G
print (alig.consensus()) # AAGATA

from Class_AlignSeq import AlignSeq


from Class_SubstMatrix import SubstMatrix
sm = SubstMatrix ()
sm.loadFromFile ("blosum62.mat", "\t")
aseq = AlignSeq (sm, -2)
alin = MyAlign (["-RADN", "ARCD-", "AR-DN"], "protein")
print (alin)
# -RADN
# ARCD-
# AR-DN

35
BioPython

Conjunto de recursos escritos na linguagem Python para a abordagem


de problemas Bioinformáticos. É um repositório de software livre que
inclui módulos, scripts e a respetica documentação. As suas principais
funcionalidades são:
 Parsing/ Análise de ficheiros em formatos importantes para a
bioinformática: FASTA, GenBank, PubMed, SwissProt, Unigene
 Interface com ferramentas e bases de dados bioinformáticas. Através
da Web / instalações locais: Blast, Entrez, PubMed, SwissProt,
Prosite, ClustalW
 Implementação de classes para manipulação de sequências e sua
anotação (features), bem como operações de processamento sobre
sequências (tradução, transcrição, motifs, etc.)
 Implementação de algoritmos de alinhamento de sequências e
tratamento de matrizes de scoring
 Ferramentas básicas de mineração de dados
 Interface com o BioSQL, um esquema de manipulação de bases de dados
de sequências

36
Alfabetos
Um dos principais objectos no BioPython é o objecto Seq. Este
permite guardar sequências e trabalhar sobre elas. Os objectos desta
classe são imutáveis.
O objecto alfabeto é o que faz o objecto Seq mais do que uma string.
Vamos usar os alfabetos IUPAC para trabalhar com o ADN, RNA e Proteínas.
Alfabeto para ADN: my_seq = Seq (‘sequência’, IUPAC.unambiguous_dna)
Alfabeto para Proteínas: my_seq = Seq (‘sequência’, IUPAC.protein)

from Bio.Seq import Seq


from Bio.Alphabet import IUPAC

'''Definição de alfabeto para ADN'''


my_seq = Seq ('AGTACACTGGT', IUPAC.unambiguous_dna) # cria sequência
print (my_seq) # AGTACACTGGT
print (my_seq.alphabet) #IUPACUnambiguousDNA()

'''Definição de alfabeto para Proteínas'''


my_prot = Seq ('AGTACACTGGT', IUPAC.protein)
print (my_prot) # AGTACACTGGT
print (my_prot.alphabet) # IUPACProtein()

O Bio.Alphabet fornece as definições básicas de proteínas, ADN e RNA, mas


também fornece a habilidade de alterar as definições básicas. Por exemplo, para
as proteínas, existe a classe IUPACProtein, mas também existe a classe
ExtendedIUPACProtein para os elementos adicionais, “U” (ou “Sec” para
selenocisteína) e “O” (ou “Pyl” para pyrrolisina), mais os símbolos ambíguos, B
(ou “Asx” para asparagina) e “X” (ou “Xxx” para aminoácido desconhecido).

37
print (IUPAC.unambiguous_dna.letters) # GATC
print (IUPAC.ambiguous_dna.letters) # GATCRYWSMKHBVDN
print (IUPAC.IUPACProtein.letters) # ACDEFGHIKLMNPQRSTVWY
print (IUPAC.ExtendedIUPACProtein.letters) # ACDEFGHIKLMNPQRSTVWYBXZJUO

Manipulação de sequências
from Bio.Seq import Seq
from Bio.Alphabet import IUPAC
from Bio.Alphabet import generic_nucleotide

'''Iteração'''
my_seq = Seq ('GATCG', IUPAC.unambiguous_dna)
for i in my_seq:
print (i) # imprime uma letra por linha

for index, letter in enumerate (my_seq):


print (index, letter) # imprime uma letra, e correspondente índice, por linha

'''Funções Semelhantes às strings'''


my_seq = Seq ('GATCG', IUPAC.unambiguous_dna)
len (my_seq) # 5
my_seq [2] # 'T'
my_seq.count ('G') # 2
my_seq.lower () # Seq ('gatcg', DNAAlphabet())
'GATC' in my_seq # True
my_seq.find ('ATC') # 1

my_seq = Seq ('GATCGATGGGCCTATATAGGATCG', IUPAC.unambiguous_dna)


my_seq [4:12] # Seq ('GATGGGCC', IUPACUnambiguousDNA())
my_seq [0::3] # Seq ('GCTGTAGT', IUPACUnambiguousDNA())

'''Concatenação de sequências'''
# Mesmo alfabeto
seq1 = Seq ('EVRNAK', IUPAC.protein)
seq2 = Seq ('GHERW', IUPAC.protein)
seq1 + seq2 # Seq ('EVRNAKGHERW', IUPACprotein())

38
# Alfabetos compatíveis
nuc_seq = Seq ('GATCGATGC', generic_nucleotide)
dna_seq = Seq ('ACGT', IUPAC.unambiguous_dna)
nuc_seq + dna_seq # Seq ('GATCGATGCACGT', generic_nucleotide)

Complemento (ADN)

my_seq = Seq (‘sequência’, IUPAC.unambiguous_dna)


Complemento: my_seq.complement ()
Complemento Inverso: my_seq.reverse_complement ()

from Bio.Seq import Seq


from Bio.Alphabet import IUPAC

coding_dna = Seq ('ATGGCCATTGTAATGGGCCGC', IUPAC.unambiguous_dna)


template_dna = coding_dna.reverse_complement()
# Seq ('GCGGCCCATTACAATGGCCAT', IUPACUnambiguousDNA ())

Transcrição e Tradução (ADN)

Transcrição: mRNA = my_seq.transcribe ()


Tradução: Proteina = my_seq.translate ()

menssenger_rna = coding_dna.transcribe ()
# Seq ('AUGGCCAUUGUAAUGGGCCGC', IUPACUnambiguousRNA())

coding_dna.translate () # Seq ('MAIVMGR', IUPACProtein ())

coding_dna = Seq ('ATGGCCATTGTAATGGGCCGCTGAAAGGGTGCCCGATAG", IUPAC.unambiguous_dna)

coding_dna.translate () # Seq ('MAIVMGR*KGAR*',HasStopCodon(IUPACProtein (),'*'))


coding_dna.translate (to_stop = True) # Seq ('MAIVMGR', IUPACProtein ())

39
coding_dna.translate (table = 'Vertebrate Mitochondrial')
# Seq ('MAIVMGRWKGAR*, HasStopCodon (IUPACProtein (), '*'))

Tradução (RNA)

my_seq = Seq (‘sequência’, IUPAC.unambiguous_rna)


Tradução: Proteina = my_seq.translate ()
Cadeia de AND original: ADN = my_seq.back_trancribe ()

rna_seq = Seq ('CGUUUAACU', IUPAC.unambiguous_rna)


rna_seq.translate () # Seq ('RLT', IUPACProtein ())
rna_seq.back_transcribe () # Seq ('CGTTTAACT', IUPACUnanbiguousDNA ())

Tabelas de Tradução
from Bio.Data import CodonTable

standard_table = CodonTable.unambiguous_dna_by_name ['Standard']


mito_table = CodonTable.unambiguous_dna_by_name ['Vertebrate Mitochondrial']

40
mito_table.stop_codons # ['TAA', 'TAG', 'AGA', 'AGG'] -> codões stop
mito_table.start_codons # ['ATT', 'ATC', 'ATA', 'ATG', 'GTG'] -> codões start
mito_table.forward_table ['ACG'] # T -> aminoácido correspondente

Anotação de sequências: objecto SeqRecord


Permite associar às sequências biológicas aspetos relacionados com a
sua anotação, isto é, características das sequências e das entidades que
estas representam.
Objeto SeqRecord é o tipo base para o I/O de sequências (a tratar
mais adiante).
Um objeto SeqRecord tem os seguintes campos:
 seq: a sequência propriamente dita
 id: identificador da sequência
 name: nome da sequência
 description: descrição
 letter_annotations: anotações por letra (posição) da sequência
 annotations: anotações globais da sequência (não estruturadas)
 features: anotações estruturadas da sequência (lista de
objetos SeqFeature)
 dbxrefs: referências a bases de dados (externas)

from Bio.SeqRecord import SeqRecord

'''Criação de um SeqRecord manualmente'''


seq = Seq ('ATGAATGATAGCTGAT')
seRec = SeqRecord (seq)
seqRec.id # '<unknown id>'
seqRec.id = 'AB12345'
seqRec.description = 'Minha Sequência'
seqRec.seq # Seq (ATGAATGATAGCTGAT', Alphabet ())
seqRec.annotations ['role'] = 'unkwon'
seqRec.letter_annotations ['qualidade'] = [40, 40, 38, 30]

41
Formatos de sequências: objeto SeqIO
O objeto SeqIO fornece um conjunto de interfaces para trabalhar com
vários formatos de sequências biológicas.
As funções disponíveis permitem ler e escrever ficheiros com
sequências em diversos formatos distintos. Normalmente, ao ler as
sequências o resultado será um objeto SeqIO, ou um iterador que retorna
estes objetos se o ficheiro tiver mais do que uma sequência.
record = SeqIO.read (‘ficheiro’, ‘formato’)
record.função

from Bio import SeqIO

Função read: Ficheiro Fasta


record = SeqIO.read ('NC_005816.fna', 'fasta')

record
'''SeqRecord (seq = Seq (’TGTAACGAACGGTGCAATAGTGATCCACACCCAACGCCTGA...CTG’, Sin-
gleLetterAlphabet ()), id = ’gi|45478711|ref|NC_005816.1|’, name= ’gi|45478711|
ref|NC_005816.1|’, description = ’gi|45478711|ref|NC_005816.1| Yersinia pestis
biovar Microtus ... sequence’, dbxrefs = [])'''

record.seq
'''Seq (’TGTAACGAACGGTGCAATAGTGATCCACACCCAACGCCTGAAATCAGATCCAGG...CTG’, Sin-
gleLetterAlphabet ())''' -> Default: alfabeto genérico

record.id # gi|45478711|ref|NC_005816.1| -> 1ª palavra da linha do titulo

record.name # gi|45478711|ref|NC_005816.1| -> 1ª palavra da linha do titulo

record.description
'''gi|45478711|ref|NC_005816.1| Yersinia pestis biovar Microtus ... pPCP1,
complete sequence''' -> linha do titulo

42
# Não existe mais nenhum dos outros campos:
record.dbxrefs # []
record.annotations # {}
record.letter_annotations # {}
record.features # []
Função read: Ficheiro Genbank
record = SeqIO.read ("NC_005816.gb", "genbank")

record
'''SeqRecord (seq = Seq (’TGTAACGAACGGTGCAATAGTGATCCACACCCAACGCCTGA...CTG’, IU-
PACAmbiguousDNA ()), id = ’NC_005816.1’, name = ’NC_005816’, description =
’Yersinia pestis biovar Microtus str. 91001 plasmid pPCP1, complete sequence.’,
dbxrefs = [’Project:10638’])''' -> Alfabeto definido automaticamente

record.seq
# Seq (’TGTAACGAACGGTGCAATAGTGATCCACACCCAACGCCTGAAATC...CTG’,IUPACAmbiguousDNA())

record.id # NC_005816.1 -> LOCUS + sufixo da versão

record.name # NC_005816 -> LOCUS

record.description # Yersinia pestis biovar Microtus str. 91001 plasmid pPCP1,


complete sequence -> DEFENITION

len (record.annotations) # 11
record.annotations ["source"] # ’Yersinia pestis biovar Microtus str. 91001’
record.dbxrefs # [’Project: 10638’] -> PROJECT e DBLINK
len (record.features) # 29 -> tabela de features (ex: genes, CDS)

43
Parse
É usado para ler informação de sequências como objectos SeqRecord e
é normalmente usado num loop. Esta função tem dois argumentos:
 Handle: é o primeiro argumento, usado para ler a informação.
Tipicamente é um ficheiro aberto para leitura, mas também pode
ser o output de uma linha de comando do programa, ou informação
downloaded da net.
 Lower case string: é o segundo argumento e especifica o
formato da sequência. Os formatos suportados podem ser
encontrados em: http://biopython.org/wiki/SeqIO
 Alfabeto: argumento opcional usado para especificar o
alfabeto. É útil para os ficheiros em formatos FASTA que por
default usam o alfabeto genérico.

from Bio import SeqIO

for seq_record in SeqIO.parse ('ls_orchid.fasta', 'fasta'):


print (seq_record.id)
print (seq_record.seq)
print (len (seq_record))

all_species = []
for seq_record in SeqIO.parse ('ls_orchid.gbk', 'genbank'):
print (seq_record.id)
print (seq_record.seq)
print (len (seq_record))
all_species.append (seq_record.annotations ['organism'])
print (all_species)

44
Em vez de se usar o loop for, pode-se usar a função next () num
iterador para passar ordenadamente pelas entradas:
record_iterator = SeqIO.parse ('ls_orchid.gbk', 'genbank')
first_record = next (record_iterator)
print (first_record)
print (first_record.annotations ['source'])

second_record = next (record_iterator)


print (second_record)

Normalmente é necessário acesso aos records sem ordem específica.


Para isso, utiliza-se a função list () para criar uma lista de todos os
records.
records = list (SeqIO.parse ("ls_orchid.gbk", "genbank"))
print ("Found %i records" % len (records)) # Found 94 records
print ("The last record")
last_record = records[-1] # Z78439.1
print (last_record.id)
print (len (last_record)) # 592
print (repr (last_record.seq))
# Seq ('CATTGTTGAGATCACATAATAATTGATCGAGTTAATCTGGAGGATCTGTTTACT...GCC', IUPACAm-
biguousDNA ())

print ("The first record")


first_record = records[0] # Z78533.1
print (first_record.id)
print (len (first_record)) # 740
print (repr (first_record.seq))
# Seq ('CGTAACAAGGTTTCCGTAGGTGAACCTGCGGAAGGATCATTGATGAGACCGTGG...CGC', IUPACAm-
biguousDNA ())

45
Sequências retiradas da net
Como já vimos anteriormente a sequência (handle) usada pode ser
retirada da net usando a interface Entrez EFetch.
Se o handle for uma só sequência, usar a função Bio.SeqIO.read ().
Se o handle tiver vários records, usar a função Bio.SeqIO.parse ().

from Bio import SeqIO


from Bio import Entrez

Entrez.email = '...@example.com'
handle = Entrez.efetch (db ='nucleotide', rettype ='fasta', retmode ='text', id
='6273291') # se o formato usado for o genbank: rettype = ‘gb’
seq_record = SeqIO.read (handle, 'fasta')
handle.close ()
print (seq_record.id, 'com', len (seq_record.features), 'features') # AF191665.1
com 0 features

Entrez.email = '...@example.com'
handle = Entrez.efetch (db = 'nucleotide', rettype = 'gb', retmode = 'text', id =
'6273291, 6273290, 6273289')
for seq_record in SeqIO.parse (handle, 'gb'):
print (seq_record.id, seq_record.description [:100], '...')
print ('Tamanho da sequência:', len (seq_record))
print (len (seq_record.features), 'features')
print ('from:', seq_record.annotations ['source'])
handle.close ()

46
Escrita de sequências
Falou-se de Bio.SeqIO.parse () para o input de sequências, agora
vai-se falar de Bio.SeqIO.write () para o output de sequências (escrever
ficheiros).
Esta função tem três argumentos:
 Lista de objectos SeqRecord: representam as sequências e as
anotações que se pretende escrever
 Handle ou nome do ficheiro
 Formato (string)

from Bio.Seq import Seq


from Bio.SeqRecord import SeqRecord
from Bio.Alphabet import generic_protein
from Bio import SeqIO

s1 = SeqRecord (Seq ("MMYQQGCFAGGTV", generic_protein),


id = "gi|14150838|gb|AAK54648.1|AF376133_1",
description="chalcone synthase [Cucumis sativus]")

s2 = SeqRecord (Seq ("MVTVEEFRRAQ", generic_protein),


id="gi|13919613|gb|AAK33142.1|",
description="chalcone synthase [Fragaria vesca]")

lr = [s1, s2]
SeqIO.write(lr, 'ex.faa', 'fasta') # cria um ficheiro fasta de nome ex.faa que
contém as sequências s1 e s2 e respectiva informação

47
Conversão de Formatos
A função Bio.Seq.write () também aceita iteradores, como o que
obtemos de Bio.SeqIO.parse (), isto permite nos converter ficheiros
combinando estas duas funções.

from Bio import SeqIO

records = SeqIO.parse ("ls_orchid.gbk", "genbank")


count = SeqIO.write (records, "my_example.fasta", "fasta")
print ("Convertidos %i registos" % count )

A função Bio.Seq.convert () permite fazer a conversão de ficheiros,


mas atenção que se o ficheiro output já existe, esta função vai
sobrescrever a informação lá contida.

count = SeqIO.convert ("ls_orchid.gbk", "genbank", "my_example.fasta", "fasta")


print ("Converted %i records" % count)

48
Objetos SeqFeature
Permite guardar informação sobre features (anotações) das sequências
de forma estruturada.
Estrutura baseada no formato GenBank / EMBL, na sua tabela de
features.
Principais atributos de um objeto SeqFeature:
 location: localização da feature na sequência (pode ser uma
posição, um intervalo, etc.)
 type: (string) diz o tipo da feature, ex.: ‘gene’, ‘CDS’
 qualifiers: informação adicional (dicionário)

from Bio import SeqFeature

Localização
 ExactPosition: é um número que representa a posição exata na sequência
 BeforePosition: representa uma posição imprecisa que ocorre antes de um
local específico. Ex.: `<13', significa que a posição real está localizada
numa posição menor que 13
 AfterPosition: representa uma posição imprecisa que ocorre depois de um
local específico. Ex.: `>13', significa que a posição real está localizada
numa posição menor que 13
 OneOfPosition: existem várias possibilidades para a posição

start_pos = SeqFeature.AfterPosition (5) -> Posição Inicial


end_pos = SeqFeature.BetweenPosition (9, left = 8, right = 9) # é necessário
explicitar que posição deverá ser usada para o slicing. A posição inicial é
geralmente o valor seguinte mais baixo (left), enquanto que, a posição final é
geralmente o valor acima (right) -> Posição Final

my_location = SeqFeature.FeatureLocation (start_pos, end_pos)


print (my_location) # [>5:(8^9)]
int (my_location.start) # 5
int (my_location.end) # 9

49
A partir de uma sequência mãe e tendo a localização da feature pode-
se extrair a sequência da feature.

from Bio.SeqFeature import SeqFeature, FeatureLocation


from Bio.Seq import Seq

example_parent = Seq ('ACCGAGACGGCAAAGGCTAGCATAGGTATGAGACTT')


example_feature = SeqFeature (FeatureLocation (5, 18), type = 'gene', strand =-1)
# strand = -1, faz o complemento da sequência inversa

feature_seq = example_feature.extract (example_parent)


print (feature_seq) # AGCCTTTGCCGTC

Features: Ficheiro Genbank


from Bio import SeqIO
record = SeqIO.read ("NC_005816.gb", "genbank")

for feat in record.features:


#lista todas as features e devidos atributos
print (feat)

featcds = []
for i in range (len (record.features)):
if record.features[i].type == 'CDS':
# Identifica features do tipo CDS
featcds.append (i)
for k in featcds:
print (record.features[k].location) # Identifica a sua localização
print (record.features[k].extract (record.seq), '\n') # Identifica a
subsequência do ADN afetada pela feature

50
Alinhamento Múltiplo de Sequências

O Alinhamento Múltiplo (AM) de sequências é o procedimento de


comparação de mais do que duas sequências, procurando séries de caracteres
individuais que se encontrem na mesma ordem. O alinhamento múltiplo
permite:
 Identificar zonas conservadas de proteínas (prováveis zonas ativas)
e zonas de mutação
 Prever função/estrutura de proteínas
 Derivação de informação filogenética a partir das sequências
 Projetos de sequenciação de genomas: sequenciam-se vários segmentos
cuja ordem é desconhecida e usa-se o AM para dar a ordem a estes
segmentos

O alinhamento múltiplo pode ser feito através de programação


dinâmica ou através de algoritmos de aproximação.
A Programação Dinâmica é um método exato, mas só pode ser usado para
um número limitado de sequências e para sequências de tamanho reduzido. É
uma extensão do algoritmo para 2 sequências.
Os Algoritmos de Aproximação são métodos heurísticos que não
garantem solução óptima. Podem ser subdivididos em:
 Progressivos: iniciam com 2 sequências e vão adicionando as
restantes
 Iterativos: consideram um alinhamento inicial que vai sendo
melhorado
 Híbridos: podem usar outros tipos de informação (e.g.
Estrutura 3D)

51
Programação Dinâmica
A matriz de mérito (S) passa a ser N-dimensional:

Diagonal (1) -> sem gaps

Diagonais da face (2) -> 1 gap

Arestas (3) -> 2 gaps

1
2 2

Exemplo de alinhamento de
três sequências

52
Algoritmos Progressivos
Inicialmente calculam-se os alinhamentos para todos os pares de
sequências possíveis. Constrói-se uma árvore filogenética de acordo com o
mérito dos alinhamentos anteriores. Escolhem-se as duas sequências mais
similares e faz-se o seu alinhamento. Seguindo a estrutura da árvore vão
se adicionando as restantes sequências ao alinhamento múltiplo.
Um exemplo de um algoritmo progressivo eficiente é o CLUSTAL-W.
Uma das etapas de qualquer algoritmo progressivo é a combinação de
(pelo menos) dois alinhamentos num único. Existem várias alternativas para
realizar este processo:
 Calcular consensos dos alinhamentos e alinhar estes consensos
 Adaptar a PD para trabalhar com matrizes de ocorrência/perifis
 Ter uma sequência base em todos os MAs e basear a combinação
nas posições dessa sequência.

from Class_MyAlign import MyAlign


from Class_MySeq import MySeq
from Class_AlignSeq import AlignSeq
from Class_SubstMatrix import SubstMatrix

class MultipleAlign (object):


def __init__(self, seqs, alignseq):
self.seqs = seqs # lista de sequencias a alinhar
self.alignpars = alignseq # parâmetros do alinhamento: sm e g

def scoreColumn (self, charsCol):


sc = 0;
for i in range (len (charsCol)):
for j in range (i + 1, len (charsCol)):
if charsCol[i] != '-' or charsCol[j] != '-':
sc += self.alignpars.scorePos (charsCol[i], charsCol[j])
return (sc)

53
def scoreSP (self, alinhamento):
sp = 0
ncols = len (alinhamento[0])
for j in range (ncols):
charsCol = alinhamento.column (j)
scoreCol = self.scoreColumn (charsCol)
sp += scoreCol
return sp

def addSeqAlignment (self, alignment, seq):


'''Adiciona uma nova sequência a um alinhamento existente (fazendo o
consenso do alinhamento)'''
res = []
for i in range (len (alignment.listseqs) + 1):
res.append ("") # cria alinhamento vazio
cons = MySeq (alignment.consensus (), alignment.tipo)
# Consenso do alinhamento anterior

self.alignpars.needlemanWunsch (cons, seq)


# Alinha o consenso com a nova sequência

align2 = self.alignpars.recoverAlignment()

# Cria AM incluindo nova sequência


orig = 0
for i in range (len (align2)):
if align2 [0, i] == '-':
for k in range (len (alignment.listseqs)):
res[k] += "-"
else:
for k in range (len (alignment.listseqs)):
res[k] += alignment [k, orig]
orig += 1
res [len (alignment.listseqs)] = align2.listseqs[1]
return MyAlign (res, alignment.tipo)

54
def alignConsensus (self):
'''Alinha as duas primeiras sequências da lista. Depois, adiciona uma a
uma as restantes sequências com a função addSeqAlignment'''
self.alignpars.needlemanWunsch (self.seqs[0], self.seqs[1])
res = self.alignpars.recoverAlignment ()
for i in range (2, len (self.seqs)):
res = self.addSeqAlignment (res, self.seqs[i])
return res

def test ():


s1 = MySeq ("PHWAS", "protein")
s2 = MySeq ("HWASW", "protein")
s3 = MySeq ("HPHWA", "protein")
sm = SubstMatrix ()
sm.loadFromFile ("blosum62.mat", "\t")
aseq = AlignSeq (sm, -8)
ma = MultipleAlign ([s1, s2, s3], aseq)
alinm = ma.alignConsensus ()
print (ma.scoreSP (alinm)) # 16
print (alinm)

# -PHWAS-
# --HWASW
# HPHWA--

CLUSTAL-W
Numa primeira fase faz o alinhamento de pares de sequências usando
um algoritmo de PD, para o cálculo da similaridade entre cada par.
Similaridade = nº de carateres iguais/tamanho da sequência * 100

Na segunda fase o ClustalW cálcula uma árvore


filogenética baseada na matriz de distâncias anterior, que
irá guiar a ordem do alinhamento.

Na terceira fase, seguindo a ordem definida pela árvore (partindo do


par de sequências mais próximas), vão-se adicionando as sequências ao

55
alinhamento (alinhando sequências com os alinhamentos prévios – profiles).
Gaps são introduzidos sempre que necessário.

BLAST com Biopython

O BioPython tem interfaces com o BLAST que permitem:


 Preparar queries ao Blast, definindo os parâmetros relevantes
 Executar queries
 Tratar os resultados de queries, quer corridas usando
BioPython quer diretamente executadas pelo utilizador

Estas funcionalidades são extremamente úteis para automatizar estes


procedimentos e tratar quantidades grandes de dados.

Executar Blast pela Web


Para se executar o BLAST pela web no Biopython utiliza-se a função
qblast() do módulo Bio.Blast.NCBIWWW, com três parâmetros não opcionais:
 Programa a usar (string): “blastn”, “blastp”, “blastx”,
“tblast”, “tblastx”)
 Base de dados a procurar (string): “nt”, “nr”,... – lista
completa no site do Blast
 Sequência query: pode ser a própria sequência, a sequência em
formato Fasta, ou um identificador (e.g. GI)
 Existem ainda vários parâmetros opcionais que permitem
definir: o tipo de output (XML por omissão), o e-value, a
matriz de substituição a usar, gap penalties, …

from Bio.Blast import NCBIWWW


from Bio import SeqIO

# Correr BLASTN com sequência em formato FASTA (base de dados nt)


record = SeqIO.read (open ("NC_005816.fasta"), format = "fasta")
result_handle = NCBIWWW.qblast ("blastn", "nt", record.format ("fasta"))

# Guardar o resultado
save_file = open ("my_blast.xml", "w")
save_file.write (result_handle.read ())

56
save_file.close ()
result_handle.close ()

Parsing dos resultados do Blast


Os parsers do BioPython funcionam garantidamente apenas com o
formato de output XML; existe um parser para formato texto mas não
funciona em todos os casos dadas as alterações aos formatos de saída do
Blast.
Os parsers do Blast funcionam com qualquer resultado de Blast quer
corrido na web, quer com programas locais; quer usando o BioPython com
qblast, quer executando directamente.
O primeiro passo será obter o handle com os resultados, dependendo
da forma como se corre:

# Usanso qblast (neste caso para query por GI com blastn)


from Bio.Blast import NCBIWWW
result_handle = NCBIWWW.qblast ("blastn", "nt", "8332116")

# Lendo resultados de um ficheiro


result_handle = open ("my_blast.xml")

Podemos então processar os resultados, usando as funções read (),


para uma query, ou parse () para múltiplas queries.

from Bio.Blast import NCBIXML


blast_record = NCBIXML.read (open ("my_blast.xml"))

from Bio.Blast import NCBIXML


blast_records = NCBIXML.parse (open ("my_blast.xml"))
for blast_record in blast_records:
# faz alguma coisa com o record …

57
Classe BlastRecord
Um objeto BlastRecord contém toda a informação que se pode querer
retirar do resultado de um Blast, incluindo: todos os parâmetros usados e
os resultados completos. Os resultados de cada alinhamento estão
organizados pelos seus HSPs.

E_VALUE_THRESH = 0.05
for blast_record in blast_records:
# record: matriz de substituição, gap penalties, database e alignment
for alignment in blast_record.alignments:
# alignment: accession, hit_id, hit_def, alignment.length, hsps
for hsp in alignment.hsps:
# hsp: expext (e-value), score, align_length, query, match, sbjct
if hsp.expect < E_VALUE_THRESH:
print ('****Alignment****’)
print ('sequence:', alignment.title)
print ('length:', alignment.length)
print ('e value:', hsp.expect)
print (hsp.query [0:75] + '...' )
print (hsp.match [0:75] + '...' )
print (hsp.sbjct [0:75] + '...' )

58
Representação de Alinhamentos
O objeto MultipleSeqAlignment contém objetos e funções que permitem
lidar com alinhamentos (com duas ou mais sequências); vem substituir o
objecto Align que está deprecated.
Estes objetos são usados para guardar a estrutura dos alinhamentos e
não métodos para a sua criação.

from Bio import Alphabet


from Bio.SeqRecord import SeqRecord
from Bio.Align import MultipleSeqAlignment
from Bio.Alphabet import IUPAC
from Bio.Seq import Seq

seq1 = 'MHQAIFIYQIGYPLKSGTIQSIRSPEYDNW'
seq2 = 'MH--IFIYQIGYALKSGYIQSIRSPEY-NW'

seqr1 = SeqRecord (Seq (seq1, Alphabet.Gapped (IUPAC.protein)), id = "seq1")


seqr2 = SeqRecord (Seq (seq2, Alphabet.Gapped (IUPAC.protein)), id = "seq2")
alin = MultipleSeqAlignment ([seqr1, seqr2])

print (alin.get_alignment_length ())


# 30 -> As sequências têm de ter o mesmo comprimento

print (alin[:, 2]) # Q- -> coluna 3 de todas as sequências

print (alin)
'''IUPACProtein() alignment with 2 rows and 30 columns
MHQAIFIYQIGYPLKSGTIQSIRSPEYDNW seq1
MH--IFIYQIGYALKSGYIQSIRSPEY-NW seq2'''

59
Objeto AlignIO
O objeto AlignIO funciona para os alinhamentos de forma semelhante
ao SeqIO para sequências, isto é, permite ler e escrever alinhamentos em
diversos formatos

Para a leitura de alinhamento existem duas funções, tendo ambas como


parâmetros obrigatórios o nome de ficheiro (ou handle) e uma string a
especificar o formato:
 Bio.AlignIO.read (): lê um único alinhamento; retorna um objeto
MultipleSeqAlignment
 Bio.AlignIO.parse (): lê um conjunto de alinhamentos, retornando um
iterador

from Bio import AlignIO


alignment = AlignIO.read ("PF05371_seed.sth", "stockholm")
print ("Tam. alinhamento %i" % alignment.get_alignment_length()) #Tam. alinhamento
52
print (alignment) # sumário do alinhamento
'''SingleLetterAlphabet() alignment with 7 rows and 52 columns
AEPNAATNYATEAMDSLKTQAIDLISQTWPVVTT...SKA COATB_BPIKE/30-81
AEPNAATNYATEAMDSLKTQAIDLISQTWPVVTT...SRA Q9T0Q8_BPIKE/1-52
DGTSTATSYATEAMNSLKTQATDLIDQTWPVVTS...SKA COATB_BPI22/32-83
AEGDDP---AKAAFNSLQASATEYIGYAWAMVV...SKA COATB_BPM13/24-72
AEGDDP---AKAAFDSLQASATEYIGYAWAMVV...SKA COATB_BPZJ2/1-49
AEGDDP---AKAAFDSLQASATEYIGYAWAMVV...SKA Q9T0Q9_BPFD/1-49
FAADDATSQAKAAFDSLTAQATEMSGYAWALV...SRA COATB_BPIF1/22-73'''

for record in alignment:


print ("%s - %s" % (record.seq, record.id))
'''AEGDDP---AKAAFDSLQASATEYIGYAWAMVVVIVGATIGIKLFKKFTSKA - Q9T0Q9_BPFD/1-49
AEGDDP---AKAAFNSLQASATEYIGYAWAMVVVIVGATIGIKLFKKFTSKA - J7I0P6_BPM13/24-72
AEGDDP---AKAAFDSLQASATEYIGYAWAMVVVIVGATIGIKLFKKFASKA - CAPSD_BPZJ2/1-49
FAADDATSQAKAAFDSLTAQATEMSGYAWALVVLVVGATVGIKLFKKFVSRA - CAPSD_BPIF1/22-73
AEPNAATNYATEAMDSLKTQAIDLISQTWPVVTTVVVAGLVIKLFKKFVSRA - Q9T0Q8_BPIKE/1-52
DGTSTATSYATEAMNSLKTQATDLIDQTWPVVTSVAVAGLAIRLFKKFSSKA - CAPSD_BPI22/32-83

60
AEPNAATNYATEAMDSLKTQAIDLISQTWPVVTTVVVAGLVIRLFKKFSSKA - CAPSD_BPIKE/30-81'''

for record in alignment:


if record.dbxrefs:
print (record.id, record.dbxrefs)
'''Q9T0Q9_BPFD/1-49 ['PDB; 1NH4 A; 6-49;']
CAPSD_BPIF1/22-73 ['PDB; 1IFK A; 1-50;']
CAPSD_BPIKE/30-81 ['PDB; 1IFL A; 1-52;']'''

alignments = AlignIO.parse ("resampled.phy", "phylip")


for alignment in alignments:
print (alignment)
'''SingleLetterAlphabet() alignment with 5 rows and 6 columns
AAACCA Alpha
AAACCC Beta
ACCCCA Gamma
CCCAAC Delta
CCCAAA Epsilon'''

alignments = list (AlignIO.parse ("resampled.phy", "phylip"))


for record in alignments:
last_align = record[-1]
print (last_align)
'''ID: Epsilon
Name: Epsilon
Description: Epsilon
Number of features: 0
Seq ('CCAAAC', SingleLetterAlphabet())'''

first_align = record[0]
print (first_align)
'''ID: Alpha
Name: Alpha
Description: Alpha
Number of features: 0

61
Seq ('AACAAC', SingleLetterAlphabet())'''

A função Bio.AlignIO.write() permite escrever alinhamentos em vários


formatos, sendo necessários como argumentos uma lista com objetos
MultipleSeqAlignment, o nome do ficheiro (ou handle) e o seu formato
(string).

from Bio.Alphabet import generic_dna


from Bio.Seq import Seq
from Bio.SeqRecord import SeqRecord
from Bio.Align import MultipleSeqAlignment

align1 = MultipleSeqAlignment ([SeqRecord (Seq ("ACTGCTAGC", generic_dna),


id="A"), SeqRecord (Seq ("ACT-CTAGC", generic_dna), id = "B"),
SeqRecord (Seq ("ACTGCTAGD", generic_dna), id = "C"),])

align2 = MultipleSeqAlignment ([SeqRecord (Seq ("TCAGC-AG", generic_dna),


id="D"), SeqRecord (Seq ("ACAGCTAG", generic_dna), id = "E"),
SeqRecord (Seq ("TCAGCTAG", generic_dna), id = "F"),])

my_alignments = [align1, align2]

from Bio import AlignIO


AlignIO.write (my_alignments, "my_example.phy", "phylip")
'''3 9
A ACTGCTAGC
B ACT-CTAGC...
3 8
D TCAGC-AG...'''

AlignIO.write (my_alignments, "my_example.sth", "stockholm")


'''# STOCKHOLM 1.0
#=GF SQ 3
A ACTGCTAGC
#=GS A AC A
#=GS A DE <unknown description>...
//
# STOCKHOLM 1.0
#=GF SQ 3
D TCAGC-AG
#=GS D AC D
#=GS D DE <unknown description>... '''

62
AlignIO.write (my_alignments, "my_example.faa", "fasta")
'''>A <unknown description>
ACTGCTAGC...
>F <unknown description>
TCAGCTAG'''
Conversão de Formatos
from Bio import AlignIO
count = AlignIO.convert ("PF05371_seed.sth", "stockholm", "PF05371_seed.aln", "clustal")
print ("Convertidos %i alinhamentos" % count )

ou usa-se Bio.AlignIO.read(), quando se sabe que no ficheiro só existe um


alinhamento, e Bio.AlignIO.write()

alignment = AlignIO.read ("PF05371_seed.sth", "stockholm")


AlignIO.write ([alignment], "PF05371_seed.aln", "clustal")

ou usa-se Bio.AlignIO.parse(), quando no ficheiro existem vários


alinhamento, e Bio.AlignIO.write()

alignment = AlignIO.parse ("PF05371_seed.sth", "stockholm")


AlignIO.write ([alignment], "PF05371_seed.aln", "clustal")

63
Manipulação dos Alinhamentos
alignment = AlignIO.read ("Ficheiro", "Formato")
print (alignment [sequências : colunas]

alignment = AlignIO.read ("PF05371_seed.sth", "stockholm")


print (alignment)
'''SingleLetterAlphabet() alignment with 7 rows and 52 columns
AEPNAATNYATEAMDSLKTQAIDLISQTWPVVTT...SKA COATB_BPIKE/30-81
AEPNAATNYATEAMDSLKTQAIDLISQTWPVVTT...SRA Q9T0Q8_BPIKE/1-52
DGTSTATSYATEAMNSLKTQATDLIDQTWPVVTS...SKA COATB_BPI22/32-83
AEGDDP---AKAAFNSLQASATEYIGYAWAMVV...SKA COATB_BPM13/24-72
AEGDDP---AKAAFDSLQASATEYIGYAWAMVV...SKA COATB_BPZJ2/1-49
AEGDDP---AKAAFDSLQASATEYIGYAWAMVV...SKA Q9T0Q9_BPFD/1-49
FAADDATSQAKAAFDSLTAQATEMSGYAWALV...SRA COATB_BPIF1/22-73'''

print (alignment [3:7])


# Sequências entre a 4ª e a 7ª do alinhamento
'''SingleLetterAlphabet() alignment with 4 rows and 52 columns
AEGDDP---AKAAFNSLQASATEYIGYAWAMVVVIVGATIGIKL...SKA COATB_BPM13/24-72
AEGDDP---AKAAFDSLQASATEYIGYAWAMVVVIVGATIGIKL...SKA COATB_BPZJ2/1-49
AEGDDP---AKAAFDSLQASATEYIGYAWAMVVVIVGATIGIKL...SKA Q9T0Q9_BPFD/1-49
FAADDATSQAKAAFDSLTAQATEMSGYAWALVVLVVGATVGIKL...SRA COATB_BPIF1/22-73'''

print (alignment [2, 6]) # T -> Terceira sequência, 7ª coluna


print (alignment [2].seq[6]) # T -> Terceira sequência, 7ª coluna
print (alignment [:, 6]) # TTT---T -> Todas as sequências, 7ª coluna

print (alignment [3:6, :6]) -> Sequências 4 a 7, primeiras 6 colunas


'''SingleLetterAlphabet() alignment with 3 rows and 6 columns
AEGDDP COATB_BPM13/24-72
AEGDDP COATB_BPZJ2/1-49
AEGDDP Q9T0Q9_BPFD/1-49'''

64
Módulo Bio.pairwise2
Este módulo faz os alinhamentos de pares locais e globais.

from Bio import pairwise2


alignments = pairwise2.align.globalxx ('ACCGT', 'ACG')
# xx - score conta o nº de carateres iguais (matches), sendo g = mismatches = 0
print (alignments) # pode retornar até 1000 alinhamentos
# [('ACCGT', 'A-CG-', 3.0, 0, 5), ('ACCGT', 'AC-G-', 3.0, 0, 5)]
# ['seq1', 'seq2', score, start, end]

from Bio.pairwise2 import format_alignment


for a in alignments:
print (format_alignment (*a))
# *a equivale a a[0], a[1], a[2], a[3], a[4]

from Bio.SubsMat import MatrixInfo


matrix = MatrixInfo.blosum62
for a in pairwise2.align.globalds ('KEVLA', 'EVL', matrix, -4, -1):
#ds - matriz de substituição; penalização constante por gap
print (format_alignment (*a))

65
Análise de Dados Ómicos

Os dados ómicos são divididos em várias categorias:


 Genómica: estudo do genoma dos organismos (sequências de DNA)
 Transcriptómica: medidas de expressão genética em tecidos /
condições distintas (DNA microarrays, RNAseq)
 Proteómica: medição da quantidade de cada proteína em determinados
tecidos/ condições (eletroforese 2D, espectrometria de massa)
 Metabolómica: identificação e medição da quantidade de metabolitos
(compostos de pequena dimensão) proteína em determinados tecidos/
condições (espectrometria de massa, ressonância magnética)
 Interactómica: identificação de interações proteína-proteina ou
proteina-DNA (e.g. chip-seq)
 Fluxómica: medição de fluxos de reações – implica medição dinâmica
da variação da concentração de compostos (e.g. carbono marcado)

A análise dos dados ómicos permite a:


 Reconstrução modelos (ex: regulatórios)
 Descoberta de fármacos
 Identificação de biomarcadores
 Análise de agentes patogénicos

66
 Identificação de vias metabólicas
 Estudo da regulação
 Determinar a função de genes/anotação

Estrutura
Independentemente da técnica usada, dados de são normalmente
transformados numa matriz de quantidades/ concentrações (e.g. expressão
genes, proteínas, metabolitos) x condições.
Permite que os biólogos cheguem a correlações entre genes/
proteínas/ compostos diferentes e que tentem perceber como as suas funções
podem estar ligadas.

A Matriz de dados é normalmente complementada por um conjunto de


variáveis (metadados) que caracterizam cada uma das amostras, podendo
estas ser:
 Discretas/ nominais: podem servir para dividir as amostras em
dois ou mais grupos
 Numéricas

67
Dados de expressão genética
Nos pontos seguintes, iremos usar essencialmente expressão genética
como exemplos dos dados a analisar, mas problemas semelhantes ocorrem com
outros tipos de dados ómicos.
Técnicas como DNA microarrays e RNA sequencing medem o nível de
expressão de todos os genes numa célula, em diversas condições/ instantes
de tempo.
O nível de expressão de um dado gene é estimado pela medição da
quantidade de mRNA respectivo.
• Um gene está ativo se está a ser transcrito.
• Mais mRNA indica mais atividade do gene (embora em termos
biológicos isto nem sempre seja verdade)

Pré-tratamento dos dados brutos


Dados provenientes dos equipamentos são extensos e com informação
que é necessário tratar antes da análise de dados. Grande parte do
tratamento inicial é realizado por software específico para cada
equipamento.
Passos deste pré-processamento em microarrays incluem o tratamento
da imagem para chegar à expressão, eliminação de ruído de background,
consolidação de réplicas, etc.
Dados de RNA-seq têm algumas etapas distintas de processamento pois
são contagens absolutas. Outros dados ómicos têm necessidades de
préprocessamento específicas.

Pré-processamento dos dados


Mesmo quando já temos os dados na forma de uma matriz genes x
amostras há necessidade de algumas tarefas adicionais de pré-processamento
para várias tarefas de análise de dados.

68
Passos do pré-processamento a este nível incluem tratamento de
valores omissos, normalização, filtros de flat patterns, transformações
logarítmicas, etc.
Estes passos permitem que os dados sejam de dimensões mais tratáveis
e que estejam em gamas de valores adequadas para análise posterior.
Transformação logarítmica

Filtros de “flat patterns”


Genes com valores muito constantes normalmente não trazem informação
relevante.

COMO DETECTAR?
• Desvio padrão/ desvio absoluto médio / IQR
• Valor dos picos mínimos e máximos (e.g. max/min)

SOLUÇÃO
• Remover estes genes da análise
• Remover apenas os que têm valores médios próximos de 0

69
Standardização entre diferentes amostras
Tipicamente, os valores são re-escalonadas para ficarem dentro de
limites normalizados (distribuição normal com média 0 e variância 1) em
cada variável. Como:
• Subtrair cada valor pela média (ou mediana) dos valores de
expressão desse gene
• Dividir pelo desvio padrão (ou desvio absoluto médio)
• Por vezes faz-se apenas a primeira

Análise de dados

Expressão diferencial
Em termos de investigação biológica é muito importante identificar o
conjunto de genes que têm níveis diferentes de expressão comparando duas
condições experimentais (e.g. célula normal vs cancerígena, wild
type vs mutante).
A identificação dos genes que são diferencialmente expressos assenta
em testes estatísticos de hipóteses:
 Paired t-test: se as amostras são emparelhadas (e.g. duas
condições por paciente, um com o tratamento A e outro com o
tratamento B)
 Unpaired t-test: as amostras dos dois grupos não são
relacionadas

Em ambos os casos calcula-se a estatística e o correspondente p-


value; valores de p-value mais baixos significam maior confiança que as
médias são diferentes.
Estes testes são paramétricos, assumindo distribuição normal dos dados; há
outras alternativas não paramétricas.

70
 Testes múltiplos: ao testar R genes em simultâneo, mesmo com
uma probabilidade baixa de erro (p) o nº esperado de erros
(falsos positivos) é R.p, que pode ser alto pois R pode ser de
vários milhares. Solução típica: fixar valor do p-value para
garantir uma taxa de falsos-positivos aceitável.
 One way ANOVA (analysis of variance): quando temos 3 ou +
grupos de condições (amostras)
 Multifactor ANOVA: quando temos 2 ou + factores (variáveis)
 General linear models: podem incorporar análise da influência
de variáveis contínuas

Clustering
Genes co-regulados deverão mostrar comportamentos (níveis de
expressão) “similares”.
“Guilt by Association”, isto é, se um gene desconhecido i é similar
em termos de expressão a um gene conhecido j, é muito provável que estejam
envolvidos na mesma via metabólica.

Cada gene (linha da matriz) é encarado como um ponto num espaço N-


dimensional
Cria-se uma matriz de distâncias entre cada par de genes (necessário
usar uma dada métrica para calcular a distância – e.g. Euclideana). Pares
de genes com distâncias pequenas partilham os mesmos padrões de expressão,
o que pode indiciar funcionalidades similares ou relacionadas.
O Clustering revela grupos de genes com padrões de expressão
semelhante, logo potencialmente relacionados funcionalmente.

71
Medindo semelhança de formas: coeficientes de correlação (e.g.
Pearson).
Medindo distâncias: euclidiana, Manhattan

K-mean Clustering
Determina K clusters que englobam todos os pontos, de forma a
minimizar a média do quadrado das distâncias de cada ponto para o centro
do cluster a que pertence d(V,X): d(V,X) = Σd(vi, X)2 / n, 1 < i < n, d(vi,
X) refere-se à distância Euclideana entre o ponto vi e o centro de
gravidade do cluster X, a que pertence

Clustering Hierárquico
Vai agrupando os genes, iteração a iteração, criando uma árvore
Critério de junção baseado na distância entre genes/ clusters.

72
73

Você também pode gostar