sbmlteam / libsbml

LibSBML is a native library for reading, writing and manipulating files and data streams containing the Systems Biology Markup Language (SBML). It offers language bindings for C, C++, C#, Java, JavaScript, MATLAB, Perl, PHP, Python, R and Ruby.

Home Page:https://sbml.org/software/libsbml

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Possible issue with the .setAnnotation method (Python)?

woosubs opened this issue · comments

Hi, I was trying to set the annotation of a model.species instance from an SBML model, using the .setAnnotation method with the string below:

for_set_annotation

After this, I retrieved the annotation using .getAnnotationString to check whether it was successfully updated, and found below was returned:

from_get_annotation_string

So all the information exists, but the part between <rdf:Description> …. </rdf:Description> was duplicated except the nested content. It seemed weird, for example because the meta id was duplicated as well. Could you check this and let me know whether it is behaving correctly? I ran the methods on Jupiter Lab with Python version 3.9.15.

Thank you,
Woosub

Could you send us the complete example you were using? (or the sbml model (it is fine to have it reduced to just the element in question with the annotation). the setAnnotation function, replaces existing annotations.

I'm afraid we still have enough information (maybe attachments from your email reply did not get added to the github issue). Maybe you can manually attach them, or send a link to an online resource, so we can look at the issue. We need:

  • the python code you tried
  • the input sbml file and annotation string you tried to set.
  • ideally the result you hoped to get rather than the one you received.

thanks

Ok, through googling i found your Notebook. So looking at what happens here, is that setAnnotation does indeed unset the annotation first.

However, after setting the annotation that you provide, libsbml then goes ahead an parses the RDF provided. Since you use RDF that does not correspond to the subset that is described in the SBML specification this causes the issue that you see.

that will require a new version of COPASI, where setAnnotation gets an additional flag, whether to parse the annotations after setting it. You'd have to set it to false.

Note that while it is fine for you to use any RDF you'd like within SBML. Most tools wont be able to read the information that does not conform to the SBML subset. It might be better to use another annotation / RDF node to store these information in.

I'll make a PR, to handle the setAnnotation part. We might have to think about disabling processing the CVTerms during read as well. What do you think @skeating ?

just in case here the test case, requiring python-libsbml and copasi-basico:

import libsbml
import os

_TARGET_ANNOTATION = """
<annotation>
  <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:vcard4="http://www.w3.org/2006/vcard/ns#" xmlns:bqbiol="http://biomodels.net/biology-qualifiers/" xmlns:bqmodel="http://biomodels.net/model-qualifiers/">
    <rdf:Description rdf:about="#metaid_0000036">
      <bqbiol:is>
        <rdf:Bag>
          <rdf:li rdf:resource="http://identifiers.org/chebi/CHEBI:59789"/>
          <bqbiol:hasProperty>
            <rdf:Bag>
              <rdf:li rdf:resource="http://amas/match_score/by_name/1.0"/>
            </rdf:Bag>
          </bqbiol:hasProperty>
          <rdf:li rdf:resource="http://identifiers.org/chebi/CHEBI:15414"/>
          <bqbiol:hasProperty>
            <rdf:Bag>
              <rdf:li rdf:resource="http://amas/match_score/by_name/1.0"/>
            </rdf:Bag>
          </bqbiol:hasProperty>
        </rdf:Bag>
      </bqbiol:is>
    </rdf:Description>
  </rdf:RDF>
</annotation>
""".strip()


def main():
    if os.path.exists('bm190.xml'):
        with open('bm190.xml', 'r', encoding='utf8') as f:
            sbml = f.read()
    else:
        import basico.biomodels as bm
        sbml = bm.get_content_for_model(190)
        with open('bm190.xml', 'w', encoding='utf8') as f:
            f.write(sbml)

    doc = libsbml.readSBMLFromString(sbml)
    model = doc.getModel()
    one_s = model.getSpecies('SAM')

    one_s.setAnnotation(_TARGET_ANNOTATION)
    print(one_s.getAnnotationString())


if __name__ == '__main__':
    main()

yields:

<annotation>
  <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:vcard4="http://www.w3.org/2006/vcard/ns#" xmlns:bqbiol="http://biomodels.net/biology-qualifiers/" xmlns:bqmodel="http://biomodels.net/model-qualifiers/">
    <rdf:Description rdf:about="#metaid_0000036">
      <bqbiol:is>
        <rdf:Bag>
          <rdf:li rdf:resource="http://identifiers.org/chebi/CHEBI:59789"/>
          <rdf:li rdf:resource="http://identifiers.org/chebi/CHEBI:15414"/>
        </rdf:Bag>
      </bqbiol:is>
    </rdf:Description>
    <rdf:Description rdf:about="#metaid_0000036">
      <bqbiol:is>
        <rdf:Bag>
          <rdf:li rdf:resource="http://identifiers.org/chebi/CHEBI:59789"/>
          <bqbiol:hasProperty>
            <rdf:Bag>
              <rdf:li rdf:resource="http://amas/match_score/by_name/1.0"/>
            </rdf:Bag>
          </bqbiol:hasProperty>
          <rdf:li rdf:resource="http://identifiers.org/chebi/CHEBI:15414"/>
          <bqbiol:hasProperty>
            <rdf:Bag>
              <rdf:li rdf:resource="http://amas/match_score/by_name/1.0"/>
            </rdf:Bag>
          </bqbiol:hasProperty>
        </rdf:Bag>
      </bqbiol:is>
    </rdf:Description>
  </rdf:RDF>
</annotation>

with 2 instead of just the one rdf:Descriptions.

Is this sorted and can be closed ?

Closed. Thank you!