From 5c7d227a1994d47adb722455fd9aed10bbe0b752 Mon Sep 17 00:00:00 2001
From: Metehan Unal <13197858+metehanunal@users.noreply.github.com>
Date: Wed, 16 Apr 2025 17:25:26 +0100
Subject: [PATCH 1/2] Model conversion and test are done
---
sbol_utilities/sbol3_sbol2_conversion.py | 32 +++++++++++++++----
test/test_files/example_model_sbol2.xml | 11 +++++++
test/test_files/example_model_sbol2_tmp.xml | 12 +++++++
test/test_files/example_model_sbol2_tmp_2.xml | 12 +++++++
test/test_files/example_model_sbol3.ttl | 10 ++++++
test/test_files/generated_model_sbol3.ttl | 10 ++++++
test/test_sbol2_sbol3_direct.py | 21 ++++++++++++
7 files changed, 102 insertions(+), 6 deletions(-)
create mode 100644 test/test_files/example_model_sbol2.xml
create mode 100644 test/test_files/example_model_sbol2_tmp.xml
create mode 100644 test/test_files/example_model_sbol2_tmp_2.xml
create mode 100644 test/test_files/example_model_sbol3.ttl
create mode 100644 test/test_files/generated_model_sbol3.ttl
diff --git a/sbol_utilities/sbol3_sbol2_conversion.py b/sbol_utilities/sbol3_sbol2_conversion.py
index ac44446f..fd3bac5c 100644
--- a/sbol_utilities/sbol3_sbol2_conversion.py
+++ b/sbol_utilities/sbol3_sbol2_conversion.py
@@ -1,3 +1,4 @@
+import sbol2.model
import sbol3
import sbol2
from sbol2 import mapsto, model, sequenceconstraint
@@ -226,9 +227,16 @@ def visit_measure(self, a: sbol3.Measure):
# Priority: 3
raise NotImplementedError('Conversion of Measure from SBOL3 to SBOL2 not yet implemented')
- def visit_model(self, a: sbol3.Model):
- # Priority: 3
- raise NotImplementedError('Conversion of Model from SBOL3 to SBOL2 not yet implemented')
+ def visit_model(self, model3: sbol3.Model):
+ # Priority: 3
+ model2 = sbol2.model.Model(uri=model3.identity, source=model3.source,
+ language=model3.language, framework=model3.framework)
+ self.doc2.add(model2)
+ # Map over all other TopLevel properties and extensions not covered by the constructor
+ self._convert_toplevel(model3, model2)
+ # seq2 = sbol2.Sequence(seq3.identity, seq3.elements,
+ # encoding=encoding2,
+ # version=self._sbol2_version(seq3))
def visit_participation(self, a: sbol3.Participation):
# Priority: 2
@@ -257,7 +265,9 @@ def visit_sequence(self, seq3: sbol3.Sequence):
sbol3.SMILES_ENCODING: sbol2.SBOL_ENCODING_SMILES}
encoding2 = encoding_map.get(seq3.encoding, seq3.encoding)
# Make the Sequence object and add it to the document
- seq2 = sbol2.Sequence(seq3.identity, seq3.elements, encoding=encoding2, version=self._sbol2_version(seq3))
+ seq2 = sbol2.Sequence(seq3.identity, seq3.elements,
+ encoding=encoding2,
+ version=self._sbol2_version(seq3))
self.doc2.addSequence(seq2)
# Map over all other TopLevel properties and extensions not covered by the constructor
self._convert_toplevel(seq3, seq2)
@@ -496,9 +506,19 @@ def visit_measure(self, a: sbol2.measurement.Measurement):
# Priority: 3
raise NotImplementedError('Conversion of Measure from SBOL2 to SBOL3 not yet implemented')
- def visit_model(self, a: sbol2.model.Model):
+ def visit_model(self, model2: sbol2.model.Model):
# Priority: 3
- raise NotImplementedError('Conversion of Model from SBOL2 to SBOL3 not yet implemented')
+
+ model3 = sbol3.Model(model2.identity, source=model2.source, language=model2.language,
+ framework=model2.framework)
+ self.doc3.add(model3)
+
+ # Map over all other TopLevel properties and extensions not covered by the constructor
+ self._convert_toplevel(model2, model3)
+
+
+
+
def visit_module(self, a: sbol2.Module):
# Priority: 3
diff --git a/test/test_files/example_model_sbol2.xml b/test/test_files/example_model_sbol2.xml
new file mode 100644
index 00000000..978413f5
--- /dev/null
+++ b/test/test_files/example_model_sbol2.xml
@@ -0,0 +1,11 @@
+
+
+
+
+ pIKE_Toggle_1
+ pIKE_Toggle_1 toggle switch
+
+
+
+
+
\ No newline at end of file
diff --git a/test/test_files/example_model_sbol2_tmp.xml b/test/test_files/example_model_sbol2_tmp.xml
new file mode 100644
index 00000000..fa14cc88
--- /dev/null
+++ b/test/test_files/example_model_sbol2_tmp.xml
@@ -0,0 +1,12 @@
+
+
+
+ pIKE_Toggle_1 toggle switch
+
+
+ pIKE_Toggle_1
+
+ 1
+
+
+
diff --git a/test/test_files/example_model_sbol2_tmp_2.xml b/test/test_files/example_model_sbol2_tmp_2.xml
new file mode 100644
index 00000000..5ca40d9b
--- /dev/null
+++ b/test/test_files/example_model_sbol2_tmp_2.xml
@@ -0,0 +1,12 @@
+
+
+ pIKE_Toggle_1
+ 1
+
+
+
+
+ pIKE_Toggle_1 toggle switch
+
+
+
diff --git a/test/test_files/example_model_sbol3.ttl b/test/test_files/example_model_sbol3.ttl
new file mode 100644
index 00000000..a5ceddc0
--- /dev/null
+++ b/test/test_files/example_model_sbol3.ttl
@@ -0,0 +1,10 @@
+@prefix sbol: .
+@prefix ex: .
+@prefix edam: .
+@prefix sbo: .
+@prefix xsd: .
+
+ex:mymodel a sbol:Model ;
+ sbol:source ;
+ sbol:language edam:format_2585 ;
+ sbol:framework sbo:SBO:0000064 .
diff --git a/test/test_files/generated_model_sbol3.ttl b/test/test_files/generated_model_sbol3.ttl
new file mode 100644
index 00000000..460c45fc
--- /dev/null
+++ b/test/test_files/generated_model_sbol3.ttl
@@ -0,0 +1,10 @@
+@prefix sbol: .
+
+ a sbol:Model ;
+ sbol:displayId "pIKE_Toggle_1" ;
+ sbol:framework ;
+ sbol:hasNamespace ;
+ sbol:language ;
+ sbol:name "pIKE_Toggle_1 toggle switch" ;
+ sbol:source .
+
diff --git a/test/test_sbol2_sbol3_direct.py b/test/test_sbol2_sbol3_direct.py
index 94791fcf..21db3861 100644
--- a/test/test_sbol2_sbol3_direct.py
+++ b/test/test_sbol2_sbol3_direct.py
@@ -1,6 +1,9 @@
+from sbol2 import Config, ConfigOptions
+
import tempfile
from pathlib import Path
+
import unittest
import sbol2
@@ -129,6 +132,24 @@ 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_2to3_and_3to2_model_conversion(self):
+ """Test ability to convert a model from SBOL2 to SBOL3"""
+ # Load an SBOL2 document and check its contents
+ Config.setOption(ConfigOptions.SBOL_COMPLIANT_URIS, False)
+ Config.setOption(ConfigOptions.SBOL_TYPED_URIS, False)
+ doc2 = sbol2.Document()
+ doc2.read(TEST_FILES / 'example_model_sbol2.xml')
+ model2 = doc2.models[0]
+ doc3 = convert2to3(doc2, use_native_converter=True)
+ self.assertEqual(len(doc3.validate()), 0)
+ doc3.write(TEST_FILES / 'generated_model_sbol3.ttl',file_format='turtle')
+ doc2_loop = convert3to2(doc3, True)
+ model2_loop = doc2_loop.models[0]
+ self.assertEqual(model2.language, model2_loop.language)
+ self.assertEqual(model2.framework, model2_loop.framework)
+ self.assertEqual(model2.source, model2_loop.source)
+ self.assertEqual(model2.name, model2_loop.name)
+
if __name__ == '__main__':
unittest.main()
From 351863a1555a53c2f14770099f8871c0a4e21568 Mon Sep 17 00:00:00 2001
From: Metehan Unal <13197858+metehanunal@users.noreply.github.com>
Date: Thu, 17 Apr 2025 10:56:01 +0100
Subject: [PATCH 2/2] Removed the commenting lines introduced by GitHub
---
test/test_sbol2_sbol3_direct.py | 22 +++++++++++-----------
1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/test/test_sbol2_sbol3_direct.py b/test/test_sbol2_sbol3_direct.py
index e862673b..7cfaa8c3 100644
--- a/test/test_sbol2_sbol3_direct.py
+++ b/test/test_sbol2_sbol3_direct.py
@@ -20,7 +20,7 @@ class TestDirectSBOL2SBOL3Conversion(unittest.TestCase):
# TODO: turn on validation
# J23101.xml is not SBOL compliant. Leaving conversions involving it for after the compliant converter is done
- '''
+
def test_3to2_conversion(self):
"""Test ability to convert a simple part from SBOL3 to SBOL2"""
# Load an SBOL3 document and check its contents
@@ -39,10 +39,10 @@ def test_3to2_conversion(self):
tmp3 = Path(tmpdir) / 'doc3_loop.nt'
doc3_loop.write(tmp3)
self.assertFalse(file_diff(str(tmp3), str(TEST_FILES / 'BBa_J23101_patched.nt')))
- '''
+
# J23101.xml is not SBOL compliant. Leaving conversions involving it for after the compliant converter is done
- '''
+
def test_2to3_conversion(self):
"""Test ability to convert a simple part from SBOL2 to SBOL3"""
# Load an SBOL2 document and check its contents
@@ -61,10 +61,10 @@ def test_2to3_conversion(self):
tmp2 = Path(tmpdir) / 'doc2_loop.xml'
doc2_loop.write(tmp2)
self.assertFalse(file_diff(str(tmp2), str(TEST_FILES / 'BBa_J23101.xml')))
- '''
+
# sbol_3to2_implementation.xml is not SBOL compliant. Leaving conversions involving it for after the compliant converter is done
- '''
+
def test_3to2_implementation_conversion(self):
"""Test ability to convert an implementation from SBOL3 to SBOL2"""
# Load an SBOL3 document and check its contents
@@ -83,10 +83,10 @@ def test_3to2_implementation_conversion(self):
tmp3 = Path(tmpdir) / 'doc3_loop.nt'
doc3_loop.write(tmp3)
self.assertFalse(file_diff(str(tmp3), str(TEST_FILES / 'sbol3_implementation.nt')))
- '''
+
# sbol_3to2_implementation.xml is not SBOL compliant. Leaving conversions involving it for after the compliant converter is done
- '''
+
def test_2to3_implementation_conversion(self):
"""Test ability to convert an implementation from SBOL2 to SBOL3"""
# Load an SBOL2 document and check its contents
@@ -105,10 +105,10 @@ def test_2to3_implementation_conversion(self):
tmp2 = Path(tmpdir) / 'doc2_loop.xml'
doc2_loop.write(tmp2)
self.assertFalse(file_diff(str(tmp2), str(TEST_FILES / 'sbol_3to2_implementation.xml')))
- '''
+
# sbol_3to2_collection.xml is not SBOL compliant. Leaving conversions involving it for after the compliant converter is done
- '''
+
# sbol_3to2_collection.xml is not SBOL compliant. Leaving conversions involving it for after the compliant converter is done
def test_3to2_collection_conversion(self):
"""Test ability to convert a collection from SBOL3 to SBOL2"""
@@ -128,10 +128,10 @@ def test_3to2_collection_conversion(self):
tmp3 = Path(tmpdir) / 'doc3_loop.nt'
doc3_loop.write(tmp3)
self.assertFalse(file_diff(str(tmp3), str(TEST_FILES / 'sbol3_collection.nt')))
- '''
+
# sbol_3to2_collection.xml is not SBOL compliant. Leaving conversions involving it for after the compliant converter is done
- '''
+
def test_2to3_collection_conversion(self):
"""Test ability to convert a collection from SBOL2 to SBOL3"""
# Load an SBOL2 document and check its contents