SynBioDex / pySBOL2

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

Adding components to collections #384

Closed IsabelMarleen closed 4 years ago

IsabelMarleen commented 4 years ago

There does not seem to be a function to add ComponentDefinitions to collections. I was able to create new collections using doc.collections.create() but could not interact with the new collections in any way. I was also hoping for clarification on the addCollection() function as the input required is an sbol object so it cannot be used to create a new collection, but if this is the intended way to add components to existing collections, it lacks a way to specify which collection the sbol objects should be added to.

I would highly appreciate clarification on how these functions are supposed to be used and how I can add components to collections without running into uniqueness errors, because the components are already part of the document.

IsabelMarleen commented 4 years ago

This example code hopefully shows what I am trying to achieve and what I mean. Adding the component using addCollection only adds it to the general document and not the collection specifically as can be seen in the resulting SBOL file.

doc = Document()
GFP = ComponentDefinition("GFP")
collection = doc.collections.create("collection")
doc.addCollection(GFP)
doc.write("Test_Collections.xml")
1 collection 1 GFP
tcmitchell commented 4 years ago

Here is a tweaked version of your program:

import sbol2

doc = sbol2.Document()
GFP = sbol2.ComponentDefinition("GFP")
doc.add(GFP)
collection = doc.collections.create("collection")
collection.members = [GFP.identity]
doc.write("Test_Collections.xml")

That program produces the following result:

<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:sbol="http://sbols.org/v2#">
  <sbol:ComponentDefinition rdf:about="http://examples.org/ComponentDefinition/GFP/1">
    <sbol:type rdf:resource="http://www.biopax.org/release/biopax-level3.owl#DnaRegion"/>
    <sbol:displayId>GFP</sbol:displayId>
    <sbol:version>1</sbol:version>
    <sbol:persistentIdentity rdf:resource="http://examples.org/ComponentDefinition/GFP"/>
  </sbol:ComponentDefinition>
  <sbol:Collection rdf:about="http://examples.org/Collection/collection/1">
    <sbol:version>1</sbol:version>
    <sbol:persistentIdentity rdf:resource="http://examples.org/Collection/collection"/>
    <sbol:member rdf:resource="http://examples.org/ComponentDefinition/GFP/1"/>
    <sbol:displayId>collection</sbol:displayId>
  </sbol:Collection>
</rdf:RDF>

I figured out that I had to use the members property on the Collection by looking at the SBOL 2.3 specification. A Collection has a single property, called members, that refers to TopLevel entities.

There is no error checking here, and the implementation is possibly incorrect because it accepts any URI instead of constraining to URI's of other objects in a document, or even URIs that refer to TopLevel objects. And note that I had to add the ComponentDefinition to the Document separately. I guess my summary is: use with care.

Document.addCollection is a synonym for Document.add and is intended to add a Collection object to a Document. It is not intended to add an entity to a Collection, as you have already discovered. As a synonym, no error checking is done on the passed argument. The Document.addCollection exists for backward compatibility with pySBOL.

tcmitchell commented 4 years ago

And thanks very much for the sample program and output. It was very helpful in formulating my answer.

IsabelMarleen commented 4 years ago

@tcmitchell Thank you for your answer, this is exactly what I was looking for. I had looked at the members property before, but couldn't quite figure it out.