Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit f25f327
Showing
9 changed files
with
363 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
# Created by .ignore support plugin (hsz.mobi) | ||
### VirtualEnv template | ||
# Virtualenv | ||
# http://iamzed.com/2009/05/07/a-primer-on-virtualenv/ | ||
.Python | ||
[Bb]in | ||
[Ii]nclude | ||
[Ll]ib | ||
[Ll]ib64 | ||
[Ll]ocal | ||
[Ss]cripts | ||
pyvenv.cfg | ||
.venv | ||
pip-selfcheck.json | ||
### Python template | ||
# Byte-compiled / optimized / DLL files | ||
__pycache__/ | ||
*.py[cod] | ||
*$py.class | ||
|
||
# C extensions | ||
*.so | ||
|
||
# Distribution / packaging | ||
.Python | ||
env/ | ||
build/ | ||
develop-eggs/ | ||
dist/ | ||
downloads/ | ||
eggs/ | ||
.eggs/ | ||
lib/ | ||
lib64/ | ||
parts/ | ||
sdist/ | ||
var/ | ||
*.egg-info/ | ||
.installed.cfg | ||
*.egg | ||
|
||
# PyInstaller | ||
# Usually these files are written by a python script from a template | ||
# before PyInstaller builds the exe, so as to inject date/other infos into it. | ||
*.manifest | ||
*.spec | ||
|
||
# Installer logs | ||
pip-log.txt | ||
pip-delete-this-directory.txt | ||
|
||
# Unit test / coverage reports | ||
htmlcov/ | ||
.tox/ | ||
.coverage | ||
.coverage.* | ||
.cache | ||
nosetests.xml | ||
coverage.xml | ||
*,cover | ||
.hypothesis/ | ||
|
||
# Translations | ||
*.mo | ||
*.pot | ||
|
||
# Django stuff: | ||
*.log | ||
local_settings.py | ||
|
||
# Flask stuff: | ||
instance/ | ||
.webassets-cache | ||
|
||
# Scrapy stuff: | ||
.scrapy | ||
|
||
# Sphinx documentation | ||
docs/_build/ | ||
|
||
# PyBuilder | ||
target/ | ||
|
||
# IPython Notebook | ||
.ipynb_checkpoints | ||
|
||
# pyenv | ||
.python-version | ||
|
||
# celery beat schedule file | ||
celerybeat-schedule | ||
|
||
# dotenv | ||
.env | ||
|
||
# virtualenv | ||
venv/ | ||
ENV/ | ||
|
||
# Spyder project settings | ||
.spyderproject | ||
|
||
# Rope project settings | ||
.ropeproject | ||
|
||
#jetbrains ide | ||
|
||
.idea |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
include LICENSE | ||
include MANIFEST.in | ||
include README.rst | ||
include setup.py | ||
include run.py | ||
recursive-exclude * __pycache__ | ||
recursive-exclude * *.py[co] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
# Variant API Client | ||
|
||
## A basic api client implementation for [api.varsome.com](https://api.varsome.com) | ||
|
||
This client is still in beta but it is a good start to start playing around with the API. | ||
|
||
### Installation | ||
|
||
Either download clone the repository from github and place the variantapi package | ||
within your code, or do | ||
|
||
pip install https://github.com/saphetor/variant-api-client-python/archive/master.zip | ||
|
||
### API Documentation | ||
|
||
Please visit the [api documentation](http://docs.testapi2127.apiary.io/) to find out how to use the api and | ||
what values does the api provide as a response to lookup requests | ||
|
||
### Using the client in your code | ||
|
||
Using the api client is quite straightforward. Just install the api client package and from within | ||
your code use | ||
|
||
from variantapi.client import VariantAPIClient | ||
# api key is not required for single variant lookups | ||
api_key = 'Your token' | ||
api = VariantAPIClient(api_key) | ||
# fetch information about a variant into a dictionary | ||
result = api.lookup('chr19:20082943:1:G', ref_genome=1019) | ||
# access results e.g. the sequence around the variant | ||
sequence = result['ref_seq']['sequence'] | ||
# fetch information for multiple variants | ||
variants = ['chr19:20082943:1:G','chr22:39777823::CAA'] | ||
# results will be an array of dictionaries an api key will be required for this request | ||
results = api.batch_lookup(variants, ref_genome=1019) | ||
|
||
If errors occur while using the client an exception will be thrown. | ||
You may wish to catch this exception and proceed with your own code logic | ||
|
||
from variantapi.client import VariantAPIClient, VariantApiException | ||
api = VariantAPIClient() | ||
try: | ||
result = api.lookup('chr19:20082943:1:G', ref_genome=1054) | ||
except VariantApiException as e: | ||
# proceed with your code flow e.g. | ||
print(e) # 404 (invalid reference genome) | ||
|
||
### Example Usage | ||
|
||
|
||
You may download and run the run.py python file after installation of the package | ||
to test the api client directly e.g. | ||
|
||
./run.py -g 1019 -q 'chr19:20082943:1:G' | ||
|
||
You may pass more than one values after the -q argument that will make a batch request | ||
to the API but you will need a token to do that e.g. | ||
|
||
./run.py -k 'your token' -g 1019 -q 'rs113488022' 'chr19:20082943:1:G' | ||
|
||
Run | ||
|
||
./run.py -h | ||
|
||
for a list of available options | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
#!/usr/bin/env python | ||
import argparse | ||
import json | ||
import logging | ||
import sys | ||
|
||
from variantapi.client import VariantAPIClient | ||
|
||
__author__ = 'ckopanos' | ||
logging.basicConfig(level=logging.DEBUG, | ||
format='[%(levelname)s] %(threadName)s %(message)s', | ||
) | ||
|
||
|
||
def main(argv): | ||
parser = argparse.ArgumentParser(description='Sample Variant API calls') | ||
parser.add_argument('-k', help='Your key to the API', type=str, metavar='API Key', required=False) | ||
parser.add_argument('-g', help='Reference genome either 1019 or 1038', type=int, metavar='Reference Genome', | ||
required=False, default=1019) | ||
parser.add_argument('-q', | ||
help='Query to lookup in the API e.g. chr19:20082943:1:G or in case of batch request ' | ||
'e.g. chr19:20082943:1:G rs113488022', | ||
type=str, metavar='Query', required=True, nargs='+') | ||
args = parser.parse_args() | ||
api_key = args.k | ||
query = args.q | ||
ref_genome = args.g | ||
api = VariantAPIClient(api_key) | ||
if len(query) == 1: | ||
result = api.lookup(query[0], ref_genome=ref_genome) | ||
else: | ||
if api_key is None: | ||
sys.exit("You need to pass an api key to perform batch requests") | ||
result = api.batch_lookup(query, ref_genome=ref_genome) | ||
sys.stdout.write(json.dumps(result, indent=4, sort_keys=True) if result else "No result") | ||
sys.stdout.write("\n") | ||
|
||
|
||
if __name__ == "__main__": | ||
main(sys.argv[1:]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
[bdist_wheel] | ||
universal=1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
from setuptools import setup | ||
from os import path | ||
|
||
VERSION = (1, 0, '0b1') | ||
__version__ = VERSION | ||
__versionstr__ = '.'.join(map(str, VERSION)) | ||
|
||
here = path.abspath(path.dirname(__file__)) | ||
|
||
setup( | ||
name='variant_api', | ||
version=__versionstr__, | ||
packages=['variantapi'], | ||
url='https://github.com/saphetor/variant-api-client-python', | ||
license='Apache License, Version 2.0', | ||
author='Saphetor', | ||
author_email='support@saphetor.com', | ||
description='A basic python api client implementation for https://api.varsome.com', | ||
classifiers=[ | ||
'Development Status :: 4 - Beta', | ||
'Intended Audience :: Developers', | ||
'Operating System :: OS Independent', | ||
'License :: OSI Approved :: Apache License', | ||
'Programming Language :: Python :: 2.7', | ||
'Programming Language :: Python :: 3', | ||
'Programming Language :: Python :: 3.2', | ||
'Programming Language :: Python :: 3.3', | ||
'Programming Language :: Python :: 3.4', | ||
'Programming Language :: Python :: 3.5', | ||
], | ||
install_requires=[ | ||
'requests>=2.0.0, <3.0.0' | ||
], | ||
) |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
import logging | ||
|
||
import requests | ||
from requests.exceptions import HTTPError, Timeout, ConnectionError, RequestException | ||
|
||
|
||
|
||
class VariantApiException(Exception): | ||
ERROR_CODES = { | ||
400: "Bad request. A parameter you have passed is not valid, or something in your request is wrong", | ||
401: "Not Authorized: either you need to provide authentication credentials, or the credentials provided aren't" | ||
" valid.", | ||
403: "Bad Request: your request is invalid, and we'll return an error message that tells you why. This is the " | ||
"status code returned if you've exceeded the rate limit (see below).", | ||
404: "Not Found: either you're requesting an invalid URI or the resource in question doesn't exist", | ||
500: "Internal Server Error: we did something wrong.", | ||
501: "Not implemented.", | ||
502: "Bad Gateway: returned if VariantAPI is down or being upgraded.", | ||
503: "Service Unavailable: the VariantAPI servers are up, but are overloaded with requests. Try again later.", | ||
504: "Gateway Timeout", | ||
} | ||
|
||
def __init__(self, status, response=None): | ||
self.status = status | ||
self.response = response | ||
|
||
def __str__(self): | ||
return "%s (%s)" % ( | ||
self.status, | ||
self.ERROR_CODES.get(self.status, 'Unknown error.') if self.response is None else self.response) | ||
|
||
def __repr__(self): | ||
return "%s(status=%s)" % (self.__class__.__name__, self.status) | ||
|
||
|
||
class VariantAPIClientBase(object): | ||
|
||
_api_url = 'https://api.varsome.com' | ||
_accepted_methods = ('GET', 'POST') | ||
|
||
def __init__(self, api_key=None): | ||
self.api_key = api_key | ||
self._headers = {'Accept': 'application/json'} | ||
if self.api_key is not None: | ||
self._headers['Authorization'] = "Token " + self.api_key | ||
self.session = requests.Session() | ||
self.session.headers.update(self._headers) | ||
|
||
def _make_request(self, path, method="GET", data=None, json_data=None): | ||
if method not in self._accepted_methods: | ||
raise VariantApiException('', "Unsupported method %s" % method) | ||
try: | ||
if method == "GET": | ||
r = self.session.get(self._api_url + path, data=data) | ||
if method == "POST": | ||
r = self.session.post(self._api_url + path, data=data, json=json_data, | ||
headers={'Content-Type': 'application/json'} if json_data is not None else None) | ||
logging.debug('Time between request and response %s' % r.elapsed) | ||
logging.debug('Content length %s' % len(r.content)) | ||
if r.status_code in VariantApiException.ERROR_CODES: | ||
raise VariantApiException( | ||
r.status_code, | ||
r.json()['detail'] | ||
if r.headers['Content-Type'] == "application/json" else None) | ||
return r | ||
except HTTPError as e: | ||
raise VariantApiException('', "Unknown http error %s" % e) | ||
except Timeout as e: | ||
raise VariantApiException('', "Request timed out %s" % e) | ||
except ConnectionError as e: | ||
raise VariantApiException('', "Connection failure or connection refused %s" % e) | ||
except RequestException as e: | ||
raise VariantApiException('', "Unknown error %s" % e.response) | ||
|
||
def get(self, path, data=None): | ||
response = self._make_request(path, "GET", data=data) | ||
return response.json() | ||
|
||
def post(self, path, data=None, json_data=None): | ||
response = self._make_request(path, "POST", data=data, json_data=json_data) | ||
return response.json() | ||
|
||
|
||
class VariantAPIClient(VariantAPIClientBase): | ||
schema_lookup_path = "/lookup/schema/" | ||
lookup_path = "/lookup/%s/%s" | ||
batch_lookup_path = "/lookup/batch/%s" | ||
_max_variants_per_batch = 8000 | ||
|
||
def __init__(self, api_key=None): | ||
super().__init__(api_key) | ||
|
||
def schema(self): | ||
return self.get(self.schema_lookup_path) | ||
|
||
def lookup(self, query, ref_genome=1019): | ||
return self.get(self.lookup_path % (query, ref_genome)) | ||
|
||
def batch_lookup(self, variants, ref_genome=1019): | ||
results = [] | ||
for queries in [variants[x:x + self._max_variants_per_batch] for x in range(0, len(variants), | ||
self._max_variants_per_batch)]: | ||
data = self.post(self.batch_lookup_path % ref_genome, json_data={'variants': queries}) | ||
results.extend(data) | ||
return results |