diff --git a/sbol_utilities/attempt2.py b/sbol_utilities/attempt2.py new file mode 100644 index 0000000..568c6af --- /dev/null +++ b/sbol_utilities/attempt2.py @@ -0,0 +1,54 @@ +import sbol2 +import sbol3 +import tyto +from sbol_utilities.conversion import convert2to3, convert3to2 + +sbol3.set_namespace('http://examples.org') + +# sbol2.config.Config.setOption(sbol2.config.ConfigOptions.VALIDATE_ONLINE, False) +doc2 = sbol2.Document() + +component2 = sbol2.ComponentDefinition('hello') + +# This is like a subcomponent of a DNA component that would be +# used as parcitipant +subcomponent2 = sbol2.FunctionalComponent('subcomp', definition=component2.identity) + +interaction2_component = sbol2.ModuleDefinition('hello2') +interaction2_component.functionalComponents.add(subcomponent2) + +participation2 = sbol2.Participation(uri='reactant1', participant=subcomponent2) +participation2.addRole(sbol2.SBO_REACTANT) + +interaction2 = sbol2.Interaction( + 'reaction1', + interaction_type=tyto.SBO.cleavage +) + +interaction2.participations.add(participation2) + +interaction2_component.interactions.add(interaction2) + + +doc2.add(interaction2_component) +doc2.add(component2) +doc2.write('doc2.xml') + +doc3 = convert2to3(doc2,['http://examples.org'], use_native_converter=True) + +doc3.write('doc3.xml') + +doc2_roundtrip = convert3to2(doc3, use_native_converter=True) +doc2_roundtrip.write('doc2_roundrip.xml') + + + +# def compare_objects(p1, p2): +# for k in vars(p1): +# if k in ['properties', '_properties']: +# continue +# if str(getattr(p1, k)) != str(getattr(p2, k)): +# print('prop:', k) +# print('original:', getattr(p1, k)) +# print('converted:', getattr(p2, k)) +# print() \ No newline at end of file diff --git a/sbol_utilities/attempt2_simplest.py b/sbol_utilities/attempt2_simplest.py new file mode 100644 index 0000000..af08b09 --- /dev/null +++ b/sbol_utilities/attempt2_simplest.py @@ -0,0 +1,28 @@ +import sbol2 +import sbol3 +import tyto +from sbol_utilities.conversion import convert2to3, convert3to2 + +sbol3.set_namespace('http://examples.org') + +# sbol2.config.Config.setOption(sbol2.config.ConfigOptions.VALIDATE_ONLINE, False) +doc2 = sbol2.Document() + +component2 = sbol2.ComponentDefinition('comp_def') + +subcomponent2 = sbol2.FunctionalComponent('funct_comp', definition=component2.identity) + +interaction2_component = sbol2.ModuleDefinition('mod_def') +interaction2_component.functionalComponents.add(subcomponent2) + +doc2.add(interaction2_component) +doc2.add(component2) +doc2.write('doc2.xml') + +doc3 = convert2to3(doc2,['http://examples.org'], use_native_converter=True) + +doc3.write('doc3.xml') + +doc2_roundtrip = convert3to2(doc3, use_native_converter=True) +doc2_roundtrip.write('doc2_roundrip.xml') + diff --git a/sbol_utilities/attempt3.py b/sbol_utilities/attempt3.py new file mode 100644 index 0000000..a2b0fde --- /dev/null +++ b/sbol_utilities/attempt3.py @@ -0,0 +1,30 @@ +import sbol3 +import sbol2 +from sbol_utilities.conversion import convert2to3, convert3to2 +from sbol3_sbol2_conversion import SBOL2To3ConversionVisitor, SBOL3To2ConversionVisitor +import tyto + +sbol3.set_namespace('http://examples.org') + +doc3 = sbol3.Document() + +component3 = sbol3.Component('component') +subcomponent3 = sbol3.SubComponent(component3) +component3.features.append(subcomponent3) + + +participation3 = sbol3.Participation(sbol3.SBO_REACTANT, subcomponent3) + +interaction3 = sbol3.Interaction( + tyto.SBO.cleavage, + participations=[participation3] +) + +interaction3_component = sbol3.Component('interaction_component', interactions=[interaction3], types=[tyto.SBO.cleavage]) + +doc3.add(component3) +doc3.add(interaction3_component) + + + + diff --git a/sbol_utilities/attempt3_simplest.py b/sbol_utilities/attempt3_simplest.py new file mode 100644 index 0000000..4dc2504 --- /dev/null +++ b/sbol_utilities/attempt3_simplest.py @@ -0,0 +1,24 @@ +import sbol3 +import sbol2 +from sbol_utilities.conversion import convert2to3, convert3to2 +from sbol3_sbol2_conversion import SBOL2To3ConversionVisitor, SBOL3To2ConversionVisitor +import tyto + +sbol3.set_namespace('http://examples.org') + +doc3 = sbol3.Document() + +component3 = sbol3.Component('comp_def', types=[sbol3.SBO_DNA]) +subcomponent3 = sbol3.SubComponent(component3) + +interaction3_component = sbol3.Component('mod_def', types=[sbol3.SBO_BIOCHEMICAL_REACTION]) +interaction3_component.features.append(subcomponent3) + +doc3.add(component3) +doc3.add(interaction3_component) +doc3.write('doc3_simplest.xml') + + + + + diff --git a/sbol_utilities/conversion.py b/sbol_utilities/conversion.py index 225c55b..444f4b0 100644 --- a/sbol_utilities/conversion.py +++ b/sbol_utilities/conversion.py @@ -166,6 +166,8 @@ def change_orientation(o): doc.traverse(change_orientation) report = doc.validate() + print(doc.objects[0], doc.objects[0].types) + print(doc.objects[1], doc.objects[1].types) if len(report): report_string = "\n".join(str(e) for e in doc.validate()) raise ValueError(f'Conversion from SBOL2 to SBOL3 produced an invalid document: {report_string}') diff --git a/sbol_utilities/sbol3_sbol2_conversion.py b/sbol_utilities/sbol3_sbol2_conversion.py index ac44446..e59052d 100644 --- a/sbol_utilities/sbol3_sbol2_conversion.py +++ b/sbol_utilities/sbol3_sbol2_conversion.py @@ -150,16 +150,29 @@ def visit_component(self, cp3: sbol3.Component): 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] - # 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) + + # Condition to test if it is a ModuleDefinition, probably there are better ways + if cp3.interactions: + # Make the ModuleDefinition object and add it to the document + cp2 = sbol2.ModuleDefinition(cp3.identity, version=self._sbol2_version(cp3)) + self.doc2.addModuleDefinition(cp2) + else: + # 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) + cp2.sequences = cp3.sequences + # 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: + feature2 = self.visit_sub_component(feature) raise NotImplementedError('Conversion of Component features from SBOL3 to SBOL2 not yet implemented') if cp3.interactions: - raise NotImplementedError('Conversion of Component interactions from SBOL3 to SBOL2 not yet implemented') + for interaction3 in cp3.interactions: + interaction2 = self.visit_interaction(interaction3) + cp2.interactions.add(interaction2) if cp3.constraints: raise NotImplementedError('Conversion of Component constraints from SBOL3 to SBOL2 not yet implemented') if cp3.interface: @@ -210,9 +223,16 @@ def visit_implementation(self, imp3: sbol3.Implementation): # Map over all other TopLevel properties and extensions not covered by the constructor self._convert_toplevel(imp3, imp2) - def visit_interaction(self, a: sbol3.Interaction): - # Priority: 2 - raise NotImplementedError('Conversion of Interaction from SBOL3 to SBOL2 not yet implemented') + def visit_interaction(self, interaction3: sbol3.Interaction) -> sbol2.Interaction: + interaction2 = sbol2.Interaction(interaction3.identity, version=self._sbol2_version(interaction3), interaction_type=interaction3.types) + for p in interaction3.participations: + part2 = self.visit_participation(p) + interaction2.participations.add(part2) + for m in interaction3.measures: + interaction2.measurements.add(self.visit_measure(m)) + self._convert_identified(interaction3, interaction2) + + return interaction2 def visit_interface(self, a: sbol3.Interface): # Priority: 3 @@ -230,9 +250,15 @@ def visit_model(self, a: sbol3.Model): # Priority: 3 raise NotImplementedError('Conversion of Model from SBOL3 to SBOL2 not yet implemented') - def visit_participation(self, a: sbol3.Participation): - # Priority: 2 - raise NotImplementedError('Conversion of Participation from SBOL3 to SBOL2 not yet implemented') + def visit_participation(self, participation3: sbol3.Participation) -> sbol2.Participation: + participation2 = sbol2.Participation( + version=self._sbol2_version(participation3), + participant=participation3.participant + ) + for role in participation3.roles: + participation2.addRole(role) + self._convert_identified(participation3, participation2) + return participation2 def visit_plan(self, a: sbol3.Plan): # Priority: 3 @@ -406,7 +432,7 @@ def visit_component_definition(self, cd2: sbol2.ComponentDefinition): sbol2.BIOPAX_COMPLEX: sbol3.SBO_NON_COVALENT_COMPLEX} types3 = [type_map.get(t, t) for t in cd2.types] # Make the Component object and add it to the document - cp3 = sbol3.Component(cd2.identity, types3, namespace=self._sbol3_namespace(cd2), + cp3 = sbol3.Component(cd2.persistentIdentity, types3, namespace=self._sbol3_namespace(cd2), roles=cd2.roles, sequences=cd2.sequences) self.doc3.add(cp3) # Convert the Component properties not covered by the constructor @@ -468,9 +494,9 @@ def visit_experimental_data(self, a: sbol2.ExperimentalData): # Priority: 3 raise NotImplementedError('Conversion of ExperimentalData from SBOL2 to SBOL3 not yet implemented') - def visit_functional_component(self, a: sbol2.FunctionalComponent): - # Priority: 3 - raise NotImplementedError('Conversion of FunctionalComponent from SBOL2 to SBOL3 not yet implemented') + def visit_functional_component(self, fc2: sbol2.FunctionalComponent) -> sbol3.SubComponent: + # TODO: store identity + return sbol3.SubComponent(fc2.definition) def visit_generic_location(self, a: sbol2.GenericLocation): # Priority: 3 @@ -484,9 +510,15 @@ def visit_implementation(self, imp2: sbol2.Implementation): # Map over all other TopLevel properties and extensions not covered by the constructor self._convert_toplevel(imp2, imp3) - def visit_interaction(self, a: sbol2.Interaction): - # Priority: 2 - raise NotImplementedError('Conversion of Interaction from SBOL2 to SBOL3 not yet implemented') + def visit_interaction(self, interaction2: sbol2.Interaction) -> sbol3.Interaction: + + interaction3 = sbol3.Interaction( + types=interaction2.types, + participations=[self.visit_participation(p) for p in interaction2.participations], + measures=[self.visit_measure(m) for m in interaction2.measurements] + ) + self._convert_identified(interaction2, interaction3) + return interaction3 def visit_maps_to(self, a: sbol2.mapsto.MapsTo): # Priority: 3 @@ -504,13 +536,27 @@ 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): - # Priority: 3 - raise NotImplementedError('Conversion of ModuleDefinition from SBOL2 to SBOL3 not yet implemented') + def visit_module_definition(self, md2: sbol2.ModuleDefinition): + + # Make the Component object and add it to the document + interactions = [self.visit_interaction(i) for i in md2.interactions] + functional_components = [self.visit_functional_component(fc) for fc in md2.functionalComponents] + cp3 = sbol3.Component(md2.persistentIdentity, types=sbol3.SBO_FUNCTIONAL_ENTITY, namespace=self._sbol3_namespace(md2), + roles=md2.roles, interactions=interactions) + self.doc3.add(cp3) + cp3.features.extend(functional_components) + # Map over all other TopLevel properties and extensions not covered by the constructor + self._convert_toplevel(md2, cp3) + + + def visit_participation(self, participation2: sbol2.Participation) -> sbol3.Participation: + participation3 = sbol3.Participation( + roles=participation2.roles, + participant=participation2.participant + ) + self._convert_identified(participation2, participation3) + return participation3 - def visit_participation(self, a: sbol2.Participation): - # Priority: 2 - raise NotImplementedError('Conversion of Participation from SBOL2 to SBOL3 not yet implemented') def visit_plan(self, a: sbol2.Plan): # Priority: 3