Reputation: 69
In one of my scripts, I utilized the following block of code to query for the ID of a protein using another type of ID:
import os
import sys
import urllib.request
uniprot = 'A0A0M3KKX3'
url = 'https://www.uniprot.org/uploadlists/'
params = {
'from': 'ACC',
'to': 'PDB_ID',
'format': 'tab',
'query': uniprot,
'species': 'human'
}
dat = urllib.parse.urlencode(params)
dat = dat.encode('utf-8')
req = urllib.request.Request(url, dat)
with urllib.request.urlopen(req) as f:
response = f.read()
For the past few months, code involving this method has worked reliably, allowing me to build my algorithm on top of these features. However, as of last night, running the same code, I received the following error:
Traceback (most recent call last):
File "\\wsl.localhost\Ubuntu\home\defrondevillec\FASTAtest.py", line 21, in <module>
with urllib.request.urlopen(req) as f:
File "C:\Users\chris\AppData\Local\Programs\Python\Python310\lib\urllib\request.py", line 216, in urlopen
return opener.open(url, data, timeout)
File "C:\Users\chris\AppData\Local\Programs\Python\Python310\lib\urllib\request.py", line 525, in open
response = meth(req, response)
File "C:\Users\chris\AppData\Local\Programs\Python\Python310\lib\urllib\request.py", line 634, in http_response
response = self.parent.error(
File "C:\Users\chris\AppData\Local\Programs\Python\Python310\lib\urllib\request.py", line 563, in error
return self._call_chain(*args)
File "C:\Users\chris\AppData\Local\Programs\Python\Python310\lib\urllib\request.py", line 496, in _call_chain
result = func(*args)
File "C:\Users\chris\AppData\Local\Programs\Python\Python310\lib\urllib\request.py", line 643, in http_error_default
raise HTTPError(req.full_url, code, msg, hdrs, fp)
urllib.error.HTTPError: HTTP Error 405: Not Allowed
How would I go about fixing this issue?
Upvotes: 2
Views: 546
Reputation: 9954
You can now use the Unipressed package by Michael Milton (@multimeric) to do ID mapping in Python, see the announcement. This package also works with UniProt's new in 2022 REST API.
Example from original post using Unipressed:
from unipressed import IdMappingClient
request = IdMappingClient.submit(
source="UniProtKB_AC-ID", dest="PDB", ids={"A0A0M3KKX3"}
)
list(request.each_result())
Result:
[{'from': 'A0A0M3KKX3', 'to': '4U7N'},
{'from': 'A0A0M3KKX3', 'to': '4U7O'},
{'from': 'A0A0M3KKX3', 'to': '4ZKI'}]
See an example of using it to do ID mapping of three human genes to UniProt identifier / accession code here. That post also has links for more information about the Unipressed package and advice for working out source
and destination (dest
) details.
See more examples of using Unipressed to access Uniprot's new REST API here in my reply to Biostar's post 'Accessing UNIPROT using REST API', and at the bottom here includes making a Pandas dataframe from the 'from - to' results.
UPDATE: I made a repo that allows running this and other Unipressed examples right in your browser without installing anything on your machine. To get started, go here and click any 'launch binder
' badge.
Upvotes: 0
Reputation: 981
I've just hit the same issue - Uniprot have launched a new website and series of services. For now the old ones are available at legacy.uniprot.org
Use https://legacy.uniprot.org/uploadlists/
as the URL in your code. This is working in my code for a similar query (uniprotID -> gene name)
Probably best to migrate to the new ID Mapping service, which is documented here: https://www.uniprot.org/help/id_mapping
You are now required to make an ID Mapping request, which returns a job ID, then poll for the result, there is some sample python code at the bottom of the docs: https://www.uniprot.org/help/id_mapping#python-example (reproduced below)
import requests
import time
import json
POLLING_INTERVAL = 3
API_URL = "https://rest.uniprot.org"
def submit_id_mapping(fromDB, toDB, ids):
r = requests.post(
f"{API_URL}/idmapping/run", data={"from": fromDB, "to": toDB, "ids": ids},
)
r.raise_for_status()
return r.json()["jobId"]
def get_id_mapping_results(job_id):
while True:
r = requests.get(f"{API_URL}/idmapping/status/{job_id}")
r.raise_for_status()
job = r.json()
if "jobStatus" in job:
if job["jobStatus"] == "RUNNING":
print(f"Retrying in {POLLING_INTERVAL}s")
time.sleep(POLLING_INTERVAL)
else:
raise Exception(job["jobStatus"])
else:
return job
job_id = submit_id_mapping(
fromDB="UniProtKB_AC-ID", toDB="ChEMBL", ids=["P05067", "P12345"]
)
results = get_id_mapping_results(job_id)
print(json.dumps(results, indent=2))
Upvotes: 1