├── srnn.nir ├── img ├── fig3.png └── srnn.png ├── .gitignore ├── pyvenv.cfg ├── nirviz ├── __init__.py ├── style.yml ├── __main__.py └── nirviz.py ├── .github └── workflows │ └── pypi.yml ├── example.py ├── pyproject.toml ├── LICENSE ├── README.md └── example.ipynb /srnn.nir: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-neuromorphic/nirviz/main/srnn.nir -------------------------------------------------------------------------------- /img/fig3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-neuromorphic/nirviz/main/img/fig3.png -------------------------------------------------------------------------------- /img/srnn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-neuromorphic/nirviz/main/img/srnn.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /__pycache__/ 2 | /dist/ 3 | /nirviz.egg-info/ 4 | /.ipynb_checkpoints/ 5 | /build/ 6 | */__pycache__ 7 | -------------------------------------------------------------------------------- /pyvenv.cfg: -------------------------------------------------------------------------------- 1 | home = /usr/bin 2 | include-system-site-packages = false 3 | version = 3.12.3 4 | executable = /usr/bin/python3.12 5 | command = /usr/bin/python3 -m venv /home/mrontio/uni/phd/src/nir-viz 6 | -------------------------------------------------------------------------------- /nirviz/__init__.py: -------------------------------------------------------------------------------- 1 | from importlib.metadata import version as metadata_version, PackageNotFoundError 2 | 3 | # Exposing imports 4 | from .nirviz import visualize 5 | 6 | try: 7 | # For pyproject.toml dynamic versioning 8 | __version__ = version = metadata_version("nirviz") 9 | del metadata_version 10 | except PackageNotFoundError: 11 | print('nirviz: package not found') 12 | pass 13 | -------------------------------------------------------------------------------- /.github/workflows/pypi.yml: -------------------------------------------------------------------------------- 1 | on: 2 | release: 3 | types: [published] 4 | 5 | jobs: 6 | pypi-publish: 7 | name: Upload release to PyPI 8 | runs-on: ubuntu-latest 9 | environment: 10 | name: pypi 11 | url: https://pypi.org/p/nirviz 12 | permissions: 13 | id-token: write # IMPORTANT: this permission is mandatory for trusted publishing 14 | steps: 15 | - name: Checkout repository 16 | uses: actions/checkout@v2 17 | - name: Build Python package 18 | run: pip install build && python -m build 19 | - name: Publish package distributions to PyPI 20 | uses: pypa/gh-action-pypi-publish@release/v1 -------------------------------------------------------------------------------- /example.py: -------------------------------------------------------------------------------- 1 | import nir 2 | import nirviz 3 | import numpy as np 4 | 5 | a = np.random.randn(2) 6 | 7 | cuba_params = {'type': 'CubaLIF', 'tau_mem': a, 'tau_syn': a, 'r': a, 'v_leak': a, 'v_threshold': a} 8 | affine_params = {'type': 'Affine', 'weight': np.zeros((2,2)), 'bias': False} 9 | 10 | ir = nir.NIRGraph( 11 | nodes={ 12 | "input": nir.Input(input_type=np.array([2])), 13 | "affine1": nir.Affine.from_dict(affine_params), 14 | "cu1": nir.CubaLIF.from_dict(cuba_params), 15 | "affine_rec": nir.Affine.from_dict(affine_params), 16 | "affine2": nir.Affine.from_dict(affine_params), 17 | "cu2": nir.CubaLIF.from_dict(cuba_params), 18 | "output": nir.Output(output_type=np.array([2])) 19 | }, 20 | edges=[("input", "affine1"), ("affine1", "cu1"), ("affine_rec", "cu1"), ("cu1", "affine_rec"), ("cu1", "affine2"), ("affine2", "cu2"), ("cu2", "output")]) 21 | 22 | 23 | 24 | viz = nirviz.visualize(ir, draw_direction="left-right").to_image() 25 | viz.save("./img/srnn.png") 26 | viz.show() 27 | -------------------------------------------------------------------------------- /nirviz/style.yml: -------------------------------------------------------------------------------- 1 | meta-categories: 2 | orientation: "horizontal" # horizontal or vertical 3 | 4 | node-categories: 5 | input-output: 6 | patterns: ["Input", "Output"] 7 | attributes: 8 | color: "black" 9 | style: "dashed" 10 | shape: "box" 11 | 12 | connection-full: 13 | patterns: ["Affine", "Linear"] 14 | attributes: 15 | color: "#71c8b0" 16 | style: "filled" 17 | shape: "box" 18 | 19 | connection-conv: 20 | patterns: ["Conv1d", "Conv2d"] 21 | attributes: 22 | color: "#ffc655" 23 | style: "filled" 24 | shape: "box" 25 | 26 | transform: 27 | patterns: ["Flatten"] 28 | attributes: 29 | color: "#e4b9dd" 30 | style: "filled" 31 | shape: "box" 32 | 33 | pool: 34 | patterns: ["AvgPool1d", "AvgPool2d", "SumPool2d"] 35 | attributes: 36 | color: "#4a9bff" 37 | style: "filled" 38 | shape: "box" 39 | 40 | computation: 41 | patterns: ["CubaLI", "CubaLIF", "I", "IF", "LI", "LIF"] 42 | attributes: 43 | color: "#a0d5f1" 44 | style: "filled" 45 | shape: "box" 46 | 47 | defaults: 48 | node: 49 | attributes: 50 | color: "black" 51 | style: "dashed" 52 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["setuptools>=42", "setuptools_scm"] 3 | build-backend = "setuptools.build_meta" 4 | 5 | [project] 6 | name = "nirviz" 7 | dynamic = ["version"] 8 | description = "Visualisation tool for the Neuromorphic Intermediate Representation" 9 | license-files = ["LICENSE"] 10 | license = "BSD-3-Clause" 11 | readme = "README.md" 12 | authors = [ 13 | { name = "Jens Egholm Pedersen", email = "jens@jepedersen.dk" }, 14 | { name = "Michail Rontionov", email = "mrontionov@mront.io" } 15 | ] 16 | classifiers = [ 17 | "Development Status :: 1 - Planning", 18 | "Intended Audience :: Developers", 19 | "Intended Audience :: Science/Research", 20 | "Programming Language :: Python :: 3", 21 | "Topic :: Scientific/Engineering :: Artificial Intelligence", 22 | "Topic :: Scientific/Engineering :: Information Analysis", 23 | "Topic :: Scientific/Engineering :: Mathematics", 24 | "Topic :: Scientific/Engineering :: Physics", 25 | "Topic :: Software Development :: Libraries :: Python Modules", 26 | ] 27 | dependencies = ["nir", "graphviz", "cairosvg", "pyyaml"] 28 | requires-python = ">=3.9" 29 | 30 | [project.urls] 31 | homepage = "https://github.com/open-neuromorphic/nirviz" 32 | 33 | [tool.setuptools] 34 | packages = ["nirviz"] 35 | 36 | [tool.setuptools.package-data] 37 | nirviz = ["style.yml"] 38 | 39 | [tool.setuptools_scm] 40 | version_scheme = "only-version" 41 | local_scheme = "no-local-version" 42 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2025, open-neuromorphic/nirviz 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /nirviz/__main__.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import sys 3 | 4 | import nirviz 5 | 6 | if __name__ == "__main__": 7 | parser = argparse.ArgumentParser(description="CLI tool for visualizing NIR graphs.") 8 | parser.add_argument("file", type=argparse.FileType('r'), help="The NIR graph file to read from.") 9 | 10 | parser.add_argument("output", type=str, default="stdout", nargs='?', help="The output file to write the graph to. Defaults to stdout.") 11 | parser.add_argument("--orientation", choices=["horizontal", "vertical"], default="horizontal", help="Set orientation to 'horizontal' or 'vertical' (default: horizontal).") 12 | parser.add_argument("--yaml", type=str, default=None, help="Style file defined in yaml. Defaults to the bundled style file.") 13 | 14 | args = parser.parse_args() 15 | 16 | nir_file = args.file.name 17 | yaml_file = args.yaml 18 | orientation = args.orientation 19 | # Load the NIR graph 20 | if args.output == "stdout": 21 | graph = nirviz.visualize(nir_file, style_file=yaml_file, orientation=orientation) 22 | graph_svg = str(graph) 23 | sys.stdout.write(graph_svg) 24 | elif args.output.endswith(".svg"): 25 | graph = nirviz.visualize(nir_file, style_file=yaml_file, orientation=orientation) 26 | graph_svg = str(graph) 27 | with open(args.output, "w") as f: 28 | f.write(graph_svg) 29 | elif args.output.endswith(".png"): 30 | graph = nirviz.visualize(nir_file, style_file=yaml_file, orientation=orientation) 31 | graph_image = graph.to_image() 32 | graph_image.save(args.output) 33 | 34 | else: 35 | raise ValueError("Output file must be either .svg or .png format.") 36 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Neuromorphic Intermediate Representation Visualisation Tool 2 | 3 | Turn your NIR definitions into a nice graph, the original publication serving as a template. 4 | 5 | Customise your node colour preferences in [style.yml](nirviz/style.yml), and quickly generate graphs from your neuromorphic networks. 6 | 7 | This work is in progress. 8 | 9 | ## Running Example (Jupyter Notebook) 10 | By running the following code (from a notebook), 11 | ```python 12 | import nir 13 | import nirviz 14 | import numpy as np 15 | 16 | 17 | a = np.random.randn(2) 18 | ir = nir.NIRGraph( 19 | nodes={ 20 | "input": nir.Input(input_type=np.array([2])), 21 | "affine1": nir.Affine(weight=np.zeros((2,2)), bias=False), 22 | "cu1": nir.CubaLIF(tau_mem=a, tau_syn=a, r=a, v_leak=a, v_threshold=a, v_reset=a), 23 | "affine_rec": nir.Affine(weight=np.zeros((2,2)), bias=False), 24 | "affine2": nir.Affine(weight=np.zeros((2,2)), bias=False), 25 | "cu2": nir.CubaLIF(tau_mem=a, tau_syn=a, r=a, v_leak=a, v_threshold=a, v_reset=a), 26 | "output": nir.Output(output_type=np.array([2])) 27 | }, 28 | edges=[("input", "affine1"), ("affine1", "cu1"), ("affine_rec", "cu1"), ("cu1", "affine_rec"), ("cu1", "affine2"), ("affine2", "cu2"), ("cu2", "output")]) 29 | 30 | viz = nirviz.visualize(ir) 31 | viz.show() 32 | ``` 33 | 34 | You would get the following visualisation 35 | 36 | 37 | nirviz output 38 | 39 | 40 | Similar to Figure 3 of the publication. 41 | 42 | 43 | Figure 3 of NIR paper for comparison to output 44 | 45 | 46 | ## Running example (CLI) 47 | To convert a saved NIR graph (e.g. srnn.nir) to a PNG or SVG, you can use one of the following commands: 48 | ```bash 49 | python -m nirviz srnn.nir # SVG -> stdout 50 | python -m nirviz srnn.nir img/srnn.png # PNG -> file 51 | python -m nirviz srnn.nir img/srnn.svg # SVG -> file 52 | ``` 53 | 54 | ## Customising the style 55 | You can customise the style you see via the *style file*. 56 | ### Style file location 57 | The style file is defined in YAML. You can find the default location by running: 58 | ```python 59 | import nirviz 60 | print(f"nirviz style file location: {nirviz.visualize.default_style_file()}") 61 | ``` 62 | 63 | or by passing your own `style.yml`: 64 | ```python 65 | import nirviz 66 | viz = nirviz.visualize(nir_graph, style_file="style.yml") 67 | viz.show() 68 | ``` 69 | ```bash 70 | python -m nirviz --yaml './style.yml' srnn.nir 71 | ``` 72 | 73 | ### Style file format 74 | The format currently only supports setting node attributes. The node attributes correspond to [Graphviz node attributes](https://graphviz.org/docs/nodes/). An example file would contain: 75 | 76 | ```yaml 77 | node-categories: 78 | category-name: # User defined 79 | patterns: ["Affine", "IF"] 80 | attributes: 81 | # Corresponds to node attributes of graphviz 82 | # https://graphviz.org/docs/nodes/ 83 | color: "red" 84 | style: "filled" 85 | shape: "box" 86 | ``` 87 | 88 | Which would paint all "Affine" and "IF" NIR nodes red. 89 | -------------------------------------------------------------------------------- /nirviz/nirviz.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | import yaml 3 | import re 4 | import graphviz 5 | import cairosvg 6 | import nir 7 | import typing 8 | import importlib.util 9 | import importlib.resources 10 | import pathlib 11 | import PIL 12 | import io 13 | 14 | 15 | @dataclass 16 | class visualize: 17 | nir_graph: typing.Union['nir.NIRGraph', str, pathlib.Path] 18 | style_file: typing.Optional[pathlib.Path] = None 19 | orientation: typing.Optional[str] = None 20 | DEFAULT_STYLE_FILE = importlib.resources.files(__package__) / "style.yml" 21 | 22 | @classmethod 23 | def default_style_file(cls): 24 | return cls.DEFAULT_STYLE_FILE 25 | 26 | def __post_init__(self): 27 | if isinstance(self.nir_graph, (str, pathlib.Path)): 28 | self.nir_graph = nir.read(self.nir_graph) 29 | 30 | if self.style_file is not None and not isinstance(self.style_file, pathlib.Path): 31 | # Translate from string 32 | self.style_file = pathlib.Path(self.style_file) 33 | elif self.style_file is None: 34 | # Insert default 35 | self.style_file = self.DEFAULT_STYLE_FILE 36 | 37 | self.style_dict = self.__load_style_file() 38 | self.viz_graph = self.__construct_graph() 39 | 40 | def __load_style_file(self) -> typing.Dict[str, typing.Dict[str, str]]: 41 | assert self.style_file is not None 42 | with open(self.style_file, 'r') as f: 43 | config = yaml.safe_load(f) 44 | return config 45 | 46 | def __pick_style(self, name: str) -> typing.Dict[str, str]: 47 | categories = self.style_dict['node-categories'] 48 | for cat_id in categories: 49 | cat = categories[cat_id] 50 | if name in cat['patterns']: 51 | return cat['attributes'] 52 | 53 | return self.style_dict['defaults']['node']['attributes'] 54 | 55 | def __get_rankdir(self) -> str: 56 | if self.orientation is None: 57 | self.orientation = self.style_dict["meta-categories"]["draw-direction"] 58 | source = f"{self.style_file} [meta-categories/draw-direction]" 59 | else: 60 | source = "argument \"orientation\"" 61 | 62 | rankdirMap = {'vertical': "TB", 63 | 'horizontal': "LR"} 64 | try: 65 | return rankdirMap[self.orientation] 66 | except KeyError as x: 67 | raise ValueError(f'invalid value \"{x.args[0]}\" in {source}: must be either {list(rankdirMap.keys())}') 68 | 69 | 70 | def __construct_graph(self) -> graphviz.Digraph: 71 | viz_graph = graphviz.Digraph(format="svg", 72 | graph_attr={'rankdir': self.__get_rankdir()}) 73 | # Generate nodes 74 | for node_id in self.nir_graph.nodes: 75 | name = type(self.nir_graph.nodes[node_id]).__name__ 76 | style = self.__pick_style(name) 77 | viz_graph.node(node_id, label=name, **style) 78 | 79 | # Generate edges 80 | for src_id, tgt_id in self.nir_graph.edges: 81 | viz_graph.edge(src_id, tgt_id) 82 | 83 | return viz_graph 84 | 85 | def show(self) -> None: 86 | if importlib.util.find_spec("IPython"): 87 | import IPython 88 | 89 | svg_output = self.viz_graph.pipe(format="svg") 90 | image = IPython.display.SVG(svg_output) 91 | IPython.display.display(image) 92 | else: 93 | print("error: cannot display graph: no IPython environment detected.") 94 | 95 | def to_image(self) -> PIL.Image.Image: 96 | svg_output = self.viz_graph.pipe(format="svg") 97 | png_bytes = cairosvg.svg2png(bytestring=svg_output) 98 | return PIL.Image.open(io.BytesIO(png_bytes)) 99 | 100 | def __repr__(self) -> str: 101 | return self.viz_graph.pipe(format="svg", encoding="utf-8") 102 | -------------------------------------------------------------------------------- /example.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": null, 6 | "id": "e6489ed2", 7 | "metadata": { 8 | "collapsed": false, 9 | "jupyter": { 10 | "outputs_hidden": false 11 | } 12 | }, 13 | "outputs": [], 14 | "source": [ 15 | "import nir\n", 16 | "import nirviz\n", 17 | "import importlib\n", 18 | "importlib.reload(nirviz)\n", 19 | "import numpy as np\n", 20 | "\n", 21 | "print(f\"nirviz style file location: {nirviz.visualize.default_style_file()}\")" 22 | ] 23 | }, 24 | { 25 | "cell_type": "code", 26 | "execution_count": null, 27 | "id": "f20f2f04-b905-4398-8134-4b8c529a4097", 28 | "metadata": { 29 | "collapsed": false 30 | }, 31 | "outputs": [], 32 | "source": [ 33 | "w = np.random.randn(2, 2)\n", 34 | "graph = nir.NIRGraph.from_list(nir.Linear(weight=w), nir.Linear(weight=w))\n", 35 | "viz = nirviz.visualize(graph)\n", 36 | "viz.show()" 37 | ] 38 | }, 39 | { 40 | "cell_type": "code", 41 | "execution_count": null, 42 | "id": "dc7287c0-888d-4d1a-a149-a0620866fd1b", 43 | "metadata": { 44 | "collapsed": false, 45 | "jupyter": { 46 | "outputs_hidden": false 47 | } 48 | }, 49 | "outputs": [], 50 | "source": [ 51 | "import snntorch as snn\n", 52 | "import torch\n", 53 | "\n", 54 | "importlib.reload(snn)\n", 55 | "importlib.reload(nirviz)\n", 56 | "import numpy as np\n", 57 | "\n", 58 | "lif1 = snn.Leaky(beta=0.9, init_hidden=True)\n", 59 | "lif2 = snn.Leaky(beta=0.9, init_hidden=True, output=True)\n", 60 | "\n", 61 | "# Create a network\n", 62 | "snntorch_network = torch.nn.Sequential(\n", 63 | " torch.nn.Flatten(),\n", 64 | " torch.nn.Linear(784, 500),\n", 65 | " lif1,\n", 66 | " torch.nn.Linear(500, 10),\n", 67 | " lif2\n", 68 | ")\n", 69 | "\n", 70 | "sample_data = torch.randn(1, 784)\n", 71 | "\n", 72 | "# Export to nir\n", 73 | "nir_model = snn.export_to_nir(snntorch_network, sample_data)\n", 74 | "\n", 75 | "viz = nirviz.visualize(nir_model)\n", 76 | "viz.show()" 77 | ] 78 | }, 79 | { 80 | "cell_type": "code", 81 | "execution_count": null, 82 | "id": "bef33566-65eb-4c5f-b227-c65f5aec2224", 83 | "metadata": { 84 | "collapsed": false, 85 | "jupyter": { 86 | "outputs_hidden": false 87 | } 88 | }, 89 | "outputs": [], 90 | "source": [ 91 | "a = np.random.randn(2)\n", 92 | "ir = nir.NIRGraph(\n", 93 | " nodes={\n", 94 | " \"input\": nir.Input(input_type=np.array([2])),\n", 95 | " \"affine1\": nir.Affine(weight=np.zeros((2,2)), bias=False),\n", 96 | " \"cu1\": nir.CubaLIF(tau_mem=a, tau_syn=a, r=a, v_leak=a, v_threshold=a, v_reset=a),\n", 97 | " \"affine_rec\": nir.Affine(weight=np.zeros((2,2)), bias=False),\n", 98 | " \"affine2\": nir.Affine(weight=np.zeros((2,2)), bias=False),\n", 99 | " \"cu2\": nir.CubaLIF(tau_mem=a, tau_syn=a, r=a, v_leak=a, v_threshold=a, v_reset=a),\n", 100 | " \"output\": nir.Output(output_type=np.array([2]))\n", 101 | " },\n", 102 | " edges=[(\"input\", \"affine1\"), (\"affine1\", \"cu1\"), (\"affine_rec\", \"cu1\"), (\"cu1\", \"affine_rec\"), (\"cu1\", \"affine2\"), (\"affine2\", \"cu2\"), (\"cu2\", \"output\")])\n", 103 | "\n", 104 | "nir.write(\"./srnn.nir\", ir)\n", 105 | "\n", 106 | "viz = nirviz.visualize(ir)\n", 107 | "viz.show()\n", 108 | "viz.to_image().save(\"./img/srnn.png\")" 109 | ] 110 | }, 111 | { 112 | "cell_type": "code", 113 | "execution_count": null, 114 | "id": "771a1f1e-f538-4eb1-992e-a05b87f6e5d5", 115 | "metadata": { 116 | "collapsed": false 117 | }, 118 | "outputs": [], 119 | "source": [ 120 | "import nir\n", 121 | "import nirviz\n", 122 | "import numpy as np\n", 123 | "\n", 124 | "a = np.random.randn(2)\n", 125 | "\n", 126 | "cuba_params = {'type': 'CubaLIF', 'tau_mem': a, 'tau_syn': a, 'r': a, 'v_leak': a, 'v_threshold': a}\n", 127 | "affine_params = {'type': 'Affine', 'weight': np.zeros((2,2)), 'bias': False}\n", 128 | "\n", 129 | "ir = nir.NIRGraph(\n", 130 | " nodes={\n", 131 | " \"input\": nir.Input(input_type=np.array([2])),\n", 132 | " \"affine1\": nir.Affine.from_dict(affine_params),\n", 133 | " \"cu1\": nir.CubaLIF.from_dict(cuba_params),\n", 134 | " \"affine_rec\": nir.Affine.from_dict(affine_params),\n", 135 | " \"affine2\": nir.Affine.from_dict(affine_params),\n", 136 | " \"cu2\": nir.CubaLIF.from_dict(cuba_params),\n", 137 | " \"output\": nir.Output(output_type=np.array([2]))\n", 138 | " },\n", 139 | " edges=[(\"input\", \"affine1\"), (\"affine1\", \"cu1\"), (\"affine_rec\", \"cu1\"), (\"cu1\", \"affine_rec\"), (\"cu1\", \"affine2\"), (\"affine2\", \"cu2\"), (\"cu2\", \"output\")])\n", 140 | "\n", 141 | "\n", 142 | "\n", 143 | "viz = nirviz.visualize(ir)\n", 144 | "viz.show()\n" 145 | ] 146 | } 147 | ], 148 | "metadata": { 149 | "kernelspec": { 150 | "argv": [ 151 | "python", 152 | "-m", 153 | "ipykernel_launcher", 154 | "-f", 155 | "{connection_file}" 156 | ], 157 | "display_name": "Python 3 (ipykernel)", 158 | "env": null, 159 | "interrupt_mode": "signal", 160 | "language": "python", 161 | "metadata": { 162 | "debugger": true 163 | }, 164 | "name": "python3" 165 | }, 166 | "language_info": { 167 | "codemirror_mode": { 168 | "name": "ipython", 169 | "version": 3 170 | }, 171 | "file_extension": ".py", 172 | "mimetype": "text/x-python", 173 | "name": "python", 174 | "nbconvert_exporter": "python", 175 | "pygments_lexer": "ipython3", 176 | "version": "3.12.3" 177 | }, 178 | "name": "example.ipynb" 179 | }, 180 | "nbformat": 4, 181 | "nbformat_minor": 5 182 | } 183 | --------------------------------------------------------------------------------