LIBSBML Developer's Manual


Ben Bornstein

bornstei@cds.caltech.edu

The SBML Team
Control and Dynamical Systems, MC 107-81
California Institute of Technology, Pasadena, CA 91125, USA
http://www.sbml.org/

6 October 2004

LIBSBML Version 2.2.0



This and other projects of the SBML Team are supported by the following organizations: the National Institutes of Health (USA); the International Joint Research Program of NEDO (Japan); the JST ERATO-SORST Program (Japan); the Japanese Ministry of Agriculture; the Japanese Ministry of Education, Culture, Sports, Science and Technology; the BBSRC e-Science Initiative (UK); the DARPA IPTO Bio-Computation Program (USA); the Army Research Office's Institute for Collaborative Biotechnologies (USA); the Air Force Office of Scientific Research (USA); the California Institute of Technology (USA); the University of Hertfordshire (UK); the Molecular Sciences Institute (USA); and the Systems Biology Institute (Japan).



Contents


1 Quick Start

LIBSBML requires a separate XML library for low-level XML tokenizing and Unicode support. It currently supports the Xerces-C++ and Expat XML libraries on Linux, Windows, MacOS X and Solaris. Many Linux systems provide one or both of these libraries either as part of their standard distribution or as an optional RPM, Debian or Mandrake package. For more information, see http://xml.apache.org/xerces-c/ for Xerces and http://expat.sf.net for Expat.

1.1 Linux, MacOS X and Solaris

If you have obtained the source code distribution of LIBSBML, then at your Linux, MacOS X or Solaris command prompt, unpack the distribution, cd into the directory created as a result (e.g., libsbml-2.1.0/), and type the following command to configure LIBSBML for your system:

  ./configure

To specify Expat explicitly rather than the LIBSBML default of Xerces, use a command such as the following instead (and make sure to read about the limitations surrounding the use of Expat explained in Section 3):

  ./configure --with-expat

By default, LIBSBML only builds the C and C++ API library. If you want to configure LIBSBML to build the Java, Python, Lisp and/or MATLAB API libraries as well, add the flags -with-java, -with-python, -with-lisp, and/or -with-matlab to the configure command. For example,

  ./configure --with-expat --with-java --with-python

Next, compile and install the LIBSBML library using the following command:

  make
  make install

To compile programs that use LIBSBML with GCC (for an example, see Section 5.1):

  gcc -o myapp.c myapp.c -lsbml

Note: A Perl binding is available but is not yet hooked into the configuration system. See the file bindings/perl/README.txt for information about building and installing the Perl bindings

1.2 Windows

Unzip the LIBSBML distribution and open the resulting folder (which will have a name such as libsbml-2.1.0-expat or libsbml-2.1.0-xerces). There are debug (libsbmld) and release (libsbml) versions of LIBSBML, with .dll and .lib files for both versions in the win32 subdirectory of the LIBSBML distribution. Header files are located in the subdirectory src/sbml.

Users of Visual C++ should make their Visual C++ projects link with the files libsbml.lib or libsbmld.lib and generate code for the Multithreaded DLL or Debug Multithreaded DLL version of the VC++ runtime, respectively.


2 Introduction

This manual describes LIBSBML, a application programming interface (API) library for reading, writing and manipulating the Systems Biology Markup Language (SBML; Finney and Hucka, 2003; Hucka et al., 2001,2003). Currently, the library supports all of SBML Level 1 Version 1 and Version 2, and nearly all of SBML Level 2 Version 1. (The still-unimplemented parts of Level 2 are: support for RDF, and support for MathML's semantics, annotation and annotation-xml elements. These will be implemented in the near future.) For more information about SBML, please see the references or visit http://www.sbml.org/ on the Internet. LIBSBML is entirely open-source under the terms of the GNU LGPL, and all source code and other materials are freely and publicly available.

Some of the features of LIBSBML include:

A companion document (Bornstein, 2004) provides a detailed reference manual for the API.


3 Detailed Instructions for Configuring and Installing the Library

The LIBSBML distributions can be downloaded from the SBML project area on SourceForge.net, at http://sf.net/projects/sbml. A link to the download area is also provided on the SBML project home page, http://www.sbml.org.

Before you can build and use LIBSBML, you must first make sure you have on your system an XML library for low-level XML tokenizing and Unicode support. Currently, LIBSBML can use either Apache's Xerces-C++ XML library or James Clark's Expat XML library on Linux, Windows, MacOS X and Solaris. Many systems provide one or both of these libraries either as part of their standard distribution or as an optional RPM or Debian package. For Windows, DLL and LIB file distributions are available for both Xerces and Expat. For more information, see the following:

Note that if you use Expat instead of Xerces, LIBSBML will not be able to validate SBML input against the XML Schema for SBML because Expat is not a validating XML parser. Xerces is currently the only validating parser library usable with LIBSBML. The implication of this is that when using Expat, some syntactic errors in SBML inputs may go undetected; examples include identifiers not using the correct character set, and missing required attributes. (However, the LIBSBML consistency checks described in Section 8 can still be performed.) The tradeoff is that Expat may be faster than Xerces at parsing large models.

Unless instructed otherwise, the LIBSBML build process will default to using Xerces. A good way to determine whether Xerces-C++ is installed on your system is to run the configuration command (see below); it will halt if it cannot find the Xerces-C++ library. You can provide the configuration command with a flag telling it to use Expat instead of Xerces and you can indicate where the libraries are located if they are not in standard locations on your system.

3.1 Instructions for Linux, MacOS X and Solaris

3.1.1 Configuring LIBSBML

After obtaining, uncompressing and unpacking the LIBSBML distribution, configure the package by typing the following command at your Linux, MacOS X or Solaris command prompt:

  ./configure

To specify Expat explicitly rather than the LIBSBML default of Xerces, use a command such as the following instead:

  ./configure --with-expat

If either Expat or Xerces is installed in a non-standard location on your computer system (e.g., a home directory), configure will not be able to detect it. In this case, configure needs to be told explicitly where to find the libraries. Use the following forms:

  ./configure --with-expat="DIR"
or
  ./configure --with-xerces="DIR"

where DIR is the parent directory of where the include and lib directories of Xerces or Expat (whichever one you are trying to use) is located. For example, on MacOS X, if you used Fink to install Expat in Fink's default software tree, you would configure LIBSBML using the following:

  ./configure --with-xerces="/sw"

During the installation phase (i.e., during make install, discussed below), the default LIBSBML installation commands will copy header files to /usr/local/include/sbml, the (shared and static) library files to /usr/local/lib, and documentation files in various formats to /usr/local/share/doc/libsbml-version, by default. To specify a different installation location, use the -prefix argument to configure. For example,

  ./configure --prefix="/my/favorite/path"

Of course, you can combine the flags to configure, giving both -prefix and -with-expat or -with-xerces to set both options. The LIBSBML configuration command also supports a number of other options described below.

3.1.2 Building and Installing LIBSBML

Once configured, building should be very easy. Simply execute the following commands at your Linux, MacOS X or Solaris command prompt:

  make
  make install

Note that you will probably have to perform the make install command as the user 'root' on your system if you used the default installation directory (/usr/local) or you set -prefix to a system directory that only root is permitted to write into.

Finally, on most platforms, you will also need to either run the command ldconfig as user 'root' (consult the man page for ldconfig if this is unfamiliar), or else set the environment variable LD_LIBRARY_PATH in your terminal shell window. (On MacOS X, the variable is named DYLD_LIBRARY_PATH.) If you do not do this, attempts to run other programs that were linked with the LIBSBML library will probably fail with errors about being unable to find the library.

If all went as it should, LIBSBML should end up compiled and installed on your system, in either the default location (/usr/local/) or in the location you indicated during the configuration step.

3.1.3 Additional Options: Interfaces to Java, Python, Lisp and MATLAB

LIBSBML includes language bindings for Java, Python, Common Lisp and MATLAB, enabling you to write Java, Python, Lisp and MATLAB programs that call LIBSBML methods, and work with LIBSBML through Python's, Lisp's and MATLAB's interactive modes. Short tutorials for how to use these facilities are available in the directory docs/formatted.

To enable the library extensions for Java, Python, Lisp and MATLAB, you need to supply additional options to configure. These options are -with-java, -with-python, -with-lisp, and -with-matlab. As with other configure options, these three take an optional prefix argument; for example,

  ./configure --with-java="DIR"

If you want to build multiple language bindings for LIBSBML, combine multiple flags together as in the following example:

  ./configure --with-java --with-python

The LIBSBML distribution ships with certain interface files provided, so that you do not need to have the software necessary to recreate them. However, if you obtained the LIBSBML distribution from CVS or want to recreate the files deliberately, you will need need SWIG, the Simplified Wrapper and Interface Generator. More information about SWIG is available from http://www.swig.org. At this time, LIBSBML is known to work only with version 1.3.21 of SWIG; earlier versions are known not to work and the newest versions have not yet been tested. To tell configure to enable the use of SWIG to regenerate the interface files, use the -with-swig option to configure. If your copy of SWIG is installed in a non-standard location, you can specify it on the configure command line like this:

  ./configure --with-swig="DIR"

As with Expat and Xerces, the /sw directory is what you would specify if you were running on MacOS X and you used Fink to install SWIG, Python, etc.

3.1.4 Additional Options: Unit Testing

LIBSBML provides built-in facilities for testing itself. To run the unit tests, a second library is required, libcheck. Check is a very lightweight C unit test framework based on the xUnit framework popularized by Kent Beck and eXtreme Programming. Check is quite small and once installed, it consists of only two files: libcheck.a and check.h. To download Check, visit http://check.sf.net/. Note: Debian users can find Check as a standard add-on package (.deb). MacOS X users can find and install Check using the Fink system.

To enable the unit testing facilities in LIBSBML, add the -with-check flag during configuration:

  ./configure --with-check

Following this, you must build LIBSBML and then you can run the tests:

  make
  make check

The make check step is optional and will build and run an extensive suite of unit tests to verify all facets of the library. These tests are meant primarily for developers of LIBSBML and running them is not required for the library to function properly. All tests should pass with no failures or errors. If for some reason this is not the case on your system, please submit a bug report using the facilities at http://www.sf.net/projects/sbml.

3.1.5 Additional Options: Memory Tracing

In addition to the unit tests, a custom memory tracing facility is available. It is disabled by default and must be enabled explicitly at build time, either as an argument to configure:

  ./configure --enable-memory-tracing

or, in your own projects, by defining the C preprocessor symbol TRACE_MEMORY:

  #define TRACE_MEMORY

With memory tracing turned on, every piece of memory in both the library and all test suites is tracked. At the end of the test run, statistics are printed on total memory allocations, deallocations and leaks. The memory statistics for the test suites should report zero leaks. If for some reason this is not the case, please submit a report at http://www.sf.net/projects/sbml.

For performance reasons, memory tracing should be disabled in production environments. It is disabled by default in LIBSBML, but if enabled it, you can reconfigure and disable it as follows:

  ./configure --disable-memory-tracing

After doing this, make sure to rebuild and reinstall the LIBSBML library.

3.2 Instructions for Microsoft Windows

The Windows distributions of LIBSBML come in the form of both precompiled binaries (with a self-extracting installer), and source code. The precompiled binaries come ready-to-use and only need to be installed. The source distribution is a .zip file containing the LIBSBML code that must be extracted in a directory on your system, compiled and installed.

As mentioned above, LIBSBML requires that either the Xerces-C or Expat XML parsing libraries be available on your computer prior to attempting to compile LIBSBML. (See the beginning of this section for tips on obtaining these packages.) The DLL for Xerces or Expat must be placed in the win32/bin subdirectory of the LIBSBML directory.

The following are the steps for using Visual Studio to compile LIBSBML under Windows:

  1. In Visual Studio 7, open the file win32/libsbml.vcproj located in the LIBSBML directory. In Visual Studio 6, the file is win32/libsbml.dsw.

  2. Select the ``Options'' item out of the ``Tools'' pull-down menu, and select ``Projects/Directories'' (in VS7) or click the ``Directories'' tab (in VS6). The screen for indicating which directories contain project-relevant files will then be displayed.

  3. For ``Show Directories For:'', select ``Include Files''. Add the win32/include directory from the LIBSBML directory if it is not already shown.

  4. For ``Show Directories For:'', select ``Library Files''. Add the win32/bin directory from the LIBSBML directory if it is not already shown. (This is the directory were you should place the DLLs for Xerces or Expat.)

  5. Select the ``Rebuild All'' option from the ``Build'' pull-down menu in Visual Studio.


4 SBML Classes in C

The SBML specification, with its UML diagrams, suggests an object-oriented (OO) design. An API for interacting with SBML would do well to use an object-oriented programming (OOP) style to lower the inevitable impedance mismatch between specification and implementation. Unfortunately, the C programming language was not designed with OOP in mind and therefore does not support many object-oriented concepts. It is possible, however, to construct a minimal object-like system in C with few, if any, drawbacks. For these reasons, the LIBSBML API mimics an object-oriented programming style.

The particular OOP-like style used by LIBSBML is not revolutionary. In fact, it is quite common and comprised of only a few simple stylistic conventions:

  1. SBML classes are represented as C structs with a typedef shorthand. The shorthand form is derived by appending _t to the name of the SBML class, e.g., Model becomes Model_t.

  2. C ``objects'' are nothing more than pointers to specific C structs in memory. These pointers, instead of the structs themselves, are passed to and returned from ``methods'' (functions).

  3. Functions meant to represent methods of (or messages to) an object are named beginning with the SBML class, followed by an underscore and ending in the method name. The functions take the object (pointer to struct) receiving the method as their first argument. For example, the function prototype for the addCompartment() method of a Model is:

        void Model_addCompartment(Model_t *m, Compartment_t *c);
    

  4. Constructor and destructor names are similar to method names, but end in _create() and _free(), respectively.

Every SBML class defined in the specification has a corresponding C class (see Table 1). The two SBML enumeration types, UnitKind and RuleType are represented as C enumerations, but deviate slightly from the rules above (see Section 4.5). Finally, there is one class, SBMLDocument_t, that exists in the LIBSBML API, but not in SBML Level 1 (though the equivalent exists in Level 2). It serves as a top-level container for models and stores warnings and error messages encountered when an SBML document was read (see Section 5).

The methods for SBML classes are declared in header files that correspond to the class name (e.g., Model.h). To include all methods for all classes in one fell swoop, #include SBMLTypes.h.


Table: SBML classes and enumerations and their corresponding C class. Italicized classes are abstract, which sets their C implementation slightly apart from the others. See Section 4.6 for more information.
SBML Class C Class (typedef struct)
SBase SBase_t
Model Model_t
FunctionDefinition FunctionDefinition_t
UnitDefinition UnitDefinition_t
Unit Unit_t
Compartment Compartment_t
Parameter Parameter_t
Species Species_t
Reaction Reaction_t
SpeciesReference SpeciesReference_t
ModifierSpeciesReference ModifierSpeciesReference_t
SimpleSpeciesReference SimpleSpeciesReference_t
KineticLaw KineticLaw_t
Rule Rule_t
AssignmentRule AssignmentRule_t
RateRule RateRule_t
AlgebraicRule AlgebraicRule_t
CompartmentVolumeRule CompartmentVolumeRule_t
ParameterRule ParameterRule_t
SpeciesConcentrationRule SpeciesConcentrationRule_t
Event Event_t
EventAssignment EventAssignment_t

SBML Enumeration

C Enumeration (typedef enum)
UnitKind UnitKind_t
RuleType RuleType_t


4.1 Primitive Types

The mapping from SBML primitive types to C is straightforward, as an example will help illustrate. A Species has at least one attribute of every primitive type defined by SBML. Figure 1 shows the UML definition for Species and the corresponding C struct side-by-side. The similarity between the two demonstrates the mapping rules for primitive types:

  1. In all cases, the form of UML attribute names, including their capitalization, are preserved (e.g., initialAmount) when mapped to C struct fields. The names of getters and setters (see below) reflect these names.

  2. SName (in SBML Level 1) and SId (in SBML Level 2) are mapped to standard C strings (pointers to arrays of char terminated by a NULL or 0 character; e.g., char *name). Note that the syntax of SName and SId is not yet enforced in the API.

  3. SBML types double and integer are mapped to C double and int respectively.

  4. Boolean is mapped to C int, where zero represents false and non-zero represents true.

Figure: Example: the definition of SBML's Species in UML (left) and the corresponding Species_t C struct (right) in LIBSBML. SBASE_FIELDS is part of the OOP-like style used to implement objects in C; it is a macro that expands into the fields defined by SBase. The use of a union for amount and concentration reflects that these two fields are mutually exclusive in the SBML Species definition.
\includegraphics[scale=0.67]{graphics/species}
typedef struct
{
  SBASE_FIELDS;
  char   *id;
  char   *name;
  char   *compartment;
  union
  {
    double Amount;
    double Concentration;
  } initial;
  char   *substanceUnits;
  char   *spatialSizeUnits;
  int     hasOnlySubstanceUnits;
  int     boundaryCondition;
  int     charge;
  int     constant;
} Species_t;

4.2 Object Creation and Destruction

This section and subsequent ones focus on functions or methods to create, destroy and otherwise manipulate SBML C objects. Since all functions and methods follow the same naming convention, when discussing them generically, XXX will be used to stand for some class name and YYY some class attribute.

To instantiate (create) an object use either the XXX_create() or XXX_createWith() constructor. To destroy (free) an object use XXX_free().

To give a concrete example, the following are the constructors and destructors for SBML's Species objects. (The complete list of API methods for Species_t and other data objects in LIBSBML is available in the LIBSBML API Reference Manual.)


\begin{methoddef}{Species\_t *Species\_create (void)}
Creates a new Species and returns a pointer to it.
\end{methoddef}


\begin{methoddef}{Species\_t *Species\_createWith (const char *name,
const char...
... id); Species_setCompartment(s, compartment); ...;\end{cVerbatim}\end{methoddef}


\begin{methoddef}{void Species\_free (Species\_t *s)}
Frees the given Species.
\end{methoddef}

The XXX_createWith() constructors are a convenient way both to create SBML objects and initialize many of their attributes in a single operation. If XXX_create() is used instead, only attributes with default values (as defined by the SBML specification) will be set. All other attributes will be marked as not having been set.

When an SBML object is destroyed with XXX_free(), all of its strings are freed (see Section 4.3 for more information) and all of its contained objects are freed (see Section 4.4 for more information).


4.3 Accessing Fields

Accessing fields in data structures is accomplished using functions that offer interfaces to getting and setting the values of the fields. The generic form of these is discussed in this section. To give concrete examples, we repeatedly use the SBML Species class of objects.

4.3.1 Getters

The getter methods follow the naming convention XXX_getYYY(). To give a concrete example, here are the getters for Species_t:


\begin{methoddef}{const char * Species\_getId (const Species\_t *s)}
Returns the \attrib{id} field of this Species.
\end{methoddef}


\begin{methoddef}{const char * Species\_getName (const Species\_t *s)}
Returns the \attrib{name} field of this Species.
\end{methoddef}


\begin{methoddef}{const char * Species\_getCompartment (const Species\_t *s)}
Returns the \attrib{compartment} field of this Species.
\end{methoddef}


\begin{methoddef}{double Species\_getInitialAmount (const Species\_t *s)}
Returns the \attrib{initialAmount} field of this Species.
\end{methoddef}


\begin{methoddef}{double Species\_getInitialConcentration (const Species\_t *s)}
Returns the \attrib{initialConcentration} field of this Species.
\end{methoddef}


\begin{methoddef}{const char * Species\_getSubstanceUnits (const Species\_t *s)}
Returns the \attrib{substanceUnits} field of this Species.
\end{methoddef}


\begin{methoddef}{const char * Species\_getSpatialSizeUnits (const Species\_t *s)}
Returns the \attrib{spatialSizeUnits} field of this Species.
\end{methoddef}


\begin{methoddef}{const char * Species\_getUnits (const Species\_t *s)}
Returns the \attrib{units} field of this Species (SBML Level~1 only).
\end{methoddef}


\begin{methoddef}{int Species\_getHasOnlySubstanceUnits (const Species\_t *s)}
...
...sOnlySubstanceUnits}
field is true, false (\code{0}) otherwise.
\end{methoddef}


\begin{methoddef}{int Species\_getBoundaryCondition (const Species\_t *s)}
Returns the \attrib{boundaryCondition} field of this Species.
\end{methoddef}


\begin{methoddef}{int Species\_getCharge (const Species\_t *s)}
Returns the \attrib{charge} field of this Species.
\end{methoddef}


\begin{methoddef}{int Species\_getConstant (const Species\_t *s)}
Returns true ...
...-zero) if this Species is constant, false (\code{0})
otherwise.
\end{methoddef}

Notice the Species_t passed to each getter is constant. The purpose of this constness is twofold: (1) it reinforces the notion that a getter simply returns a value and does not modify the state of the passed-in object and (2) as a result, in certain contexts a compiler may be able to use this information to perform certain optimizations. Notice also, whenever a getter returns a string, it is constant (const char *); i.e., it cannot be modified or freed. The reason for this is each struct tracks and owns all of its internal memory. To modify (or especially free) this memory without using one of the sanctioned access methods could be particularly disasterous (most likely resulting in a segmentation or general protection fault). Memory management issues are elaborated in the discussion of setters in the next section.

Figure 2 provides an example of using getters.

Figure 2: Demonstrates accessing the fields of an SBML Level 2 object (in this case, Species_t) using getter methods.
\begin{figure}\begin{boxedCodeVerbatim}/**
* Prints some basic information a...
...t id: %s\n'', comp != NULL ? comp : none);
}\end{boxedCodeVerbatim} \end{figure}

4.3.2 Setters

A value is assigned to a field via a set method. Requiring all assignments to be done using setter methods allows LIBSBML to track (and the developer to query) the set or unset state of a field apart from its actual value. The need to distinguish between state and value is critical and is discussed further in Section 4.3.3. (Earlier versions of LIBSBML allowed primitive types to be set directly; however, direct access made it impossible to distinguish between set and unset states of a field, since all possible values are valid--no sentinel value exists to indicate an unset state.)

The setter methods follow the naming convention XXX_setYYY(). The setters for Species_t are:


\begin{methoddef}{void Species\_setId (Species\_t *s, const char *sid)}
Sets the \attrib{id} field of this Species to a copy of \code{sid}.
\end{methoddef}


\begin{methoddef}{void Species\_setName (Species\_t *s, const char *string)}
Se...
... \code{string}
(which must be conform to \class{SName} syntax).
\end{methoddef}


\begin{methoddef}{void Species\_setCompartment (Species\_t *s, const char *sid)}...
...rib{compartment} field of this Species to a copy of
\code{sid}.
\end{methoddef}


\begin{methoddef}{void Species\_setInitialAmount (Species\_t *s, double value)}
...
...s the
\attrib{initialConentration} field of the Species object.
\end{methoddef}


\begin{methoddef}{void Species\_setInitialConcentration (Species\_t *s, double v...
... set. This method also unsets the
\attrib{initialAmount} field.
\end{methoddef}


\begin{methoddef}{void Species\_setSubstanceUnits (Species\_t *s, const char *si...
...b{substanceUnits} field of this Species to a copy of \code{sid}.
\end{methoddef}


\begin{methoddef}{void Species\_setSpatialSizeUnits (Species\_t *s, const char *...
...spatialSizeUnits} field of this Species to a copy of \code{sid}.
\end{methoddef}


\begin{methoddef}{void Species\_setUnits (Species\_t *s, const char *sname)}
Se...
...its} field of this Species to a copy of \code{sname}
(L1 only).
\end{methoddef}


\begin{methoddef}{void Species\_setHasOnlySubstanceUnits (Species\_t *s, int val...
...ubstanceUnits} field of this Species to
\code{value} (boolean).
\end{methoddef}


\begin{methoddef}{void Species\_setBoundaryCondition (Species\_t *s, int value)}...
...daryCondition} field of this Species to \code{value}
(boolean).
\end{methoddef}


\begin{methoddef}{void Species\_setCharge (Species\_t *s, int value)}
Sets the ...
...eld of this Species to \code{value} and marks the
field as set.
\end{methoddef}


\begin{methoddef}{void Species\_setConstant (Species\_t *s, int value)}
Sets th...
...ttrib{constant} field of this Species to \code{value} (boolean).
\end{methoddef}

In the case of strings, requiring setter methods also enables clean and simple memory semantics. The rule is: every SBML object is responsible for its own memory, including SId and SName strings. Whenever a set method is called, the passed-in string is copied and stored. If the field being set previously contained a string, it is freed. When XXX_free() is called, all strings are freed.

For example, to set the compartment of a Species object stored in variable s to the string "cell", you could do the following:

  Species_setCompartment(s, "cell");

The effect of passing a NULL pointer as the string argument is to free the previously stored string and mark the field as unset. The preferred method for doing this, however, is to use the XXX_unsetYYY() class of methods (see Section 4.3.3).


4.3.3 Field States

For each optional field without a default value, LIBSBML tracks both its state and value. The state of a field indicates whether the field is set (contains a valid value) or unset (contains no value at all). As mentioned before, the distinction between a set and unset field is critical for both LIBSBML and applications that depend upon it to function correctly (in accordance with the SBML specifications).

Take, for example, the case of outputting SBML for a species. The SBML Species object has an optional field named charge with no defined default value. Because it's optional, it need not ever be read in (specified), written or manipulated. It may not have a value for a given species in a given model. Upon writing out the definition of the species in a model, LIBSBML must be able to determine whether the field has ever been set in order to know whether to output or omit the field while writing the model.

To determine whether a particular field in a structure is set or unset, calling programs should use LIBSBML's XXX_isSetYYY() class of methods. For Species_t, the following are available:


\begin{methoddef}{int Species\_isSetId (const Species\_t *s)}
Returns \code{1} ...
...rib{id} field of this Species has been set,
\code{0} otherwise.
\end{methoddef}


\begin{methoddef}{int Species\_isSetName (const Species\_t *s)}
Returns \code{1...
...evel~2, the name is optional and as such may or
may not be set.
\end{methoddef}


\begin{methoddef}{int Species\_isSetCompartment (const Species\_t *s)}
Returns ...
...rtment} field of this Species has
been set, \code{0} otherwise.
\end{methoddef}


\begin{methoddef}{int Species\_isSetInitialAmount (const Species\_t *s)}
Return...
...unt} field value is optional and as such may or may not
be set.
\end{methoddef}


\begin{methoddef}{int Species\_isSetInitialConcentration (const Species\_t *s)}
...
...oncentration} of this Species has
been set, \code{0} otherwise.
\end{methoddef}


\begin{methoddef}{int Species\_isSetSubstanceUnits (const Species\_t *s)}
Retur...
...bstanceUnits} of this Species has been set,
\code{0} otherwise.
\end{methoddef}


\begin{methoddef}{int Species\_isSetSpatialSizeUnits (const Species\_t *s)}
Ret...
...ialSizeUnits} of this Species has been set,
\code{0} otherwise.
\end{methoddef}


\begin{methoddef}{int Species\_isSetUnits (const Species\_t *s)}
Returns \code{...
...s Species has been set, \code{0}
otherwise (SBML Level~1 only).
\end{methoddef}


\begin{methoddef}{int Species\_isSetCharge (const Species\_t *s)}
Returns \code...
...ttrib{charge} of this Species has been set, \code{0}
otherwise.
\end{methoddef}

Fields with default values do not have a isSetYYY() method. If the value for such a field is never supplied by an SBML document or user, the default is used. Therefore, if an isSetYYY() method did exist, it would always return true (1).

Required fields, on the other hand, do have isSetYYY() methods. There are two points worth mentioning here. First, it is possible that a value for a required field is not given and a program may want to check for and handle this case (especially if the program is an SBML validator). Second, please be aware that in the transition from SBML Level 1 to Level 2, some fields changed from being required to being optional. If this is the case for a particular field, the documentation for the corresponding isSetYYY() will state it (as above).

Just as fields may be set and their set state queried, they may also be unset. Unset methods are named (predictably) XXX_unsetYYY(). The methods for unsetting fields in Species are:


\begin{methoddef}{void Species\_unsetName (Species\_t *s)}
Unsets the \attrib{n...
...2, \attrib{name} is optional and
as such may or may not be set.
\end{methoddef}


\begin{methoddef}{void Species\_unsetInitialAmount (Species\_t *s)}
Unsets the ...
...ib{initialAmount} is optional and as such may or may not be set.
\end{methoddef}


\begin{methoddef}{void Species\_unsetInitialConcentration (Species\_t *s)}
Unsets the \attrib{initialConcentration} field of this Species.
\end{methoddef}


\begin{methoddef}{void Species\_unsetSubstanceUnits (Species\_t *s)}
Unsets the \attrib{substanceUnits} field of this Species.
\end{methoddef}


\begin{methoddef}{void Species\_unsetSpatialSizeUnits (Species\_t *s)}
Unsets the \attrib{spatialSizeUnits} field of this Species.
\end{methoddef}


\begin{methoddef}{void Species\_unsetUnits (Species\_t *s)}
Unsets the \attrib{units} field of this Species (Level~1 only).
\end{methoddef}


\begin{methoddef}{void Species\_unsetCharge (Species\_t *s)}
Unsets the \attrib{charge} field of this Species.
\end{methoddef}

Again, for the reason mentioned above, fields with default values do not have unsetYYY() methods. Similarly, required fields have unsetYYY() methods only if they are declared optional in at least one of SBML Level 1 and Level 2. Notice, for example, there is an isSetCompartment() method but no corresponding unsetCompartment() (because a compartment is required for a Species in both SBML Level 1 and Level 2).


4.4 Lists

The Species class of object only contains fields having types SId, SName and primitive types, but many SBML classes also contain lists of other objects. For example, a UnitDefinition contains a list of Units, as shown in Figure 3.

Figure 3: SBML Level 2's UnitDefinition and Unit.
\includegraphics[scale=0.68]{graphics/unitdefinition}

To help manage this containment relationship, three standard functions are provided by LIBSBML: XXX_addYYY(), XXX_getYYY() and XXX_getNumYYY(). For example, the methods for UnitDefinition are:


\begin{methoddef}{void UnitDefinition\_addUnit (UnitDefinition\_t *ud,
Unit\_t *u)}
Adds the given Unit to this UnitDefinition.
\end{methoddef}


\begin{methoddef}{Unit\_t *UnitDefinition\_getUnit (const UnitDefinition\_t
*ud, unsigned int n)}
Returns the nth Unit of this UnitDefinition.
\end{methoddef}


\begin{methoddef}{unsigned int UnitDefinition\_getNumUnits (const
UnitDefinition\_t *ud)}
Return the number of Units in this UnitDefinition.
\end{methoddef}

Furthering the example, creating the UnitDefinition mmol/l/s with an identifer of ``mmls'', corresponding to the following SBML,

  <listOfUnitDefinitions>
    <unitDefinition id="mmls">
      <listOfUnits>
        <unit kind="mole"   scale="-3"/>
        <unit kind="litre"  exponent="-1"/>
        <unit kind="second" exponent="-1"/>
      </listOfUnits>
    </unitDefinition>
  </listOfUnitDefinitions>

could be accomplished with the following C:

  UnitDefinition_t *ud = UnitDefinition_createWith("mmls");

  UnitDefinition_addUnit(ud, Unit_createWith(UNIT_KIND_MOLE  ,  1, -3) );
  UnitDefinition_addUnit(ud, Unit_createWith(UNIT_KIND_LITRE , -1,  0) );
  UnitDefinition_addUnit(ud, Unit_createWith(UNIT_KIND_SECOND, -1,  0) );

List items are numbered starting at zero. For the case above, UnitDefinition_getNumUnits(ud) would return 3 and UnitDefinition_getUnit(ud, 1) would return the second Unit structure. (The UNIT_KIND_XXX enumerations are discussed later.)

Related to lists is a set of convenience methods for creating and adding SBML objects to a Model object in a single operation. The rationale is that since a Model is the top-level container for all other SBML objects, programmers are likely to have handles to them. Another way to construct the above UnitDefinition_t object, but this time inside a Model_t, is:

  Model_t            *m  = Model_createWith("MyModel");
  UnitDefinition_t   *ud = Model_createUnitDefinition(m);

  UnitDefinition_setName(ud, "mmls");

  Model_createUnit(m, Unit_createWith(UNIT_KIND_MOLE  ,  1, -3) );
  Model_createUnit(m, Unit_createWith(UNIT_KIND_LITRE , -1,  0) );
  Model_createUnit(m, Unit_createWith(UNIT_KIND_SECOND, -1,  0) );

Model_createUnit() creates a new Unit inside the Model m and returns a pointer to it (in this case the result is discarded). The Unit_t is added to the last UnitDefinition_t created. One caveat to be aware of with these methods is the case where no intermediate container exists; e.g., if no UnitDefinition_t were created above. In that case, the call to Model_createUnit() does nothing. More specifically, no Unit_t is created, nothing is added to the model, and NULL is returned.

For more detailed information on lists in LIBSBML and the ListOf_t utility type provided in the library, see Appendix A.


4.5 Enumerations

SBML has two enumeration types, UnitKind and RuleType (the latter only for SBML Level 1). These translate directly to C enums with a few support functions for equality testing and converting to and from strings.

  typedef enum
  {
      UNIT_KIND_AMPERE
    , UNIT_KIND_BECQUEREL
  
     /* Omitted for space */
  
    , UNIT_KIND_WEBER
    , UNIT_KIND_INVALID
  } UnitKind_t;

The following are the methods available for UnitKind:


\begin{methoddef}{int UnitKind\_equals (UnitKind\_t uk1, UnitKind\_t uk2)}
Test...
...uk1 is logically equivalent to uk2, false
(\code{0}) otherwise.
\end{methoddef}


\begin{methoddef}{UnitKind\_t UnitKind\_forName (const char *name)}
Returns the UnitKind with the given name (case-insensitive).
\end{methoddef}


\begin{methoddef}{const char *UnitKind\_toString (UnitKind\_t uk)}
Returns the ...
... the
returned string and is therefore not allowed to modify it.
\end{methoddef}

The last item in the enumeration, UNIT_KIND_INVALID, is used whenever, as the name implies, the UnitKind is invalid or unknown. The corresponding string representation is ``(Invalid UnitKind)''. When a Unit is created, its kind field is initialized to UNIT_KIND_INVALID. Also, UnitKind_forName() will return UNIT_KIND_INVALID if the passed-in name does not match any known UnitKind.

The same ideas apply to RuleType, except there is no need for RuleType_equals(). See RuleType.h for more information.

Implementation Note: The internal table of UNIT_KIND_STRINGS is sorted alphabetically and UnitKind_t matches this sort order. Because of this, UnitKind_forName() is able to perform a binary search to find a matching name, making its complexity O(log(n)). That is, UnitKind_forName() is implemented efficiently.


4.6 Abstract Classes

The SBML specification defines three classes that have no representation apart from subclasses that specialize (inherit from) them. In OOP parlance, these types are termed abstract. The abstract SBML classes are listed in Table 2.


Table: Abstract SBML classes their corresponding C class. Although all classes are present in LIBSBML at the same time, some of the classes only have meaning for certain levels of SBML.


SBML Class C Class (typedef struct) SBML Level
SBase SBase_t all
Rule Rule_t all
AssignmentRule AssignmentRule_t Level 1
SimpleSpeciesReference SimpleSpeciesReference_t Level 2


The conventions for abstract classes in the LIBSBML API are similar to that of other classes with a few modifications and additions.

Since abstract classes cannot be created or destroyed directly, they have no XXX_create() or XXX_free() methods. Instead they have XXX_init() and XXX_clear() methods which subclasses use to initialize and free their memory, respectively. Users of the API do not need to worry about the create and free operations on these classes.


4.7 Fields Inherited from SBase

Every major structure in SBML is derived from an abstract base type called SBase. Figure 4 shows the pseudo-UML definition of SBase itself, while Figure 5 shows the overall inheritance hierarchy of SBML. In addition to the relationships shown in Figure 5, all substructures such as trigger on Event and the listOf lists in SBML are also derived from SBase.

Figure 4: The definition of SBase in SBML Level 2. See the SBML specifications for an explanation of the notation.
\includegraphics[scale = 0.7]{graphics/sbase}

Figure 5: A UML diagram of the inheritance hierarchy of major data types in SBML. Open arrows indicate inheritance, pointing from inheritors to their parents. In addition to these types, all substructures in SBML (including, for example, all the listOf lists) are also derived from SBase.
\includegraphics[scale = 0.7]{graphics/top-level}

The practical implication is that every class has methods for working with the metaid, notes and annotation fields. However, the methods to work with these fields in LIBSBML are generic:


\begin{methoddef}{const char * SBase\_getMetaId (const SBase\_t *sb)}
Returns the \attrib{metaid} field for this SBML object.
\end{methoddef}


\begin{methoddef}{const char * SBase\_getNotes (const SBase\_t *sb)}
Returns the \attrib{notes} field for this SBML object.
\end{methoddef}


\begin{methoddef}{const char * SBase\_getAnnotation (const SBase\_t *sb)}
Returns the \attrib{annotation} field for this SBML object.
\end{methoddef}


\begin{methoddef}{unsigned int SBase\_getColumn (const SBase\_t *sb)}
Returns the column number for this SBML object.
\end{methoddef}


\begin{methoddef}{unsigned int SBase\_getLine (const SBase\_t *sb)}
Returns the line number for this SBML object.
\end{methoddef}


\begin{methoddef}{int SBase\_isSetMetaId (const SBase\_t *sb)}
Returns \code{1}...
...{metaid} for this SBML object has been
set, \code{0} otherwise.
\end{methoddef}


\begin{methoddef}{int SBase\_isSetNotes (const SBase\_t *sb)}
Returns \code{1} ...
...b{notes} for this SBML object has been set,
\code{0} otherwise.
\end{methoddef}


\begin{methoddef}{int SBase\_isSetAnnotation (const SBase\_t *sb)}
Returns \cod...
...otation} for this SBML object has been
set, \code{0} otherwise.
\end{methoddef}


\begin{methoddef}{void SBase\_setMetaId (SBase\_t *sb, const char *metaid)}
Set...
...aid, the existing string is freed
before the new one is copied.
\end{methoddef}


\begin{methoddef}{void SBase\_setNotes (SBase\_t *sb, const char *notes)}
Sets ...
...tes, the existing string is freed before the new
one is copied.
\end{methoddef}


\begin{methoddef}{void SBase\_setAnnotation (SBase\_t *sb, const char *annotatio...
...ion, the existing string
is freed before the new one is copied.
\end{methoddef}


\begin{methoddef}{void SBase\_unsetMetaId (SBase\_t *sb)}
Unsets the metaid for this SBML object.
\end{methoddef}


\begin{methoddef}{void SBase\_unsetNotes (SBase\_t *sb)}
Unsets the notes for this SBML object.
\end{methoddef}


\begin{methoddef}{void SBase\_unsetAnnotation (SBase\_t *sb)}
Unsets the annotation for this SBML object.
\end{methoddef}

The first argument to these functions is, of course, an object of type SBase. Since Species inherits from SBase, i.e., Species_t is an SBase, it can be used as the first argument to these functions. Beware, however, that a cast is required. For example, to set the notes field of some Species held in variable s, cast the variable to type SBase_t:

  SBase_setNotes( (SBase_t *) s, "My Favorite Species" );

The same applies to all other SBML objects.

The LIBSBML library's handling of annotation elements merits further explanation. The method SBase_getAnnotation(), listed above, returns the entire annotation string attached to an SBML data object, including the opening <annotation> XML element. This is useful when reading SBML model files because it gives access to any XML namespaces defined on the annotation element. For example, if a model had the following on a structure,

  <annotation xmlns:mstb="http://www.sbml.org/2001/ns/matlab-sbmltoolbox">
    <mstb:timestamp>2004-May-13 10:30 PST</mstb:timestamp>
    <mstb:message>These are my annotations</mstb:message>
  </annotation>

then SBase_getAnnotation() would return all of the above as one string. (In other words, it would not return simply what is being the <annnotation> </annotation tags. Similarly, when creating/setting an annotation, programs should pass the entire annotation string including the opening <annotation> element to SBase_setAnnotation(). Here is an example C program setting the same annotation string as in the example above:

  const char *annotation =
      "<annotation xmlns:mstb=\"http://www.sbml.org/2001/ns/matlab-sbmltoolbox\">"
      "  <mstb:timestamp>2004-May-13 10:30 PST</mstb:timestamp>\n"
      "  <mstb:message>These are my annotations</mstb:message>\n"
      "</annotation>";
  
  SBase_setAnnotation(model, annotation);


4.8 Typecodes

Each SBML class has a typecode that is initialized when an object is instantiated. The typecode is a simple C enumeration, defined in SBMLTypeCodes.h (which is included by the main LIBSBML include file, SBMLTypes.h, so client code does not need to include it separately):

  /**
   * An enumeration of SBML Level 2 types to help identify SBML objects at runtime.
   * Abstract types do not have a typecode since they cannot be instantiated.
   */
  typedef enum
  {
      SBML_COMPARTMENT
    , SBML_DOCUMENT
    , SBML_EVENT
    , SBML_EVENT_ASSIGNMENT
    , SBML_FUNCTION_DEFINITION
    , SBML_KINETIC_LAW
    , SBML_LIST_OF
    , SBML_MODEL
    , SBML_PARAMETER
    , SBML_REACTION
    , SBML_SPECIES
    , SBML_SPECIES_REFERENCE
    , SBML_MODIFIER_SPECIES_REFERENCE
    , SBML_UNIT_DEFINITION
    , SBML_UNIT
    , SBML_ALGEBRAIC_RULE
    , SBML_ASSIGNMENT_RULE
    , SBML_RATE_RULE
    , SBML_SPECIES_CONCENTRATION_RULE
    , SBML_COMPARTMENT_VOLUME_RULE
    , SBML_PARAMETER_RULE
  } SBMLTypeCode_t;

The primary reason for the typecode is distinguish specific types of rules in a Model. A Model_t contains a list of rules, but a Rule_t in SBML Level 1 may be of one of four specific types: AlgebraicRule, SpeciesConcentrationRule, CompartmentVolumeRule and ParameterRule. Having a type code associated with each object allows calling programs to distinguish its type. Without type codes, it would be impossible.


5 Reading and Writing SBML Files

SBML may be read from a file or an in memory string into an SBMLDocument. LIBSBML defines two basic read functions:


\begin{methoddef}{SBMLDocument\_t *readSBML (const char *filename)}
Reads the S...
... file named by \variable{filename} and
returns a pointer to it.
\end{methoddef}


\begin{methoddef}{SBMLDocument\_t *readSBMLFromString (const char *xml)}
Reads ...
...rbatim}<?xml version='1.0' encoding='UTF-8'?>\end{xmlVerbatim}\end{methoddef}

These functions return a pointer to an SBMLDocument_t object. This object represents the whole SBML model; it corresponds to the Sbml class object in the SBML Level 2 specification, but does not have a direct correspondence in SBML Level 1. (But, it is created by LIBSBML no matter whether the model is Level 1 or Level 2.)

SBMLDocument_t in Level 2 is derived from SBase, so that it contains the usual SBase fields of metaid, notes and annotation, as well as two other fields defined by Sbml: level and version. The following methods provide access to information about the level and version of the SBML input:


\begin{methoddef}{unsigned int SBMLDocument\_getLevel (const SBMLDocument\_t *d)}
Returns the SBML level of this SBML document.
\end{methoddef}


\begin{methoddef}{unsigned int SBMLDocument\_getVersion (const SBMLDocument\_t *d)}
Returns the SBML version of this SBML document.
\end{methoddef}

Of course, the whole point of reading an SBML file or data stream is to get at the SBML model it contains. The following method allows access to the Model object within an SBML document:


\begin{methoddef}{Model\_t * SBMLDocument\_getModel (const SBMLDocument\_t *d)}
...
...s the Model associated with this \class{SBMLDocument\_t} object.
\end{methoddef}

LIBSBML stores warnings and error messages that may be encountered while parsing the XML input. Each warning or error is a ParseMessage_t object. To access the lists of diagnostic messages in an SBMLDocument_t object, use the following methods:


\begin{methoddef}{ParseMessage\_t *SBMLDocument\_getWarning
(SBMLDocument\_t *d,...
...SBMLDocument or \code{NULL} if \code{n > getNumWarnings() - 1}.
\end{methoddef}


\begin{methoddef}{ParseMessage\_t *SBMLDocument\_getError (SBMLDocument\_t *d,
u...
...
SBMLDocument or \code{NULL} if \code{n > getNumErrors() - 1}.
\end{methoddef}


\begin{methoddef}{ParseMessage\_t *SBMLDocument\_getFatal (SBMLDocument\_t *d,
u...
...
SBMLDocument or \code{NULL} if \code{n > getNumErrors() - 1}.
\end{methoddef}


\begin{methoddef}{unsigned int SBMLDocument\_getNumWarnings
(SBMLDocument\_t *d)...
...of warnings encountered during the parse of this
SBMLDocument.
\end{methoddef}


\begin{methoddef}{unsigned int SBMLDocument\_getNumErrors (SBMLDocument\_t *d)}
...
...r of errors encountered during the parse of this
SBMLDocument.
\end{methoddef}


\begin{methoddef}{unsigned int SBMLDocument\_getNumFatals (SBMLDocument\_t *d)}
...
...atal errors encountered during the parse of this
SBMLDocument.
\end{methoddef}


\begin{methoddef}{void SBMLDocument\_printWarnings (SBMLDocument\_t *d,
FILE *st...
...For example:\\
\code{SBMLDocument\_printWarnings(d, stdout)}.
\end{methoddef}


\begin{methoddef}{void SBMLDocument\_printErrors (SBMLDocument\_t *d,
FILE *stre...
.... For example:\\
\code{SBMLDocument\_printErrors(d, stdout)}.
\end{methoddef}


\begin{methoddef}{void SBMLDocument\_printFatals (SBMLDocument\_t *d,
FILE *stre...
.... For example:\\
\code{SBMLDocument\_printFatals(d, stdout)}.
\end{methoddef}

There are a few other methods defined by SBMLDocument_t, but their discussion is left to Section 7


5.1 A Simple Example of Reading SBML

The following example is included in the LIBSBML distribution as readSBML.c in the subdirectory examples. It is not compiled as part of the normal build process, but a Makefile is provided in the examples subdirectory that can be used to build readSBML.c and other examples. Once LIBSBML itself is installed, you should be able to compile the examples by simply typing the following command in the examples directory:

  make

The readSBML program takes a single command-line argument, the name of an SBML file, reads it into memory and reports some basic information about the file and any warnings or errors generated by LIBSBML while parsing the file. Here is an example of using it on some of the sample SBML files provided in the src/test-data subdirectory of the LIBSBML distribution. In this example, the current directory is assumed to be examples.

  ./readSBML ../src/test-data/l1v1-branch.xml
  ./readSBML ../src/test-data/l1v1-minimal.xml
  ./readSBML ../src/test-data/l1v1-rules.xml
  # etc...

The complete text of readSBML is shown in Figure 6.

Figure: The text of the program printSBML.c provided in the examples subdirectory of the LIBSBML distribution.
\begin{figure}\begin{boxedCodeVerbatim}...


5.2 XML Schema Validation

To have LIBSBML validate an SBML document against an SBML (XML) Schema when using a Schema-aware parser such as Xerces requires creating an SBMLReader object and setting the appropriate schema filename and validation level. The functions for doing this are:


\begin{methoddef}{SBMLReader\_t *SBMLReader\_create (void)}
Creates a new SBMLR...
...ALIDATION\_NONE})
and \texttt{schemaFilename} is \texttt{NULL}.
\end{methoddef}


\begin{methoddef}{void SBMLReader\_free (SBMLReader\_t *sr)}
Frees the given SBMLReader.
\end{methoddef}


\begin{methoddef}{void SBMLReader\_setSchemaFilenameL1v1 (SBMLReader\_t *sr, con...
...lative to the
directory containing the SBML file(s) to be read.
\end{methoddef}


\begin{methoddef}{void SBMLReader\_setSchemaFilenameL1v2 (SBMLReader\_t *sr, con...
...lative to the
directory containing the SBML file(s) to be read.
\end{methoddef}


\begin{methoddef}{void SBMLReader\_setSchemaFilenameL2v1 (SBMLReader\_t *sr, con...
...lative to the
directory containing the SBML file(s) to be read.
\end{methoddef}


\begin{methoddef}{void SBMLReader\_setSchemaValidationLevel (SBMLReader\_t *sr,
...
...intensive. Few users will be interested in
this.
\end{itemize}\end{methoddef}

Note that the SBMLReader_setXYZ methods above have no effect when using a parser such as Expat, because it is not a validating XML parser and the settings have no meaning for it.

Once an SBMLReader_t object has been created, two variants of the functions readSBML() and readSBMLFromString() previously discussed in Section 5 become available. These variants can be thought of as methods of the SBMLReader_t class:


\begin{methoddef}{SBMLDocument\_t *SBMLReader\_readSBML (SBMLReader\_t *sr,
cons...
... from the given \variable{filename} and returns a
pointer to it.
\end{methoddef}


\begin{methoddef}{SBMLDocument\_t *SBMLReader\_readSBMLFromString (SBMLReader\_t...
...rbatim}<?xml version='1.0' encoding='UTF-8'?>\end{xmlVerbatim}\end{methoddef}

Schema violations are reported in the SBMLDocument_t's list of ParseMessages_t, according to the principles discussed in Section 5.


5.3 Writing SBML Files

Writing SBML is, in the end, a very simple matter in LIBSBML. The library provides the following two methods for this purposes.


\begin{methoddef}{int writeSBML (SBMLDocument\_t *d, \\ const char *filename)}
...
... named by
\variable{filename} could not be opened for writing).
\end{methoddef}


\begin{methoddef}{char *writeSBMLToString (SBMLDocument\_t *d)}
Writes the give...
...free()}) when no longer needed. Returns \code{NULL} on
failure.
\end{methoddef}


6 Handling of Mathematical Formulas and MathML

LIBSBML can read and write MathML 2.0 (Ausbrooks et al., 2001) content in SBML documents and data streams, as well as translate between MathML and the text-string formulas used in SBML Level 1. This section describes the library's capabilities for handling MathML and mathematics.


6.1 Reading and Writing Formulas in Text-String Form

In SBML Level 1, mathematical formulas are expressed as text strings using a simple C-like syntax. In SBML Level 2, mathematical formulas are expressed in MathML syntax. LIBSBML helps calling programs smooth over this difference by providing an API that allows working with formulas in both text-string and MathML form, and to interconvert mathematical expressions between these forms (to the extent possible by the differences between SBML Levels 1 and 2.)

Formulas in LIBSBML are represented internally using Abstract Syntax Trees (ASTs). ASTs are described in detail in Appendix B. When LIBSBML reads an SBML model, it converts the expressions into ASTs and stores the ASTs in the corresponding data structures that have mathematical formulas (such as in an SBML KineticLaw). Thus, the KineticLaw_getMath() method, for example, returns a pointer to the root of an AST corresponding to the formula stored there.

Many software packages provide users with the ability to express formulas for such things as reaction rate expressions, and these packages' interfaces often let users type in the formulas directly as strings. LIBSBML provides two high-level functions for working with mathematical expressions in the form of strings: SBML_parseFormula() and SBML_formulaToString().


\begin{methoddef}{ASTNode\_t *SBML\_parseFormula (const char *formula)}
Parses ...
...tains a syntax error, this function returns \code{NULL} instead.
\end{methoddef}


\begin{methoddef}{char *SBML\_formulaToString (ASTNode\_t *tree)}
Returns a tex...
... and is responsible for freeing it when
it is no longer needed.
\end{methoddef}

Using these methods is easy. The following is a code fragment that illustrates calling the parser function repeatedly with different formula strings, taking the ASTs returned each time and handing them back to the formula generator and comparing the strings to make sure they matched. (This is not something a real application would ever need to do, but it does simply illustrate the use of these two methods.)

  const char *formulae[] =
  {
    "1",
    "2.1",
    "2.1e+10",
    "foo",
    "1 + foo",
    "1 + 2",
    "1 + 2 * 3",
    "(1 - 2) * 3",
    "1 + -2 / 3",
    "1 + -2e-100 / 3",
    "1 - -foo / 3",
    "2 * foo^bar + 3.1",
    "foo()",
    "foo(1)",
    "foo(1, bar)",
    "foo(1, bar, 2^-3)",
    ""
  };
  
  ASTNode_t *n;
  char      *s;
  int        i;
  
  for (i = 0; i < *formulae[i]; i++)
  {
    n = SBML_parseFormula( formulae[i] );  /* Convert string to AST */
    s = SBML_formulaToString(n);           /* Convert AST back to string */
  
    if ( strcmp(s, formulae[i]) != 0 ) 
    {
      printf("Formula '%s' parsed incorrectly\n", formulae[i] );
    }
  
    ASTNode_free(n);
    free(s);
  }

Section 6.4 describes some additional points that are worth knowing about the mathematical formula handling in LIBSBML. For example, Level 1 formula strings and Level 2 MathML expressions can be interconverted.


6.2 Reading Formulas in MathML Form: MathMLDocument_t and ASTs

There may arise situations in which an application needs to convert MathML directly into an AST. LIBSBML provides the utility function readMathMLFromString() for this purpose:


\begin{methoddef}{MathMLDocument\_t *readMathMLFromString (const char *xml)}
Re...
... a
\class{MathMLDocument\_t} object holding the tree structure.
\end{methoddef}

The object returned by readMathMLFromString() is a simple container for an AST. The class of this object, MathMLDocument, is not defined by the SBML language standard but is provided in LIBSBML as a utility class. MathMLDocument serves as a top-level container for XML documents containing only MathML; in some ways it mirrors the SBMLDocument class, which acts as a container for XML documents containing SBML. The definition of MathMLDocument_t is as follows:

  /**
   * The MathMLDocument
   */
  typedef struct
  {
    ASTNode_t *math;
  } MathMLDocument_t;

The following are the functions defined for the MathMLDocument class:


\begin{methoddef}{MathMLDocument\_t *MathMLDocument\_create ()}
Creates a \class{MathMLDocument\_t} object.
\end{methoddef}


\begin{methoddef}{void MathMLDocument\_free (MathMLDocument\_t *d)}
Frees the given \class{MathMLDocument\_t} object.
\end{methoddef}


\begin{methoddef}{ASTNode\_t *MathMLDocument\_getMath (const MathMLDocument\_t *...
...atical
formula stored in this \class{MathMLDocument\_t} object.
\end{methoddef}


\begin{methoddef}{int MathMLDocument\_isSetMath (const MathMLDocument\_t *d)}
R...
...e math of this MathMLDocument has been set, \code{0}
otherwise.
\end{methoddef}


\begin{methoddef}{void MathMLDocument\_setMath (MathMLDocument\_t *d, ASTNode\_t...
...)} will free the AST node (and any child
nodes attached to it).
\end{methoddef}

Note that because the content passed to readMathMLFromString() is handed to an XML parser, the string given as argument must be a complete XML (though not necessarily SBML) document. The following example illustrates the use of this function with a valid MathML input.

  MathMLDocument_t *doc;
  ASTNode_t          *ast;
  char               *result;
  
  const char* s = "<?xml version='1.0' encoding='UTF-8'?>"
                    "<math xmlns='http://www.w3.org/1998/Math/MathML'>"
                      "<apply><arccos/><ci> x </ci></apply>"
                    "</math>";
  
  doc    = readMathMLFromString(s);
  ast    = MathMLDocument_getMath(doc);

The code above would create an AST structure stored in the variable ast. This tree structure could then be inspected using the AST node methods described in Appendix B.

Finally, LIBSBML provides two utility methods for writing out MathML represented in ASTs. Both of the following take a MathMLDocument_t class object, convert the expression tree stored there, and write out the appropriate text in MathML syntax.


\begin{methoddef}{int writeMathML (MathMLDocument\_t *d, const char *filename)}
...
... for writing or the MathMLWriter character encoding is invalid).
\end{methoddef}


\begin{methoddef}{char * writeMathMLToString (MathMLDocument\_t *d)}
Writes the...
...{free()}) when no longer needed. Returns \code{NULL} on
failure
\end{methoddef}


6.3 Differences between SBML Level 1 Formulas and MathML

The text-string based mathematical formula syntax of SBML Level 1 is mostly compatible with the representation of formulas in MathML. A few differences exist in the names of predefined functions such as arccos. Table 3 gives the mapping between SBML Level 1 and Level 2 function names.


Table 3: Basic mathematical functions defined in SBML Levels 1 and 2. The underlined functions are different between the two levels of SBML.
SBML Level 1 SBML Level 2
abs abs
acos arccos
asin arcsin
atan arctan
ceil ceiling
cos cos
exp exp
floor floor
log ln
log10(x) log(10, x)
pow(x, y) power(x, y)
sqr(x) power(x, 2)
sqrt(x) root(2, x)
sin sin
tan tan



6.4 Additional Notes about the Handling of Mathematical Formulas

The LIBSBML formula parser has been carefully engineered so that transformations from MathML to infix string notation and back is possible with a minimum of disruption to the structure of the mathematical expression.

Figure 7 shows a simple program that, when run, takes a MathML string compiled into the program, converts it to an AST, converts that to an infix representation of the formula, compares it to the expected form of that formula, and finally translates that formula back to MathML and displays it. The output displayed on the terminal should have the same structure as the MathML it started with. The program is a simple example of using the various MathML and AST reading and writing methods, and shows that LIBSBML preserves the ordering and structure of the mathematical expressions.

Figure 7: Short program to translate MathML into a formula string and back.
\begin{figure}\begin{boxedCodeVerbatim}...

The string form produced by SBML_formulaToString() and written by writeMathMLToString() is in SBML Level 1 formula string syntax, a simple C-inspired infix notation defined in the SBML Level 1 specification Hucka et al. (2001). It can therefore be handed to a program that understands SBML Level 1 mathematical expressions, or used as part of a translation system. The LIBSBML distribution comes with an example program in the examples subdirectory called translateMath that implements an interactive command-line demonstration of translating infix formulas into MathML and vice-versa.

LIBSBML offers the ability to translate entire SBML Level 1 models to SBML Level 2, as explained below, and hopefully in the future will also provide the ability to translate a subset of Level 2 models to Level 1 (though this latter capability is not yet implemented).


7 Levels of SBML

At the time of this writing, there exist 3 flavors of SBML: Level 1 Versions 1 and 2, and SBML Level 2 Version 1. A software application may need to read and/or write any of these versions, depending on its purpose. LIBSBML provides support for all three definitions of SBML.

Along with the methods discussed in Section 5, the SBMLDocument_t object class also defines the following methods that impact how a model is written out:


\begin{methoddef}{void SBMLDocument\_setModel (SBMLDocument\_t *d, Model\_t *m)}...
...Any previously defined model in \variable{d} is unset and freed.
\end{methoddef}


\begin{methoddef}{void SBMLDocument\_setLevel (SBMLDocument\_t *d, unsigned int ...
...ument to \variable{level}. Valid levels
are currently 1 and 2.
\end{methoddef}


\begin{methoddef}{void SBMLDocument\_setVersion (SBMLDocument\_t *d, unsigned in...
... are currently 1 and 2 for SBML Level~1 and 1 for SBML
Level~2.
\end{methoddef}

Setting the level using SBMLDocument_setLevel() affects the possible fields and values available when setting and reading fields. Certain translations take place immediately upon changing levels. For example, if one starts with a Level 1 model and then calls SBMLDocument_setLevel() to set the level to 2, the model structure at that moment is translated internally so that such things as object names are converted to id's (which do not exist in Level 1).

Figure 8: The text of the example C program convertSBML.c.
\begin{figure}\begin{boxedCodeVerbatim}...

The C program listed in Figure 8 is provided in the LIBSBML distribution in the examples subdirectory. This command-line program takes two arguments: the name of an input file and the name of an output file. It then translates the SBML in the input file into SBML Level 2 and writes it out to the named output file. It may be surprising to see how short this program is.


8 Checking the Consistency of SBML Models

LIBSBML performs a certain amount of validation of SBML inputs at the time of parsing files and data streams. However, the checks performed are mostly syntactic in nature, based on the XML Schema for SBML (and as noted elsewhere, using this validation capability requires using an XML Schema-aware parser such as Xerces).

The LIBSBML library also implements more extensive semantic tests and consistency checks than those represented by the XML Schema for SBML. At the time of this writing, over 30 tests are implemented. Examples of these consistency checks include: testing that compartments' spatialSizeUnits fields are consistent with their spatialDimensions; testing that species with hasOnlySubstanceUnits set to true do not also have an initialConcentration; and others.

Consistency checking rules in LIBSBML (and indeed, in SBML in general) are still experimental; for this reason, the library does not perform them automatically. Calling programs must request consistency checking to be invoked explicitly by calling the following method.


\begin{methoddef}{unsigned int SBMLDocument\_checkConsistency (const SBMLDocumen...
...ged confusing
and has been deprecated in favor of the new name.
\end{methoddef}

Here is some additional information about the LIBSBML procedures for checking the consistency of an SBML model. The program contains an internal list of consistency checks. These checks are run sequentially when SBMLDocument_checkConsistency() is invoked. LIBSBML keeps track of every consistency check executed; if a check returns a negative value (i.e., a failure), it increments an internal counter and also logs an error message returned by the check. That error message is logged to the same list of error messages where XML Schema validation errors are stored (that is, the list kept in the SBMLDocument). The method SBMLDocument_checkConsistency() returns the count of checks failed, and the method SBMLDocument.getNumErrors() returns the length of the list on SBMLDocument.


9 Special Considerations and Known Issues

This section summarizes special considerations, known issues and caveats surrounding the use and behavior of LIBSBML.

9.1 Conformance to SBML

Currently, LIBSBML supports all of SBML Level 1 Version 1 and Version 2, and nearly all of SBML Level 2 Version 1. The still-unsupported parts of the Level 2 specification are:


9.2 Issues Related to XML Parsers

Using Expat prevents LIBSBML from performing XML Schema-based validation of SBML input. This removes a number of verification checks from the parsing stage and may cause unexpected behavior in the face of malformed or invalid SBML content. Here are some implications of not performing XML Schema validation:

Although it is poorly documented, SBML XML documents must use only the UTF-8 encoding. Parsing a non-UTF-8 document may fail unpredictably and this particular error may be difficult to diagnose, because it will happen in the underlying XML parser and not LIBSBML itself.


10 Acknowledgments

Thanks to Mike Hucka for updating and editing this manual for versions 2.0 and 2.1 of LIBSBML, for developing the look-and-feel and the LaTeX style used for this and other SBML-related manuals, and for developing the LaTeX2HTML macros used to create the HTML version.


A. Lists and ListOf_t

While list-based convenience methods (e.g., XXX_getNumYYY()) are provided for every class, it is possible to access and manipulate each list directly. All lists are themselves objects of type ListOf_t. The full set of list methods are:


\begin{methoddef}{unsigned int ListOf\_getNumItems (const ListOf\_t *lo)}
Returns the number of items in this list.
\end{methoddef}


\begin{methoddef}{void ListOf\_append (ListOf\_t *lo, void *item)}
Adds item to the end of this list.
\end{methoddef}


\begin{methoddef}{void * ListOf\_get (const ListOf\_t *lo, unsigned int n)}
Ret...
...f \code{n > ListOf\_getNumItems(list)},
it returns \code{NULL}.
\end{methoddef}


\begin{methoddef}{void ListOf\_prepend (ListOf\_t *lo, void *item)}
Adds item to the beginning of this \class{ListOf\_t} object.
\end{methoddef}


\begin{methoddef}{void * ListOf\_remove (ListOf\_t *lo, unsigned int n)}
Remove...
...f \code{n > ListOf\_getNumItems(list)}, it returns
\code{NULL}.
\end{methoddef}

Since UnitDefinitions maintains a list of Units, the UnitDefinition example presented in Section 4.4 could also be written as:

  UnitDefinition_t *ud = UnitDefinition_createWith("mmls");
  
  UnitDefinition_addUnit(ud, Unit_createWith(UNIT_KIND_MOLE  ,  1, -3) );
  UnitDefinition_addUnit(ud, Unit_createWith(UNIT_KIND_LITRE , -1,  0) );
  UnitDefinition_addUnit(ud, Unit_createWith(UNIT_KIND_SECOND, -1,  0) );

However, this approach is not the preferred one. The best reason to use specific XXX_getYYY() methods over the list API in LIBSBML is that the former are typed to specific items, whereas ListOf_get() returns a void pointer that must be cast to a specific type. Moreover, the code resulting from using the XXX_getYYY() methods is arguably more readable.

Although many specialized methods are available for accessing various data objects in SBML, the list API is necessary for accessing such things as the content of notes and annotation elements on SBML's listOf*** elements. In addition, the only way to remove an item from a list is to use the API directly.


B. Abstract Syntax Trees and ASTNode_t

Abstract Syntax Trees (ASTs) in LIBSBML are a simple data structure for storing mathematical expressions. For many applications, the details of ASTs are irrelevant because the applications can use the text-string based translation functions described in Sections 6.1 and 6.2. However, other applications do need to read and manipulate ASTs directly. This section describes LIBSBML's AST in detail so software authors can write code to work with them.

An AST node is a recursive structure containing a pointer to the node's value (e.g., a number or a symbol) and a list of children nodes. LIBSBML provides a number of methods for manipulating ASTNode_t objects, the full set of which is documented in the LIBSBML API Reference Manual. The following discussion only covers a subset of all the possible methods.

B..1 Methods for Manipulating AST Nodes

First, there is a set of methods for creating and manipulating LIBSBML AST nodes and their children structures:


\begin{methoddef}{ASTNode\_t * ASTNode\_create (void)}
Creates a new \class{AST...
...KNOWN} and should be set
to something else as soon as possible.
\end{methoddef}


\begin{methoddef}{void ASTNode\_free (ASTNode\_t *node)}
Frees the given \class{ASTNode\_t} including any child nodes.
\end{methoddef}


\begin{methoddef}{unsigned int ASTNode\_getNumChildren (const ASTNode\_t *node)}...
...of children of this AST node or 0 is this node has no
children.
\end{methoddef}


\begin{methoddef}{void ASTNode\_addChild (ASTNode\_t *node, ASTNode\_t *child)}
...
...of this AST node. Child nodes are added
in left-to-right order.
\end{methoddef}


\begin{methoddef}{void ASTNode\_prependChild (ASTNode\_t *node, ASTNode\_t *chil...
... AST node. This method adds child
nodes in right-to-left order.
\end{methoddef}


\begin{methoddef}{ASTNode\_t * ASTNode\_getChild (const ASTNode\_t *node, unsign...
...s no nth
child (n $>$\ \method{ASTNode\_getNumChildren()} - 1).
\end{methoddef}


\begin{methoddef}{ASTNode\_t * ASTNode\_getLeftChild (const ASTNode\_t *node)}
...
...ode. This is equivalent to
\method{ASTNode\_getChild(node, 0)};
\end{methoddef}


\begin{methoddef}{ASTNode\_t * ASTNode\_getRightChild (const ASTNode\_t *node)}
...
..._getChild(node, ASTNode_getNumChildren(node) - 1);\end{cVerbatim}\end{methoddef}


Table 4: The list of AST node types in the enumeration ASTNodeType_t.
AST_PLUS AST_FUNCTION_ARCCOTH AST_FUNCTION_POWER
AST_MINUS AST_FUNCTION_ARCCSC AST_FUNCTION_ROOT
AST_TIMES AST_FUNCTION_ARCCSCH AST_FUNCTION_SEC
AST_DIVIDE AST_FUNCTION_ARCSEC AST_FUNCTION_SECH
AST_POWER AST_FUNCTION_ARCSECH AST_FUNCTION_SIN
AST_INTEGER AST_FUNCTION_ARCSIN AST_FUNCTION_SINH
AST_REAL AST_FUNCTION_ARCSINH AST_FUNCTION_TAN
AST_REAL_E AST_FUNCTION_ARCTAN AST_FUNCTION_TANH
AST_RATIONAL AST_FUNCTION_ARCTANH AST_LOGICAL_AND
AST_NAME AST_FUNCTION_CEILING AST_LOGICAL_NOT
AST_NAME_DELAY AST_FUNCTION_COS AST_LOGICAL_OR
AST_NAME_TIME AST_FUNCTION_COSH AST_LOGICAL_XOR
AST_CONSTANT_E AST_FUNCTION_COT AST_RELATIONAL_EQ
AST_CONSTANT_FALSE AST_FUNCTION_COTH AST_RELATIONAL_GEQ
AST_CONSTANT_PI AST_FUNCTION_CSC AST_RELATIONAL_GT
AST_CONSTANT_TRUE AST_FUNCTION_CSCH AST_RELATIONAL_LEQ
AST_LAMBDA AST_FUNCTION_EXP AST_RELATIONAL_LT
AST_FUNCTION AST_FUNCTION_FACTORIAL AST_RELATIONAL_NEQ
AST_FUNCTION_ABS AST_FUNCTION_FLOOR AST_UNKNOWN
AST_FUNCTION_ARCCOS AST_FUNCTION_LN
AST_FUNCTION_ARCCOSH AST_FUNCTION_LOG
AST_FUNCTION_ARCCOT AST_FUNCTION_PIECEWISE


AST nodes are typed. The list of possible types is quite long, because it covers all the mathematical functions that are permitted in SBML. Table 4 shows the list of type names which are part of the enumeration ASTNodeType_t. Most of the names are hopefully fairly-self explanatory; e.g., AST_PLUS stands for the ``+'' operator, AST_REAL signifies a real number, etc. The following methods can be used to interrogate the type of a given AST node:


\begin{methoddef}{ASTNodeType\_t ASTNode\_getType (const ASTNode\_t *node)}
Returns the type of this AST node.
\end{methoddef}


\begin{methoddef}{int ASTNode\_isConstant (const ASTNode\_t *node)}
Returns tru...
...nt (true,
false, pi, exponentiale), false (\code{0}) otherwise.
\end{methoddef}


\begin{methoddef}{int ASTNode\_isFunction (const ASTNode\_t *node)}
Returns tru...
... to \code{tanh()}) or user-defined,
false (\code{0}) otherwise.
\end{methoddef}


\begin{methoddef}{int ASTNode\_isInteger (const ASTNode\_t *node)}
Returns true...
...de is of type \class{AST\_INTEGER}, false
(\code{0}) otherwise.
\end{methoddef}


\begin{methoddef}{int ASTNode\_isLambda (const ASTNode\_t *node)}
Returns true ...
...ode is of type \class{AST\_LAMBDA},
false (\code{0}) otherwise.
\end{methoddef}


\begin{methoddef}{int ASTNode\_isLog10 (const ASTNode\_t *node)}
Returns true (...
...ldren the first of which is an \class{AST\_INTEGER} equal to 10.
\end{methoddef}


\begin{methoddef}{int ASTNode\_isLogical (const ASTNode\_t *node)}
Returns true...
...gical operator
(and, or, not, xor), false (\code{0}) otherwise.
\end{methoddef}


\begin{methoddef}{int ASTNode\_isName (const ASTNode\_t *node)}
Returns true (n...
... the special symbols delay or time, false (\code{0})
otherwise.
\end{methoddef}


\begin{methoddef}{int ASTNode\_isNumber (const ASTNode\_t *node)}
Returns true ...
...ode)} \verb+\vert\vert+ \code{ASTNode\_isReal(node)}
\end{quote}\end{methoddef}


\begin{methoddef}{int ASTNode\_isOperator (const ASTNode\_t *node)}
Returns tru...
...verb\vert*\vert, \verb\vert/\vert and
\verb\vert^\vert (power).
\end{methoddef}


\begin{methoddef}{int ASTNode\_isRational (const ASTNode\_t *node)}
Returns tru...
...e is of type
\class{AST\_RATIONAL}, false (\code{0}) otherwise.
\end{methoddef}


\begin{methoddef}{int ASTNode\_isReal (const ASTNode\_t *node)}
Returns true (n...
...lass{AST\_REAL}, \class{AST\_REAL\_E} or
\class{AST\_RATIONAL}.
\end{methoddef}


\begin{methoddef}{int ASTNode\_isRelational (const ASTNode\_t *node)}
Returns t...
...erb\vert<\vert, \verb\vert!=\vert), false
(\code{0}) otherwise.
\end{methoddef}


\begin{methoddef}{int ASTNode\_isSqrt (const ASTNode\_t *node)}
Returns true (n...
...ildren the first of which is an \class{AST\_INTEGER} equal to 2.
\end{methoddef}


\begin{methoddef}{int ASTNode\_isUMinus (const ASTNode\_t *node)}
Returns true ...
... if it is of type
\class{AST\_MINUS} and has exactly one child.
\end{methoddef}


\begin{methoddef}{int ASTNode\_isUnknown (const ASTNode\_t *node)}
Returns true...
...de is of type \class{AST\_UNKNOWN},
false (\code{0}) otherwise.
\end{methoddef}

Programs manipulating AST node structures should check the type of a given node before calling methods that return a value from the node. The following meethods are available for returning values from nodes:


\begin{methoddef}{char ASTNode\_getCharacter (const ASTNode\_t *node)}
Returns ...
... \class{AST\_TIMES},
\class{AST\_DIVIDE} or \class{AST\_POWER}.
\end{methoddef}


\begin{methoddef}{long ASTNode\_getInteger (const ASTNode\_t *node)}
Returns th...
...d be called only when \code{ASTNode\_getType() == AST\_INTEGER}.
\end{methoddef}


\begin{methoddef}{const char * ASTNode\_getName (const ASTNode\_t *node)}
Retur...
...r numbers
(in which case, \code{ASTNode\_isNumber(node) == 0}).
\end{methoddef}


\begin{methoddef}{long ASTNode\_getNumerator (const ASTNode\_t *node)}
Returns ...
... be called only when \code{ASTNode\_getType() == AST\_RATIONAL}.
\end{methoddef}


\begin{methoddef}{long ASTNode\_getDenominator (const ASTNode\_t *node)}
Return...
... be called only when \code{ASTNode\_getType() == AST\_RATIONAL}.
\end{methoddef}


\begin{methoddef}{double ASTNode\_getReal (const ASTNode\_t *node)}
Returns the...
...t exponent) or \class{AST\_RATIONAL}
(numerator / denominator).
\end{methoddef}


\begin{methoddef}{double ASTNode\_getMantissa (const ASTNode\_t *node)}
Returns...
...REAL}, this method is identical to
\method{ASTNode\_getReal()}.
\end{methoddef}


\begin{methoddef}{long ASTNode\_getExponent (const ASTNode\_t *node)}
Returns t...
...TNode\_getType()} is \class{AST\_REAL\_E}
or \class{AST\_REAL}.
\end{methoddef}


\begin{methoddef}{int ASTNode\_getPrecedence (const ASTNode\_t *node)}
Returns ...
...nce of this AST node (as defined in the SBML L1
specification).
\end{methoddef}

Finally (and rather predictably), LIBSBML provides methods for setting the values of AST nodes.


\begin{methoddef}{void ASTNode\_setCharacter (ASTNode\_t *node, char value)}
Se...
... characters, the node type will be
set to \class{AST\_UNKNOWN}.
\end{methoddef}


\begin{methoddef}{void ASTNode\_setName (ASTNode\_t *node, const char *name)}
S...
...allows names to be set for
\class{AST\_FUNCTION}s and the like.
\end{methoddef}


\begin{methoddef}{void ASTNode\_setInteger (ASTNode\_t *node, long value)}
Sets...
... (long) integer and sets the
node type to \class{AST\_INTEGER}.
\end{methoddef}


\begin{methoddef}{void ASTNode\_setRational (ASTNode\_t *node, long numerator, l...
... and denominator. The node type is set to \class{AST\_RATIONAL}.
\end{methoddef}


\begin{methoddef}{void ASTNode\_setReal (ASTNode\_t *node, double value)}
Sets ...
...im}ASTNode_setRealWithExponent(node, value, 0);\end{cVerbatim}\end{methoddef}


\begin{methoddef}{void ASTNode\_setRealWithExponent (ASTNode\_t *node, double ma...
...and the exponent. The node type is set to
\class{AST\_REAL\_E}.
\end{methoddef}


\begin{methoddef}{void ASTNode\_setType (ASTNode\_t *node, ASTNodeType\_t type)}
Sets the type of this AST node to the given AST node type.
\end{methoddef}

B..2 Notes about ASTNode

The following are noteworthy about the AST node representation in LIBSBML:

Bibliography

Ausbrooks, R., Buswell, S., Dalmas, S., Devitt, S., Diaz, A., Hunter, R., Smith, B., Soiffer, N., Sutor, R., and Watt, S. (2001).
Mathematical markup language (MathML) version 2.0 (second edition) W3C recommendation 21 October 2003.

Bornstein, B. J. (2004).
LibSBML API reference manual.
Available on the Internet at http://www.sbml.org/software/libsbml.

Finney, A. M. and Hucka, M. (2003).
Systems biology markup language: Level 2 and beyond.
Biochemical Society Transactions, 31:1472-1473.

Hucka, M., Finney, A., Sauro, H. M., and Bolouri, H. (2001).
Systems biology markup language (sbml) level 1: Structures and facilities for basic model definitions.
Technical report.
Available on the Internet at http://www.sbml.org/.

Hucka, M., Finney, A., Sauro, H. M., Bolouri, H., Doyle, J. C., Kitano, H., Arkin, A. P., Bornstein, B. J., Bray, D., Cornish-Bowden, A., Cuellar, A. A., Dronov, S., Gilles, E. D., Ginkel, M., Gor, V., Goryanin, I. I., Hedley, W. J., Hodgman, T. C., Hofmeyr, J.-H., Hunter, P. J., Juty, N. S., Kasberger, J. L., Kremling, A., Kummer, U., Le Novre, N., Loew, L. M., Lucio, D., Mendes, P., Minch, E., Mjolsness, E. D., Nakayama, Y., Nelson, M. R., Nielsen, P. F., Sakurada, T., Schaff, J. C., Shapiro, B. E., Shimizu, T. S., Spence, H. D., Stelling, J., Takahashi, K., Tomita, M., Wagner, J., and Wang, J. (2003).
The systems biology markup language (sbml): A medium for representation and exchange of biochemical network models.
Bioinformatics, 19(4):524-531.

About this document ...

LIBSBML Developer's Manual

This document was generated using the LaTeX2HTML translator Version 2002 (1.62)

Copyright © 1993, 1994, 1995, 1996, Nikos Drakos, Computer Based Learning Unit, University of Leeds.
Copyright © 1997, 1998, 1999, Ross Moore, Mathematics Department, Macquarie University, Sydney.

The command line arguments were:
latex2html -white -split +0 -show_section_numbers -image_type gif -no_navigation -local_icons -discard -antialias -t 'libSBML 2.2.0 Developer's Manual' -mkdir -dir libsbml-manual libsbml-manual

The translation was initiated by on 2004-10-06


2004-10-06