Neste trabalho utilizamos dois serviços disponibilizados pelo site UniProt:
A lista dos serviços disponibilizados pelo site pode ser encontrado aqui.
As funções apresentadas aqui podem ser encontradas no módulo util.www
.
A UniProt oferece um serviço de mapeamento de identificadores entre diferentes bases de dados (mais informação aqui). Neste caso, mapeamos de Entrez Gene (GeneID) (P_ENTREZGENEID) para UniProtKB ID (ID).
def gene_ids_to_uniprot_ids(ids):
"""
Mapeia a lista de gene ids passada como argumento para uniprot ids.
Retorna um dictionário em que as chaves são gene_id e os valores
são uniprot_id.
"""
url = "http://www.uniprot.org/mapping/"
query = " ".join(ids)
data = {
"format": "tab",
"from": "P_ENTREZGENEID",
"to": "ACC",
"query": query
}
# HTTP POST
response = requests.post(
url,
data=data
)
result = {}
# ignorar a primeira linha
for row in response.text.splitlines()[1:]:
gene_id, uniprot_id = row.split("\t")
result[gene_id] = uniprot_id
return result
Utilizamos ainda outro serviço de extração de informação em batch. Criámos uma função que dada uma lista de uniprot_id retorna um dicionário que mapeia estes id para um outro dicionário com a informação desejada.
def fetch_uniprots(ids):
"""
Faz download da informação presente no site uniprot
em formato xml dada uma lista de ids uniprot.
"""
url = "http://www.uniprot.org/uploadlists/"
max_retries = 100
# Cada pedido à uniprot vai no máximo com 1000 ids.
queries = [ids[i:i+1000] for i in range(0, len(ids), 1000)]
files = []
for query in queries:
query_all = " ".join(query)
md5 = util.md5(query_all)
data = {
"format": "xml",
"from": "ID",
"to": "ACC",
"uploadQuery": query_all,
"jobId": md5
}
done = False
attempt = 0
# enquanto não acabar ou não esgotar as tentativas todas
while not done and attempt < max_retries:
# HTTP POST
response = requests.post(
url,
data=data
)
if response.status_code == 200:
# Gravar o xml
file_path = "/tmp/" + md5 + ".xml"
rw.write_file(response.text, file_path)
files.append(file_path)
done = True
attempt += 1
if not done:
print("Não consegui fazer download de " + str(query))
uniprots = {}
for file_path in files:
tree = parse_xml(file_path, add_root=True, start=2, end=1)
entries = tree.findall(".//entry")
for entry in entries:
(uniprot_id, info) = extract_uniprot_info(entry)
uniprots[uniprot_id] = info
return uniprots
Esta função utiliza duas outras funções:
md5
definida no util.util
(a descrição deste módulo pode ser encontrada aqui).extract_uniprot_info
definida no módulo util.www
:def extract_uniprot_info(entry):
"""
Extrai a informação que necessitamos da uniprot.
"""
# dataset
ds = entry.get("dataset")
if ds == "Swiss-Prot":
status = "reviewed"
elif ds == "TrEMBL":
status = "unreviewed"
else:
print("Não conheço o dataset " + ds)
# accessions
accessions = [a.text for a in entry.findall(".//accession")]
accession = accessions[0]
# short name
short_name = entry.find("name").text
# full name
full_name = entry.find(".//fullName").text
# ec number
ec_number = entry.find(".//ecNumber")
if ec_number != None:
ec_number = ec_number.text
# organism
organisms = entry.findall(".//name[@type='scientific']")
if len(organisms) == 1:
organism = organisms[0].text
else:
print("Encontrei um número de organismos diferente de 1: ", accession)
organism = None
# encontrar o texto função que costuma estar no início da
# página da uniprot
comment_functions = [c.find("text").text for c in entry.findall(".//comment[@type='function']")]
# cofator
cofactors = [c.find("cofactor").find("name").text for c in entry.findall(".//comment[@type='cofactor']")]
# patologias
pathologies = [c.find("disease").find("name").text for c in entry.findall(".//comment[@type='disease']")]
# PDB
pdbs = []
PDB = entry.findall(".//dbReference[@type='PDB']")
for pdb in PDB:
id = pdb.get("id")
method = pdb.find("property[@type='method']")
chains = pdb.find("property[@type='chains']")
if (not method == None) and (not chains == None):
method = method.get("value")
chains = chains.get("value")
d = {}
d["id"] = id
d["method"] = method
d["chains"] = chains
pdbs.append(d)
# encontrar GO - Molecular Function
# e GO - Biological process
molecular_functions = []
biological_processes = []
locations = []
GO = entry.findall(".//dbReference[@type='GO']")
for go in GO:
value = go.find("property[@type='term']").get("value")
is_molecular_function = value.startswith("F:")
is_biological_process = value.startswith("P:")
is_location = value.startswith("C:")
value = value[2:]
if is_molecular_function:
molecular_functions.append(value)
elif is_biological_process:
biological_processes.append(value)
elif is_location:
locations.append(value)
# sequência
sequences = entry.findall(".//sequence[@length]")
assert len(sequences) == 1
sequence = sequences[0].text.replace("\n", "")
length = int(sequences[0].get("length"))
mass = int(sequences[0].get("mass"))
# modified residue
mrs = []
res = entry.findall(".//feature[@type='modified residue']")
for r in res:
desc = r.get("description")
position = r.find("location").find("position").get("position")
mrs.append({"desc": desc, "position": position})
dictionary = {}
dictionary["status"] = status
dictionary["accessions"] = accessions
dictionary["short_name"] = short_name
dictionary["product"] = full_name
dictionary["EC_number"] = ec_number
dictionary["organism"] = organism
dictionary["comment_functions"] = comment_functions
dictionary["cofactors"] = cofactors
dictionary["pathologies"] = pathologies
dictionary["pdbs"] = pdbs
dictionary["molecular_functions"] = molecular_functions
dictionary["biological_processes"] = biological_processes
dictionary["locations"] = locations
dictionary["translation"] = sequence
dictionary["length"] = length
dictionary["mass"] = mass
dictionary["modified_residues"] = mrs
return (accession, dictionary)