Skip to content

Commit

Permalink
Merge pull request #556 from NBISweden/feature/range-only-start
Browse files Browse the repository at this point in the history
Make it possible to request ranges as single position
  • Loading branch information
viklund authored May 9, 2019
2 parents 07cea86 + ddd6572 commit ff7db7f
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 22 deletions.
19 changes: 12 additions & 7 deletions backend/modules/browser/browser_handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,12 +88,12 @@ def get(self, dataset:str, datatype:str, item:str, ds_version:str=None):
"""
dataset, ds_version = utils.parse_dataset(dataset, ds_version)
ret = utils.get_coverage(dataset, datatype, item, ds_version)
if 'bad_region' in ret:
self.send_error(status_code=400, reason="Unable to parse the region")
return
if 'region_too_large' in ret:
self.send_error(status_code=400, reason="The region is too large")
return
if not ret['coverage']:
self.send_error(status_code=404, reason="No coverage found")
return
self.finish(ret)


Expand All @@ -111,7 +111,13 @@ def get(self, dataset:str, datatype:str, item:str, ds_version:str=None):
ds_version (str): dataset version
"""
dataset, ds_version = utils.parse_dataset(dataset, ds_version)
ret = utils.get_coverage_pos(dataset, datatype, item, ds_version)
try:
ret = utils.get_coverage_pos(dataset, datatype, item, ds_version)
except ValueError:
logging.error('GetCoveragePos: unable to parse region ({})'.format(region))
self.send_error(status_code=400, reason='Unable to parse region')
return

self.finish(ret)


Expand Down Expand Up @@ -171,10 +177,9 @@ def get(self, dataset:str, region:str, ds_version:str=None):
ds_version (str): dataset version
"""
dataset, ds_version = utils.parse_dataset(dataset, ds_version)

try:
chrom, start, stop = region.split('-')
start = int(start)
stop = int(stop)
chrom, start, stop = utils.parse_region(region)
except ValueError:
logging.error('GetRegion: unable to parse region ({})'.format(region))
self.send_error(status_code=400, reason='Unable to parse region')
Expand Down
2 changes: 1 addition & 1 deletion backend/modules/browser/tests/test_browser_handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ def test_get_coverage():
assert response.status_code == 400
data_item = '1-1-5'
response = requests.get('{}/api/dataset/{}/browser/coverage/{}/{}'.format(BASE_URL, dataset, data_type, data_item))
assert response.status_code == 404
assert response.status_code == 200


def test_get_coverage_pos():
Expand Down
5 changes: 2 additions & 3 deletions backend/modules/browser/tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ def test_get_coverage():
assert len(res['coverage']) == 17
res = utils.get_coverage('SweGen', 'region', '22:46615715-46615880')
assert not res['coverage']
assert res['bad_region']
res = utils.get_coverage('SweGen', 'region', '22-46615715asd-46615880')
assert not res['coverage']
assert res['bad_region']
Expand Down Expand Up @@ -197,8 +196,8 @@ def test_get_variant_list():
res = utils.get_variant_list('SweGen', 'region', '22-1-1000000')
assert res['region_too_large']

res = utils.get_variant_list('SweGen', 'region', '22-11000000')
assert not res
res = utils.get_variant_list('SweGen', 'region', '22-16272587')
assert len(res['variants']) == 4


def test_order_vep_by_csq():
Expand Down
49 changes: 38 additions & 11 deletions backend/modules/browser/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,22 +174,23 @@ def get_coverage(dataset:str, datatype:str, item:str, ds_version:str=None):
start = transcript['start'] - EXON_PADDING
stop = transcript['stop'] + EXON_PADDING
ret['coverage'] = lookups.get_coverage_for_transcript(dataset, transcript['chrom'], start, stop, ds_version)

elif datatype == 'region':
try:
chrom, start, stop = item.split('-')
start = int(start)
stop = int(stop)
chrom, start, stop = parse_region(item)
except ValueError:
return {'coverage': [], 'bad_region':True}
if is_region_too_large(start, stop):
return {'coverage': [], 'region_too_large': True}
ret['coverage'] = lookups.get_coverage_for_bases(dataset, chrom, start, stop, ds_version)

elif datatype == 'transcript':
transcript = lookups.get_transcript(dataset, item)
if transcript:
start = transcript['start'] - EXON_PADDING
stop = transcript['stop'] + EXON_PADDING
ret['coverage'] = lookups.get_coverage_for_transcript(dataset, transcript['chrom'], start, stop, ds_version)

return ret


Expand All @@ -203,17 +204,16 @@ def get_coverage_pos(dataset:str, datatype:str, item:str, ds_version:str=None):
item (str): the datatype item to look up
Returns:
dict: start, stop, chromosome
dict: start, stop, chrom
"""
ret = {'start':None, 'stop':None, 'chrom':None}

if datatype == 'region':
chrom, start, stop = item.split('-')
if start and stop and chrom:
ret['start'] = int(start)
ret['stop'] = int(stop)
ret['chrom'] = chrom
chrom, start, stop = parse_region(item)
ret['start'] = start
ret['stop'] = stop
ret['chrom'] = chrom
else:
if datatype == 'gene':
gene = lookups.get_gene(dataset, item)
Expand Down Expand Up @@ -339,9 +339,10 @@ def get_variant_list(dataset:str, datatype:str, item:str, ds_version:str=None):

if datatype == 'gene':
variants = lookups.get_variants_in_gene(dataset, item, ds_version)

elif datatype == 'region':
try:
chrom, start, stop = item.split('-')
chrom, start, stop = parse_region(item)
start = int(start)
stop = int(stop)
except ValueError:
Expand All @@ -350,6 +351,7 @@ def get_variant_list(dataset:str, datatype:str, item:str, ds_version:str=None):
if is_region_too_large(start, stop):
return {'variants': [], 'headers': [], 'region_too_large': True}
variants = lookups.get_variants_in_region(dataset, chrom, start, stop, ds_version)

elif datatype == 'transcript':
variants = lookups.get_variants_in_transcript(dataset, item, ds_version)

Expand Down Expand Up @@ -425,7 +427,7 @@ def is_region_too_large(start:int, stop:int):
return int(stop)-int(start) > region_limit


def parse_dataset(dataset, ds_version=None):
def parse_dataset(dataset:str, ds_version:str=None):
"""
Check/parse if the dataset name is in the beacon form (``reference:dataset:version``).
Expand All @@ -443,6 +445,31 @@ def parse_dataset(dataset, ds_version=None):
return (dataset, ds_version)


def parse_region(region:str):
"""
Parse a region with either one or two positions
Args:
region (str): region, e.g. `3:1000000` or `3:100100`
Returns:
tuple: (chrom, start, pos)
"""
parts = region.split('-')
if len(parts) == 2:
chrom, start = parts
stop = start
elif len(parts) == 3:
chrom, start, stop = parts
else:
raise ValueError

start = int(start)
stop = int(stop)

return chrom, start, stop


def remove_extraneous_information(variant:dict):
"""
Remove information that is not used in the frontend from a variant.
Expand Down

0 comments on commit ff7db7f

Please sign in to comment.