Skip to content

Commit

Permalink
Strucutural variant endpoint to power plotting position.
Browse files Browse the repository at this point in the history
  Eschew additional info for initial implementation.
  • Loading branch information
grosscol committed Nov 13, 2023
1 parent 44539e7 commit 8454cc5
Show file tree
Hide file tree
Showing 4 changed files with 171 additions and 0 deletions.
Empty file.
74 changes: 74 additions & 0 deletions bravo_api/blueprints/structvar/structvar.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import logging
import pymongo
from flask import current_app, Blueprint, jsonify, make_response, Response
from flask_cors import CORS
from webargs import fields
from webargs.flaskparser import FlaskParser
from marshmallow import RAISE

logger = logging.getLogger(__name__)
bp = Blueprint('structvar', __name__)
CORS(bp)


class Parser(FlaskParser):
# Override in order to raise validation error for unknown args
DEFAULT_UNKNOWN_BY_LOCATION = {"query": RAISE}


parser = Parser()

sv_region_argmap = {
'chrom': fields.Str(required=False, validate=lambda x: len(x) > 0,
error_messages={'validator_failed': 'Value must be a non-empty string.'}),
'start': fields.Int(required=False, validate=lambda x: x >= 0,
error_messages={
'validator_failed': 'Value must be greater than or equal to 0.'
}),
'stop': fields.Int(required=False, validate=lambda x: x > 0,
error_messages={'validator_failed': 'Value must be greater than 0.'}),
}


@bp.route('/sv/region', methods=['GET'])
@parser.use_args(sv_region_argmap, location='query')
def get_sv_region(args: dict) -> Response:
result = sv_region(current_app.mmongo.db.structvar, args['chrom'], args['start'], args['stop'])
return make_response(jsonify(result))


def sv_region(structvars: pymongo.collection.Collection,
chrom: str, roi_start: int, roi_stop: int) -> list:
""" Lookup structual variant data by region. Include all structural variants where the pos OR
end is within the given range of interest.
@param structvars: Structural variants collection
@param chrom: Chromosome containing regoin of interest.
@param roi_start: Start position of region of interest.
@param roi_stop: Stop position of region of interest.
"""

pipeline = [
{'$match': {
'$and': [
{'chrom': {'$eq': chrom}},
{'$or': [
{'$and': [
{'pos': {'$gte': roi_start}},
{'pos': {'$lte': roi_stop}}
]},
{'$and': [
{'end': {'$gte': roi_start}},
{'end': {'$lte': roi_stop}}
]},
{'$and': [
{'pos': {'$lte': roi_start}},
{'end': {'$gte': roi_stop}}
]}
]}
]}
}
]

cursor = structvars.aggregate(pipeline)
return [item for item in cursor]
57 changes: 57 additions & 0 deletions tests/mongo_fixtures/structvar.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
[
{
"_id": {
"$oid": "deadbeefdeadbeef22000001"
},
"chrom": "1",
"pos": 718601,
"ref": "A",
"sv_type": "DUP",
"sv_len": 105000,
"end": 823600
},
{
"_id": {
"$oid": "deadbeefdeadbeef22000002"
},
"chrom": "1",
"pos": 968168,
"ref": "G",
"sv_type": "DEL",
"sv_len": 20516,
"end": 988683
},
{
"_id": {
"$oid": "deadbeefdeadbeef22000003"
},
"chrom": "3",
"pos": 957868,
"ref": "A",
"sv_type": "INV",
"sv_len": 343440,
"end": 1301307
},
{
"_id": {
"$oid": "deadbeefdeadbeef22000004"
},
"chrom": "3",
"pos": 966074,
"ref": "A",
"sv_type": "DUP",
"sv_len": 174,
"end": 966247
},
{
"_id": {
"$oid": "deadbeefdeadbeef22000005"
},
"chrom": "3",
"pos": 968537,
"ref": "C",
"sv_type": "DUP",
"sv_len": 51788,
"end": 1020324
}
]
40 changes: 40 additions & 0 deletions tests/structvar/test_structvar.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
from bravo_api.blueprints.structvar import structvar
from flask import Flask

app = Flask('dummy')
app.register_blueprint(structvar.bp)

# See mongo_fixtures/strucvar.json for structvar collection fixture values


def test_structvar_fully_within_roi(mongodb):
result = structvar.sv_region(mongodb.structvar, "1", roi_start=718600, roi_stop=823600)
assert isinstance(result, list)
assert len(result) == 1
assert result[0]['pos'] == 718601


def test_structvar_only_start_in_roi(mongodb):
result = structvar.sv_region(mongodb.structvar, "1", roi_start=718600, roi_stop=718700)
assert isinstance(result, list)
assert len(result) == 1
assert result[0]['pos'] == 718601


def test_structvar_not_in_roi(mongodb):
result = structvar.sv_region(mongodb.structvar, "1", roi_start=600600, roi_stop=718600)
assert isinstance(result, list)
assert len(result) == 0


def test_structvar_spans_roi(mongodb):
result = structvar.sv_region(mongodb.structvar, "1", roi_start=720000, roi_stop=820000)
assert isinstance(result, list)
assert len(result) == 1
assert result[0]['pos'] == 718601


def test_structvar_multiple_results(mocker, mongodb):
result = structvar.sv_region(mongodb.structvar, "3", roi_start=950000, roi_stop=1400000)
assert isinstance(result, list)
assert len(result) == 3

0 comments on commit 8454cc5

Please sign in to comment.