diff --git a/sbol_utilities/component.py b/sbol_utilities/component.py index 04d78dd6..6e2db7ac 100644 --- a/sbol_utilities/component.py +++ b/sbol_utilities/component.py @@ -624,7 +624,70 @@ def part_in_backbone(identity: str, part: sbol3.Component, backbone: sbol3.Compo part_in_backbone_component.types.append(topology_type) return part_in_backbone_component, part_in_backbone_seq -def digestion(reactant:sbol3.Component, restriction_enzymes:List[sbol3.ExternallyDefined], assembly_plan:sbol3.Component)-> Tuple[sbol3.Component, sbol3.Sequence]: +def part_in_backbone_from_sbol(identity: Union[str, None], sbol_comp: sbol3.Component, part_location: List[int], part_roles:List[str], fusion_site_length:int, linear:bool=False, **kwargs) -> Tuple[sbol3.Component, sbol3.Sequence]: + """Restructures a non-hierarchical plasmid Component to follow the part-in-backbone pattern following BP011. + It overwrites the SBOL3 Component provided. + A part inserted into a backbone is represented by a Component that includes both the part insert + as a feature that is a SubComponent and the backbone as another SubComponent. + For more information about BP011 visit https://github.com/SynBioDex/SBOL-examples/tree/main/SBOL/best-practices/BP011 + + :param identity: The identity of the Component, is its a String it build a new SBOL Component, if None it adds on top of the input. The identity of Sequence is also identity with the suffix '_seq'. + :param sbol_comp: The SBOL3 Component that will be used to create the part in backbone Component and Sequence. + :param part_location: List of 2 integers that indicates the start and the end of the unitary part. Note that the index of the first location is 1, as is typical practice in biology, rather than 0, as is typical practice in computer science. + :param part_roles: List of strings that indicates the roles to add on the part. + :param fusion_site_length: Integer of the length of the fusion sites (eg. BsaI fusion site lenght is 4, SapI fusion site lenght is 3) + :param linear: Boolean than indicates if the backbone is linear, by default it is seted to Flase which means that it has a circular topology. + :param kwargs: Keyword arguments of any other Component attribute. + :return: A tuple of Component and Sequence. + """ + if len(part_location) != 2: + raise ValueError('The part_location only accepts 2 int values in a list.') + if len(sbol_comp.sequences)!=1: + raise ValueError(f'The reactant needs to have precisely one sequence. The input reactant has {len(sbol3_comp.sequences)} sequences') + sequence = sbol_comp.sequences[0].lookup().elements + if identity == None: + part_in_backbone_component = sbol_comp + part_in_backbone_seq = sbol_comp.sequences[0] + else: + part_in_backbone_component, part_in_backbone_seq = dna_component_with_sequence(identity, sequence, **kwargs) + part_in_backbone_component.roles.append(sbol3.SO_DOUBLE_STRANDED) + for part_role in part_roles: + part_in_backbone_component.roles.append(part_role) + # creating part feature + part_location_comp = sbol3.Range(sequence=part_in_backbone_seq, start=part_location[0], end=part_location[1]) + #TODO: add the option of fusion sites to be of different lenghts + insertion_site_location1 = sbol3.Range(sequence=part_in_backbone_seq, start=part_location[0], end=part_location[0]+fusion_site_length, order=1) + insertion_site_location2 = sbol3.Range(sequence=part_in_backbone_seq, start=part_location[1]-fusion_site_length, end=part_location[1], order=3) + part_sequence_feature = sbol3.SequenceFeature(locations=[part_location_comp], roles=part_roles) + part_sequence_feature.roles.append(tyto.SO.engineered_insert) + insertion_sites_feature = sbol3.SequenceFeature(locations=[insertion_site_location1, insertion_site_location2], roles=[tyto.SO.insertion_site]) + #TODO: infer topology from the input + if linear: + part_in_backbone_component.types.append(sbol3.SO_LINEAR) + part_in_backbone_component.roles.append(sbol3.SO_ENGINEERED_REGION) + # creating backbone feature + open_backbone_location1 = sbol3.Range(sequence=part_in_backbone_seq, start=1, end=part_location[0]+fusion_site_length-1, order=1) + open_backbone_location2 = sbol3.Range(sequence=part_in_backbone_seq, start=part_location[1]-fusion_site_length, end=len(sequence), order=3) + open_backbone_feature = sbol3.SequenceFeature(locations=[open_backbone_location1, open_backbone_location2]) + else: + part_in_backbone_component.types.append(sbol3.SO_CIRCULAR) + part_in_backbone_component.roles.append(tyto.SO.plasmid_vector) + # creating backbone feature + open_backbone_location1 = sbol3.Range(sequence=part_in_backbone_seq, start=1, end=part_location[0]+fusion_site_length-1, order=2) + open_backbone_location2 = sbol3.Range(sequence=part_in_backbone_seq, start=part_location[1]-fusion_site_length, end=len(sequence), order=1) + open_backbone_feature = sbol3.SequenceFeature(locations=[open_backbone_location1, open_backbone_location2]) + part_in_backbone_component.features.append(part_sequence_feature) + part_in_backbone_component.features.append(insertion_sites_feature) + part_in_backbone_component.features.append(open_backbone_feature) + backbone_dropout_meets = sbol3.Constraint(restriction='http://sbols.org/v3#meets', subject=part_sequence_feature, object=open_backbone_feature) + part_in_backbone_component.constraints.append(backbone_dropout_meets) + #TODO: Add a branch to create a component without overwriting the WHOLE input component + #removing repeated types and roles + part_in_backbone_component.types = set(part_in_backbone_component.types) + part_in_backbone_component.roles = set(part_in_backbone_component.roles) + return part_in_backbone_component, part_in_backbone_seq + +def digestion(reactant:sbol3.Component, restriction_enzymes:List[sbol3.ExternallyDefined], assembly_plan:sbol3.Component, **kwargs)-> Tuple[sbol3.Component, sbol3.Sequence]: """Digests a Component using the provided restriction enzymes and creates a product Component and a digestion Interaction. The product Component is assumed to be the insert for parts in backbone and the backbone for backbones. @@ -641,7 +704,6 @@ def digestion(reactant:sbol3.Component, restriction_enzymes:List[sbol3.Externall for re in restriction_enzymes: enzyme = Restriction.__dict__[re.name] restriction_enzymes_pydna.append(enzyme) - assembly_plan.features.append(re) modifier_participation = sbol3.Participation(roles=[sbol3.SBO_MODIFIER], participant=re) participations.append(modifier_participation) @@ -662,15 +724,11 @@ def digestion(reactant:sbol3.Component, restriction_enzymes:List[sbol3.Externall raise NotImplementedError(f'Not supported number of products. Found{len(digested_reactant)}') #TODO select them based on content rather than size. elif circular and len(digested_reactant)==2: - digested_reactant = ds_reactant.cut(restriction_enzymes_pydna) part_extract, backbone = sorted(digested_reactant, key=len) elif linear and len(digested_reactant)==3: - digested_reactant = ds_reactant.cut(restriction_enzymes_pydna) - # check digested_reactant prefix, part_extract, suffix = digested_reactant else: raise NotImplementedError('The reactant has no valid topology type') - # Compute the lenth of single strand sticky ends or fusion sites - digested_reactant_5_prime_ss_strand, digested_reactant_5_prime_ss_end = digested_reactant.five_prime_end() + # Extracting roles from features reactant_features_roles = [] for f in reactant.features: @@ -678,23 +736,36 @@ def digestion(reactant:sbol3.Component, restriction_enzymes:List[sbol3.Externall reactant_features_roles.append(r) # if part if any(n==tyto.SO.engineered_insert for n in reactant_features_roles): + # Compute the length of single strand sticky ends or fusion sites + product_5_prime_ss_strand, product_5_prime_ss_end = part_extract.seq.five_prime_end() + product_3_prime_ss_strand, product_3_prime_ss_end = part_extract.seq.three_prime_end() + product_sequence = str(part_extract.seq) - prod_comp, prod_seq = dna_component_with_sequence(identity=f'{reactant.name}_part_extract', sequence=product_sequence) #str(product_sequence)) + prod_comp, prod_seq = dna_component_with_sequence(identity=f'{reactant.name}_part_extract', sequence=product_sequence, **kwargs) #str(product_sequence)) # add sticky ends features - five_prime_fusion_site_location = sbol3.Range(sequence=product_sequence, start=1, end=dropout_location[0]+fusion_site_length, order=1) - three_prime_fusion_site_location = sbol3.Range(sequence=product_sequence, start=dropout_location[1]-fusion_site_length, end=dropout_location[1], order=3) - insertion_sites_feature = sbol3.SequenceFeature(locations=[insertion_site_location1, insertion_site_location2], roles=[tyto.SO.insertion_site]) - + five_prime_fusion_site_location = sbol3.Range(sequence=product_sequence, start=1, end=len(product_5_prime_ss_end), order=1) + three_prime_fusion_site_location = sbol3.Range(sequence=product_sequence, start=len(product_sequence)-len(product_3_prime_ss_end), end=len(product_sequence), order=3) + fusion_sites_feature = sbol3.SequenceFeature(locations=[five_prime_fusion_site_location, three_prime_fusion_site_location], roles=[tyto.SO.insertion_site]) + prod_comp.features.append(fusion_sites_feature) + # if backbone elif any(n==tyto.SO.deletion for n in reactant_features_roles): + # Compute the length of single strand sticky ends or fusion sites + product_5_prime_ss_strand, product_5_prime_ss_end = backbone.seq.five_prime_end() + product_3_prime_ss_strand, product_3_prime_ss_end = backbone.seq.three_prime_end() product_sequence = str(backbone.seq) - prod_comp, prod_seq = dna_component_with_sequence(identity=f'{reactant.name}_backbone', sequence=product_sequence) #str(product_sequence)) + prod_comp, prod_seq = dna_component_with_sequence(identity=f'{reactant.name}_backbone', sequence=product_sequence, **kwargs) #str(product_sequence)) # add sticky ends features - # add recognition site features - else: raise NotImplementedError('The reactant has no valid roles') + five_prime_fusion_site_location = sbol3.Range(sequence=product_sequence, start=1, end=len(product_5_prime_ss_end), order=1) + three_prime_fusion_site_location = sbol3.Range(sequence=product_sequence, start=len(product_sequence)-len(product_3_prime_ss_end), end=len(product_sequence), order=3) + fusion_sites_feature = sbol3.SequenceFeature(locations=[five_prime_fusion_site_location, three_prime_fusion_site_location], roles=[tyto.SO.insertion_site]) + prod_comp.features.append(fusion_sites_feature) - # + else: raise NotImplementedError('The reactant has no valid roles') + #Add reference to part in backbone + reactant_subcomponent = sbol3.SubComponent(reactant) + prod_comp.features.append(reactant_subcomponent) # Create reactant Participation. react_subcomp = sbol3.SubComponent(reactant) assembly_plan.features.append(react_subcomp) @@ -737,8 +808,6 @@ def ligation(reactants:List[sbol3.Component], assembly_plan:sbol3.Component)-> L alignments.pop(0) # compare to all other alignments for alignment in alignments: - #working_alignment_5_prime_fusion_site_length = working_alignment[0].features[0].locations[0].end - #alignment_3_prime_fusion_site_length = alignment[-1].features[0].locations[1].start working_alignment_5_prime_fusion_site = working_alignment[0].sequences[0].lookup().elements[:working_alignment[0].features[0].locations[0].end] working_alignment_3_prime_fusion_site = working_alignment[-1].sequences[0].lookup().elements[working_alignment[-1].features[0].locations[1].start:] alignment_5_prime_fusion_site = alignment[0].sequences[0].lookup().elements[:alignment[0].features[0].locations[0].end] @@ -749,9 +818,7 @@ def ligation(reactants:List[sbol3.Component], assembly_plan:sbol3.Component)-> L if working_alignment_5_prime_fusion_site in used_fusion_sites: raise ValueError(f"Fusion site {working_alignment[0].sequences[0].lookup().elements[:fusion_site_length-1]} already used") else: used_fusion_sites.add(working_alignment_5_prime_fusion_site) - # if repeated elements pass - #if(all(x in working_alignment for x in alignment)): - # raise ValueError(f"Repeated elements in alignment {alignment}") + working_alignment = alignment + working_alignment @@ -774,9 +841,6 @@ def ligation(reactants:List[sbol3.Component], assembly_plan:sbol3.Component)-> L # if in used_fusion_sites, raise error if working_alignment_3_prime_fusion_site in used_fusion_sites: raise ValueError(f"Fusion site {working_alignment[0].sequences[0].lookup().elements[:fusion_site_length-1]} already used") - # if repeated elements, raise error - #if(all(x in working_alignment for x in alignment)): - # raise ValueError(f"Repeated elements in alignment {alignment}") working_alignment = working_alignment + alignment @@ -798,7 +862,6 @@ def ligation(reactants:List[sbol3.Component], assembly_plan:sbol3.Component)-> L break # TODO: feed working alignment to alignments - #alignments.insert(0, working_alignment) # use final products to build assembly product somponent fusion_site_length = 4 @@ -809,39 +872,27 @@ def ligation(reactants:List[sbol3.Component], assembly_plan:sbol3.Component)-> L # calculate sequence composite_sequence_str = "" composite_name = "" - for part in composite: - composite_sequence_str = composite_sequence_str + part.sequences[0].lookup().elements[:-fusion_site_length] #needs a version for linear + #part_subcomponents = [] + part_extract_subcomponents = [] + for part_extract in composite: + composite_sequence_str = composite_sequence_str + part_extract.sequences[0].lookup().elements[:-fusion_site_length] #needs a version for linear # create participations - part_subcomponent = sbol3.SubComponent(part) # LocalSubComponent?? - # if not in assemblye plan? - assembly_plan.features.append(part_subcomponent) - part_participation = sbol3.Participation(roles=[sbol3.SBO_REACTANT], participant=part_subcomponent) - participations.append(part_participation) - composite_name = composite_name + part.name + part_extract_subcomponent = sbol3.SubComponent(part_extract) # LocalSubComponent?? + part_extract_subcomponents.append(part_extract_subcomponent) + composite_name = composite_name + part_extract.name # create dna componente and sequence composite_component, composite_seq = dna_component_with_sequence(f'composite_{composite_number}_{composite_name}', composite_sequence_str) # **kwarads use in future? - #composite_component.types.append() composite_component.roles.append(sbol3.SO_ENGINEERED_REGION) - #composite_component.features = composite + composite_component.features = part_extract_subcomponents # TODO fix order of features - #composite_component.constraints.append(sbol3.Constraint(sbol3.SBOL_MEETS, composite_component.features[composite_number-1], composite_component.features[composite_number])) - # add product participation - #composite_subcomponent = sbol3.SubComponent(composite_component) - #participations.append(sbol3.Participation(roles=[sbol3.SBO_PRODUCT], participant=composite_subcomponent)) - # create interactions - #assembly_plan.interactions.append(sbol3.Interaction(types=[tyto.SBO.conversion], participations=participations)) products_list.append([composite_component, composite_seq]) composite_number += 1 - #create preceed constrain - #create composite part or part in backbone - #add interactions to assembly_plan - #add participations to assembly_plan + # TODO: modify to work outside of an assembly plan as well return products_list class Assembly_plan_composite_in_backbone_single_enzyme(): """Creates a Assembly Plan. - #classes uses param here? :param parts_in_backbone: Parts in backbone to be assembled. :param acceptor_backbone: Backbone in which parts are inserted on the assembly. :param restriction_enzymes: Restriction enzyme with correct name from Bio.Restriction as Externally Defined. @@ -855,15 +906,14 @@ def __init__(self, name: str, parts_in_backbone: List[sbol3.Component], acceptor self.parts_in_backbone = parts_in_backbone self.acceptor_backbone = acceptor_backbone self.restriction_enzyme = restriction_enzyme - self.unitary_parts = None - self.products = None + self.products = [] self.extracted_parts = [] - self.assembly_plan_component = None self.document = document #create assembly plan self.assembly_plan_component = sbol3.Component(identity=f'{self.name}_assembly_plan', types=sbol3.SBO_FUNCTIONAL_ENTITY) self.document.add(self.assembly_plan_component) + self.composites = [] def run(self): self.assembly_plan_component.features.append(self.restriction_enzyme) @@ -881,49 +931,9 @@ def run(self): self.extracted_parts.append(backbone_comp) #create composite part from extracted parts - composites_comp = ligation(reactants=self.extracted_parts, assembly_plan=self.assembly_plan_component) - self.products = composites_comp - for composite in composites_comp: - self.document.add(composite) - -def part_in_backbone2(identity: str, sequence: str, part_location: List[int], part_roles:List[str], fusion_site_length:int, linear:bool, **kwargs) -> Tuple[sbol3.Component, sbol3.Sequence]: - """Creates a Backbone Component and its Sequence. - - :param identity: The identity of the Component. The identity of Sequence is also identity with the suffix '_seq'. - :param sequence: The DNA sequence of the Component encoded in IUPAC. - :param dropout_location: List of 2 integers that indicates the start and the end of the dropout sequence including overhangs. Note that the index of the first location is 1, as is typical practice in biology, rather than 0, as is typical practice in computer science. - :param fusion_site_length: Integer of the lenght of the fusion sites (eg. BsaI fusion site lenght is 4, SapI fusion site lenght is 3) - :param linear: Boolean than indicates if the backbone is linear, by default it is seted to Flase which means that it has a circular topology. - :param kwargs: Keyword arguments of any other Component attribute. - :return: A tuple of Component and Sequence. - """ - if len(part_location) != 2: - raise ValueError('The part_location only accepts 2 int values in a list.') - part_in_backbone_component, part_in_backbone_seq = dna_component_with_sequence(identity, sequence, **kwargs) - part_in_backbone_component.roles.append(sbol3.SO_DOUBLE_STRANDED) - for part_role in part_roles: - part_in_backbone_component.roles.append(part_role) - part_location_comp = sbol3.Range(sequence=part_in_backbone_seq, start=part_location[0], end=part_location[1]) - insertion_site_location1 = sbol3.Range(sequence=part_in_backbone_seq, start=part_location[0], end=part_location[0]+fusion_site_length, order=1) - insertion_site_location2 = sbol3.Range(sequence=part_in_backbone_seq, start=part_location[1]-fusion_site_length, end=part_location[1], order=3) - part_sequence_feature = sbol3.SequenceFeature(locations=[part_location_comp], roles=part_roles) - part_sequence_feature.roles.append(tyto.SO.engineered_insert) - insertion_sites_feature = sbol3.SequenceFeature(locations=[insertion_site_location1, insertion_site_location2], roles=[tyto.SO.insertion_site]) - if linear: - part_in_backbone_component.types.append(sbol3.SO_LINEAR) - part_in_backbone_component.roles.append(sbol3.SO_ENGINEERED_REGION) - open_backbone_location1 = sbol3.Range(sequence=part_in_backbone_seq, start=1, end=part_location[0]+fusion_site_length-1, order=1) - open_backbone_location2 = sbol3.Range(sequence=part_in_backbone_seq, start=part_location[1]-fusion_site_length, end=len(sequence), order=3) - open_backbone_feature = sbol3.SequenceFeature(locations=[open_backbone_location1, open_backbone_location2]) - else: - part_in_backbone_component.types.append(sbol3.SO_CIRCULAR) - part_in_backbone_component.roles.append(tyto.SO.plasmid_vector) - open_backbone_location1 = sbol3.Range(sequence=part_in_backbone_seq, start=1, end=part_location[0]+fusion_site_length-1, order=2) - open_backbone_location2 = sbol3.Range(sequence=part_in_backbone_seq, start=part_location[1]-fusion_site_length, end=len(sequence), order=1) - open_backbone_feature = sbol3.SequenceFeature(locations=[open_backbone_location1, open_backbone_location2]) - part_in_backbone_component.features.append(part_sequence_feature) - part_in_backbone_component.features.append(insertion_sites_feature) - part_in_backbone_component.features.append(open_backbone_feature) - backbone_dropout_meets = sbol3.Constraint(restriction='http://sbols.org/v3#meets', subject=part_sequence_feature, object=open_backbone_feature) - part_in_backbone_component.constraints.append(backbone_dropout_meets) - return part_in_backbone_component, part_in_backbone_seq \ No newline at end of file + composites_list = ligation(reactants=self.extracted_parts, assembly_plan=self.assembly_plan_component) + for composite in composites_list: + composite[0].generated_by.append(self.assembly_plan_component) # + self.composites.append(composite) + self.products.append(composite) + self.document.add(composite) \ No newline at end of file diff --git a/test/test_component.py b/test/test_component.py index 0da0104d..ce21aed2 100644 --- a/test/test_component.py +++ b/test/test_component.py @@ -15,9 +15,11 @@ protein_stability_element, gene, operator, engineered_region, mrna, transcription_factor, \ strain, ed_simple_chemical, ed_protein -from sbol_utilities.component import ed_restriction_enzyme, backbone, part_in_backbone +from sbol_utilities.component import ed_restriction_enzyme, backbone, part_in_backbone, part_in_backbone_from_sbol, \ + digestion, ligation, Assembly_plan_composite_in_backbone_single_enzyme from sbol_utilities.helper_functions import find_top_level, toplevel_named, TopLevelNotFound, outgoing_links from sbol_utilities.sbol_diff import doc_diff +from sbol_utilities.conversion import convert_from_genbank class TestComponent(unittest.TestCase): @@ -291,16 +293,19 @@ def test_high_level_constructors(self): doc.add(media_comp) assert doc_diff(doc, hlc_doc) == 0, f'Constructor Error: {media_identity}' - def test_sep055(self): - """Test construction of components and features using helper functions: for each, build manually and compare.""" - hlc_doc = sbol3.Document() - doc = sbol3.Document() + def test_restriction_enzyme_bp011(self): + """Test the restriction_enzyme function""" sbol3.set_namespace('http://sbolstandard.org/testfiles') - restriction_enzyme_name = 'BsaI' restriction_enzyme_definition = 'http://rebase.neb.com/rebase/enz/BsaI.html' # TODO: replace with getting the URI from Enzyme when REBASE identifiers become available in biopython 1.80 bsai = ed_restriction_enzyme(restriction_enzyme_name) assert bsai.definition == restriction_enzyme_definition, 'Constructor Error: ed_restriction_enzyme' + + def test_backbone_bp011(self): + """Test the backbone function""" + hlc_doc = sbol3.Document() + doc = sbol3.Document() + sbol3.set_namespace('http://sbolstandard.org/testfiles') backbone_identity = 'backbone' backbone_sequence = 'aaGGGGttttCCCCaa' @@ -357,8 +362,9 @@ def test_sep055(self): linear_backbone_component.constraints.append(backbone_dropout_meets) doc.add([linear_backbone_component, linear_backbone_seq]) assert doc_diff(doc, hlc_doc) == 0, f'Constructor Error: Linear {backbone_identity}' - - + + def test_part_in_backbone_bp011(self): + """Test the part_in_backbone function""" hlc_doc = sbol3.Document() doc = sbol3.Document() sbol3.set_namespace('http://sbolstandard.org/testfiles') @@ -373,9 +379,11 @@ def test_sep055(self): hl_part_in_backbone_circular, hl_part_in_backbone_circular_sequence = part_in_backbone(identity_pib, part=test_promoter, backbone=test_backbone) hlc_doc.add([hl_part_in_backbone_circular, hl_part_in_backbone_circular_sequence]) + backbone_sequence = test_backbone.sequences[0].lookup().elements open_backbone_sequence_from_location1=backbone_sequence[test_backbone.features[-1].locations[0].start -1 : test_backbone.features[-1].locations[0].end] open_backbone_sequence_from_location2=backbone_sequence[test_backbone.features[-1].locations[1].start -1 : test_backbone.features[-1].locations[1].end] + part_sequence = test_promoter.sequences[0].lookup().elements part_in_backbone_seq_str = part_sequence + open_backbone_sequence_from_location2 + open_backbone_sequence_from_location1 part_in_backbone_component, part_in_backbone_seq = dna_component_with_sequence(identity_pib, part_in_backbone_seq_str) @@ -399,7 +407,6 @@ def test_sep055(self): hlc_doc.add([test_promoter, test_promoter_seq, test_backbone, test_backbone_seq]) doc.add([test_promoter, test_promoter_seq, test_backbone, test_backbone_seq]) - hl_part_in_backbone_linear, hl_part_in_backbone_linear_sequence = part_in_backbone(identity_pib, part=test_promoter, backbone=test_backbone, linear=True) hlc_doc.add([hl_part_in_backbone_linear, hl_part_in_backbone_linear_sequence]) @@ -417,6 +424,91 @@ def test_sep055(self): part_in_backbone_component_linear.types.append(sbol3.SO_LINEAR) doc.add([part_in_backbone_component_linear, part_in_backbone_seq]) assert doc_diff(doc, hlc_doc) == 0, f'Constructor Error: Linear {identity_pib}' + + def test_part_in_backbone_from_sbol_bp011(self): + hlc_doc = sbol3.Document() + sbol3.set_namespace('http://sbolstandard.org/testfiles') + test_dir = os.path.dirname(os.path.realpath(__file__)) + b0015_dir = os.path.join(test_dir, 'test_files', 'b0015.gb') + # Part in backbone from SBOL + target_b0015_unitary_part_sequence = 'ccaggcatcaaataaaacgaaaggctcagtcgaaagactgggcctttcgttttatctgttgtttgtcggtgaacgctctctactagagtcacactggctcaccttcgggtgggcctttctgcgtttata' + b0015_doc = convert_from_genbank(b0015_dir, 'https://github.com/Gonza10V') + b0015_ef = [top_level for top_level in b0015_doc if type(top_level)==sbol3.Component][0] + hlc_b0015_ef_in_bb, hlc_b0015_ef_in_bb_seq = part_in_backbone_from_sbol('b0015_ef_in_bb', b0015_ef, [518,646], [sbol3.SO_TERMINATOR], 4, False, name='b0015_ef_in_bb') + hlc_doc.add([hlc_b0015_ef_in_bb, hlc_b0015_ef_in_bb_seq]) + for feature in hlc_b0015_ef_in_bb.features: + if feature.roles == [sbol3.SO_TERMINATOR, tyto.SO.engineered_insert]: + b0015_unitary_part_sequence = feature.locations[0].sequence.lookup().elements[feature.locations[0].start-1:feature.locations[0].end] + assert target_b0015_unitary_part_sequence == b0015_unitary_part_sequence , "Unitary part sequence does not match target sequence" + assert len(hlc_b0015_ef_in_bb.features) == 3, f"Incorrect number of features, number of features expeted is 3, got {len(hlc_b0015_ef_in_bb.features)}" + assert set(hlc_b0015_ef_in_bb.types) == set([sbol3.SBO_DNA, sbol3.SO_CIRCULAR]) , f"Incorrect types, types expected are [sbol3.SBO_DNA, sbol3.SO_CIRCULAR], got {hlc_b0015_ef_in_bb.types}" + assert set(hlc_b0015_ef_in_bb.roles) == set([sbol3.SO_DOUBLE_STRANDED, sbol3.SO_TERMINATOR, tyto.SO.plasmid_vector]), f"Incorrect roles, roles expected are [sbol3.SO_DOUBLE_STRANDED, sbol3.SO_TERMINATOR, tyto.SO.plasmid_vector], got {hlc_b0015_ef_in_bb.roles}" + features_roles = set() + for ft in hlc_b0015_ef_in_bb.features: + for role in ft.roles: + features_roles.add(role) + assert features_roles == set([tyto.SO.insertion_site, sbol3.SO_TERMINATOR, tyto.SO.engineered_insert]), f"Incorrect feature roles, roles expected are [tyto.SO.insertion_site, sbol3.SO_TERMINATOR, tyto.SO.engineered_insert], got {features_roles}" + + def test_assembly_plan_bp011(self): + """Test assembly plan class""" + doc = sbol3.Document() + sbol3.set_namespace('http://sbolstandard.org/testfiles') + test_dir = os.path.dirname(os.path.realpath(__file__)) + # Assembly plan setup + bsai = ed_restriction_enzyme('BsaI') + #lvl1 acceptor + lvl1_pOdd_acceptor_seq = 'gctcgagtcccgtcaagtcagcgtaatgctctgccagtgttacaaccaattaaccaattctgattagaaaaactcatcgagcatcaaatgaaactgcaatttattcatatcaggattatcaataccatatttttgaaaaagccgtttctgtaatgaaggagaaaactcaccgaggcagttccataggatggcaagatcctggtatcggtctgcgattccgactcgtccaacatcaatacaacctattaatttcccctcgtcaaaaataaggttatcaagtgagaaatcaccatgagtgacgactgaatccggtgagaatggcaaaagcttatgcatttctttccagacttgttcaacaggccagccattacgctcgtcatcaaaatcactcgcatcaaccaaaccgttattcattcgtgattgcgcctgagcgagacgaaatacgcgatcgctgttaaaaggacaattacaaacaggaatcgaatgcaaccggcgcaggaacactgccagcgcatcaacaatattttcacctgaatcaggatattcttctaatacctggaatgctgttttcccggggatcgcagtggtgagtaaccatgcatcatcaggagtacggataaaatgcttgatggtcggaagaggcataaattccgtcagccagtttagtctgaccatctcatctgtaacatcattggcaacgctacctttgccatgtttcagaaacaactctggcgcatcgggcttcccatacaatcgatagattgtcgcacctgattgcccgacattatcgcgagcccatttatacccatataaatcagcatccatgttggaatttaatcgcggcctggagcaagacgtttcccgttgaatatggctcataacaccccttgtattactgtttatgtaagcagacagttttattgttcatgatgatatatttttatcttgtgcaatgtaacatcagagattttgagacacaacgtggctttgttgaataaatcgaacttttgctgagttgaaggatcagctcgagtgccacctgacgtctaagaaaccattattatcatgacattaacctataaaaataggcgtatcacgaggcagaatttcagataaaaaaaatccttagctttcgctaaggatgatttctggaattcgctcttcaatgggagtgagacccaatacgcaaaccgcctctccccgcgcgttggccgattcattaatgcagctggcacgacaggtttcccgactggaaagcgggcagtgagcgcaacgcaattaatgtgagttagctcactcattaggcaccccaggctttacactttatgcttccggctcgtatgttgtgtggaattgtgagcggataacaatttcacacatactagagaaagaggagaaatactagatggcttcctccgaagacgttatcaaagagttcatgcgtttcaaagttcgtatggaaggttccgttaacggtcacgagttcgaaatcgaaggtgaaggtgaaggtcgtccgtacgaaggtacccagaccgctaaactgaaagttaccaaaggtggtccgctgccgttcgcttgggacatcctgtccccgcagttccagtacggttccaaagcttacgttaaacacccggctgacatcccggactacctgaaactgtccttcccggaaggtttcaaatgggaacgtgttatgaacttcgaagacggtggtgttgttaccgttacccaggactcctccctgcaagacggtgagttcatctacaaagttaaactgcgtggtaccaacttcccgtccgacggtccggttatgcagaaaaaaaccatgggttgggaagcttccaccgaacgtatgtacccggaagacggtgctctgaaaggtgaaatcaaaatgcgtctgaaactgaaagacggtggtcactacgacgctgaagttaaaaccacctacatggctaaaaaaccggttcagctgccgggtgcttacaaaaccgacatcaaactggacatcacctcccacaacgaagactacaccatcgttgaacagtacgaacgtgctgaaggtcgtcactccaccggtgcttaataacgctgatagtgctagtgtagatcgctactagagccaggcatcaaataaaacgaaaggctcagtcgaaagactgggcctttcgttttatctgttgtttgtcggtgaacgctctctactagagtcacactggctcaccttcgggtgggcctttctgcgtttataggtctcaGCTTgcatgaagagcctgcagtccggcaaaaaagggcaaggtgtcaccaccctgccctttttctttaaaaccgaaaagattacttcgcgttatgcaggcttcctcgctcactgactcgctgcgctcggtcgttcggctgcggcgagcggtatcagctcactcaaaggcggtaatacggttatccacagaatcaggggataacgcaggaaagaacatgtgagcaaaaggccagcaaaaggccaggaaccgtaaaaaggccgcgttgctggcgtttttccacaggctccgcccccctgacgagcatcacaaaaatcgacgctcaagtcagaggtggcgaaacccgacaggactataaagataccaggcgtttccccctggaagctccctcgtgcgctctcctgttccgaccctgccgcttaccggatacctgtccgcctttctcccttcgggaagcgtggcgctttctcatagctcacgctgtaggtatctcagttcggtgtaggtcgttcgctccaagctgggctgtgtgcacgaaccccccgttcagcccgaccgctgcgccttatccggtaactatcgtcttgagtccaacccggtaagacacgacttatcgccactggcagcagccactggtaacaggattagcagagcgaggtatgtaggcggtgctacagagttcttgaagtggtggcctaactacggctacactagaagaacagtatttggtatctgcgctctgctgaagccagttaccttcggaaaaagagttggtagctcttgatccggcaaacaaaccaccgctggtagcggtggtttttttgtttgcaagcagcagattacgcgcagaaaaaaaggatctcaagaagatcctttgatcttttctacggggtctgacgctcagtggaacgaaaactcacgttaagggattttggtcatgagattatcaaaaaggatcttcacctagatccttttaaattaaaaatgaagttttaaatcaatctaaagtatatatgagtaaacttggtctgaca' + podd_backbone, podd_backbone_seq = backbone('pOdd_bb', lvl1_pOdd_acceptor_seq, [1169,2259], 4, False, name='pOdd_bb') + doc.add([podd_backbone,podd_backbone_seq]) + #parts in backbone + ##get parts from genbank + j23100_b0034_dir = os.path.join(test_dir, 'test_files', 'j23100_b0034.gb') + sfgfp_dir = os.path.join(test_dir, 'test_files', 'sfgfp.gb') + b0015_dir = os.path.join(test_dir, 'test_files', 'b0015.gb') + j23100_b0034_doc = convert_from_genbank(j23100_b0034_dir, 'https://github.com/Gonza10V') + j23100_b0034_ac = [top_level for top_level in j23100_b0034_doc if type(top_level)==sbol3.Component][0] + j23100_b0034_ac_seq_str = j23100_b0034_ac.sequences[0].lookup().elements + sfgfp_doc = convert_from_genbank(sfgfp_dir, 'https://github.com/Gonza10V') + sfgfp_ce = [top_level for top_level in sfgfp_doc if type(top_level)==sbol3.Component][0] + sfgfp_ce_seq_str = sfgfp_ce.sequences[0].lookup().elements + b0015_doc = convert_from_genbank(b0015_dir, 'https://github.com/Gonza10V') + b0015_ef = [top_level for top_level in b0015_doc if type(top_level)==sbol3.Component][0] + b0015_ef_seq_str = b0015_ef.sequences[0].lookup().elements + ##SBOL parts in backbone + j23100_b0034_ac_in_bb, j23100_b0034_ac_in_bb_seq = part_in_backbone_from_sbol('j23100_b0034_ac_in_bb', j23100_b0034_ac, [476,545], [sbol3.SO_PROMOTER, sbol3.SO_RBS], 4, False, name='j23100_b0034_ac_in_bb') + doc.add([j23100_b0034_ac_in_bb, j23100_b0034_ac_in_bb_seq]) + sfgfp_ce_in_bb, sfgfp_ce_in_bb_seq = part_in_backbone_from_sbol('sfgfp_ce_in_bb', sfgfp_ce, [130,854], [sbol3.SO_CDS], 4, False, name='sfgfp_ce_in_bb') + doc.add([sfgfp_ce_in_bb, sfgfp_ce_in_bb_seq]) + b0015_ef_in_bb, b0015_ef_in_bb_seq = part_in_backbone_from_sbol('b0015_ef_in_bb', b0015_ef, [518,646], [sbol3.SO_TERMINATOR], 4, False, name='b0015_ef_in_bb') + doc.add([b0015_ef_in_bb, b0015_ef_in_bb_seq]) + #Assembly plan + test_assembly_plan = Assembly_plan_composite_in_backbone_single_enzyme( + name='constitutive_gfp_tu', + parts_in_backbone=[j23100_b0034_ac_in_bb, sfgfp_ce_in_bb, b0015_ef_in_bb], + acceptor_backbone=podd_backbone, + restriction_enzyme=bsai, + document=doc) + test_assembly_plan.run() + #Check assembly plan + expected_assembled_j23100_b0034_ac_seq_str = j23100_b0034_ac_seq_str[475:545] + assembled_j23100_b0034_ac_seq_str = test_assembly_plan.extracted_parts[0].sequences[0].lookup().elements + assert expected_assembled_j23100_b0034_ac_seq_str==assembled_j23100_b0034_ac_seq_str, 'Constructor Error: First extracted part sequence does not match expected sequence' + + expected_assembled_sfgfp_ce_seq_str = sfgfp_ce_seq_str[129:854] + assembled_sfgfp_ce_seq_str = test_assembly_plan.extracted_parts[1].sequences[0].lookup().elements + assert expected_assembled_sfgfp_ce_seq_str==assembled_sfgfp_ce_seq_str, 'Constructor Error: Second extracted part sequence does not match expected sequence' + + expected_assembled_b0015_ef_seq_str = b0015_ef_seq_str[513:650] + assembled_b0015_ef_seq_str = test_assembly_plan.extracted_parts[2].sequences[0].lookup().elements + assert expected_assembled_b0015_ef_seq_str==assembled_b0015_ef_seq_str, 'Constructor Error: Third extracted part sequence does not match expected sequence' + + expected_assembled_open_backbone_seq_str = lvl1_pOdd_acceptor_seq[2255:] + lvl1_pOdd_acceptor_seq[:1172] + assembled_open_backbone_seq_str = test_assembly_plan.extracted_parts[-1].sequences[0].lookup().elements + assert expected_assembled_open_backbone_seq_str==assembled_open_backbone_seq_str, 'Constructor Error: Last extracted part (open backbone) sequence does not match expected sequence' + + expected_composite_seq_str = expected_assembled_open_backbone_seq_str[:-4] + expected_assembled_j23100_b0034_ac_seq_str[:-4] + expected_assembled_sfgfp_ce_seq_str[:-4] + expected_assembled_b0015_ef_seq_str[:-4] + assembled_composite_seq_str = test_assembly_plan.composites[0][0].sequences[0].lookup().elements + assert expected_composite_seq_str==assembled_composite_seq_str, 'Constructor Error: Composite sequence does not match expected sequence' if __name__ == '__main__': unittest.main() diff --git a/test/test_files/b0015.gb b/test/test_files/b0015.gb new file mode 100644 index 00000000..079d75ae --- /dev/null +++ b/test/test_files/b0015.gb @@ -0,0 +1,87 @@ +LOCUS Copy_of_B0015_EF:_pSB1C 2190 bp ds-DNA circular 28-JAN-2023 +DEFINITION . +COMMENT From pSB1C00 - Loop universal L0 acceptor and B0015_EF +FEATURES Location/Qualifiers + misc_feature 385..404 + /label="VF Primer binding site" + /ApEinfo_revcolor="#b7e6d7" + /ApEinfo_fwdcolor="#b7e6d7" + misc_feature complement(461..505) + /label="Terminator" + /ApEinfo_revcolor="#c7b0e3" + /ApEinfo_fwdcolor="#c7b0e3" + BioBrick 507..512 + /label="BsaI Site" + /ApEinfo_revcolor="#f58a5e" + /ApEinfo_fwdcolor="#f58a5e" + terminator 517..646 + /label="BBa-B0015 Terminator" + /ApEinfo_revcolor="#ff9ccd" + /ApEinfo_fwdcolor="#ff9ccd" + terminator 526..597 + /label="rrnB T1 terminator" + /ApEinfo_revcolor="#c7b0e3" + /ApEinfo_fwdcolor="#c7b0e3" + terminator 613..640 + /label="T7Te terminator" + /ApEinfo_revcolor="#75c6a9" + /ApEinfo_fwdcolor="#75c6a9" + misc_feature 664..735 + /label="His Terminator" + /ApEinfo_revcolor="#ffef86" + /ApEinfo_fwdcolor="#ffef86" + misc_feature complement(799..818) + /label="VR Primer binding site" + /ApEinfo_revcolor="#b1ff67" + /ApEinfo_fwdcolor="#b1ff67" + misc_feature complement(903..1517) + /label="rep (pMB1)" + /ApEinfo_revcolor="#85dae9" + /ApEinfo_fwdcolor="#85dae9" + misc_feature complement(1684..1789) + /label="Terminator T0" + /ApEinfo_revcolor="#c6c9d1" + /ApEinfo_fwdcolor="#c6c9d1" + CDS complement(1802..271) + /label="Cam Resistance" + /ApEinfo_revcolor="#ff9ccd" + /ApEinfo_fwdcolor="#ff9ccd" +ORIGIN + 1 aagggtgaac actatcccat atcaccagct caccgtcttt cattgccata cgaaattccg + 61 gatgagcatt catcaggcgg gcaagaatgt gaataaaggc cggataaaac ttgtgcttat + 121 ttttctttac ggtctttaaa aaggccgtaa tatccagctg aacggtctgg ttataggtac + 181 attgagcaac tgactgaaat gcctcaaaat gttctttacg atgccattgg gatatatcaa + 241 cggtggtata tccagtgatt tttttctcca ttttagcttc cttagctcct gaaaatctcg + 301 ataactcaaa aaatacgccc ggtagtgatc ttatttcatt atggtgaaag ttggaacctc + 361 ttacgtgccc gatcaactcg agtgccacct gacgtctaag aaaccattat tatcatgaca + 421 ttaacctata aaaataggcg tatcacgagg cagaatttca gataaaaaaa atccttagct + 481 ttcgctaagg atgatttctg gaattcggtc tcggcttcca ggcatcaaat aaaacgaaag + 541 gctcagtcga aagactgggc ctttcgtttt atctgttgtt tgtcggtgaa cgctctctac + 601 tagagtcaca ctggctcacc ttcgggtggg cctttctgcg tttatacgct CGAGaccctg + 661 cagtccggca aaaaagggca aggtgtcacc accctgccct ttttctttaa aaccgaaaag + 721 attacttcgc gttatgcagg cttcctcgct cactgactcg ctgcgctcgg tcgttcggct + 781 gcggcgagcg gtatcagctc actcaaaggc ggtaatacgg ttatccacag aatcagggga + 841 taacgcagga aagaacatgt gagcaaaagg ccagcaaaag gccaggaacc gtaaaaaggc + 901 cgcgttgctg gcgtttttcc acaggctccg cccccctgac gagcatcaca aaaatcgacg + 961 ctcaagtcag aggtggcgaa acccgacagg actataaaga taccaggcgt ttccccctgg + 1021 aagctccctc gtgcgctctc ctgttccgac cctgccgctt accggatacc tgtccgcctt + 1081 tctcccttcg ggaagcgtgg cgctttctca tagctcacgc tgtaggtatc tcagttcggt + 1141 gtaggtcgtt cgctccaagc tgggctgtgt gcacgaaccc cccgttcagc ccgaccgctg + 1201 cgccttatcc ggtaactatc gtcttgagtc caacccggta agacacgact tatcgccact + 1261 ggcagcagcc actggtaaca ggattagcag agcgaggtat gtaggcggtg ctacagagtt + 1321 cttgaagtgg tggcctaact acggctacac tagaagaaca gtatttggta tctgcgctct + 1381 gctgaagcca gttaccttcg gaaaaagagt tggtagctct tgatccggca aacaaaccac + 1441 cgctggtagc ggtggttttt ttgtttgcaa gcagcagatt acgcgcagaa aaaaaggatc + 1501 tcaagaagat cctttgatct tttctacggg gtctgacgct cagtggaacg aaaactcacg + 1561 ttaagggatt ttggtcatga gattatcaaa aaggatcttc acctagatcc ttttaaatta + 1621 aaaatgaagt tttaaatcaa tctaaagtat atatgagtaa acttggtctg acagctcgag + 1681 gcttggattc tcaccaataa aaaacgcccg gcggcaaccg agcgttctga acaaatccag + 1741 atggagttct gaggtcatta ctggatctat caacaggagt ccaagcgagc tcgatatcaa + 1801 attacgcccc gccctgccac tcatcgcagt actgttgtaa ttcattaagc attctgccga + 1861 catggaagcc atcacaaacg gcatgatgaa cctgaatcgc cagcggcatc agcaccttgt + 1921 cgccttgcgt ataatatttg cccatggtga aaacgggggc gaagaagttg tccatattgg + 1981 ccacgtttaa atcaaaactg gtgaaactca cccagggatt ggctgagacg aaaaacatat + 2041 tctcaataaa ccctttaggg aaataggcca ggttttcacc gtaacacgcc acatcttgcg + 2101 aatatatgtg tagaaactgc cggaaatcgt cgtggtattc actccagagc gatgaaaacg + 2161 tttcagtttg ctcatggaaa acggtgtaac +// \ No newline at end of file diff --git a/test/test_files/j23100_b0034.gb b/test/test_files/j23100_b0034.gb new file mode 100644 index 00000000..e3c10b03 --- /dev/null +++ b/test/test_files/j23100_b0034.gb @@ -0,0 +1,82 @@ +LOCUS Copy_of_J23100_B0034_AC 2123 bp ds-DNA circular 27-JAN-2023 +DEFINITION . +COMMENT From pSB1C00 - Loop universal L0 acceptor and J23100_B0034_AC +FEATURES Location/Qualifiers + misc_feature 347..366 + /label="VF Primer binding site" + /ApEinfo_revcolor="#b7e6d7" + /ApEinfo_fwdcolor="#b7e6d7" + misc_feature complement(423..467) + /label="Terminator" + /ApEinfo_revcolor="#c7b0e3" + /ApEinfo_fwdcolor="#c7b0e3" + BioBrick 469..474 + /label="BsaI Site" + /ApEinfo_revcolor="#f58a5e" + /ApEinfo_fwdcolor="#f58a5e" + Promoter 483..517 + /label="BBa_J23100" + /ApEinfo_revcolor="#b4abac" + /ApEinfo_fwdcolor="#b4abac" + RBS 524..535 + /label="B0034" + /ApEinfo_revcolor="#b4abac" + /ApEinfo_fwdcolor="#b4abac" + misc_feature 559..630 + /label="His Terminator" + /ApEinfo_revcolor="#ffef86" + /ApEinfo_fwdcolor="#ffef86" + misc_feature complement(694..713) + /label="VR Primer binding site" + /ApEinfo_revcolor="#b1ff67" + /ApEinfo_fwdcolor="#b1ff67" + misc_feature complement(798..1412) + /label="rep (pMB1)" + /ApEinfo_revcolor="#85dae9" + /ApEinfo_fwdcolor="#85dae9" + misc_feature complement(1579..1684) + /label="Terminator T0" + /ApEinfo_revcolor="#c6c9d1" + /ApEinfo_fwdcolor="#c6c9d1" + CDS complement(1697..233) + /label="Cam Resistance" + /ApEinfo_revcolor="#ff9ccd" + /ApEinfo_fwdcolor="#ff9ccd" +ORIGIN + 1 ttcattgcca tacgaaattc cggatgagca ttcatcaggc gggcaagaat gtgaataaag + 61 gccggataaa acttgtgctt atttttcttt acggtcttta aaaaggccgt aatatccagc + 121 tgaacggtct ggttataggt acattgagca actgactgaa atgcctcaaa atgttcttta + 181 cgatgccatt gggatatatc aacggtggta tatccagtga tttttttctc cattttagct + 241 tccttagctc ctgaaaatct cgataactca aaaaatacgc ccggtagtga tcttatttca + 301 ttatggtgaa agttggaacc tcttacgtgc ccgatcaact cgagtgccac ctgacgtcta + 361 agaaaccatt attatcatga cattaaccta taaaaatagg cgtatcacga ggcagaattt + 421 cagataaaaa aaatccttag ctttcgctaa ggatgatttc tggaattcgg tctcgggagt + 481 ctTTGACGGC TAGCTCAGTC CTAGGTACAG TGCTAGCCTA GAGAAAGAGG AGAAATACTA + 541 GaatgCGAGa ccctgcagtc cggcaaaaaa gggcaaggtg tcaccaccct gccctttttc + 601 tttaaaaccg aaaagattac ttcgcgttat gcaggcttcc tcgctcactg actcgctgcg + 661 ctcggtcgtt cggctgcggc gagcggtatc agctcactca aaggcggtaa tacggttatc + 721 cacagaatca ggggataacg caggaaagaa catgtgagca aaaggccagc aaaaggccag + 781 gaaccgtaaa aaggccgcgt tgctggcgtt tttccacagg ctccgccccc ctgacgagca + 841 tcacaaaaat cgacgctcaa gtcagaggtg gcgaaacccg acaggactat aaagatacca + 901 ggcgtttccc cctggaagct ccctcgtgcg ctctcctgtt ccgaccctgc cgcttaccgg + 961 atacctgtcc gcctttctcc cttcgggaag cgtggcgctt tctcatagct cacgctgtag + 1021 gtatctcagt tcggtgtagg tcgttcgctc caagctgggc tgtgtgcacg aaccccccgt + 1081 tcagcccgac cgctgcgcct tatccggtaa ctatcgtctt gagtccaacc cggtaagaca + 1141 cgacttatcg ccactggcag cagccactgg taacaggatt agcagagcga ggtatgtagg + 1201 cggtgctaca gagttcttga agtggtggcc taactacggc tacactagaa gaacagtatt + 1261 tggtatctgc gctctgctga agccagttac cttcggaaaa agagttggta gctcttgatc + 1321 cggcaaacaa accaccgctg gtagcggtgg tttttttgtt tgcaagcagc agattacgcg + 1381 cagaaaaaaa ggatctcaag aagatccttt gatcttttct acggggtctg acgctcagtg + 1441 gaacgaaaac tcacgttaag ggattttggt catgagatta tcaaaaagga tcttcaccta + 1501 gatcctttta aattaaaaat gaagttttaa atcaatctaa agtatatatg agtaaacttg + 1561 gtctgacagc tcgaggcttg gattctcacc aataaaaaac gcccggcggc aaccgagcgt + 1621 tctgaacaaa tccagatgga gttctgaggt cattactgga tctatcaaca ggagtccaag + 1681 cgagctcgat atcaaattac gccccgccct gccactcatc gcagtactgt tgtaattcat + 1741 taagcattct gccgacatgg aagccatcac aaacggcatg atgaacctga atcgccagcg + 1801 gcatcagcac cttgtcgcct tgcgtataat atttgcccat ggtgaaaacg ggggcgaaga + 1861 agttgtccat attggccacg tttaaatcaa aactggtgaa actcacccag ggattggctg + 1921 agacgaaaaa catattctca ataaaccctt tagggaaata ggccaggttt tcaccgtaac + 1981 acgccacatc ttgcgaatat atgtgtagaa actgccggaa atcgtcgtgg tattcactcc + 2041 agagcgatga aaacgtttca gtttgctcat ggaaaacggt gtaacaaggg tgaacactat + 2101 cccatatcac cagctcaccg tct +// \ No newline at end of file diff --git a/test/test_files/sfgfp.gb b/test/test_files/sfgfp.gb new file mode 100644 index 00000000..b667e882 --- /dev/null +++ b/test/test_files/sfgfp.gb @@ -0,0 +1,102 @@ +LOCUS Copy_of_sfGFP_CE:_pSB1C 2778 bp ds-DNA circular 15-NOV-2022 +DEFINITION . +COMMENT From pSB1C00 - Loop universal L0 acceptor and sfGFP_CE Sequencing + data suggests primer needs to be re-designed - appears to have part + of B0015 at the end +FEATURES Location/Qualifiers + misc_feature 1..20 + /label="VF Primer binding site" + /ApEinfo_revcolor="#b7e6d7" + /ApEinfo_fwdcolor="#b7e6d7" + misc_feature complement(77..121) + /label="Terminator" + /ApEinfo_revcolor="#c7b0e3" + /ApEinfo_fwdcolor="#c7b0e3" + BioBrick 123..128 + /label="BsaI Site" + /ApEinfo_revcolor="#f58a5e" + /ApEinfo_fwdcolor="#f58a5e" + CDS 131..850 + /label="sfGFP (BBa_I746916)" + /ApEinfo_revcolor="#84b0dc" + /ApEinfo_fwdcolor="#84b0dc" + CDS 131..850 + /label="Translation 131-850" + /translation="MRKGEELFTGVVPILVELDGDVNGHKFSVRGEGEGDATNGKLTLKFICTTGKLPVPWPTLVTTLTYGVQCFARYPDHMKQHDFFKSAMPEGYVQERTISFKDDGTYKTRAEVKFEGDTLVNRIELKGIDFKEDGNILGHKLEYNFNSHNVYITADKQKNGIKANFKIRHNVEDGSVQLADHYQQNTPIGDGPVLLPDNHYLSTQSVLSKDPNEKRDHMVLLEFVTAAGITHGMDELYK**" + misc_feature 851..854 + /label="Fusion Site" + /ApEinfo_revcolor="#b1ff67" + /ApEinfo_fwdcolor="#b1ff67" + misc_feature 856..861 + /label="BsaI Site" + /ApEinfo_revcolor="#ff9ccd" + /ApEinfo_fwdcolor="#ff9ccd" + misc_feature 868..939 + /label="His Terminator" + /ApEinfo_revcolor="#ffef86" + /ApEinfo_fwdcolor="#ffef86" + misc_feature complement(1003..1022) + /label="VR Primer binding site" + /ApEinfo_revcolor="#b1ff67" + /ApEinfo_fwdcolor="#b1ff67" + misc_feature complement(1107..1721) + /label="rep (pMB1)" + /ApEinfo_revcolor="#85dae9" + /ApEinfo_fwdcolor="#85dae9" + misc_feature complement(1888..1993) + /label="Terminator T0" + /ApEinfo_revcolor="#c6c9d1" + /ApEinfo_fwdcolor="#c6c9d1" + CDS complement(2006..2665) + /label="Cam Resistance" + /ApEinfo_revcolor="#ff9ccd" + /ApEinfo_fwdcolor="#ff9ccd" +ORIGIN + 1 ccacctgacg tctaagaaac cattattatc atgacattaa cctataaaaa taggcgtatc + 61 acgaggcaga atttcagata aaaaaaatcc ttagctttcg ctaaggatga tttctggaat + 121 tcggtctcga atgcgtaaag gcgaggaact gttcactggt gtcgtcccta ttctggtgga + 181 actggatggt gatgtcaacg gtcataagtt ttccgtgcgt ggcgagggtg aaggtgacgc + 241 aactaatggt aaactgacgc tgaagttcat ctgtactact ggtaaactgc cggtaccttg + 301 gccgactctg gtaacgacgc tgacttatgg tgttcagtgc tttgctcgtt atccggacca + 361 tatgaagcag catgacttct tcaagtccgc catgccggaa ggctatgtgc aggaacgcac + 421 gatttccttt aaggatgacg gcacgtacaa aacgcgtgcg gaagtgaaat ttgaaggcga + 481 taccctggta aaccgcattg agctgaaagg cattgacttt aaagaagacg gcaatatcct + 541 gggccataag ctggaataca attttaacag ccacaatgtt tacatcaccg ccgataaaca + 601 aaaaaatggc attaaagcga attttaaaat tcgccacaac gtggaggatg gcagcgtgca + 661 gctggctgat cactaccagc aaaacactcc aatcggtgat ggtcctgttc tgctgccaga + 721 caatcactat ctgagcacgc aaagcgttct gtctaaagat ccgaacgaga aacgcgatca + 781 tatggttctg ctggagttcg taaccgcagc gggcatcacg catggtatgg atgaactgta + 841 caaatgatga gcttCGAGac cctgcagtcc ggcaaaaaag ggcaaggtgt caccaccctg + 901 ccctttttct ttaaaaccga aaagattact tcgcgttatg caggcttcct cgctcactga + 961 ctcgctgcgc tcggtcgttc ggctgcggcg agcggtatca gctcactcaa aggcggtaat + 1021 acggttatcc acagaatcag gggataacgc aggaaagaac atgtgagcaa aaggccagca + 1081 aaaggccagg aaccgtaaaa aggccgcgtt gctggcgttt ttccacaggc tccgcccccc + 1141 tgacgagcat cacaaaaatc gacgctcaag tcagaggtgg cgaaacccga caggactata + 1201 aagataccag gcgtttcccc ctggaagctc cctcgtgcgc tctcctgttc cgaccctgcc + 1261 gcttaccgga tacctgtccg cctttctccc ttcgggaagc gtggcgcttt ctcatagctc + 1321 acgctgtagg tatctcagtt cggtgtaggt cgttcgctcc aagctgggct gtgtgcacga + 1381 accccccgtt cagcccgacc gctgcgcctt atccggtaac tatcgtcttg agtccaaccc + 1441 ggtaagacac gacttatcgc cactggcagc agccactggt aacaggatta gcagagcgag + 1501 gtatgtaggc ggtgctacag agttcttgaa gtggtggcct aactacggct acactagaag + 1561 aacagtattt ggtatctgcg ctctgctgaa gccagttacc ttcggaaaaa gagttggtag + 1621 ctcttgatcc ggcaaacaaa ccaccgctgg tagcggtggt ttttttgttt gcaagcagca + 1681 gattacgcgc agaaaaaaag gatctcaaga agatcctttg atcttttcta cggggtctga + 1741 cgctcagtgg aacgaaaact cacgttaagg gattttggtc atgagattat caaaaaggat + 1801 cttcacctag atccttttaa attaaaaatg aagttttaaa tcaatctaaa gtatatatga + 1861 gtaaacttgg tctgacagct cgaggcttgg attctcacca ataaaaaacg cccggcggca + 1921 accgagcgtt ctgaacaaat ccagatggag ttctgaggtc attactggat ctatcaacag + 1981 gagtccaagc gagctcgata tcaaattacg ccccgccctg ccactcatcg cagtactgtt + 2041 gtaattcatt aagcattctg ccgacatgga agccatcaca aacggcatga tgaacctgaa + 2101 tcgccagcgg catcagcacc ttgtcgcctt gcgtataata tttgcccatg gtgaaaacgg + 2161 gggcgaagaa gttgtccata ttggccacgt ttaaatcaaa actggtgaaa ctcacccagg + 2221 gattggctga gacgaaaaac atattctcaa taaacccttt agggaaatag gccaggtttt + 2281 caccgtaaca cgccacatct tgcgaatata tgtgtagaaa ctgccggaaa tcgtcgtggt + 2341 attcactcca gagcgatgaa aacgtttcag tttgctcatg gaaaacggtg taacaagggt + 2401 gaacactatc ccatatcacc agctcaccgt ctttcattgc catacgaaat tccggatgag + 2461 cattcatcag gcgggcaaga atgtgaataa aggccggata aaacttgtgc ttatttttct + 2521 ttacggtctt taaaaaggcc gtaatatcca gctgaacggt ctggttatag gtacattgag + 2581 caactgactg aaatgcctca aaatgttctt tacgatgcca ttgggatata tcaacggtgg + 2641 tatatccagt gatttttttc tccattttag cttccttagc tcctgaaaat ctcgataact + 2701 caaaaaatac gcccggtagt gatcttattt cattatggtg aaagttggaa cctcttacgt + 2761 gcccgatcaa ctcgagtg +// \ No newline at end of file diff --git a/test/test_files/test_part_in_backbone_from_sbol_bp011.nt b/test/test_files/test_part_in_backbone_from_sbol_bp011.nt new file mode 100644 index 00000000..0e244d22 --- /dev/null +++ b/test/test_files/test_part_in_backbone_from_sbol_bp011.nt @@ -0,0 +1,67 @@ + "Constraint1" . + . + . + . + . + "Range1" . + "646"^^ . + . + "518"^^ . + . + "SequenceFeature1" . + . + . + . + . + "Range1" . + "522"^^ . + . + "1"^^ . + "518"^^ . + . + "Range2" . + "646"^^ . + . + "3"^^ . + "642"^^ . + . + "SequenceFeature2" . + . + . + . + . + "Range1" . + "521"^^ . + . + "2"^^ . + "1"^^ . + . + "Range2" . + "2190"^^ . + . + "1"^^ . + "642"^^ . + . + "SequenceFeature3" . + . + . + . + "b0015_ef_in_bb" . + . + . + . + . + . + . + "b0015_ef_in_bb" . + . + . + . + . + . + . + "b0015_ef_in_bb_seq" . + "aagggtgaacactatcccatatcaccagctcaccgtctttcattgccatacgaaattccggatgagcattcatcaggcgggcaagaatgtgaataaaggccggataaaacttgtgcttatttttctttacggtctttaaaaaggccgtaatatccagctgaacggtctggttataggtacattgagcaactgactgaaatgcctcaaaatgttctttacgatgccattgggatatatcaacggtggtatatccagtgatttttttctccattttagcttccttagctcctgaaaatctcgataactcaaaaaatacgcccggtagtgatcttatttcattatggtgaaagttggaacctcttacgtgcccgatcaactcgagtgccacctgacgtctaagaaaccattattatcatgacattaacctataaaaataggcgtatcacgaggcagaatttcagataaaaaaaatccttagctttcgctaaggatgatttctggaattcggtctcggcttccaggcatcaaataaaacgaaaggctcagtcgaaagactgggcctttcgttttatctgttgtttgtcggtgaacgctctctactagagtcacactggctcaccttcgggtgggcctttctgcgtttatacgctCGAGaccctgcagtccggcaaaaaagggcaaggtgtcaccaccctgccctttttctttaaaaccgaaaagattacttcgcgttatgcaggcttcctcgctcactgactcgctgcgctcggtcgttcggctgcggcgagcggtatcagctcactcaaaggcggtaatacggttatccacagaatcaggggataacgcaggaaagaacatgtgagcaaaaggccagcaaaaggccaggaaccgtaaaaaggccgcgttgctggcgtttttccacaggctccgcccccctgacgagcatcacaaaaatcgacgctcaagtcagaggtggcgaaacccgacaggactataaagataccaggcgtttccccctggaagctccctcgtgcgctctcctgttccgaccctgccgcttaccggatacctgtccgcctttctcccttcgggaagcgtggcgctttctcatagctcacgctgtaggtatctcagttcggtgtaggtcgttcgctccaagctgggctgtgtgcacgaaccccccgttcagcccgaccgctgcgccttatccggtaactatcgtcttgagtccaacccggtaagacacgacttatcgccactggcagcagccactggtaacaggattagcagagcgaggtatgtaggcggtgctacagagttcttgaagtggtggcctaactacggctacactagaagaacagtatttggtatctgcgctctgctgaagccagttaccttcggaaaaagagttggtagctcttgatccggcaaacaaaccaccgctggtagcggtggtttttttgtttgcaagcagcagattacgcgcagaaaaaaaggatctcaagaagatcctttgatcttttctacggggtctgacgctcagtggaacgaaaactcacgttaagggattttggtcatgagattatcaaaaaggatcttcacctagatccttttaaattaaaaatgaagttttaaatcaatctaaagtatatatgagtaaacttggtctgacagctcgaggcttggattctcaccaataaaaaacgcccggcggcaaccgagcgttctgaacaaatccagatggagttctgaggtcattactggatctatcaacaggagtccaagcgagctcgatatcaaattacgccccgccctgccactcatcgcagtactgttgtaattcattaagcattctgccgacatggaagccatcacaaacggcatgatgaacctgaatcgccagcggcatcagcaccttgtcgccttgcgtataatatttgcccatggtgaaaacgggggcgaagaagttgtccatattggccacgtttaaatcaaaactggtgaaactcacccagggattggctgagacgaaaaacatattctcaataaaccctttagggaaataggccaggttttcaccgtaacacgccacatcttgcgaatatatgtgtagaaactgccggaaatcgtcgtggtattcactccagagcgatgaaaacgtttcagtttgctcatggaaaacggtgtaac" . + . + . + .