www.python.org 1 1 © 2015 Dr. Walter F. de Azevedo Jr. 000000000000000000000000000000000000000 000000000000000000000000000000000000000 000000000000111111111110001100000000000 000000000001111111111111111111000000001 000000000111111111111111111111111000000 000000000111111111111111111111111000000 000000000011111111111111111111100000000 000000001111111111111111111111111000000 000011111111111111111111111111111000000 001111111111111111111111111111110000000 111111111111111111111111111110000000000 111111111111111111111111111110000000000 000011111111111111111111111111111110000 001111111111111111111111111111111111000 011111111111111111111111111111111111000 001111111111111111111111111111111111100 000000011111111111111111111111111111110 000000001111111111111111111111111111110 000000000001111111111111111111111111110 000000000000011111111111111111111111110 000000000000000111111111111111111111000 000000000000000000000000001111000000000 000000000000000000000000000000000000000 000000000000000000000000000000000000000 000000000000000000000000000000000000000 Programa: bfactor_plot2.py www.python.org Gráfico de B-factor de um arquivo PDB (versão 2) Programa: bfactor_plot2.py Resumo Programa para calcular o fator de vibração (B-factor) para cada resíduo de um arquivo PDB. O programa gera um gráfico do B-factor médio de cada resíduo de aminoácido. No eixo x temos os números dos resíduos e no eixo y o valor médio do B-factor para cada resíduo. Os dados dos valores de B-factor são mostrados na forma de três linhas. Uma para o B-factor de todos os átomos de cada resíduo, outro para o B-factor médio só para os átomos da cadeia principal de cada resíduo e o último para os B-factors médios dos átomos da cadeia lateral de cada resíduo. Só serão calculados os valores médios para a parte proteica do PDB, ou seja, hetero átomos ficam de fora do gráfico. 2 Programa: bfactor_plot2.py www.python.org No programa principal temos, como na versão anterior, a função read_PDB(). Para calcularmos os fatores de vibração térmica médios, para cada porção da estrutura, temos uma nova função, chamada calc_prot_bfactors(my_list_of_atoms), que tem como parâmetro uma lista de átomos, obtida de função read_PDB(). A nova função retorna um array com os B-factors para cada trecho da estrutura, armazenados em colunas distintas do array. Assim temos um array com quatro colunas, a primeira traz os números dos resíduos, a segunda os B-factors para todos os átomos de cada resíduo, a terceira para a cadeia principal e a quarta para a cadeia lateral. A última função faz o gráfico. Veja que criamos uma lista, antes da chamada da função plot_mult_array(), para as legendas do gráfico. Esta lista está atribuída à variável list_legends. # Main program # Calls function to read PDB my_list_of_atoms = read_PDB() # Calls function to calculate mean B-factor for each residue (protein atoms only) my_bfactors = calc_prot_bfactors(my_list_of_atoms) # Creates a list of legends list_legends = ["All","Main-chain","Side-chain"] # Calls function to plot B-factor plot_mult_array(my_bfactors,"Residue Number","B-factor(A**2)",list_legends) 3 Programa: bfactor_plot2.py www.python.org def calc_prot_bfactors(list_of_atoms_in): """Function to calculate average B-factor for each residue in a protein PDB""" import numpy as np list_mc = ["CA","C ","O ","N ","OX"] # List of main-chain atoms all_atoms = [] # Sets lists for all, main-chain and side-chain atoms mc_atoms = [] sc_atoms = [] for line in list_of_atoms_in: if line[0:6] == "ATOM # looping through all atoms in the list ": all_atoms.append(line) # Picks all atoms if line[13:15] in list_mc: # Picks main-chain atoms mc_atoms.append(line) else: sc_atoms.append(line) # Picks side-chain atoms nres, bf_all = calculate_bfactors(all_atoms) # Calls function calculate_bfactors() nres, bf_mc = calculate_bfactors(mc_atoms) # Calls function calculate_bfactors() nres, bf_sc = calculate_bfactors(sc_atoms) # Calls function calculate_bfactors() columns = 4 rows = len(nres) bf = np.array([[0]*columns]*rows,float) # Sets initial matrix as a NumPy array bf[:,0] = nres # Gets residue number bf[:,1] = bf_all[:rows] # Gets all atom B-factors bf[:,2] = bf_mc[:rows] # Gets main-chain atom B-factor bf[:,3] = bf_sc[:rows] # Gets side-chain atom B-factor return bf O código da função calc_prot_bfactors() está mostrado ao lado. As strings com os tipos de átomos da cadeia principal, foram atribuídos à variável list_mc. Esta lista é usada num loop for, para a seleção das linhas para cada tipo de átomo. Temos uma lista com todos os átomos, atribuídos à variável all_atoms, a lista com os átomos da cadeia principal são atribuídos à variável mc_atoms. As linhas com os átomos das cadeias laterais, são atribuídos à variável sc_atoms. 4 Programa: bfactor_plot2.py www.python.org def calc_prot_bfactors(list_of_atoms_in): """Function to calculate average B-factor for each residue in a protein PDB""" import numpy as np list_mc = ["CA","C ","O ","N ","OX"] # List of main-chain atoms all_atoms = [] # Sets lists for all, main-chain and side-chain atoms mc_atoms = [] sc_atoms = [] for line in list_of_atoms_in: if line[0:6] == "ATOM # looping through all atoms in the list ": all_atoms.append(line) # Picks all atoms if line[13:15] in list_mc: # Picks main-chain atoms mc_atoms.append(line) else: sc_atoms.append(line) # Picks side-chain atoms nres, bf_all = calculate_bfactors(all_atoms) # Calls function calculate_bfactors() nres, bf_mc = calculate_bfactors(mc_atoms) # Calls function calculate_bfactors() nres, bf_sc = calculate_bfactors(sc_atoms) # Calls function calculate_bfactors() Depois chamamos a antiga função calculate_bfators(), para cada lista de átomos. Esses valores de B-factors são atribuídos a um novo array, como quatro colunas. Sendo a primeira coluna do array, a do número dos resíduos. As colunas restantes trazem os B-factors. O array é retornado da função. columns = 4 rows = len(nres) bf = np.array([[0]*columns]*rows,float) # Sets initial matrix as a NumPy array bf[:,0] = nres # Gets residue number bf[:,1] = bf_all[:rows] # Gets all atom B-factors bf[:,2] = bf_mc[:rows] # Gets main-chain atom B-factor bf[:,3] = bf_sc[:rows] # Gets side-chain atom B-factor return bf 5 Programa: bfactor_plot2.py www.python.org def plot_mult_array(x,x_label_in,y_label_in,list_legends_in): """Function to plot two multi-dimensional arrays""" import matplotlib.pyplot as plt num_var = len(x[0,:]) # Number of variables x1 = x[1:,0] # Gets array for number of residues(column 0) # Looping variables to get B-factor arrays for i in range(1,num_var): x2 = x[1:,i] # Gets each column (1-3) for B-factors plt.plot(x1,x2,label=list_legends_in[i-1]) # Generates plot plt.legend(loc='upper left') # Positioning the legends plt.xlabel(x_label_in) # Adds axis label plt.ylabel(y_label_in) # Adds axis label plt.grid(True) # Adds grid to the plot plt.show() # Shows plot plt.savefig("bfactor.png") # Saves plot on png file A função plot_mult_array() gera o gráfico de um array. No caso, o número de colunas do array é obtido com num_var = len(x[0,:]), que fixa na linha zero, e retorna o número de colunas. A linha x1 = x[1:,0], atribui o número de resíduos à variável x1. Em seguida temos um loop for, que atribui cada coluna de B-factors do array à variável x2, que será usada na função plt.plot(). Veja que o loop for inicia na segunda coluna e vai até a última. Os dados da primeira coluna, variável x1, foram atribuídos antes 6 do loop. Programa: bfactor_plot2.py www.python.org Abaixo temos o resultado de rodarmos o código para o arquivo 1kxy.pdb. Type input file name => 1kxy.pdb 7 Programa: plot_bar_FASTA.py www.python.org Gráfico de Barras de um arquivo FASTA Programa: plot_bar_FASTA.py Resumo Programa que lê um arquivo FASTA e gera um gráfico de barras, indicando a quantidade de cada tipo de resíduo de aminoácido, encontrada na sequência lida. Ou seja, o eixo x indicará os vinte aminoácidos naturais com o código de uma letra. A altura das barras do gráfico, indica quanto de cada resíduo de aminoácido foi encontrado na sequência lida do arquivo de entrada FASTA. O programa gera o arquivo bar.png. 8 Programa: plot_bar_FASTA.py www.python.org O código do programa principal está mostrado abaixo. Usamos as funções read_FASTA() e edit_seq(), vista em outro programa. O programa traz duas novas funções, a count_residues(my_seq), que tem como parâmetro uma string com a sequência lida do arquivo FASTA. Esta função retorna um array com o número de cada tipo de aminoácido e uma lista com os 20 aminoácidos naturais. Por último, temos a função plot_bar(), que gera o gráfico de barras, para o array com os números de ocorrência de cada aminoácidos e para lista dos aminoácidos. # Main program # Calls read_FASTA() my_seq = read_FASTA() # Calls function edit_seq(my_seq) my_seq = edit_seq(my_seq) # Calls count_res(my_seq) my_res_count, list_aa = count_residues(my_seq) # Calls plot_bar() plot_bar(list_aa,my_res_count,"Amino acid","Number of Amino Acids") 9 Programa: plot_bar_FASTA.py www.python.org A função count_residues(seq_in) recebe a sequência, na forma de string, e conta a ocorrência de cada tipo de aminoácido, que é atribuído como elemento do array res_count. Os códigos de uma letra dos aminoácidos estão na forma de lista e atribuídos à variável my_list. Um loop for varre os elementos da lista my_list e conta cada aminoácido na sequência. A função retorna o array res_count e a lista my_list. def count_residues(seq_in): """Function to count residues""" import numpy as np res_count = np.zeros(20,int) my_list =["A","R","N","D","C","E","Q","G","H","I", "L","K","M","F","P","S","T","W","Y","V"] i = 0 for aa in my_list: res_count[i] = seq_in.count(aa) i += 1 return res_count,my_list 10 Programa: plot_bar_FASTA.py www.python.org Para gerar o gráfico de barras, usamos a função plot_bar(), mostrada abaixo. Os parâmetros da função são o array y e a lista x. Além de parâmetros para os rótulos dos eixos. À variável x1, é atribuído um array com 20 números. O gráfico de barras é gerado com a função plt.bar(x1,y). def plot_bar(x,y,x_label_in,y_label_in): """Function to generate bar plot""" import numpy as np import matplotlib.pyplot as plt x1 = np.arange(20) # Generates plot plt.bar(x1,y) plt.xticks(x1+0.4,x) plt.xlabel(x_label_in) # Adds axis label plt.ylabel(y_label_in) # Adds axis label # Shows plot plt.show() # Saves plot on png file plt.savefig("bar.png") 11 Programa: plot_bar_FASTA.py www.python.org Para termos os códigos de uma letra no eixo x, usamos o comando plt.xticks(x1+0.4,x) . O “0.4”, somado ao x1, é para deslocarmos o centro onde será escrito o código de uma letra no eixo x. As strings atribuídas à variáveis x_label_in e y_label_in, são usadas como rótulos dos eixos. O gráfico é gerado e salvo no arquivo bar.png. def plot_bar(x,y,x_label_in,y_label_in): """Function to generate bar plot""" import numpy as np import matplotlib.pyplot as plt x1 = np.arange(20) # Generates plot plt.bar(x1,y) plt.xticks(x1+0.4,x) plt.xlabel(x_label_in) # Adds axis label plt.ylabel(y_label_in) # Adds axis label # Shows plot plt.show() # Saves plot on png file plt.savefig("bar.png") 12 Programa: plot_bar_FASTA.py www.python.org Abaixo temos o resultado de rodarmos o código para o arquivo 1kxy.fasta. Type information about protein sequence (FASTA file). Type input file name => 1kxy.fasta 13 Tratando exceções www.python.org Frequentemente digitamos informações erradas nos programas que desenvolvemos, como no exemplo abaixo. Type information about protein sequence (FASTA file). Type input file name => 1xya.fasta Traceback (most recent call last): File "C:\Users\Walter\workspace\Bionfo_Aula15\plot_bar_FASTA.py", line 78, in <module> my_seq = read_FASTA() File "C:\Users\Walter\workspace\Bionfo_Aula15\plot_bar_FASTA.py", line 18, in read_FASTA my_fo = open(input_file_name,"r") FileNotFoundError: [Errno 2] No such file or directory: '1xya.fasta' Ao digitarmos, como arquivo de entrada, 1kxa.fasta o programa tenta abrir um arquivo inexistente. Temos a mensagem de erro FileNotFoundError. Em Python temos como tratar tais situações, chamadas de exceções. Para isto, usamos a função try/except. Funciona de forma similar ao if/else. Se uma tentamos um bloco de comandos, vinculados ao try, caso tenha um erro, o bloco de comandos, vinculados ao except é executado. 14 Tratando exceções www.python.org Abaixo temos um trecho da função read_FASTA(), onde lemos o arquivo FASTA. Veja que temos o comando try, antes da função open(). A função open() está recuada com relação ao comando try. Caso o arquivo não exista, não podemos realizar a leitura. Temos uma exceção do tipo IOError, exceção de entrada/saída O bloco de comandos, vinculado ao except, será executado, caso o arquivo FASTA não exista. No bloco, vinculado ao except, além de duas funções print(), temos o sys.exit(), que finaliza a execução do programa. A nova função read_FASTA() está no programa new_plot_bar_FASTA.py. Execute o código, usando um nome de arquivo FASTA que não exista. try: # Opens FASTA file my_fo = open(input_file_name,"r") except IOError: print("Error! I can't find file ",input_file_name) print("Finishing program execution!") sys.exit() 15 Tratando exceções www.python.org Além da exceção IOError, o Python tem um arsenal de outras exceções. A tabela a seguir traz uma lista com as principais. Tipo de exceção Descrição da exceção IOError Erro em leitura ou escrita de arquivo. IndexError Erro em índice, quando uma sequência é indexada com um número não existente. KeyError Erro de chave, ocorre quando uma chave de dicionário não existe. NameError Erro de nome, ocorre quando uma variável ou função não existente é chamada. SyntaxError Erro de sintaxe de linguagem. TypeError Erro de tipo, ocorre quando uma função é aplicada a um objeto de tipo inadequado, por exemplo, o parâmetro de uma função pede um float e é passado uma string. ValueError Erro de valor, ocorre quando o tipo está certo, mas o valor está inadequado. ZeroDivisionError Erro de divisão por zero. 16 Tratando exceções www.python.org Exercício de programação: Refaça os programas da lista abaixo, onde agora as exceções são do tipo IOError são tratadas. bfactor_plot1.py bfactor_plot2.py movePDB3.py ssBondPDB5.py 17 Coordenadas Atômicas www.python.org A figura mostrada abaixo traz a estrutura tridimensional dos resíduos de aminoácido alanina 2 e prolina 3, da estrutura tridimensional da chiquimato quinase (código de acesso PDB: 1WE2). O arquivo PDB traz as coordenadas atômicas que foram usadas para gerar a figura. Para cada átomo mostrado na figura, temos uma posição atômica no arquivo PDB. Lembre-se, as coordenadas atômicas dos arquivos PDB estão em angstrom (Å), 1 Å = 10-10 m. Trecho do arquivo PDB para os resíduos Ala2 e Pro3 ATOM ATOM ATOM ATOM ATOM ATOM ATOM ATOM ATOM ATOM ATOM ATOM 1 2 3 4 5 6 7 8 9 10 11 12 N CA C O CB N CA C O CB CG CD ALA ALA ALA ALA ALA PRO PRO PRO PRO PRO PRO PRO A A A A A A A A A A A A 2 2 2 2 2 3 3 3 3 3 3 3 26.424 26.646 28.080 29.031 26.357 28.256 29.592 30.578 30.179 29.292 27.920 27.228 27.695 26.892 27.086 26.973 25.374 27.322 27.533 26.368 25.186 27.869 28.471 27.520 8.672 9.925 10.395 9.615 9.691 11.685 12.232 12.108 12.111 13.700 13.656 12.720 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 38.67 38.14 36.44 36.87 37.83 35.89 32.15 31.97 32.12 31.84 31.93 33.67 N C C O C N C C O C C C 18 Coordenadas Atômicas www.python.org Abaixo temos o detalhamento da estrutura, onde vemos as coordenadas atômicas usadas para gerar as posições para cada átomo da figura, exceto os hidrogênios. As coordenadas atômicas estão em angstrom (Å). A legenda de cores dos átomos está ATOM 12 CD PRO A 3 27.228 27.520 12.720 1.00 33.67 C mostrada abaixo à direita. ATOM ATOM 10 ATOM 11 CG PRO A 3 27.920 28.471 13.656 CB PRO A 3 29.292 27.869 13.700 1.00 31.84 C 8 C PRO A 3 30.578 26.368 12.108 1.00 31.97 C ATOM 9 O PRO A 3 30.179 25.186 12.111 1.00 32.12 O ATOM 7 CA PRO A 3 29.592 27.533 12.232 1.00 32.15 C ATOM 6 N PRO A 3 28.256 27.322 11.685 1.00 35.89 N ATOM 4 O ALA A 2 29.031 26.973 9.615 1.00 36.87 O ATOM 3 C ALA A ATOM 5 2 CB ATOM ALA A 2 ATOM 28.080 CA 1 27.086 2 26.357 ALA A N 2 ALA A 10.395 25.374 26.646 2 1.00 36.44 9.691 26.892 26.424 C C 1.00 37.83 9.925 27.695 1.00 31.93 1.00 38.14 8.672 1.00 38.67 C C N 19 Representação Vetorial das Coordenadas Atômicas www.python.org As coordenadas atômicas, armazenadas nos arquivos PDB, permitem a determinação direta de diversos parâmetros estruturais, tais como, distâncias, ângulos de ligação e ângulos de torção. Os átomos na estrutura podem ser representados por vetores, onde as coordenadas x,y,z dos átomos são as coordenadas dos vetores, como indicado para o carbono alfa (CA) abaixo. Lembrando-se, vetores apresentam direção, sentido e magnitude (tamanho do vetor). O tamanho do vetor também é chamado de módulo. CA2 j k rCA2 26,646 i 26,892 j 9,925k i 20 Representação Vetorial das Coordenadas Atômicas www.python.org A coordenada ao longo de x é multiplicada pelo vetor unitário i, a coordenada ao longo de y é multiplicada pelo vetor j, e a coordenada ao longo z pelo vetor k. Assim, o vetor rCA2 = 26,646i + 26,892j + 9,925k indica a posição do átomo carbono alfa da alanina 2 da estrutura 1WE2, como mostrado abaixo. A representação vetorial será usada para determinação dos parâmetros estruturais já citados. CA2 j k rCA2 26,646 i 26,892 j 9,925k i 21 Representação Vetorial das Coordenadas Atômicas www.python.org Como destacado, vetores apresentam direção e sentido, indicado pela flecha abaixo. Além disso, apresentam módulo, indicado pelo tamanho da flecha. Para o cálculo do módulo do vetor r = xi + yj + zk, usamos a seguinte equação: r x2 y2 z2 (Equação 1) Onde x,y,z são as coordenadas do vetor r. Usamos as barras verticais || para representar o módulo, assim |rCA2| é o módulo do vetor rCA2. CA2 j k rCA2 26,646 i 26,892 j 9,925k i 22 Representação Vetorial das Coordenadas Atômicas www.python.org Exemplo 1. Determine o módulo do vetor rCA2. Solução Para determinarmos rCA2 usamos a equação 1, como segue: rCA2 26,646 2 26,892 2 9,925 2 rCA2 39,137 Å CA2 j k rCA2 26,646 i 26,892 j 9,925k i 23 Representação Vetorial das Coordenadas Atômicas www.python.org Para determinarmos o vetor diferença entre os vetores r1 = x1i + y1j + z1k e r2 =x2i + y2j + z2k, usamos a seguinte equação: r1 r2 x1 x2 i y1 y2 j z1 z 2 k (Equação 2) A figura abaixo indica o vetor diferença r1 - r2 , entre os pontos P1 e P2. r1 x1i y1 j z1k P1 r1 – r2 P2 r2 x 2 i y 2 j z 2k 24 Distância Interatômica www.python.org Assim, para determinarmos as distância (d12) entre dois pontos P1 e P2, basta determinarmos o módulo do vetor diferença entre os pontos P1 e P2. Como já temos uma equação para o vetor diferença, basta calcularmos o módulo deste vetor, com a seguinte equação: d12 r1 r2 x1 x2 y1 y2 z1 z2 2 2 2 (Equação 3) Usando-se as coordenadas atômicas de um arquivo PDB para um par de átomos teremos a distância em Å (10-10 m). P1 r1 x1i y1 j z1k r1 – r2 P2 r2 x 2 i y 2 j z 2k 25 Distância Interatômica (Exemplo 2) www.python.org Exemplo2. Determine a distância interatômica para os átomos CA2 e N2, indicados na estrutura abaixo. rCA2 26,646 i 26,892 j 9,925k CA2 N2 j k rN2 26,424 i 27,695 j 8,672k i 26 Distância Interatômica (Exemplo 2) www.python.org Exemplo 2 (Solução). Os vetores são os seguintes: rN2 26,424 i 27,695 j 8,672k rCA2 26,646 i 26,892 j 9,925k A distância é dada pela equação 3, como segue: d CA 2, N 2 x1 x2 2 y1 y2 2 z1 z2 2 d CA 2, N 2 0,222 2 - 0,8032 1,2532 26,646 26,424 2 26,892 27,695 2 9,925 8,672 2 d CA 2, N 2 2.264102 d CA 2, N 2 1,504 Å rCA2 26,646 i 26,892 j 9,925k CA2 N2 j k rN2 26,424 i 27,695 j 8,672k i 27 Programa: interatomic_dist_PDB.py www.python.org Distância interatômica num arquivo PDB Programa: interatomic_dist_PDB.py Resumo Programa que lê um arquivo PDB e mostra as distâncias médias entre os átomos da cadeia principal. A lista terá as distâncias N-CA, CA-C, C-O e C-N, esta última envolvendo resíduos consecutivos. 28 Produto Escalar www.python.org Definimos produto escalar (.) entre os vetores r1 = x1i + y1j + z1k e r2 =x2i + y2j + z2k, pela seguinte equação: r1 r2 x1 x2 y1 y2 z1 z 2 (Equação 4) A partir do ângulo entre os vetores r1 e r2 , podemos usar a seguinte equação para determinarmos o produto escalar (.): r1 r2 r1 r2 cos (Equação 5) r1 x1i y1 j z1k P1 P2 r2 x 2 i y 2 j z 2k 29 Ângulos de Ligação www.python.org Para calcularmos o ângulo de um sistema com três pontos, temos que ter as distâncias entre os pontos. A relação matemática que usaremos é a lei dos cossenos. Para revisar o conceito, consideremos o triângulo ABC qualquer abaixo. B C A O triângulo não é retângulo, mas se traçarmos uma perpendicular à linha AC, a partir do vértice B, temos dois triângulos retângulos, como mostrado abaixo. B h A C D 30 Ângulos de Ligação www.python.org O cos é dado pelo cateto adjacente (AD) dividido pela hipotenusa (AB), como segue: cos AD AB (Equação 6) Se usarmos os dois triângulos internos e o teorema de Pitágoras, podemos determinar (AD) em função dos lados do triângulo externo ABC. Considere o triângulo ABD, temos pelo teorema de Pitágoras: (AB)2 = x2 + h2 (Equação 7) => h2 = (AB)2 – x2 Do triângulo BCD temos: (BC)2 = (CD)2 + h2 => (BC)2 = ((AC) –x)2 + h2 (Equação 8) B (BD) = h (AD) = x (CD) = (AC) - x h A C D 31 Ângulos de Ligação www.python.org Só lembrando onde queremos chegar, procuramos uma equação para o cos em função dos lados do triângulo ABC. Assim, a equação 6 tem a seguinte forma: cos AD x AB ( AB ) (Equação 6) Substituindo-se a equação 7 na equação 8, chegaremos a uma expressão para x, como segue: (BC)2 = ((AC) –x)2 + h2 h2 = (AB)2 – x2 (Equação 8) (Equação 7) Assim temos: (BC)2 = ((AC) –x)2 + h2 = (AC)2 -2x(AC) + x2 + (AB)2 – x2 (BC)2 = (AC)2 -2x(AC) + (AB)2 => 2x(AC) = (AC)2 + (AB)2 - (BC)2 Isolando-se x, temos: 2 2 2 x AB AC BC 2 AC (Equação 9) 32 Ângulos de Ligação www.python.org Resumindo-se, chegamos a duas equações: AD x cos AB ( AB ) (Equação 6) 2 2 2 AB AC BC x 2 AC (Equação 9) Substituindo-se a equação 9 na equação 6, chegamos a: 2 2 2 AD AB AC BC cos AB 2( AB ) AC (Equação 10) A equação 10 traz o cosseno do ângulo em função dos lados do triângulo ABC. Nosso objetivo é obtermos o ângulo , em função da informação sobre os tamanhos dos lados do triângulo ABC ou, de forma equivalente, as distâncias entre os pontos dos vértices do triângulo ABC. Assim faremos uso da função inversa do cosseno, a função arco-cosseno, como segue. AB 2 AC 2 - BC 2 α arccos (Equação 11) 2(AB)(AC) 33 Ângulos de Ligação www.python.org O ângulo de ligação (), entre as ligações AB e AC, mostrado na figura abaixo, pode ser determinado a partir da seguinte equação: AB 2 AC 2 - BC 2 α arccos (Equação 11) 2(AB)(AC) Onde AB, AC e BC são as distâncias entre os pontos, ou no caso molecular, as distâncias interatômicas, determinadas usando-se a equação da distância interatômica (equação 3), descrita anteriormente. B A AC C 34 Ângulos de Ligação (Exemplo 3) www.python.org Exemplo 3. Determine o ângulo de ligação formados pelos átomos N2 CA2 C2. rC2 28,080 i 27,086 j 10,395k rCA2 26,646 i 26,892 j 9,925k j k C2 CA2 N2 rN2 26,424 i 27,695 j 8,672k i 35 Ângulos de Ligação (Exemplo 3) www.python.org Solução Passo 1: Inicialmente usamos a equação 3 para determinar as seguintes distâncias interatômicas: dC2,CA2, dCA2,N2 e dC2,N2. O cálculo é feito a partir da aplicação direta da equação 3, como vimos no exemplo 2. Por isso não iremos repeti-lo aqui. Usaremos os valores das distâncias para os próximos passos. d C 2,CA 2 1,520 Å d CA 2, N 2 1,504 Å d C 2, N 2 2,470 Å rC2 28,080 i 27,086 j 10,395k rCA2 26,646 i 26,892 j 9,925k j k C2 CA2 N2 rN2 26,424 i 27,695 j 8,672k i 36 Ângulos de Ligação (Exemplo 3) www.python.org Solução (Continuação) Passo 2: Usamos as distâncias interatômicas e substituímos na equação 11, como segue: 1,52 2 1,504 2 - 2,47 2 α arccos 2 ( 1 , 52 )( 1 , 504 ) 2,3104 2,262016 - 6,1009 α arccos 4,57216 α arccos - 0,3343 109,5 o rC2 28,080 i 27,086 j 10,395k α 109,5 o rCA2 26,646 i 26,892 j 9,925k O ângulo de 109,5º era o esperado para um carbono tetraédrico, como o carbono alfa (CA). j k C2 CA2 N2 rN2 26,424 i 27,695 j 8,672k i 37 Programa: bond_angle_PDB.py www.python.org Ângulo de ligação num arquivo PDB Programa: bond_angle_PDB.py Resumo Programa que lê um arquivo PDB e mostra as ângulos médios entre os átomos da cadeia principal. A lista terá os seguinte ângulos N-CA-C, CA-C-O e CA-C-N, este último envolvendo resíduos consecutivos. 38 Ângulos de Torção www.python.org O ângulo de torção é medido considerando-se duas ternas de pontos, como no sistema de quatro pontos mostrado ao lado, indicados por P1, P2, P3 e P4. Os pontos P1, P2 e P3 definem um plano, e os pontos P2, P3 e P4 um segundo plano. O ângulo de torção envolvendo os pontos P2 e P3 é definido como o ângulo formado entre os planos P1, P2 e P3 e P2, P3 e P4. P4 P1 P3 P2 39 Ângulos de Torção www.python.org Para entendermos a equação do ângulo de torção (), necessitamos de alguns conceitos básicos de geometria analítica. Usaremos o conceito de vetor, para determinarmos a interação entre os pontos no sistema. Manteremos a notação de usarmos letras em negrito para representar vetores. Assim, os vetores que indicam as posições dos pontos P1, P2, P3 e P4 são dados por: y P4 P1 p1 x1i y1 j z1k p 2 x 2 i y 2 j z 2k p 3 x 3i y3 j z3k p1 j k p2 P3 P2 i x p 4 x 4 i y 4 j z 4k z onde i, j e k são vetores unitários (tamanho (módulo) igual 1) ao longo das direções x, y e z. 40 Ângulos de Torção www.python.org O vetor entre os pontos P1 e P2, aqui chamado de vetor q1, é o vetor subtração, p2 – p1. Em coordenadas cartesianas tem a seguinte expressão: y q1 = (x2 – x1 )i + (y2 – y1 )j + (z2 – z1 )k P4 De forma análoga temos os vetores q2 e q3, como segue: q3 P1 q2 = (x3 – x2 )i + (y3 – y2 )j + (z3 – z2 )k p1 j q3 = (x4 – x3 )i + (y4 – y3 )j + (z4 – z3 )k k q1 p2 P2 q2 P3 i x z 41 Ângulos de Torção www.python.org Para determinarmos o ângulo de torção, precisamos de mais uma definição relacionadas aos vetores, o produto vetorial (x). O produto vetorial entre os vetores q1 e q2 é um terceiro vetor perpendicular ao plano, definido por estes dois vetores, assim, na figura ao lado, temos que o vetor n1 é perpendicular aos vetores q1 e q2 e . O vetor n1 é chamado vetor normal ao plano e é dado pela seguinte equação: q1 q 2 n1 q1 q 2 q1 q 2 q1 q 2 sen y P4 q1xq2 q3 P1 p1 j k q1 p2 n1 P2 q2 P3 i x z as barras em volta dos vetores indicam seu módulo, ou seja, seu tamanho. 42 Ângulos de Torção www.python.org Uma forma alternativa de representarmos o produto vetorial, é a forma cartesiana, definida como segue: y q1x q2 = = (ai + b j + c k) x (d i + e k + f k) P4 q1xq2 O “x” indica o produto vetorial. Podemos obter o produto vetorial a partir do determinante da matriz abaixo. q3 P1 p1 j i j k k a b c d e f q1 p2 n1 P2 q2 P3 i x z 43 Ângulos de Torção www.python.org Calculamos o determinante da seguinte forma: y i j k a b c P4 q1xq2 q3 d e f P1 p1 j q1x q2 = i ( b f - ec) + j (d c - af) + k (a e - bd) k q1 p2 n1 P2 q2 P3 i x z 44 Ângulos de Torção www.python.org Como já vimos na equação 5, o produto escalar entre dois vetores q1 e q2 é dado por: q1 . q2 = |q1||q2| cos y O resultado do produto vetorial é um vetor, enquanto o resultado do produto escalar é um número puro. Vimos, também, que podemos calcular o produto escalar a partir das coordenadas cartesianas dos vetores, como segue: q1 q 2 a.d b.e c. f Onde a, b e c são as coordenadas cartesianas do vetor q1 e d, e, f são as coordenadas do vetor q2. z P4 q1xq2 P1 p1 j k q1 p2 n1 P2 q2xq3 n2 q3 q2 P3 i x 45 Ângulos de Torção www.python.org Os programas que calculam ângulos de torção, usam a geometria da figura ao lado para construir uma equação computacionalmente eficiente, baseada na função arco-tangente, especificamente uma implementação desta função é chamada atan2. Bem, para usamos a função atan2, temos que usar os vetores unitários normais aos planos pelos pontos P1, P2, e P3 e P2, P3 e P4 . Chamando-se n1 o vetor normal ao primeiro plano e n2 vetor normal ao segundo plano temos: n1 q1 q 2 q1 q 2 e n2 q2 q3 q2 q3 P4 q1xq2 P1 q1 n1 P2 q2xq3 n2 q3 q2 P3 46 Ângulos de Torção www.python.org Definimos os vetores unitários pelas equações abaixo: u1 n 2 u3 q2 q2 P4 q1xq2 u 2 u 3 u1 O cosseno e seno de são dados por: cos n1 .u1 sen n1 .u 2 P1 q1 n1 P2 q2xq3 n2 q3 q2 P3 O ângulo é dado por n1 u1 a tan 2 n1 u 2 47 Ângulos de Torção www.python.org Resumindo-se, para o cálculo do ângulo de torção de um sistema de quatro pontos, como o mostrado ao lado, temos os seguintes passos: 1) Determinar os vetores q1, q2 e q3: P4 q1xq2 q1 = (x2 – x1 )i + (y2 – y1 )j + (z2 – z1 )k q2 = (x3 – x2 )i + (y3 – y2 )j + (z3 – z2 )k q3 = (x4 – x3 )i + (y4 – y3 )j + (z4 – z3 )k P1 q1 n1 P2 q2xq3 n2 q3 q2 P3 2) Calcular os produtos vetoriais q1 x q2 e q2 x q3. q1 x q2 q2 x q3 48 Ângulos de Torção www.python.org 3) Calcular as normais aos planos: n1 q1 q 2 q1 q 2 4) Calcular ortogonais: n2 os q2 q3 q2 q3 vetores P4 unitários q1xq2 u1 n 2 P1 q2 u3 q2 q1 n1 P2 u 2 u 3 u1 q2xq3 n2 q3 q2 P3 5) Calcular o ângulo de torção : cos n1 .u1 sen n1 .u 2 n1 u1 n1 u 2 a tan 2 49 Ângulos de Torção (Exemplo 4) www.python.org Exemplo 4. Determine o ângulo de torção , dos planos formados pelos pontos P1, P2, P3 e P4, sabendo-se que as coordenadas dos pontos são as seguintes: p1 8,326 i 10,351 j 0,000k p 2 9,000 i 9,000 j 0,000k p 3 10,325 i 9,000 j 0,000k p 4 11,096 i 7,766 j 0,000k 8.326 10.351 0.000 P1 q1 q2 10.325 9.000 0.000 P3 9.000 9.000 0.000 P2 q3 P4 11.096 7.766 0.000 50 Ângulos de Torção (Exemplo 4) www.python.org Solução Passo 1: Para determinar o ângulo de torção, dos planos formados pelos pontos P1, P2, P3 e P4 , precisamos inicialmente calcular os vetores p, como segue: q1 = (x2 – x1 )i + (y2 – y1 )j + (z2 – z1 )k = (0,674)i + (-1,351)j = 0,674i - 1,351j q2 = (x3 – x2 )i + (y3 – y2 )j + (z3 – z2 )k = (1,351)i + (0 )j = 1,351i q3 = (x4 – x3 )i + (y4 – y3 )j + (z4 – z3 )k = (0,771)i + (-1,234)j = 0,771i -1,234j 51 Ângulos de Torção (Exemplo 4) www.python.org Solução (Continuação) Passo 2: Agora com os vetores q determinados, podemos calcular os produtos vetoriais como segue: q1 x q2 = (0,674i - 1,351j ) x (1,351i) = 1,8252k q2 x q3 = (1,351i) x (0,771i -1,234j) = - 1,6671k Passo 3: Calcularemos as normais aos planos: q1 q 2 1,8252 k n1 k q1 q 2 1,8252 q 2 q 3 - 1,6671k n2 -k q2 q3 1,6671 Regra do produto vetorial: ixi=0 jxj=0 kxk=0 ixj=k jxk=i kxi=j i x k = - j j x i = -k k x j = -i 52 Ângulos de Torção (Exemplo 4) www.python.org Solução (Continuação) Passo 4: Calcularemos os vetores unitários: u1 n 2 -k q 2 1,351i u3 i q 2 1,351 u 2 u 3 u1 i (-k ) j 8.326 10.351 0.000 P1 q1 q2 cos n1 .u1 k k -1 P3 9.000 9.000 0.000 P2 Passo 5: Finalmente o ângulo de torção: 10.325 9.000 0.000 q3 P4 11.096 7.766 0.000 sen n1 .u 2 k j 1 1 a tan 2 180 o 1 53 Ângulos de Torção (Exemplo 5) www.python.org Exemplo 5. Determine o ângulo de torção , dos planos formados pelos pontos P1, P2, P3 e P4, sabendo-se que as coordenadas dos pontos são as seguintes: y p1 i p2 0 P3 p3 j j p4 j k P4 P2 k P1 i x z 54 Ângulos de Torção (Exemplo 5) www.python.org Solução (Continuação) Passo 1: Para determinar o ângulo de torção, dos planos formados pelos pontos P1, P2, P3 e P4 , precisamos inicialmente calcular os vetores p, como segue: q1 = (x2 – x1 )i + (y2 – y1 )j + (z2 – z1 )k = (0 – 1 )i + (0 – 0 )j + (0 – 0 )k = - i q2 = (x3 – x2 )i + (y3 – y2 )j + (z3 – z2 )k = (0 – 0 )i + (1 – 0 )j + (0 – 0 )k = j q3 = (x4 – x3 )i + (y4 – y3 )j + (z4 – z3 )k = (0 – 0 )i + (1 – 1 )j + (1 – 0 )k = k 55 Ângulos de Torção (Exemplo 5) www.python.org Solução (Continuação) Passo 2: Agora com os vetores q determinados, podemos calcular os produtos vetoriais, como segue: q1 x q2 = -i x j = -k q2 x q3 = j x k = i Regra do produto vetorial: ixi=0 jxj=0 kxk=0 ixj=k jxk=i kxi=j i x k = - j j x i = -k k x j = -i Passo 3: Calcularemos as normais aos planos: q1 q 2 - k n1 k q1 q 2 1 q2 q3 i n2 i q2 q3 1 56 Ângulos de Torção (Exemplo 5) www.python.org Solução (Continuação) Passo 4: Calcularemos unitários: os vetores u1 n 2 i y q2 u3 j q2 u 2 u 3 u1 j i -k P3 Passo 5: Finalmente o ângulo de torção: j P4 cos n1 .u1 k i 0 P2 sen n1 .u 2 k k 1 k 1 a tan 2 90 o 0 = P1 i x 90o z 57 Programa: torsion_angle.py www.python.org Ângulo de Torção de Um Sistema com 4 Átomos Programa: torsion_angle.py Resumo Programa que calcula o ângulo de torção em graus para um sistema de quatro pontos (P1,P2,P3,P4). O ângulo de torção é definido por dois planos, o primeiro determinado pelos pontos P1, P2 e P3 e o segundo pelos pontos P2, P3 e P4. O resultado é mostrado na tela em graus. As coordenadas cartesianas dos pontos estarão no próprio código fonte. 58 Diagrama de Ramachandran www.python.org Na cadeia polipeptídica a definição do enovelamento da proteína depende dos ângulos de torção anterior ao carbono alfa, chamado de ângulo fi (phi em inglês) (), e do ângulo de torção após o carbono alfa, chamado ângulo psi (). A análise da rotação desses ângulos levou à identificação de regiões permitidas, onde não há choques entre os átomos, e regiões não-permitidas, onde há choques entre os átomos. i+3 CA N O C CA N CB C CA N CB i+2 i+1 O i 59 Diagrama de Ramachandran www.python.org Gerando-se o gráfico para cada resíduo de aminoácido, o ângulo (fi) e (psi), temos um diagrama bidimensional, onde as regiões permitidas e proibidas são identificáveis, tal diagrama é chamado de diagrama de Ramachandran. A cadeia principal apresenta um terceiro ângulo de torção, chamado ômega (). Este ângulo envolve a ligação parcialmente dupla entre o carbono da carbonila do resíduo de aminoácido i+1, com o nitrogênio do aminoácido i+2, ou seja, a ligação peptídica entre dois resíduos de aminoácido. Devido ao caráter parcialmente duplo desta ligação, não há a liberdade estrutural observada para os ângulos (fi) e (psi). O ângulo (ômega) admite duas situações, trans, onde seu valor é 180o e cis, onde seu valore é 0o. i+3 CA N O C CA N CB C CA N CB i+2 i+1 O i 60 Diagrama de Ramachandran Os eixos, fi () e psi (), no diagrama de Ramachandran, variam de -180o a +180o, as regiões no interior das áreas demarcadas no gráfico são regiões permitidas. Fica claro, a partir da análise do gráfico, que a área não permitida é maior do que a permitida. As regiões, não permitidas são possíveis de ocupação para a glicina, pois sua cadeia lateral restringe-se a um átomo de hidrogênio, permitindo mais liberdade para os ângulos (fi) e (psi). (o) www.python.org (o) 61 Diagrama de Ramachandran www.python.org Em 1993 Laskowski e col. elaboraram o programa Procheck que define 4 regiões no diagrama de Ramachandran, são elas: região permitida (indicada em vermelho), região adicionalmente permitida (amarelo), região generosamente permitida (amarelo claro) e região proibida (branco). O programa Procheck usa dados da estrutura cristalográfica de 118 proteínas resolvidas a uma resolução melhor que 2,0 Å, para definir as regiões permitidas e proibidas do diagrama. Referência:Laskowski, R.A.; MacArthur, M.W., Moss, D.S., Thornton, J.M. Procheck: a program to check the stereochemical quality of protein structures. J. of Appl. Cryst. 26(2), 283-291, (1993). 62 Diagrama de Ramachandran www.python.org O programa Procheck indica as glicinas como triângulos, e estas podem ocupar qualquer região do diagrama de Ramachandran, visto que sua cadeia lateral restringe-se a um hidrogênio, que permite maior flexibilidade da cadeia principal. Os resíduos localizados nas regiões generosamente permitida e proibida são indicados em vermelho. Na figura ao lado o resíduo Val116 está na região generosamente permitida do gráfico. 63 Diagrama de Ramachandran www.python.org O Procheck oferece diversas informações, em outros gráficos, ou mesmo no gráfico principal. Uma delas é a estatística geral dos ângulos (fi) e (psi), indicando a porcentagem de resíduos de aminoácido em cada região, na estrutura 1WE2 (Pereira et al., 2004) temos 92,7 % dos resíduos da região permitida, 6,6 % na região adicionalmente permitida, e 0,7 % na região adicionalmente permitida. Para estruturas resolvidas a resolução acima de 2,0 Å espera-se acima de 90 % dos resíduos nas regiões permitidas. Pereira, J.H., Oliveira, J. S., Canduri, F., Dias, M.V.B., Palma, M. S., Basso, L. A., Santos, D. S., & De Azevedo, W.F. Structure of shikimate kinase from Mycobacterium tuberculosis reveals the binding of shikimic acid. Acta Crystallogr. Sect. D.-Biol. Crystallogr. 60 , 2310-2319, 2004. 64 Diagrama de Ramachandran www.python.org A análise da qualidade estereoquímica de modelos de proteínas é uma ferramenta poderosa na análise estrutural, sejam obtidos experimentalmente ou obtidos por modelagem molecular. O Programa Procheck facilita a análise dos modelos estruturais. Há versões do Procheck para Mac OS X, Windows e Linux, bem como, sites dedicados a análise on-line de proteínas. 65 Diagrama de Ramachandran www.python.org Como exemplo do uso do programa Procheck na análise da qualidade estereoquímica de modelos estruturais de proteínas, considere a proteína humana Purina Nucleosídeo Fosforilase (PNP, EC. 2.4.2.1). A PNP foi resolvida inicialmente em 1990 por Ealick et al. 1990 (código de acesso no PDB: 1ULA), a 2,75 Å de resolução. Uma nova estrutura foi refinada a 2,3 Å (De Azevedo et al., 2003) (Código de acesso PDB: 1M73). Referências: De Azevedo, W. F., Canduri, F., Santos, D. M., Silva, R. G., Oliveira, J. S., Carvalho, L. P. S., Basso, L. A., Mendes, M. A., Palma, M. S., and Santos, D. S. Crystal structure of human purine nucleoside phosphorylase at 2.3 A resolution. Biochem. Biophys. Res. Commun., 308(3), 545-552, 2003. Ealick, S. E., Rule, S. A., Carter, D. C., Greenhough, T. J., Babu, Y. S., Cook, W. J., Habash, J., Helliwell, J. R., Stoeckler, J. D., Parks, R. E., Jr., Chen, S, -F., and Bugg, C. E. (1990). Three-dimensional structure of human erythrocytic purine nucleoside phosphorylase at 3.2Å resolution. J. Biol. Chem. 265(3), 1812-1820. 66 Diagrama de Ramachandran www.python.org 67 Diagrama de Ramachandran www.python.org A análise dos dois diagramas de Ramachandran, indica claramente que a estrutura de coordenadas atômicas 1M73 apresenta melhor estatística estereoquímica. Na realidade, uma análise detalhada da estrutura tridimensional, resolvida de 2,3 Å, indicou que a estrutura 1ULA apresentava diversos erros, inclusive no sítio ativo. A estrutura 1ULA previa a participação de Lys244 no sítio ativo da enzima, a estrutura a mais alta resolução revelou que esta lisina estava a mais de 9 Å da posição inicialmente prevista. A análise do gráfico de Ramachandran, por si só, não valida a estrutura de uma proteína, mas é uma ferramenta valiosa na análise da estrutura 3D. 68 Diagrama de Ramachandran www.python.org O programa VMD tem a opção de gerar o diagrama de Ramachandran para uma estrutura de proteína carregada no sistema. Após carregar um arquivo PDB com a estrutura de uma proteína clique nas seguintes opções no VMD Main: Extensions>Analysis>Ramachandran Plot. Você terá o gráfico de Ramachandran na tela, clique em Molecule para selecionar o arquivo PDB para o qual será gerado o diagrama. Depois de gerado o digrama teremos o gráfico, como mostrado abaixo. Cada quadrado amarelo indica os ângulos phi e psi de cada aminoácido presente na estrutura. Se clicarmos sobre o quadrado amarelo teremos o valor dos ângulos de torção mostrados na tela. 69 Programa: plot_Rama1.py www.python.org Diagrama de Ramachandran Programa: plot_Rama1.py Resumo Programa que lê um arquivo PDB e gera o gráfico de Ramachandran. 70 Referências www.python.org -BRESSERT, Eli. SciPy and NumPy. Sebastopol: O’Reilly Media, Inc., 2013. 56 p. -DAWSON, Michael. Python Programming, for the absolute beginner. 3ed. Boston: Course Technology, 2010. 455 p. -HETLAND, Magnus Lie. Python Algorithms. Mastering Basic Algorithms in the Python Language. Nova York: Springer Science+Business Media LLC, 2010. 316 p. -IDRIS, Ivan. NumPy 1.5. An action-packed guide dor the easy-to-use, high performance, Python based free open source NumPy mathematical library using real-world examples. Beginner’s Guide. Birmingham: Packt Publishing Ltd., 2011. 212 p. -KIUSALAAS, Jaan. Numerical Methods in Engineering with Python. 2ed. Nova York: Cambridge University Press, 2010. 422 p. -LANDAU, Rubin H. A First Course in Scientific Computing: Symbolic, Graphic, and Numeric Modeling Using Maple, Java, Mathematica, and Fortran90. Princeton: Princeton University Press, 2005. 481p. -LANDAU, Rubin H., PÁEZ, Manuel José, BORDEIANU, Cristian C. A Survey of Computational Physics. Introductory Computational Physics. Princeton: Princeton University Press, 2008. 658 p. -LUTZ, Mark. Programming Python. 4ed. Sebastopol: O’Reilly Media, Inc., 2010. 1584 p. -MODEL, Mitchell L. Bioinformatics Programming Using Python. Sebastopol: O’Reilly Media, Inc., 2011. 1584 p. -TOSI, Sandro. Matplotlib for Python Developers. Birmingham: Packt Publishing Ltd., 2009. 293 p. Última atualização: 10 de julho de 2015. 71