Skip to content

Commit

Permalink
get started on pydantic integration
Browse files Browse the repository at this point in the history
  • Loading branch information
eagmon committed Mar 11, 2024
1 parent a09ff2b commit 50ec92a
Show file tree
Hide file tree
Showing 2 changed files with 785 additions and 376 deletions.
94 changes: 89 additions & 5 deletions builder/builder_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from bigraph_schema.protocols import local_lookup_module
from process_bigraph import Process, Step, Composite, ProcessTypes
from bigraph_viz.diagram import plot_bigraph
from pydantic import create_model


pretty = pprint.PrettyPrinter(indent=2)
Expand Down Expand Up @@ -188,6 +189,41 @@ def interface(self, print_ports=False):
else:
print(pf(process_ports))

def emit(self, key=None, port=None):
if key is None:
key = port
value = self.value()
schema = self.schema()
if self.builder.core.check('edge', value):
inputs = value.get('inputs', {})
outputs = value.get('outputs', {})
inputs_schema = schema.get('_inputs', {})
outputs_schema = schema.get('_outputs', {})

if not port:
# connect to all ports
for prt, val in inputs_schema.items():
self.builder.node['emitter', 'config', 'emit', prt] = val
for prt, val in outputs_schema.items():
self.builder.node['emitter', 'config', 'emit', prt] = val
elif port in inputs_schema:
# update the emitter config
self.builder.node['emitter', 'config', 'emit'].value().update({key: inputs_schema[port]})
self.builder.node['emitter', 'inputs', key] = list(self.path[:-1]) + list(inputs[port])
self.builder.node['emitter'].schema()['_inputs'].update({key: inputs_schema[port]})

elif port in outputs_schema:
self.builder.node['emitter', 'config', 'emit'].update({key: outputs_schema[port]})
self.builder.node['emitter', 'inputs', key] = list(self.path[:-1]) + list(outputs[port])
self.builder.node['emitter'].schema()['_inputs'].update({key: outputs_schema[port]})

else:
raise Exception(f"can not connect port {port}. available ports for this edge include {inputs_schema.keys()} {outputs_schema.keys()}")
else:
# emit the path
self.builder.node['emitter', 'config', 'emit', key] = schema
self.builder.node['emitter', 'inputs', key] = self.path


class Builder:

Expand All @@ -196,6 +232,7 @@ def __init__(
schema=None,
tree=None,
core=None,
emitter='ram-emitter',
file_path=None,
):
schema = schema or {}
Expand All @@ -209,6 +246,7 @@ def __init__(
self.core = core or ProcessTypes()
self.schema, self.tree = self.core.complete(schema, tree)
self.node = node_from_tree(self, self.schema, self.tree)
self.add_emitter(emitter=emitter)

def __repr__(self):
return f"Builder({pf(self.tree)})"
Expand All @@ -220,6 +258,18 @@ def __setitem__(self, keys, value):
self.node.__setitem__(keys, value)
self.complete()

def add_emitter(self, emitter='ram-emitter'):
"""
key is the node id for the emitter, at the top level
name is the emitter type
"""
# hardcode that emitter is called "emitter"
self.node['emitter'].add_process(
name=emitter,
config={'emit': {}},
inputs={},
)

def update(self, state):
self.node.update(state)

Expand Down Expand Up @@ -247,10 +297,10 @@ def visualize(self, filename=None, out_dir=None, **kwargs):
def generate(self):
composite = Composite({
'state': self.tree,
'composition': self.schema
},
'composition': self.schema},
core=self.core)

self.tree = composite.state
self.schema =composite.composition
return composite

def document(self):
Expand Down Expand Up @@ -378,6 +428,13 @@ def test_builder():
show_values=True,
show_types=True)

# we can turn on the emits through a port
# builder.add_emitter()
builder['interval_process'].emit(port='DNA')
builder['interval_process'].emit(port='mRNA')



# update state
update_state = {
'DNA_store': {
Expand All @@ -396,15 +453,42 @@ def test_builder():
composite = builder.generate()
composite.run(10)

results = composite.gather_results()

print(f"RESULTS: {results}")

# save document
builder.write(filename='builder_test_doc')

# load builder from document
builder2 = Builder(core=core, file_path='out/builder_test_doc.json')
builder.visualize(filename='builder_test4',
builder2.visualize(filename='builder_test4',
show_values=True,
show_types=True)


def test_pydantic():
from process_bigraph.experiments.minimal_gillespie import GillespieEvent, GillespieInterval, EXPORT #

core = ProcessTypes()
core.import_types(EXPORT) # TODO -- make this better

# make the builder
builder = Builder(core=core)

## register processes by name: what processes do we want and where do they come from
builder.register_process(
'GillespieEvent', GillespieEvent)
builder.register_process(
'GillespieInterval', GillespieEvent)

# get a pydantic model
model = builder.get_pydantic_model('GillespieEvent') # TODO -- make this
config = model(kdeg=1.0)
builder['event_process'].add_process(**config)



if __name__ == '__main__':
test_builder()
# test_builder()
test_pydantic()
Loading

0 comments on commit 50ec92a

Please sign in to comment.