def add_interaction(interaction_type: str, participants: Dict[Union[sbol3.Feature, sbol3.Component], str], system: sbol3.Component = None, name: str = None) -> sbol3.Interaction: """Compact function for creation of an interaction Implicitly identifies system and creates/adds features as necessary :param interaction_type: SBO type of interaction to be to be added :param participants: dictionary assigning features/components to roles for participations :param system: system to add interaction to :param name: name for the interaction :return: interaction """ # transform implicit arguments into explicit system = ensure_singleton_system(system, *participants.keys()) participations = [ sbol3.Participation([r], ensure_singleton_feature(system, p)) for p, r in participants.items() ] # make and return interaction interaction = sbol3.Interaction([interaction_type], participations=participations, name=name) system.interactions.append(interaction) return interaction
def test_list_wrapping(self): # Ensure that at least certain properties handle automatic list # wrapping and are typed to do so. # See https://github.com/SynBioDex/pySBOL3/issues/301 sbol3.set_namespace('https://github.com/synbiodex/pysbol3') test_type = sbol3.SBO_INHIBITION int1 = sbol3.Interaction(types=test_type) self.assertEqual([test_type], int1.types)
def test_change_object_namespace_errors(self): # Test bad arguments, like non-top-levels namespace = 'https://github.com/synbiodex/pysbol3' new_namespace = 'https://example.com/test_ns' sbol3.set_namespace(namespace) doc = sbol3.Document() # Non-TopLevel should raise ValueError i1 = sbol3.Interaction([sbol3.SBO_INHIBITION]) with self.assertRaises(ValueError): doc.change_object_namespace([i1], new_namespace)
def test_set_document(self): # Ensure that document is set on child objects # See https://github.com/SynBioDex/pySBOL3/issues/176 sbol3.set_namespace('https://bioprotocols.org/paml/primitives/') doc = sbol3.Document() c = sbol3.Component("scratch", sbol3.SBO_DNA) doc.add(c) lsc = sbol3.LocalSubComponent([sbol3.SBO_DNA]) self.assertIsNone(lsc.document) c.features.append(lsc) self.assertIsNotNone(lsc.document) interaction = sbol3.Interaction([sbol3.SBO_DEGRADATION]) c.interactions.append(interaction) self.assertEqual(doc, interaction.document) p = sbol3.Participation([sbol3.SBO_REACTANT], lsc) interaction.participations.append(p) self.assertEqual(doc, p.document) resolved_lsc = p.participant.lookup() self.assertEqual(lsc, resolved_lsc) self.assertEqual(lsc.identity, resolved_lsc.identity)
def test_compose_then_set_document(self): # Ensure that document is set on child objects # See https://github.com/SynBioDex/pySBOL3/issues/230 sbol3.set_namespace('https://bioprotocols.org/paml/primitives/') c = sbol3.Component("scratch", sbol3.SBO_DNA) lsc = sbol3.LocalSubComponent([sbol3.SBO_DNA]) self.assertIsNone(lsc.document) c.features.append(lsc) doc = sbol3.Document() doc.add(c) self.assertIsNotNone(lsc.document) self.assertEqual(doc, lsc.document) interaction = sbol3.Interaction([sbol3.SBO_DEGRADATION]) p = sbol3.Participation([sbol3.SBO_REACTANT], lsc) interaction.participations.append(p) c.interactions.append(interaction) # Now that we've composed the objects, add them to the parent. # This should assign the document to all the objects in the hierarchy # See https://github.com/SynBioDex/pySBOL3/issues/230 self.assertEqual(doc, interaction.document) self.assertEqual(doc, p.document) resolved_lsc = p.participant.lookup() self.assertEqual(lsc, resolved_lsc) self.assertEqual(lsc.identity, resolved_lsc.identity)
def to_sbol(self, sbol_doc: sbol3.Document = None) -> sbol3.Document: """Convert the genetic network to SBOL. :param sbol_doc: The SBOL document to add the genetic network to. """ if sbol_doc: doc=sbol_doc else: print('No SBOL Document provided') print('Generating a new SBOL Document') doc = sbol3.Document() products = set() geneticnetwork = sbol3.Component('geneticnetwork', sbol3.SBO_DNA) geneticnetwork.roles.append(sbol3.SO_ENGINEERED_REGION) loica_set = set() for op in self.operators: # Operator Component operator_comp = op.sbol_comp operator_sc = sbol3.SubComponent(operator_comp) # GeneProduct Outputs Component output_str = '' output_scs = [] if type(op.output) != list: outputs = [op.output] else: outputs = op.output for op_output in outputs: output_comp = op_output.sbol_comp output_scs.append(sbol3.SubComponent(output_comp)) output_str += f'_{op_output.name}' # TODO output string for policistronic operators # TU Component if type(op)==Source: input_str= 'c' tu = sbol3.Component(f'TU_{input_str}_{op}{output_str}', sbol3.SBO_DNA) #generalize to multi input/output TUs tu.roles.append(sbol3.SO_ENGINEERED_REGION) tu.features = [operator_sc] for sc in output_scs: tu.features.append(sc) elif type(op)==Hill2: # type(op.input)==List: input_str = '' for inp in op.input: input_str += f'_{inp.name}' tu = sbol3.Component(f'TU{input_str}_{op}{output_str}', sbol3.SBO_DNA) #generalize to multi input/output TUs tu.features = [operator_sc] for sc in output_scs: tu.features.append(sc) for inp in op.input: input_comp = inp.sbol_comp if type(input_comp)==sbol3.Component: input_sc = sbol3.SubComponent(input_comp) tu.features.append(input_sc) else: tu.features.append(input_comp) else: input_str= f'_{op.input.name}' tu = sbol3.Component(f'TU{input_str}_{op}{output_str}', sbol3.SBO_DNA) #generalize to multi input/output TUs tu.features = [operator_sc] for sc in output_scs: tu.features.append(sc) input_comp = op.input.sbol_comp if type(input_comp)==sbol3.Component: input_sc = sbol3.SubComponent(input_comp) tu.features.append(input_sc) else: tu.features.append(input_comp) tu.roles.append(sbol3.SO_ENGINEERED_REGION) for i in range(len(tu.features)-1): constraint = sbol3.Constraint(sbol3.SBOL_PRECEDES, tu.features[i], tu.features[i + 1]) tu.constraints = [constraint] #tu.constraints = [sbol3.Constraint(sbol3.SBOL_PRECEDES, operator_sc, output_sc)] # generate a sequence for the TU assuming assembly by type IIS REsnf both parts will have the fusion sites. # compare last 4 bp with thefirst 4 bp of the next part, given the preceds constraint. # if they are the same then delete one of them and concatenate the rest. # else error or comment TU sequence can not be generated, provide ways to add it. # Output GeneProduct Component for op_output, sc in zip(outputs, output_scs): #make list of tuples? for output_participation if type(op_output)==Regulator: if op_output.type_ == 'PRO': output_gp_comp = sbol3.Component(f'{op_output.name}_protein', sbol3.SBO_PROTEIN) output_gp_comp.roles.append(sbol3.SO_TRANSCRIPTION_FACTOR) elif op_output.type_ == 'RNA': output_gp_comp = sbol3.Component(f'{op_output.name}_rna', sbol3.SBO_RNA) output_gp_comp.roles.append(sbol3.SO_TRANSCRIPTION_FACTOR) else: print('Unsupported output molecule type') elif type(op_output)==Reporter: # For now just support fluorescent reporters if op_output.type_ == 'PRO': output_gp_comp = sbol3.Component(f'{op_output.name}_protein', sbol3.SBO_PROTEIN) output_gp_comp.roles.append('http://purl.obolibrary.org/obo/NCIT_C37894') elif op_output.type_ == 'RNA': output_gp_comp = sbol3.Component(f'{op_output.name}_rna', sbol3.SBO_RNA) output_gp_comp.roles.append('http://purl.obolibrary.org/obo/NCIT_C37894') else: print('Unsupported output molecule type') else: print('Unsupported output Type') output_gp_sc = sbol3.SubComponent(output_gp_comp) tu.features.append(output_gp_sc) if op_output not in products: products.add(op_output) loica_set.add(output_gp_comp) # Genetic Production Interaction pf the output output_participation = sbol3.Participation(roles=[sbol3.SBO_TEMPLATE], participant=sc) gp_participation = sbol3.Participation(roles=[sbol3.SBO_PRODUCT], participant=output_gp_sc) production = sbol3.Interaction(types=[sbol3.SBO_GENETIC_PRODUCTION], participations=[output_participation, gp_participation]) tu.interactions.append(production) # obtain TU subcomponents sequences, specially CDS and flanking parts sequences # look for ATG on the CDS and upstream part sequences (in the case of MoClo the ATG is in the fusion sites) # look for stop codons on frame with the ATG. # add translated the sequence between the ATG and the stop codon as protein sequence. #protein.sequence = tu.cds.sequence # Input Product Component if type(op) == Source: inputs=[] elif type(op) == Hill2: #type(op.input) != List: inputs = op.input else: inputs = [op.input] #inputs_prod_sc = [] for op_input in inputs: if type(op_input)==Regulator: if op_input.type_ == 'PRO': input_prod_comp = sbol3.Component(f'{op_input.name}_protein', sbol3.SBO_PROTEIN) input_prod_comp.roles.append(sbol3.SO_TRANSCRIPTION_FACTOR) elif op_input.type_ == 'RNA': input_prod_comp = sbol3.Component(f'{op_input.name}_rna', sbol3.SBO_RNA) input_prod_comp.roles.append(sbol3.SO_TRANSCRIPTION_FACTOR) else: print('Unsupported input molecule type') elif type(op_input)==Supplement: input_prod_comp = sbol3.Component(f'{op_input.name}_chemical', sbol3.SBO_SIMPLE_CHEMICAL) input_prod_comp.roles.append(sbol3.SO_TRANSCRIPTION_FACTOR) else: print('Unsupported input Type') # adds two times prod comp on the repressilator but necessary for normal circuits if op_input not in products: products.add(op_input) loica_set.add(input_prod_comp) input_prod_sc = sbol3.SubComponent(input_prod_comp) tu.features.append(input_prod_sc) #inputs_prod_sc.append(input_prod_sc) #how can I not create 2 times the same component? if type(op_input)!=Regulator: # if it is a regulator it is already created loica_set.add(input_prod_comp) # Input Interaction if type(op)==Hill1 and op.alpha[0]>op.alpha[1]: input_participation = sbol3.Participation(roles=[sbol3.SBO_INHIBITOR], participant=input_prod_sc) op_participation = sbol3.Participation(roles=[sbol3.SBO_INHIBITED], participant=operator_sc) interaction = sbol3.Interaction(types=[sbol3.SBO_INHIBITION], participations=[input_participation, op_participation]) tu.interactions.append(interaction) elif type(op)==Hill2 and op.alpha[0]== max(op.alpha): input_participation = sbol3.Participation(roles=[sbol3.SBO_INHIBITOR], participant=input_prod_sc) op_participation = sbol3.Participation(roles=[sbol3.SBO_INHIBITED], participant=operator_sc) interaction = sbol3.Interaction(types=[sbol3.SBO_INHIBITION], participations=[input_participation, op_participation]) tu.interactions.append(interaction) elif type(op)==Receiver: input_participation = sbol3.Participation(roles=[sbol3.SBO_STIMULATOR], participant=input_prod_sc) op_participation = sbol3.Participation(roles=[sbol3.SBO_STIMULATED], participant=operator_sc) interaction = sbol3.Interaction(types=[sbol3.SBO_STIMULATION], participations=[input_participation, op_participation]) tu.interactions.append(interaction) elif type(op)==Hill1 and op.alpha[0]<op.alpha[1]: input_participation = sbol3.Participation(roles=[sbol3.SBO_STIMULATOR], participant=input_prod_sc) op_participation = sbol3.Participation(roles=[sbol3.SBO_STIMULATED], participant=operator_sc) interaction = sbol3.Interaction(types=[sbol3.SBO_STIMULATION], participations=[input_participation, op_participation]) tu.interactions.append(interaction) elif type(op)==Source: pass else: print('Unsupported operator Type') # Model #model_string = str(op.__dict__) op_model = sbol3.Model(f'LOICA{input_str}_{op}{output_str}_model', source='https://github.com/SynBioUC/LOICA/blob/master/loica/operators', language='http://identifiers.org/EDAM:format_3996', framework='http://identifiers.org/SBO:0000062',) #attachments=[model_string]) doc.add(op_model) tu.models.append(op_model) doc.add(tu) tu_sc = sbol3.SubComponent(tu) geneticnetwork.features.append(tu_sc) loica_list = list(loica_set) doc.add(loica_list) if len(geneticnetwork.features) > 1: for i in range(len(geneticnetwork.features)-1): geneticnetwork.constraints = [sbol3.Constraint(sbol3.SBOL_PRECEDES, geneticnetwork.features[i], geneticnetwork.features[i+1])] else: pass doc.add(geneticnetwork) return doc
def test_create(self): types = [sbol3.SBO_INHIBITION] interaction = sbol3.Interaction(types) self.assertIsNotNone(interaction) self.assertEqual(types, interaction.types)