A definition of a unit used in an SBML model.
Units of measurement may be supplied in a number of contexts in an SBML model. The SBML unit definition facility uses two classes of objects, UnitDefinition_t and Unit_t. The approach to defining units in SBML is compositional; for example, meter second –2 is constructed by combining a Unit_t object representing meter with another Unit_t object representing second –2. The combination is wrapped inside a UnitDefinition_t, which provides for assigning an identifier and optional name to the combination. The identifier can then be referenced from elsewhere in a model. Thus, the UnitDefinition_t class is the container, and Unit_t instances are placed inside UnitDefinition_t instances.
Two points are worth discussing in the context of SBML units. First, unit declarations in SBML models are optional. The consequence of this is that a model must be numerically self-consistent independently of unit declarations, for the benefit of software tools that cannot interpret or manipulate units. Unit_t declarations in SBML are thus more akin to a type of annotation; they can indicate intentions, and can be used by model readers for checking the consistency of the model, labeling simulation output, etc., but any transformations of values implied by different units must be incorporated explicitly into a model.
Second, the vast majority of situations that require new SBML unit definitions involve simple multiplicative combinations of base units and factors. An example is moles per litre per second. What distinguishes these sorts of unit definitions from more complex ones is that they may be expressed without the use of an additive offset from a zero point. The use of offsets complicates all unit definition systems, yet in the domain of SBML, the real-life cases requiring offsets are few (and in fact, to the best of our knowledge, only involve temperature). Consequently, the SBML unit system has been consciously designed to simplify implementation of unit support for the most common cases in systems biology. The cost of this simplification is to require units with offsets to be handled explicitly by the modeler.
Summary of the UnitDefinition_t construct
UnitDefinition_t has two attributes and one subelement. The two attributes are "id" and "name", and the subelement is ListOfUnits_t.
The required attribute "id" and optional attribute "name" are both strings. The "id" attribute is used to give the defined unit a unique identifier by which other parts of an SBML model definition can refer to it. The "name" attribute is intended to be used for giving the unit definition an optional human-readable name. Please see the next section for information about the values permitted for "id".
A UnitDefinition_t may contain exactly one ListOfUnits_t, and this list may contain one or more Unit_t definitions; see the definitions of these other object classes for more information about them. In SBML Level 2 and SBML Level 3 Version 1, if the ListOfUnits_t was present, it must have one or more Unit_t definitions. In SBML Level 3 Version 2, this restriction was relaxed, and a ListOfUnits_t was allowed to be empty. In either case, if a UnitDefinition_t had no child Unit_t elements, the unit was considered to be undefined.
The following example illustrates a complete unit definition (when written in XML) when all the pieces are combined together. This defines "mmls" to be millimoles per litre per second.
<listOfUnitDefinitions>
<unitDefinition id="mmls">
<listOfUnits>
<unit kind="mole" scale="-3"/>
<unit kind="litre" exponent="-1"/>
<unit kind="second" exponent="-1"/>
</listOfUnits>
</unitDefinition>
</listOfUnitDefinitions>
Special considerations for Unit_t object identifiers
The attribute "id" in UnitDefinition_t cannot be given simply any value, and the precise details of the values permitted differ slightly between Levels of SBML:
-
The "id" of a UnitDefinition_t must not contain a value from the list of SBML's predefined base unit names (i.e., the strings gram
, litre
, etc.). In SBML Level 3, this list consists of the following:
ampere | farad | joule | lux | radian | volt |
avogadro | gram | katal | metre | second | watt |
becquerel | gray | kelvin | mole | siemens | weber |
candela | henry | kilogram | newton | sievert |
coulomb | hertz | litre | ohm | steradian |
dimensionless | item | lumen | pascal | tesla |
This list of predefined base units is nearly identical in SBML Level 2 Version 4, the exception being that Level 2 does not define avogadro
. SBML Level 2 Version 1 (and only this Level+Version combination) provides an additional predefined unit name, Celsius
, not available in Level 3. Finally, SBML Level 1 Versions 2–3 provide two more additional predefined unit names, meter
and liter
. This is explained in somewhat greater detail in the description of the Unit_t class.
-
In SBML Level 2 (all Versions), there is an additional set of reserved identifiers:
substance
, volume
, area
, length
, and time
. Using one of these values for the attribute "id" of a UnitDefinition_t has the effect of redefining the model-wide default units for the corresponding quantities. The list of special unit names in SBML Level 2 is given in the table below:
Identifier |
Possible scalable units |
Default units |
substance | mole, item, gram, kilogram, dimensionless | mole |
volume | litre, cubic metre, dimensionless | litre |
area | square metre, dimensionless | square metre |
length | metre, dimensionless | metre |
time | second, dimensionless | second |
Also, SBML Level 2 imposes two limitations on redefining the predefined unit substance
, volume
, area
, length
, and time:
(1) The UnitDefinition_t of a predefined SBML unit can only contain a single Unit_t object within it. (2) The value of the "kind" attribute in a Unit_t instance must be drawn from one of the values in the second column of the table above.
The special unit names substance
, volume
, area
, length
, and time
are not defined by SBML Level 3, which uses a different approach to setting model-wide inherited units.
Further comments about SBML's unit definition system
The vast majority of modeling situations requiring new SBML unit definitions involve simple multiplicative combinations of base units and factors. An example of this might be moles per litre per second. What distinguishes these sorts of simpler unit definitions from more complex ones is that they may be expressed without the use of an additive offset from a zero point. The use of offsets complicates all unit definition systems, yet in the domain of SBML the real-life cases requiring offsets are few (and in fact, to the best of our knowledge, only involve temperature). Consequently, the SBML unit system has been consciously designed in a way that attempts to simplify implementation of unit support for the most common cases in systems biology.
As of SBML Level 2 Version 2, Unit_t no longer has the attribute called "offset" introduced in SBML Level 2 Version 1. It turned out that the general case involving units with offsets was incorrectly defined, and few (if any) developers even attempted to support offset-based units in their software. In the development of Level 2 Version 2, a consensus among SBML developers emerged that a fully generalized unit scheme is so confusing and complicated that it actually impedes interoperability. SBML Level 2 Version 2, Version 3 and Version 4 acknowledge this reality by reducing and simplifying the unit system, specifically by removing the "offset" attribute on Unit_t and Celsius
as a pre-defined unit.
The following guidelines suggest methods for handling units that do require the use of zero offsets for their definitions:
-
Handling Celsius. A model in which certain quantities are temperatures measured in degrees Celsius can be converted straightforwardly to a model in which those temperatures are in kelvin. A software tool could do this by performing a straightforward substitution using the following relationship: T kelvin = TCelsius + 273.15. In every mathematical formula of the model where a quantity (call it x) in degrees Celsius appears, replace x with xk+ 273.15, where xk is now in kelvin. An alternative approach would be to use a FunctionDefinition_t object to define a function encapsulating this relationship above and then using that in the rest of the model as needed. Since Celsius is a commonly-used unit, software tools could help users by providing users with the ability to express temperatures in Celsius in the tools' interfaces, and making substitutions automatically when writing out the SBML.
-
Other units requiring offsets. One approach to handling other kinds of units is to use a FunctionDefinition_t to define a function encapsulating the necessary mathematical relationship, then substituting a call to this function wherever the original quantity appeared in the model. For example, here is a possible definition for converting Fahrenheit to Celsius degrees:
<functionDefinition id="Fahrenheit_to_kelvin">
<math xmlns="http://www.w3.org/1998/Math/MathML">
<lambda>
<bvar><ci> temp_in_fahrenheit </ci></bvar>
<apply>
<divide/>
<apply>
<plus/>
<ci> temp_in_fahrenheit </ci>
<cn> 459.67 </cn>
</apply>
<cn> 1.8 </cn>
</apply>
</lambda>
</math>
</functionDefinition>
-
An alternative approach not requiring the use of function definitions is to use an AssignmentRule_t for each variable in Fahrenheit units. The AssignmentRule_t could compute the conversion from Fahrenheit to (say) kelvin, assign its value to a variable (in Kelvin units), and then that variable could be used elsewhere in the model.
-
Still another approach is to rewrite the mathematical formulas of a model to directly incorporate the conversion formula wherever the original quantity appeared.
Please consult the SBML specifications for more information about this and other issues involving units.
- Examples:
- createExampleSBML.c, printAnnotation.c, printNotes.c, unsetAnnotation.c, and unsetNotes.c.
|
int | UnitDefinition_addUnit (UnitDefinition_t *ud, const Unit_t *u) |
| Adds a copy of the given Unit_t to the given UnitDefinition_t structure. More...
|
|
int | UnitDefinition_areEquivalent (UnitDefinition_t *ud1, UnitDefinition_t *ud2) |
| Predicate returning 1 (true) if two UnitDefinition_t structures are equivalent. More...
|
|
int | UnitDefinition_areIdentical (UnitDefinition_t *ud1, UnitDefinition_t *ud2) |
| Predicate returning 1 (true) if two UnitDefinition_t structures are identical. More...
|
|
UnitDefinition_t * | UnitDefinition_clone (const UnitDefinition_t *ud) |
| Creates and returns a deep copy of the given UnitDefinition_t structure. More...
|
|
UnitDefinition_t * | UnitDefinition_combine (UnitDefinition_t *ud1, UnitDefinition_t *ud2) |
| Combines two UnitDefinition_t structures into a single UnitDefinition_t. More...
|
|
UnitDefinition_t * | UnitDefinition_convertToSI (UnitDefinition_t *ud) |
| Convert a given. More...
|
|
UnitDefinition_t * | UnitDefinition_create (unsigned int level, unsigned int version) |
| Creates a new UnitDefinition_t structure using the given SBML level and version values. More...
|
|
Unit_t * | UnitDefinition_createUnit (UnitDefinition_t *ud) |
| Creates a new and empty Unit_t structure, adds it to the given UnitDefinition_t structure's list of units, and returns the Unit_t structure. More...
|
|
UnitDefinition_t * | UnitDefinition_createWithNS (SBMLNamespaces_t *sbmlns) |
| Creates a new UnitDefinition_t structure using the given SBMLNamespaces_t structure. More...
|
|
UnitDefinition_t * | UnitDefinition_divide (UnitDefinition_t *ud1, UnitDefinition_t *ud2) |
| Combines two UnitDefinition_t structures into a single UnitDefinition_t as a division. More...
|
|
void | UnitDefinition_free (UnitDefinition_t *ud) |
| Frees the given UnitDefinition_t. More...
|
|
const char * | UnitDefinition_getId (const UnitDefinition_t *ud) |
| Returns the identifier of this UnitDefinition_t structure. More...
|
|
ListOf_t * | UnitDefinition_getListOfUnits (UnitDefinition_t *ud) |
| Returns the list of Units for the given UnitDefinition_t structure. More...
|
|
const char * | UnitDefinition_getName (const UnitDefinition_t *ud) |
| Returns the name of this UnitDefinition_t structure. More...
|
|
const XMLNamespaces_t * | UnitDefinition_getNamespaces (UnitDefinition_t *ud) |
| Returns a list of XMLNamespaces_t associated with this UnitDefinition_t structure. More...
|
|
unsigned int | UnitDefinition_getNumUnits (const UnitDefinition_t *ud) |
| Returns the number of Unit_t structures contained within this UnitDefinition_t. More...
|
|
Unit_t * | UnitDefinition_getUnit (UnitDefinition_t *ud, unsigned int n) |
| Returns a specific Unit_t instance belonging to the given UnitDefinition_t structure. More...
|
|
int | UnitDefinition_isSetId (const UnitDefinition_t *ud) |
| Predicate to test whether the "id" attribute of the given UnitDefinition_t ud is set. More...
|
|
int | UnitDefinition_isSetName (const UnitDefinition_t *ud) |
| Predicate to test whether the "name" attribute of the given UnitDefinition_t ud is set. More...
|
|
int | UnitDefinition_isVariantOfArea (const UnitDefinition_t *ud) |
| Convenience function for testing if a given unit definition is a variant of the built-in unit "area" . More...
|
|
int | UnitDefinition_isVariantOfDimensionless (const UnitDefinition_t *ud) |
| Convenience function for testing if a given unit definition is a variant of the unit "dimensionless" . More...
|
|
int | UnitDefinition_isVariantOfLength (const UnitDefinition_t *ud) |
| Convenience function for testing if a given unit definition is a variant of the built-in unit "length" . More...
|
|
int | UnitDefinition_isVariantOfMass (const UnitDefinition_t *ud) |
| Convenience function for testing if a given unit definition is a variant of the built-in unit "mass" . More...
|
|
int | UnitDefinition_isVariantOfSubstance (const UnitDefinition_t *ud) |
| Convenience function for testing if a given unit definition is a variant of the built-in unit "substance" . More...
|
|
int | UnitDefinition_isVariantOfSubstancePerTime (const UnitDefinition_t *ud) |
| Convenience function for testing if a given unit definition is a variant of the built-in unit "substance" divided by the built-in unit "time" . More...
|
|
int | UnitDefinition_isVariantOfTime (const UnitDefinition_t *ud) |
| Convenience function for testing if a given unit definition is a variant of the built-in unit "time" . More...
|
|
int | UnitDefinition_isVariantOfVolume (const UnitDefinition_t *ud) |
| Convenience function for testing if a given unit definition is a variant of the built-in unit "volume" . More...
|
|
char * | UnitDefinition_printUnits (UnitDefinition_t *ud, int compact) |
| Expresses the given definition in a plain-text form. More...
|
|
Unit_t * | UnitDefinition_removeUnit (UnitDefinition_t *ud, unsigned int n) |
| Removes the nth Unit_t structure from this UnitDefinition_t structure and returns a pointer to it. More...
|
|
void | UnitDefinition_reorder (UnitDefinition_t *ud) |
| Alphabetically orders the Unit_t structures within the list of Unit_t's of a ud UnitDefinition_t. More...
|
|
int | UnitDefinition_setId (UnitDefinition_t *ud, const char *sid) |
| Sets the attribute "id" of the given UnitDefinition_t structure to a copy of the given string. More...
|
|
int | UnitDefinition_setName (UnitDefinition_t *ud, const char *name) |
| Sets the attribute "name" of the given UnitDefinition_t structure to a copy of the given string. More...
|
|
void | UnitDefinition_simplify (UnitDefinition_t *ud) |
| Simplifies the ud UnitDefinition_t such that any given kind of Unit_t structure occurs only once in the ListOfUnits_t. More...
|
|
int | UnitDefinition_unsetName (UnitDefinition_t *ud) |
| Unsets the name of the given UnitDefinition_t structure. More...
|
|