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:
-
- 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:
-
-
-
- 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:
+
+
+
+ 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
- ConstraintListener
s.
-
-
-
- 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 () {
-
- 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
+ ConstraintListener
s.
+
+
+
+ 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 () {
+
+ 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
- ConstraintListener
s.
-
-
-
- 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 () {
-
- 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
+ ConstraintListener
s.
+
+
+
+ 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 () {
+
+ 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
-
- 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/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 Simulator
s - use this field to attach Observer
s.
+ */
+ 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 Network
s
+ * 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; iset 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; j