forked from draeger-lab/SBSCL
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added post-processing which works with repeatedTasks
- Loading branch information
1 parent
6ee457d
commit f5ac28e
Showing
3 changed files
with
405 additions
and
92 deletions.
There are no files selected for viewing
88 changes: 88 additions & 0 deletions
88
src/main/java/org/simulator/sedml/IProcessedSedMLSimulationResultsWrapper.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
package org.simulator.sedml; | ||
|
||
import org.jlibsedml.execution.IProcessedSedMLSimulationResults; | ||
|
||
/** | ||
* Non-API Implementation of {@link IProcessedSedMLSimulationResults} | ||
* Because this class is non-API we don't have exhaustive arg checking etc., | ||
* Borrowed from jlibsedml | ||
* @author Shalin Shah | ||
* | ||
*/ | ||
class IProcessedSedMLSimulationResultsWrapper implements IProcessedSedMLSimulationResults { | ||
|
||
private double [][] _data; | ||
private String [] _headers; | ||
|
||
IProcessedSedMLSimulationResultsWrapper(double [][]data, String []headers) { | ||
_headers = new String[headers.length]; | ||
System.arraycopy(headers, 0, _headers, 0, headers.length); | ||
_data = new double[data.length][]; | ||
copyDataFromTo(data, _data); | ||
|
||
} | ||
|
||
public String[] getColumnHeaders() { | ||
String[] rc = new String[_headers.length]; | ||
System.arraycopy(_headers, 0, rc, 0, _headers.length); | ||
return rc; | ||
} | ||
|
||
public double[][] getData() { | ||
double[][] copy = new double[_data.length][]; | ||
copyDataFromTo(_data, copy); | ||
return copy; | ||
|
||
} | ||
|
||
private void copyDataFromTo(double[][] data2, double[][] copy) { | ||
int i = 0; | ||
for (double[] row : data2) { | ||
double[] copyRow = new double[row.length]; | ||
System.arraycopy(row, 0, copyRow, 0, row.length); | ||
|
||
copy[i++] = copyRow; | ||
} | ||
|
||
} | ||
|
||
|
||
public int getNumColumns() { | ||
return _headers.length; | ||
} | ||
|
||
public int getNumDataRows() { | ||
return _data.length; | ||
} | ||
|
||
public Double [] getDataByColumnId(String colID) { | ||
int colInd = getIndexByColumnID(colID); | ||
if(colInd == -1){ | ||
return null; | ||
} | ||
Double [] rc = new Double[_data.length]; | ||
for (int i=0; i< _data.length;i++){ | ||
rc[i]=_data[i][colInd]; | ||
} | ||
return rc; | ||
} | ||
|
||
public int getIndexByColumnID(String colID){ | ||
int colInd=-1; | ||
for (int i =0; i< _headers.length;i++){ | ||
if(_headers[i].equals(colID)){ | ||
colInd=i; | ||
} | ||
} | ||
return colInd; | ||
} | ||
|
||
public Double[] getDataByColumnIndex(int index) { | ||
Double [] rc = new Double[_data.length]; | ||
for (int i=0; i< _data.length;i++){ | ||
rc[i]=_data[i][index]; | ||
} | ||
return rc; | ||
} | ||
|
||
} |
296 changes: 296 additions & 0 deletions
296
src/main/java/org/simulator/sedml/ProcessSedMLResults.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,296 @@ | ||
package org.simulator.sedml; | ||
|
||
import java.util.ArrayList; | ||
import java.util.Arrays; | ||
import java.util.HashMap; | ||
import java.util.Iterator; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.Set; | ||
|
||
import org.jlibsedml.AbstractTask; | ||
import org.jlibsedml.DataGenerator; | ||
import org.jlibsedml.Output; | ||
import org.jlibsedml.Parameter; | ||
import org.jlibsedml.SedML; | ||
import org.jlibsedml.Variable; | ||
import org.jlibsedml.VariableSymbol; | ||
import org.jlibsedml.execution.IModel2DataMappings; | ||
import org.jlibsedml.execution.IProcessedSedMLSimulationResults; | ||
import org.jlibsedml.execution.IRawSedmlSimulationResults; | ||
import org.jlibsedml.execution.IXPathToVariableIDResolver; | ||
import org.jlibsedml.modelsupport.SBMLSupport; | ||
import org.jmathml.ASTCi; | ||
import org.jmathml.ASTNode; | ||
import org.jmathml.ASTNumber; | ||
import org.jmathml.EvaluationContext; | ||
|
||
import de.binfalse.bflog.LOGGER; | ||
|
||
|
||
/** | ||
* Processes raw simulation results according to instructions specified in the | ||
* {@link DataGenerator} elements specified in the output. <br/> | ||
* This class is used to process results using information in dataGenerator elements. | ||
* It is similar to jlibsedml's ProcessSedMLResults2 with the added support for working | ||
* with repeatedTasks. | ||
* @author Shalin Shah | ||
* @since 1.5 | ||
*/ | ||
public class ProcessSedMLResults { | ||
private Output wanted; | ||
private SedML sedml; | ||
IProcessedSedMLSimulationResults prRes; | ||
|
||
public ProcessSedMLResults(SedML sedml, Output output) { | ||
// Check for nulls | ||
if (sedml == null || output == null) { | ||
throw new IllegalArgumentException(); | ||
} | ||
this.sedml = sedml; | ||
this.wanted = output; | ||
|
||
// Check that required output exists in sedml | ||
boolean found = false; | ||
for (Output o : sedml.getOutputs()) { | ||
if (o.getId().equals(wanted.getId())) { | ||
found = true; | ||
} | ||
} | ||
if (!found) { | ||
throw new IllegalArgumentException("Output [" + wanted.getId() | ||
+ "] does not belong the SED-ML object. "); | ||
} | ||
} | ||
|
||
/** | ||
* This method modifies jlibsedml's process method to support dataGenerators for | ||
* repeatedTasks. Processed results can be extracted using getProcessedResult(). | ||
* @param Map<AbstractTask, List<IRawSedmlSimulationResults>> | ||
*/ | ||
public void process(Map<AbstractTask, List<IRawSedmlSimulationResults>> res){ | ||
|
||
// Check for nulls | ||
if (res == null) { | ||
throw new IllegalArgumentException(); | ||
} | ||
if(wanted.getAllDataGeneratorReferences().isEmpty()) { | ||
LOGGER.warn("Data generator list is empty!"); | ||
throw new NullPointerException(); | ||
} | ||
|
||
// calculate total number of rows in all the results | ||
int numRows = 0; | ||
for (AbstractTask t : res.keySet()) { | ||
List<IRawSedmlSimulationResults> result = res.get(t); | ||
for(IRawSedmlSimulationResults curRes: result) { | ||
numRows += curRes.getNumDataRows(); | ||
} | ||
} | ||
Map<AbstractTask, double[][]> rawTask2Results = new HashMap<AbstractTask, double[][]>(); | ||
|
||
// Iterate over all the data generators to process results | ||
List<double[]> processed = new ArrayList<double[]>(); | ||
IXPathToVariableIDResolver variable2IDResolver = new SBMLSupport(); | ||
for (String dgId : wanted.getAllDataGeneratorReferences()) { | ||
double[] mutated = new double[numRows]; | ||
processed.add(mutated); | ||
DataGenerator dg = sedml.getDataGeneratorWithId(dgId); | ||
if (dg == null) { | ||
LOGGER.warn("Empty data generator recevied. Correct SED-ML!"); | ||
return; | ||
} | ||
|
||
List<Variable> vars = dg.getListOfVariables(); | ||
List<Parameter> params = dg.getListOfParameters(); | ||
Map<String, String> Var2Model = new HashMap<String, String>(); | ||
Map<String, IRawSedmlSimulationResults> var2Result = new HashMap<String, IRawSedmlSimulationResults>(); | ||
Map<String, double[][]> var2Data = new HashMap<String, double[][]>(); | ||
String timeID = ""; | ||
// map varIds to result, based upon task reference | ||
for (Variable variable : vars) { | ||
String modelID; | ||
|
||
if (variable.isVariable()) { | ||
// get the task from which this result variable was generated. | ||
modelID = variable2IDResolver.getIdFromXPathIdentifer(variable.getTarget()); | ||
String taskRef = variable.getReference(); | ||
AbstractTask t = sedml.getTaskWithId(taskRef); | ||
|
||
// get results list for this task. If it is repeatedTask then multiple results | ||
List<IRawSedmlSimulationResults> resList = res.get(t); | ||
|
||
// set up lookups to results, raw data and model ID | ||
if (resList.size() > 1) { | ||
// It's a repeatedTask so process each iteration | ||
int index = 0; | ||
for(IRawSedmlSimulationResults curRes: resList) { | ||
|
||
// Add _index to the id of variable for one iteration of RepeatedTask | ||
var2Result.put(variable.getId() + "_" + Integer.toString(index), curRes); | ||
var2Data.put(variable.getId() + "_" + Integer.toString(index), rawTask2Results.get(t)); | ||
Var2Model.put(variable.getId() + "_" + Integer.toString(index), modelID); | ||
index++; | ||
} | ||
}else { | ||
// Just a Task so get first element | ||
var2Result.put(variable.getId(), resList.get(0)); | ||
var2Data.put(variable.getId(), rawTask2Results.get(t)); | ||
Var2Model.put(variable.getId(), modelID); | ||
} | ||
|
||
// it's a symbol | ||
} else if (variable.isSymbol() | ||
&& variable.getSymbol().equals(VariableSymbol.TIME)) { | ||
timeID = variable.getId(); | ||
var2Data.put(variable.getId(), rawTask2Results.values().iterator() | ||
.next()); | ||
Var2Model.put(variable.getId(), variable.getId()); | ||
|
||
} | ||
} | ||
|
||
// get Parameter values | ||
Map<String, Double> Param2Value = new HashMap<String, Double>(); | ||
for (Parameter p : params) { | ||
Param2Value.put(p.getId(), p.getValue()); | ||
} | ||
|
||
// now parse maths, and replace raw simulation results with | ||
// processed results. | ||
ASTNode node = dg.getMath(); | ||
Set<ASTCi> identifiers = node.getIdentifiers(); | ||
for (ASTCi var : identifiers) { | ||
if (var.isVector()) { | ||
String varName = var.getName(); | ||
IModel2DataMappings coll = var2Result.get(varName).getMappings(); | ||
int otherVarInx = coll.getColumnIndexFor(Var2Model.get(varName)); | ||
if (otherVarInx < 0 || otherVarInx >= var2Result.get(varName).getNumColumns()) { | ||
LOGGER.warn("No data column for " + var); | ||
return; | ||
} | ||
EvaluationContext con = new EvaluationContext(); | ||
Double[] data = var2Result.get(varName).getDataByColumnIndex(otherVarInx); | ||
|
||
con.setValueFor(varName, Arrays.asList(data)); | ||
|
||
if (var.getParentNode() == null || var.getParentNode().getParentNode() == null) { | ||
LOGGER.warn("Could not evaluate [" + var + "] as symbol does not have parent element"); | ||
return; | ||
} | ||
if (!var.getParentNode().canEvaluate(con)) { | ||
LOGGER.warn("Could not evaluate [" + var + "]"); | ||
return; | ||
} | ||
ASTNumber num = var.getParentNode().evaluate(con); | ||
// replace vector operation with calculated value. | ||
var.getParentNode().getParentNode().replaceChild(var.getParentNode(), num); | ||
} | ||
} | ||
// identifiers.add(var.getSpId()); | ||
if (identifiersMapToData(identifiers, Var2Model, Param2Value, var2Result, timeID)) { | ||
|
||
for (int i = 0; i < numRows; i++) { | ||
EvaluationContext con = new EvaluationContext(); | ||
|
||
for (String id : Param2Value.keySet()) { | ||
con.setValueFor(id, Param2Value.get(id)); | ||
} | ||
|
||
for (ASTCi var : identifiers) { | ||
// we've already resolved parameters | ||
if (Param2Value.get(var.getName()) != null) { | ||
continue; | ||
} | ||
int otherVarInx = 0; | ||
if (!var.getName().equals(timeID)) { | ||
IModel2DataMappings coll = var2Result.get( | ||
var.getName()).getMappings(); | ||
otherVarInx = coll.getColumnIndexFor(Var2Model | ||
.get(var.getName())); | ||
if (otherVarInx < 0 | ||
|| otherVarInx >= var2Result.get( | ||
var.getName()).getNumColumns()) { | ||
LOGGER.warn("No data column for " + var); | ||
return; | ||
} | ||
} | ||
con.setValueFor(var.getName(), | ||
var2Data.get(var.getName())[i][otherVarInx]); | ||
} | ||
|
||
if (node.canEvaluate(con)) { | ||
mutated[i] = node.evaluate(con).getValue(); | ||
} else { | ||
LOGGER.warn("Math could not be executed for data generator " + dgId); | ||
} | ||
} | ||
} else { | ||
LOGGER.warn("Math could not be executed for data generator " + dgId); | ||
return; | ||
} | ||
} | ||
|
||
prRes = createData(processed, numRows); | ||
} | ||
|
||
// Helper method for processing simulation results as per dataGenerator instructions | ||
// Borrowed from jlibsedml library to deal with repeatedTasks | ||
private boolean identifiersMapToData(Set<ASTCi> identifiers, | ||
Map<String, String> Var2Model, Map<String, Double> Param2Value, | ||
Map<String, IRawSedmlSimulationResults> var2Result, String timeID) { | ||
|
||
for (ASTCi var : identifiers) { | ||
boolean seen = false; | ||
if (Param2Value.get(var.getName()) != null) { | ||
seen = true; | ||
} else if (Var2Model.get(var.getName()) != null) { | ||
if (var.getName().equals(timeID)) { | ||
seen = true; | ||
} else { | ||
IModel2DataMappings coll = var2Result.get(var.getName()) | ||
.getMappings(); | ||
if (coll.hasMappingFor(Var2Model.get(var.getName())) | ||
&& coll.getColumnTitleFor(Var2Model.get(var | ||
.getName())) != null | ||
|| var.getName().equals(timeID)) { | ||
seen = true; | ||
} | ||
} | ||
} | ||
|
||
if (!seen) { | ||
return false; | ||
} | ||
|
||
} | ||
return true; | ||
} | ||
|
||
// Helper method for processing simulation results as per dataGenerator instructions | ||
// Borrowed from jlibsedml library to deal with repeatedTasks | ||
private IProcessedSedMLSimulationResults createData( | ||
List<double[]> processed, int NumRows) { | ||
|
||
String[] hdrs = new String[processed.size()]; | ||
int colInd = 0; | ||
for (Iterator<String> it = wanted.getAllDataGeneratorReferences() | ||
.iterator(); it.hasNext();) { | ||
hdrs[colInd++] = it.next(); | ||
} | ||
|
||
double[][] data = new double[NumRows][hdrs.length]; | ||
for (int j = 0; j < NumRows; j++) { | ||
for (int i = 0; i < hdrs.length; i++) { | ||
data[j][i] = processed.get(i)[j]; | ||
} | ||
|
||
} | ||
return new IProcessedSedMLSimulationResultsWrapper(data, hdrs); | ||
|
||
} | ||
|
||
public IProcessedSedMLSimulationResults getProcessedResult() { | ||
return prRes; | ||
} | ||
} |
Oops, something went wrong.