use of org.jlibsedml.SubTask in project vcell by virtualcell.
the class SEDMLExporter method translateBioModelToSedML.
private void translateBioModelToSedML(String savePath) {
sbmlFilePathStrAbsoluteList.clear();
// models
try {
SimulationContext[] simContexts = vcBioModel.getSimulationContexts();
cbit.vcell.model.Model vcModel = vcBioModel.getModel();
// "urn:sedml:language:sbml";
String sbmlLanguageURN = SUPPORTED_LANGUAGE.SBML_GENERIC.getURN();
String bioModelName = TokenMangler.mangleToSName(vcBioModel.getName());
// String usrHomeDirPath = ResourceUtil.getUserHomeDir().getAbsolutePath();
// to get Xpath string for variables.
SBMLSupport sbmlSupport = new SBMLSupport();
// for model count, task subcount
int simContextCnt = 0;
// for dtaGenerator count.
int varCount = 0;
boolean bSpeciesAddedAsDataGens = false;
String sedmlNotesStr = "";
for (SimulationContext simContext : simContexts) {
String simContextName = simContext.getName();
// export all applications that are not spatial stochastic
if (!(simContext.getGeometry().getDimension() > 0 && simContext.isStoch())) {
// to compute and set the sizes of the remaining structures.
if (!simContext.getGeometryContext().isAllSizeSpecifiedPositive()) {
Structure structure = simContext.getModel().getStructure(0);
double structureSize = 1.0;
StructureMapping structMapping = simContext.getGeometryContext().getStructureMapping(structure);
StructureSizeSolver.updateAbsoluteStructureSizes(simContext, structure, structureSize, structMapping.getSizeParameter().getUnitDefinition());
}
// Export the application itself to SBML, with default overrides
String sbmlString = null;
int level = 2;
int version = 4;
boolean isSpatial = simContext.getGeometry().getDimension() > 0 ? true : false;
SimulationJob simJob = null;
// if (simContext.getGeometry().getDimension() > 0) {
// sbmlString = XmlHelper.exportSBML(vcBioModel, 2, 4, 0, true, simContext, null);
// } else {
// sbmlString = XmlHelper.exportSBML(vcBioModel, 2, 4, 0, false, simContext, null);
// }
//
// TODO: we need to salvage from the SBMLExporter info about the fate of local parameters
// some of them may stay as locals, some others may become globals
// Any of these, if used in a repeated task or change or whatever, needs to be used in a consistent way,
// that is, if a param becomes a global in SBML, we need to refer at it in SEDML as the same global
//
// We'll use:
// Map<Pair <String reaction, String param>, String global> - if local converted to global
// Set<Pair <String reaction, String param>> (if needed?) - if local stays local
//
// local to global translation map
Map<Pair<String, String>, String> l2gMap = null;
if (vcBioModel instanceof BioModel) {
try {
// check if model to be exported to SBML has units compatible with SBML default units (default units in SBML can be assumed only until SBML Level2)
ModelUnitSystem forcedModelUnitSystem = simContext.getModel().getUnitSystem();
if (level < 3 && !ModelUnitSystem.isCompatibleWithDefaultSBMLLevel2Units(forcedModelUnitSystem)) {
forcedModelUnitSystem = ModelUnitSystem.createDefaultSBMLLevel2Units();
}
// create new Biomodel with new (SBML compatible) unit system
BioModel modifiedBiomodel = ModelUnitConverter.createBioModelWithNewUnitSystem(simContext.getBioModel(), forcedModelUnitSystem);
// extract the simContext from new Biomodel. Apply overrides to *this* modified simContext
SimulationContext simContextFromModifiedBioModel = modifiedBiomodel.getSimulationContext(simContext.getName());
SBMLExporter sbmlExporter = new SBMLExporter(modifiedBiomodel, level, version, isSpatial);
sbmlExporter.setSelectedSimContext(simContextFromModifiedBioModel);
// no sim job
sbmlExporter.setSelectedSimulationJob(null);
sbmlString = sbmlExporter.getSBMLFile();
l2gMap = sbmlExporter.getLocalToGlobalTranslationMap();
} catch (ExpressionException | SbmlException e) {
e.printStackTrace(System.out);
throw new XmlParseException(e);
}
} else {
throw new RuntimeException("unsupported Document Type " + vcBioModel.getClass().getName() + " for SBML export");
}
String sbmlFilePathStrAbsolute = savePath + FileUtils.WINDOWS_SEPARATOR + bioModelName + "_" + simContextName + ".xml";
String sbmlFilePathStrRelative = bioModelName + "_" + simContextName + ".xml";
XmlUtil.writeXMLStringToFile(sbmlString, sbmlFilePathStrAbsolute, true);
sbmlFilePathStrAbsoluteList.add(sbmlFilePathStrRelative);
String simContextId = TokenMangler.mangleToSName(simContextName);
sedmlModel.addModel(new Model(simContextId, simContextName, sbmlLanguageURN, sbmlFilePathStrRelative));
// required for mathOverrides, if any
MathMapping mathMapping = simContext.createNewMathMapping();
MathSymbolMapping mathSymbolMapping = mathMapping.getMathSymbolMapping();
// create sedml simulation objects and tasks (mapping each sim with current simContext)
int simCount = 0;
String taskRef = null;
int overrideCount = 0;
for (Simulation vcSimulation : simContext.getSimulations()) {
List<DataGenerator> dataGeneratorsOfSim = new ArrayList<DataGenerator>();
// if simContext is non-spatial stochastic, check if sim is histogram
SolverTaskDescription simTaskDesc = vcSimulation.getSolverTaskDescription();
if (simContext.getGeometry().getDimension() == 0 && simContext.isStoch()) {
long numOfTrials = simTaskDesc.getStochOpt().getNumOfTrials();
if (numOfTrials > 1) {
String msg = "\n\t" + simContextName + " ( " + vcSimulation.getName() + " ) : export of non-spatial stochastic simulation with histogram option to SEDML not supported at this time.";
sedmlNotesStr += msg;
continue;
}
}
// create Algorithm and sedmlSimulation (UniformtimeCourse)
SolverDescription vcSolverDesc = simTaskDesc.getSolverDescription();
// String kiSAOIdStr = getKiSAOIdFromSimulation(vcSolverDesc); // old way of doing it, going directly to the web site
String kiSAOIdStr = vcSolverDesc.getKisao();
Algorithm sedmlAlgorithm = new Algorithm(kiSAOIdStr);
TimeBounds vcSimTimeBounds = simTaskDesc.getTimeBounds();
double startingTime = vcSimTimeBounds.getStartingTime();
String simName = vcSimulation.getName();
UniformTimeCourse utcSim = new UniformTimeCourse(TokenMangler.mangleToSName(simName), simName, startingTime, startingTime, vcSimTimeBounds.getEndingTime(), (int) simTaskDesc.getExpectedNumTimePoints(), sedmlAlgorithm);
// if solver is not CVODE, add a note to utcSim to indicate actual solver name
if (!vcSolverDesc.equals(SolverDescription.CVODE)) {
String simNotesStr = "Actual Solver Name : '" + vcSolverDesc.getDisplayLabel() + "'.";
utcSim.addNote(createNotesElement(simNotesStr));
}
sedmlModel.addSimulation(utcSim);
// add SEDML tasks (map simulation to model:simContext)
// repeated tasks
MathOverrides mathOverrides = vcSimulation.getMathOverrides();
if (mathOverrides != null && mathOverrides.hasOverrides()) {
String[] overridenConstantNames = mathOverrides.getOverridenConstantNames();
String[] scannedConstantsNames = mathOverrides.getScannedConstantNames();
HashMap<String, String> scannedParamHash = new HashMap<String, String>();
HashMap<String, String> unscannedParamHash = new HashMap<String, String>();
for (String name : scannedConstantsNames) {
scannedParamHash.put(name, name);
}
for (String name : overridenConstantNames) {
if (!scannedParamHash.containsKey(name)) {
unscannedParamHash.put(name, name);
}
}
if (!unscannedParamHash.isEmpty() && scannedParamHash.isEmpty()) {
// only parameters with simple overrides (numeric/expression) no scans
// create new model with change for each parameter that has override; add simple task
String overriddenSimContextId = simContextId + "_" + overrideCount;
String overriddenSimContextName = simContextName + " modified";
Model sedModel = new Model(overriddenSimContextId, overriddenSimContextName, sbmlLanguageURN, simContextId);
overrideCount++;
for (String unscannedParamName : unscannedParamHash.values()) {
SymbolTableEntry ste = getSymbolTableEntryForModelEntity(mathSymbolMapping, unscannedParamName);
Expression unscannedParamExpr = mathOverrides.getActualExpression(unscannedParamName, 0);
if (unscannedParamExpr.isNumeric()) {
// if expression is numeric, add ChangeAttribute to model created above
XPathTarget targetXpath = getTargetAttributeXPath(ste, l2gMap);
ChangeAttribute changeAttribute = new ChangeAttribute(targetXpath, unscannedParamExpr.infix());
sedModel.addChange(changeAttribute);
} else {
// non-numeric expression : add 'computeChange' to modified model
ASTNode math = Libsedml.parseFormulaString(unscannedParamExpr.infix());
XPathTarget targetXpath = getTargetXPath(ste, l2gMap);
ComputeChange computeChange = new ComputeChange(targetXpath, math);
String[] exprSymbols = unscannedParamExpr.getSymbols();
for (String symbol : exprSymbols) {
String symbolName = TokenMangler.mangleToSName(symbol);
SymbolTableEntry ste1 = vcModel.getEntry(symbol);
if (ste != null) {
if (ste1 instanceof SpeciesContext || ste1 instanceof Structure || ste1 instanceof ModelParameter) {
XPathTarget ste1_XPath = getTargetXPath(ste1, l2gMap);
org.jlibsedml.Variable sedmlVar = new org.jlibsedml.Variable(symbolName, symbolName, taskRef, ste1_XPath.getTargetAsString());
computeChange.addVariable(sedmlVar);
} else {
double doubleValue = 0.0;
if (ste1 instanceof ReservedSymbol) {
doubleValue = getReservedSymbolValue(ste1);
}
Parameter sedmlParameter = new Parameter(symbolName, symbolName, doubleValue);
computeChange.addParameter(sedmlParameter);
}
} else {
throw new RuntimeException("Symbol '" + symbol + "' used in expression for '" + unscannedParamName + "' not found in model.");
}
}
sedModel.addChange(computeChange);
}
}
sedmlModel.addModel(sedModel);
String taskId = "tsk_" + simContextCnt + "_" + simCount;
Task sedmlTask = new Task(taskId, taskId, sedModel.getId(), utcSim.getId());
sedmlModel.addTask(sedmlTask);
// to be used later to add dataGenerators : one set of DGs per model (simContext).
taskRef = taskId;
} else if (!scannedParamHash.isEmpty() && unscannedParamHash.isEmpty()) {
// only parameters with scans : only add 1 Task and 1 RepeatedTask
String taskId = "tsk_" + simContextCnt + "_" + simCount;
Task sedmlTask = new Task(taskId, taskId, simContextId, utcSim.getId());
sedmlModel.addTask(sedmlTask);
String repeatedTaskId = "repTsk_" + simContextCnt + "_" + simCount;
// TODO: temporary solution - we use as range here the first range
String scn = scannedConstantsNames[0];
String rId = "range_" + simContextCnt + "_" + simCount + "_" + scn;
RepeatedTask rt = new RepeatedTask(repeatedTaskId, repeatedTaskId, true, rId);
// to be used later to add dataGenerators - in our case it has to be the repeated task
taskRef = repeatedTaskId;
SubTask subTask = new SubTask("0", taskId);
rt.addSubtask(subTask);
for (String scannedConstName : scannedConstantsNames) {
ConstantArraySpec constantArraySpec = mathOverrides.getConstantArraySpec(scannedConstName);
String rangeId = "range_" + simContextCnt + "_" + simCount + "_" + scannedConstName;
// list of Ranges, if sim is parameter scan.
if (constantArraySpec != null) {
Range r = null;
System.out.println(" " + constantArraySpec.toString());
if (constantArraySpec.getType() == ConstantArraySpec.TYPE_INTERVAL) {
// ------ Uniform Range
r = new UniformRange(rangeId, constantArraySpec.getMinValue(), constantArraySpec.getMaxValue(), constantArraySpec.getNumValues());
rt.addRange(r);
} else {
// ----- Vector Range
cbit.vcell.math.Constant[] cs = constantArraySpec.getConstants();
ArrayList<Double> values = new ArrayList<Double>();
for (int i = 0; i < cs.length; i++) {
String value = cs[i].getExpression().infix();
values.add(Double.parseDouble(value));
}
r = new VectorRange(rangeId, values);
rt.addRange(r);
}
// list of Changes
SymbolTableEntry ste = getSymbolTableEntryForModelEntity(mathSymbolMapping, scannedConstName);
XPathTarget target = getTargetXPath(ste, l2gMap);
// ASTNode math1 = new ASTCi(r.getId()); // was scannedConstName
ASTNode math1 = Libsedml.parseFormulaString(r.getId());
SetValue setValue = new SetValue(target, r.getId(), simContextId);
setValue.setMath(math1);
rt.addChange(setValue);
} else {
throw new RuntimeException("No scan ranges found for scanned parameter : '" + scannedConstName + "'.");
}
}
sedmlModel.addTask(rt);
} else {
// both scanned and simple parameters : create new model with change for each simple override; add RepeatedTask
// create new model with change for each unscanned parameter that has override
String overriddenSimContextId = simContextId + "_" + overrideCount;
String overriddenSimContextName = simContextName + " modified";
Model sedModel = new Model(overriddenSimContextId, overriddenSimContextName, sbmlLanguageURN, simContextId);
overrideCount++;
String taskId = "tsk_" + simContextCnt + "_" + simCount;
Task sedmlTask = new Task(taskId, taskId, overriddenSimContextId, utcSim.getId());
sedmlModel.addTask(sedmlTask);
// scanned parameters
String repeatedTaskId = "repTsk_" + simContextCnt + "_" + simCount;
// TODO: temporary solution - we use as range here the first range
String scn = scannedConstantsNames[0];
String rId = "range_" + simContextCnt + "_" + simCount + "_" + scn;
RepeatedTask rt = new RepeatedTask(repeatedTaskId, repeatedTaskId, true, rId);
// to be used later to add dataGenerators - in our case it has to be the repeated task
taskRef = repeatedTaskId;
SubTask subTask = new SubTask("0", taskId);
rt.addSubtask(subTask);
for (String scannedConstName : scannedConstantsNames) {
ConstantArraySpec constantArraySpec = mathOverrides.getConstantArraySpec(scannedConstName);
String rangeId = "range_" + simContextCnt + "_" + simCount + "_" + scannedConstName;
// list of Ranges, if sim is parameter scan.
if (constantArraySpec != null) {
Range r = null;
System.out.println(" " + constantArraySpec.toString());
if (constantArraySpec.getType() == ConstantArraySpec.TYPE_INTERVAL) {
// ------ Uniform Range
r = new UniformRange(rangeId, constantArraySpec.getMinValue(), constantArraySpec.getMaxValue(), constantArraySpec.getNumValues());
rt.addRange(r);
} else {
// ----- Vector Range
cbit.vcell.math.Constant[] cs = constantArraySpec.getConstants();
ArrayList<Double> values = new ArrayList<Double>();
for (int i = 0; i < cs.length; i++) {
String value = cs[i].getExpression().infix() + ", ";
values.add(Double.parseDouble(value));
}
r = new VectorRange(rangeId, values);
rt.addRange(r);
}
// use scannedParamHash to store rangeId for that param, since it might be needed if unscanned param has a scanned param in expr.
if (scannedParamHash.get(scannedConstName).equals(scannedConstName)) {
// the hash was originally populated as <scannedParamName, scannedParamName>. Replace 'value' with rangeId for scannedParam
scannedParamHash.put(scannedConstName, r.getId());
}
// create setValue for scannedConstName
SymbolTableEntry ste2 = getSymbolTableEntryForModelEntity(mathSymbolMapping, scannedConstName);
XPathTarget target1 = getTargetXPath(ste2, l2gMap);
ASTNode math1 = new ASTCi(scannedConstName);
SetValue setValue1 = new SetValue(target1, r.getId(), sedModel.getId());
setValue1.setMath(math1);
rt.addChange(setValue1);
} else {
throw new RuntimeException("No scan ranges found for scanned parameter : '" + scannedConstName + "'.");
}
}
// for unscanned parameter overrides
for (String unscannedParamName : unscannedParamHash.values()) {
SymbolTableEntry ste = getSymbolTableEntryForModelEntity(mathSymbolMapping, unscannedParamName);
Expression unscannedParamExpr = mathOverrides.getActualExpression(unscannedParamName, 0);
if (unscannedParamExpr.isNumeric()) {
// if expression is numeric, add ChangeAttribute to model created above
XPathTarget targetXpath = getTargetAttributeXPath(ste, l2gMap);
ChangeAttribute changeAttribute = new ChangeAttribute(targetXpath, unscannedParamExpr.infix());
sedModel.addChange(changeAttribute);
} else {
// check for any scanned parameter in unscanned parameter expression
ASTNode math = Libsedml.parseFormulaString(unscannedParamExpr.infix());
String[] exprSymbols = unscannedParamExpr.getSymbols();
boolean bHasScannedParameter = false;
String scannedParamNameInUnscannedParamExp = null;
for (String symbol : exprSymbols) {
if (scannedParamHash.get(symbol) != null) {
bHasScannedParameter = true;
scannedParamNameInUnscannedParamExp = new String(symbol);
// @TODO check for multiple scannedParameters in expression.
break;
}
}
// (scanned parameter in expr) ? (add setValue for unscanned param in repeatedTask) : (add computeChange to modifiedModel)
if (bHasScannedParameter && scannedParamNameInUnscannedParamExp != null) {
// create setValue for unscannedParamName (which contains a scanned param in its expression)
SymbolTableEntry entry = getSymbolTableEntryForModelEntity(mathSymbolMapping, unscannedParamName);
XPathTarget target = getTargetXPath(entry, l2gMap);
String rangeId = scannedParamHash.get(scannedParamNameInUnscannedParamExp);
// @TODO: we have no range??
SetValue setValue = new SetValue(target, rangeId, sedModel.getId());
setValue.setMath(math);
rt.addChange(setValue);
} else {
// non-numeric expression : add 'computeChange' to modified model
XPathTarget targetXpath = getTargetXPath(ste, l2gMap);
ComputeChange computeChange = new ComputeChange(targetXpath, math);
for (String symbol : exprSymbols) {
String symbolName = TokenMangler.mangleToSName(symbol);
SymbolTableEntry ste1 = vcModel.getEntry(symbol);
// ste1 could be a math parameter, hence the above could return null
if (ste1 == null) {
ste1 = simContext.getMathDescription().getEntry(symbol);
}
if (ste1 != null) {
if (ste1 instanceof SpeciesContext || ste1 instanceof Structure || ste1 instanceof ModelParameter) {
XPathTarget ste1_XPath = getTargetXPath(ste1, l2gMap);
org.jlibsedml.Variable sedmlVar = new org.jlibsedml.Variable(symbolName, symbolName, taskRef, ste1_XPath.getTargetAsString());
computeChange.addVariable(sedmlVar);
} else {
double doubleValue = 0.0;
if (ste1 instanceof ReservedSymbol) {
doubleValue = getReservedSymbolValue(ste1);
} else if (ste instanceof Function) {
try {
doubleValue = ste.getExpression().evaluateConstant();
} catch (Exception e) {
e.printStackTrace(System.out);
throw new RuntimeException("Unable to evaluate function '" + ste.getName() + "' used in '" + unscannedParamName + "' expression : ", e);
}
} else {
doubleValue = ste.getConstantValue();
}
// TODO: shouldn't be s1_init_uM which is a math symbol, should be s0 (so use the ste-something from above)
// TODO: revert to Variable, not Parameter
Parameter sedmlParameter = new Parameter(symbolName, symbolName, doubleValue);
computeChange.addParameter(sedmlParameter);
}
} else {
throw new RuntimeException("Symbol '" + symbol + "' used in expression for '" + unscannedParamName + "' not found in model.");
}
}
sedModel.addChange(computeChange);
}
}
}
sedmlModel.addModel(sedModel);
sedmlModel.addTask(rt);
}
} else {
// no math overrides, add basic task.
String taskId = "tsk_" + simContextCnt + "_" + simCount;
Task sedmlTask = new Task(taskId, taskId, simContextId, utcSim.getId());
sedmlModel.addTask(sedmlTask);
// to be used later to add dataGenerators : one set of DGs per model (simContext).
taskRef = taskId;
}
// add one dataGenerator for 'time' for entire SEDML model.
// (using the id of the first task in model for 'taskRef' field of var since
String timeDataGenPrefix = DATAGENERATOR_TIME_NAME + "_" + taskRef;
DataGenerator timeDataGen = sedmlModel.getDataGeneratorWithId(timeDataGenPrefix);
if (timeDataGen == null) {
// org.jlibsedml.Variable timeVar = new org.jlibsedml.Variable(DATAGENERATOR_TIME_SYMBOL, DATAGENERATOR_TIME_SYMBOL, sedmlModel.getTasks().get(0).getId(), VariableSymbol.TIME);
org.jlibsedml.Variable timeVar = new org.jlibsedml.Variable(DATAGENERATOR_TIME_SYMBOL, DATAGENERATOR_TIME_SYMBOL, taskRef, VariableSymbol.TIME);
ASTNode math = Libsedml.parseFormulaString(DATAGENERATOR_TIME_SYMBOL);
timeDataGen = new DataGenerator(timeDataGenPrefix, timeDataGenPrefix, math);
timeDataGen.addVariable(timeVar);
sedmlModel.addDataGenerator(timeDataGen);
dataGeneratorsOfSim.add(timeDataGen);
}
// add dataGenerators for species
// get species list from SBML model.
String dataGenIdPrefix = "dataGen_" + taskRef;
String[] varNamesList = SimSpec.fromSBML(sbmlString).getVarsList();
for (String varName : varNamesList) {
org.jlibsedml.Variable sedmlVar = new org.jlibsedml.Variable(varName, varName, taskRef, sbmlSupport.getXPathForSpecies(varName));
ASTNode varMath = Libsedml.parseFormulaString(varName);
// "dataGen_" + varCount; - old code
String dataGenId = dataGenIdPrefix + "_" + TokenMangler.mangleToSName(varName);
DataGenerator dataGen = new DataGenerator(dataGenId, dataGenId, varMath);
dataGen.addVariable(sedmlVar);
sedmlModel.addDataGenerator(dataGen);
dataGeneratorsOfSim.add(dataGen);
varCount++;
}
// add DataGenerators for output functions here
ArrayList<AnnotatedFunction> outputFunctions = simContext.getOutputFunctionContext().getOutputFunctionsList();
for (AnnotatedFunction annotatedFunction : outputFunctions) {
Expression functionExpr = annotatedFunction.getExpression();
ASTNode funcMath = Libsedml.parseFormulaString(functionExpr.infix());
// "dataGen_" + varCount; - old code
String dataGenId = dataGenIdPrefix + "_" + TokenMangler.mangleToSName(annotatedFunction.getName());
DataGenerator dataGen = new DataGenerator(dataGenId, dataGenId, funcMath);
String[] functionSymbols = functionExpr.getSymbols();
for (String symbol : functionSymbols) {
String symbolName = TokenMangler.mangleToSName(symbol);
// try to get symbol from model, if null, try simContext.mathDesc
SymbolTableEntry ste = vcModel.getEntry(symbol);
if (ste == null) {
ste = simContext.getMathDescription().getEntry(symbol);
}
if (ste instanceof SpeciesContext || ste instanceof Structure || ste instanceof ModelParameter) {
XPathTarget targetXPath = getTargetXPath(ste, l2gMap);
org.jlibsedml.Variable sedmlVar = new org.jlibsedml.Variable(symbolName, symbolName, taskRef, targetXPath.getTargetAsString());
dataGen.addVariable(sedmlVar);
} else {
double value = 0.0;
if (ste instanceof Function) {
try {
value = ste.getExpression().evaluateConstant();
} catch (Exception e) {
e.printStackTrace(System.out);
throw new RuntimeException("Unable to evaluate function '" + ste.getName() + "' for output function '" + annotatedFunction.getName() + "'.", e);
}
} else {
value = ste.getConstantValue();
}
Parameter sedmlParameter = new Parameter(symbolName, symbolName, value);
dataGen.addParameter(sedmlParameter);
}
}
sedmlModel.addDataGenerator(dataGen);
dataGeneratorsOfSim.add(dataGen);
varCount++;
}
simCount++;
// ignoring output for spatial deterministic (spatial stochastic is not exported to SEDML) and non-spatial stochastic applications with histogram
if (!(simContext.getGeometry().getDimension() > 0)) {
// ignore Output (Plot2d) for non-spatial stochastic simulation with histogram.
boolean bSimHasHistogram = false;
if (simContext.isStoch()) {
long numOfTrials = simTaskDesc.getStochOpt().getNumOfTrials();
if (numOfTrials > 1) {
// not histogram {
bSimHasHistogram = true;
}
}
if (!bSimHasHistogram) {
String plot2dId = "plot2d_" + TokenMangler.mangleToSName(vcSimulation.getName());
Plot2D sedmlPlot2d = new Plot2D(plot2dId, simContext.getName() + "plots");
sedmlPlot2d.addNote(createNotesElement("Plot of all variables and output functions from application '" + simContext.getName() + "' ; simulation '" + vcSimulation.getName() + "' in VCell model"));
List<DataGenerator> dataGenerators = sedmlModel.getDataGenerators();
String xDataRef = sedmlModel.getDataGeneratorWithId(DATAGENERATOR_TIME_NAME + "_" + taskRef).getId();
// add a curve for each dataGenerator in SEDML model
int curveCnt = 0;
for (DataGenerator dataGenerator : dataGeneratorsOfSim) {
// no curve for time, since time is xDateReference
if (dataGenerator.getId().equals(xDataRef)) {
continue;
}
String curveId = "curve_" + curveCnt++;
Curve curve = new Curve(curveId, curveId, false, false, xDataRef, dataGenerator.getId());
sedmlPlot2d.addCurve(curve);
}
sedmlModel.addOutput(sedmlPlot2d);
}
}
}
// end - for 'sims'
} else {
// end if (!(simContext.getGeometry().getDimension() > 0 && simContext.isStoch()))
String msg = "\n\t" + simContextName + " : export of spatial stochastic (Smoldyn solver) applications to SEDML not supported at this time.";
sedmlNotesStr += msg;
}
// end : if-else simContext is not spatial stochastic
simContextCnt++;
}
// if sedmlNotesStr is not null, there were some applications that could not be exported to SEDML (eg., spatial stochastic). Create a notes element and add it to sedml Model.
if (sedmlNotesStr.length() > 0) {
sedmlNotesStr = "\n\tThe following applications in the VCell model were not exported to VCell : " + sedmlNotesStr;
sedmlModel.addNote(createNotesElement(sedmlNotesStr));
}
// error check : if there are no non-spatial deterministic applications (=> no models in SEDML document), complain.
if (sedmlModel.getModels().isEmpty()) {
throw new RuntimeException("No applications in biomodel to export to Sedml.");
}
} catch (Exception e) {
e.printStackTrace(System.out);
throw new RuntimeException("Error adding model to SEDML document : " + e.getMessage());
}
}
use of org.jlibsedml.SubTask in project vcell by virtualcell.
the class XmlHelper method sedmlToBioModel.
public static VCDocument sedmlToBioModel(VCLogger transLogger, ExternalDocInfo externalDocInfo, SedML sedml, AbstractTask selectedTask) throws Exception {
if (sedml.getModels().isEmpty()) {
return null;
}
VCDocument doc = null;
try {
// extract the path only from the sedml file
String fullPath = FileUtils.getFullPath(externalDocInfo.getFile().getAbsolutePath());
// Namespace namespace = sedml.getNamespace();
// iterate through all the elements and show them at the console
List<org.jlibsedml.Model> mmm = sedml.getModels();
for (Model mm : mmm) {
System.out.println(mm.toString());
}
List<org.jlibsedml.Simulation> sss = sedml.getSimulations();
for (org.jlibsedml.Simulation ss : sss) {
System.out.println(ss.toString());
}
List<AbstractTask> ttt = sedml.getTasks();
for (AbstractTask tt : ttt) {
System.out.println(tt.toString());
}
List<DataGenerator> ddd = sedml.getDataGenerators();
for (DataGenerator dd : ddd) {
System.out.println(dd.toString());
}
List<Output> ooo = sedml.getOutputs();
for (Output oo : ooo) {
System.out.println(oo.toString());
}
KisaoTerm sedmlKisao = null;
// this will become the vCell simulation
org.jlibsedml.Simulation sedmlSimulation = null;
// the "original" model referred to by the task
org.jlibsedml.Model sedmlOriginalModel = null;
String sedmlOriginalModelName = null;
if (selectedTask == null) {
// no task, just pick the Model and find its sbml file
sedmlOriginalModelName = SEDMLUtil.getName(mmm.get(0));
} else {
if (selectedTask instanceof Task) {
sedmlOriginalModel = sedml.getModelWithId(selectedTask.getModelReference());
sedmlSimulation = sedml.getSimulation(selectedTask.getSimulationReference());
} else if (selectedTask instanceof RepeatedTask) {
RepeatedTask rt = (RepeatedTask) selectedTask;
assert (rt.getSubTasks().size() == 1);
// first (and only) subtask
SubTask st = rt.getSubTasks().entrySet().iterator().next().getValue();
String taskId = st.getTaskId();
AbstractTask t = sedml.getTaskWithId(taskId);
// get model and simulation from subtask
sedmlOriginalModel = sedml.getModelWithId(t.getModelReference());
sedmlSimulation = sedml.getSimulation(t.getSimulationReference());
} else {
throw new RuntimeException("Unexpected task " + selectedTask);
}
sedmlOriginalModelName = sedmlOriginalModel.getId();
sedmlKisao = KisaoOntology.getInstance().getTermById(sedmlSimulation.getAlgorithm().getKisaoID());
}
// UniformTimeCourse [initialTime=0.0, numberOfPoints=1000, outputEndTime=1.0, outputStartTime=0.0,
// Algorithm [kisaoID=KISAO:0000019], getId()=SimSlow]
// identify the vCell solvers that would match best the sedml solver kisao id
List<SolverDescription> solverDescriptions = new ArrayList<>();
for (SolverDescription sd : SolverDescription.values()) {
KisaoTerm solverKisaoTerm = KisaoOntology.getInstance().getTermById(sd.getKisao());
if (solverKisaoTerm == null) {
break;
}
boolean isExactlySame = solverKisaoTerm.equals(sedmlKisao);
if (isExactlySame && !solverKisaoTerm.isObsolete()) {
// we make a list with all the solvers that match the kisao
solverDescriptions.add(sd);
}
}
// from the list of vcell solvers that match the sedml kisao we select the ones that have a matching time step
SolverDescription solverDescription = null;
for (SolverDescription sd : solverDescriptions) {
if (true) {
solverDescription = sd;
break;
}
}
// find out everything else we need about the application we're going to use,
// some of the info will be needed when we parse the sbml file
boolean bSpatial = false;
Application appType = Application.NETWORK_DETERMINISTIC;
Set<SolverDescription.SolverFeature> sfList = solverDescription.getSupportedFeatures();
for (SolverDescription.SolverFeature sf : sfList) {
switch(sf) {
case Feature_Rulebased:
appType = Application.RULE_BASED_STOCHASTIC;
break;
case Feature_Stochastic:
appType = Application.NETWORK_STOCHASTIC;
break;
case Feature_Deterministic:
appType = Application.NETWORK_DETERMINISTIC;
break;
case Feature_Spatial:
bSpatial = true;
break;
default:
break;
}
}
// -------------------------------------------------------------------------------------------
// extract bioModel name from sedx (or sedml) file
String bioModelName = FileUtils.getBaseName(externalDocInfo.getFile().getAbsolutePath());
// if we have repeated task, we ignore them, we just use the normal resolvers for archive and changes
// once the application and simulation are built, we iterate through the repeated tasks and
// add math overrides to the simulation for each repeated task
ArchiveComponents ac = null;
if (externalDocInfo.getFile().getPath().toLowerCase().endsWith("sedx") || externalDocInfo.getFile().getPath().toLowerCase().endsWith("omex")) {
ac = Libsedml.readSEDMLArchive(new FileInputStream(externalDocInfo.getFile().getPath()));
}
ModelResolver resolver = new ModelResolver(sedml);
if (ac != null) {
resolver.add(new ArchiveModelResolver(ac));
}
resolver.add(new FileModelResolver());
resolver.add(new RelativeFileModelResolver(fullPath));
String newMdl = resolver.getModelString(sedmlOriginalModel);
// sbmlSource with all the changes applied
XMLSource sbmlSource = new XMLSource(newMdl);
doc = XmlHelper.importSBML(transLogger, sbmlSource, bSpatial);
BioModel bioModel = (BioModel) doc;
bioModel.setName(bioModelName);
// we already have an application loaded from the sbml file, with initial conditions and stuff
// which may be not be suitable because the sedml kisao may need a different app type
// so we do a "copy as" to the right type and then delete the original we loaded from the sbml file
// the new application we're making from the old one
SimulationContext newSimulationContext = null;
if (bioModel.getSimulationContexts().length == 1) {
SimulationContext oldSimulationContext = bioModel.getSimulationContext(0);
newSimulationContext = SimulationContext.copySimulationContext(oldSimulationContext, sedmlOriginalModelName, bSpatial, appType);
bioModel.removeSimulationContext(oldSimulationContext);
bioModel.addSimulationContext(newSimulationContext);
} else {
// length == 0
newSimulationContext = bioModel.addNewSimulationContext(sedmlOriginalModelName, appType);
}
// making the new vCell simulation based on the sedml simulation
newSimulationContext.refreshDependencies();
MathMappingCallback callback = new MathMappingCallbackTaskAdapter(null);
newSimulationContext.refreshMathDescription(callback, NetworkGenerationRequirements.ComputeFullStandardTimeout);
Simulation newSimulation = new Simulation(newSimulationContext.getMathDescription());
newSimulation.setName(SEDMLUtil.getName(sedmlSimulation));
// TODO: make sure that everything has proper names
// we check the repeated tasks, if any, and add to the list of math overrides
// if(selectedTask instanceof RepeatedTask) {
// for(Change change : ((RepeatedTask) selectedTask).getChanges()) {
// if(!(change instanceof SetValue)) {
// throw new RuntimeException("Only 'SetValue' changes are supported for repeated tasks.");
// }
// SetValue setValue = (SetValue)change;
// // TODO: extract target from XPath
// // ......
// //
// String target = "s0"; // for now we just use a hardcoded thing
// ConstantArraySpec cas;
// Range range = ((RepeatedTask) selectedTask).getRange(setValue.getRangeReference());
// if(range instanceof UniformRange) {
// cas = ConstantArraySpec.createIntervalSpec(target, ((UniformRange) range).getStart(), ((UniformRange) range).getEnd(),
// range.getNumElements(), ((UniformRange) range).getType() == UniformRange.UniformType.LOG ? true : false);
// } else if(range instanceof VectorRange) {
// // List<String> constants = new ArrayList<> ();
// // for(int i=0; i<range.getNumElements(); i++) {
// // constants.add(new Constant(i+"", new Expression(range.getElementAt(i))));
// // }
// // cas = ConstantArraySpec.createListSpec(target, constants);
//
// } else {
// throw new RuntimeException("Only 'Uniform Range' and 'Vector Range' are supported at this time.");
// }
//
// }
// }
// we identify the type of sedml simulation (uniform time course, etc)
// and set the vCell simulation parameters accordingly
SolverTaskDescription simTaskDesc = newSimulation.getSolverTaskDescription();
TimeBounds timeBounds = new TimeBounds();
TimeStep timeStep = new TimeStep();
double outputTimeStep = 0.1;
if (sedmlSimulation instanceof UniformTimeCourse) {
// we translate initial time to zero, we provide output for the duration of the simulation
// because we can't select just an interval the way the SEDML simulation can
double initialTime = ((UniformTimeCourse) sedmlSimulation).getInitialTime();
double outputStartTime = ((UniformTimeCourse) sedmlSimulation).getOutputStartTime();
double outputEndTime = ((UniformTimeCourse) sedmlSimulation).getOutputEndTime();
double outputNumberOfPoints = ((UniformTimeCourse) sedmlSimulation).getNumberOfPoints();
outputTimeStep = (outputEndTime - outputStartTime) / outputNumberOfPoints;
timeBounds = new TimeBounds(0, outputEndTime - initialTime);
} else if (sedmlSimulation instanceof OneStep) {
// for anything other than UniformTimeCourse we just ignore
} else if (sedmlSimulation instanceof SteadyState) {
} else {
}
OutputTimeSpec outputTimeSpec = new UniformOutputTimeSpec(outputTimeStep);
simTaskDesc.setTimeBounds(timeBounds);
simTaskDesc.setTimeStep(timeStep);
simTaskDesc.setOutputTimeSpec(outputTimeSpec);
newSimulation.setSolverTaskDescription(simTaskDesc);
bioModel.addSimulation(newSimulation);
newSimulation.refreshDependencies();
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("Unable to initialize bioModel for the given selection.");
}
return doc;
}
use of org.jlibsedml.SubTask in project vcell by virtualcell.
the class SEDMLChooserPanel method initialize.
private void initialize() {
Set<String> issues = new HashSet<>();
setLayout(new GridBagLayout());
int gridy = 0;
// (incompatibility with vCell for example) and for them we create a list of problems which we show to the user
for (AbstractTask at : sedml.getTasks()) {
String text = "";
String tooltip = "";
boolean issueFound = false;
if (at instanceof Task) {
Task t = (Task) at;
text = " Simple task '" + t.getId() + "' - " + sedml.getModelWithId(t.getModelReference()).getClass().getSimpleName() + // model class
" '" + SEDMLUtil.getName(sedml.getModelWithId(t.getModelReference())) + "' : " + sedml.getSimulation(t.getSimulationReference()).getClass().getSimpleName() + // simulation class
" '" + SEDMLUtil.getName(sedml.getSimulation(t.getSimulationReference())) + "' ";
tooltip = "The model has " + sedml.getModelWithId(t.getModelReference()).getListOfChanges().size() + " changes.";
} else if (at instanceof RepeatedTask) {
RepeatedTask rt = (RepeatedTask) at;
// TODO: we issue warning that importing repeated task is not implemented yet
// but we have still can import it as simple task, so we don't set issueFound to true
issues.add("Importing a RepeatedTask is not implemented yet, '" + SEDMLUtil.getName(rt) + "' may be imported as SimpleTask.");
// add an error message to the list of errors and skip the task
for (Change c : rt.getChanges()) {
if (!c.getChangeKind().equals(SEDMLTags.SET_VALUE_KIND)) {
issues.add("The '" + c.getChangeKind() + "' change kind is not supported.");
issueFound = true;
}
}
switch(rt.getSubTasks().size()) {
case 0:
issues.add("At least one subtask is required within a repeated task: " + rt.getId());
issueFound = true;
case 1:
// first (and only) element
SubTask st = rt.getSubTasks().entrySet().iterator().next().getValue();
String taskId = st.getTaskId();
AbstractTask t = sedml.getTaskWithId(taskId);
text = " Repeated task '" + rt.getId() + "' - " + sedml.getModelWithId(t.getModelReference()).getClass().getSimpleName() + // model class
" '" + SEDMLUtil.getName(sedml.getModelWithId(t.getModelReference())) + "' : " + sedml.getSimulation(t.getSimulationReference()).getClass().getSimpleName() + // simulation class
" '" + SEDMLUtil.getName(sedml.getSimulation(t.getSimulationReference())) + "' ";
tooltip = "The repeated task has " + rt.getChanges().size() + " changes and " + rt.getRanges().size() + " ranges.";
break;
default:
issues.add("Multiple subtasks within a repeated task '" + rt.getId() + "' are not supported.");
issueFound = true;
}
} else {
issues.add("The task class '" + SEDMLUtil.getName(at) + "' is not supported.");
issueFound = true;
}
if (issueFound) {
// we skip the tasks we don't know how to import in vCell
continue;
}
JRadioButton rb = new JRadioButton(text);
rb.setToolTipText(tooltip);
SEDMLRadioButtonModel bm = new SEDMLRadioButtonModel(at);
rb.setModel(bm);
if (gridy == 0) {
rb.setSelected(true);
}
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = gridy;
gbc.anchor = GridBagConstraints.WEST;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.insets = new Insets(2, 4, 2, 4);
group.add(rb);
add(rb, gbc);
gridy++;
}
// we display the issues (but no more than a certain number)
final int MAX_ISSUES = 10;
int issueIndex = 0;
for (String issue : issues) {
if (issueIndex >= MAX_ISSUES) {
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = gridy;
gbc.anchor = GridBagConstraints.WEST;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.insets = new Insets(2, 4, 2, 4);
add(new JLabel("<html><font color = \"#8B0000\">" + "...More" + "</font></html>"), gbc);
gridy++;
break;
}
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = gridy;
gbc.anchor = GridBagConstraints.WEST;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.insets = new Insets(2, 4, 2, 4);
add(new JLabel("<html><font color = \"#8B0000\">" + issue + "</font></html>"), gbc);
gridy++;
issueIndex++;
}
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = gridy;
gbc.gridwidth = 2;
gbc.weightx = 1;
// fake cell used for filling all the vertical empty space
gbc.weighty = 1;
gbc.anchor = GridBagConstraints.WEST;
gbc.insets = new Insets(4, 4, 4, 10);
add(new JLabel(""), gbc);
}
use of org.jlibsedml.SubTask in project vcell by virtualcell.
the class SEDMLExporter method translateBioModelToSedML.
private void translateBioModelToSedML(String savePath, String sBaseFileName, boolean bForceVCML, boolean bHasDataOnly, boolean bFromOmex) {
// true if invoked for omex export, false if for sedml
sbmlFilePathStrAbsoluteList.clear();
// models
try {
SimulationContext[] simContexts = vcBioModel.getSimulationContexts();
cbit.vcell.model.Model vcModel = vcBioModel.getModel();
// "urn:sedml:language:sbml";
String sbmlLanguageURN = SUPPORTED_LANGUAGE.SBML_GENERIC.getURN();
// "urn:sedml:language:vcml";
String vcmlLanguageURN = SUPPORTED_LANGUAGE.VCELL_GENERIC.getURN();
String bioModelName = vcBioModel.getName();
String bioModelID = TokenMangler.mangleToSName(bioModelName);
// String usrHomeDirPath = ResourceUtil.getUserHomeDir().getAbsolutePath();
// to get Xpath string for variables.
SBMLSupport sbmlSupport = new SBMLSupport();
// for model count, task subcount
int simContextCnt = 0;
boolean bSpeciesAddedAsDataGens = false;
String sedmlNotesStr = "";
for (SimulationContext simContext : simContexts) {
// Export the application itself to SBML, with default overrides
String sbmlString = null;
int level = 3;
int version = 1;
boolean isSpatial = simContext.getGeometry().getDimension() > 0 ? true : false;
// local to global translation map
Map<Pair<String, String>, String> l2gMap = null;
boolean sbmlExportFailed = false;
if (!bForceVCML) {
// we try to save to SBML
try {
// to compute and set the sizes of the remaining structures.
if (!simContext.getGeometryContext().isAllSizeSpecifiedPositive()) {
Structure structure = simContext.getModel().getStructure(0);
double structureSize = 1.0;
StructureMapping structMapping = simContext.getGeometryContext().getStructureMapping(structure);
StructureSizeSolver.updateAbsoluteStructureSizes(simContext, structure, structureSize, structMapping.getSizeParameter().getUnitDefinition());
// StructureMapping structureMapping = simContext.getGeometryContext().getStructureMappings()[0];
// StructureSizeSolver.updateAbsoluteStructureSizes(simContext, structureMapping.getStructure(), 1.0, structureMapping.getSizeParameter().getUnitDefinition());
}
SBMLExporter sbmlExporter = new SBMLExporter(vcBioModel, level, version, isSpatial);
sbmlExporter.setSelectedSimContext(simContext);
// no sim job
sbmlExporter.setSelectedSimulationJob(null);
sbmlString = sbmlExporter.getSBMLString();
l2gMap = sbmlExporter.getLocalToGlobalTranslationMap();
} catch (Exception e) {
sbmlExportFailed = true;
}
} else {
// we want to force VCML, we act as if saving to SBML failed
sbmlExportFailed = true;
}
// marked as failed, even if exporting to sbml didn't throw any exception
if (simContext.getGeometry().getDimension() > 0 && simContext.getApplicationType() == Application.NETWORK_STOCHASTIC) {
sbmlExportFailed = true;
} else if (simContext.getApplicationType() == Application.RULE_BASED_STOCHASTIC) {
sbmlExportFailed = true;
}
String simContextName = simContext.getName();
String filePathStrAbsolute = null;
String filePathStrRelative = null;
String urn = null;
String simContextId = null;
if (sbmlExportFailed) {
// filePathStrAbsolute = Paths.get(savePath, bioModelName + ".vcml").toString();
filePathStrAbsolute = Paths.get(savePath, sBaseFileName + ".vcml").toString();
// filePathStrRelative = bioModelName + ".vcml";
filePathStrRelative = sBaseFileName + ".vcml";
if (!bFromOmex) {
// the vcml file is managed elsewhere when called for omex
String vcmlString = XmlHelper.bioModelToXML(vcBioModel);
XmlUtil.writeXMLStringToFile(vcmlString, filePathStrAbsolute, true);
sbmlFilePathStrAbsoluteList.add(filePathStrRelative);
}
urn = vcmlLanguageURN;
sedmlModel.addModel(new Model(bioModelID, bioModelName, urn, filePathStrRelative));
} else {
// filePathStrAbsolute = Paths.get(savePath, bioModelName + "_" + TokenMangler.mangleToSName(simContextName) + ".xml").toString();
filePathStrAbsolute = Paths.get(savePath, sBaseFileName + "_" + TokenMangler.mangleToSName(simContextName) + ".xml").toString();
// filePathStrRelative = bioModelName + "_" + TokenMangler.mangleToSName(simContextName) + ".xml";
filePathStrRelative = sBaseFileName + "_" + TokenMangler.mangleToSName(simContextName) + ".xml";
XmlUtil.writeXMLStringToFile(sbmlString, filePathStrAbsolute, true);
urn = sbmlLanguageURN;
sbmlFilePathStrAbsoluteList.add(filePathStrRelative);
simContextId = TokenMangler.mangleToSName(simContextName);
sedmlModel.addModel(new Model(simContextId, simContextName, urn, filePathStrRelative));
}
MathMapping mathMapping = simContext.createNewMathMapping();
MathSymbolMapping mathSymbolMapping = mathMapping.getMathSymbolMapping();
// -------
// create sedml objects (simulation, task, datagenerators, report, plot) for each simulation in simcontext
// -------
int simCount = 0;
String taskRef = null;
int overrideCount = 0;
for (Simulation vcSimulation : simContext.getSimulations()) {
if (bHasDataOnly) {
// skip simulations not present in hash
if (!simsToExport.contains(vcSimulation))
continue;
}
// 1 -------> check compatibility
// if simContext is non-spatial stochastic, check if sim is histogram; if so, skip it, it can't be encoded in sedml 1.x
SolverTaskDescription simTaskDesc = vcSimulation.getSolverTaskDescription();
if (simContext.getGeometry().getDimension() == 0 && simContext.isStoch()) {
long numOfTrials = simTaskDesc.getStochOpt().getNumOfTrials();
if (numOfTrials > 1) {
String msg = "\n\t" + simContextName + " ( " + vcSimulation.getName() + " ) : export of non-spatial stochastic simulation with histogram option to SEDML not supported at this time.";
sedmlNotesStr += msg;
continue;
}
}
// 2 ------->
// create Algorithm and sedmlSimulation (UniformtimeCourse)
SolverDescription vcSolverDesc = simTaskDesc.getSolverDescription();
String kiSAOIdStr = vcSolverDesc.getKisao();
Algorithm sedmlAlgorithm = new Algorithm(kiSAOIdStr);
TimeBounds vcSimTimeBounds = simTaskDesc.getTimeBounds();
double startingTime = vcSimTimeBounds.getStartingTime();
String simName = vcSimulation.getName();
UniformTimeCourse utcSim = new UniformTimeCourse(TokenMangler.mangleToSName(simName), simName, startingTime, startingTime, vcSimTimeBounds.getEndingTime(), (int) simTaskDesc.getExpectedNumTimePoints(), sedmlAlgorithm);
// --------- deal with error tolerance
boolean enableAbsoluteErrorTolerance;
boolean enableRelativeErrorTolerance;
if (vcSolverDesc.isSemiImplicitPdeSolver() || vcSolverDesc.isChomboSolver()) {
enableAbsoluteErrorTolerance = false;
enableRelativeErrorTolerance = true;
} else if (vcSolverDesc.hasErrorTolerance()) {
enableAbsoluteErrorTolerance = true;
enableRelativeErrorTolerance = true;
} else {
enableAbsoluteErrorTolerance = false;
enableRelativeErrorTolerance = false;
}
if (enableAbsoluteErrorTolerance) {
ErrorTolerance et = simTaskDesc.getErrorTolerance();
String kisaoStr = ErrorTolerance.ErrorToleranceDescription.Absolute.getKisao();
AlgorithmParameter sedmlAlgorithmParameter = new AlgorithmParameter(kisaoStr, et.getAbsoluteErrorTolerance() + "");
sedmlAlgorithm.addAlgorithmParameter(sedmlAlgorithmParameter);
}
if (enableRelativeErrorTolerance) {
ErrorTolerance et = simTaskDesc.getErrorTolerance();
String kisaoStr = ErrorTolerance.ErrorToleranceDescription.Relative.getKisao();
AlgorithmParameter sedmlAlgorithmParameter = new AlgorithmParameter(kisaoStr, et.getRelativeErrorTolerance() + "");
sedmlAlgorithm.addAlgorithmParameter(sedmlAlgorithmParameter);
}
// ---------- deal with time step (code adapted from TimeSpecPanel.refresh()
boolean enableDefaultTimeStep;
boolean enableMinTimeStep;
boolean enableMaxTimeStep;
if (vcSolverDesc.compareEqual(SolverDescription.StochGibson)) {
// stochastic time
enableDefaultTimeStep = false;
enableMinTimeStep = false;
enableMaxTimeStep = false;
} else if (vcSolverDesc.compareEqual(SolverDescription.NFSim)) {
enableDefaultTimeStep = false;
enableMinTimeStep = false;
enableMaxTimeStep = false;
} else {
// fixed time step solvers and non spatial stochastic solvers only show default time step.
if (!vcSolverDesc.hasVariableTimestep() || vcSolverDesc.isNonSpatialStochasticSolver()) {
enableDefaultTimeStep = true;
enableMinTimeStep = false;
enableMaxTimeStep = false;
} else {
// variable time step solvers shows min and max, but sundials solvers don't show min
enableDefaultTimeStep = false;
enableMinTimeStep = true;
enableMaxTimeStep = true;
if (vcSolverDesc.hasSundialsTimeStepping()) {
enableMinTimeStep = false;
}
}
}
TimeStep ts = simTaskDesc.getTimeStep();
if (enableDefaultTimeStep) {
String kisaoStr = TimeStep.TimeStepDescription.Default.getKisao();
AlgorithmParameter sedmlAlgorithmParameter = new AlgorithmParameter(kisaoStr, ts.getDefaultTimeStep() + "");
sedmlAlgorithm.addAlgorithmParameter(sedmlAlgorithmParameter);
}
if (enableMinTimeStep) {
String kisaoStr = TimeStep.TimeStepDescription.Minimum.getKisao();
AlgorithmParameter sedmlAlgorithmParameter = new AlgorithmParameter(kisaoStr, ts.getMinimumTimeStep() + "");
sedmlAlgorithm.addAlgorithmParameter(sedmlAlgorithmParameter);
}
if (enableMaxTimeStep) {
String kisaoStr = TimeStep.TimeStepDescription.Maximum.getKisao();
AlgorithmParameter sedmlAlgorithmParameter = new AlgorithmParameter(kisaoStr, ts.getMaximumTimeStep() + "");
sedmlAlgorithm.addAlgorithmParameter(sedmlAlgorithmParameter);
}
if (simTaskDesc.getSimulation().getMathDescription().isNonSpatialStoch()) {
// ------- deal with seed
NonspatialStochSimOptions nssso = simTaskDesc.getStochOpt();
if (nssso.isUseCustomSeed()) {
// 488
String kisaoStr = SolverDescription.AlgorithmParameterDescription.Seed.getKisao();
AlgorithmParameter sedmlAlgorithmParameter = new AlgorithmParameter(kisaoStr, nssso.getCustomSeed() + "");
sedmlAlgorithm.addAlgorithmParameter(sedmlAlgorithmParameter);
}
} else {
// (... isRuleBased(), isSpatial(), isMovingMembrane(), isSpatialHybrid() ...
;
}
if (// -------- deal with hybrid solvers (non-spatial)
vcSolverDesc == SolverDescription.HybridEuler || vcSolverDesc == SolverDescription.HybridMilAdaptive || vcSolverDesc == SolverDescription.HybridMilstein) {
NonspatialStochHybridOptions nssho = simTaskDesc.getStochHybridOpt();
String kisaoStr = SolverDescription.AlgorithmParameterDescription.Epsilon.getKisao();
AlgorithmParameter sedmlAlgorithmParameter = new AlgorithmParameter(kisaoStr, nssho.getEpsilon() + "");
sedmlAlgorithm.addAlgorithmParameter(sedmlAlgorithmParameter);
kisaoStr = SolverDescription.AlgorithmParameterDescription.Lambda.getKisao();
sedmlAlgorithmParameter = new AlgorithmParameter(kisaoStr, nssho.getLambda() + "");
sedmlAlgorithm.addAlgorithmParameter(sedmlAlgorithmParameter);
kisaoStr = SolverDescription.AlgorithmParameterDescription.MSRTolerance.getKisao();
sedmlAlgorithmParameter = new AlgorithmParameter(kisaoStr, nssho.getMSRTolerance() + "");
sedmlAlgorithm.addAlgorithmParameter(sedmlAlgorithmParameter);
}
if (vcSolverDesc == SolverDescription.HybridMilAdaptive) {
// --------- one more param for hybrid-adaptive
NonspatialStochHybridOptions nssho = simTaskDesc.getStochHybridOpt();
String kisaoStr = SolverDescription.AlgorithmParameterDescription.SDETolerance.getKisao();
AlgorithmParameter sedmlAlgorithmParameter = new AlgorithmParameter(kisaoStr, nssho.getSDETolerance() + "");
sedmlAlgorithm.addAlgorithmParameter(sedmlAlgorithmParameter);
}
// TODO: consider adding notes for the algorithm parameters, to provide human-readable description of kisao terms
// sedmlAlgorithm.addNote(createNotesElement(algorithmNotesStr));
// TODO: even better, AlgorithmParameter in sed-ml should also have a human readable "name" field
// add a note to utcSim to indicate actual solver name
String simNotesStr = "Actual Solver Name : '" + vcSolverDesc.getDisplayLabel() + "'.";
utcSim.addNote(createNotesElement(simNotesStr));
sedmlModel.addSimulation(utcSim);
// 3 ------->
// create Tasks
MathOverrides mathOverrides = vcSimulation.getMathOverrides();
if ((sbmlExportFailed == false) && mathOverrides != null && mathOverrides.hasOverrides()) {
String[] overridenConstantNames = mathOverrides.getOverridenConstantNames();
String[] scannedConstantsNames = mathOverrides.getScannedConstantNames();
HashMap<String, String> scannedParamHash = new HashMap<String, String>();
HashMap<String, String> unscannedParamHash = new HashMap<String, String>();
for (String name : scannedConstantsNames) {
scannedParamHash.put(name, name);
}
for (String name : overridenConstantNames) {
if (!scannedParamHash.containsKey(name)) {
unscannedParamHash.put(name, name);
}
}
if (!unscannedParamHash.isEmpty() && scannedParamHash.isEmpty()) {
// only parameters with simple overrides (numeric/expression) no scans
// create new model with change for each parameter that has override; add simple task
String overriddenSimContextId = simContextId + "_" + overrideCount;
String overriddenSimContextName = simContextName + " modified";
Model sedModel = new Model(overriddenSimContextId, overriddenSimContextName, sbmlLanguageURN, simContextId);
overrideCount++;
for (String unscannedParamName : unscannedParamHash.values()) {
SymbolTableEntry ste = getSymbolTableEntryForModelEntity(mathSymbolMapping, unscannedParamName);
Expression unscannedParamExpr = mathOverrides.getActualExpression(unscannedParamName, 0);
if (unscannedParamExpr.isNumeric()) {
// if expression is numeric, add ChangeAttribute to model created above
XPathTarget targetXpath = getTargetAttributeXPath(ste, l2gMap);
ChangeAttribute changeAttribute = new ChangeAttribute(targetXpath, unscannedParamExpr.infix());
sedModel.addChange(changeAttribute);
} else {
// non-numeric expression : add 'computeChange' to modified model
ASTNode math = Libsedml.parseFormulaString(unscannedParamExpr.infix());
XPathTarget targetXpath = getTargetXPath(ste, l2gMap);
ComputeChange computeChange = new ComputeChange(targetXpath, math);
String[] exprSymbols = unscannedParamExpr.getSymbols();
// }
for (String symbol : exprSymbols) {
String symbolName = TokenMangler.mangleToSName(symbol);
SymbolTableEntry ste1 = vcModel.getEntry(symbol);
if (ste != null) {
if (ste1 instanceof SpeciesContext || ste1 instanceof Structure || ste1 instanceof ModelParameter) {
XPathTarget ste1_XPath = getTargetXPath(ste1, l2gMap);
org.jlibsedml.Variable sedmlVar = new org.jlibsedml.Variable(symbolName, symbolName, taskRef, ste1_XPath.getTargetAsString());
computeChange.addVariable(sedmlVar);
} else {
double doubleValue = 0.0;
if (ste1 instanceof ReservedSymbol) {
doubleValue = getReservedSymbolValue(ste1);
}
Parameter sedmlParameter = new Parameter(symbolName, symbolName, doubleValue);
computeChange.addParameter(sedmlParameter);
}
} else {
throw new RuntimeException("Symbol '" + symbol + "' used in expression for '" + unscannedParamName + "' not found in model.");
}
}
sedModel.addChange(computeChange);
}
}
sedmlModel.addModel(sedModel);
String taskId = "tsk_" + simContextCnt + "_" + simCount;
Task sedmlTask = new Task(taskId, vcSimulation.getName(), sedModel.getId(), utcSim.getId());
sedmlModel.addTask(sedmlTask);
// to be used later to add dataGenerators : one set of DGs per model (simContext).
taskRef = taskId;
} else if (!scannedParamHash.isEmpty() && unscannedParamHash.isEmpty()) {
// only parameters with scans : only add 1 Task and 1 RepeatedTask
String taskId = "tsk_" + simContextCnt + "_" + simCount;
Task sedmlTask = new Task(taskId, vcSimulation.getName(), simContextId, utcSim.getId());
sedmlModel.addTask(sedmlTask);
String repeatedTaskId = "repTsk_" + simContextCnt + "_" + simCount;
// TODO: temporary solution - we use as range here the first range
String scn = scannedConstantsNames[0];
String rId = "range_" + simContextCnt + "_" + simCount + "_" + scn;
RepeatedTask rt = new RepeatedTask(repeatedTaskId, repeatedTaskId, true, rId);
// to be used later to add dataGenerators - in our case it has to be the repeated task
taskRef = repeatedTaskId;
SubTask subTask = new SubTask("0", taskId);
rt.addSubtask(subTask);
for (String scannedConstName : scannedConstantsNames) {
ConstantArraySpec constantArraySpec = mathOverrides.getConstantArraySpec(scannedConstName);
String rangeId = "range_" + simContextCnt + "_" + simCount + "_" + scannedConstName;
// list of Ranges, if sim is parameter scan.
if (constantArraySpec != null) {
Range r = null;
// System.out.println(" " + constantArraySpec.toString());
if (constantArraySpec.getType() == ConstantArraySpec.TYPE_INTERVAL) {
// ------ Uniform Range
r = new UniformRange(rangeId, constantArraySpec.getMinValue(), constantArraySpec.getMaxValue(), constantArraySpec.getNumValues());
rt.addRange(r);
} else {
// ----- Vector Range
cbit.vcell.math.Constant[] cs = constantArraySpec.getConstants();
ArrayList<Double> values = new ArrayList<Double>();
for (int i = 0; i < cs.length; i++) {
String value = cs[i].getExpression().infix();
values.add(Double.parseDouble(value));
}
r = new VectorRange(rangeId, values);
rt.addRange(r);
}
// list of Changes
SymbolTableEntry ste = getSymbolTableEntryForModelEntity(mathSymbolMapping, scannedConstName);
XPathTarget target = getTargetXPath(ste, l2gMap);
// ASTNode math1 = new ASTCi(r.getId()); // was scannedConstName
ASTNode math1 = Libsedml.parseFormulaString(r.getId());
SetValue setValue = new SetValue(target, r.getId(), simContextId);
setValue.setMath(math1);
rt.addChange(setValue);
} else {
throw new RuntimeException("No scan ranges found for scanned parameter : '" + scannedConstName + "'.");
}
}
sedmlModel.addTask(rt);
} else {
// both scanned and simple parameters : create new model with change for each simple override; add RepeatedTask
// create new model with change for each unscanned parameter that has override
String overriddenSimContextId = simContextId + "_" + overrideCount;
String overriddenSimContextName = simContextName + " modified";
Model sedModel = new Model(overriddenSimContextId, overriddenSimContextName, sbmlLanguageURN, simContextId);
overrideCount++;
String taskId = "tsk_" + simContextCnt + "_" + simCount;
Task sedmlTask = new Task(taskId, vcSimulation.getName(), overriddenSimContextId, utcSim.getId());
sedmlModel.addTask(sedmlTask);
// scanned parameters
String repeatedTaskId = "repTsk_" + simContextCnt + "_" + simCount;
// TODO: temporary solution - we use as range here the first range
String scn = scannedConstantsNames[0];
String rId = "range_" + simContextCnt + "_" + simCount + "_" + scn;
RepeatedTask rt = new RepeatedTask(repeatedTaskId, repeatedTaskId, true, rId);
// to be used later to add dataGenerators - in our case it has to be the repeated task
taskRef = repeatedTaskId;
SubTask subTask = new SubTask("0", taskId);
rt.addSubtask(subTask);
for (String scannedConstName : scannedConstantsNames) {
ConstantArraySpec constantArraySpec = mathOverrides.getConstantArraySpec(scannedConstName);
String rangeId = "range_" + simContextCnt + "_" + simCount + "_" + scannedConstName;
// list of Ranges, if sim is parameter scan.
if (constantArraySpec != null) {
Range r = null;
// System.out.println(" " + constantArraySpec.toString());
if (constantArraySpec.getType() == ConstantArraySpec.TYPE_INTERVAL) {
// ------ Uniform Range
r = new UniformRange(rangeId, constantArraySpec.getMinValue(), constantArraySpec.getMaxValue(), constantArraySpec.getNumValues());
rt.addRange(r);
} else {
// ----- Vector Range
cbit.vcell.math.Constant[] cs = constantArraySpec.getConstants();
ArrayList<Double> values = new ArrayList<Double>();
for (int i = 0; i < cs.length; i++) {
String value = cs[i].getExpression().infix() + ", ";
values.add(Double.parseDouble(value));
}
r = new VectorRange(rangeId, values);
rt.addRange(r);
}
// use scannedParamHash to store rangeId for that param, since it might be needed if unscanned param has a scanned param in expr.
if (scannedParamHash.get(scannedConstName).equals(scannedConstName)) {
// the hash was originally populated as <scannedParamName, scannedParamName>. Replace 'value' with rangeId for scannedParam
scannedParamHash.put(scannedConstName, r.getId());
}
// create setValue for scannedConstName
SymbolTableEntry ste2 = getSymbolTableEntryForModelEntity(mathSymbolMapping, scannedConstName);
XPathTarget target1 = getTargetXPath(ste2, l2gMap);
ASTNode math1 = new ASTCi(scannedConstName);
SetValue setValue1 = new SetValue(target1, r.getId(), sedModel.getId());
setValue1.setMath(math1);
rt.addChange(setValue1);
} else {
throw new RuntimeException("No scan ranges found for scanned parameter : '" + scannedConstName + "'.");
}
}
// for unscanned parameter overrides
for (String unscannedParamName : unscannedParamHash.values()) {
SymbolTableEntry ste = getSymbolTableEntryForModelEntity(mathSymbolMapping, unscannedParamName);
Expression unscannedParamExpr = mathOverrides.getActualExpression(unscannedParamName, 0);
if (unscannedParamExpr.isNumeric()) {
// if expression is numeric, add ChangeAttribute to model created above
XPathTarget targetXpath = getTargetAttributeXPath(ste, l2gMap);
ChangeAttribute changeAttribute = new ChangeAttribute(targetXpath, unscannedParamExpr.infix());
sedModel.addChange(changeAttribute);
} else {
// check for any scanned parameter in unscanned parameter expression
ASTNode math = Libsedml.parseFormulaString(unscannedParamExpr.infix());
String[] exprSymbols = unscannedParamExpr.getSymbols();
boolean bHasScannedParameter = false;
String scannedParamNameInUnscannedParamExp = null;
for (String symbol : exprSymbols) {
if (scannedParamHash.get(symbol) != null) {
bHasScannedParameter = true;
scannedParamNameInUnscannedParamExp = new String(symbol);
// @TODO check for multiple scannedParameters in expression.
break;
}
}
// (scanned parameter in expr) ? (add setValue for unscanned param in repeatedTask) : (add computeChange to modifiedModel)
if (bHasScannedParameter && scannedParamNameInUnscannedParamExp != null) {
// create setValue for unscannedParamName (which contains a scanned param in its expression)
SymbolTableEntry entry = getSymbolTableEntryForModelEntity(mathSymbolMapping, unscannedParamName);
XPathTarget target = getTargetXPath(entry, l2gMap);
String rangeId = scannedParamHash.get(scannedParamNameInUnscannedParamExp);
// @TODO: we have no range??
SetValue setValue = new SetValue(target, rangeId, sedModel.getId());
setValue.setMath(math);
rt.addChange(setValue);
} else {
// non-numeric expression : add 'computeChange' to modified model
XPathTarget targetXpath = getTargetXPath(ste, l2gMap);
ComputeChange computeChange = new ComputeChange(targetXpath, math);
for (String symbol : exprSymbols) {
String symbolName = TokenMangler.mangleToSName(symbol);
SymbolTableEntry ste1 = vcModel.getEntry(symbol);
// ste1 could be a math parameter, hence the above could return null
if (ste1 == null) {
ste1 = simContext.getMathDescription().getEntry(symbol);
}
if (ste1 != null) {
if (ste1 instanceof SpeciesContext || ste1 instanceof Structure || ste1 instanceof ModelParameter) {
XPathTarget ste1_XPath = getTargetXPath(ste1, l2gMap);
org.jlibsedml.Variable sedmlVar = new org.jlibsedml.Variable(symbolName, symbolName, taskRef, ste1_XPath.getTargetAsString());
computeChange.addVariable(sedmlVar);
} else {
double doubleValue = 0.0;
if (ste1 instanceof ReservedSymbol) {
doubleValue = getReservedSymbolValue(ste1);
} else if (ste instanceof Function) {
try {
doubleValue = ste.getExpression().evaluateConstant();
} catch (Exception e) {
e.printStackTrace(System.out);
throw new RuntimeException("Unable to evaluate function '" + ste.getName() + "' used in '" + unscannedParamName + "' expression : ", e);
}
} else {
doubleValue = ste.getConstantValue();
}
// TODO: shouldn't be s1_init_uM which is a math symbol, should be s0 (so use the ste-something from above)
// TODO: revert to Variable, not Parameter
Parameter sedmlParameter = new Parameter(symbolName, symbolName, doubleValue);
computeChange.addParameter(sedmlParameter);
}
} else {
throw new RuntimeException("Symbol '" + symbol + "' used in expression for '" + unscannedParamName + "' not found in model.");
}
}
sedModel.addChange(computeChange);
}
}
}
sedmlModel.addModel(sedModel);
sedmlModel.addTask(rt);
}
} else {
// no math overrides, add basic task.
String taskId = "tsk_" + simContextCnt + "_" + simCount;
// temporary workaround
// TODO better fix
simContextId = sbmlExportFailed ? bioModelID : simContextId;
Task sedmlTask = new Task(taskId, vcSimulation.getName(), simContextId, utcSim.getId());
sedmlModel.addTask(sedmlTask);
// to be used later to add dataGenerators : one set of DGs per model (simContext).
taskRef = taskId;
}
// 4 ------->
// Create DataGenerators
List<DataGenerator> dataGeneratorsOfSim = new ArrayList<DataGenerator>();
// add one DataGenerator for 'time'
String timeDataGenPrefix = DATAGENERATOR_TIME_NAME + "_" + taskRef;
DataGenerator timeDataGen = sedmlModel.getDataGeneratorWithId(timeDataGenPrefix);
org.jlibsedml.Variable timeVar = new org.jlibsedml.Variable(DATAGENERATOR_TIME_SYMBOL + "_" + taskRef, DATAGENERATOR_TIME_SYMBOL, taskRef, VariableSymbol.TIME);
ASTNode math = Libsedml.parseFormulaString(DATAGENERATOR_TIME_SYMBOL + "_" + taskRef);
timeDataGen = new DataGenerator(timeDataGenPrefix, timeDataGenPrefix, math);
timeDataGen.addVariable(timeVar);
sedmlModel.addDataGenerator(timeDataGen);
dataGeneratorsOfSim.add(timeDataGen);
// add dataGenerators for species
// get species list from SBML model.
// Map<String, String> name2IdMap = new LinkedHashMap<> ();
String dataGenIdPrefix = "dataGen_" + taskRef;
if (sbmlExportFailed) {
// we try vcml export
for (SpeciesContext sc : vcModel.getSpeciesContexts()) {
String varName = sc.getName();
String varId = varName + "_" + taskRef;
// name2IdMap.put(varName, varId);
ASTNode varMath = Libsedml.parseFormulaString(varId);
String dataGenId = dataGenIdPrefix + "_" + TokenMangler.mangleToSName(varName);
DataGenerator dataGen = new DataGenerator(dataGenId, dataGenId, varMath);
org.jlibsedml.Variable variable = new org.jlibsedml.Variable(varId, varName, taskRef, XmlHelper.getXPathForSpecies(varName));
dataGen.addVariable(variable);
sedmlModel.addDataGenerator(dataGen);
dataGeneratorsOfSim.add(dataGen);
}
} else {
String[] varNamesList = SimSpec.fromSBML(sbmlString).getVarsList();
for (String varName : varNamesList) {
String varId = varName + "_" + taskRef;
// name2IdMap.put(varName, varId);
org.jlibsedml.Variable sedmlVar = new org.jlibsedml.Variable(varId, varName, taskRef, sbmlSupport.getXPathForSpecies(varName));
ASTNode varMath = Libsedml.parseFormulaString(varId);
// "dataGen_" + varCount; - old code
String dataGenId = dataGenIdPrefix + "_" + TokenMangler.mangleToSName(varName);
DataGenerator dataGen = new DataGenerator(dataGenId, dataGenId, varMath);
dataGen.addVariable(sedmlVar);
sedmlModel.addDataGenerator(dataGen);
dataGeneratorsOfSim.add(dataGen);
}
}
// add DataGenerators for output functions here
ArrayList<AnnotatedFunction> outputFunctions = simContext.getOutputFunctionContext().getOutputFunctionsList();
for (AnnotatedFunction annotatedFunction : outputFunctions) {
// Expression originalFunctionExpression = annotatedFunction.getExpression();
// Expression modifiedFunctionExpr = new Expression(annotatedFunction.getExpression());
// System.out.println("Before: " + originalFunctionExpression);
// String[] symbols = modifiedFunctionExpr.getSymbols();
// for(String symbol : symbols) {
// String id = name2IdMap.get(symbol);
// if(id == null) {
// System.err.println("Could not find id for " + symbol);
// } else {
// modifiedFunctionExpr.substituteInPlace(new Expression(symbol), new Expression(id));
// }
// }
// System.out.println("After: " + modifiedFunctionExpr);
// ASTNode funcMath = Libsedml.parseFormulaString(modifiedFunctionExpr.infix());
// "dataGen_" + varCount; - old code
String dataGenId = dataGenIdPrefix + "_" + TokenMangler.mangleToSName(annotatedFunction.getName());
String varId = TokenMangler.mangleToSName(annotatedFunction.getName()) + taskRef;
if (sbmlExportFailed) {
// VCML
Expression exp = new Expression(varId);
ASTNode funcMath = Libsedml.parseFormulaString(exp.infix());
DataGenerator dataGen = new DataGenerator(dataGenId, dataGenId, funcMath);
org.jlibsedml.Variable sedmlVar = new org.jlibsedml.Variable(varId, annotatedFunction.getName(), taskRef, XmlHelper.getXPathForOutputFunction(simContextName, annotatedFunction.getName()));
dataGen.addVariable(sedmlVar);
sedmlModel.addDataGenerator(dataGen);
dataGeneratorsOfSim.add(dataGen);
} else {
// SBML
}
// String[] functionSymbols = originalFunctionExpression.getSymbols();
// for (String symbol : functionSymbols) {
// String symbolName = TokenMangler.mangleToSName(symbol);
// // try to get symbol from model, if null, try simContext.mathDesc
// SymbolTableEntry ste = vcModel.getEntry(symbol);
// if (ste == null) {
// ste = simContext.getMathDescription().getEntry(symbol);
// }
// if (ste instanceof SpeciesContext || ste instanceof Structure || ste instanceof ModelParameter) {
// XPathTarget targetXPath = getTargetXPath(ste, l2gMap);
// if(sbmlExportFailed) { // VCML
// if(ste instanceof SpeciesContext) {
// // String varId = symbolName + "_" + taskRef;
// // org.jlibsedml.Variable sedmlVar = new org.jlibsedml.Variable(varId, symbolName, taskRef, XmlHelper.getXPathForSpecies(symbolName));
// // dataGen.addVariable(sedmlVar);
// } else {
// System.err.println("Not a species");
// }
// } else { // SBML
// // String varId = symbolName + "_" + taskRef;
// // org.jlibsedml.Variable sedmlVar = new org.jlibsedml.Variable(varId, symbolName, taskRef, targetXPath.getTargetAsString());
// // dataGen.addVariable(sedmlVar);
// }
// } else {
// double value = 0.0;
// if (ste instanceof Function) {
// try {
// value = ste.getExpression().evaluateConstant();
// } catch (Exception e) {
// e.printStackTrace(System.out);
// throw new RuntimeException("Unable to evaluate function '" + ste.getName() + "' for output function '" + annotatedFunction.getName() + "'.", e);
// }
// } else {
// value = ste.getConstantValue();
// }
// Parameter sedmlParameter = new Parameter(symbolName, symbolName, value);
// dataGen.addParameter(sedmlParameter);
// }
// }
}
// ignoring output for spatial deterministic (spatial stochastic is not exported to SEDML) and non-spatial stochastic applications with histogram
if (!(simContext.getGeometry().getDimension() > 0)) {
String plot2dId = "plot2d_" + TokenMangler.mangleToSName(vcSimulation.getName());
String reportId = "report_" + TokenMangler.mangleToSName(vcSimulation.getName());
// String reportId = "__plot__" + plot2dId;
String plotName = simContextName + "_" + simName + "_plot";
Plot2D sedmlPlot2d = new Plot2D(plot2dId, plotName);
Report sedmlReport = new Report(reportId, plotName);
sedmlPlot2d.addNote(createNotesElement("Plot of all variables and output functions from application '" + simContext.getName() + "' ; simulation '" + vcSimulation.getName() + "' in VCell model"));
sedmlReport.addNote(createNotesElement("Report of all variables and output functions from application '" + simContext.getName() + "' ; simulation '" + vcSimulation.getName() + "' in VCell model"));
DataGenerator dgtime = sedmlModel.getDataGeneratorWithId(DATAGENERATOR_TIME_NAME + "_" + taskRef);
String xDataRef = dgtime.getId();
String xDatasetXId = "__data_set__" + plot2dId + dgtime.getId();
// id, name, label, data generator reference
DataSet dataSet = new DataSet(xDatasetXId, DATAGENERATOR_TIME_NAME, xDataRef, xDataRef);
sedmlReport.addDataSet(dataSet);
// add a curve for each dataGenerator in SEDML model
int curveCnt = 0;
// String id, String name, ASTNode math
for (DataGenerator dg : dataGeneratorsOfSim) {
// no curve for time, since time is xDateReference
if (dg.getId().equals(xDataRef)) {
continue;
}
String curveId = "curve_" + plot2dId + "_" + dg.getName();
String datasetYId = "__data_set__" + plot2dId + dg.getName();
Curve curve = new Curve(curveId, dg.getName(), false, false, xDataRef, dg.getId());
sedmlPlot2d.addCurve(curve);
// // id, name, label, dataRef
// // dataset id <- unique id
// // dataset name <- data generator name
// // dataset label <- dataset id
DataSet yDataSet = new DataSet(datasetYId, dg.getName(), dg.getId(), dg.getId());
sedmlReport.addDataSet(yDataSet);
curveCnt++;
}
sedmlModel.addOutput(sedmlPlot2d);
sedmlModel.addOutput(sedmlReport);
} else {
// spatial deterministic
if (simContext.getApplicationType().equals(Application.NETWORK_DETERMINISTIC)) {
// we ignore spatial stochastic (Smoldyn)
if (bForceVCML) {
String reportId = "_report_" + TokenMangler.mangleToSName(vcSimulation.getName());
Report sedmlReport = new Report(reportId, simContext.getName() + "plots");
String xDataRef = sedmlModel.getDataGeneratorWithId(DATAGENERATOR_TIME_NAME + "_" + taskRef).getId();
String xDatasetXId = "datasetX_" + DATAGENERATOR_TIME_NAME + "_" + timeDataGen.getId();
DataSet dataSetTime = new DataSet(xDatasetXId, xDataRef, xDatasetXId, xDataRef);
sedmlReport.addDataSet(dataSetTime);
int surfaceCnt = 0;
for (DataGenerator dg : dataGeneratorsOfSim) {
if (dg.getId().equals(xDataRef)) {
continue;
}
// String datasetYId = "datasetY_" + surfaceCnt;
String datasetYId = "__data_set__" + surfaceCnt + "_" + dg.getName();
DataSet yDataSet = new DataSet(datasetYId, dg.getName(), datasetYId, dg.getId());
sedmlReport.addDataSet(yDataSet);
surfaceCnt++;
}
sedmlModel.addOutput(sedmlReport);
} else {
// spatial deterministic SBML
// TODO: add surfaces to the plots
String plot3dId = "plot3d_" + TokenMangler.mangleToSName(vcSimulation.getName());
String reportId = "report_" + TokenMangler.mangleToSName(vcSimulation.getName());
String plotName = simContext.getName() + "plots";
Plot3D sedmlPlot3d = new Plot3D(plot3dId, plotName);
Report sedmlReport = new Report(reportId, plotName);
sedmlPlot3d.addNote(createNotesElement("Plot of all variables and output functions from application '" + simContext.getName() + "' ; simulation '" + vcSimulation.getName() + "' in VCell model"));
sedmlReport.addNote(createNotesElement("Report of all variables and output functions from application '" + simContext.getName() + "' ; simulation '" + vcSimulation.getName() + "' in VCell model"));
DataGenerator dgtime = sedmlModel.getDataGeneratorWithId(DATAGENERATOR_TIME_NAME + "_" + taskRef);
String xDataRef = dgtime.getId();
String xDatasetXId = "__data_set__" + plot3dId + dgtime.getId();
// id, name, label, data generator reference
DataSet dataSet = new DataSet(xDatasetXId, DATAGENERATOR_TIME_NAME, xDataRef, xDataRef);
sedmlReport.addDataSet(dataSet);
// add a curve for each dataGenerator in SEDML model
int curveCnt = 0;
// String id, String name, ASTNode math
for (DataGenerator dg : dataGeneratorsOfSim) {
// no curve for time, since time is xDateReference
if (dg.getId().equals(xDataRef)) {
continue;
}
String curveId = "curve_" + plot3dId + "_" + dg.getName();
String datasetYId = "__data_set__" + plot3dId + dg.getName();
DataSet yDataSet = new DataSet(datasetYId, dg.getName(), dg.getId(), dg.getId());
sedmlReport.addDataSet(yDataSet);
curveCnt++;
}
sedmlModel.addOutput(sedmlReport);
}
}
}
simCount++;
}
// end - for 'sims'
simContextCnt++;
}
// if sedmlNotesStr is not null, there were some applications that could not be exported to SEDML (eg., spatial stochastic). Create a notes element and add it to sedml Model.
if (sedmlNotesStr.length() > 0) {
sedmlNotesStr = "\n\tThe following applications in the VCell model were not exported to VCell : " + sedmlNotesStr;
sedmlModel.addNote(createNotesElement(sedmlNotesStr));
}
if (sedmlModel.getModels() != null && sedmlModel.getModels().size() > 1) {
System.out.println("Number of models in the sedml is " + sedmlModel.getModels().size());
}
} catch (Exception e) {
e.printStackTrace(System.out);
throw new RuntimeException("Error adding model to SEDML document : " + e.getMessage());
}
}
use of org.jlibsedml.SubTask in project vcell by virtualcell.
the class XmlHelper method sedmlToBioModel.
public static List<VCDocument> sedmlToBioModel(VCLogger transLogger, ExternalDocInfo externalDocInfo, SedML sedml, List<AbstractTask> tasks, String sedmlFileLocation, boolean exactMatchOnly) throws Exception {
if (sedml.getModels().isEmpty()) {
throw new Exception("No models found in SED-ML document");
}
try {
// iterate through all the elements and show them at the console
List<org.jlibsedml.Model> mmm = sedml.getModels();
for (Model mm : mmm) {
System.out.println(mm.toString());
}
List<org.jlibsedml.Simulation> sss = sedml.getSimulations();
for (org.jlibsedml.Simulation ss : sss) {
System.out.println(ss.toString());
}
List<AbstractTask> ttt = sedml.getTasks();
if (ttt.isEmpty()) {
throw new Exception("No tasks found in SED-ML document");
}
for (AbstractTask tt : ttt) {
System.out.println(tt.toString());
}
List<DataGenerator> ddd = sedml.getDataGenerators();
for (DataGenerator dd : ddd) {
System.out.println(dd.toString());
}
List<Output> ooo = sedml.getOutputs();
for (Output oo : ooo) {
System.out.println(oo.toString());
}
if (ooo.isEmpty()) {
System.err.println("List of outputs cannot be empty!");
}
if (tasks == null || tasks.isEmpty()) {
// no task selection, we'll import all that we find in the SED-ML
tasks = sedml.getTasks();
}
// We need to make a separate BioModel for each SED-ML model
// We will parse all tasks and create Simulations for each in the BioModel(s) corresponding to the model referenced by the tasks
List<VCDocument> docs = new ArrayList<VCDocument>();
// extract bioModel name from sedx (or sedml) file
String bioModelBaseName = FileUtils.getBaseName(externalDocInfo.getFile().getAbsolutePath());
String kisaoID = null;
// this will become the vCell simulation
org.jlibsedml.Simulation sedmlSimulation = null;
// the "original" model referred to by the task
org.jlibsedml.Model sedmlOriginalModel = null;
// this will be used in the BioModel name
String sedmlOriginalModelName = null;
// can be sbml or vcml
String sedmlOriginalModelLanguage = null;
ArchiveComponents ac = null;
if (externalDocInfo.getFile().getPath().toLowerCase().endsWith("sedx") || externalDocInfo.getFile().getPath().toLowerCase().endsWith("omex")) {
ac = Libsedml.readSEDMLArchive(new FileInputStream(externalDocInfo.getFile().getPath()));
}
ModelResolver resolver = new ModelResolver(sedml);
if (ac != null) {
resolver.add(new ArchiveModelResolver(ac));
}
resolver.add(new FileModelResolver());
if (sedmlFileLocation != null) {
File sedmlFile = new File(sedmlFileLocation);
String sedmlRelativePrefix = sedmlFile.getParent() + File.separator;
if (sedmlRelativePrefix != null) {
resolver.add(new RelativeFileModelResolver(sedmlRelativePrefix));
}
}
for (AbstractTask selectedTask : tasks) {
if (selectedTask instanceof Task) {
sedmlOriginalModel = sedml.getModelWithId(selectedTask.getModelReference());
sedmlSimulation = sedml.getSimulation(selectedTask.getSimulationReference());
} else if (selectedTask instanceof RepeatedTask) {
System.err.println("RepeatedTask not supported yet, task " + SEDMLUtil.getName(selectedTask) + " is being skipped");
continue;
// TODO the below is unfinished code
// RepeatedTask rt = (RepeatedTask)selectedTask;
// assert(rt.getSubTasks().size() == 1);
// SubTask st = rt.getSubTasks().entrySet().iterator().next().getValue(); // first (and only) subtask
// String taskId = st.getTaskId();
// AbstractTask t = sedml.getTaskWithId(taskId);
// sedmlOriginalModel = sedml.getModelWithId(t.getModelReference()); // get model and simulation from subtask
// sedmlSimulation = sedml.getSimulation(t.getSimulationReference());
} else {
throw new RuntimeException("Unexpected task " + selectedTask);
}
sedmlOriginalModelName = sedmlOriginalModel.getId();
sedmlOriginalModelLanguage = sedmlOriginalModel.getLanguage();
// at this point we assume that the sedml simulation, algorithm and kisaoID are all valid
Algorithm algorithm = sedmlSimulation.getAlgorithm();
kisaoID = algorithm.getKisaoID();
// identify the vCell solvers that would match best the sedml solver kisao id
// try to find a match in the ontology tree
SolverDescription solverDescription = SolverUtilities.matchSolverWithKisaoId(kisaoID, exactMatchOnly);
if (solverDescription != null) {
System.out.println("Task (id='" + selectedTask.getId() + "') is compatible, solver match found in ontology: '" + kisaoID + "' matched to " + solverDescription);
} else {
// give it a try anyway with our deterministic default solver
solverDescription = SolverDescription.CombinedSundials;
System.err.println("Task (id='" + selectedTask.getId() + ")' is not compatible, no equivalent solver found in ontology for requested algorithm '" + kisaoID + "'; trying with deterministic default solver " + solverDescription);
}
// find out everything else we need about the application we're going to use,
// some of the info will be needed when we parse the sbml file
boolean bSpatial = false;
Application appType = Application.NETWORK_DETERMINISTIC;
Set<SolverDescription.SolverFeature> sfList = solverDescription.getSupportedFeatures();
for (SolverDescription.SolverFeature sf : sfList) {
switch(sf) {
case Feature_Rulebased:
appType = Application.RULE_BASED_STOCHASTIC;
break;
case Feature_Stochastic:
appType = Application.NETWORK_STOCHASTIC;
break;
case Feature_Deterministic:
appType = Application.NETWORK_DETERMINISTIC;
break;
case Feature_Spatial:
bSpatial = true;
break;
default:
break;
}
}
// we make a biomodel for each task; if there are many simulations, probably
// only one will match the selected task id, the others are parasites and must not be run
BioModel bioModel = null;
boolean justMade = false;
String newMdl = resolver.getModelString(sedmlOriginalModel);
String bioModelName = bioModelBaseName + "_" + sedml.getFileName() + "_" + sedmlOriginalModelName;
// get it if we made it already
for (VCDocument existingDoc : docs) {
if (!docs.isEmpty()) {
if (existingDoc.getName().equals(bioModelName)) {
bioModel = (BioModel) existingDoc;
break;
}
}
}
// make it if we didn't and mark it as fresh
if (bioModel == null) {
if (sedmlOriginalModelLanguage.contentEquals(SUPPORTED_LANGUAGE.VCELL_GENERIC.getURN())) {
// vcml
XMLSource vcmlSource = new XMLSource(newMdl);
bioModel = (BioModel) XmlHelper.XMLToBioModel(vcmlSource);
bioModel.setName(bioModelName);
docs.add(bioModel);
justMade = true;
try {
bioModel.getVCMetaData().createBioPaxObjects(bioModel);
} catch (Exception e) {
e.printStackTrace();
}
} else {
// we assume it's sbml, if it's neither import will fail
// sbmlSource with all the changes applied
XMLSource sbmlSource = new XMLSource(newMdl);
bioModel = (BioModel) XmlHelper.importSBML(transLogger, sbmlSource, bSpatial);
bioModel.setName(bioModelName);
docs.add(bioModel);
justMade = true;
}
}
if (sedmlOriginalModelLanguage.contentEquals(SUPPORTED_LANGUAGE.VCELL_GENERIC.getURN())) {
// we basically ignore the sedml simulation altogether
for (Simulation sim : bioModel.getSimulations()) {
if (sim.getName().equals(selectedTask.getName())) {
System.out.println(" --- selected task - name: " + selectedTask.getName() + ", id: " + selectedTask.getId());
sim.setImportedTaskID(selectedTask.getId());
}
}
continue;
}
// even if we just created the biomodel from the sbml file we have at least one application with initial conditions and stuff
// see if there is a suitable application type for the sedml kisao
// if not, we add one by doing a "copy as" to the right type
SimulationContext[] existingSimulationContexts = bioModel.getSimulationContexts();
SimulationContext matchingSimulationContext = null;
for (SimulationContext simContext : existingSimulationContexts) {
if (simContext.getApplicationType().equals(appType) && ((simContext.getGeometry().getDimension() > 0) == bSpatial)) {
matchingSimulationContext = simContext;
break;
}
}
if (matchingSimulationContext == null) {
if (justMade) {
matchingSimulationContext = SimulationContext.copySimulationContext(existingSimulationContexts[0], sedmlOriginalModelName, bSpatial, appType);
bioModel.removeSimulationContext(existingSimulationContexts[0]);
} else {
matchingSimulationContext = SimulationContext.copySimulationContext(existingSimulationContexts[0], sedmlOriginalModelName + "_" + existingSimulationContexts.length, bSpatial, appType);
}
bioModel.addSimulationContext(matchingSimulationContext);
}
// making the new vCell simulation based on the sedml simulation
matchingSimulationContext.refreshDependencies();
MathMappingCallback callback = new MathMappingCallbackTaskAdapter(null);
matchingSimulationContext.refreshMathDescription(callback, NetworkGenerationRequirements.ComputeFullStandardTimeout);
Simulation newSimulation = new Simulation(matchingSimulationContext.getMathDescription());
newSimulation.setSimulationOwner(matchingSimulationContext);
if (selectedTask instanceof Task) {
String newSimName = selectedTask.getId();
if (SEDMLUtil.getName(selectedTask) != null) {
newSimName += "_" + SEDMLUtil.getName(selectedTask);
}
newSimulation.setName(newSimName);
newSimulation.setImportedTaskID(selectedTask.getId());
} else {
newSimulation.setName(SEDMLUtil.getName(sedmlSimulation) + "_" + SEDMLUtil.getName(selectedTask));
}
// we identify the type of sedml simulation (uniform time course, etc)
// and set the vCell simulation parameters accordingly
SolverTaskDescription simTaskDesc = newSimulation.getSolverTaskDescription();
if (solverDescription != null) {
simTaskDesc.setSolverDescription(solverDescription);
}
TimeBounds timeBounds = new TimeBounds();
TimeStep timeStep = new TimeStep();
double outputTimeStep = 0.1;
int outputNumberOfPoints = 1;
if (sedmlSimulation instanceof UniformTimeCourse) {
// we translate initial time to zero, we provide output for the duration of the simulation
// because we can't select just an interval the way the SEDML simulation can
double initialTime = ((UniformTimeCourse) sedmlSimulation).getInitialTime();
double outputStartTime = ((UniformTimeCourse) sedmlSimulation).getOutputStartTime();
double outputEndTime = ((UniformTimeCourse) sedmlSimulation).getOutputEndTime();
outputNumberOfPoints = ((UniformTimeCourse) sedmlSimulation).getNumberOfPoints();
outputTimeStep = (outputEndTime - outputStartTime) / outputNumberOfPoints;
timeBounds = new TimeBounds(0, outputEndTime - initialTime);
ErrorTolerance errorTolerance = new ErrorTolerance();
// we look for explicit algorithm parameters
List<AlgorithmParameter> sedmlAlgorithmParameters = algorithm.getListOfAlgorithmParameters();
for (AlgorithmParameter sedmlAlgorithmParameter : sedmlAlgorithmParameters) {
String apKisaoID = sedmlAlgorithmParameter.getKisaoID();
String apValue = sedmlAlgorithmParameter.getValue();
if (apKisaoID == null || apKisaoID.isEmpty()) {
System.err.println("Undefined KisaoID algorithm parameter for algorithm '" + kisaoID + "'");
}
// TODO: use the proper ontology for the algorithm parameters kisao id
if (apKisaoID.contentEquals(ErrorTolerance.ErrorToleranceDescription.Absolute.getKisao())) {
double value = Double.parseDouble(apValue);
errorTolerance.setAbsoluteErrorTolerance(value);
} else if (apKisaoID.contentEquals(ErrorTolerance.ErrorToleranceDescription.Relative.getKisao())) {
double value = Double.parseDouble(apValue);
errorTolerance.setRelativeErrorTolerance(value);
} else if (apKisaoID.contentEquals(TimeStep.TimeStepDescription.Default.getKisao())) {
double value = Double.parseDouble(apValue);
timeStep.setDefaultTimeStep(value);
} else if (apKisaoID.contentEquals(TimeStep.TimeStepDescription.Maximum.getKisao())) {
double value = Double.parseDouble(apValue);
timeStep.setMaximumTimeStep(value);
} else if (apKisaoID.contentEquals(TimeStep.TimeStepDescription.Minimum.getKisao())) {
double value = Double.parseDouble(apValue);
timeStep.setMinimumTimeStep(value);
} else if (apKisaoID.contentEquals(AlgorithmParameterDescription.Seed.getKisao())) {
// custom seed
if (simTaskDesc.getSimulation().getMathDescription().isNonSpatialStoch()) {
NonspatialStochSimOptions nssso = simTaskDesc.getStochOpt();
int value = Integer.parseInt(apValue);
nssso.setCustomSeed(value);
} else {
System.err.println("Algorithm parameter '" + AlgorithmParameterDescription.Seed.getDescription() + "' is only supported for nonspatial stochastic simulations");
}
// some arguments used only for non-spatial hybrid solvers
} else if (apKisaoID.contentEquals(AlgorithmParameterDescription.Epsilon.getKisao())) {
NonspatialStochHybridOptions nssho = simTaskDesc.getStochHybridOpt();
nssho.setEpsilon(Double.parseDouble(apValue));
} else if (apKisaoID.contentEquals(AlgorithmParameterDescription.Lambda.getKisao())) {
NonspatialStochHybridOptions nssho = simTaskDesc.getStochHybridOpt();
nssho.setLambda(Double.parseDouble(apValue));
} else if (apKisaoID.contentEquals(AlgorithmParameterDescription.MSRTolerance.getKisao())) {
NonspatialStochHybridOptions nssho = simTaskDesc.getStochHybridOpt();
nssho.setMSRTolerance(Double.parseDouble(apValue));
} else if (apKisaoID.contentEquals(AlgorithmParameterDescription.SDETolerance.getKisao())) {
NonspatialStochHybridOptions nssho = simTaskDesc.getStochHybridOpt();
nssho.setSDETolerance(Double.parseDouble(apValue));
} else {
System.err.println("Algorithm parameter with kisao id '" + apKisaoID + "' not supported at this time, skipping.");
}
}
simTaskDesc.setErrorTolerance(errorTolerance);
} else if (sedmlSimulation instanceof OneStep) {
// for anything other than UniformTimeCourse we just ignore
System.err.println("OneStep Simulation not supported");
continue;
} else if (sedmlSimulation instanceof SteadyState) {
System.err.println("SteadyState Simulation not supported");
continue;
}
OutputTimeSpec outputTimeSpec = new UniformOutputTimeSpec(outputTimeStep);
simTaskDesc.setTimeBounds(timeBounds);
simTaskDesc.setTimeStep(timeStep);
if (simTaskDesc.getSolverDescription().supports(outputTimeSpec)) {
simTaskDesc.setOutputTimeSpec(outputTimeSpec);
} else {
simTaskDesc.setOutputTimeSpec(new DefaultOutputTimeSpec(1, Integer.max(DefaultOutputTimeSpec.DEFAULT_KEEP_AT_MOST, outputNumberOfPoints)));
}
newSimulation.setSolverTaskDescription(simTaskDesc);
newSimulation.setDescription(SEDMLUtil.getName(selectedTask));
bioModel.addSimulation(newSimulation);
newSimulation.refreshDependencies();
}
return docs;
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("Unable to initialize bioModel for the given selection\n" + e.getMessage());
}
}
Aggregations