Skip to content

Commit 7f03200

Browse files
Basic generation and execution progress
1 parent dfe4e00 commit 7f03200

File tree

16 files changed

+1157
-299
lines changed

16 files changed

+1157
-299
lines changed

poetry.lock

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

pyproject.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@ requires-python = ">=3.10, <4.0"
1111
dependencies = [
1212
"process-bigraph (>=0.0.35, <1.0)",
1313
"typer (>=0.15.3, <1.0)",
14-
"process-bigraph-lang @ git+https://github.com/biosimulations/process-bigraph-lang.git",
15-
"spatio-flux @ git+https://github.com/vivarium-collective/spatio-flux.git"
14+
"process-bigraph-lang @ git+https://github.com/biosimulations/process-bigraph-lang.git#bind-to-object",
15+
"spatio-flux @ git+https://github.com/vivarium-collective/spatio-flux.git",
16+
"vivarium-interface (>=0.0.5,<0.0.6)"
1617
]
1718

1819
[tool.poetry]
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
from registry import standard_processes
1+
from registry import spatio_flux_library
Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import os
22
import rich
3+
from process_bigraph_lang.antlr_dsl.generate import bind_model
34
from process_bigraph_lang.dsl import generate
45
from process_bigraph_lang.dsl.model import (
56
Model,
@@ -9,6 +10,7 @@
910
def generateModelAst(pblang_file: os.PathLike[str]) -> Model:
1011
model_json: str = generate.generate_model(pblang_file)
1112
model: Model = Model.model_validate_json(model_json)
12-
result: str = model.model_dump_json(indent=4)
13-
rich.print(result)
13+
bind_model(model)
14+
#result: str = model.model_dump_json(indent=4)
15+
#rich.print(result)
1416
return model
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import warnings
2+
import re
3+
from typing import Any
4+
5+
from vivarium import Vivarium
6+
from process_bigraph_lang.dsl.model import Model, StoreDef, ProcessDef, Reference
7+
8+
def process_composite(model: Model, assembler: Vivarium):
9+
for composite_def in model.compositeDefs:
10+
store_to_store_def_map: dict[str, StoreDef] = {}
11+
for store_ref in composite_def.stores:
12+
# verify we have a reference for desired process
13+
match_obj = re.match("^#(/(\w+)(@(\d+))+)+$", store_ref.store_def.ref)
14+
if not match_obj:
15+
raise ValueError(
16+
f"Unexpected reference for process reference: `{store_ref.store_def.ref_text}` ({store_ref.store_def.ref})")
17+
full, section, _, index = match_obj.groups()
18+
if section != "store_defs":
19+
raise ValueError(f"Unexpected section `{section}` for reference `{store_ref.store_def.ref_text}` ({full})`")
20+
store_to_store_def_map[composite_def.name + "::" + store_ref.name] = model.store_defs[int(index)]
21+
22+
store_value_mapping: dict[str, Any] = {}
23+
for process in composite_def.processes:
24+
# verify we have a reference for desired process
25+
match_obj = re.match("^#(/(\w+)(@(\d+))+)+$", process.process_def.ref)
26+
if not match_obj:
27+
raise ValueError(f"Unexpected reference for process reference: `{process.process_def.ref_text}` ({process.process_def.ref})")
28+
full, section, _, index = match_obj.groups()
29+
if section != "processDefs":
30+
raise ValueError(f"Unexpected section `{section}` for reference `{process.process_def.ref_text}` ({full})`")
31+
# create config
32+
config = {}
33+
# for param in process.config:
34+
# pass
35+
# Identify ports needing to be bound
36+
process_def_actual: ProcessDef = model.processDefs[int(index)]
37+
input_bindings: dict[str, list[str]] = {elem.ref_text : [] for elem in process_def_actual.inputs}
38+
output_bindings: dict[str, list[str]] = {elem.ref_text : [] for elem in process_def_actual.outputs}
39+
40+
# store validation
41+
store_ref: Reference
42+
for store_ref in process.stores:
43+
match_obj = re.match("^#(/[\w]+(@\d)+)+$", store_ref.ref)
44+
if not match_obj:
45+
raise ValueError(f"Unexpected reference for process reference: `{store_ref.ref_text}` ({store_ref.ref})")
46+
tokenized_reference_path: list[tuple[str, int]] = [(elem.split("@")[0], int(elem.split("@")[1])) for elem in store_ref.ref[1:].split("/") if '@' in elem]
47+
map_key: str = composite_def.name + "::" + store_ref.ref_text
48+
if map_key not in store_to_store_def_map:
49+
raise ValueError(f"Store {store_ref} not found in mapping using key `{map_key}`")
50+
actual_def = store_to_store_def_map[map_key]
51+
for state_def in actual_def.states:
52+
in_path = input_bindings[state_def.name] if state_def.name in input_bindings else []
53+
out_binding = output_bindings[state_def.name] if state_def.name in output_bindings else []
54+
if 0 != len(in_path and 0 != len(out_binding)):
55+
continue
56+
if 0 == len(in_path) and 0 == len(out_binding): #nothing has been initialized with this store
57+
store_value_mapping[map_key] = state_def.default.val if state_def.default is not None else determine_builtin_default(state_def.type.ref_text)
58+
if 0 == len(in_path):
59+
for token in map_key.split("::"):
60+
in_path.append(token)
61+
if 0 == len(out_binding):
62+
for token in map_key.split("::"):
63+
out_binding.append(token)
64+
assembler.add_process(
65+
name=process.name,
66+
process_id=".".join(process_def_actual.python_path.path),
67+
#config={???},
68+
inputs=input_bindings,
69+
outputs=output_bindings,
70+
)
71+
# end scope of composite def for loop
72+
for path_str in store_value_mapping:
73+
path = path_str.split("::")
74+
assembler.set_value(path=path, value=store_value_mapping[path_str])
75+
assembler.add_emitter()
76+
77+
def determine_builtin_default(type_to_infer: str):
78+
if type_to_infer == "float":
79+
return 0.0
80+
elif type_to_infer == "int":
81+
return 0
82+
else:
83+
raise ValueError(f"Unknown built-in default for type `{type_to_infer}`")
Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,17 @@
11
import warnings
2+
from vivarium import Vivarium
3+
from process_bigraph_lang.dsl.model import Model
24
with warnings.catch_warnings(): # Temporary minimal_impact bug in process_bigraphs
35
warnings.simplefilter("ignore", SyntaxWarning)
46
#warnings.filterwarnings("error", category=SyntaxWarning)
57
from process_bigraph import ProcessTypes, Process
68

79

8-
def generateProcessFromDescription(instructions) -> Process:
9-
pass
10+
def register_process_defs(assembler: Vivarium, model: Model) -> None:
11+
# note: does not actually dynamically build processes...yet
12+
registry = assembler.core
13+
for process_def in model.processDefs:
14+
if registry.process_registry.find(process_def.name) is not None:
15+
continue
16+
raise ValueError(f"Unknown process definition {process_def.name}")
1017

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
import warnings
2-
3-
from process_bigraph_lang.dsl.model import Model
2+
from typing import Any
3+
from process_bigraph_lang.dsl.model import Model, Store
4+
from vivarium import Vivarium
45

56
with warnings.catch_warnings(): # Temporary minimal_impact bug in process_bigraphs
67
warnings.simplefilter("ignore", SyntaxWarning)
78
#warnings.filterwarnings("error", category=SyntaxWarning)
89
from process_bigraph import ProcessTypes
910

1011

11-
def collect_stores(model: Model):
12+
def collect_stores(model: Model) -> tuple[list[Store], Any]:
1213
pass
1314

14-
def register_stores(core: ProcessTypes) -> None:
15+
def register_stores(assembler: Vivarium, stores_to_register: list[Store]) -> None:
1516
pass
Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,21 @@
11
import warnings
22

33
from process_bigraph_lang.dsl.model import Model, Type
4-
4+
from vivarium import Vivarium
55
with warnings.catch_warnings(): # Temporary minimal_impact bug in process_bigraphs
66
warnings.simplefilter("ignore", SyntaxWarning)
77
#warnings.filterwarnings("error", category=SyntaxWarning)
88
from process_bigraph import ProcessTypes
99

10-
1110
def collect_types(model: Model) -> list[Type]:
1211
types_to_process: list[Type] = []
13-
for type in model.types:
12+
for type_to_add in model.types:
1413
# Insert some parsing code here
15-
types_to_process.append(type)
14+
types_to_process.append(type_to_add)
1615
return types_to_process
1716

18-
def register_type(core: ProcessTypes, types_to_register: list[Type]):
19-
pass
17+
def register_types(assembler: Vivarium, types_to_register: list[Type]):
18+
for type_to_register in types_to_register:
19+
if 0 == assembler.get_type(type_to_register.name).size:
20+
raise ValueError(f"Type {type_to_register.name} is an unknown type")
21+
# in the future, we'd attempt to generate a new type
Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
11
import warnings
22

3-
from process_bigraph_lang.dsl.model import Model
4-
3+
from process_bigraph_lang.dsl.model import Model, Unit
4+
from vivarium import Vivarium
55
with warnings.catch_warnings(): # Temporary minimal_impact bug in process_bigraphs
66
warnings.simplefilter("ignore", SyntaxWarning)
77
#warnings.filterwarnings("error", category=SyntaxWarning)
88
from process_bigraph import ProcessTypes
99

1010

11-
def collect_units(model: Model):
12-
pass
11+
def collect_units(model: Model) -> list[Unit]:
12+
units_to_process: list[Unit] = []
13+
for unit in model.units:
14+
# Insert some parsing code here
15+
units_to_process.append(unit)
16+
return units_to_process
1317

14-
def register_unit(core: ProcessTypes, ) -> None:
18+
def register_units(assembler: Vivarium, units_to_register: list[Unit]) -> None:
1519
pass

src/simple_process_bigraph_runtime/main.py

Lines changed: 49 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,23 +10,56 @@
1010
#warnings.filterwarnings("error", category=SyntaxWarning)
1111
from process_bigraph import ProcessTypes
1212
from simple_process_bigraph_runtime import dsl_adapter
13-
from spatio_flux import processes
13+
from vivarium import Vivarium
14+
from process_bigraph import Composite
1415

15-
app = typer.Typer()
16+
from simple_process_bigraph_runtime.generation.type_generator import register_types, collect_types
17+
from simple_process_bigraph_runtime.generation.unit_generator import register_units, collect_units
18+
from simple_process_bigraph_runtime.generation.composite_generator import process_composite
19+
from simple_process_bigraph_runtime.registry.spatio_flux_library import apply_to_vivarium as register_spatio_flux_library
20+
from simple_process_bigraph_runtime.registry.toy_library import apply_to_vivarium as register_toy_library
21+
from bigraph_viz import plot_bigraph
1622

23+
plot_settings = {
24+
'remove_process_place_edges': True
25+
}
26+
save_images = True
27+
if save_images:
28+
plot_settings.update({
29+
'out_dir': '/Users/logandrescher/Documents/pb_output_dir',
30+
'dpi': '70'
31+
})
1732

18-
core = ProcessTypes()
33+
app = typer.Typer()
1934

2035
@app.command()
2136
def validate(pblang_path: Annotated[str, typer.Argument(help="Path to the pblang file to validate")]):
22-
generatePythonModel(pblang_path)
37+
ast_model: Model = generatePythonModel(pblang_path)
38+
_, pb_doc, pb_core = performConversion(ast_model)
39+
plot_bigraph(state=pb_doc['state'], schema=pb_doc['composition'],
40+
core=pb_core,
41+
show_values=True,
42+
out_dir=os.path.expanduser("~/Documents/pb_output_dir"),
43+
filename='final_diagram',
44+
dpi='140')
45+
46+
@app.command()
47+
def execute(duration: float, pblang_path: Annotated[str, typer.Argument(help="Path to the pblang file to validate")]):
48+
ast_model: Model = generatePythonModel(pblang_path)
49+
pb_composite, _0, _1 = performConversion(ast_model)
50+
51+
pb_composite.run(duration)
2352

2453
@app.command()
25-
def execute(pblang_path: Annotated[str, typer.Argument(help="Path to the pblang file to validate")]):
26-
generatePythonModel(pblang_path)
54+
def playground():
55+
pass
2756

2857
def generatePythonModel(pblang_path: os.PathLike[str]) -> Model:
29-
absolute_path: str = os.path.abspath(pblang_path)
58+
absolute_path: str = validate_pb_absolute_path(os.path.abspath(pblang_path))
59+
60+
return dsl_adapter.generateModelAst(pblang_path)
61+
62+
def validate_pb_absolute_path(absolute_path: str) -> str:
3063
if not os.path.exists(absolute_path):
3164
sys.stderr.write(f"Error finding pblang file ({absolute_path}):: no file with that name exists.\n")
3265
exit(1)
@@ -36,11 +69,17 @@ def generatePythonModel(pblang_path: os.PathLike[str]) -> Model:
3669
if not absolute_path.endswith(".pblang"):
3770
sys.stderr.write(f"Error finding pblang file ({absolute_path}):: file is labeled with an unexpected extension.\n")
3871
exit(1)
72+
return absolute_path
3973

40-
return dsl_adapter.generateModelAst(pblang_path)
74+
def performConversion(ast_model: Model) -> tuple[Composite, dict, ProcessTypes]:
75+
assembler = Vivarium()
76+
register_spatio_flux_library(assembler)
77+
register_toy_library(assembler)
78+
register_types(assembler, collect_types(ast_model))
79+
register_units(assembler, collect_units(ast_model))
80+
process_composite(ast_model, assembler)
4181

42-
def performConversion(ast_model: Model) -> tuple[str, ProcessTypes]:
43-
pass
82+
return assembler.composite, assembler.make_document(), assembler.core
4483

4584
if __name__ == "__main__":
4685
app()

0 commit comments

Comments
 (0)