Browse Source
Added SBML-to-PRISM generation code.
Added SBML-to-PRISM generation code.
git-svn-id: https://www.prismmodelchecker.org/svn/prism/prism/trunk@284 bbc10eb1-c90d-0410-af57-cb519fbb1720master
2 changed files with 674 additions and 0 deletions
@ -0,0 +1,222 @@ |
|||
//============================================================================== |
|||
// |
|||
// Copyright (c) 2002- |
|||
// Authors: |
|||
// * Dave Parker <dxp@cs.bham.uc.uk> (University of Birmingham) |
|||
// |
|||
//------------------------------------------------------------------------------ |
|||
// |
|||
// This file is part of PRISM. |
|||
// |
|||
// PRISM is free software; you can redistribute it and/or modify |
|||
// it under the terms of the GNU General Public License as published by |
|||
// the Free Software Foundation; either version 2 of the License, or |
|||
// (at your option) any later version. |
|||
// |
|||
// PRISM is distributed in the hope that it will be useful, |
|||
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
// GNU General Public License for more details. |
|||
// |
|||
// You should have received a copy of the GNU General Public License |
|||
// along with PRISM; if not, write to the Free Software Foundation, |
|||
// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|||
// |
|||
//============================================================================== |
|||
|
|||
package prism; |
|||
|
|||
import java.io.*; |
|||
import java.util.*; |
|||
import javax.xml.parsers.*; |
|||
import javax.xml.transform.*; |
|||
import javax.xml.transform.dom.*; |
|||
import javax.xml.transform.stream.*; |
|||
import org.w3c.dom.*; |
|||
import org.xml.sax.*; |
|||
|
|||
public class MathML2Prism |
|||
{ |
|||
// Converts a MathML object to the corresponding PRISM expression (as a string) |
|||
|
|||
public static String convert(Node node) throws PrismException |
|||
{ |
|||
String s, nodeName, apply; |
|||
int nodeType, i, n; |
|||
NodeList allChildren; |
|||
ArrayList<Node> children; |
|||
ArrayList<String> translatedChildren; |
|||
|
|||
nodeType = node.getNodeType(); |
|||
switch (nodeType) { |
|||
|
|||
// MathML node |
|||
case Node.ELEMENT_NODE: |
|||
nodeName = node.getNodeName(); |
|||
|
|||
// Top-level element |
|||
if (nodeName.equals("math")) { |
|||
// return string for first non-text element |
|||
allChildren = node.getChildNodes(); |
|||
n = allChildren.getLength(); |
|||
children = new ArrayList<Node>(); |
|||
for (i = 0; i < n; i++) { |
|||
if (allChildren.item(i).getNodeType() != Node.TEXT_NODE) children.add(allChildren.item(i)); |
|||
} |
|||
if (children.size() == 0) throw new PrismException("Empty MathML expression"); |
|||
if (children.size() > 1) throw new PrismException("Too many top-level nodes in MathML expression"); |
|||
return convert(children.get(0)); |
|||
} |
|||
|
|||
// Literal |
|||
if (nodeName.equals("cn")) { |
|||
s = node.getFirstChild().getNodeValue().trim(); |
|||
return s; |
|||
} |
|||
|
|||
// Identifier |
|||
else if (nodeName.equals("ci")) { |
|||
s = node.getFirstChild().getNodeValue().trim(); |
|||
return s; |
|||
} |
|||
|
|||
// Apply operator |
|||
else if (nodeName.equals("apply")) { |
|||
// Get list of non-text nodes |
|||
allChildren = node.getChildNodes(); |
|||
n = allChildren.getLength(); |
|||
children = new ArrayList<Node>(); |
|||
for (i = 0; i < n; i++) { |
|||
if (allChildren.item(i).getNodeType() != Node.TEXT_NODE) children.add(allChildren.item(i)); |
|||
} |
|||
n = children.size(); |
|||
if (n == 0) throw new PrismException("Empty apply node in MathML expression"); |
|||
// Find operator and translate children |
|||
apply = children.get(0).getNodeName(); |
|||
translatedChildren = new ArrayList<String>(); |
|||
n = children.size() - 1; |
|||
for (i = 0; i < n; i++) { |
|||
translatedChildren.add(convert(children.get(i+1))); |
|||
} |
|||
|
|||
// Apply "plus" |
|||
if (apply.equals("plus")) { |
|||
s = "("; |
|||
for (i = 0; i < n; i++) { |
|||
if (i > 0) s += "+"; |
|||
s += translatedChildren.get(i); |
|||
} |
|||
s += ")"; |
|||
return s; |
|||
} |
|||
|
|||
// Apply "minus" |
|||
if (apply.equals("minus")) { |
|||
if (n != 2) throw new PrismException("MathML apply minus operations has "+n+" operands"); |
|||
s = "("+translatedChildren.get(0)+"-"+translatedChildren.get(1)+")"; |
|||
return s; |
|||
} |
|||
|
|||
// Apply "times" |
|||
if (apply.equals("times")) { |
|||
s = "("; |
|||
for (i = 0; i < n; i++) { |
|||
if (i > 0) s += "*"; |
|||
s += translatedChildren.get(i); |
|||
} |
|||
s += ")"; |
|||
return s; |
|||
} |
|||
|
|||
// Apply "divide" |
|||
if (apply.equals("divide")) { |
|||
if (n != 2) throw new PrismException("MathML apply divide operations has "+n+" operands"); |
|||
s = "("+translatedChildren.get(0)+"/"+translatedChildren.get(1)+")"; |
|||
return s; |
|||
} |
|||
|
|||
// Apply "power" |
|||
if (apply.equals("power")) { |
|||
if (n != 2) throw new PrismException("MathML apply power operations has "+n+" operands"); |
|||
s = "(func(pow,"+translatedChildren.get(0)+","+translatedChildren.get(1)+"))"; |
|||
return s; |
|||
} |
|||
|
|||
throw new PrismException("Unknown MathML apply operator \""+apply+"\""); |
|||
} |
|||
else { |
|||
throw new PrismException("Unknown MathML element \""+nodeName+"\""); |
|||
} |
|||
|
|||
// Ignore CDATA sections + entity references |
|||
case Node.CDATA_SECTION_NODE: |
|||
case Node.ENTITY_REFERENCE_NODE: |
|||
return ""; |
|||
|
|||
// Ignore text. For cases where we need it, e.g. "<ci> k4prime </ci>", |
|||
// this is processed by the parent node, e.g. <ci> |
|||
case Node.TEXT_NODE: |
|||
return ""; |
|||
|
|||
// Ignore processing instructions |
|||
case Node.PROCESSING_INSTRUCTION_NODE: |
|||
return ""; |
|||
} |
|||
|
|||
// Default: return empty string |
|||
return ""; |
|||
} |
|||
|
|||
// Additional utility method (currently unused except for testing) |
|||
// which parses a MathML expression from an InputStream before calling the conversion method above |
|||
|
|||
public static String parseAndConvert(InputStream in) throws PrismException |
|||
{ |
|||
DocumentBuilderFactory factory; |
|||
DocumentBuilder builder; |
|||
Document doc = null; |
|||
|
|||
// Create XML parser |
|||
factory = DocumentBuilderFactory.newInstance(); |
|||
factory.setValidating(false); |
|||
factory.setIgnoringElementContentWhitespace(true); |
|||
try { |
|||
builder = factory.newDocumentBuilder(); |
|||
//builder.setEntityResolver(this); |
|||
builder.setErrorHandler(new ErrorHandler() { |
|||
public void fatalError(SAXParseException e) throws SAXException { throw e; } |
|||
public void error(SAXParseException e) throws SAXException { throw e; } |
|||
public void warning(SAXParseException e) {} |
|||
}); |
|||
} |
|||
catch (ParserConfigurationException e) { |
|||
throw new PrismException("Couldn't create XML parser"); |
|||
} |
|||
|
|||
// Parse |
|||
try { |
|||
doc = builder.parse(in); |
|||
|
|||
return convert(doc.getDocumentElement()); |
|||
} |
|||
catch (IOException e) { |
|||
throw new PrismException("I/O error: "+e.getMessage()); |
|||
} |
|||
catch (SAXException e) { |
|||
throw new PrismException("Invalid XML file:\n"+ e.getMessage()); |
|||
} |
|||
} |
|||
|
|||
// Test call function - read MathML expression from stdin, convert, send to stdout |
|||
|
|||
public static void main(String args[]) |
|||
{ |
|||
try { |
|||
String s = parseAndConvert(System.in); |
|||
System.out.println(s); |
|||
} |
|||
catch (PrismException e) { |
|||
System.err.println("Error: "+e.getMessage()); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,452 @@ |
|||
//============================================================================== |
|||
// |
|||
// Copyright (c) 2002- |
|||
// Authors: |
|||
// * Dave Parker <dxp@cs.bham.uc.uk> (University of Birmingham) |
|||
// |
|||
//------------------------------------------------------------------------------ |
|||
// |
|||
// This file is part of PRISM. |
|||
// |
|||
// PRISM is free software; you can redistribute it and/or modify |
|||
// it under the terms of the GNU General Public License as published by |
|||
// the Free Software Foundation; either version 2 of the License, or |
|||
// (at your option) any later version. |
|||
// |
|||
// PRISM is distributed in the hope that it will be useful, |
|||
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
// GNU General Public License for more details. |
|||
// |
|||
// You should have received a copy of the GNU General Public License |
|||
// along with PRISM; if not, write to the Free Software Foundation, |
|||
// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|||
// |
|||
//============================================================================== |
|||
|
|||
package prism; |
|||
|
|||
import java.io.*; |
|||
import java.util.*; |
|||
import javax.xml.parsers.*; |
|||
import javax.xml.transform.*; |
|||
import javax.xml.transform.dom.*; |
|||
import javax.xml.transform.stream.*; |
|||
import org.w3c.dom.*; |
|||
import org.xml.sax.*; |
|||
|
|||
public class SBML2Prism implements EntityResolver |
|||
{ |
|||
private ArrayList<Species> speciesList; |
|||
private ArrayList<Reaction> reactionList; |
|||
private int scaleFactor; |
|||
|
|||
// Calling point: e.g. java -cp classes prism.SBML2Prism myfile.sbml 100 |
|||
// (100 denotes (integer) scale factor used to compute population sizes from (real-valued) concentrations, default is 10) |
|||
|
|||
public static void main(String args[]) |
|||
{ |
|||
try { |
|||
if (args.length < 1) { |
|||
System.err.println("Usage: java -cp classes prism.SBML2Prism <sbml_file> [scale_factor]"); |
|||
System.exit(1); |
|||
} |
|||
new SBML2Prism().load(new File(args[0]), (args.length>1)?args[1]:"10"); |
|||
} |
|||
catch (PrismException e) { |
|||
System.err.println("Error: "+e.getMessage()); |
|||
} |
|||
} |
|||
|
|||
// Main method: load SBML file, process and sent resulting PRISM file to stdout |
|||
|
|||
public void load(File f, String scaleFactor) throws PrismException |
|||
{ |
|||
try { this.scaleFactor = Integer.parseInt(scaleFactor); } |
|||
catch (NumberFormatException e) { throw new PrismException("Invalid scale factor \""+scaleFactor+"\""); } |
|||
Document doc = parseSBML(f); |
|||
extractModelFromSBML(doc); |
|||
printModel(System.err); |
|||
processModel(); |
|||
printPRISMModel(f); |
|||
} |
|||
|
|||
// Parse the SBML file and return an XML Document object |
|||
|
|||
private Document parseSBML(File f) throws PrismException |
|||
{ |
|||
DocumentBuilderFactory factory; |
|||
DocumentBuilder builder; |
|||
Document doc = null; |
|||
|
|||
// Create XML parser |
|||
factory = DocumentBuilderFactory.newInstance(); |
|||
factory.setValidating(false); |
|||
factory.setIgnoringElementContentWhitespace(true); |
|||
try { |
|||
builder = factory.newDocumentBuilder(); |
|||
builder.setEntityResolver(this); |
|||
builder.setErrorHandler(new ErrorHandler() { |
|||
public void fatalError(SAXParseException e) throws SAXException { throw e; } |
|||
public void error(SAXParseException e) throws SAXException { throw e; } |
|||
public void warning(SAXParseException e) {} |
|||
}); |
|||
} |
|||
catch (ParserConfigurationException e) { |
|||
throw new PrismException("Couldn't create XML parser"); |
|||
} |
|||
|
|||
// Parse |
|||
try { |
|||
doc = builder.parse(f); |
|||
} |
|||
catch (IOException e) { |
|||
throw new PrismException("Couldn't load file \""+f.getPath()+"\": " + e.getMessage()); |
|||
} |
|||
catch (SAXException e) { |
|||
throw new PrismException("Invalid XML file:\n" + e.getMessage()); |
|||
} |
|||
|
|||
return doc; |
|||
} |
|||
|
|||
// Function used by parseSBML() above to find the SBML DTD |
|||
// (this currently unused since we do not validate the SBML file when reading) |
|||
// (and since the DTD specified in the SBML files is not local) |
|||
// (if validation is enabled, put the DTD file "sbml.dtd" in PRISM's "dtds" directory) |
|||
|
|||
public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException |
|||
{ |
|||
InputSource inputSource = null; |
|||
|
|||
// override the resolve method for the dtd |
|||
if (systemId.endsWith("dtd")) |
|||
{ |
|||
// get appropriate dtd from classpath |
|||
InputStream inputStream = ClassLoader.getSystemResourceAsStream("dtds/sbml.dtd"); |
|||
if (inputStream != null) inputSource = new InputSource(inputStream); |
|||
} |
|||
|
|||
return inputSource; |
|||
} |
|||
|
|||
// Extract the information about the model from the parsed SBML file |
|||
|
|||
private void extractModelFromSBML(Document doc) throws PrismException |
|||
{ |
|||
Element e, e_model, e_list, e_species, e_reaction, e_kinetics, e_mathml, e_params; |
|||
NodeList nodes, nodes2; |
|||
Species species; |
|||
Reaction reaction; |
|||
int i, j, n, m; |
|||
double d; |
|||
String s; |
|||
|
|||
// Get "model" element of SBML file |
|||
nodes = doc.getDocumentElement().getElementsByTagName("model"); |
|||
e_model = (Element)nodes.item(0); |
|||
|
|||
// Process list of species |
|||
speciesList = new ArrayList<Species>(); |
|||
e_list = (Element)e_model.getElementsByTagName("listOfSpecies").item(0); |
|||
nodes = e_list.getElementsByTagName("species"); |
|||
n = nodes.getLength(); |
|||
for (i = 0; i < n; i++) { |
|||
e_species = (Element)nodes.item(i); |
|||
d = Double.parseDouble(e_species.getAttribute("initialAmount")); |
|||
species = new Species(e_species.getAttribute("id"), e_species.getAttribute("name"), d); |
|||
speciesList.add(species); |
|||
} |
|||
|
|||
// Process list of reactions |
|||
reactionList = new ArrayList<Reaction>(); |
|||
e_list = (Element)e_model.getElementsByTagName("listOfReactions").item(0); |
|||
nodes = e_list.getElementsByTagName("reaction"); |
|||
n = nodes.getLength(); |
|||
for (i = 0; i < n; i++) { |
|||
|
|||
// Process a single reaction... |
|||
e_reaction = (Element)nodes.item(i); |
|||
reaction = new Reaction(e_reaction.getAttribute("id"), e_reaction.getAttribute("name")); |
|||
|
|||
// Reactant list |
|||
e_list = (Element)e_reaction.getElementsByTagName("listOfReactants").item(0); |
|||
if (e_list != null) { |
|||
nodes2 = e_list.getElementsByTagName("speciesReference"); |
|||
m = nodes2.getLength(); |
|||
for (j = 0; j < m; j++) { |
|||
e = (Element)nodes2.item(j); |
|||
s = e.getAttribute("species"); |
|||
reaction.addReactant(s); |
|||
} |
|||
} |
|||
|
|||
// Product list |
|||
e_list = (Element)e_reaction.getElementsByTagName("listOfProducts").item(0); |
|||
if (e_list != null) { |
|||
nodes2 = e_list.getElementsByTagName("speciesReference"); |
|||
m = nodes2.getLength(); |
|||
for (j = 0; j < m; j++) { |
|||
e = (Element)nodes2.item(j); |
|||
s = e.getAttribute("species"); |
|||
reaction.addProduct(s); |
|||
} |
|||
} |
|||
|
|||
// Kinetic law |
|||
e_kinetics = (Element)e_reaction.getElementsByTagName("kineticLaw").item(0); |
|||
e_mathml = (Element)e_kinetics.getElementsByTagName("math").item(0); |
|||
reaction.setKineticLaw(e_mathml); |
|||
e_list = (Element)e_kinetics.getElementsByTagName("listOfParameters").item(0); |
|||
nodes2 = e_list.getElementsByTagName("parameter"); |
|||
m = nodes2.getLength(); |
|||
for (j = 0; j < m; j++) { |
|||
e = (Element)nodes2.item(j); |
|||
reaction.addParameter(e.getAttribute("id"), e.getAttribute("value")); |
|||
} |
|||
|
|||
// Add reaction to list |
|||
reactionList.add(reaction); |
|||
} |
|||
} |
|||
|
|||
// Print model |
|||
|
|||
private void printModel(PrintStream out) |
|||
{ |
|||
int i, n; |
|||
Reaction reaction; |
|||
|
|||
out.println(speciesList.size() + " species: "+speciesList); |
|||
n = reactionList.size(); |
|||
out.println(n + " reactions:"); |
|||
for (i = 0; i < n; i++) { |
|||
reaction = reactionList.get(i); |
|||
out.print(" * "+reaction); |
|||
} |
|||
} |
|||
|
|||
// Process model |
|||
|
|||
private void processModel() |
|||
{ |
|||
int i, j, k, n, m; |
|||
String s, s2; |
|||
Species species; |
|||
Reaction reaction; |
|||
HashSet<String> modulesNames; |
|||
HashSet<String> prismIdents; |
|||
|
|||
// Generate unique and valid PRISM identifier (module and variable name) for each species |
|||
modulesNames = new HashSet<String>(); |
|||
prismIdents = new HashSet<String>(); |
|||
n = speciesList.size(); |
|||
for (i = 0; i < n; i++) { |
|||
species = speciesList.get(i); |
|||
s = species.id; |
|||
s2 = convertToValidPrismIdent(s); |
|||
if (!s.equals(s2)) System.err.println("Warning: Converted species id \""+s+"\" to \""+s2+"\" (invalid PRISM identifier)"); |
|||
if (!modulesNames.add(s2)) { |
|||
j = 2; |
|||
while (!modulesNames.add(s2+"_"+j)) j++; |
|||
s2 = s2+"_"+j; |
|||
System.err.println("Warning: Converted species id \""+s+"\" to \""+s2+"\" (duplicate PRISM identifiers)"); |
|||
} |
|||
species.prismName = s2; |
|||
prismIdents.add(s2); |
|||
} |
|||
|
|||
// Generate unique and valid PRISM constant name for each reaction parameter |
|||
n = reactionList.size(); |
|||
for (i = 0; i < n; i++) { |
|||
reaction = reactionList.get(i); |
|||
m = reaction.parameters.size(); |
|||
for (j = 0; j < m; j++) { |
|||
s = reaction.parameters.get(j).name; |
|||
s2 = convertToValidPrismIdent(s); |
|||
if (!s.equals(s2)) System.err.println("Warning: Converted parameter id \""+s+"\" to \""+s2+"\" (invalid PRISM identifier)"); |
|||
if (!prismIdents.add(s2)) { |
|||
k = 2; |
|||
while (!prismIdents.add(s2+"_"+k)) k++; |
|||
s2 = s2+"_"+k; |
|||
System.err.println("Warning: Converted parameter id \""+s+"\" to \""+s2+"\" (duplicate PRISM identifiers)"); |
|||
} |
|||
reaction.parameters.get(j).prismName = s2; |
|||
} |
|||
} |
|||
} |
|||
|
|||
// Generate and print PRISM code |
|||
|
|||
private void printPRISMModel(File f) throws PrismException |
|||
{ |
|||
int i, i2, n, n2; |
|||
Species species; |
|||
Reaction reaction; |
|||
Parameter parameter; |
|||
String s = ""; |
|||
|
|||
// Header |
|||
s += "// File generated by automatic SBML-to-PRISM conversion\n"; |
|||
s += "// Original SBML file: " + f.getPath() + "\n\n"; |
|||
s += "ctmc\n"; |
|||
|
|||
// |
|||
s += "\nconst int SCALE_FACTOR = " + scaleFactor + ";\n"; |
|||
|
|||
// Generate constant definition for each (reaction) parameter |
|||
n = reactionList.size(); |
|||
for (i = 0; i < n; i++) { |
|||
reaction = reactionList.get(i); |
|||
n2 = reaction.parameters.size(); |
|||
if (n2 > 0) s += "\n// Parameters for reaction " + reaction.id + "\n"; |
|||
for (i2 = 0; i2 < n2; i2++) { |
|||
parameter = reaction.parameters.get(i2); |
|||
s += "const double " + parameter.prismName + " = " + parameter.value + "; // "+parameter.name+"\n"; |
|||
} |
|||
} |
|||
|
|||
// Generate module for each species |
|||
n = speciesList.size(); |
|||
for (i = 0; i < n; i++) { |
|||
species = speciesList.get(i); |
|||
s += "\n// Species " + species + "\n"; |
|||
s += "module " + species.prismName + "\n"; |
|||
|
|||
// Generate variable representing the amount of this species |
|||
s += "\t\n\t" + species.prismName + " : [0.." + scaleFactor + "]"; |
|||
s += " init " + (int)Math.round(scaleFactor*species.init) + "; // Initial amount " + species.init + "\n\t\n"; |
|||
|
|||
// Generate a command for each reaction that involves this species as a reactant |
|||
n2 = reactionList.size(); |
|||
for (i2 = 0; i2 < n2; i2++) { |
|||
reaction = reactionList.get(i2); |
|||
if (reaction.reactants.contains(species.id)) { |
|||
s += "\t// " + reaction.id; |
|||
if (reaction.name.length() > 0) s += " (" + reaction.name + ")"; |
|||
s += "\n"; |
|||
s += "\t[" + reaction.id + "] " ; |
|||
s += species.prismName + " > 0 -> (" + species.prismName + "'=" + species.prismName + "-1);\n"; |
|||
} |
|||
} |
|||
|
|||
// Generate a command for each reaction that involves this species as a product |
|||
n2 = reactionList.size(); |
|||
for (i2 = 0; i2 < n2; i2++) { |
|||
reaction = reactionList.get(i2); |
|||
if (reaction.products.contains(species.id)) { |
|||
s += "\t// " + reaction.id; |
|||
if (reaction.name.length() > 0) s += " (" + reaction.name + ")"; |
|||
s += "\n"; |
|||
s += "\t[" + reaction.id + "] " ; |
|||
s += species.prismName + " < " + scaleFactor + " -> (" + species.prismName + "'=" + species.prismName + "+1);\n"; |
|||
} |
|||
} |
|||
|
|||
// Generate the end of this module definition |
|||
s += "\t\nendmodule\n"; |
|||
} |
|||
|
|||
// Generate dummy module to store reaction rates |
|||
s += "\n// Reaction rates\nmodule dummy\n\n"; |
|||
n = reactionList.size(); |
|||
for (i = 0; i < n; i++) { |
|||
reaction = reactionList.get(i); |
|||
s += "\t// " + reaction.id; |
|||
if (reaction.name.length() > 0) s += " (" + reaction.name + ")"; |
|||
s += "\n"; |
|||
s += "\t[" + reaction.id + "] " + MathML2Prism.convert(reaction.kineticLaw) + " > 0 -> " + MathML2Prism.convert(reaction.kineticLaw) + " : true;\n"; |
|||
System.err.println(MathML2Prism.convert(reaction.kineticLaw)); |
|||
} |
|||
s += "\nendmodule\n"; |
|||
|
|||
// Generate a reward structure for each species |
|||
s += "\n// Reward structures (one per species)\n\n"; |
|||
n = speciesList.size(); |
|||
for (i = 0; i < n; i++) { |
|||
species = speciesList.get(i); |
|||
s += "// " + (i+1) + "\nrewards \"" + species.prismName + "\" true : " + species.prismName + "; endrewards\n"; |
|||
} |
|||
|
|||
System.out.print(s); |
|||
} |
|||
|
|||
// Check whether a given string is a valid PRISM language identifier |
|||
|
|||
private static boolean isValidPrismIdent(String s) |
|||
{ |
|||
return s.matches("[_a-zA-Z_][_a-zA-Z0-9]*"); |
|||
} |
|||
|
|||
// Convert a string to a valid PRISM language identifier (by removing invalid characters) |
|||
|
|||
private static String convertToValidPrismIdent(String s) |
|||
{ |
|||
String s2; |
|||
if (isValidPrismIdent(s)) return s; |
|||
s2 = s.replaceAll("[^_a-zA-Z0-9]", ""); |
|||
return s2; |
|||
} |
|||
|
|||
// Classes to store info from an SBML file |
|||
|
|||
class Species |
|||
{ |
|||
public String id; |
|||
public String name; |
|||
public double init; |
|||
public String prismName; |
|||
public Species(String id, String name, double init) |
|||
{ |
|||
this.id = id; |
|||
this.name = name; |
|||
this.init = init; |
|||
this.prismName = null; |
|||
} |
|||
public String toString() { return id+(name.length()>0 ? (" ("+name+")") : ""); } |
|||
} |
|||
|
|||
class Parameter |
|||
{ |
|||
public String name; |
|||
public String value; |
|||
public String prismName; |
|||
public Parameter(String name, String value) { this.name = name; this.value = value; this.prismName = null; } |
|||
public String toString() { return name+"="+value; } |
|||
} |
|||
|
|||
class Reaction |
|||
{ |
|||
public String id; |
|||
public String name; |
|||
public ArrayList<String> reactants; |
|||
public ArrayList<String> products; |
|||
public Element kineticLaw; |
|||
public ArrayList<Parameter> parameters; |
|||
public Reaction(String id, String name) |
|||
{ |
|||
this.id = id; |
|||
this.name = name; |
|||
reactants = new ArrayList<String>(); |
|||
products = new ArrayList<String>(); |
|||
kineticLaw = null; |
|||
parameters = new ArrayList<Parameter>(); |
|||
} |
|||
public void addReactant(String reactant) { reactants.add(reactant); } |
|||
public void addProduct(String product) { products.add(product); } |
|||
public void setKineticLaw(Element kineticLaw) { this.kineticLaw = kineticLaw; } |
|||
public void addParameter(String name, String value) { parameters.add(new Parameter(name, value)); } |
|||
public String toString() |
|||
{ |
|||
String s = ""; |
|||
s += id; |
|||
if (name.length() > 0) s+= " ("+name+")"; |
|||
s += ":\n"; |
|||
s += " Reactants: " + reactants+"\n"; |
|||
s += " Products: " + products+"\n"; |
|||
s += " Kinetic law: " + kineticLaw+"\n"; |
|||
s += " Parameters: " + parameters+"\n"; |
|||
return s; |
|||
} |
|||
} |
|||
} |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue