Post on 06-May-2020
© 2
01
7 D
r. W
alter
F.
de
Aze
ve
do
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
www.python.org
1
def generate_Fibonacci(number_of_elements):
"""This function generates the Fibonacci sequence"""
fibonacci = []
fibonacci.append(1)
fibonacci.append(1)
# Generate Fibonacci sequence
for i in range(2,number_of_elements):
fibonacci.append(fibonacci[i-2] + fibonacci[i-1])
return fibonacci
Vimos o programa fibonacci.py, que por meio da função generate_Fibonacci() gera a
sequência de Fibonacci. Iremos usar a estrutura deste código para montar um método
da classe Fibo().
fibonacci2.py
www.python.org
2
# Program to calculate Fibonacci sequence
class Fibo(object):
"""Class to calculate Fibonacci sequence"""
# Define constructor method
def __init__(self,n):
# Define attributes
self.n = n
self.fibonacci = []
# Define generate_Fibonacci() method
def generate_Fibonacci(self):
"""This method generates the Fibonacci sequence"""
# Set up the first two elements of Fibonacci sequence
self.fibonacci.append(1)
self.fibonacci.append(1)
# Generate Fibonacci sequence
for i in range(2,self.n):
self.fibonacci.append(self.fibonacci[i-2] + self.fibonacci[i-1])
# Define show_sequence() method
def show_sequence(self):
"""This method shows a list on screen"""
# Looping through self.fibonacci
for line in self.fibonacci:
print(line)
# main program
def main():
# Instantiating an object of the Fibo() class and assign it to f
f = Fibo(10)
# Invoking generate_Fibonacci() method
f.generate_Fibonacci()
# Invoking show_sequence() method
f.show_sequence()
main()
Inicialmente definimos a classe Fibo(). O principal método da classe Fibo() é o método
generate_Fibonacci(). Usamos a mesma estrutura do código da função
generate_Fibonacci().
fibonacci2.py
www.python.org
3
# Program to calculate Fibonacci sequence
class Fibo(object):
"""Class to calculate Fibonacci sequence"""
# Define constructor method
def __init__(self,n):
# Define attributes
self.n = n
self.fibonacci = []
# Define generate_Fibonacci() method
def generate_Fibonacci(self):
"""This method generates the Fibonacci sequence"""
# Set up the first two elements of Fibonacci sequence
self.fibonacci.append(1)
self.fibonacci.append(1)
# Generate Fibonacci sequence
for i in range(2,self.n):
self.fibonacci.append(self.fibonacci[i-2] + self.fibonacci[i-1])
# Define show_sequence() method
def show_sequence(self):
"""This method shows a list on screen"""
# Looping through self.fibonacci
for line in self.fibonacci:
print(line)
# main program
def main():
# Instantiating an object of the Fibo() class and assign it to f
f = Fibo(10)
# Invoking generate_Fibonacci() method
f.generate_Fibonacci()
# Invoking show_sequence() method
f.show_sequence()
main()
Abaixo temos em destaque a função e o método generate_Fibonacci(), onde vemos
claramente a equivalência entre os dois códigos. def generate_Fibonacci(number_of_elements):
"""This function generates the Fibonacci sequence"""
fibonacci = []
fibonacci.append(1)
fibonacci.append(1)
# Generate Fibonacci sequence
for i in range(2,number_of_elements):
fibonacci.append(fibonacci[i-2] + fibonacci[i-1])
return fibonacci
fibonacci2.py
www.python.org
4
# Program to calculate Fibonacci sequence
class Fibo(object):
"""Class to calculate Fibonacci sequence"""
# Define constructor method
def __init__(self,n):
# Define attributes
self.n = n
self.fibonacci = []
# Define generate_Fibonacci() method
def generate_Fibonacci(self):
"""This method generates the Fibonacci sequence"""
# Set up the first two elements of Fibonacci sequence
self.fibonacci.append(1)
self.fibonacci.append(1)
# Generate Fibonacci sequence
for i in range(2,self.n):
self.fibonacci.append(self.fibonacci[i-2] + self.fibonacci[i-1])
# Define show_sequence() method
def show_sequence(self):
"""This method shows a list on screen"""
# Looping through self.fibonacci
for line in self.fibonacci:
print(line)
# main program
def main():
# Instantiating an object of the Fibo() class and assign it to f
f = Fibo(10)
# Invoking generate_Fibonacci() method
f.generate_Fibonacci()
# Invoking show_sequence() method
f.show_sequence()
main()
A principal diferença é que não usamos o comando return no método. Podemos
acessar a sequência por meio do atributo self.fibonacci, definido no método construtor.
O self.fibonacci() também é acessado no método show_sequence().
fibonacci2.py
www.python.org
5
# Program to calculate Fibonacci sequence
class Fibo(object):
"""Class to calculate Fibonacci sequence"""
# Define constructor method
def __init__(self,n):
# Define attributes
self.n = n
self.fibonacci = []
# Define generate_Fibonacci() method
def generate_Fibonacci(self):
"""This method generates the Fibonacci sequence"""
# Set up the first two elements of Fibonacci sequence
self.fibonacci.append(1)
self.fibonacci.append(1)
# Generate Fibonacci sequence
for i in range(2,self.n):
self.fibonacci.append(self.fibonacci[i-2] + self.fibonacci[i-1])
# Define show_sequence() method
def show_sequence(self):
"""This method shows a list on screen"""
# Looping through self.fibonacci
for line in self.fibonacci:
print(line)
# main program
def main():
# Instantiating an object of the Fibo() class and assign it to f
f = Fibo(10)
# Invoking generate_Fibonacci() method
f.generate_Fibonacci()
# Invoking show_sequence() method
f.show_sequence()
main()
No programa principal, criamos um objeto da classe Fibo() que é atribuído à variável f.
Temos como argumento o inteiro 10, que indica o número de elementos da sequência
de Fibonacci.
fibonacci2.py
www.python.org
6
# Program to calculate Fibonacci sequence
class Fibo(object):
"""Class to calculate Fibonacci sequence"""
# Define constructor method
def __init__(self,n):
# Define attributes
self.n = n
self.fibonacci = []
# Define generate_Fibonacci() method
def generate_Fibonacci(self):
"""This method generates the Fibonacci sequence"""
# Set up the first two elements of Fibonacci sequence
self.fibonacci.append(1)
self.fibonacci.append(1)
# Generate Fibonacci sequence
for i in range(2,self.n):
self.fibonacci.append(self.fibonacci[i-2] + self.fibonacci[i-1])
# Define show_sequence() method
def show_sequence(self):
"""This method shows a list on screen"""
# Looping through self.fibonacci
for line in self.fibonacci:
print(line)
# main program
def main():
# Instantiating an object of the Fibo() class and assign it to f
f = Fibo(10)
# Invoking generate_Fibonacci() method
f.generate_Fibonacci()
# Invoking show_sequence() method
f.show_sequence()
main()
Em seguida chamamos o método generate_Fibonacci() e por último o método
show.sequence(), que mostra a sequência na tela.
fibonacci2.py
www.python.org
7
1
1
2
3
5
8
13
21
34
55
Abaixo temos o resultado da execução do código fibonacci2.py.
fibonacci2.py
www.python.org
8
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.
Gráfico de B-factor de um arquivo PDB
Programa: bfactor_plot.py
Programa: bfactor_plot.py
www.python.org
9
10
Para o programa bfactor_plot.py, teremos que ler o arquivo PDB e extrair informações
sobre o número de resíduos (line[22:26]) e o fator de vibração térmica (line[61:65]).
ATOM 1 N MET A 1 101.710 112.330 93.759 1.00 48.54 N
Colunas de 1-6 para string com ATOM ou HETATM, é atribuída à variável line[0:6]
Colunas de 7-11 para a ordem do átomo, é atribuída à variável line[6:11]
Colunas de 14-15 para o nome do átomo, é atribuída à variável line[13:15]
Colunas de 18-20 para o nome do aminoácido (ou ligante, ou HOH), é atribuída à variável line[17:20]
Coluna 22 para o identificador da cadeia, é atribuída à variável line[21:22]
Colunas 23-26 para o número do resíduo, é atribuída à variável line[22:26]
Colunas 32-53 para as coordenadas atômicas, são atribuídas às variáveis
line[30:38], line[38:46], line[46:54]
Colunas 57-60 para a ocupação, é atribuída à variável line[56:60]
Colunas 62-65 para o fator de vibração térmica, é atribuída à variável line[61:65]
Programa: bfactor_plot.py
www.python.org
# Main program
def main():
# 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)
main()
11
No programa principal, temos a função read_PDB(), que retorna a lista de átomos. Para
calcularmos os fatores de vibração térmica médios, para cada porção da estrutura,
temos a 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(). Esta 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.
Programa: bfactor_plot.py
www.python.org
def read_file_name():
"""Function to read file name"""
my_file = input("Type input file name => ")
# Returns input file name
return my_file
def read_PDB():
"""Function to read a PDB file"""
# Sets initial list
my_atoms = []
# Calls function read_file_name()
input_file_name = read_file_name()
# Opens PDB file
my_fo = open(input_file_name,"r")
# Looping through PDB file content
for line in my_fo:
if line[0:6] == "ATOM " or line[0:6] == "HETATM":
my_atoms.append(line)
my_fo.close()
return my_atoms 12
O código da função
read_PDB() está mostrado
ao lado. Inicialmente é
criada uma lista vazia que
é atribuída à variável
my_atoms. Em seguida, é
feita a chamada da função
read_file_name(), que
retorna o nome do arquivo
PDB a ser lido que é
atribuído à variável
input_file_name.
Programa: bfactor_plot.py
www.python.org
def read_file_name():
"""Function to read file name"""
my_file = input("Type input file name => ")
# Returns input file name
return my_file
def read_PDB():
"""Function to read a PDB file"""
# Sets initial list
my_atoms = []
# Calls function read_file_name()
input_file_name = read_file_name()
# Opens PDB file
my_fo = open(input_file_name,"r")
# Looping through PDB file content
for line in my_fo:
if line[0:6] == "ATOM " or line[0:6] == "HETATM":
my_atoms.append(line)
my_fo.close()
return my_atoms 13
Posteriormente o arquivo
PDB é aberto e o conteúdo
atribuído à variável my_fo.
Depois o conteúdo é lido
num loop for. No loop
selecionamos as linhas que
iniciam com “ATOM “ ou
“HETATM”. No final a
função retorna uma lista
com todos os átomos
(my_atoms).
Programa: bfactor_plot.py
www.python.org
def calculate_bfactors(list_of_atoms_in):
"""Function to calculate average B-factor for each residue"""
import numpy as np
# Calculates the number of atoms in the list_of_atoms_in
count_atoms = len(list_of_atoms_in)
bfactor = np.zeros(count_atoms)
residues = np.zeros(count_atoms,int)
bfactor_res = np.zeros(999)
# To have different number of residue for the first iteration
former_res = -9999
new_res = -9998
# Sets count_res and count_atoms to zero
count_res = 0
count_atoms = 0
14
A função calculate_bfactors(my_list_of_atoms) tem como parâmetro a lista de átomos.
Como a função é longa, dividiremos em vários slides.
Programa: bfactor_plot.py
www.python.org
def calculate_bfactors(list_of_atoms_in):
"""Function to calculate average B-factor for each residue"""
import numpy as np
# Calculates the number of atoms in the list_of_atoms_in
count_atoms = len(list_of_atoms_in)
bfactor = np.zeros(count_atoms)
residues = np.zeros(count_atoms,int)
bfactor_res = np.zeros(999)
# To have different number of residue for the first iteration
former_res = -9999
new_res = -9998
# Sets count_res and count_atoms to zero
count_res = 0
count_atoms = 0
15
Inicialmente criamos arrays e contadores de átomos e resíduos, como indicado abaixo.
Programa: bfactor_plot.py
www.python.org
# Looping through list_of_atoms_in
for line in list_of_atoms_in:
if former_res == new_res:
bfactor_res[count_atoms] = float(line[61:65])
new_res = int(line[22:26])
count_atoms += 1
else:
new_res = int(line[22:26])
former_res = new_res
if count_res > 0:
bfactor[count_res] = bfactor_res[0:count_atoms].mean()
residues[count_res] = count_res
count_res += 1
count_atoms = 0
else:
count_res = int(line[22:26]) # Allows to get first residue
# Returns arrays
return residues[0:count_res],bfactor[0:count_res]
16
Depois temos um loop for, para a leitura dos átomos. Dentro do loop verificamos se o
número do resíduo muda, o que indica que temos um novo resíduo.
Programa: bfactor_plot.py
www.python.org
# Looping through list_of_atoms_in
for line in list_of_atoms_in:
if former_res == new_res:
bfactor_res[count_atoms] = float(line[61:65])
new_res = int(line[22:26])
count_atoms += 1
else:
new_res = int(line[22:26])
former_res = new_res
if count_res > 0:
bfactor[count_res] = bfactor_res[0:count_atoms].mean()
residues[count_res] = count_res
count_res += 1
count_atoms = 0
else:
count_res = int(line[22:26]) # Allows to get first residue
# Returns arrays
return residues[0:count_res],bfactor[0:count_res]
17
Quando terminamos de ler um resíduo, calculamos a média dos B-factors. Usamos o
.mean(), aplicado ao array bfactor_res[0:count_res], para obter o valor médio
Programa: bfactor_plot.py
www.python.org
# Looping through list_of_atoms_in
for line in list_of_atoms_in:
if former_res == new_res:
bfactor_res[count_atoms] = float(line[61:65])
new_res = int(line[22:26])
count_atoms += 1
else:
new_res = int(line[22:26])
former_res = new_res
if count_res > 0:
bfactor[count_res] = bfactor_res[0:count_atoms].mean()
residues[count_res] = count_res
count_res += 1
count_atoms = 0
else:
count_res = int(line[22:26]) # Allows to get first residue
# Returns arrays
return residues[0:count_res],bfactor[0:count_res]
18
Restringimos o array para a faixa bfactor_res[0:count_res], para considerarmos só a
faixa de valores lidos. Caso contrário teríamos zeros para interferir na média.
Programa: bfactor_plot.py
www.python.org
# Looping through list_of_atoms_in
for line in list_of_atoms_in:
if former_res == new_res:
bfactor_res[count_atoms] = float(line[61:65])
new_res = int(line[22:26])
count_atoms += 1
else:
new_res = int(line[22:26])
former_res = new_res
if count_res > 0:
bfactor[count_res] = bfactor_res[0:count_atoms].mean()
residues[count_res] = count_res
count_res += 1
count_atoms = 0
else:
count_res = int(line[22:26]) # Allows to get first residue
# Returns arrays
return residues[0:count_res],bfactor[0:count_res]
19
Por último, a função retorna os arrays residues[0:count_res],bfactor[0:count_res] .
Programa: bfactor_plot.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: # looping through all atoms in the list
if line[0:6] == "ATOM ":
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 20
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.
Programa: bfactor_plot.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: # looping through all atoms in the list
if line[0:6] == "ATOM ":
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 21
Depois chamamos a
função calculate_bfators(),
para cada lista de átomos.
Esses valores de B-factors
são atribuídos a um novo
array com quatro colunas
(bf). 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.
Programa: bfactor_plot.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
22
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
do loop.
Programa: bfactor_plot.py
www.python.org
Abaixo temos o resultado de rodarmos o código para o arquivo 1kxy.pdb.
23
Programa: bfactor_plot.py
www.python.org
Type input file name => 1kxy.pdb
Exercício de Programação
www.python.org
Pegue o programa bfactor_plot.py e use o paradigma de programação orientada a
objeto para gerar um novo código. O novo programa será chamado bfactor_plot2.py .
24
Author
I graduated in Physics (BSc in Physics) at University of Sao Paulo (USP) in 1990. I
completed a Master Degree in Applied Physics also at USP (1992), working under
supervision of Prof. Yvonne P. Mascarenhas, the founder of crystallography in Brazil.
My dissertation was about X-ray crystallography applied to organometallics compounds
(De Azevedo Jr. et al.,1995). During my PhD I worked under supervision of Prof. Sung-Hou
Kim (University of California, Berkeley. Department of Chemistry), on a split PhD program
with a fellowship from Brazilian Research Council (CNPq)(1993-1996). My PhD was
about the crystallographic structure of CDK2 (De Azevedo Jr. et al., 1996).
In 1996, I returned to Brazil. In April 1997, I finished my PhD and moved to Sao Jose do
Rio Preto (SP, Brazil) (UNESP) and worked there from 1997 to 2005. In 1997, I started the Laboratory of
Biomolecular Systems- Department of Physics-UNESP - São Paulo State University. In 2005, I moved to Porto
Alegre/RS (Brazil), where I am now. My current position is coordinator of the Laboratory of Computational
Systems Biology at Pontifical Catholic University of Rio Grande do Sul (PUCRS). My research interests are
focused on application of computer simulations to analyze protein-ligand interactions. I'm also interested in the
development of biological inspired computing and machine learning algorithms. We apply these algorithms to
molecular docking simulations, protein-ligand interactions and other scientific and technological problems. I
published over 160 scientific papers about protein structures and computer simulation methods applied to the
study of biological systems (H-index: 36). These publications have over 4000 citations. I am editor for the following
journals:
-BRESSERT, Eli. SciPy and NumPy. Sebastopol: O’Reilly Media, Inc., 2013. 57 p. Link
-DAWSON, Michael. Python Programming, for the Absolute Beginner. 3ed. Boston: Course Technology, 2010. 455 p.
-HACKELING G. Mastering Machine Learning with scikit-learn. Birmingham: Packt Publishing Ltd., 2014. 221 p. Link
-HETLAND, Magnus Lie. Python Algorithms. Mastering Basic Algorithms in the Python Language. 2ed. Nova York: Springer
Science+Business Media LLC, 2010. 294 p. Link
-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.
Link
-LUTZ, Mark. Programming Python. 4ed. Sebastopol: O’Reilly Media, Inc., 2010. 1584 p. Link
-TOSI, Sandro. Matplotlib for Python Developers. Birmingham: Packt Publishing Ltd., 2009. 293 p. Link
Última atualização: 4 de novembro de 2017.
Referências
www.python.org
26