package uk.ac.ed.inf.biopepa.core; import java.util.*; import uk.ac.ed.inf.biopepa.core.interfaces.Result; import uk.ac.ed.inf.biopepa.core.sba.Parameters; import uk.ac.ed.inf.biopepa.core.sba.Parameters.Parameter; public class BasicResult implements Result { protected String simulator = "unknown"; protected String[] actionNames, componentNames; protected Map<String, Number> modelParameters = new HashMap<String, Number>(), uModelParameters = Collections .unmodifiableMap(modelParameters); protected Map<String, Number> simulatorParameters = new HashMap<String, Number>(), uSimulatorParameters = Collections .unmodifiableMap(simulatorParameters); protected boolean throughput = false; protected double[] throughputValues; protected double [] timePoints; protected double[][] results; protected double simulationRunTime; public BasicResult(Parameters parameters, Map<String, Number> modelParameters) { for (Map.Entry<Parameter, Object> me : parameters.getParameters().entrySet()) if (!me.getKey().equals(Parameter.Components) && me.getValue() instanceof Number) simulatorParameters.put(me.getKey().getDescriptiveName(), (Number) me.getValue()); for (Map.Entry<String, Number> me : modelParameters.entrySet()) this.modelParameters.put(me.getKey(), me.getValue()); } public BasicResult(){ } public void setSimulator(String sim){ this.simulator = sim; } public void setTimePoints(double [] times){ this.timePoints = times; } public void setResults(double[][] results){ this.results = results; } public String[] getActionNames() { if (actionNames == null) return new String[] {}; return actionNames.clone(); } public double getActionThroughput(int index) { return throughputValues[index]; } public void setComponentNames (String[] names){ this.componentNames = names; } public String[] getComponentNames() { if (componentNames == null) return new String[] {}; return componentNames.clone(); } public Map<String, Number> getModelParameters() { return uModelParameters; } public double getPopulation(int index) { return results[index][results[0].length - 1]; } public String getSimulatorName() { return simulator; } public Map<String, Number> getSimulatorParameters() { return uSimulatorParameters; } public double[] getTimeSeries(int index) { return results[index]; } public boolean throughputSupported() { return throughput; } public double[] getTimePoints() { return timePoints; } public void setSimulationRunTime(double s){ this.simulationRunTime = s; } public double getSimulationRunTime(){ return this.simulationRunTime; } /* * Normalise these results to the new set of time points. */ public void normaliseResult (double [] newTimePoints){ /* Note we could avoid making whole new arrays if newTimePoints * is the same length as the old time points array. */ double[][] newResults = new double [componentNames.length][]; for (int index = 0; index < componentNames.length; index++){ newResults[index] = new double [newTimePoints.length]; } double [] newThroughput = null; if (this.throughput){ newThroughput = new double [newTimePoints.length]; } int oldIndex = 0; for (int newIndex = 0; newIndex < newTimePoints.length; newIndex++){ /* * Skip past as many old results as we need to, to get to the next * new time point. Note that if there are more new time points then * the for-loop will execute many times without executing the while * loop. */ while (timePoints[oldIndex] < newTimePoints[newIndex] && oldIndex < timePoints.length){ oldIndex++; } /* * Once we have the corresponding oldIndex we just update the new results */ for (int nameIndex = 0; nameIndex < componentNames.length; nameIndex++){ newResults[nameIndex][newIndex] = results[nameIndex][oldIndex]; } /* * Now if throughput is supported update the throughput value. */ if (this.throughput){ newThroughput[newIndex] = throughputValues[oldIndex]; } } this.results = newResults; this.timePoints = newTimePoints; if (this.throughput){ this.throughputValues = newThroughput; } } /* * Concatenate two double arrays, the given offset is how much of the * second one to ignore. */ private double[] concatenateDoubleArrays(double []a1, double[]a2, int offset){ double [] result = new double [a1.length + a2.length - offset]; for (int index = 0; index < a1.length; index++){ result[index] = a1[index]; } for (int index = offset; index < a2.length; index++){ result[index + a1.length - offset] = a2[index]; } return result; } /* * (non-Javadoc) * @see uk.ac.ed.inf.biopepa.core.interfaces.Result#concatenateResults(uk.ac.ed.inf.biopepa.core.interfaces.Result) * It's a little tempting to more aggressively check the constraints * which we put on the incoming results. That is that they should have * the same names plotted and should start from time point 0.0 */ public void concatenateResults(Result result) { double [] extraTimePoints = result.getTimePoints(); double [] additionalTimePoints = new double [extraTimePoints.length]; double lastCurrent = this.timePoints[this.timePoints.length - 1]; // First of all, add for (int index = 0; index < additionalTimePoints.length; index++){ additionalTimePoints[index] = lastCurrent + extraTimePoints[index]; } // Now when we add the time points together we do not // wish to include the first timepoint as that should // be 0.0 double [] newTimePoints = concatenateDoubleArrays(this.timePoints, additionalTimePoints, 1); this.timePoints = newTimePoints; double[][] newResults = new double[this.results.length][]; for (int index = 0; index < newResults.length; index++){ newResults[index] = concatenateDoubleArrays(this.results[index], result.getTimeSeries(index), 1); } this.results = newResults; /* * Throughput is supposed to be the throughput at the end * of the simulation hence we just wish to make the throughput * here equal to that of the given result. */ if (this.throughput && result.throughputSupported()){ for (int index = 0; index < this.throughputValues.length; index++){ this.throughputValues[index] = result.getActionThroughput(index); } } /* * Finally the simulation time should be equal to the addition * of both results' simulation times */ this.simulationRunTime += result.getSimulationRunTime(); } }