Skip to content

Commit 8b78cfb

Browse files
authored
Merge pull request #14 from virtualcell/fielddata
add support for field data
2 parents ec2adb4 + 501da65 commit 8b78cfb

File tree

10 files changed

+395
-62
lines changed

10 files changed

+395
-62
lines changed
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import os
2+
import shutil
3+
from pathlib import Path
4+
5+
from pyvcell.vcml import Simulation, VcmlReader
6+
from pyvcell.vcml.vcml_simulation import VcmlSpatialSimulation as Solver
7+
8+
# ----- make a workspace
9+
workspace_dir = Path(os.getcwd()) / "workspace"
10+
sim1_dir = workspace_dir / "sim1_dir"
11+
if sim1_dir.exists():
12+
shutil.rmtree(sim1_dir)
13+
sim2_dir = workspace_dir / "sim2_dir"
14+
if sim2_dir.exists():
15+
shutil.rmtree(sim2_dir)
16+
17+
# ---- read in VCML file
18+
model_fp = Path(os.getcwd()).parent / "models" / "SmallSpatialProject_3D.vcml"
19+
bio_model1 = VcmlReader.biomodel_from_file(model_fp)
20+
21+
# ---- get the application and the species mappings for species "s0" and "s1"
22+
app = bio_model1.applications[0]
23+
s1_mapping = next(s for s in app.species_mappings if s.species_name == "s1")
24+
s0_mapping = next(s for s in app.species_mappings if s.species_name == "s0")
25+
26+
# ---- add a simulation to the first application in the biomodel (didn't already have a simulation in the VCML file)
27+
new_sim = Simulation(name="new_sim", duration=10.0, output_time_step=0.1, mesh_size=(20, 20, 20))
28+
app.simulations.append(new_sim)
29+
30+
# ---- set the initial concentration of species "s0" and "s1" in the first application
31+
s0_mapping.init_conc = "3+sin(x)+cos(y)+sin(z)"
32+
s1_mapping.init_conc = "3+sin(x+y+z)"
33+
34+
# ---- run simulation, store in sim1_dir, and plot results
35+
# >>>>> This forms the data for the "Field Data" identified by 'sim1_dir' <<<<<<
36+
sim1_result = Solver(bio_model=bio_model1, out_dir=sim1_dir).run(new_sim.name)
37+
print([c.label for c in sim1_result.channel_data])
38+
print(sim1_result.time_points[::11])
39+
sim1_result.plotter.plot_slice_3d(time_index=0, channel_id="s0")
40+
sim1_result.plotter.plot_slice_3d(time_index=0, channel_id="s1")
41+
sim1_result.plotter.plot_concentrations()
42+
43+
44+
# ----- use field data from sim1_dir to set initial concentration of species "s0"
45+
s0_mapping.init_conc = "vcField('sim1_dir','s0',0.0,'Volume') * vcField('sim1_dir','s1',0.0,'Volume')"
46+
s1_mapping.init_conc = "5.0"
47+
# ---- re-run simulation and store in sim2_dir
48+
# note that the solution of s0 draws from the data from sim1_dir
49+
sim2_result = Solver(bio_model=bio_model1, out_dir=sim2_dir).run(new_sim.name)
50+
sim2_result.plotter.plot_slice_3d(time_index=0, channel_id="s0")
51+
sim2_result.plotter.plot_slice_3d(time_index=0, channel_id="s1")
52+
sim2_result.plotter.plot_concentrations()

poetry.lock

Lines changed: 14 additions & 14 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "pyvcell"
3-
version = "0.1.4"
3+
version = "0.1.6"
44
description = "This is the python wrapper for vcell modeling and simulation"
55
authors = ["Jim Schaff <[email protected]>"]
66
repository = "https://github.com/virtualcell/pyvcell"
@@ -33,7 +33,7 @@ matplotlib = "^3.10.0"
3333
lxml = "^5.3.1"
3434
imageio = "^2.37.0"
3535
tensorstore = "^0.1.72"
36-
libvcell = "^0.0.6"
36+
libvcell = "^0.0.8"
3737

3838
[tool.poetry.group.dev.dependencies]
3939
pytest = "^7.2.0"

pyvcell/_internal/simdata/simdata_models.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
PYTHON_ENDIANNESS: Literal["little", "big"] = "big"
1515
NUMPY_FLOAT_DTYPE = ">f8"
16+
UNSUPPORTED_VCELL_FUNCTIONS = ["vcField(", "vcRegionVolume(", "vcRegionArea(", "vcConv(", "vcGrad(", "vcProject("]
1617

1718

1819
class SpecialLogFileType(Enum):
@@ -290,5 +291,8 @@ def read(self) -> None:
290291
_unknown_skipped = parts[2]
291292
variable_type = VariableType.from_string(parts[3].strip(" "))
292293
_boolean_skipped = parts[4]
294+
295+
if any(u in expression for u in UNSUPPORTED_VCELL_FUNCTIONS):
296+
continue
293297
function = NamedFunction(name=name, vcell_expression=expression, variable_type=variable_type)
294298
self.named_functions.append(function)

tests/conftest.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
sbml_spatial_model_3d_path,
66
)
77
from tests.fixtures.vcell_model_fixtures import ( # noqa: F401
8+
vcml_field_data_demo_path,
9+
vcml_field_data_tgz_archive_path,
810
vcml_spatial_bunny_3d_path,
911
vcml_spatial_model_1d_path,
1012
vcml_spatial_small_3d_path,

tests/data_model/test_simulations.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import tarfile
2+
import tempfile
13
from pathlib import Path
24

35
import numpy as np
@@ -271,3 +273,49 @@ def test_vcml_model_parse_3d(vcml_spatial_model_1d_path: Path) -> None:
271273
dtype=np.float64,
272274
),
273275
)
276+
277+
278+
def test_vcml_field_data_demo(vcml_field_data_demo_path: Path, vcml_field_data_tgz_archive_path: Path) -> None:
279+
assert vcml_field_data_demo_path.is_file()
280+
281+
# create a temporary parent directory with a subdirectory for simulation data and a subdirectory to extract the archive
282+
parent_dir = Path(tempfile.mkdtemp())
283+
sim_dir = parent_dir / "sim"
284+
sim_dir.mkdir()
285+
assert sim_dir.is_dir()
286+
287+
with tarfile.open(vcml_field_data_tgz_archive_path, "r:gz") as tar:
288+
tar.extractall(parent_dir)
289+
290+
data_dir = parent_dir / "test2_lsm_DEMO"
291+
assert data_dir.is_dir()
292+
293+
bio_model: Biomodel = VcmlReader.biomodel_from_file(vcml_source=vcml_field_data_demo_path)
294+
assert bio_model.model is not None
295+
parameters: list[ModelParameter] = bio_model.model.model_parameters
296+
assert {p.name: p.value for p in parameters} == {}
297+
298+
sim_name = bio_model.applications[0].simulations[0].name
299+
simulation_orig = VcmlSpatialSimulation(bio_model=bio_model, out_dir=sim_dir)
300+
# # create a temporary file to write the VCML content to
301+
# vcml_path = Path(tempfile.mktemp(prefix="model_", suffix=".xml"))
302+
# vcml_spatial_model.export(vcml_path)
303+
results_orig: Result = simulation_orig.run(simulation_name=sim_name)
304+
305+
channels_orig = results_orig.channel_data
306+
assert [channel.label for channel in channels_orig] == [
307+
"region_mask",
308+
"t",
309+
"x",
310+
"y",
311+
"z",
312+
"species0_cyt",
313+
"species0_ec",
314+
]
315+
# assert np.allclose(
316+
# results_orig.concentrations[0, 0::10],
317+
# np.array(
318+
# [500000.00000000006, 236185.00811512678, 111567.6111715472],
319+
# dtype=np.float64,
320+
# ),
321+
# )

0 commit comments

Comments
 (0)