Tutorial: Building a Model¶
This tutorial walks through defining a reaction network with Antimony, creating a 3D geometry, visualizing it, and running a spatial simulation.
See also the Building a Model reference guide.
Define a reaction network with Antimony¶
In [1]:
Copied!
import pyvcell.vcml as vc
antimony_str = """
compartment ec = 1;
compartment cell = 2;
compartment pm = 1;
species A in cell;
species B in cell;
J0: A -> B; cell * (k1*A - k2*B)
J0 in cell;
k1 = 5.0; k2 = 2.0
A = 10
"""
biomodel = vc.load_antimony_str(antimony_str)
model = biomodel.model
model.get_compartment("pm").dim = 2
print(model)
print("Parameters:", model.parameter_values)
import pyvcell.vcml as vc
antimony_str = """
compartment ec = 1;
compartment cell = 2;
compartment pm = 1;
species A in cell;
species B in cell;
J0: A -> B; cell * (k1*A - k2*B)
J0 in cell;
k1 = 5.0; k2 = 2.0
A = 10
"""
biomodel = vc.load_antimony_str(antimony_str)
model = biomodel.model
model.get_compartment("pm").dim = 2
print(model)
print("Parameters:", model.parameter_values)
2026-03-08T04:06:59.387256Z main WARN The use of package scanning to locate Log4j plugins is deprecated.
Please remove the `packages` attribute from your configuration file.
See https://logging.apache.org/log4j/2.x/faq.html#package-scanning for details.
2026-03-07 23:06:59,390 ERROR (SBMLDocument.java:573) - There was an error accessing the sbml online validator!
2026-03-08T04:06:59.395136Z main WARN The Logger cbit.vcell.model.Kinetics was created with the message factory org.apache.logging.log4j.message.ReusableMessageFactory@497f857d and is now requested with a null message factory (defaults to org.apache.logging.log4j.message.ParameterizedMessageFactory), which may create log events with unexpected formatting.
2026-03-08T04:06:59.397797Z main WARN The Logger cbit.vcell.mapping.AbstractMathMapping was created with the message factory org.apache.logging.log4j.message.ReusableMessageFactory@497f857d and is now requested with a null message factory (defaults to org.apache.logging.log4j.message.ParameterizedMessageFactory), which may create log events with unexpected formatting.
2026-03-07 23:06:59,398 INFO (DiffEquMathMapping.java:1457) - WARNING:::: MathMapping.refreshMathDescription() ... assigning boundary condition types not unique
2026-03-07 23:06:59,398 INFO (DiffEquMathMapping.java:1457) - WARNING:::: MathMapping.refreshMathDescription() ... assigning boundary condition types not unique
2026-03-07 23:06:59,398 INFO (Entrypoints.java:172) - Returning from sbmlToVcell: {"success":true,"message":"Success"}
name='unnamed' species=[Species(name='A', compartment_name='cell'), Species(name='B', compartment_name='cell')] compartments=[Compartment(name='ec', dim=3), Compartment(name='cell', dim=3), Compartment(name='pm', dim=2)] reactions=[Reaction(name='J0', compartment_name='cell', reversible=True, is_flux=False, kinetics=Kinetics(kinetics_type='GeneralKinetics', kinetics_parameters=[KineticsParameter(name='J', value='((A * k1) - (B * k2))', role='reaction rate', unit='s-1', reaction_name='J0')]), reactants=[SpeciesReference(name='A', stoichiometry=1, species_ref_type=<SpeciesRefType.reactant: 'reactant'>)], products=[SpeciesReference(name='B', stoichiometry=1, species_ref_type=<SpeciesRefType.product: 'product'>)])] model_parameters=[ModelParameter(name='k1', value=5.0, role='user defined', unit='tbd'), ModelParameter(name='k2', value=2.0, role='user defined', unit='tbd')]
Parameters: {'k1': 5.0, 'k2': 2.0, 'J0.J': '((A * k1) - (B * k2))'}
Create a 3D geometry¶
Define a sphere inside a box. Subvolumes added first have higher priority.
In [2]:
Copied!
geo = vc.Geometry(name="geo", origin=(0, 0, 0), extent=(10, 10, 10), dim=3)
geo.add_sphere(name="cell_domain", radius=4, center=(5, 5, 5))
geo.add_background(name="ec_domain")
geo.add_surface(name="pm_domain", sub_volume_1="cell_domain", sub_volume_2="ec_domain")
geo = vc.Geometry(name="geo", origin=(0, 0, 0), extent=(10, 10, 10), dim=3)
geo.add_sphere(name="cell_domain", radius=4, center=(5, 5, 5))
geo.add_background(name="ec_domain")
geo.add_surface(name="pm_domain", sub_volume_1="cell_domain", sub_volume_2="ec_domain")
Out[2]:
SurfaceClass(name='pm_domain', subvolume_ref_1='cell_domain', subvolume_ref_2='ec_domain')
Visualize the geometry¶
Use geo.plot() to render a 3D view of the geometry before running any simulation.
In [3]:
Copied!
geo.plot(save_path="../images/building-geometry.png")
geo.plot(save_path="../images/building-geometry.png")
/Users/jimschaff/Documents/workspace/pyvcell/pyvcell/_internal/geometry/segmented_image_geometry.py:94: UserWarning: FigureCanvasAgg is non-interactive, and thus cannot be shown plt.show()
Create an application and map compartments¶
In [4]:
Copied!
app = biomodel.add_application("app1", geometry=geo)
app.map_compartment("cell", "cell_domain")
app.map_compartment("ec", "ec_domain")
app.map_species("A", init_conc="3+sin(x)", diff_coef=1.0)
app.map_species("B", init_conc="2+cos(x+y+z)", diff_coef=1.0)
app = biomodel.add_application("app1", geometry=geo)
app.map_compartment("cell", "cell_domain")
app.map_compartment("ec", "ec_domain")
app.map_species("A", init_conc="3+sin(x)", diff_coef=1.0)
app.map_species("B", init_conc="2+cos(x+y+z)", diff_coef=1.0)
Out[4]:
SpeciesMapping(species_name='B', init_conc='2+cos(x+y+z)', diff_coef=1.0, boundary_values=[0.0, 0.0, 0.0, 0.0, 0.0, 0.0])
Simulate¶
In [5]:
Copied!
sim = app.add_sim(
name="sim1",
duration=2.0,
output_time_step=0.05,
mesh_size=(30, 30, 30),
)
results = vc.simulate(biomodel=biomodel, simulation="sim1")
sim = app.add_sim(
name="sim1",
duration=2.0,
output_time_step=0.05,
mesh_size=(30, 30, 30),
)
results = vc.simulate(biomodel=biomodel, simulation="sim1")
2026-03-08T04:06:59.777017Z main WARN The use of package scanning to locate Log4j plugins is deprecated. Please remove the `packages` attribute from your configuration file. See https://logging.apache.org/log4j/2.x/faq.html#package-scanning for details. 2026-03-08T04:06:59.780746Z main WARN The Logger cbit.vcell.model.Kinetics was created with the message factory org.apache.logging.log4j.message.ReusableMessageFactory@38726aff and is now requested with a null message factory (defaults to org.apache.logging.log4j.message.ParameterizedMessageFactory), which may create log events with unexpected formatting. 2026-03-08T04:06:59.969051Z main WARN The Logger cbit.vcell.mapping.AbstractMathMapping was created with the message factory org.apache.logging.log4j.message.ReusableMessageFactory@38726aff and is now requested with a null message factory (defaults to org.apache.logging.log4j.message.ParameterizedMessageFactory), which may create log events with unexpected formatting. 2026-03-07 23:06:59,970 INFO (DiffEquMathMapping.java:1457) - WARNING:::: MathMapping.refreshMathDescription() ... assigning boundary condition types not unique
2026-03-07 23:06:59,980 INFO (Entrypoints.java:200) - Returning from vcellToVcml: {"success":true,"message":"Success"}
2026-03-08T04:06:59.995692Z main WARN The use of package scanning to locate Log4j plugins is deprecated.
Please remove the `packages` attribute from your configuration file.
See https://logging.apache.org/log4j/2.x/faq.html#package-scanning for details.
2026-03-08T04:06:59.996553Z main WARN The Logger org.vcell.libvcell.Entrypoints was created with the message factory org.apache.logging.log4j.message.ReusableMessageFactory@25ecfd7c and is now requested with a null message factory (defaults to org.apache.logging.log4j.message.ParameterizedMessageFactory), which may create log events with unexpected formatting.
2026-03-08T04:06:59.999910Z main WARN The Logger cbit.vcell.model.Kinetics was created with the message factory org.apache.logging.log4j.message.ReusableMessageFactory@25ecfd7c and is now requested with a null message factory (defaults to org.apache.logging.log4j.message.ParameterizedMessageFactory), which may create log events with unexpected formatting.
2026-03-08T04:07:00.005494Z main WARN The Logger cbit.vcell.mapping.AbstractMathMapping was created with the message factory org.apache.logging.log4j.message.ReusableMessageFactory@25ecfd7c and is now requested with a null message factory (defaults to org.apache.logging.log4j.message.ParameterizedMessageFactory), which may create log events with unexpected formatting.
2026-03-07 23:07:00,006 INFO (DiffEquMathMapping.java:1457) - WARNING:::: MathMapping.refreshMathDescription() ... assigning boundary condition types not unique
2026-03-07 23:07:00,030 INFO (Entrypoints.java:83) - Returning from vcmlToFiniteVolumeInput: {"success":true,"message":"Success"}
Setting Base file name to: `"/Users/jimschaff/Documents/workspace/pyvcell/docs/guides/notebooks/workspace/out_dir_6nca5s9_/SimID_242707378_0_"`
Simulation Complete in Main() ...
initializing mesh numVolume=27000 CartesianMesh::computeNormalsFromNeighbors(), compute normals from neighbors Membrane Elements -> N=2544 ============================================== --------Num of points that have zero neighbors 0 --------Num Neighbors before symmetrize 14856 --------Num Neighbors after symmetrize 15720 Total volume=199.330193 Total FluxArea =0 Total FluxAreaXM =0 Total FluxAreaXP =0 Total FluxAreaYM =0 Total FluxAreaYP =0 Total FluxAreaZM =0 Total FluxAreaZP =0 mesh initialized preprocessing finished pdeCount=2, odeCount=0 No log-file found at constructed path `/Users/jimschaff/Documents/workspace/pyvcell/docs/guides/notebooks/workspace/out_dir_6nca5s9_/SimID_242707378_0_.log`.simulation [SimID_242707378_0_] started temporary directory used is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/ sim file name is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/SimID_242707378_0_0000.sim **This is a little endian machine.** [[[data:0]]] numVolRegions=2 Region 0: size=20512, offset=0 Region 1: size=6488, offset=20512 # of active points = 27000 Constant diffusion/advection in region cell_domain1 numUnknowns = 12976 ****** using Sundials CVode with PREC_LEFT, relTol=1e-07, absTol=1e-09, maxStep=0.1 ---------------------------------- sundials pde solver is starting from time 0 ---------------------------------- temporary directory used is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/ sim file name is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/SimID_242707378_0_0001.sim [[[data:0.05]]]temporary directory used is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/ sim file name is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/SimID_242707378_0_0002.sim [[[data:0.1]]]temporary directory used is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/ sim file name is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/SimID_242707378_0_0003.sim [[[data:0.15]]]temporary directory used is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/ sim file name is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/SimID_242707378_0_0004.sim [[[data:0.2]]]temporary directory used is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/ sim file name is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/SimID_242707378_0_0005.sim [[[data:0.25]]]temporary directory used is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/ sim file name is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/SimID_242707378_0_0006.sim [[[data:0.3]]]temporary directory used is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/ sim file name is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/SimID_242707378_0_0007.sim [[[data:0.35]]]temporary directory used is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/ sim file name is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/SimID_242707378_0_0008.sim [[[data:0.4]]]temporary directory used is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/ sim file name is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/SimID_242707378_0_0009.sim [[[data:0.45]]]temporary directory used is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/ sim file name is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/SimID_242707378_0_0010.sim [[[data:0.5]]]temporary directory used is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/ sim file name is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/SimID_242707378_0_0011.sim [[[data:0.55]]]temporary directory used is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/ sim file name is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/SimID_242707378_0_0012.sim [[[data:0.6]]]temporary directory used is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/ sim file name is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/SimID_242707378_0_0013.sim [[[data:0.65]]]temporary directory used is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/ sim file name is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/SimID_242707378_0_0014.sim [[[data:0.7]]]temporary directory used is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/ sim file name is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/SimID_242707378_0_0015.sim [[[data:0.75]]]temporary directory used is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/ sim file name is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/SimID_242707378_0_0016.sim [[[data:0.8]]]temporary directory used is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/ sim file name is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/SimID_242707378_0_0017.sim [[[data:0.85]]]temporary directory used is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/ sim file name is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/SimID_242707378_0_0018.sim [[[data:0.9]]]temporary directory used is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/ sim file name is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/SimID_242707378_0_0019.sim [[[data:0.95]]]temporary directory used is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/ sim file name is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/SimID_242707378_0_0020.sim [[[data:1]]]temporary directory used is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/ sim file name is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/SimID_242707378_0_0021.sim [[[data:1.05]]]temporary directory used is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/ sim file name is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/SimID_242707378_0_0022.sim [[[data:1.1]]]temporary directory used is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/ sim file name is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/SimID_242707378_0_0023.sim [[[data:1.15]]]temporary directory used is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/ sim file name is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/SimID_242707378_0_0024.sim [[[data:1.2]]]temporary directory used is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/ sim file name is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/SimID_242707378_0_0025.sim [[[data:1.25]]]temporary directory used is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/ sim file name is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/SimID_242707378_0_0026.sim [[[data:1.3]]]temporary directory used is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/ sim file name is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/SimID_242707378_0_0027.sim [[[data:1.35]]]temporary directory used is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/ sim file name is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/SimID_242707378_0_0028.sim [[[data:1.4]]]temporary directory used is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/ sim file name is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/SimID_242707378_0_0029.sim [[[data:1.45]]]temporary directory used is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/ sim file name is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/SimID_242707378_0_0030.sim [[[data:1.5]]]temporary directory used is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/ sim file name is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/SimID_242707378_0_0031.sim [[[data:1.55]]]temporary directory used is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/ sim file name is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/SimID_242707378_0_0032.sim [[[data:1.6]]]temporary directory used is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/ sim file name is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/SimID_242707378_0_0033.sim [[[data:1.65]]]temporary directory used is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/ sim file name is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/SimID_242707378_0_0034.sim [[[data:1.7]]]temporary directory used is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/ sim file name is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/SimID_242707378_0_0035.sim [[[data:1.75]]]temporary directory used is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/ sim file name is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/SimID_242707378_0_0036.sim [[[data:1.8]]]temporary directory used is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/ sim file name is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/SimID_242707378_0_0037.sim [[[data:1.85]]]temporary directory used is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/ sim file name is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/SimID_242707378_0_0038.sim [[[data:1.9]]]temporary directory used is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/ sim file name is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/SimID_242707378_0_0039.sim [[[data:1.95]]] Final Statistics.. lenrw = 129849 leniw = 50 lenrwLS = 129806 leniwLS = 10 nst = 164 nfe = 185 nfeLS = 217 nni = 181 nli = 217 nsetups = 56 netf = 1 npe = 3 nps = 372 ncfn = 0 ncfl = 0 last step = 0.050000 temporary directory used is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/ sim file name is /var/folders/zz/gcfcvgtd5v1cdgj2sw4bjzdr0000gr/T/SimID_242707378_0_0040.sim [[[data:2]]][[[progress:100%]]]
Visualize results¶
In [6]:
Copied!
results.plotter.plot_concentrations(save_path="../images/building-concentrations.png")
results.plotter.plot_concentrations(save_path="../images/building-concentrations.png")
/Users/jimschaff/Documents/workspace/pyvcell/pyvcell/sim_results/plotter.py:71: UserWarning: FigureCanvasAgg is non-interactive, and thus cannot be shown return plt.show()
In [7]:
Copied!
results.plotter.plot_slice_3d(time_index=0, channel_id="A", save_path="../images/building-slice3d-A.png")
results.plotter.plot_slice_3d(time_index=0, channel_id="A", save_path="../images/building-slice3d-A.png")
/Users/jimschaff/Documents/workspace/pyvcell/pyvcell/sim_results/plotter.py:138: UserWarning: FigureCanvasAgg is non-interactive, and thus cannot be shown return plt.show()
Clean up¶
In [8]:
Copied!
results.cleanup()
results.cleanup()