Working with CellML models using Java

Working with CellML models using Java

About the Java documentation

This documentation starts off with a few examples, and then moves into Java-specific reference documentation. Much of the CellML API documentation is language independent, so once you have a grasp of how the language independent documentation relates to Java, refer to the documentation (for example, interfaces listed in the class listing) for more details on how to use the services the API provides.

Loading java_cellml library

Here we create a class to load the java_cellml library.

import cellml_api.CellMLBootstrap;
public class CellMLLoader {
private CellMLBootstrap bootstrap;
public CellMLLoader(){
System.loadLibrary("java_cellml");
bootstrap = cellml_bootstrap.CellMLBootstrap.createCellMLBootstrap();
}
public CellMLBootstrap getCellMLBootstrap(){
return bootstrap;
}
}

Loading and creating CellML models

Here we create a class with methods that we could call to create or load CellML models.

import cellml_api.CellMLBootstrap;
import cellml_api.Model;
public class CellMLReader {
public static Model loadFromURL(CellMLBootstrap cb, String inputFileName){
return cb.getModelLoader().loadFromURL(inputFileName);
}
public static Model createModel(CellMLBootstrap cb, String modelString){
return cb.createModel(modelString);
}
}

Iterating CellML elements

The example shown below iterates through components, variables, and connections defined in the Hodgkin-Huxley model that is available at http://www.cellml.org/models/hodgkin_huxley_1952_version07/download.

import cellml_api.CellMLComponent;
import cellml_api.CellMLComponentIterator;
import cellml_api.CellMLComponentSet;
import cellml_api.CellMLVariable;
import cellml_api.CellMLVariableIterator;
import cellml_api.CellMLVariableSet;
import cellml_api.Connection;
import cellml_api.ConnectionIterator;
import cellml_api.ConnectionSet;
import cellml_api.MapComponents;
import cellml_api.MapVariables;
import cellml_api.MapVariablesIterator;
import cellml_api.MapVariablesSet;
import cellml_api.Model;
public class IterateElementTest {
CellMLLoader cLoader;
public IterateElementTest(){
cLoader = new CellMLLoader();
}
private void iterateModelElements(){
Model model = CellMLReader.loadFromURL(cLoader.getCellMLBootstrap(),
"http://www.cellml.org/models/hodgkin_huxley_1952_version07/download");
System.out.println("Model Name:" + model.getName() + "\n");
CellMLComponentSet componentSet = model.getModelComponents();
CellMLComponentIterator iter = componentSet.iterateComponents();
for(int i = 0; i < componentSet.getLength(); i++){
CellMLComponent comp = iter.nextComponent();
System.out.println("Component Name:"+comp.getName());
CellMLVariableSet variableSet = comp.getVariables();
CellMLVariableIterator varIter = variableSet.iterateVariables();
for(int j = 0; j < variableSet.getLength(); j ++){
CellMLVariable variable = varIter.nextVariable();
System.out.println("Variable Name:"+variable.getName());
}
System.out.println();
}
ConnectionSet connectionSet = model.getConnections();
ConnectionIterator conIter = connectionSet.iterateConnections();
for(int i = 0; i < connectionSet.getLength(); i++){
Connection connection = conIter.nextConnection();
MapComponents mapComponent = connection.getComponentMapping();
System.out.println("Connection Component1: "+mapComponent.getFirstComponentName() +
" Component2: " + mapComponent.getSecondComponentName());
MapVariablesSet variableSet = connection.getVariableMappings();
MapVariablesIterator varIter = variableSet.iterateMapVariables();
for(int j =0; j < variableSet.getLength(); j++){
MapVariables mapVar = varIter.nextMapVariable();
System.out.println("\t Variable1: "+mapVar.getFirstVariableName() +
" Variable2: " + mapVar.getSecondVariableName());
}
System.out.println();
}
}
public static void main(String [] args ){
IterateElementTest ietest = new IterateElementTest();
ietest.iterateModelElements();
}
}

To compile and run this code on Linux (with /path/to/sdk/ changed to the appropriate path):

  export CLASSPATH=/path/to/sdk/lib/cellml.jar:.:$CLASSPATH
  export LD_LIBRARY_PATH=/path/to/sdk/lib:$LD_LIBRARY_PATH
  javac IterateElementTest.java
  java -Djava.library.path=/path/to/sdk/lib IterateElementTest

On Windows (with c:/path/to/sdk/ changed to the appropriate path):

  set CLASSPATH="c:/path/to/sdk/lib/cellml.jar;.;%CLASSPATH%"
  set PATH="c:/path/to/sdk/lib;%PATH%"
  javac IterateElementTest.java
  java "-Djava.library.path=c:/path/to/sdk/lib" IterateElementTest

On Mac OS X:

  export CLASSPATH=/path/to/sdk/lib/cellml.jar:.:$CLASSPATH
  export DYLD_LIBRARY_PATH=/path/to/sdk/lib:$LD_LIBRARY_PATH
  javac IterateElementTest.java
  java -Djava.library.path=/path/to/sdk/lib IterateElementTest

Writing CellML models to files

Here we create a class with a method that we could call to write CellML models to files.

import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import cellml_api.Model;
public class CellMLWriter {
public static void writeToFile(Model model, String outputFileName ){
try{
PrintWriter writer = new PrintWriter(new FileWriter(outputFileName));
writer.println(model.getSerialisedText());
writer.close();
}
catch(IOException e)
{
e.printStackTrace();
}
}
}

Creating a CellML 1.1 model

The example code below creates a CellML 1.1 model with two components.

import cellml_api.CellMLComponent;
import cellml_api.CellMLVariable;
import cellml_api.Connection;
import cellml_api.MapComponents;
import cellml_api.MapVariables;
import cellml_api.Model;
import cellml_api.Unit;
import cellml_api.Units;
import cellml_api.VariableInterface;
public class CreateModelTest {
CellMLLoader cLoader;
public CreateModelTest(){
cLoader = new CellMLLoader();
}
private void createCellMLModel(){
Model m = CellMLReader.createModel(cLoader.getCellMLBootstrap(),"1.1");
m.setName("example1");
Units units = m.createUnits();
m.addElement(units);
units.setName("second");
Unit unit = m.createUnit();
units.addElement(unit);
unit.setUnits("second");
CellMLComponent comp1 = m.createComponent();
m.addElement(comp1);
comp1.setName("component1");
CellMLVariable var1 = m.createCellMLVariable();
comp1.addElement(var1);
var1.setName("variable1");
var1.setUnitsElement(units);
var1.setInitialValue("10");
var1.setPublicInterface(VariableInterface.INTERFACE_OUT);
CellMLComponent comp2 = m.createComponent();
m.addElement(comp2);
comp2.setName("component2");
CellMLVariable var2 = m.createCellMLVariable();
comp2.addElement(var2);
var2.setName("variable2");
var2.setUnitsElement(units);
var2.setPublicInterface(VariableInterface.INTERFACE_IN);
Connection con = m.createConnection();
m.addElement(con);
MapComponents mapComp = con.getComponentMapping();
mapComp.setFirstComponent(comp1);
mapComp.setSecondComponent(comp2);
MapVariables mapvar = m.createMapVariables();
con.addElement(mapvar);
mapvar.setFirstVariable(var1);
mapvar.setSecondVariable(var2);
CellMLWriter.writeToFile(m, m.getName()+ ".cellml");
}
public static void main(String [] args ){
CreateModelTest cmtest = new CreateModelTest();
cmtest.createCellMLModel();
}
}

General concepts when using the CellML API Reference Implementation from Java

Every language-independent interface defined in this operation is mapped to a Java interface. Operations defined on the interfaces map to interface methods of the same name. Attributes map to a getter and a setter (or just a getter in the case of readonly attributes). The getter is named by pre-pending 'get' to the attribute name, capitalising the first letter of the attribute name. The setter is named similarly, except with a prefix of 'set'.

Java is a garbage collected language, and the CellML API Reference Implementation uses reference counting. The Java bridges make these work together by ensuring that a reference is kept whenever you reference a CellML API object from Java, and so for the most part a Java programmer does not need to worry about memory management with the CellML API. The one exception is that cycles, where Java code references the API, and the API references a callback to Java, need to be explicitly broken or the objects in the cycle will never be released.

The same CellML API object can implement multiple interfaces, but doing a Java cast between different interfaces supported by an object will not work, because access to the CellML API object is through a bridge, and each bridge object only supports one chain of interfaces. To get access to other interfaces supported by an object, you need to do a query_interface operation. In Java, you do this using a static method on the bridge of the interface you want to obtain. These bridge classes are named pjm2pcm.namespace.interfaceName, and the static method is called queryInterface. The return value is an object of that class; these classes implement the corresponding Java interfaces.

Note that before you use any objects from a particular Java service, you must load the bridge using System.loadLibrary("java_modulename"), where modulename is the name of the module for the service (for example, cellml for the core of the API, cis for the integration service, ccgs for the code generation service).

Bootstrapping in Java

The language-independent part of the CellML API documentation describes what interfaces objects can support, and how to get different objects by performing operations and retrieving attributes on the existing objects. However, there is a chicken-and-egg problem - you need to get the first object before you can do anything on an interface. This problem is solved differently in different language bindings. In Java, the reference implementation solves the problem using static native methods, called Bootstrap Methods, that return a Java interface.

Here are some of the bootstrap methods available in the CellML API:

ServiceBootstrap methodReturn typeModule to load
Corecellml_bootstrap.CellMLBootstrap.createCellMLBootstrapcellml_api.CellMLBootstrapjava_cellml
AnnoToolscellml_bootstrap.AnnoToolsBootstrap.createAnnotationToolServicecellml_services.AnnotationToolServicejava_annotools
CCGScellml_bootstrap.CCGSBootstrap.createCodeGeneratorBootstrapcellml_services.CodeGeneratorBootstrapjava_ccgs
CGRScellml_bootstrap.CGRSBootstrap.createGenericsServicecellml_services.GenericsServicejava_cgrs
CIScellml_bootstrap.CISBootstrap.createIntegrationServicecellml_services.CellMLIntegrationServicejava_cis
CUSEScellml_bootstrap.CUSESBootstrap.createCUSESBootstrapcellml_services.CUSESBootstrapjava_cuses
CeLEDScellml_bootstrap.CeLEDSBootstrap.createCeLEDSBootstrapcellml_services.CeLEDSBootstrapjava_celeds
CeLEDSExportercellml_bootstrap.CeLEDSExporterBootstrap.createCeLEDSExporterBootstrapcellml_services.CeLEDSExporterBootstrapjava_celedsexporter
CeVAScellml_bootstrap.CeVASBootstrap.createCeVASBootstrapcellml_services.CeVASBootstrapjava_cevas
MaLAEScellml_bootstrap.MaLaESBootstrap.createMaLaESBootstrapcellml_services.MaLaESBootstrapjava_malaes
SProScellml_bootstrap.SProSBootstrap.createSProSBootstrapSProS.Bootstrapjava_spros
SRuScellml_bootstrap.SRuSBootstrap.createSRuSBootstrapSRuS.Bootstrapjava_srus
TeLICeMScellml_bootstrap.TeLICeMService.createTeLICeMServicecellml_services.TeLICeMServicejava_telicems
VACSScellml_bootstrap.VACSSBootstrap.createVACSServicecellml_services.VACSServicejava_vacss
Back to Top