Skip to content

WIP: CSG round trip to SBML #424

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion vcell-core/src/main/java/cbit/vcell/geometry/CSGObject.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@
package cbit.vcell.geometry;

import org.vcell.util.Compare;
import org.vcell.util.Extent;
import org.vcell.util.Matchable;
import org.vcell.util.Origin;
import org.vcell.util.document.KeyValue;

import cbit.image.ImageException;
Expand All @@ -33,7 +35,18 @@ public CSGObject(CSGObject csgObj) {
root = csgObj.root.clone();
}

public boolean compareEqual(Matchable obj) {
public static CSGObject createBackgroundObject(Origin vcOrigin, Extent vcExtent, String name, int handle) {
CSGPrimitive cube = new CSGPrimitive("background", CSGPrimitive.PrimitiveType.CUBE);
CSGScale scale = new CSGScale("scale",new Vect3d(2*vcExtent.getX(),2*vcExtent.getY(), 2*vcExtent.getZ()));
CSGTranslation translation = new CSGTranslation("translate", new Vect3d(-vcOrigin.getX(), -vcOrigin.getY(), -vcOrigin.getZ()));
scale.setChild(translation);
translation.setChild(cube);
CSGObject csgObject = new CSGObject(null ,name, handle);
csgObject.setRoot(scale);
return csgObject;
}

public boolean compareEqual(Matchable obj) {
if (!compareEqual0(obj)){
return false;
}
Expand Down
2 changes: 1 addition & 1 deletion vcell-core/src/main/java/cbit/vcell/model/Kinetics.java
Original file line number Diff line number Diff line change
Expand Up @@ -905,7 +905,7 @@ private final void cleanupParameters() throws ModelException, ExpressionExceptio
try {
exp.bindExpression(reactionStep);
}catch (ExpressionBindingException e){
logger.error("error binding expression '"+exp.infix()+"': "+e.getMessage(), e);
logger.warn("error binding expression '"+exp.infix()+"': "+e.getMessage());
}
}
}
Expand Down
115 changes: 90 additions & 25 deletions vcell-core/src/main/java/org/vcell/sbml/vcell/SBMLExporter.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
import cbit.vcell.field.FieldFunctionArguments;
import cbit.vcell.field.FieldUtilities;
import cbit.vcell.geometry.CSGObject;
import cbit.vcell.geometry.CSGPrimitive;
import cbit.vcell.geometry.CSGScale;
import cbit.vcell.geometry.CSGTranslation;
import cbit.vcell.geometry.Geometry;
import cbit.vcell.geometry.*;
import cbit.vcell.geometry.RegionImage.RegionInfo;
Expand Down Expand Up @@ -53,6 +56,7 @@
import cbit.vcell.parser.ExpressionMathMLPrinter;
import cbit.vcell.parser.ExpressionMathMLPrinter.MathType;
import cbit.vcell.parser.SymbolTableEntry;
import cbit.vcell.render.Vect3d;
import cbit.vcell.solver.AnnotatedFunction;
import cbit.vcell.solver.Simulation;
import cbit.vcell.solver.SimulationSymbolTable;
Expand All @@ -75,7 +79,7 @@
import org.vcell.sbml.UnsupportedSbmlExportException;
import org.vcell.sbml.vcell.SBMLSymbolMapping.SBaseWrapper;
import org.vcell.util.*;
import org.vcell.util.document.VCellSoftwareVersion;
import org.vcell.vis.core.Vect3D;

import javax.xml.stream.XMLStreamException;
import java.beans.PropertyVetoException;
Expand Down Expand Up @@ -2243,7 +2247,8 @@ private void addGeometry() throws SbmlException {
if (vcGeomClasses[i] instanceof AnalyticSubVolume) {
AnalyticSubVolume vcAnalyticSubVolume = (AnalyticSubVolume) vcGeomClasses[i];
// need to avoid id name clash with structures (compartments)
AnalyticVolume analyticVol = sbmlAnalyticGeomDefinition.createAnalyticVolume(TokenMangler.mangleToSName("AnalyticVol_"+vcAnalyticSubVolume.getName()));
String id = TokenMangler.mangleToSName("AnalyticVol_" + vcAnalyticSubVolume.getName());
AnalyticVolume analyticVol = sbmlAnalyticGeomDefinition.createAnalyticVolume(id);
// analyticVol.setSpatialId(vcGeomClasses[i].getName());
analyticVol.setDomainType(DOMAIN_TYPE_PREFIX+vcAnalyticSubVolume.getName());
analyticVol.setFunctionType(FunctionKind.layered);
Expand All @@ -2262,9 +2267,46 @@ private void addGeometry() throws SbmlException {
addGeometrySamplingAnnotation(dimension, vcGSD, sbmlAnalyticGeomDefinition);
}
//
// add CSGeometry
// add CSGeometry without any AnalyticSubVolumes
//
if (!bAnyAnalyticSubvolumes && !bAnyImageSubvolumes && bAnyCSGSubvolumes){
// if (!bAnyAnalyticSubvolumes && !bAnyImageSubvolumes && bAnyCSGSubvolumes){
if (!bAnyImageSubvolumes && bAnyCSGSubvolumes){
CSGeometry sbmlCSGeomDefinition = sbmlGeometry.createCSGeometry();
sbmlCSGeomDefinition.setSpatialId(TokenMangler.mangleToSName("CSG_"+vcGeometry.getName()));
sbmlCSGeomDefinition.setIsActive(true);
for (int i = 0; i < vcGeomClasses.length; i++) {
if (vcGeomClasses[i] instanceof CSGObject) {
CSGObject vcellCSGObject = (CSGObject)vcGeomClasses[i];
String id = TokenMangler.mangleToSName("CSGObject_" + vcellCSGObject.getName());
org.sbml.jsbml.ext.spatial.CSGObject sbmlCSGObject = sbmlCSGeomDefinition.createCSGObject(id);
sbmlCSGObject.setDomainType(DOMAIN_TYPE_PREFIX+vcellCSGObject.getName());
sbmlCSGObject.setOrdinal(vcellCSGObject.getHandle()); // numSubVols - (i+1)); // the ordinal should be the least for the default/background subVolume
org.sbml.jsbml.ext.spatial.CSGNode sbmlcsgNode = getSBMLCSGNode(vcellCSGObject.getRoot());
sbmlcsgNode.setParent(sbmlCSGObject);
sbmlCSGObject.setCSGNode(sbmlcsgNode);
}else if (vcGeomClasses[i] instanceof AnalyticSubVolume && ((AnalyticSubVolume)vcGeomClasses[i]).getExpression().isOne()) {
AnalyticSubVolume analyticSubVolume = (AnalyticSubVolume)vcGeomClasses[i];
String id = TokenMangler.mangleToSName("CSGObject_" + analyticSubVolume.getName());
org.sbml.jsbml.ext.spatial.CSGObject sbmlCSGObject = sbmlCSGeomDefinition.createCSGObject(id);
sbmlCSGObject.setDomainType(DOMAIN_TYPE_PREFIX+analyticSubVolume.getName());
sbmlCSGObject.setOrdinal(analyticSubVolume.getHandle()); // the ordinal should be the least for the default/background subVolume
CSGObject backgroundObject = CSGObject.createBackgroundObject(vcOrigin, vcExtent, analyticSubVolume.getName(), analyticSubVolume.getHandle());
org.sbml.jsbml.ext.spatial.CSGNode sbmlcsgNode = getSBMLCSGNode(backgroundObject.getRoot());
sbmlcsgNode.setParent(sbmlCSGObject);
sbmlCSGObject.setCSGNode(sbmlcsgNode);
}
}
addGeometrySamplingAnnotation(dimension, vcGSD, sbmlCSGeomDefinition);
}
//
// add CSGeometry with a single AnalyticSubVolume as the background
//
List<AnalyticSubVolume> analyticSubVolumes = Arrays.stream(vcGeometry.getGeometrySpec().getSubVolumes())
.filter(sv -> sv instanceof AnalyticSubVolume)
.map(sv -> (AnalyticSubVolume)sv).collect(Collectors.toList());
if (analyticSubVolumes.size()==1 && analyticSubVolumes.get(0).getExpression().isOne() && !bAnyImageSubvolumes && bAnyCSGSubvolumes){
AnalyticSubVolume backgroundAnalyticSubVolume = analyticSubVolumes.get(0);

CSGeometry sbmlCSGeomDefinition = new CSGeometry();
sbmlGeometry.addGeometryDefinition(sbmlCSGeomDefinition);
sbmlCSGeomDefinition.setSpatialId(TokenMangler.mangleToSName("CSG_"+vcGeometry.getName()));
Expand All @@ -2275,9 +2317,28 @@ private void addGeometry() throws SbmlException {
sbmlCSGeomDefinition.addCSGObject(sbmlCSGObject);
sbmlCSGObject.setSpatialId(vcellCSGObject.getName());
sbmlCSGObject.setDomainType(DOMAIN_TYPE_PREFIX+vcellCSGObject.getName());
sbmlCSGObject.setOrdinal(numSubVols - (i+1)); // the ordinal should the the least for the default/background subVolume
sbmlCSGObject.setOrdinal(numSubVols - (i+1)); // the ordinal should the the least for the default/background subVolume
org.sbml.jsbml.ext.spatial.CSGNode sbmlcsgNode = getSBMLCSGNode(vcellCSGObject.getRoot());
sbmlCSGObject.setCSGNode(sbmlcsgNode);
}else if (vcGeomClasses[i] == backgroundAnalyticSubVolume){
org.sbml.jsbml.ext.spatial.CSGObject sbmlCSGObject = new org.sbml.jsbml.ext.spatial.CSGObject();
sbmlCSGeomDefinition.addCSGObject(sbmlCSGObject);
sbmlCSGObject.setSpatialId(backgroundAnalyticSubVolume.getName());
sbmlCSGObject.setDomainType(DOMAIN_TYPE_PREFIX+backgroundAnalyticSubVolume.getName());
sbmlCSGObject.setOrdinal(numSubVols - (i+1)); // the ordinal should the the least for the default/background subVolume
CSGPrimitive cube = new CSGPrimitive("background_cube", CSGPrimitive.PrimitiveType.CUBE);
CSGScale cubeScale = new CSGScale("background_scale", new Vect3d(
vcExtent.getX()/2.0,
vcExtent.getY()/2.0,
vcExtent.getZ()/2.0));
CSGTranslation cubeTranslate = new CSGTranslation("background_translate",new Vect3d(
vcOrigin.getX() + vcExtent.getX()/2.0,
vcOrigin.getX() + vcExtent.getY()/2.0,
vcOrigin.getZ() + vcExtent.getZ()/2.0));
cubeScale.setChild(cube);
cubeTranslate.setChild(cubeScale);
org.sbml.jsbml.ext.spatial.CSGNode sbmlcsgNode = getSBMLCSGNode(cubeTranslate);
sbmlCSGObject.setCSGNode(sbmlcsgNode);
}
}
addGeometrySamplingAnnotation(dimension, vcGSD, sbmlCSGeomDefinition);
Expand Down Expand Up @@ -2435,6 +2496,10 @@ private void addGeometry() throws SbmlException {
}
*/
}

if (sbmlGeometry.getListOfGeometryDefinitions().size()==0){
throw new SbmlException("did not export any SBML geometry definitions for this spatial application");
}
//
// add "SurfaceMesh" ParametricGeometry
//
Expand Down Expand Up @@ -2475,31 +2540,31 @@ private boolean goodPointer(Object obj, Class<?> clzz, String sourceName) {
}

private static org.sbml.jsbml.ext.spatial.CSGNode getSBMLCSGNode(cbit.vcell.geometry.CSGNode vcCSGNode) {
String csgNodeName = vcCSGNode.getName();
String csgNodeName = "CSGObjectNode_"+vcCSGNode.getName();
if (vcCSGNode instanceof cbit.vcell.geometry.CSGPrimitive){
cbit.vcell.geometry.CSGPrimitive vcCSGprimitive = (cbit.vcell.geometry.CSGPrimitive)vcCSGNode;
org.sbml.jsbml.ext.spatial.CSGPrimitive sbmlPrimitive = new org.sbml.jsbml.ext.spatial.CSGPrimitive();
sbmlPrimitive.setSpatialId(csgNodeName);
switch (vcCSGprimitive.getType()){
case SPHERE: {
sbmlPrimitive.setPrimitiveType(SBMLSpatialConstants.SOLID_SPHERE);
break;
}
case CONE: {
sbmlPrimitive.setPrimitiveType(SBMLSpatialConstants.SOLID_CONE);
break;
}
case CUBE: {
sbmlPrimitive.setPrimitiveType(SBMLSpatialConstants.SOLID_CUBE);
break;
}
case CYLINDER: {
sbmlPrimitive.setPrimitiveType(SBMLSpatialConstants.SOLID_CYLINDER);
break;
}
default: {
throw new RuntimeException("unsupported primitive type "+vcCSGprimitive.getType());
}
case SPHERE: {
sbmlPrimitive.setPrimitiveType(PrimitiveKind.sphere);
break;
}
case CONE: {
sbmlPrimitive.setPrimitiveType(PrimitiveKind.cone);
break;
}
case CUBE: {
sbmlPrimitive.setPrimitiveType(PrimitiveKind.cube);
break;
}
case CYLINDER: {
sbmlPrimitive.setPrimitiveType(PrimitiveKind.cylinder);
break;
}
default: {
throw new RuntimeException("unsupported primitive type "+vcCSGprimitive.getType());
}
}
return sbmlPrimitive;
}else if (vcCSGNode instanceof cbit.vcell.geometry.CSGPseudoPrimitive){
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4026,7 +4026,7 @@ private static void addGeometry(org.sbml.jsbml.Model sbmlModel, BioModel vcBioMo
// CSGObject[] vcCSGSubVolumes = new CSGObject[n];
for (int i = 0; i < n; i++) {
org.sbml.jsbml.ext.spatial.CSGObject sbmlCSGObject = sbmlCSGs.get(i);
CSGObject vcellCSGObject = new CSGObject(null, sbmlCSGObject.getSpatialId(), i);
CSGObject vcellCSGObject = new CSGObject(null, sbmlCSGObject.getDomainType(), i);
if (domainTypeId_to_handle_map.get(sbmlCSGObject.getDomainType()) != null){
vcellCSGObject.setHandle(domainTypeId_to_handle_map.get(sbmlCSGObject.getDomainType()));
}
Expand Down

This file was deleted.

Loading