def test_create(self): sbol3.set_namespace('https://github.com/synbiodex/pysbol3') template = 'https://github.com/synbiodex/pysbol3/component' cd1 = sbol3.CombinatorialDerivation('cd1', template) self.assertEqual(template, cd1.template) comp1 = sbol3.Component('comp1', sbol3.SBO_DNA) cd2 = sbol3.CombinatorialDerivation('cd2', comp1) self.assertEqual(comp1.identity, cd2.template)
def test_invalid_strategy(self): sbol3.set_namespace('https://github.com/synbiodex/pysbol3') # Test with invalid strategy comp1 = sbol3.Component('comp1', sbol3.SBO_DNA) cd1 = sbol3.CombinatorialDerivation('cd1', comp1) cd1.strategy = sbol3.SBOL_INLINE report = cd1.validate() self.assertIsNotNone(report) self.assertEqual(1, len(report.errors))
def test_round_trip(self): # See https://github.com/SynBioDex/pySBOL3/issues/156 sbol3.set_namespace('https://github.com/synbiodex/pysbol3') comp1 = sbol3.Component('comp1', sbol3.SBO_DNA) cd1 = sbol3.CombinatorialDerivation('cd1', comp1) self.assertEqual(comp1.identity, cd1.template) doc1 = sbol3.Document() doc1.add(comp1) doc1.add(cd1) doc2 = sbol3.Document() doc2.read_string(doc1.write_string(sbol3.SORTED_NTRIPLES), sbol3.SORTED_NTRIPLES) comp2 = doc2.find(comp1.identity) self.assertIsInstance(comp2, sbol3.Component) cd2 = doc2.find(cd1.identity) self.assertIsInstance(cd2, sbol3.CombinatorialDerivation)
def make_combinatorial_derivation(document, display_id, part_lists, reverse_complements, constraints): # Make the combinatorial derivation and its template template = sbol3.Component(display_id + "_template", sbol3.SBO_DNA) document.add(template) cd = sbol3.CombinatorialDerivation(display_id, template) cd.strategy = sbol3.SBOL_ENUMERATE # for each part, make a SubComponent or LocalSubComponent in the template and link them together in sequence template_part_list = [] for part_list, rc in zip(part_lists, reverse_complements): # it's a variable if there are multiple values or if there's a single value that's a combinatorial derivation if len(part_list) > 1 or not isinstance(part_list[0], sbol3.Component): sub = sbol3.LocalSubComponent({sbol3.SBO_DNA }) # make a template variable sub.name = "Part " + str(len(template_part_list) + 1) template.features.append(sub) var = sbol3.VariableFeature(cardinality=sbol3.SBOL_ONE, variable=sub) cd.variable_features.append(var) # add all of the parts as variables for part in part_list: if isinstance(part, sbol3.Component): var.variants.append(part) elif isinstance(part, sbol3.CombinatorialDerivation): var.variant_derivations.append(part) else: raise ValueError( "Don't know how to make library element for " + part.name + ", a " + str(part)) else: # otherwise it's a fixed element of the template sub = sbol3.SubComponent(part_list[0]) template.features.append(sub) # in either case, orient and order the template elements sub.orientation = (sbol3.SBOL_REVERSE_COMPLEMENT if rc else sbol3.SBOL_INLINE) if template_part_list: template.constraints.append( sbol3.Constraint(sbol3.SBOL_MEETS, template_part_list[-1], sub)) template_part_list.append(sub) # next, add all of the constraints to the template #template.constraints = (make_constraint(c.strip(),template_part_list) for c in (constraints.split(',') if constraints else [])) # impacted by pySBOL3 appending c_list = (make_constraint(c.strip(), template_part_list) for c in (constraints.split(',') if constraints else [])) for c in c_list: template.constraints.append(c) # return the completed part return cd
def test_round_trip2(self): # See https://github.com/SynBioDex/pySBOL3/issues/159 sbol3.set_namespace('https://github.com/synbiodex/pysbol3') doc1 = sbol3.Document() comp1 = sbol3.Component('comp1', sbol3.SBO_DNA) doc1.add(comp1) cd1 = sbol3.CombinatorialDerivation('cd1', comp1) self.assertEqual(comp1.identity, cd1.template) doc1.add(cd1) vf1 = sbol3.VariableFeature(cardinality=sbol3.SBOL_ONE, variable=sbol3.PYSBOL3_MISSING) hour = 'https://identifiers.org/ncit:C25529' m1 = sbol3.Measure(32, hour) vf1.variant_measures.append(m1) cd1.variable_features.append(vf1) self.assertTrue(vf1.identity.startswith(cd1.identity)) # Ensure that Measure m1 is valid. The bug tested here was that it # had been assigned an invalid displayId. report = m1.validate() self.assertEqual(0, len(report.errors))
def test_round_trip1(self): # See https://github.com/SynBioDex/pySBOL3/issues/155 sbol3.set_namespace('https://github.com/synbiodex/pysbol3') doc1 = sbol3.Document() comp1 = sbol3.Component('comp1', sbol3.SBO_DNA) doc1.add(comp1) cd1 = sbol3.CombinatorialDerivation('cd1', comp1) self.assertEqual(comp1.identity, cd1.template) doc1.add(cd1) vf1 = sbol3.VariableFeature(cardinality=sbol3.SBOL_ONE, variable=sbol3.PYSBOL3_MISSING) cd1.variable_features.append(vf1) self.assertTrue(vf1.identity.startswith(cd1.identity)) doc2 = sbol3.Document() doc2.read_string(doc1.write_string(sbol3.SORTED_NTRIPLES), sbol3.SORTED_NTRIPLES) comp2 = doc2.find(comp1.identity) self.assertIsInstance(comp2, sbol3.Component) cd2 = doc2.find(cd1.identity) self.assertIsInstance(cd2, sbol3.CombinatorialDerivation) vf2 = doc2.find(vf1.identity) self.assertIsInstance(vf2, sbol3.VariableFeature)
def make_composite_part(document, row, composite_parts, linear_products, final_products, config): """ Create a composite part from a row in the composites sheet :param document: Document to add parts to :param row: Excel row to be processed :param composite_parts: collection of parts to add to :param linear_products: collection of linear parts to add to :param final_products: collection of final parts to add to :param config: dictionary of sheet parsing configuration variables """ # Parse material from sheet row name = row[config['composite_name_col']].value if name is None: return # skip lines without names else: name = name.strip() # make sure we're discarding whitespace display_id = sbol3.string_to_display_id(name) design_notes = (row[config['composite_notes_col']].value if row[config['composite_notes_col']].value else "") description = \ (row[config['composite_description_col']].value if row[config['composite_description_col']].value else "") final_product = row[config['composite_final_col']].value # boolean transformed_strain = row[config['composite_strain_col']].value if config[ 'composite_strain_col'] else None backbone_or_locus_raw = row[ config['composite_context_col']].value if config[ 'composite_context_col'] else None backbone_or_locus = part_names( backbone_or_locus_raw) if backbone_or_locus_raw else [] constraints = row[config['composite_constraints_col']].value if config[ 'composite_constraints_col'] else None reverse_complements = [ is_RC(spec) for spec in part_specifications(row, config) ] part_lists = \ [[partname_to_part(document, name) for name in part_names(spec)] for spec in part_specifications(row, config)] combinatorial = any( x for x in part_lists if len(x) > 1 or isinstance(x[0], sbol3.CombinatorialDerivation)) # Build the composite logging.debug( f'Creating {"library" if combinatorial else "composite part"} "{name}"' ) linear_dna_display_id = (f'{display_id}_ins' if backbone_or_locus else display_id) if combinatorial: composite_part = make_combinatorial_derivation(document, linear_dna_display_id, part_lists, reverse_complements, constraints) else: composite_part = make_composite_component(linear_dna_display_id, part_lists, reverse_complements) composite_part.name = (f'{name} insert' if backbone_or_locus else name) composite_part.description = f'{design_notes}\n{description}'.strip() # add the component to the appropriate collections document.add(composite_part) composite_parts.members.append(composite_part.identity) if final_product: linear_products.members.append(composite_part.identity) ############### # Consider strain and locus information if transformed_strain: warnings.warn("Not yet handling strain information: " + transformed_strain) if backbone_or_locus: # TODO: handle integration locuses as well as plasmid backbones backbones = [ partname_to_part(document, name) for name in backbone_or_locus ] if any(b is None for b in backbones): raise ValueError( f'Could not find specified backbone(s) "{backbone_or_locus}"') if any(not is_plasmid(b) for b in backbones): raise ValueError( f'Specified backbones "{backbone_or_locus}" are not all plasmids' ) if combinatorial: logging.debug( f"Embedding library '{composite_part.name}' in plasmid backbone(s) '{backbone_or_locus}'" ) plasmid = sbol3.Component(f'{display_id}_template', sbol3.SBO_DNA) document.add(plasmid) part_sub = sbol3.LocalSubComponent([sbol3.SBO_DNA], name="Inserted Construct") plasmid.features.append(part_sub) plasmid_cd = sbol3.CombinatorialDerivation(display_id, plasmid, name=name) document.add(plasmid_cd) part_var = sbol3.VariableFeature(cardinality=sbol3.SBOL_ONE, variable=part_sub) plasmid_cd.variable_features.append(part_var) part_var.variant_derivations.append(composite_part) if final_product: final_products.members.append(plasmid_cd) else: if len(backbones) == 1: logging.debug( f'Embedding part "{composite_part.name}" in plasmid backbone "{backbone_or_locus}"' ) plasmid = sbol3.Component(display_id, sbol3.SBO_DNA, name=name) document.add(plasmid) part_sub = sbol3.SubComponent(composite_part) plasmid.features.append(part_sub) if final_product: final_products.members += {plasmid} else: logging.debug( f'Embedding part "{composite_part.name}" in plasmid library "{backbone_or_locus}"' ) plasmid = sbol3.Component(f'{display_id}_template', sbol3.SBO_DNA) document.add(plasmid) part_sub = sbol3.SubComponent(composite_part) plasmid.features.append(part_sub) plasmid_cd = sbol3.CombinatorialDerivation(display_id, plasmid, name=name) document.add(plasmid_cd) if final_product: final_products.members.append(plasmid_cd) if len(backbones) == 1: backbone_sub = sbol3.SubComponent(backbones[0]) plasmid.features.append(backbone_sub) else: backbone_sub = sbol3.LocalSubComponent([sbol3.SBO_DNA]) backbone_sub.name = "Vector" plasmid.features.append(backbone_sub) backbone_var = sbol3.VariableFeature(cardinality=sbol3.SBOL_ONE, variable=backbone_sub) plasmid_cd.variable_features.append(backbone_var) backbone_var.variants += backbones plasmid.constraints.append( sbol3.Constraint(sbol3.SBOL_MEETS, part_sub, backbone_sub)) plasmid.constraints.append( sbol3.Constraint(sbol3.SBOL_MEETS, backbone_sub, part_sub))