From d13f75e93533926ff3795ab4975a8fc983cd415a Mon Sep 17 00:00:00 2001 From: Yehuda Binik Date: Wed, 22 Nov 2023 12:43:54 -0500 Subject: [PATCH 01/14] began working on visit_sub_component in sbol3_sbol2_conversion, added a test file, and wrote a unit test --- sbol_utilities/sbol3_sbol2_conversion.py | 9 +- test/test_files/sbol3_toggle_switch.nt | 370 +++++++++++++++++++++++ test/test_sbol2_sbol3_direct.py | 21 ++ 3 files changed, 399 insertions(+), 1 deletion(-) create mode 100644 test/test_files/sbol3_toggle_switch.nt diff --git a/sbol_utilities/sbol3_sbol2_conversion.py b/sbol_utilities/sbol3_sbol2_conversion.py index ac44446f..29d0db14 100644 --- a/sbol_utilities/sbol3_sbol2_conversion.py +++ b/sbol_utilities/sbol3_sbol2_conversion.py @@ -270,8 +270,15 @@ def visit_singular_unit(self, a: sbol3.SingularUnit): # Priority: 4 raise NotImplementedError('Conversion of SingularUnit from SBOL3 to SBOL2 not yet implemented') - def visit_sub_component(self, a: sbol3.SubComponent): + def visit_sub_component(self, sub3: sbol3.SubComponent): # Priority: 1 + + component2 = sbol2.Component(sub3.identity, ) + module2 = sbol2.Module(sub3.identity, definition=sub3.instance_of, ) + # mapsTo - optional + # measures - optional + functional_component2 = sbol2.FunctionalComponent(sub3.identity, ) + """ raise NotImplementedError('Conversion of SubComponent from SBOL3 to SBOL2 not yet implemented') def visit_unit_division(self, a: sbol3.UnitDivision): diff --git a/test/test_files/sbol3_toggle_switch.nt b/test/test_files/sbol3_toggle_switch.nt new file mode 100644 index 00000000..d67e540b --- /dev/null +++ b/test/test_files/sbol3_toggle_switch.nt @@ -0,0 +1,370 @@ + . + . + "lacI" . + . + "lacI" . + "lacI coding sequence" . + . + . + "SubComponent6" . + . + . + . + "tetR terminator" . + . + "ter_tetR" . + "Terminator" . + . + . + "IPTG_LacI" . + . + "IPTG_LacI" . + "IPTG_LacI complex" . + . + . + . + . + "Constraint2" . + . + . + . + "lacI terminator" . + . + "ter_lacI" . + "Terminator" . + . + . + . + "SubComponent6" . + . + . + . + "IPTG" . + . + "IPTG" . + "IPTG" . + . + . + . + "Participation1" . + . + . + . + "Participation1" . + . + . + . + "pTetR" . + . + "pTetR" . + "TetR repressible promoter" . + . + . + . + "LacI" . + . + "LacI_protein" . + "LacI protein" . + . + . + . + "rbs" . + . + "rbs_gfp" . + "RBS" . + . + . + "SubComponent5" . + . + . + . + . + . + "Interaction4" . + . + . + "atC_TetR" . + . + "atC_TetR" . + "atC_TetR complex" . + . + . + . + . + "Constraint1" . + . + . + . + "SubComponent5" . + . + . + . + "ComponentReference4" . + . + . + . + "SubComponent4" . + . + . + . + . + . + "Interaction3" . + . + . + "SubComponent10" . + . + . + . + . + "Interaction3" . + . + . + . + "Participation3" . + . + . + . + "TetR" . + . + "TetR_protein" . + "TetR protein" . + . + . + . + . + "toggle_switch" . + "Toggle Switch genetic circuit" . + . + . + . + . + . + . + "Toggle Switch" . + . + . + . + . + "SubComponent4" . + . + . + . + "pLacI promoter" . + . + "pLacI" . + "LacI repressible promoter" . + . + . + "SubComponent9" . + . + . + . + "ComponentReference3" . + . + . + . + "rbs" . + . + "rbs_tetR" . + "tetR RBS" . + . + . + . + "gfp" . + . + "gfp" . + "gfp coding sequence" . + . + . + . + . + . + . + "LacI producer" . + "LacI_producer" . + . + . + . + . + . + . + . + . + . + "LacI producer" . + . + . + . + . + . + . + "SubComponent3" . + . + . + . + . + "Interaction2" . + . + . + . + "Participation2" . + . + . + "SubComponent2" . + . + . + . + "Participation2" . + . + . + . + . + "Interaction2" . + . + . + . + "Participation2" . + . + . + . + "Participation2" . + . + . + "SubComponent9" . + . + . + . + "rbs" . + . + "rbs_lacI" . + "RBS" . + . + . + . + . + "TetR_producer" . + . + . + . + . + . + . + . + . + "TetR producer" . + . + . + "TetR device" . + . + . + . + . + . + "SubComponent3" . + . + . + "SubComponent8" . + . + . + . + "ComponentReference2" . + . + . + . + "tetR" . + . + "tetR" . + "tetR coding sequence" . + . + . + . + "Participation2" . + . + . + . + "SubComponent2" . + . + . + . + . + "Interaction1" . + . + . + . + . + "Interaction1" . + . + . + "SubComponent1" . + . + . + . + "Participation1" . + . + . + . + "Participation1" . + . + . + . + "Participation1" . + . + . + . + "Participation1" . + . + . + "SubComponent8" . + . + . + "GFP" . + . + "GFP_protein" . + "GFP" . + . + . + . + "SubComponent2" . + . + . + . + "Participation3" . + . + . + . + "aTC" . + . + "aTC" . + "aTC" . + . + . + "SubComponent7" . + . + . + . + "ComponentReference1" . + . + . + . + "Participation1" . + . + . + . + "SubComponent1" . + . + . + "SubComponent7" . + . + . + . + "SubComponent1" . + . + . + . + "Participation2" . + . + . + . + "Participation2" . + . diff --git a/test/test_sbol2_sbol3_direct.py b/test/test_sbol2_sbol3_direct.py index 94791fcf..849db10c 100644 --- a/test/test_sbol2_sbol3_direct.py +++ b/test/test_sbol2_sbol3_direct.py @@ -129,6 +129,27 @@ def test_2to3_collection_conversion(self): doc2_loop.write(tmp2) self.assertFalse(file_diff(str(tmp2), str(TEST_FILES / 'sbol_3to2_collection.xml'))) + def test_3to2_sub_component_conversion(self): + """Test ability to convert a collection from SBOL3 to SBOL2""" + # Load an SBOL3 document and check its contents + doc3 = sbol3.Document() + doc3.read(TEST_FILES / 'sbol3_toggle_switch.nt') + # Convert to SBOL2 and check contents + doc2 = convert3to2(doc3, True) + #report = doc2.validate() + #self.assertEqual(len(report), 0, f'Validation failed: {report}') + with tempfile.TemporaryDirectory() as tmpdir: + tmp2 = Path(tmpdir) / 'doc2.xml' + doc2.write(tmp2) + self.assertFalse(file_diff(str(tmp2), str(TEST_FILES / 'sbol_3to2_collection.xml'))) + doc3_loop = convert2to3(doc2, use_native_converter=True) + self.assertEqual(len(doc3_loop.validate()), 0) + tmp3 = Path(tmpdir) / 'doc3_loop.nt' + doc3_loop.write(tmp3) + self.assertFalse(file_diff(str(tmp3), str(TEST_FILES / 'sbol3_collection.nt'))) + + + if __name__ == '__main__': unittest.main() From 172960509074c2d27fac6b42e31145e883eb670a Mon Sep 17 00:00:00 2001 From: Yehuda Binik Date: Wed, 22 Nov 2023 17:11:08 -0500 Subject: [PATCH 02/14] Coded the preliminary version of the visit_sub_component method --- sbol_utilities/sbol3_sbol2_conversion.py | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/sbol_utilities/sbol3_sbol2_conversion.py b/sbol_utilities/sbol3_sbol2_conversion.py index 29d0db14..800a5c0c 100644 --- a/sbol_utilities/sbol3_sbol2_conversion.py +++ b/sbol_utilities/sbol3_sbol2_conversion.py @@ -273,13 +273,17 @@ def visit_singular_unit(self, a: sbol3.SingularUnit): def visit_sub_component(self, sub3: sbol3.SubComponent): # Priority: 1 - component2 = sbol2.Component(sub3.identity, ) - module2 = sbol2.Module(sub3.identity, definition=sub3.instance_of, ) - # mapsTo - optional - # measures - optional - functional_component2 = sbol2.FunctionalComponent(sub3.identity, ) - """ - raise NotImplementedError('Conversion of SubComponent from SBOL3 to SBOL2 not yet implemented') + # Make the Component, Module, and Functional_Component objects and add them to the document + component2 = sbol2.Component(sub3.identity) + module2 = sbol2.Module(sub3.identity, definition=sub3.instance_of) + functional_component2 = sbol2.FunctionalComponent(sub3.identity) + self.doc2.addSequence(component2) + self.doc2.addSequence(module2) + self.doc2.addSequence(functional_component2) + # Map over all other TopLevel properties and extensions not covered by the constructor + self._convert_toplevel(sub3, component2) + self._convert_toplevel(sub3, module2) + self._convert_toplevel(sub3, functional_component2) def visit_unit_division(self, a: sbol3.UnitDivision): # Priority: 4 From 80146132ce3a2072be274ebdb34a5c47acef7a91 Mon Sep 17 00:00:00 2001 From: Yehuda Binik Date: Thu, 8 Aug 2024 17:18:49 -0400 Subject: [PATCH 03/14] First commit in a very long time --- sbol_utilities/sbol3_sbol2_conversion.py | 87 +++- test/sbol3.nt | 436 ++++++++++++++++ test/test_files/create_subcomponent_test.py | 89 ++++ test/test_files/sbol_3to2_toggle_switch.nt | 7 + test/test_files/subcomponent_test_3.nt | 464 ++++++++++++++++++ .../subcomponent_test_3_bare_bones.nt | 254 ++++++++++ .../test_files/~$circular_inference_test.xlsx | Bin 0 -> 165 bytes test/test_sbol2_sbol3_direct.py | 63 ++- 8 files changed, 1374 insertions(+), 26 deletions(-) create mode 100644 test/sbol3.nt create mode 100644 test/test_files/create_subcomponent_test.py create mode 100644 test/test_files/sbol_3to2_toggle_switch.nt create mode 100644 test/test_files/subcomponent_test_3.nt create mode 100644 test/test_files/subcomponent_test_3_bare_bones.nt create mode 100644 test/test_files/~$circular_inference_test.xlsx diff --git a/sbol_utilities/sbol3_sbol2_conversion.py b/sbol_utilities/sbol3_sbol2_conversion.py index 800a5c0c..8afb61ec 100644 --- a/sbol_utilities/sbol3_sbol2_conversion.py +++ b/sbol_utilities/sbol3_sbol2_conversion.py @@ -22,6 +22,7 @@ class SBOL3To2ConversionVisitor: doc2: sbol2.Document def __init__(self, doc3: sbol3.Document): + self.doc3 = doc3 # Create the target document self.doc2 = sbol2.Document() # # Immediately run the conversion @@ -157,11 +158,30 @@ def visit_component(self, cp3: sbol3.Component): cp2.roles = cp3.roles cp2.sequences = cp3.sequences if cp3.features: - raise NotImplementedError('Conversion of Component features from SBOL3 to SBOL2 not yet implemented') + for feature in cp3.features: + if type(feature) == sbol3.subcomponent.SubComponent: + try: + self.visit_sub_component(feature) + except NotImplementedError as e: + print(f"\033[91m{e}\033[0m") + if type(feature) == sbol3.compref.ComponentReference: + try: + self.visit_component_reference(feature) + except NotImplementedError as e: + print(f"\033[91m{e}\033[0m") if cp3.interactions: - raise NotImplementedError('Conversion of Component interactions from SBOL3 to SBOL2 not yet implemented') + for interaction in cp3.interactions: + try: + self.visit_interaction(interaction) + except NotImplementedError as e: + print(f"\033[91m{e}\033[0m") if cp3.constraints: - raise NotImplementedError('Conversion of Component constraints from SBOL3 to SBOL2 not yet implemented') + for constraint in cp3.constraints: + try: + pass + self.visit_constraint(constraint) + except NotImplementedError as e: + print(f"\033[91m{e}\033[0m") if cp3.interface: raise NotImplementedError('Conversion of Component interface from SBOL3 to SBOL2 not yet implemented') if cp3.models: @@ -169,13 +189,29 @@ def visit_component(self, cp3: sbol3.Component): # Map over all other TopLevel properties and extensions not covered by the constructor self._convert_toplevel(cp3, cp2) - def visit_component_reference(self, a: sbol3.ComponentReference): + def visit_component_reference(self, comp_ref3: sbol3.ComponentReference): # Priority: 3 raise NotImplementedError('Conversion of ComponentReference from SBOL3 to SBOL2 not yet implemented') - def visit_constraint(self, a: sbol3.Constraint): + def visit_constraint(self, constraint: sbol3.Constraint): # Priority: 2 - raise NotImplementedError('Conversion of Constraint from SBOL3 to SBOL2 not yet implemented') + + if constraint.restriction == "http://sbols.org/v3#verifyIdentical": + maps_to = sbol2.mapsto.MapsTo(constraint.identity, refinement="http://sbols.org/v2#verifyIdentical") + module_definition = sbol2.ModuleDefinition(constraint.identity) + module_definition.modules.add(maps_to) + self.doc2.addModuleDefinition(module_definition) + local = sbol2.Component(constraint.object) + remote = sbol2.Component(self.doc3.find(constraint.subject).refers_to) + maps_to.local = local + maps_to.remote = remote + + + + + if constraint.restriction == "http://sbols.org/v3#replaces": + raise NotImplementedError( + 'Conversion of Constraint from SBOL3 to SBOL2 with replaces restriction not yet implemented') def visit_cut(self, a: sbol3.Cut): # Priority: 2 @@ -262,7 +298,7 @@ def visit_sequence(self, seq3: sbol3.Sequence): # Map over all other TopLevel properties and extensions not covered by the constructor self._convert_toplevel(seq3, seq2) - def visit_sequence_feature(self, a: sbol3.SequenceFeature): + def visit_sequence_feature(self, feat3: sbol3.SequenceFeature): # Priority: 1 raise NotImplementedError('Conversion of SequenceFeature from SBOL3 to SBOL2 not yet implemented') @@ -273,17 +309,27 @@ def visit_singular_unit(self, a: sbol3.SingularUnit): def visit_sub_component(self, sub3: sbol3.SubComponent): # Priority: 1 - # Make the Component, Module, and Functional_Component objects and add them to the document + + # Make the Component, Module, or Functional_Component objects and add them to the document + # TODO Handle converting sub_components into Modules and FunctionalEntities when necessary component2 = sbol2.Component(sub3.identity) - module2 = sbol2.Module(sub3.identity, definition=sub3.instance_of) - functional_component2 = sbol2.FunctionalComponent(sub3.identity) - self.doc2.addSequence(component2) - self.doc2.addSequence(module2) - self.doc2.addSequence(functional_component2) - # Map over all other TopLevel properties and extensions not covered by the constructor - self._convert_toplevel(sub3, component2) - self._convert_toplevel(sub3, module2) - self._convert_toplevel(sub3, functional_component2) + component2.roles = sub3.roles + component2.roleIntegration = sub3.role_integration + component2.sourceLocations = sub3.source_locations + self.doc2.addComponentDefinition(component2) + + module2 = sbol2.Module(sub3.identity) + module2.definition = sub3.instance_of + print("JKLFDSJZFKLDSJLKSDJKLDS") + print(module2) + self.doc2.addModuleDefinition(module2) + # print(f"Module: {self.doc2.getModuleDefinition('https://synbiohub.org/public/igem/device1_ecoli/SubComponent3')}") + print(f"components: {self.doc2.componentDefinitions}") + + + raise NotImplementedError( + 'Conversion of SubComponent from SBOL3 to SBOL2 not yet implemented in case of Module and FunctionalEntities') + def visit_unit_division(self, a: sbol3.UnitDivision): # Priority: 4 @@ -433,8 +479,13 @@ def visit_component_definition(self, cd2: sbol2.ComponentDefinition): # Map over all other TopLevel properties and extensions not covered by the constructor self._convert_toplevel(cd2, cp3) - def visit_component(self, a: sbol2.Component): + def visit_component(self, comp2: sbol2.Component): # Priority: 2 + sub3 = sbol3.SubComponent(comp2.identity) + comp2.roles = sub3.roles + comp2.roleIntegration = sub3.role_integration + comp2.sourceLocations = sub3.source_locations + self.doc3.add(sub3) raise NotImplementedError('Conversion of Component from SBOL2 to SBOL3 not yet implemented') def visit_cut(self, a: sbol2.Cut): diff --git a/test/sbol3.nt b/test/sbol3.nt new file mode 100644 index 00000000..ed4e70d4 --- /dev/null +++ b/test/sbol3.nt @@ -0,0 +1,436 @@ + "Range1" . + "3242"^^ . + . + . + "0"^^ . + . + "GenbankReference1" . + "Tyson,G.H., McDermott,P.F., Li,C., Chen,Y., Tadesse,D.A., Mukherjee,S., Bodeis-Jones,S., Kabera,C., Gaines,S.A., Loneragan,G.H., Edrington,T.S., Torrence,M., Harhay,D.M. and Zhao,S." . + "" . + "JWYZ01000115" . + "" . + "J. Antimicrob. Chemother. 70 (10), 2763-2769 (2015)" . + . + "" . + "26142410" . + "WGS accurately predicts antimicrobial resistance in Escherichia coli" . + . + . + "Range1" . + "3242"^^ . + . + . + "0"^^ . + . + "GenbankReference2" . + "Tyson,G.H., McDermott,P.F., Li,C., Tadesse,D.A., Mukherjee,S., Bodeis-Jones,S., Kabera,C., Gaines,S.A., Loneragan,G.H., Edrington,T.S., Torrence,M., Harhay,D.M. and Zhao,S." . + "" . + "JWYZ01000115" . + "" . + "Submitted (17-NOV-2014) CVM, FDA, 8401 Muirkirk Rd, Laurel, MD 20708, USA" . + . + "" . + "" . + "Direct Submission" . + . + . + "GenbankStructuredComment1" . + "JWYZ01000115" . + "Genome-Assembly-Data" . + "1::Assembly Method" . + "2::Assembly Name" . + "3::Genome Coverage" . + "4::Sequencing Technology" . + "1::CLC Genomics Workbench v. 7.5" . + "2::Escherichia coli CVM N37069PS v1.0" . + "3::48.5x" . + "4::Illumina MiSeq" . + . + . + "GenbankStructuredComment2" . + "JWYZ01000115" . + "Genome-Annotation-Data" . + "10::CRISPR Arrays" . + "11::rRNAs" . + "12::tRNAs" . + "13::ncRNA" . + "14::Frameshifted Genes" . + "1::Annotation Provider" . + "2::Annotation Date" . + "3::Annotation Pipeline" . + "4::Annotation Method" . + "5::Annotation Software revision" . + "6::Features Annotated" . + "7::Genes" . + "8::CDS" . + "9::Pseudo Genes" . + "10::2" . + "11::11 (5S, 16S, 23S)" . + "12::78" . + "13::17" . + "14::41" . + "1::NCBI" . + "2::12/29/2014 14:07:05" . + "3::NCBI Prokaryotic Genome Annotation Pipeline" . + "4::Best-placed reference protein set; GeneMarkS+" . + "5::2.9 (rev. 455303)" . + "6::Gene; CDS; rRNA; tRNA; ncRNA; repeat_region" . + "7::4,855" . + "8::4,642" . + "9::107" . + . + . + "Range1" . + "115"^^ . + . + . + "1"^^ . + . + "Range1" . + "2299"^^ . + . + . + "1706"^^ . + . + "SequenceFeature10" . + . + . + . + "0:locus_tag" . + "0:PU64_23680" . + . + "Range1" . + "2299"^^ . + . + . + "1706"^^ . + . + "SequenceFeature11" . + . + . + . + "0:locus_tag" . + "1:inference" . + "2:note" . + "3:codon_start" . + "4:transl_table" . + "5:product" . + "6:protein_id" . + "7:translation" . + "0:PU64_23680" . + "1:EXISTENCE: similar to AA sequence:RefSeq:WP_001544295.1" . + "2:Derived by automated computational analysis using gene prediction method: Protein Homology." . + "3:1" . + "4:11" . + "5:TetR family transcriptional regulator" . + "6:KIG36582.1" . + "7:MVTKKQSRVPGRPRRFAPEQAISAAKVLFHQKGFDAVSVAEVTDYLGINPPSLYAAFGSKAGLFSRVLNEYVGTEAIPLADILRDDRPVGECLVEVLKEAARRYSQNGGCAGCMVLEGIHSHDPLARDIAVQYYHAAETTIYDYIARRHPQSAQCVTDFMSTVMSGLSAKAREGHSIEQLCATAALAGEAIKTLLKE" . + . + "Range1" . + "2896"^^ . + . + . + "2444"^^ . + . + "SequenceFeature12" . + . + . + . + "0:locus_tag" . + "0:PU64_23685" . + . + "Range1" . + "2896"^^ . + . + . + "2444"^^ . + . + "SequenceFeature13" . + . + . + . + "0:locus_tag" . + "1:inference" . + "2:note" . + "3:codon_start" . + "4:transl_table" . + "5:product" . + "6:protein_id" . + "7:translation" . + "0:PU64_23685" . + "1:EXISTENCE: similar to AA sequence:RefSeq:WP_001570607.1" . + "2:Derived by automated computational analysis using gene prediction method: Protein Homology." . + "3:1" . + "4:11" . + "5:toxin-antitoxin biofilm protein TabA" . + "6:KIG36583.1" . + "7:MIIGNIHNLQPWLPQELRQAIEHIKAHVTAETPKGKHDIEGNHLFYLISEDMTEPYEARRAEYHARYLDIQIVLKGQEGMTFSTQPAGTPDTDWLADKDIAFLPEGVDEKTVILNEGDFVVFYPGEVHKPLCAVGAPAQVRKAVVKMLMA" . + . + "Range1" . + "3242"^^ . + . + . + "3019"^^ . + . + "SequenceFeature14" . + . + . + . + "0:locus_tag" . + "0:PU64_23690" . + . + "Range1" . + "3242"^^ . + . + . + "3019"^^ . + . + "SequenceFeature15" . + . + . + . + "0:locus_tag" . + "1:inference" . + "2:note" . + "3:codon_start" . + "4:transl_table" . + "5:product" . + "6:protein_id" . + "7:translation" . + "0:PU64_23690" . + "1:EXISTENCE: similar to AA sequence:RefSeq:WP_000036524.1" . + "2:Derived by automated computational analysis using gene prediction method: Protein Homology." . + "3:1" . + "4:11" . + "5:DNA-binding protein" . + "6:KIG36584.1" . + "7:MSKISGWNFSQNITSADNCKQKNEDLDTWYVGMNDFARIAGGQNSRSNILSPRAFLEFLAKIFTLGYVDFSKRS" . + . + "SequenceFeature1" . + . + . + . + "0:locus_tag" . + "0:PU64_23660" . + . + "Range1" . + "115"^^ . + . + . + "1"^^ . + . + "SequenceFeature2" . + . + . + . + "0:locus_tag" . + "1:inference" . + "2:note" . + "3:codon_start" . + "4:transl_table" . + "5:product" . + "6:protein_id" . + "7:translation" . + "0:PU64_23660" . + "1:EXISTENCE: similar to AA sequence:RefSeq:WP_005059815.1" . + "2:Derived by automated computational analysis using gene prediction method: Protein Homology." . + "3:1" . + "4:11" . + "5:pyrBI operon leader peptide" . + "6:KIG36579.1" . + "7:MVQCVRHFVLPRLKKDAGLPFFFPLITHSQPLNRGAFF" . + . + "Range1" . + "3242"^^ . + . + . + "1"^^ . + . + "SequenceFeature3" . + . + . + . + "0:organism" . + "1:mol_type" . + "2:submitter_seqid" . + "3:strain" . + "4:isolation_source" . + "5:db_xref" . + "6:country" . + "7:collection_date" . + "0:Escherichia coli" . + "1:genomic DNA" . + "2:N37069PS_contig_115" . + "3:CVM N37069PS" . + "4:Farm" . + "5:taxon:562" . + "6:USA" . + "7:20-Jan-2012" . + . + "Range1" . + "427"^^ . + . + . + "95"^^ . + . + "SequenceFeature4" . + . + . + . + "0:locus_tag" . + "0:PU64_23665" . + . + "Range1" . + "427"^^ . + . + . + "95"^^ . + . + "SequenceFeature5" . + . + . + . + "0:locus_tag" . + "1:inference" . + "2:note" . + "3:codon_start" . + "4:transl_table" . + "5:product" . + "6:protein_id" . + "7:translation" . + "0:PU64_23665" . + "1:EXISTENCE: similar to AA sequence:RefSeq:WP_001349257.1" . + "2:Derived by automated computational analysis using gene prediction method: Protein Homology." . + "3:1" . + "4:11" . + "5:hypothetical protein" . + "6:KIG36585.1" . + "7:MSNTLNHTSSRQIVRHYTHRQKRRKHLMQYFVSANGLFELKVKVYAFLFDVILQGNCPSVSIIADIPCFFLFHFHAIRYAFYSIHPTYRAECESERLTLLLTAQGCALSL" . + . + "Range1" . + "791"^^ . + . + . + "396"^^ . + . + "SequenceFeature6" . + . + . + . + "0:locus_tag" . + "0:PU64_23670" . + . + "Range1" . + "791"^^ . + . + . + "396"^^ . + . + "SequenceFeature7" . + . + . + . + "0:locus_tag" . + "1:inference" . + "2:note" . + "3:codon_start" . + "4:transl_table" . + "5:product" . + "6:protein_id" . + "7:translation" . + "0:PU64_23670" . + "1:EXISTENCE: similar to AA sequence:RefSeq:WP_001701843.1" . + "2:Derived by automated computational analysis using gene prediction method: Protein Homology." . + "3:1" . + "4:11" . + "5:mRNA endoribonuclease" . + "6:KIG36580.1" . + "7:MVERTAVFPAGRHSLYAEHRYSAAIRSGDLLFVSGQVGSREDGTPEPDFQQQVRLAFDNLHATLAAAGCTFDDIIDVTSFHTDPENQFEDIMTVKNEIFSAPPYPNWTAVGVTWLAGFDFEIKVIARIPEQ" . + . + "Range1" . + "1635"^^ . + . + . + "922"^^ . + . + "SequenceFeature8" . + . + . + . + "0:locus_tag" . + "0:PU64_23675" . + . + "Range1" . + "1635"^^ . + . + . + "922"^^ . + . + "SequenceFeature9" . + . + . + . + "0:locus_tag" . + "1:inference" . + "2:note" . + "3:codon_start" . + "4:transl_table" . + "5:product" . + "6:protein_id" . + "7:translation" . + "0:PU64_23675" . + "1:EXISTENCE: similar to AA sequence:SwissProt:P39333.2" . + "2:Derived by automated computational analysis using gene prediction method: Protein Homology." . + "3:1" . + "4:11" . + "5:oxidoreductase" . + "6:KIG36581.1" . + "7:MGAFTGKTVLILGGSRGIGAAIVRRFVTDGANVRFTYAGSKDAAKRLAQETGATAVFTDSADRDAVIDVVRKSGALDILVVNAGIGVFGEALELNADDIDRLFKINIHAPYHASVEAARQMPEGGRILIIGSVNGDRMPVAGMAAYAASKSALQGMARGLARDFGPRGITINVVQPGPIDTDANPANGPMRDMLHSLMAIKRHGQPEEVAGMVAWLAGPEASFVTGAMHTIDGAFGA" . + . + "Escherichia coli strain CVM N37069PS N37069PS_contig_115, whole genome shotgun sequence" . + "JWYZ01000115" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "JWYZ01000115" . + "Annotation was added by the NCBI Prokaryotic Genome Annotation\nPipeline (released 2013). Information about the Pipeline can be\nfound here: http://www.ncbi.nlm.nih.gov/genome/annotation_prok/" . + "16-JAN-2015" . + "BioProject:PRJNA266657::BioSample:SAMN03177677" . + "BCT" . + "JWYZ01000115.1" . + "WGS" . + "JWYZ01000115" . + "DNA" . + "JWYZ01000115" . + "Escherichia coli" . + . + . + "1"^^ . + "Escherichia coli" . + . + . + "Bacteria,Proteobacteria,Gammaproteobacteria,Enterobacterales,Enterobacteriaceae,Escherichia" . + "linear" . + . + "JWYZ01000115_sequence" . + "aaaaaaaagcccctcgattgaggggctgggaatgggtgatcaacgggaagaaaaacggcaggccagcgtcttttttcagacgcggtaagacaaaatgtcgaacacactgaaccatacatcctcccggcaaattgtccggcattatactcatcgtcagaagcggcgcaagcatttgatgcaatattttgtcagcgcaaacggtttatttgaattaaaagtcaaggtatatgcatttttatttgatgtgattctgcaggggaactgtccttcggtatcaataattgcagacattccctgctttttcctttttcactttcacgcaatcagatatgcattttattccattcatccgacttatagggcggagtgtgaaagcgaacggctaacactattgcttactgctcagggatgcgcgctatcactttaatttcaaaatcaaagcctgccagccatgtaacacccaccgccgtccagtttggataaggtggggcgctaaatatttcatttttcaccgtcatgatgtcttcaaattggttttctggatcggtatggaagctcgtaacatcaatgatatcgtcaaaagtgcatcccgcagctgccagggtcgcatgcaaattatcaaatgccagtctgacttgttgctgaaaatcgggttctggtgttccgtcctctcgacttcctacttgcccggaaacaaacagcaaatcgccggaacgaatagccgcagaataacgatgctcagcatatagtgaatgtcggccagcagggaaaacagcggttctttctaccatttggttatcctcaagatttacgacatgaacagaagatttctctttaccgggagccgcttttagcggacgacgtgagtaaacaaaacccagacatcatggataatggctgggcttaattgagcgtagtcggttatgcgccaaacgcgccatcaatggtatgcattgcgccggtaacaaaactggcttctggccctgctaaccatgcgaccataccagcgacctcttccggttgcccatgtcttttgatagccatcaaactatgcaacatatcgcgcattggcccgttggcgggattagcgtcggtatcaattggccctggctggacgacgttaatggtgatcccacgcggtccaaaatcacgggccagcccgcgcgccatgccttgcagggcagatttgctggcggcataagcagccatgcctgcaacaggcatacgatcgccattcacggagccgatgattaagatgcgcccgccttcgggcatctgccgggcggcttcaacagaggcatgataaggagcatgaatattgattttgaaaaggcgatcaatatcgtcggcatttaattccagggcctcgccaaagacgccaatacctgcatttaccaccaggatatccaatgcgccgctcttacgaacgacatcaatgacagcgtctctgtcagcactatctgtgaatactgctgtcgctccagtctcttgtgccaggcgtttagcggcatctttcgaccccgcataggtgaatcgtacattggccccatcggtgacgaaacgacgtacgatagcggcaccgataccacgactgccaccgaggatgagaactgtcttacctgtaaaagcgcccataaggactccttgatttattatgtaacatgcattacaaaactgttttaactttctgtcaacatgttttgtaatggtcactaaaaaacaatctcgcgttccaggtcgtcccagacgtttcgctcctgagcaggcaatctctgcggcaaaagtgctttttcaccaaaaaggtttcgatgctgtcagtgttgctgaagttactgattatcttggtattaaccccccgagcctctacgcggcttttggcagtaaagctgggttatttagccgtgtactcaatgaatacgtcggtacggaagctattccgcttgccgatattcttcgtgatgatcgtccagtaggcgagtgcctggttgaggtattaaaagaagcggcgcgcagatatagccaaaacggcggctgcgctggctgtatggttcttgaaggtattcatagtcatgatccactagcgcgtgatattgccgttcaatattatcacgccgcagaaacgaccatttatgactatatcgccaggcggcatccacaaagcgcacaatgtgtgactgattttatgagtaccgtgatgtcagggctttctgcgaaggcacgggaggggcactcaatcgaacaactctgtgcaacagctgcactggcgggggaagcgataaaaactcttctcaaggagtgatgctggccttgatccgaaaggcgggaacgcgcctgccgataagttgtgataagacaataattcacgcattaaggctagcggaattgatcatcttttcgtataacgatagaaatgaaacgttgttttaattaaggagtggaaaagatgatcatcggaaatattcataatcttcagccgtggctaccccaggagttacgccaggcgattgagcatatcaaagcacacgttacggcagaaacgccaaagggcaagcacgatatcgaaggcaatcatctgttttatcttatctcggaagatatgaccgagccgtacgaagcccgccgtgcggagtaccatgcccgctatctcgacattcagattgtgttaaaaggtcaggaaggcatgaccttcagcacgcaacctgcaggcacgccggataccgactggttagctgataaagacatcgcatttttgccggaaggcgttgatgagaaaacagttatccttaatgaaggtgattttgttgtgttttatccgggggaagtgcataaaccgctgtgcgcagtgggtgcaccagcccaggttcgcaaagcagtagtgaagatgctgatggcgtgatgacttttcgccgtaaataactccaggtttacggcgagtttgtgaaaagagcgttttttgatatttttttgtgagtaaaatttgtaatgcttagacgttcttattaactcaaggagtccgtcatgagcaaaatatcaggttggaatttttctcaaaacattacatcagccgacaattgtaaacaaaaaaatgaagacttagatacctggtatgtgggaatgaatgattttgcccgaattgccggagggcagaatagcagaagcaatattctttctcccagagcatttttggagtttttggctaagatatttaccctgggttatgtggattttagcaaacgctccaa" . + . + . + . diff --git a/test/test_files/create_subcomponent_test.py b/test/test_files/create_subcomponent_test.py new file mode 100644 index 00000000..f55dff1d --- /dev/null +++ b/test/test_files/create_subcomponent_test.py @@ -0,0 +1,89 @@ +from sbol3 import * +from sbol_utilities.calculate_sequences import compute_sequence +from sbol_utilities.component import * +from sbol_utilities.helper_functions import url_to_identity +import tyto + +set_namespace('https://synbiohub.org/public/igem/') +doc = Document() + +i13504 = Component('i13504', SBO_DNA) +i13504.name = 'iGEM 2016 interlab reporter' +i13504.description = 'GFP expression cassette used for 2016 iGEM interlab study' +i13504.roles.append(tyto.SO.engineered_region) + +doc.add(i13504) + +b0034, b0034_seq = doc.add(rbs('B0034', sequence='aaagaggagaaa', name='RBS (Elowitz 1999)')) + + +e0040_sequence = 'atgcgtaaaggagaagaacttttcactggagttgtcccaattcttgttgaattagatggtgatgttaatgggcacaaattttctgtcagtggagagggtgaaggtgatgcaacatacggaaaacttacccttaaatttatttgcactactggaaaactacctgttccatggccaacacttgtcactactttcggttatggtgttcaatgctttgcgagatacccagatcatatgaaacagcatgactttttcaagagtgccatgcccgaaggttatgtacaggaaagaactatatttttcaaagatgacgggaactacaagacacgtgctgaagtcaagtttgaaggtgatacccttgttaatagaatcgagttaaaaggtattgattttaaagaagatggaaacattcttggacacaaattggaatacaactataactcacacaatgtatacatcatggcagacaaacaaaagaatggaatcaaagttaacttcaaaattagacacaacattgaagatggaagcgttcaactagcagaccattatcaacaaaatactccaattggcgatggccctgtccttttaccagacaaccattacctgtccacacaatctgccctttcgaaagatcccaacgaaaagagagaccacatggtccttcttgagtttgtaacagctgctgggattacacatggcatggatgaactatacaaataataa' +e0040, _ = doc.add(cds('E0040', sequence=e0040_sequence, name='GFP')) + +b0015_sequence = 'ccaggcatcaaataaaacgaaaggctcagtcgaaagactgggcctttcgttttatctgttgtttgtcggtgaacgctctctactagagtcacactggctcaccttcgggtgggcctttctgcgtttata' +b0015, _ = doc.add(terminator('B0015', sequence=b0015_sequence, name='double terminator')) + + +order(b0034, e0040, i13504) +order(e0040, b0015, i13504) + +i13504_seq = compute_sequence(i13504) + +b0015_subcomponent = next(f for f in i13504.features if f.instance_of == b0015.identity) +b0015_range = b0015_subcomponent.locations[0] +print(f'Range of {b0015.display_name}: ({b0015_range.start}, {b0015_range.end})') + +i13504_system = functional_component('i13504_system') +doc.add(i13504_system) + +gfp = add_feature(i13504_system, ed_protein('https://www.fpbase.org/protein/gfpmut3/', name='GFP')) + +i13504_subcomponent = add_feature(i13504_system, i13504) + +e0040_subcomponent = next(f for f in i13504.features if f.instance_of == e0040.identity) +e0040_reference = ComponentReference(i13504_subcomponent, e0040_subcomponent) +i13504_system.features.append(e0040_reference) + + +add_interaction(tyto.SBO.genetic_production, + participants={gfp: tyto.SBO.product, e0040_reference: tyto.SBO.template}) + +J23101_sequence = 'tttacagctagctcagtcctaggtattatgctagc' +J23101, _ = doc.add(promoter('J23101', sequence=J23101_sequence)) +J23106_sequence = 'tttacggctagctcagtcctaggtatagtgctagc' +J23106, _ = doc.add(promoter('J23106', sequence=J23106_sequence)) + +device1 = doc.add(functional_component('interlab16device1')) +device1_i13504_system = add_feature(device1, SubComponent(i13504_system)) +order(J23101, ComponentReference(device1_i13504_system, i13504_subcomponent), device1) +device2 = doc.add(functional_component('interlab16device2')) +device2_i13504_system = add_feature(device2, SubComponent(i13504_system)) +order(J23106, ComponentReference(device2_i13504_system, i13504_subcomponent), device2) +print(f'Device 1 second subcomponent points to {device1.constraints[0].object.lookup().refers_to.lookup().instance_of}') + +interlab16 = doc.add(Collection('interlab16',members=[device1, device2])) +print(f'Members are {", ".join(m.lookup().display_id for m in interlab16.members)}') + +ecoli = doc.add(strain('Ecoli_DH5_alpha')) +pSB1C3 = doc.add(Component('pSB1C3', SBO_DNA, roles=[tyto.SO.plasmid_vector])) + +device1_ecoli = doc.add(strain('device1_ecoli')) + +plasmid = LocalSubComponent(SBO_DNA, roles=[tyto.SO.plasmid_vector], name="Interlab Device 1 in pSB1C3") +device1_ecoli.features.append(plasmid) +device1_subcomponent = contains(plasmid, device1) +contains(plasmid, pSB1C3) +order(device1, pSB1C3, device1_ecoli) + +contains(ecoli, plasmid, device1_ecoli) + + +report = doc.validate() +if report: + print('Document is not valid') + print(f'Document has {len(report.errors)} errors') + print(f'Document has {len(report.warnings)} warnings') +else: + print('Document is valid') + +doc.write('subcomponent_test_3_bare_bones.nt', file_format=SORTED_NTRIPLES) diff --git a/test/test_files/sbol_3to2_toggle_switch.nt b/test/test_files/sbol_3to2_toggle_switch.nt new file mode 100644 index 00000000..53c8766e --- /dev/null +++ b/test/test_files/sbol_3to2_toggle_switch.nt @@ -0,0 +1,7 @@ +https://sbolstandard.org/examples/col1, http://sbols.org/v2#version, 1 +https://sbolstandard.org/examples/col1, http://sbols.org/v2#member, https://sbolstandard.org/examples/LacI_protein +https://sbolstandard.org/examples/col1, http://sboltools.org/backport#sbol3namespace, https://sbolstandard.org/examples +https://sbolstandard.org/examples/col1, http://sbols.org/v2#persistentIdentity, https://sbolstandard.org/examples/col1 +https://sbolstandard.org/examples/col1, http://sbols.org/v2#member, https://sbolstandard.org/examples/TetR_protein +https://sbolstandard.org/examples/col1, http://www.w3.org/1999/02/22-rdf-syntax-ns#type, http://sbols.org/v2#Collection +https://sbolstandard.org/examples/col1, http://sbols.org/v2#displayId, col1 diff --git a/test/test_files/subcomponent_test_3.nt b/test/test_files/subcomponent_test_3.nt new file mode 100644 index 00000000..793f13c2 --- /dev/null +++ b/test/test_files/subcomponent_test_3.nt @@ -0,0 +1,464 @@ + "pubchem_compound_5460291" . + . + . + . + "pubchem_compound_5793" . + . + . + . + "pubchem_compound_6134" . + . + . + . + "pubchem_compound_6255" . + . + . + . + "B0015" . + . + . + "double terminator" . + . + . + . + "B0015_seq" . + "ccaggcatcaaataaaacgaaaggctcagtcgaaagactgggcctttcgttttatctgttgtttgtcggtgaacgctctctactagagtcacactggctcaccttcgggtgggcctttctgcgtttata" . + . + . + . + "B0034" . + . + . + "RBS (Elowitz 1999)" . + . + . + . + "B0034_seq" . + "aaagaggagaaa" . + . + . + . + "E0040" . + . + . + "GFP" . + . + . + . + "E0040_seq" . + "atgcgtaaaggagaagaacttttcactggagttgtcccaattcttgttgaattagatggtgatgttaatgggcacaaattttctgtcagtggagagggtgaaggtgatgcaacatacggaaaacttacccttaaatttatttgcactactggaaaactacctgttccatggccaacacttgtcactactttcggttatggtgttcaatgctttgcgagatacccagatcatatgaaacagcatgactttttcaagagtgccatgcccgaaggttatgtacaggaaagaactatatttttcaaagatgacgggaactacaagacacgtgctgaagtcaagtttgaaggtgatacccttgttaatagaatcgagttaaaaggtattgattttaaagaagatggaaacattcttggacacaaattggaatacaactataactcacacaatgtatacatcatggcagacaaacaaaagaatggaatcaaagttaacttcaaaattagacacaacattgaagatggaagcgttcaactagcagaccattatcaacaaaatactccaattggcgatggccctgtccttttaccagacaaccattacctgtccacacaatctgccctttcgaaagatcccaacgaaaagagagaccacatggtccttcttgagtttgtaacagctgctgggattacacatggcatggatgaactatacaaataataa" . + . + . + . + "Ecoli_DH5_alpha" . + . + . + . + . + "J23101" . + . + . + . + . + . + "J23101_seq" . + "tttacagctagctcagtcctaggtattatgctagc" . + . + . + . + "J23106" . + . + . + . + . + . + "J23106_seq" . + "tttacggctagctcagtcctaggtatagtgctagc" . + . + . + . + "Measure1" . + "78.0"^^ . + . + . + . + . + "ExternallyDefined1" . + . + . + . + "Measure1" . + "2.0"^^ . + . + . + . + . + "ExternallyDefined2" . + . + . + . + "Measure1" . + "200.0"^^ . + . + . + . + . + "ExternallyDefined3" . + . + . + . + "Measure1" . + "10.0"^^ . + . + . + . + . + "ExternallyDefined4" . + . + . + . + "Measure1" . + "20.0"^^ . + . + . + . + "LocalSubComponent1" . + . + "M9 salts" . + . + . + "M9_media" . + . + . + . + . + . + . + . + . + . + . + "Replicate1" . + . + . + . + "Replicate1_cytometry_fcs" . + . + . + . + . + . + "Replicate2" . + . + . + . + "Replicate2_cytometry_fcs" . + . + . + . + . + "Replicate3" . + . + . + . + "Replicate3_cytometry_fcs" . + . + . + . + "Measure1" . + . + "2.5"^^ . + . + . + . + . + "ExternallyDefined1" . + . + . + . + "Measure1" . + . + "200.0"^^ . + . + . + . + "SubComponent1" . + . + . + . + "Measure1" . + . + "10000.0"^^ . + . + . + . + "SubComponent2" . + . + . + . + "Sample1" . + . + . + . + . + . + . + "Measure1" . + . + "10000.0"^^ . + . + . + . + "LocalSubComponent1" . + . + . + . + "Measure1" . + . + "2.5"^^ . + . + . + . + "LocalSubComponent2" . + . + . + . + "Measure1" . + . + "200.0"^^ . + . + . + . + "SubComponent1" . + . + . + . + "SampleSpec" . + . + . + . + . + . + . + "ComponentReference1" . + . + . + . + "ComponentReference2" . + . + . + . + "Constraint1" . + . + . + . + . + "Constraint2" . + . + . + . + . + "Constraint3" . + . + . + . + . + "Constraint4" . + . + . + . + . + "Interface1" . + . + . + "LocalSubComponent1" . + "Interlab Device 1 in pSB1C3" . + . + . + . + "SubComponent1" . + . + . + "SubComponent2" . + . + . + "SubComponent3" . + . + . + "device1_ecoli" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "Constraint1" . + . + . + . + . + "Constraint2" . + . + . + . + . + "Range1" . + "12"^^ . + . + "1"^^ . + . + "SubComponent1" . + . + . + . + "Range1" . + "732"^^ . + . + "13"^^ . + . + "SubComponent2" . + . + . + . + "Range1" . + "861"^^ . + . + "733"^^ . + . + "SubComponent3" . + . + . + . + "GFP expression cassette used for 2016 iGEM interlab study" . + "i13504" . + . + . + . + . + . + . + . + "iGEM 2016 interlab reporter" . + . + . + . + "i13504_sequence" . + "aaagaggagaaaatgcgtaaaggagaagaacttttcactggagttgtcccaattcttgttgaattagatggtgatgttaatgggcacaaattttctgtcagtggagagggtgaaggtgatgcaacatacggaaaacttacccttaaatttatttgcactactggaaaactacctgttccatggccaacacttgtcactactttcggttatggtgttcaatgctttgcgagatacccagatcatatgaaacagcatgactttttcaagagtgccatgcccgaaggttatgtacaggaaagaactatatttttcaaagatgacgggaactacaagacacgtgctgaagtcaagtttgaaggtgatacccttgttaatagaatcgagttaaaaggtattgattttaaagaagatggaaacattcttggacacaaattggaatacaactataactcacacaatgtatacatcatggcagacaaacaaaagaatggaatcaaagttaacttcaaaattagacacaacattgaagatggaagcgttcaactagcagaccattatcaacaaaatactccaattggcgatggccctgtccttttaccagacaaccattacctgtccacacaatctgccctttcgaaagatcccaacgaaaagagagaccacatggtccttcttgagtttgtaacagctgctgggattacacatggcatggatgaactatacaaataataaccaggcatcaaataaaacgaaaggctcagtcgaaagactgggcctttcgttttatctgttgtttgtcggtgaacgctctctactagagtcacactggctcaccttcgggtgggcctttctgcgtttata" . + . + . + . + "ComponentReference1" . + . + . + . + . + "ExternallyDefined1" . + "GFP" . + . + . + "Participation1" . + . + . + . + "Participation2" . + . + . + . + "Interaction1" . + . + . + . + . + "SubComponent1" . + . + . + "i13504_system" . + . + . + . + . + . + . + . + "interlab16" . + . + . + . + . + "ComponentReference1" . + . + . + . + "Constraint1" . + . + . + . + . + "SubComponent1" . + . + . + "SubComponent2" . + . + . + "interlab16device1" . + . + . + . + . + . + . + . + "ComponentReference1" . + . + . + . + "Constraint1" . + . + . + . + . + "SubComponent1" . + . + . + "SubComponent2" . + . + . + "interlab16device2" . + . + . + . + . + . + . + . + "Usage1" . + . + . + . + "measure_sample_1" . + . + . + . + . + . + "my_iBioSIM_ODE" . + . + . + . + . + . + "pSB1C3" . + . + . + . + . diff --git a/test/test_files/subcomponent_test_3_bare_bones.nt b/test/test_files/subcomponent_test_3_bare_bones.nt new file mode 100644 index 00000000..8b338e9c --- /dev/null +++ b/test/test_files/subcomponent_test_3_bare_bones.nt @@ -0,0 +1,254 @@ + "B0015" . + . + . + "double terminator" . + . + . + . + "B0015_seq" . + "ccaggcatcaaataaaacgaaaggctcagtcgaaagactgggcctttcgttttatctgttgtttgtcggtgaacgctctctactagagtcacactggctcaccttcgggtgggcctttctgcgtttata" . + . + . + . + "B0034" . + . + . + "RBS (Elowitz 1999)" . + . + . + . + "B0034_seq" . + "aaagaggagaaa" . + . + . + . + "E0040" . + . + . + "GFP" . + . + . + . + "E0040_seq" . + "atgcgtaaaggagaagaacttttcactggagttgtcccaattcttgttgaattagatggtgatgttaatgggcacaaattttctgtcagtggagagggtgaaggtgatgcaacatacggaaaacttacccttaaatttatttgcactactggaaaactacctgttccatggccaacacttgtcactactttcggttatggtgttcaatgctttgcgagatacccagatcatatgaaacagcatgactttttcaagagtgccatgcccgaaggttatgtacaggaaagaactatatttttcaaagatgacgggaactacaagacacgtgctgaagtcaagtttgaaggtgatacccttgttaatagaatcgagttaaaaggtattgattttaaagaagatggaaacattcttggacacaaattggaatacaactataactcacacaatgtatacatcatggcagacaaacaaaagaatggaatcaaagttaacttcaaaattagacacaacattgaagatggaagcgttcaactagcagaccattatcaacaaaatactccaattggcgatggccctgtccttttaccagacaaccattacctgtccacacaatctgccctttcgaaagatcccaacgaaaagagagaccacatggtccttcttgagtttgtaacagctgctgggattacacatggcatggatgaactatacaaataataa" . + . + . + . + "Ecoli_DH5_alpha" . + . + . + . + . + "J23101" . + . + . + . + . + . + "J23101_seq" . + "tttacagctagctcagtcctaggtattatgctagc" . + . + . + . + "J23106" . + . + . + . + . + . + "J23106_seq" . + "tttacggctagctcagtcctaggtatagtgctagc" . + . + . + . + "Constraint1" . + . + . + . + . + "Constraint2" . + . + . + . + . + "Constraint3" . + . + . + . + . + "Constraint4" . + . + . + . + . + "LocalSubComponent1" . + "Interlab Device 1 in pSB1C3" . + . + . + . + "SubComponent1" . + . + . + "SubComponent2" . + . + . + "SubComponent3" . + . + . + "device1_ecoli" . + . + . + . + . + . + . + . + . + . + . + . + . + "Constraint1" . + . + . + . + . + "Constraint2" . + . + . + . + . + "Range1" . + "12"^^ . + . + "1"^^ . + . + "SubComponent1" . + . + . + . + "Range1" . + "732"^^ . + . + "13"^^ . + . + "SubComponent2" . + . + . + . + "Range1" . + "861"^^ . + . + "733"^^ . + . + "SubComponent3" . + . + . + . + "GFP expression cassette used for 2016 iGEM interlab study" . + "i13504" . + . + . + . + . + . + . + . + "iGEM 2016 interlab reporter" . + . + . + . + "i13504_sequence" . + "aaagaggagaaaatgcgtaaaggagaagaacttttcactggagttgtcccaattcttgttgaattagatggtgatgttaatgggcacaaattttctgtcagtggagagggtgaaggtgatgcaacatacggaaaacttacccttaaatttatttgcactactggaaaactacctgttccatggccaacacttgtcactactttcggttatggtgttcaatgctttgcgagatacccagatcatatgaaacagcatgactttttcaagagtgccatgcccgaaggttatgtacaggaaagaactatatttttcaaagatgacgggaactacaagacacgtgctgaagtcaagtttgaaggtgatacccttgttaatagaatcgagttaaaaggtattgattttaaagaagatggaaacattcttggacacaaattggaatacaactataactcacacaatgtatacatcatggcagacaaacaaaagaatggaatcaaagttaacttcaaaattagacacaacattgaagatggaagcgttcaactagcagaccattatcaacaaaatactccaattggcgatggccctgtccttttaccagacaaccattacctgtccacacaatctgccctttcgaaagatcccaacgaaaagagagaccacatggtccttcttgagtttgtaacagctgctgggattacacatggcatggatgaactatacaaataataaccaggcatcaaataaaacgaaaggctcagtcgaaagactgggcctttcgttttatctgttgtttgtcggtgaacgctctctactagagtcacactggctcaccttcgggtgggcctttctgcgtttata" . + . + . + . + "ComponentReference1" . + . + . + . + . + "ExternallyDefined1" . + "GFP" . + . + . + "Participation1" . + . + . + . + "Participation2" . + . + . + . + "Interaction1" . + . + . + . + . + "SubComponent1" . + . + . + "i13504_system" . + . + . + . + . + . + . + . + "interlab16" . + . + . + . + . + "ComponentReference1" . + . + . + . + "Constraint1" . + . + . + . + . + "SubComponent1" . + . + . + "SubComponent2" . + . + . + "interlab16device1" . + . + . + . + . + . + . + . + "ComponentReference1" . + . + . + . + "Constraint1" . + . + . + . + . + "SubComponent1" . + . + . + "SubComponent2" . + . + . + "interlab16device2" . + . + . + . + . + . + . + . + "pSB1C3" . + . + . + . + . diff --git a/test/test_files/~$circular_inference_test.xlsx b/test/test_files/~$circular_inference_test.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..802e3f9c33c0f5cda473fbf4d22eadaa9a99b84f GIT binary patch literal 165 ycmd;yOwA}wNmOvk%*)JHAR6#6L^7l@WH6L6q%b5hC@?rNWHRIdaW;@meFy*yp%Zfe literal 0 HcmV?d00001 diff --git a/test/test_sbol2_sbol3_direct.py b/test/test_sbol2_sbol3_direct.py index 849db10c..860f5f1e 100644 --- a/test/test_sbol2_sbol3_direct.py +++ b/test/test_sbol2_sbol3_direct.py @@ -129,24 +129,71 @@ def test_2to3_collection_conversion(self): doc2_loop.write(tmp2) self.assertFalse(file_diff(str(tmp2), str(TEST_FILES / 'sbol_3to2_collection.xml'))) - def test_3to2_sub_component_conversion(self): - """Test ability to convert a collection from SBOL3 to SBOL2""" + def test_3to2_subcomponent_test(self): + """Test ability to convert a sub_component from SBOL3 to SBOL2""" # Load an SBOL3 document and check its contents doc3 = sbol3.Document() - doc3.read(TEST_FILES / 'sbol3_toggle_switch.nt') + doc3.read(TEST_FILES / 'subcomponent_test_3_bare_bones.nt') # Convert to SBOL2 and check contents - doc2 = convert3to2(doc3, True) - #report = doc2.validate() - #self.assertEqual(len(report), 0, f'Validation failed: {report}') + doc2 = sbol2.Document() + doc2 = convert3to2(doc3, use_native_converter=True) + + # report = doc2.validate() + # self.assertEqual(len(report), 0, f'Validation failed: {report}') with tempfile.TemporaryDirectory() as tmpdir: tmp2 = Path(tmpdir) / 'doc2.xml' doc2.write(tmp2) - self.assertFalse(file_diff(str(tmp2), str(TEST_FILES / 'sbol_3to2_collection.xml'))) + with open(tmp2, "r") as file: + # Read the contents of the file + file_contents = file.read() + + # Print the contents + # self.assertFalse(file_diff(str(tmp2), str(TEST_FILES / 'sbol_3to2_collection.xml'))) doc3_loop = convert2to3(doc2, use_native_converter=True) self.assertEqual(len(doc3_loop.validate()), 0) tmp3 = Path(tmpdir) / 'doc3_loop.nt' doc3_loop.write(tmp3) - self.assertFalse(file_diff(str(tmp3), str(TEST_FILES / 'sbol3_collection.nt'))) + + print("DOC_3") + print(doc3) + component_list = [] + for object in doc3.objects: + if type(object) == sbol3.component.Component: + component_list.append(object) + subcomponent_list = [] + for component in component_list: + print(component.display_id) + print(f"Type: {component.types}") + for feat in component.features: + if type(feat) == sbol3.subcomponent.SubComponent: + print(f"\tInstance Of: {feat.instance_of}") + print(f"\t\tRoles: {feat.roles}") + print(f"\t\tRole Integration: {feat.role_integration}") + print(f"\t\tSource Locations: {feat.source_locations}") + + print("\nDOC_2") + print(doc2) + for object in doc2: + if type(object) == sbol2.componentdefinition.ComponentDefinition: + print(object) + print(f"\tComponents: {object.components}") + + + print("\nDOCK_3_loop") + print(doc3_loop) + component_list = [] + for object in doc3_loop.objects: + if type(object) == sbol3.component.Component: + component_list.append(object) + for component in component_list: + print(component.display_id) + for feat in component.features: + print("\t" + str(type(feat))) + + self.assertFalse(file_diff(str(tmp3), str(TEST_FILES / 'subcomponent_test_3_bare_bones.nt'))) + + + From 7727c2ded9dae265820ef364b0d7537c744135a8 Mon Sep 17 00:00:00 2001 From: Yehuda Binik Date: Tue, 13 Aug 2024 15:59:02 -0400 Subject: [PATCH 04/14] Made some progress --- sbol_utilities/sbol3_sbol2_conversion.py | 35 +- test/doc3_loop.nt | 50 +++ test/test.nt | 0 test/test.xml | 0 test/test_files/create_subcomponent_test.py | 2 +- test/test_files/subcomponent_test.nt | 67 +++ test/test_files/subcomponent_test_3.nt | 397 ------------------ ....nt => subcomponent_test_3_bare_bones.xml} | 0 test/test_sbol2_sbol3_direct.py | 25 +- 9 files changed, 150 insertions(+), 426 deletions(-) create mode 100644 test/doc3_loop.nt create mode 100644 test/test.nt create mode 100644 test/test.xml create mode 100644 test/test_files/subcomponent_test.nt rename test/test_files/{subcomponent_test_3_bare_bones.nt => subcomponent_test_3_bare_bones.xml} (100%) diff --git a/sbol_utilities/sbol3_sbol2_conversion.py b/sbol_utilities/sbol3_sbol2_conversion.py index 8afb61ec..d4fa64d9 100644 --- a/sbol_utilities/sbol3_sbol2_conversion.py +++ b/sbol_utilities/sbol3_sbol2_conversion.py @@ -145,6 +145,7 @@ def visit_combinatorial_derivation(self, a: sbol3.CombinatorialDerivation): def visit_component(self, cp3: sbol3.Component): # Remap type if it's one of the ones that needs remapping; otherwise pass through unchanged + type_map = {sbol3.SBO_DNA: sbol2.BIOPAX_DNA, # TODO: distinguish BioPAX Dna from DnaRegion sbol3.SBO_RNA: sbol2.BIOPAX_RNA, # TODO: distinguish BioPAX Rna from RnaRegion sbol3.SBO_PROTEIN: sbol2.BIOPAX_PROTEIN, @@ -161,7 +162,7 @@ def visit_component(self, cp3: sbol3.Component): for feature in cp3.features: if type(feature) == sbol3.subcomponent.SubComponent: try: - self.visit_sub_component(feature) + self.visit_sub_component(cp3, feature) except NotImplementedError as e: print(f"\033[91m{e}\033[0m") if type(feature) == sbol3.compref.ComponentReference: @@ -206,9 +207,6 @@ def visit_constraint(self, constraint: sbol3.Constraint): maps_to.local = local maps_to.remote = remote - - - if constraint.restriction == "http://sbols.org/v3#replaces": raise NotImplementedError( 'Conversion of Constraint from SBOL3 to SBOL2 with replaces restriction not yet implemented') @@ -306,31 +304,23 @@ def visit_singular_unit(self, a: sbol3.SingularUnit): # Priority: 4 raise NotImplementedError('Conversion of SingularUnit from SBOL3 to SBOL2 not yet implemented') - def visit_sub_component(self, sub3: sbol3.SubComponent): + def visit_sub_component(self, comp3: sbol3.Component, sub3: sbol3.SubComponent): # Priority: 1 - # Make the Component, Module, or Functional_Component objects and add them to the document # TODO Handle converting sub_components into Modules and FunctionalEntities when necessary component2 = sbol2.Component(sub3.identity) component2.roles = sub3.roles component2.roleIntegration = sub3.role_integration component2.sourceLocations = sub3.source_locations + component2.definition = sub3.instance_of self.doc2.addComponentDefinition(component2) - module2 = sbol2.Module(sub3.identity) - module2.definition = sub3.instance_of - print("JKLFDSJZFKLDSJLKSDJKLDS") - print(module2) - self.doc2.addModuleDefinition(module2) - # print(f"Module: {self.doc2.getModuleDefinition('https://synbiohub.org/public/igem/device1_ecoli/SubComponent3')}") print(f"components: {self.doc2.componentDefinitions}") - raise NotImplementedError( 'Conversion of SubComponent from SBOL3 to SBOL2 not yet implemented in case of Module and FunctionalEntities') - def visit_unit_division(self, a: sbol3.UnitDivision): # Priority: 4 raise NotImplementedError('Conversion of UnitDivision from SBOL3 to SBOL2 not yet implemented') @@ -482,11 +472,11 @@ def visit_component_definition(self, cd2: sbol2.ComponentDefinition): def visit_component(self, comp2: sbol2.Component): # Priority: 2 sub3 = sbol3.SubComponent(comp2.identity) - comp2.roles = sub3.roles - comp2.roleIntegration = sub3.role_integration - comp2.sourceLocations = sub3.source_locations + sub3.roles = comp2.roles + sub3.roleIntegration = comp2.role_integration + sub3.sourceLocations = comp2.source_locations + sub3.instance_of = comp2.definition self.doc3.add(sub3) - raise NotImplementedError('Conversion of Component from SBOL2 to SBOL3 not yet implemented') def visit_cut(self, a: sbol2.Cut): # Priority: 2 @@ -566,9 +556,14 @@ def visit_module(self, a: sbol2.Module): # Priority: 3 raise NotImplementedError('Conversion of Module from SBOL2 to SBOL3 not yet implemented') - def visit_module_definition(self, a: sbol2.ModuleDefinition): + def visit_module_definition(self, md2: sbol2.ModuleDefinition): # Priority: 3 - raise NotImplementedError('Conversion of ModuleDefinition from SBOL2 to SBOL3 not yet implemented') + + # Make the Component object and add it to the document + cp3 = sbol3.Component(md2.identity, types=['https://identifiers.org/SBO:0000241']) + self.doc3.add(cp3) + # Map over all other TopLevel properties and extensions not covered by the constructor + self._convert_toplevel(md2, cp3) def visit_participation(self, a: sbol2.Participation): # Priority: 2 diff --git a/test/doc3_loop.nt b/test/doc3_loop.nt new file mode 100644 index 00000000..a2b58801 --- /dev/null +++ b/test/doc3_loop.nt @@ -0,0 +1,50 @@ + . + . + . + . + . + "B0034" . + "1" . + . + "B0034_seq" . + "B0015_seq" . + "ccaggcatcaaataaaacgaaaggctcagtcgaaagactgggcctttcgttttatctgttgtttgtcggtgaacgctctctactagagtcacactggctcaccttcgggtgggcctttctgcgtttata" . + "1" . + "1" . + . + "1" . + "iGEM 2016 interlab reporter" . + "E0040" . + "GFP expression cassette used for 2016 iGEM interlab study" . + "atgcgtaaaggagaagaacttttcactggagttgtcccaattcttgttgaattagatggtgatgttaatgggcacaaattttctgtcagtggagagggtgaaggtgatgcaacatacggaaaacttacccttaaatttatttgcactactggaaaactacctgttccatggccaacacttgtcactactttcggttatggtgttcaatgctttgcgagatacccagatcatatgaaacagcatgactttttcaagagtgccatgcccgaaggttatgtacaggaaagaactatatttttcaaagatgacgggaactacaagacacgtgctgaagtcaagtttgaaggtgatacccttgttaatagaatcgagttaaaaggtattgattttaaagaagatggaaacattcttggacacaaattggaatacaactataactcacacaatgtatacatcatggcagacaaacaaaagaatggaatcaaagttaacttcaaaattagacacaacattgaagatggaagcgttcaactagcagaccattatcaacaaaatactccaattggcgatggccctgtccttttaccagacaaccattacctgtccacacaatctgccctttcgaaagatcccaacgaaaagagagaccacatggtccttcttgagtttgtaacagctgctgggattacacatggcatggatgaactatacaaataataa" . + . + . + . + "E0040_seq" . + . + . + . + "B0015" . + . + "1" . + "double terminator" . + . + . + "1" . + . + "GFP" . + . + "RBS (Elowitz 1999)" . + . + . + . + . + . + . + . + . + . + . + "1" . + "i13504" . + "aaagaggagaaa" . diff --git a/test/test.nt b/test/test.nt new file mode 100644 index 00000000..e69de29b diff --git a/test/test.xml b/test/test.xml new file mode 100644 index 00000000..e69de29b diff --git a/test/test_files/create_subcomponent_test.py b/test/test_files/create_subcomponent_test.py index f55dff1d..58bea7a6 100644 --- a/test/test_files/create_subcomponent_test.py +++ b/test/test_files/create_subcomponent_test.py @@ -86,4 +86,4 @@ else: print('Document is valid') -doc.write('subcomponent_test_3_bare_bones.nt', file_format=SORTED_NTRIPLES) +doc.write('subcomponent_test.nt', file_format=SORTED_NTRIPLES) diff --git a/test/test_files/subcomponent_test.nt b/test/test_files/subcomponent_test.nt new file mode 100644 index 00000000..13964df4 --- /dev/null +++ b/test/test_files/subcomponent_test.nt @@ -0,0 +1,67 @@ + "B0015" . + . + . + "double terminator" . + . + . + . + "B0015_seq" . + "ccaggcatcaaataaaacgaaaggctcagtcgaaagactgggcctttcgttttatctgttgtttgtcggtgaacgctctctactagagtcacactggctcaccttcgggtgggcctttctgcgtttata" . + . + . + . + "B0034" . + . + . + "RBS (Elowitz 1999)" . + . + . + . + "B0034_seq" . + "aaagaggagaaa" . + . + . + . + "E0040" . + . + . + "GFP" . + . + . + . + "E0040_seq" . + "atgcgtaaaggagaagaacttttcactggagttgtcccaattcttgttgaattagatggtgatgttaatgggcacaaattttctgtcagtggagagggtgaaggtgatgcaacatacggaaaacttacccttaaatttatttgcactactggaaaactacctgttccatggccaacacttgtcactactttcggttatggtgttcaatgctttgcgagatacccagatcatatgaaacagcatgactttttcaagagtgccatgcccgaaggttatgtacaggaaagaactatatttttcaaagatgacgggaactacaagacacgtgctgaagtcaagtttgaaggtgatacccttgttaatagaatcgagttaaaaggtattgattttaaagaagatggaaacattcttggacacaaattggaatacaactataactcacacaatgtatacatcatggcagacaaacaaaagaatggaatcaaagttaacttcaaaattagacacaacattgaagatggaagcgttcaactagcagaccattatcaacaaaatactccaattggcgatggccctgtccttttaccagacaaccattacctgtccacacaatctgccctttcgaaagatcccaacgaaaagagagaccacatggtccttcttgagtttgtaacagctgctgggattacacatggcatggatgaactatacaaataataa" . + . + . + . + "Constraint1" . + . + . + . + . + "Constraint2" . + . + . + . + . + "SubComponent1" . + . + . + "SubComponent2" . + . + . + "SubComponent3" . + . + . + "GFP expression cassette used for 2016 iGEM interlab study" . + "i13504" . + . + . + . + . + . + . + "iGEM 2016 interlab reporter" . + . + . + . diff --git a/test/test_files/subcomponent_test_3.nt b/test/test_files/subcomponent_test_3.nt index 793f13c2..13964df4 100644 --- a/test/test_files/subcomponent_test_3.nt +++ b/test/test_files/subcomponent_test_3.nt @@ -1,19 +1,3 @@ - "pubchem_compound_5460291" . - . - . - . - "pubchem_compound_5793" . - . - . - . - "pubchem_compound_6134" . - . - . - . - "pubchem_compound_6255" . - . - . - . "B0015" . . . @@ -50,258 +34,6 @@ . . . - "Ecoli_DH5_alpha" . - . - . - . - . - "J23101" . - . - . - . - . - . - "J23101_seq" . - "tttacagctagctcagtcctaggtattatgctagc" . - . - . - . - "J23106" . - . - . - . - . - . - "J23106_seq" . - "tttacggctagctcagtcctaggtatagtgctagc" . - . - . - . - "Measure1" . - "78.0"^^ . - . - . - . - . - "ExternallyDefined1" . - . - . - . - "Measure1" . - "2.0"^^ . - . - . - . - . - "ExternallyDefined2" . - . - . - . - "Measure1" . - "200.0"^^ . - . - . - . - . - "ExternallyDefined3" . - . - . - . - "Measure1" . - "10.0"^^ . - . - . - . - . - "ExternallyDefined4" . - . - . - . - "Measure1" . - "20.0"^^ . - . - . - . - "LocalSubComponent1" . - . - "M9 salts" . - . - . - "M9_media" . - . - . - . - . - . - . - . - . - . - . - "Replicate1" . - . - . - . - "Replicate1_cytometry_fcs" . - . - . - . - . - . - "Replicate2" . - . - . - . - "Replicate2_cytometry_fcs" . - . - . - . - . - "Replicate3" . - . - . - . - "Replicate3_cytometry_fcs" . - . - . - . - "Measure1" . - . - "2.5"^^ . - . - . - . - . - "ExternallyDefined1" . - . - . - . - "Measure1" . - . - "200.0"^^ . - . - . - . - "SubComponent1" . - . - . - . - "Measure1" . - . - "10000.0"^^ . - . - . - . - "SubComponent2" . - . - . - . - "Sample1" . - . - . - . - . - . - . - "Measure1" . - . - "10000.0"^^ . - . - . - . - "LocalSubComponent1" . - . - . - . - "Measure1" . - . - "2.5"^^ . - . - . - . - "LocalSubComponent2" . - . - . - . - "Measure1" . - . - "200.0"^^ . - . - . - . - "SubComponent1" . - . - . - . - "SampleSpec" . - . - . - . - . - . - . - "ComponentReference1" . - . - . - . - "ComponentReference2" . - . - . - . - "Constraint1" . - . - . - . - . - "Constraint2" . - . - . - . - . - "Constraint3" . - . - . - . - . - "Constraint4" . - . - . - . - . - "Interface1" . - . - . - "LocalSubComponent1" . - "Interlab Device 1 in pSB1C3" . - . - . - . - "SubComponent1" . - . - . - "SubComponent2" . - . - . - "SubComponent3" . - . - . - "device1_ecoli" . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . "Constraint1" . . . @@ -312,31 +44,13 @@ . . . - "Range1" . - "12"^^ . - . - "1"^^ . - . "SubComponent1" . - . . . - "Range1" . - "732"^^ . - . - "13"^^ . - . "SubComponent2" . - . . . - "Range1" . - "861"^^ . - . - "733"^^ . - . "SubComponent3" . - . . . "GFP expression cassette used for 2016 iGEM interlab study" . @@ -347,118 +61,7 @@ . . . - . "iGEM 2016 interlab reporter" . . . . - "i13504_sequence" . - "aaagaggagaaaatgcgtaaaggagaagaacttttcactggagttgtcccaattcttgttgaattagatggtgatgttaatgggcacaaattttctgtcagtggagagggtgaaggtgatgcaacatacggaaaacttacccttaaatttatttgcactactggaaaactacctgttccatggccaacacttgtcactactttcggttatggtgttcaatgctttgcgagatacccagatcatatgaaacagcatgactttttcaagagtgccatgcccgaaggttatgtacaggaaagaactatatttttcaaagatgacgggaactacaagacacgtgctgaagtcaagtttgaaggtgatacccttgttaatagaatcgagttaaaaggtattgattttaaagaagatggaaacattcttggacacaaattggaatacaactataactcacacaatgtatacatcatggcagacaaacaaaagaatggaatcaaagttaacttcaaaattagacacaacattgaagatggaagcgttcaactagcagaccattatcaacaaaatactccaattggcgatggccctgtccttttaccagacaaccattacctgtccacacaatctgccctttcgaaagatcccaacgaaaagagagaccacatggtccttcttgagtttgtaacagctgctgggattacacatggcatggatgaactatacaaataataaccaggcatcaaataaaacgaaaggctcagtcgaaagactgggcctttcgttttatctgttgtttgtcggtgaacgctctctactagagtcacactggctcaccttcgggtgggcctttctgcgtttata" . - . - . - . - "ComponentReference1" . - . - . - . - . - "ExternallyDefined1" . - "GFP" . - . - . - "Participation1" . - . - . - . - "Participation2" . - . - . - . - "Interaction1" . - . - . - . - . - "SubComponent1" . - . - . - "i13504_system" . - . - . - . - . - . - . - . - "interlab16" . - . - . - . - . - "ComponentReference1" . - . - . - . - "Constraint1" . - . - . - . - . - "SubComponent1" . - . - . - "SubComponent2" . - . - . - "interlab16device1" . - . - . - . - . - . - . - . - "ComponentReference1" . - . - . - . - "Constraint1" . - . - . - . - . - "SubComponent1" . - . - . - "SubComponent2" . - . - . - "interlab16device2" . - . - . - . - . - . - . - . - "Usage1" . - . - . - . - "measure_sample_1" . - . - . - . - . - . - "my_iBioSIM_ODE" . - . - . - . - . - . - "pSB1C3" . - . - . - . - . diff --git a/test/test_files/subcomponent_test_3_bare_bones.nt b/test/test_files/subcomponent_test_3_bare_bones.xml similarity index 100% rename from test/test_files/subcomponent_test_3_bare_bones.nt rename to test/test_files/subcomponent_test_3_bare_bones.xml diff --git a/test/test_sbol2_sbol3_direct.py b/test/test_sbol2_sbol3_direct.py index 860f5f1e..2b2a12a3 100644 --- a/test/test_sbol2_sbol3_direct.py +++ b/test/test_sbol2_sbol3_direct.py @@ -133,7 +133,8 @@ def test_3to2_subcomponent_test(self): """Test ability to convert a sub_component from SBOL3 to SBOL2""" # Load an SBOL3 document and check its contents doc3 = sbol3.Document() - doc3.read(TEST_FILES / 'subcomponent_test_3_bare_bones.nt') + doc3.read(TEST_FILES / 'subcomponent_test_3.nt') + # Convert to SBOL2 and check contents doc2 = sbol2.Document() doc2 = convert3to2(doc3, use_native_converter=True) @@ -151,22 +152,25 @@ def test_3to2_subcomponent_test(self): # self.assertFalse(file_diff(str(tmp2), str(TEST_FILES / 'sbol_3to2_collection.xml'))) doc3_loop = convert2to3(doc2, use_native_converter=True) self.assertEqual(len(doc3_loop.validate()), 0) - tmp3 = Path(tmpdir) / 'doc3_loop.nt' + tmp3 = 'doc3_loop.nt' doc3_loop.write(tmp3) + print("DOC_3") print(doc3) component_list = [] for object in doc3.objects: if type(object) == sbol3.component.Component: component_list.append(object) - subcomponent_list = [] for component in component_list: print(component.display_id) - print(f"Type: {component.types}") + print(f"Component Type: {component.types}") for feat in component.features: if type(feat) == sbol3.subcomponent.SubComponent: - print(f"\tInstance Of: {feat.instance_of}") + print("\tSubComponent:") + print(f"\t\tName: {feat.name}") + print(f"\t\tDescription: {feat.description}") + print(f"\t\tInstance Of: {feat.instance_of}") print(f"\t\tRoles: {feat.roles}") print(f"\t\tRole Integration: {feat.role_integration}") print(f"\t\tSource Locations: {feat.source_locations}") @@ -181,16 +185,21 @@ def test_3to2_subcomponent_test(self): print("\nDOCK_3_loop") print(doc3_loop) - component_list = [] for object in doc3_loop.objects: if type(object) == sbol3.component.Component: component_list.append(object) for component in component_list: print(component.display_id) + print(f"Component Type: {component.types}") for feat in component.features: - print("\t" + str(type(feat))) + if type(feat) == sbol3.subcomponent.SubComponent: + print("\tSubComponent:") + print(f"\t\tInstance Of: {feat.instance_of}") + print(f"\t\tRoles: {feat.roles}") + print(f"\t\tRole Integration: {feat.role_integration}") + print(f"\t\tSource Locations: {feat.source_locations}") - self.assertFalse(file_diff(str(tmp3), str(TEST_FILES / 'subcomponent_test_3_bare_bones.nt'))) + self.assertFalse(file_diff(str(tmp3), str(TEST_FILES / 'subcomponent_test_3.nt'))) From b684dffa3e91159967bb5b620b48c5f5bb532de7 Mon Sep 17 00:00:00 2001 From: Yehuda Binik Date: Tue, 13 Aug 2024 16:13:55 -0400 Subject: [PATCH 05/14] First working version of visit_sub_component working --- sbol_utilities/sbol3_sbol2_conversion.py | 48 +++++++++++------------- 1 file changed, 22 insertions(+), 26 deletions(-) diff --git a/sbol_utilities/sbol3_sbol2_conversion.py b/sbol_utilities/sbol3_sbol2_conversion.py index d4fa64d9..a1c29e29 100644 --- a/sbol_utilities/sbol3_sbol2_conversion.py +++ b/sbol_utilities/sbol3_sbol2_conversion.py @@ -143,7 +143,7 @@ def visit_combinatorial_derivation(self, a: sbol3.CombinatorialDerivation): # Priority: 2 raise NotImplementedError('Conversion of CombinatorialDerivation from SBOL3 to SBOL2 not yet implemented') - def visit_component(self, cp3: sbol3.Component): + def visit_component(self, comp3: sbol3.Component): # Remap type if it's one of the ones that needs remapping; otherwise pass through unchanged type_map = {sbol3.SBO_DNA: sbol2.BIOPAX_DNA, # TODO: distinguish BioPAX Dna from DnaRegion @@ -151,44 +151,41 @@ def visit_component(self, cp3: sbol3.Component): sbol3.SBO_PROTEIN: sbol2.BIOPAX_PROTEIN, sbol3.SBO_SIMPLE_CHEMICAL: sbol2.BIOPAX_SMALL_MOLECULE, sbol3.SBO_NON_COVALENT_COMPLEX: sbol2.BIOPAX_COMPLEX} - types2 = [type_map.get(t, t) for t in cp3.types] + types2 = [type_map.get(t, t) for t in comp3.types] # Make the Component object and add it to the document - cp2 = sbol2.ComponentDefinition(cp3.identity, types2, version=self._sbol2_version(cp3)) - self.doc2.addComponentDefinition(cp2) + compDef2 = sbol2.ComponentDefinition(comp3.identity, types2, version=self._sbol2_version(comp3)) + self.doc2.addComponentDefinition(compDef2) # Convert the Component properties not covered by the constructor - cp2.roles = cp3.roles - cp2.sequences = cp3.sequences - if cp3.features: - for feature in cp3.features: + compDef2.roles = comp3.roles + compDef2.sequences = comp3.sequences + if comp3.features: + for feature in comp3.features: if type(feature) == sbol3.subcomponent.SubComponent: - try: - self.visit_sub_component(cp3, feature) - except NotImplementedError as e: - print(f"\033[91m{e}\033[0m") + self.visit_sub_component(comp3, feature, compDef2) if type(feature) == sbol3.compref.ComponentReference: try: self.visit_component_reference(feature) except NotImplementedError as e: print(f"\033[91m{e}\033[0m") - if cp3.interactions: - for interaction in cp3.interactions: + if comp3.interactions: + for interaction in comp3.interactions: try: self.visit_interaction(interaction) except NotImplementedError as e: print(f"\033[91m{e}\033[0m") - if cp3.constraints: - for constraint in cp3.constraints: + if comp3.constraints: + for constraint in comp3.constraints: try: pass self.visit_constraint(constraint) except NotImplementedError as e: print(f"\033[91m{e}\033[0m") - if cp3.interface: + if comp3.interface: raise NotImplementedError('Conversion of Component interface from SBOL3 to SBOL2 not yet implemented') - if cp3.models: + if comp3.models: raise NotImplementedError('Conversion of Component models from SBOL3 to SBOL2 not yet implemented') # Map over all other TopLevel properties and extensions not covered by the constructor - self._convert_toplevel(cp3, cp2) + self._convert_toplevel(comp3, compDef2) def visit_component_reference(self, comp_ref3: sbol3.ComponentReference): # Priority: 3 @@ -304,9 +301,9 @@ def visit_singular_unit(self, a: sbol3.SingularUnit): # Priority: 4 raise NotImplementedError('Conversion of SingularUnit from SBOL3 to SBOL2 not yet implemented') - def visit_sub_component(self, comp3: sbol3.Component, sub3: sbol3.SubComponent): + def visit_sub_component(self, comp3: sbol3.Component, sub3: sbol3.SubComponent, + comp_def2: sbol2.ComponentDefinition): # Priority: 1 - # Make the Component, Module, or Functional_Component objects and add them to the document # TODO Handle converting sub_components into Modules and FunctionalEntities when necessary component2 = sbol2.Component(sub3.identity) @@ -314,12 +311,11 @@ def visit_sub_component(self, comp3: sbol3.Component, sub3: sbol3.SubComponent): component2.roleIntegration = sub3.role_integration component2.sourceLocations = sub3.source_locations component2.definition = sub3.instance_of - self.doc2.addComponentDefinition(component2) - - print(f"components: {self.doc2.componentDefinitions}") + comp_def2.components.add(component2) - raise NotImplementedError( - 'Conversion of SubComponent from SBOL3 to SBOL2 not yet implemented in case of Module and FunctionalEntities') + print("components:") + for component in comp_def2.components: + print(component) def visit_unit_division(self, a: sbol3.UnitDivision): # Priority: 4 From 4c044c7a70015d4080c7c2355efae1a6a9233fae Mon Sep 17 00:00:00 2001 From: Yehuda Binik Date: Tue, 13 Aug 2024 16:32:04 -0400 Subject: [PATCH 06/14] visit_component function is working --- sbol_utilities/sbol3_sbol2_conversion.py | 32 +++++---- test/doc3_loop.nt | 90 ++++++++++++++---------- test/test_sbol2_sbol3_direct.py | 10 +-- 3 files changed, 74 insertions(+), 58 deletions(-) diff --git a/sbol_utilities/sbol3_sbol2_conversion.py b/sbol_utilities/sbol3_sbol2_conversion.py index a1c29e29..f7c4c47c 100644 --- a/sbol_utilities/sbol3_sbol2_conversion.py +++ b/sbol_utilities/sbol3_sbol2_conversion.py @@ -438,7 +438,7 @@ def visit_combinatorial_derivation(self, a: sbol2.CombinatorialDerivation): # Priority: 2 raise NotImplementedError('Conversion of CombinatorialDerivation from SBOL2 to SBOL3 not yet implemented') - def visit_component_definition(self, cd2: sbol2.ComponentDefinition): + def visit_component_definition(self, comp_def2: sbol2.ComponentDefinition): # Remap type if it's one of the ones that needs remapping; otherwise pass through unchanged type_map = {sbol2.BIOPAX_DNA: sbol3.SBO_DNA, 'http://www.biopax.org/release/biopax-level3.owl#Dna': sbol3.SBO_DNA, # TODO: make reversible @@ -447,32 +447,34 @@ def visit_component_definition(self, cd2: sbol2.ComponentDefinition): sbol2.BIOPAX_PROTEIN: sbol3.SBO_PROTEIN, sbol2.BIOPAX_SMALL_MOLECULE: sbol3.SBO_SIMPLE_CHEMICAL, sbol2.BIOPAX_COMPLEX: sbol3.SBO_NON_COVALENT_COMPLEX} - types3 = [type_map.get(t, t) for t in cd2.types] + types3 = [type_map.get(t, t) for t in comp_def2.types] # Make the Component object and add it to the document - cp3 = sbol3.Component(cd2.identity, types3, namespace=self._sbol3_namespace(cd2), - roles=cd2.roles, sequences=cd2.sequences) - self.doc3.add(cp3) + comp3 = sbol3.Component(comp_def2.identity, types3, namespace=self._sbol3_namespace(comp_def2), + roles=comp_def2.roles, sequences=comp_def2.sequences) + self.doc3.add(comp3) # Convert the Component properties not covered by the constructor - if cd2.components: - raise NotImplementedError('Conversion of ComponentDefinition components ' - 'from SBOL2 to SBOL3 not yet implemented') - if cd2.sequenceAnnotations: + if comp_def2.components: + for comp2 in comp_def2.components: + self.visit_component(comp2, comp3) + if comp_def2.sequenceAnnotations: raise NotImplementedError('Conversion of ComponentDefinition sequenceAnnotations ' 'from SBOL2 to SBOL3 not yet implemented') - if cd2.sequenceConstraints: + if comp_def2.sequenceConstraints: raise NotImplementedError('Conversion of ComponentDefinition sequenceConstraints ' 'from SBOL2 to SBOL3 not yet implemented') # Map over all other TopLevel properties and extensions not covered by the constructor - self._convert_toplevel(cd2, cp3) + self._convert_toplevel(comp_def2, comp3) - def visit_component(self, comp2: sbol2.Component): + def visit_component(self, comp2: sbol2.Component, comp3: sbol3.Component): # Priority: 2 sub3 = sbol3.SubComponent(comp2.identity) sub3.roles = comp2.roles - sub3.roleIntegration = comp2.role_integration - sub3.sourceLocations = comp2.source_locations + if comp2.roleIntegration: + sub3.role_integration = comp2.roleIntegration + if comp2.sourceLocations: + sub3.source_locations = comp2.sourceLocations sub3.instance_of = comp2.definition - self.doc3.add(sub3) + comp3.features += [sub3] def visit_cut(self, a: sbol2.Cut): # Priority: 2 diff --git a/test/doc3_loop.nt b/test/doc3_loop.nt index a2b58801..eb5fefe1 100644 --- a/test/doc3_loop.nt +++ b/test/doc3_loop.nt @@ -1,50 +1,62 @@ - . - . - . - . - . - "B0034" . - "1" . - . + . + "E0040_seq" . + . + . + . + . "B0034_seq" . - "B0015_seq" . + . + "E0040" . "ccaggcatcaaataaaacgaaaggctcagtcgaaagactgggcctttcgttttatctgttgtttgtcggtgaacgctctctactagagtcacactggctcaccttcgggtgggcctttctgcgtttata" . - "1" . - "1" . . - "1" . - "iGEM 2016 interlab reporter" . - "E0040" . + . + . + . + . + . "GFP expression cassette used for 2016 iGEM interlab study" . + . + . + "RBS (Elowitz 1999)" . + "1" . + "B0015_seq" . + . + . "atgcgtaaaggagaagaacttttcactggagttgtcccaattcttgttgaattagatggtgatgttaatgggcacaaattttctgtcagtggagagggtgaaggtgatgcaacatacggaaaacttacccttaaatttatttgcactactggaaaactacctgttccatggccaacacttgtcactactttcggttatggtgttcaatgctttgcgagatacccagatcatatgaaacagcatgactttttcaagagtgccatgcccgaaggttatgtacaggaaagaactatatttttcaaagatgacgggaactacaagacacgtgctgaagtcaagtttgaaggtgatacccttgttaatagaatcgagttaaaaggtattgattttaaagaagatggaaacattcttggacacaaattggaatacaactataactcacacaatgtatacatcatggcagacaaacaaaagaatggaatcaaagttaacttcaaaattagacacaacattgaagatggaagcgttcaactagcagaccattatcaacaaaatactccaattggcgatggccctgtccttttaccagacaaccattacctgtccacacaatctgccctttcgaaagatcccaacgaaaagagagaccacatggtccttcttgagtttgtaacagctgctgggattacacatggcatggatgaactatacaaataataa" . - . - . - . - "E0040_seq" . - . - . - . "B0015" . - . + . + . + . + "i13504" . + . + "1" . + . + . + . + "1" . + "SubComponent2" . + "SubComponent3" . + . + "SubComponent1" . + . + "GFP" . "1" . + . + "iGEM 2016 interlab reporter" . "double terminator" . - . - . + . + "aaagaggagaaa" . "1" . - . - "GFP" . - . - "RBS (Elowitz 1999)" . - . + . + . + "B0034" . + . . - . - . - . - . - . - . - . - . + . + . + . + . + . + "1" . + . "1" . - "i13504" . - "aaagaggagaaa" . diff --git a/test/test_sbol2_sbol3_direct.py b/test/test_sbol2_sbol3_direct.py index 2b2a12a3..f155b4a6 100644 --- a/test/test_sbol2_sbol3_direct.py +++ b/test/test_sbol2_sbol3_direct.py @@ -150,10 +150,7 @@ def test_3to2_subcomponent_test(self): # Print the contents # self.assertFalse(file_diff(str(tmp2), str(TEST_FILES / 'sbol_3to2_collection.xml'))) - doc3_loop = convert2to3(doc2, use_native_converter=True) - self.assertEqual(len(doc3_loop.validate()), 0) - tmp3 = 'doc3_loop.nt' - doc3_loop.write(tmp3) + print("DOC_3") @@ -175,6 +172,11 @@ def test_3to2_subcomponent_test(self): print(f"\t\tRole Integration: {feat.role_integration}") print(f"\t\tSource Locations: {feat.source_locations}") + doc3_loop = convert2to3(doc2, use_native_converter=True) + self.assertEqual(len(doc3_loop.validate()), 0) + tmp3 = 'doc3_loop.nt' + doc3_loop.write(tmp3) + print("\nDOC_2") print(doc2) for object in doc2: From b7170efaeb8a24963faa0a0aed43c43787eeee2e Mon Sep 17 00:00:00 2001 From: Yehuda Binik Date: Tue, 13 Aug 2024 18:51:35 -0400 Subject: [PATCH 07/14] Changed .nt test file to eliminate all order constraints --- test/doc3_loop.nt | 98 +++++++++++++------------- test/test_files/subcomponent_test_3.nt | 12 ---- 2 files changed, 49 insertions(+), 61 deletions(-) diff --git a/test/doc3_loop.nt b/test/doc3_loop.nt index eb5fefe1..9584ee75 100644 --- a/test/doc3_loop.nt +++ b/test/doc3_loop.nt @@ -1,62 +1,62 @@ - . - "E0040_seq" . - . - . - . - . - "B0034_seq" . - . - "E0040" . - "ccaggcatcaaataaaacgaaaggctcagtcgaaagactgggcctttcgttttatctgttgtttgtcggtgaacgctctctactagagtcacactggctcaccttcgggtgggcctttctgcgtttata" . - . . - . - . - . - . - "GFP expression cassette used for 2016 iGEM interlab study" . - . - . + "1" . + "SubComponent1" . + . + "B0015_seq" . + . "RBS (Elowitz 1999)" . "1" . - "B0015_seq" . - . - . - "atgcgtaaaggagaagaacttttcactggagttgtcccaattcttgttgaattagatggtgatgttaatgggcacaaattttctgtcagtggagagggtgaaggtgatgcaacatacggaaaacttacccttaaatttatttgcactactggaaaactacctgttccatggccaacacttgtcactactttcggttatggtgttcaatgctttgcgagatacccagatcatatgaaacagcatgactttttcaagagtgccatgcccgaaggttatgtacaggaaagaactatatttttcaaagatgacgggaactacaagacacgtgctgaagtcaagtttgaaggtgatacccttgttaatagaatcgagttaaaaggtattgattttaaagaagatggaaacattcttggacacaaattggaatacaactataactcacacaatgtatacatcatggcagacaaacaaaagaatggaatcaaagttaacttcaaaattagacacaacattgaagatggaagcgttcaactagcagaccattatcaacaaaatactccaattggcgatggccctgtccttttaccagacaaccattacctgtccacacaatctgccctttcgaaagatcccaacgaaaagagagaccacatggtccttcttgagtttgtaacagctgctgggattacacatggcatggatgaactatacaaataataa" . - "B0015" . - . - . - . - "i13504" . + "ccaggcatcaaataaaacgaaaggctcagtcgaaagactgggcctttcgttttatctgttgtttgtcggtgaacgctctctactagagtcacactggctcaccttcgggtgggcctttctgcgtttata" . . - "1" . - . - . - . - "1" . - "SubComponent2" . + "B0034" . + . + . + . + "aaagaggagaaa" . "SubComponent3" . - . - "SubComponent1" . - . "GFP" . - "1" . + . + "1" . . + . + . "iGEM 2016 interlab reporter" . + . + . + . + "i13504" . "double terminator" . + . + . + . + . . - "aaagaggagaaa" . + . + . + . + . "1" . - . - . - "B0034" . - . - . + "GFP expression cassette used for 2016 iGEM interlab study" . . - . - . - . - . - "1" . - . + "B0015" . + . + "1" . + . + . "1" . + . + . + "B0034_seq" . + "1" . + "E0040" . + "SubComponent2" . + . + "E0040_seq" . + . + . + . + . + "atgcgtaaaggagaagaacttttcactggagttgtcccaattcttgttgaattagatggtgatgttaatgggcacaaattttctgtcagtggagagggtgaaggtgatgcaacatacggaaaacttacccttaaatttatttgcactactggaaaactacctgttccatggccaacacttgtcactactttcggttatggtgttcaatgctttgcgagatacccagatcatatgaaacagcatgactttttcaagagtgccatgcccgaaggttatgtacaggaaagaactatatttttcaaagatgacgggaactacaagacacgtgctgaagtcaagtttgaaggtgatacccttgttaatagaatcgagttaaaaggtattgattttaaagaagatggaaacattcttggacacaaattggaatacaactataactcacacaatgtatacatcatggcagacaaacaaaagaatggaatcaaagttaacttcaaaattagacacaacattgaagatggaagcgttcaactagcagaccattatcaacaaaatactccaattggcgatggccctgtccttttaccagacaaccattacctgtccacacaatctgccctttcgaaagatcccaacgaaaagagagaccacatggtccttcttgagtttgtaacagctgctgggattacacatggcatggatgaactatacaaataataa" . + . + . + . diff --git a/test/test_files/subcomponent_test_3.nt b/test/test_files/subcomponent_test_3.nt index 13964df4..85c5d9ba 100644 --- a/test/test_files/subcomponent_test_3.nt +++ b/test/test_files/subcomponent_test_3.nt @@ -34,16 +34,6 @@ . . . - "Constraint1" . - . - . - . - . - "Constraint2" . - . - . - . - . "SubComponent1" . . . @@ -55,8 +45,6 @@ . "GFP expression cassette used for 2016 iGEM interlab study" . "i13504" . - . - . . . . From 123309be59a559e1e1b1e6bc3473d77d59a2805b Mon Sep 17 00:00:00 2001 From: Yehuda Binik Date: Wed, 14 Aug 2024 21:52:36 -0400 Subject: [PATCH 08/14] Working roundtrip of subcomponent --- sbol_utilities/sbol3_sbol2_conversion.py | 40 +++++---- test/doc3_loop.nt | 104 +++++++++++------------ test/test_sbol2_sbol3_direct.py | 67 +++------------ 3 files changed, 88 insertions(+), 123 deletions(-) diff --git a/sbol_utilities/sbol3_sbol2_conversion.py b/sbol_utilities/sbol3_sbol2_conversion.py index f7c4c47c..dd9ff552 100644 --- a/sbol_utilities/sbol3_sbol2_conversion.py +++ b/sbol_utilities/sbol3_sbol2_conversion.py @@ -153,15 +153,15 @@ def visit_component(self, comp3: sbol3.Component): sbol3.SBO_NON_COVALENT_COMPLEX: sbol2.BIOPAX_COMPLEX} types2 = [type_map.get(t, t) for t in comp3.types] # Make the Component object and add it to the document - compDef2 = sbol2.ComponentDefinition(comp3.identity, types2, version=self._sbol2_version(comp3)) - self.doc2.addComponentDefinition(compDef2) + comp_def2 = sbol2.ComponentDefinition(comp3.identity, types2, version=self._sbol2_version(comp3)) + self.doc2.addComponentDefinition(comp_def2) # Convert the Component properties not covered by the constructor - compDef2.roles = comp3.roles - compDef2.sequences = comp3.sequences + comp_def2.roles = comp3.roles + comp_def2.sequences = comp3.sequences if comp3.features: for feature in comp3.features: if type(feature) == sbol3.subcomponent.SubComponent: - self.visit_sub_component(comp3, feature, compDef2) + self.visit_sub_component(feature, comp_def2) if type(feature) == sbol3.compref.ComponentReference: try: self.visit_component_reference(feature) @@ -185,7 +185,7 @@ def visit_component(self, comp3: sbol3.Component): if comp3.models: raise NotImplementedError('Conversion of Component models from SBOL3 to SBOL2 not yet implemented') # Map over all other TopLevel properties and extensions not covered by the constructor - self._convert_toplevel(comp3, compDef2) + self._convert_toplevel(comp3, comp_def2) def visit_component_reference(self, comp_ref3: sbol3.ComponentReference): # Priority: 3 @@ -301,21 +301,20 @@ def visit_singular_unit(self, a: sbol3.SingularUnit): # Priority: 4 raise NotImplementedError('Conversion of SingularUnit from SBOL3 to SBOL2 not yet implemented') - def visit_sub_component(self, comp3: sbol3.Component, sub3: sbol3.SubComponent, + def visit_sub_component(self, sub3: sbol3.SubComponent, comp_def2: sbol2.ComponentDefinition): # Priority: 1 # Make the Component, Module, or Functional_Component objects and add them to the document # TODO Handle converting sub_components into Modules and FunctionalEntities when necessary - component2 = sbol2.Component(sub3.identity) - component2.roles = sub3.roles - component2.roleIntegration = sub3.role_integration - component2.sourceLocations = sub3.source_locations - component2.definition = sub3.instance_of - comp_def2.components.add(component2) - - print("components:") - for component in comp_def2.components: - print(component) + comp2 = sbol2.Component(sub3.identity) + comp2.roles = sub3.roles + comp2.roleIntegration = sub3.role_integration + comp2.sourceLocations = sub3.source_locations + comp2.definition = sub3.instance_of + comp_def2.components.add(comp2) + print(comp_def2) + print(f"SBOL3: {sub3} -> {sub3.instance_of}") + print(f"SBOL2: {comp2} -> {comp2.definition}") def visit_unit_division(self, a: sbol3.UnitDivision): # Priority: 4 @@ -453,6 +452,9 @@ def visit_component_definition(self, comp_def2: sbol2.ComponentDefinition): roles=comp_def2.roles, sequences=comp_def2.sequences) self.doc3.add(comp3) # Convert the Component properties not covered by the constructor + if comp_def2.components: + for comp2 in comp_def2.components: + print(comp2) if comp_def2.components: for comp2 in comp_def2.components: self.visit_component(comp2, comp3) @@ -475,7 +477,9 @@ def visit_component(self, comp2: sbol2.Component, comp3: sbol3.Component): sub3.source_locations = comp2.sourceLocations sub3.instance_of = comp2.definition comp3.features += [sub3] - + print(comp3) + print(f"SBOL2: {comp2} -> {comp2.definition}") + print(f"SBOL3: {sub3} -> {sub3.instance_of}") def visit_cut(self, a: sbol2.Cut): # Priority: 2 raise NotImplementedError('Conversion of Cut from SBOL2 to SBOL3 not yet implemented') diff --git a/test/doc3_loop.nt b/test/doc3_loop.nt index 9584ee75..1759f7c2 100644 --- a/test/doc3_loop.nt +++ b/test/doc3_loop.nt @@ -1,62 +1,62 @@ - . - "1" . - "SubComponent1" . - . - "B0015_seq" . - . - "RBS (Elowitz 1999)" . - "1" . - "ccaggcatcaaataaaacgaaaggctcagtcgaaagactgggcctttcgttttatctgttgtttgtcggtgaacgctctctactagagtcacactggctcaccttcgggtgggcctttctgcgtttata" . - . + . "B0034" . - . - . - . - "aaagaggagaaa" . - "SubComponent3" . - "GFP" . - . - "1" . + "1" . + . + . + . + . + . + "1" . + . + . + "1" . + . + . . - . - . - "iGEM 2016 interlab reporter" . + . . - . - . - "i13504" . + "SubComponent2" . + "B0015" . + "1" . + . + "1" . + . + . + "B0034_seq" . + . "double terminator" . - . - . - . + . + "ccaggcatcaaataaaacgaaaggctcagtcgaaagactgggcctttcgttttatctgttgtttgtcggtgaacgctctctactagagtcacactggctcaccttcgggtgggcctttctgcgtttata" . + "E0040_seq" . + . + . + . + "GFP" . . + . + "aaagaggagaaa" . + "i13504" . + "RBS (Elowitz 1999)" . + . + . + "E0040" . + "atgcgtaaaggagaagaacttttcactggagttgtcccaattcttgttgaattagatggtgatgttaatgggcacaaattttctgtcagtggagagggtgaaggtgatgcaacatacggaaaacttacccttaaatttatttgcactactggaaaactacctgttccatggccaacacttgtcactactttcggttatggtgttcaatgctttgcgagatacccagatcatatgaaacagcatgactttttcaagagtgccatgcccgaaggttatgtacaggaaagaactatatttttcaaagatgacgggaactacaagacacgtgctgaagtcaagtttgaaggtgatacccttgttaatagaatcgagttaaaaggtattgattttaaagaagatggaaacattcttggacacaaattggaatacaactataactcacacaatgtatacatcatggcagacaaacaaaagaatggaatcaaagttaacttcaaaattagacacaacattgaagatggaagcgttcaactagcagaccattatcaacaaaatactccaattggcgatggccctgtccttttaccagacaaccattacctgtccacacaatctgccctttcgaaagatcccaacgaaaagagagaccacatggtccttcttgagtttgtaacagctgctgggattacacatggcatggatgaactatacaaataataa" . + . . - . - . - . + . + . + . . - "1" . - "GFP expression cassette used for 2016 iGEM interlab study" . - . - "B0015" . . - "1" . - . - . - "1" . - . - . - "B0034_seq" . + . + "GFP expression cassette used for 2016 iGEM interlab study" . + . + "B0015_seq" . + "iGEM 2016 interlab reporter" . + "SubComponent1" . "1" . - "E0040" . - "SubComponent2" . - . - "E0040_seq" . + . . - . - . - . - "atgcgtaaaggagaagaacttttcactggagttgtcccaattcttgttgaattagatggtgatgttaatgggcacaaattttctgtcagtggagagggtgaaggtgatgcaacatacggaaaacttacccttaaatttatttgcactactggaaaactacctgttccatggccaacacttgtcactactttcggttatggtgttcaatgctttgcgagatacccagatcatatgaaacagcatgactttttcaagagtgccatgcccgaaggttatgtacaggaaagaactatatttttcaaagatgacgggaactacaagacacgtgctgaagtcaagtttgaaggtgatacccttgttaatagaatcgagttaaaaggtattgattttaaagaagatggaaacattcttggacacaaattggaatacaactataactcacacaatgtatacatcatggcagacaaacaaaagaatggaatcaaagttaacttcaaaattagacacaacattgaagatggaagcgttcaactagcagaccattatcaacaaaatactccaattggcgatggccctgtccttttaccagacaaccattacctgtccacacaatctgccctttcgaaagatcccaacgaaaagagagaccacatggtccttcttgagtttgtaacagctgctgggattacacatggcatggatgaactatacaaataataa" . - . - . - . + "SubComponent3" . + "1" . + . diff --git a/test/test_sbol2_sbol3_direct.py b/test/test_sbol2_sbol3_direct.py index f155b4a6..bb94d895 100644 --- a/test/test_sbol2_sbol3_direct.py +++ b/test/test_sbol2_sbol3_direct.py @@ -22,8 +22,8 @@ def test_3to2_conversion(self): doc3.read(TEST_FILES / 'BBa_J23101_patched.nt') # Convert to SBOL2 and check contents doc2 = convert3to2(doc3, True) - #report = doc2.validate() - #self.assertEqual(len(report), 0, f'Validation failed: {report}') + # report = doc2.validate() + # self.assertEqual(len(report), 0, f'Validation failed: {report}') with tempfile.TemporaryDirectory() as tmpdir: tmp2 = Path(tmpdir) / 'doc2.xml' doc2.write(tmp2) @@ -60,8 +60,8 @@ def test_3to2_implementation_conversion(self): doc3.read(TEST_FILES / 'sbol3_implementation.nt') # Convert to SBOL2 and check contents doc2 = convert3to2(doc3, True) - #report = doc2.validate() - #self.assertEqual(len(report), 0, f'Validation failed: {report}') + # report = doc2.validate() + # self.assertEqual(len(report), 0, f'Validation failed: {report}') with tempfile.TemporaryDirectory() as tmpdir: tmp2 = Path(tmpdir) / 'doc2.xml' doc2.write(tmp2) @@ -98,8 +98,8 @@ def test_3to2_collection_conversion(self): doc3.read(TEST_FILES / 'sbol3_collection.nt') # Convert to SBOL2 and check contents doc2 = convert3to2(doc3, True) - #report = doc2.validate() - #self.assertEqual(len(report), 0, f'Validation failed: {report}') + # report = doc2.validate() + # self.assertEqual(len(report), 0, f'Validation failed: {report}') with tempfile.TemporaryDirectory() as tmpdir: tmp2 = Path(tmpdir) / 'doc2.xml' doc2.write(tmp2) @@ -149,64 +149,25 @@ def test_3to2_subcomponent_test(self): file_contents = file.read() # Print the contents + print(file_contents) # self.assertFalse(file_diff(str(tmp2), str(TEST_FILES / 'sbol_3to2_collection.xml'))) - - - print("DOC_3") - print(doc3) - component_list = [] - for object in doc3.objects: - if type(object) == sbol3.component.Component: - component_list.append(object) - for component in component_list: - print(component.display_id) - print(f"Component Type: {component.types}") - for feat in component.features: - if type(feat) == sbol3.subcomponent.SubComponent: - print("\tSubComponent:") - print(f"\t\tName: {feat.name}") - print(f"\t\tDescription: {feat.description}") - print(f"\t\tInstance Of: {feat.instance_of}") - print(f"\t\tRoles: {feat.roles}") - print(f"\t\tRole Integration: {feat.role_integration}") - print(f"\t\tSource Locations: {feat.source_locations}") - doc3_loop = convert2to3(doc2, use_native_converter=True) self.assertEqual(len(doc3_loop.validate()), 0) tmp3 = 'doc3_loop.nt' doc3_loop.write(tmp3) - print("\nDOC_2") - print(doc2) - for object in doc2: - if type(object) == sbol2.componentdefinition.ComponentDefinition: - print(object) - print(f"\tComponents: {object.components}") - - - print("\nDOCK_3_loop") - print(doc3_loop) - for object in doc3_loop.objects: - if type(object) == sbol3.component.Component: - component_list.append(object) - for component in component_list: - print(component.display_id) - print(f"Component Type: {component.types}") - for feat in component.features: - if type(feat) == sbol3.subcomponent.SubComponent: - print("\tSubComponent:") - print(f"\t\tInstance Of: {feat.instance_of}") - print(f"\t\tRoles: {feat.roles}") - print(f"\t\tRole Integration: {feat.role_integration}") - print(f"\t\tSource Locations: {feat.source_locations}") - - self.assertFalse(file_diff(str(tmp3), str(TEST_FILES / 'subcomponent_test_3.nt'))) - + print() + with open(tmp3, "r") as file: + # Read the contents of the file + file_contents = file.read() + # Print the contents + print(file_contents) + self.assertFalse(file_diff(str(tmp3), str(TEST_FILES / 'subcomponent_test_3.nt'))) if __name__ == '__main__': From 6420e5575f6492cea2ac2c52607107c6052ba948 Mon Sep 17 00:00:00 2001 From: Yehuda Binik Date: Mon, 2 Sep 2024 22:43:54 -0400 Subject: [PATCH 09/14] First working version of visit_subcomponent --- sbol_utilities/sbol3_sbol2_conversion.py | 46 +++++++++--- test/doc3_loop.nt | 96 ++++++++++++------------ test/test_files/subcomponent_test_3.nt | 7 ++ test/test_sbol2_sbol3_direct.py | 15 ++-- 4 files changed, 94 insertions(+), 70 deletions(-) diff --git a/sbol_utilities/sbol3_sbol2_conversion.py b/sbol_utilities/sbol3_sbol2_conversion.py index dd9ff552..c97554d4 100644 --- a/sbol_utilities/sbol3_sbol2_conversion.py +++ b/sbol_utilities/sbol3_sbol2_conversion.py @@ -1,3 +1,5 @@ +import os + import sbol3 import sbol2 from sbol2 import mapsto, model, sequenceconstraint @@ -311,10 +313,8 @@ def visit_sub_component(self, sub3: sbol3.SubComponent, comp2.roleIntegration = sub3.role_integration comp2.sourceLocations = sub3.source_locations comp2.definition = sub3.instance_of + comp2.displayId = sub3.display_id comp_def2.components.add(comp2) - print(comp_def2) - print(f"SBOL3: {sub3} -> {sub3.instance_of}") - print(f"SBOL2: {comp2} -> {comp2.definition}") def visit_unit_division(self, a: sbol3.UnitDivision): # Priority: 4 @@ -437,7 +437,7 @@ def visit_combinatorial_derivation(self, a: sbol2.CombinatorialDerivation): # Priority: 2 raise NotImplementedError('Conversion of CombinatorialDerivation from SBOL2 to SBOL3 not yet implemented') - def visit_component_definition(self, comp_def2: sbol2.ComponentDefinition): + def visit_component_definition(self, comp_def2: sbol2.ComponentDefinition, sub3_comp2_equivalencies=None): # Remap type if it's one of the ones that needs remapping; otherwise pass through unchanged type_map = {sbol2.BIOPAX_DNA: sbol3.SBO_DNA, 'http://www.biopax.org/release/biopax-level3.owl#Dna': sbol3.SBO_DNA, # TODO: make reversible @@ -451,13 +451,13 @@ def visit_component_definition(self, comp_def2: sbol2.ComponentDefinition): comp3 = sbol3.Component(comp_def2.identity, types3, namespace=self._sbol3_namespace(comp_def2), roles=comp_def2.roles, sequences=comp_def2.sequences) self.doc3.add(comp3) + # Convert the Component properties not covered by the constructor + sub3_comp2_equivalencies = {} if comp_def2.components: for comp2 in comp_def2.components: - print(comp2) - if comp_def2.components: - for comp2 in comp_def2.components: - self.visit_component(comp2, comp3) + self.visit_component(comp2, comp3, sub3_comp2_equivalencies) + if comp_def2.sequenceAnnotations: raise NotImplementedError('Conversion of ComponentDefinition sequenceAnnotations ' 'from SBOL2 to SBOL3 not yet implemented') @@ -466,8 +466,10 @@ def visit_component_definition(self, comp_def2: sbol2.ComponentDefinition): 'from SBOL2 to SBOL3 not yet implemented') # Map over all other TopLevel properties and extensions not covered by the constructor self._convert_toplevel(comp_def2, comp3) + self.set_subcomponent_identities(sub3_comp2_equivalencies) + - def visit_component(self, comp2: sbol2.Component, comp3: sbol3.Component): + def visit_component(self, comp2: sbol2.Component, comp3: sbol3.Component, sub3_comp2_equivalencies): # Priority: 2 sub3 = sbol3.SubComponent(comp2.identity) sub3.roles = comp2.roles @@ -477,9 +479,29 @@ def visit_component(self, comp2: sbol2.Component, comp3: sbol3.Component): sub3.source_locations = comp2.sourceLocations sub3.instance_of = comp2.definition comp3.features += [sub3] - print(comp3) - print(f"SBOL2: {comp2} -> {comp2.definition}") - print(f"SBOL3: {sub3} -> {sub3.instance_of}") + sub3_comp2_equivalencies[f"<{sub3.identity}> "] = f"<{comp2.identity}> " + + def set_subcomponent_identities(self, sub3_comp2_equivalencies): + temporary_file = 'temporary_file.nt' + self.doc3.write(temporary_file) + with open(temporary_file, 'r+') as file: + content = file.read() + triples = content.splitlines() + for index, triple in enumerate(triples): + for sub3 in sub3_comp2_equivalencies: + if sub3 in triple: + triples[index] = triple.replace(sub3, sub3_comp2_equivalencies[sub3]) + # Move the file pointer to the beginning + file.seek(0) + + # Write the modified triples back to the file + file.writelines(triple + "\n" for triple in triples) + + # Truncate the file to the current position to remove any leftover data + file.truncate() + self.doc3.read('temporary_file.nt') + os.remove(temporary_file) + def visit_cut(self, a: sbol2.Cut): # Priority: 2 raise NotImplementedError('Conversion of Cut from SBOL2 to SBOL3 not yet implemented') diff --git a/test/doc3_loop.nt b/test/doc3_loop.nt index 1759f7c2..817beddf 100644 --- a/test/doc3_loop.nt +++ b/test/doc3_loop.nt @@ -1,62 +1,62 @@ - . - "B0034" . - "1" . + "RBS (Elowitz 1999)" . + "E0040" . + "B0034_seq" . + . + . + . + . . - . + "atgcgtaaaggagaagaacttttcactggagttgtcccaattcttgttgaattagatggtgatgttaatgggcacaaattttctgtcagtggagagggtgaaggtgatgcaacatacggaaaacttacccttaaatttatttgcactactggaaaactacctgttccatggccaacacttgtcactactttcggttatggtgttcaatgctttgcgagatacccagatcatatgaaacagcatgactttttcaagagtgccatgcccgaaggttatgtacaggaaagaactatatttttcaaagatgacgggaactacaagacacgtgctgaagtcaagtttgaaggtgatacccttgttaatagaatcgagttaaaaggtattgattttaaagaagatggaaacattcttggacacaaattggaatacaactataactcacacaatgtatacatcatggcagacaaacaaaagaatggaatcaaagttaacttcaaaattagacacaacattgaagatggaagcgttcaactagcagaccattatcaacaaaatactccaattggcgatggccctgtccttttaccagacaaccattacctgtccacacaatctgccctttcgaaagatcccaacgaaaagagagaccacatggtccttcttgagtttgtaacagctgctgggattacacatggcatggatgaactatacaaataataa" . + "1" . + . + . . - . - . - "1" . - . - . + "GFP" . + "i13504" . "1" . - . - . - . - . - . - "SubComponent2" . - "B0015" . - "1" . + "1" . . - "1" . - . - . - "B0034_seq" . . - "double terminator" . + . + . + "1" . + . + . + "SubComponent1" . + . + "GFP expression cassette used for 2016 iGEM interlab study" . + . + . . + . + . + "aaagaggagaaa" . "ccaggcatcaaataaaacgaaaggctcagtcgaaagactgggcctttcgttttatctgttgtttgtcggtgaacgctctctactagagtcacactggctcaccttcgggtgggcctttctgcgtttata" . - "E0040_seq" . - . - . - . - "GFP" . + "1" . + . + . + "iGEM 2016 interlab reporter" . + . . + . + "1" . + . + "E0040_seq" . . - "aaagaggagaaa" . - "i13504" . - "RBS (Elowitz 1999)" . - . - . - "E0040" . - "atgcgtaaaggagaagaacttttcactggagttgtcccaattcttgttgaattagatggtgatgttaatgggcacaaattttctgtcagtggagagggtgaaggtgatgcaacatacggaaaacttacccttaaatttatttgcactactggaaaactacctgttccatggccaacacttgtcactactttcggttatggtgttcaatgctttgcgagatacccagatcatatgaaacagcatgactttttcaagagtgccatgcccgaaggttatgtacaggaaagaactatatttttcaaagatgacgggaactacaagacacgtgctgaagtcaagtttgaaggtgatacccttgttaatagaatcgagttaaaaggtattgattttaaagaagatggaaacattcttggacacaaattggaatacaactataactcacacaatgtatacatcatggcagacaaacaaaagaatggaatcaaagttaacttcaaaattagacacaacattgaagatggaagcgttcaactagcagaccattatcaacaaaatactccaattggcgatggccctgtccttttaccagacaaccattacctgtccacacaatctgccctttcgaaagatcccaacgaaaagagagaccacatggtccttcttgagtttgtaacagctgctgggattacacatggcatggatgaactatacaaataataa" . - . + . + . . - . - . - . - . - . - . - "GFP expression cassette used for 2016 iGEM interlab study" . - . + "B0034" . "B0015_seq" . - "iGEM 2016 interlab reporter" . - "SubComponent1" . - "1" . . - . + "SubComponent2" . "SubComponent3" . + . + . + . "1" . - . + "double terminator" . + . + . + "B0015" . + . diff --git a/test/test_files/subcomponent_test_3.nt b/test/test_files/subcomponent_test_3.nt index 85c5d9ba..26ab10bc 100644 --- a/test/test_files/subcomponent_test_3.nt +++ b/test/test_files/subcomponent_test_3.nt @@ -53,3 +53,10 @@ . . . + "1" . + "1" . + "1" . + "1" . + "1" . + "1" . + "1" . diff --git a/test/test_sbol2_sbol3_direct.py b/test/test_sbol2_sbol3_direct.py index bb94d895..44f731f9 100644 --- a/test/test_sbol2_sbol3_direct.py +++ b/test/test_sbol2_sbol3_direct.py @@ -129,6 +129,7 @@ def test_2to3_collection_conversion(self): doc2_loop.write(tmp2) self.assertFalse(file_diff(str(tmp2), str(TEST_FILES / 'sbol_3to2_collection.xml'))) + # @unittest.skip("Feature in Progress") def test_3to2_subcomponent_test(self): """Test ability to convert a sub_component from SBOL3 to SBOL2""" # Load an SBOL3 document and check its contents @@ -148,27 +149,21 @@ def test_3to2_subcomponent_test(self): # Read the contents of the file file_contents = file.read() - # Print the contents - print(file_contents) # self.assertFalse(file_diff(str(tmp2), str(TEST_FILES / 'sbol_3to2_collection.xml'))) doc3_loop = convert2to3(doc2, use_native_converter=True) self.assertEqual(len(doc3_loop.validate()), 0) tmp3 = 'doc3_loop.nt' doc3_loop.write(tmp3) - - print() - with open(tmp3, "r") as file: - # Read the contents of the file - file_contents = file.read() - - # Print the contents - print(file_contents) + with open(tmp3, 'r') as file: + data = file.read() self.assertFalse(file_diff(str(tmp3), str(TEST_FILES / 'subcomponent_test_3.nt'))) + # ToDo: add a test with two components, each with two subcomponents + if __name__ == '__main__': unittest.main() From ae4c6c2567d5f79e4c947503aade53118b87ca39 Mon Sep 17 00:00:00 2001 From: Yehuda Binik Date: Tue, 3 Sep 2024 10:33:02 -0400 Subject: [PATCH 10/14] CLeaned up files before pull request --- sbol_utilities/sbol3_sbol2_conversion.py | 23 +- test/doc3_loop.nt | 62 ----- test/test_files/create_subcomponent_test.py | 89 ------ test/test_files/sbol_3to2_toggle_switch.nt | 7 - test/test_files/subcomponent_test.nt | 67 ----- .../subcomponent_test_3_bare_bones.xml | 254 ------------------ .../test_files/~$circular_inference_test.xlsx | Bin 165 -> 0 bytes test/test_sbol2_sbol3_direct.py | 6 +- 8 files changed, 4 insertions(+), 504 deletions(-) delete mode 100644 test/doc3_loop.nt delete mode 100644 test/test_files/create_subcomponent_test.py delete mode 100644 test/test_files/sbol_3to2_toggle_switch.nt delete mode 100644 test/test_files/subcomponent_test.nt delete mode 100644 test/test_files/subcomponent_test_3_bare_bones.xml delete mode 100644 test/test_files/~$circular_inference_test.xlsx diff --git a/sbol_utilities/sbol3_sbol2_conversion.py b/sbol_utilities/sbol3_sbol2_conversion.py index c97554d4..3eb5d6ac 100644 --- a/sbol_utilities/sbol3_sbol2_conversion.py +++ b/sbol_utilities/sbol3_sbol2_conversion.py @@ -195,20 +195,8 @@ def visit_component_reference(self, comp_ref3: sbol3.ComponentReference): def visit_constraint(self, constraint: sbol3.Constraint): # Priority: 2 - - if constraint.restriction == "http://sbols.org/v3#verifyIdentical": - maps_to = sbol2.mapsto.MapsTo(constraint.identity, refinement="http://sbols.org/v2#verifyIdentical") - module_definition = sbol2.ModuleDefinition(constraint.identity) - module_definition.modules.add(maps_to) - self.doc2.addModuleDefinition(module_definition) - local = sbol2.Component(constraint.object) - remote = sbol2.Component(self.doc3.find(constraint.subject).refers_to) - maps_to.local = local - maps_to.remote = remote - - if constraint.restriction == "http://sbols.org/v3#replaces": - raise NotImplementedError( - 'Conversion of Constraint from SBOL3 to SBOL2 with replaces restriction not yet implemented') + raise NotImplementedError( + 'Conversion of Constraint from SBOL3 to SBOL2 not yet implemented') def visit_cut(self, a: sbol3.Cut): # Priority: 2 @@ -582,12 +570,7 @@ def visit_module(self, a: sbol2.Module): def visit_module_definition(self, md2: sbol2.ModuleDefinition): # Priority: 3 - - # Make the Component object and add it to the document - cp3 = sbol3.Component(md2.identity, types=['https://identifiers.org/SBO:0000241']) - self.doc3.add(cp3) - # Map over all other TopLevel properties and extensions not covered by the constructor - self._convert_toplevel(md2, cp3) + raise NotImplementedError('Conversion of ModuleDefinition from SBOL2 to SBOL3 not yet implemented') def visit_participation(self, a: sbol2.Participation): # Priority: 2 diff --git a/test/doc3_loop.nt b/test/doc3_loop.nt deleted file mode 100644 index 817beddf..00000000 --- a/test/doc3_loop.nt +++ /dev/null @@ -1,62 +0,0 @@ - "RBS (Elowitz 1999)" . - "E0040" . - "B0034_seq" . - . - . - . - . - . - "atgcgtaaaggagaagaacttttcactggagttgtcccaattcttgttgaattagatggtgatgttaatgggcacaaattttctgtcagtggagagggtgaaggtgatgcaacatacggaaaacttacccttaaatttatttgcactactggaaaactacctgttccatggccaacacttgtcactactttcggttatggtgttcaatgctttgcgagatacccagatcatatgaaacagcatgactttttcaagagtgccatgcccgaaggttatgtacaggaaagaactatatttttcaaagatgacgggaactacaagacacgtgctgaagtcaagtttgaaggtgatacccttgttaatagaatcgagttaaaaggtattgattttaaagaagatggaaacattcttggacacaaattggaatacaactataactcacacaatgtatacatcatggcagacaaacaaaagaatggaatcaaagttaacttcaaaattagacacaacattgaagatggaagcgttcaactagcagaccattatcaacaaaatactccaattggcgatggccctgtccttttaccagacaaccattacctgtccacacaatctgccctttcgaaagatcccaacgaaaagagagaccacatggtccttcttgagtttgtaacagctgctgggattacacatggcatggatgaactatacaaataataa" . - "1" . - . - . - . - "GFP" . - "i13504" . - "1" . - "1" . - . - . - . - . - "1" . - . - . - "SubComponent1" . - . - "GFP expression cassette used for 2016 iGEM interlab study" . - . - . - . - . - . - "aaagaggagaaa" . - "ccaggcatcaaataaaacgaaaggctcagtcgaaagactgggcctttcgttttatctgttgtttgtcggtgaacgctctctactagagtcacactggctcaccttcgggtgggcctttctgcgtttata" . - "1" . - . - . - "iGEM 2016 interlab reporter" . - . - . - . - "1" . - . - "E0040_seq" . - . - . - . - . - "B0034" . - "B0015_seq" . - . - "SubComponent2" . - "SubComponent3" . - . - . - . - "1" . - "double terminator" . - . - . - "B0015" . - . diff --git a/test/test_files/create_subcomponent_test.py b/test/test_files/create_subcomponent_test.py deleted file mode 100644 index 58bea7a6..00000000 --- a/test/test_files/create_subcomponent_test.py +++ /dev/null @@ -1,89 +0,0 @@ -from sbol3 import * -from sbol_utilities.calculate_sequences import compute_sequence -from sbol_utilities.component import * -from sbol_utilities.helper_functions import url_to_identity -import tyto - -set_namespace('https://synbiohub.org/public/igem/') -doc = Document() - -i13504 = Component('i13504', SBO_DNA) -i13504.name = 'iGEM 2016 interlab reporter' -i13504.description = 'GFP expression cassette used for 2016 iGEM interlab study' -i13504.roles.append(tyto.SO.engineered_region) - -doc.add(i13504) - -b0034, b0034_seq = doc.add(rbs('B0034', sequence='aaagaggagaaa', name='RBS (Elowitz 1999)')) - - -e0040_sequence = 'atgcgtaaaggagaagaacttttcactggagttgtcccaattcttgttgaattagatggtgatgttaatgggcacaaattttctgtcagtggagagggtgaaggtgatgcaacatacggaaaacttacccttaaatttatttgcactactggaaaactacctgttccatggccaacacttgtcactactttcggttatggtgttcaatgctttgcgagatacccagatcatatgaaacagcatgactttttcaagagtgccatgcccgaaggttatgtacaggaaagaactatatttttcaaagatgacgggaactacaagacacgtgctgaagtcaagtttgaaggtgatacccttgttaatagaatcgagttaaaaggtattgattttaaagaagatggaaacattcttggacacaaattggaatacaactataactcacacaatgtatacatcatggcagacaaacaaaagaatggaatcaaagttaacttcaaaattagacacaacattgaagatggaagcgttcaactagcagaccattatcaacaaaatactccaattggcgatggccctgtccttttaccagacaaccattacctgtccacacaatctgccctttcgaaagatcccaacgaaaagagagaccacatggtccttcttgagtttgtaacagctgctgggattacacatggcatggatgaactatacaaataataa' -e0040, _ = doc.add(cds('E0040', sequence=e0040_sequence, name='GFP')) - -b0015_sequence = 'ccaggcatcaaataaaacgaaaggctcagtcgaaagactgggcctttcgttttatctgttgtttgtcggtgaacgctctctactagagtcacactggctcaccttcgggtgggcctttctgcgtttata' -b0015, _ = doc.add(terminator('B0015', sequence=b0015_sequence, name='double terminator')) - - -order(b0034, e0040, i13504) -order(e0040, b0015, i13504) - -i13504_seq = compute_sequence(i13504) - -b0015_subcomponent = next(f for f in i13504.features if f.instance_of == b0015.identity) -b0015_range = b0015_subcomponent.locations[0] -print(f'Range of {b0015.display_name}: ({b0015_range.start}, {b0015_range.end})') - -i13504_system = functional_component('i13504_system') -doc.add(i13504_system) - -gfp = add_feature(i13504_system, ed_protein('https://www.fpbase.org/protein/gfpmut3/', name='GFP')) - -i13504_subcomponent = add_feature(i13504_system, i13504) - -e0040_subcomponent = next(f for f in i13504.features if f.instance_of == e0040.identity) -e0040_reference = ComponentReference(i13504_subcomponent, e0040_subcomponent) -i13504_system.features.append(e0040_reference) - - -add_interaction(tyto.SBO.genetic_production, - participants={gfp: tyto.SBO.product, e0040_reference: tyto.SBO.template}) - -J23101_sequence = 'tttacagctagctcagtcctaggtattatgctagc' -J23101, _ = doc.add(promoter('J23101', sequence=J23101_sequence)) -J23106_sequence = 'tttacggctagctcagtcctaggtatagtgctagc' -J23106, _ = doc.add(promoter('J23106', sequence=J23106_sequence)) - -device1 = doc.add(functional_component('interlab16device1')) -device1_i13504_system = add_feature(device1, SubComponent(i13504_system)) -order(J23101, ComponentReference(device1_i13504_system, i13504_subcomponent), device1) -device2 = doc.add(functional_component('interlab16device2')) -device2_i13504_system = add_feature(device2, SubComponent(i13504_system)) -order(J23106, ComponentReference(device2_i13504_system, i13504_subcomponent), device2) -print(f'Device 1 second subcomponent points to {device1.constraints[0].object.lookup().refers_to.lookup().instance_of}') - -interlab16 = doc.add(Collection('interlab16',members=[device1, device2])) -print(f'Members are {", ".join(m.lookup().display_id for m in interlab16.members)}') - -ecoli = doc.add(strain('Ecoli_DH5_alpha')) -pSB1C3 = doc.add(Component('pSB1C3', SBO_DNA, roles=[tyto.SO.plasmid_vector])) - -device1_ecoli = doc.add(strain('device1_ecoli')) - -plasmid = LocalSubComponent(SBO_DNA, roles=[tyto.SO.plasmid_vector], name="Interlab Device 1 in pSB1C3") -device1_ecoli.features.append(plasmid) -device1_subcomponent = contains(plasmid, device1) -contains(plasmid, pSB1C3) -order(device1, pSB1C3, device1_ecoli) - -contains(ecoli, plasmid, device1_ecoli) - - -report = doc.validate() -if report: - print('Document is not valid') - print(f'Document has {len(report.errors)} errors') - print(f'Document has {len(report.warnings)} warnings') -else: - print('Document is valid') - -doc.write('subcomponent_test.nt', file_format=SORTED_NTRIPLES) diff --git a/test/test_files/sbol_3to2_toggle_switch.nt b/test/test_files/sbol_3to2_toggle_switch.nt deleted file mode 100644 index 53c8766e..00000000 --- a/test/test_files/sbol_3to2_toggle_switch.nt +++ /dev/null @@ -1,7 +0,0 @@ -https://sbolstandard.org/examples/col1, http://sbols.org/v2#version, 1 -https://sbolstandard.org/examples/col1, http://sbols.org/v2#member, https://sbolstandard.org/examples/LacI_protein -https://sbolstandard.org/examples/col1, http://sboltools.org/backport#sbol3namespace, https://sbolstandard.org/examples -https://sbolstandard.org/examples/col1, http://sbols.org/v2#persistentIdentity, https://sbolstandard.org/examples/col1 -https://sbolstandard.org/examples/col1, http://sbols.org/v2#member, https://sbolstandard.org/examples/TetR_protein -https://sbolstandard.org/examples/col1, http://www.w3.org/1999/02/22-rdf-syntax-ns#type, http://sbols.org/v2#Collection -https://sbolstandard.org/examples/col1, http://sbols.org/v2#displayId, col1 diff --git a/test/test_files/subcomponent_test.nt b/test/test_files/subcomponent_test.nt deleted file mode 100644 index 13964df4..00000000 --- a/test/test_files/subcomponent_test.nt +++ /dev/null @@ -1,67 +0,0 @@ - "B0015" . - . - . - "double terminator" . - . - . - . - "B0015_seq" . - "ccaggcatcaaataaaacgaaaggctcagtcgaaagactgggcctttcgttttatctgttgtttgtcggtgaacgctctctactagagtcacactggctcaccttcgggtgggcctttctgcgtttata" . - . - . - . - "B0034" . - . - . - "RBS (Elowitz 1999)" . - . - . - . - "B0034_seq" . - "aaagaggagaaa" . - . - . - . - "E0040" . - . - . - "GFP" . - . - . - . - "E0040_seq" . - "atgcgtaaaggagaagaacttttcactggagttgtcccaattcttgttgaattagatggtgatgttaatgggcacaaattttctgtcagtggagagggtgaaggtgatgcaacatacggaaaacttacccttaaatttatttgcactactggaaaactacctgttccatggccaacacttgtcactactttcggttatggtgttcaatgctttgcgagatacccagatcatatgaaacagcatgactttttcaagagtgccatgcccgaaggttatgtacaggaaagaactatatttttcaaagatgacgggaactacaagacacgtgctgaagtcaagtttgaaggtgatacccttgttaatagaatcgagttaaaaggtattgattttaaagaagatggaaacattcttggacacaaattggaatacaactataactcacacaatgtatacatcatggcagacaaacaaaagaatggaatcaaagttaacttcaaaattagacacaacattgaagatggaagcgttcaactagcagaccattatcaacaaaatactccaattggcgatggccctgtccttttaccagacaaccattacctgtccacacaatctgccctttcgaaagatcccaacgaaaagagagaccacatggtccttcttgagtttgtaacagctgctgggattacacatggcatggatgaactatacaaataataa" . - . - . - . - "Constraint1" . - . - . - . - . - "Constraint2" . - . - . - . - . - "SubComponent1" . - . - . - "SubComponent2" . - . - . - "SubComponent3" . - . - . - "GFP expression cassette used for 2016 iGEM interlab study" . - "i13504" . - . - . - . - . - . - . - "iGEM 2016 interlab reporter" . - . - . - . diff --git a/test/test_files/subcomponent_test_3_bare_bones.xml b/test/test_files/subcomponent_test_3_bare_bones.xml deleted file mode 100644 index 8b338e9c..00000000 --- a/test/test_files/subcomponent_test_3_bare_bones.xml +++ /dev/null @@ -1,254 +0,0 @@ - "B0015" . - . - . - "double terminator" . - . - . - . - "B0015_seq" . - "ccaggcatcaaataaaacgaaaggctcagtcgaaagactgggcctttcgttttatctgttgtttgtcggtgaacgctctctactagagtcacactggctcaccttcgggtgggcctttctgcgtttata" . - . - . - . - "B0034" . - . - . - "RBS (Elowitz 1999)" . - . - . - . - "B0034_seq" . - "aaagaggagaaa" . - . - . - . - "E0040" . - . - . - "GFP" . - . - . - . - "E0040_seq" . - "atgcgtaaaggagaagaacttttcactggagttgtcccaattcttgttgaattagatggtgatgttaatgggcacaaattttctgtcagtggagagggtgaaggtgatgcaacatacggaaaacttacccttaaatttatttgcactactggaaaactacctgttccatggccaacacttgtcactactttcggttatggtgttcaatgctttgcgagatacccagatcatatgaaacagcatgactttttcaagagtgccatgcccgaaggttatgtacaggaaagaactatatttttcaaagatgacgggaactacaagacacgtgctgaagtcaagtttgaaggtgatacccttgttaatagaatcgagttaaaaggtattgattttaaagaagatggaaacattcttggacacaaattggaatacaactataactcacacaatgtatacatcatggcagacaaacaaaagaatggaatcaaagttaacttcaaaattagacacaacattgaagatggaagcgttcaactagcagaccattatcaacaaaatactccaattggcgatggccctgtccttttaccagacaaccattacctgtccacacaatctgccctttcgaaagatcccaacgaaaagagagaccacatggtccttcttgagtttgtaacagctgctgggattacacatggcatggatgaactatacaaataataa" . - . - . - . - "Ecoli_DH5_alpha" . - . - . - . - . - "J23101" . - . - . - . - . - . - "J23101_seq" . - "tttacagctagctcagtcctaggtattatgctagc" . - . - . - . - "J23106" . - . - . - . - . - . - "J23106_seq" . - "tttacggctagctcagtcctaggtatagtgctagc" . - . - . - . - "Constraint1" . - . - . - . - . - "Constraint2" . - . - . - . - . - "Constraint3" . - . - . - . - . - "Constraint4" . - . - . - . - . - "LocalSubComponent1" . - "Interlab Device 1 in pSB1C3" . - . - . - . - "SubComponent1" . - . - . - "SubComponent2" . - . - . - "SubComponent3" . - . - . - "device1_ecoli" . - . - . - . - . - . - . - . - . - . - . - . - . - "Constraint1" . - . - . - . - . - "Constraint2" . - . - . - . - . - "Range1" . - "12"^^ . - . - "1"^^ . - . - "SubComponent1" . - . - . - . - "Range1" . - "732"^^ . - . - "13"^^ . - . - "SubComponent2" . - . - . - . - "Range1" . - "861"^^ . - . - "733"^^ . - . - "SubComponent3" . - . - . - . - "GFP expression cassette used for 2016 iGEM interlab study" . - "i13504" . - . - . - . - . - . - . - . - "iGEM 2016 interlab reporter" . - . - . - . - "i13504_sequence" . - "aaagaggagaaaatgcgtaaaggagaagaacttttcactggagttgtcccaattcttgttgaattagatggtgatgttaatgggcacaaattttctgtcagtggagagggtgaaggtgatgcaacatacggaaaacttacccttaaatttatttgcactactggaaaactacctgttccatggccaacacttgtcactactttcggttatggtgttcaatgctttgcgagatacccagatcatatgaaacagcatgactttttcaagagtgccatgcccgaaggttatgtacaggaaagaactatatttttcaaagatgacgggaactacaagacacgtgctgaagtcaagtttgaaggtgatacccttgttaatagaatcgagttaaaaggtattgattttaaagaagatggaaacattcttggacacaaattggaatacaactataactcacacaatgtatacatcatggcagacaaacaaaagaatggaatcaaagttaacttcaaaattagacacaacattgaagatggaagcgttcaactagcagaccattatcaacaaaatactccaattggcgatggccctgtccttttaccagacaaccattacctgtccacacaatctgccctttcgaaagatcccaacgaaaagagagaccacatggtccttcttgagtttgtaacagctgctgggattacacatggcatggatgaactatacaaataataaccaggcatcaaataaaacgaaaggctcagtcgaaagactgggcctttcgttttatctgttgtttgtcggtgaacgctctctactagagtcacactggctcaccttcgggtgggcctttctgcgtttata" . - . - . - . - "ComponentReference1" . - . - . - . - . - "ExternallyDefined1" . - "GFP" . - . - . - "Participation1" . - . - . - . - "Participation2" . - . - . - . - "Interaction1" . - . - . - . - . - "SubComponent1" . - . - . - "i13504_system" . - . - . - . - . - . - . - . - "interlab16" . - . - . - . - . - "ComponentReference1" . - . - . - . - "Constraint1" . - . - . - . - . - "SubComponent1" . - . - . - "SubComponent2" . - . - . - "interlab16device1" . - . - . - . - . - . - . - . - "ComponentReference1" . - . - . - . - "Constraint1" . - . - . - . - . - "SubComponent1" . - . - . - "SubComponent2" . - . - . - "interlab16device2" . - . - . - . - . - . - . - . - "pSB1C3" . - . - . - . - . diff --git a/test/test_files/~$circular_inference_test.xlsx b/test/test_files/~$circular_inference_test.xlsx deleted file mode 100644 index 802e3f9c33c0f5cda473fbf4d22eadaa9a99b84f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 165 ycmd;yOwA}wNmOvk%*)JHAR6#6L^7l@WH6L6q%b5hC@?rNWHRIdaW;@meFy*yp%Zfe diff --git a/test/test_sbol2_sbol3_direct.py b/test/test_sbol2_sbol3_direct.py index 44f731f9..5450a991 100644 --- a/test/test_sbol2_sbol3_direct.py +++ b/test/test_sbol2_sbol3_direct.py @@ -153,12 +153,8 @@ def test_3to2_subcomponent_test(self): doc3_loop = convert2to3(doc2, use_native_converter=True) self.assertEqual(len(doc3_loop.validate()), 0) - tmp3 = 'doc3_loop.nt' + tmp3 = Path(tmpdir) / 'doc3_loop.nt' doc3_loop.write(tmp3) - with open(tmp3, 'r') as file: - data = file.read() - - self.assertFalse(file_diff(str(tmp3), str(TEST_FILES / 'subcomponent_test_3.nt'))) From e106ea951f9c92b74c06705fb1aad538c86eb68f Mon Sep 17 00:00:00 2001 From: Yehuda Binik Date: Tue, 3 Sep 2024 10:48:50 -0400 Subject: [PATCH 11/14] Cleaned up the files some more, and refoactored set_subcomponent_identities() --- sbol_utilities/sbol3_sbol2_conversion.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/sbol_utilities/sbol3_sbol2_conversion.py b/sbol_utilities/sbol3_sbol2_conversion.py index 3eb5d6ac..ffd0d2b2 100644 --- a/sbol_utilities/sbol3_sbol2_conversion.py +++ b/sbol_utilities/sbol3_sbol2_conversion.py @@ -24,7 +24,6 @@ class SBOL3To2ConversionVisitor: doc2: sbol2.Document def __init__(self, doc3: sbol3.Document): - self.doc3 = doc3 # Create the target document self.doc2 = sbol2.Document() # # Immediately run the conversion @@ -147,7 +146,6 @@ def visit_combinatorial_derivation(self, a: sbol3.CombinatorialDerivation): def visit_component(self, comp3: sbol3.Component): # Remap type if it's one of the ones that needs remapping; otherwise pass through unchanged - type_map = {sbol3.SBO_DNA: sbol2.BIOPAX_DNA, # TODO: distinguish BioPAX Dna from DnaRegion sbol3.SBO_RNA: sbol2.BIOPAX_RNA, # TODO: distinguish BioPAX Rna from RnaRegion sbol3.SBO_PROTEIN: sbol2.BIOPAX_PROTEIN, @@ -164,11 +162,15 @@ def visit_component(self, comp3: sbol3.Component): for feature in comp3.features: if type(feature) == sbol3.subcomponent.SubComponent: self.visit_sub_component(feature, comp_def2) - if type(feature) == sbol3.compref.ComponentReference: + elif type(feature) == sbol3.compref.ComponentReference: try: self.visit_component_reference(feature) except NotImplementedError as e: + # highlights the error message in red. print(f"\033[91m{e}\033[0m") + else: + raise NotImplementedError( + 'Conversion of Component features from SBOL3 to SBOL2 not yet implemented') if comp3.interactions: for interaction in comp3.interactions: try: @@ -195,8 +197,7 @@ def visit_component_reference(self, comp_ref3: sbol3.ComponentReference): def visit_constraint(self, constraint: sbol3.Constraint): # Priority: 2 - raise NotImplementedError( - 'Conversion of Constraint from SBOL3 to SBOL2 not yet implemented') + raise NotImplementedError('Conversion of Constraint from SBOL3 to SBOL2 not yet implemented') def visit_cut(self, a: sbol3.Cut): # Priority: 2 @@ -437,7 +438,7 @@ def visit_component_definition(self, comp_def2: sbol2.ComponentDefinition, sub3_ types3 = [type_map.get(t, t) for t in comp_def2.types] # Make the Component object and add it to the document comp3 = sbol3.Component(comp_def2.identity, types3, namespace=self._sbol3_namespace(comp_def2), - roles=comp_def2.roles, sequences=comp_def2.sequences) + roles=comp_def2.roles, sequences=comp_def2.sequences) self.doc3.add(comp3) # Convert the Component properties not covered by the constructor @@ -456,7 +457,6 @@ def visit_component_definition(self, comp_def2: sbol2.ComponentDefinition, sub3_ self._convert_toplevel(comp_def2, comp3) self.set_subcomponent_identities(sub3_comp2_equivalencies) - def visit_component(self, comp2: sbol2.Component, comp3: sbol3.Component, sub3_comp2_equivalencies): # Priority: 2 sub3 = sbol3.SubComponent(comp2.identity) @@ -467,7 +467,7 @@ def visit_component(self, comp2: sbol2.Component, comp3: sbol3.Component, sub3_c sub3.source_locations = comp2.sourceLocations sub3.instance_of = comp2.definition comp3.features += [sub3] - sub3_comp2_equivalencies[f"<{sub3.identity}> "] = f"<{comp2.identity}> " + sub3_comp2_equivalencies[sub3.identity] = comp2.identity def set_subcomponent_identities(self, sub3_comp2_equivalencies): temporary_file = 'temporary_file.nt' @@ -477,7 +477,7 @@ def set_subcomponent_identities(self, sub3_comp2_equivalencies): triples = content.splitlines() for index, triple in enumerate(triples): for sub3 in sub3_comp2_equivalencies: - if sub3 in triple: + if f"<{sub3}> " in triple: triples[index] = triple.replace(sub3, sub3_comp2_equivalencies[sub3]) # Move the file pointer to the beginning file.seek(0) From 44e31ed0ffb29ce9cb535466dccf5dfcabab3c37 Mon Sep 17 00:00:00 2001 From: Yehuda Binik Date: Tue, 3 Sep 2024 11:19:23 -0400 Subject: [PATCH 12/14] Refactored variable names in set_subcomponent_identities() --- sbol_utilities/sbol3_sbol2_conversion.py | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/sbol_utilities/sbol3_sbol2_conversion.py b/sbol_utilities/sbol3_sbol2_conversion.py index ffd0d2b2..2537f359 100644 --- a/sbol_utilities/sbol3_sbol2_conversion.py +++ b/sbol_utilities/sbol3_sbol2_conversion.py @@ -442,10 +442,10 @@ def visit_component_definition(self, comp_def2: sbol2.ComponentDefinition, sub3_ self.doc3.add(comp3) # Convert the Component properties not covered by the constructor - sub3_comp2_equivalencies = {} + identity_mappings = {} if comp_def2.components: for comp2 in comp_def2.components: - self.visit_component(comp2, comp3, sub3_comp2_equivalencies) + self.visit_component(comp2, comp3, identity_mappings) if comp_def2.sequenceAnnotations: raise NotImplementedError('Conversion of ComponentDefinition sequenceAnnotations ' @@ -455,9 +455,9 @@ def visit_component_definition(self, comp_def2: sbol2.ComponentDefinition, sub3_ 'from SBOL2 to SBOL3 not yet implemented') # Map over all other TopLevel properties and extensions not covered by the constructor self._convert_toplevel(comp_def2, comp3) - self.set_subcomponent_identities(sub3_comp2_equivalencies) + self.set_subcomponent_identities(identity_mappings) - def visit_component(self, comp2: sbol2.Component, comp3: sbol3.Component, sub3_comp2_equivalencies): + def visit_component(self, comp2: sbol2.Component, comp3: sbol3.Component, identity_mappings): # Priority: 2 sub3 = sbol3.SubComponent(comp2.identity) sub3.roles = comp2.roles @@ -467,18 +467,17 @@ def visit_component(self, comp2: sbol2.Component, comp3: sbol3.Component, sub3_c sub3.source_locations = comp2.sourceLocations sub3.instance_of = comp2.definition comp3.features += [sub3] - sub3_comp2_equivalencies[sub3.identity] = comp2.identity + identity_mappings[sub3.identity] = comp2.identity - def set_subcomponent_identities(self, sub3_comp2_equivalencies): + def set_subcomponent_identities(self, identity_mappings): temporary_file = 'temporary_file.nt' self.doc3.write(temporary_file) with open(temporary_file, 'r+') as file: - content = file.read() - triples = content.splitlines() + triples = file.readlines() for index, triple in enumerate(triples): - for sub3 in sub3_comp2_equivalencies: - if f"<{sub3}> " in triple: - triples[index] = triple.replace(sub3, sub3_comp2_equivalencies[sub3]) + for old_identity, new_identity in identity_mappings: + if f"<{old_identity}> " in triple: + triples[index] = triple.replace(old_identity, new_identity) # Move the file pointer to the beginning file.seek(0) From ba403b700aba7df46689bb64cbed19b57ab5c9f8 Mon Sep 17 00:00:00 2001 From: Yehuda Binik Date: Tue, 3 Sep 2024 11:28:26 -0400 Subject: [PATCH 13/14] Fixed bug in set_subcomponent_identities --- sbol_utilities/sbol3_sbol2_conversion.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/sbol_utilities/sbol3_sbol2_conversion.py b/sbol_utilities/sbol3_sbol2_conversion.py index 2537f359..e9be52af 100644 --- a/sbol_utilities/sbol3_sbol2_conversion.py +++ b/sbol_utilities/sbol3_sbol2_conversion.py @@ -475,16 +475,12 @@ def set_subcomponent_identities(self, identity_mappings): with open(temporary_file, 'r+') as file: triples = file.readlines() for index, triple in enumerate(triples): - for old_identity, new_identity in identity_mappings: + for old_identity, new_identity in identity_mappings.items(): if f"<{old_identity}> " in triple: triples[index] = triple.replace(old_identity, new_identity) - # Move the file pointer to the beginning - file.seek(0) - - # Write the modified triples back to the file - file.writelines(triple + "\n" for triple in triples) - # Truncate the file to the current position to remove any leftover data + file.seek(0) + file.writelines(triples) file.truncate() self.doc3.read('temporary_file.nt') os.remove(temporary_file) From c1d50e4f0b73dc6f3ea04f3cef7c42b5ea344a81 Mon Sep 17 00:00:00 2001 From: Yehuda Binik Date: Tue, 3 Sep 2024 11:41:13 -0400 Subject: [PATCH 14/14] Refactored set_subcomponent_identity name and also changed it to create a file in a temporary directory --- sbol_utilities/sbol3_sbol2_conversion.py | 36 +++++++++++++----------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/sbol_utilities/sbol3_sbol2_conversion.py b/sbol_utilities/sbol3_sbol2_conversion.py index e9be52af..0be263d8 100644 --- a/sbol_utilities/sbol3_sbol2_conversion.py +++ b/sbol_utilities/sbol3_sbol2_conversion.py @@ -1,4 +1,5 @@ -import os +import tempfile +from pathlib import Path import sbol3 import sbol2 @@ -455,7 +456,7 @@ def visit_component_definition(self, comp_def2: sbol2.ComponentDefinition, sub3_ 'from SBOL2 to SBOL3 not yet implemented') # Map over all other TopLevel properties and extensions not covered by the constructor self._convert_toplevel(comp_def2, comp3) - self.set_subcomponent_identities(identity_mappings) + self.handle_subcomponent_identity_triple_surgery(identity_mappings) def visit_component(self, comp2: sbol2.Component, comp3: sbol3.Component, identity_mappings): # Priority: 2 @@ -469,21 +470,22 @@ def visit_component(self, comp2: sbol2.Component, comp3: sbol3.Component, identi comp3.features += [sub3] identity_mappings[sub3.identity] = comp2.identity - def set_subcomponent_identities(self, identity_mappings): - temporary_file = 'temporary_file.nt' - self.doc3.write(temporary_file) - with open(temporary_file, 'r+') as file: - triples = file.readlines() - for index, triple in enumerate(triples): - for old_identity, new_identity in identity_mappings.items(): - if f"<{old_identity}> " in triple: - triples[index] = triple.replace(old_identity, new_identity) - - file.seek(0) - file.writelines(triples) - file.truncate() - self.doc3.read('temporary_file.nt') - os.remove(temporary_file) + def handle_subcomponent_identity_triple_surgery(self, identity_mappings): + with tempfile.TemporaryDirectory() as tmpdir: + temporary_file = Path(tmpdir) / 'temporary_file.nt' + self.doc3.write(temporary_file) + with open(temporary_file, 'r+') as file: + + triples = file.readlines() + for index, triple in enumerate(triples): + for old_identity, new_identity in identity_mappings.items(): + if f"<{old_identity}> " in triple: + triples[index] = triple.replace(old_identity, new_identity) + + file.seek(0) + file.writelines(triples) + file.truncate() + self.doc3.read(temporary_file) def visit_cut(self, a: sbol2.Cut): # Priority: 2