Skip to content

Commit

Permalink
Merge pull request #96 from ginkgobioworks/include-feature-sequence
Browse files Browse the repository at this point in the history
add sequence to feature and option to get in api
  • Loading branch information
Lioscro committed Sep 13, 2022
2 parents 6536ba6 + afaed1b commit ab1df96
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 5 deletions.
13 changes: 12 additions & 1 deletion src/edge/models/chunk.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import gzip
import json

from Bio.Seq import Seq
from django.db import models
from django.db import transaction

Expand Down Expand Up @@ -58,7 +59,6 @@ def from_chunk_feature_and_location_array(chunk_feature_locs):
(t[0].feature.strand if t[0].feature.strand is not None else 1)
* t[0].feature_base_first)
)

annotations = []
for cf, fcl in chunk_feature_locs:
if (
Expand Down Expand Up @@ -300,6 +300,17 @@ class Meta:
def set_qualifiers(self, qualifiers):
self._qualifiers = json.dumps(qualifiers)

@property
def sequence(self):
seq = ''
cfs = self.chunk_feature_set.all()
for cf in sorted(cfs, key=lambda cf: cf.feature_base_first):
seq += cf.chunk.get_sequence()
# Reverse complement if on negative strand
return str(
Seq(seq).reverse_complement()
) if self.strand is not None and self.strand < 0 else seq

@property
def qualifiers(self):
if self._qualifiers is not None:
Expand Down
17 changes: 17 additions & 0 deletions src/edge/tests/test_feature.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from django.test import TestCase

from edge.models import Fragment


class FeatureTests(TestCase):
def setUp(self):
self.root_sequence = "agttcgaggctga"
self.root = Fragment.create_with_sequence("Foo", self.root_sequence)

def test_sequence_positive_strand(self):
feature = self.root.annotate(3, 5, "A1", "gene", 1)
self.assertEqual(feature.sequence, "ttc")

def test_sequence_negative_strand(self):
feature = self.root.annotate(3, 5, "A1", "gene", -1)
self.assertEqual(feature.sequence, "gaa")
19 changes: 15 additions & 4 deletions src/edge/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -193,8 +193,8 @@ def on_get(self, request, fragment_id):

class FragmentAnnotationsView(ViewBase):
@staticmethod
def to_dict(annotation):
return dict(
def to_dict(annotation, include_feature_sequence=False):
result = dict(
base_first=annotation.base_first,
base_last=annotation.base_last,
strand=annotation.feature.strand,
Expand All @@ -212,16 +212,21 @@ def to_dict(annotation):
qualifiers=annotation.feature.qualifiers,
feature_full_length=annotation.feature.length
)
if include_feature_sequence:
result['feature']['sequence'] = annotation.feature.sequence
return result

def on_get(self, request, fragment_id):
q_parser = RequestParser()
q_parser.add_argument("f", field_type=int, location="get")
q_parser.add_argument("l", field_type=int, location="get")
q_parser.add_argument("m", field_type=int, location="get")
q_parser.add_argument("include_feature_sequence", field_type=str, default='false', location="get")
args = q_parser.parse_args(request)
f = args["f"]
ll = args["l"]
m = args["m"]
include_feature_sequence = args["include_feature_sequence"].lower() == "true"

fragment = get_fragment_or_404(fragment_id)
annotations = fragment.indexed_fragment().annotations(bp_lo=f, bp_hi=ll)
Expand All @@ -234,7 +239,9 @@ def on_get(self, request, fragment_id):
annotations = new_a
annotations = to_return
return [
FragmentAnnotationsView.to_dict(annotation) for annotation in annotations
FragmentAnnotationsView.to_dict(
annotation, include_feature_sequence=include_feature_sequence
) for annotation in annotations
]

@transaction.atomic()
Expand Down Expand Up @@ -580,9 +587,13 @@ def on_post(self, request, genome_id):

parser = RequestParser()
parser.add_argument("primers", field_type=list, required=True, location="json")
parser.add_argument(
"include_feature_sequence", field_type=bool, required=False, default=False, location="json"
)

args = parser.parse_args(request)
primers = args["primers"]
include_feature_sequence = args["include_feature_sequence"]

if len(primers) != 2:
raise Exception("Expecting two primers, got %s" % (primers,))
Expand All @@ -593,7 +604,7 @@ def on_post(self, request, genome_id):
# Convert annotations in template_info to dictionary.
if template_info and "annotations" in template_info:
template_info["annotations"] = [
FragmentAnnotationsView.to_dict(annotation)
FragmentAnnotationsView.to_dict(annotation, include_feature_sequence=include_feature_sequence)
for annotation in template_info["annotations"]
]
r = (
Expand Down

0 comments on commit ab1df96

Please sign in to comment.