use of cbit.vcell.parser.SimpleSymbolTable in project vcell by virtualcell.
the class FunctionFileGenerator method readFunctionsFile.
/**
* This method was created in VisualAge.
* @param logFile java.io.File
*/
public static synchronized Vector<AnnotatedFunction> readFunctionsFile(File functionsFile, String simJobID) throws java.io.FileNotFoundException, java.io.IOException {
// Check if file exists
if (!functionsFile.exists()) {
throw new java.io.FileNotFoundException("functions file " + functionsFile.getPath() + " not found");
}
//
// Read characters from functionFile into character array and transfer into string buffer.
//
Vector<AnnotatedFunction> annotatedFunctionsVector = new Vector<AnnotatedFunction>();
long fnFileLength = functionsFile.length();
StringBuffer stringBuffer = new StringBuffer();
FileInputStream is = null;
try {
is = new FileInputStream(functionsFile);
InputStreamReader reader = new InputStreamReader(is);
BufferedReader br = new BufferedReader(reader);
char[] charArray = new char[10000];
while (true) {
int numRead = br.read(charArray, 0, charArray.length);
if (numRead > 0) {
stringBuffer.append(charArray, 0, numRead);
} else if (numRead == -1) {
break;
}
}
} finally {
if (is != null) {
is.close();
}
}
if (stringBuffer.length() != fnFileLength) {
System.out.println("<<<SYSOUT ALERT>>>SimulationData.readFunctionFile(), read " + stringBuffer.length() + " of " + fnFileLength + " bytes of input file");
}
String newLineDelimiters = "\n\r";
StringTokenizer lineTokenizer = new StringTokenizer(stringBuffer.toString(), newLineDelimiters);
String token1 = new String("");
int j = 0;
//
// Each token is a line representing a function name and function expression,
// separated by a semicolon
//
HashSet<String> allSymbols = new HashSet<String>();
while (lineTokenizer.hasMoreTokens()) {
token1 = lineTokenizer.nextToken();
FunctionFileGenerator.FuncFileLineInfo funcFileLineInfo = readFunctionLine(token1);
if (funcFileLineInfo != null && funcFileLineInfo.functionName != null && funcFileLineInfo.functionExpr != null && funcFileLineInfo.funcVarType != null) {
Expression functionExpr = null;
try {
functionExpr = new Expression(funcFileLineInfo.functionExpr);
functionExpr = MathFunctionDefinitions.fixFunctionSyntax(functionExpr);
} catch (cbit.vcell.parser.ExpressionException e) {
throw new RuntimeException("Error in reading expression '" + funcFileLineInfo.functionExpr + "' for function \"" + funcFileLineInfo.functionName + "\"");
}
Domain domain = Variable.getDomainFromCombinedIdentifier(funcFileLineInfo.functionName);
String funcName = Variable.getNameFromCombinedIdentifier(funcFileLineInfo.functionName);
AnnotatedFunction annotatedFunc = new AnnotatedFunction(funcName, functionExpr, domain, funcFileLineInfo.errorString, funcFileLineInfo.funcVarType, funcFileLineInfo.funcIsUserDefined ? FunctionCategory.OLDUSERDEFINED : FunctionCategory.PREDEFINED);
allSymbols.add(annotatedFunc.getName());
String[] symbols = annotatedFunc.getExpression().getSymbols();
if (symbols != null) {
allSymbols.addAll(Arrays.asList(symbols));
}
annotatedFunctionsVector.addElement(annotatedFunc);
}
j++;
}
if (simJobID != null && simJobID.trim().length() > 0) {
SimpleSymbolTable simpleSymbolTable = new SimpleSymbolTable(allSymbols.toArray(new String[0]));
// bind
for (AnnotatedFunction func : annotatedFunctionsVector) {
if (func.isOldUserDefined()) {
try {
func.bind(simpleSymbolTable);
} catch (ExpressionBindingException e) {
e.printStackTrace();
}
}
}
// rename symbol table entries
for (int i = 0; i < annotatedFunctionsVector.size(); i++) {
AnnotatedFunction func = annotatedFunctionsVector.get(i);
if (func.isOldUserDefined()) {
SimpleSymbolTableEntry ste = (SimpleSymbolTableEntry) simpleSymbolTable.getEntry(func.getName());
ste.setName(simJobID + "_" + func.getName());
}
}
// rename in the expressions
for (int i = 0; i < annotatedFunctionsVector.size(); i++) {
AnnotatedFunction func = annotatedFunctionsVector.get(i);
if (func.isOldUserDefined()) {
try {
Expression exp = func.getExpression().renameBoundSymbols(simpleSymbolTable.getNameScope());
AnnotatedFunction newfunc = new AnnotatedFunction(simJobID + "_" + func.getName(), exp, func.getDomain(), func.getName(), func.getErrorString(), func.getFunctionType(), FunctionCategory.OLDUSERDEFINED);
annotatedFunctionsVector.set(i, newfunc);
} catch (ExpressionBindingException e) {
e.printStackTrace();
}
}
}
}
return annotatedFunctionsVector;
}
use of cbit.vcell.parser.SimpleSymbolTable in project vcell by virtualcell.
the class PropensitySolver method solvePropensity.
public static PropensityFunction solvePropensity(Expression original_expression, String[] speciesNames, int maxOrder) throws ExpressionException, MathException {
boolean[][] rootExists = new boolean[speciesNames.length][maxOrder];
ArrayList<Binomial> binomialList = new ArrayList<Binomial>();
int[] order = new int[speciesNames.length];
int totalOrder = 0;
// Actually, if order is 3, the roots can be either 0 (implies var^3) or 0,1,2 (implies var*(var-1)*(var-2))
for (int i = 0; i < speciesNames.length; i++) {
order[i] = -1;
Expression diff_i = new Expression(original_expression);
for (int j = 0; j < rootExists[0].length; j++) {
Expression exp_subX_j = original_expression.getSubstitutedExpression(new Expression(speciesNames[i]), new Expression(j));
if (ExpressionUtils.functionallyEquivalent(exp_subX_j, new Expression(0.0), false, 1e-8, 1e-8)) {
rootExists[i][j] = true;
} else {
rootExists[i][j] = false;
}
diff_i = diff_i.differentiate(speciesNames[i]).flatten();
if (!ExpressionUtils.functionallyEquivalent(diff_i, new Expression(0.0), false, 1e-8, 1e-8)) {
order[i] = j + 1;
if (order[i] > maxOrder) {
throw new MathException("order of " + speciesNames[i] + " in expression " + original_expression.infix() + " is larger than expected for a propensity function");
}
}
}
}
// check if the roots are valid for mass actions (roots should start with 0 and increase consecutively)
for (int i = 0; i < speciesNames.length; i++) {
int ord = order[i];
totalOrder = totalOrder + order[i];
int expectedRootCount = 0;
int totalRootCount = 0;
// expectedRootCount should be 1 or order
for (int j = 0; j < ord; j++) {
if (rootExists[i][j]) {
expectedRootCount++;
}
}
// total root count
for (int j = 0; j < rootExists[i].length; j++) {
if (rootExists[i][j]) {
totalRootCount++;
}
}
// either root is 0, or number of roots equals to order.
if (!((totalRootCount == 1 && expectedRootCount == totalRootCount && rootExists[i][0]) || (totalRootCount > 1 && expectedRootCount == totalRootCount))) {
throw new MathException("\n\nSpecies \'" + speciesNames[i] + "\' has wrong form in propensity function. Hybrid solvers require strict propensity functions which should only contain the reactants in the function. \n\nIntegers in '" + speciesNames[i] + "' binomials should start with 0 and increase consecutively." + "e.g. species1*(species1-1)*(species1-2)*species2*(speceis2-1)...");
}
}
// get all the constraints(for expponets vars)
ArrayList<String> constraintSymbols = new ArrayList<String>();
ArrayList<Expression> constraints = new ArrayList<Expression>();
ArrayList<ArrayList<String>> exponents = new ArrayList<ArrayList<String>>();
Expression canonical_expression = new Expression(1.0);
for (int i = 0; i < rootExists.length; i++) {
exponents.add(new ArrayList<String>());
for (int j = 0; j < rootExists[i].length; j++) {
if (rootExists[i][j]) {
String exponentVar = "n_" + speciesNames[i] + "_" + j;
constraintSymbols.add(exponentVar);
exponents.get(i).add(exponentVar);
canonical_expression = Expression.mult(canonical_expression, new Expression("(" + speciesNames[i] + " - " + j + ")^" + exponentVar));
Binomial binomial = new Binomial();
binomial.varName = speciesNames[i];
binomial.root = j;
binomial.powerVarName = exponentVar;
binomialList.add(binomial);
}
}
Expression expConstraint = new Expression(0.0);
for (int j = 0; j < exponents.get(i).size(); j++) {
expConstraint = Expression.add(expConstraint, new Expression(exponents.get(i).get(j)));
constraints.add(new Expression(exponents.get(i).get(j) + " >= 1"));
constraints.add(new Expression(exponents.get(i).get(j) + " <= " + order[i]));
}
constraints.add(new Expression(expConstraint.flatten().infix() + " == " + order[i]));
}
SimpleSymbolTable constraintSymbolTable = new SimpleSymbolTable(constraintSymbols.toArray(new String[constraintSymbols.size()]));
for (int i = 0; i < constraints.size(); i++) {
constraints.get(i).bindExpression(constraintSymbolTable);
}
// the array list to save different conbination values of orders of binomials. one element saves one conbination
ArrayList<int[]> orderList = new ArrayList<int[]>();
try {
PropensitySolver.RootOrderIterator iter = new PropensitySolver.RootOrderIterator(totalOrder, constraintSymbols.size());
while (iter.nextOrder() != null) {
orderList.add(iter.getCurrentOrders().clone());
}
} catch (Exception e) {
e.printStackTrace();
throw new MathException("Did not recognize propensity function from \"" + original_expression.infix() + " product of species shoulde have order less than or equal to 3 and the form like 'rateConstant*species1*(species1-1)*species2'.");
}
Expression expression_for_K = Expression.mult(original_expression.flatten(), Expression.invert(canonical_expression.flatten()));
Random rand = new Random(0);
for (int[] values : orderList) {
//
// for each valid combination of orders (via constraints), choose the one that always gives the same answer for K
//
Expression order_substituted_canonical_expression = new Expression(canonical_expression);
Expression order_substituted_expression_for_K = new Expression(expression_for_K);
for (int j = 0; j < values.length; j++) {
order_substituted_canonical_expression.substituteInPlace(new Expression(constraintSymbols.get(j)), new Expression(values[j]));
order_substituted_expression_for_K.substituteInPlace(new Expression(constraintSymbols.get(j)), new Expression(values[j]));
}
order_substituted_canonical_expression = order_substituted_canonical_expression.flatten();
order_substituted_expression_for_K = order_substituted_expression_for_K.flatten();
Hashtable<String, Integer> k_hash = new Hashtable<String, Integer>();
boolean bFailed = false;
// for the specific conbination of orders, replace species names with random numbers, therefore to get rate constant value.
for (int i = 0; !bFailed && i < 40; i++) {
Expression substituted_expression_for_K = new Expression(order_substituted_expression_for_K);
// substitute variables with random number and save the results in a hashtable.
for (int j = 0; j < speciesNames.length; j++) {
int randInt = rand.nextInt(20) - 10;
while (randInt < rootExists[j].length && randInt >= 0 && rootExists[j][randInt]) {
// make sure it is not a root of the system
randInt = rand.nextInt(20) - 10;
}
substituted_expression_for_K.substituteInPlace(new Expression(speciesNames[j]), new Expression(randInt));
substituted_expression_for_K = substituted_expression_for_K.flatten();
}
String k_key = substituted_expression_for_K.infix();
if (k_hash.containsKey(k_key)) {
int numOccur = k_hash.get(k_key);
k_hash.put(k_key, numOccur + 1);
} else {
k_hash.put(k_key, 1);
}
}
// to see if the results in the hashtable are the same all the time. if so, the conbination is correct.
Set<String> keySet = k_hash.keySet();
String[] keys = keySet.toArray(new String[k_hash.size()]);
Expression k_exp_0 = new Expression(keys[0]);
Expression k_most_popular = k_exp_0;
Integer mostOccurances = k_hash.get(keys[0]);
// why not check if there is only one key, the conbination is correct??
for (int i = 1; !bFailed && i < keys.length; i++) {
Expression k_exp_i = new Expression(keys[i]);
Integer occurances = k_hash.get(keys[i]);
if (occurances > mostOccurances) {
mostOccurances = occurances;
k_most_popular = k_exp_i;
}
if (!ExpressionUtils.functionallyEquivalent(k_exp_0, k_exp_i, false, 1e-8, 1e-8)) {
bFailed = true;
}
}
if (!bFailed) {
PropensityFunction propensityFunction = new PropensityFunction();
propensityFunction.speciesNames = speciesNames.clone();
propensityFunction.speciesOrders = order.clone();
propensityFunction.canonicalExpression = Expression.mult(k_most_popular, order_substituted_canonical_expression);
propensityFunction.k_expression = k_most_popular;
for (int i = 0; i < binomialList.size(); i++) {
binomialList.get(i).power = (int) values[i];
}
propensityFunction.binomials = binomialList.toArray(new Binomial[binomialList.size()]);
return propensityFunction;
}
}
throw new MathException("Did not recognize propensity function from \"" + original_expression.infix() + "\", looking for product of species (e.g. \"rateConstant*species1*(species1-1)*species2\")");
}
use of cbit.vcell.parser.SimpleSymbolTable in project vcell by virtualcell.
the class DataSetControllerImpl method getPostProcessStateVariables.
private static FunctionHelper getPostProcessStateVariables(AnnotatedFunction annotatedFunction, DataOperationResults.DataProcessingOutputInfo dataProcessingOutputInfo) throws Exception {
Expression flattenedExpression = annotatedFunction.getExpression().flatten();
String[] postProcessSymbols = flattenedExpression.getSymbols();
ArrayList<String> alteredPostProcessSymbols = new ArrayList<String>();
for (int i = 0; i < postProcessSymbols.length; i++) {
if (postProcessSymbols[i].equals("t") || postProcessSymbols[i].equals("x") || postProcessSymbols[i].equals("y") || postProcessSymbols[i].equals("z")) {
// skip
} else {
alteredPostProcessSymbols.add(postProcessSymbols[i]);
}
}
postProcessSymbols = alteredPostProcessSymbols.toArray(new String[0]);
String[] bindSymbols = new String[postProcessSymbols.length + TXYZ_OFFSET];
bindSymbols[0] = "t";
bindSymbols[1] = "x";
bindSymbols[2] = "y";
bindSymbols[3] = "z";
for (int i = 0; i < postProcessSymbols.length; i++) {
bindSymbols[i + TXYZ_OFFSET] = postProcessSymbols[i];
}
SimpleSymbolTable simpleSymbolTable = new SimpleSymbolTable(bindSymbols);
flattenedExpression.bindExpression(simpleSymbolTable);
return new FunctionHelper(postProcessSymbols, flattenedExpression);
}
use of cbit.vcell.parser.SimpleSymbolTable in project vcell by virtualcell.
the class SmoldynFileWriter method writeInitialConcentration.
private int writeInitialConcentration(ParticleInitialConditionConcentration initialConcentration, SubDomain subDomain, Variable variable, String variableName, StringBuilder sb) throws ExpressionException, MathException {
SimpleSymbolTable simpleSymbolTable = new SimpleSymbolTable(new String[] { ReservedVariable.X.getName(), ReservedVariable.Y.getName(), ReservedVariable.Z.getName() });
Expression disExpression = new Expression(initialConcentration.getDistribution());
disExpression.bindExpression(simulationSymbolTable);
disExpression = simulationSymbolTable.substituteFunctions(disExpression).flatten();
disExpression.bindExpression(simpleSymbolTable);
double[] values = new double[3];
if (dimension == 1) {
if (disExpression.getSymbolBinding(ReservedVariable.Y.getName()) != null || disExpression.getSymbolBinding(ReservedVariable.Z.getName()) != null) {
throw new MathException(VCellErrorMessages.getSmoldynWrongCoordinates("'y' or 'z'", dimension, variable, disExpression));
}
} else if (dimension == 2) {
if (disExpression.getSymbolBinding(ReservedVariable.Z.getName()) != null) {
throw new MathException(VCellErrorMessages.getSmoldynWrongCoordinates("'z'", dimension, variable, disExpression));
}
}
int totalCount = 0;
StringBuilder localsb = new StringBuilder();
if (subDomain instanceof CompartmentSubDomain) {
MeshSpecification meshSpecification = simulation.getMeshSpecification();
ISize sampleSize = meshSpecification.getSamplingSize();
int numX = sampleSize.getX();
int numY = dimension < 2 ? 1 : sampleSize.getY();
int numZ = dimension < 3 ? 1 : sampleSize.getZ();
boolean bCellCentered = simulation.hasCellCenteredMesh();
double dx = meshSpecification.getDx(bCellCentered);
double dy = meshSpecification.getDy(bCellCentered);
double dz = meshSpecification.getDz(bCellCentered);
Origin origin = resampledGeometry.getGeometrySpec().getOrigin();
double ox = origin.getX();
double oy = origin.getY();
double oz = origin.getZ();
Extent extent = resampledGeometry.getExtent();
double ex = extent.getX();
double ey = extent.getY();
double ez = extent.getZ();
int offset = 0;
for (int k = 0; k < numZ; k++) {
double centerz = oz + k * dz;
double loz = Math.max(oz, centerz - dz / 2);
double hiz = Math.min(oz + ez, centerz + dz / 2);
double lz = hiz - loz;
values[2] = centerz;
for (int j = 0; j < numY; j++) {
double centery = oy + j * dy;
double loy = Math.max(oy, centery - dy / 2);
double hiy = Math.min(oy + ey, centery + dy / 2);
values[1] = centery;
double ly = hiy - loy;
for (int i = 0; i < numX; i++) {
int regionIndex = resampledGeometry.getGeometrySurfaceDescription().getRegionImage().getRegionInfoFromOffset(offset).getRegionIndex();
offset++;
GeometricRegion region = resampledGeometry.getGeometrySurfaceDescription().getGeometricRegions(regionIndex);
if (region instanceof VolumeGeometricRegion) {
if (!((VolumeGeometricRegion) region).getSubVolume().getName().equals(subDomain.getName())) {
continue;
}
}
double centerx = ox + i * dx;
double lox = Math.max(ox, centerx - dx / 2);
double hix = Math.min(ox + ex, centerx + dx / 2);
double lx = hix - lox;
values[0] = centerx;
double volume = lx;
if (dimension > 1) {
volume *= ly;
if (dimension > 2) {
volume *= lz;
}
}
double expectedCount = disExpression.evaluateVector(values) * volume;
if (expectedCount <= 0) {
continue;
}
long count = dist.nextPoisson(expectedCount);
if (count <= 0) {
continue;
}
totalCount += count;
localsb.append(SmoldynVCellMapper.SmoldynKeyword.mol + " " + count + " " + variableName + " " + (float) lox + "-" + (float) hix);
if (lg.isDebugEnabled()) {
lg.debug("Component subdomain " + variableName + " count " + count);
}
if (dimension > 1) {
localsb.append(" " + loy + "-" + hiy);
if (dimension > 2) {
localsb.append(" " + loz + "-" + hiz);
}
}
localsb.append("\n");
}
}
}
// otherwise we append the distributed molecules in different small boxes
try {
subsituteFlattenToConstant(disExpression);
sb.append(SmoldynVCellMapper.SmoldynKeyword.compartment_mol);
sb.append(" " + totalCount + " " + variableName + " " + subDomain.getName() + "\n");
} catch (// can not be evaluated to a constant
Exception e) {
sb.append(localsb);
}
} else if (subDomain instanceof MembraneSubDomain) {
ArrayList<TrianglePanel> trianglePanelList = membraneSubdomainTriangleMap.get(subDomain);
for (TrianglePanel trianglePanel : trianglePanelList) {
Triangle triangle = trianglePanel.triangle;
switch(dimension) {
case 1:
values[0] = triangle.getNodes(0).getX();
break;
case 2:
{
double centroidX = triangle.getNodes(0).getX();
double centroidY = triangle.getNodes(0).getY();
if (triangle.getNodes(0).getX() == triangle.getNodes(1).getX() && triangle.getNodes(0).getY() == triangle.getNodes(1).getY()) {
centroidX += triangle.getNodes(2).getX();
centroidY += triangle.getNodes(2).getY();
} else {
centroidX += triangle.getNodes(1).getX();
centroidY += triangle.getNodes(1).getY();
}
values[0] = centroidX / 2;
values[1] = centroidY / 2;
break;
}
case 3:
{
double centroidX = triangle.getNodes(0).getX() + triangle.getNodes(1).getX() + triangle.getNodes(2).getX();
double centroidY = triangle.getNodes(0).getY() + triangle.getNodes(1).getY() + triangle.getNodes(2).getY();
double centroidZ = triangle.getNodes(0).getZ() + triangle.getNodes(1).getZ() + triangle.getNodes(2).getZ();
values[0] = centroidX / 3;
values[1] = centroidY / 3;
values[2] = centroidZ / 3;
break;
}
}
double expectedCount = disExpression.evaluateVector(values) * triangle.getArea();
if (expectedCount <= 0) {
continue;
}
long count = dist.nextPoisson(expectedCount);
if (count <= 0) {
continue;
}
totalCount += count;
if (lg.isDebugEnabled()) {
lg.debug("Membrane subdomain " + subDomain.getName() + ' ' + variableName + " count " + count);
}
localsb.append(SmoldynVCellMapper.SmoldynKeyword.surface_mol + " " + count + " " + variableName + " " + subDomain.getName() + " " + SmoldynVCellMapper.SmoldynKeyword.tri + " " + trianglePanel.name + "\n");
}
// otherwise we append the distributed molecules in different small boxes
try {
subsituteFlattenToConstant(disExpression);
sb.append(SmoldynVCellMapper.SmoldynKeyword.surface_mol);
sb.append(" " + totalCount + " " + variableName + " " + subDomain.getName() + " " + SmoldynVCellMapper.SmoldynKeyword.all + " " + SmoldynVCellMapper.SmoldynKeyword.all + "\n");
} catch (// can not be evaluated to a constant
Exception e) {
sb.append(localsb);
}
}
if (lg.isDebugEnabled()) {
lg.debug("Subdomain " + subDomain.getName() + ' ' + variableName + " total count " + totalCount);
}
return totalCount;
}
use of cbit.vcell.parser.SimpleSymbolTable in project vcell by virtualcell.
the class ChomboVtkFileWriter method evaluateFunction.
private double[] evaluateFunction(VtuVarInfo var, ChomboMeshData chomboMeshData, List<ChomboCellIndices> cellIndices) throws ExpressionException, ExpressionBindingException, DivideByZeroException {
Expression exp = new Expression(var.functionExpression);
String[] symbols = exp.getSymbols();
double[][] symbolData = new double[symbols.length][];
for (int s = 0; s < symbols.length; s++) {
symbolData[s] = chomboMeshData.getVolumeCellData(symbols[s], cellIndices);
}
SimpleSymbolTable symbolTable = new SimpleSymbolTable(symbols);
exp.bindExpression(symbolTable);
double[] values = new double[symbols.length];
double[] functionData = new double[cellIndices.size()];
for (int c = 0; c < cellIndices.size(); c++) {
for (int s = 0; s < symbols.length; s++) {
values[s] = symbolData[s][c];
}
functionData[c] = exp.evaluateVector(values);
}
return functionData;
}
Aggregations