Bioinformática – O lado do programador

Problemas e Soluções

No seguimento do artigo “Introdução à Bioinformática” (11ª Edição da PROGRAMAR), no qual abordei a existência desta área da Informática (e da Biologia), passo agora a exemplificar, em termos mais práticos, as ferramentas e técnicas mais populares, que são diariamente usadas por milhares de cientistas.

Relembrando, Bioinformática define-se como o aplicar de técnicas de Matemática Aplicada, Informática, Estatística e Inteligência Artificial a problemas concretos de Biologia e/ou Bioquímica. Entre os problemas mais comuns, temos o alinhamento de sequências de DNA, a procura de genes (por associação e prévio conhecimento de outros), a assemblagem de genomas, a predição de estruturas de proteínas (secundárias, terciárias e quaternárias), bem como outras áreas menos “moleculares”, como a evolução.

Para cada uma destas tarefas há determinadas estratégias a seguir, e, obviamente, uma boa estratégia aplicada a outro problema, resulta provavelmente num desastre em termos de eficácia. A razão mais simples por detrás desta pouca plasticidade de métodos, é o diferente conjunto de requisitos que cada problema assume. Exemplificando: um problema comum em Biologia é o acesso a bases de dados de diferentes tipos e de diferentes especificações. Isto resulta numa difícil uniformização dos dados e, consequentemente, do tipo de métodos a usar para os obter e tratar. Além disso, é necessário pouco poder de computação “puro” para resolver estas tarefas. Interessa mais tirar partido de métodos que façam boa gestão do tráfego na web e que sejam eficientes a fazê-lo. Obviamente, uma linguagem como C é preterida em relação a outra como Perl. Já noutro problema, como a predição de estruturas de proteínas, onde milhões de complexos cálculos matemáticos são efectuados por segundo, já nos interessa tirar o máximo partido do poder de computação disponível, recorrendo então a linguagens que nos permitam desprezar operações supérfluas e canalizar recursos para onde de facto interessam. Não é de estranhar então que, ao procurar aplicações de Bioinformática, se encontrem destas escritas nas mais variadas linguagens, sendo as mais usadas: Java, Python, Perl, C, C++ e C# [1]. Outras linguagens, como por exemplo Ruby, encontram também alguns adeptos entre os bioinformáticos. Porém, para além das diferentes escolhas no que toca a linguagens de programação, diferentes implementações de diferentes estratégias têm um efeito preponderante na eficácia final do programa. Ainda assim, alguns problemas podem partilhar soluções ou partilhar de ideias e conceitos que, à partida, seriam úteis num ou noutro caso isolado.

Reinventar a roda?

Em ciência, os resultados são, geralmente, publicados. Nas ciências biomédicas em geral, partilham-se métodos, ideias, conceitos e resultados, permitindo o avanço rápido da investigação, uma vez que, salvo raros casos, há sempre alguém que já tocou, nem que seja ao de leve, no problema que temos em mãos, e que para ele contribuiu. Esta filosofia de partilha estende-se também à Bioinformática. Apesar de haver programas cujo código está fechado, há grupos de investigadores que se associaram para facilitar o trabalho na área, construindo verdadeiros repositórios de código, bem documentado e testado, que permite resolver problemas casuais de forma (quase) instantânea. Um bom exemplo é a Open Bioinformatics Foundation. Dela, surgiram vários projectos “filhos”, entre os quais o projecto BioPython, o BioPerl e o BioJava. Fora estes, mais famosos e mais maduros, uma pesquisa no Google revela várias comunidades, organizadas por linguagem, que servem de repositórios de código, disponibilizando facilmente, ao utilizador, bibliotecas e módulos que lhe simplificam o trabalho. Segue-se uma breve lista das que uma pesquisa simples por “bio[nome da linguagem]” produziu (infelizmente, ou felizmente, parece que ainda não houve alma que se lembrasse de criar um bioassembly!):

Pegando numa delas, vamos analisar o potencial prático deste tipo de abordagem. Escolhi o BioPython porque é a com que trabalho e porque código em Python é, de facto, legível e perceptível mesmo a quem não programa na linguagem.

Exemplos

Um problema simples, ideal para começar, seria partir de uma sequência de ADN e obter o respectivo ARN, a molécula que vai servir de molde à síntese de uma proteína. Lembrando conceitos básicos de biologia molecular, há quatro tipos de bases (comuns) no ADN, cada uma identificada por uma letra (a inicial): Adenina, Guanina, Timina, Citosina. Para o ARN, troca a Timina pelo Uracilo. Para além disso, temos que as bases são complementares entre si. Quando se dá a reacção de transcrição (ADN – ARN), cada base do ADN é “transcrita” numa exacta do ARN: A-U, T-A, C-G, G-C. Podemos então construir um programa que, dada uma sequência de ADN, nos devolva a correspondente de ARN. Porém, já não terão pensado nisso antes de nós? De facto, já, e como o processo de transcrição não é tão linear como o descrevi, já houve quem tenha escrito (e complementado) algoritmos que reproduzem in silico a transcrição (quase) tal como in vivo. Se estivermos a usar Python, basta-nos aceder ao módulo BioPython e chamar a classe Bio.Tools. O código fica tão simples como:

(dada uma sequência my_seq de ADN)

from Bio.Tools import Transcribe
transcriber = Transcribe.unambiguous_transcriber
my_rna_seq = transcriber.transcribe(my_seq)
print my_rna_seq Seq('GAUCGAUGGGCCUAUAUAGGAUCGAAAAUCGC', IUPACUnambiguousRNA())

Uma vantagem notável de usar o módulo bioPython para uma simples operação de transcrição, quando comparada com a nossa alternativa de escrever o algoritmo à mão (que não passará das 5 linhas), é a fiabilidade dos resultados. Na verdade, a sequência my_seq não se trata de uma simples string. Trata-se de um objecto de uma outra classe, Bio.Seq, que é verificada, a nível de integridade biológica, e que define as operações que podem ser efectuadas sobre ela. Este simples mecanismo previne, por exemplo, o aplicar do método Transcribe numa sequência de ARN.

Entre as outras classes do BioPython, podemos encontrar código que funciona como parser de vários formatos. As diferentes bases de dados espalhadas pela web usam cada uma seu formato. Daí, são necessários diferentes parsers para podermos tratar esta informação. Em vez de os escrevemos nós (que dá muito trabalho e é complicado, experiência própria), podemos aceder facilmente a classes que o fazem na perfeição. O exemplo que se segue é bem ilustrativo da ilegibilidade de alguns formatos:

gi|6273290|gb|AF191664.1|AF191664 Opuntia clavata rpl16 gene; chloroplast gene for (resto da descrição)...
TATACATTAAAGGAGGGGGATGCGGATAAATGGAAAGGCGAAAGAAAGAAAAAAATGAATCTAAATGATATAGGATTCCACTATGTAAGGTCTTTGAATCATATCATAAAAGACAATGTAATAAA..(resto da sequência)..

Para obter informação de um ficheiro deste género (formato FASTA), usamos:

from Bio import Fasta
parser = Fasta.RecordParser()
file = open("ls_orchid.fasta")
iterator = Fasta.Iterator(file, parser)
cur_record = iterator.next()
dir(cur_record)
['_colwidth', 'sequence', 'title']

Chamando os métodos title ou sequence, podemos aceder selectivamente a diferentes campos de informação. E assim, poupamos o trabalho de escrevermos nós um parser.

Como estes dois breves exemplos, há muitos outros. Há classes que importam duas estruturas proteicas de bases de dados e depois fazem a superimposição das duas, permitindo compará-las e discernir semelhanças e diferenças. Por exemplo, na comparação entre duas proteínas, uma funcional e outra mutante não-funcional, podemos ver quais os domínios (regiões) que podem estar na origem da perca de função. Outras classes permitem, com “one-liners”, aceder a bases de dados e delas recuperar informação estruturada (tendo previamente definido as variáveis search_command, search_database, search_term e return_format):

from Bio.WWW import NCBI
result_handle = NCBI.query(search, base_de_dados, term = termo_a_pesquisar, doptcmdl = formato(ex. FASTA))

Conclusão

Concluindo, vemos que muita da contribuição de um bioinformático é facilitar o trabalho dos outros, seja construindo aplicações que facilitam o trabalho do cientista de wet-lab (quem realmente trabalha com material biológico), seja cedendo partes do seu código que aliviam o esforço do cientista de dry-lab (um bioinformático, portanto). Vemos também que, com o surgir diário de novas bases de dados, novas técnicas de análise, novas tecnologias disponíveis ao biólogo/bioquímico, há ainda muito trabalho a ser feito. Tal como disse no primeiro artigo sobre Bioinformática, há investigação em informática para além dos bits e dos bytes, onde o contributo é muitas vezes relevante e visível. É uma questão de procurar, aventurar-se e de, no fundo, ter vontade de aprender.

Referências

  1. Fourment, M., Gillings, M.R., “A comparison of common programming languages used in bioinformatics”, BMC Bioinformatics (9:82), 2008

Publicado na edição 13 (PDF) da Revista PROGRAMAR.