/*******************************************************************************
* Copyright (c) 2009 University of Edinburgh.
* All rights reserved. This program and the accompanying materials are made
* available under the terms of the BSD Licence, which accompanies this feature
* and can be downloaded from http://groups.inf.ed.ac.uk/pepa/update/licence.txt
******************************************************************************/
package uk.ac.ed.inf.biopepa.core.sba;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.systemsbiology.chem.Compartment;
import org.systemsbiology.chem.Model;
import org.systemsbiology.chem.Reaction;
import org.systemsbiology.chem.ReservedSymbolMapperChemCommandLanguage;
import org.systemsbiology.chem.SimulationController;
import org.systemsbiology.chem.SimulationProgressReporter;
import org.systemsbiology.chem.SimulationResults;
import org.systemsbiology.chem.Simulator;
import org.systemsbiology.chem.SimulatorParameters;
import org.systemsbiology.chem.SimulatorStochasticBase;
import org.systemsbiology.chem.SimulatorStochasticGibsonBruck;
import org.systemsbiology.chem.SimulatorStochasticGillespie;
import org.systemsbiology.chem.SimulatorStochasticTauLeapBase;
import org.systemsbiology.chem.SimulatorStochasticTauLeapComplex;
import org.systemsbiology.chem.Species;
import org.systemsbiology.chem.odetojava.SimulatorOdeToJavaBase;
import org.systemsbiology.chem.odetojava.SimulatorOdeToJavaRungeKuttaAdaptive;
import org.systemsbiology.chem.odetojava.SimulatorOdeToJavaRungeKuttaImplicit;
import org.systemsbiology.math.Expression;
import org.systemsbiology.math.Expression.Element;
import org.systemsbiology.math.Expression.ElementCode;
import org.systemsbiology.math.Symbol;
import org.systemsbiology.math.Value;
import uk.ac.ed.inf.biopepa.core.BasicResult;
import uk.ac.ed.inf.biopepa.core.BioPEPAException;
import uk.ac.ed.inf.biopepa.core.compiler.CompartmentData;
import uk.ac.ed.inf.biopepa.core.compiler.CompiledDynamicComponent;
import uk.ac.ed.inf.biopepa.core.compiler.CompiledExpression;
import uk.ac.ed.inf.biopepa.core.compiler.CompiledExpressionVisitor;
import uk.ac.ed.inf.biopepa.core.compiler.CompiledFunction;
import uk.ac.ed.inf.biopepa.core.compiler.CompiledNumber;
import uk.ac.ed.inf.biopepa.core.compiler.CompiledOperatorNode;
import uk.ac.ed.inf.biopepa.core.compiler.CompiledSystemVariable;
import uk.ac.ed.inf.biopepa.core.compiler.ComponentNode;
import uk.ac.ed.inf.biopepa.core.interfaces.ProgressMonitor;
import uk.ac.ed.inf.biopepa.core.interfaces.Result;
import uk.ac.ed.inf.biopepa.core.interfaces.Solver;
import uk.ac.ed.inf.biopepa.core.sba.Parameters.Parameter;
import uk.ac.ed.inf.biopepa.core.sba.SBAComponentBehaviour.Type;
public class ISBJava {
static class DormandPrince implements Solver {
public String getDescriptiveName() {
return "Adaptive step-size 5th-order Dormand Prince ODE Solver";
}
public Parameters getRequiredParameters() {
return odeParameters();
}
public String getShortName() {
return "dopr-adaptive";
}
public Result startTimeSeriesAnalysis(SBAModel model, Parameters parameters,
ProgressMonitor monitor) throws BioPEPAException {
ISBJava isbjava = new ISBJava(model, (String[]) parameters.getValue(Parameter.Components));
isbjava.simulator = new SimulatorOdeToJavaRungeKuttaAdaptive();
isbjava.simulatorParameters = ((SimulatorOdeToJavaBase) isbjava.simulator).getDefaultSimulatorParameters();
isbjava.mapModel();
try {
((SimulatorOdeToJavaRungeKuttaAdaptive) isbjava.simulator).initialize(isbjava.model);
} catch (Exception e) {
throw new BioPEPAException(e);
}
SimulationResults results = isbjava.run(getRequiredParameters(), parameters, monitor);
if (monitor.isCanceled())
return null;
return new Results(results, false, parameters, isbjava.parameterMap, getDescriptiveName());
}
public SolverResponse getResponse(final SBAModel model) {
return new SolverResponse() {
public String getMessage() {
if (model.nonDifferentiableFunctions)
return "The model uses functions that may invalidate the results from ODE analysis.";
return null;
}
public Suitability getSuitability() {
if (model.nonDifferentiableFunctions)
return Suitability.WARNING;
return Suitability.PERMISSIBLE;
}
};
}
}
static class GibsonBruck implements Solver {
public String getDescriptiveName() {
return "Gibson-Bruck Stochastic Algorithm";
}
public Parameters getRequiredParameters() {
return stochasticParameters();
}
public String getShortName() {
return "gibson-bruck";
}
public Result startTimeSeriesAnalysis(SBAModel model, Parameters parameters,
ProgressMonitor monitor) throws BioPEPAException {
ISBJava isbjava = new ISBJava(model, (String[]) parameters.getValue(Parameter.Components));
isbjava.simulator = new SimulatorStochasticGibsonBruck();
isbjava.simulatorParameters = ((SimulatorStochasticBase) isbjava.simulator).getDefaultSimulatorParameters();
isbjava.mapModel();
try {
((SimulatorStochasticGibsonBruck) isbjava.simulator).initialize(isbjava.model);
} catch (Exception e) {
throw new BioPEPAException(e);
}
SimulationResults results = isbjava.run(getRequiredParameters(), parameters, monitor);
if (monitor.isCanceled())
return null;
return new Results(results, true, parameters, isbjava.parameterMap, getDescriptiveName());
}
public SolverResponse getResponse(final SBAModel model) {
return new SolverResponse() {
public String getMessage() {
if (model.timeDependentRates)
return "This algorithm may not correctly simulate models dependent on time.";
return null;
}
public Suitability getSuitability() {
if (model.timeDependentRates)
return Suitability.WARNING;
return Suitability.PERMISSIBLE;
}
};
}
}
static class Gillespie implements Solver {
public String getDescriptiveName() {
return "Gillespie's Stochastic Algorithm";
}
public Parameters getRequiredParameters() {
return stochasticParameters();
}
public String getShortName() {
return "gillespie";
}
public Result startTimeSeriesAnalysis(SBAModel model, Parameters parameters,
ProgressMonitor monitor) throws BioPEPAException {
ISBJava isbjava = new ISBJava(model, (String[]) parameters.getValue(Parameter.Components));
isbjava.simulator = new SimulatorStochasticGillespie();
isbjava.simulatorParameters = ((SimulatorStochasticBase) isbjava.simulator).getDefaultSimulatorParameters();
isbjava.mapModel();
try {
((SimulatorStochasticGillespie) isbjava.simulator).initialize(isbjava.model);
} catch (Exception e) {
throw new BioPEPAException(e);
}
SimulationResults results = isbjava.run(getRequiredParameters(), parameters, monitor);
if (monitor.isCanceled())
return null;
return new Results(results, true, parameters, isbjava.parameterMap, getDescriptiveName());
}
public SolverResponse getResponse(final SBAModel model) {
return new SolverResponse() {
public String getMessage() {
if (model.timeDependentRates)
return "This algorithm may not correctly simulate models dependent on time.";
return null;
}
public Suitability getSuitability() {
if (model.timeDependentRates)
return Suitability.WARNING;
return Suitability.PERMISSIBLE;
}
};
}
}
static class IMEX implements Solver {
public String getDescriptiveName() {
return "Implicit-Explicit Runge Kutta ODE Solver";
}
public Parameters getRequiredParameters() {
return odeParameters();
}
public String getShortName() {
return "imex-stiff";
}
public Result startTimeSeriesAnalysis(SBAModel model, Parameters parameters,
ProgressMonitor monitor) throws BioPEPAException {
ISBJava isbjava = new ISBJava(model, (String[]) parameters.getValue(Parameter.Components));
isbjava.simulator = new SimulatorOdeToJavaRungeKuttaImplicit();
isbjava.simulatorParameters = ((SimulatorOdeToJavaBase) isbjava.simulator).getDefaultSimulatorParameters();
isbjava.mapModel();
try {
((SimulatorOdeToJavaRungeKuttaImplicit) isbjava.simulator).initialize(isbjava.model);
} catch (Exception e) {
throw new BioPEPAException(e);
}
SimulationResults results = isbjava.run(getRequiredParameters(), parameters, monitor);
if (monitor.isCanceled())
return null;
return new Results(results, false, parameters, isbjava.parameterMap, getDescriptiveName());
}
public SolverResponse getResponse(final SBAModel model) {
return new SolverResponse() {
public String getMessage() {
if (model.nonDifferentiableFunctions)
return "The model uses functions that may invalidate the results from ODE analysis.";
return null;
}
public Suitability getSuitability() {
if (model.nonDifferentiableFunctions)
return Suitability.WARNING;
return Suitability.PERMISSIBLE;
}
};
}
}
static class TauLeap implements Solver {
public String getDescriptiveName() {
return "Gillespie's Tau-Leap Stochastic Algorithm";
}
public Parameters getRequiredParameters() {
Parameters p = stochasticParameters();
p.add(Parameter.Step_Size);
p.add(Parameter.Relative_Error);
return p;
}
public String getShortName() {
return "tau-leap";
}
public Result startTimeSeriesAnalysis(SBAModel model, Parameters parameters,
ProgressMonitor monitor) throws BioPEPAException {
ISBJava isbjava = new ISBJava(model, (String[]) parameters.getValue(Parameter.Components));
isbjava.simulator = new SimulatorStochasticTauLeapComplex();
isbjava.simulatorParameters = ((SimulatorStochasticTauLeapBase) isbjava.simulator)
.getDefaultSimulatorParameters();
isbjava.mapModel();
try {
((SimulatorStochasticTauLeapComplex) isbjava.simulator).initialize(isbjava.model);
} catch (Exception e) {
throw new BioPEPAException(e);
}
SimulationResults results = isbjava.run(getRequiredParameters(), parameters, monitor);
if (monitor.isCanceled())
return null;
Results ourResults = new Results(results, false, parameters, isbjava.parameterMap, getDescriptiveName());
return ourResults;
}
public SolverResponse getResponse(final SBAModel model) {
return new SolverResponse() {
public String getMessage() {
if (model.timeDependentRates)
return "This algorithm cannot simulate models dependent on time.";
return null;
}
public Suitability getSuitability() {
if (model.timeDependentRates)
return Suitability.UNSUITABLE;
return Suitability.PERMISSIBLE;
}
};
}
}
public class RatesVisitor extends CompiledExpressionVisitor {
Element element;
SBAReaction reaction;
// boolean root = true;
boolean reversing = false;
public RatesVisitor() {
super();
}
public boolean visit(CompiledDynamicComponent component) {
// As it's already a reference to a variable of some sort there
// is nothing to inline or to not inline.
String name = component.getName();
CompiledExpression ce = sbaModel.getDynamicExpression(name);
if (ce != null && !addedParameters.contains(name)) {
addedParameters.add(name);
ce.accept(this);
if (element.mCode.equals(ElementCode.NUMBER))
model.addParameter(new org.systemsbiology.chem.Parameter(name, element.mNumericValue));
else
model.addParameter(new org.systemsbiology.chem.Parameter(name, new Expression(element)));
}
element = new Element(ElementCode.SYMBOL);
element.mSymbol = new Symbol(name);
return true;
}
public boolean visit(CompiledFunction function) {
if (removeInline(function)){
return true;
}
// root = false;
// We no longer check if this expression is the root of the
// expression, since we are allowing built-in functions to occur
// anywhere in the expression. Hence you may have: fMA(r) + r
// for example.
if (function.getFunction().isRateLaw()) {
Element e1, e2;
switch (function.getFunction()) {
case fMA:
function.getArguments().get(0).accept(this);
if (element.mCode.equals(ElementCode.NUMBER))
break; // ISBJava will handle the mass action rate.
List<SBAComponentBehaviour> reactants = reaction.reactants;
if (reversing)
reactants = reaction.products;
if (reactants.size() == 0)
break; // constant rate production.
e1 = prep(reactants.get(0));
for (int i = 1; i < reactants.size(); i++) {
e2 = new Element(ElementCode.MULT);
e2.mSecondOperand = e1;
e2.mFirstOperand = prep(reactants.get(i));
e1 = e2;
}
e2 = new Element(ElementCode.MULT);
e2.mSecondOperand = e1;
e2.mFirstOperand = element;
element = e2;
break;
case fMM:
function.getArguments().get(0).accept(this);
e1 = new Element(ElementCode.MULT);
e1.mFirstOperand = element;
e2 = new Element(ElementCode.MULT);
SBAComponentBehaviour substrate = null;
Element[] eArray = new Element[2];
int i = 0;
for (SBAComponentBehaviour cb : reaction.reactants) {
if (cb.type.equals(Type.REACTANT))
substrate = cb;
eArray[i++] = prep(cb);
}
e2.mFirstOperand = eArray[0];
e2.mSecondOperand = eArray[1];
e1.mSecondOperand = e2;
e2 = new Element(ElementCode.DIV);
e2.mFirstOperand = e1;
e1 = e2;
e2 = new Element(ElementCode.ADD);
function.getArguments().get(1).accept(this);
e2.mFirstOperand = element;
e2.mSecondOperand = prep(substrate);
e1.mSecondOperand = e2;
element = e1;
break;
default:
throw new IllegalStateException();
}
return true;
}
if (function.getFunction().args() == 1) {
function.getArguments().get(0).accept(this);
Element newElement;
switch (function.getFunction()) {
case LOG:
newElement = new Element(ElementCode.LN);
break;
case EXP:
newElement = new Element(ElementCode.EXP);
break;
case H:
newElement = new Element(ElementCode.THETA);
break;
case FLOOR:
newElement = new Element(ElementCode.FLOOR);
break;
case CEILING:
newElement = new Element(ElementCode.CEIL);
break;
case TANH:
newElement = new Element(ElementCode.TANH);
break;
default:
throw new IllegalStateException();
}
newElement.mFirstOperand = element;
element = newElement;
}
return true;
}
public boolean visit(CompiledNumber number) {
if (removeInline(number))
return true;
element = new Element(number.doubleValue());
return false;
}
public boolean visit(CompiledOperatorNode operator) {
if (removeInline(operator))
return true;
// root = false;
operator.getLeft().accept(this);
Element left = element;
operator.getRight().accept(this);
Element right = element;
ElementCode code = null;
switch (operator.getOperator()) {
case PLUS:
code = ElementCode.ADD;
break;
case MINUS:
code = ElementCode.SUBT;
break;
case DIVIDE:
code = ElementCode.DIV;
break;
case MULTIPLY:
code = ElementCode.MULT;
break;
case POWER:
code = ElementCode.POW;
break;
default:
}
element = new Element(code);
element.mFirstOperand = left;
element.mSecondOperand = right;
return true;
}
private boolean removeInline(CompiledExpression ce) {
if (ce.hasExpandedForm() && (ce.returnExpandedForm() instanceof CompiledDynamicComponent)) {
CompiledDynamicComponent cdc = (CompiledDynamicComponent) ce.returnExpandedForm();
String cvName = cdc.getName();
cvName = ce.returnExpandedForm().toString();
if (sbaModel.inline(cvName)) {
return false;
}
// remove inlined expression to avoid repeated evaluation
return cdc.accept(this);
}
return false;
}
public Value getValue() {
if (element.mCode.equals(ElementCode.NUMBER))
return new Value(element.mNumericValue);
return new Value(new Expression(element));
}
private final Element prep(SBAComponentBehaviour cb) {
Element e = null;
if (cb.stoichiometry > 1) {
e = new Element(ElementCode.POW);
e.mFirstOperand = new Element(ElementCode.SYMBOL);
e.mFirstOperand.mSymbol = new Symbol(cb.getName());
e.mSecondOperand = new Element(cb.stoichiometry);
} else {
e = new Element(ElementCode.SYMBOL);
e.mSymbol = new Symbol(cb.getName());
}
return e;
}
public boolean visit(CompiledSystemVariable variable) {
if (removeInline(variable))
return true;
switch (variable.getVariable()) {
case TIME:
element = new Element(ElementCode.SYMBOL);
element.mSymbol = new Symbol(ReservedSymbolMapperChemCommandLanguage.SYMBOL_TIME);
break;
default:
throw new IllegalStateException();
}
return true;
}
}
static class Results extends BasicResult implements Result {
String[] actionNames, componentNames;
Map<String, Number> modelParameters = new HashMap<String, Number>(), uModelParameters = Collections
.unmodifiableMap(modelParameters);
String simulator;
Map<String, Number> simulatorParameters = new HashMap<String, Number>(), uSimulatorParameters = Collections
.unmodifiableMap(simulatorParameters);
/* boolean throughput = false;
double[] throughputValues, time;
double[][] results; */
private int[] resultHashes;
// private int timeHashes;
Results(SimulationResults results, boolean throughput, Parameters parameters,
Map<String, Number> modelParameters, String simulator) {
componentNames = results.getResultsSymbolNames();
this.throughput = throughput;
this.simulator = simulator;
for (Map.Entry<Parameter, Object> me : parameters.parameters.entrySet())
if (!me.getKey().equals(Parameter.Components) && me.getValue() instanceof Number)
simulatorParameters.put(me.getKey().descriptiveName, (Number) me.getValue());
for (Map.Entry<String, Number> me : modelParameters.entrySet())
this.modelParameters.put(me.getKey(), me.getValue());
timePoints = results.getResultsTimeValues();
// timeHashes = Arrays.hashCode(timePoints);
this.results = new double[componentNames.length][];
for (int i = 0; i < componentNames.length; i++)
this.results[i] = new double[timePoints.length];
Object[] values = results.getResultsSymbolValues();
double[] d;
for (int i = 0; i < values.length; i++) {
d = (double[]) values[i];
for (int j = 0; j < d.length; j++)
this.results[j][i] = d[j];
}
resultHashes = new int[componentNames.length];
for (int i = 0; i < this.resultHashes.length; i++)
resultHashes[i] = Arrays.hashCode(this.results[i]);
if (throughput) {
actionNames = results.getReactionNames();
throughputValues = new double[actionNames.length];
double[] times = results.getReactionTimes(), firings = results.getReactionCounts();
for (int i = 0; i < times.length; i++)
throughputValues[i] = (times[i] / firings[i]);
}
}
public String[] getActionNames() {
if (actionNames == null)
return new String[] {};
return actionNames.clone();
}
public double getActionThroughput(int index) {
return throughputValues[index];
}
public String[] getComponentNames() {
if (componentNames == null)
return new String[] {};
return componentNames.clone();
}
public String getSimulatorName() {
return simulator;
}
public Map<String, Number> getSimulatorParameters() {
return uSimulatorParameters;
}
public double[] getTimeSeries(int index) {
// if (Arrays.hashCode(results[index]) != resultHashes[index])
// throw new IllegalStateException("Time series has been modified since initial storage.");
return results[index];
}
public boolean throughputSupported() {
return throughput;
}
public double[] getTimePoints() {
// if (Arrays.hashCode(timePoints) != timeHashes)
// throw new IllegalStateException(" has been modified since initial storage.");
return timePoints;
}
}
private static Parameters odeParameters() {
Parameters parameters = parameters();
parameters.add(Parameter.Step_Size);
parameters.add(Parameter.Absolute_Error);
parameters.add(Parameter.Relative_Error);
return parameters;
}
private static final Parameters parameters() {
Parameters parameters = new Parameters();
parameters.add(Parameter.Start_Time);
parameters.add(Parameter.Stop_Time);
parameters.add(Parameter.Data_Points);
parameters.add(Parameter.Components);
return parameters;
}
private static Parameters stochasticParameters() {
Parameters parameters = parameters();
parameters.add(Parameter.Independent_Replications);
return parameters;
}
private Model model;
Map<String, Number> parameterMap = new HashMap<String, Number>();
private SBAModel sbaModel;
private String[] toObserve;
private SimulationController simulationController;
private SimulationProgressReporter simulationProgressReporter;
private Simulator simulator;
private SimulatorParameters simulatorParameters;
private Set<String> addedParameters;
public ISBJava(SBAModel model, String[] toObserve) {
sbaModel = model;
this.toObserve = toObserve;
}
private Value generateRate(SBAReaction reaction, boolean reverse)
throws BioPEPAException {
RatesVisitor rv = new RatesVisitor();
rv.reaction = reaction;
rv.reversing = reverse;
reaction.reactionRate.accept(rv);
return rv.getValue();
}
private void mapModel() throws BioPEPAException {
model = new Model();
model.setReservedSymbolMapper(new ReservedSymbolMapperChemCommandLanguage());
// Compartments
Map<String, Compartment> compartments = new HashMap<String, Compartment>();
Compartment compartment = new Compartment("main");
compartments.put(null, compartment);
addedParameters = new HashSet<String>();
for (Map.Entry<String, Double> me : sbaModel.compartments.entrySet()) {
compartment = new Compartment(me.getKey());
compartment.setVolume(me.getValue());
compartments.put(me.getKey(), compartment);
parameterMap.put(me.getKey(), new Double(me.getValue()));
}
// Species
Map<String, Species> speciesMap = new HashMap<String, Species>();
Species species;
CompartmentData cd;
for (ComponentNode cn : sbaModel.getComponents()) {
cd = cn.getCompartment();
String componentName = cn.getName();
double componentCount = cn.getCount();
species = new Species(componentName, compartments.get(cd == null ? null : cd.getName()));
species.setSpeciesPopulation(componentCount);
speciesMap.put(componentName, species);
parameterMap.put(componentName, new Double(componentCount));
}
// Reactions
Reaction reaction;
for (SBAReaction r : sbaModel.getReactions()) {
if (r.isEnabled() /* && experimentLine.isReactionActiviated(r.getName())*/) {
// System.out.println("reactionEnabled: " + r.getName());
if (r.isReversible())
reaction = new Reaction(r.forwardName);
else
reaction = new Reaction(r.name);
for (SBAComponentBehaviour cb : r.reactants)
reaction.addReactant(speciesMap.get(cb.getName()), cb.stoichiometry, cb.type.equals(Type.REACTANT));
for (SBAComponentBehaviour cb : r.products)
reaction.addProduct(speciesMap.get(cb.getName()), cb.stoichiometry);
reaction.setRate(generateRate(r, false));
model.addReaction(reaction);
if (r.isReversible()) {
reaction = new Reaction(r.reversibleName);
for (SBAComponentBehaviour cb : r.products)
reaction.addReactant(speciesMap.get(cb.getName()), cb.stoichiometry, true);
for (SBAComponentBehaviour cb : r.reactants)
reaction.addProduct(speciesMap.get(cb.getName()), cb.stoichiometry);
reaction.setRate(generateRate(r, true));
model.addReaction(reaction);
}
}
}
RatesVisitor rv;
CompiledExpression ce;
for (String s : toObserve) {
if (addedParameters.contains(s))
continue; // already added from traversing rates
ce = sbaModel.getDynamicExpression(s);
if (ce != null) {
rv = new RatesVisitor();
ce.accept(rv);
model.addParameter(new org.systemsbiology.chem.Parameter(s, new Expression(rv.element)));
}
}
}
private SimulationResults run(Parameters requiredParameters, Parameters suppliedParameters,
final ProgressMonitor monitor) throws BioPEPAException {
simulationProgressReporter = new SimulationProgressReporter();
simulator.setProgressReporter(simulationProgressReporter);
simulationController = new SimulationController();
simulator.setController(simulationController);
if (!suppliedParameters.setOfKeys().containsAll(requiredParameters.setOfKeys()))
throw new IllegalArgumentException("Incorrect parameters supplied.");
// Set and check parameters
int tInt, samples;
double tDouble, startTime, stopTime;
String[] species;
// Required parameters
startTime = (Double) suppliedParameters.getValue(Parameter.Start_Time);
stopTime = (Double) suppliedParameters.getValue(Parameter.Stop_Time);
if (startTime < 0.00 || startTime >= stopTime)
throw new IllegalArgumentException("Start time < 0.00 || start time >= stop time.");
samples = (Integer) suppliedParameters.getValue(Parameter.Data_Points);
if (samples < 3)
throw new IllegalArgumentException(Parameter.Data_Points.toString() + " must be greater than 2.");
species = (String[]) suppliedParameters.getValue(Parameter.Components);
if (species.length == 0)
throw new IllegalArgumentException(Parameter.Components.toString()
+ " must contain at least one component.");
// TODO reinstate species checking. I don't believe this will return the
// correct list.
// HashSet<String> knownSpecies = new
// HashSet<String>(Arrays.asList(model.getOrderedSpeciesNamesArray()));
/*
* for (String component : species) if
* (!knownSpecies.contains(component)) { species = null; throw new
* IllegalArgumentException(Parameter.Components .toString() + ": " +
* component + " is not a valid selection."); }
*/
// Solver dependent parameters
for (Parameter p : requiredParameters.arrayOfKeys()) {
if (p.equals(Parameter.Step_Size)) {
tDouble = (Double) suppliedParameters.getValue(p);
if (tDouble <= 0.00)
throw new IllegalArgumentException(p.toString() + " must be greater than 0.00.");
simulatorParameters.setStepSizeFraction(tDouble);
} else if (p.equals(Parameter.Independent_Replications)) {
tInt = (Integer) suppliedParameters.getValue(p);
if (tInt < 1)
throw new IllegalArgumentException(p.toString() + " must be greater than 0.");
simulatorParameters.setEnsembleSize(tInt);
} else if (p.equals(Parameter.Relative_Error)) {
tDouble = (Double) suppliedParameters.getValue(p);
if (tDouble <= 0.00)
throw new IllegalArgumentException(p.toString() + " must be greater than 0.00.");
simulatorParameters.setMaxAllowedRelativeError(tDouble);
} else if (p.equals(Parameter.Absolute_Error)) {
tDouble = (Double) suppliedParameters.getValue(p);
if (tDouble <= 0.00)
throw new IllegalArgumentException(p.toString() + " must be greater than 0.00.");
simulatorParameters.setMaxAllowedAbsoluteError(tDouble);
}
}
// Prepare monitor thread
simulationProgressReporter.setSimulationFinished(false);
Thread monitorController = null;
if (monitor != null) {
monitorController = new Thread() {
public void run() {
try {
int SCALING_UNIT = 100;
int previous = 0, current = 0;
monitor.beginTask(SCALING_UNIT);
while (!simulationProgressReporter.getSimulationFinished()) {
if (monitor.isCanceled())
simulationController.setCancelled(true);
simulationProgressReporter.waitForUpdate();
current = (int) (simulationProgressReporter.getFractionComplete() * 100);
monitor.worked(current - previous);
previous = current;
}
} finally {
monitor.done();
}
}
};
monitorController.start();
}
// Start simulator
SimulationResults results = null;
try {
if (simulator instanceof SimulatorStochasticBase)
results = ((SimulatorStochasticBase) simulator).simulate(startTime, stopTime, simulatorParameters,
samples, species);
else if (simulator instanceof SimulatorOdeToJavaBase)
results = ((SimulatorOdeToJavaBase) simulator).simulate(startTime, stopTime, simulatorParameters,
samples, species);
} catch (Exception e) {
throw new BioPEPAException(e.getMessage());
}
return results;
}
}