From e4f90f4af67d37ef0ae1dcf1fd1688d88ae103ba Mon Sep 17 00:00:00 2001 From: Eran Date: Thu, 29 Feb 2024 09:52:06 -0500 Subject: [PATCH] connect_all is working --- builder/builder_api.py | 43 ++++--- builder/dict_utils.py | 21 +++ notebooks/demo.ipynb | 286 +++++++++++++++++++++++++++++++++++++---- 3 files changed, 312 insertions(+), 38 deletions(-) create mode 100644 builder/dict_utils.py diff --git a/builder/builder_api.py b/builder/builder_api.py index 1331550..9817817 100644 --- a/builder/builder_api.py +++ b/builder/builder_api.py @@ -151,17 +151,22 @@ def connect(self, port=None, target=None): if port in schema['_outputs']: value['outputs'][port] = target - def connect_all(self, append_to_store_name=''): + def connect_all(self, append_to_store_name='_store'): + # Check if the current node is an edge and perform connections if it is value = self.value() - schema = self.schema() - assert self.builder.core.check('edge', value), "connect_all only works on edges" - - for port, port_schema in schema['_inputs'].items(): - if port not in value['inputs']: - value['inputs'][port] = [port + append_to_store_name] - for port, port_schema in schema['_outputs'].items(): - if port not in value['outputs']: - value['outputs'][port] = [port + append_to_store_name] + if self.builder.core.check('edge', value): + schema = self.schema() + for port in schema.get('_inputs', {}).keys(): + if port not in value.get('inputs', {}): + value['inputs'][port] = [port + append_to_store_name] + for port in schema.get('_outputs', {}).keys(): + if port not in value.get('outputs', {}): + value['outputs'][port] = [port + append_to_store_name] + # Optionally, update the current node value here if necessary + + # Recursively apply connect_all to all child nodes + for child in self.branches.values(): + child.connect_all(append_to_store_name=append_to_store_name) def interface(self, print_ports=False): value = self.value() @@ -212,6 +217,9 @@ def list_processes(self): def complete(self): self.schema, self.tree = self.core.complete(self.schema, self.tree) + def connect_all(self, append_to_store_name='_store'): + self.node.connect_all(append_to_store_name=append_to_store_name) + def visualize(self, filename=None, out_dir=None, **kwargs): return plot_bigraph( state=self.tree, @@ -291,10 +299,10 @@ def test_builder(): '_type': 'map[float]', 'A gene': 2.0, 'B gene': 1.0}, - 'RNA_store': { + 'mRNA_store': { '_type': 'map[float]', - 'A rna': 0.0, - 'B rna': 0.0}, + 'A mRNA': 0.0, + 'B mRNA': 0.0}, } builder = Builder(core=core, tree=initial_tree) @@ -331,6 +339,10 @@ def test_builder(): # inputs={'port_id': ['store']} # we should be able to set the wires directly like this ) + ## print the ports + print(f"EVENT PROCESS PORTS: {pf(builder['event_process'].interface())}") + print(f"INTERVAL PROCESS PORTS: {pf(builder['interval_process'].interface())}") + # make bigraph-viz diagram before connect builder.visualize(filename='builder_test1', show_values=True, @@ -342,8 +354,9 @@ def test_builder(): # builder['interval_process'].connect(port='DNA', target=['DNA_store']) # builder['interval_process'].connect(port='mRNA', target=['mRNA_store']) builder['interval_process'].connect(port='interval', target=['event_process', 'interval']) # TODO -- viz needs to show interval in process - builder['interval_process'].connect_all(append_to_store_name='_store') - builder['event_process'].connect_all(append_to_store_name='_store') + # builder['interval_process'].connect_all(append_to_store_name='_store') + # builder['event_process'].connect_all(append_to_store_name='_store') + builder.connect_all(append_to_store_name='_store') # make bigraph-viz diagram after connect builder.visualize(filename='builder_test2', diff --git a/builder/dict_utils.py b/builder/dict_utils.py new file mode 100644 index 0000000..f083c29 --- /dev/null +++ b/builder/dict_utils.py @@ -0,0 +1,21 @@ + +def custom_pf(d, indent=0): + """Custom dictionary formatter to achieve specific indentation styles.""" + items = [] + for k, v in d.items(): + key_str = f"{repr(k)}: " + if isinstance(v, dict): + if v: # Check if the dictionary is not empty + value_str = custom_pf(v, indent + 3) + else: + value_str = "{}" + else: + value_str = repr(v) + items.append(f"{' ' * indent}{key_str}{value_str}") + + # final formatting + items_str = ','.join(items) + if indent > 0: + return f"{{\n{items_str}\n{' ' * (indent - 4)}}}" + else: + return f"{{\n{items_str}\n}}" diff --git a/notebooks/demo.ipynb b/notebooks/demo.ipynb index 5e84147..1423b3d 100644 --- a/notebooks/demo.ipynb +++ b/notebooks/demo.ipynb @@ -103,7 +103,7 @@ { "data": { "text/plain": [ - "['console-emitter', 'ram-emitter']" + "['ram-emitter', 'console-emitter']" ] }, "execution_count": 4, @@ -213,11 +213,11 @@ { "data": { "text/plain": [ - "['console-emitter',\n", - " 'toy',\n", + "['ram-emitter',\n", + " 'GillespieEvent',\n", " 'GillespieInterval',\n", - " 'ram-emitter',\n", - " 'GillespieEvent']" + " 'toy',\n", + " 'console-emitter']" ] }, "execution_count": 8, @@ -292,7 +292,7 @@ "\n" ], "text/plain": [ - "" + "" ] }, "execution_count": 10, @@ -319,14 +319,12 @@ "metadata": {}, "outputs": [ { - "ename": "AttributeError", - "evalue": "'BuilderNode' object has no attribute 'interface'", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)", - "Cell \u001b[0;32mIn[11], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mb\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mevent_process\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m]\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43minterface\u001b[49m(\u001b[38;5;28;01mTrue\u001b[39;00m)\n", - "\u001b[0;31mAttributeError\u001b[0m: 'BuilderNode' object has no attribute 'interface'" + "name": "stdout", + "output_type": "stream", + "text": [ + "{ '_inputs': { 'DNA': {'A gene': 'float', 'B gene': 'float'},\n", + " 'mRNA': 'map[float]'},\n", + " '_outputs': {'mRNA': 'map[float]'}}\n" ] } ], @@ -344,10 +342,27 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 12, "id": "c9f462bb-5316-4724-aa8e-b3b71eb379b2", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "Builder({ 'event_process': { '_type': 'process',\n", + " 'address': 'local:GillespieEvent',\n", + " 'config': {'kdeg': 1.0, 'ktsc': 5.0},\n", + " 'inputs': {'DNA': ['DNA_store'], 'mRNA': ['mRNA_store']},\n", + " 'instance': ,\n", + " 'interval': 1.0,\n", + " 'outputs': {'mRNA': ['mRNA_store']}}})" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "b['event_process'].connect(port='mRNA', target=['mRNA_store'])\n", "b['event_process'].connect(port='DNA', target=['DNA_store'])\n", @@ -356,17 +371,115 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 13, "id": "79809baf-1d87-475a-b85f-3729f4716cb4", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "bigraph\n", + "\n", + "\n", + "\n", + "('event_process', 'interval')\n", + "\n", + "interval\n", + "\n", + "\n", + "\n", + "('mRNA_store',)\n", + "\n", + "mRNA_store\n", + "\n", + "\n", + "\n", + "('event_process',)\n", + "\n", + "event_process\n", + "\n", + "\n", + "\n", + "('mRNA_store',)->('event_process',)\n", + "\n", + "\n", + "mRNA\n", + "\n", + "\n", + "\n", + "('mRNA_store',)->('event_process',)\n", + "\n", + "\n", + "mRNA\n", + "\n", + "\n", + "\n", + "('DNA_store',)\n", + "\n", + "DNA_store\n", + "\n", + "\n", + "\n", + "('DNA_store', 'A gene')\n", + "\n", + "A gene\n", + "\n", + "\n", + "\n", + "('DNA_store',)->('DNA_store', 'A gene')\n", + "\n", + "\n", + "\n", + "\n", + "('DNA_store', 'B gene')\n", + "\n", + "B gene\n", + "\n", + "\n", + "\n", + "('DNA_store',)->('DNA_store', 'B gene')\n", + "\n", + "\n", + "\n", + "\n", + "('DNA_store',)->('event_process',)\n", + "\n", + "\n", + "DNA\n", + "\n", + "\n", + "\n", + "('event_process',)->('event_process', 'interval')\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "b.visualize()" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 14, "id": "f02c15797bdb73b8", "metadata": { "ExecuteTime": { @@ -387,7 +500,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 15, "id": "aeb344bcd6a120ae", "metadata": { "ExecuteTime": { @@ -398,17 +511,144 @@ "outputs_hidden": false } }, - "outputs": [], + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "bigraph\n", + "\n", + "\n", + "\n", + "('event_process', 'interval')\n", + "\n", + "interval\n", + "\n", + "\n", + "\n", + "('interval_process', 'interval')\n", + "\n", + "interval\n", + "\n", + "\n", + "\n", + "('mRNA_store',)\n", + "\n", + "mRNA_store\n", + "\n", + "\n", + "\n", + "('event_process',)\n", + "\n", + "event_process\n", + "\n", + "\n", + "\n", + "('mRNA_store',)->('event_process',)\n", + "\n", + "\n", + "mRNA\n", + "\n", + "\n", + "\n", + "('mRNA_store',)->('event_process',)\n", + "\n", + "\n", + "mRNA\n", + "\n", + "\n", + "\n", + "('DNA_store',)\n", + "\n", + "DNA_store\n", + "\n", + "\n", + "\n", + "('DNA_store', 'A gene')\n", + "\n", + "A gene\n", + "\n", + "\n", + "\n", + "('DNA_store',)->('DNA_store', 'A gene')\n", + "\n", + "\n", + "\n", + "\n", + "('DNA_store', 'B gene')\n", + "\n", + "B gene\n", + "\n", + "\n", + "\n", + "('DNA_store',)->('DNA_store', 'B gene')\n", + "\n", + "\n", + "\n", + "\n", + "('DNA_store',)->('event_process',)\n", + "\n", + "\n", + "DNA\n", + "\n", + "\n", + "\n", + "('event_process',)->('event_process', 'interval')\n", + "\n", + "\n", + "\n", + "\n", + "('interval_process',)\n", + "\n", + "interval_process\n", + "\n", + "\n", + "\n", + "('interval_process',)->('interval_process', 'interval')\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "b.visualize()" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 16, "id": "a5a1f48a-41aa-4768-b931-ad268495d836", "metadata": {}, - "outputs": [], + "outputs": [ + { + "ename": "AttributeError", + "evalue": "'Builder' object has no attribute 'connect_all'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[16], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mb\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mconnect_all\u001b[49m()\n", + "\u001b[0;31mAttributeError\u001b[0m: 'Builder' object has no attribute 'connect_all'" + ] + } + ], "source": [ "b.connect_all()" ]