SynBioDex / pySBOL2

A pure Python implementation of the SBOL standard.
Apache License 2.0
20 stars 6 forks source link

Functional Components #423

Closed JMante1 closed 2 years ago

JMante1 commented 2 years ago

There is something slightly odd happening here.

This does not throw an error but also doesn't provide the expected output.

doc = sbol2.Document()

fc1 = sbol2.FunctionalComponent("fc1")
fc2 = sbol2.FunctionalComponent("fc2")
cp1 = sbol2.ComponentDefinition("cp1")

doc.add(cp1)

fc2.definition = cp1

mod1 = sbol2.ModuleDefinition("mod1")
mod2 = sbol2.ModuleDefinition("mod2")

mod1.functionalComponents.add(fc1)
mod2.functionalComponents.add(fc1)

doc.add(mod1)
doc.add(mod2)

doc.write(file_path_out)

Whilst this throws an error:

doc = sbol2.Document()

fc1 = sbol2.FunctionalComponent("fc1")
fc2 = sbol2.FunctionalComponent("fc2")
cp1 = sbol2.ComponentDefinition("cp1")

doc.add(cp1)

fc2.definition = cp1

mod1 = sbol2.ModuleDefinition("mod1")
mod2 = sbol2.ModuleDefinition("mod2")

doc.add(mod1)
doc.add(mod2)

mod1.functionalComponents.add(fc1)
mod2.functionalComponents.add(fc1)

doc.write(file_path_out)
JMante1 commented 2 years ago

I am not sure if the issue is that functional components can't be referred to more than once. The error is: <SBOLErrorCode.SBOL_ERROR_URI_NOT_UNIQUE: 17>, 'Cannot update SBOL-compliant URI. An object with URI http://examples.org/ModuleDefinition/mod2/fc1/1 is already in the Document

bbartley commented 2 years ago

Yes, I believe that error indicates that you can't add the same object fc1 to more than one parent ModuleDefinition

JMante1 commented 2 years ago

It is interesting as the error seems to indicate a difficulty with the specific uri e.g. http://examples.org/ModuleDefinition/mod2/fc1/1 and http://examples.org/ModuleDefinition/mod1/fc1/1 would work. Is it an SBOL thing that you can't have repeated functional components?

bbartley commented 2 years ago

The error message is indirectly telling you that fc1 already has a parent and that you can't assign it to more that one parent. The error message is not as clear and direct as it should be.

When you add a child object to a parent, pySBOL automatically generates the URI of the child object. Once an object is assigned a URI, pySBOL prohibits you from changing the URI. So when you attempt to add that child object to a different parent, pySBOL tries to change the URI, hence the error message.

It's not an error specific to FunctionalComponents. It's that a child object (black diamond relationship in UML) cannot have more than one parent. This is different from a reference association(white diamond relationship) which may be what you are expecting.

JMante1 commented 2 years ago

Is it possible to keep a copy unlinked so I can add the sub properties only once? like a template fc?

bbartley commented 2 years ago

Yes, I believe so. I think sbol-utilities may have some convenience method for handling template copies. @tcmitchell or @jakebeal would know more about that. Regardless, I think you should be able to implement something like this for your specific use case.

tcmitchell commented 2 years ago

You could try the copy method and see if it works for your use case. I'm not sure it will, and it's worth a try. I have modified your erroring example to use copy:

doc = sbol2.Document()

fc1 = sbol2.FunctionalComponent("fc1")
fc2 = sbol2.FunctionalComponent("fc2")
cp1 = sbol2.ComponentDefinition("cp1")

doc.add(cp1)

fc2.definition = cp1

mod1 = sbol2.ModuleDefinition("mod1")
mod2 = sbol2.ModuleDefinition("mod2")

doc.add(mod1)
doc.add(mod2)

mod1.functionalComponents.add(fc1.copy())
mod2.functionalComponents.add(fc1.copy())

doc.write(file_path_out)

Please let us know if this works for you.

JMante1 commented 2 years ago

This works, thanks.