Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add SBMLNamespaces_addPackageNamespace{,s} functions to C API #235

Merged
merged 1 commit into from
Jul 15, 2022

Conversation

giordano
Copy link
Contributor

Description

Motivation and Context

Functions SBMLNamespaces::addPackageNamespace and SBMLNamespaces::addPackageNamespaces don't currently have counterparts in the C API. With this patch I was able to create an SBMLDocument_t with fbc package in SBML.jl (which only uses the C API).

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Change in documentation

Checklist:

  • I have updated all documentation necessary.
  • I have checked spelling in (new) comments.

Testing

  • Testing is done automatically and codecov shows test coverage
  • This cannot be tested automatically

@giordano
Copy link
Contributor Author

giordano commented Jun 10, 2022

However I'm having a problem, here is a pure C reproducer:

% cat test.c 
#include <stdio.h>
#include <sbml/SBMLNamespaces.h>
#include <sbml/SBMLDocument.h>

int main(void) {
    SBMLNamespaces_t *ns;
    SBMLDocument_t *doc;

    ns = SBMLNamespaces_create(3, 2);
    SBMLNamespaces_addPackageNamespace(ns, "fbc", 2, "");
    doc = SBMLDocument_createWithSBMLNamespaces(ns);
    printf("%s\n", writeSBMLToString(doc));

    SBMLDocument_free(doc);
    SBMLNamespaces_free(ns);

    return 0;
}
% ./test 
<?xml version="1.0" encoding="UTF-8"?>
<sbml xmlns="http://www.sbml.org/sbml/level3/version2/core" xmlns:fbc="http://www.sbml.org/sbml/level3/version1/fbc/version2" level="3" version="2"/>

I'm creating the namespace with level,version,package version = 3,2,2 but then I get sbml/level3/version1/fbc/version2 in the generated file. Am I doing something wrong?

@giordano
Copy link
Contributor Author

@exaexa pointed out this may be due to

const std::string&
FbcExtension::getURI(unsigned int sbmlLevel,
unsigned int sbmlVersion,
unsigned int pkgVersion) const
{
if (sbmlLevel == 3)
{
if (sbmlVersion == 1 || sbmlVersion == 2)
{
if (pkgVersion == 1)
{
return getXmlnsL3V1V1();
}
if (pkgVersion == 2)
{
return getXmlnsL3V1V2();
}
if (pkgVersion == 3)
{
return getXmlnsL3V1V3();
}
}
}
static std::string empty = "";
return empty;
}
which unconditionally returns L3V1*, whatever is the value of sbmlVersion. Is this intentional?

Copy link
Member

@skeating skeating left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Mose

The reason the fbc uri is always l3v1vx is because it hasnt been adapted to explicitly work with l3v2 (there are subtly changes).
It can be used in an l3v2 document but the released versions of fbc are l3v1v1 and l3v1v2 so you will get one of those. The header you got is correct and perfectly acceptable by code reading an l3v2 model and the fbc package

@giordano
Copy link
Contributor Author

giordano commented Jun 11, 2022

My problem was that trying to add gene products to an fbc plugin I was getting a LIBSBML_VERSION_MISMATCH error. Downgrading sbml level/version to SBMLNamespaces_create(3, 1) to match the level/version of the fbc package worked around the issue.

@exaexa
Copy link
Contributor

exaexa commented Jun 11, 2022

@skeating Hello! I'll rephrase the problem a bit: is there a way currently to create a L3V2 model with libsbml that contains FBC? So far everything we have tried has failed, and the downgrade to L3V1 is apparently what others also use (CobraPy in this case, which is anyway how we got the (semi-) working solution with namespaces).

Any guidance on how to do this properly would be great, because apparently there has to be the way -- e.g., SBML test suite contains sbml L3V2 + fbc L3V1V2 tests.

EDIT: References to hardcoded L3V1:

@skeating
Copy link
Member

skeating commented Jun 22, 2022

Sorry to have taken so long to look into this.

The following code
`
int main(int argc, char** argv)
{
/* get fbc registry entry */
SBMLExtension_t *sbmlext = SBMLExtensionRegistry_getExtension("fbc");

/* create the sbml namespaces object with fbc */
XMLNamespaces_t * fbc = XMLNamespaces_create();
XMLNamespaces_add(fbc, SBMLExtension_getURI(sbmlext, 3, 1, 2), "fbc");

SBMLNamespaces_t * sbmlns = SBMLNamespaces_create(3, 2);
SBMLNamespaces_addNamespaces(sbmlns, fbc);

/* create the document */
SBMLDocument_t * doc = SBMLDocument_createWithSBMLNamespaces(sbmlns);

/* set the fbc reqd attribute to false /
SBMLDocumentPlugin_t * docPlug = (SBMLDocumentPlugin_t
)(SBase_getPlugin((SBase_t*)(doc), "fbc"));
SBMLDocumentPlugin_setRequired(docPlug, 0);

// create the Model

Model_t * model = SBMLDocument_createModel(doc);
Model_setId(model, "model1");

// Get a SBasePlugin_t object plugged in the model object.

SBasePlugin_t * modelPlug = SBase_getPlugin((SBase_t *)(model), "fbc");

// set the fbc strict attribute
FbcModelPlugin_setStrict(modelPlug, 0);

// create the Compartment

Compartment_t * compartment = Model_createCompartment(model);
Compartment_setId(compartment, "compartment");
Compartment_setConstant(compartment, 1);
Compartment_setSize(compartment, 1);

// create the Species

Species_t * species = Model_createSpecies(model);
Species_setId(species, "Node1");
Species_setCompartment(species, "compartment");
Species_setBoundaryCondition(species, 0);
Species_setConstant(species, 0);
Species_setHasOnlySubstanceUnits(species, 0);

// create GeneProduct

GeneProduct_t *gp = GeneProduct_create(3, 1, 2);
GeneProduct_setId(gp, "geneP1");
GeneProduct_setLabel(gp, "label1");
GeneProduct_setAssociatedSpecies(gp, "Node1");

// add to model plugin
FbcModelPlugin_addGeneProduct(modelPlug, gp);

/* write the file */
std::cout << writeSBMLToString(doc);
}
`
gives the following xml

@skeating
Copy link
Member

skeating commented Jun 22, 2022

"

<?xml version="1.0" encoding="UTF-8"?>
<sbml xmlns="http://www.sbml.org/sbml/level3/version2/core" xmlns:fbc="http://www.sbml.org/sbml/level3/version1/fbc/version2" level="3" version="2" fbc:required="false">
  <model id="model1" fbc:strict="false">
    <listOfCompartments>
      <compartment id="compartment" size="1" constant="true"/>
    </listOfCompartments>
    <listOfSpecies>
      <species id="Node1" compartment="compartment" hasOnlySubstanceUnits="false" boundaryCondition="false" constant="false"/>
    </listOfSpecies>
    <fbc:listOfGeneProducts>
      <fbc:geneProduct fbc:id="geneP1" fbc:label="label1"/>
    </fbc:listOfGeneProducts>
  </model>
</sbml>

"

giordano added a commit to giordano/SBML.jl that referenced this pull request Jun 22, 2022
@giordano
Copy link
Contributor Author

Lovely, I ported your code to Julia at LCSB-BioCore/SBML.jl#143 and it's working great! Thanks a lot!!

BTW, this detour is unrelated to the PR, we just bumped into the above problem once we were able to call SBMLNamespaces_addPackageNamespace{,s} with the C API

giordano added a commit to giordano/SBML.jl that referenced this pull request Jun 22, 2022
@exaexa
Copy link
Contributor

exaexa commented Jun 22, 2022

wow, lovely. @skeating thanks a lot!

@fbergmann fbergmann merged commit 8344b88 into sbmlteam:development Jul 15, 2022
@giordano giordano deleted the mg/addpackagenamespace branch July 15, 2022 06:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants