I wonder if there is a simpler solution recently? (and hopefully, I can solve it within the scope of python. )
A simpler solution, I don't know... but this is at least one Python solution using Biopython's ELink method via NCBI's Entrez E-utils.
The Biopython library is flexible enough (they have an in-depth tutorial worth reading) to modify the code below to to fit project-specific needs. For example, the mapping between snp id and gene id is lost with this bulk request method.
from Bio import Entrez
Entrez.email = "youremail@gmail.com"
snp_ids = ["rs8179065",
"rs12899845",
"rs8179066",
"rs80357332",
"rs80356920"]
record = Entrez.read(Entrez.elink(dbfrom="snp",
id=",".join(snp_ids).replace('rs', ''),
db="gene"))
This returns a record
object
[{'LinkSetDb': [{'DbTo': 'gene', 'LinkName': 'snp_gene', 'Link': [{'Id': '374654'}, {'Id': '90381'}, {'Id': '672'}]}], 'ERROR': [], 'LinkSetDbHistory': [], 'DbFrom': 'snp', 'IdList': ['8179065', '8179066', '12899845', '80356920', '80357332']}]
which contains several iterable fields -- 'Link' has a list of the Gene UID's that can be converted to names using ESummary
.
for gene_id in record[0]['LinkSetDb'][0]['Link']:
handle = Entrez.esummary(db="gene", id=gene_id['Id'])
uid_record = Entrez.read(handle)
handle.close()
uid_summary = uid_record["DocumentSummarySet"]['DocumentSummary'][0]
print (gene_id['Id'], uid_summary['Name'])
# ...or something more interesting than print
374654 KIF7
90381 TICRR
672 BRCA1
An option to preserve discrete mapping, is to loop over each snp id and extract the gene(s):
although I don't endorse the method below, especially for long lists of snps, you may flood the server with too many requests, maybe someone more familiar can comment on request limits or best practices for Entrez
for snp_id in snp_ids:
record = Entrez.read(Entrez.elink(dbfrom="snp",
id=snp_id.replace('rs',''),
db="gene"))
results = record[0]['LinkSetDb'][0]['Link']
for result in results:
uid = result['Id']
handle = Entrez.esummary(db="gene", id=uid)
uid_record = Entrez.read(handle)
handle.close()
uid_summary = uid_record["DocumentSummarySet"]['DocumentSummary'][0]
gene_name = uid_summary['Name']
print(snp_id, uid, gene_name)
rs8179065 374654 KIF7
rs12899845 374654 KIF7
rs12899845 90381 TICRR
rs8179066 374654 KIF7
rs80357332 672 BRCA1
rs80356920 672 BRCA1