diff --git a/.gitignore b/.gitignore index 37b67890..7f962a1f 100644 --- a/.gitignore +++ b/.gitignore @@ -27,4 +27,20 @@ src/test/resources/sbml-test-suite/ # log files *.log + +# Maven +target/ +pom.xml.tag +pom.xml.releaseBackup +pom.xml.versionsBackup +pom.xml.next +release.properties +dependency-reduced-pom.xml +buildNumber.properties +.mvn/timing.properties +.mvn/wrapper/maven-wrapper.jar +.flattened-pom.xml + +# Eclipse +**/.metadata /bin/ diff --git a/FernMLSchema.xsd b/FernMLSchema.xsd new file mode 100644 index 00000000..6e70ba06 --- /dev/null +++ b/FernMLSchema.xsd @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/README.md b/README.md index f7f39468..fbad95e3 100644 --- a/README.md +++ b/README.md @@ -1,67 +1,67 @@ -# The Systems Biology Simulation Core Library - -[![License (LGPL version 3)](https://img.shields.io/badge/license-LGPLv3.0-blue.svg?style=plastic)](http://opensource.org/licenses/LGPL-3.0) -[![Latest version](https://img.shields.io/badge/Latest_version-1.4.0-brightgreen.svg?style=plastic)](https://github.com/draeger-lab/SBSCL/releases/) -[![DOI](https://img.shields.io/badge/DOI-10.1186%2F1752--0509--7--55-blue.svg?style=plastic)](https://doi.org/10.1186/1752-0509-7-55) -[![Build Status](https://travis-ci.com/draeger-lab/SBSCL.svg?branch=master&style=plastic)](https://travis-ci.com/draeger-lab/SBSCL) - -*Authors*: [Roland Keller](https://github.com/RolandKeller5), [Andreas Dräger](https://github.com/draeger), [Shalin Shah](https://github.com/shalinshah1993), [Matthias König](https://github.com/matthiaskoenig), [Alexander Dörr](https://github.com/a-doerr), [Richard Adams](https://github.com/otter606), [Nicolas Le Novère](https://github.com/lenov), [Max Zwiessele](https://github.com/mzwiessele) - -*Contributors to predecessor projects:* Philip Stevens, Marcel Kronfeld, Sandra Saliger, Simon Schäfer, Dieudonné Motsou Wouamba, Hannes Borch - -#### Description -The Systems Biology Simulation Core Library (SBSCL) provides an efficient and exhaustive Java™ implementation of methods to interpret the content of models encoded in the Systems Biology Markup Language ([SBML](http://sbml.org)) and its numerical solution. This library is based on the [JSBML](http://sbml.org/Software/JSBML) project and can be used on every operating system for which a Java Virtual Machine is available. Please note that this project does not contain any user interface, neither a command-line interface, nor a graphical user interface. This project has been developed as a pure programming library. To support the [MIASE](http://co.mbine.org/standards/miase) effort, it understands [SED-ML](http://sed-ml.org) files. Its abstract type and interface hierarchy facilitates the implementation of further community standards, such as [CellML](https://www.cellml.org). - -When using this library, please cite: http://www.biomedcentral.com/1752-0509/7/55. - -#### Categories -Bio-Informatics, Libraries, Simulations - -#### Features -* Numerical simulation -* Ordinary differential equation solver -* Time-course analysis -* Systems Biology Markup Language -* Application programming interface - -#### Licensing terms - -This file is part of Simulation Core Library, a Java-based library for efficient numerical simulation of biological models. - -Copyright (C) 2007 jointly held by the individual authors. - -This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation. A copy of the license agreement is provided in the file named "LICENSE.txt" included with this software distribution and also available online as http://www.gnu.org/licenses/lgpl-3.0-standalone.html. - -Please cite the original work and the authors when using this program. See the [project homepage](https://draeger-lab.github.io/SBSCL/) for details. - -## Getting started - -For an introduction of how to use this library, please open the javadoc [homepage](https://draeger-lab.github.io/SBSCL/apidocs/overview-summary.html). There you can find instructions and source code examples, including some use cases. Once a maven build is ran, the binaries will be generated in the target folder. This folder will also include a JAR files of the simulation core library to work with. - -## File structure - -Just a brief explanation of the folders and files contained in this distribution. - -Most importantly, see - * the [`INSTALL.md`](INSTALL.md) file for instruction to run maven build - * the docs folder containing an exhaustive documentation under apidocs - -The package structure in more detail: -``` - / - |- docs -> Contains code for the maven built website - |- src -> The main source folder containing all the code and test files - |- assembly -> assembly files for maven plugins - |- lib -> 3rd party libraries needed for compilation and execution - |- main -> Core java files of simulation library - |- test -> JUnit test files along with resources required - |- site -> Contains markup files, old javadoc, site.xml and other website - resources - |- LICENSE.txt -> the license, under which this project is distributed - |- pom.xml -> Maven file for building the project - |- README.md -> this file -``` - -## Troubleshooting - -Please e-mail any bugs, problems, suggestions, or issues regarding this library to the bug tracker at https://github.com/draeger-lab/SBSCL/issues +# The Systems Biology Simulation Core Library + +[![License (LGPL version 3)](https://img.shields.io/badge/license-LGPLv3.0-blue.svg?style=plastic)](http://opensource.org/licenses/LGPL-3.0) +[![Latest version](https://img.shields.io/badge/Latest_version-1.4.0-brightgreen.svg?style=plastic)](https://github.com/draeger-lab/SBSCL/releases/) +[![DOI](https://img.shields.io/badge/DOI-10.1186%2F1752--0509--7--55-blue.svg?style=plastic)](https://doi.org/10.1186/1752-0509-7-55) +[![Build Status](https://travis-ci.com/draeger-lab/SBSCL.svg?branch=master&style=plastic)](https://travis-ci.com/draeger-lab/SBSCL) + +*Authors*: [Roland Keller](https://github.com/RolandKeller5), [Andreas Dräger](https://github.com/draeger), [Shalin Shah](https://github.com/shalinshah1993), [Matthias König](https://github.com/matthiaskoenig), [Alexander Dörr](https://github.com/a-doerr), [Richard Adams](https://github.com/otter606), [Nicolas Le Novère](https://github.com/lenov), [Max Zwiessele](https://github.com/mzwiessele) + +*Contributors to predecessor projects:* Philip Stevens, Marcel Kronfeld, Sandra Saliger, Simon Schäfer, Dieudonné Motsou Wouamba, Hannes Borch + +#### Description +The Systems Biology Simulation Core Library (SBSCL) provides an efficient and exhaustive Java™ implementation of methods to interpret the content of models encoded in the Systems Biology Markup Language ([SBML](http://sbml.org)) and its numerical solution. This library is based on the [JSBML](http://sbml.org/Software/JSBML) project and can be used on every operating system for which a Java Virtual Machine is available. Please note that this project does not contain any user interface, neither a command-line interface, nor a graphical user interface. This project has been developed as a pure programming library. To support the [MIASE](http://co.mbine.org/standards/miase) effort, it understands [SED-ML](http://sed-ml.org) files. Its abstract type and interface hierarchy facilitates the implementation of further community standards, such as [CellML](https://www.cellml.org). + +When using this library, please cite: http://www.biomedcentral.com/1752-0509/7/55. + +#### Categories +Bio-Informatics, Libraries, Simulations + +#### Features +* Numerical simulation +* Ordinary differential equation solver +* Time-course analysis +* Systems Biology Markup Language +* Application programming interface + +#### Licensing terms + +This file is part of Simulation Core Library, a Java-based library for efficient numerical simulation of biological models. + +Copyright (C) 2007 jointly held by the individual authors. + +This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation. A copy of the license agreement is provided in the file named "LICENSE.txt" included with this software distribution and also available online as http://www.gnu.org/licenses/lgpl-3.0-standalone.html. + +Please cite the original work and the authors when using this program. See the [project homepage](https://draeger-lab.github.io/SBSCL/) for details. + +## Getting started + +For an introduction of how to use this library, please open the javadoc [homepage](https://draeger-lab.github.io/SBSCL/apidocs/overview-summary.html). There you can find instructions and source code examples, including some use cases. Once a maven build is ran, the binaries will be generated in the target folder. This folder will also include a JAR files of the simulation core library to work with. + +## File structure + +Just a brief explanation of the folders and files contained in this distribution. + +Most importantly, see + * the [`INSTALL.md`](INSTALL.md) file for instruction to run maven build + * the docs folder containing an exhaustive documentation under apidocs + +The package structure in more detail: +``` + / + |- docs -> Contains code for the maven built website + |- src -> The main source folder containing all the code and test files + |- assembly -> assembly files for maven plugins + |- lib -> 3rd party libraries needed for compilation and execution + |- main -> Core java files of simulation library + |- test -> JUnit test files along with resources required + |- site -> Contains markup files, old javadoc, site.xml and other website + resources + |- LICENSE.txt -> the license, under which this project is distributed + |- pom.xml -> Maven file for building the project + |- README.md -> this file +``` + +## Troubleshooting + +Please e-mail any bugs, problems, suggestions, or issues regarding this library to the bug tracker at https://github.com/draeger-lab/SBSCL/issues diff --git a/docs/old_javadoc/version_1.2/overview-summary.html b/docs/old_javadoc/version_1.2/overview-summary.html index 8e175145..b7e44b0e 100644 --- a/docs/old_javadoc/version_1.2/overview-summary.html +++ b/docs/old_javadoc/version_1.2/overview-summary.html @@ -84,13 +84,13 @@

Systems Biology Simulation Core Library 1.2

-Simulation Core Library: Documentation - - About Simulation Core Library - - The Java™ API Simulation Core Library comprises a collection of - integrators for differential equation systems combined with an interpreter - for the Systems Biology Markup Language +Simulation Core Library: Documentation + + About Simulation Core Library + + The Java™ API Simulation Core Library comprises a collection of + integrators for differential equation systems combined with an interpreter + for the Systems Biology Markup Language (SBML).

See: @@ -146,158 +146,158 @@

 

-

Simulation Core Library: Documentation

- -

About Simulation Core Library

-

- The Java™ API Simulation Core Library comprises a collection of - integrators for differential equation systems combined with an interpreter - for the Systems Biology Markup Language - (SBML). - It is the first simulation library that is based on - JSBML. - The user can read an SBML model and simulate it with one of the provided - numerical integration routines. All SBML levels and versions are - supported. - The library can easily be integrated into customized software, such as - parameter estimation tools. -

- -

The provided integration methods

-

- The Rosenbrock solver is best suitable for integrating stiff differential - equation systems and also has a precise timing of SBML events. It is taken - and adapted from Kotcon et al. - Several solvers have been taken from the - Apache Commons - Math Library and wrapped into our library: -

- - The following solvers have been implemented additionally and are fast, but - not suitable for all differential equation systems: - -

- -

Reading in a model and creating the respective differential equation - system

-

- A model can be read in by using the SBMLReader class of JSBML. - With the model in memory the SBMLinterpreter can create the - differential equation system that provides the basis for simulation: -

-

-      Model model = (new SBMLReader()).readSBML(sbmlfile).getModel();
- SBMLinterpreter interpreter = new SBMLinterpreter(model); -
- -

Simulation of a differential equation system

-

- The created differential equation system can then be simulated with a - chosen solver and given time points. - The result is stored in a data structure called MultiTable. -

-

-      AbstractDESSolver solver = new RosenbrockSolver();
- double[] timePoints = {0.0, 0.1, 0.2, 0.3, 0.4, 0.5};
- MultiTable solution = solver.solve(interpreter, interpreter.getInitialValues(), timePoints); -
- -

Using SED-ML for simulation

-

- The following example shows how to read in a File f (in SED-ML - format) and how to run a simulation described in this file afterwards. - The simulation results are stored in a MultiTable. -

- -

-      SEDMLDocument doc = Libsedml.readDocument(f);
- SedML sedml = doc.getSBMLModel();
- Output wanted = sedml.getOutputs().get(0);
- SedMLSBMLSimulatorExecutor exe = new SedMLSBMLSimulatorExecutor(sedml, wanted);
- Map res = exe.runSimulations();
- MultiTable solution = exe.processSimulationResults(wanted, res);
-
- -

How to integrate Simulation Core Library into your software?

-

- You just have to add the provided jar-file simulation-core-library.jar to the class path of your Java project. - Then you have access to all classes of the library. - This library depends on the following third-party libraries: -

- For SED-ML support, the following - additional libraries are required: - - Please make sure to include the correct third-party libraries into your - class path before working with this library. -

- -

Simulation of the models in the SBML Test Suite

-

- You can run the simulation of the models in the - SBML Test - Suite by using the command below. TestSuiteDirectory denotes - the directory containing your copy of the (entire) SBML test suite. - Here we assume that the actual test cases are located in the sub-folder - cases/semantic/ within the TestSuiteDirectory on your - computer. - The simulation is conducted for the models with numbers from first - to last (these numbers are the indices of the models in the test - suite, without leading zeros). -

-

-      java -cp SimulationCoreLibrary_vX.Y_incl-libs.jar org.simulator.SBMLTestSuiteRunner  TestSuiteDirectory/cases/semantic/ first last
-    
- Please note that, you have to replace _vX.Y_ within the library's - name by the current release number, e.g., 1.2. -

- For example, if you like to simulate all test suite models ranging from - 00259 to 00326, simply call the algorithm with - first = 259 and last = 326. -

-

- Note that for the sake of a simple configuration, the simulation is - started using default settings for the selection of the - integration routine, step size etc. -

- -

Simulation of the models from BioModels database

-

- In a similar way, you can also download and simulate all models from - BioModels database: -


-      java -cp SimulationCoreLibrary_vX.Y_incl-libs.jar org.simulator.TestBiomodels BioModelsDirectory/ first last
-    
- Again, you have to replace _vX.Y_ within the library's - name by the current release number, e.g., 1.2. Please use the variables - first and last without leading zeros as in the previous - case. The variable BioModelsDirectory gives the path to your local - copy of the BioModels database. -

-

- As in the previous case, the simulation is conducted using default - settings. +

Simulation Core Library: Documentation

+ +

About Simulation Core Library

+

+ The Java™ API Simulation Core Library comprises a collection of + integrators for differential equation systems combined with an interpreter + for the Systems Biology Markup Language + (SBML). + It is the first simulation library that is based on + JSBML. + The user can read an SBML model and simulate it with one of the provided + numerical integration routines. All SBML levels and versions are + supported. + The library can easily be integrated into customized software, such as + parameter estimation tools. +

+ +

The provided integration methods

+

+ The Rosenbrock solver is best suitable for integrating stiff differential + equation systems and also has a precise timing of SBML events. It is taken + and adapted from Kotcon et al. + Several solvers have been taken from the + Apache Commons + Math Library and wrapped into our library: +

+ + The following solvers have been implemented additionally and are fast, but + not suitable for all differential equation systems: + +

+ +

Reading in a model and creating the respective differential equation + system

+

+ A model can be read in by using the SBMLReader class of JSBML. + With the model in memory the SBMLinterpreter can create the + differential equation system that provides the basis for simulation: +

+

+      Model model = (new SBMLReader()).readSBML(sbmlfile).getModel();
+ SBMLinterpreter interpreter = new SBMLinterpreter(model); +
+ +

Simulation of a differential equation system

+

+ The created differential equation system can then be simulated with a + chosen solver and given time points. + The result is stored in a data structure called MultiTable. +

+

+      AbstractDESSolver solver = new RosenbrockSolver();
+ double[] timePoints = {0.0, 0.1, 0.2, 0.3, 0.4, 0.5};
+ MultiTable solution = solver.solve(interpreter, interpreter.getInitialValues(), timePoints); +
+ +

Using SED-ML for simulation

+

+ The following example shows how to read in a File f (in SED-ML + format) and how to run a simulation described in this file afterwards. + The simulation results are stored in a MultiTable. +

+ +

+      SEDMLDocument doc = Libsedml.readDocument(f);
+ SedML sedml = doc.getSBMLModel();
+ Output wanted = sedml.getOutputs().get(0);
+ SedMLSBMLSimulatorExecutor exe = new SedMLSBMLSimulatorExecutor(sedml, wanted);
+ Map res = exe.runSimulations();
+ MultiTable solution = exe.processSimulationResults(wanted, res);
+
+ +

How to integrate Simulation Core Library into your software?

+

+ You just have to add the provided jar-file simulation-core-library.jar to the class path of your Java project. + Then you have access to all classes of the library. + This library depends on the following third-party libraries: +

+ For SED-ML support, the following + additional libraries are required: + + Please make sure to include the correct third-party libraries into your + class path before working with this library. +

+ +

Simulation of the models in the SBML Test Suite

+

+ You can run the simulation of the models in the + SBML Test + Suite by using the command below. TestSuiteDirectory denotes + the directory containing your copy of the (entire) SBML test suite. + Here we assume that the actual test cases are located in the sub-folder + cases/semantic/ within the TestSuiteDirectory on your + computer. + The simulation is conducted for the models with numbers from first + to last (these numbers are the indices of the models in the test + suite, without leading zeros). +

+

+      java -cp SimulationCoreLibrary_vX.Y_incl-libs.jar org.simulator.SBMLTestSuiteRunner  TestSuiteDirectory/cases/semantic/ first last
+    
+ Please note that, you have to replace _vX.Y_ within the library's + name by the current release number, e.g., 1.2. +

+ For example, if you like to simulate all test suite models ranging from + 00259 to 00326, simply call the algorithm with + first = 259 and last = 326. +

+

+ Note that for the sake of a simple configuration, the simulation is + started using default settings for the selection of the + integration routine, step size etc. +

+ +

Simulation of the models from BioModels database

+

+ In a similar way, you can also download and simulate all models from + BioModels database: +


+      java -cp SimulationCoreLibrary_vX.Y_incl-libs.jar org.simulator.TestBiomodels BioModelsDirectory/ first last
+    
+ Again, you have to replace _vX.Y_ within the library's + name by the current release number, e.g., 1.2. Please use the variables + first and last without leading zeros as in the previous + case. The variable BioModelsDirectory gives the path to your local + copy of the BioModels database. +

+

+ As in the previous case, the simulation is conducted using default + settings.

diff --git a/docs/old_javadoc/version_1.3/overview-summary.html b/docs/old_javadoc/version_1.3/overview-summary.html index ab58b0b8..9c728a0c 100644 --- a/docs/old_javadoc/version_1.3/overview-summary.html +++ b/docs/old_javadoc/version_1.3/overview-summary.html @@ -84,13 +84,13 @@

Systems Biology Simulation Core Library 1.3

-Simulation Core Library: Documentation - - About Simulation Core Library - - The Java™ API Simulation Core Library comprises a collection of - integrators for differential equation systems combined with an interpreter - for the Systems Biology Markup Language +Simulation Core Library: Documentation + + About Simulation Core Library + + The Java™ API Simulation Core Library comprises a collection of + integrators for differential equation systems combined with an interpreter + for the Systems Biology Markup Language (SBML).

See: @@ -157,228 +157,228 @@

 

-

Simulation Core Library: Documentation

- -

About Simulation Core Library

-

- The Java™ API Simulation Core Library comprises a collection of - integrators for differential equation systems combined with an interpreter - for the Systems Biology Markup Language - (SBML). - It is the first simulation library that is based on - JSBML. - The user can read an SBML model and simulate it with one of the provided - numerical integration routines. All SBML levels and versions are - supported. - The library can easily be integrated into customized software, such as - parameter estimation tools. -

- -

How to integrate Simulation Core Library into your software?

-

- You just have to add the provided jar-file simulation-core-library.jar to the class path of your Java project. - Then you have access to all classes of the library. - This library depends on the following third-party libraries: -

- For SED-ML support, the following - additional libraries are required: - - Please make sure to include the correct third-party libraries into your - class path before working with this library. -

- -

The provided integration methods

-

- The RosenbrockSolver is best suitable for integrating stiff differential - equation systems and also has a precise timing of SBML events. It is taken - and adapted from - Kotcon et al. (2011) -

- Several further solvers have been taken from the - Apache Commons - Math Library and wrapped into our library: -

- - The following solvers have been implemented additionally and are fast, but - not suitable for all differential equation systems: - -

- For a full list of available solvers, see org.simulator.math.odes. -

- -

Reading an SBML model and creating the respective differential equation - system

-

- A model can be read in by using the SBMLReader - class from JSBML. - With the model in memory the SBMLinterpreter - can create the differential equation system that provides the basis for - simulation: -

-

-      Model model = (new SBMLReader()).readSBML(sbmlfile).getModel();
- SBMLinterpreter interpreter = new SBMLinterpreter(model); -
-

- For more documentation about working with SBML models in simulations see - org.simulator.sbml. -

- -

Simulation of a differential equation system

-

- The created differential equation system can then be simulated with a - chosen solver and given time points. - The result is stored in a data structure called - MultiTable. -

-

-      AbstractDESSolver solver = new RosenbrockSolver();
- double[] timePoints = {0.0, 0.1, 0.2, 0.3, 0.4, 0.5};
- MultiTable solution = solver.solve(interpreter, interpreter.getInitialValues(), timePoints); -
- -

Using SED-ML for simulation

-

- The following example shows how to read in a File f (in - SED-ML format) and how to run a simulation - described in this file afterwards. The simulation results are stored in a - MultiTable: -

- -

-      SEDMLDocument doc = Libsedml.readDocument(f);
- SedML sedml = doc.getSBMLModel();
- Output wanted = sedml.getOutputs().get(0);
- SedMLSBMLSimulatorExecutor exe = new SedMLSBMLSimulatorExecutor(sedml, wanted);
- Map res = exe.runSimulations();
- MultiTable solution = exe.processSimulationResults(wanted, res);
-
- -

- For more information about how to use SED-ML to execute your simulation - experiments, see org.simulator.sedml. -

- -

Simulation of the models in the SBML Test Suite

-

- You can run the simulation of the models in the - SBML Test - Suite by using the command below. TestSuiteDirectory denotes - the directory containing your copy of the (entire) SBML test suite. - Here we assume that the actual test cases are located in the sub-folder - cases/semantic/ within the TestSuiteDirectory on your - computer. - The simulation is conducted for the models with numbers from first - to last (these numbers are the indices of the models in the test - suite, without leading zeros). -

-

-      java -cp SimulationCoreLibrary_vX.Y_incl-libs.jar org.simulator.SBMLTestSuiteRunner TestSuiteDirectory/cases/semantic/ first last
-    
- Please note that, you have to replace _vX.Y_ within the library's - name by the current release number, e.g., 1.2. -

- For example, if you like to simulate all test suite models ranging from - 00259 to 00326, simply call the algorithm with - first = 259 and last = 326. -

- -

- Note that for the sake of a simple configuration, the simulation is - started using default settings for the selection of the - integration routine, step size etc. -

- -

- The - SBML Test Suite Database - provides an up-to-date overview about the - capabilities of various SBML-compliant solver implementations. -

- -

Simulation of the models from BioModels database

-

- In a similar way, you can also download and simulate all models from - BioModels database: -


-      java -cp SimulationCoreLibrary_vX.Y_incl-libs.jar org.simulator.TestBiomodels BioModelsDirectory/ first last
-    
- Again, you have to replace _vX.Y_ within the library's - name by the current release number, e.g., 1.2. Please use the variables - first and last without leading zeros as in the previous - case. The variable BioModelsDirectory gives the path to your local - copy of - BioModels database. -

-

- As in the previous case, the simulation is conducted using default - settings. -

- -

Listening to SBML constraint violation

-

- In version 1.3 a new listener interface has been added to - this library, which can be used to perform user-defined actions upon violation - of a Constraint's math expression during a simulation. - A simple implementation is already included in this package, - which logs violation at the - Level.WARNING using standard Java™ - logging (see Logger). - By default the - SBMLinterpreter adds this - SimpleConstraintListener to its internal list of - ConstraintListeners. -

- -

- You can remove this listener by calling the method - SBMLinterpreter.removeConstraintListener(int), - with the argument 0 for the first listener in the list, - and add your own listener implementation with the help of method - SBMLinterpreter.addConstraintListener(ConstraintListener). -

-

The following example demonstrates how you can easily define your customized - ConstraintListener: -


-      double timeEnd = 5d;
- SBMLDocument doc = SBMLReader.read(new File("path/to/file.xml"));
- SBMLinterpreter interpreter = new SBMLinterpreter(doc.getModel());
- interpreter.addConstraintListener(new ConstraintListener() {
-   /* (non-Javadoc)
-    * @see org.simulator.sbml.ConstraintListener#processViolation(org.simulator.sbml.ConstraintEvent)
-    */

-   public void processViolation(ConstraintEvent evt) {
-     System.err.println("Constraint violated at time " + evt.getTime() + ": " + evt.getSource().getMath().toFormula());
-   }
- });
- solver.solve(interpreter, interpreter.getInitialValues(), 0d, timeEnd); -
-

-

- You can find more details about this topic in the description of package - org.simulator.sbml. +

Simulation Core Library: Documentation

+ +

About Simulation Core Library

+

+ The Java™ API Simulation Core Library comprises a collection of + integrators for differential equation systems combined with an interpreter + for the Systems Biology Markup Language + (SBML). + It is the first simulation library that is based on + JSBML. + The user can read an SBML model and simulate it with one of the provided + numerical integration routines. All SBML levels and versions are + supported. + The library can easily be integrated into customized software, such as + parameter estimation tools. +

+ +

How to integrate Simulation Core Library into your software?

+

+ You just have to add the provided jar-file simulation-core-library.jar to the class path of your Java project. + Then you have access to all classes of the library. + This library depends on the following third-party libraries: +

+ For SED-ML support, the following + additional libraries are required: + + Please make sure to include the correct third-party libraries into your + class path before working with this library. +

+ +

The provided integration methods

+

+ The RosenbrockSolver is best suitable for integrating stiff differential + equation systems and also has a precise timing of SBML events. It is taken + and adapted from + Kotcon et al. (2011) +

+ Several further solvers have been taken from the + Apache Commons + Math Library and wrapped into our library: +

+ + The following solvers have been implemented additionally and are fast, but + not suitable for all differential equation systems: + +

+ For a full list of available solvers, see org.simulator.math.odes. +

+ +

Reading an SBML model and creating the respective differential equation + system

+

+ A model can be read in by using the SBMLReader + class from JSBML. + With the model in memory the SBMLinterpreter + can create the differential equation system that provides the basis for + simulation: +

+

+      Model model = (new SBMLReader()).readSBML(sbmlfile).getModel();
+ SBMLinterpreter interpreter = new SBMLinterpreter(model); +
+

+ For more documentation about working with SBML models in simulations see + org.simulator.sbml. +

+ +

Simulation of a differential equation system

+

+ The created differential equation system can then be simulated with a + chosen solver and given time points. + The result is stored in a data structure called + MultiTable. +

+

+      AbstractDESSolver solver = new RosenbrockSolver();
+ double[] timePoints = {0.0, 0.1, 0.2, 0.3, 0.4, 0.5};
+ MultiTable solution = solver.solve(interpreter, interpreter.getInitialValues(), timePoints); +
+ +

Using SED-ML for simulation

+

+ The following example shows how to read in a File f (in + SED-ML format) and how to run a simulation + described in this file afterwards. The simulation results are stored in a + MultiTable: +

+ +

+      SEDMLDocument doc = Libsedml.readDocument(f);
+ SedML sedml = doc.getSBMLModel();
+ Output wanted = sedml.getOutputs().get(0);
+ SedMLSBMLSimulatorExecutor exe = new SedMLSBMLSimulatorExecutor(sedml, wanted);
+ Map res = exe.runSimulations();
+ MultiTable solution = exe.processSimulationResults(wanted, res);
+
+ +

+ For more information about how to use SED-ML to execute your simulation + experiments, see org.simulator.sedml. +

+ +

Simulation of the models in the SBML Test Suite

+

+ You can run the simulation of the models in the + SBML Test + Suite by using the command below. TestSuiteDirectory denotes + the directory containing your copy of the (entire) SBML test suite. + Here we assume that the actual test cases are located in the sub-folder + cases/semantic/ within the TestSuiteDirectory on your + computer. + The simulation is conducted for the models with numbers from first + to last (these numbers are the indices of the models in the test + suite, without leading zeros). +

+

+      java -cp SimulationCoreLibrary_vX.Y_incl-libs.jar org.simulator.SBMLTestSuiteRunner TestSuiteDirectory/cases/semantic/ first last
+    
+ Please note that, you have to replace _vX.Y_ within the library's + name by the current release number, e.g., 1.2. +

+ For example, if you like to simulate all test suite models ranging from + 00259 to 00326, simply call the algorithm with + first = 259 and last = 326. +

+ +

+ Note that for the sake of a simple configuration, the simulation is + started using default settings for the selection of the + integration routine, step size etc. +

+ +

+ The + SBML Test Suite Database + provides an up-to-date overview about the + capabilities of various SBML-compliant solver implementations. +

+ +

Simulation of the models from BioModels database

+

+ In a similar way, you can also download and simulate all models from + BioModels database: +


+      java -cp SimulationCoreLibrary_vX.Y_incl-libs.jar org.simulator.TestBiomodels BioModelsDirectory/ first last
+    
+ Again, you have to replace _vX.Y_ within the library's + name by the current release number, e.g., 1.2. Please use the variables + first and last without leading zeros as in the previous + case. The variable BioModelsDirectory gives the path to your local + copy of + BioModels database. +

+

+ As in the previous case, the simulation is conducted using default + settings. +

+ +

Listening to SBML constraint violation

+

+ In version 1.3 a new listener interface has been added to + this library, which can be used to perform user-defined actions upon violation + of a Constraint's math expression during a simulation. + A simple implementation is already included in this package, + which logs violation at the + Level.WARNING using standard Java™ + logging (see Logger). + By default the + SBMLinterpreter adds this + SimpleConstraintListener to its internal list of + ConstraintListeners. +

+ +

+ You can remove this listener by calling the method + SBMLinterpreter.removeConstraintListener(int), + with the argument 0 for the first listener in the list, + and add your own listener implementation with the help of method + SBMLinterpreter.addConstraintListener(ConstraintListener). +

+

The following example demonstrates how you can easily define your customized + ConstraintListener: +


+      double timeEnd = 5d;
+ SBMLDocument doc = SBMLReader.read(new File("path/to/file.xml"));
+ SBMLinterpreter interpreter = new SBMLinterpreter(doc.getModel());
+ interpreter.addConstraintListener(new ConstraintListener() {
+   /* (non-Javadoc)
+    * @see org.simulator.sbml.ConstraintListener#processViolation(org.simulator.sbml.ConstraintEvent)
+    */

+   public void processViolation(ConstraintEvent evt) {
+     System.err.println("Constraint violated at time " + evt.getTime() + ": " + evt.getSource().getMath().toFormula());
+   }
+ });
+ solver.solve(interpreter, interpreter.getInitialValues(), 0d, timeEnd); +
+

+

+ You can find more details about this topic in the description of package + org.simulator.sbml.

diff --git a/docs/old_javadoc/version_1.4/overview-summary.html b/docs/old_javadoc/version_1.4/overview-summary.html index ea78afe6..8f16363a 100644 --- a/docs/old_javadoc/version_1.4/overview-summary.html +++ b/docs/old_javadoc/version_1.4/overview-summary.html @@ -84,13 +84,13 @@

Systems Biology Simulation Core Library 1.4

-Simulation Core Library: Documentation - - About Simulation Core Library - - The Java™ API Simulation Core Library comprises a collection of - integrators for differential equation systems combined with an interpreter - for the Systems Biology Markup Language +Simulation Core Library: Documentation + + About Simulation Core Library + + The Java™ API Simulation Core Library comprises a collection of + integrators for differential equation systems combined with an interpreter + for the Systems Biology Markup Language (SBML).

See: @@ -157,238 +157,238 @@

 

-

Simulation Core Library: Documentation

- -

About Simulation Core Library

-

- The Java™ API Simulation Core Library comprises a collection of - integrators for differential equation systems combined with an interpreter - for the Systems Biology Markup Language - (SBML). - It is the first simulation library that is based on - JSBML. - The user can read an SBML model and simulate it with one of the provided - numerical integration routines. All SBML levels and versions are - supported. - The library can easily be integrated into customized software, such as - parameter estimation tools. -

-

- When using the Simulation Core Library, please cite:
- Roland Keller, Alexander Dörr, Akito Tabira, Akira Funahashi, Michael - J. Ziller, Richard Adams, Nicolas Rodriguez, Nicolas Le Novère, - Noriko Hiroi, Hannes Planatscher, Andreas Zell, and Andreas Dräger. - The systems biology simulation core algorithm. BMC Systems Biology, 7:55, - July 2013. [ DOI | - link | - pdf ] -

- -

How to integrate Simulation Core Library into your software?

-

- You just have to add the provided jar-file simulation-core-library.jar to the class path of your Java project. - Then you have access to all classes of the library. - This library depends on the following third-party libraries: -

- For SED-ML support, the following - additional libraries are required: - - Please make sure to include the correct third-party libraries into your - class path before working with this library. -

- -

The provided integration methods

-

- The RosenbrockSolver is best suitable for integrating stiff differential - equation systems and also has a precise timing of SBML events. It is taken - and adapted from - Kotcon et al. (2011) -

- Several further solvers have been taken from the - Apache Commons - Math Library and wrapped into our library: -

- - The following solvers have been implemented additionally and are fast, but - not suitable for all differential equation systems: - -

- For a full list of available solvers, see org.simulator.math.odes. -

- -

Reading an SBML model and creating the respective differential equation - system

-

- A model can be read in by using the SBMLReader - class from JSBML. - With the model in memory the SBMLinterpreter - can create the differential equation system that provides the basis for - simulation: -

-

-      Model model = (new SBMLReader()).readSBML(sbmlfile).getModel();
- SBMLinterpreter interpreter = new SBMLinterpreter(model); -
-

- For more documentation about working with SBML models in simulations see - org.simulator.sbml. -

- -

Simulation of a differential equation system

-

- The created differential equation system can then be simulated with a - chosen solver and given time points. - The result is stored in a data structure called - MultiTable. -

-

-      AbstractDESSolver solver = new RosenbrockSolver();
- double[] timePoints = {0.0, 0.1, 0.2, 0.3, 0.4, 0.5};
- MultiTable solution = solver.solve(interpreter, interpreter.getInitialValues(), timePoints); -
- -

Using SED-ML for simulation

-

- The following example shows how to read in a File f (in - SED-ML format) and how to run a simulation - described in this file afterwards. The simulation results are stored in a - MultiTable: -

- -

-      SEDMLDocument doc = Libsedml.readDocument(f);
- SedML sedml = doc.getSBMLModel();
- Output wanted = sedml.getOutputs().get(0);
- SedMLSBMLSimulatorExecutor exe = new SedMLSBMLSimulatorExecutor(sedml, wanted);
- Map res = exe.runSimulations();
- MultiTable solution = exe.processSimulationResults(wanted, res);
-
- -

- For more information about how to use SED-ML to execute your simulation - experiments, see org.simulator.sedml. -

- -

Simulation of the models in the SBML Test Suite

-

- You can run the simulation of the models in the - SBML Test - Suite by using the command below. TestSuiteDirectory denotes - the directory containing your copy of the (entire) SBML test suite. - Here we assume that the actual test cases are located in the sub-folder - cases/semantic/ within the TestSuiteDirectory on your - computer. - The simulation is conducted for the models with numbers from first - to last (these numbers are the indices of the models in the test - suite, without leading zeros). -

-

-      java -cp SimulationCoreLibrary_vX.Y_incl-libs.jar org.simulator.SBMLTestSuiteRunner TestSuiteDirectory/cases/semantic/ first last
-    
- Please note that, you have to replace _vX.Y_ within the library's - name by the current release number, e.g., 1.2. -

- For example, if you like to simulate all test suite models ranging from - 00259 to 00326, simply call the algorithm with - first = 259 and last = 326. -

- -

- Note that for the sake of a simple configuration, the simulation is - started using default settings for the selection of the - integration routine, step size etc. -

- -

- The - SBML Test Suite Database - provides an up-to-date overview about the - capabilities of various SBML-compliant solver implementations. -

- -

Simulation of the models from BioModels database

-

- In a similar way, you can also download and simulate all models from - BioModels database: -


-      java -cp SimulationCoreLibrary_vX.Y_incl-libs.jar org.simulator.TestBiomodels BioModelsDirectory/ first last
-    
- Again, you have to replace _vX.Y_ within the library's - name by the current release number, e.g., 1.2. Please use the variables - first and last without leading zeros as in the previous - case. The variable BioModelsDirectory gives the path to your local - copy of - BioModels database. -

-

- As in the previous case, the simulation is conducted using default - settings. -

- -

Listening to SBML constraint violation

-

- In version 1.3 a new listener interface has been added to - this library, which can be used to perform user-defined actions upon violation - of a Constraint's math expression during a simulation. - A simple implementation is already included in this package, - which logs violation at the - Level.WARNING using standard Java™ - logging (see Logger). - By default the - SBMLinterpreter adds this - SimpleConstraintListener to its internal list of - ConstraintListeners. -

- -

- You can remove this listener by calling the method - SBMLinterpreter.removeConstraintListener(int), - with the argument 0 for the first listener in the list, - and add your own listener implementation with the help of method - SBMLinterpreter.addConstraintListener(ConstraintListener). -

-

The following example demonstrates how you can easily define your customized - ConstraintListener: -


-      double timeEnd = 5d;
- SBMLDocument doc = SBMLReader.read(new File("path/to/file.xml"));
- SBMLinterpreter interpreter = new SBMLinterpreter(doc.getModel());
- interpreter.addConstraintListener(new ConstraintListener() {
-   /* (non-Javadoc)
-    * @see org.simulator.sbml.ConstraintListener#processViolation(org.simulator.sbml.ConstraintEvent)
-    */

-   public void processViolation(ConstraintEvent evt) {
-     System.err.println("Constraint violated at time " + evt.getTime() + ": " + evt.getSource().getMath().toFormula());
-   }
- });
- solver.solve(interpreter, interpreter.getInitialValues(), 0d, timeEnd); -
-

-

- You can find more details about this topic in the description of package - org.simulator.sbml. +

Simulation Core Library: Documentation

+ +

About Simulation Core Library

+

+ The Java™ API Simulation Core Library comprises a collection of + integrators for differential equation systems combined with an interpreter + for the Systems Biology Markup Language + (SBML). + It is the first simulation library that is based on + JSBML. + The user can read an SBML model and simulate it with one of the provided + numerical integration routines. All SBML levels and versions are + supported. + The library can easily be integrated into customized software, such as + parameter estimation tools. +

+

+ When using the Simulation Core Library, please cite:
+ Roland Keller, Alexander Dörr, Akito Tabira, Akira Funahashi, Michael + J. Ziller, Richard Adams, Nicolas Rodriguez, Nicolas Le Novère, + Noriko Hiroi, Hannes Planatscher, Andreas Zell, and Andreas Dräger. + The systems biology simulation core algorithm. BMC Systems Biology, 7:55, + July 2013. [ DOI | + link | + pdf ] +

+ +

How to integrate Simulation Core Library into your software?

+

+ You just have to add the provided jar-file simulation-core-library.jar to the class path of your Java project. + Then you have access to all classes of the library. + This library depends on the following third-party libraries: +

+ For SED-ML support, the following + additional libraries are required: + + Please make sure to include the correct third-party libraries into your + class path before working with this library. +

+ +

The provided integration methods

+

+ The RosenbrockSolver is best suitable for integrating stiff differential + equation systems and also has a precise timing of SBML events. It is taken + and adapted from + Kotcon et al. (2011) +

+ Several further solvers have been taken from the + Apache Commons + Math Library and wrapped into our library: +

+ + The following solvers have been implemented additionally and are fast, but + not suitable for all differential equation systems: + +

+ For a full list of available solvers, see org.simulator.math.odes. +

+ +

Reading an SBML model and creating the respective differential equation + system

+

+ A model can be read in by using the SBMLReader + class from JSBML. + With the model in memory the SBMLinterpreter + can create the differential equation system that provides the basis for + simulation: +

+

+      Model model = (new SBMLReader()).readSBML(sbmlfile).getModel();
+ SBMLinterpreter interpreter = new SBMLinterpreter(model); +
+

+ For more documentation about working with SBML models in simulations see + org.simulator.sbml. +

+ +

Simulation of a differential equation system

+

+ The created differential equation system can then be simulated with a + chosen solver and given time points. + The result is stored in a data structure called + MultiTable. +

+

+      AbstractDESSolver solver = new RosenbrockSolver();
+ double[] timePoints = {0.0, 0.1, 0.2, 0.3, 0.4, 0.5};
+ MultiTable solution = solver.solve(interpreter, interpreter.getInitialValues(), timePoints); +
+ +

Using SED-ML for simulation

+

+ The following example shows how to read in a File f (in + SED-ML format) and how to run a simulation + described in this file afterwards. The simulation results are stored in a + MultiTable: +

+ +

+      SEDMLDocument doc = Libsedml.readDocument(f);
+ SedML sedml = doc.getSBMLModel();
+ Output wanted = sedml.getOutputs().get(0);
+ SedMLSBMLSimulatorExecutor exe = new SedMLSBMLSimulatorExecutor(sedml, wanted);
+ Map res = exe.runSimulations();
+ MultiTable solution = exe.processSimulationResults(wanted, res);
+
+ +

+ For more information about how to use SED-ML to execute your simulation + experiments, see org.simulator.sedml. +

+ +

Simulation of the models in the SBML Test Suite

+

+ You can run the simulation of the models in the + SBML Test + Suite by using the command below. TestSuiteDirectory denotes + the directory containing your copy of the (entire) SBML test suite. + Here we assume that the actual test cases are located in the sub-folder + cases/semantic/ within the TestSuiteDirectory on your + computer. + The simulation is conducted for the models with numbers from first + to last (these numbers are the indices of the models in the test + suite, without leading zeros). +

+

+      java -cp SimulationCoreLibrary_vX.Y_incl-libs.jar org.simulator.SBMLTestSuiteRunner TestSuiteDirectory/cases/semantic/ first last
+    
+ Please note that, you have to replace _vX.Y_ within the library's + name by the current release number, e.g., 1.2. +

+ For example, if you like to simulate all test suite models ranging from + 00259 to 00326, simply call the algorithm with + first = 259 and last = 326. +

+ +

+ Note that for the sake of a simple configuration, the simulation is + started using default settings for the selection of the + integration routine, step size etc. +

+ +

+ The + SBML Test Suite Database + provides an up-to-date overview about the + capabilities of various SBML-compliant solver implementations. +

+ +

Simulation of the models from BioModels database

+

+ In a similar way, you can also download and simulate all models from + BioModels database: +


+      java -cp SimulationCoreLibrary_vX.Y_incl-libs.jar org.simulator.TestBiomodels BioModelsDirectory/ first last
+    
+ Again, you have to replace _vX.Y_ within the library's + name by the current release number, e.g., 1.2. Please use the variables + first and last without leading zeros as in the previous + case. The variable BioModelsDirectory gives the path to your local + copy of + BioModels database. +

+

+ As in the previous case, the simulation is conducted using default + settings. +

+ +

Listening to SBML constraint violation

+

+ In version 1.3 a new listener interface has been added to + this library, which can be used to perform user-defined actions upon violation + of a Constraint's math expression during a simulation. + A simple implementation is already included in this package, + which logs violation at the + Level.WARNING using standard Java™ + logging (see Logger). + By default the + SBMLinterpreter adds this + SimpleConstraintListener to its internal list of + ConstraintListeners. +

+ +

+ You can remove this listener by calling the method + SBMLinterpreter.removeConstraintListener(int), + with the argument 0 for the first listener in the list, + and add your own listener implementation with the help of method + SBMLinterpreter.addConstraintListener(ConstraintListener). +

+

The following example demonstrates how you can easily define your customized + ConstraintListener: +


+      double timeEnd = 5d;
+ SBMLDocument doc = SBMLReader.read(new File("path/to/file.xml"));
+ SBMLinterpreter interpreter = new SBMLinterpreter(doc.getModel());
+ interpreter.addConstraintListener(new ConstraintListener() {
+   /* (non-Javadoc)
+    * @see org.simulator.sbml.ConstraintListener#processViolation(org.simulator.sbml.ConstraintEvent)
+    */

+   public void processViolation(ConstraintEvent evt) {
+     System.err.println("Constraint violated at time " + evt.getTime() + ": " + evt.getSource().getMath().toFormula());
+   }
+ });
+ solver.solve(interpreter, interpreter.getInitialValues(), 0d, timeEnd); +
+

+

+ You can find more details about this topic in the description of package + org.simulator.sbml.

diff --git a/docs/publications/2012_BMC_SystBiol/readme.html b/docs/publications/2012_BMC_SystBiol/readme.html index 93095a2f..2108a857 100644 --- a/docs/publications/2012_BMC_SystBiol/readme.html +++ b/docs/publications/2012_BMC_SystBiol/readme.html @@ -1,237 +1,237 @@ - - - -BioMed Central TeX template files - - - -

BioMed Central TeX template  - Version 0.4 (January 27th 2006)

-

1 BioMed Central LaTeX template distribution

- - - - - - - - - - - - - - - - - - - - - -
-

bmc_article.tex

-
-

The BioMed Central  manuscript template. - Edit a copy of this file.

-
-

bmc_article.bib

-
-

A sample BibTeX bibliography file used to create a .bbl by BibTeX using the bmc_article.bst file

-
-

bmc_article.bst

-
-

The BibTeX bibliography style file - for the BioMed Central reference format

-
-

bmc_article.cls

-
-

Page layout for for manuscripts. This makes small - changes to the standard article template

-
-

readme.html

-
-

This document.

-
-

 

-

 

-

2 Requirements

-

2.1

-

The BioMed Central TeX template - should work with TeX distributions on any platform – it has been tested with - TeXShop on Mac OS - X and MiKTeX for Windows.

-

2.2

-

In order to submit a manuscript - as a .tex file to BioMed Central, you must

- -

If your TeX manuscript does not - meet the criteria above it will need to be converted to DVI format prior to - submission.

-

2 Guidelines for creating your manuscript using TeX

-

2.1

-

Follow the guidelines in the BioMed Central instructions - for authors given at http://www.biomedcentral.com/info/authors/

-

2.2

-

Make - sure your manuscript is compiled with LaTeX2e by using documentclass{.. - . } and not documentstyle{. . . } in the preamble at the top of your - .tex document.

-

A template manuscript is supplied entitled bmc_article.tex which -sets up the preferred page layout based on the standard article.cls. Two different styles are supplied; Review Style, which produces single column double spaced text, and Publication Style which produces two-column text. They can be toggled by commenting or uncommenting the relevant lines in the TeX file. -

-

2.3

-

Make sure that you only a single .tex document - for the entire manuscript, as you will need to upload it as a single file (together - with its associated formatted bibliography file) . Do not use the \input command to include other .tex files.

-

2.4

-

The BioMed Central template uses the cite.sty - citation style and url.sty for url references. It also uses ifthen.sty and multicol.sty You should also use these - during the creation of your manuscript.

-

See

-

http://www.ctan.org/tex-archive/macros/latex/contrib/cite/cite.sty, -
- http://www.ctan.org/tex-archive/macros/latex/contrib/misc/url.sty

- http://www.ctan.org/tex-archive/macros/latex/unpacked/ifthen.sty
- http://www.ctan.org/tex-archive/macros/latex209/contrib/geomsty/multicol.sty

-

for these style files if they are not in your local - archive.

-

cite.sty turns [1,2,3,4] into [1-4].

-

url.sty formats urls so they can be broken down - cleanly when overflowing the right text boundary.

-

3 BibTeX

-

References must be formatted with BibTeX using - the BioMed Central style file.

-

i.e. when using the template, do not alter the command: - \bibliographystyle{bmc_article}

-

The bibliography datafile is referred to with \bibliography{datafile1, - . . . , . . . }

-

The template makes use of a sample bibliography called - bmc_article.bib - you should update the \bibliography tag to - refer to your own bibliography.

-

4 Notes on uploading your manuscript

-

4.1

-

Make sure you are submitting only one .tex document - Please note that figures, large tables and any other - reference material should be submitted as separate files, not embedded in the - manuscript.

-

4.2

-

A .bbl file is generated when you use BibTeX - to format your article's reference list. It contains formatted details of all - references used in the manuscript. After uploading a TeX file to BioMed Central, - you will then be prompted to upload the .bbl file which goes with it..
-

-

5 The TeX article layout

-

This is the sectioning for a BMC-series Research Article l - manuscript submission . . .
For other types of articles or for non-BMC series journals, see the relevant section headings at http://www.biomedcentral.com/info/authors/

-

• Abstract

-

– Background

-

– Results

-

– Conclusions

-

• Background

-

• Methods

-

• Results and Discussion

-

• Conclusions

-• Authors contributions

-

• Acknowledgements

-

• References

-

• Figures

-

• Tables

-

• Additional files

-

5 Further information

-

The latest version of the BioMed Central TeX - template distribution, and full instructions on its use, are available here:

-

http://www.biomedcentral.com/info/ifora/tex/

- - + + + +BioMed Central TeX template files + + + +

BioMed Central TeX template  - Version 0.4 (January 27th 2006)

+

1 BioMed Central LaTeX template distribution

+ + + + + + + + + + + + + + + + + + + + + +
+

bmc_article.tex

+
+

The BioMed Central  manuscript template. + Edit a copy of this file.

+
+

bmc_article.bib

+
+

A sample BibTeX bibliography file used to create a .bbl by BibTeX using the bmc_article.bst file

+
+

bmc_article.bst

+
+

The BibTeX bibliography style file + for the BioMed Central reference format

+
+

bmc_article.cls

+
+

Page layout for for manuscripts. This makes small + changes to the standard article template

+
+

readme.html

+
+

This document.

+
+

 

+

 

+

2 Requirements

+

2.1

+

The BioMed Central TeX template + should work with TeX distributions on any platform – it has been tested with + TeXShop on Mac OS + X and MiKTeX for Windows.

+

2.2

+

In order to submit a manuscript + as a .tex file to BioMed Central, you must

+ +

If your TeX manuscript does not + meet the criteria above it will need to be converted to DVI format prior to + submission.

+

2 Guidelines for creating your manuscript using TeX

+

2.1

+

Follow the guidelines in the BioMed Central instructions + for authors given at http://www.biomedcentral.com/info/authors/

+

2.2

+

Make + sure your manuscript is compiled with LaTeX2e by using documentclass{.. + . } and not documentstyle{. . . } in the preamble at the top of your + .tex document.

+

A template manuscript is supplied entitled bmc_article.tex which +sets up the preferred page layout based on the standard article.cls. Two different styles are supplied; Review Style, which produces single column double spaced text, and Publication Style which produces two-column text. They can be toggled by commenting or uncommenting the relevant lines in the TeX file. +

+

2.3

+

Make sure that you only a single .tex document + for the entire manuscript, as you will need to upload it as a single file (together + with its associated formatted bibliography file) . Do not use the \input command to include other .tex files.

+

2.4

+

The BioMed Central template uses the cite.sty + citation style and url.sty for url references. It also uses ifthen.sty and multicol.sty You should also use these + during the creation of your manuscript.

+

See

+

http://www.ctan.org/tex-archive/macros/latex/contrib/cite/cite.sty, +
+ http://www.ctan.org/tex-archive/macros/latex/contrib/misc/url.sty

+ http://www.ctan.org/tex-archive/macros/latex/unpacked/ifthen.sty
+ http://www.ctan.org/tex-archive/macros/latex209/contrib/geomsty/multicol.sty

+

for these style files if they are not in your local + archive.

+

cite.sty turns [1,2,3,4] into [1-4].

+

url.sty formats urls so they can be broken down + cleanly when overflowing the right text boundary.

+

3 BibTeX

+

References must be formatted with BibTeX using + the BioMed Central style file.

+

i.e. when using the template, do not alter the command: + \bibliographystyle{bmc_article}

+

The bibliography datafile is referred to with \bibliography{datafile1, + . . . , . . . }

+

The template makes use of a sample bibliography called + bmc_article.bib - you should update the \bibliography tag to + refer to your own bibliography.

+

4 Notes on uploading your manuscript

+

4.1

+

Make sure you are submitting only one .tex document + Please note that figures, large tables and any other + reference material should be submitted as separate files, not embedded in the + manuscript.

+

4.2

+

A .bbl file is generated when you use BibTeX + to format your article's reference list. It contains formatted details of all + references used in the manuscript. After uploading a TeX file to BioMed Central, + you will then be prompted to upload the .bbl file which goes with it..
+

+

5 The TeX article layout

+

This is the sectioning for a BMC-series Research Article l + manuscript submission . . .
For other types of articles or for non-BMC series journals, see the relevant section headings at http://www.biomedcentral.com/info/authors/

+

• Abstract

+

– Background

+

– Results

+

– Conclusions

+

• Background

+

• Methods

+

• Results and Discussion

+

• Conclusions

+• Authors contributions

+

• Acknowledgements

+

• References

+

• Figures

+

• Tables

+

• Additional files

+

5 Further information

+

The latest version of the BioMed Central TeX + template distribution, and full instructions on its use, are available here:

+

http://www.biomedcentral.com/info/ifora/tex/

+ + diff --git a/lib/celldesigner_fern.jar b/lib/celldesigner_fern.jar new file mode 100644 index 00000000..ed85d0f7 Binary files /dev/null and b/lib/celldesigner_fern.jar differ diff --git a/lib/colt/colt-2.1.4.jar b/lib/colt/colt-2.1.4.jar new file mode 100644 index 00000000..9c829c3f Binary files /dev/null and b/lib/colt/colt-2.1.4.jar differ diff --git a/lib/colt/concurrent-1.3.4.jar b/lib/colt/concurrent-1.3.4.jar new file mode 100644 index 00000000..551f3471 Binary files /dev/null and b/lib/colt/concurrent-1.3.4.jar differ diff --git a/lib/cytoscape_fern.jar b/lib/cytoscape_fern.jar new file mode 100644 index 00000000..5f330187 Binary files /dev/null and b/lib/cytoscape_fern.jar differ diff --git a/lib/jdom-1.1.3.jar b/lib/jdom-1.1.3.jar new file mode 100644 index 00000000..a2877278 Binary files /dev/null and b/lib/jdom-1.1.3.jar differ diff --git a/lib/sbmlj.jar b/lib/sbmlj.jar new file mode 100644 index 00000000..42be4c4c Binary files /dev/null and b/lib/sbmlj.jar differ diff --git a/modules/cellDesigner/CellDesignerNetworkWrapper.java b/modules/cellDesigner/CellDesignerNetworkWrapper.java new file mode 100644 index 00000000..ea91c90a --- /dev/null +++ b/modules/cellDesigner/CellDesignerNetworkWrapper.java @@ -0,0 +1,87 @@ +/* + * Created on 03.03.2008 + * + * To change the template for this generated file go to + * Window>Preferences>Java>Code Generation>Code and Comments + */ +package fern.cellDesigner; + +import java.util.HashMap; +import java.util.Map; + +import jp.sbi.celldesigner.plugin.PluginModel; +import jp.sbi.celldesigner.plugin.PluginReaction; +import jp.sbi.celldesigner.plugin.PluginSpecies; +import fern.network.AbstractNetworkImpl; +import fern.network.AmountManager; +import fern.network.AnnotationManagerImpl; +import fern.network.DefaultAmountManager; +import fern.network.sbml.SBMLPropensityCalculator; + +public class CellDesignerNetworkWrapper extends AbstractNetworkImpl { + + private PluginModel model; + private Map speciesToReference = new HashMap(); + + public CellDesignerNetworkWrapper(PluginModel model) { + super(model.getName()); + this.model = model; + + createAnnotationManager(); + createSpeciesMapping(); + createAmountManager(); + createAdjacencyLists(); + createPropensityCalulator(); + } + + @Override + protected void createAdjacencyLists() { + adjListPro = new int[model.getNumReactions()][]; + adjListRea = new int[model.getNumReactions()][]; + for (int r=0; r(model.getNumSpecies()); + indexToSpeciesId = new String[model.getNumSpecies()]; + + for (int s=0; sPreferences>Java>Code Generation>Code and Comments + */ +package fern.cellDesigner; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.sbml.libsbml.ASTNode; + +import jp.sbi.celldesigner.plugin.PluginModel; +import jp.sbi.celldesigner.plugin.PluginReaction; + + +import fern.network.AmountManager; +import fern.network.ComplexDependenciesPropensityCalculator; +import fern.network.sbml.MathTree; +import fern.network.sbml.SBMLPropensityCalculator; +import fern.simulation.Simulator; + +/** + * Propensity calculator which is used for {@link SBMLNetwork}s. The propensities are + * calculated by using a {@link MathTree} derived by the MathML representation of the + * kinetic law for each reaction. + * + * @author Florian Erhard + * + */ +public class CellDesignerPropensityCalculator extends SBMLPropensityCalculator { + + private PluginModel model; + private MathTree[] propensities; + private Map globalParameter; + + /** + * Creates the {@link MathTree}s and parses the parameters. + * + * @param net sbml netowrk + */ + public CellDesignerPropensityCalculator(PluginModel model, CellDesignerNetworkWrapper net) { + super(null); + this.model = model; + globalParameter = new HashMap(); + for (int i=0; i localParameter = new HashMap(); + PluginReaction reaction = model.getReaction(i); + for (int j=0; j getGlobalParameters() { + return globalParameter; + } + + public double calculatePropensity(int reaction, AmountManager amount, Simulator sim) { + double re = propensities[reaction].calculate(amount, sim); + if (re<0) throw new RuntimeException("The propensity of reaction "+sim.getNet().getReactionName(reaction)+" is negative"); + return Math.abs(re); + } + + public List getKineticLawSpecies(int reaction) { + return propensities[reaction].getSpecies(); + } + + + + + +} diff --git a/modules/cellDesigner/FernCellDesignerPlugin.java b/modules/cellDesigner/FernCellDesignerPlugin.java new file mode 100644 index 00000000..9cd76ca7 --- /dev/null +++ b/modules/cellDesigner/FernCellDesignerPlugin.java @@ -0,0 +1,70 @@ +/* + * Created on 03.03.2008 + * + * To change the template for this generated file go to + * Window>Preferences>Java>Code Generation>Code and Comments + */ +package fern.cellDesigner; + +import java.awt.event.ActionEvent; + +import jp.sbi.celldesigner.plugin.CellDesignerPlugin; +import jp.sbi.celldesigner.plugin.PluginAction; +import jp.sbi.celldesigner.plugin.PluginMenu; +import jp.sbi.celldesigner.plugin.PluginMenuItem; +import jp.sbi.celldesigner.plugin.PluginSBase; +import fern.cellDesigner.ui.MainFrame; + +public class FernCellDesignerPlugin extends CellDesignerPlugin { + + public FernCellDesignerPlugin(){ + PluginMenu menu = new PluginMenu("FERN"); + PluginAction action = new FernPluginAction(); + PluginMenuItem item = new PluginMenuItem("Simulation", action); + menu.add(item); + addCellDesignerPluginMenu(menu); + } + + + private class FernPluginAction extends PluginAction { + + public void myActionPerformed(ActionEvent arg0) { + new MainFrame(FernCellDesignerPlugin.this).setVisible(true); + } + } + + + public void SBaseAdded(PluginSBase arg0) { + + } + + + public void SBaseChanged(PluginSBase arg0) { + + } + + + public void SBaseDeleted(PluginSBase arg0) { + + } + + + public void addPluginMenu() { + + } + + + public void modelClosed(PluginSBase arg0) { + + } + + + public void modelOpened(PluginSBase arg0) { + } + + + public void modelSelectChanged(PluginSBase model) { + + } + +} \ No newline at end of file diff --git a/modules/cellDesigner/ui/ExtendedPane.java b/modules/cellDesigner/ui/ExtendedPane.java new file mode 100644 index 00000000..b39f7141 --- /dev/null +++ b/modules/cellDesigner/ui/ExtendedPane.java @@ -0,0 +1,279 @@ +/* + * Created on 03.03.2008 + * + * To change the template for this generated file go to + * Window>Preferences>Java>Code Generation>Code and Comments + */ +package fern.cellDesigner.ui; + +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.ScrollPane; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.Iterator; +import java.util.Set; +import java.util.TreeSet; + +import javax.swing.AbstractAction; +import javax.swing.DefaultListModel; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JSeparator; +import javax.swing.JTextField; + +import fern.network.Network; + + + + +public class ExtendedPane extends JPanel { + + private static final long serialVersionUID = 1L; + public static final String sep = "________"; + + + MainFrame main ; + + JComboBox nodeTypePicker = null; + JComboBox reactionPicker = null; + JComboBox speciesPicker = null; + JComboBox initialAmountPicker = null; + JComboBox reactioncoefficientPicker = null; + + JTextField eps = null; + JTextField nc = null; + JTextField thresh = null; + JTextField num = null; + + JList notList = null; + JList trendList = null; + + public ExtendedPane(MainFrame mainFrame) { + this.main = mainFrame; + + initializeComponents(); + } + + + + private void initializeComponents() { + removeAll(); + + setLayout(new GridBagLayout()); + GridBagConstraints c = new GridBagConstraints(); + c.insets = new Insets(3,3,3,3); + c.anchor = GridBagConstraints.NORTHWEST; + + + + c.gridx=0; + c.gridy++; + c.gridwidth=2; + add(new JLabel("Tau leaping parameter: "),c); + c.gridx=2; + add(createTauLeapingHelpButton(),c); + + c.gridx=0; + c.gridy++; + c.gridwidth=1; + add(new JLabel("eps:"),c); + c.gridx=1; + if (eps==null) eps = new JTextField("0.03",6); + add(eps,c); + c.gridx=2; + add(new JLabel("n_c:"),c); + c.gridx=3; + if (nc==null) nc = new JTextField("10",6); + add(nc,c); + + c.gridy++; + c.gridx=0; + add(new JLabel("threshold:"),c); + c.gridx=1; + if (thresh==null) thresh = new JTextField("10",6); + add(thresh,c); + c.gridx=2; + add(new JLabel("#exact:"),c); + c.gridx=3; + if (num==null) num = new JTextField("100",6); + add(num,c); + + c.gridy++; + c.gridwidth=4; + add(new JSeparator(),c); + + c.gridx=0; + c.gridy++; + add(new JLabel("Trends:"),c); + + c.anchor = GridBagConstraints.CENTER; + c.gridy++; + add(createTrendLists(),c); + } + + private JPanel createTrendLists() { + if (notList==null) { + notList = new JList(new DefaultListModel()); +// ((DefaultListModel)notList.getModel()).addElement("A"); +// ((DefaultListModel)notList.getModel()).addElement("B"); +// ((DefaultListModel)notList.getModel()).addElement("C"); +// ((DefaultListModel)notList.getModel()).addElement("D"); +// ((DefaultListModel)notList.getModel()).addElement("E"); +// ((DefaultListModel)notList.getModel()).addElement("F"); + } + if (trendList==null) { + trendList = new JList(new DefaultListModel()); + } + + + JPanel pane = new JPanel(new GridBagLayout()); + GridBagConstraints c = new GridBagConstraints(); + c.insets = new Insets(3,3,3,3); + + c.gridheight=3; + ScrollPane scroll1 = new ScrollPane(); + scroll1.setPreferredSize(new Dimension(120,95)); + scroll1.add(notList); + pane.add(scroll1,c); + + c.gridheight=1; + c.gridx=1; + c.gridy=0; + JButton r = new JButton(">"); + r.addActionListener(new TrendActionListener()); + pane.add(r,c); + + c.gridy=1; + JButton m = new JButton("-"); + m.addActionListener(new TrendActionListener()); + pane.add(m,c); + + c.gridy=2; + JButton l = new JButton("<"); + l.addActionListener(new TrendActionListener()); + pane.add(l,c); + + c.gridheight=3; + c.gridx=2; + c.gridy=0; + ScrollPane scroll2 = new ScrollPane(); + scroll2.setPreferredSize(new Dimension(120,95)); + scroll2.add(trendList); + pane.add(scroll2,c); + + + return pane; + } + + private class TrendActionListener implements ActionListener { + public void actionPerformed(ActionEvent e) { + String a = ((JButton)e.getSource()).getText(); + if (a.equals(">") && notList.getSelectedValues().length>0) { + int pos = trendList.getSelectedIndex(); + if (pos==-1) pos = trendList.getModel().getSize(); + for (Object o : notList.getSelectedValues()) + ((DefaultListModel)trendList.getModel()).add(pos++,o); + for (Object o : notList.getSelectedValues()) + ((DefaultListModel)notList.getModel()).removeElement(o); + } + else if (a.equals("<") && trendList.getSelectedValues().length>0) { + int pos = notList.getSelectedIndex(); + if (pos==-1) pos = notList.getModel().getSize(); + for (Object o : trendList.getSelectedValues()) + if (!o.equals(sep)) + ((DefaultListModel)notList.getModel()).add(pos++,o); + for (Object o : trendList.getSelectedValues()) + ((DefaultListModel)trendList.getModel()).removeElement(o); + } else if (a.equals("-")) { + int pos = trendList.getSelectedIndex(); + if (pos==-1) pos = trendList.getModel().getSize(); + ((DefaultListModel)trendList.getModel()).add(pos,sep); + } + } + } + + private JButton createTauLeapingHelpButton() { + return new JButton(new AbstractAction("?") { + private static final long serialVersionUID = 1L; + public void actionPerformed(ActionEvent arg0) { + StringBuilder sb = new StringBuilder(); + sb.append("Here you can specify parameters for the tau leaping procedures:\n\n"); + sb.append("eps\nerror bounding\n\n"); + sb.append("n_c\nthreshold for critical reactions\n\n"); + sb.append("threshold\nfor temporarily abandoning tau leaping\n\n"); + sb.append("#exact\nhow many exact SSA steps when abandoning tau leaping\n\n"); + sb.append("For more explanation refer to Cao et al., Efficient step\n"); + sb.append("size selection for the tau-leaping simulation method,\n"); + sb.append("Journal of chemical physics 124"); + JOptionPane.showMessageDialog(main, sb.toString()); + } + }); + } + + + + + + public void setSpecies(Network net) { + ((DefaultListModel)notList.getModel()).removeAllElements(); + ((DefaultListModel)trendList.getModel()).removeAllElements(); + + for (int i=0; iPreferences>Java>Code Generation>Code and Comments + */ +package fern.cellDesigner.ui; + + +import java.awt.BorderLayout; +import java.awt.Container; +import java.awt.event.ActionEvent; +import java.io.PrintWriter; +import java.util.LinkedList; + +import javax.swing.AbstractAction; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JProgressBar; + +import fern.cellDesigner.CellDesignerNetworkWrapper; +import fern.cellDesigner.FernCellDesignerPlugin; +import fern.network.Network; +import fern.simulation.Simulator; +import fern.simulation.algorithm.AbstractBaseTauLeaping; +import fern.simulation.controller.SimulationController; +import fern.simulation.observer.AmountIntervalObserver; +import fern.simulation.observer.InstantOutputObserver; +import fern.tools.gnuplot.GnuPlot; + +public class MainFrame extends JFrame { + + private static final int numSamplePoints = 100; + private static final long serialVersionUID = 1L; + private CellDesignerNetworkWrapper network = null; + + private OverviewPane overview = null; + private ExtendedPane extended = null; + + private JButton startStopButton = null; + private JProgressBar progress = null; + + private SimulationAction startSimulation; + + private FernCellDesignerPlugin plugin = null; + + public MainFrame(FernCellDesignerPlugin plugin) { + super("FERN plugin"); + + this.plugin = plugin; + + + setResizable(false); + setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + + + startSimulation = new SimulationAction(); + + initializeComponents(); + pack(); + reloadNetwork(); + } + + + public void reloadNetwork() { + + try { + + this.network = new CellDesignerNetworkWrapper(plugin.getSelectedModel()); + startStopButton.setEnabled(getNetwork()!=null && getNetwork().getNumSpecies()>0); + + overview.setErrorMessage(getNetwork(), null); + extended.setSpecies(this.network); + } catch (Exception e) { + overview.setErrorMessage(getNetwork(),e.getMessage()); + } + } + + + public CellDesignerNetworkWrapper getNetwork() { + return network; + } + + + private void initializeComponents() { + Container pane = getContentPane(); + + overview = new OverviewPane(this); + extended = new ExtendedPane(this); + + pane.add(overview, BorderLayout.WEST); + pane.add(extended, BorderLayout.EAST); + + startStopButton = new JButton(startSimulation); + progress = new JProgressBar(); + JPanel south = new JPanel(new BorderLayout()); + south.add(startStopButton,BorderLayout.NORTH); + south.add(progress,BorderLayout.SOUTH); + pane.add(south,BorderLayout.SOUTH); + } + + + public static void main(String[] args) { + new MainFrame(null).setVisible(true); + } + + + private class SimulationAction extends AbstractAction { + private static final long serialVersionUID = 1L; + + boolean cancelFlag = false; + + public SimulationAction() { + super("Start"); + } + + public void cancel() { + cancelFlag = true; + } + + public void actionPerformed(ActionEvent e) { + if (startStopButton.getText().equals("Start")){ + startStopButton.setText("Stop"); + cancelFlag = false; + + progress.setMaximum((int) (overview.getTime()*100)); + progress.setValue(0); + overview.setEnabled(false); + extended.setEnabled(false); + + new Thread(new Runnable() { + + public void run() { + try { + int runs = overview.getNumRuns();; + Simulator sim = overview.getSimulator(); + AmountIntervalObserver[] trendObserver = createTrendObservers(sim, extended.getTrendSpecies(), overview.getTime()); +// sim.addObserver(new InstantOutputObserver(sim,new PrintWriter("sim.log"))); + if (sim instanceof AbstractBaseTauLeaping) { + ((AbstractBaseTauLeaping)sim).setEpsilon(extended.getEpsilon()); + ((AbstractBaseTauLeaping)sim).setNCritical(extended.getNc()); + ((AbstractBaseTauLeaping)sim).setUseSimpleFactor(extended.getThreshold()); + ((AbstractBaseTauLeaping)sim).setNumSimpleCalls(extended.getNum()); + } + while (!cancelFlag && runs--!=0) { + sim.start(new SimulationController() { + double recentTime = 0; + public boolean goOn(Simulator sim) { + boolean goOn = sim.getTime() t = new LinkedList(); + + double interval = time/numSamplePoints; + int s = 0; + for (int i=0; iPreferences>Java>Code Generation>Code and Comments + */ +package fern.cellDesigner.ui; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.ScrollPane; +import java.awt.event.ActionEvent; +import java.io.File; +import java.io.IOException; +import java.io.StringWriter; + +import javax.swing.AbstractAction; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JComboBox; +import javax.swing.JFileChooser; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JSeparator; +import javax.swing.JTextArea; +import javax.swing.JTextField; +import javax.swing.filechooser.FileFilter; + +import fern.network.Network; +import fern.network.NetworkLoader; +import fern.network.fernml.FernMLNetwork; +import fern.simulation.Simulator; +import fern.simulation.algorithm.GibsonBruckSimulator; +import fern.simulation.algorithm.GillespieEnhanced; +import fern.simulation.algorithm.GillespieSimple; +import fern.simulation.algorithm.HybridMaximalTimeStep; +import fern.simulation.algorithm.TauLeapingAbsoluteBoundSimulator; +import fern.simulation.algorithm.TauLeapingRelativeBoundSimulator; +import fern.simulation.algorithm.TauLeapingSpeciesPopulationBoundSimulator; +import fern.tools.NetworkTools; + +public class OverviewPane extends JPanel { + private static final long serialVersionUID = 1L; + + private MainFrame main ; + private JLabel networkStatus = null; + private JTextArea message = null; + private JComboBox simulator = null; + private JTextField time = null; + private JTextField runs = null; + + public OverviewPane(MainFrame mainFrame) { + this.main = mainFrame; + + initializeComponents(); + } + + + + private void initializeComponents() { + removeAll(); + + setLayout(new GridBagLayout()); + GridBagConstraints c = new GridBagConstraints(); + c.insets = new Insets(3,3,3,3); + + c.gridx=0; + c.gridy=0; + add(new JLabel("Network:"),c); + + c.gridx=1; + if (networkStatus==null) networkStatus = new JLabel(); + add(networkStatus,c); + + c.gridwidth=2; + c.gridx=0; + c.gridy++; + JPanel buttons = new JPanel(); + buttons.add(getReloadButton()); +// buttons.add(getLoadButton()); + buttons.add(getSaveButton()); + add(buttons,c); + + c.gridx=0; + c.gridy++; + ScrollPane scroll = new ScrollPane(); + scroll.setSize(300, 150); + add(scroll,c); + + if (message==null) message = new JTextArea(); + message.setEditable(false); + scroll.add(message); + + + c.gridx=0; + c.gridy++; + add(new JSeparator(JSeparator.HORIZONTAL),c); + + c.gridx=0; + c.gridy++; + c.anchor = GridBagConstraints.WEST; + add(new JLabel("Simulator:"),c); + + c.gridx=0; + c.gridy++; + c.anchor = GridBagConstraints.CENTER; + if (simulator == null) + simulator = new JComboBox(new String[] { + "GillespieSimple", + "GillespieEnhanced", + "GibsonBruckSimulator", + "TauLeapingAbsoluteBoundSimulator", + "TauLeapingRelativeBoundSimulator", + "TauLeapingSpeciesPopulationBoundSimulator", + "Hybrid Maximal Time Step Method" + }); + + add(simulator,c); + + c.gridx=0; + c.gridy++; + c.gridwidth = 1; + c.anchor=GridBagConstraints.WEST; + add(new JLabel("Time:"),c); + + c.gridx=1; + if (time==null) + time = new JTextField("10",10); + add(time,c); + + c.gridx=0; + c.gridy++; + c.gridwidth = 1; + c.anchor=GridBagConstraints.WEST; + add(new JLabel("Runs:"),c); + + c.gridx=1; + if (runs==null) + runs = new JTextField("1",10); + add(runs,c); + + repaint(); + + } + + + + private Component getSaveButton() { + return new JButton(new AbstractAction("Save") { + private static final long serialVersionUID = 1L; + public void actionPerformed(ActionEvent e) { + JFileChooser dia = new JFileChooser(); + dia.addChoosableFileFilter(new FileFilter() { + @Override + public boolean accept(File f) { + if (f.isDirectory()) { + return true; + } + return f.getName().endsWith(".xml"); + } + + @Override + public String getDescription() { + return "FernML-Files (*.xml)"; + } + }); + if (dia.showSaveDialog(main)!=JFileChooser.CANCEL_OPTION) { + try { + new FernMLNetwork(main.getNetwork()).saveToFile(dia.getSelectedFile()); + } catch (IOException e1) {} + } + } + + }); + } + + + +// private Component getLoadButton() { +// return new JButton(new AbstractAction("Load") { +// private static final long serialVersionUID = 1L; +// public void actionPerformed(ActionEvent e) { +// JFileChooser dia = new JFileChooser(); +// NetworkLoader.addTypesToFileChooser(dia); +// +// if (dia.showSaveDialog(main)!=JFileChooser.CANCEL_OPTION) { +// try { +// Network net = NetworkLoader.readNetwork(dia.getSelectedFile()); +// main.loadNetwork(net); +// } catch (Exception e1) {} +// } +// } +// +// }); +// } + + + + private Component getReloadButton() { + return new JButton(new AbstractAction("Reload") { + private static final long serialVersionUID = 1L; + public void actionPerformed(ActionEvent e) { + main.reloadNetwork(); + } + + }); + } + + public void setErrorMessage(Network net,String message) { + if (message==null) { + StringWriter sw = new StringWriter(); + try { + NetworkTools.dumpNetwork(net,sw); + } catch (IOException e) {} + this.message.setText(sw.toString()); + } else { + this.message.setText("Error:\n\n"+message); + } + + if (net!=null && net.getNumSpecies()>0) { + networkStatus.setText("ok"); + networkStatus.setForeground(new Color(0,127,0)); + } + else if (net!=null && net.getNumSpecies()==0) { + networkStatus.setText("empty"); + networkStatus.setForeground(Color.red); + } + else { + networkStatus.setText("not loaded"); + networkStatus.setForeground(Color.red); + } + + } + + public double getTime() { + double re = 0; + try { + re = Double.parseDouble(time.getText()); + } catch (Exception e){} + return re; + } + + public int getNumRuns() { + return Integer.parseInt(runs.getText()); + } + + + public Simulator getSimulator() throws Exception { + switch (simulator.getSelectedIndex()) { + case 0: + return new GillespieSimple(main.getNetwork()); + case 1: + return new GillespieEnhanced(main.getNetwork()); + case 2: + return new GibsonBruckSimulator(main.getNetwork()); + case 3: + return new TauLeapingAbsoluteBoundSimulator(main.getNetwork()); + case 4: + return new TauLeapingRelativeBoundSimulator(main.getNetwork()); + case 5: + return new TauLeapingSpeciesPopulationBoundSimulator(main.getNetwork()); + case 6: + return new HybridMaximalTimeStep(main.getNetwork()); + } + return (Simulator) ClassLoader.getSystemClassLoader().loadClass("fern.simulation.algorithm."+(String) simulator.getSelectedItem()).getConstructor(ClassLoader.getSystemClassLoader().loadClass("fern.network.Network")).newInstance(main.getNetwork()); + } + + @Override + public void setEnabled(boolean enabled) { + setEnabledDeep(enabled, this); + } + + private void setEnabledDeep(boolean enabled, Container component) { + for (Component c : component.getComponents()) { + c.setEnabled(enabled); + if (c instanceof Container) setEnabledDeep(enabled, (Container) c); + } + } + + +} diff --git a/modules/cytoscape/ColorCalculator.java b/modules/cytoscape/ColorCalculator.java new file mode 100644 index 00000000..e64e6617 --- /dev/null +++ b/modules/cytoscape/ColorCalculator.java @@ -0,0 +1,83 @@ +package fern.cytoscape; + +import java.awt.Color; +import fern.tools.ColorSpectrum; + +public class ColorCalculator implements Cloneable { + + private Color reactionColor = Color.red; + private Color amountBottomColor = Color.white; + private Color amountTopColor = Color.black; + private Scale scale = Scale.Linear; + private double scaleMax = -1; + + public Object clone() throws CloneNotSupportedException { + ColorCalculator re = new ColorCalculator(); + re.reactionColor = reactionColor; + re.amountBottomColor = amountBottomColor; + re.amountTopColor = amountTopColor; + re.scale = scale; + re.scaleMax = scaleMax; + return re; + } + + public Color getReactionColor() { + return reactionColor; + } + + public void setReactionColor(Color reactionColor) { + this.reactionColor = reactionColor; + } + + public Color getAmountBottomColor() { + return amountBottomColor; + } + + public void setAmountBottomColor(Color amountBottomColor) { + this.amountBottomColor = amountBottomColor; + } + + public Color getAmountTopColor() { + return amountTopColor; + } + + public void setAmountTopColor(Color amountTopColor) { + this.amountTopColor = amountTopColor; + } + + public Scale getScale() { + return scale; + } + + public void setScale(Scale scale) { + this.scale = scale; + } + + public double getScaleMax() { + return scaleMax; + } + + public void setScaleMax(double scaleMax) { + this.scaleMax = scaleMax; + } + + public Color getColor(double d, double max) { + float val; + if (scale==Scale.Linear) + val =(float)(d/(scaleMax<0 ? max : scaleMax)); + else + val = (float)(Math.log(d+1)/Math.log((scaleMax<0 ? max : scaleMax)+1)); + return ColorSpectrum.getSpectrum(val, amountBottomColor, amountTopColor); + } + + + + public static enum Scale { + Linear, Logarithmic + } + + + + + +} diff --git a/modules/cytoscape/CytoscapeAnnotationManager.java b/modules/cytoscape/CytoscapeAnnotationManager.java new file mode 100644 index 00000000..08130113 --- /dev/null +++ b/modules/cytoscape/CytoscapeAnnotationManager.java @@ -0,0 +1,118 @@ +package fern.cytoscape; + +import java.util.Arrays; +import java.util.Collection; + +import cytoscape.Cytoscape; +import cytoscape.data.CyAttributes; +import fern.network.AnnotationManager; + +public class CytoscapeAnnotationManager implements AnnotationManager { + + + + + CytoscapeNetworkWrapper network; + public CytoscapeAnnotationManager(CytoscapeNetworkWrapper network) { + this.network = network; + } + + + +// public double[] getReactionCoefficients() { +// CyAttributes na = network.getNodeAttributeObject(); +// +//// if (na.getType(getReactionCoefficientIdentifier())==CyAttributes.TYPE_UNDEFINED) +//// throw new IllegalArgumentException(getReactionCoefficientIdentifier()+" is not specified in the net!"); +// +// double[] reactionCoeffient = new double[network.getNumReactions()]; +// for (int i=0; i getNetworkAnnotationTypes() { + return Arrays.asList(Cytoscape.getNetworkAttributes().getAttributeNames()); + } + + public String getReactionAnnotation(int reaction, String typ) { + return getAttribute(Cytoscape.getNodeAttributes(),network.reactions[reaction].getNode().getIdentifier(),typ); + } + + public Collection getReactionAnnotationTypes(int reaction) { + return Arrays.asList(Cytoscape.getNodeAttributes().getAttributeNames()); + } + + public String getSpeciesAnnotation(int species, String typ) { + return getAttribute(Cytoscape.getNodeAttributes(),network.species[species].getNode().getIdentifier(),typ); + } + + public Collection getSpeciesAnnotationTypes(int species) { + return Arrays.asList(Cytoscape.getNodeAttributes().getAttributeNames()); + } + + public void setNetworkAnnotation(String typ, String annotation) { + Cytoscape.getNetworkAttributes().setAttribute(network.net.getIdentifier(), typ, annotation); + } + + public void setReactionAnnotation(int reaction, String typ, + String annotation) { + Cytoscape.getNodeAttributes().setAttribute(network.reactions[reaction].getNode().getIdentifier(), typ, annotation); + } + + public void setSpeciesAnnotation(int species, String typ, String annotation) { + Cytoscape.getNodeAttributes().setAttribute(network.species[species].getNode().getIdentifier(), typ, annotation); } + + + + + + + + + + +} diff --git a/modules/cytoscape/CytoscapeColorChangeObserver.java b/modules/cytoscape/CytoscapeColorChangeObserver.java new file mode 100644 index 00000000..031f26bd --- /dev/null +++ b/modules/cytoscape/CytoscapeColorChangeObserver.java @@ -0,0 +1,210 @@ +package fern.cytoscape; + +import java.awt.Color; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.Map; + +import javax.swing.JOptionPane; + +import cytoscape.CyNetwork; +import cytoscape.Cytoscape; +import cytoscape.visual.NodeAppearance; +import cytoscape.visual.NodeAppearanceCalculator; +import fern.cytoscape.ui.ExtendedPane; +import fern.simulation.Simulator; +import fern.simulation.Simulator.FireType; +import fern.simulation.observer.AmountIntervalObserver; +import fern.simulation.observer.Observer; +import fern.tools.gnuplot.GnuPlot; +import giny.model.Node; +import giny.view.NodeView; + +public class CytoscapeColorChangeObserver extends Observer { + + final static int numSamplePoints = 100; + + boolean visualize; + boolean showTrendSteps; + CytoscapeNetworkWrapper net; + LinkedList activated = null; +// ColorChangingNodeAppeareanceCalculator changingNodeAppeareanceCalculator; +// NodeAppearanceCalculator defaultNodeAppereanceCalculator; + private FernVisualStyle style = null; + AmountIntervalObserver[] trendObserver = null; + GnuPlot[] gp = null; + double[] oldTheta; + + public CytoscapeColorChangeObserver(boolean visualize, boolean showTrendSteps, Simulator sim, CytoscapeNetworkWrapper net, FernVisualStyle style, String[] trendSpecies, double time) { + super(sim); + this.visualize = visualize; + this.showTrendSteps = showTrendSteps; + this.net = net; + this.style = style; + + activated = new LinkedList(); +// this.defaultNodeAppereanceCalculator = defaultNodeAppereanceCalculator; + + + createTrendObservers(trendSpecies,time); + } + + private void createTrendObservers(String[] trendSpecies, double time) { + LinkedList t = new LinkedList(); + + double interval = time/numSamplePoints; + int s = 0; + for (int i=0; ioldTheta[i]) { + oldTheta[i] = trendObserver[i].getTheta(); + gp[i].clearData(); + trendObserver[i].toGnuplotRecent(gp[i]); + gp[i].setVisible(true); + gp[i].plot(); + } + } + } catch (Exception e) {} + } + if (visualize) { + + while (!activated.isEmpty()) + style.setReactionUnFire(activated.poll().getNode()); +// changingNodeAppeareanceCalculator.unsetColor(activated.poll().getNode()); + + double maxAmount = 0; + for (int i=0; i colorMapping; + public ColorChangingNodeAppeareanceCalculator(NodeAppearanceCalculator parent) { + super(parent); + this.colorMapping = new HashMap(); + } + + @Override + public void calculateNodeAppearance(NodeAppearance app, Node node,CyNetwork net) { + // TODO Auto-generated method stub + super.calculateNodeAppearance(app,node,net); + if (colorMapping.containsKey(node)) + app.setFillColor(colorMapping.get(node)); + } + + public void setColor(Node n, Color c) { + colorMapping.put(n, c); + } + public void unsetColor(Node n) { + colorMapping.remove(n); + } + } + + @Override + public void theta(double theta) { + // TODO Auto-generated method stub + + } + +} diff --git a/modules/cytoscape/CytoscapeNetworkWrapper.java b/modules/cytoscape/CytoscapeNetworkWrapper.java new file mode 100644 index 00000000..fd85d288 --- /dev/null +++ b/modules/cytoscape/CytoscapeNetworkWrapper.java @@ -0,0 +1,173 @@ +package fern.cytoscape; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; + +import cytoscape.CyNetwork; +import cytoscape.CyNode; +import cytoscape.data.CyAttributes; +import cytoscape.view.CyNetworkView; +import fern.network.AbstractNetworkImpl; +import fern.network.AmountManager; +import fern.network.ArrayKineticConstantPropensityCalculator; +import giny.model.Edge; +import giny.model.Node; +import giny.view.NodeView; + +public class CytoscapeNetworkWrapper extends AbstractNetworkImpl { + + + CyNetwork net = null; + CyNetworkView cyView = null; + CyAttributes nodeAttr = null; + NetworkChecker checker = null; + NodeView[] reactions = null; + NodeView[] species = null; + + + public CytoscapeNetworkWrapper(NetworkChecker checker, CyNetwork net, CyNetworkView cyView, CyAttributes nodeAttr) { + super(net.getIdentifier()); + this.checker = checker; + this.net = net; + this.cyView = cyView; + this.nodeAttr = nodeAttr; + + + createAnnotationManager(); + createArrays(); + createSpeciesMapping(); + createAmountManager(); + createAdjacencyLists(); + createPropensityCalulator(); + + } + + public long getInitialAmount(int species) { +// return getNodeAttributeObject().getDoubleAttribute(getSpeciesName(species), INITIAL_AMOUNT_IDENTIFIER).longValue(); + return checker.getNodeParameter().getSpeciesInitialAmount(this.species[species].getNode()); + } + + public void setInitialAmount(int species, long value) { +// getNodeAttributeObject().setAttribute(getSpeciesName(species), INITIAL_AMOUNT_IDENTIFIER, (double)value); + checker.getNodeParameter().setSpeciesInitialAmount(this.species[species].getNode(), value); + } + + @SuppressWarnings("unchecked") + private void createArrays() { +// CytoscapeAnnotationManager prop = (CytoscapeAnnotationManager)annotationManager; + + LinkedList reactionCreate = new LinkedList(); + LinkedList speciesCreate = new LinkedList(); + + for (Iterator i = cyView.getNodeViewsIterator(); i.hasNext();) { + NodeView nodeView = i.next(); + CyNode node = (CyNode) nodeView.getNode(); + //if (nodeAttr.getStringAttribute(node.getIdentifier(), prop.getTypeIdentifier() ).equals(prop.getSpeciesIdentifier())) + if (checker.getNodeClassifier().isSpeciesNode(node)) + speciesCreate.add(nodeView); +// else if (nodeAttr.getStringAttribute(node.getIdentifier(), prop.getTypeIdentifier()).equals(prop.getReactionIdentifier())) + else if (checker.getNodeClassifier().isReactionNode(node)) + reactionCreate.add(nodeView); + else + throw new IllegalArgumentException("NodeType unknown"); + } + + reactions = reactionCreate.toArray(new NodeView[reactionCreate.size()]); + species = speciesCreate.toArray(new NodeView[speciesCreate.size()]); + } + + @Override + protected void createAdjacencyLists() { + +// CytoscapeAnnotationManager prop = (CytoscapeAnnotationManager) getAnnotationManager(); + + adjListPro = new int[reactions.length][]; + adjListRea = new int[reactions.length][]; + for (int i=0; i(species.length); + indexToSpeciesId = new String[species.length]; + for (int i=0; i colorMapping = null; + public static ColorCalculator colorCalculator = new ColorCalculator(); + + public FernVisualStyle() { + super("FERN"); + + colorMapping = new HashMap(); + networkChecker = new NetworkChecker(); + + setNodeAppearanceCalculator(createNodeAppearanceCalculator()); + setEdgeAppearanceCalculator(createEdgeAppearanceCalculator()); + setGlobalAppearanceCalculator(createGlobalAppearanceCalculator()); + } + + private GlobalAppearanceCalculator createGlobalAppearanceCalculator() { + return Cytoscape.getVisualMappingManager().getVisualStyle().getGlobalAppearanceCalculator(); + } + + private NodeAppearanceCalculator createNodeAppearanceCalculator() { + return new NodeAppearanceCalculator() { + + @Override + public void calculateNodeAppearance(NodeAppearance appr, Node node,CyNetwork network) { + networkChecker.isValid(); + if (networkChecker.getNodeClassifier()!=null && networkChecker.getNodeClassifier().isReactionNode(node)) { + appr.setShape(ShapeNodeRealizer.DIAMOND); + appr.setLabel(""); + } else if (networkChecker.getNodeClassifier()!=null && networkChecker.getNodeClassifier().isSpeciesNode(node)){ + appr.setShape(ShapeNodeRealizer.ELLIPSE); + appr.setLabel(node.getIdentifier()); + } else { + appr.setShape(ShapeNodeRealizer.RECT); + appr.setLabel(node.getIdentifier()); + } + appr.setSize(20); + appr.setWidth(20); + appr.setHeight(20); + appr.setToolTip(node.getIdentifier()); + appr.setBorderColor(Color.black); + appr.setBorderLineType(LineType.LINE_1); + appr.setFont(new Font("Arial",Font.PLAIN,10)); + appr.setLabelColor(Color.black); + appr.setLabelPosition(new LabelPosition()); + appr.setNodeSizeLocked(true); + if (colorMapping.containsKey(node)) + appr.setFillColor(colorMapping.get(node)); + else + appr.setFillColor(Color.white); + } + + @Override + public NodeAppearance calculateNodeAppearance(Node node,CyNetwork network) { + NodeAppearance app = new NodeAppearance(); + calculateNodeAppearance(app, node, network); + return app; + } + }; + } + + private EdgeAppearanceCalculator createEdgeAppearanceCalculator() { + return new EdgeAppearanceCalculator() { + @Override + public void calculateEdgeAppearance(EdgeAppearance appr, Edge edge,CyNetwork network) { + appr.setSourceArrow(Arrow.NONE); + appr.setTargetArrow(Arrow.NONE); + if (networkChecker.getEdgeClassifier()!=null && networkChecker.getNodeClassifier()!=null) { + if (networkChecker.getEdgeClassifier().isReactionToProductEdge(edge)) { + if (networkChecker.getNodeClassifier().isSpeciesNode(edge.getSource())) + appr.setSourceArrow(Arrow.BLACK_ARROW); + else if (networkChecker.getNodeClassifier().isSpeciesNode(edge.getTarget())) + appr.setTargetArrow(Arrow.BLACK_ARROW); + } + if (networkChecker.getEdgeClassifier().isReactionToReactantEdge(edge)) { + if (networkChecker.getNodeClassifier().isReactionNode(edge.getSource())) + appr.setSourceArrow(Arrow.BLACK_ARROW); + else if (networkChecker.getNodeClassifier().isReactionNode(edge.getTarget())) + appr.setTargetArrow(Arrow.BLACK_ARROW); + } + } + appr.setColor(Color.black); + appr.setLabel(""); + appr.setLineType(LineType.LINE_1); + appr.setToolTip(edge.getSource().getIdentifier()+"\n->\n"+edge.getTarget().getIdentifier()); + } + + @Override + public EdgeAppearance calculateEdgeAppearance(Edge edge,CyNetwork network) { + EdgeAppearance app = new EdgeAppearance(); + calculateEdgeAppearance(app, edge, network); + return app; + } + }; + } + + public void setNetworkChecker(NetworkChecker networkChecker) { + this.networkChecker = networkChecker; + Cytoscape.getCurrentNetworkView().redrawGraph(true, true); + } + + public void setValue(Node node, double val, double max) { + colorMapping.put(node, colorCalculator.getColor(val,max)); + } + + public void setReactionFire(Node node) { + colorMapping.put(node, colorCalculator.getReactionColor()); + } + + public void setReactionUnFire(Node node) { + colorMapping.remove(node); + } + + public void resetColors() { + colorMapping.clear(); + Cytoscape.getCurrentNetworkView().redrawGraph(true, true); + } + +} diff --git a/modules/cytoscape/NetworkChecker.java b/modules/cytoscape/NetworkChecker.java new file mode 100644 index 00000000..cae0cb58 --- /dev/null +++ b/modules/cytoscape/NetworkChecker.java @@ -0,0 +1,296 @@ +package fern.cytoscape; + +import giny.model.Edge; +import giny.model.Node; +import giny.view.EdgeView; +import giny.view.NodeView; + +import java.util.Iterator; + +import cytoscape.CyEdge; +import cytoscape.CyNetwork; +import cytoscape.CyNode; +import cytoscape.Cytoscape; +import cytoscape.data.CyAttributes; +import cytoscape.view.CyNetworkView; + +public class NetworkChecker { + + private CyAttributes nodeAttr; + private CyNetwork network; + private CyNetworkView view; + + private NodeClassifier nodeClassifier = null; + private EdgeClassifier edgeClassifier = null; + private NodeParameter nodeParameter = null; + private Boolean valid = null; + + public String nodeType; + public Object nodeTypeReaction; + public Object nodeTypeSpecies; + public String coefficient; + public String initialAmount; + + public NetworkChecker() { + this( + "sbml type", + "reaction", + "species", + "reaction coefficient", + "sbml initial amount" + ); + } + + public NetworkChecker(String nodeType, Object nodeTypeReaction, Object nodeTypeSpecies, String coefficient, String initialAmount) { + network = Cytoscape.getCurrentNetwork(); + view = Cytoscape.getCurrentNetworkView(); + nodeAttr = Cytoscape.getNodeAttributes(); + + this.nodeType = nodeType; + this.nodeTypeReaction = nodeTypeReaction; + this.nodeTypeSpecies = nodeTypeSpecies; + this.coefficient = coefficient; + this.initialAmount = initialAmount; + } + + public boolean isValid() { + if (valid==null) + try { + check(); + return true; + } catch (Exception e) { + return false; + } + else return valid.booleanValue(); + } + + public void check() { + valid = Boolean.FALSE; + // create nodeClassifier + if (nodeTypeReaction instanceof String) + nodeClassifier = new NodeClassifierByAnnotation(nodeType, (String)nodeTypeReaction, (String)nodeTypeSpecies); + else if (nodeTypeReaction instanceof Integer) + nodeClassifier = new NodeClassifierByAnnotation(nodeType, (Integer)nodeTypeReaction, (Integer)nodeTypeSpecies); + else if (nodeTypeReaction instanceof Double) + nodeClassifier = new NodeClassifierByAnnotation(nodeType, (Double)nodeTypeReaction, (Double)nodeTypeSpecies); + else throw new IllegalArgumentException("Only String, Integer and Double are permitted as types!"); + + if (!nodeClassifier.isUsable()) + throw new IllegalArgumentException("Could not distinguish between reactions and species!\nTry to choose valid keys for the nodes."); + + edgeClassifier = new EdgeClassifierByIdentifier(); + if (!edgeClassifier.isUsable()) + edgeClassifier = new EdgeClassifierByDirection(); + if (!edgeClassifier.isUsable()) + throw new RuntimeException("Could not determine edge types!"); + + nodeParameter = new NodeParameter(coefficient,initialAmount); + + if (!nodeParameter.isUsable()) + throw new IllegalArgumentException("The nodes do not contain reaction coefficients / initial amounts!"); + + valid = Boolean.TRUE; + } + + public NodeClassifier getNodeClassifier() { + return nodeClassifier; + } + + public EdgeClassifier getEdgeClassifier() { + return edgeClassifier; + } + + public NodeParameter getNodeParameter() { + return nodeParameter; + } + + + public class NodeParameter { + + String coeff; + String initAm; + + public NodeParameter(String coeff, String initAm) { + this.coeff = coeff; + this.initAm = initAm; + } + + public double getReactionCoefficient(Node n) { + Number re; + switch (nodeAttr.getType(coeff)) { + case CyAttributes.TYPE_FLOATING: + re = nodeAttr.getDoubleAttribute(n.getIdentifier(), coeff); + break; + case CyAttributes.TYPE_INTEGER: + re = nodeAttr.getIntegerAttribute(n.getIdentifier(), coeff); + break; + default: + throw new RuntimeException(coeff+" has wrong type or is not present as identifier for the reaction coefficients in reaction nodes.\nOnly Double and Integer are permitted!\n\nTry to load node attributes or change the field name!"); + } + if (re==null) + throw new RuntimeException(coeff+" has wrong type or is not present as identifier for the reaction coefficients in reaction nodes.\nOnly Double and Integer are permitted!\n\nTry to load node attributes or change the field name!"); + return re.doubleValue(); + } + + public long getSpeciesInitialAmount(Node n){ + Number re; + switch (nodeAttr.getType(initAm)) { + case CyAttributes.TYPE_FLOATING: + re = nodeAttr.getDoubleAttribute(n.getIdentifier(), initAm); + break; + case CyAttributes.TYPE_INTEGER: + re = nodeAttr.getIntegerAttribute(n.getIdentifier(), initAm); + break; + default: + throw new RuntimeException(initAm+" has wrong type or is not present as identifier for the initial amounts in species nodes.\nOnly Double and Integer are permitted!\n\nTry to load node attributes or change the field name!"); + } + if (re==null) + throw new RuntimeException(initAm+" has wrong type or is not present as identifier for the initial amounts in species nodes.\nOnly Double and Integer are permitted!\n\nTry to load node attributes or change the field name!"); + return re.longValue(); + } + + public void setSpeciesInitialAmount(Node n, long value) { + switch (nodeAttr.getType(initAm)) { + case CyAttributes.TYPE_FLOATING: + nodeAttr.setAttribute(n.getIdentifier(), initAm,(double)value); + break; + case CyAttributes.TYPE_INTEGER: + nodeAttr.setAttribute(n.getIdentifier(), initAm,(int)value); + break; + default: + throw new RuntimeException(initAm+" has wrong type. Only Double and Integer are permitted!"); + } + } + + @SuppressWarnings("unchecked") + public boolean isUsable() { + for (Iterator i = view.getNodeViewsIterator(); i.hasNext();) { + NodeView nodeView = i.next(); + CyNode node = (CyNode) nodeView.getNode(); + if (nodeClassifier.isReactionNode(node) && getReactionCoefficient(node)<=0) + return false; + if (nodeClassifier.isSpeciesNode(node) && getSpeciesInitialAmount(node)<0) + return false; + } + return true; + } + + + } + + + + public interface NodeClassifier { + public boolean isReactionNode(Node n); + public boolean isSpeciesNode(Node n); + public boolean isUsable(); + } + + public class NodeClassifierByAnnotation implements NodeClassifier { + + private String typeIdentifier; + private T reactionType; + private T speciesType; + + public NodeClassifierByAnnotation(String typeIdentifier, T reactionType, T speciesType) { + this.typeIdentifier = typeIdentifier; + this.reactionType = reactionType; + this.speciesType = speciesType; + } + + public boolean isReactionNode(Node n) { + if (reactionType instanceof String) + return reactionType.equals(nodeAttr.getStringAttribute(n.getIdentifier(), typeIdentifier)); + else if (reactionType instanceof Integer) + return reactionType.equals(nodeAttr.getIntegerAttribute(n.getIdentifier(), typeIdentifier)); + else if (reactionType instanceof Double) + return reactionType.equals(nodeAttr.getDoubleAttribute(n.getIdentifier(), typeIdentifier)); + else + throw new RuntimeException("Only String, Integer and Double allowed as node identifier type!"); + } + + public boolean isSpeciesNode(Node n) { + if (speciesType instanceof String) + return speciesType.equals(nodeAttr.getStringAttribute(n.getIdentifier(), typeIdentifier)); + else if (speciesType instanceof Integer) + return speciesType.equals(nodeAttr.getIntegerAttribute(n.getIdentifier(), typeIdentifier)); + else if (speciesType instanceof Double) + return speciesType.equals(nodeAttr.getDoubleAttribute(n.getIdentifier(), typeIdentifier)); + else + throw new RuntimeException("Only String, Integer and Double allowed as node identifier type!"); + } + + @SuppressWarnings("unchecked") + public boolean isUsable() { + for (Iterator i = view.getEdgeViewsIterator(); i.hasNext();) { + EdgeView edgeView = i.next(); + CyEdge edge = (CyEdge) edgeView.getEdge(); + if (!isSpeciesNode(edge.getSource()) && !isReactionNode(edge.getSource())) + return false; + if (!isSpeciesNode(edge.getTarget()) && !isReactionNode(edge.getTarget())) + return false; + if (isSpeciesNode(edge.getSource()) && isSpeciesNode(edge.getTarget())) + return false; + if (isReactionNode(edge.getSource()) && isReactionNode(edge.getTarget())) + return false; + } + return true; + } + + } + + + public interface EdgeClassifier { + public boolean isReactionToProductEdge(Edge e); + public boolean isReactionToReactantEdge(Edge e); + public boolean isUsable(); + } + + public class EdgeClassifierByIdentifier implements EdgeClassifier { + public boolean isReactionToProductEdge(Edge e) { + return e.getIdentifier().contains("product"); + } + + public boolean isReactionToReactantEdge(Edge e) { + return e.getIdentifier().contains("reactant"); + } + + @SuppressWarnings("unchecked") + public boolean isUsable() { + for (Iterator i = view.getEdgeViewsIterator(); i.hasNext();) { + EdgeView edgeView = i.next(); + CyEdge edge = (CyEdge) edgeView.getEdge(); + if (!isReactionToProductEdge(edge) && !isReactionToReactantEdge(edge)) + return false; + } + return true; + } + } + + public class EdgeClassifierByDirection implements EdgeClassifier { + + public boolean isReactionToProductEdge(Edge e) { + return nodeClassifier.isReactionNode(e.getSource()) && nodeClassifier.isSpeciesNode(e.getTarget()); + } + + public boolean isReactionToReactantEdge(Edge e) { + return nodeClassifier.isSpeciesNode(e.getSource()) && nodeClassifier.isReactionNode(e.getTarget()); + } + + @SuppressWarnings("unchecked") + public boolean isUsable() { + for (Iterator i = view.getNodeViewsIterator(); i.hasNext();) { + NodeView nodeView = i.next(); + CyNode node = (CyNode) nodeView.getNode(); + int index = network.getIndex(node); + if (nodeClassifier.isReactionNode(node)) + if (network.getAdjacentEdgeIndicesArray(index,false,true,false).length<=0 ||network.getAdjacentEdgeIndicesArray(index, false, false, true).length<=0) + return false; + } + return true; + } + + } + + +} diff --git a/modules/cytoscape/ui/ColorPicker.java b/modules/cytoscape/ui/ColorPicker.java new file mode 100644 index 00000000..69bd045c --- /dev/null +++ b/modules/cytoscape/ui/ColorPicker.java @@ -0,0 +1,224 @@ +package fern.cytoscape.ui; + +import java.awt.Color; +import java.awt.Container; +import java.awt.Font; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; + +import javax.swing.AbstractAction; +import javax.swing.JButton; +import javax.swing.JColorChooser; +import javax.swing.JComboBox; +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JTextField; + +import fern.cytoscape.ColorCalculator; +import fern.cytoscape.FernVisualStyle; +import fern.cytoscape.ColorCalculator.Scale; + +public class ColorPicker extends JDialog { + + private static final long serialVersionUID = 1L; + private ColorField reactionColor = null; + private ColorField amountBottomColor = null; + private ColorField amountTopColor = null; + private PreviewField preview = null; + private JComboBox scaleType = null; + private JTextField scaleMax = null; + private ColorCalculator colcalc; + private PreviewChangeAction action = null; + + public ColorPicker(Frame frame) { + super(frame, "Colors",ModalityType.APPLICATION_MODAL); + try { + this.colcalc = (ColorCalculator) FernVisualStyle.colorCalculator.clone(); + } catch (CloneNotSupportedException e) {} + action = new PreviewChangeAction(); + + setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + initializeComponents(); + pack(); + } + + private void initializeComponents() { + + Container pane = getContentPane(); + pane.removeAll(); + + preview = new PreviewField(colcalc); + reactionColor = new ColorField(colcalc.getReactionColor()); + amountBottomColor = new ColorField(colcalc.getAmountBottomColor()); + amountTopColor = new ColorField(colcalc.getAmountTopColor()); + scaleType = new JComboBox(new ColorCalculator.Scale[] {Scale.Linear,Scale.Logarithmic}); + scaleType.setSelectedItem(colcalc.getScale()); + scaleMax = new JTextField(colcalc.getScaleMax()<0 ? "" : colcalc.getScaleMax()+"",8); + + amountBottomColor.addMouseListener(action); + amountTopColor.addMouseListener(action); + scaleType.addActionListener(action); + scaleMax.addMouseListener(action); + reactionColor.addMouseListener(action); + + pane.setLayout(new GridBagLayout()); + GridBagConstraints c = new GridBagConstraints(); + c.insets = new Insets(3,3,3,3); + c.anchor = GridBagConstraints.WEST; + + c.gridx=0; + c.gridy=0; + pane.add(new JLabel("Reaction:"),c); + + c.gridy++; + pane.add(new JLabel("Amount scale;"),c); + c.gridy++; + pane.add(new JLabel("Maximal value:"),c); + c.gridy++; + c.gridwidth=2; + JLabel exp = new JLabel("(leave emtpy if you want to scale up to the actual maximum)"); + exp.setFont(new Font("",0,9)); + pane.add(exp,c); + c.gridwidth=1; + c.gridy++; + pane.add(amountBottomColor,c); + + c.anchor = GridBagConstraints.CENTER; + c.gridx=1; + c.gridy=0; + pane.add(reactionColor,c); + c.gridy++; + pane.add(scaleType,c); + c.gridy++; + pane.add(scaleMax,c); + c.anchor = GridBagConstraints.EAST; + c.gridy++; + c.gridy++; + pane.add(amountTopColor,c); + + c.anchor = GridBagConstraints.CENTER; + c.gridwidth=2; + c.gridx=0; + c.gridy++; + pane.add(preview,c); + + c.gridwidth=1; + c.gridy++; + c.anchor = GridBagConstraints.EAST; + pane.add(new JButton(new AbstractAction("Ok") { + private static final long serialVersionUID = 1L; + + public void actionPerformed(ActionEvent e) { + double s = -1; + try { s = Double.parseDouble(scaleMax.getText()); } catch (Exception ed) {} + colcalc.setScaleMax(s); + + FernVisualStyle.colorCalculator = colcalc; + dispose(); + } + }),c); + + c.gridx++; + c.anchor = GridBagConstraints.WEST; + pane.add(new JButton(new AbstractAction("Cancel") { + private static final long serialVersionUID = 1L; + public void actionPerformed(ActionEvent e) { + dispose(); + } + }),c); + + } + + private class PreviewChangeAction extends MouseAdapter implements ActionListener { + + @Override + public void mouseClicked(MouseEvent e) { + update(); + } + + public void actionPerformed(ActionEvent arg0) { + update(); + } + + private void update() { + colcalc.setAmountBottomColor(amountBottomColor.getBackground()); + colcalc.setAmountTopColor(amountTopColor.getBackground()); + colcalc.setReactionColor(reactionColor.getBackground()); + colcalc.setScale((Scale) scaleType.getSelectedItem()); + + preview.repaint(); + } + } + + private static class PreviewField extends JTextField { + private static final long serialVersionUID = 1L; + + ColorCalculator colcalc; + public PreviewField(ColorCalculator colcalc) { + super(25); + this.colcalc = colcalc; + + } + + @Override + public void paint(Graphics g) { + double max = colcalc.getScaleMax(); + colcalc.setScaleMax(getWidth()); + Graphics2D g2 = (Graphics2D) g; + for (int i=0; i"); + r.addActionListener(new TrendActionListener()); + pane.add(r,c); + + c.gridy=1; + JButton m = new JButton("-"); + m.addActionListener(new TrendActionListener()); + pane.add(m,c); + + c.gridy=2; + JButton l = new JButton("<"); + l.addActionListener(new TrendActionListener()); + pane.add(l,c); + + c.gridheight=3; + c.gridx=2; + c.gridy=0; + ScrollPane scroll2 = new ScrollPane(); + scroll2.setPreferredSize(new Dimension(120,95)); + scroll2.add(trendList); + pane.add(scroll2,c); + + + return pane; + } + + private class TrendActionListener implements ActionListener { + public void actionPerformed(ActionEvent e) { + String a = ((JButton)e.getSource()).getText(); + if (a.equals(">") && notList.getSelectedValues().length>0) { + int pos = trendList.getSelectedIndex(); + if (pos==-1) pos = trendList.getModel().getSize(); + for (Object o : notList.getSelectedValues()) + ((DefaultListModel)trendList.getModel()).add(pos++,o); + for (Object o : notList.getSelectedValues()) + ((DefaultListModel)notList.getModel()).removeElement(o); + } + else if (a.equals("<") && trendList.getSelectedValues().length>0) { + int pos = notList.getSelectedIndex(); + if (pos==-1) pos = notList.getModel().getSize(); + for (Object o : trendList.getSelectedValues()) + if (!o.equals(sep)) + ((DefaultListModel)notList.getModel()).add(pos++,o); + for (Object o : trendList.getSelectedValues()) + ((DefaultListModel)trendList.getModel()).removeElement(o); + } else if (a.equals("-")) { + int pos = trendList.getSelectedIndex(); + if (pos==-1) pos = trendList.getModel().getSize(); + ((DefaultListModel)trendList.getModel()).add(pos,sep); + } + } + } + + private JButton createTauLeapingHelpButton() { + return new JButton(new AbstractAction("?") { + private static final long serialVersionUID = 1L; + public void actionPerformed(ActionEvent arg0) { + StringBuilder sb = new StringBuilder(); + sb.append("Here you can specify parameters for the tau leaping procedures:\n\n"); + sb.append("eps\nerror bounding\n\n"); + sb.append("n_c\nthreshold for critical reactions\n\n"); + sb.append("threshold\nfor temporarily abandoning tau leaping\n\n"); + sb.append("#exact\nhow many exact SSA steps when abandoning tau leaping\n\n"); + sb.append("For more explanation refer to Cao et al., Efficient step\n"); + sb.append("size selection for the tau-leaping simulation method,\n"); + sb.append("Journal of chemical physics 124"); + JOptionPane.showMessageDialog(main, sb.toString()); + } + }); + } + + + + private void initializePickers() { + nodeTypePicker = new JComboBox(); + reactionPicker = new JComboBox(); + speciesPicker = new JComboBox(); + initialAmountPicker = new JComboBox(); + reactioncoefficientPicker = new JComboBox(); + Dimension d = nodeTypePicker.getPreferredSize(); + d.width=140; + nodeTypePicker.setPreferredSize(d); + reactionPicker.setPreferredSize(d); + speciesPicker.setPreferredSize(d); + initialAmountPicker.setPreferredSize(d); + reactioncoefficientPicker.setPreferredSize(d); + nodeTypePicker.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent ae) { + updateReactionAndSpeciesPicker(); + } + }); + } + + @SuppressWarnings("unchecked") + private void updateReactionAndSpeciesPicker() { + Set vals = new TreeSet(); + + CyNetworkView view = Cytoscape.getCurrentNetworkView(); + CyAttributes nodeAttr = Cytoscape.getNodeAttributes(); + String nodeType = (String) nodeTypePicker.getSelectedItem(); + + if (nodeType!=null) { + for (Iterator i = view.getNodeViewsIterator(); i.hasNext();) { + NodeView nodeView = i.next(); + CyNode node = (CyNode) nodeView.getNode(); + Object o = null; + switch (nodeAttr.getType(nodeType)) { + case CyAttributes.TYPE_STRING: + o = nodeAttr.getStringAttribute(node.getIdentifier(),nodeType).intern(); + break; + case CyAttributes.TYPE_FLOATING: + o = nodeAttr.getDoubleAttribute(node.getIdentifier(),nodeType); + break; + case CyAttributes.TYPE_INTEGER: + o = nodeAttr.getIntegerAttribute(node.getIdentifier(),nodeType); + break; + } + if (o!=null) vals.add(o); + } + } + + reactionPicker.removeAllItems(); + reactionPicker.addItem("reaction"); + for (Object o : vals) reactionPicker.addItem(o); + reactionPicker.setSelectedItem(main.getNetworkChecker().nodeTypeReaction); + + speciesPicker.removeAllItems(); + speciesPicker.addItem("species"); + for (Object o : vals) speciesPicker.addItem(o); + speciesPicker.setSelectedItem(main.getNetworkChecker().nodeTypeSpecies); + } + + public void setSpecies(Network net) { + ((DefaultListModel)notList.getModel()).removeAllElements(); + ((DefaultListModel)trendList.getModel()).removeAllElements(); + + for (int i=0; i0) + if (JOptionPane.YES_OPTION == JOptionPane.showConfirmDialog(Cytoscape.getDesktop(), "Reset colors to normal?", "FERN", JOptionPane.YES_NO_OPTION)) { + style.resetColors(); + } + + startSimulation.cancel(); + } + + }); +// defaultNodeAppereanceCalculator = Cytoscape.getVisualMappingManager().getVisualStyle().getNodeAppearanceCalculator(); + startSimulation = new SimulationAction(); + + initializeComponents(); + setSize(630,480); + + reloadNetwork(new NetworkChecker()); + } + + public void reloadNetworkByButton() { + String[] attr = extended.getAttributeKeys(); + + if (attr[0]!=null && attr[1]!=null && attr[2]!=null && attr[3]!=null && attr[4]!=null) + reloadNetwork(new NetworkChecker(attr[0],attr[1],attr[2],attr[3],attr[4])); + else + reloadNetwork(recentNetworkChecker); + + } + + public void reloadNetwork(NetworkChecker networkChecker) { + this.recentNetworkChecker = networkChecker; + extended.setAttributes(networkChecker); + + try { + networkChecker.check(); + + CyNetwork network = Cytoscape.getCurrentNetwork(); + CyNetworkView view = Cytoscape.getCurrentNetworkView(); + CyAttributes nodeAttr = Cytoscape.getNodeAttributes(); + + this.network = new CytoscapeNetworkWrapper(networkChecker,network, view, nodeAttr); + startStopButton.setEnabled(getNetwork()!=null && getNetwork().getNumSpecies()>0); + + overview.setErrorMessage(getNetwork(), null); + extended.setSpecies(this.network); + style.setNetworkChecker(networkChecker); + } catch (Exception e) { + overview.setErrorMessage(getNetwork(),e.getMessage()); + } + } + + + public CytoscapeNetworkWrapper getNetwork() { + return network; + } + + public NetworkChecker getNetworkChecker() { + return recentNetworkChecker; + } + + private void initializeComponents() { + Container pane = getContentPane(); + + overview = new OverviewPane(this); + extended = new ExtendedPane(this); + + pane.add(overview, BorderLayout.WEST); + pane.add(extended, BorderLayout.EAST); + + startStopButton = new JButton(startSimulation); + progress = new JProgressBar(); + JPanel south = new JPanel(new BorderLayout()); + south.add(startStopButton,BorderLayout.NORTH); + south.add(progress,BorderLayout.SOUTH); + pane.add(south,BorderLayout.SOUTH); + } + + + public static void main(String[] args) { + new MainFrame(null).setVisible(true); + } + + + private class SimulationAction extends AbstractAction { + private static final long serialVersionUID = 1L; + + boolean cancelFlag = false; + + public SimulationAction() { + super("Start"); + } + + public void cancel() { + cancelFlag = true; + } + + public void actionPerformed(ActionEvent e) { + if (startStopButton.getText().equals("Start")){ + startStopButton.setText("Stop"); + cancelFlag = false; + + progress.setMaximum((int) (overview.getTime()*100)); + progress.setValue(0); + overview.setEnabled(false); + extended.setEnabled(false); + + new Thread(new Runnable() { + + public void run() { + try { + int runs = overview.getNumRuns();; + Simulator sim = overview.getSimulator(); + if (sim instanceof AbstractBaseTauLeaping) { + ((AbstractBaseTauLeaping)sim).setEpsilon(extended.getEpsilon()); + ((AbstractBaseTauLeaping)sim).setNCritical(extended.getNc()); + ((AbstractBaseTauLeaping)sim).setUseSimpleFactor(extended.getThreshold()); + ((AbstractBaseTauLeaping)sim).setNumSimpleCalls(extended.getNum()); + } + sim.addObserver(new CytoscapeColorChangeObserver(overview.isVisualize(),overview.isRealTime(),sim,getNetwork(),style,extended.getTrendSpecies(),overview.getTime())); + while (!cancelFlag && runs--!=0) { + sim.start(new SimulationController() { + double recentTime = 0; + public boolean goOn(Simulator sim) { + boolean goOn = sim.getTime()0) { + networkStatus.setText("ok"); + networkStatus.setForeground(new Color(0,127,0)); + } + else if (net!=null && net.getNumSpecies()==0) { + networkStatus.setText("empty"); + networkStatus.setForeground(Color.red); + } + else { + networkStatus.setText("not loaded"); + networkStatus.setForeground(Color.red); + } + + } + + public double getTime() { + double re = 0; + try { + re = Double.parseDouble(time.getText()); + } catch (Exception e){} + return re; + } + + public int getNumRuns() { + return Integer.parseInt(runs.getText()); + } + + public boolean isRealTime() { + return realTime.isSelected(); + } + + public boolean isVisualize() { + return visu.isSelected(); + } + + public Simulator getSimulator() throws Exception { + switch (simulator.getSelectedIndex()) { + case 0: + return new GillespieSimple(main.getNetwork()); + case 1: + return new GillespieEnhanced(main.getNetwork()); + case 2: + return new GibsonBruckSimulator(main.getNetwork()); + case 3: + return new TauLeapingAbsoluteBoundSimulator(main.getNetwork()); + case 4: + return new TauLeapingRelativeBoundSimulator(main.getNetwork()); + case 5: + return new TauLeapingSpeciesPopulationBoundSimulator(main.getNetwork()); + case 6: + return new HybridMaximalTimeStep(main.getNetwork()); + } + return (Simulator) ClassLoader.getSystemClassLoader().loadClass("fern.simulation.algorithm."+(String) simulator.getSelectedItem()).getConstructor(ClassLoader.getSystemClassLoader().loadClass("fern.network.Network")).newInstance(main.getNetwork()); + } + + @Override + public void setEnabled(boolean enabled) { + setEnabledDeep(enabled, this); + } + + private void setEnabledDeep(boolean enabled, Container component) { + for (Component c : component.getComponents()) { + c.setEnabled(enabled); + if (c instanceof Container) setEnabledDeep(enabled, (Container) c); + } + } + + +} diff --git a/pom.xml b/pom.xml index 8a954620..ac7abd69 100644 --- a/pom.xml +++ b/pom.xml @@ -232,6 +232,11 @@ file:${project.basedir}/src/lib/maven + + libs + file://${project.basedir}/lib + + JSBML-SNAPSHOT @@ -297,6 +302,11 @@ jfreechart 1.0.19 + + com.blazegraph + colt + 2.1.4 + diff --git a/src/main/java/fern/Start.java b/src/main/java/fern/Start.java new file mode 100644 index 00000000..a4e8619f --- /dev/null +++ b/src/main/java/fern/Start.java @@ -0,0 +1,201 @@ +package fern; + +import java.io.File; +import java.io.IOException; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import org.jdom.JDOMException; + +import fern.network.FeatureNotSupportedException; +import fern.network.Network; +import fern.simulation.Simulator; +import fern.simulation.algorithm.AbstractBaseTauLeaping; +import fern.simulation.algorithm.GillespieEnhanced; +import fern.simulation.algorithm.HybridMaximalTimeStep; +import fern.simulation.algorithm.TauLeapingSpeciesPopulationBoundSimulator; +import fern.simulation.observer.AmountIntervalObserver; +import fern.tools.NetworkTools; +import fern.tools.NumberTools; +import fern.tools.gnuplot.GnuPlot; +import org.simulator.math.odes.MultiTable; + +public class Start { + + /** + * @param args + */ + public static void main(String[] args) { + try { + Map orderedArgs = getArguments(args); + + Network net = createNetwork(orderedArgs); + Simulator sim = createSimulator(net,orderedArgs); + AmountIntervalObserver obs = createObserver(sim,orderedArgs); + GnuPlot gp = runSimulation(sim,obs,orderedArgs); + output(obs,sim,orderedArgs,gp); + + }catch(Exception e) { + System.out.println(getUsage()); + System.out.println(); + System.out.println(e.getMessage()); + } + } + + + private static void output(AmountIntervalObserver obs, Simulator sim, + Map orderedArgs, GnuPlot gp) throws IOException { + obs.toGnuplot(gp); + gp.setDefaultStyle("with linespoints"); + + if ((Boolean)orderedArgs.get("i")) { + gp.setVisible(true); + gp.plot(); + } + + if (((String)orderedArgs.get("p")).length()>0) { + gp.plot(); + gp.saveImage(new File((String)orderedArgs.get("p"))); + } + + double[][] output = obs.getAvgLog(); + double[] timepoints = output[0]; + String[] identifiers = getIdentifiers(sim, orderedArgs); + + double[][] result = new double[output[0].length][output.length-1]; + for (int i = 0; i != result.length; i++) { + Arrays.fill(result[i], Double.NaN); + } + + for (int i = 0; i < result.length; i++){ + for (int j = 0; j < result[0].length; j++){ + result[i][j] = output[j+1][i]; + } + } + + MultiTable multiTable = new MultiTable(timepoints, result, identifiers, null); + System.out.println(multiTable); + + } + + + private static GnuPlot runSimulation(Simulator sim, AmountIntervalObserver obs, + Map orderedArgs) throws IOException { + + GnuPlot gp = new GnuPlot(); + gp.setDefaultStyle("with linespoints"); + if ((Boolean)orderedArgs.get("i")) { + gp.setVisible(true); + } + + for (int i=0; i<(Integer)orderedArgs.get("n"); i++) { + sim.start((Double)orderedArgs.get("time")); + + if ((Boolean)orderedArgs.get("i")) { + obs.toGnuplot(gp); + gp.plot(); + gp.clearData(); + } + } + + return gp; + } + + private static AmountIntervalObserver createObserver(Simulator sim, + Map orderedArgs) { + String[] species = getIdentifiers(sim, orderedArgs); + return (AmountIntervalObserver) sim.addObserver(new AmountIntervalObserver(sim,(Double)orderedArgs.get("interval"),((Double)orderedArgs.get("time")).intValue(),species)); + } + + private static String[] getIdentifiers(Simulator sim, Map orderedArgs) { + String[] species = (String[]) orderedArgs.get("s"); + if (species.length==0) + species = NetworkTools.getSpeciesNames(sim.getNet(), NumberTools.getNumbersTo(sim.getNet().getNumSpecies()-1)); + return species; + } + + private static Simulator createSimulator(Network net, + Map orderedArgs) { + double eps = (Double) orderedArgs.get("method"); + if (eps==0) + return new GillespieEnhanced(net); + else if (eps==-1) + return new HybridMaximalTimeStep(net); + else { + AbstractBaseTauLeaping re = new TauLeapingSpeciesPopulationBoundSimulator(net); + re.setEpsilon(eps); + return re; + } + } + + + private static Network createNetwork(Map orderedArgs) throws IOException, JDOMException, FeatureNotSupportedException, ClassNotFoundException { + return NetworkTools.loadNetwork(new File((String) orderedArgs.get("file"))); + } + + + private static Map getArguments(String[] args) { + Map re = new HashMap(); + if (args.length<3) throw new IllegalArgumentException("Not enough arguments!"); + + re.put("file", args[0]); + re.put("time", Double.parseDouble(args[1])); + re.put("interval", Double.parseDouble(args[2])); + re.put("n", 1); + re.put("s", new String[0]); + re.put("method", 0.0); + re.put("i", false); + re.put("p", ""); + + for (int i=3; inetwork is a ModifierNetwork. + * Otherwise it contains also net network. + */ + protected Network originalNetwork = null; + + /** + * Contains the adjacency list for molecule species towards reactions, where the species + * is a reactant. + */ + protected int[][] adjListAsRea = null; + + /** + * Contains the adjacency list for molecule species towards reactions, where the species + * is a product. + */ + protected int[][] adjListAsPro = null; + + /** + * Creates an analysis instance. In order to do that, a {@link Network} is required. + * If the network is a {@link ModifierNetwork}, the original network is also + * discovered and stored. + * + * @param network the network for analysis + */ + public AnalysisBase(Network network) { + this.network = network; + originalNetwork = network instanceof ModifierNetwork ? ((ModifierNetwork)network).getOriginalNetwork() : network; + } + + /** + * Creates the adjacency lists for the molecule species. A subclass has to invoke this + * before it can use the protected fields adjListAsRea and adjListAsPro. + */ + @SuppressWarnings("unchecked") + protected void createSpeciesAdjacencyLists() { + adjListAsPro = new int[network.getNumSpecies()][]; + adjListAsRea = new int[network.getNumSpecies()][]; + + LinkedList[] proCreate = new LinkedList[network.getNumSpecies()]; + for (int i=0; i(); + for (int i=0; i[] reaCreate = new LinkedList[network.getNumSpecies()]; + for (int i=0; i(); + for (int i=0; ispeciesSource + * and reactionSource are the initial content of the queue. The search is controlled by an {@link NetworkSearchAction}. + * + * @param speciesSource indices of the species to start with + * @param reactionSource indices of the reactions to start with + * @param action controls what species/reactions have to be visited and what to do after discovering/finishing a species/reaction + * @return number of visited species/reactions + */ + public int bfs(int[] speciesSource, int[] reactionSource, NetworkSearchAction action) { + return search(new IntQueue(),speciesSource,reactionSource,action); + } + + /** + * Performs a depth first search starting at the given sources (which means the contents of speciesSource + * and reactionSource are the initial content of the stack. The search is controlled by an {@link NetworkSearchAction}. + * + * @param speciesSource indices of the species to start with + * @param reactionSource indices of the reactions to start with + * @param action controls what species/reactions have to be visited and what to do after discovering/finishing a species/reaction + * @return number of visited species/reactions + */ + public int dfs(int[] speciesSource, int[] reactionSource, NetworkSearchAction action) { + return search(new IntStack(),speciesSource,reactionSource,action); + } + + /** + * Performs a search starting at the given sources (which means the contents of speciesSource + * and reactionSource are the initial content of the search structure {@link IntSearchStructure}. + * The search is controlled by an {@link NetworkSearchAction}. + * + * @param str the search structure (fifo/lifo) + * @param speciesSource indices of the species to start with + * @param reactionSource indices of the reactions to start with + * @param action controls what species/reactions have to be visited and what to do after discovering/finishing a species/reaction + * @return number of visited species/reactions + * @see AnalysisBase#bfs(int[], int[], NetworkSearchAction) + * @see AnalysisBase#dfs(int[], int[], NetworkSearchAction) + */ + public int search(IntSearchStructure str, int[] speciesSource, int[] reactionSource, NetworkSearchAction action) { + if (adjListAsPro==null) createSpeciesAdjacencyLists(); + + action.initialize(this.network); + + BitVector reactionDiscovered = new BitVector(network.getNumReactions()); + BitVector speciesDiscovered = new BitVector(network.getNumSpecies()); + + if (decode(network.getNumReactions())!=network.getNumReactions() || + decode(network.getNumSpecies())!=network.getNumSpecies()) + throw new IllegalArgumentException("Net is too big"); + + int queueElement; + int index; + int count = 0; + + for (int i : speciesSource) { + str.add(i); + speciesDiscovered.set(i); + action.speciesDiscovered(i); + } + + for (int i : reactionSource) { + str.add(encode(i)); + reactionDiscovered.set(i); + action.reactionDiscovered(i); + } + + while (!str.isEmpty()) { + ++count; + queueElement = str.get(); + index = decode(queueElement); + + + if (queueElement!=index) { // reaction + action.reactionFinished(index); + + for (int n : network.getReactants(index)) + if (!speciesDiscovered.get(n) && action.checkSpecies(n,NeighborType.Reactant)){ + speciesDiscovered.set(n); + str.add(n); + action.speciesDiscovered(n); + } + for (int n : network.getProducts(index)) + if (!speciesDiscovered.get(n) && action.checkSpecies(n,NeighborType.Product)){ + speciesDiscovered.set(n); + str.add(n); + action.speciesDiscovered(n); + } + Iterable additionals = action.getAdditionalReactionNeighbors(index); + if (additionals!=null) + for (int n : additionals) + if (!speciesDiscovered.get(n) && action.checkSpecies(n,NeighborType.Additional)){ + speciesDiscovered.set(n); + str.add(n); + action.speciesDiscovered(n); + } + + } else { // species + action.speciesFinished(index); + + for (int n : adjListAsRea[index]) + if (!reactionDiscovered.get(n) && action.checkReaction(n, NeighborType.Reactant)){ + reactionDiscovered.set(n); + str.add(encode(n)); + action.reactionDiscovered(n); + } + for (int n : adjListAsPro[index]) + if (!reactionDiscovered.get(n) && action.checkReaction(n, NeighborType.Product)){ + reactionDiscovered.set(n); + str.add(encode(n)); + action.reactionDiscovered(n); + } + Iterable additionals = action.getAdditionalSpeciesNeighbors(index); + if (additionals!=null) + for (int n : additionals) + if (!reactionDiscovered.get(n) && action.checkReaction(n, NeighborType.Additional)){ + reactionDiscovered.set(n); + str.add(encode(n)); + action.reactionDiscovered(n); + } + } + } + + action.finished(); + return count; + } + + private int encode(int i) { + return i | (1 << 31); + } + + private int decode(int i) { + return i & ~(1 << 31); + } + + + +} diff --git a/src/main/java/fern/analysis/AutocatalyticNetworkDetection.java b/src/main/java/fern/analysis/AutocatalyticNetworkDetection.java new file mode 100644 index 00000000..ff234f23 --- /dev/null +++ b/src/main/java/fern/analysis/AutocatalyticNetworkDetection.java @@ -0,0 +1,372 @@ +package fern.analysis; + +import java.util.LinkedList; + +import cern.colt.bitvector.BitVector; +import fern.network.Network; +import fern.network.creation.CatalystIterator; +import fern.tools.NumberTools; + +/** + * Detects the autocatalytic set of the given network if there is any. An autocatalytic + * set is defined as a set of species that are produced by a path of reactions, starting + * at some food molecules and fully catalyzed by members of the autocatalytic set. + *

+ * The algorithm iterates over two modified breath first searches until none of them can + * exclude species / reactions any more. The first bfs removes reactions that are not + * catalyzed in the remaining network (and molecule species that are only produced by that + * reactions). The second bfs removes species, that do not have a path from each necessary + * food molecule. + * + * @author Florian Erhard + * + */ +public class AutocatalyticNetworkDetection extends AnalysisBase { + + private BitVector removedReactions = null; + private BitVector removedSpecies = null; + private int[] numCatalysts = null; // for each reaction -> how many catalysts are remaining + private int[] numReactants = null; // for each reaction -> how many reactants are remaining + private int[] numCreated = null; // for each species -> how many creating reactions are remaining + + private LinkedList[] adjListAsCata = null; // for each species -> list of reactions catalyzed + private CatalystIterator cataIt = null; // for each reaction -> list of catalysts + + /** + * Creates the AutocatalyticDetection by using the in the network built in {@link CatalystIterator}. + * The network has to implement CatalystIterator, otherwise an IllegalArgumentException is thrown. + * + * @param network the network to detect the autocatalytic set in + */ + public AutocatalyticNetworkDetection(Network network) { + super(network); + + if (! (originalNetwork instanceof CatalystIterator)) + throw new IllegalArgumentException("Cannot find a CatalystIterator"); + else + cataIt = (CatalystIterator) originalNetwork; + } + + /** + * Creates the AutocatalyticDetection by using the second argument as {@link CatalystIterator}. + * + * @param network network the network to detect the autocatalytic set in + * @param cataIt a CatalystIterator for the network + */ + public AutocatalyticNetworkDetection(Network network, CatalystIterator cataIt) { + super(network); + + this.cataIt = cataIt; + } + + /** + * Performs the detection algorithm. The results can be retrieved by the methods + * getAutocatalyticReactions, + * getAutocatalyticSpecies, + * isAutocatalyticReaction, + * isAutocatalyticSpecies, + * annotate + * + * @return number of iterations + */ + public int detect() { + removedReactions = new BitVector(network.getNumReactions()); + removedSpecies = new BitVector(network.getNumSpecies()); + + int count = -1; + int re = 0; + ConnectedComponentIdentificationAction ccAction = new ConnectedComponentIdentificationAction(); + AutocatalyticSubsetDetectionAction asAction = new AutocatalyticSubsetDetectionAction(); + createAdjacencListsAsCata(); + preprocessingCounts(); + int[] monomers = getFoodSpecies(); + + while (countRuntimeException + * if the detection algorithms has not been called. + * + * @return autocatalytic reactions + */ + public BitVector getAutocatalyticReactions() { + if (removedReactions==null) + throw new RuntimeException("Detection hasn't been called!"); + BitVector re = removedReactions.copy(); + re.not(); + return re; + } + + /** + * Gets the autocatalytic species as {@link BitVector}. Throws a RuntimeException + * if the detection algorithms has not been called. + * + * @return autocatalytic species + */ + public BitVector getAutocatalyticSpecies() { + if (removedSpecies==null) + throw new RuntimeException("Detection hasn't been called!"); + BitVector re = removedSpecies.copy(); + re.not(); + return re; + } + + /** + * Returns true if the given reaction is autocatalytic. Throws a RuntimeException + * if the detection algorithms has not been called. + * + * @param reaction the reaction index + * @return if the reaction is autocatalytic + */ + public boolean isAutocatalyticReaction(int reaction) { + if (removedReactions==null) + throw new RuntimeException("Detection hasn't been called!"); + return !removedReactions.get(reaction); + } + + /** + * Returns true if the given species is autocatalytic. Throws a RuntimeException + * if the detection algorithms has not been called. + * + * @param species the species index + * @return if the species is autocatalytic + */ + public boolean isAutocatalyticSpecies(int species) { + if (removedSpecies==null) + throw new RuntimeException("Detection hasn't been called!"); + return !removedSpecies.get(species); + } + + /** + * Adds annotations to each autocatalytic reaction / species. + * @param field name of the annotation + * @param value value of the annotation + */ + public void annotate(String field, String value) { + for (int i=0; i re = new LinkedList(); + for (int i=0; i re = new LinkedList(); + for (int i=0; i(); + for (int i=0; i the reaction cannot be any more + * or if the species catalyzes the reaction and there is no other catalyst. + */ + public boolean checkReaction(int reaction, NeighborType neighborType) { + return !removedReactions.getQuick(reaction) && + ((neighborType==NeighborType.Additional && numCatalysts[reaction]==0) + || neighborType==NeighborType.Reactant); + } + + /** + * Walk from a reaction to a species, if the species is product and + * not created by another reaction. + */ + public boolean checkSpecies(int species, NeighborType neighborType) { + return !removedSpecies.getQuick(species) && network.getSpeciesName(species).length()>1 && + neighborType==NeighborType.Product && numCreated[species]==0; + } + + + public void reactionFinished(int reaction) {} + public void speciesFinished(int species) {} + + public void reactionDiscovered(int reaction) { + removedReactions.putQuick(reaction,true); + for (int p : network.getProducts(reaction)) + if (!removedSpecies.get(p)) + numCreated[p]--; + } + public void speciesDiscovered(int species) { + removedSpecies.putQuick(species,true); + for (int r : adjListAsCata[species]) + if (!removedReactions.get(r)) + numCatalysts[r]--; + for (int r : adjListAsRea[species]) + if (!removedReactions.get(r)) + numReactants[r]--; + } + + + public Iterable getAdditionalReactionNeighbors(int index) { + return null; + } + + public Iterable getAdditionalSpeciesNeighbors(int index) { + return adjListAsCata[index]; + } + + } + + /** + * NetworkSearchAction for the second search + * @author Florian Erhard + * + */ + private class ConnectedComponentIdentificationAction implements NetworkSearchAction { + + BitVector discoveredReactions; + BitVector discoveredSpecies; + + int[] discoveredReactants; + + + public void initialize(Network net) { + discoveredReactions = new BitVector(removedReactions.size()); + discoveredSpecies = new BitVector(removedSpecies.size()); + discoveredReactants = new int[network.getNumReactions()]; + } + + public void finished() { + + for (int i=0; i getAdditionalReactionNeighbors(int index) { + return null; + } + + + public Iterable getAdditionalSpeciesNeighbors(int index) { + return null; + } + + } + +} diff --git a/src/main/java/fern/analysis/IntQueue.java b/src/main/java/fern/analysis/IntQueue.java new file mode 100644 index 00000000..b6285ff3 --- /dev/null +++ b/src/main/java/fern/analysis/IntQueue.java @@ -0,0 +1,28 @@ +package fern.analysis; + +import cern.colt.list.IntArrayList; + +/** + * IntQueue is an search structure for {@link AnalysisBase} representing an fifo queue for + * a breadth first search. + * @author Florian Erhard + * + */ +public class IntQueue extends IntArrayList implements IntSearchStructure { +private static final long serialVersionUID = 1L; + + public IntQueue() { + super(); + } + + public IntQueue(int initialCapacity) { + super(initialCapacity); + } + + public int get() { + int re = super.get(0); + remove(0); + return re; + } + +} diff --git a/src/main/java/fern/analysis/IntSearchStructure.java b/src/main/java/fern/analysis/IntSearchStructure.java new file mode 100644 index 00000000..59c56a13 --- /dev/null +++ b/src/main/java/fern/analysis/IntSearchStructure.java @@ -0,0 +1,16 @@ +package fern.analysis; + +/** + * Implementing class can be used as search structure for searches in {@link AnalysisBase}. + * @author Florian Erhard + * + */ +public interface IntSearchStructure { + + void add(int i); + + boolean isEmpty(); + + int get(); + +} diff --git a/src/main/java/fern/analysis/IntStack.java b/src/main/java/fern/analysis/IntStack.java new file mode 100644 index 00000000..a28afa9e --- /dev/null +++ b/src/main/java/fern/analysis/IntStack.java @@ -0,0 +1,28 @@ +package fern.analysis; + +import cern.colt.list.IntArrayList; + +/** + * IntStack is an search structure for {@link AnalysisBase} representing an lifo stack for + * a depth first search. + * @author Florian Erhard + * + */ +public class IntStack extends IntArrayList implements IntSearchStructure { +private static final long serialVersionUID = 1L; + + public IntStack() { + super(); + } + + public IntStack(int initialSize) { + super(initialSize); + } + + public int get() { + int re = super.get(size()-1); + remove(size()-1); + return re; + } + +} diff --git a/src/main/java/fern/analysis/NetworkSearchAction.java b/src/main/java/fern/analysis/NetworkSearchAction.java new file mode 100644 index 00000000..3dedf867 --- /dev/null +++ b/src/main/java/fern/analysis/NetworkSearchAction.java @@ -0,0 +1,94 @@ +package fern.analysis; + +import fern.network.Network; + +/** + * + * Implementing classes of NetworkSearchAction are able to control/watch searches in + * {@link AnalysisBase}. On the one hand they control by using checkReaction, checkSpecies (control + * if a network node should be visited) and getAdditionalSpeciesNeighbors, getAdditionalSpeciesNeighbors + * (if there are other neighbors to visit e.g. catalysts of reactions). + * On the other hand they can watch the searches by implementing reactionDiscovered, reactionFinished and + * speciesDiscovered, speciesFinished. + * + * @author Florian Erhard + * + */ +public interface NetworkSearchAction { + + /** + * Gets called when a reaction is inserted into the search structure. + * @param reaction index of the inserted reaction + */ + public void reactionDiscovered(int reaction); + + /** + * Gets called when a species is inserted into the search structure. + * @param species index of the inserted species + */ + public void speciesDiscovered(int species); + + /** + * Gets called when a reaction gets out of the search structure. + * @param reaction index of the reactions + */ + public void reactionFinished(int reaction); + + /** + * Gets called when a species gets out of the search structure. + * @param species index of the species + */ + public void speciesFinished(int species); + + /** + * Gets called, before the species is inserted into the search structure. + * If the implementing instance returns false, the species is not inserted. + * @param species species index + * @param neighborType one of the NeighborTypes + * @return true if the species should be inserted + */ + public boolean checkSpecies(int species, NeighborType neighborType); + + /** + * Gets called, before the reaction is inserted into the search structure. + * If the implementing instance returns false, the reaction is not inserted. + * @param reaction reaction index + * @param neighborType one of the NeighborTypes + * @return true if the reaction should be inserted + */ + public boolean checkReaction(int reaction, NeighborType neighborType); + + /** + * Gets called before anything is inserted into the search structure. + * @param net the network where the search is going to be performed + */ + public void initialize(Network net); + + /** + * Gets called, when the search is done. + */ + public void finished(); + + /** + * Returns an iterator for additional neighbors of this reaction + * @param index reaction index + * @return iterator of additional neighbors + */ + public Iterable getAdditionalSpeciesNeighbors(int index); + + /** + * Returns an iterator for additional neighbors of this species + * @param index species index + * @return iterator of additional neighbors + */ + public Iterable getAdditionalReactionNeighbors(int index); + + /** + * Defines different types of neighborhoods in a Network. + * @author Florian Erhard + * + */ + public enum NeighborType { + Reactant, Product, Additional + } +} diff --git a/src/main/java/fern/analysis/NodeChecker.java b/src/main/java/fern/analysis/NodeChecker.java new file mode 100644 index 00000000..24253c8e --- /dev/null +++ b/src/main/java/fern/analysis/NodeChecker.java @@ -0,0 +1,18 @@ +package fern.analysis; + +import fern.network.Network; + +/** + * + * Implementing classes can be used for a {@link NetworkSearchAction}s checkReaction, + * checkSpecies, if the information whether or not to visit the nodes is not + * accessible for the NetworkSearchAction. + * + * @author Florian Erhard + * + */ +public interface NodeChecker { + + public boolean checkReactionNode(Network network, int reaction); + public boolean checkSpeciesNode(Network network, int species); +} diff --git a/src/main/java/fern/analysis/NodeCheckerByAnnotation.java b/src/main/java/fern/analysis/NodeCheckerByAnnotation.java new file mode 100644 index 00000000..661997b6 --- /dev/null +++ b/src/main/java/fern/analysis/NodeCheckerByAnnotation.java @@ -0,0 +1,45 @@ +package fern.analysis; + +import fern.network.Network; + +/** + * + * An instance of NodeCheckerByAnnotation can be used to control a search in + * AnalysisBase by a NetworkSearchAction. Then the reactions / species + * in the network are only visited, if they have the specified annotation. + * + * @author Florian Erhard + * + */ +public class NodeCheckerByAnnotation implements NodeChecker { + + private String field; + private String value; + + /** + * Creates the NodeChecker with the specified annotation field and value. If + * value is null then the reaction / species is valid if an annotation + * named field exists. + * @param field the annotation name + * @param value the annotation value + */ + public NodeCheckerByAnnotation(String field, String value) { + this.field = field; + this.value = value; + } + + public boolean checkReactionNode(Network network, int reaction) { + String rval = network.getAnnotationManager().getReactionAnnotation(reaction, field); + if (rval==null) return false; + else if (value==null) return true; + else return rval.equals(value); + } + + public boolean checkSpeciesNode(Network network, int species) { + String rval = network.getAnnotationManager().getSpeciesAnnotation(species, field); + if (rval==null) return false; + else if (value==null) return true; + else return rval.equals(value); + } + +} diff --git a/src/main/java/fern/analysis/ShortestPath.java b/src/main/java/fern/analysis/ShortestPath.java new file mode 100644 index 00000000..7a07236f --- /dev/null +++ b/src/main/java/fern/analysis/ShortestPath.java @@ -0,0 +1,269 @@ +package fern.analysis; + +import java.util.Arrays; +import java.util.LinkedList; + +import fern.network.Network; +import fern.tools.NumberTools; + +/** + * Computes shortest paths in the network by a bfs. Either the path from some + * source species to only one species can be calculated (by using one of the + * computePath methods) or paths to all species (by computePaths). + * A {@link NodeChecker} can optionally be given for each method. + * + * @author Florian Erhard + * + */ +public class ShortestPath extends AnalysisBase { + + /** + * Creates the class with the specified network. + * @param network the network where shortest paths shall be computed + */ + public ShortestPath(Network network) { + super(network); + } + + /** + * Compute all shortest paths from some source species. + * @param species the names of the source species + * @return an array of paths + * @see ShortestPath.Path + */ + public Path[] computePaths(String...species) { + return computePaths(null,species); + } + + /** + * Compute all shortest paths from some source species by only using parts of the + * network specified by the {@link NodeChecker} checker. + * @param species the names of the source species + * @param checker a NodeChecker for the search + * @return an array of paths + * @see ShortestPath.Path + */ + public Path[] computePaths(NodeChecker checker, String...species) { + int[] speciesIndex = getSpeciesIndices(species); + ShortestPathAction action = new ShortestPathAction(checker); + bfs(speciesIndex,new int[0],action); + Path[] re = new Path[network.getNumSpecies()]; + for (int i=0; ichecker. + * + * @param checker a NodeChecker for the search + * @param toSpecies the name of the species where the shortest path should be computed to + * @param species the names of the source species + * @return the shortest path + * + * @see ShortestPath.Path + */ + public Path computePath(NodeChecker checker, String toSpecies, String...species) { + int[] speciesIndex = getSpeciesIndices(species); + ShortestPathAction action = new ShortestPathAction(checker); + bfs(speciesIndex,new int[0],action); + int toSpeciesIndex = network.getSpeciesByName(toSpecies); + if (toSpeciesIndex<0) throw new IllegalArgumentException(toSpecies+" doesn't belong to the network!"); + return action.getPath(toSpeciesIndex); + } + + private int[] getSpeciesIndices(String[] species) { + int[] speciesIndex = new int[species.length]; + for (int i=0; i0) sb.delete(sb.length()-2,sb.length()); + return sb.toString(); + } + + } + + /** + * NetworkSearchAction for computing shortest paths in a network. + * + * @author Florian Erhard + * + */ + private class ShortestPathAction implements NetworkSearchAction { + + int[] reactionDist = null; + int[] speciesDist = null; + int[] reactionParent = null; + int[] speciesParent = null; + int dist = 0; + int parent = -1; + NodeChecker checker = null; + + public ShortestPathAction(NodeChecker checker) { + this.checker = checker; + } + + + public int[] getReactionDistances() { + return reactionDist; + } + + public int[] getSpeciesDistances() { + return speciesDist; + } + + /** + * Return the path starting at the given species and ending at either of the + * search' sources. + * @param species Index of the species where the path starts. + * @return + */ + public Path getPath(int species) { + LinkedList path = new LinkedList(); + int reaction; + while (species>=0){ + path.add(0,species); + reaction = speciesParent[species]; + if (reaction<0) break; + path.add(0,reaction); + species = reactionParent[reaction]; + } + return new Path(NumberTools.toIntArray(path)); + } + + public void initialize(Network net) { + reactionDist = new int[net.getNumReactions()]; + speciesDist = new int[net.getNumSpecies()]; + reactionParent = new int[net.getNumReactions()]; + speciesParent = new int[net.getNumSpecies()]; + Arrays.fill(reactionDist, -1); + Arrays.fill(speciesDist, -1); + Arrays.fill(reactionParent, -1); + Arrays.fill(speciesParent, -1); + } + + + public void reactionDiscovered(int reaction) { + reactionDist[reaction] = dist; + reactionParent[reaction] = parent; + } + + public void reactionFinished(int reaction) { + dist = reactionDist[reaction]+1; + parent = reaction; + } + + public void speciesDiscovered(int species) { + speciesDist[species] = dist; + speciesParent[species] = parent; + } + + public void speciesFinished(int species) { + dist = speciesDist[species]+1; + parent = species; + } + + + + public void finished() {} + + + public boolean checkReaction(int reaction, NeighborType neighborType) { + if (neighborType!=NeighborType.Reactant) return false; + else return checker==null ? true : checker.checkReactionNode(network,reaction); + } + + + public boolean checkSpecies(int species, NeighborType neighborType) { + if (neighborType!=NeighborType.Product) return false; + else return checker==null ? true : checker.checkSpeciesNode(network,species); + } + + + public Iterable getAdditionalReactionNeighbors(int index) { + return null; + } + + + public Iterable getAdditionalSpeciesNeighbors(int index) { + return null; + } + + + + } +} diff --git a/src/main/java/fern/benchmark/Benchmark.java b/src/main/java/fern/benchmark/Benchmark.java new file mode 100644 index 00000000..10ed983c --- /dev/null +++ b/src/main/java/fern/benchmark/Benchmark.java @@ -0,0 +1,142 @@ +package fern.benchmark; + +import java.util.Collection; +import java.util.LinkedList; + +import cern.jet.random.AbstractDistribution; +import fern.tools.NumberTools; +import fern.tools.gnuplot.GnuPlot; + +/** + * Base class for all benchmark classes. Gives methods for measuring elapsed time + * as well as methods for creating test sets and benchmark data handling. + * @author Florian Erhard + * + */ +public abstract class Benchmark { + + private long startTime; + private Collection data = new LinkedList(); + private int numBins = 100; + + /** + * Gets the number of bins that are used for creating gnuplot histograms. + * Default is 100. + * + * @return number of bins + */ + public int getNumBins() { + return numBins; + } + + /** + * Sets the number of bins that are used for creating gnuplot histograms. + * Default is 100. + * + * @param numBins number of bins + */ + public void setNumBins(int numBins) { + this.numBins = numBins; + } + + /** + * Adds benchmark data to the data pool. + * + * @param d benchmark data + */ + public void addData(double[] d) { + data.add(d); + } + + /** + * Clears all collected benchmark data. + */ + public void clearData() { + data.clear(); + } + + /** + * Adds the benchmark data without conversion to a new {@link GnuPlot} object. + * + * @param dataLabels labels for the benchmark data + * @param styles styles for the benchmark data + * @return a GnuPlot object containing the benchmark data + * + * @see GnuPlot + */ + public GnuPlot toGnuplot(String[] dataLabels, String[] styles) { + return toGnuplot(new GnuPlot(),dataLabels,styles); + } + + /** + * Adds the benchmark data without conversion to a given {@link GnuPlot} object. + * + * @param dataLabels labels for the benchmark data + * @param styles styles for the benchmark data + * @return a GnuPlot object containing the benchmark data + * + * @see GnuPlot + */ + public GnuPlot toGnuplot(GnuPlot gnuplot, String[] dataLabels, String[] styles) { + if (gnuplot==null) return null; + gnuplot.addData(data, dataLabels, styles); + return gnuplot; + } + + /** + * Adds the benchmark data as histogram to a new {@link GnuPlot} object. + * + * @param dataLabels labels for the benchmark data + * @param styles styles for the benchmark data + * @return a GnuPlot object containing the benchmark data + * + * @see GnuPlot + */ + public GnuPlot toGnuPlotAsHistogram(String[] dataLabels, String[] styles) { + return toGnuPlotAsHistogram(new GnuPlot(),dataLabels,styles); + } + + /** + * Adds the benchmark data as histogram to a given {@link GnuPlot} object. + * + * @param dataLabels labels for the benchmark data + * @param styles styles for the benchmark data + * @return a GnuPlot object containing the benchmark data + * + * @see GnuPlot + */ + public GnuPlot toGnuPlotAsHistogram(GnuPlot gnuplot, String[] dataLabels,String[] styles) { + if (gnuplot==null) return null; + gnuplot.addData(NumberTools.createHistogram(data,numBins), dataLabels, styles); + return gnuplot; + } + + /** + * sets a start time for the benchmark system + */ + public void start() { + startTime = System.nanoTime(); + } + + /** + * Gets the elapsed time since the last call of start in nanoseconds + * @return elapsed time in ns + */ + public long end() { + return System.nanoTime()-startTime; + } + + /** + * Creates a test set containing size random numbers of the + * distribution dist. + * @param size the size of the test set + * @param dist the probability distribution + * @return test set + */ + public double[] createRandomDoubleArray(int size, AbstractDistribution dist) { + double[] re = new double[size]; + for (int i=0; ibenchmark method can be invoked + * repeatedly to calculate the average over many simulations. + *

+ * For references, see Yang Cao, Linda Petzold, Accuracy limitations and the measurement of errors in + * the stochastic simulation of chemically reacting systems, Journal of Computational Physics 212 (2006) 6�24. + * + * @author Florian Erhard + */ +public class SimulatorCorrectness extends SimulatorPerformance { + + private AmountAtMomentObserver[] obs; + private GnuPlot gnuplot; + private String[] speciesNames; + + /** + * Creates the benchmark instance with given network, moment in time and species. + * + * @param net the network to benchmark + * @param moment the moment in time at which the amounts are to be measured + * @param speciesNames the names of the species of which the amounts are to be measured + */ + public SimulatorCorrectness(Network net, double moment, String... speciesNames) { + super(net); + + this.speciesNames = speciesNames; + + obs = new AmountAtMomentObserver[simulators.length]; + for (int i = 0; i < obs.length; i++) { + obs[i] = new AmountAtMomentObserver(simulators[i], moment, speciesNames); + simulators[i].addObserver(obs[i]); + obs[i].setLabelFormat("%l - %a"); + } + + gnuplot = new GnuPlot(); + gnuplot.setDefaultStyle("with linespoints"); + } + + /** + * Returns the {@link SimulationController} for the base class. + * + * @param i index of the Simulator + * @return a SimulationController for the ith Simulator + */ + @Override + protected SimulationController getController(int i) { + return obs[i]; + } + + /** + * Gets called after some iterations of the method benchmark in the base class. + * A gnuplot is created containing histograms for each species and simulator and the + * histogram distances for the simulators is printed to stdout + * + * @see SimulatorPerformance#setShowSteps + */ + @Override + public void present() { + gnuplot.setVisible(true); + try { + for (int j = 0; j < obs.length; j++) + if (simulators[j] != null) + obs[j].toGnuplot(gnuplot); + gnuplot.plot(); + } catch (IOException e) { + } + gnuplot.clearData(); + + + String format = speciesNames.length > 1 ? "%.3f|%.3f\t" : "%.3f\t"; + double[][][] histogramDistance = calcHistoDistances(); + for (int i = 0; i < histogramDistance.length; i++) { + for (int j = 0; j < histogramDistance[i].length; j++) { + System.out.printf(format, NumberTools.avg(histogramDistance[i][j]), NumberTools.stddev(histogramDistance[i][j])); + } + System.out.println(); + } + System.out.println(); + } + + private double[][][] calcHistoDistances() { + double[][][] re = new double[simulators.length][simulators.length][speciesNames.length]; + for (int i = 0; i < re.length; i++) + for (int j = 0; j < re[i].length; j++) + for (int s = 0; s < speciesNames.length; s++) + re[i][j][s] = NumberTools.calculateHistogramDistance(obs[i].getHistogram(s), obs[j].getHistogram(s)); + return re; + } + + public static void main(String[] args) throws IOException, JDOMException { + ConfigReader cfg = new ConfigReader("test/configs/s3.cfg"); + + SimulatorPerformance sp = new SimulatorCorrectness(new FernMLNetwork( + new File(cfg.getAsString("file"))), cfg.getAsDouble("moment"), cfg.getAsStringArr("species")); + while (true) + sp.benchmark(); + } + + +} diff --git a/src/main/java/fern/benchmark/SimulatorFireTypes.java b/src/main/java/fern/benchmark/SimulatorFireTypes.java new file mode 100644 index 00000000..7f50fb99 --- /dev/null +++ b/src/main/java/fern/benchmark/SimulatorFireTypes.java @@ -0,0 +1,64 @@ +package fern.benchmark; + +import java.io.IOException; + +import fern.network.Network; +import fern.simulation.Simulator.FireType; +import fern.simulation.observer.FireTypeObserver; +import fern.tools.gnuplot.GnuPlot; + +/** + * Benchmark the {@link FireType}s for a given net. Use this benchmark, if you want to know, + * how many SSA steps are performed at tau leaping for a given network. + * The benchmark method can be invoked + * repeatedly to calculate the average over many simulations. + * + * @author Florian Erhard + * + */ +public class SimulatorFireTypes extends SimulatorTime { + + private FireTypeObserver[] obs; + private GnuPlot gnuplotRandom; + + /** + * Create the benchmark and defines the time each simulator has to run in one iteration. + * @param net the network to benchmark + * @param time running time for the simulators + */ + public SimulatorFireTypes(Network net, double time) { + super(net, time); + + obs = new FireTypeObserver[simulators.length]; + for (int i=0; ipresent and getController and add some {@link Observer}s to the + * simulators. + * + * @author Florian Erhard + * + */ +public abstract class SimulatorPerformance extends Benchmark { + + /** + * Contains the Simulators - use this field to attach Observers. + */ + protected Simulator[] simulators; + /** + * Contains the names of the simulators for using in the present-method of extending classes. + */ + protected String[] simulatorNames; + /** + * Contains the number of iterations done for using in the present-method of extending classes. + */ + protected int count = 0; + + private int showSteps = 100; + private int[] indices; + + /** + * Registers the six built-in simulators for the performance benchmarks. + * @param net the network to benchmark + * @see GillespieSimple + * @see GillespieEnhanced + * @see GibsonBruckSimulator + * @see TauLeapingAbsoluteBoundSimulator + * @see TauLeapingRelativeBoundSimulator + * @see TauLeapingSpeciesPopulationBoundSimulator + */ + public SimulatorPerformance(Network net) { + simulators = new Simulator[] { + new GillespieSimple(net), + new GillespieEnhanced(net), + new GibsonBruckSimulator(net), + new TauLeapingAbsoluteBoundSimulator(net), + new TauLeapingRelativeBoundSimulator(net), + new TauLeapingSpeciesPopulationBoundSimulator(net), + new HybridMaximalTimeStep(net), + new CompositionRejection(net) + }; + + simulatorNames = new String[simulators.length]; + for (int i=0; iBenchmark's + * data pool. After each {@link SimulatorPerformance#getShowSteps()} iterations, present + * is called. + * + * @see Benchmark#addData(double[]) + */ + public void benchmark(){ + + NumberTools.shuffle(indices); + + double[] d = new double[simulators.length]; + for (int i=0; ipresent-calls. + * @return the showSteps + */ + public int getShowSteps() { + return showSteps; + } + + /** + * Sets the number of iterations between two present-calls. + * @param showSteps the showSteps to set + */ + public void setShowSteps(int showSteps) { + this.showSteps = showSteps; + } + + /** + * Gets the simulators used by this benchmark. + * + * @return simulators. + */ + public Simulator[] getSimulators() { + return simulators; + } + + /** + * Extending classes have to determine the {@link SimulationController} of each + * Simulator here. + * @param i index of the simulator + * @return a SimulationController for the ith simulator + */ + protected abstract SimulationController getController(int i); + + + /** + * Is called after getShowSteps iterations. Implement your benchmark + * presentation here. + */ + protected abstract void present(); + + + +} diff --git a/src/main/java/fern/benchmark/SimulatorRandomNumbers.java b/src/main/java/fern/benchmark/SimulatorRandomNumbers.java new file mode 100644 index 00000000..b8cd6811 --- /dev/null +++ b/src/main/java/fern/benchmark/SimulatorRandomNumbers.java @@ -0,0 +1,79 @@ +package fern.benchmark; + +import java.io.IOException; + +import fern.network.Network; +import fern.simulation.controller.DefaultController; +import fern.simulation.controller.SimulationController; +import fern.simulation.observer.RandomNumberGeneratorCallObserver; +import fern.tools.gnuplot.GnuPlot; + +/** + + * Check the number of random number creations of different distributions for a given net. + * The random number creations are essential for the performance of the simulation algorithms. + * The benchmark method can be invoked + * repeatedly to calculate the average over many simulations. + * + * @author Florian Erhard + * + */ +public class SimulatorRandomNumbers extends SimulatorTime { + + private RandomNumberGeneratorCallObserver[] obs; + private GnuPlot gnuplotRandom; + private SimulationController controller; + + /** + * Create the benchmark and defines the time each simulator has to run in one iteration. + * @param net the network to benchmark + * @param time running time for the simulators + */ + public SimulatorRandomNumbers(Network net, double time) { + super(net,time); + this.controller = new DefaultController(time); + + obs = new RandomNumberGeneratorCallObserver[simulators.length]; + for (int i=0; iSimulator + * @return a SimulationController for the ith Simulator + */ + @Override + protected SimulationController getController(int i) { + return controller; + } + + /** + * Present results of this benchmark is gnuplot and text to stdout. + */ + @Override + public void present() { + super.present(); + + for (int i=0; iSimulator + * @return a SimulationController for the ith Simulator + */ + @Override + protected SimulationController getController(int i) { + return controller; + } + + /** + * Present results of this benchmark is gnuplot and text to stdout. + */ + @Override + public void present() { + + toGnuPlotAsHistogram(gnuplotTime, simulatorNames, null); + gnuplotTime.setVisible(true); + try { + gnuplotTime.plot(); + } catch (IOException e) {} + gnuplotTime.clearData(); + } + + +} diff --git a/src/main/java/fern/example/AutocatalyticNetworkExample.java b/src/main/java/fern/example/AutocatalyticNetworkExample.java new file mode 100644 index 00000000..1fed0432 --- /dev/null +++ b/src/main/java/fern/example/AutocatalyticNetworkExample.java @@ -0,0 +1,148 @@ +package fern.example; + +import java.io.IOException; + +import fern.analysis.AutocatalyticNetworkDetection; +import fern.analysis.ShortestPath; +import fern.analysis.ShortestPath.Path; +import fern.network.Network; +import fern.network.creation.AutocatalyticNetwork; +import fern.network.modification.CatalysedNetwork; +import fern.network.modification.ExtractSubNetwork; +import fern.network.modification.ReversibleNetwork; +import fern.simulation.Simulator; +import fern.simulation.algorithm.GillespieSimple; +import fern.simulation.observer.AmountIntervalObserver; +import fern.simulation.observer.IntervalObserver; +import fern.simulation.observer.ReactionIntervalObserver; +import fern.tools.NetworkTools; +import fern.tools.NumberTools; +import fern.tools.Stochastics; +import fern.tools.functions.Probability; +import fern.tools.gnuplot.GnuPlot; + +/** + * Here, the evolution of a reaction network as proposed by [1] + * is performed. Then, the autocatalytic subset [1] is determined and extracted. + * This subnet is then simulated to examine the dynamic behaviour of autocatalytic + * reaction networks. For more information about the evolution and the detection algorithm, + * please refer {@link AutocatalyticNetwork} and {@link AutocatalyticNetworkDetection}. + *

+ * References: + * [1] Kauffmann S.A, The Origins of Order: Self-Organization and Selection in Evolution. New York: Oxford University Press, (1993) + * + * @author Florian Erhard + * + */ +public class AutocatalyticNetworkExample { + + public static void main(String[] args) throws IOException { + + + Stochastics.getInstance().setSeed(1176374877921L); + + /* + * Create the autocatalytic network. + */ + AutocatalyticNetwork net = new AutocatalyticNetwork( + new char[] {'A','B'}, + new Probability.ReactionProbability(1,0), + new Probability.Constant(0.1), + 10 + ); + Network netR = new ReversibleNetwork(net, net.getReversePropensityCalculator()); + + /* + * Detect the autocatalytic subset, annotate it and print it out + */ + AutocatalyticNetworkDetection detection = new AutocatalyticNetworkDetection(netR); + detection.detect(); + detection.annotate("Autocatalytic", "yes"); + NetworkTools.dumpNetwork(netR); + + /* + * Extract the autocatalytic subnet and print it out. + * Then compute the shortest paths from the monomers to + * each other species and print the paths. + */ + Network autoNet = new ExtractSubNetwork(netR,detection.getAutocatalyticReactions(), detection.getAutocatalyticSpecies()); + System.out.println(); + System.out.println("Autocatalytic Subnet"); + NetworkTools.dumpNetwork(autoNet); + ShortestPath sp = new ShortestPath(autoNet); + for (Path p : sp.computePaths("A","B")) + System.out.println(p); + + /* + * Create a network that can be simulated and print it out. + */ + Network cataNet = new CatalysedNetwork(netR); + System.out.println(); + System.out.println("Catalysed Net"); + NetworkTools.dumpNetwork(cataNet); + + System.out.println("Seed: "+Stochastics.getInstance().getSeed()+"L"); + Stochastics.getInstance().resetSeed(); + + /* + * Simulate the network and show the trend of each species and of the + * firings of reactions in two different plots. + */ + Simulator sim = new GillespieSimple(cataNet); + ReactionIntervalObserver obs = new AutocatalyticReactionsAllObserver(sim,1); + IntervalObserver obs2 = new AmountIntervalObserver(sim,1,NumberTools.getNumbersTo(sim.getNet().getNumSpecies()-1)); + sim.addObserver(obs); + sim.addObserver(obs2); + + GnuPlot gp = new GnuPlot(); + gp.setDefaultStyle("with lines"); + GnuPlot gp2 = new GnuPlot(); + gp2.setDefaultStyle("with lines"); + + + sim.start(200); + obs.toGnuplot(gp); + gp.setVisible(true); + gp.plot(); + gp.clearData(); + obs2.toGnuplot(gp2); + gp2.setVisible(true); + gp2.plot(); + gp2.clearData(); + + /* + * Print the final values of firings. + */ + obs.setLabelFormat("%l"); + System.out.println(obs.toString()); + } + + + private static class AutocatalyticReactionsAllObserver extends ReactionIntervalObserver { + + public AutocatalyticReactionsAllObserver(Simulator sim, double interval) { + super(sim, interval, NetworkTools.getSpeciesNames(sim.getNet(), NumberTools.getNumbersTo(sim.getNet().getNumSpecies()-1))); + setLabelFormat(""); + } + + public String[] getStyles() { + String[] styles = new String[getSimulator().getNet().getNumReactions()]; + for (int i=0; i + * This class is used for the LacZ examples, so at a cell division the amount of PLac (the + * promoter) is set to 1. + * + * @author Florian Erhard + * + */ +public class CellGrowthObserver extends Observer { + + + private double generationTime; + private double timeOffset; + private double initialTimeOffset; + private double recentTime; + private long numSteps; + + /** + * Creates the observer for given simulator, generation time and a time offset (because + * the simulator starts at time 0 and for one example it actually starts at time 1000) + * + * @param sim the simulator + * @param generationTime generation time + * @param timeOffset time offset + */ + public CellGrowthObserver(Simulator sim, double generationTime, double timeOffset) { + super(sim); + + this.generationTime = generationTime; + this.initialTimeOffset = timeOffset; + } + + @Override + public void activateReaction(int mu, double tau, FireType fireType, int times) { + } + + @Override + public void finished() {} + + @Override + public void started() { + getSimulator().setVolume(1); + recentTime = Double.POSITIVE_INFINITY; + numSteps=0; + timeOffset = initialTimeOffset; + } + + @Override + public void step() { + + if((int)(getSimulator().getTime()/generationTime)>(int)(recentTime/generationTime)){ + for (int i=0; i + * For references see + * [1] Gillespie D.T., J. Comput. Phys. 22, 403 (1976), + * [2] D.Gillespie, J.Chem.Phys. 115, 1716 (2001), + * [3] Cao Y., J. Chem. Phys. 124, 044109 (2006) , + * [4] Cao Y. and Petzold L., J. Comp. Phys. 212, 6�24 (2006). + * + * @author Florian Erhard + */ +public class DecayingDimerizingHistogramDistances { + + public static void main(String args[]) throws IOException, JDOMException { + String species = "S1"; + int runs = 100000; + double time = 10; + + /* + * Create the network from file, print it out and set the proposed initial parameters. + */ + FernMLNetwork net = new FernMLNetwork(ExamplePath.find("decaydimer.xml")); + net.setInitialAmount(0, 4150); + net.setInitialAmount(1, 39565); + net.setInitialAmount(2, 3445); + + /* + * Set up the simulators + */ + Simulator tla = new TauLeapingAbsoluteBoundSimulator(net); + Simulator tlr = new TauLeapingRelativeBoundSimulator(net); + Simulator tls = new TauLeapingSpeciesPopulationBoundSimulator(net); + + /* + * Create the test sets + */ + HistogramDistanceTestSet ssaSet = new HistogramDistanceTestSet(new GibsonBruckSimulator(net), 0, runs, time, species); + HistogramDistanceTestSet[][] tauLeapingSets = new HistogramDistanceTestSet[3][]; + double[] absEps = new double[]{0.01, 0.015, 0.02, 0.025, 0.03, 0.035, 0.04}; + double[] othEps = new double[]{0.03, 0.04, 0.05, 0.06, 0.07, 0.08}; + tauLeapingSets[0] = new HistogramDistanceTestSet[absEps.length]; + tauLeapingSets[1] = new HistogramDistanceTestSet[othEps.length]; + tauLeapingSets[2] = new HistogramDistanceTestSet[othEps.length]; + for (int i = 0; i < absEps.length; i++) + tauLeapingSets[0][i] = new HistogramDistanceTestSet(tla, absEps[i], runs, time, species); + for (int i = 0; i < othEps.length; i++) + tauLeapingSets[1][i] = new HistogramDistanceTestSet(tlr, othEps[i], runs, time, species); + for (int i = 0; i < othEps.length; i++) + tauLeapingSets[2][i] = new HistogramDistanceTestSet(tls, othEps[i], runs, time, species); + + /* + * Create / read the histograms. + */ + ssaSet.createHistogram(); + for (int i = 0; i < tauLeapingSets.length; i++) + for (int j = 0; j < tauLeapingSets[i].length; j++) + tauLeapingSets[i][j].createHistogram(); + + /* + * Calculate histogram distances + */ + System.out.println("Histogram distances:"); + for (int i = 0; i < tauLeapingSets.length; i++) { + for (int j = 0; j < tauLeapingSets[i].length; j++) + System.out.println(tauLeapingSets[i][j].getSimulator().getName() + " Eps=" + tauLeapingSets[i][j].getEpsilon() + ": " + NumberTools.calculateHistogramDistance(ssaSet.getHistogram(), tauLeapingSets[i][j].getHistogram())); + System.out.println(); + } + } + +} diff --git a/src/main/java/fern/example/DecayingDimerizingInteractive.java b/src/main/java/fern/example/DecayingDimerizingInteractive.java new file mode 100644 index 00000000..fc18aebc --- /dev/null +++ b/src/main/java/fern/example/DecayingDimerizingInteractive.java @@ -0,0 +1,162 @@ +package fern.example; + +import java.io.IOException; +import java.util.Map; + +import org.jdom.JDOMException; + +import fern.network.Network; +import fern.network.fernml.FernMLNetwork; +import fern.simulation.Simulator; +import fern.simulation.algorithm.GillespieEnhanced; +import fern.simulation.algorithm.HybridMaximalTimeStep; +import fern.simulation.algorithm.TauLeapingAbsoluteBoundSimulator; +import fern.simulation.algorithm.TauLeapingRelativeBoundSimulator; +import fern.simulation.algorithm.TauLeapingSpeciesPopulationBoundSimulator; +import fern.simulation.controller.AndController; +import fern.simulation.controller.SimulationController; +import fern.simulation.observer.AmountAtMomentObserver; +import fern.tools.NetworkTools; +import fern.tools.NumberTools; +import fern.tools.gnuplot.GnuPlot; + +/** + * Demonstration of performance and accuracy differences of the different + * simulation algorithms. The reaction network proposed in [1] + * are used to calculate histograms and the histogram distances [4] of the amount + * of some molecular species at a special time point in order to compare results + * of different algorithms. Here, Fig. 3 of [3] is reproduced and the gain + * of accuracy when using a species bounded tau leaping procedure without + * loss of performance is shown. + *

+ * For references see + * [1] Gillespie D.T., J. Comput. Phys. 22, 403 (1976), + * [2] D.Gillespie, J.Chem.Phys. 115, 1716 (2001), + * [3] D.Gillespie and L.Petzold, J.Chem.Phys. 119, 8229 (2003), + * [4] Cao Y. and Petzold L., J. Comp. Phys. 212, 6�24 (2006). + * + * @author Florian Erhard + */ +@SuppressWarnings("unchecked") +public class DecayingDimerizingInteractive { + + public static void main(String[] args) throws IOException, JDOMException { + /* + * Create the network from file, print it out and set the proposed initial parameters. + */ + FernMLNetwork net = new FernMLNetwork(ExamplePath.find("decaydimer.xml")); + NetworkTools.dumpNetwork(net); + net.setInitialAmount(0, 4150); + net.setInitialAmount(1, 39565); + net.setInitialAmount(2, 3445); + + /* + * Start the trajectories. + */ + allTrajectory(net, 100000); + + } + + + private static void allTrajectory(Network net, int times) throws IOException { + /* + * Create the simulators, gnuplot objects (for each species) + * and histograms (for each species and each simulator) + */ + Simulator[] sims = new Simulator[]{ + new TauLeapingAbsoluteBoundSimulator(net), + new TauLeapingRelativeBoundSimulator(net), + new TauLeapingSpeciesPopulationBoundSimulator(net), + new HybridMaximalTimeStep(net), + new GillespieEnhanced(net) + }; + GnuPlot[] gp = new GnuPlot[3]; + for (int i = 0; i < 3; i++) { + gp[i] = new GnuPlot(); + gp[i].setDefaultStyle("with linespoints"); + } + Map[][] histos = new Map[sims.length][3]; + + /* + * Use each simulator to create times trajectories and store the resulting + * histograms. + */ + for (int s = 0; s < sims.length; s++) { + System.out.println(sims[s].getName()); + histos[s] = trajectory(sims[s], gp, times); + for (int i = 0; i < gp.length; i++) { + gp[i].setVisible(true); + gp[i].plot(); + } + System.out.println(); + } + System.out.println(); + + /* + * calculate the pairwise histogram distances for each histogram + */ + for (int s = 0; s < 3; s++) { + System.out.println("Histogram distances for S" + (s + 1) + ":"); + for (int i = 0; i < histos.length; i++) { + for (int j = 0; j < histos.length; j++) { + System.out.printf("%.4f\t", NumberTools.calculateHistogramDistance(histos[i][s], histos[j][s])); + } + System.out.println(); + } + } + } + + private static Map[] trajectory(Simulator sim, GnuPlot[] gp, int times) throws IOException { + /* + * Create the observers for the three different species S1, S2, S3 + */ + AmountAtMomentObserver[] obs = new AmountAtMomentObserver[3]; + for (int i = 0; i < 3; i++) { + obs[i] = new AmountAtMomentObserver(sim, 10, "S" + (i + 1)); + obs[i].setLabelFormat("%a - %l"); + sim.addObserver(obs[i]); + } + /* + * Stop the simulation after each species is recorded. + */ + SimulationController c = new AndController(obs); + + /* + * Perform the simulations and print a simple progressbar (one dot means 1% done) + */ + long start = System.currentTimeMillis(); + for (int i = 1; i <= times; i++) { + sim.start(c); + if (i % (times / 100.0) == 0) + System.out.print("."); + } + long end = System.currentTimeMillis(); + System.out.println(); + System.out.println(dateFormat(end - start)); + + /* + * Present and return the results. + */ + for (int i = 0; i < 3; i++) + obs[i].toGnuplot(gp[i]); + Map[] re = new Map[obs.length]; + for (int i = 0; i < re.length; i++) + re[i] = obs[i].getHistogram(0); + return re; + } + + private static String dateFormat(long l) { + int ms = (int) (l % 1000); + l /= 1000; + int s = (int) (l % 60); + l /= 60; + int m = (int) (l % 60); + l /= 60; + StringBuilder sb = new StringBuilder(); + if (l > 0) sb.append(l + "h "); + if (m > 0) sb.append(m + "m "); + if (s > 0) sb.append(s + "s "); + sb.append(ms + "ms "); + return sb.toString(); + } +} diff --git a/src/main/java/fern/example/DecayingDimerizingPlots.java b/src/main/java/fern/example/DecayingDimerizingPlots.java new file mode 100644 index 00000000..3a7b6b5b --- /dev/null +++ b/src/main/java/fern/example/DecayingDimerizingPlots.java @@ -0,0 +1,129 @@ +package fern.example; + +import java.io.File; +import java.io.IOException; +import java.util.Map; + +import org.jdom.JDOMException; + +import fern.network.fernml.FernMLNetwork; +import fern.simulation.Simulator; +import fern.simulation.algorithm.GibsonBruckSimulator; +import fern.simulation.algorithm.TauLeapingAbsoluteBoundSimulator; +import fern.simulation.algorithm.TauLeapingRelativeBoundSimulator; +import fern.simulation.algorithm.TauLeapingSpeciesPopulationBoundSimulator; +import fern.simulation.observer.AmountAtMomentObserver; +import fern.tools.NumberTools; +import fern.tools.gnuplot.GnuPlot; + +/** + * Demonstration of performance and accuracy differences of the different + * simulation algorithms. The reaction network proposed in [1] + * are used to calculate histograms and the histogram distances [4] of the amount + * of some molecular species at a special time point in order to compare results + * of different algorithms. Here, Fig. 3 of [3] is reproduced and the gain + * of accuracy when using a species bounded tau leaping procedure without + * loss of performance is shown. + *

+ * For references see + * [1] Gillespie D.T., J. Comput. Phys. 22, 403 (1976), + * [2] D.Gillespie, J.Chem.Phys. 115, 1716 (2001), + * [3] D.Gillespie and L.Petzold, J.Chem.Phys. 119, 8229 (2003), + * [4] Cao Y. and Petzold L., J. Comp. Phys. 212, 6�24 (2006). + */ +@Deprecated +public class DecayingDimerizingPlots { + + public static void main(String[] args) throws IOException, JDOMException { + /* + * Create the network from file, print it out and set the proposed initial parameters. + */ + FernMLNetwork net = new FernMLNetwork(ExamplePath.find("decaydimer.xml")); + net.setInitialAmount(0, 4150); + net.setInitialAmount(1, 39565); + net.setInitialAmount(2, 3445); + + /* + * Create the histograms (very time consuming) or load them from files + */ + Map ssaHisto; + Map tlaHisto; + Map tlrHisto; + Map tlsHisto; + if (ExamplePath.exists("decayssa.hist")) { + ssaHisto = NumberTools.loadHistogram(ExamplePath.find("decayssa.hist")); + } else { + ssaHisto = createHisto(new GibsonBruckSimulator(net), 100000); + NumberTools.saveHistogram(ssaHisto, new File("decayssa.hist")); + } + + if (ExamplePath.exists("decaytla.hist")) { + tlaHisto = NumberTools.loadHistogram(ExamplePath.find("decaytla.hist")); + } else { + tlaHisto = createHisto(new TauLeapingAbsoluteBoundSimulator(net), 100000); + NumberTools.saveHistogram(tlaHisto, new File("decaytla.hist")); + } + + if (ExamplePath.exists("decaytlr.hist")) { + tlrHisto = NumberTools.loadHistogram(ExamplePath.find("decaytlr.hist")); + } else { + tlrHisto = createHisto(new TauLeapingRelativeBoundSimulator(net), 100000); + NumberTools.saveHistogram(tlrHisto, new File("decaytlr.hist")); + } + if (ExamplePath.exists("decaytls.hist")) { + tlsHisto = NumberTools.loadHistogram(ExamplePath.find("decaytls.hist")); + } else { + tlsHisto = createHisto(new TauLeapingSpeciesPopulationBoundSimulator(net), 100000); + NumberTools.saveHistogram(tlsHisto, new File("decaytls.hist")); + } + + + /* + * Plot the histograms into one gnuplot object. + */ + GnuPlot gp = new GnuPlot(); + gp.addData(getHistoAsParallelArray(ssaHisto), new String[]{"exact SSA"}, new String[]{"with linespoints"}); + gp.addData(getHistoAsParallelArray(tlaHisto), new String[]{"Absolute Bound 0.03"}, new String[]{"with linespoints"}); + gp.addData(getHistoAsParallelArray(tlrHisto), new String[]{"Relative Bound 0.03"}, new String[]{"with linespoints"}); + gp.addData(getHistoAsParallelArray(tlsHisto), new String[]{"Species Bound 0.03"}, new String[]{"with linespoints"}); + gp.setVisible(true); + gp.plot(); + + /* + * Calculate the histogram distances. + */ + System.out.println("Histogram distance exact SSA - "); + System.out.println("Absolute Bound: " + NumberTools.calculateHistogramDistance(ssaHisto, tlaHisto)); + System.out.println("Relative Bound: " + NumberTools.calculateHistogramDistance(ssaHisto, tlrHisto)); + System.out.println("Species Bound: " + NumberTools.calculateHistogramDistance(ssaHisto, tlsHisto)); + System.out.println("(each eps=0.03)"); + } + + private static double[][] getHistoAsParallelArray(Map histo) throws IOException { + int max = NumberTools.max(histo.keySet()); + int min = NumberTools.min(histo.keySet()); + + double[][] data = new double[max - min + 1][2]; + for (int i = min; i <= max; i++) { + data[i - min][0] = i; + data[i - min][1] = histo.containsKey(i) ? (double) histo.get(i) / 100000.0 : 0.0; + } + return data; + } + + @SuppressWarnings("unused") + private static Map createHisto(Simulator sim, int runs) { + AmountAtMomentObserver obs = new AmountAtMomentObserver(sim, 10, "S1"); + sim.addObserver(obs); + + for (int i = 1; i <= runs; i++) { + sim.start(obs); + if (i % (runs / 1000.0) == 0) + System.out.print("."); + if (i % (runs / 10.0) == 0) + System.out.println(); + } + return obs.getHistogram(0); + } + +} diff --git a/src/main/java/fern/example/Dsmts.java b/src/main/java/fern/example/Dsmts.java new file mode 100644 index 00000000..60c32917 --- /dev/null +++ b/src/main/java/fern/example/Dsmts.java @@ -0,0 +1,255 @@ +package fern.example; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.util.LinkedList; +import java.util.List; + +import fern.network.FeatureNotSupportedException; +import fern.network.sbml.SBMLNetwork; +import fern.simulation.Simulator; +import fern.simulation.algorithm.CompositionRejection; +import fern.simulation.algorithm.GillespieEnhanced; +import fern.simulation.algorithm.GillespieSimple; +import fern.simulation.observer.AmountIntervalObserver; +import fern.simulation.observer.IntervalObserver; +import fern.tools.NumberTools; +import fern.tools.gnuplot.GnuPlot; +import org.sbml.jsbml.validator.ModelOverdeterminedException; + +import javax.xml.stream.XMLStreamException; + +/** + * Perform a series of tests (refer to http://www.calibayes.ncl.ac.uk/Resources/dsmts). + * You have to specify the path to the unpacked dsmts archive. The method test produces + * one line of text containing the test results for each species in the model. If specified, + * it also produces 4 plots: + *

    + *
  • average trend curve of the simulated trajectories and the analytical determined
  • + *
  • stddev trend curve of the simulated trajectories and the analytical determined
  • + *
  • deviation of the simulated averages to the real ones (the z values described in the dsmts user guide)
  • + *
  • deviation of the simulated stddevs to the real ones (the y values described in the dsmts user guide)
  • + *
+ * + * It may be wise to leave the producePlot flag set to false in the for loop because for + * each test model 4 windows will pop up! + * + */ +public class Dsmts { + + public static void main(String[] args) throws IOException { + int runs = 10000; + String path = "dsmts/"; + + for (String f : new File(path).list()) { + try { + if (f.endsWith(".xml")) + System.out.println(test(path+f.substring(0,f.length()-4),runs,false)); + } catch (Exception e) { + System.out.println("Error: "+e.getMessage()); + } + } + + //System.out.println(test("dsmts3/dsmts-001-01",runs, true)); + } + + private static String test(String test, int runs, boolean producePlot) throws FeatureNotSupportedException, IOException, XMLStreamException, ModelOverdeterminedException { + + // usual stuff: load network, create simulator and add the observer + SBMLNetwork net = new SBMLNetwork(new File(test+".xml")); + Simulator sim = new CompositionRejection(net); + net.registerEvents(sim); // important for sbml event handling! + IntervalObserver obs = (IntervalObserver)sim.addObserver(new AmountIntervalObserver(sim,1,NumberTools.getNumbersTo(net.getNumSpecies()-1))); + + // collect the data also outside of the observer since we want to calculate stddevs + double[][][] data = new double[runs][][]; // runs, time, species + + // perform the simulations and collect the data + for (int i=0; i3) { + numA[s-1]++; + } + } + Z[0][t]=t; + } + + + + // count occurrences of stddev outside [-5:5] of the transformed means + int[] numS = new int[avg[0].length-1]; + double[][] Y = new double[avg[0].length][Math.min(calcAvg.length, avg.length)]; + double y; + for (int t=0; t5) + numS[s-1]++; + } + Y[0][t]=t; + } + + // if you want plots, you will get them! + if (producePlot) { + String[] species = new String[net.getNumSpecies()]; + for (int i=0; i re = new LinkedList(); + String line; + String[] tok; + double[] ele; + + while((line=reader.readLine())!=null) { + tok = line.split(","); + ele = new double[tok.length]; + for (int i=0; i histogram; + private double epsilon; + private Simulator simulator; + private int runs; + private String species; + private AmountAtMomentObserver observer; + + public HistogramDistanceTestSet(Simulator sim, double eps, int runs, double time, String species) { + this.simulator = sim; + this.species = species; + this.runs = runs; + this.epsilon = eps; + observer = new AmountAtMomentObserver(sim,time,species); + sim.addObserver(observer); + } + + public void createHistogram() throws IOException { + if (getFile().exists()) { + System.out.println("Load histogram from file "+getFile()); + histogram = NumberTools.loadHistogram(getFile()); + } + else { + if (simulator instanceof AbstractBaseTauLeaping) + ((AbstractBaseTauLeaping) simulator).setEpsilon(epsilon); + + System.out.println("Calculate histogram"); + for (int i=1; i<=runs; i++) { + simulator.start(observer); + if (i%(runs/1000.0)==0) + System.out.print("."); + if (i%(runs/10.0)==0) + System.out.println(); + } + histogram = observer.getHistogram(0); + System.out.println("Done and saved to "+getFile()); + NumberTools.saveHistogram(histogram, getFile()); + } + } + + public double[][] getHistoAsParallelArray(){ + int max = NumberTools.max(histogram.keySet()); + int min = NumberTools.min(histogram.keySet()); + + double[][] data = new double[max-min+1][2]; + for (int i=min; i<=max; i++) { + data[i-min][0] = i; + data[i-min][1] = histogram.containsKey(i) ? (double)histogram.get(i)/runs : 0.0; + } + return data; + } + + public File getFile() { + String fn = simulator.getNet().getName()+"_"+ + simulator.getName()+"_eps"+epsilon+"_runs"+runs+"_species"+species+".hist"; + + if (ExamplePath.exists(fn)) + return ExamplePath.find(fn); + else + return new File(fn); + } + + public Map getHistogram() { + return histogram; + } + + public double getEpsilon() { + return epsilon; + } + + public Simulator getSimulator() { + return simulator; + } + +} diff --git a/src/main/java/fern/example/IrreversibleIsomerization.java b/src/main/java/fern/example/IrreversibleIsomerization.java new file mode 100644 index 00000000..1ee3b363 --- /dev/null +++ b/src/main/java/fern/example/IrreversibleIsomerization.java @@ -0,0 +1,72 @@ +package fern.example; + +import java.io.IOException; +import java.util.Locale; + +import org.jdom.JDOMException; + +import fern.network.Network; +import fern.network.fernml.FernMLNetwork; +import fern.simulation.Simulator; +import fern.simulation.algorithm.AbstractBaseTauLeaping; +import fern.simulation.algorithm.GibsonBruckSimulator; +import fern.simulation.algorithm.TauLeapingAbsoluteBoundSimulator; +import fern.simulation.observer.AmountIntervalObserver; +import fern.simulation.observer.LeapObserver; +import fern.tools.gnuplot.GnuPlot; + +/** + * Uses the Irreversible-isomerization model to show effects of different + * choices for epsilon. The number of leaps is slightly greater than proposed + * in the paper because in the paper tau wasn't bound by sigma yet (yielding + * sometimes to lower tau and hence more leaps) + *

+ * For references see D.Gillespie, J.Chem.Phys. 115, 1716 (2001) + * + * @author Florian Erhard + * + */ +public class IrreversibleIsomerization { + + public static void main(String[] args) throws IOException, JDOMException { + double endTime = 12.67; // as proposed in the paper + + /* + * Create the network and the gnuplot + */ + Network net = new FernMLNetwork(ExamplePath.find("isomerization.xml")); + GnuPlot gp = new GnuPlot(); + gp.addCommand("set xrange [0:5]"); + gp.setVisible(true); + + /* + * First create a line in the plot representing the exact SSA done by a + * GibsonBruckSimulator + */ + Simulator ssa = new GibsonBruckSimulator(net); + AmountIntervalObserver amount = (AmountIntervalObserver) ssa.addObserver(new AmountIntervalObserver(ssa,0.01, "S1")); + ssa.start(endTime); + amount.setLabelFormat("exact SSA"); + amount.toGnuplot(gp); + gp.getAxes().get(0).setStyle(1, "with lines"); + gp.plot(); + + /* + * Now create a tau leap simulator and perform the simulation for different values + * of epsilon. Feel free to try different Tau leaping procedures. + */ + AbstractBaseTauLeaping sim = new TauLeapingAbsoluteBoundSimulator(net); + sim.setUseSimpleFactor(0); + LeapObserver obs = (LeapObserver) sim.addObserver(new LeapObserver(sim,"S1")); + + for (double eps : new double[] {0.03, 0.15, 0.5}) { + sim.setEpsilon(eps); + sim.start(endTime); + obs.setLabelFormat(String.format(Locale.US,"%.2f",eps)); + obs.toGnuplot(gp); + gp.plot(); + System.out.println("Number of leaps for eps="+eps+": "+obs.getNumLeaps()); + } + } + +} diff --git a/src/main/java/fern/example/LacYComplete.java b/src/main/java/fern/example/LacYComplete.java new file mode 100644 index 00000000..58bb24d0 --- /dev/null +++ b/src/main/java/fern/example/LacYComplete.java @@ -0,0 +1,108 @@ +package fern.example; + +import java.io.IOException; +import java.io.PrintStream; +import java.util.Locale; + +import org.jdom.JDOMException; + +import fern.network.fernml.FernMLNetwork; +import fern.simulation.Simulator; +import fern.simulation.Simulator.FireType; +import fern.simulation.algorithm.GillespieEnhanced; +import fern.simulation.algorithm.HybridMaximalTimeStep; +import fern.simulation.observer.AmountIntervalObserver; +import fern.simulation.observer.Observer; +import fern.tools.NetworkTools; +import fern.tools.gnuplot.GnuPlot; + +/** + * The LacZ/LacY model of procaryotic gene expression proposed by [1] + * is simulated. Here, the full model (containing LacZ and LacY regulation) + * is simulated for one full cell cycle. Since it is very time consuming with an exact method, + * the simulation progress is shown online in the console. + * + *

+ * For references see [1] Kierzek A.M., Bioinformatics 18, 670 (2002) + * + * @author Florian Erhard + * + */ +public class LacYComplete { + + public static void main(String[] args) throws IOException, JDOMException { + final PrintStream out = args.length==0 ? System.out : new PrintStream(args[0]); + /* + * Load the network and print it out. + */ + FernMLNetwork net = new FernMLNetwork(ExamplePath.find("lacy.xml")); + + if (args.length==0) + NetworkTools.dumpNetwork(net); + + Simulator ssa = args.length<2 || args[1].equals("hybrid") ? + new HybridMaximalTimeStep(net) : new GillespieEnhanced(net); + + /* + * Create the necessary CellGrowthObserver and one to show the progress. + */ + final long startTime = System.currentTimeMillis(); + ssa.addObserver(new CellGrowthObserver(ssa,2100,0)); + ssa.addObserver(new Observer(ssa) { + long num = 0; + @Override + public void activateReaction(int mu, double tau, FireType fireType, int times) { + num+=times; + } + + @Override + public void finished() {} + + @Override + public void started() { + setTheta(0); + } + + @Override + public void step() {} + + @Override + public void theta(double theta) { + out.printf(Locale.US,"%s %4.0f %9d %9f\n",dateFormat(System.currentTimeMillis()-startTime),theta,num,getSimulator().getAmount(getSimulator().getNet().getSpeciesByName("product"))); + setTheta(theta+10); + } + + }); + + AmountIntervalObserver obs = new AmountIntervalObserver(ssa,10,"product"); + ssa.addObserver(obs); + + ssa.start(2100); + + if (args.length==0) { + GnuPlot gp = new GnuPlot(); + gp.setDefaultStyle("with linespoints"); + obs.toGnuplot(gp); + gp.setVisible(true); + gp.plot(); + gp.clearData(); + } + + } + + + private static String dateFormat(long l) { + int ms = (int) (l % 1000); + l/=1000; + int s = (int) (l % 60); + l/=60; + int m = (int) (l % 60); + l/=60; + StringBuilder sb = new StringBuilder(); + sb.append(String.format("%03d", l)+":"); + sb.append(String.format("%02d", m)+":"); + sb.append(String.format("%02d", s)+"."); + sb.append(String.format("%-3d", ms)); + return sb.toString(); + } +} diff --git a/src/main/java/fern/example/LacYHistogramDistances.java b/src/main/java/fern/example/LacYHistogramDistances.java new file mode 100644 index 00000000..e741d728 --- /dev/null +++ b/src/main/java/fern/example/LacYHistogramDistances.java @@ -0,0 +1,89 @@ +package fern.example; + +import java.io.IOException; + +import org.jdom.JDOMException; + +import fern.network.fernml.FernMLNetwork; +import fern.simulation.Simulator; +import fern.simulation.algorithm.GillespieSimple; +import fern.simulation.algorithm.TauLeapingAbsoluteBoundSimulator; +import fern.simulation.algorithm.TauLeapingRelativeBoundSimulator; +import fern.simulation.algorithm.TauLeapingSpeciesPopulationBoundSimulator; +import fern.tools.NumberTools; +/** + * The LacZ/LacY model of procaryotic gene expression proposed by [1] + * is simulated. This reproduces the values [2] Fig. 4, which represent + * histogram distances of the different procedures regarding the simulation + * of time 1000 to 1001 of the cell cycle. + * + *

+ * For references see + * [1] Kierzek A.M., Bioinformatics 18, 670 (2002) and + * [2] Cao Y., J. Chem. Phys. 124, 044109 (2006). + * + * @author Florian Erhard + * + */ + +public class LacYHistogramDistances { + + public static void main(String[] args) throws IOException, JDOMException { + String species = "LacZlactose"; + int runs = 100000; + double time = 1; + /* + * Create the network from file. + */ + FernMLNetwork net = new FernMLNetwork(ExamplePath.find("lacy1000.xml")); + + /* + * Create and set up simulators + */ + Simulator tla = new TauLeapingAbsoluteBoundSimulator(net); + Simulator tlr = new TauLeapingRelativeBoundSimulator(net); + Simulator tls = new TauLeapingSpeciesPopulationBoundSimulator(net); + Simulator exact = new GillespieSimple(net); + tla.addObserver(new CellGrowthObserver(tla,2100,1000)); + tlr.addObserver(new CellGrowthObserver(tlr,2100,1000)); + tls.addObserver(new CellGrowthObserver(tls,2100,1000)); + exact.addObserver(new CellGrowthObserver(exact,2100,1000)); + + /* + * Create test sets. + */ + HistogramDistanceTestSet ssaSet = new HistogramDistanceTestSet(exact,0,runs,time,species); + HistogramDistanceTestSet[][] tauLeapingSets = new HistogramDistanceTestSet[3][]; + double[] absEps = new double[] {0.01,0.015,0.02,0.025,0.03,0.035,0.040,0.045,0.05}; + double[] othEps = new double[] {0.03,0.04,0.05,0.06,0.07,0.08,0.09,0.1}; + tauLeapingSets[0] = new HistogramDistanceTestSet[absEps.length]; + tauLeapingSets[1] = new HistogramDistanceTestSet[othEps.length]; + tauLeapingSets[2] = new HistogramDistanceTestSet[othEps.length]; + for (int i=0; i + * For references see [1] Kierzek A.M., Bioinformatics 18, 670 (2002) + * + * @author Florian Erhard + * + */ +public class LacZ { + + public static void main(String[] args) throws IOException, JDOMException { + /* + * Load the network and print it out. + */ + FernMLNetwork net = new FernMLNetwork(ExamplePath.find("lacz.xml")); + NetworkTools.dumpNetwork(net); + + /* + * Simulate it with an CellGrowthObserver which adjusts the volume accordingly + * to the cell growth of E.Coli. Feel free to try other simulators! + */ + Simulator ssa = new GillespieSimple(net); + AmountIntervalObserver obs = new AmountIntervalObserver(ssa,10,"LacZ"); + ssa.addObserver(obs); + ssa.addObserver(new CellGrowthObserver(ssa,2100,0)); + + GnuPlot gp = new GnuPlot(); + gp.setDefaultStyle("with linespoints"); + for (int i=0; i<1000; i++) { + ssa.start(10*35*60); + obs.toGnuplot(gp); + gp.setVisible(true); + gp.plot(); + gp.clearData(); + } + + + } + +} diff --git a/src/main/java/fern/example/Mapk.java b/src/main/java/fern/example/Mapk.java new file mode 100644 index 00000000..9e70cccf --- /dev/null +++ b/src/main/java/fern/example/Mapk.java @@ -0,0 +1,80 @@ +package fern.example; + +import java.io.IOException; +import java.io.PrintWriter; + +import org.jdom.JDOMException; + +import fern.network.DefaultAmountManager; +import fern.network.Network; +import fern.network.fernml.FernMLNetwork; +import fern.simulation.Simulator; +import fern.simulation.algorithm.CompositionRejection; +import fern.simulation.algorithm.GillespieEnhanced; +import fern.simulation.algorithm.GillespieSimple; +import fern.simulation.controller.AmountLowerThanController; +import fern.simulation.controller.AndController; +import fern.simulation.controller.DefaultController; +import fern.simulation.controller.OrController; +import fern.simulation.controller.SimulationController; +import fern.simulation.observer.AmountIntervalObserver; +import fern.simulation.observer.IntervalObserver; +import fern.tools.NetworkTools; +import fern.tools.gnuplot.GnuPlot; + +/** + * The most basic example uses the famous enzyme kinetics equation by + * Michaelis and Menten + * S + E <-> ES -> P + * to introduce fundamental loading and repeated simulation of reaction networks. + * Furthermore, some advanced usage of the Gnuplot class is presented: + * Two plots are created from the data of one Observer, one showing the average + * trend curve over all trajectories, the other showing each trajectory individually. + * Both plots are updated after each simulation run. + */ +public class Mapk { + + public static void main(String[] args) throws IOException, JDOMException { + + /* + * create network, simulator and observer + */ + + Network net = new FernMLNetwork( + ExamplePath.find("mapk.xml")); // load the network from the file + NetworkTools.dumpNetwork( + net, new PrintWriter(System.out)); // print out the network structure + + Simulator sim = new GillespieEnhanced(net); // create a simulator; feel free to replace GillespieSimple with other simulator classes + IntervalObserver amount = + new AmountIntervalObserver( + sim,10,"E0*","E1*","E2*","E3*","E4*","E5*"); // create the observer + + amount.setLabelFormat(""); // just a beautification: no titles + sim.addObserver(amount); // register the observer to the simulator + + /* + * create 2 gnuplot objects, one to plot each trajectory, the other one to plot + * the average trajectory + */ + GnuPlot avg = new GnuPlot(); // create a gnuplot object to plot the observer's average data + avg.setDefaultStyle("with linespoints"); // beautification: set the plot style to linespoints + avg.addCommand("set xrange [0:800]"); // beautification: set the xrange + avg.setVisible(true); // show the plot jframe - once it is visible and plot is called, the plot will be refreshed + + SimulationController amountController = new AmountLowerThanController(25,"E5*"); + SimulationController timeController = new DefaultController(800); + /* + * perform 50 simulation runs and plot the data interactively + */ + for (int i=0; i<100; i++) { + sim.start(new OrController(amountController,timeController)); // start the simulation up to 10 time units + amount.toGnuplot(avg); // add the average data to the other gnuplot object + avg.plot(); // invoke gnuplot and plot the data + avg.clearData(); // clear the data (we want only the recent average trends) + } + + + } + +} diff --git a/src/main/java/fern/example/MapkBenchmark.java b/src/main/java/fern/example/MapkBenchmark.java new file mode 100644 index 00000000..c565608a --- /dev/null +++ b/src/main/java/fern/example/MapkBenchmark.java @@ -0,0 +1,51 @@ +package fern.example; + +import java.io.IOException; + +import org.jdom.JDOMException; + +import fern.benchmark.Benchmark; +import fern.benchmark.SimulatorPerformance; +import fern.benchmark.SimulatorRandomNumbers; +import fern.network.Network; +import fern.network.fernml.FernMLNetwork; + +/** + * Use the signal transduction pathway network of the epidermal growth factor + * proposed by [1] to introduce the benchmark system. For more information + * please refer to {@link Benchmark}. + *

+ * References: + * [1] Lee D.-Y., Metabolic Engineering 8, 112-122 (2006) + * + * @author Florian Erhard + * + */ +public class MapkBenchmark { + + public static void main(String[] args) throws IOException, JDOMException { + Network net = new FernMLNetwork(ExamplePath.find("mapk.xml")); + + /* + * Load the network into the benchmark system. Feel free to try other benchmarks! + */ + SimulatorPerformance bench = new SimulatorRandomNumbers(net, 1000); + bench.setShowSteps(10); + + /* + * We only want GibsonBruck and the newest Tau leaping method. + */ + bench.getSimulators()[0] = null; + bench.getSimulators()[1] = null; + bench.getSimulators()[3] = null; + bench.getSimulators()[4] = null; + + + while (true) + bench.benchmark(); + + + + } + +} diff --git a/src/main/java/fern/example/MichaelisMentenKinetic.java b/src/main/java/fern/example/MichaelisMentenKinetic.java new file mode 100644 index 00000000..4a12aa23 --- /dev/null +++ b/src/main/java/fern/example/MichaelisMentenKinetic.java @@ -0,0 +1,78 @@ +package fern.example; + +import java.io.IOException; +import java.io.PrintWriter; + +import org.jdom.JDOMException; + +import fern.network.Network; +import fern.network.fernml.FernMLNetwork; +import fern.simulation.Simulator; +import fern.simulation.algorithm.GillespieSimple; +import fern.simulation.observer.AmountIntervalObserver; +import fern.simulation.observer.IntervalObserver; +import fern.tools.NetworkTools; +import fern.tools.gnuplot.GnuPlot; + +/** + * The most basic example uses the famous enzyme kinetics equation by + * Michaelis and Menten + * S + E <-> ES -> P + * to introduce fundamental loading and repeated simulation of reaction networks. + * Furthermore, some advanced usage of the Gnuplot class is presented: + * Two plots are created from the data of one Observer, one showing the average + * trend curve over all trajectories, the other showing each trajectory individually. + * Both plots are updated after each simulation run. + */ +public class MichaelisMentenKinetic { + + public static void main(String[] args) throws IOException, JDOMException { + + /* + * create network, simulator and observer + */ + + Network net = new FernMLNetwork( + ExamplePath.find("mm.xml")); // load the network from the file + NetworkTools.dumpNetwork( + net, new PrintWriter(System.out)); // print out the network structure + + Simulator sim = new GillespieSimple(net); // create a simulator; feel free to replace GillespieSimple with other simulator classes + IntervalObserver amount = + new AmountIntervalObserver( + sim,0.1,"S","E","ES","P"); // create the observer + + amount.setLabelFormat(""); // just a beautification: no titles + sim.addObserver(amount); // register the observer to the simulator + + /* + * create 2 gnuplot objects, one to plot each trajectory, the other one to plot + * the average trajectory + */ + GnuPlot all = new GnuPlot(); // create a gnuplot object to plot the observer's data + all.setDefaultStyle("with lines"); // beautification: set the plot style to lines + all.addCommand("set xrange [0:10]"); // beautification: set the xrange + all.setVisible(true); // show the plot jframe - once it is visible and plot is called, the plot will be refreshed + + GnuPlot avg = new GnuPlot(); // create a gnuplot object to plot the observer's average data + avg.setDefaultStyle("with linespoints"); // beautification: set the plot style to linespoints + avg.addCommand("set xrange [0:10]"); // beautification: set the xrange + avg.setVisible(true); // show the plot jframe - once it is visible and plot is called, the plot will be refreshed + + /* + * perform 50 simulation runs and plot the data interactively + */ + for (int i=0; i<50; i++) { + sim.start(10); // start the simulation up to 10 time units + amount.toGnuplotRecent(all); // add the recent data to the gnuplot object + amount.toGnuplot(avg); // add the average data to the other gnuplot object +// avg.merge(all); // merges the plots + avg.plot(); // invoke gnuplot and plot the data + avg.clearData(); // clear the data (we want only the recent average trends) + all.plot(); + } + + + } + +} diff --git a/src/main/java/fern/example/SBMLMathTreeTest.java b/src/main/java/fern/example/SBMLMathTreeTest.java new file mode 100644 index 00000000..86dc405a --- /dev/null +++ b/src/main/java/fern/example/SBMLMathTreeTest.java @@ -0,0 +1,30 @@ +package fern.example; + +import fern.network.FeatureNotSupportedException; +import fern.network.Network; +import fern.network.sbml.SBMLNetwork; +import fern.network.sbml.SBMLPropensityCalculator; +import fern.tools.NetworkTools; +import org.sbml.jsbml.validator.ModelOverdeterminedException; + +import javax.xml.stream.XMLStreamException; +import java.io.IOException; + +public class SBMLMathTreeTest { + + /** + * Dumb the MathTrees of an SBML network to Stdout + * + * @param args + * @throws FeatureNotSupportedException + */ + public static void main(String[] args) throws FeatureNotSupportedException, IOException, XMLStreamException, ModelOverdeterminedException { + Network net = new SBMLNetwork(ExamplePath.find("mapk_sbml.xml")); + for (int i=0; iPropensityCalculator. The propensity is simply + * a product of the populations of its reactant species and a specific reaction + * probability rate constant (which is related to the conventional deterministic + * rate constant and can be calculated by getConstantFromDeterministicRateConstant. + *

+ * Some of the tau leap procedures need partial derivatives of the propensity function (and + * use therefore the method calculatePartialDerivative) so the use of this + * procedures is only possible when the network's PropensityCalculator + * is a AbstractKineticConstantPropensityCalculator. + * + * @author Florian Erhard + * + */ +public abstract class AbstractKineticConstantPropensityCalculator implements + KineticConstantPropensityCalculator, PartialDerivativePropensityCalculator { + +// private Map[] reactantHistos = null; + private int[][] reactantHistosKeys = null; + private int[][] reactantHistosVals = null; + private int[][] reactants; + + /** + * Creates a AbstractKineticConstantPropensityCalculator by an array of + * adjacency arrays for the reaction's reactant species (which are the only one needed + * for the propensity calculation). + * + * @param reactants array of adjacency arrays + */ + @SuppressWarnings("unchecked") + public AbstractKineticConstantPropensityCalculator( int[][] reactants) { + reactantHistosKeys = new int[reactants.length][]; + reactantHistosVals = new int[reactants.length][]; + + for (int i=0; i reactantHisto = NumberTools.createHistogramAsMap(reactants[i]); + reactantHistosKeys[i] = new int[reactantHisto.size()]; + reactantHistosVals[i] = new int[reactantHisto.size()]; + int index = 0; + for (int r : reactantHisto.keySet()) { + reactantHistosKeys[i][index] = r; + reactantHistosVals[i][index] = reactantHisto.get(r); + index++; + } + } + this.reactants = reactants; + } + + /** + * Calculates the propensity for reaction by the formula h*c, where + * c is the kinetic constant for reaction and h is the number of + * distinct molecular reactant combinations for reaction. If a positive + * value for volume is given, it is assumed that the constants are deterministic rate + * constants and are hence transformed to specific reaction rate constants. + * + * @param reaction the index of the reaction + * @param amount the AmountManager + * @param sim the simulator + * @return the propensity for the reaction + */ + public double calculatePropensity(int reaction, AmountManager amount, Simulator sim) { + double re = getConstant(reaction); + double volume = sim.getVolume(); + if (volume>0) + re = getConstantFromDeterministicRateConstant(re, reaction, volume); + for (int i=0; iAmountManager + * @param reactantIndex the network index of the reactant to calculate the partial differential for + * @param volume the volume of the reaction space + * @return partial differential + */ + public double calculatePartialDerivative(int reaction, AmountManager amount, int reactantIndex, double volume) { + int speciesIndex = reactantIndex; + +// if (!reactantHistos[reaction].containsKey(speciesIndex)) +// return 0; + int histoIndex = -1; + + double re = getConstant(reaction); + if (volume>0) + re = getConstantFromDeterministicRateConstant(re, reaction, volume); + + for (int i=0; i3 reactants of the same species!"); + } + + return re; + } + + + + /** + * Calculates the specific reaction probability rate constant c from the conventional + * deterministic rate constant k in some fixed volume v by the formula + * c=|reactants| ! * k / V^(|reactants|-1) + *

+ * For references see Daniel T. Gillespie, A General Method for Numerically Simulating + * the Stochastic Time Evolution of Coupled Chemical Reactions, Journal of Computational + * Physics 22, 403-434 (1976) + * @param k deterministic rate constant + * @param reaction the index of the constant's reaction + * @param V the fixed volume + * @return the specific reaction probability rate constant + */ + public double getConstantFromDeterministicRateConstant(double k, int reaction, double V) { + double re = k/Math.pow(V,reactants[reaction].length-1); + for (int i=0; i speciesIdToIndex = null; + /** + * Stores a mapping from species indices to their names. + */ + protected String[] indexToSpeciesId = null; + /** + * Stores the network's identifier. + */ + protected String name = null; + + + + /** + * Reminds extending class to fill {@link AbstractNetworkImpl#annotationManager}. + */ + protected abstract void createAnnotationManager(); + /** + * Reminds extending class to fill {@link AbstractNetworkImpl#speciesIdToIndex} and {@link AbstractNetworkImpl#indexToSpeciesId}. + */ + protected abstract void createSpeciesMapping(); + /** + * Reminds extending class to fill {@link AbstractNetworkImpl#adjListPro} and {@link AbstractNetworkImpl#adjListRea}. + */ + protected abstract void createAdjacencyLists(); + /** + * Reminds extending class to fill {@link AbstractNetworkImpl#amountManager}. + */ + protected abstract void createAmountManager(); + /** + * Reminds extending class to fill {@link AbstractNetworkImpl#propensitiyCalculator}. + */ + protected abstract void createPropensityCalulator() throws ModelOverdeterminedException; + + + /** + * Create the network and give it an identifier. + * + * @param name identifier for the network + */ + public AbstractNetworkImpl(String name) { + this.name = name; + } + + public AmountManager getAmountManager() { + return amountManager; + } + public PropensityCalculator getPropensityCalculator() { + return propensitiyCalculator; + } + + public AnnotationManager getAnnotationManager() { + return annotationManager; + } + + public int getNumReactions() { + return adjListPro.length; + } + + public int getNumSpecies() { + return speciesIdToIndex.size(); + } + public int[] getProducts(int reaction) { + return adjListPro[reaction]; + } + public int[] getReactants(int reaction) { + return adjListRea[reaction]; + } + + public int getSpeciesByName(String name) { + if (speciesIdToIndex.containsKey(name)) + return speciesIdToIndex.get(name); + else + return -1; + } + + + + /** + * Gets the mapping from species names to their indices. + * + * @return species mapping + */ + public Map getSpeciesMapping() { + return speciesIdToIndex; + } + + public String getSpeciesName(int index) { + return indexToSpeciesId[index]; + } + + public String getReactionName(int index) { + StringBuilder sb = new StringBuilder(); + for (int i : getReactants(index)) + sb.append(getSpeciesName(i)+"+"); + if (sb.length()>0) sb.deleteCharAt(sb.length()-1); + sb.append("->"); + for (int i : getProducts(index)) + sb.append(getSpeciesName(i)+"+"); + if (getProducts(index).length>0) sb.deleteCharAt(sb.length()-1); + return sb.toString(); + } + +// public int[][] getAdjacencyListReactants() { +// return adjListRea; +// } +// +// public int[][] getAdjacencyListProducts() { +// return adjListPro; +// } + + public String getName() { + return name; + } + + + +} diff --git a/src/main/java/fern/network/AmountManager.java b/src/main/java/fern/network/AmountManager.java new file mode 100644 index 00000000..3a44e3fc --- /dev/null +++ b/src/main/java/fern/network/AmountManager.java @@ -0,0 +1,63 @@ +package fern.network; + +import fern.simulation.Simulator; + +/** + * + * The AmountManager is one of the most important connections between a + * {@link Network} and a {@link Simulator}. Each Simulator calls the + * performReaction method when it fires a reaction. The amount manager then + * reflects the change of its reactant / product populations. Additionally, the + * {@link PropensityCalculator} uses getAmount to calculate the propensity + * of a reaction. + *

+ * It is also possible (and necessary for the tau leaping algorithms) to save the actual + * amount of each species and, if some error happened, restore these saved values. + *

+ * The amounts are stored in an array. + * + * @author Florian Erhard + * + */ +public interface AmountManager { + + /** + * Reflects a (multiple) firing of a reaction by adjusting the populations of the + * reactants and the products. If a population becomes negative, a + * RuntimeException is thrown. + * @param reaction the index of the reaction fired + * @param times the number of firings + */ + public void performReaction(int reaction, int times); + + /** + * Gets the current amount of a species. + * @param species index of the species + * @return actual amount of the species + */ + public long getAmount(int species); + + /** + * Sets the current amount of a species. + * @param species index of the species + */ + public void setAmount(int species, long amount); + + + + /** + * Resets the amount of each species to the initial amount retrieved by the networks + * {@link AnnotationManager}. This is called whenever a {@link Simulator} is started. + */ + public void resetAmount(); + + /** + * Makes a copy of the amount array. + */ + public void save(); + /** + * Restore the amount array from the recently saved one. + */ + public void rollback(); + +} diff --git a/src/main/java/fern/network/AnnotationManager.java b/src/main/java/fern/network/AnnotationManager.java new file mode 100644 index 00000000..811221ac --- /dev/null +++ b/src/main/java/fern/network/AnnotationManager.java @@ -0,0 +1,109 @@ +/* + * Created on 12.03.2007 + * + * To change the template for this generated file go to + * Window>Preferences>Java>Code Generation>Code and Comments + */ +package fern.network; + +import java.util.Collection; + +/** + * AnnotationManager objects are the places, where static (or quasi-static) properties + * of a network are stored. At this time, all the annotations and the initial amounts of the species + * belong to the static properties. Annotations are + * only supposed to hold data which + *

    + *
  • almost never changes
  • + *
  • is read very infrequently
  • + *
+ * + * @author Florian Erhard + * + */ +public interface AnnotationManager { + + + /** + * Returns true iff the species contains an annotation of the specified type. + * + * @param species index of the species + * @param typ field name of the annotation + * @return true iff such an annotation is present + */ + public boolean containsSpeciesAnnotation(int species, String typ); + /** + * Gets the names of the species annotations. + * @param species index of the species + * @return names of the fields + */ + public Collection getSpeciesAnnotationTypes(int species); + /** + * Gets the species annotation of the specified field. + * @param species index of the species + * @param typ name of the field + * @return species annotation + */ + public String getSpeciesAnnotation(int species, String typ); + /** + * Sets the species annotation of the specified field. + * @param species index of the species + * @param typ name of the field + * @param annotation species annotation + */ + public void setSpeciesAnnotation(int species, String typ, String annotation); + + /** + * Returns true iff the reaction contains an annotation of the specified type. + * + * @param reaction index of the reaction + * @param typ field name of the annotation + * @return true iff such an annotation is present + */ + public boolean containsReactionAnnotation(int reaction, String typ); + /** + * Gets the names of the species reaction. + * @param reaction index of the reaction + * @return names of the fields + */ + public Collection getReactionAnnotationTypes(int reaction); + /** + * Gets the reaction annotation of the specified field. + * @param reaction index of the reaction + * @param typ name of the field + * @return reaction annotation + */ + public String getReactionAnnotation(int reaction, String typ); + /** + * Sets the reaction annotation of the specified field. + * @param reaction index of the reaction + * @param typ name of the field + * @param annotation reaction annotation + */ + public void setReactionAnnotation(int reaction, String typ, String annotation); + + /** + * Returns true iff the network contains an annotation of the specified type. + * + * @param typ field name of the annotation + * @return true iff such an annotation is present + */ + public boolean containsNetworkAnnotation(String typ); + /** + * Gets the names of the network reaction. + * @return names of the fields + */ + public Collection getNetworkAnnotationTypes(); + /** + * Gets the network annotation of the specified field. + * @param typ name of the field + * @return network annotation + */ + public String getNetworkAnnotation(String typ); + /** + * Sets the network annotation of the specified field. + * @param typ name of the field + * @param annotation network annotation + */ + public void setNetworkAnnotation(String typ, String annotation); +} diff --git a/src/main/java/fern/network/AnnotationManagerImpl.java b/src/main/java/fern/network/AnnotationManagerImpl.java new file mode 100644 index 00000000..d2551fa5 --- /dev/null +++ b/src/main/java/fern/network/AnnotationManagerImpl.java @@ -0,0 +1,113 @@ +package fern.network; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; + +/** + * + * Base implementation of the {@link AnnotationManager} interface. Annotations are stored + * in one big hash with Strings as keys. If you are looking for a high performance + * implementation of AnnotationManager, don't look here. However, annotations are + * only supposed to hold data which + *
    + *
  • almost never changes
  • + *
  • is read very infrequently
  • + *
+ * + * @author Florian Erhard + * + */ +public class AnnotationManagerImpl implements AnnotationManager { + + HashMap bigHash = null; + + public AnnotationManagerImpl() { + bigHash = new HashMap(); + } + + + private String makeSpeciesKey(int i, String typ) { + String s = String.valueOf(i); + StringBuffer sb = new StringBuffer(s.length()+typ.length()+2); + sb.append(s); + sb.append("S#"); + sb.append(typ); + return sb.toString(); + } + + private String makeReactionKey(int i, String typ) { + String s = String.valueOf(i); + StringBuffer sb = new StringBuffer(s.length()+typ.length()+2); + sb.append(s); + sb.append("R#"); + sb.append(typ); + return sb.toString(); + } + + public boolean containsNetworkAnnotation(String typ) { + return bigHash.containsKey(typ); + } + + public boolean containsReactionAnnotation(int reaction, String typ) { + return bigHash.containsKey(makeReactionKey(reaction, typ)); + } + + public boolean containsSpeciesAnnotation(int species, String typ) { + return bigHash.containsKey(makeSpeciesKey(species, typ)); + } + + + public String getNetworkAnnotation(String typ) { + return bigHash.get(typ); + } + + public Collection getNetworkAnnotationTypes() { + ArrayList re = new ArrayList(); + for (String key : bigHash.keySet()) { + int index = key.indexOf('#'); + if (index==-1) re.add(key); + } + return re; + } + + public String getReactionAnnotation(int reaction, String typ) { + return bigHash.get(makeReactionKey(reaction,typ)); + } + + public Collection getReactionAnnotationTypes(int reaction) { + ArrayList re = new ArrayList(); + for (String key : bigHash.keySet()) { + int index = key.indexOf('#'); + if (index>0 && key.charAt(index-1)=='R' && Integer.parseInt(key.substring(0,index-1))==reaction) re.add(key.substring(index+1)); + } + return re; + } + + public String getSpeciesAnnotation(int species, String typ) { + return bigHash.get(makeSpeciesKey(species,typ)); + } + + public Collection getSpeciesAnnotationTypes(int species) { + ArrayList re = new ArrayList(); + for (String key : bigHash.keySet()) { + int index = key.indexOf('#'); + if (index>0 && key.charAt(index-1)=='S' && Integer.parseInt(key.substring(0,index-1))==species) re.add(key.substring(index+1)); + } + return re; + } + + public void setNetworkAnnotation(String typ, String annotation) { + bigHash.put(typ, annotation); + } + + public void setReactionAnnotation(int reaction, String typ, + String annotation) { + bigHash.put(makeReactionKey(reaction,typ), annotation); + } + + public void setSpeciesAnnotation(int species, String typ, String annotation) { + bigHash.put(makeSpeciesKey(species,typ),annotation); + } + +} diff --git a/src/main/java/fern/network/ArrayKineticConstantPropensityCalculator.java b/src/main/java/fern/network/ArrayKineticConstantPropensityCalculator.java new file mode 100644 index 00000000..d9969882 --- /dev/null +++ b/src/main/java/fern/network/ArrayKineticConstantPropensityCalculator.java @@ -0,0 +1,38 @@ +package fern.network; + +/** + * + * Implementation of an AbstractKineticConstantPropensityCalculator which uses + * an array to store the constants for each reaction. + * + * @author Florian Erhard + * + */ +public class ArrayKineticConstantPropensityCalculator extends AbstractKineticConstantPropensityCalculator { + + private double[] constants = null; + + /** + * Create the propensity calculator with given constants and given reactant + * adjacency arrays + * + * @param reactants array of adjacency arrays + * @param constants array of kinetic constants + */ + public ArrayKineticConstantPropensityCalculator( int[][] reactants, double[] constants) { + super(reactants); + + for (int i=0; i getKineticLawSpecies(int reaction); +} diff --git a/src/main/java/fern/network/ConstantAmountManager.java b/src/main/java/fern/network/ConstantAmountManager.java new file mode 100644 index 00000000..85abb673 --- /dev/null +++ b/src/main/java/fern/network/ConstantAmountManager.java @@ -0,0 +1,31 @@ +package fern.network; + +public class ConstantAmountManager implements AmountManager { + + private long constantAmount; + + public ConstantAmountManager(long constantAmount) { + this.constantAmount = constantAmount; + } + + public long getAmount(int species) { + return constantAmount; + } + + public void performReaction(int reaction, int times) { + } + + public void resetAmount() { + } + + public void rollback() { + } + + public void save() { + } + + public void setAmount(int species, long amount) { + } + + +} diff --git a/src/main/java/fern/network/DefaultAmountManager.java b/src/main/java/fern/network/DefaultAmountManager.java new file mode 100644 index 00000000..8e9a9573 --- /dev/null +++ b/src/main/java/fern/network/DefaultAmountManager.java @@ -0,0 +1,95 @@ +package fern.network; + +import fern.simulation.Simulator; + +/** + * Default implementation of an amount manager, that stores the amounts in arrays. + * @author erhard + * + */ +public class DefaultAmountManager implements AmountManager { + + private Network net; + private long[] amount; + private long[] save = null; + private boolean[] boundaryConditionSpecies; + + /** + * Creates an AmountManager for a given network + * @param net the network + */ + public DefaultAmountManager(Network net) { + this.net = net; + if (net!=null) { + amount = new long[net.getNumSpecies()]; + save = new long[amount.length]; + boundaryConditionSpecies = new boolean[amount.length]; + for (int i=0; i + * RuntimeException is thrown. + * @param reaction the index of the reaction fired + * @param times the number of firings + */ + public void performReaction(int reaction, int times) { + + int[] p = net.getProducts(reaction); + for (int i=0; iPreferences>Java>Code Generation>Code and Comments + */ +package fern.network; + +public class FeatureNotSupportedException extends Exception { +private static final long serialVersionUID = 1L; + + public FeatureNotSupportedException(String msg) { + super(msg); + } +} diff --git a/src/main/java/fern/network/KineticConstantPropensityCalculator.java b/src/main/java/fern/network/KineticConstantPropensityCalculator.java new file mode 100644 index 00000000..74976a8e --- /dev/null +++ b/src/main/java/fern/network/KineticConstantPropensityCalculator.java @@ -0,0 +1,27 @@ +package fern.network; + +public interface KineticConstantPropensityCalculator extends PropensityCalculator { + + /** + * Gets the constant for a reaction + * @param reaction index of the reaction + * @return constant for the reaction + */ + public abstract double getConstant(int reaction); + + /** + * Calculates the specific reaction probability rate constant c from the conventional + * deterministic rate constant k in some fixed volume v by the formula + * c=|reactants| ! * k / V^(|reactants|-1) + *

+ * For references see Daniel T. Gillespie, A General Method for Numerically Simulating + * the Stochastic Time Evolution of Coupled Chemical Reactions, Journal of Computational + * Physics 22, 403-434 (1976) + * @param k deterministic rate constant + * @param reaction the index of the constant's reaction + * @param V the fixed volume + * @return the specific reaction probability rate constant + */ + public double getConstantFromDeterministicRateConstant(double k, int reaction, double V); + +} diff --git a/src/main/java/fern/network/Network.java b/src/main/java/fern/network/Network.java new file mode 100644 index 00000000..47efd192 --- /dev/null +++ b/src/main/java/fern/network/Network.java @@ -0,0 +1,126 @@ +/* + * Created on 12.03.2007 + * + * To change the template for this generated file go to + * Window>Preferences>Java>Code Generation>Code and Comments + */ +package fern.network; + +import fern.analysis.AnalysisBase; +import fern.network.fernml.FernMLNetwork; +import fern.network.modification.ModifierNetwork; +import fern.simulation.Simulator; + +/** + * + * The central interface of the whole framework. Each {@link Simulator} takes a Network + * for simulation, as well as each analysis algorithm takes one. Additionally Networks + * can be modified or saved as FernML-Files. + *

+ * Basically only the networks structure is stored here, other things like management of + * the species populations (amounts), propensities or annotations is sourced out to separate + * classes. The advantage is that you can reuse existing {@link AmountManager}s,... when + * you are implementing your own network (reader, wrapper, evolver,...) when you think, one + * of the existing ones is suitable. + * + * @author Florian Erhard + * + * @see AnalysisBase + * @see FernMLNetwork#FernMLNetwork(Network) + * @see FernMLNetwork#saveToFile(java.io.File) + * @see ModifierNetwork + */ +public interface Network { + + /** + * Gets the {@link AmountManager} for this network. + * + * @return the AmountManager + */ + public AmountManager getAmountManager(); + /** + * Gets the {@link PropensityCalculator} for this network. + * + * @return the PropensityCalculator + */ + public PropensityCalculator getPropensityCalculator(); + /** + * Gets the {@link AnnotationManager} for this network. + * + * @return the AnnotationManager + */ + public AnnotationManager getAnnotationManager(); + + /** + * Gets the number of species within the network. + * + * @return number of species + */ + public int getNumSpecies(); + /** + * Gets the number of reaction within the network. + * + * @return number of reactions + */ + public int getNumReactions(); + + /** + * Gets the reactants of the specified reaction. + * + * @param reaction index of the reaction + * @return indices of the reactants + */ + public int[] getReactants(int reaction); + /** + * Gets the products of the specified reaction. + * + * @param reaction index of the reaction + * @return indices of the products + */ + public int[] getProducts(int reaction); + + /** + * Gets the species index by name. If the argument is no valid species, -1 is returned. + * + * @param name name of the species + * @return index of the species + */ + public int getSpeciesByName(String name); + /** + * Gets the species name by index. + * + * @param index index of the species + * @return name of the species + */ + public String getSpeciesName(int index); + /** + * Gets a string representation of the reaction. + * + * @param index reaction index + * @return string representation + */ + public String getReactionName(int index); + /** + * Gets an identifier of the network. + * + * @return identifier of the network + */ + public String getName(); + + /** + * Gets the initial amount of the specified molecule species. + * @param species index of the species + * @return initial amount of the species + */ + public long getInitialAmount(int species); + /** + * Sets the initial amount of the specified molecule species. + * @param species index of the species + * @param value initial amount of the species + */ + public void setInitialAmount(int species, long value); + + + + +} diff --git a/src/main/java/fern/network/NetworkLoader.java b/src/main/java/fern/network/NetworkLoader.java new file mode 100644 index 00000000..09ce7a2d --- /dev/null +++ b/src/main/java/fern/network/NetworkLoader.java @@ -0,0 +1,59 @@ +package fern.network; + +import fern.network.fernml.FernMLNetwork; +import org.jdom.JDOMException; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; + +public class NetworkLoader { + + /** + * Gets types of networks that are readable by FERN. They are returned as String[N][2] + * containing for N types a description and the file pattern. + * + * @return readable file types + */ + public static String[][] getAvailableTypes() { + return new String[][] {{"FernML (*.xml)", "*.xml"},}; + } + + /** + * Tries to read the given file and returns the network in it (if there is one) + * + * @param file network file + * @throws IOException file could not be found + * @throws JDOMException file could not be parsed correctly + * @throws FeatureNotSupportedException file contains a not supported sbml feature + * @throws ClassNotFoundException the class SBMLNetwork could not be found + * @return network object + */ + public static Network readNetwork(File file) + throws IOException, JDOMException, FeatureNotSupportedException, + ClassNotFoundException { + BufferedReader r = new BufferedReader(new FileReader(file)); + Network net = null; + String line; + while ((line = r.readLine()) != null) + if (line.toLowerCase().contains("AmountManager + * @param reactantIndex the network index of the reactant to calculate the partial differential for + * @param volume the volume of the reaction space + * @return partial differential + */ + public double calculatePartialDerivative(int reaction, AmountManager amount, int reactantIndex, double volume); + +} diff --git a/src/main/java/fern/network/PropensityCalculator.java b/src/main/java/fern/network/PropensityCalculator.java new file mode 100644 index 00000000..ee5d40c1 --- /dev/null +++ b/src/main/java/fern/network/PropensityCalculator.java @@ -0,0 +1,26 @@ +package fern.network; + +import fern.simulation.Simulator; + +/** + * A PropensityCalculator is the way, a {@link Network} tells a {@link Simulator} + * how to calculate propensities for the reactions. Each Simulator calls the + * calculatePropensity method, when the amount of some reactants of a reactions has changed. + * + * @author Florian Erhard + * + */ +public interface PropensityCalculator { + /** + * Calculates the propensity for a reaction given the amounts of the AmountManager. + * If a positive + * value for volume is given, it is assumed that the constants are deterministic rate + * constants and are hence to be transformed to specific reaction rate constants. + * + * @param reaction index of the reaction + * @param amount AmountManager + * @param sim Simulator + * @return actual propensity of the reaction + */ + public double calculatePropensity(int reaction, AmountManager amount, Simulator sim); +} diff --git a/src/main/java/fern/network/creation/AutocatalyticNetwork.java b/src/main/java/fern/network/creation/AutocatalyticNetwork.java new file mode 100644 index 00000000..48c899cd --- /dev/null +++ b/src/main/java/fern/network/creation/AutocatalyticNetwork.java @@ -0,0 +1,461 @@ +package fern.network.creation; + + +import java.util.HashMap; +import java.util.LinkedList; + +import cern.colt.bitvector.BitVector; +import fern.network.AnnotationManagerImpl; +import fern.network.AbstractKineticConstantPropensityCalculator; +import fern.network.AbstractNetworkImpl; +import fern.network.AmountManager; +import fern.network.AnnotationManager; +import fern.network.DefaultAmountManager; +import fern.network.PropensityCalculator; +import fern.network.modification.ReversibleNetwork; +import fern.tools.NumberTools; +import fern.tools.Stochastics; +import fern.tools.functions.Probability; + +/** + * + * Evolve an autocatalytic network. The evolution starts at some monomers, let them aggregate + * (e.g. A+B -> AB) by a given probability and up to a given length. Then, each reaction + * is catalyzed by a given probability by some molecule species (the catalysts are stored + * as fields in the net's annotation). Since the reactions are only unidirectional you have + * to create a {@link ReversibleNetwork} out of it. Because of this, also catalysts for + * the reverse reactions are stored in the corresponding fields. + *

+ * The advantage of the unidirectional reactions is space efficiency since the ReversibleNetwork + * does not copy the reactions but redirects the indices. + *

+ * This network can of course be used for stochastic simulations. If it is just converted + * into a ReversibleNetwork, there are just different kinetic constants used for + * catalyzed and not catalyzed reactions ({@link AutocatalyticNetwork#getCatalyzedKineticConstant} + * and {@link AutocatalyticNetwork#getUncatalyzedKineticConstant}). + * + * @author Florian Erhard + * + */ +public class AutocatalyticNetwork extends AbstractNetworkImpl implements CatalystIterator { + /** + * Name of the field where catalysts are stored. + */ + public static final String CATALYSTS_FIELD = "Catalysts"; + /** + * Name of the field where catalysts for the reverse reactions are stored. + */ + public static final String CATALYSTS_FIELD_REVERSIBLE = CATALYSTS_FIELD+ReversibleNetwork.REVERSIBLE_SUFFIX; + + private char[] monomers; + private Probability createProb; + private Probability catProb; + private int maxLength; + + private int[][] shellCutPosSize = null; + private int[] shellSize = null; + private int[] shellSizeCumSum = null; + + private long monomerAmount = 1; + private long otherAmount = 1; + private double catalyzedKineticConstant = 1; + private double uncatalyzedKineticConstant = 0.001; + + private boolean useFastMethod = true; + + + /** + * Creates the autocatalytic network from given monomers, reaction probability, catalysis probability up to a + * given polymer length. By default, the fast (but memory consuming) method of creating / catalyzing is beeing used. + * + * @param monomers the monomers to start the network evolution with + * @param createProb the reaction probability + * @param catProb the catalyzation probability + * @param maxLength the maximal polymer length + * @see Probability + */ + public AutocatalyticNetwork(char[] monomers, Probability createProb, Probability catProb, int maxLength) { + this(monomers,createProb,catProb,maxLength,true); + } + + /** + * Creates the autocatalytic network from given monomers, reaction probability, catalysis probability up to a + * given polymer length. useDefault should usually set to true unless you want to evolve really huge networks. The + * slower method only needs O(log(V)) extra space where the faster method needs O(V). + * + * @param monomers the monomers to start the network evolution with + * @param createProb the reaction probability + * @param catProb the catalysis probability + * @param maxLength the maximal polymer length + * @param useFastMethod what method is going to be used for creating / catalyzing + * @see Probability + */ + public AutocatalyticNetwork(char[] monomers, Probability createProb, Probability catProb, int maxLength, boolean useFastMethod) { + super("Autocatalytic network"); + this.monomers = monomers; + this.catProb = catProb; + this.createProb = createProb; + this.maxLength = maxLength; + this.useFastMethod = useFastMethod; + init(); + } + + private void init() { + createAnnotationManager(); + createSpeciesMapping(); + createAdjacencyLists(); + createAmountManager(); + createPropensityCalulator(); + } + + /** + * Creates the adjacency lists for this network. + */ + @Override + protected void createAdjacencyLists() { + createShellSizes(); + int size = NumberTools.sum(shellSize); + adjListPro = new int[size-monomers.length][]; + adjListRea = new int[size-monomers.length][]; + indexToSpeciesId = new String[size]; + speciesIdToIndex = new HashMap(size); + for (int i=0; i0) { + sb.deleteCharAt(sb.length()-1); + annotationManager.setReactionAnnotation(reaction, field, sb.toString()); + } + } + + private void catalyzeRandomFast(int count, int reaction, String field) { + int[] r = NumberTools.getNumbersTo(getNumSpecies()); + NumberTools.shuffle(r); + + StringBuilder sb = new StringBuilder(count*(maxLength/2+1)); + // obtain count catalysts + for (int i=0; i0) { + sb.deleteCharAt(sb.length()-1); + annotationManager.setReactionAnnotation(reaction, field, sb.toString()); + } + } + + private void createShellSizes() { + shellSize = new int[maxLength+1]; + shellCutPosSize = new int[maxLength+1][]; + shellSize[1] = monomers.length; + + //shells + for (int shell=2; shell<=maxLength; shell++) { + shellCutPosSize[shell] = new int[shell]; + //cutpos + for (int c=1; cPropensityCalculator which has to be used for instantiation + * of the {@link ReversibleNetwork}. + * + * @return the PropensityCalculator for the ReversibleNetwork + */ + public PropensityCalculator getReversePropensityCalculator() { + return new AbstractKineticConstantPropensityCalculator(adjListPro) { + public double getConstant(int i) { + return (getCatalystsPopulation(i, CATALYSTS_FIELD_REVERSIBLE)) * catalyzedKineticConstant + uncatalyzedKineticConstant; + } + }; + } + + private double getCatalystsPopulation(int reaction, String field) { + if (!annotationManager.containsReactionAnnotation(reaction, field)) + return 0; + String[] catas = annotationManager.getReactionAnnotation(reaction, field).split(" "); + double re = 0; + for (String cata : catas) + re+=getAmountManager().getAmount(getSpeciesByName(cata)); + return re; + } + + @Override + protected void createSpeciesMapping() { + // done in createAdjacencyLists + } + + /** + * Implementation for the {@link CatalystIterator}. Returns the indices of + * catalysts for the given reaction. By using getAnnotationManager + * it returns the correct catalysts even if a {@link ReversibleNetwork} is used. + * + * @param reaction index of the reaction for which the catalysts have to be returned + * @return the catalysts of the reaction + */ + public Iterable getCatalysts(int reaction) { + String c = getAnnotationManager().getReactionAnnotation(reaction % getNumReactions(), reaction re = new LinkedList(); + if (c==null) return re; + String[] catas = c.split(" "); + for (int i = 0; i < catas.length; i++) { + int s = getSpeciesByName(catas[i]); + if (s>=0) + re.add(s); + } + return re; + } + + + private static class Offset { + public int Reaction = 0; + public int Species = 0; + @Override + public String toString() { + return "R="+Reaction+" S="+Species; + } + } + + + public long getInitialAmount(int species) { + return (speciesCatalystIterator is used to enumerate the catalysts of a reaction in + * an {@link AutocatalyticNetwork}. For instance the {@link AutocatalyticNetworkDetection} + * uses it to be able to walk from reactions to their catalysts in its breadth first searches. + * + * @author Florian Erhard + * + */ +public interface CatalystIterator { + /** + * Gets the indices of the catalysts of a reaction. + * @param reaction the index of the reaction + * @return catalysts of the reaction + */ + public Iterable getCatalysts(int reaction); +} diff --git a/src/main/java/fern/network/fernml/FernMLAnnotationManager.java b/src/main/java/fern/network/fernml/FernMLAnnotationManager.java new file mode 100644 index 00000000..c4b02db1 --- /dev/null +++ b/src/main/java/fern/network/fernml/FernMLAnnotationManager.java @@ -0,0 +1,196 @@ +package fern.network.fernml; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.LinkedList; +import java.util.List; + +import org.jdom.Element; + +import fern.network.AnnotationManager; + +/** + * AnnotationManager for {@link FernMLNetwork}s. The data is not copied but maintained within the tree (which should not be an efficiency + * issue except you want to use the annotations to store user data of reactions / species and + * do this very excessive - so don't do that). This avoids problems when saving the + * FernMLNetwork again. + * + * @author Florian Erhard + * + */ +public class FernMLAnnotationManager implements AnnotationManager { + + private static final String NAME = "name"; + private static final String KINETIC_CONSTANT_REVERSIBLE = "kineticConstantReversible"; + private static final String LIST_OF_REACTIONS = "listOfReactions"; + private static final String LIST_OF_SPECIES = "listOfSpecies"; + private static final String LIST_OF_ANNOTATIONS = "listOfAnnotations"; + + + private Element root = null; + + /** + * Create the AnnotationManager from the root element of the jdom tree. + * + * + * @param rootElement the root element of the jdom tree + */ + public FernMLAnnotationManager(Element rootElement) { + this.root = rootElement; + } + + + /** + * Gets the reaction jdom element for an index. The difficulty is that some + * reaction might be reversible, some might not. + * + * @param reaction index of the reaction + * @return jdom {@link Element} + */ + @SuppressWarnings("unchecked") + private Element findReaction(int reaction) { + List reactions = root.getChild(LIST_OF_REACTIONS).getChildren(); + int numReaction = 0; + for (Element r : reactions) { + boolean reversible = r.getAttribute(KINETIC_CONSTANT_REVERSIBLE)!=null; + if (numReaction==reaction || (reversible && numReaction+1==reaction)) { + return r; + } + numReaction += reversible ? 2 : 1; + } + return null; + } + + + private boolean containsAnnotation(List annotations, String typ) { + for (Element e : annotations) + if (e.getAttributeValue(NAME).equals(typ)) return true; + return false; + } + + private String getAnnotation(List annotations, String typ) { + for (Element e : annotations) + if (e.getAttributeValue(NAME).equals(typ)) return e.getText(); + return null; + } + + private Collection getAnnotationTypes(List annotations) { + ArrayList re = new ArrayList(annotations.size()); + for (Element e : annotations) + re.add(e.getAttributeValue(NAME)); + return re; + } + + private void setAnnotation(List annotations, String typ, String annotation) { + for (Element e : annotations) + if (e.getAttributeValue(NAME).equals(typ)) { + e.setText(annotation); + return; + } + Element e = new Element("annotation"); + e.setAttribute(NAME, typ); + e.setText(annotation); + annotations.add(e); + } + + @SuppressWarnings("unchecked") + public boolean containsNetworkAnnotation(String typ) { + if (root.getChild(LIST_OF_ANNOTATIONS)==null) + return false; + return containsAnnotation(root.getChild(LIST_OF_ANNOTATIONS).getChildren(), typ); + } + + @SuppressWarnings("unchecked") + public String getNetworkAnnotation(String typ) { + if (root.getChild(LIST_OF_ANNOTATIONS)==null) + return null; + return getAnnotation(root.getChild(LIST_OF_ANNOTATIONS).getChildren(),typ); + } + + @SuppressWarnings("unchecked") + public Collection getNetworkAnnotationTypes() { + if (root.getChild(LIST_OF_ANNOTATIONS)==null) + return new LinkedList(); + return getAnnotationTypes(root.getChild(LIST_OF_ANNOTATIONS).getChildren()); + } + + @SuppressWarnings("unchecked") + public void setNetworkAnnotation(String typ, String annotation) { + if (root.getChild(LIST_OF_ANNOTATIONS)==null) + root.getChildren().add(0, new Element(LIST_OF_ANNOTATIONS)); + setAnnotation(root.getChild(LIST_OF_ANNOTATIONS).getChildren(), typ, annotation); + } + + + + @SuppressWarnings("unchecked") + public boolean containsReactionAnnotation(int reaction, String typ) { + Element el = findReaction(reaction); + if (el.getChild(LIST_OF_ANNOTATIONS)==null) + return false; + return containsAnnotation(el.getChild(LIST_OF_ANNOTATIONS).getChildren(), typ); + } + + @SuppressWarnings("unchecked") + public String getReactionAnnotation(int reaction, String typ) { + Element el = findReaction(reaction); + if (el.getChild(LIST_OF_ANNOTATIONS)==null) + return null; + return getAnnotation(el.getChild(LIST_OF_ANNOTATIONS).getChildren(), typ); + } + + @SuppressWarnings("unchecked") + public Collection getReactionAnnotationTypes(int reaction) { + Element el = findReaction(reaction); + if (el.getChild(LIST_OF_ANNOTATIONS)==null) + return new LinkedList(); + return getAnnotationTypes(el.getChild(LIST_OF_ANNOTATIONS).getChildren()); + } + + @SuppressWarnings("unchecked") + public void setReactionAnnotation(int reaction, String typ, + String annotation) { + Element el = findReaction(reaction); + if (el.getChild(LIST_OF_ANNOTATIONS)==null) + el.getChildren().add(0, new Element(LIST_OF_ANNOTATIONS)); + setAnnotation(el.getChild(LIST_OF_ANNOTATIONS).getChildren(), typ, annotation); + } + + + + @SuppressWarnings("unchecked") + public boolean containsSpeciesAnnotation(int species, String typ) { + Element el = (Element) root.getChild(LIST_OF_SPECIES).getChildren().get(species); + if (el.getChild(LIST_OF_ANNOTATIONS)==null) + return false; + return containsAnnotation(el.getChild(LIST_OF_ANNOTATIONS).getChildren(), typ); + } + + @SuppressWarnings("unchecked") + public String getSpeciesAnnotation(int species, String typ) { + Element el = (Element) root.getChild(LIST_OF_SPECIES).getChildren().get(species); + if (el.getChild(LIST_OF_ANNOTATIONS)==null) + return null; + return getAnnotation(el.getChild(LIST_OF_ANNOTATIONS).getChildren(), typ); + } + + @SuppressWarnings("unchecked") + public Collection getSpeciesAnnotationTypes(int species) { + Element el = (Element) root.getChild(LIST_OF_SPECIES).getChildren().get(species); + if (el.getChild(LIST_OF_ANNOTATIONS)==null) + return new LinkedList(); + return getAnnotationTypes(el.getChild(LIST_OF_ANNOTATIONS).getChildren()); + } + + @SuppressWarnings("unchecked") + public void setSpeciesAnnotation(int species, String typ, String annotation) { + Element el = (Element) root.getChild(LIST_OF_SPECIES).getChildren().get(species); + if (el.getChild(LIST_OF_ANNOTATIONS)==null) + el.getChildren().add(0, new Element(LIST_OF_ANNOTATIONS)); + setAnnotation(el.getChild(LIST_OF_ANNOTATIONS).getChildren(), typ, annotation); + } + + + + +} diff --git a/src/main/java/fern/network/fernml/FernMLNetwork.java b/src/main/java/fern/network/fernml/FernMLNetwork.java new file mode 100644 index 00000000..d49149ba --- /dev/null +++ b/src/main/java/fern/network/fernml/FernMLNetwork.java @@ -0,0 +1,350 @@ +package fern.network.fernml; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.net.URL; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; + +import org.jdom.Document; +import org.jdom.Element; +import org.jdom.JDOMException; +import org.jdom.input.SAXBuilder; +import org.jdom.output.XMLOutputter; + +import fern.network.AbstractKineticConstantPropensityCalculator; +import fern.network.AbstractNetworkImpl; +import fern.network.AnnotationManager; +import fern.network.ArrayKineticConstantPropensityCalculator; +import fern.network.DefaultAmountManager; +import fern.network.Network; +import fern.network.PropensityCalculator; +import fern.tools.NetworkTools; + + +/** + * A FernMLNetwork is usually loaded from a file. For specifications see + * the included FernMLSchema.xsd or the examples. Additionally, a FernMLNetwork + * can be created out of an arbitrary {@link Network}. By using the saveToFile + * method, every Network can be saved as a fernml-File. + * + * + * @author Florian Erhard + * + */ +public class FernMLNetwork extends AbstractNetworkImpl { + + private Document document = null; + private int numReaction = 0; + private int numSpecies = 0; + private long[] initialAmount = null; + + + /** + * Creates a FernMLNetwork from a file. + * @param file file containing the network + * @throws IOException if the file cannot be read + * @throws JDOMException if the file is malformed + */ + public FernMLNetwork(File file) throws IOException, JDOMException { + super(file.getName()); + + File schemeFile = new File("FernMLSchema.xsd"); + String schemeFilePath = schemeFile.getAbsolutePath(); + + SAXBuilder sax = new SAXBuilder(true); + sax.setFeature("http://apache.org/xml/features/validation/schema", true); + sax.setProperty("http://java.sun.com/xml/jaxp/properties/schemaLanguage","http://www.w3.org/2001/XMLSchema" ); + sax.setProperty("http://java.sun.com/xml/jaxp/properties/schemaSource",schemeFilePath);; + document = sax.build(file); + + init(); + } + + /** + * Create a FernMLNetwork from an existing {@link Network}. If the + * network's {@link PropensityCalculator} is not an {@link AbstractKineticConstantPropensityCalculator}, + * the constant for the rate reaction is obtained by the propensity calculator by setting + * each reactant species' amount to 1. If the stoichiometry of some reactant is greater than 1 the value + * is set accordingly. + * + * @param net the network to create a FernMLNetwork from + */ + public FernMLNetwork(Network net) { + super(net.getName()); +// if (!(net.getPropensityCalculator() instanceof AbstractKineticConstantPropensityCalculator)) +// throw new IllegalArgumentException("net's PropensitiyCalculator is not a AbstractKineticConstantPropensityCalculator! Use FernMLNetwork(Network,double[]) instead!"); + document = createDocument(net,null); + init(); + } + + /** + * Creates a FernMLNetwork out of an existing network (e.g. to save it to a fernml file) + * using explicitly given kineticConstants (when net doesn't use KineticConstantPropensityCalculator + * If kineticConstants is null or to short, a default value of 1 is taken. + * @param net An existing network + * @param kineticConstants kinetic constants for each reaction in net + */ + public FernMLNetwork(Network net, double[] kineticConstants) { + super(net.getName()); + document = createDocument(net, kineticConstants); + init(); + } + + private void init() { + createAnnotationManager(); + createSpeciesMapping(); + createAmountManager(); + createAdjacencyLists(); + createPropensityCalulator(); + } + + + @Override + public ArrayKineticConstantPropensityCalculator getPropensityCalculator() { + return (ArrayKineticConstantPropensityCalculator) super.getPropensityCalculator(); + } + + @Override + public int getNumReactions() { + return numReaction; + } + + @Override + public int getNumSpecies() { + return numSpecies; + } + + @SuppressWarnings("unchecked") + public void setInitialAmount(int species, long value) { + List speciesList = document.getRootElement().getChild("listOfSpecies").getChildren(); + speciesList.get(species).setAttribute("initialAmount", value+""); + + initialAmount[species] = value; + } + + public long getInitialAmount(int species) { + return initialAmount[species]; + } + + @Override + protected void createAmountManager() { + amountManager = new DefaultAmountManager(this); + } + + /** + * Creates the adjacency lists by parsing the jdom tree. + */ + @SuppressWarnings("unchecked") + @Override + protected void createAdjacencyLists() { + List listOfReactions = document.getRootElement().getChild("listOfReactions").getChildren(); + + adjListPro = new int[numReaction][]; + adjListRea = new int[numReaction][]; + double[] constants = new double[numReaction]; + + int index = 0; + for (Element reaction : listOfReactions) { + boolean reversible = reaction.getAttribute("kineticConstantReversible")!=null; + + constants[index] = Double.parseDouble(reaction.getAttributeValue("kineticConstant")); + if (reversible) + constants[index+1] = Double.parseDouble(reaction.getAttributeValue("kineticConstantReversible")); + + + List reactants = reaction.getChild("listOfReactants").getChildren(); + List products = reaction.getChild("listOfProducts").getChildren(); + int[] rea = createSpeciesReferences(reactants); + int[] pro = createSpeciesReferences(products); + + adjListRea[index] = rea; + adjListPro[index] = pro; + + if (reversible) { + adjListRea[index+1] = pro; + adjListPro[index+1] = rea; + } + + index+=reversible ? 2 : 1; + } + + propensitiyCalculator = new ArrayKineticConstantPropensityCalculator(adjListRea,constants); + } + + /** + * Does nothing, the {@link PropensityCalculator} is created in createAdjacencyLists + * because the reactions constants are already parsed there. + */ + @Override + protected void createPropensityCalulator() { + // done in createAdjacencyLists + } + + private int[] createSpeciesReferences(List speciesReference) { + int[] re = new int[speciesReference.size()]; + int index = 0; + for (Element e : speciesReference) + re[index++] = getSpeciesByName(e.getAttributeValue("name")); + return re; + } + + /** + * Creates the {@link AnnotationManager} as a {@link FernMLAnnotationManager}. + */ + @SuppressWarnings("unchecked") + @Override + protected void createAnnotationManager() { + // read number of species/reactions + List reactions = document.getRootElement().getChild("listOfReactions").getChildren(); + numReaction = 0; + for (Element r : reactions) { + boolean reversible = r.getAttribute("kineticConstantReversible")!=null; + numReaction += reversible ? 2 : 1; + } + + numSpecies = document.getRootElement().getChild("listOfSpecies").getChildren().size(); + + annotationManager = new FernMLAnnotationManager(document.getRootElement()); + } + + /** + * Creates the species mapping by parsing the jdom tree. + */ + @SuppressWarnings("unchecked") + @Override + protected void createSpeciesMapping() { + List listOfSpecies = document.getRootElement().getChild("listOfSpecies").getChildren(); + + speciesIdToIndex = new HashMap(listOfSpecies.size()); + indexToSpeciesId = new String[listOfSpecies.size()]; + initialAmount = new long[indexToSpeciesId.length]; + int index = 0; + for (Element species : listOfSpecies) { + String name = species.getAttributeValue("name"); + long initialAmount = (long) Double.parseDouble(species.getAttributeValue("initialAmount")); + speciesIdToIndex.put(name, index); + indexToSpeciesId[index] = name; + this.initialAmount[index] = initialAmount; + index++; + } + + } + + /** + * Saves the actual FernMLNetwork to a file. + * + * @param file the file to save the network in + * @throws IOException if the file cannot be written + */ + public void saveToFile(File file) throws IOException { + XMLOutputter output = new XMLOutputter(); + output.output(document, new FileWriter(file)); + } + + + @SuppressWarnings("unchecked") + private Document createDocument(Network net, double[] kineticConstants) { + AnnotationManager prop = net.getAnnotationManager(); + + AbstractKineticConstantPropensityCalculator kin = null; + if (net.getPropensityCalculator() instanceof AbstractKineticConstantPropensityCalculator) + kin = (AbstractKineticConstantPropensityCalculator) net.getPropensityCalculator(); + + + + // create root + Document doc = new Document(); + doc.setRootElement(new Element("fernml")); + Element root = doc.getRootElement();; + root.setAttribute("version", "1.0"); + + // create network annotations if present + Collection annotations = prop.getNetworkAnnotationTypes(); + if (annotations!=null && annotations.size()>0) { + Element annotationsRoot = new Element("listOfAnnotations"); + for (String key : annotations) + annotationsRoot.getChildren().add(createAnnotation(key, prop.getNetworkAnnotation(key))); + root.getChildren().add(annotationsRoot); + } + + // create listofspecies + Element listOfSpecies = new Element("listOfSpecies"); + root.getChildren().add(listOfSpecies); + for (int i=0; i speciesAnnotations = prop.getSpeciesAnnotationTypes(i); + + Element s = new Element("species"); + s.setAttribute("name",name); + s.setAttribute("initialAmount", String.valueOf(initialAmount)); + if (speciesAnnotations!=null && speciesAnnotations.size()>0) { + Element annotationsRoot = new Element("listOfAnnotations"); + for (String key : speciesAnnotations) + annotationsRoot.getChildren().add(createAnnotation(key, prop.getSpeciesAnnotation(i, key))); + s.getChildren().add(annotationsRoot); + } + listOfSpecies.getChildren().add(s); + } + + // create listOfReactions + Element listOfReactions = new Element("listOfReactions"); + root.getChildren().add(listOfReactions); + for (int i=0; i reactionAnnotations = prop.getReactionAnnotationTypes(i); + double constant; + + if (kineticConstants!=null && i0) { + Element annotationsRoot = new Element("listOfAnnotations"); + for (String key : reactionAnnotations) + annotationsRoot.getChildren().add(createAnnotation(key, prop.getReactionAnnotation(i, key))); + r.getChildren().add(annotationsRoot); + } + + // reactants + Element loR = new Element("listOfReactants"); + r.getChildren().add(loR); + for (int j=0; j Y+C (where C is each catalyst of the + * original reaction). If a reaction has n catalysts, there will be n+1 reactions + * generated. It is only possible to create a CatalysedNetwork out of a + * {@link AutocatalyticNetwork} (or at least of a {@link ModifierNetwork} whose original network + * is a AutocatalyticNetwork). + *

+ * The {@link AmountManager} automatically monitors the food molecules amounts and whenever + * it changes, it is reset to the initial value (given by {@link AutocatalyticNetwork#getMonomerAmount()}. + *

+ * The {@link PropensityCalculator}'s constant is {@link AutocatalyticNetwork#getCatalyzedKineticConstant()} + * for each reaction with a catalyst and {@link AutocatalyticNetwork#getUncatalyzedKineticConstant()} for + * the other ones. + *

+ * The {@link AnnotationManager} uses the underlying one but removes the {@link AutocatalyticNetwork#CATALYSTS_FIELD} + * and the field Autocatalytic from not catalyzed reactions. + * + * @author Florian Erhard + * + */ +public class CatalysedNetwork extends ModifierNetwork { + + + private int[] reactionToOriginal; + private int[] catalyst; + private PropensityCalculator propensityCalculator = null; + private AmountManager amountManager = null; + private int[][] adjListRea; + private int[][] adjListPro; + + /** + * Create a catalyzed network from an original network. + * + * @param originalNet the original network + */ + public CatalysedNetwork(Network originalNet) { + super(originalNet); + + if (!(getOriginalNetwork() instanceof AutocatalyticNetwork)) + throw new IllegalArgumentException("Original network must be an AutocatalyticNetwork!"); + + AnnotationManager anno = originalNet.getAnnotationManager(); + LinkedList rTOCreate = new LinkedList(); + LinkedList cataCreate = new LinkedList(); + for (int i=0; i getNetworkAnnotationTypes() { + return ori.getNetworkAnnotationTypes(); + } + + public String getReactionAnnotation(int reaction, String typ) { + String re = ori.getReactionAnnotation(getOriginalReaction(reaction), typ); + if (!containsReactionAnnotation(reaction, typ)) + return null; + else + return re; + } + + public Collection getReactionAnnotationTypes(int reaction) { + Collection re = ori.getReactionAnnotationTypes(getOriginalReaction(reaction)); + Iterator it = re.iterator(); + while (it.hasNext()) + if (!containsReactionAnnotation(reaction, it.next())) + it.remove(); + return re; + } + + public String getSpeciesAnnotation(int species, String typ) { + return ori.getSpeciesAnnotation((species), typ); + } + + public Collection getSpeciesAnnotationTypes(int species) { + return ori.getSpeciesAnnotationTypes((species)); + } + + public void setNetworkAnnotation(String typ, String annotation) { + ori.setNetworkAnnotation(typ, annotation); + } + + public void setReactionAnnotation(int reaction, String typ, + String annotation) { + ori.setReactionAnnotation(getOriginalReaction(reaction), typ, annotation); + } + + public void setSpeciesAnnotation(int species, String typ, + String annotation) { + ori.setSpeciesAnnotation((species), typ, annotation); + } + + + }; + } + + @Override + public String getReactionName(int index) { + StringBuilder sb = new StringBuilder(); + for (int i : getReactants(index)) + sb.append(getSpeciesName(i)+"+"); + sb.deleteCharAt(sb.length()-1); + sb.append("->"); + for (int i : getProducts(index)) + sb.append(getSpeciesName(i)+"+"); + sb.deleteCharAt(sb.length()-1); + return sb.toString(); + } + +} diff --git a/src/main/java/fern/network/modification/ExtractSubNetwork.java b/src/main/java/fern/network/modification/ExtractSubNetwork.java new file mode 100644 index 00000000..38479e2a --- /dev/null +++ b/src/main/java/fern/network/modification/ExtractSubNetwork.java @@ -0,0 +1,261 @@ +package fern.network.modification; + +import java.util.Collection; +import java.util.LinkedList; + +import cern.colt.bitvector.BitVector; +import fern.network.AmountManager; +import fern.network.AnnotationManager; +import fern.network.DefaultAmountManager; +import fern.network.Network; +import fern.network.PropensityCalculator; +import fern.simulation.Simulator; +import fern.tools.NumberTools; + +/** + * Extracts some reactions / species from a given net to form a new network. As proposed by + * {@link ModifierNetwork}, the network is not copied but the indices are redirected. + *

+ * The subnet to be extracted has to be given by {@link BitVector}s containing a 1 for an index + * to be in the extracted subnet. + *

+ * This class can be used e.g. to extract only the autocatalytic set of an evolved network. + * + * @author Florian Erhard + * + */ +public class ExtractSubNetwork extends ModifierNetwork { + + private AmountManager amountManager = null; + private AmountManager redirectingAmountManager = null; + + private int[] reactionsToOriginal = null; + private int[] speciesToOriginal = null; + private int[] speciesFromOriginal = null; + + /** + * Extracts a given subnet from a network. The subnet has to be given by {@link BitVector}s containing a 1 + * for each index which has to be in the extracted subnet. + * @param originalNet network containing the subnet + * @param reactions reactions of the subnet + * @param species species of the subnet + */ + public ExtractSubNetwork(Network originalNet, BitVector reactions, BitVector species) { + super(originalNet); + reactionsToOriginal = NumberTools.getContentAsArray(reactions); + speciesToOriginal = NumberTools.getContentAsArray(species); + speciesFromOriginal = NumberTools.createInverse(speciesToOriginal); + this.amountManager = new DefaultAmountManager(this); + createRedirectingAmountManager(); + } + + private void createRedirectingAmountManager() { + redirectingAmountManager = new DefaultAmountManager(null) { + @Override + public long getAmount(int species) { + return amountManager.getAmount(speciesFromOriginal[species]); + } + }; + } + + /** + * Redirects a reaction index from the subnet index space to the original index space + * @param reaction index in subnet index space + * @return index in original index space + */ + protected int getOriginalReaction(int reaction) { + return reactionsToOriginal[reaction]; + } + + /** + * Redirects a species index from the subnet index space to the original index space + * @param species index in subnet index space + * @return index in original index space + */ + protected int getOriginalSpecies(int species) { + return speciesToOriginal[species]; + } + + private int[] translateAndTrimSpecies(int[] ori) { + LinkedList re = new LinkedList(); + for (int i : ori) + if (speciesFromOriginal[i]>=0) + re.add(speciesFromOriginal[i]); + return NumberTools.toIntArray(re); + } + + + /** + * Gets an {@link AnnotationManager} for the redirected index space. + * @return the AnnotationManager object + */ + @Override + public AnnotationManager getAnnotationManager() { + final AnnotationManager ori = getParentNetwork().getAnnotationManager(); + return new AnnotationManager() { + + public boolean containsNetworkAnnotation(String typ) { + return ori.containsNetworkAnnotation(typ); + } + + public boolean containsReactionAnnotation(int reaction, String typ) { + return ori.containsReactionAnnotation(getOriginalReaction(reaction), typ); + } + + public boolean containsSpeciesAnnotation(int species, String typ) { + return ori.containsSpeciesAnnotation(getOriginalSpecies(species), typ); + } + + public String getNetworkAnnotation(String typ) { + return ori.getNetworkAnnotation(typ); + } + + public Collection getNetworkAnnotationTypes() { + return ori.getNetworkAnnotationTypes(); + } + + public String getReactionAnnotation(int reaction, String typ) { + return ori.getReactionAnnotation(getOriginalReaction(reaction), typ); + } + + public Collection getReactionAnnotationTypes(int reaction) { + return ori.getReactionAnnotationTypes(getOriginalReaction(reaction)); + } + + public String getSpeciesAnnotation(int species, String typ) { + return ori.getSpeciesAnnotation(getOriginalSpecies(species), typ); + } + + public Collection getSpeciesAnnotationTypes(int species) { + return ori.getSpeciesAnnotationTypes(getOriginalSpecies(species)); + } + + public void setNetworkAnnotation(String typ, String annotation) { + ori.setNetworkAnnotation(typ, annotation); + } + + public void setReactionAnnotation(int reaction, String typ, + String annotation) { + ori.setReactionAnnotation(getOriginalReaction(reaction), typ, annotation); + } + + public void setSpeciesAnnotation(int species, String typ, + String annotation) { + ori.setSpeciesAnnotation(getOriginalSpecies(species), typ, annotation); + } + + + }; + } + + /** + * Gets the number of reactions in the extracted subnet. + * @return number of reactions + */ + @Override + public int getNumReactions() { + return reactionsToOriginal.length; + } + + /** + * Gets the number of species in the extracted subnet. + * @return number of species + */ + @Override + public int getNumSpecies() { + return speciesToOriginal.length; + } + + /** + * Gets the products of a reaction. + * + * @param reaction the index of the reaction + * @return indices of the products + */ + @Override + public int[] getProducts(int reaction) { + int[] ori = getParentNetwork().getProducts(getOriginalReaction(reaction)); + return translateAndTrimSpecies(ori); + } + + + /** + * Gets the reactants of a reaction. + * + * @param reaction the index of the reaction + * @return indices of the reactants + */ + @Override + public int[] getReactants(int reaction) { + int[] ori = getParentNetwork().getReactants(getOriginalReaction(reaction)); + return translateAndTrimSpecies(ori); + } + + + public long getInitialAmount(int species) { + return getParentNetwork().getInitialAmount(getOriginalSpecies(species)); + } + + public void setInitialAmount(int species, long value) { + getParentNetwork().setInitialAmount(getOriginalSpecies(species), value); + } + + + /** + * Gets the name of the species with given index. + * @param index index of the species + * @return name of the species + */ + @Override + public String getSpeciesName(int index) { + return getParentNetwork().getSpeciesName(getOriginalSpecies(index)); + } + + /** + * Gets the index of the species by its name. + * @param name name of the species + * @return index of the species + */ + @Override + public int getSpeciesByName(String name) { + return speciesFromOriginal[getParentNetwork().getSpeciesByName(name)]; + } + + /** + * Gets the {@link AmountManager} for the extracted subnet. + * @return the amount manager + */ + @Override + public AmountManager getAmountManager() { + return amountManager; + } + + /** + * Gets the {@link PropensityCalculator} for the extracted subnet. + * @return the propensity calculator + */ + @Override + public PropensityCalculator getPropensityCalculator() { + final PropensityCalculator ori = getParentNetwork().getPropensityCalculator(); + return new PropensityCalculator() { + public double calculatePropensity(int reaction, + AmountManager amount, Simulator sim) { + return ori.calculatePropensity(getOriginalReaction(reaction), redirectingAmountManager, sim); + } + }; + } + + /** + * Gets a string representation of the reaction + * @param index index of the reaction + * @return string representation of the reaction + */ + @Override + public String getReactionName(int index) { + return getParentNetwork().getReactionName(getOriginalReaction(index)); + } + + + + +} diff --git a/src/main/java/fern/network/modification/ModifierNetwork.java b/src/main/java/fern/network/modification/ModifierNetwork.java new file mode 100644 index 00000000..e5e13740 --- /dev/null +++ b/src/main/java/fern/network/modification/ModifierNetwork.java @@ -0,0 +1,173 @@ +package fern.network.modification; + +import fern.network.AmountManager; +import fern.network.AnnotationManager; +import fern.network.Network; +import fern.network.PropensityCalculator; + +/** + * + * Base class for modified networks, which implements the full {@link Network} interface. + * Extending classes should override each method which is + * different in the modified network (e.g. in the {@link ReversibleNetwork} only reactions are + * virtually doubled, so each method concerning the species do not change). + *

+ * Note: An extending class should definitely not copy the whole network but should rather + * redirect indices to the original network when possible in order to minimize the + * necessary memory. + * + * @author Florian Erhard + * + */ +public abstract class ModifierNetwork implements Network { + + private Network originalNet = null; + + /** + * Creates a ModifierNetwork from an original network. + * + * @param originalNet the network to modify + */ + public ModifierNetwork(Network originalNet) { + this.originalNet = originalNet; + } + + /** + * Gets the name of the original network + * + * @return name of the original network. + */ + public String getName() { + return originalNet.getName(); + } + + /** + * Gets the {@link AnnotationManager} of the original network + * + * @return AnnotationManager of the original network + */ + public AnnotationManager getAnnotationManager() { + return originalNet.getAnnotationManager(); + } + + /** + * Gets the number of reaction in the original network. + * + * @return number of reactions in the original network + */ + public int getNumReactions() { + return originalNet.getNumReactions(); + } + + /** + * Gets the number of species in the original network. + * + * @return number of species in the original network + */ + public int getNumSpecies() { + return originalNet.getNumSpecies(); + } + + /** + * Gets the products of a reaction in the original network. + * + * @param reaction index of the reaction in the original network + * @return indices of the products in the original network + */ + public int[] getProducts(int reaction) { + return originalNet.getProducts(reaction); + } + + /** + * Gets the reactants of a reaction in the original network. + * + * @param reaction index of the reaction in the original network + * @return indices of the reactants in the original network + */ + public int[] getReactants(int reaction) { + return originalNet.getReactants(reaction); + } + + /** + * Gets the name of the species by index in the original network. + * + * @param index index of the species the original network + * @return name of the species + */ + public String getSpeciesName(int index) { + return originalNet.getSpeciesName(index); + } + + /** + * Gets the index of the species by its name in the original network. + * + * @param name name of the species + * @return index of the species in the original network + */ + public int getSpeciesByName(String name) { + return originalNet.getSpeciesByName(name); + } + + /** + * Gets the {@link AmountManager} of the original network. + * @return AmountManager of the the original network + */ + public AmountManager getAmountManager() { + return originalNet.getAmountManager(); + } + + /** + * Gets the {@link PropensityCalculator} of the original network. + * @return PropensityCalculator of the the original network + */ + public PropensityCalculator getPropensityCalculator() { + return originalNet.getPropensityCalculator(); + } + + /** + * Gets a string representation of the reactio in the original network. + * + * @param index index of the reaction in the original network + * @return string represenation of the reaction + */ + public String getReactionName(int index) { + return originalNet.getReactionName(index); + } + + public long getInitialAmount(int species) { + return originalNet.getInitialAmount(species); + } + + public void setInitialAmount(int species, long value) { + originalNet.setInitialAmount(species, value); + } + + /** + * Gets the original network. If there is a higher hierarchy of modified networks + * (e.g. a ExtractSubNetwork of a ReversibleNetwork of a + * AutocatalyticNetworkExample), the highest network (here the AutocatalyticNetworkExample + * is returned. + * + * @return the original network + */ + public Network getOriginalNetwork() { + if (originalNet instanceof ModifierNetwork) + return ((ModifierNetwork)originalNet).getOriginalNetwork(); + else + return originalNet; + } + + /** + * Gets the parent network. If there is a higher hierarchy of modified networks + * (e.g. a ExtractSubNetwork of a ReversibleNetwork of a + * AutocatalyticNetworkExample), the parental network (here the ReversibleNetwork + * is returned. + * + * @return the parent network + */ + public Network getParentNetwork() { + return originalNet; + } + + +} diff --git a/src/main/java/fern/network/modification/ReversibleNetwork.java b/src/main/java/fern/network/modification/ReversibleNetwork.java new file mode 100644 index 00000000..b9576eb6 --- /dev/null +++ b/src/main/java/fern/network/modification/ReversibleNetwork.java @@ -0,0 +1,269 @@ +package fern.network.modification; + +import java.util.Collection; +import java.util.LinkedList; + +import fern.network.AbstractKineticConstantPropensityCalculator; +import fern.network.AmountManager; +import fern.network.AnnotationManager; +import fern.network.DefaultAmountManager; +import fern.network.Network; +import fern.network.PropensityCalculator; +import fern.network.creation.AutocatalyticNetwork; +import fern.simulation.Simulator; + +/** + * Doubles each reaction in a way that each original unidirectional reaction becomes + * reversible.As proposed by {@link ModifierNetwork}, the reactions are not copied + * but the indices are redirected. + *

+ * Note: The reverse reactions do not have any annotation, unless in the original network + * the reactions have annotation with fields ending with REVERSIBLE_SUFFIX. + * If such annotations are present in the original network, the corresponding reactions + * in the reversible network will not have these annotations but the corresponding reversible + * reactions will have these annotations without this suffix (e.g. if you create an {@link + * AutocatalyticNetwork}, the reactions have annotations Catalyst and + * CatalystReversible, if you create a ReversibleNetwork out of this, + * each reaction will have only the annotation Catalyst). + *

+ * For the new reactions you have to specify a new {@link PropensityCalculator} whose index + * space is equal to the original network's index space. If you have, for instance, in your + * original network two reactions, A+A->B, B->C, the PropensityCalculatory has to + * calculate the propensity for A+A<-B when index 0 is given, the propensity for B<-C, when + * index 1 is given. + * + * @author Florian Erhard + * + */ +public class ReversibleNetwork extends ModifierNetwork { + + /** + * Suffix which marks annotations for virtually created reverse reactions. + * If there are no annotations with this suffix in the original network, + * the reverse reactions will have no annotations. + */ + public static final String REVERSIBLE_SUFFIX = "Reversible"; + + private AmountManager amountManager = null; + private PropensityCalculator reversiblePropensityCalculator = null; + + /** + * Creates a new network from an original network and virtually creates for each reaction a + * new inverse reaction. For the reverse reactions a {@link PropensityCalculator} has + * to be given. + * + * @param originalNet the original network + * @param reversiblePropensityCalculator the PropensityCalculator for the reverse reactions + */ + public ReversibleNetwork(Network originalNet, PropensityCalculator reversiblePropensityCalculator) { + super(originalNet); + this.reversiblePropensityCalculator = reversiblePropensityCalculator; + amountManager = new DefaultAmountManager(this); + } + + /** + * Gets the {@link AmountManager} for the modified network. + * + * @return AmountManager for the modified network + */ + @Override + public AmountManager getAmountManager() { + return amountManager; + } + + /** + * Gets the number of reactions in the modified network (which is 2*number of reaction + * in the original network). + * + * @return number of reactions in the modified network + */ + public int getNumReactions() { + return getParentNetwork().getNumReactions()*2; + } + + /** + * Gets the products of a reaction + * + * @param reaction index of the reaction + * @return indices of the products + */ + public int[] getProducts(int reaction) { + return (reactionPropensityCalculator and the one for the reverse reactions + * is a {@link AbstractKineticConstantPropensityCalculator}, an AbstractKineticConstantPropensityCalculator + * is returned. + * + * @return the PropensityCalculator for the modified network + */ + public PropensityCalculator getPropensityCalculator() { + if (getParentNetwork().getPropensityCalculator() instanceof AbstractKineticConstantPropensityCalculator + && reversiblePropensityCalculator instanceof AbstractKineticConstantPropensityCalculator) + return new AbstractKineticConstantPropensityCalculator(new int[0][]) { + + @Override + public double calculatePropensity(int reaction, + AmountManager amount, Simulator sim) { + if (reactionAnnotationManager for the modified network. + */ + @Override + public AnnotationManager getAnnotationManager() { + final AnnotationManager ori = getParentNetwork().getAnnotationManager(); + final int numReactions = getParentNetwork().getNumReactions(); + return new AnnotationManager() { + + + public boolean containsNetworkAnnotation(String typ) { + return ori.containsNetworkAnnotation(typ); + } + + public boolean containsReactionAnnotation(int reaction, String typ) { + typ = reaction getNetworkAnnotationTypes() { + return ori.getNetworkAnnotationTypes(); + } + + public String getReactionAnnotation(int reaction, String typ) { + typ = reaction getReactionAnnotationTypes(int reaction) { + Collection oriList = ori.getReactionAnnotationTypes(reaction % numReactions); + Collection re = new LinkedList(); + for (String s : oriList) { + if (s.endsWith(REVERSIBLE_SUFFIX) && reaction>=numReactions) + re.add(s.substring(0,s.length()-REVERSIBLE_SUFFIX.length())); + else if (!s.endsWith(REVERSIBLE_SUFFIX) && reaction getSpeciesAnnotationTypes(int species) { + return ori.getSpeciesAnnotationTypes(species); + } + + public void setNetworkAnnotation(String typ, String annotation) { + ori.setNetworkAnnotation(typ, annotation); + } + + public void setReactionAnnotation(int reaction, String typ, + String annotation) { + typ = reaction"); + for (int i : getProducts(index)) + sb.append(getSpeciesName(i)+"+"); + sb.deleteCharAt(sb.length()-1); + return sb.toString(); + } + + + +} + diff --git a/src/main/java/fern/network/sbml/MathTree.java b/src/main/java/fern/network/sbml/MathTree.java new file mode 100644 index 00000000..45e7257e --- /dev/null +++ b/src/main/java/fern/network/sbml/MathTree.java @@ -0,0 +1,94 @@ +package fern.network.sbml; + +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Stack; +import java.util.stream.Stream; + +import fern.network.AmountManager; +import fern.simulation.Simulator; +import org.sbml.jsbml.*; +import org.sbml.jsbml.validator.ModelOverdeterminedException; +import org.simulator.sbml.SBMLinterpreter; +import org.simulator.sbml.astnode.ASTNodeValue; + +/** + * Representation of am evaluation tree. Within a sbml file, MathML branches may occur at + * different positions. These are represented as MathTrees in FERN. + * + * @author Florian Erhard + */ +public class MathTree { + + private SBMLNetwork net; + private ASTNode copiedAST; + private SBMLinterpreter sbmLinterpreter; + private Map bindings; + public static final String TEMP_VALUE = "SBML_SIMULATION_TEMP_VALUE"; + + /** + * Creates a MathTree {@link ASTNode}. + * + * @param net sbml network + * @param ast ASTNode + * @param globals pointer to the global variable mapping + * @param locals pointer to the local variable mapping of this entity + * @param bindings mapping of the variable names to their indices + */ + public MathTree(SBMLNetwork net, ASTNode ast, Map globals, Map locals, Map bindings) throws ModelOverdeterminedException { + this.net = net; + this.bindings = bindings; + sbmLinterpreter = new SBMLinterpreter(net.getSBMLModel()); + copiedAST = sbmLinterpreter.copyAST(ast, true, null, null); + } + + /** + * Gets the species present in this tree. + * + * @return indices of the species. + */ + public List getSpecies() { + List re = new LinkedList<>(); + Stack dfs = new Stack<>(); + dfs.add(copiedAST); + while (!dfs.empty()) { + ASTNode node = dfs.pop(); + if ((node.getNumChildren() == 0) && !node.isOperator() && !node.isNumber()){ + Integer index = bindings.get(node.getName()); + if ((index != null) && !re.contains(index)){ + re.add(bindings.get(node.getName())); + } + } else if (node.getNumChildren() != 0) { + for (int i = 0; i < node.getNumChildren(); i++){ + dfs.add(node.getChild(i)); + } + } + } + return re; + } + + /** + * Gets the ASTNode of this MathTree. + * + * @return the copiedAST of this MathTree + */ + public ASTNode getCopiedAST() { + return copiedAST; + } + + /** + * Evaluate the MathTree. + * + * @param amount AmountManager + * @param sim Simulator + * @return value of the expression + */ + public double calculate(AmountManager amount, Simulator sim) { + + sbmLinterpreter.updateSpeciesConcentration(amount); + return ((ASTNodeValue) copiedAST.getUserObject(TEMP_VALUE)).compileDouble(sim.getTime(), 0d); + + } + +} diff --git a/src/main/java/fern/network/sbml/SBMLEventHandlerObserver.java b/src/main/java/fern/network/sbml/SBMLEventHandlerObserver.java new file mode 100644 index 00000000..2ecb3e8f --- /dev/null +++ b/src/main/java/fern/network/sbml/SBMLEventHandlerObserver.java @@ -0,0 +1,128 @@ +package fern.network.sbml; + +import java.util.HashMap; +import java.util.Map; + +import org.sbml.jsbml.Event; + +import fern.simulation.Simulator; +import fern.simulation.Simulator.FireType; +import fern.simulation.observer.TriggerObserver; +import org.sbml.jsbml.validator.ModelOverdeterminedException; + +/** + * Observer which handles an event of a sbml model. + * + * @author Florian Erhard + * + */ +public class SBMLEventHandlerObserver extends TriggerObserver { + + private String name; + private MathTree trigger; + private MathTree delay; + private SBMLNetwork net; + private Map variableAssignment; + private Map parameterAssignment; + private boolean lastStepTriggered; + + /** + * Creates the observer. + * + * @param sim the simulator + * @param net the sbml network + * @param event the event object of the sbml model + */ + public SBMLEventHandlerObserver(Simulator sim, SBMLNetwork net, Event event) throws ModelOverdeterminedException { + super(sim); + + this.net = net; + parse(event); + } + + private void parse(Event event) throws ModelOverdeterminedException { + this.name = event.getId(); + this.trigger = new MathTree(net, + event.getTrigger().getMath(), + ((SBMLPropensityCalculator)net.getPropensityCalculator()).getGlobalParameters(), + new HashMap(), + net.getSpeciesMapping()); + this.delay = event.getDelay()==null ? null : new MathTree(net, + event.getDelay().getMath(), + ((SBMLPropensityCalculator)net.getPropensityCalculator()).getGlobalParameters(), + new HashMap(), + net.getSpeciesMapping()); + variableAssignment = new HashMap(); + parameterAssignment = new HashMap(); + + for (int i=0; i(), + net.getSpeciesMapping()); + if (net.getSpeciesMapping().containsKey(var)) + variableAssignment.put(var, tree); + else + parameterAssignment.put(var, tree); + } + } + + private void executeEvent() { + for (String var : variableAssignment.keySet()) + net.getAmountManager().setAmount(net.getSpeciesByName(var), (long)variableAssignment.get(var).calculate(net.getAmountManager(),getSimulator())); + for (String par : parameterAssignment.keySet()) { + Map globals = ((SBMLPropensityCalculator)net.getPropensityCalculator()).getGlobalParameters(); + globals.put(par, parameterAssignment.get(par).calculate(net.getAmountManager(),getSimulator())); + } + getSimulator().reinitialize(); + } + + @Override + public void activateReaction(int mu, double tau, FireType fireType, + int times) {} + + @Override + public void finished() {} + + @Override + public void started() { + lastStepTriggered = true; + } + + @Override + public void step() { + } + + @Override + public boolean trigger() { + boolean triggered = trigger.calculate(net.getAmountManager(),getSimulator())!=0; + if (!lastStepTriggered && triggered) { + lastStepTriggered = triggered; + double delaytime = delay==null ? 0 : delay.calculate(net.getAmountManager(),getSimulator()); + if (delaytime<=0) + executeEvent(); + else + setTheta(delaytime); + return true; + } + lastStepTriggered = triggered; + return false; + } + + @Override + public void theta(double theta) { + executeEvent(); + } + + public void setSimulatorAsync(Simulator sim) { + this.setSimulator(sim); + } + + @Override + public String toString() { + return name; + } + +} diff --git a/src/main/java/fern/network/sbml/SBMLNetwork.java b/src/main/java/fern/network/sbml/SBMLNetwork.java new file mode 100644 index 00000000..6a489ec0 --- /dev/null +++ b/src/main/java/fern/network/sbml/SBMLNetwork.java @@ -0,0 +1,346 @@ +/* + * Created on 12.03.2007 + * + * To change the template for this generated file go to + * Window>Preferences>Java>Code Generation>Code and Comments + */ +package fern.network.sbml; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.Collection; +import java.util.HashMap; +import java.util.LinkedList; + +import fern.network.AbstractNetworkImpl; +import fern.network.AnnotationManagerImpl; +import fern.network.DefaultAmountManager; +import fern.network.FeatureNotSupportedException; +import fern.network.Network; +import fern.simulation.Simulator; +import fern.tools.NetworkTools; +import org.sbml.jsbml.*; +import org.sbml.jsbml.validator.ModelOverdeterminedException; + +import javax.xml.stream.XMLStreamException; + +/** + * For specifications of the sbml format refer to http:\\www.sbml.org. + * Not every feature is implemented in FERN (for a list please see the user guide). + *

+ * When you want to use a sbml model with events included, you have to call + * registerEvents, since the event handling is treated by {@link SBMLEventHandlerObserver}s + * which need to be attached to the {@link Simulator}. + * + * + * @author Florian Erhard + * + */ +public class SBMLNetwork extends AbstractNetworkImpl { + + /** + * The sbml model created by libsbml. + */ + protected Model model; + private SBMLDocument document; + + private long[] initialAmount = null; + private Collection events = null; + + /** + * Creates a network from a sbmlfile. If the file contains features not supported by FERN, + * an exception will be thrown. + * + * @param file SBML file + * @throws FeatureNotSupportedException + */ + public SBMLNetwork(File file) throws FeatureNotSupportedException, IOException, XMLStreamException, ModelOverdeterminedException { + this(file,false); + } + + /** + * Creates a network from a sbml file. If the file contains features not supported by FERN, + * depending on ignoreExceptions they will be ignored or a exception is thrown. + * + * @param file SBML file + * @param ignoreExceptions wheter or not exceptions should be thrown + * @throws FeatureNotSupportedException + */ + public SBMLNetwork(File file, boolean ignoreExceptions) throws FeatureNotSupportedException, IOException, XMLStreamException, ModelOverdeterminedException { + super(file.toString()); + + document = new SBMLReader().readSBML(file.toString()); + + if (!ignoreExceptions) { + if (document.getModel().getNumRules() > 0) { + throw new FeatureNotSupportedException("Rules are not allowed at the moment!"); + } + if (document.getModel().getNumConstraints() > 0) { + throw new FeatureNotSupportedException("Constraints are not allowed at the moment!"); + } + if (document.getModel().getNumFunctionDefinitions() > 0) { + throw new FeatureNotSupportedException("Function definitions are not allowed at the moment!"); + } + if (document.getModel().getNumInitialAssignments() > 0) { + throw new FeatureNotSupportedException("Initial assignments are not allowed at the moment!"); + } + for (int s = 0; s < document.getModel().getNumSpecies(); s++) { + if (!document.getModel().getSpecies(s).isSetHasOnlySubstanceUnits()) { + throw new FeatureNotSupportedException("For each species the hasOnlySubstanceUnits flag has to be set!"); + } + } + } + + model = document.getModel(); + + init(); + } + + /** + * Create a SBMLNetwork from an existing {@link Network}. The constant for + * the rate reaction is obtained by the propensity calculator by setting + * each reactant species' amount to 1. + * + * @param net the network to create a SBMLNetwork from + */ + public SBMLNetwork(Network net) throws ModelOverdeterminedException { + super(net.getName()); + + document = createDocument(net); + model = document.getModel(); + + init(); + } + + private void init() throws ModelOverdeterminedException { + createAnnotationManager(); + createSpeciesMapping(); + createAdjacencyLists(); + createPropensityCalulator(); + createAmountManager(); + createEventHandlers(); + + initialAmount = new long[getNumSpecies()]; + for (int i=0; i(); + for (int i=0; i=0; j--) + for (int k=0; k=0; j--) + for (int k=0; k((int) model.getNumSpecies()); + indexToSpeciesId = new String[(int) model.getNumSpecies()]; + for (int i=0; iSBMLNetwork to a file. + * + * @param file the file to save the network in + * @throws IOException if the file cannot be written + */ + public void saveToFile(File file) throws IOException, XMLStreamException { +// FileWriter fw = new FileWriter(file); +// fw.write("\n"); +// fw.write(document.toSBML()); +// fw.flush(); +// fw.close(); + /** + * [Changes made] + * As currently JSBML is lacking in toSBML() method so I am using SBML Writer here + */ + SBMLWriter sbmlWriter = new SBMLWriter(); + sbmlWriter.writeSBMLToFile(document, file.toString()); + } + + + /** + * Saves the current SBMLNetwork to a sbml file with given + * level and version. + * + * @param file the file to save the network in + * @param level sbml level + * @param version sbml version + * @throws IOException if the file cannot be written + */ + public void saveToFile(File file, int level, int version) throws IOException, XMLStreamException { + int oldlevel = document.getLevel(); + int oldversion = document.getVersion(); + document.setLevelAndVersion(Math.toIntExact(level), Math.toIntExact(version)); +// FileWriter fw = new FileWriter(file); +// fw.write("\n"); +// fw.write(document.toSBML()); +// fw.flush(); +// fw.close(); + /** + * [Changes made] + * As currently JSBML is lacking in toSBML() method so I am using SBML Writer here + */ + SBMLWriter sbmlWriter = new SBMLWriter(); + sbmlWriter.writeSBMLToFile(document, file.toString()); + document.setLevelAndVersion(Math.toIntExact(oldlevel), Math.toIntExact(oldversion)); + } + + private SBMLDocument createDocument(Network net) { + SBMLDocument doc = new SBMLDocument(); + Model re = doc.createModel(net.getName()); + + + Compartment comp = new Compartment("Cell"); + re.addCompartment(comp); + + for (int s=0; s1) { + ASTNode times = new ASTNode(ASTNode.Type.TIMES); + ASTNode reacNode = new ASTNode(ASTNode.Type.REAL); + reacNode.setValue(1.0/stoich[i]); + times.addChild(node); + times.addChild(reacNode); + node = times; + } + } + + return node; + } + + +} diff --git a/src/main/java/fern/network/sbml/SBMLPropensityCalculator.java b/src/main/java/fern/network/sbml/SBMLPropensityCalculator.java new file mode 100644 index 00000000..9d3908b4 --- /dev/null +++ b/src/main/java/fern/network/sbml/SBMLPropensityCalculator.java @@ -0,0 +1,98 @@ +/* + * Created on 12.03.2007 + * + * To change the template for this generated file go to + * Window>Preferences>Java>Code Generation>Code and Comments + */ +package fern.network.sbml; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import fern.network.AmountManager; +import fern.network.ComplexDependenciesPropensityCalculator; +import fern.simulation.Simulator; +import org.sbml.jsbml.Model; +import org.sbml.jsbml.Reaction; +import org.sbml.jsbml.validator.ModelOverdeterminedException; + +/** + * Propensity calculator which is used for {@link SBMLNetwork}s. The propensities are + * calculated by using a {@link MathTree} derived by the MathML representation of the + * kinetic law for each reaction. + * + * @author Florian Erhard + * + */ +public class SBMLPropensityCalculator implements ComplexDependenciesPropensityCalculator { + + + private MathTree[] propensities; + private Map globalParameter; + + /** + * Creates the {@link MathTree}s and parses the parameters. + * + * @param net sbml netowrk + */ + public SBMLPropensityCalculator(SBMLNetwork net) throws ModelOverdeterminedException { + if (net==null) return; + + Model model = net.getSBMLModel(); + globalParameter = new HashMap(); + for (int i=0; i localParameter = new HashMap(); + Reaction reaction = model.getReaction(i); + /** + * [Changes made] + * Removed deprecated method call + */ + for (int j=0; j getGlobalParameters() { + return globalParameter; + } + + public double calculatePropensity(int reaction, AmountManager amount, Simulator sim) { + double re = propensities[reaction].calculate(amount, sim); + if (re<0) throw new RuntimeException("The propensity of reaction "+sim.getNet().getReactionName(reaction)+" is negative"); + return Math.abs(re); + } + + public List getKineticLawSpecies(int reaction) { + return propensities[reaction].getSpecies(); + } + + + /** + * Gets the internal representation of the sbml kinetic law. + * + * @param reaction index of the reaction + * @return a MathTree representation of the kinetic law + */ + public MathTree getMathTree(int reaction) { + return propensities[reaction]; + } + + + +} diff --git a/src/main/java/fern/simulation/Simulator.java b/src/main/java/fern/simulation/Simulator.java new file mode 100644 index 00000000..c2fc4480 --- /dev/null +++ b/src/main/java/fern/simulation/Simulator.java @@ -0,0 +1,481 @@ +/* + * Created on 12.03.2007 + * + * To change the template for this generated file go to + * Window>Preferences>Java>Code Generation>Code and Comments + */ +package fern.simulation; + +import java.util.HashMap; +import java.util.LinkedList; +import java.util.Map; + +import fern.network.AmountManager; +import fern.network.Network; +import fern.network.PropensityCalculator; +import fern.simulation.controller.DefaultController; +import fern.simulation.controller.SimulationController; +import fern.simulation.observer.Observer; +import fern.simulation.observer.TriggerObserver; +import fern.tools.NumberTools; +import fern.tools.Stochastics; + + +/** + * Base class for stochastic simulators. Extending classes just have to implement + * performStep which gets invoked as long as the simulation is lasting. They also may + * override initialize but should in that case call super.initialize() + * to avoid unwished effects. + *

+ * Simulators also should handle the special time theta: is is a moment in time + * when thetaEvent is supposed to be invoked (e.g. to measure species populations + * at this moment). Consider this, if you want to implement a simulator. + *

+ * The fireReaction are supposed to be invoked when a simulator causes a reaction + * to fire. + *

+ * If an extending class sticks to these conventions, it can take full benefit of the + * observer system: One or more {@link Observer} can be registered at a simulator and + * observe certain aspects of the simulation (see the {@link Observer}s javadoc for more + * information). + * + * + * + * @author Florian Erhard + * + */ +public abstract class Simulator { + + private double volume = 0; + + + private Network net; + private AmountManager amountManager; + private PropensityCalculator propensityCalculator; + private Observer[] observer; + private DefaultController timeController = null; + private ThetaQueue thetaQueue = null; + private boolean interpolateTheta = false; + private DelayedThetaInvokationParameters interpolationParameters = null; + + + + /** + * Contains the actual time of the simulation. + */ + protected double t = 0; + /** + * Contains the propensities of the reactions. + */ + protected double[] a = null; + /** + * Contains a shortcut to the {@link Stochastics} framework. + */ + protected Stochastics stochastics = Stochastics.getInstance(); + + /** + * Creates a new simulator for the given network. + * + * @param net the network to simulate + */ + public Simulator(Network net) { + this.net = net; + this.amountManager = net.getAmountManager(); + this.propensityCalculator = net.getPropensityCalculator(); + observer = new Observer[0]; + a = new double[net.getNumReactions()]; + } + + /** + * Starts the simulation up to a given time. It just uses a {@link DefaultController} + * and calls {@link Simulator#start(SimulationController)}. + * + * @param time simulation time + */ + public void start(double time) { + if (timeController==null) + timeController = new DefaultController(time); + timeController.setTime(time); + start(timeController); + } + + /** + * Start the simulation with the given {@link SimulationController}. + * Basically calls {@link #preRun()},{@link #run(SimulationController)} and {@link #postRun()}. + * + * @param control the SimulationController + */ + public void start(SimulationController control) { + preRun(); + run(control); + postRun(); + } + + /** + * Initializes this simulator for the first run (or a further run starting from time 0). + */ + public void preRun() { + initialize(); + + for (int o=0; otheta. It + * invokes {@link Observer#theta(double)} of the appropriate observer. + *

+ * It has to be called in extending classes. + *

+ * It also handles the interpolation. + */ + protected void thetaEvent() { +// double theta = getNextThetaEvent(); +// for (int o=0; o obs = thetaQueue.getNextObserversAndRemove(); + + double t_save = t; + t = theta; + boolean fired = false; + for (Observer o : observer) { + if (o instanceof TriggerObserver) + fired |= ((TriggerObserver)o).trigger(); + } + if (!fired) t = t_save; + + if (interpolateTheta) { + long[] beforeThetaAmounts = new long[net.getNumSpecies()]; + for (int i=0; i

  • set t=0
  • reset the {@link AmountManager}
  • recalculate the propensities
  • + * Gets called at the very beginning of start + */ + public void initialize() { + t=0; + amountManager.resetAmount(); + thetaQueue = new ThetaQueue(); + + for (int i=0; itheta of + * a observer. It is used e.g. to determine the amounts of species at one moments. + * Extending class just have to call {@link Simulator#thetaEvent()} which basically + * calls the observer. + * + * @return the theta + */ + public double getNextThetaEvent() { +// double theta = Double.POSITIVE_INFINITY; +// for (Observer o : observer) +// theta = Math.min(theta,o.getTheta()); +// return theta; + return thetaQueue.getNextTheta(); + } + + /** + * Gets the {@link AmountManager}. + * @return the AmountManager + */ + protected AmountManager getAmountManager() { + return amountManager; + } + + /** + * Gets the amount of the given species. + * + * @param species species index + * @return amount of species + * + * @see AmountManager#getAmount(int) + */ + public double getAmount(int species) { + if (interpolateTheta && interpolationParameters!=null) + return NumberTools.interpolateLinear(interpolationParameters.interpolationTheta, interpolationParameters.beforeTheta, getTime(), (int)interpolationParameters.beforeThetaAmounts[species], (int)amountManager.getAmount(species)); + else + return amountManager.getAmount(species); + } + + /** + * Sets the amount of the given species. Propensities have to be recalculated! + * + * @param species species index + * @param amount amount of species + * + * @see AmountManager#setAmount(int, long) + */ + public void setAmount(int species, long amount) { + amountManager.setAmount(species, amount); + } + + /** + * Gets the {@link PropensityCalculator}. + * @return the PropensityCalculator + */ + public PropensityCalculator getPropensityCalculator() { + return propensityCalculator; + } + + /** + * Gets the simulation network. + * @return the network + */ + public Network getNet() { + return net; + } + + /** + * Adds an observer to the list of observers. + * + * @param observer the observer to add + * @return the added observer + */ + public Observer addObserver(Observer observer) { + if (observer.getSimulator()!=this) + throw new IllegalArgumentException("Observer doesn't belong to this simulator!"); + Observer[] n = new Observer[this.observer.length+1]; + System.arraycopy(this.observer, 0, n, 0, this.observer.length); + n[n.length-1] = observer; + this.observer = n; + return observer; + } + + + + /** + * Gets the volume of the reaction network. + * + * @return volume + */ + public double getVolume() { + return volume; + } + + + /** + * Sets the volume of the reaction network. + * + * @param volume the volume + */ + public void setVolume(double volume) { + this.volume = volume; + } + + /** + * Gets whether the amount values are returned interpolated for theta events. + * + * @return interpolated + */ + public boolean isInterpolateTheta() { + return interpolateTheta; + } + + /** + * Sets whether the amount values are returned interpolated for theta events. + */ + public void setInterpolateTheta(boolean interpolateTheta) { + this.interpolateTheta = interpolateTheta; + } + + /** + * Gets the current propensity for the given reaction. + * + * @param reaction index of the reaction + * @return propensity for the reaction + */ + public double getPropensity(int reaction) { + return a[reaction]; + } + + /** + * Defines different types of a firing for reactions. + * + * @author Florian Erhard + * + */ + public enum FireType { + GillespieSimple,GillespieEnhanced, GibsonBruck, TauLeapCritical, TauLeapNonCritical + } + + + private static class DelayedThetaInvokationParameters + { + public double beforeTheta = -1; + public long[] beforeThetaAmounts = null; + public double interpolationTheta = 0; + public LinkedList observers; + + public DelayedThetaInvokationParameters(double beforeTheta, long[] beforeThetaAmounts, double interpolationTheta,LinkedList observers) { + this.beforeTheta = beforeTheta; + this.beforeThetaAmounts = beforeThetaAmounts; + this.interpolationTheta = interpolationTheta; + this.observers = observers; + } + } + + /** + * Manages the registered thetas + * + * @author Florian Erhard + * + */ + private static class ThetaQueue { + private Map> thetas; + private double nextTheta = Double.POSITIVE_INFINITY; + + public ThetaQueue() { + thetas = new HashMap>(); + } + + public void pushTheta(double theta, Observer obs) { + if (!thetas.containsKey(theta)) + thetas.put(theta,new LinkedList()); + thetas.get(theta).add(obs); + nextTheta = Math.min(nextTheta, theta); + } + + public double getNextTheta() { + return nextTheta; + } + + public LinkedList getNextObserversAndRemove() { + LinkedList re = thetas.remove(nextTheta); + nextTheta = Double.POSITIVE_INFINITY; + for (Double t : thetas.keySet()) + nextTheta = Math.min(nextTheta,t); + return re; + } + } + + + + +} diff --git a/src/main/java/fern/simulation/algorithm/AbstractBaseTauLeaping.java b/src/main/java/fern/simulation/algorithm/AbstractBaseTauLeaping.java new file mode 100644 index 00000000..7eb26afc --- /dev/null +++ b/src/main/java/fern/simulation/algorithm/AbstractBaseTauLeaping.java @@ -0,0 +1,426 @@ +package fern.simulation.algorithm; + +import java.util.Map; + + +import cern.colt.bitvector.BitVector; +import fern.network.AbstractKineticConstantPropensityCalculator; +import fern.network.Network; +import fern.simulation.controller.SimulationController; +import fern.tools.NetworkTools; +import fern.tools.NumberTools; + + +/** + * Base class for all tau leaping procedures (which are different in the methods choosing + * the timestep candidates for critical and noncritical reactions). It extends GillespieEnhanced + * because it uses the SSP algorithm, when the timestep candidate is to small. + *

    + * Each tau leaping algorithm only works with an {@link AbstractKineticConstantPropensityCalculator} and + * only if the highest order of a reaction is maximal 3. + *

    + * For references see Daniel T. Gillespie, Approximate accelerated stochastic simulation + * of chemically reacting systems, Journal of chemical physics vol 115, nr 4 (2001); Cao et al., Efficient + * step size selection for the tau-leaping simulation method, Journal of chemical physics 124, 044109 (2006) + * + * @author Florian Erhard + * @see GillespieEnhanced + */ +public abstract class AbstractBaseTauLeaping extends GillespieEnhanced { + + private double langevinThreshold = Double.POSITIVE_INFINITY; + private double useSimpleFactor = 10; + private int numSimpleCalls = 100; + private int nCritical = 10; + private double epsilon = 0.03; + private int[][] v = null; + private BitVector criticals = null; + protected boolean verbose = false; + + protected Map[] reactantHistos; + protected Map[] productHistos; + + + /** + * Create the simulator for a given network. + * @param net the simulation network + */ + @SuppressWarnings("unchecked") + public AbstractBaseTauLeaping(Network net) { + super(net); + reactantHistos = new Map[net.getNumReactions()]; + for (int i=0; inumSimpleCalls steps + * from the SSP-Algorithm GillespieEnhanced are perform. Otherwise a second timestep + * candidate is drawn for the criticals (such that only one critical reaction is firing + * and only once in this leap). The smaller candidate is then used as tau. + */ + @Override + public void performStep(SimulationController control) { + + double tau1,tau2,tau3; + + recalculatePropensities(); + if (Double.isInfinite(getTime())) + return; + + + tau3 = getNextThetaEvent()-getTime(); + + while (control.goOn(this) && getNextThetaEvent()<=getTime()) + thetaEvent(); + + + + + if (verbose) { + System.out.println("Step started at ("+getTime()+")\n-----------------\n"); + System.out.println("use simple threshold: "+(useSimpleFactor/a_sum)); + } + + identifyCriticals(); + + if (verbose) + System.out.println("critical reactions: \n"+NetworkTools.getReactionNameWithAmounts(getNet(), NumberTools.getContentAsArray(criticals))+"\n"); + + tau1 = chooseTauNonCriticals(criticals); + + boolean success = false; + while (!success) { + + if (verbose) + System.out.println("Chose tau': "+tau1); + + if (tau1=test) return i; + } + + throw new RuntimeException("Drawing variable aborted!"); + } + + + /** + * Identifies critical reactions. + * @return Bitvector identifying the critical reactions + */ + private void identifyCriticals() { + if (criticals==null) + criticals = new BitVector(getNet().getNumReactions()); + else + criticals.clear(); + + for (int j=0; j0 && computeL(j)reaction + * can fire before exhausting one of its reactants. + * @param reaction the index of the reaction + * @return maximal number of firing times + */ + private int computeL(int reaction) { + int firings = Integer.MAX_VALUE; + + Map reactantHisto = this.reactantHistos[reaction]; + for (Integer reactant : reactantHisto.keySet()) + firings = Math.min(firings,(int)Math.floor(getAmountManager().getAmount(reactant)/reactantHisto.get(reactant))); + + return firings; + } + + /** + * Tries to perform the tau leap by generating random numbers for the times of + * firings of each noncritical reaction. If the leap is unsuccessful (because the + * reactants of one reaction are exhausted), false is returned (but the already performed + * firings are not canceled). If the parameter for the used Poisson distribution + * is greater than langevinThreshold, a Normal distribution is used + * as an approximation (which is faster). + * @param tau the timestep for the leap + * @param criticals Bitvector identifying the critical reactions + * @return + */ + private boolean leapBy(double tau, BitVector criticals, FireType fireType) { + int max = 0; + int sum = 0; + try { + int times; + double at; + for (int i=0; ilangevinThreshold) + times = Math.max(0, (int) Math.round(at+Math.sqrt(at)*stochastics.getNormal())); + else + times = stochastics.getPoisson(at); + if (times>0) + fireReaction(i, t, t+tau, times, fireType); + max = Math.max(max, times); + sum+=times; + } + if (verbose) + System.out.println("Sum="+sum+" Max="+max); + t+=tau; + return true; + } catch (RuntimeException e) { + return false; + } + } + + protected int getV(int species, int reaction) { + return v[species][reaction]; + } + + /** + * The Langevin threshold determines, when the normal distribution is used as an + * approximation for the poisson distribution. The default value is Infinity (no + * approximation). + * @return the langevinThreshold + */ + public double getLangevinThreshold() { + return langevinThreshold; + } + + + /** + * The Langevin threshold determines, when the normal distribution is used as an + * approximation for the poisson distribution. The default value is Infinity (no + * approximation). + * @param langevinThreshold the langevinThreshold to set + */ + public void setLangevinThreshold(double langevinThreshold) { + this.langevinThreshold = langevinThreshold; + } + + + /** + * The useSimpleFactor determines, when the tau leaping is abandoned and the SSA + * method is used (if tau + * Daniel T. Gillespie, Approximate accelerated stochastic simulation + * of chemically reacting systems, Journal of chemical physics vol 115, nr 4 (2001); Cao et al., Efficient + * step size selection for the tau-leaping simulation method, Journal of chemical physics 124, 044109 (2006) + * + * + * + * @author Florian Erhard + * + */ +public abstract class AbstractTauLeapingPropensityBoundSimulator extends AbstractBaseTauLeaping { + + + protected double[][] f; + protected double[] mu; + protected double[] sigma; + + + public AbstractTauLeapingPropensityBoundSimulator(Network net) { + super(net); + f = new double[net.getNumReactions()][net.getNumReactions()]; + mu = new double[net.getNumReactions()]; + sigma = new double[net.getNumReactions()]; + } + + + @Override + protected double chooseTauNonCriticals(BitVector criticals) { + preprocessNonCriticals(criticals); + + String min = null; + double top; + double tau = Double.POSITIVE_INFINITY; + for (int j=0; jPreferences>Java>Code Generation>Code and Comments + */ +package fern.simulation.algorithm; + +import fern.network.ConstantAmountManager; +import fern.network.AmountManager; +import fern.network.DefaultAmountManager; +import fern.network.Network; +import fern.network.PropensityCalculator; +import fern.simulation.Simulator; +import fern.simulation.Simulator.FireType; +import fern.simulation.controller.SimulationController; + + +/** + * + * This is an enhanced version of the original Direct method developed by + * Gillespie. Just like the algorithm of Gibson and Bruck it uses a dependency graph to know what propensities + * have to be recalculated. Additionally, the composition and rejection method proposed in Slepoy 2008 is used + * to determine the next firing reaction. + *

    + * For references see Daniel T. Gillespie., A General Method for Numerically Simulating + * the Stochastic Time Evolution of Coupled Chemical Reactions, J.Comp.Phys. 22, 403 (1976) + * and M.A.Gibson and J.Bruck, Efficient Exact Stochastic Simulation of Chemical + * Systems with Many Species and Many Channels, J.Phys.Chem.A., Vol 104, no 9, 2000 + * and Alexander Slepoy Aidan P. Thompson and Steven J. Plimpton, A constant-time kinetic Monte Carlo + * algorithm for simulation of large biochemical reaction networks, J. Chem. Phys. 128, 205101 (2008); DOI:10.1063/1.2919546 + * + * @author Florian Erhard + * @see GillespieEnhanced + * @see DependencyGraph + */ +public class CompositionRejection extends GillespieEnhanced { + + private GroupContainer groups; + + public CompositionRejection(Network net) { + super(net); + + groups = new GroupContainer(this); + } + + + @Override + public boolean isEfficientlyAdaptSum() { + return true; + } + + @Override + public void initialize() { + super.initialize(); + groups.initialize(a); + } + + @Override + public void reinitialize() { + super.reinitialize(); + groups.initialize(a); + } + + @Override + public void performStep(SimulationController control) { + + if (changed) { + initialize(); + } + + // obtain mu and tau by the direct method described in chapter 5A page 417ff + double tau = directMCTau(groups.getA_sum()); + + if (!Double.isInfinite(tau)) { + changed = false; + while (t<=getNextThetaEvent() && t+tau>getNextThetaEvent() && !changed) + thetaEvent(); + + if (changed) { + performStep(control); + return; + + } + int mu = groups.drawReaction(stochastics, a); + + fireReaction(mu, t+tau, FireType.GillespieEnhanced); + + for (int alpha : dep.getDependent(mu)) { + double old = a[alpha]; + a[alpha] = getPropensityCalculator().calculatePropensity(alpha,getAmountManager(), this); + groups.propensityChanged(alpha, old, a[alpha]); + } + } + + t+=tau; + + if (Double.isInfinite(tau)) + thetaEvent(); + } + + + + @Override + public String getName() { + return "Composition rejection"; + } + + +} diff --git a/src/main/java/fern/simulation/algorithm/DependencyGraph.java b/src/main/java/fern/simulation/algorithm/DependencyGraph.java new file mode 100644 index 00000000..ca1ec9dd --- /dev/null +++ b/src/main/java/fern/simulation/algorithm/DependencyGraph.java @@ -0,0 +1,104 @@ +/* + * Created on 03.08.2006 + * + * To change the template for this generated file go to + * Window>Preferences>Java>Code Generation>Code and Comments + */ +package fern.simulation.algorithm; + +import java.util.LinkedList; +import java.util.Map; + +import fern.network.ComplexDependenciesPropensityCalculator; +import fern.network.Network; +import fern.tools.NumberTools; + +/** + * + * Implements a dependency graph. It is a directed graph whose vertices are the reactions + * of a network. From vertex i to vertex j is an edge iff i=j or there is at least one species + * that changes quantity when reaction i fires and is reactant of reaction j. + *

    + * This definition implies that if a reaction i fires, the propensities of each descendant + * in the dependency graph has to be recalculated and no other. + * + * + *

    + * For reference see M.A.Gibson and J.Bruck, Efficient Exact Stochastic Simulation of Chemical + * Systems with Many Species and Many Channels, J.Phys.Chem.A., Vol 104, no 9, 2000 + * + * @author Florian Erhard + * @see GillespieEnhanced + * @see GibsonBruckSimulator + */ +public class DependencyGraph { + + private LinkedList[] dependsOn = null; + + /** + * Creates the dependency graph for a given network + * @param net the network + */ + @SuppressWarnings("unchecked") + public DependencyGraph(Network net) { + dependsOn = new LinkedList[net.getNumReactions()]; + + Map[] reactants = new Map[net.getNumReactions()]; + for (int i=0; i[] products = new Map[net.getNumReactions()]; + for (int i=0; i getDependent(int reaction) { + return dependsOn[reaction]; + } + + private boolean haveToCreateEdgeFromTo(int i, int j, Network net, Map[] reactants, Map[] products) { + // if and only if there is at least one molecule that: + // 1. changes quantity, when i is executed + // 2. is reactant of j + // or i = j + // or we have a ComplexDependenciesPropensityCalculator: + // one molecule that + // 1. is dependent on j + // 2. changes quantitiy + if (i==j) return true; + + for (int j_reactant : net.getReactants(j)) { + int i_reactant = reactants[i].containsKey(j_reactant) ? reactants[i].get(j_reactant) : 0; + int i_product = products[i].containsKey(j_reactant) ? products[i].get(j_reactant) : 0; + if (i_reactant!=i_product) + return true; + } + + if (net.getPropensityCalculator() instanceof ComplexDependenciesPropensityCalculator) + for (int j_reactant : ((ComplexDependenciesPropensityCalculator)net.getPropensityCalculator()).getKineticLawSpecies(j)) { + int i_reactant = reactants[i].containsKey(j_reactant) ? reactants[i].get(j_reactant) : 0; + int i_product = products[i].containsKey(j_reactant) ? products[i].get(j_reactant) : 0; + if (i_reactant!=i_product) + return true; + } + + return false; + } + + +} diff --git a/src/main/java/fern/simulation/algorithm/GibsonBruckSimulator.java b/src/main/java/fern/simulation/algorithm/GibsonBruckSimulator.java new file mode 100644 index 00000000..403d349b --- /dev/null +++ b/src/main/java/fern/simulation/algorithm/GibsonBruckSimulator.java @@ -0,0 +1,169 @@ +/* + * Created on 03.08.2006 + * + * To change the template for this generated file go to + * Window>Preferences>Java>Code Generation>Code and Comments + */ +package fern.simulation.algorithm; + +import fern.network.Network; +import fern.simulation.Simulator; +import fern.simulation.controller.SimulationController; + + +/** + * Implementation of the algorithm of Gibson and Bruck. They made two major improvements + * to Gillespie's Direct method ({@link GillespieSimple}): + *

      + *
    1. using a dependency graph
    2. + *
    3. using a indexed priority queue
    4. + *
    + * The first describes, which propensities have to be recalculates after some reaction + * has fired, the latter puts an end to the time consuming search for the Direct + * which fires after one firing. The priority queue just yields the next reaction to fire (from + * which the name "Next reaction method" is derived). The priority queue holds for each + * reaction the time of its next firing. + *

    + * In order to do that the perspective of viewing the simulators time has to be changed + * from relative to absolute. As a consequence, a new random number has to be drawn for + * each reaction whose propensity has changed by a firing. To avoid this inefficient permanent + * discarding of random numbers (drawing a random number is a time expensive operation) + * Gibson and Bruck developed a method for reusing unused random numbers. + *

    + * One pitfall remains: What happens, when a propensity decreases to 0 and after a time + * ceases to be 0. Then the propensity from the pre-0 state can be reused which is tricky + * to implement. Some implementations (including Dizzy) just draw a new random number which + * is always valid but slow. Actually may these extra random numbers spoil the whole + * improvement of the indexed priority queue in certain networks and it would be faster to + * use the Direct method with the dependency graph (as in {@link GillespieEnhanced} ). + * + * + *

    + * For reference see M.A.Gibson and J.Bruck, Efficient Exact Stochastic Simulation of Chemical + * Systems with Many Species and Many Channels, J.Phys.Chem.A., Vol 104, no 9, 2000 + * + * @author Florian Erhard + * @see GillespieSimple + * @see GillespieEnhanced + * @see DependencyGraph + * @see IndexedPriorityQueue + */ +public class GibsonBruckSimulator extends Simulator { + + private boolean changed = false; + private DependencyGraph dep = null; + private IndexedPriorityQueue queue = null; + private double[] tBeforeAlphaBecomesNull = null; + private double[] aBeforeAlphaBecomesNull = null; + + public GibsonBruckSimulator(Network net) { + super(net); + } + + @Override + public void reinitialize() { + changed = true; + } + + public void performStep(SimulationController control) { + + if (changed) { + initialize(); + changed = false; + } + + double tau = queue.getMinKey(); + + if (!Double.isInfinite(tau)) { + + changed = false; + while (t<=getNextThetaEvent() && tau>getNextThetaEvent() && !changed) + thetaEvent(); + + if (changed) { + performStep(control); + return; + } + + int mu = queue.getMin(); + + fireReaction(mu, tau, FireType.GibsonBruck); + + for (int alpha : dep.getDependent(mu)) { + double a_alphaold = a[alpha]; + a[alpha] = getPropensityCalculator().calculatePropensity(alpha,getAmountManager(), this); + + double tau_alpha; + + if (a[alpha]==0) { + tau_alpha = Double.POSITIVE_INFINITY; + if (a_alphaold>0) { + tBeforeAlphaBecomesNull[alpha] = queue.getKey(alpha)-tau; + aBeforeAlphaBecomesNull[alpha] = alpha==mu ? 0 : a_alphaold; + } + } else { + if (a_alphaold==0 && a[alpha]>0) { + // alpha != mu + if (aBeforeAlphaBecomesNull[alpha]==0) + tau_alpha = stochastics.getExponential(a[alpha])+tau; + else + tau_alpha = (aBeforeAlphaBecomesNull[alpha]/a[alpha])*(tBeforeAlphaBecomesNull[alpha])+tau; + + } else { + if (alpha!=mu) + tau_alpha = (a_alphaold/a[alpha])*(queue.getKey(alpha)-tau)+tau; + else + tau_alpha = stochastics.getExponential(a[alpha])+tau; + } + } + + queue.update(alpha, tau_alpha); + + + } + } + + t=tau; + + if (Double.isInfinite(tau)) + thetaEvent(); + } + + @Override + public void initialize() { + super.initialize(); + + if (dep==null) + dep = new DependencyGraph(getNet()); + + // create initial values for tau + double[] t = new double[getNet().getNumReactions()]; + for (int i=0; iPreferences>Java>Code Generation>Code and Comments + */ +package fern.simulation.algorithm; + +import fern.network.Network; +import fern.simulation.Simulator; +import fern.simulation.controller.SimulationController; + + +/** + * + * This is an enhanced version of the original Direct method developed by + * Gillespie. Just like the algorithm of Gibson and Bruck it uses a dependency graph to know what propensities + * have to be recalculated. + *

    + * Take care with the option efficientlyAdaptSum: if it is true, it is possible that the sum + * become numerically unstable and the simulation fails, but especially for sparse networks + * it should be much more efficient. + * + *

    + * For references see Daniel T. Gillespie., A General Method for Numerically Simulating + * the Stochastic Time Evolution of Coupled Chemical Reactions, J.Comp.Phys. 22, 403 (1976) + * and M.A.Gibson and J.Bruck, Efficient Exact Stochastic Simulation of Chemical + * Systems with Many Species and Many Channels, J.Phys.Chem.A., Vol 104, no 9, 2000 + * + * @author Florian Erhard + * @see GillespieSimple + * @see DependencyGraph + */ +public class GillespieEnhanced extends Simulator { + + protected double a_sum = 0; + protected DependencyGraph dep = null; + protected boolean efficientlyAdaptSum = false; + protected boolean changed = false; + + public GillespieEnhanced(Network net) { + super(net); + } + + @Override + public void initialize() { + super.initialize(); + + if (dep==null) + dep = new DependencyGraph(getNet()); + + a_sum = 0; + for (int i=0; igetNextThetaEvent() && !changed) + thetaEvent(); + + if (changed) { + performStep(control); + return; + + } + int mu = directMCReaction(); + + fireReaction(mu, t+tau, FireType.GillespieEnhanced); + + for (int alpha : dep.getDependent(mu)) { + if (efficientlyAdaptSum) a_sum-=a[alpha]; + a[alpha] = getPropensityCalculator().calculatePropensity(alpha,getAmountManager(), this); + if (efficientlyAdaptSum) a_sum+=a[alpha]; + } + } + if (!efficientlyAdaptSum) { + a_sum = 0; + for (int i=0; i=test) + return i; + } + + throw new RuntimeException("No reaction could be selected!"); + } + + /** + * obtains a random (but following a specific distribution) timestep as described by the + * direct method in chapter 5A page 417ff + * @param sum sum of the propensities + * @return tau + */ + protected double directMCTau(double sum) { + double r1 = stochastics.getUnif(); + return (1/sum)*Math.log(1/r1); + } + + @Override + public void setVolume(double volume) { + super.setVolume(volume); + changed = true; + } + + @Override + public void setAmount(int species, long amount) { + super.setAmount(species, amount); + changed = true; + } + + @Override + public String getName() { + return "enhanced Gillespie"; + } + + public boolean isEfficientlyAdaptSum() { + return efficientlyAdaptSum; + } + + public void setEfficientlyAdaptSum(boolean efficientlyAdaptSum) { + this.efficientlyAdaptSum = efficientlyAdaptSum; + } +} diff --git a/src/main/java/fern/simulation/algorithm/GillespieSimple.java b/src/main/java/fern/simulation/algorithm/GillespieSimple.java new file mode 100644 index 00000000..6528c17e --- /dev/null +++ b/src/main/java/fern/simulation/algorithm/GillespieSimple.java @@ -0,0 +1,118 @@ +/* + * Created on 12.03.2007 + * + * To change the template for this generated file go to + * Window>Preferences>Java>Code Generation>Code and Comments + */ +package fern.simulation.algorithm; + +import fern.network.Network; +import fern.simulation.Simulator; +import fern.simulation.controller.SimulationController; + + +/** + * + * Implementation of Gillespie's Direct method. It is a simple + * Monte-Carlo algorithm which draws from a from Gillspie derived distribution + * a reaction that will fire and a time at which the reaction will fire. + *

    + * For reference see Daniel T. Gillespie., A General Method for Numerically Simulating + * the Stochastic Time Evolution of Coupled Chemical Reactions, J.Comp.Phys. 22, 403 (1976) + * + * + * @author Florian Erhard + * + */ +public class GillespieSimple extends Simulator { + + private double a_sum = 0; + private boolean changed = false; + + public GillespieSimple(Network net) { + super(net); + + } + + @Override + public void reinitialize() { + changed = true; + } + + @Override + public void performStep(SimulationController control) { + a_sum = 0; + // calc the h's described in (14) page 413 and the sum a (26) page 418 + for (int i=0; igetNextThetaEvent() && !changed) + thetaEvent(); + + if (changed) { + performStep(control); + return; + } + + int mu = directMCReaction(); + + fireReaction(mu, t+tau, FireType.GillespieSimple); + } + + + // advance the time + t+=tau; + + if (Double.isInfinite(tau)) + thetaEvent(); + } + + /** + * obtains a random (but following a specific distribution) reaction as described by the + * direct method in chapter 5A page 417ff + * @param reactions + * @param a + * @return + */ + private int directMCReaction() { + double r2 = stochastics.getUnif(); + double test = r2*a_sum; + + double sum = 0; + for (int i=0; i=test) + return i; + } + + throw new RuntimeException("No reaction could be selected!"); + } + + /** + * obtains a random (but following a specific distribution) timestep as described by the + * direct method in chapter 5A page 417ff + * @param sum sum of the propensities + * @return tau + */ + protected double directMCTau(double sum) { + double r1 = stochastics.getUnif(); + return (1/sum)*Math.log(1/r1); + } + + @Override + public String getName() { + return "original Gillespie"; + } + + + + + + +} diff --git a/src/main/java/fern/simulation/algorithm/GroupContainer.java b/src/main/java/fern/simulation/algorithm/GroupContainer.java new file mode 100644 index 00000000..186c0721 --- /dev/null +++ b/src/main/java/fern/simulation/algorithm/GroupContainer.java @@ -0,0 +1,185 @@ +package fern.simulation.algorithm; + +import java.util.Arrays; + +import fern.network.AmountManager; +import fern.network.DefaultAmountManager; +import fern.network.Network; +import fern.network.PropensityCalculator; +import fern.simulation.Simulator; +import fern.tools.Stochastics; + + +public class GroupContainer { + + private int[][] groups; + private int[] groupSizes; + private double[] groupPropensitySums; + + private double min; + private double max; + private int[] groupOfReaction; + private int[] positionOfReaction; + private int topGroup = 0; + + private double a_sum; + + public GroupContainer(Simulator sim) { + determineMaxMin(sim); + + int numReactions = sim.getNet().getNumReactions(); + int numGroups = (int)(1+Math.log(max/min)/Math.log(2)); + + + groupOfReaction = new int[numReactions]; + positionOfReaction = new int[numReactions]; + Arrays.fill(groupOfReaction, -1); + Arrays.fill(positionOfReaction, -1); + + groupSizes = new int[numGroups]; + groups = new int[numGroups][numReactions]; + groupPropensitySums = new double[numGroups]; + } + + public double getA_sum() { + return a_sum; + } + + private void determineMaxMin(Simulator sim) { + Network net = sim.getNet(); + PropensityCalculator prop = net.getPropensityCalculator(); + AmountManager amount = new DefaultAmountManager(net); + + min = Double.POSITIVE_INFINITY; + max = Double.NEGATIVE_INFINITY; + for (int i=0; i0) { + a_sum += a[i]; + checkMax(a[i]); + + int g = getGroup(a[i]); + groupOfReaction[i] = g; + positionOfReaction[i] = groupSizes[g]; + groups[g][groupSizes[g]++] = i; + groupPropensitySums[g]+=a[i]; + topGroup = Math.max(topGroup,g); + } + else { + groupOfReaction[i] = -1; + positionOfReaction[i] = -1; + } + } + } + + private void checkMax(double a) { + if (a>max) { + int g = getGroup(a); + if (g>=groups.length) { + int numGroups = g+1; + int[] n_groupSizes = new int[numGroups]; + int[][] n_groups = new int[numGroups][groupOfReaction.length]; + double[] n_groupPropensityCumSums = new double[numGroups]; + System.arraycopy(groupSizes, 0, n_groupSizes, 0, groupSizes.length); + System.arraycopy(groups, 0, n_groups, 0, groups.length); + System.arraycopy(groupPropensitySums, 0, n_groupPropensityCumSums, 0, groupPropensitySums.length); + groupSizes = n_groupSizes; + groups = n_groups; + groupPropensitySums = n_groupPropensityCumSums; + } + + max = a; + } + } + + public int drawReaction(Stochastics s, double[] a) { + double t = s.getUnif()*a_sum; + + double sum = 0; + int group; + for (group=topGroup; group>=0; group--) { + sum+=groupPropensitySums[group]; + if (sum>=t) + break; + } + + int[] currentGroup = groups[group]; + int currentGroupSize = groupSizes[group]; + + int reaction; + double p; + + if (currentGroupSize==1) + reaction = 0; + else { + do { + reaction = s.getUnif(0, currentGroupSize); + p = s.getUnif()*min*(1<a[currentGroup[reaction]]); + } + + return currentGroup[reaction]; + } + + + private int getGroup(double a) { + double t = a/min; + return (int) (Math.log(t)/Math.log(2)); + } + + public void propensityChanged(int reaction, double a_old, double a_new) { + checkMax(a_new); + + int g = groupOfReaction[reaction]; + int p = positionOfReaction[reaction]; + if (g>-1) { + groupPropensitySums[g]-=a_old; + a_sum-=a_old; + } + + int ng = a_new==0 ? -1 : getGroup(a_new); + if (ng!=g) { + if (g>-1) { + groups[g][p] = groups[g][--groupSizes[g]]; + positionOfReaction[groups[g][p]] = p; + } + if (ng>-1) { + groupOfReaction[reaction] = ng; + positionOfReaction[reaction] = groupSizes[ng]; + groups[ng][groupSizes[ng]++] = reaction; + } else { + groupOfReaction[reaction] = -1; + positionOfReaction[reaction] = -1; + } + + } + if (ng>-1) { + groupPropensitySums[ng]+=a_new; + a_sum+=a_new; + } + if (ng>g && ng>topGroup) + topGroup = ng; + else if (ng0 && groupSizes[topGroup]==0; topGroup--); + } + } + + +} diff --git a/src/main/java/fern/simulation/algorithm/HybridMaximalTimeStep.java b/src/main/java/fern/simulation/algorithm/HybridMaximalTimeStep.java new file mode 100644 index 00000000..a5e7e379 --- /dev/null +++ b/src/main/java/fern/simulation/algorithm/HybridMaximalTimeStep.java @@ -0,0 +1,210 @@ +package fern.simulation.algorithm; + +import cern.colt.bitvector.BitVector; +import fern.network.Network; +import fern.simulation.Simulator; +import fern.simulation.controller.SimulationController; + +/** + * + * This is an modified version of Maximal Time Step Method by Puchalka and Kierzec. + * Reactions are divided into slow and fast reaction. The slow ones are fired according + * to Gillespies Direct Method as in {@link GillespieEnhanced}, the fast ones are handled by + * tau leaping. This method can be a substancial improvement on speed when simulating a network + * composed of different realms of magnitude (e.g. when simulating both gene regulation and + * metabolism). + * + *

    + * For references see J. Puchalka. and A.M. Kierzek, Briding the Gap betwwen Stochastic and + * Determininistic Regimes in the Kinetic Simulations of the Biochemical Reaction Networks, + * Biophysical 86, 1357-1372 (2004) + * + * @author Florian Erhard + * @see GillespieEnhanced + * @see DependencyGraph + */ +public class HybridMaximalTimeStep extends Simulator { + + protected double a_sum = 0; + private DependencyGraph dep = null; + private boolean changed = false; + + private double kappa = 1E-3; + private double r = 1E-4; + private int n = 100; + private BitVector fast; + private BitVector dependent; + + + public HybridMaximalTimeStep(Network net) { + super(net); + fast = new BitVector(getNet().getNumReactions()); + dependent = new BitVector(getNet().getNumReactions()); + dep = new DependencyGraph(net); + } + + @Override + public void initialize() { + super.initialize(); + + a_sum = 0; + for (int i=0; igetNextThetaEvent() && !changed) + thetaEvent(); + + if (changed) { + performStep(control); + return; + } + + dependent.clear(); + + for (int i=0; i=test) + return i; + } + } + + throw new RuntimeException("No reaction could be selected!"); + } + + private boolean isFast(int mu) { + return condition2(mu) && condition1(mu); + } + + private boolean condition1(int mu) { + int[] r = getNet().getReactants(mu); + for (int i=0; ir; + } + + private void partition() { + fast.clear(); + for (int i=0; iPreferences>Java>Code Generation>Code and Comments + */ +package fern.simulation.algorithm; + +import java.util.Arrays; +import java.util.LinkedList; +import java.util.Queue; +import java.util.Random; + + +/** + * + * Implements an indexed priority queue. It is a data structure to manage the absolute taus + * of the Gibson-Bruck algorithm in an efficient way. It is composed of a binary heap (the + * taus are the keys) and an index for fast access to a node of the heap. The fast access + * is necessary to update unused taus in the queue. + *

    + * For reference see M.A.Gibson and J.Bruck, Efficient Exact Stochastic Simulation of Chemical + * Systems with Many Species and Many Channels, J.Phys.Chem.A., Vol 104, no 9, 2000 + * + * @author Florian Erhard + * @see GibsonBruckSimulator + */ +public class IndexedPriorityQueue { + + private double[] t; + private int[] oldIndex; + + private Node heapRoot = null; + private Node[] index = null; + + + /** + * Creates a IndexedPriorityQueue from the given taus + * @param t taus + */ + public IndexedPriorityQueue(double[] t) { + this.t=t; + oldIndex = new int[t.length]; + for (int i=0; i queue = new LinkedList(); + queue.add(heapRoot); + index[heapRoot.index] = heapRoot; + for (int i=1; i q = new LinkedList(); + q.add(heapRoot); + while (!q.isEmpty()) { + Node n = q.poll(); + s++; + if (n.left!=null) q.add(n.left); + if (n.right!=null) q.add(n.right); + } + return s; + } + + /** + * Gets the index of the minimal tau in the queue. + * + * @return index of the minimal tau + */ + public int getMin() { + return heapRoot.index; + } + + /** + * Gets the minimal tau in the queue. + * + * @return minimal tau + */ + public double getMinKey() { + return heapRoot.key; + } + + /** + * Updates the tau of a reaction to a given value + * @param i index of the reaction + * @param value new tau + */ + public void update(int i, double value) { + if (Double.isNaN(value)) value=Double.POSITIVE_INFINITY; + + Node n = index[i]; + n.key = value; + update_aux(n); + } + + /** + * Gets the tau of a reaction by lookup in the index + * @param i index of the reaction + * @return tau of the reaction + */ + public double getKey(int i) { + return index[i].key; + } + + private void update_aux(Node n) { + if (n.parent!=null && n.key < n.parent.key) { + swap(n,n.parent); + update_aux(n.parent); + } else if(n.left!=null && n.right!=null && n.key>Math.min(n.left.key, n.right.key)) { + Node child = n.left.keyn.left.key) { + swap (n,n.left); + update_aux(n.left); + } + } + + private void swap(Node n, Node m) { + double tmp = n.key; + n.key = m.key; + m.key = tmp; + int tmp2 = n.index; + n.index = m.index; + m.index = tmp2; + Node tmp3 = index[n.index]; + index[n.index] = index[m.index]; + index[m.index] = tmp3; + } + + private class Node { + Node left = null; + Node right = null; + Node parent = null; + int index; + double key; + public Node(int index, double key) { + this.index = index; this.key = key; + } + @Override + public String toString() { + return key+""; + } + } + + public static final Random RND = new Random(); + + private void swap(int i, int j) { + double tmp = t[i]; + t[i] = t[j]; + t[j] = tmp; + int tmp2 = oldIndex[i]; + oldIndex[i] = oldIndex[j]; + oldIndex[j] = tmp2; + } + + private int partition(int begin, int end) { + int index = begin + RND.nextInt(end - begin + 1); + double pivot = t[index]; + swap(index, end); + for (int i = index = begin; i < end; ++ i) { + if (t[i]< pivot) { + swap(index++, i); + } } + swap(index, end); + return (index); + } + + private void qsort(int begin, int end) { + if (end > begin) { + int index = partition(begin, end); + qsort(begin, index - 1); + qsort(index + 1, end); + } + } + + +} diff --git a/src/main/java/fern/simulation/algorithm/TauLeapingAbsoluteBoundSimulator.java b/src/main/java/fern/simulation/algorithm/TauLeapingAbsoluteBoundSimulator.java new file mode 100644 index 00000000..bb8c4af2 --- /dev/null +++ b/src/main/java/fern/simulation/algorithm/TauLeapingAbsoluteBoundSimulator.java @@ -0,0 +1,35 @@ +package fern.simulation.algorithm; + +import fern.network.Network; + +/** + * There are some possibilities to bind the expected change of the propensities by a + * value epsilon in order to fulfill the leap condition. Here the expected change is bound + * to the sum of all propensities. + *

    + * Daniel T. Gillespie, Approximate accelerated stochastic simulation + * of chemically reacting systems, Journal of chemical physics vol 115, nr 4 (2001); Cao et al., Efficient + * step size selection for the tau-leaping simulation method, Journal of chemical physics 124, 044109 (2006) + * + * @author Florian Erhard + * + * + */ +public class TauLeapingAbsoluteBoundSimulator extends + AbstractTauLeapingPropensityBoundSimulator { + + public TauLeapingAbsoluteBoundSimulator(Network net) { + super(net); + } + + + @Override + protected double getTop(int j) { + return getEpsilon()*a_sum; + } + + @Override + public String getName() { + return "Tau Leap Propensitiy Absolute Bound"; + } +} diff --git a/src/main/java/fern/simulation/algorithm/TauLeapingRelativeBoundSimulator.java b/src/main/java/fern/simulation/algorithm/TauLeapingRelativeBoundSimulator.java new file mode 100644 index 00000000..ee135b0c --- /dev/null +++ b/src/main/java/fern/simulation/algorithm/TauLeapingRelativeBoundSimulator.java @@ -0,0 +1,42 @@ +package fern.simulation.algorithm; + +import fern.network.KineticConstantPropensityCalculator; +import fern.network.Network; + +/** + * There are some possibilities to bind the expected change of the propensities by a + * value epsilon in order to fulfill the leap condition. Here the expected change is bound + * to individual propensities. + *

    + * Daniel T. Gillespie, Approximate accelerated stochastic simulation + * of chemically reacting systems, Journal of chemical physics vol 115, nr 4 (2001); Cao et al., Efficient + * step size selection for the tau-leaping simulation method, Journal of chemical physics 124, 044109 (2006) + * + * @author Florian Erhard + * + * + */ +public class TauLeapingRelativeBoundSimulator extends + AbstractTauLeapingPropensityBoundSimulator { + + KineticConstantPropensityCalculator propCalc; + public TauLeapingRelativeBoundSimulator(Network net) { + super(net); + if (! (getNet().getPropensityCalculator() instanceof KineticConstantPropensityCalculator)) + throw new RuntimeException("Cannot use this tau leap method for not constant propensity calculators!"); + + propCalc = (KineticConstantPropensityCalculator) getNet().getPropensityCalculator(); + + } + + @Override + protected double getTop(int j) { + double cj = getVolume()>0 ? propCalc.getConstantFromDeterministicRateConstant(propCalc.getConstant(j), j, getVolume()) : propCalc.getConstant(j); + return Math.max(getEpsilon()*a[j],cj); + } + + @Override + public String getName() { + return "Tau Leap Propensitiy Relative Bound"; + } +} diff --git a/src/main/java/fern/simulation/algorithm/TauLeapingSpeciesPopulationBoundSimulator.java b/src/main/java/fern/simulation/algorithm/TauLeapingSpeciesPopulationBoundSimulator.java new file mode 100644 index 00000000..b8a6e9b0 --- /dev/null +++ b/src/main/java/fern/simulation/algorithm/TauLeapingSpeciesPopulationBoundSimulator.java @@ -0,0 +1,120 @@ +/** + * + */ +package fern.simulation.algorithm; + +import cern.colt.bitvector.BitVector; +import fern.network.Network; +import fern.tools.NetworkTools; + + +/** + * There are some possibilities to bind the expected change of the propensities by a + * value epsilon in order to fulfill the leap condition. Here it is bound indirectly + * by the reactant species of each reaction which gives the same leaps in a more + * efficient manner. + *

    + * Daniel T. Gillespie, Approximate accelerated stochastic simulation + * of chemically reacting systems, Journal of chemical physics vol 115, nr 4 (2001); Cao et al., Efficient + * step size selection for the tau-leaping simulation method, Journal of chemical physics 124, 044109 (2006) + * + * + * + * @author Florian Erhard + * + */ +public class TauLeapingSpeciesPopulationBoundSimulator extends + AbstractBaseTauLeaping { + + // g[i]=-2 -> some second order reaction requires two i molecules + // g[i]=-3 -> some third order reaction requires three i molecules + // g[i]=-4 -> some third order reaction requires two i molecules + private int[] g; + private double[] mu; + private double[] sigma; + + + public TauLeapingSpeciesPopulationBoundSimulator(Network net) { + super(net); + + calculateG(); + mu = new double[net.getNumSpecies()]; + sigma = new double[net.getNumSpecies()]; + } + + + @Override + protected double chooseTauNonCriticals(BitVector criticals) { + preprocessNonCriticals(criticals); + + double tau = Double.POSITIVE_INFINITY; + + for (int i=0; iSimulationController. + * If one controller tells to stop, the simulation will stop. + * + * @author Florian Erhard + * @see OrController + */ +public class AndController implements SimulationController { + + private SimulationController[] controllers; + + public AndController(SimulationController...controllers) { + this.controllers = controllers; + } + + public boolean goOn(Simulator sim) { + for (int i=0; iPreferences>Java>Code Generation>Code and Comments + */ +package fern.simulation.controller; + +import fern.simulation.Simulator; + +/** + * + * The probably most common implementation of an {@link SimulationController}. It + * causes the simulation to stop, after a given moment in time is crossed. + * + * @author Florian Erhard + * + */ +public class DefaultController implements SimulationController { + + private double maxTime; + + /** + * Creates the controller for a given time where the simulation has to stop. + * @param maxTime the moment in time where to stop the simulation + */ + public DefaultController(double maxTime) { + this.maxTime = maxTime; + } + + public boolean goOn(Simulator sim) { + return sim.getTime()SimulationController. + * If one controller tells to go on, the simulation will go on. + * + * @author Florian Erhard + * @see AndController + */ +public class OrController implements SimulationController { + + private SimulationController[] controllers; + + public OrController(SimulationController...controllers) { + this.controllers = controllers; + } + + public boolean goOn(Simulator sim) { + for (int i=0; iPreferences>Java>Code Generation>Code and Comments + */ +package fern.simulation.controller; + +import fern.simulation.Simulator; + +/** + * {@link Simulator}s are controlled by implementing classes. Each simulation step + * the goOn method is called to check whether to go on or not. + * + * @author Florian Erhard + * + */ +public interface SimulationController { + + /** + * Returns whether or not to go on with the given simulation + * @param sim simulation + * @return whether or not to go on + */ + public boolean goOn(Simulator sim); +} diff --git a/src/main/java/fern/simulation/observer/AmountAtMomentObserver.java b/src/main/java/fern/simulation/observer/AmountAtMomentObserver.java new file mode 100644 index 00000000..be9b719a --- /dev/null +++ b/src/main/java/fern/simulation/observer/AmountAtMomentObserver.java @@ -0,0 +1,162 @@ +package fern.simulation.observer; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import fern.simulation.Simulator; +import fern.simulation.Simulator.FireType; +import fern.simulation.controller.SimulationController; +import fern.tools.NetworkTools; +import fern.tools.NumberTools; +import fern.tools.gnuplot.GnuPlot; + + +/** + * + * Observes the amount of some molecule species at a certain moment. In order to + * accomplish that, this class also implements a {@link SimulationController} and + * registers a theta at the simulator. The data produced after are histograms + * for each species representing the distribution of amounts at theta. + * + * @author Florian Erhard + * @see IntervalObserver#getTheta() + * + */ +public class AmountAtMomentObserver extends Observer implements SimulationController, GnuPlotObserver { + + private String[] speciesNames; + private int[] species; + private double moment; + private boolean thetaReached; + private Map[] histogram; + private int count = 0; + + /** + * Creates the observer for the given simulator, the given theta and the given species + * @param sim simulator + * @param moment theta + * @param speciesName names of the species to observe + */ + @SuppressWarnings("unchecked") + public AmountAtMomentObserver(Simulator sim, double moment, String... speciesName) { + super(sim); + this.species = NetworkTools.getSpeciesIndices(sim.getNet(), speciesName); + this.speciesNames = speciesName; + this.moment = moment; + histogram = new HashMap[species.length]; + for (int i=0; i(); + } + + /** + * Creates the observer for the given simulator, the given theta and the given species + * @param sim simulator + * @param moment theta + * @param speciesIndices indices of the species to observe + */ + public AmountAtMomentObserver(Simulator sim, double moment, int... speciesIndices) { + this(sim,moment,NetworkTools.getSpeciesNames(sim.getNet(), speciesIndices)); + } + + /** + * Causes the simulator to stop when theta has been passed and the amounts + * have been recorded. + */ + public boolean goOn(Simulator sim) { + return !thetaReached; + } + + /** + * Do nothing + */ + @Override + public void activateReaction(int mu, double tau, FireType fireType, int times) {} + + /** + * Records the amounts of the species and puts it into the histogram. + */ + @Override + public void theta(double theta) { + for (int i=0; i histo : histogram) { + int max = NumberTools.max(histo.keySet()); + int min = NumberTools.min(histo.keySet()); + + double[][] data = new double[max-min+1][2]; + for (int i=min; i<=max; i++) { + data[i-min][0] = i; + data[i-min][1] = histo.containsKey(i) ? (double)histo.get(i)/(double)count : 0.0; + } + + gnuplot.addData(data, new String[] {getLabel(speciesNames[index++])}, getStyles()); + } + + return gnuplot; + } + + /** + * Gets the histogram of the distribution for a species + * + * @param species species index (but not in network index space - i means the ith passed species) + * @return histogram as map + */ + public Map getHistogram(int species) { + return histogram[species]; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + for (int i=0; iPreferences>Java>Code Generation>Code and Comments + */ +package fern.simulation.observer; + +import fern.simulation.Simulator; +import fern.tools.NetworkTools; + +/** + * + * Observes amounts of molecule species repeatedly after certain intervals. + *

    + * This observer does take repeats into account. If you repeat the simulation, + * you will get an average over the results of each run. + * + * @author Florian Erhard + * + */ +public class AmountIntervalObserver extends IntervalObserver { + + private int[] speciesIndices = null; + + /** + * Creates the observer for a given simulator, a given interval and given species indices + * @param sim simulator + * @param interval interval + * @param species species indices + */ + public AmountIntervalObserver(Simulator sim, double interval, int...species) { + super(sim,interval,NetworkTools.getSpeciesNames(sim.getNet(), species)); + this.speciesIndices = species; + + } + + /** + * Creates the observer for a given simulator, a given interval and given species names. + * @param sim simulator + * @param interval interval + * @param speciesName species names + */ + public AmountIntervalObserver(Simulator sim, double interval, String...speciesName) { + super(sim,interval,speciesName); + this.speciesIndices = NetworkTools.getSpeciesIndices(sim.getNet(), speciesName); + + } + + /** + * Creates the observer for a given simulator, a given interval and given species names with + * total simulation time. + * @param sim + * @param interval + * @param duration + * @param speciesName + */ + public AmountIntervalObserver(Simulator sim, double interval, int duration, String...speciesName) { + super(sim,interval, duration,speciesName); + this.speciesIndices = NetworkTools.getSpeciesIndices(sim.getNet(), speciesName); + } + + /** + * Gets the actual amount of a species. + */ + protected double getEntityValue(int i) { + return getSimulator().getAmount(speciesIndices[i]); + } + + + public String[] getStyles() { + return null; + } + + + + + + + + +} diff --git a/src/main/java/fern/simulation/observer/FireTypeObserver.java b/src/main/java/fern/simulation/observer/FireTypeObserver.java new file mode 100644 index 00000000..c3757a3f --- /dev/null +++ b/src/main/java/fern/simulation/observer/FireTypeObserver.java @@ -0,0 +1,118 @@ +package fern.simulation.observer; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +import fern.simulation.Simulator; +import fern.simulation.Simulator.FireType; +import fern.tools.NumberTools; +import fern.tools.gnuplot.GnuPlot; + +/** + * + * Observes the different types of firings. + *

    + * If the simulation is repeated, the average numbers are calculated. + * + * @author Florian Erhard + * @see FireType + */ +public class FireTypeObserver extends Observer implements GnuPlotObserver { + + private double[] numTypesAvg; + private long[] numTypes; + private Set addedTitles; + + /** + * Create the observer for the given simulator. + * @param sim simulator + */ + public FireTypeObserver(Simulator sim) { + super(sim); + numTypes = new long[FireType.values().length]; + numTypesAvg = new double[numTypes.length]; + addedTitles = new HashSet(); + } + + + /** + * Counts the firing for the given {@link FireType} + */ + @Override + public void activateReaction(int mu, double tau, FireType fireType, int times) { + numTypes[fireType.ordinal()]+=times; + } + + /** + * Calculates the average over all runs of the simulator. + */ + @Override + public void finished() { + for (int i=0; iGnuPlot object + * @throws IOException if gnuplot could not be accessed + */ + public GnuPlot toGnuplot()throws IOException; + + /** + * Passes the actual observer data to a {@link GnuPlot} object. + * + * @param gnuplot the GnuPlot object to pass the data to + * @return the GnuPlot object + * @throws IOException if gnuplot could not be accessed + */ + public GnuPlot toGnuplot(GnuPlot gnuplot)throws IOException; + + +} diff --git a/src/main/java/fern/simulation/observer/InstantOutputObserver.java b/src/main/java/fern/simulation/observer/InstantOutputObserver.java new file mode 100644 index 00000000..caeff8c5 --- /dev/null +++ b/src/main/java/fern/simulation/observer/InstantOutputObserver.java @@ -0,0 +1,76 @@ +package fern.simulation.observer; + +import java.io.PrintWriter; + +import fern.simulation.Simulator; +import fern.simulation.Simulator.FireType; + + +/** + * Simply prints out every event that the simulator reports to the observer. + * + * @author Florian Erhard + */ +public class InstantOutputObserver extends Observer { + + private PrintWriter pw; + + /** + * Creates the observer for a given simulator and a given {@link PrintWriter} + * @param sim simulator + * @param pw PrintWriter + */ + public InstantOutputObserver(Simulator sim, PrintWriter pw) { + super(sim); + this.pw = pw; + } + + /** + * Prints event. + */ + @Override + public void activateReaction(int mu, double tau, FireType fireType, int times) { + pw.append("Fired "+getSimulator().getNet().getReactionName(mu)+" at "+tau+" by "+fireType.toString()+"\n"); + pw.flush(); + } + + /** + * Prints event. + */ + @Override + public void finished() { + pw.append("finished\n"); + pw.flush(); + } + + /** + * Prints event. + */ + @Override + public void started() { + pw.append("started\n"); + pw.flush(); + } + + /** + * Prints event. + */ + @Override + public void step() { + pw.append("step\n"); + for (int i=0; i

  • step: check after each step if a interval range has been passed + *
  • theta: register thetas for the interval ranges
  • + * + *

    + * The type of the used method can be set by using {@link IntervalObserver#setThetaMethod(boolean)}. + *

    + * Extending classes just have to implement {@link IntervalObserver#getEntityValue(int)} and to + * pass some indices and names to to constructor. + * + * @author Florian Erhard + * + */ +public abstract class IntervalObserver extends Observer implements GnuPlotObserver{ + + private double recentStep; + private double[][] avgLog = null; + private int[] quality = null; + private boolean plotQuality = false; + private boolean thetaMethod = true; + private double interval; + private String[] entityName; + private LinkedList log; + private int duration; + + + + /** + * Create the observer for a given simulator, a given interval, given indices with names. + * @param sim simulator + * @param interval interval + * @param entityName names of the entities + */ + public IntervalObserver(Simulator sim, double interval, String[] entityName) { + super(sim); + this.interval = interval; + + if (entityName.length==0) + throw new IllegalArgumentException("At least one entity has to be specified!"); + + this.entityName = entityName; + + + log = new LinkedList(); + + avgLog = new double[this.entityName.length+1][0]; + quality = new int[0]; + } + + public IntervalObserver(Simulator sim, double interval, int duration, String[] entityName) { + super(sim); + this.interval = interval; + this.duration = duration; + + if (entityName.length==0) + throw new IllegalArgumentException("At least one entity has to be specified!"); + + this.entityName = entityName; + + + log = new LinkedList(); + + avgLog = new double[this.entityName.length+1][this.duration + 1]; + quality = new int[0]; + } + + /** + * Gets the actual value of the entity. + * + * @param i index of the entity + * @return value of the entity + */ + protected abstract double getEntityValue(int i); + + /** + * Clears the recorded values and registers (if needed) theta + */ + @Override + public void started() { + log.clear(); + if (thetaMethod) + setTheta(0); + recentStep = Double.NEGATIVE_INFINITY; + } + + /** + * Do nothing. + */ + @Override + public void activateReaction(int mu, double tau, FireType fireType, int times) {} + + /** + * Adds the recorded data to the average data pool. Moreover a linear interpolation + * is done to the recorded values in order to guarantee that the time axis matches + * exactly the intervals. If the theta method has been used no interpolation is performed. + */ + @Override + public void finished() { + step(); + if (log.size()==0) return; + + double[][] actLog = getAsArray(log); + + if (!thetaMethod) { + for (int i=actLog.length-1; i>=0; i--) + actLog[i] = NumberTools.interpolateLinear(interval, actLog[0], actLog[i]); + + // workaround: correct last timeindex + if( actLog[0].length>1) + actLog[0][actLog[0].length-1] = actLog[0][actLog[0].length-2]+interval; + } + + double[][] newAvgLog = new double[entityName.length+1][Math.max(avgLog[0].length,actLog[0].length)]; + for (int i=0; i= 1)){ + newAvgLog[i][j] = newAvgLog[i][j-1] + 1; + } + } + } + } + int[] newQuality = new int[Math.max(avgLog[0].length,actLog[0].length)]; + System.arraycopy(quality, 0, newQuality, 0, Math.min(newQuality.length, quality.length)); + for (int i=0; istep method is used, the data is recorded here. + */ + @Override + public void step() { + if (!thetaMethod && (int)(getSimulator().getTime()/interval)>(int)(recentStep/interval)) { + double[] l = new double[entityName.length+1]; + l[0]=getSimulator().getTime(); + for (int i=0; itheta method is used, the data is recorded here. + */ + @Override + public void theta(double theta) { + if (thetaMethod){ + double[] l = new double[entityName.length+1]; + l[0]=theta; + for (int i=0; iGnuPlot object + * @throws IOException if gnuplot could not be accessed + */ + public GnuPlot toGnuplotRecent() throws IOException { + return toGnuplotRecent(new GnuPlot()); + } + + /** + * Passes the recent observer data to a {@link GnuPlot} object. + * Recent means that not the average data is used but only the recently produced. + * + * @param gnuplot the GnuPlot object to pass the data to + * @return the GnuPlot object + * @throws IOException if gnuplot could not be accessed + */ + public GnuPlot toGnuplotRecent(GnuPlot gnuplot) throws IOException { + return toGnuplot(gnuplot, new LinkedList(log)); + } + + /** + * Sets whether or not to plot quality data. If set to true, + * a call to toGnuplot adds not only the values but also one + * column in which the number of experiments (from how many values is the average of + * the regarding row calculated) is + * + * @param plotQuality whether or not to plot qualities + */ + public void setPlotQuality(boolean plotQuality) { + this.plotQuality = plotQuality; + } + + /** + * Gets whether or not to plot quality data. If set to true, + * a call to toGnuplot adds not only the values but also one + * column in which the number of experiments (from how many values is the average of + * the regarding row calculated) is + * + * @return whether or not to plot qualities + */ + public boolean isPlotQuality() { + return plotQuality; + } + + /** + * Gets the last value of the given entity. + * + * @param entityIndex index of the entity + * @return last recorded value + */ + public double getFinalValue(int entityIndex) { + return avgLog[entityIndex+1][avgLog[entityIndex+1].length-1]; + } + + @Override + public String toString() { + String[] names = applyLabelFormat(entityName); + StringBuilder sb = new StringBuilder(); + for (int i=0; i values) throws IOException { + if (gnuplot==null) return null; + String[] names = applyLabelFormat(entityName); + gnuplot.addData(values, names, getStyles()); + return gnuplot; + } + + + private double[][] getAsArray(LinkedList l) { + double[][] re = new double[l.get(0).length][l.size()]; + int i=0; + for (double[] t : l){ + for (int j=0; jstep. It particularly + * makes sense for the approximative leaping algorithms whose steps are + * precisely the leaps and you want to know about amount differences after each leap. + *

    + * This observer does not take repeats into account. If you repeat the simulation, + * you will just get the results of the recent run. + * + * @author Florian Erhard + * + */ +public class LeapObserver extends Observer implements GnuPlotObserver { + + private LinkedList leap; + private int[] species; + private String[] speciesNames; + + /** + * Creates the observer with a given simulator and given species + * @param sim simulator + * @param speciesNames names of the species + */ + public LeapObserver(Simulator sim, String...speciesNames) { + super(sim); + leap = new LinkedList(); + this.species = NetworkTools.getSpeciesIndices(sim.getNet(), speciesNames); + this.speciesNames = speciesNames; + } + + /** + * Do nothing. + */ + @Override + public void activateReaction(int mu, double tau, FireType fireType, int times) {} + + /** + * Do nothing. + */ + @Override + public void finished() {} + + /** + * Clears the recorded data. + */ + @Override + public void started() { + leap.clear(); + } + + /** + * Record the time and amounts of the species. + */ + @Override + public void step() { + double[] l = new double[speciesNames.length+1]; + l[0]=getSimulator().getTime(); + for (int i=0; i(leap), names, getStyles()); + return gnuplot; + } + + /** + * Gets the number of the performed leaps + * + * @return number of leaps. + */ + public int getNumLeaps() { + return leap.size(); + } + + public String[] getStyles() { + return null; + } + + + @Override + public String toString() { + GnuPlot x = new GnuPlot(); + x.addData(leap, null, null); + return x.getData().get(0); + } +} diff --git a/src/main/java/fern/simulation/observer/MultiAmountIntervalObserver.java b/src/main/java/fern/simulation/observer/MultiAmountIntervalObserver.java new file mode 100644 index 00000000..819efc35 --- /dev/null +++ b/src/main/java/fern/simulation/observer/MultiAmountIntervalObserver.java @@ -0,0 +1,73 @@ +/* + * Created on 12.03.2007 + * + * To change the template for this generated file go to + * Window>Preferences>Java>Code Generation>Code and Comments + */ +package fern.simulation.observer; + +import fern.simulation.Simulator; +import fern.tools.NetworkTools; + +/** + * + * Observes amounts of molecule species repeatedly after certain intervals. The amount of the + * given molecules is summed up. + *

    + * This observer does take repeats into account. If you repeat the simulation, + * you will get an average over the results of each run. + * + * @author Florian Erhard + * + */ +public class MultiAmountIntervalObserver extends IntervalObserver { + + private int[] speciesIndices = null; + + /** + * Creates the observer for a given simulator, a given interval and given species indices + * @param sim simulator + * @param interval interval + * @param species species indices + */ + public MultiAmountIntervalObserver(Simulator sim, String presentationName, double interval, int...species) { + super(sim,interval,new String[] {presentationName}); + this.speciesIndices = species; + + } + + /** + * Creates the observer for a given simulator, a given interval and given species names. + * @param sim simulator + * @param interval interval + * @param speciesName species names + */ + public MultiAmountIntervalObserver(Simulator sim, String presentationName, double interval, String...speciesName) { + super(sim,interval,new String[] {presentationName}); + this.speciesIndices = NetworkTools.getSpeciesIndices(sim.getNet(), speciesName); + + } + + /** + * Gets the actual amount of a species. + */ + protected double getEntityValue(int e) { + double sum = 0; + for (int i=0; iPreferences>Java>Code Generation>Code and Comments + */ +package fern.simulation.observer; + +import java.io.PrintWriter; + +import fern.simulation.Simulator; +import fern.simulation.Simulator.FireType; + + +/** + * Implementing classes are used to observe certain aspects of simulations. It is basically + * just an interface of methods that get called during a simulation together with some + * common methods useful for many types of observers. + *

    + * Some observers take repeats into account. If you repeat the simulations, they will + * yield average data. + *

    + * Each observer should override the toString method which should return + * a string representation of its data. + *

    + * You can register a {@link PrintWriter} to the Observer. If you have, the + * return value of toString is printed if a simulation has finished. + * + * + * @author Florian Erhard + * + */ +public abstract class Observer { + + private Simulator simulator; + private String labelFormat = "%s"; + private PrintWriter pw = null; + private int numSimulations = 0; + + /** + * Contains the theta for this observer. + * + */ + private double theta = Double.POSITIVE_INFINITY; + + /** + * Creates an observer dedicated to one simulator. The observer is NOT registered at the + * simulator, you have to call {@link Simulator#addObserver(Observer)} in order to do this. + * + * @param sim the simulator + */ + public Observer(Simulator sim) { + this.simulator = sim; + } + + /** + * Gets called when the simulation has started after the initialization and before + * the termination condition is checked the first time. + */ + public abstract void started(); + /** + * Gets called after each termination check and before {@link Simulator#performStep(fern.simulation.controller.SimulationController)} + * is called. + */ + public abstract void step(); + /** + * Gets called when a simulation has finished, directly after the termination check. + */ + public abstract void finished(); + /** + * Gets called by simulators when a certain moment in time is reached. This moment in + * time has to be registered by {@link Observer#getTheta()} + * + * @param theta moment in time + */ + public abstract void theta(double theta); + /** + * Gets called before a reaction fires. + * @param mu the reaction which is supposed to fire + * @param tau the time the reaction fires (at this time {@link Simulator#getTime()} does not necessarily yield the firing time) + * @param fireType the type of the firing + * @param times TODO + */ + public abstract void activateReaction(int mu, double tau, FireType fireType, int times); + /** + * Gets called after the finish call and prints the results of this + * observer if a {@link PrintWriter} is registered. + */ + public void print() { + if (pw!=null) { + pw.append(toString()); + pw.append("\n"); + pw.flush(); + } + numSimulations++; + } + + /** + * Gets the moment in time, where the simulator has to invoke {@link Observer#theta(double)}. + * + * @return theta + */ + public double getTheta() { + return theta; + } + + /** + * Sets the moment in time, where the simulator has to invoke {@link Observer#theta(double)}. + * + * @param theta the theta + */ + public void setTheta(double theta) { + this.theta = Math.min(this.theta,theta); + getSimulator().registerNewTheta(this,theta); + } + + /** + * Gets the registered {@link PrintWriter} + * @return the PrintWriter + */ + public PrintWriter getPrintWriter() { + return pw; + } + + /** + * Registers a {@link PrintWriter} + * @param printWriter the PrintWriter + */ + public void setPrintWriter(PrintWriter printWriter) { + this.pw = printWriter; + } + + + /** + * Sets the label format for {@link Observer#getLabel(String)}. + * + * @param labelFormat the label format + * + * @see Observer#getLabel(String) + */ + public void setLabelFormat(String labelFormat) { + this.labelFormat = labelFormat; + } + + /** + * Gets the label format of {@link Observer#getLabel(String)}. + * + * @return labelFormat the label format + * + * @see Observer#getLabel(String) + */ + public String getLabelFormat() { + return labelFormat; + } + + /** + * Applies the actual label format to the whole array (but does not change the + * passed array, it return a new one) + * + * @param name array of labels + * @return array of formatted labels + */ + protected String[] applyLabelFormat(String[] name) { + String[] re = new String[name.length]; + for (int i=0; i

  • %l is replaced by the passed argument
  • + *
  • %a is replaced by the simulator's name
  • + *
  • %n is replaced by the network's name
  • + * + * + * @param label label to format + * @return formatted label + */ + protected String getLabel(String label) { + String format = labelFormat.replace("%l", "%1$s").replace("%a", "%2$s").replace("%n", "%3$s"); + return String.format(format, label, simulator.getName(), simulator.getNet().getName()); + } + + /** + * Gets the simulator + * @return simulator + */ + public Simulator getSimulator() { + return simulator; + } + + /** + * Sets the simulator. For internal use only. If you want to override it, be careful + * with the consistency between the simulator's observer list and the observer's simulator! + * + * @param simulator the simulator + */ + protected void setSimulator(Simulator simulator) { + this.simulator = simulator; + } + + /** + * Gets the number of finished repeats of the simulation. The number is increased + * after the finished call, so within finish of an extending + * class it is the number of repeats without the actual simulation. + * + * @return number of repeats + */ + public int getNumSimulations() { + return numSimulations; + } + +} diff --git a/src/main/java/fern/simulation/observer/RandomNumberGeneratorCallObserver.java b/src/main/java/fern/simulation/observer/RandomNumberGeneratorCallObserver.java new file mode 100644 index 00000000..012254f1 --- /dev/null +++ b/src/main/java/fern/simulation/observer/RandomNumberGeneratorCallObserver.java @@ -0,0 +1,116 @@ +package fern.simulation.observer; + +import java.util.HashSet; +import java.util.Set; + +import fern.simulation.Simulator; +import fern.simulation.Simulator.FireType; +import fern.tools.NumberTools; +import fern.tools.Stochastics; +import fern.tools.gnuplot.GnuPlot; + +/** + * Observes the calls to the random number generator and count the number of drawn + * random number of different distributions. These calls are crucial for the stochastic + * algorithms because besides algebraic calculations are these the most time + * consuming operations. + *

    + * This observer does take repeats into account. If you repeat the simulation, + * you will get an average over the results each run. + * + * @author Florian Erhard + * @see Stochastics + */ +public class RandomNumberGeneratorCallObserver extends Observer implements GnuPlotObserver { + + private double[] numCalls = null; + private Set addedTitles; + + /** + * Creates the observer for the given simulator. + * @param sim simulator + */ + public RandomNumberGeneratorCallObserver(Simulator sim) { + super(sim); + Stochastics.getInstance().setCountGenerations(true); + addedTitles = new HashSet(); + } + + /** + * Do nothing. + */ + @Override + public void activateReaction(int mu, double tau, FireType fireType, int times) {} + + /** + * Calculates the average. + */ + @Override + public void finished() { + if (numCalls==null) numCalls = NumberTools.convertIntToDouble(Stochastics.getInstance().getCounts()); + else { + int[] act = Stochastics.getInstance().getCounts(); + for (int i=0; i + * This observer does take repeats into account. If you repeat the simulation, + * you will get an average over the results of each run. + * + * @author Florian Erhard + * + */ +public class ReactionIntervalObserver extends IntervalObserver { + + private int[] observeReactions; + private Map reactionIndexToObserverIndex; + private double recordStart = 0; + + /** + * Creates the observer for a given simulator, a given interval and given neighbors. + * @param sim simulator + * @param interval interval + * @param speciesNames the names of the species, each neighboring reaction of any of these is added + */ + public ReactionIntervalObserver(Simulator sim, double interval, String... speciesNames) { + this(sim,interval,NetworkTools.getReactionsOf(sim.getNet(),speciesNames)); + } + + /** + * Creates the observer for a given simulator, a given interval and given reaction indices. + * @param sim simulator + * @param interval interval + * @param reactions reaction indices + */ + public ReactionIntervalObserver(Simulator sim, double interval, int... reactions) { + super(sim, interval, NetworkTools.getReactionNames(sim.getNet(),reactions)); + + this.reactionIndexToObserverIndex = NumberTools.createInverseAsMap(reactions); + this.observeReactions = new int[reactions.length]; + } + + /** + * Record the firing of mu, if mu is registered. + */ + @Override + public void activateReaction(int mu, double t, FireType fireType, int times) { + if (recordStart1) return colors[colors.length-1]; + + int leftIndex = (int) Math.floor((colors.length-1)*val); + int rightIndex = (int) Math.ceil((colors.length-1)*val); + + if (leftIndex==rightIndex) + return colors[leftIndex]; + + val = (val-(float)leftIndex/(float)(colors.length-1))*(colors.length-1); + + return new Color( + colors[leftIndex].getRed()/255f*(1-val)+colors[rightIndex].getRed()/255f*val, + colors[leftIndex].getGreen()/255f*(1-val)+colors[rightIndex].getGreen()/255f*val, + colors[leftIndex].getBlue()/255f*(1-val)+colors[rightIndex].getBlue()/255f*val + ); + } + + + +} diff --git a/src/main/java/fern/tools/ConfigReader.java b/src/main/java/fern/tools/ConfigReader.java new file mode 100644 index 00000000..0adcb8fc --- /dev/null +++ b/src/main/java/fern/tools/ConfigReader.java @@ -0,0 +1,99 @@ +/* + * Created on 05.10.2006 + * + * To change the template for this generated file go to + * Window>Preferences>Java>Code Generation>Code and Comments + */ +package fern.tools; + +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; +import java.util.HashMap; + +/** + * + * Reads simple config files for test cases and makes the data of it accessible. + *

    + * The file has to contain lines like
    field=value + *

    + * If a line starts with // or # it is ignored. + * + * @author Florian Erhard + * + */ +public class ConfigReader { + + private HashMap config; + + /** + * Reads the given file and stores the data. + * + * @param fn config file + * + * @throws IOException + */ + public ConfigReader(String fn) throws IOException { + config = new HashMap(); + + BufferedReader bf = new BufferedReader(new FileReader(fn)); + String line; + while ((line = bf.readLine()) != null) { + line = line.trim(); + if (line.startsWith("//") || line.startsWith("#")) + line = ""; + + if (line.length()>0) + parseLine(line); + + } + } + + private void parseLine(String line) { + String key = line.substring(0,line.indexOf('=')); + String value = line.substring(line.indexOf('=')+1); + + config.put(key,value); + } + + /** + * Gets the value of the line key=value as string + * + * @param key name of the field + * @return value + */ + public String getAsString(String key) { + return config.get(key); + } + + /** + * Gets the value of the line key=value as string array (the value is simply splitted by ,) + * + * @param key name of the field + * @return value + */ + public String[] getAsStringArr(String key) { + return config.get(key).split(","); + } + + /** + * Gets the value of the line key=value as double + * + * @param key name of the field + * @return value + */ + public double getAsDouble(String key) { + return Double.parseDouble(config.get(key)); + } + + /** + * Gets the value of the line key=value as int + * + * @param key name of the field + * @return value + */ + public int getAsInt(String key) { + return Integer.parseInt(config.get(key)); + } + +} diff --git a/src/main/java/fern/tools/NetworkTools.java b/src/main/java/fern/tools/NetworkTools.java new file mode 100644 index 00000000..9f9f80c2 --- /dev/null +++ b/src/main/java/fern/tools/NetworkTools.java @@ -0,0 +1,355 @@ +package fern.tools; + + +import java.io.File; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.Writer; + +import org.jdom.JDOMException; + +import cern.colt.bitvector.BitVector; +import fern.network.AbstractKineticConstantPropensityCalculator; +import fern.network.AnnotationManager; +import fern.network.FeatureNotSupportedException; +import fern.network.KineticConstantPropensityCalculator; +import fern.network.Network; +import fern.network.NetworkLoader; +import fern.network.sbml.MathTree; +import fern.simulation.Simulator; +import fern.simulation.algorithm.GillespieSimple; +import org.sbml.jsbml.ASTNode; + +/** + * Contains various helper methods dealing with the {@link Network} interface. + * + * @author Florian Erhard + * + */ +public class NetworkTools { + + /** + * Gets the reaction rate constant by setting the reactant amounts to the stoichiometric + * coefficient. + * + * @param net network + * @param r reaction index + * @return reaction rate constant + */ + public static double getConstantBySettingReactantsToStoich(Network net, int r) { + int[] reactants = net.getReactants(r); + int[] stoich = new int[net.getNumSpecies()]; + for (int i=0; i0) + sb.deleteCharAt(sb.length()-1); + return sb.toString(); + } + + /** + * Gets a string representation of the given reactions and the amounts of each participating species in parentheses. + * + * @param net network + * @param reactions reaction indices + * @return reaction string representation with amounts of participating species + */ + public static String getReactionNameWithAmounts(Network net, int... reactions) { + StringBuilder sb = new StringBuilder(); + for (int reaction : reactions) { + for (int i : net.getReactants(reaction)) + sb.append(getSpeciesNameWithAmount(net,i)+"+"); + sb.deleteCharAt(sb.length()-1); + sb.append("->"); + for (int i : net.getProducts(reaction)) + sb.append(getSpeciesNameWithAmount(net, i)+"+"); + sb.deleteCharAt(sb.length()-1); + sb.append("\n"); + } + if (sb.length()>0) + sb.deleteCharAt(sb.length()-1); + return sb.toString(); + } + + + /** + * Transforms the reaction indices in the given array to the corresponding names. + * + * @param net the network + * @param reaction reaction indices + * @return names of the reactions + */ + public static String[] getReactionNames(Network net, int[] reaction) { + String[] re = new String[reaction.length]; + for (int i=0; i l) { + int max = Integer.MIN_VALUE; + for (int i : l) + max = Math.max(max, i); + return max; + } + + /** + * Gets the minimal value within the given {@link Iterable}. + * + * @param l the iterable + * @return the minimal number + */ + public static int min(Iterable l) { + int min = Integer.MAX_VALUE; + for (int i : l) + min = Math.min(min, i); + return min; + } + + /** + * Gets the argmax of the given map. The argmax is the key whose + * value is the maximum within the values. + * + * @param l map + * @return argmax(map) + */ + public static int argMax(Map l) { + int max = Integer.MIN_VALUE; + int arg = 0; + for (Integer key : l.keySet()) { + if (l.get(key)>max) { + max = l.get(key); + arg = key; + } + } + return arg; + } + + /** + * Gets the sum of the values in the array. + * + * @param l the array + * @return sum of the values + */ + public static int sum(int[] l) { + int sum = 0; + for (int i=0; i list) { + int[] re = new int[list.size()]; + int index = 0; + for (Integer i : list) + re[index++] = i.intValue(); + return re; + } + + + /** + * Copies the values of the given collection and unboxes them to an array. + * + * @param list collection + * @return array with the same values + */ + public static double[] toDoubleArray(Collection list) { + double[] re = new double[list.size()]; + int index = 0; + for (Double i : list) + re[index++] = i.doubleValue(); + return re; + } + + /** + * Creates the inverse array to the given array. In the inverse array a' of a + * following condition holds: + *

    + * a[i]=j <=> a'[j]=i + *

    + * Be careful with sparse arrays, the inverse array could be very large (prefer + * {@link NumberTools#createInverseAsMap(int[])}. It should preferably be used + * with bijective arrays. + * + * @param a the array + * @return the inverse + */ + public static int[] createInverse(int[] a) { + int max = 0; + for (int i=0; i + * a[i]=j <=> a'.get(j)=i + * + * + * @param a the array + * @return the inverse map + */ + public static Map createInverseAsMap(int[] a) { + Map re = new HashMap(); + for (int i=0; i data, int numBins, int... indices) { + double min = Double.POSITIVE_INFINITY; + double max = Double.NEGATIVE_INFINITY; + for (double[] d : data) { + if (indices.length>0) + for (int index : indices) { + min = Math.min(min, d[index]); + max = Math.max(max, d[index]); + } + else + for (int index=0; index0?indices.length+1:data.iterator().next().length+1]; + for (int i=0; i0) + for (int i=0; i createHistogramAsMap(int[] a) { + Map re = new HashMap(); + if (a==null || a.length==0) return re; + + for (int i=0; i loadHistogram. + * + * @param histo the histogram to save + * @param file the file + * + * @throws IOException + */ + public static void saveHistogram(Map histo, File file) throws IOException { + FileWriter fw = new FileWriter(file); + fw.write(getHistogramAsString(histo)); + fw.close(); + } + + /** + * Reads a previously saved histogram from a file. + * + * @param file the file + * @return the histogram + * + * @throws IOException + */ + public static Map loadHistogram(File file) throws IOException { + BufferedReader bf = new BufferedReader(new FileReader(file)); + Map re = new HashMap(); + String line; + while((line=bf.readLine())!=null) { + String[] vals = line.split("\t"); + if (vals.length!=2) + throw new IOException("Illegal file format"); + re.put(Integer.parseInt(vals[0]),Integer.parseInt(vals[1])); + } + return re; + } + + + /** + * Gets a string representation of the histogram map. + * @param h histogram + * @return string representation + */ + public static String getHistogramAsString(Map h) { + StringBuilder sb = new StringBuilder(); + int min = Integer.MAX_VALUE; + int max = Integer.MIN_VALUE; + for (int i : h.keySet()) { + min = Math.min(min, i); + max = Math.max(max, i); + } + + for (int i=min; i<=max; i++) { + sb.append(i+"\t"+(h.containsKey(i)?h.get(i):0)+"\n"); + } + return sb.toString(); + } + + /** + * Gets the content of the given array as {@link BitVector}, which means, that + * the BitVector will have a size equal to the maximal value in the + * array and contains a 1 for each element which is contained at least once in the array + * + * @param a array + * @return BitVector> for the array + */ + public static BitVector getContentAsBitVector(int[] a) { + int max = a[0]; + for (int i=1; iBitVector + * @return array with the set indices + */ + public static int[] getContentAsArray(BitVector bv) { + int[] re = new int[bv.cardinality()]; + + int bvIndex = 0; + for (int i=0; i + * For reference see Cao & Petzold, Accuracy limitations and the measurement of errors in + * the stochastic simulation of chemically reacting systems, Journal of Computational Physics 212 (2006) 6�24 + * + * @param h1 first histogram + * @param h2 second histogram + * @return histogram distance + */ + public static double calculateHistogramDistance(Map h1, Map h2) { + int min = Integer.MAX_VALUE; + int max = Integer.MIN_VALUE; + double s1 = 0; + double s2 = 0; + + for (int i : h1.keySet()) { + min = Math.min(min, i); + max = Math.max(max, i); + s1+=h1.get(i); + } + for (int i : h2.keySet()) { + min = Math.min(min, i); + max = Math.max(max, i); + s2+=h2.get(i); + } + + + + double sum = 0; + for (int i=min; i<=max; i++) { + sum+=Math.abs((h1.containsKey(i)?h1.get(i):0)/s1-(h2.containsKey(i)?h2.get(i):0)/s2); + } + return sum; + } + + /** + * Gets the avg of the array + * @param a array + * @return avg(array) + */ + public static double avg(double[] a) { + double s = 0; + for (double d : a) + s+=d; + return s/a.length; + } + + /** + * Gets the standard deviation of the array + * @param a array + * @return stddev(array) + */ + public static double stddev(double[] a) { + double avg = avg(a); + double s = 0; + for (double d : a) + s+=(d-avg)*(d-avg); + return Math.sqrt(s/(a.length-1)); + } + + /** + * Inverts the given array in place and returns it. + * @param a array + * @return inverted array + */ + public static String[] inverse(String[] a) { + String d; + for (int i=0; iMath.abs(desiredTime-time[j+1])) + j++; + + int a,b; + if (time[j]0) + b--; + } + + if (a==b || time[a]afterTime) + throw new IllegalArgumentException("Cannot interpolate "+desiredTime+" in ["+beforeTime+":"+afterTime+"]"); + + double b = desiredTime-beforeTime; + double a = afterTime-desiredTime; + return beforeValue*a/(a+b)+afterValue*b/(a+b); + } + + private static int getIntervalIndex(double time, double interval) { + return (int) Math.round(time/interval); + } + + +} diff --git a/src/main/java/fern/tools/Stochastics.java b/src/main/java/fern/tools/Stochastics.java new file mode 100644 index 00000000..db14afc7 --- /dev/null +++ b/src/main/java/fern/tools/Stochastics.java @@ -0,0 +1,249 @@ +/* + * Created on 12.03.2007 + * + * To change the template for this generated file go to + * Window>Preferences>Java>Code Generation>Code and Comments + */ +package fern.tools; + +import java.util.Date; + +import cern.jet.random.Binomial; +import cern.jet.random.Exponential; +import cern.jet.random.Normal; +import cern.jet.random.Poisson; +import cern.jet.random.Uniform; +import cern.jet.random.engine.MersenneTwister; + +/** + * + * Manages a random number generators for various distributions. By only using this class for every + * random number drawing in the whole framework, some advantages emerge: + *

    • it is guaranteed that the most quickest possible generator is used for each drawing
    • + *
    • one can derandomize the algorithms by using {@link Stochastics#setSeed(Date)}
    • + *
    • the number of random number generations can easily be counted
    + * + * @author Florian Erhard + * + */ +public class Stochastics { + + + private static Stochastics inst = null; + /** + * Singleton pattern method. + * @return the singleton object + */ + public static Stochastics getInstance() { + if (inst==null) inst = new Stochastics(); + return inst; + } + + private Date seed = null; + private Uniform unif = null; + private Exponential exponential = null; + private Binomial binom = null; + private Poisson poisson = null; + private Normal normal = null; + private int unifCount = 0; + private int exponentialCount = 0; + private int binomCount = 0; + private int poissonCount = 0; + private int normalCount = 0; + + + private boolean countGenerations = false; + + private Stochastics() { + resetSeed(); + } + + /** + * Sets the seed to the current date + */ + public void resetSeed() { + setSeed(new Date()); + } + + /** + * Gets the actual seed of the random number generator. + * + * @return seed + */ + public long getSeed() { + return seed.getTime(); + } + + /** + * Sets a new seed for the random number generator. + * + * @param seed the seed + */ + public void setSeed(long seed) { + setSeed(new Date(seed)); + } + + /** + * Sets a new seed for the random number generator. + * + * @param seed the seed + */ + public void setSeed(Date seed) { + unif = new Uniform(new MersenneTwister(seed)); + exponential = new Exponential(0, new MersenneTwister(seed)); + binom = new Binomial(10,0.5,new MersenneTwister(seed)); + poisson = new Poisson(1,new MersenneTwister(seed)); + normal = new Normal(0,1,new MersenneTwister(seed)); + this.seed = seed; + } + + + + /** + * Gets whether or not to count the number of random number generations + * + * @return whether or not to count + */ + public boolean isCountGenerations() { + return countGenerations; + } + + + /** + * Sets whether or not to count the number of random number generations + * + * @param countGenerations whether or not to count + */ + public void setCountGenerations(boolean countGenerations) { + this.countGenerations = countGenerations; + } + + + /** + * Gets the number of random number generations for each distribution (same order as in + * {@link Stochastics#getNames()} since the last call of resetCounts. + * + * @return number of random number generations + */ + public int[] getCounts() { + return new int[] {unifCount, binomCount,exponentialCount,normalCount,poissonCount}; + } + + /** + * Gets the names of the built-in distributions. + * + * @return names of the distributions + */ + public String[] getNames() { + return new String[] {"Uniform", "Binomial","Exponential","Normal","Poisson"}; + } + + /** + * Resets the counts for each distribution to zero. + */ + public void resetCounts() { + unifCount = binomCount = exponentialCount = normalCount = poissonCount = 0; + } + + /** + * Gets a random number from the uniform distribution between 0 and 1. + * + * @return random number between 0 and 1 + * + * @see Uniform#nextDouble() + */ + public double getUnif() { + if (countGenerations) unifCount++; + return unif.nextDouble(); + } + + /** + * Gets a random number from the exponential distribution. + * + * @param d mean + * @return random number + * + * @see Exponential#nextDouble() + */ + public double getExponential(double d) { + if (Double.isInfinite(d)) return d; + if (countGenerations) exponentialCount++; + + return exponential.nextDouble(d); + } + + /** + * Gets a random number from the binomial distribution. + * + * @param i size + * @param prob probability + * @return random number + * + * @see Binomial#nextInt(int, double) + */ + public int getBinom(int i, double prob) { + if (countGenerations) binomCount++; + if (prob==0 || i==0) + return 0; + else if (prob==1) + return i; + else + return binom.nextInt(i, prob); + } + + /** + * Gets a uniformly chosen random number between min (inclusive) and max (exclusive) + * + * @param min inclusive minimum + * @param max exclusive maximum + * @return uniformly chosen random number + * + * @see Uniform#nextIntFromTo(int, int) + */ + public int getUnif(int min, int max) { + if (countGenerations) unifCount++; + return unif.nextIntFromTo(min, max-1); + } + + /** + * Gets a random number from the Poisson distribution. + * + * @param mean mean + * @return random number + * + * @see Poisson#nextInt(double) + */ + public int getPoisson(double mean) { + if (mean==0) return 0; + if (countGenerations) poissonCount++; + return poisson.nextInt(mean); + } + + /** + * Gets a random number from the Normal distribution + * + * @return random number + * + * @see Normal#nextDouble() + */ + public double getNormal() { + if (countGenerations) normalCount++; + return normal.nextDouble(); + } + + /** + * Gets a random number from the Normal distribution with given mean and stddev. + * + * @param mean the mean + * @param stddev the stddev + * @return random number + * + * @see Normal#nextDouble(double, double) + */ + public double getNormal(double mean, double stddev) { + if (countGenerations) normalCount++; + return normal.nextDouble(mean,stddev); + } + + +} diff --git a/src/main/java/fern/tools/functions/Probability.java b/src/main/java/fern/tools/functions/Probability.java new file mode 100644 index 00000000..231f6a5d --- /dev/null +++ b/src/main/java/fern/tools/functions/Probability.java @@ -0,0 +1,65 @@ +package fern.tools.functions; + +/** + * + * Function delegate for conditional probabilities. + * + * @author Florian Erhard + * + */ +public interface Probability { + + /** + * Gets the probability depending on two integers. + * + * @param l1 interger 1 + * @param l2 integer 2 + * @return probability + */ + public double getProb(int l1, int l2); + + /** + * Implementation that yields a constant (and hence independent) + * probability. + * + * @author Florian Erhard + * + */ + public static class Constant implements Probability { + private double p; + public Constant(double p) { + this.p = p; + } + public double getProb(int l1, int l2) { + return p; + } + } + + /** + * + * Implementation for the reaction probability for the autocatalytic network creation. + * The probability is calculated by the formula + *

    + * factor / max(l1,l2) + *

    + * if + * l1+l2 > oneToLength, else 1. + * + * @author Florian Erhard + * + */ + public static class ReactionProbability implements Probability { + + private double factor; + private int oneToLength; + + public ReactionProbability(double factor, int oneToLength){ + this.factor = factor; this.oneToLength = oneToLength; + } + + public double getProb(int l1, int l2) { + return l1+l2<=oneToLength ? 1 : factor / Math.max(l1,l2); + } + + } +} diff --git a/src/main/java/fern/tools/gnuplot/ArrayMatrixAxes.java b/src/main/java/fern/tools/gnuplot/ArrayMatrixAxes.java new file mode 100644 index 00000000..9df77ce2 --- /dev/null +++ b/src/main/java/fern/tools/gnuplot/ArrayMatrixAxes.java @@ -0,0 +1,113 @@ +package fern.tools.gnuplot; + +import java.lang.reflect.Array; +import java.util.Iterator; + +/** + * Implementation of {@link Axes} to use with array matrixes + * of any number type (the type of the arrays is inferred by + * using the reflection api). An array matrix is just a two dimensional + * rectangular array (new double[3][20]). The first index + * of the matrix gives the row, the second the column (3 rows and 20 columns). + *

    + * If your array matrix is transposed (your first index denotes the column, the second + * one the row), just use {@link TransposedArrayMatrixAxes}. + * + * @author Florian Erhard + * @see Axes + */ +public class ArrayMatrixAxes extends Axes { + + /** + * Contains the matrix array + */ + protected Object array; + + /** + * Create a new Axes object containing the given array matrix + * without labels / styles. If the passed object is not a valid array matrix, + * an {@link IllegalArgumentException} will be thrown. + * + * @param matrix array matrix + */ + public ArrayMatrixAxes(Object matrix) { + this(matrix,null,null); + } + + /** + * Create a new Axes object containing the given array matrix + * with the given labels /styles (either can be null). + * If the passed object is not a valid array matrix, + * an {@link IllegalArgumentException} will be thrown. + * + * @param matrix the array matrix + * @param labels the labels + * @param styles the styles + */ + public ArrayMatrixAxes(Object matrix, String[] labels, String[] styles) { + super(); + this.array = matrix; + getNumColumns(); + getNumRows(); + checkMatrix(); + + loadLabelsAndLineStyles(labels,styles); + } + + /** + * Checks if the passed object is a valid array matrix. + */ + protected void checkMatrix() { + int cols = Array.getLength(Array.get(array, 0)); + for (int i=0; i iterator() { + return new Iterator() { + + @SuppressWarnings("unchecked") + int index = 0; + Iterator itAdd = getAdditionalAxesIterator(); + + public boolean hasNext() { + return index0) sb.deleteCharAt(sb.length()-1); + return sb.toString() + s; + + } + + public void remove() { } + + }; + } + +} diff --git a/src/main/java/fern/tools/gnuplot/Axes.java b/src/main/java/fern/tools/gnuplot/Axes.java new file mode 100644 index 00000000..aa823544 --- /dev/null +++ b/src/main/java/fern/tools/gnuplot/Axes.java @@ -0,0 +1,327 @@ +package fern.tools.gnuplot; + +import java.util.Collection; +import java.util.Iterator; +import java.util.LinkedList; + + +/** + * + * Contains the data columns for {@link GnuPlot}. GnuPlot has a list of + * Axes objects and assumes that each of these Axes object has one + * x column (the first one), optionally one y column and n value columns. + *

    + * The main access point to the data is the {@link Iterable} interface which yields + * the tab separated values of each columns row by row. + *

    + * It is possible to add other Axes object to an Axes object. So + * If you call the {@link Axes#iterator()}, all of the columns of each attached Axes + * object will be yielded. Hence attached Axes objects must have the + * same number of rows (if they don't, an {@link IllegalArgumentException} will be thrown). + *

    + * This class also manages labels and styles for each column. If you specify either of them, + * then either the length must be equal to the number of columns or 1 shorter (then the + * Axes objects knows that its first column is an x column). + *

    + * The content of labels is directly passed to the plot command as title "label", + * the content of styles also is attached to the corresponding place in the plot + * command (e.g. styles[i]="with linespoints"). + * + * @author Florian Erhard + * + */ +public abstract class Axes implements Iterable { + + public static final int TwoD = 0; + public static final int ThreeD = 1; + public static final int Additional = 2; + + private Collection additionalAxes = null; + private String[] labels = null; + private String[] styles = null; + private boolean hasXAxis; + private boolean hasYAxis; + + public Axes() { + additionalAxes = new LinkedList(); + } + + /** + * Adds new labels and styles to the axes object. If either of them is not null + * then the length must be equal to the number of columns or 1 shorter. + * + * @param labels labels for the columns + * @param styles styles for the columns + */ + protected void loadLabelsAndLineStyles(String[] labels, String[] styles) { + int numLabels = labels==null ? 0 : labels.length; + int dif = getNumColumns()-numLabels; + + if (labels!=null) { + if (dif>=0 && dif<=2) + this.labels = labels; + else + throw new IllegalArgumentException("Length of labels is not equal to the number of columns"); + } + else + this.labels = new String[getNumColumns()]; + + if (styles!=null) { + if (styles.length==this.labels.length) + this.styles = styles; + else + throw new IllegalArgumentException("Length of styles is not equal to the number of labels"); + } + else + this.styles = new String[this.labels.length]; + + hasXAxis = dif>=1; + hasYAxis = dif==2; + } + + /** + * Gets if this Axes object contains 2 or 3 dimensional data. If it is an additional axes object of another, + * it does not have a dimension. The dimension is infered by inspecting the number of labels and styles given. + * + * @see Axes#TwoD + * @see Axes#ThreeD + * @see Axes#Additional + * @return + */ + public int getDimensionType() { + if (hasXAxis && hasYAxis) + return ThreeD; + else if (hasXAxis) + return TwoD; + else + return Additional; + } + + /** + * Attaches an Axes object to this one. It cannot have an Axes + * object with an x axis (which means that the labels/styles array is 1 shorter then the number + * of columns). + *

    + * Additionally the numbers of rows must be equal. + * + * @param axes the Axes object to attach + */ + public void addAxes(Axes axes) { + if (axes.hasXAxis || axes.hasYAxis) + throw new IllegalArgumentException("You cannot add an axes object with a x axis to another axes object!"); + if (getNumRows()!=axes.getNumRows()) + throw new IllegalArgumentException("Number of rows is not equal!"); + additionalAxes.add(axes); + + } + + /** + * Gets the number of columns. The number of the attached Axes + * object is also included. + * + * @return number of columns. + */ + public abstract int getNumColumns(); + + /** + * Gets the number of rows. + * + * @return number of rows. + */ + public abstract int getNumRows(); + + /** + * Gets the entry of this axes at the specified position. + * @param row the row of the entry + * @param col the col of the entry + * @return the entry + */ + protected abstract Number getNumber_internal(int row, int col); + + public Number getX(int row) { + if (hasXAxis) + return getNumber(row,-getNumLabelAxes()); + else + throw new RuntimeException("This axes object does not have an x axis!"); + } + + + /** + * Gets the entry of this axes at the specified position. + * @param row the row of the entry + * @param col the col of the entry + * @return the entry + */ + public Number getNumber(int row, int col) { + col+=getNumLabelAxes(); + return getNumber_internal(row, col); + } + + /** + * Gets the number of label axes (e.g. =2 if this object has a x and a y axis). + * @return + */ + protected int getNumLabelAxes() { + int re = 0; + if (hasXAxis) + re++; + if (hasYAxis) + re++; + return re; + } + + /** + * Sets the label for a column. If this Axes object has a x axis, the label + * of the 0th column cannot be set (because it is the x axis). + * + * @param col zero based index of the column + * @param label label for the column + */ + public void setLabel(int col, String label) { + col-=getNumLabelAxes(); + int column = col; + if (col>=labels.length) { + col-=labels.length; + for (Axes a : additionalAxes){ + if (colAxes object has a x axis, the label + * of the 0th column cannot be retrieved (because it is the x axis). + * + * @param col zero based index of the column + * @return label for the column + */ + public String getLabel(int col) { + if (hasXAxis) col--; + if (hasYAxis) col--; + int column = col; + if (col>=labels.length) { + col-=labels.length; + for (Axes a : additionalAxes){ + if (colAxes object has a x axis, the style + * of the 0th column cannot be set (because it is the x axis). + * + * @param col zero based index of the column + * @param style style for the column + */ + public void setStyle(int col, String style) { + if (hasXAxis) col--; + if (hasYAxis) col--; + int column = col; + if (col>=styles.length) { + col-=styles.length; + for (Axes a : additionalAxes){ + if (colAxes object has a x axis, the style + * of the 0th column cannot be retrieved (because it is the x axis). + * + * @param col zero based index of the column + * style style for the column + */ + public String getStyle(int col) { + if (hasXAxis) col--; + if (hasYAxis) col--; + int column = col; + if (col>=styles.length) { + col-=styles.length; + for (Axes a : additionalAxes){ + if (colAxes objects. + * + * @return number of attached columns + */ + protected int getNumAdditionalColumns() { + int re = 0; + for (Axes a : additionalAxes) + re+=a.getNumColumns(); + return re; + } + + /** + * Iterator for the attached Axes objects. + * + * @return iterator + */ + @SuppressWarnings("unchecked") + protected Iterator getAdditionalAxesIterator() { + final Iterator[] it = new Iterator[additionalAxes.size()]; + int index = 0; + for (Axes a : additionalAxes) it[index++] = a.iterator(); + return new Iterator() { + + public boolean hasNext() { + for (int i=0; iAxes object containing the given collection without labels /styles. + * + * @param collection the collection + */ + public CollectionAxes(Collection collection) { + this(collection,null,null); + } + + /** + * Create a new Axes object containing a collection (which is copied from + * the given iterable) without labels /styles. + * + * @param iterable the iterable + */ + public CollectionAxes(Iterable iterable) { + this(iterable,null,null); + } + + /** + * Create a new Axes object containing the given collection + * with the given labels /styles (either can be null). + * + * @param collection the collection + * @param labels labels for each column + * @param styles styles for each column + */ + public CollectionAxes(Collection collection,String[] labels, String[] styles) { + super(); + this.collection = collection; + checkCollection(); + loadLabelsAndLineStyles(labels, styles); + } + + /** + * Create a new Axes object containing a collection (which is copied from + * the given iterable) with the given labels /styles (either can be null). + * + * @param iterable the iterable + * @param labels labels for each column + * @param styles styles for each column + */ + public CollectionAxes(Iterable iterable, String[] labels, String[] styles) { + super(); + this.collection = new LinkedList(); + for (Object o : iterable) + collection.add(o); + checkCollection(); + loadLabelsAndLineStyles(labels, styles); + } + + private void checkCollection() { + if (collection.size()==0) return; + Object o = collection.iterator().next(); + if (o instanceof Number) return; + try { + if (!(Array.get(o, 0) instanceof Number)) + throw new Exception(); + } catch (Exception e) { + throw new IllegalArgumentException(o.toString()+" is not a number nor an array of numbers!"); + } + // check if arrays in collection have same size + int cols = getNumColumns(); + for (Object o2 : collection) + if (Array.getLength(o2)!=cols) + throw new IllegalArgumentException("The arrays in the collection do not have the same length!"); + } + + /** + * Yields the tab separated columns row by row. + */ + public Iterator iterator() { + return new Iterator() { + + @SuppressWarnings("unchecked") + Iterator it = collection.iterator(); + Iterator itAdd = getAdditionalAxesIterator(); + + public boolean hasNext() { + return it.hasNext(); + } + + public String next() { + Object o = it.next(); + String s = itAdd.hasNext() ? itAdd.next() : ""; + + if (o instanceof Number) + return ((Number)o).toString()+s; + else { + StringBuilder sb = new StringBuilder(); + for (int i=0; i0) sb.deleteCharAt(sb.length()-1); + return sb.toString() + s ; + } + } + + public void remove() { } + + }; + } + + + + + @Override + public int getNumColumns() { + if (collection.size()==0) return 0; + Object o = collection.iterator().next(); + if (o instanceof Number) return 1+getNumAdditionalColumns(); + else return Array.getLength(o)+getNumAdditionalColumns(); + } + + + + @Override + public int getNumRows() { + return collection.size(); + } + + @Override + protected Number getNumber_internal(int row, int col) { + if (row>=getNumRows()) + throw new IllegalArgumentException("Axes does not contain enough rows."); + Object o = null; + Iterator it=collection.iterator(); + for (int r = 0; rGnuPlot provides methods for handling gnuplot data. Additionally + * this class can be used as an interface to gnuplot in order to actually plot data.
    + * After data has been added by one of the addData methods, you are able either + * to retrieve the gnuplot data file (as String - getData - or saved to a file - + * saveData) or to plot the data by invoking gnuplot. + * Once the plot is created, it can be retrieved as an Image object by getImage, + * saved to a png file by saveImage or presented interactively to the screen + * (by setting the visible property to true). + *

    + * Multiple data can be added as well as another gnuplot object can be merged. + *

    + * If the plot is shown in the {@link JFrame}, it can be saved by rightclicking on the frame or + * pressing F3 / CTRL-S. + * + * @author Florian Erhard + * @see Axes + */ +public class GnuPlot extends JFrame { + private static final long serialVersionUID = 1L; + + protected BufferedImage img = null; + protected List commands = null; + protected List axes = null; + protected List clearedAxes = null; + + protected String defaultStyle = null; + + + /** + * The constructor sets the DefaultCloseOperation of this JFrame to DISPOSE_ON_CLOSE. + * Additionally the listeners for saving are created. + */ + public GnuPlot() { + super("GnuPlot"); + setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + commands = new ArrayList(); + axes = new LinkedList(); + clearedAxes = new LinkedList(); + defaultStyle = ""; + + addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + showSaveAsDialog(); + } + + }); + + addKeyListener(new KeyAdapter() { + @Override + public void keyPressed(KeyEvent e) { + if (e.getKeyCode()==KeyEvent.VK_F3) + showSaveAsDialog(); + else if (e.getKeyCode()==KeyEvent.VK_S && (e.getModifiersEx() & KeyEvent.CTRL_DOWN_MASK)==KeyEvent.CTRL_DOWN_MASK) + showSaveAsDialog(); + if (e.getKeyCode()==KeyEvent.VK_ESCAPE) + dispose(); + } + + }); + + + + } + + + + private void showSaveAsDialog() { + JFileChooser dia = new JFileChooser(); + dia.setFileFilter(new FileFilter() { + @Override + public boolean accept(File f) { + return f.isDirectory() || f.getName().endsWith(".gnuplot") || f.getName().endsWith(".ps") || f.getName().endsWith(".eps") || f.getName().endsWith(".png"); + } + + @Override + public String getDescription() { + return "Supported Formats (ps,eps,png,gnuplot)"; + } + + }); + List files = null; + try { + if (dia.showSaveDialog(this)==JFileChooser.APPROVE_OPTION) { + String end = dia.getSelectedFile().getName().substring(dia.getSelectedFile().getName().lastIndexOf(".")+1); + if (end.equals("gnuplot")) { + saveData(dia.getSelectedFile()); + } else { + String cmd; + if (end.equals("png")) + cmd = "set term png"; + else + cmd = "set term postscript color"; + + + String tmp = this.hashCode()+".gnuplot"; + // String tmpPic = this.hashCode()+"."+end; + files = saveData(new File(tmp)); + + String plotCommand = getPlotCommand(files); + Process p ; + try { + p = new ProcessBuilder("gnuplot").start(); + } catch (Exception e) { + throw new IOException("Gnuplot could not be called!"); + } + + BufferedWriter c = new BufferedWriter(new OutputStreamWriter(p.getOutputStream())); + for (String line : plotCommand.split("\n")) { + if (line.startsWith("set term")) + line = cmd+"\n"+"set output \""+dia.getSelectedFile().toString().replace("\\", "\\\\")+"\""; + c.append(line+"\n"); + c.flush(); + checkGnuplotError(p); + } + + c.close(); + + p.destroy(); + +// if (new File(tmpPic).exists()) { +// if (dia.getSelectedFile().exists()) +// dia.getSelectedFile().delete(); +// if (!new File(tmpPic).renameTo(dia.getSelectedFile())) { +// new File(tmpPic).delete(); +// throw new Exception("Could not create file "+dia.getSelectedFile().toString()); +// } +// } + } + + } + } catch (Exception e) { + JOptionPane.showMessageDialog(this, "Error:\n"+e.getMessage()); + } finally { + if (files!=null) + for (File f : files) + f.delete(); + } + } + + + /** + * Adds commands to the list of commands which are given to gnuplot by invoking plot + * + * @param command the gnuplot command (e.g. set xrange [0:100]) + */ + public void addCommand(String... command) { + for (String c : command) + commands.add(c); + } + + /** + * Returns the list of commands, e.g. if you want to remove some command from it. + * + * @return the list of gnuplot commands + */ + public Collection getCommands() { + return commands; + } + + /** + * Clears the loaded data. + */ + public void clearData() { + clearedAxes.addAll(axes); + axes.clear(); + } + + /** + * Adds data in order to plot it. The data has to be given as a collection of Numbers, + * Doubles, Integer,... or as double[], int[], ... The type is inferred by using + * the java reflection api. + * + * @param col the collections array with the data + * @param dataLabels label for each value column + * @param styles additional styles for each value column + * @return axes object containing the data + */ + @SuppressWarnings("unchecked") + public Axes addData(Collection col, String[] dataLabels, String[] styles) { + Axes axes = new CollectionAxes(col,dataLabels,styles); + return addData(axes); + } + + + /** + * Adds data in order to plot it. The data has to be given as an axes object. + * + * @param axes an axes object with data to plot + * @return axes object containing the data + */ + public Axes addData(Axes axes) { + if (this.axes.size()>0 && this.axes.get(0).getDimensionType()!= axes.getDimensionType()) + throw new IllegalArgumentException("No mixture of 2 and 3 dimensional axes allowed!"); + this.axes.add(axes); + return axes; + } + + /** + * Adds data in order to plot it. The data has to be given as a matrix of double, int, ... + * The first index of the matrix gives the row, the second the column. The type is inferred by using + * the java reflection api. + * In lineTypes and dataLabels you can give line style + * and labels for each column. + * + * @param arr the data matrix to plot + * @param styles additional styles for each value column + * @param dataLabels label for each value column + * @return axes object containing the data + */ + public Axes addData(Object arr, String[] dataLabels, String[] styles) { + Axes axes = new ArrayMatrixAxes(arr,dataLabels,styles); + return addData(axes); + } + + /** + * Adds data in order to plot it. The data has to be given as a matrix of double, int, ... + * If transposed=true, the first index of the matrix gives the row, the second the column. + * The type is inferred by using + * the java reflection api. + * In lineTypes and dataLabels you can give line style + * and labels for each column. + * + * @param arr the data matrix to plot + * @param transposed if the given matrix is transposed + * @param styles additional styles for each value column + * @param dataLabels label for each value column + * @return axes object containing the data + */ + public Axes addData(Object[] arr, boolean transposed, String[] dataLabels, String[] styles) { + Axes axes = transposed ? new TransposedArrayMatrixAxes(arr,dataLabels,styles) : new ArrayMatrixAxes(arr,dataLabels,styles); + return addData(axes); + } + + /** + * Merges another gnuplot object with this one by add its axes and copy its + * default style to the axes (if they have no style). + * + * @param gnuplot the gnuplot object to merge with + */ + public void merge(GnuPlot gnuplot) { + for (Axes a : gnuplot.axes) + addData(a); + for (Axes a : gnuplot.axes) + a.applyDefaultStyle(gnuplot.getDefaultStyle()); + } + + /** + * Returns the Axes object containing the data, labels and styles. + * + * @return Axes object + */ + public List getAxes() { + return axes; + } + + + /** + * Returns the plot command for a given filename + * + * @param files a list (parallel to axes) of files containing the gnuplot data + * @return plot command to use in gnuplot + */ + public String getPlotCommand(List files) { + String plotCommand, usingPrefix; + int labelColumns; + + if (axes.size()>0 && axes.get(0).getDimensionType()==Axes.ThreeD) { + plotCommand = "splot"; + usingPrefix = "1:2"; + labelColumns = 2; + } else { + plotCommand = "plot"; + usingPrefix = "1"; + labelColumns = 1; + } + + StringBuilder sb = new StringBuilder(); + for (String cmd : commands) + sb.append(cmd+"\n"); + + sb.append("set term png\n"); + sb.append(plotCommand); + + Iterator fIt = files.iterator(); + Iterator aIt = axes.iterator(); + while (fIt.hasNext() || aIt.hasNext()) { + if (!fIt.hasNext() || !aIt.hasNext()) + throw new RuntimeException("Fileslist and Axeslist don't have the same size!"); + File f = fIt.next(); + Axes a = aIt.next(); + for (int i=labelColumns; i0) sb.append(" title \""+a.getLabel(i)+"\""); + else sb.append(" notitle"); + if (a.getStyle(i).length()>0) sb.append(" "+a.getStyle(i)); + else if (defaultStyle.length()>0) sb.append(" "+defaultStyle); + if (i+1 getData() { + List re = new LinkedList(); + for (Axes a : axes) { + StringBuilder sb = new StringBuilder(); + for (String row : a) { + sb.append(row); + sb.append("\n"); + } + re.add(sb.toString()); + } + return re; + } + + /** + * Saves the gnuplot data to one ore more files. If only one data axes has been loaded, + * the file is named as given. If there are more than one, the number is attached to the + * given filename. + * + * @param file where to save to file + * @return list of the saved files + * + * @throws IOException + */ + public List saveData(File file) throws IOException { + List re = new LinkedList(); + + if (axes.size()==1) { + FileWriter fw = new FileWriter(file); + fw.append(getData().iterator().next()); + fw.flush(); + fw.close(); + re.add(file); + } else { + int index = 1; + for (String content : getData()) { + String fn = file.toString(); + if (fn.lastIndexOf(".")>fn.lastIndexOf(File.pathSeparator)) + fn = fn.substring(0,fn.lastIndexOf("."))+(index++)+fn.substring(fn.lastIndexOf(".")); + else + fn = fn+(index++); + + File file2 = new File(fn); + FileWriter fw = new FileWriter(file2); + fw.append(content); + fw.flush(); + fw.close(); + re.add(file2); + } + } + return re; + } + + /** + * Returns whether or not gnuplot is accessible + * + * @return whether or not gnuplot is accessible + */ + public boolean isAccessible() { + Process p ; + try { + p = new ProcessBuilder("gnuplot","--version").start(); + String re = new BufferedReader(new InputStreamReader(p.getInputStream())).readLine(); + if (re==null || re.length()==0) return false; + return true; + } catch (Exception e) { + return false; + } + } + + + /** + * Calls gnuplot to plot the data. loadData has + * to be invoked first. A temporary file is created in the working directory + * to hold the data (for compatibility + * with cygwin, this file is not created by File.createTempFile) + * and deleted after plotting. If the JFrame is visible, it will be repainted. + * The commands are given to gnuplot via its stdin, the plotted image is retrieved + * via its stdout. + *

    + * The name(s) of the temporary files are hashCode()i.gnuplot. If there + * is only one file created, i is omitted. + * + * @throws IOException + */ + public void plot() throws IOException { + if (!isAccessible()) throw new IOException("gnuplot is not accessible! Add it to your path variable!"); + + String tmp = this.hashCode()+".gnuplot"; + List files = saveData(new File(tmp)); + + String plotCommand = getPlotCommand(files); + Process p ; + try { + p = new ProcessBuilder("gnuplot").start(); + } catch (Exception e) { + throw new IOException("Gnuplot could not be called!"); + } + + BufferedWriter c = new BufferedWriter(new OutputStreamWriter(p.getOutputStream())); + for (String line : plotCommand.split("\n")) { + c.append(line+"\n"); + c.flush(); + checkGnuplotError(p); + } + + c.close(); + + img = ImageIO.read(new BufferedInputStream(p.getInputStream())); + if (img==null) + checkGnuplotError(p); + + + + p.destroy(); + + for (File f : files) + f.delete(); + + if (this.isVisible()) { + setSize(img.getWidth(null),img.getHeight(null)+getInsets().top); + repaint(); + } + } + + private void checkGnuplotError(Process p) throws IOException { + try { + Thread.sleep(100); + } catch (InterruptedException e1) {} + if (p.getErrorStream().available()>0) { + StringBuilder e = new StringBuilder(); + BufferedReader br = new BufferedReader(new InputStreamReader(p.getErrorStream())); + String line; + while (br.ready()){ + line=br.readLine(); + e.append(line+"\n"); + } + throw new IOException(e.toString()); + } + } + + @Override + public void paint(Graphics g) { + g.drawImage(img, 0, getInsets().top, null); + } + + /** + * The defaultStyle is used, when no style is defined for an column in an axes object. + * + * @return the defaultStyle + */ + public String getDefaultStyle() { + return defaultStyle; + } + + /** + * The defaultStyle is used, when no style is defined for an column in an axes object. + * + * @param defaultStyle the defaultStyle to set + */ + public void setDefaultStyle(String defaultStyle) { + this.defaultStyle = defaultStyle; + } + + +} + diff --git a/src/main/java/fern/tools/gnuplot/TransposedArrayMatrixAxes.java b/src/main/java/fern/tools/gnuplot/TransposedArrayMatrixAxes.java new file mode 100644 index 00000000..de83bd07 --- /dev/null +++ b/src/main/java/fern/tools/gnuplot/TransposedArrayMatrixAxes.java @@ -0,0 +1,97 @@ +package fern.tools.gnuplot; + +import java.lang.reflect.Array; +import java.util.Iterator; + + +/** + * Implementation of {@link Axes} to use with transposed array matrixes + * of any number type (the type of the arrays is inferred by + * using the reflection api). An array matrix is just a two dimensional + * rectangular array (new double[20][3]). The first index + * of the transposed matrix gives the column, the second the row (3 rows and 20 columns). + *

    + * If your array matrix is not transposed (your first index denotes the row, the second + * one the column), just use {@link ArrayMatrixAxes}. + * + * @author Florian Erhard + * @see Axes + */ +public class TransposedArrayMatrixAxes extends ArrayMatrixAxes{ + + + /** + * Create a new Axes object containing the given array matrix + * without labels / styles. If the passed object is not a valid array matrix, + * an {@link IllegalArgumentException} will be thrown. + * + * @param matrix array matrix + */ + public TransposedArrayMatrixAxes(Object matrix) { + this(matrix, null, null); + } + + /** + * Create a new Axes object containing the given array matrix + * with the given labels /styles (either can be null). + * If the passed object is not a valid array matrix, + * an {@link IllegalArgumentException} will be thrown. + * + * @param matrix the array matrix + * @param labels the labels + * @param styles the styles + */ + public TransposedArrayMatrixAxes(Object matrix, String[] labels, String[] styles) { + super(matrix, labels, styles); + + } + + + @Override + public Number getNumber(int row, int col) { + return super.getNumber(col+getNumLabelAxes(), row-getNumLabelAxes()); + } + + @Override + public int getNumRows() { + return Array.getLength(Array.get(array, 0)); + } + + @Override + public int getNumColumns() { + return Array.getLength(array)+getNumAdditionalColumns(); + } + + /** + * Yields the tab separated columns row by row. + */ + public Iterator iterator() { + return new Iterator() { + + @SuppressWarnings("unchecked") + int index = 0; + Iterator itAdd = getAdditionalAxesIterator(); + + public boolean hasNext() { + return index0) sb.deleteCharAt(sb.length()-1); + index++; + return sb.toString() + s; + + } + + public void remove() { } + + }; + } + + +} diff --git a/src/main/java/org/simulator/math/odes/AbstractDESSolver.java b/src/main/java/org/simulator/math/odes/AbstractDESSolver.java index 34189879..47d8cde2 100644 --- a/src/main/java/org/simulator/math/odes/AbstractDESSolver.java +++ b/src/main/java/org/simulator/math/odes/AbstractDESSolver.java @@ -442,9 +442,9 @@ public int eventOccurred(double t, double[] y, boolean increasing) * {@inheritDoc} */ @Override - public void firePropertyChange(double currTime, double[] currResult) { + public void firePropertyChange(double previousTimePoint, double currTimePoint, double[] currResult) { if (!listenerList.isEmpty()) { - PropertyChangeEvent evt1 = new PropertyChangeEvent(this, PROGRESS, currTime, currTime); + PropertyChangeEvent evt1 = new PropertyChangeEvent(this, PROGRESS, previousTimePoint, currTimePoint); PropertyChangeEvent evt2 = new PropertyChangeEvent(this, RESULT, currResult, currResult); // logger.info(String.format("Progress: %s %%", StringTools.toString(newValue))); for (PropertyChangeListener listener : listenerList) { @@ -784,7 +784,7 @@ public MultiTable solve(DESystem DES, double[] initialValues, double timeBegin, // execute events that trigger at 0.0 and process rules on changes due to the events processEventsAndRules(true, (EventDESystem) DES, 0d, 0d, result[0]); System.arraycopy(result[0], 0, yTemp, 0, yTemp.length); - firePropertyChange(0d, result[0]); + firePropertyChange(-stepSize, 0d, result[0]); for (int i = 1; (i < result.length) && (!Thread.currentThread().isInterrupted()); i++) { double oldT = t; System.arraycopy(yTemp, 0, yPrev, 0, yTemp.length); @@ -801,7 +801,7 @@ public MultiTable solve(DESystem DES, double[] initialValues, double timeBegin, // if (logger.getLevel().intValue() < Level.INFO.intValue()) { // logger.fine("additional results: " + Arrays.toString(v)); // } - firePropertyChange(t * intervalFactor, yTemp); + firePropertyChange(oldT * intervalFactor, t * intervalFactor, yTemp); } return data; } @@ -852,7 +852,7 @@ public MultiTable solve(DESystem DES, double[] initialValues, double[] timePoint // execute events that trigger at 0.0 and process rules on changes due to the events processEventsAndRules(true, (EventDESystem) DES, 0d, 0d, result[0]); System.arraycopy(result[0], 0, yTemp, 0, result[0].length); - firePropertyChange(0d, result[0]); + firePropertyChange(-stepSize, 0d, result[0]); for (int i = 1; (i < timePoints.length) && (!Thread.currentThread().isInterrupted()); i++) { h = stepSize; // h = h / 10; @@ -879,7 +879,7 @@ public MultiTable solve(DESystem DES, double[] initialValues, double[] timePoint // if (logger.getLevel().intValue() < Level.INFO.intValue()) { // logger.fine("additional results: " + Arrays.toString(v)); // } - firePropertyChange(timePoints[i], yTemp); + firePropertyChange(timePoints[i-1], timePoints[i], yTemp); t = timePoints[i]; } return data; @@ -923,7 +923,7 @@ public MultiTable solve(DESystem DES, MultiTable.Block initConditions, double[] double[] change = new double[DES.getDimension()]; double t = timePoints[0]; double v[] = additionalResults(DES, t, result[0], data, 0); - firePropertyChange(0d, result[0]); + firePropertyChange(-stepSize, 0d, result[0]); for (i = 1; (i < timePoints.length) && (!Thread.currentThread().isInterrupted()); i++) { double h = stepSize; if (!missingIds.isEmpty()) { @@ -955,7 +955,7 @@ public MultiTable solve(DESystem DES, MultiTable.Block initConditions, double[] // if ((logger != null) && (logger.getLevel().intValue() < Level.INFO.intValue())) { // logger.fine("additional results: " + Arrays.toString(v)); // } - firePropertyChange(timePoints[i] * intervalFactor, yTemp); + firePropertyChange(timePoints[i-1] * intervalFactor, timePoints[i] * intervalFactor, yTemp); t = timePoints[i]; } return data; diff --git a/src/main/java/org/simulator/math/odes/DESSolver.java b/src/main/java/org/simulator/math/odes/DESSolver.java index 1b9aa31c..a66c006f 100644 --- a/src/main/java/org/simulator/math/odes/DESSolver.java +++ b/src/main/java/org/simulator/math/odes/DESSolver.java @@ -57,10 +57,11 @@ public interface DESSolver extends Cloneable, Serializable { * current time point of simulation, respectively. CurrResult * is the row of the result at the current time point of simulation. * - * @param currTime + * @param previousTimePoint + * @param currTimePoint * @param currResult */ - public void firePropertyChange(double currTime, double[] currResult); + public void firePropertyChange(double previousTimePoint, double currTimePoint, double[] currResult); /** * For details about the Kinetic Simulation Algorithm Ontology (KiSAO) see diff --git a/src/main/java/org/simulator/sbml/AlgebraicRuleConverter.java b/src/main/java/org/simulator/sbml/AlgebraicRuleConverter.java index 9353882d..70c54c3f 100644 --- a/src/main/java/org/simulator/sbml/AlgebraicRuleConverter.java +++ b/src/main/java/org/simulator/sbml/AlgebraicRuleConverter.java @@ -30,6 +30,7 @@ import java.util.List; import java.util.Map; +import de.binfalse.bflog.LOGGER; import org.sbml.jsbml.ASTNode; import org.sbml.jsbml.AlgebraicRule; import org.sbml.jsbml.AssignmentRule; @@ -396,9 +397,9 @@ public List getAssignmentRules() { // //System.out.println(entry.getKey() + " -> " + entry.getValue()); // } } else { - System.out.println("no matching found"); + LOGGER.error("no matching found"); } - //determine matchings for algebraic rules + // determine matchings for algebraic rules // create for every algebraic rule an adequate assignment rule for (int i = 0; i < model.getRuleCount(); i++) { Rule r = model.getRule(i); @@ -414,7 +415,6 @@ public List getAssignmentRules() { // when assignment rule created add to the list if (as != null) { assignmentRules.add(as); - as = null; } } } diff --git a/src/main/java/org/simulator/sbml/SBMLinterpreter.java b/src/main/java/org/simulator/sbml/SBMLinterpreter.java index d5ab8eeb..54f1e0c8 100644 --- a/src/main/java/org/simulator/sbml/SBMLinterpreter.java +++ b/src/main/java/org/simulator/sbml/SBMLinterpreter.java @@ -39,6 +39,7 @@ import java.util.logging.Level; import java.util.logging.Logger; +import fern.network.AmountManager; import org.apache.commons.math.ode.DerivativeException; import org.sbml.jsbml.ASTNode; import org.sbml.jsbml.AssignmentRule; @@ -364,6 +365,12 @@ public int getConstraintListenerCount() { */ private List rateRulesRoots; + /** + * Map for getting the raterule index (in the rateRulesRoots ArrayList) + * of particular id + */ + private Map rateRuleHash; + /** * Current time for the ASTNode processing (not equal to the simulation time!) */ @@ -482,12 +489,17 @@ public int getConstraintListenerCount() { private boolean containsDelays; /** - * The value of the last time point processed + * The value of the latest time point */ private double latestTimePoint; /** - * An array of the concentration of each species at last processed time point + * The value of the previous time point + */ + private double previousTimePoint; + + /** + * An array of the concentration of each species at latest processed time point * within the model system. */ private double[] latestTimePointResult; @@ -585,6 +597,7 @@ public SBMLinterpreter(Model model, double defaultSpeciesValue, double defaultPa nodes = new LinkedList(); latestTimePoint = 0d; latestTimePointResult = new double[Y.length]; + rateRuleHash = new HashMap<>(); init(true, defaultSpeciesValue, defaultParameterValue, defaultCompartmentValue, amountHash); } @@ -638,8 +651,7 @@ private Species determineMajorSpeciesAttributes() { */ private void evaluateAlgebraicRules() throws ModelOverdeterminedException { OverdeterminationValidator odv = new OverdeterminationValidator(model); - // model has not to be overdetermined (violation of the SBML - // specifications) + // model must not be overdetermined (violation of the SBML specifications) if (odv.isOverdetermined()) { throw new ModelOverdeterminedException(); } @@ -1772,11 +1784,12 @@ private void initializeRules() { } if (rr.isSetMath()) { rateRulesRoots.add(new RateRuleValue((ASTNodeValue) copyAST(rr.getMath(), true, null, null).getUserObject(TEMP_VALUE), symbolIndex, sp, compartmentHash.get(sp.getId()), hasZeroSpatialDimensions, this, rr.getVariable(), isAmount[symbolIndex])); + rateRuleHash.put(rr.getVariable(), rateRulesRoots.size() - 1); } } else if (compartmentHash.containsValue(symbolIndex)) { List speciesIndices = new LinkedList(); for (Entry entry : compartmentHash.entrySet()) { - if (entry.getValue() == symbolIndex) { + if (entry.getValue().equals(symbolIndex)) { Species s = model.getSpecies(entry.getKey()); int speciesIndex = symbolHash.get(entry.getKey()); if ((!isAmount[speciesIndex]) && (!s.isConstant())) { @@ -1786,10 +1799,36 @@ private void initializeRules() { } if (rr.isSetMath()) { rateRulesRoots.add(new RateRuleValue((ASTNodeValue) copyAST(rr.getMath(), true, null, null).getUserObject(TEMP_VALUE), symbolIndex, speciesIndices, this, rr.getVariable())); + rateRuleHash.put(rr.getVariable(), rateRulesRoots.size() - 1); } } else { if (rr.isSetMath()) { rateRulesRoots.add(new RateRuleValue((ASTNodeValue) copyAST(rr.getMath(), true, null, null).getUserObject(TEMP_VALUE), symbolIndex, rr.getVariable())); + rateRuleHash.put(rr.getVariable(), rateRulesRoots.size() - 1); + } + } + } + } + } + + /* + * Traversing through all the rate rules for finding if species + * are present in changing compartment. Traversing is done again as the + * the compartment rate rules in the SBML models can be declared after the + * species rate rule. + */ + for (int i = 0; i < model.getRuleCount(); i++) { + Rule rr = model.getRule(i); + if (rr.isRate()) { + RateRule rateRule = (RateRule) rr; + symbolIndex = symbolHash.get(rateRule.getVariable()); + if (symbolIndex != null) { + Species sp = model.getSpecies(rateRule.getVariable()); + if (sp != null) { + Compartment c = sp.getCompartmentInstance(); + + if ((c != null) && (rateRuleHash.get(c.getId()) != null)) { + rateRulesRoots.get(rateRuleHash.get(sp.getId())).setCompartmentRateRule(rateRulesRoots.get(rateRuleHash.get(c.getId()))); } } } @@ -1948,7 +1987,7 @@ private Set getSetOfVariables(ASTNode math, Set variables, Set inFunctionNodes) { + public ASTNode copyAST(ASTNode node, boolean mergingPossible, FunctionValue function, List inFunctionNodes) { String nodeString = node.toString(); ASTNode copiedAST = null; if (mergingPossible && !nodeString.equals("") && !nodeString.contains("")) { @@ -2407,6 +2446,26 @@ public boolean processRules(double time, double[] changeRate, double[] Y, boolea return changeByAssignmentRules; } + public void computeDerivativeWithChangingCompartment (Species sp, double[] changeRate) { + + double latestSpeciesValue = latestTimePointResult[symbolHash.get(sp.getId())]; + double latestCompartmentValue = latestTimePointResult[symbolHash.get(sp.getCompartment())]; + + String speciesId = sp.getId(); + String compartmentId = sp.getCompartment(); + + changeRate[symbolHash.get(compartmentId)] = rateRulesRoots.get(rateRuleHash.get(compartmentId)).getNodeObject().compileDouble(astNodeTime, 0d); + latestCompartmentValue = latestCompartmentValue + (latestTimePoint - previousTimePoint) * changeRate[symbolHash.get(sp.getCompartment())]; + + changeRate[symbolHash.get(speciesId)] = rateRulesRoots.get(rateRuleHash.get(speciesId)).getNodeObject().compileDouble(astNodeTime, 0d); + + double a1 = (latestSpeciesValue / latestCompartmentValue) * changeRate[symbolHash.get(compartmentId)]; + double a2 = latestCompartmentValue * changeRate[symbolHash.get(speciesId)]; + + changeRate[symbolHash.get(speciesId)] = a1 + a2; + + } + /** * This method computes the multiplication of the stoichiometric matrix of the @@ -2568,6 +2627,17 @@ private void updateSpeciesConcentrationByCompartmentRateRule(int compartmentInde } } + /** + * Updates the species concentration as per the updated values in the + * AmountManager. + * + * @param amountManager + */ + public void updateSpeciesConcentration(AmountManager amountManager){ + for (int i=0;i= 0) { double oldValue = Y[index]; - processAssignmentVariable(time); + processAssignmentVariable(time, null); if (changeY) { Y[index] = value; } @@ -107,7 +107,7 @@ public boolean processRule(double[] Y, double time, boolean changeY) { return true; } } else if (speciesReferenceID != null) { - processAssignmentVariable(time); + processAssignmentVariable(time, null); Double v = stoichiometricCoefHash.get(speciesReferenceID); stoichiometricCoefHash.put(speciesReferenceID, value); if ((v != null) && (v.doubleValue() != value)) { diff --git a/src/main/java/org/simulator/sbml/astnode/RateRuleValue.java b/src/main/java/org/simulator/sbml/astnode/RateRuleValue.java index fabe5dc0..99f79ca9 100644 --- a/src/main/java/org/simulator/sbml/astnode/RateRuleValue.java +++ b/src/main/java/org/simulator/sbml/astnode/RateRuleValue.java @@ -54,6 +54,12 @@ public class RateRuleValue extends RuleValue { */ private String variable; + /** + * The rate rule of the compartment (if present) in which the species is + * present. + */ + private RateRuleValue compartmentRateRule; + /** * @param nodeObject * @param index @@ -77,6 +83,7 @@ public RateRuleValue(ASTNodeValue nodeObject, int index, String variable) { public RateRuleValue(ASTNodeValue nodeObject, int index, Species sp, int compartmentIndex, boolean hasZeroSpatialDimensions, SBMLValueHolder valueHolder, String variable, boolean isAmount) { super(nodeObject, index, sp, compartmentIndex, hasZeroSpatialDimensions, valueHolder, isAmount); this.variable = variable; + this.compartmentRateRule = null; } /** @@ -109,7 +116,7 @@ public String getVariable() { * @param time */ public void processRule(double[] changeRate, double[] Y, double time) { - changeRate[index] = processAssignmentVariable(time); + changeRate[index] = processAssignmentVariable(time, compartmentRateRule); // when the size of a compartment changes, the concentrations of the // species located in this compartment have to change as well if (isCompartment) { @@ -120,4 +127,8 @@ public void processRule(double[] changeRate, double[] Y, double time) { } } } + + public void setCompartmentRateRule(RateRuleValue compartmentRateRule) { + this.compartmentRateRule = compartmentRateRule; + } } diff --git a/src/main/java/org/simulator/sbml/astnode/RuleValue.java b/src/main/java/org/simulator/sbml/astnode/RuleValue.java index 1dd7f79b..2ed641d4 100644 --- a/src/main/java/org/simulator/sbml/astnode/RuleValue.java +++ b/src/main/java/org/simulator/sbml/astnode/RuleValue.java @@ -130,12 +130,15 @@ public RuleValue(ASTNodeValue nodeObject, int index, Species sp, int compartment * @param time * @return value the computed value of the variable */ - protected double processAssignmentVariable(double time) { + protected double processAssignmentVariable(double time, RateRuleValue compartmentRateRule) { value = nodeObject.compileDouble(time, 0d); if (isSpecies && !hasZeroSpatialDimensions) { double compartmentValue = valueHolder.getCurrentValueOf(compartmentIndex); if (isAmount && !hasOnlySubstanceUnits) { value = value * compartmentValue; + if (compartmentRateRule != null) { + value += (valueHolder.getCurrentValueOf(index) / compartmentValue) * compartmentRateRule.getNodeObject().compileDouble(time, 0d); + } } else if (!isAmount && hasOnlySubstanceUnits) { value = value / compartmentValue; } diff --git a/src/main/resources/examples/decaydimer.xml b/src/main/resources/examples/decaydimer.xml new file mode 100644 index 00000000..2f9e636f --- /dev/null +++ b/src/main/resources/examples/decaydimer.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/examples/isomerization.xml b/src/main/resources/examples/isomerization.xml new file mode 100644 index 00000000..746d21ba --- /dev/null +++ b/src/main/resources/examples/isomerization.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/examples/isomerization_sbml.xml b/src/main/resources/examples/isomerization_sbml.xml new file mode 100644 index 00000000..85dd9887 --- /dev/null +++ b/src/main/resources/examples/isomerization_sbml.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + 1 + S1 + + + + + + + \ No newline at end of file diff --git a/src/main/resources/examples/lacy.xml b/src/main/resources/examples/lacy.xml new file mode 100644 index 00000000..1a89488d --- /dev/null +++ b/src/main/resources/examples/lacy.xml @@ -0,0 +1,214 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/examples/lacy1000.xml b/src/main/resources/examples/lacy1000.xml new file mode 100644 index 00000000..9cbf29c3 --- /dev/null +++ b/src/main/resources/examples/lacy1000.xml @@ -0,0 +1,222 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/examples/lacy1000_sbml.xml b/src/main/resources/examples/lacy1000_sbml.xml new file mode 100644 index 00000000..3043e3a8 --- /dev/null +++ b/src/main/resources/examples/lacy1000_sbml.xml @@ -0,0 +1,427 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0.17 + PLac + RNAP + + + + + + + + + + + + + + + + + 10 + PLacRNAP + + + + + + + + + + + + + + + + 1 + PLacRNAP + + + + + + + + + + + + + + + + + + 1 + TrLacZ1 + + + + + + + + + + + + + + + + 0.015 + TrLacZ2 + + + + + + + + + + + + + + + + + 1 + TrLacY1 + + + + + + + + + + + + + + + + 0.36 + TrLacY2 + + + + + + + + + + + + + + + + + 0.17 + Ribosome + RbsLacZ + + + + + + + + + + + + + + + + + 0.17 + Ribosome + RbsLacY + + + + + + + + + + + + + + + + + 0.45 + RbsRibosomeLacZ + + + + + + + + + + + + + + + + + 0.45 + RbsRibosomeLacY + + + + + + + + + + + + + + + + + 0.4 + RbsRibosomeLacZ + + + + + + + + + + + + + + + + + 0.4 + RbsRibosomeLacY + + + + + + + + + + + + + + + + 0.015 + TrRbsLacZ + + + + + + + + + + + + + + + + 0.036 + TrRbsLacY + + + + + + + + + + + + + + + + 6.42 -5 + LacZ + + + + + + + + + + + + + + + + 6.42 -5 + LacY + + + + + + + + + + + + + + + + 0.3 + RbsLacZ + + + + + + + + + + + + + + + + 0.3 + RbsLacY + + + + + + + + + + + + + + + + + 9.52 -5 + LacZ + lactose + + + + + + + + + + + + + + + + + 431 + LacZlactose + + + + + + + + + + + + + + + + + 14 + LacY + + + + + + + \ No newline at end of file diff --git a/src/main/resources/examples/lacy_sbml.xml b/src/main/resources/examples/lacy_sbml.xml new file mode 100644 index 00000000..bb1ba9f1 --- /dev/null +++ b/src/main/resources/examples/lacy_sbml.xml @@ -0,0 +1,410 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0.17 + PLac + RNAP + + + + + + + + + + + + + + + + + 10 + PLacRNAP + + + + + + + + + + + + + + + + 1 + PLacRNAP + + + + + + + + + + + + + + + + + + 1 + TrLacZ1 + + + + + + + + + + + + + + + + 0.015 + TrLacZ2 + + + + + + + + + + + + + + + + + 1 + TrLacY1 + + + + + + + + + + + + + + + + 0.36 + TrLacY2 + + + + + + + + + + + + + + + + + 0.17 + Ribosome + RbsLacZ + + + + + + + + + + + + + + + + + 0.17 + Ribosome + RbsLacY + + + + + + + + + + + + + + + + + 0.45 + RbsRibosomeLacZ + + + + + + + + + + + + + + + + + 0.45 + RbsRibosomeLacY + + + + + + + + + + + + + + + + + 0.4 + RbsRibosomeLacZ + + + + + + + + + + + + + + + + + 0.4 + RbsRibosomeLacY + + + + + + + + + + + + + + + + 0.015 + TrRbsLacZ + + + + + + + + + + + + + + + + 0.036 + TrRbsLacY + + + + + + + + + + + + + + + + 6.42 -5 + LacZ + + + + + + + + + + + + + + + + 6.42 -5 + LacY + + + + + + + + + + + + + + + + 0.3 + RbsLacZ + + + + + + + + + + + + + + + + 0.3 + RbsLacY + + + + + + + + + + + + + + + + + + 0.0005731 + LacZ + lactose + + + + + + + + + + + + + + + + + 14 + LacY + + + + + + + \ No newline at end of file diff --git a/src/main/resources/examples/lacy_sbmll1v2.xml b/src/main/resources/examples/lacy_sbmll1v2.xml new file mode 100644 index 00000000..2a05214e --- /dev/null +++ b/src/main/resources/examples/lacy_sbmll1v2.xml @@ -0,0 +1,238 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/examples/lacz.xml b/src/main/resources/examples/lacz.xml new file mode 100644 index 00000000..5b355ae0 --- /dev/null +++ b/src/main/resources/examples/lacz.xml @@ -0,0 +1,115 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/examples/lacz_sbml.xml b/src/main/resources/examples/lacz_sbml.xml new file mode 100644 index 00000000..a997c0d6 --- /dev/null +++ b/src/main/resources/examples/lacz_sbml.xml @@ -0,0 +1,220 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0.17 + PLac + RNAP + + + + + + + + + + + + + + + + + 10 + PLacRNAP + + + + + + + + + + + + + + + + 1 + PLacRNAP + + + + + + + + + + + + + + + + + + 1 + TrLacZ1 + + + + + + + + + + + + + + + + 0.015 + TrLacZ2 + + + + + + + + + + + + + + + + + 0.17 + Ribosome + RbsLacZ + + + + + + + + + + + + + + + + + 0.45 + RbsRibosome + + + + + + + + + + + + + + + + + 0.4 + RbsRibosome + + + + + + + + + + + + + + + + 0.015 + TrRbsLacZ + + + + + + + + + + + + + + + + 6.42 -5 + LacZ + + + + + + + + + + + + + + + + 0.3 + RbsLacZ + + + + + + + \ No newline at end of file diff --git a/src/main/resources/examples/mapk.xml b/src/main/resources/examples/mapk.xml new file mode 100755 index 00000000..38c74490 --- /dev/null +++ b/src/main/resources/examples/mapk.xml @@ -0,0 +1,245 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/examples/mapk_sbml.xml b/src/main/resources/examples/mapk_sbml.xml new file mode 100644 index 00000000..a19469f0 --- /dev/null +++ b/src/main/resources/examples/mapk_sbml.xml @@ -0,0 +1,973 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0.003 + L + R + + + + + + + + + + + + + + + + + 0.06 + C + + + + + + + + + + + + + + + + + 0.01 + C + + + C + 1 + + 0.5 + + + + + + + + + + + + + + + + + 0.1 + C2 + + + + + + + + + + + + + + + + 1 + C2 + + + + + + + + + + + + + + + + 0.01 + C* + + + + + + + + + + + + + + + + + 0.003 + C* + A1 + + + + + + + + + + + + + + + + + 0.05 + C*A1 + + + + + + + + + + + + + + + + + 0.01 + C*A1 + A2 + + + + + + + + + + + + + + + + + 0.06 + E0* + + + + + + + + + + + + + + + + + 0.0001 + A1 + A2 + + + + + + + + + + + + + + + + + 0.0015 + A1A2 + + + + + + + + + + + + + + + + + 0.0045 + C* + A1A2 + + + + + + + + + + + + + + + + + 0.03 + E0* + + + + + + + + + + + + + + + + + 0.01 + E1 + E0* + + + + + + + + + + + + + + + + + 0.5 + E1E0* + + + + + + + + + + + + + + + + + 0.1 + E1E0* + + + + + + + + + + + + + + + + + 0.01 + E1* + P1 + + + + + + + + + + + + + + + + + 0.5 + E1*P1 + + + + + + + + + + + + + + + + + 0.1 + E1*P1 + + + + + + + + + + + + + + + + + 0.01 + E2 + E1* + + + + + + + + + + + + + + + + + 0.5 + E2E1* + + + + + + + + + + + + + + + + + 0.1 + E2E1* + + + + + + + + + + + + + + + + + 0.01 + E2* + P2 + + + + + + + + + + + + + + + + + 0.5 + E2*P2 + + + + + + + + + + + + + + + + + 0.1 + E2*P2 + + + + + + + + + + + + + + + + + 0.01 + E3 + E2* + + + + + + + + + + + + + + + + + 0.5 + E3E2* + + + + + + + + + + + + + + + + + 0.1 + E3E2* + + + + + + + + + + + + + + + + + 0.01 + E3* + P3 + + + + + + + + + + + + + + + + + 0.5 + E3*P3 + + + + + + + + + + + + + + + + + 0.1 + E3*P3 + + + + + + + + + + + + + + + + + 0.01 + E4 + E3* + + + + + + + + + + + + + + + + + 0.5 + E4E3* + + + + + + + + + + + + + + + + + 0.1 + E4E3* + + + + + + + + + + + + + + + + + 0.01 + E4* + P4 + + + + + + + + + + + + + + + + + 0.5 + E4*P4 + + + + + + + + + + + + + + + + + 0.1 + E4*P4 + + + + + + + + + + + + + + + + + 0.01 + E5 + E4* + + + + + + + + + + + + + + + + + 0.5 + E5E4* + + + + + + + + + + + + + + + + + 0.1 + E5E4* + + + + + + + + + + + + + + + + + 0.01 + E5* + P5 + + + + + + + + + + + + + + + + + 0.5 + E5*P5 + + + + + + + + + + + + + + + + + 0.1 + E5*P5 + + + + + + + + + + + + + + + + + 0.01 + E0* + E4* + + + + + + + + + + + + + + + + + 0.5 + E0*E4* + + + + + + + + + + + + + + + + + + 0.1 + E0*E4* + + + + + + + + + + + + + + + + + 0.01 + E2* + E4* + + + + + + + + + + + + + + + + + 0.5 + E2*E4* + + + + + + + + + + + + + + + + + 0.1 + E2*E4* + + + + + + + \ No newline at end of file diff --git a/src/main/resources/examples/mapk_sbmll1v2.xml b/src/main/resources/examples/mapk_sbmll1v2.xml new file mode 100644 index 00000000..8c8cec58 --- /dev/null +++ b/src/main/resources/examples/mapk_sbmll1v2.xml @@ -0,0 +1,555 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/examples/mm.xml b/src/main/resources/examples/mm.xml new file mode 100644 index 00000000..40e6f019 --- /dev/null +++ b/src/main/resources/examples/mm.xml @@ -0,0 +1,66 @@ + + + + Michaelis-Menten kinetic + + + + + substrate + + + + + free enzyme + + + + + product + + + + + enzyme substrate complex + + + + + + + complex aggregation + + + + + + + + + + + + complex disaggregation + + + + + + + + + + + + product creation + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/examples/mm_sbml.xml b/src/main/resources/examples/mm_sbml.xml new file mode 100644 index 00000000..5e9b1104 --- /dev/null +++ b/src/main/resources/examples/mm_sbml.xml @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + S + E + + + + + + + + + + + + + + + + + 4 + ES + + + + + + + + + + + + + + + + + 1 + ES + + + + + + + \ No newline at end of file diff --git a/src/site/resources/old_javadoc/version_1.2/overview-summary.html b/src/site/resources/old_javadoc/version_1.2/overview-summary.html index 8e175145..b7e44b0e 100644 --- a/src/site/resources/old_javadoc/version_1.2/overview-summary.html +++ b/src/site/resources/old_javadoc/version_1.2/overview-summary.html @@ -84,13 +84,13 @@

    Systems Biology Simulation Core Library 1.2

    -Simulation Core Library: Documentation - - About Simulation Core Library - - The Java™ API Simulation Core Library comprises a collection of - integrators for differential equation systems combined with an interpreter - for the Systems Biology Markup Language +Simulation Core Library: Documentation + + About Simulation Core Library + + The Java™ API Simulation Core Library comprises a collection of + integrators for differential equation systems combined with an interpreter + for the Systems Biology Markup Language (SBML).

    See: @@ -146,158 +146,158 @@

     

    -

    Simulation Core Library: Documentation

    - -

    About Simulation Core Library

    -

    - The Java™ API Simulation Core Library comprises a collection of - integrators for differential equation systems combined with an interpreter - for the Systems Biology Markup Language - (SBML). - It is the first simulation library that is based on - JSBML. - The user can read an SBML model and simulate it with one of the provided - numerical integration routines. All SBML levels and versions are - supported. - The library can easily be integrated into customized software, such as - parameter estimation tools. -

    - -

    The provided integration methods

    -

    - The Rosenbrock solver is best suitable for integrating stiff differential - equation systems and also has a precise timing of SBML events. It is taken - and adapted from Kotcon et al. - Several solvers have been taken from the - Apache Commons - Math Library and wrapped into our library: -

      -
    • Adams Bashforth
    • -
    • Adams Moulton
    • -
    • Dormand Prince 54
    • -
    • Dormand Prince 853
    • -
    • Gragg Bulirsch Stoer
    • -
    • Higham Hall 54
    • -
    - - The following solvers have been implemented additionally and are fast, but - not suitable for all differential equation systems: -
      -
    • Euler
    • -
    • Runge Kutta
    • -
    -

    - -

    Reading in a model and creating the respective differential equation - system

    -

    - A model can be read in by using the SBMLReader class of JSBML. - With the model in memory the SBMLinterpreter can create the - differential equation system that provides the basis for simulation: -

    -
    
    -      Model model = (new SBMLReader()).readSBML(sbmlfile).getModel();
    - SBMLinterpreter interpreter = new SBMLinterpreter(model); -
    - -

    Simulation of a differential equation system

    -

    - The created differential equation system can then be simulated with a - chosen solver and given time points. - The result is stored in a data structure called MultiTable. -

    -
    
    -      AbstractDESSolver solver = new RosenbrockSolver();
    - double[] timePoints = {0.0, 0.1, 0.2, 0.3, 0.4, 0.5};
    - MultiTable solution = solver.solve(interpreter, interpreter.getInitialValues(), timePoints); -
    - -

    Using SED-ML for simulation

    -

    - The following example shows how to read in a File f (in SED-ML - format) and how to run a simulation described in this file afterwards. - The simulation results are stored in a MultiTable. -

    - -
    
    -      SEDMLDocument doc = Libsedml.readDocument(f);
    - SedML sedml = doc.getSBMLModel();
    - Output wanted = sedml.getOutputs().get(0);
    - SedMLSBMLSimulatorExecutor exe = new SedMLSBMLSimulatorExecutor(sedml, wanted);
    - Map res = exe.runSimulations();
    - MultiTable solution = exe.processSimulationResults(wanted, res);
    -
    - -

    How to integrate Simulation Core Library into your software?

    -

    - You just have to add the provided jar-file simulation-core-library.jar to the class path of your Java project. - Then you have access to all classes of the library. - This library depends on the following third-party libraries: -

    - For SED-ML support, the following - additional libraries are required: - - Please make sure to include the correct third-party libraries into your - class path before working with this library. -

    - -

    Simulation of the models in the SBML Test Suite

    -

    - You can run the simulation of the models in the - SBML Test - Suite by using the command below. TestSuiteDirectory denotes - the directory containing your copy of the (entire) SBML test suite. - Here we assume that the actual test cases are located in the sub-folder - cases/semantic/ within the TestSuiteDirectory on your - computer. - The simulation is conducted for the models with numbers from first - to last (these numbers are the indices of the models in the test - suite, without leading zeros). -

    -
    
    -      java -cp SimulationCoreLibrary_vX.Y_incl-libs.jar org.simulator.SBMLTestSuiteRunner  TestSuiteDirectory/cases/semantic/ first last
    -    
    - Please note that, you have to replace _vX.Y_ within the library's - name by the current release number, e.g., 1.2. -

    - For example, if you like to simulate all test suite models ranging from - 00259 to 00326, simply call the algorithm with - first = 259 and last = 326. -

    -

    - Note that for the sake of a simple configuration, the simulation is - started using default settings for the selection of the - integration routine, step size etc. -

    - -

    Simulation of the models from BioModels database

    -

    - In a similar way, you can also download and simulate all models from - BioModels database: -

    
    -      java -cp SimulationCoreLibrary_vX.Y_incl-libs.jar org.simulator.TestBiomodels BioModelsDirectory/ first last
    -    
    - Again, you have to replace _vX.Y_ within the library's - name by the current release number, e.g., 1.2. Please use the variables - first and last without leading zeros as in the previous - case. The variable BioModelsDirectory gives the path to your local - copy of the BioModels database. -

    -

    - As in the previous case, the simulation is conducted using default - settings. +

    Simulation Core Library: Documentation

    + +

    About Simulation Core Library

    +

    + The Java™ API Simulation Core Library comprises a collection of + integrators for differential equation systems combined with an interpreter + for the Systems Biology Markup Language + (SBML). + It is the first simulation library that is based on + JSBML. + The user can read an SBML model and simulate it with one of the provided + numerical integration routines. All SBML levels and versions are + supported. + The library can easily be integrated into customized software, such as + parameter estimation tools. +

    + +

    The provided integration methods

    +

    + The Rosenbrock solver is best suitable for integrating stiff differential + equation systems and also has a precise timing of SBML events. It is taken + and adapted from Kotcon et al. + Several solvers have been taken from the + Apache Commons + Math Library and wrapped into our library: +

      +
    • Adams Bashforth
    • +
    • Adams Moulton
    • +
    • Dormand Prince 54
    • +
    • Dormand Prince 853
    • +
    • Gragg Bulirsch Stoer
    • +
    • Higham Hall 54
    • +
    + + The following solvers have been implemented additionally and are fast, but + not suitable for all differential equation systems: +
      +
    • Euler
    • +
    • Runge Kutta
    • +
    +

    + +

    Reading in a model and creating the respective differential equation + system

    +

    + A model can be read in by using the SBMLReader class of JSBML. + With the model in memory the SBMLinterpreter can create the + differential equation system that provides the basis for simulation: +

    +
    
    +      Model model = (new SBMLReader()).readSBML(sbmlfile).getModel();
    + SBMLinterpreter interpreter = new SBMLinterpreter(model); +
    + +

    Simulation of a differential equation system

    +

    + The created differential equation system can then be simulated with a + chosen solver and given time points. + The result is stored in a data structure called MultiTable. +

    +
    
    +      AbstractDESSolver solver = new RosenbrockSolver();
    + double[] timePoints = {0.0, 0.1, 0.2, 0.3, 0.4, 0.5};
    + MultiTable solution = solver.solve(interpreter, interpreter.getInitialValues(), timePoints); +
    + +

    Using SED-ML for simulation

    +

    + The following example shows how to read in a File f (in SED-ML + format) and how to run a simulation described in this file afterwards. + The simulation results are stored in a MultiTable. +

    + +
    
    +      SEDMLDocument doc = Libsedml.readDocument(f);
    + SedML sedml = doc.getSBMLModel();
    + Output wanted = sedml.getOutputs().get(0);
    + SedMLSBMLSimulatorExecutor exe = new SedMLSBMLSimulatorExecutor(sedml, wanted);
    + Map res = exe.runSimulations();
    + MultiTable solution = exe.processSimulationResults(wanted, res);
    +
    + +

    How to integrate Simulation Core Library into your software?

    +

    + You just have to add the provided jar-file simulation-core-library.jar to the class path of your Java project. + Then you have access to all classes of the library. + This library depends on the following third-party libraries: +

    + For SED-ML support, the following + additional libraries are required: + + Please make sure to include the correct third-party libraries into your + class path before working with this library. +

    + +

    Simulation of the models in the SBML Test Suite

    +

    + You can run the simulation of the models in the + SBML Test + Suite by using the command below. TestSuiteDirectory denotes + the directory containing your copy of the (entire) SBML test suite. + Here we assume that the actual test cases are located in the sub-folder + cases/semantic/ within the TestSuiteDirectory on your + computer. + The simulation is conducted for the models with numbers from first + to last (these numbers are the indices of the models in the test + suite, without leading zeros). +

    +
    
    +      java -cp SimulationCoreLibrary_vX.Y_incl-libs.jar org.simulator.SBMLTestSuiteRunner  TestSuiteDirectory/cases/semantic/ first last
    +    
    + Please note that, you have to replace _vX.Y_ within the library's + name by the current release number, e.g., 1.2. +

    + For example, if you like to simulate all test suite models ranging from + 00259 to 00326, simply call the algorithm with + first = 259 and last = 326. +

    +

    + Note that for the sake of a simple configuration, the simulation is + started using default settings for the selection of the + integration routine, step size etc. +

    + +

    Simulation of the models from BioModels database

    +

    + In a similar way, you can also download and simulate all models from + BioModels database: +

    
    +      java -cp SimulationCoreLibrary_vX.Y_incl-libs.jar org.simulator.TestBiomodels BioModelsDirectory/ first last
    +    
    + Again, you have to replace _vX.Y_ within the library's + name by the current release number, e.g., 1.2. Please use the variables + first and last without leading zeros as in the previous + case. The variable BioModelsDirectory gives the path to your local + copy of the BioModels database. +

    +

    + As in the previous case, the simulation is conducted using default + settings.

    diff --git a/src/site/resources/old_javadoc/version_1.3/overview-summary.html b/src/site/resources/old_javadoc/version_1.3/overview-summary.html index ab58b0b8..9c728a0c 100644 --- a/src/site/resources/old_javadoc/version_1.3/overview-summary.html +++ b/src/site/resources/old_javadoc/version_1.3/overview-summary.html @@ -84,13 +84,13 @@

    Systems Biology Simulation Core Library 1.3

    -Simulation Core Library: Documentation - - About Simulation Core Library - - The Java™ API Simulation Core Library comprises a collection of - integrators for differential equation systems combined with an interpreter - for the Systems Biology Markup Language +Simulation Core Library: Documentation + + About Simulation Core Library + + The Java™ API Simulation Core Library comprises a collection of + integrators for differential equation systems combined with an interpreter + for the Systems Biology Markup Language (SBML).

    See: @@ -157,228 +157,228 @@

     

    -

    Simulation Core Library: Documentation

    - -

    About Simulation Core Library

    -

    - The Java™ API Simulation Core Library comprises a collection of - integrators for differential equation systems combined with an interpreter - for the Systems Biology Markup Language - (SBML). - It is the first simulation library that is based on - JSBML. - The user can read an SBML model and simulate it with one of the provided - numerical integration routines. All SBML levels and versions are - supported. - The library can easily be integrated into customized software, such as - parameter estimation tools. -

    - -

    How to integrate Simulation Core Library into your software?

    -

    - You just have to add the provided jar-file simulation-core-library.jar to the class path of your Java project. - Then you have access to all classes of the library. - This library depends on the following third-party libraries: -

    - For SED-ML support, the following - additional libraries are required: - - Please make sure to include the correct third-party libraries into your - class path before working with this library. -

    - -

    The provided integration methods

    -

    - The RosenbrockSolver is best suitable for integrating stiff differential - equation systems and also has a precise timing of SBML events. It is taken - and adapted from - Kotcon et al. (2011) -

    - Several further solvers have been taken from the - Apache Commons - Math Library and wrapped into our library: -

    - - The following solvers have been implemented additionally and are fast, but - not suitable for all differential equation systems: - -

    - For a full list of available solvers, see org.simulator.math.odes. -

    - -

    Reading an SBML model and creating the respective differential equation - system

    -

    - A model can be read in by using the SBMLReader - class from JSBML. - With the model in memory the SBMLinterpreter - can create the differential equation system that provides the basis for - simulation: -

    -
    
    -      Model model = (new SBMLReader()).readSBML(sbmlfile).getModel();
    - SBMLinterpreter interpreter = new SBMLinterpreter(model); -
    -

    - For more documentation about working with SBML models in simulations see - org.simulator.sbml. -

    - -

    Simulation of a differential equation system

    -

    - The created differential equation system can then be simulated with a - chosen solver and given time points. - The result is stored in a data structure called - MultiTable. -

    -
    
    -      AbstractDESSolver solver = new RosenbrockSolver();
    - double[] timePoints = {0.0, 0.1, 0.2, 0.3, 0.4, 0.5};
    - MultiTable solution = solver.solve(interpreter, interpreter.getInitialValues(), timePoints); -
    - -

    Using SED-ML for simulation

    -

    - The following example shows how to read in a File f (in - SED-ML format) and how to run a simulation - described in this file afterwards. The simulation results are stored in a - MultiTable: -

    - -
    
    -      SEDMLDocument doc = Libsedml.readDocument(f);
    - SedML sedml = doc.getSBMLModel();
    - Output wanted = sedml.getOutputs().get(0);
    - SedMLSBMLSimulatorExecutor exe = new SedMLSBMLSimulatorExecutor(sedml, wanted);
    - Map res = exe.runSimulations();
    - MultiTable solution = exe.processSimulationResults(wanted, res);
    -
    - -

    - For more information about how to use SED-ML to execute your simulation - experiments, see org.simulator.sedml. -

    - -

    Simulation of the models in the SBML Test Suite

    -

    - You can run the simulation of the models in the - SBML Test - Suite by using the command below. TestSuiteDirectory denotes - the directory containing your copy of the (entire) SBML test suite. - Here we assume that the actual test cases are located in the sub-folder - cases/semantic/ within the TestSuiteDirectory on your - computer. - The simulation is conducted for the models with numbers from first - to last (these numbers are the indices of the models in the test - suite, without leading zeros). -

    -
    
    -      java -cp SimulationCoreLibrary_vX.Y_incl-libs.jar org.simulator.SBMLTestSuiteRunner TestSuiteDirectory/cases/semantic/ first last
    -    
    - Please note that, you have to replace _vX.Y_ within the library's - name by the current release number, e.g., 1.2. -

    - For example, if you like to simulate all test suite models ranging from - 00259 to 00326, simply call the algorithm with - first = 259 and last = 326. -

    - -

    - Note that for the sake of a simple configuration, the simulation is - started using default settings for the selection of the - integration routine, step size etc. -

    - -

    - The - SBML Test Suite Database - provides an up-to-date overview about the - capabilities of various SBML-compliant solver implementations. -

    - -

    Simulation of the models from BioModels database

    -

    - In a similar way, you can also download and simulate all models from - BioModels database: -

    
    -      java -cp SimulationCoreLibrary_vX.Y_incl-libs.jar org.simulator.TestBiomodels BioModelsDirectory/ first last
    -    
    - Again, you have to replace _vX.Y_ within the library's - name by the current release number, e.g., 1.2. Please use the variables - first and last without leading zeros as in the previous - case. The variable BioModelsDirectory gives the path to your local - copy of - BioModels database. -

    -

    - As in the previous case, the simulation is conducted using default - settings. -

    - -

    Listening to SBML constraint violation

    -

    - In version 1.3 a new listener interface has been added to - this library, which can be used to perform user-defined actions upon violation - of a Constraint's math expression during a simulation. - A simple implementation is already included in this package, - which logs violation at the - Level.WARNING using standard Java™ - logging (see Logger). - By default the - SBMLinterpreter adds this - SimpleConstraintListener to its internal list of - ConstraintListeners. -

    - -

    - You can remove this listener by calling the method - SBMLinterpreter.removeConstraintListener(int), - with the argument 0 for the first listener in the list, - and add your own listener implementation with the help of method - SBMLinterpreter.addConstraintListener(ConstraintListener). -

    -

    The following example demonstrates how you can easily define your customized - ConstraintListener: -

    
    -      double timeEnd = 5d;
    - SBMLDocument doc = SBMLReader.read(new File("path/to/file.xml"));
    - SBMLinterpreter interpreter = new SBMLinterpreter(doc.getModel());
    - interpreter.addConstraintListener(new ConstraintListener() {
    -   /* (non-Javadoc)
    -    * @see org.simulator.sbml.ConstraintListener#processViolation(org.simulator.sbml.ConstraintEvent)
    -    */

    -   public void processViolation(ConstraintEvent evt) {
    -     System.err.println("Constraint violated at time " + evt.getTime() + ": " + evt.getSource().getMath().toFormula());
    -   }
    - });
    - solver.solve(interpreter, interpreter.getInitialValues(), 0d, timeEnd); -
    -

    -

    - You can find more details about this topic in the description of package - org.simulator.sbml. +

    Simulation Core Library: Documentation

    + +

    About Simulation Core Library

    +

    + The Java™ API Simulation Core Library comprises a collection of + integrators for differential equation systems combined with an interpreter + for the Systems Biology Markup Language + (SBML). + It is the first simulation library that is based on + JSBML. + The user can read an SBML model and simulate it with one of the provided + numerical integration routines. All SBML levels and versions are + supported. + The library can easily be integrated into customized software, such as + parameter estimation tools. +

    + +

    How to integrate Simulation Core Library into your software?

    +

    + You just have to add the provided jar-file simulation-core-library.jar to the class path of your Java project. + Then you have access to all classes of the library. + This library depends on the following third-party libraries: +

    + For SED-ML support, the following + additional libraries are required: + + Please make sure to include the correct third-party libraries into your + class path before working with this library. +

    + +

    The provided integration methods

    +

    + The RosenbrockSolver is best suitable for integrating stiff differential + equation systems and also has a precise timing of SBML events. It is taken + and adapted from + Kotcon et al. (2011) +

    + Several further solvers have been taken from the + Apache Commons + Math Library and wrapped into our library: +

    + + The following solvers have been implemented additionally and are fast, but + not suitable for all differential equation systems: + +

    + For a full list of available solvers, see org.simulator.math.odes. +

    + +

    Reading an SBML model and creating the respective differential equation + system

    +

    + A model can be read in by using the SBMLReader + class from JSBML. + With the model in memory the SBMLinterpreter + can create the differential equation system that provides the basis for + simulation: +

    +
    
    +      Model model = (new SBMLReader()).readSBML(sbmlfile).getModel();
    + SBMLinterpreter interpreter = new SBMLinterpreter(model); +
    +

    + For more documentation about working with SBML models in simulations see + org.simulator.sbml. +

    + +

    Simulation of a differential equation system

    +

    + The created differential equation system can then be simulated with a + chosen solver and given time points. + The result is stored in a data structure called + MultiTable. +

    +
    
    +      AbstractDESSolver solver = new RosenbrockSolver();
    + double[] timePoints = {0.0, 0.1, 0.2, 0.3, 0.4, 0.5};
    + MultiTable solution = solver.solve(interpreter, interpreter.getInitialValues(), timePoints); +
    + +

    Using SED-ML for simulation

    +

    + The following example shows how to read in a File f (in + SED-ML format) and how to run a simulation + described in this file afterwards. The simulation results are stored in a + MultiTable: +

    + +
    
    +      SEDMLDocument doc = Libsedml.readDocument(f);
    + SedML sedml = doc.getSBMLModel();
    + Output wanted = sedml.getOutputs().get(0);
    + SedMLSBMLSimulatorExecutor exe = new SedMLSBMLSimulatorExecutor(sedml, wanted);
    + Map res = exe.runSimulations();
    + MultiTable solution = exe.processSimulationResults(wanted, res);
    +
    + +

    + For more information about how to use SED-ML to execute your simulation + experiments, see org.simulator.sedml. +

    + +

    Simulation of the models in the SBML Test Suite

    +

    + You can run the simulation of the models in the + SBML Test + Suite by using the command below. TestSuiteDirectory denotes + the directory containing your copy of the (entire) SBML test suite. + Here we assume that the actual test cases are located in the sub-folder + cases/semantic/ within the TestSuiteDirectory on your + computer. + The simulation is conducted for the models with numbers from first + to last (these numbers are the indices of the models in the test + suite, without leading zeros). +

    +
    
    +      java -cp SimulationCoreLibrary_vX.Y_incl-libs.jar org.simulator.SBMLTestSuiteRunner TestSuiteDirectory/cases/semantic/ first last
    +    
    + Please note that, you have to replace _vX.Y_ within the library's + name by the current release number, e.g., 1.2. +

    + For example, if you like to simulate all test suite models ranging from + 00259 to 00326, simply call the algorithm with + first = 259 and last = 326. +

    + +

    + Note that for the sake of a simple configuration, the simulation is + started using default settings for the selection of the + integration routine, step size etc. +

    + +

    + The + SBML Test Suite Database + provides an up-to-date overview about the + capabilities of various SBML-compliant solver implementations. +

    + +

    Simulation of the models from BioModels database

    +

    + In a similar way, you can also download and simulate all models from + BioModels database: +

    
    +      java -cp SimulationCoreLibrary_vX.Y_incl-libs.jar org.simulator.TestBiomodels BioModelsDirectory/ first last
    +    
    + Again, you have to replace _vX.Y_ within the library's + name by the current release number, e.g., 1.2. Please use the variables + first and last without leading zeros as in the previous + case. The variable BioModelsDirectory gives the path to your local + copy of + BioModels database. +

    +

    + As in the previous case, the simulation is conducted using default + settings. +

    + +

    Listening to SBML constraint violation

    +

    + In version 1.3 a new listener interface has been added to + this library, which can be used to perform user-defined actions upon violation + of a Constraint's math expression during a simulation. + A simple implementation is already included in this package, + which logs violation at the + Level.WARNING using standard Java™ + logging (see Logger). + By default the + SBMLinterpreter adds this + SimpleConstraintListener to its internal list of + ConstraintListeners. +

    + +

    + You can remove this listener by calling the method + SBMLinterpreter.removeConstraintListener(int), + with the argument 0 for the first listener in the list, + and add your own listener implementation with the help of method + SBMLinterpreter.addConstraintListener(ConstraintListener). +

    +

    The following example demonstrates how you can easily define your customized + ConstraintListener: +

    
    +      double timeEnd = 5d;
    + SBMLDocument doc = SBMLReader.read(new File("path/to/file.xml"));
    + SBMLinterpreter interpreter = new SBMLinterpreter(doc.getModel());
    + interpreter.addConstraintListener(new ConstraintListener() {
    +   /* (non-Javadoc)
    +    * @see org.simulator.sbml.ConstraintListener#processViolation(org.simulator.sbml.ConstraintEvent)
    +    */

    +   public void processViolation(ConstraintEvent evt) {
    +     System.err.println("Constraint violated at time " + evt.getTime() + ": " + evt.getSource().getMath().toFormula());
    +   }
    + });
    + solver.solve(interpreter, interpreter.getInitialValues(), 0d, timeEnd); +
    +

    +

    + You can find more details about this topic in the description of package + org.simulator.sbml.

    diff --git a/src/site/resources/old_javadoc/version_1.4/overview-summary.html b/src/site/resources/old_javadoc/version_1.4/overview-summary.html index ea78afe6..8f16363a 100644 --- a/src/site/resources/old_javadoc/version_1.4/overview-summary.html +++ b/src/site/resources/old_javadoc/version_1.4/overview-summary.html @@ -84,13 +84,13 @@

    Systems Biology Simulation Core Library 1.4

    -Simulation Core Library: Documentation - - About Simulation Core Library - - The Java™ API Simulation Core Library comprises a collection of - integrators for differential equation systems combined with an interpreter - for the Systems Biology Markup Language +Simulation Core Library: Documentation + + About Simulation Core Library + + The Java™ API Simulation Core Library comprises a collection of + integrators for differential equation systems combined with an interpreter + for the Systems Biology Markup Language (SBML).

    See: @@ -157,238 +157,238 @@

     

    -

    Simulation Core Library: Documentation

    - -

    About Simulation Core Library

    -

    - The Java™ API Simulation Core Library comprises a collection of - integrators for differential equation systems combined with an interpreter - for the Systems Biology Markup Language - (SBML). - It is the first simulation library that is based on - JSBML. - The user can read an SBML model and simulate it with one of the provided - numerical integration routines. All SBML levels and versions are - supported. - The library can easily be integrated into customized software, such as - parameter estimation tools. -

    -

    - When using the Simulation Core Library, please cite:
    - Roland Keller, Alexander Dörr, Akito Tabira, Akira Funahashi, Michael - J. Ziller, Richard Adams, Nicolas Rodriguez, Nicolas Le Novère, - Noriko Hiroi, Hannes Planatscher, Andreas Zell, and Andreas Dräger. - The systems biology simulation core algorithm. BMC Systems Biology, 7:55, - July 2013. [ DOI | - link | - pdf ] -

    - -

    How to integrate Simulation Core Library into your software?

    -

    - You just have to add the provided jar-file simulation-core-library.jar to the class path of your Java project. - Then you have access to all classes of the library. - This library depends on the following third-party libraries: -

    - For SED-ML support, the following - additional libraries are required: - - Please make sure to include the correct third-party libraries into your - class path before working with this library. -

    - -

    The provided integration methods

    -

    - The RosenbrockSolver is best suitable for integrating stiff differential - equation systems and also has a precise timing of SBML events. It is taken - and adapted from - Kotcon et al. (2011) -

    - Several further solvers have been taken from the - Apache Commons - Math Library and wrapped into our library: -

    - - The following solvers have been implemented additionally and are fast, but - not suitable for all differential equation systems: - -

    - For a full list of available solvers, see org.simulator.math.odes. -

    - -

    Reading an SBML model and creating the respective differential equation - system

    -

    - A model can be read in by using the SBMLReader - class from JSBML. - With the model in memory the SBMLinterpreter - can create the differential equation system that provides the basis for - simulation: -

    -
    
    -      Model model = (new SBMLReader()).readSBML(sbmlfile).getModel();
    - SBMLinterpreter interpreter = new SBMLinterpreter(model); -
    -

    - For more documentation about working with SBML models in simulations see - org.simulator.sbml. -

    - -

    Simulation of a differential equation system

    -

    - The created differential equation system can then be simulated with a - chosen solver and given time points. - The result is stored in a data structure called - MultiTable. -

    -
    
    -      AbstractDESSolver solver = new RosenbrockSolver();
    - double[] timePoints = {0.0, 0.1, 0.2, 0.3, 0.4, 0.5};
    - MultiTable solution = solver.solve(interpreter, interpreter.getInitialValues(), timePoints); -
    - -

    Using SED-ML for simulation

    -

    - The following example shows how to read in a File f (in - SED-ML format) and how to run a simulation - described in this file afterwards. The simulation results are stored in a - MultiTable: -

    - -
    
    -      SEDMLDocument doc = Libsedml.readDocument(f);
    - SedML sedml = doc.getSBMLModel();
    - Output wanted = sedml.getOutputs().get(0);
    - SedMLSBMLSimulatorExecutor exe = new SedMLSBMLSimulatorExecutor(sedml, wanted);
    - Map res = exe.runSimulations();
    - MultiTable solution = exe.processSimulationResults(wanted, res);
    -
    - -

    - For more information about how to use SED-ML to execute your simulation - experiments, see org.simulator.sedml. -

    - -

    Simulation of the models in the SBML Test Suite

    -

    - You can run the simulation of the models in the - SBML Test - Suite by using the command below. TestSuiteDirectory denotes - the directory containing your copy of the (entire) SBML test suite. - Here we assume that the actual test cases are located in the sub-folder - cases/semantic/ within the TestSuiteDirectory on your - computer. - The simulation is conducted for the models with numbers from first - to last (these numbers are the indices of the models in the test - suite, without leading zeros). -

    -
    
    -      java -cp SimulationCoreLibrary_vX.Y_incl-libs.jar org.simulator.SBMLTestSuiteRunner TestSuiteDirectory/cases/semantic/ first last
    -    
    - Please note that, you have to replace _vX.Y_ within the library's - name by the current release number, e.g., 1.2. -

    - For example, if you like to simulate all test suite models ranging from - 00259 to 00326, simply call the algorithm with - first = 259 and last = 326. -

    - -

    - Note that for the sake of a simple configuration, the simulation is - started using default settings for the selection of the - integration routine, step size etc. -

    - -

    - The - SBML Test Suite Database - provides an up-to-date overview about the - capabilities of various SBML-compliant solver implementations. -

    - -

    Simulation of the models from BioModels database

    -

    - In a similar way, you can also download and simulate all models from - BioModels database: -

    
    -      java -cp SimulationCoreLibrary_vX.Y_incl-libs.jar org.simulator.TestBiomodels BioModelsDirectory/ first last
    -    
    - Again, you have to replace _vX.Y_ within the library's - name by the current release number, e.g., 1.2. Please use the variables - first and last without leading zeros as in the previous - case. The variable BioModelsDirectory gives the path to your local - copy of - BioModels database. -

    -

    - As in the previous case, the simulation is conducted using default - settings. -

    - -

    Listening to SBML constraint violation

    -

    - In version 1.3 a new listener interface has been added to - this library, which can be used to perform user-defined actions upon violation - of a Constraint's math expression during a simulation. - A simple implementation is already included in this package, - which logs violation at the - Level.WARNING using standard Java™ - logging (see Logger). - By default the - SBMLinterpreter adds this - SimpleConstraintListener to its internal list of - ConstraintListeners. -

    - -

    - You can remove this listener by calling the method - SBMLinterpreter.removeConstraintListener(int), - with the argument 0 for the first listener in the list, - and add your own listener implementation with the help of method - SBMLinterpreter.addConstraintListener(ConstraintListener). -

    -

    The following example demonstrates how you can easily define your customized - ConstraintListener: -

    
    -      double timeEnd = 5d;
    - SBMLDocument doc = SBMLReader.read(new File("path/to/file.xml"));
    - SBMLinterpreter interpreter = new SBMLinterpreter(doc.getModel());
    - interpreter.addConstraintListener(new ConstraintListener() {
    -   /* (non-Javadoc)
    -    * @see org.simulator.sbml.ConstraintListener#processViolation(org.simulator.sbml.ConstraintEvent)
    -    */

    -   public void processViolation(ConstraintEvent evt) {
    -     System.err.println("Constraint violated at time " + evt.getTime() + ": " + evt.getSource().getMath().toFormula());
    -   }
    - });
    - solver.solve(interpreter, interpreter.getInitialValues(), 0d, timeEnd); -
    -

    -

    - You can find more details about this topic in the description of package - org.simulator.sbml. +

    Simulation Core Library: Documentation

    + +

    About Simulation Core Library

    +

    + The Java™ API Simulation Core Library comprises a collection of + integrators for differential equation systems combined with an interpreter + for the Systems Biology Markup Language + (SBML). + It is the first simulation library that is based on + JSBML. + The user can read an SBML model and simulate it with one of the provided + numerical integration routines. All SBML levels and versions are + supported. + The library can easily be integrated into customized software, such as + parameter estimation tools. +

    +

    + When using the Simulation Core Library, please cite:
    + Roland Keller, Alexander Dörr, Akito Tabira, Akira Funahashi, Michael + J. Ziller, Richard Adams, Nicolas Rodriguez, Nicolas Le Novère, + Noriko Hiroi, Hannes Planatscher, Andreas Zell, and Andreas Dräger. + The systems biology simulation core algorithm. BMC Systems Biology, 7:55, + July 2013. [ DOI | + link | + pdf ] +

    + +

    How to integrate Simulation Core Library into your software?

    +

    + You just have to add the provided jar-file simulation-core-library.jar to the class path of your Java project. + Then you have access to all classes of the library. + This library depends on the following third-party libraries: +

    + For SED-ML support, the following + additional libraries are required: + + Please make sure to include the correct third-party libraries into your + class path before working with this library. +

    + +

    The provided integration methods

    +

    + The RosenbrockSolver is best suitable for integrating stiff differential + equation systems and also has a precise timing of SBML events. It is taken + and adapted from + Kotcon et al. (2011) +

    + Several further solvers have been taken from the + Apache Commons + Math Library and wrapped into our library: +

    + + The following solvers have been implemented additionally and are fast, but + not suitable for all differential equation systems: + +

    + For a full list of available solvers, see org.simulator.math.odes. +

    + +

    Reading an SBML model and creating the respective differential equation + system

    +

    + A model can be read in by using the SBMLReader + class from JSBML. + With the model in memory the SBMLinterpreter + can create the differential equation system that provides the basis for + simulation: +

    +
    
    +      Model model = (new SBMLReader()).readSBML(sbmlfile).getModel();
    + SBMLinterpreter interpreter = new SBMLinterpreter(model); +
    +

    + For more documentation about working with SBML models in simulations see + org.simulator.sbml. +

    + +

    Simulation of a differential equation system

    +

    + The created differential equation system can then be simulated with a + chosen solver and given time points. + The result is stored in a data structure called + MultiTable. +

    +
    
    +      AbstractDESSolver solver = new RosenbrockSolver();
    + double[] timePoints = {0.0, 0.1, 0.2, 0.3, 0.4, 0.5};
    + MultiTable solution = solver.solve(interpreter, interpreter.getInitialValues(), timePoints); +
    + +

    Using SED-ML for simulation

    +

    + The following example shows how to read in a File f (in + SED-ML format) and how to run a simulation + described in this file afterwards. The simulation results are stored in a + MultiTable: +

    + +
    
    +      SEDMLDocument doc = Libsedml.readDocument(f);
    + SedML sedml = doc.getSBMLModel();
    + Output wanted = sedml.getOutputs().get(0);
    + SedMLSBMLSimulatorExecutor exe = new SedMLSBMLSimulatorExecutor(sedml, wanted);
    + Map res = exe.runSimulations();
    + MultiTable solution = exe.processSimulationResults(wanted, res);
    +
    + +

    + For more information about how to use SED-ML to execute your simulation + experiments, see org.simulator.sedml. +

    + +

    Simulation of the models in the SBML Test Suite

    +

    + You can run the simulation of the models in the + SBML Test + Suite by using the command below. TestSuiteDirectory denotes + the directory containing your copy of the (entire) SBML test suite. + Here we assume that the actual test cases are located in the sub-folder + cases/semantic/ within the TestSuiteDirectory on your + computer. + The simulation is conducted for the models with numbers from first + to last (these numbers are the indices of the models in the test + suite, without leading zeros). +

    +
    
    +      java -cp SimulationCoreLibrary_vX.Y_incl-libs.jar org.simulator.SBMLTestSuiteRunner TestSuiteDirectory/cases/semantic/ first last
    +    
    + Please note that, you have to replace _vX.Y_ within the library's + name by the current release number, e.g., 1.2. +

    + For example, if you like to simulate all test suite models ranging from + 00259 to 00326, simply call the algorithm with + first = 259 and last = 326. +

    + +

    + Note that for the sake of a simple configuration, the simulation is + started using default settings for the selection of the + integration routine, step size etc. +

    + +

    + The + SBML Test Suite Database + provides an up-to-date overview about the + capabilities of various SBML-compliant solver implementations. +

    + +

    Simulation of the models from BioModels database

    +

    + In a similar way, you can also download and simulate all models from + BioModels database: +

    
    +      java -cp SimulationCoreLibrary_vX.Y_incl-libs.jar org.simulator.TestBiomodels BioModelsDirectory/ first last
    +    
    + Again, you have to replace _vX.Y_ within the library's + name by the current release number, e.g., 1.2. Please use the variables + first and last without leading zeros as in the previous + case. The variable BioModelsDirectory gives the path to your local + copy of + BioModels database. +

    +

    + As in the previous case, the simulation is conducted using default + settings. +

    + +

    Listening to SBML constraint violation

    +

    + In version 1.3 a new listener interface has been added to + this library, which can be used to perform user-defined actions upon violation + of a Constraint's math expression during a simulation. + A simple implementation is already included in this package, + which logs violation at the + Level.WARNING using standard Java™ + logging (see Logger). + By default the + SBMLinterpreter adds this + SimpleConstraintListener to its internal list of + ConstraintListeners. +

    + +

    + You can remove this listener by calling the method + SBMLinterpreter.removeConstraintListener(int), + with the argument 0 for the first listener in the list, + and add your own listener implementation with the help of method + SBMLinterpreter.addConstraintListener(ConstraintListener). +

    +

    The following example demonstrates how you can easily define your customized + ConstraintListener: +

    
    +      double timeEnd = 5d;
    + SBMLDocument doc = SBMLReader.read(new File("path/to/file.xml"));
    + SBMLinterpreter interpreter = new SBMLinterpreter(doc.getModel());
    + interpreter.addConstraintListener(new ConstraintListener() {
    +   /* (non-Javadoc)
    +    * @see org.simulator.sbml.ConstraintListener#processViolation(org.simulator.sbml.ConstraintEvent)
    +    */

    +   public void processViolation(ConstraintEvent evt) {
    +     System.err.println("Constraint violated at time " + evt.getTime() + ": " + evt.getSource().getMath().toFormula());
    +   }
    + });
    + solver.solve(interpreter, interpreter.getInitialValues(), 0d, timeEnd); +
    +

    +

    + You can find more details about this topic in the description of package + org.simulator.sbml.

    diff --git a/src/site/resources/publications/2012_BMC_SystBiol/readme.html b/src/site/resources/publications/2012_BMC_SystBiol/readme.html index 93095a2f..2108a857 100755 --- a/src/site/resources/publications/2012_BMC_SystBiol/readme.html +++ b/src/site/resources/publications/2012_BMC_SystBiol/readme.html @@ -1,237 +1,237 @@ - - - -BioMed Central TeX template files - - - -

    BioMed Central TeX template  - Version 0.4 (January 27th 2006)

    -

    1 BioMed Central LaTeX template distribution

    - - - - - - - - - - - - - - - - - - - - - -
    -

    bmc_article.tex

    -
    -

    The BioMed Central  manuscript template. - Edit a copy of this file.

    -
    -

    bmc_article.bib

    -
    -

    A sample BibTeX bibliography file used to create a .bbl by BibTeX using the bmc_article.bst file

    -
    -

    bmc_article.bst

    -
    -

    The BibTeX bibliography style file - for the BioMed Central reference format

    -
    -

    bmc_article.cls

    -
    -

    Page layout for for manuscripts. This makes small - changes to the standard article template

    -
    -

    readme.html

    -
    -

    This document.

    -
    -

     

    -

     

    -

    2 Requirements

    -

    2.1

    -

    The BioMed Central TeX template - should work with TeX distributions on any platform – it has been tested with - TeXShop on Mac OS - X and MiKTeX for Windows.

    -

    2.2

    -

    In order to submit a manuscript - as a .tex file to BioMed Central, you must

    -
      -
    • use the BioMed Central template
    • -
    • format your references with BibTeX using - the bmc_article.bst style file
    • -
    • not rely on any non-standard macros, - classes or files
    • -
    -

    If your TeX manuscript does not - meet the criteria above it will need to be converted to DVI format prior to - submission.

    -

    2 Guidelines for creating your manuscript using TeX

    -

    2.1

    -

    Follow the guidelines in the BioMed Central instructions - for authors given at http://www.biomedcentral.com/info/authors/

    -

    2.2

    -

    Make - sure your manuscript is compiled with LaTeX2e by using documentclass{.. - . } and not documentstyle{. . . } in the preamble at the top of your - .tex document.

    -

    A template manuscript is supplied entitled bmc_article.tex which -sets up the preferred page layout based on the standard article.cls. Two different styles are supplied; Review Style, which produces single column double spaced text, and Publication Style which produces two-column text. They can be toggled by commenting or uncommenting the relevant lines in the TeX file. -

    -

    2.3

    -

    Make sure that you only a single .tex document - for the entire manuscript, as you will need to upload it as a single file (together - with its associated formatted bibliography file) . Do not use the \input command to include other .tex files.

    -

    2.4

    -

    The BioMed Central template uses the cite.sty - citation style and url.sty for url references. It also uses ifthen.sty and multicol.sty You should also use these - during the creation of your manuscript.

    -

    See

    -

    http://www.ctan.org/tex-archive/macros/latex/contrib/cite/cite.sty, -
    - http://www.ctan.org/tex-archive/macros/latex/contrib/misc/url.sty

    - http://www.ctan.org/tex-archive/macros/latex/unpacked/ifthen.sty
    - http://www.ctan.org/tex-archive/macros/latex209/contrib/geomsty/multicol.sty

    -

    for these style files if they are not in your local - archive.

    -

    cite.sty turns [1,2,3,4] into [1-4].

    -

    url.sty formats urls so they can be broken down - cleanly when overflowing the right text boundary.

    -

    3 BibTeX

    -

    References must be formatted with BibTeX using - the BioMed Central style file.

    -

    i.e. when using the template, do not alter the command: - \bibliographystyle{bmc_article}

    -

    The bibliography datafile is referred to with \bibliography{datafile1, - . . . , . . . }

    -

    The template makes use of a sample bibliography called - bmc_article.bib - you should update the \bibliography tag to - refer to your own bibliography.

    -

    4 Notes on uploading your manuscript

    -

    4.1

    -

    Make sure you are submitting only one .tex document - Please note that figures, large tables and any other - reference material should be submitted as separate files, not embedded in the - manuscript.

    -

    4.2

    -

    A .bbl file is generated when you use BibTeX - to format your article's reference list. It contains formatted details of all - references used in the manuscript. After uploading a TeX file to BioMed Central, - you will then be prompted to upload the .bbl file which goes with it..
    -

    -

    5 The TeX article layout

    -

    This is the sectioning for a BMC-series Research Article l - manuscript submission . . .
    For other types of articles or for non-BMC series journals, see the relevant section headings at http://www.biomedcentral.com/info/authors/

    -

    • Abstract

    -

    – Background

    -

    – Results

    -

    – Conclusions

    -

    • Background

    -

    • Methods

    -

    • Results and Discussion

    -

    • Conclusions

    -• Authors contributions

    -

    • Acknowledgements

    -

    • References

    -

    • Figures

    -

    • Tables

    -

    • Additional files

    -

    5 Further information

    -

    The latest version of the BioMed Central TeX - template distribution, and full instructions on its use, are available here:

    -

    http://www.biomedcentral.com/info/ifora/tex/

    - - + + + +BioMed Central TeX template files + + + +

    BioMed Central TeX template  - Version 0.4 (January 27th 2006)

    +

    1 BioMed Central LaTeX template distribution

    + + + + + + + + + + + + + + + + + + + + + +
    +

    bmc_article.tex

    +
    +

    The BioMed Central  manuscript template. + Edit a copy of this file.

    +
    +

    bmc_article.bib

    +
    +

    A sample BibTeX bibliography file used to create a .bbl by BibTeX using the bmc_article.bst file

    +
    +

    bmc_article.bst

    +
    +

    The BibTeX bibliography style file + for the BioMed Central reference format

    +
    +

    bmc_article.cls

    +
    +

    Page layout for for manuscripts. This makes small + changes to the standard article template

    +
    +

    readme.html

    +
    +

    This document.

    +
    +

     

    +

     

    +

    2 Requirements

    +

    2.1

    +

    The BioMed Central TeX template + should work with TeX distributions on any platform – it has been tested with + TeXShop on Mac OS + X and MiKTeX for Windows.

    +

    2.2

    +

    In order to submit a manuscript + as a .tex file to BioMed Central, you must

    +
      +
    • use the BioMed Central template
    • +
    • format your references with BibTeX using + the bmc_article.bst style file
    • +
    • not rely on any non-standard macros, + classes or files
    • +
    +

    If your TeX manuscript does not + meet the criteria above it will need to be converted to DVI format prior to + submission.

    +

    2 Guidelines for creating your manuscript using TeX

    +

    2.1

    +

    Follow the guidelines in the BioMed Central instructions + for authors given at http://www.biomedcentral.com/info/authors/

    +

    2.2

    +

    Make + sure your manuscript is compiled with LaTeX2e by using documentclass{.. + . } and not documentstyle{. . . } in the preamble at the top of your + .tex document.

    +

    A template manuscript is supplied entitled bmc_article.tex which +sets up the preferred page layout based on the standard article.cls. Two different styles are supplied; Review Style, which produces single column double spaced text, and Publication Style which produces two-column text. They can be toggled by commenting or uncommenting the relevant lines in the TeX file. +

    +

    2.3

    +

    Make sure that you only a single .tex document + for the entire manuscript, as you will need to upload it as a single file (together + with its associated formatted bibliography file) . Do not use the \input command to include other .tex files.

    +

    2.4

    +

    The BioMed Central template uses the cite.sty + citation style and url.sty for url references. It also uses ifthen.sty and multicol.sty You should also use these + during the creation of your manuscript.

    +

    See

    +

    http://www.ctan.org/tex-archive/macros/latex/contrib/cite/cite.sty, +
    + http://www.ctan.org/tex-archive/macros/latex/contrib/misc/url.sty

    + http://www.ctan.org/tex-archive/macros/latex/unpacked/ifthen.sty
    + http://www.ctan.org/tex-archive/macros/latex209/contrib/geomsty/multicol.sty

    +

    for these style files if they are not in your local + archive.

    +

    cite.sty turns [1,2,3,4] into [1-4].

    +

    url.sty formats urls so they can be broken down + cleanly when overflowing the right text boundary.

    +

    3 BibTeX

    +

    References must be formatted with BibTeX using + the BioMed Central style file.

    +

    i.e. when using the template, do not alter the command: + \bibliographystyle{bmc_article}

    +

    The bibliography datafile is referred to with \bibliography{datafile1, + . . . , . . . }

    +

    The template makes use of a sample bibliography called + bmc_article.bib - you should update the \bibliography tag to + refer to your own bibliography.

    +

    4 Notes on uploading your manuscript

    +

    4.1

    +

    Make sure you are submitting only one .tex document + Please note that figures, large tables and any other + reference material should be submitted as separate files, not embedded in the + manuscript.

    +

    4.2

    +

    A .bbl file is generated when you use BibTeX + to format your article's reference list. It contains formatted details of all + references used in the manuscript. After uploading a TeX file to BioMed Central, + you will then be prompted to upload the .bbl file which goes with it..
    +

    +

    5 The TeX article layout

    +

    This is the sectioning for a BMC-series Research Article l + manuscript submission . . .
    For other types of articles or for non-BMC series journals, see the relevant section headings at http://www.biomedcentral.com/info/authors/

    +

    • Abstract

    +

    – Background

    +

    – Results

    +

    – Conclusions

    +

    • Background

    +

    • Methods

    +

    • Results and Discussion

    +

    • Conclusions

    +• Authors contributions

    +

    • Acknowledgements

    +

    • References

    +

    • Figures

    +

    • Tables

    +

    • Additional files

    +

    5 Further information

    +

    The latest version of the BioMed Central TeX + template distribution, and full instructions on its use, are available here:

    +

    http://www.biomedcentral.com/info/ifora/tex/

    + + diff --git a/src/test/java/GnuplotTest.java b/src/test/java/GnuplotTest.java new file mode 100644 index 00000000..0c6cee34 --- /dev/null +++ b/src/test/java/GnuplotTest.java @@ -0,0 +1,28 @@ +import java.io.IOException; + +import fern.tools.gnuplot.GnuPlot; + +public class GnuplotTest { + + /** + * @param args + * @throws IOException + */ + public static void main(String[] args) throws IOException { + GnuPlot gp = new GnuPlot(); + double[][] matrix = { + {0,1,1}, + {1,1,2}, + {2,1,3}, + {1,2,4}, + {2,2,5}, + {3,2,6}, + }; + gp.addData(matrix,new String[]{"A","B"},null); + gp.setDefaultStyle("with linespoints"); + + gp.setVisible(true); + gp.plot(); + } + +} diff --git a/src/test/java/RNMLTest.java b/src/test/java/RNMLTest.java new file mode 100644 index 00000000..801fdece --- /dev/null +++ b/src/test/java/RNMLTest.java @@ -0,0 +1,88 @@ +import java.io.File; +import java.io.IOException; +import java.io.PrintWriter; + +import javax.xml.parsers.ParserConfigurationException; + +import org.jdom.JDOMException; +import org.xml.sax.SAXException; + +import fern.analysis.AutocatalyticNetworkDetection; +import fern.analysis.NodeChecker; +import fern.analysis.NodeCheckerByAnnotation; +import fern.analysis.ShortestPath; +import fern.network.FeatureNotSupportedException; +import fern.network.Network; +import fern.network.creation.AutocatalyticNetwork; +import fern.network.modification.ExtractSubNetwork; +import fern.network.modification.ReversibleNetwork; +//import fern.network.rnml.RNMLNetwork; +import fern.network.sbml.SBMLNetwork; +import fern.tools.Stochastics; +import fern.tools.NetworkTools; +import fern.tools.functions.Probability; + +public class RNMLTest { + + /** + * @param args + * @throws IOException + * @throws SAXException + * @throws ParserConfigurationException + * @throws JDOMException + * @throws FeatureNotSupportedException + */ + public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException, JDOMException, FeatureNotSupportedException { +// Network net = new SBMLNetwork(new File("test/data/l2v1-mm.xml")); +// NetworkDump.dump(net, new PrintWriter(System.out)); +// +// RNMLNetwork net2 = new RNMLNetwork(net, null); +// NetworkDump.dump(net2, new PrintWriter(System.out)); +// net2.saveToFile(new File("test/data/rnml/saved.xml")); + + Stochastics.getInstance().setSeed(1174567215984L); + + AutocatalyticNetwork net = new AutocatalyticNetwork( + new char[] {'A','B'}, + new Probability.Constant(1), + new Probability.Constant(1.0/(14.0)), + 3 + ); + + Network netR = new ReversibleNetwork(net, net.getReversePropensityCalculator()); + System.out.println("OriginalNetwork:"); + NetworkTools.dumpNetwork(netR, new PrintWriter(System.out)); + System.out.println("................................................"); + + AutocatalyticNetworkDetection detection = new AutocatalyticNetworkDetection(netR); + detection.detect(); + detection.annotate("Autocatalytic", "yes"); + Network autoNet = new ExtractSubNetwork(netR,detection.getAutocatalyticReactions(), detection.getAutocatalyticSpecies()); + + System.out.println(); + System.out.println("Autocatalytic Subnet"); + NetworkTools.dumpNetwork(autoNet, new PrintWriter(System.out)); + + System.out.println("Seed: "+Stochastics.getInstance().getSeed()); + +// NodeChecker checker = new NodeCheckerByAnnotation("Autocatalytic","yes"); +// +// ShortestPath sp = new ShortestPath(netR); +// for (ShortestPath.Path path : sp.computePaths(checker, "A","B")) +// System.out.println(path.toString()); + + +// ShortestPath sp = new ShortestPath(netR); +// int[] dist = sp.compute("A","B"); +// for (int i=0; iPreferences>Java>Code Generation>Code and Comments + */ + +import java.io.File; +import java.io.IOException; + +import fern.network.AnnotationManager; +import fern.network.FeatureNotSupportedException; +import fern.network.sbml.SBMLNetwork; +import org.sbml.jsbml.validator.ModelOverdeterminedException; + +import javax.xml.stream.XMLStreamException; + + +public class SBMLNetworkTest { + + /** + * @param args + * @throws FeatureNotSupportedException + */ + public static void main(String[] args) throws FeatureNotSupportedException, IOException, XMLStreamException, ModelOverdeterminedException { + SBMLNetwork net = new SBMLNetwork(new File("test/data/l1v1-minimal.xml")); + + for (int r = 0; r data() { @Test - public void testModel() throws FileNotFoundException, IOException, XMLStreamException { + public void testModel() throws IOException { String[] failedTests = new String[]{ "01126", "01127", "01129", "01130", "01131", "01132", "01133", "01134", "01140", "01142", "01143", "01144", "01145", "01148", "01149", "01151", "01154", "01155", "01156", "01157", "01158", "01159", "01160", "01161", "01162", "01164", "01166", "01169", "01170", "01174", "01175", "01176", "01178", "01180", "01181", "01182", "01183", "01344", "01345", "01346", "01347", "01348", "01349", "01350", "01351", "01352", "01355", "01356", "01358", "01359", "01360", "01364", "01365", "01367", "01368", "01369", "01371", "01372", "01373", "01374", "01375", "01376", "01377", "01378", "01379", "01380", "01381", "01382", "01383", "01384", "01385", "01386", "01387", "01388", "01389", "01468", "01469", "01470", "01474", // failed due to comp flattening (see issue #36) "01153", // (comp model) failing with IllegalArgumentException: Cannot set duplicate meta identifier "01165", "01167", "01168", "01471", "01472", "01473", "01475", "01476", "01477", "01778", // (comp model) failing with FileNotFoundException: enzyme_model.xml (No such file or directory) - "01198", "01462", "01478", "01498", "01504", "01505", "01506", "01507", "01508", "01509", "01510", "01511", "01512", "01513", "01514", // sbml model with changing compartment size (see issue #50) - "01208", + "01507", "01508", "01511", // sbml model with changing compartment size (see issue #50) "01287", "01592", // failing due to long run time (see issue #39) "01400", "01401", "01403", "01406", "01409", // failing due to delay in rateOf (see issue #46) "01444", "01445", "01446", "01447", "01448", // failing due to event triggers before mentioned condition (see issue #44) - "01454", "01456", "01480", "01481", // model below sbml l3v1 diff --git a/src/test/java/org/simulator/stochastic/StochasticTestSuiteTest.java b/src/test/java/org/simulator/stochastic/StochasticTestSuiteTest.java new file mode 100644 index 00000000..6067b6e6 --- /dev/null +++ b/src/test/java/org/simulator/stochastic/StochasticTestSuiteTest.java @@ -0,0 +1,385 @@ +package org.simulator.stochastic; + +import fern.network.FeatureNotSupportedException; +import fern.network.Network; +import fern.simulation.Simulator; +import fern.simulation.algorithm.AbstractBaseTauLeaping; +import fern.simulation.algorithm.GillespieEnhanced; +import fern.simulation.algorithm.HybridMaximalTimeStep; +import fern.simulation.algorithm.TauLeapingSpeciesPopulationBoundSimulator; +import fern.simulation.observer.AmountIntervalObserver; +import fern.tools.NetworkTools; +import fern.tools.NumberTools; +import fern.tools.gnuplot.GnuPlot; +import org.jdom.JDOMException; +import org.junit.Assert; +import org.junit.Ignore; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; +import org.sbml.jsbml.Model; +import org.sbml.jsbml.xml.stax.SBMLReader; +import org.simulator.TestUtils; +import org.simulator.io.CSVImporter; +import org.simulator.math.odes.MultiTable; +import org.simulator.math.odes.MultiTable.Block.Column; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.util.*; + +/** + * Run full stochastic test suite + */ +@RunWith(value = Parameterized.class) +public class StochasticTestSuiteTest { + + private String path; + private static final int TOTAL_SIMULATION_COUNT = 1000; + private static final Logger logger = LoggerFactory.getLogger(TestUtils.class); + private static final String DURATION = "duration"; + private static final String MEAN = "mean"; + private static final String STEPS = "steps"; + private static final String STOCHASTIC_TEST_SUITE_PATH = "STOCHASTIC_TEST_SUITE_PATH"; + + public StochasticTestSuiteTest(String path) { + this.path = path; + } + + @Parameters(name = "{index}: {0}") + public static Iterable data() { + + // environment variable for semantic test case folder + String testsuite_path = TestUtils.getPathForTestResource(File.separator + "sbml-test-suite" + File.separator + "cases" + File.separator + "stochastic" + File.separator); + System.out.println(STOCHASTIC_TEST_SUITE_PATH + ": " + testsuite_path); + + if (testsuite_path.length() == 0) { + Object[][] resources = new String[0][1]; + logger.warn(String.format("%s environment variable not set.", STOCHASTIC_TEST_SUITE_PATH)); + return Arrays.asList(resources); + } + + int N = 39; + Object[][] resources = new String[N][1]; + for (int model_number = 1; model_number <= N; model_number++){ + + // System.out.println("model " + model_number); + + StringBuilder modelFile = new StringBuilder(); + modelFile.append(model_number); + while (modelFile.length() < 5) { + modelFile.insert(0, '0'); + } + String path = modelFile.toString(); + modelFile.append(File.separator); + modelFile.append(path); + modelFile.insert(0, testsuite_path); + path = modelFile.toString(); + + resources[(model_number - 1)][0] = path; + + } + return Arrays.asList(resources); + + } + + @Ignore + @Test + public void testModel() throws IOException { + String sbmlfile, csvfile, configfile; + csvfile = path + "-results.csv"; + configfile = path + "-settings.txt"; + + Properties props = new Properties(); + props.load(new BufferedReader(new FileReader(configfile))); + + double duration = (!props.getProperty(DURATION).isEmpty()) ? Double.parseDouble(props.getProperty(DURATION)) : 0d; + double steps = (!props.getProperty(STEPS).isEmpty()) ? Double.parseDouble(props.getProperty(STEPS)) : 0d; + String outputColNames = props.getProperty("output"); + String[] list = outputColNames.split("\\s*, \\s*"); + + Map orderedArgs = new HashMap<>(); + + String[] sbmlFileTypes = {"-sbml-l1v2.xml", "-sbml-l2v1.xml", + "-sbml-l2v2.xml", "-sbml-l2v3.xml", "-sbml-l2v4.xml", + "-sbml-l3v1.xml", "-sbml-l3v2.xml"}; + + for (String sbmlFileType: sbmlFileTypes){ + sbmlfile = path + sbmlFileType; + File file = new File(sbmlfile); + + if ((sbmlfile != null) && file.exists()) { + orderedArgs.put("file", sbmlfile); + orderedArgs.put("time", duration); + orderedArgs.put("interval", (duration * 1d / steps)); + orderedArgs.put("n", 1); + orderedArgs.put("s", new String[0]); + orderedArgs.put("method", 0.0); + orderedArgs.put("i", false); + orderedArgs.put("p", ""); + // Creates a network from the SBML model + Network net = null; + boolean errorInNet = false; + try { + net = createNetwork(orderedArgs); + } catch (Exception e){ + errorInNet = true; + } + Assert.assertNotNull(net); + Assert.assertFalse(errorInNet); + // Initializes the simulator for performing the stochastic simulation + Simulator sim = null; + boolean errorInSimulator = false; + try { + sim = createSimulator(net, orderedArgs); + } catch (Exception e){ + errorInSimulator = true; + } + Assert.assertNotNull(sim); + Assert.assertFalse(errorInSimulator); + // Initializes the observer for the amounts of molecule species + AmountIntervalObserver obs = null; + boolean errorInObserver = false; + try { + obs = createObserver(sim, orderedArgs); + } catch (Exception e) { + errorInObserver = true; + } + Assert.assertNotNull(obs); + Assert.assertFalse(errorInObserver); + // Runs the stochastic simulation + boolean errorInSimulation = false; + try { + runSimulation(sim, obs, orderedArgs); + } catch (Exception e) { + errorInSimulation = true; + } + Assert.assertFalse(errorInSimulation); + // Gets the result from the observer + double[][] output = obs.getAvgLog(); + // Gets the time points of the simulation + double[] timepoints = output.clone()[0]; + // Gets the identifiers of the molecule species + String[] identifiers = getIdentifiers(sim, orderedArgs); + // 2D result array storing a simulation solution of particular simulation + double[][] result = new double[output[0].length][output.length-1]; + for (int i = 0; i != result.length; i++) { + Arrays.fill(result[i], Double.NaN); + } + for (int i = 0; i < result.length; i++){ + for (int j = 0; j < result[0].length; j++){ + result[i][j] = output[j+1][i]; + } + } + + /* + * Array of MultiTable storing the results of each stochastic simulation + */ + MultiTable[] solution = new MultiTable[TOTAL_SIMULATION_COUNT]; + solution[0] = new MultiTable(timepoints, result, identifiers, null); + // 2D array storing the square of the results required for the standard + // deviation. + double[][] square = new double[result.length][result[0].length]; + for (int i = 0; i < square.length; i++){ + for (int j = 0; j < square[0].length; j++){ + square[i][j] = Math.pow(result[i][j], 2); + } + } + // Stores the square_sum of the results of the n stochastic simulations + MultiTable square_sum = new MultiTable(timepoints, square, identifiers, null); + double[][] meanSDArray = new double[output[0].length][2 * output.length - 2]; + for (int i = 0; i != meanSDArray.length; i++) { + Arrays.fill(meanSDArray[i], Double.NaN); + } + // Stores the updated mean and standard deviations of the results till + // n stochastic simulations. + MultiTable meanSD = new MultiTable(timepoints, meanSDArray, list, null); + for (int i=1;i -3) && (meanDistance < 3)); + } + } else { + for (int j = 1; j < column.getRowCount(); j++){ + double sdDistance = sqrtN2 * ((Math.pow(left.getValueAt(j, i), 2) / Math.pow(right.getValueAt(j, i), 2)) - 1); + Assert.assertTrue((sdDistance > -5) && (sdDistance < 5)) ; + } + } + } + } + + } + + + } + + private static GnuPlot runSimulation(Simulator sim, AmountIntervalObserver obs, + Map orderedArgs) throws IOException { + + GnuPlot gp = new GnuPlot(); + gp.setDefaultStyle("with linespoints"); + if ((Boolean)orderedArgs.get("i")) { + gp.setVisible(true); + } + + for (int i=0; i<(Integer)orderedArgs.get("n"); i++) { + sim.start((Double)orderedArgs.get("time")); + + if ((Boolean)orderedArgs.get("i")) { + obs.toGnuplot(gp); + gp.plot(); + gp.clearData(); + } + } + + return gp; + } + + + private static AmountIntervalObserver createObserver(Simulator sim, + Map orderedArgs) { + String[] species = getIdentifiers(sim, orderedArgs); + return (AmountIntervalObserver) sim.addObserver(new AmountIntervalObserver(sim,(Double)orderedArgs.get("interval"),((Double)orderedArgs.get("time")).intValue(),species)); + } + + private static String[] getIdentifiers(Simulator sim, Map orderedArgs) { + String[] species = (String[]) orderedArgs.get("s"); + if (species.length==0) + species = NetworkTools.getSpeciesNames(sim.getNet(), NumberTools.getNumbersTo(sim.getNet().getNumSpecies()-1)); + return species; + } + + private static Network createNetwork(Map orderedArgs) throws IOException, + JDOMException, FeatureNotSupportedException, ClassNotFoundException { + return NetworkTools.loadNetwork(new File((String) orderedArgs.get("file"))); + } + + private static Simulator createSimulator(Network net, + Map orderedArgs) { + double eps = (Double) orderedArgs.get("method"); + if (eps==0) + return new GillespieEnhanced(net); + else if (eps==-1) + return new HybridMaximalTimeStep(net); + else { + AbstractBaseTauLeaping re = new TauLeapingSpeciesPopulationBoundSimulator(net); + re.setEpsilon(eps); + return re; + } + } + + + +} diff --git a/src/test/resources/sbml/00001/00001-sbml-l1v2.xml b/src/test/resources/sbml/00001/00001-sbml-l1v2.xml index f04ee9e2..a0944106 100644 --- a/src/test/resources/sbml/00001/00001-sbml-l1v2.xml +++ b/src/test/resources/sbml/00001/00001-sbml-l1v2.xml @@ -1,26 +1,26 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/resources/sbml/00001/00001-sbml-l2v1.xml b/src/test/resources/sbml/00001/00001-sbml-l2v1.xml index fad9a75b..dec436b7 100644 --- a/src/test/resources/sbml/00001/00001-sbml-l2v1.xml +++ b/src/test/resources/sbml/00001/00001-sbml-l2v1.xml @@ -1,35 +1,35 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - compartment - k1 - S1 - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + compartment + k1 + S1 + + + + + + + diff --git a/src/test/resources/sbml/00001/00001-sbml-l2v2.xml b/src/test/resources/sbml/00001/00001-sbml-l2v2.xml index 79bf0335..e263570e 100644 --- a/src/test/resources/sbml/00001/00001-sbml-l2v2.xml +++ b/src/test/resources/sbml/00001/00001-sbml-l2v2.xml @@ -1,35 +1,35 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - compartment - k1 - S1 - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + compartment + k1 + S1 + + + + + + + diff --git a/src/test/resources/sbml/00001/00001-sbml-l2v3.xml b/src/test/resources/sbml/00001/00001-sbml-l2v3.xml index 01da1ce1..f7640abe 100644 --- a/src/test/resources/sbml/00001/00001-sbml-l2v3.xml +++ b/src/test/resources/sbml/00001/00001-sbml-l2v3.xml @@ -1,75 +1,75 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - compartment - k1 - S1 - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + compartment + k1 + S1 + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/sbml/00001/00001-sbml-l2v4.xml b/src/test/resources/sbml/00001/00001-sbml-l2v4.xml index bd42e358..60c5c4af 100644 --- a/src/test/resources/sbml/00001/00001-sbml-l2v4.xml +++ b/src/test/resources/sbml/00001/00001-sbml-l2v4.xml @@ -1,35 +1,35 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - compartment - k1 - S1 - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + compartment + k1 + S1 + + + + + + + diff --git a/src/test/resources/sbml/00001/00001-sbml-l3v1.xml b/src/test/resources/sbml/00001/00001-sbml-l3v1.xml index f7b2f3c4..135d8337 100644 --- a/src/test/resources/sbml/00001/00001-sbml-l3v1.xml +++ b/src/test/resources/sbml/00001/00001-sbml-l3v1.xml @@ -1,52 +1,52 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - compartment - k1 - S1 - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + compartment + k1 + S1 + + + + + + + diff --git a/src/test/resources/sbml/00002/00002-sbml-l1v2.xml b/src/test/resources/sbml/00002/00002-sbml-l1v2.xml index 1ae02c8f..d65d7dea 100644 --- a/src/test/resources/sbml/00002/00002-sbml-l1v2.xml +++ b/src/test/resources/sbml/00002/00002-sbml-l1v2.xml @@ -1,36 +1,36 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/resources/sbml/00002/00002-sbml-l2v1.xml b/src/test/resources/sbml/00002/00002-sbml-l2v1.xml index 2298d839..d00b4d80 100644 --- a/src/test/resources/sbml/00002/00002-sbml-l2v1.xml +++ b/src/test/resources/sbml/00002/00002-sbml-l2v1.xml @@ -1,54 +1,54 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - compartment - k1 - S1 - - - - - - - - - - - - - - - - compartment - k2 - S2 - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + compartment + k1 + S1 + + + + + + + + + + + + + + + + compartment + k2 + S2 + + + + + + + diff --git a/src/test/resources/sbml/00002/00002-sbml-l2v2.xml b/src/test/resources/sbml/00002/00002-sbml-l2v2.xml index 602e2003..d1a25b28 100644 --- a/src/test/resources/sbml/00002/00002-sbml-l2v2.xml +++ b/src/test/resources/sbml/00002/00002-sbml-l2v2.xml @@ -1,54 +1,54 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - compartment - k1 - S1 - - - - - - - - - - - - - - - - compartment - k2 - S2 - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + compartment + k1 + S1 + + + + + + + + + + + + + + + + compartment + k2 + S2 + + + + + + + diff --git a/src/test/resources/sbml/00002/00002-sbml-l2v3.xml b/src/test/resources/sbml/00002/00002-sbml-l2v3.xml index 8f2e70b2..992b9c32 100644 --- a/src/test/resources/sbml/00002/00002-sbml-l2v3.xml +++ b/src/test/resources/sbml/00002/00002-sbml-l2v3.xml @@ -1,101 +1,101 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - compartment - k1 - S1 - - - - - - - - - - - - - - - - - - compartment - k2 - S2 - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + compartment + k1 + S1 + + + + + + + + + + + + + + + + + + compartment + k2 + S2 + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/sbml/00002/00002-sbml-l2v4.xml b/src/test/resources/sbml/00002/00002-sbml-l2v4.xml index b43846f7..7303fbc1 100644 --- a/src/test/resources/sbml/00002/00002-sbml-l2v4.xml +++ b/src/test/resources/sbml/00002/00002-sbml-l2v4.xml @@ -1,54 +1,54 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - compartment - k1 - S1 - - - - - - - - - - - - - - - - compartment - k2 - S2 - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + compartment + k1 + S1 + + + + + + + + + + + + + + + + compartment + k2 + S2 + + + + + + + diff --git a/src/test/resources/sbml/00002/00002-sbml-l3v1.xml b/src/test/resources/sbml/00002/00002-sbml-l3v1.xml index 838918e1..23f76405 100644 --- a/src/test/resources/sbml/00002/00002-sbml-l3v1.xml +++ b/src/test/resources/sbml/00002/00002-sbml-l3v1.xml @@ -1,71 +1,71 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - compartment - k1 - S1 - - - - - - - - - - - - - - - - compartment - k2 - S2 - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + compartment + k1 + S1 + + + + + + + + + + + + + + + + compartment + k2 + S2 + + + + + + + diff --git a/src/test/resources/sedml/L1V1/leloup.xml b/src/test/resources/sedml/L1V1/leloup.xml index 1fdbf684..a902158e 100644 --- a/src/test/resources/sedml/L1V1/leloup.xml +++ b/src/test/resources/sedml/L1V1/leloup.xml @@ -1,82 +1,82 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - t - - - - - - - - v1 - - - - - - - - v1a - - - - - - - - v2 - - - - - - - - v2a - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + t + + + + + + + + v1 + + + + + + + + v1a + + + + + + + + v2 + + + + + + + + v2a + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/resources/sedml/L1V2/ikappab/ikappab.xml b/src/test/resources/sedml/L1V2/ikappab/ikappab.xml index e19561cf..67faa7d4 100644 --- a/src/test/resources/sedml/L1V2/ikappab/ikappab.xml +++ b/src/test/resources/sedml/L1V2/ikappab/ikappab.xml @@ -1,77 +1,77 @@ - - - - - - - - - - - - - - - - - - - - time1 - - - - - - - - Total_NFkBn1 - - - - - - - - Total_IkBbeta1 - - - - - - - - Total_IkBeps1 - - - - - - - - Total_IkBalpha1 - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + time1 + + + + + + + + Total_NFkBn1 + + + + + + + + Total_IkBbeta1 + + + + + + + + Total_IkBeps1 + + + + + + + + Total_IkBalpha1 + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/sedml/L1V2/leloup-sbml/leloup-sbml.xml b/src/test/resources/sedml/L1V2/leloup-sbml/leloup-sbml.xml index 1b92f560..559d59b0 100644 --- a/src/test/resources/sedml/L1V2/leloup-sbml/leloup-sbml.xml +++ b/src/test/resources/sedml/L1V2/leloup-sbml/leloup-sbml.xml @@ -1,81 +1,81 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - t - - - - - - - - v1 - - - - - - - - v1a - - - - - - - - v2 - - - - - - - - v2a - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + t + + + + + + + + v1 + + + + + + + + v1a + + + + + + + + v2 + + + + + + + + v2a + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/resources/sedml/L1V2/oscli-nested-pulse/oscli-nested-pulse.xml b/src/test/resources/sedml/L1V2/oscli-nested-pulse/oscli-nested-pulse.xml index 287e9dd6..4b04d06e 100644 --- a/src/test/resources/sedml/L1V2/oscli-nested-pulse/oscli-nested-pulse.xml +++ b/src/test/resources/sedml/L1V2/oscli-nested-pulse/oscli-nested-pulse.xml @@ -1,114 +1,114 @@ - - - - - - - - - - - - - - - - - - - - 8 - - - index - 1 - - - - 0.1 - - - - - index - 4 - - - - index - 6 - - - - - 8 - - - - - - - - - current - - - - - - - - - - - - - - - time - - - - - - - - J0_v0 - - - - - - - - S1 - - - - - - - - S2 - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + 8 + + + index + 1 + + + + 0.1 + + + + + index + 4 + + + + index + 6 + + + + + 8 + + + + + + + + + current + + + + + + + + + + + + + + + time + + + + + + + + J0_v0 + + + + + + + + S1 + + + + + + + + S2 + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/sedml/L1V2/repeated-scan-oscli/repeated-scan-oscli.xml b/src/test/resources/sedml/L1V2/repeated-scan-oscli/repeated-scan-oscli.xml index af99b7a9..04111247 100644 --- a/src/test/resources/sedml/L1V2/repeated-scan-oscli/repeated-scan-oscli.xml +++ b/src/test/resources/sedml/L1V2/repeated-scan-oscli/repeated-scan-oscli.xml @@ -1,76 +1,76 @@ - - - - - - - - - - - - - - - - 8 - 4 - 0.4 - - - - - - current - - - - - - - - - - - - - - - time - - - - - - - - J0_v0 - - - - - - - - S1 - - - - - - - - S2 - - - - - - - - - - - + + + + + + + + + + + + + + + + 8 + 4 + 0.4 + + + + + + current + + + + + + + + + + + + + + + time + + + + + + + + J0_v0 + + + + + + + + S1 + + + + + + + + S2 + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/sedml/L1V2/repeated-steady-scan-oscli/repeated-steady-scan-oscli.xml b/src/test/resources/sedml/L1V2/repeated-steady-scan-oscli/repeated-steady-scan-oscli.xml index 95d99e9b..3862959f 100644 --- a/src/test/resources/sedml/L1V2/repeated-steady-scan-oscli/repeated-steady-scan-oscli.xml +++ b/src/test/resources/sedml/L1V2/repeated-steady-scan-oscli/repeated-steady-scan-oscli.xml @@ -1,72 +1,72 @@ - - - - - - - - - - - - - - - - - - - - - current - - - - - - - - - - - - - - - J0_v0 - - - - - - - - S1 - - - - - - - - S2 - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + current + + + + + + + + + + + + + + + J0_v0 + + + + + + + + S1 + + + + + + + + S2 + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/sedml/L1V2/repeated-stochastic-runs/repeated-stochastic-runs.xml b/src/test/resources/sedml/L1V2/repeated-stochastic-runs/repeated-stochastic-runs.xml index 784c0c28..b431cfc2 100644 --- a/src/test/resources/sedml/L1V2/repeated-stochastic-runs/repeated-stochastic-runs.xml +++ b/src/test/resources/sedml/L1V2/repeated-stochastic-runs/repeated-stochastic-runs.xml @@ -1,101 +1,101 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - time - - - - - - - - MAPK - - - - - - - - MAPK_P - - - - - - - - MAPK_PP - - - - - - - - MKK - - - - - - - - MKK_P - - - - - - - - MKKK - - - - - - - - MKKK_P - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + time + + + + + + + + MAPK + + + + + + + + MAPK_P + + + + + + + + MAPK_PP + + + + + + + + MKK + + + + + + + + MKK_P + + + + + + + + MKKK + + + + + + + + MKKK_P + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/sedml/L1V3/ikappab/ikappab.xml b/src/test/resources/sedml/L1V3/ikappab/ikappab.xml index e20bc430..726bc60a 100644 --- a/src/test/resources/sedml/L1V3/ikappab/ikappab.xml +++ b/src/test/resources/sedml/L1V3/ikappab/ikappab.xml @@ -1,77 +1,77 @@ - - - - - - - - - - - - - - - - - - - - time1 - - - - - - - - Total_NFkBn1 - - - - - - - - Total_IkBbeta1 - - - - - - - - Total_IkBeps1 - - - - - - - - Total_IkBalpha1 - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + time1 + + + + + + + + Total_NFkBn1 + + + + + + + + Total_IkBbeta1 + + + + + + + + Total_IkBeps1 + + + + + + + + Total_IkBalpha1 + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/sedml/L1V3/leloup-sbml/leloup-sbml.xml b/src/test/resources/sedml/L1V3/leloup-sbml/leloup-sbml.xml index 3eb6b7f6..2f96d16d 100644 --- a/src/test/resources/sedml/L1V3/leloup-sbml/leloup-sbml.xml +++ b/src/test/resources/sedml/L1V3/leloup-sbml/leloup-sbml.xml @@ -1,81 +1,81 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - t - - - - - - - - v1 - - - - - - - - v1a - - - - - - - - v2 - - - - - - - - v2a - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + t + + + + + + + + v1 + + + + + + + + v1a + + + + + + + + v2 + + + + + + + + v2a + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/resources/sedml/L1V3/oscli-nested-pulse/oscli-nested-pulse.xml b/src/test/resources/sedml/L1V3/oscli-nested-pulse/oscli-nested-pulse.xml index 7a3d7328..e849a9f4 100644 --- a/src/test/resources/sedml/L1V3/oscli-nested-pulse/oscli-nested-pulse.xml +++ b/src/test/resources/sedml/L1V3/oscli-nested-pulse/oscli-nested-pulse.xml @@ -1,114 +1,114 @@ - - - - - - - - - - - - - - - - - - - - 8 - - - index - 1 - - - - 0.1 - - - - - index - 4 - - - - index - 6 - - - - - 8 - - - - - - - - - current - - - - - - - - - - - - - - - time - - - - - - - - J0_v0 - - - - - - - - S1 - - - - - - - - S2 - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + 8 + + + index + 1 + + + + 0.1 + + + + + index + 4 + + + + index + 6 + + + + + 8 + + + + + + + + + current + + + + + + + + + + + + + + + time + + + + + + + + J0_v0 + + + + + + + + S1 + + + + + + + + S2 + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/sedml/L1V3/repeated-scan-oscli/repeated-scan-oscli.xml b/src/test/resources/sedml/L1V3/repeated-scan-oscli/repeated-scan-oscli.xml index 16c1f290..540619a7 100644 --- a/src/test/resources/sedml/L1V3/repeated-scan-oscli/repeated-scan-oscli.xml +++ b/src/test/resources/sedml/L1V3/repeated-scan-oscli/repeated-scan-oscli.xml @@ -1,76 +1,76 @@ - - - - - - - - - - - - - - - - 8 - 4 - 0.4 - - - - - - current - - - - - - - - - - - - - - - time - - - - - - - - J0_v0 - - - - - - - - S1 - - - - - - - - S2 - - - - - - - - - - - + + + + + + + + + + + + + + + + 8 + 4 + 0.4 + + + + + + current + + + + + + + + + + + + + + + time + + + + + + + + J0_v0 + + + + + + + + S1 + + + + + + + + S2 + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/sedml/L1V3/repeated-steady-scan-oscli/repeated-steady-scan-oscli.xml b/src/test/resources/sedml/L1V3/repeated-steady-scan-oscli/repeated-steady-scan-oscli.xml index 9a72fe21..f33a8d65 100644 --- a/src/test/resources/sedml/L1V3/repeated-steady-scan-oscli/repeated-steady-scan-oscli.xml +++ b/src/test/resources/sedml/L1V3/repeated-steady-scan-oscli/repeated-steady-scan-oscli.xml @@ -1,72 +1,72 @@ - - - - - - - - - - - - - - - - - - - - - current - - - - - - - - - - - - - - - J0_v0 - - - - - - - - S1 - - - - - - - - S2 - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + current + + + + + + + + + + + + + + + J0_v0 + + + + + + + + S1 + + + + + + + + S2 + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/sedml/L1V3/repeated-stochastic-runs/repeated-stochastic-runs.xml b/src/test/resources/sedml/L1V3/repeated-stochastic-runs/repeated-stochastic-runs.xml index c1c61080..54bb537c 100644 --- a/src/test/resources/sedml/L1V3/repeated-stochastic-runs/repeated-stochastic-runs.xml +++ b/src/test/resources/sedml/L1V3/repeated-stochastic-runs/repeated-stochastic-runs.xml @@ -1,101 +1,101 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - time - - - - - - - - MAPK - - - - - - - - MAPK_P - - - - - - - - MAPK_PP - - - - - - - - MKK - - - - - - - - MKK_P - - - - - - - - MKKK - - - - - - - - MKKK_P - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + time + + + + + + + + MAPK + + + + + + + + MAPK_P + + + + + + + + MAPK_PP + + + + + + + + MKK + + + + + + + + MKK_P + + + + + + + + MKKK + + + + + + + + MKKK_P + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/scripts/CellDesigner4.0beta.sh b/src/test/scripts/CellDesigner4.0beta.sh new file mode 100644 index 00000000..c53eb690 --- /dev/null +++ b/src/test/scripts/CellDesigner4.0beta.sh @@ -0,0 +1,34 @@ +#!/bin/sh +########################################################################### +# +# CellDesigner4.0beta.sh - CellDesigner version 4.0beta for Linux +# +# Copyright (c) 2006 The Systems Biology Institute. All rights reserved. +# +########################################################################### + +APP_NAME="CellDesigner4.0beta" + +CLASS_PATH="`ls exec/*.jar | tr "\n" ":"`" +CLASS_PATH=${CLASS_PATH}:"`ls lib/*.jar | tr "\n" ":"`" + + +JAR_ARGS=-sbwmodule + +CD_PREFIX="/home/e/erhardf/CellDesigner4.0beta" + +MAIN_CLASS=jp.sbi.celldesigner.Application + +JAVA="${CD_PREFIX}/jre/bin/java" +VM_ARGS="-Xms32M -Xmx512M -Djava.library.path=." + +if [ ! -d "${CD_PREFIX}" ]; then + echo "Error!! ${CD_PREFIX}: No such directory." + exit 1 +fi + +cd "${CD_PREFIX}" + +"${JAVA}" ${VM_ARGS} -cp ${CLASS_PATH} ${MAIN_CLASS} ${JAR_ARGS} + +exit 0 diff --git a/src/test/scripts/start.bat b/src/test/scripts/start.bat new file mode 100644 index 00000000..4e9e5f5d --- /dev/null +++ b/src/test/scripts/start.bat @@ -0,0 +1 @@ +java -cp lib/sbmlj-3.2.jar;lib/colt/colt-2.1.4.jar;lib/colt/concurrent-1.3.4.jar;lib/jdom-1.1.3.jar;lib/fern.jar fern.Start %1 %2 %3 %4 %5 %6 %7 %8 %9 diff --git a/src/test/scripts/start.sh b/src/test/scripts/start.sh new file mode 100755 index 00000000..a95df803 --- /dev/null +++ b/src/test/scripts/start.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +java -cp lib/libsbmlj.jar:lib/colt/colt-2.1.4.jar:lib/colt/concurrent-1.3.4.jar:lib/jdom-1.1.3.jar:lib/fern.jar fern.Start $@ diff --git a/src/test/scripts/start_cygwin.sh b/src/test/scripts/start_cygwin.sh new file mode 100755 index 00000000..17550e96 --- /dev/null +++ b/src/test/scripts/start_cygwin.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +java -cp lib/libsbmlj.jar\;lib/colt/colt-2.1.4.jar\;lib/colt/concurrent-1.3.4.jar\;lib/jdom-1.1.3.jar\;lib/fern.jar fern.Start $@