Skip to content

Instantly share code, notes, and snippets.

@noklam
Created February 20, 2020 15:13
Show Gist options
  • Save noklam/ac4142501b0582a4c5facfbc246f8ac6 to your computer and use it in GitHub Desktop.
Save noklam/ac4142501b0582a4c5facfbc246f8ac6 to your computer and use it in GitHub Desktop.
/00_core.ipynb
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "#default_exp core",
"execution_count": 1,
"outputs": []
},
{
"metadata": {},
"cell_type": "markdown",
"source": "# fastdot.core\n\n> Drawing graphs with graphviz."
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "#export\nfrom fastcore.all import *\nimport pydot\nfrom matplotlib.colors import rgb2hex, hex2color",
"execution_count": 14,
"outputs": []
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "#export\n_all_ = ['pydot']",
"execution_count": 15,
"outputs": []
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "#hide\nfrom nbdev.showdoc import *",
"execution_count": 16,
"outputs": []
},
{
"metadata": {},
"cell_type": "markdown",
"source": "## Nodes"
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "#export\ndef Dot(defaults=None, rankdir='LR', directed=True, compound=True, **kwargs):\n \"Create a `pydot.Dot` graph with fastai/fastdot style defaults\"\n return pydot.Dot(rankdir=rankdir, directed=directed, compound=compound, **kwargs)",
"execution_count": 17,
"outputs": []
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "#export\ndef uniq_name(o): return 'n'+(uuid4().hex)\n\ndef quote(x, q='\"'):\n 'Surround `x` with `\"`'\n return f'\"{x}\"'\n\n@patch\ndef _repr_svg_(self:pydot.Dot):\n return self.create_svg().decode('utf-8')",
"execution_count": 18,
"outputs": []
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "#export\ngraph_objects = {}\nobject_names = {}",
"execution_count": 19,
"outputs": []
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "#export\ndef add_mapping(graph_item, obj):\n graph_objects[graph_item.get_name()] = graph_item\n object_names[id(obj)] = graph_item.get_name()\n return graph_item",
"execution_count": 20,
"outputs": []
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "#export\ndef _pydot_create(f, obj, **kwargs):\n for k,v in kwargs.items():\n if callable(v): v = kwargs[k] = v(obj)\n if k not in ('name','graph_name'): kwargs[k] = quote(v)\n return add_mapping(f(**kwargs), obj)",
"execution_count": 21,
"outputs": []
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "#export\nnode_defaults = dict(label=str, tooltip=str, name=uniq_name, shape='box', style='rounded, filled', fillcolor='white')",
"execution_count": 22,
"outputs": []
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "#export\ndef Node(obj, **kwargs):\n \"Create a `pydot.Node` with a unique name\"\n if not isinstance(obj,str) and isinstance(obj, Collection) and len(obj)==2:\n obj,kwargs['tooltip'] = obj\n kwargs = merge(node_defaults, kwargs)\n return _pydot_create(pydot.Node, obj, **kwargs)",
"execution_count": 23,
"outputs": []
},
{
"metadata": {},
"cell_type": "markdown",
"source": "`pydot` uses the same name-based approach to identifying graph items as `graphviz`. However we would rather use python objects. Therefore, we patch `pydot` to use unique names."
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "g = Dot()\na = Node('a')\ng.add_node(a)\ng ",
"execution_count": 31,
"outputs": [
{
"data": {
"image/svg+xml": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\r\n<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\r\n \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\r\n<!-- Generated by graphviz version 2.38.0 (20140413.2041)\r\n -->\r\n<!-- Title: G Pages: 1 -->\r\n<svg width=\"62pt\" height=\"44pt\"\r\n viewBox=\"0.00 0.00 62.00 44.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\r\n<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 40)\">\r\n<title>G</title>\r\n<polygon fill=\"white\" stroke=\"none\" points=\"-4,4 -4,-40 58,-40 58,4 -4,4\"/>\r\n<!-- n0110bb65118749d09015a10b13d08221 -->\r\n<g id=\"node1\" class=\"node\"><title>n0110bb65118749d09015a10b13d08221</title>\r\n<g id=\"a_node1\"><a xlink:title=\"a\">\r\n<path fill=\"white\" stroke=\"black\" d=\"M42,-36C42,-36 12,-36 12,-36 6,-36 0,-30 0,-24 0,-24 0,-12 0,-12 0,-6 6,-0 12,-0 12,-0 42,-0 42,-0 48,-0 54,-6 54,-12 54,-12 54,-24 54,-24 54,-30 48,-36 42,-36\"/>\r\n<text text-anchor=\"middle\" x=\"27\" y=\"-14.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">a</text>\r\n</a>\r\n</g>\r\n</g>\r\n</g>\r\n</svg>\r\n",
"text/plain": "<pydot.Dot at 0x1e500a54608>"
},
"execution_count": 31,
"metadata": {},
"output_type": "execute_result"
}
]
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "type(g)",
"execution_count": 32,
"outputs": [
{
"data": {
"text/plain": "pydot.Dot"
},
"execution_count": 32,
"metadata": {},
"output_type": "execute_result"
}
]
},
{
"metadata": {},
"cell_type": "markdown",
"source": "If a 2-tuple is passed to `add_node`, then the 2nd element becomes the tooltip. You can also pass any `kwargs` that are accepted by `graphviz`."
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "g = Dot()\ng.add_node(Node(['a', \"My tooltip\"], fillcolor='pink'))\ng",
"execution_count": 33,
"outputs": [
{
"data": {
"image/svg+xml": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\r\n<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\r\n \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\r\n<!-- Generated by graphviz version 2.38.0 (20140413.2041)\r\n -->\r\n<!-- Title: G Pages: 1 -->\r\n<svg width=\"62pt\" height=\"44pt\"\r\n viewBox=\"0.00 0.00 62.00 44.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\r\n<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 40)\">\r\n<title>G</title>\r\n<polygon fill=\"white\" stroke=\"none\" points=\"-4,4 -4,-40 58,-40 58,4 -4,4\"/>\r\n<!-- n92ae0971082c409fb3641ce0767e990b -->\r\n<g id=\"node1\" class=\"node\"><title>n92ae0971082c409fb3641ce0767e990b</title>\r\n<g id=\"a_node1\"><a xlink:title=\"My tooltip\">\r\n<path fill=\"pink\" stroke=\"black\" d=\"M42,-36C42,-36 12,-36 12,-36 6,-36 0,-30 0,-24 0,-24 0,-12 0,-12 0,-6 6,-0 12,-0 12,-0 42,-0 42,-0 48,-0 54,-6 54,-12 54,-12 54,-24 54,-24 54,-30 48,-36 42,-36\"/>\r\n<text text-anchor=\"middle\" x=\"27\" y=\"-14.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">a</text>\r\n</a>\r\n</g>\r\n</g>\r\n</g>\r\n</svg>\r\n",
"text/plain": "<pydot.Dot at 0x1e500a41fc8>"
},
"execution_count": 33,
"metadata": {},
"output_type": "execute_result"
}
]
},
{
"metadata": {},
"cell_type": "markdown",
"source": "Keyword args can also be arbitrary functions, which will called with the node's label."
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "g = Dot()\no = 'a'\ng.add_node(Node(o, fillcolor=lambda o:'pink'))\ng",
"execution_count": 34,
"outputs": [
{
"data": {
"image/svg+xml": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\r\n<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\r\n \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\r\n<!-- Generated by graphviz version 2.38.0 (20140413.2041)\r\n -->\r\n<!-- Title: G Pages: 1 -->\r\n<svg width=\"62pt\" height=\"44pt\"\r\n viewBox=\"0.00 0.00 62.00 44.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\r\n<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 40)\">\r\n<title>G</title>\r\n<polygon fill=\"white\" stroke=\"none\" points=\"-4,4 -4,-40 58,-40 58,4 -4,4\"/>\r\n<!-- n9430834ba8d5483e81d5d7407b247ffc -->\r\n<g id=\"node1\" class=\"node\"><title>n9430834ba8d5483e81d5d7407b247ffc</title>\r\n<g id=\"a_node1\"><a xlink:title=\"a\">\r\n<path fill=\"pink\" stroke=\"black\" d=\"M42,-36C42,-36 12,-36 12,-36 6,-36 0,-30 0,-24 0,-24 0,-12 0,-12 0,-6 6,-0 12,-0 12,-0 42,-0 42,-0 48,-0 54,-6 54,-12 54,-12 54,-24 54,-24 54,-30 48,-36 42,-36\"/>\r\n<text text-anchor=\"middle\" x=\"27\" y=\"-14.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">a</text>\r\n</a>\r\n</g>\r\n</g>\r\n</g>\r\n</svg>\r\n",
"text/plain": "<pydot.Dot at 0x1e500a5d408>"
},
"execution_count": 34,
"metadata": {},
"output_type": "execute_result"
}
]
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "#export\ndef object2graph(o):\n \"Get graph item representing `o`\"\n return graph_objects[object_names[id(o)]]",
"execution_count": 35,
"outputs": []
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "object2graph(o).get_fillcolor()",
"execution_count": 36,
"outputs": [
{
"data": {
"text/plain": "'\"pink\"'"
},
"execution_count": 36,
"metadata": {},
"output_type": "execute_result"
}
]
},
{
"metadata": {},
"cell_type": "markdown",
"source": "## Colors"
},
{
"metadata": {},
"cell_type": "markdown",
"source": "The callable kwargs functionality can be used to map labels to colors in a consistent way.."
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "#export\ndef obj2node_color(cm, minalpha, rangealpha, o):\n \"Create a consistent mapping from objects to colors, using colormap `cm`\"\n h = hash(o)\n i = float(h % 256) / 256\n alpha = (h^hash('something')) % rangealpha + minalpha\n return rgb2hex(cm(i)) + f'{alpha:02X}'",
"execution_count": 37,
"outputs": []
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "#exports\ngraph_colors1 = partial(obj2node_color, plt.get_cmap('rainbow'), 30, 160)\ngraph_colors2 = partial(obj2node_color, plt.get_cmap('tab20'), 30, 160)",
"execution_count": 38,
"outputs": []
},
{
"metadata": {},
"cell_type": "markdown",
"source": "These predefined color mapping functions provide a good range of colors and readable text."
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "g = Dot()\ng.add_node(Node('a', fillcolor=graph_colors1))\ng.add_node(Node('b', fillcolor=graph_colors1))\ng",
"execution_count": 39,
"outputs": [
{
"data": {
"image/svg+xml": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\r\n<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\r\n \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\r\n<!-- Generated by graphviz version 2.38.0 (20140413.2041)\r\n -->\r\n<!-- Title: G Pages: 1 -->\r\n<svg width=\"62pt\" height=\"98pt\"\r\n viewBox=\"0.00 0.00 62.00 98.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\r\n<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 94)\">\r\n<title>G</title>\r\n<polygon fill=\"white\" stroke=\"none\" points=\"-4,4 -4,-94 58,-94 58,4 -4,4\"/>\r\n<!-- nf59f75a0ad614fad920015930c7e2f9a -->\r\n<g id=\"node1\" class=\"node\"><title>nf59f75a0ad614fad920015930c7e2f9a</title>\r\n<g id=\"a_node1\"><a xlink:title=\"a\">\r\n<path fill=\"#9bfba5\" fill-opacity=\"0.423529\" stroke=\"black\" d=\"M42,-36C42,-36 12,-36 12,-36 6,-36 0,-30 0,-24 0,-24 0,-12 0,-12 0,-6 6,-0 12,-0 12,-0 42,-0 42,-0 48,-0 54,-6 54,-12 54,-12 54,-24 54,-24 54,-30 48,-36 42,-36\"/>\r\n<text text-anchor=\"middle\" x=\"27\" y=\"-14.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">a</text>\r\n</a>\r\n</g>\r\n</g>\r\n<!-- n5ef1142c5dd04829b8cdc96f989741f7 -->\r\n<g id=\"node2\" class=\"node\"><title>n5ef1142c5dd04829b8cdc96f989741f7</title>\r\n<g id=\"a_node2\"><a xlink:title=\"b\">\r\n<path fill=\"#583efd\" fill-opacity=\"0.458824\" stroke=\"black\" d=\"M42,-90C42,-90 12,-90 12,-90 6,-90 0,-84 0,-78 0,-78 0,-66 0,-66 0,-60 6,-54 12,-54 12,-54 42,-54 42,-54 48,-54 54,-60 54,-66 54,-66 54,-78 54,-78 54,-84 48,-90 42,-90\"/>\r\n<text text-anchor=\"middle\" x=\"27\" y=\"-68.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">b</text>\r\n</a>\r\n</g>\r\n</g>\r\n</g>\r\n</svg>\r\n",
"text/plain": "<pydot.Dot at 0x1e500b5c688>"
},
"execution_count": 39,
"metadata": {},
"output_type": "execute_result"
}
]
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "g = Dot()\ng.add_node(Node('a', fillcolor=graph_colors2))\ng.add_node(Node('b', fillcolor=graph_colors2))\ng",
"execution_count": 40,
"outputs": [
{
"data": {
"image/svg+xml": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\r\n<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\r\n \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\r\n<!-- Generated by graphviz version 2.38.0 (20140413.2041)\r\n -->\r\n<!-- Title: G Pages: 1 -->\r\n<svg width=\"62pt\" height=\"98pt\"\r\n viewBox=\"0.00 0.00 62.00 98.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\r\n<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 94)\">\r\n<title>G</title>\r\n<polygon fill=\"white\" stroke=\"none\" points=\"-4,4 -4,-94 58,-94 58,4 -4,4\"/>\r\n<!-- n8a0a892a46294134bd6c233931178a89 -->\r\n<g id=\"node1\" class=\"node\"><title>n8a0a892a46294134bd6c233931178a89</title>\r\n<g id=\"a_node1\"><a xlink:title=\"a\">\r\n<path fill=\"#c49c94\" fill-opacity=\"0.423529\" stroke=\"black\" d=\"M42,-36C42,-36 12,-36 12,-36 6,-36 0,-30 0,-24 0,-24 0,-12 0,-12 0,-6 6,-0 12,-0 12,-0 42,-0 42,-0 48,-0 54,-6 54,-12 54,-12 54,-24 54,-24 54,-30 48,-36 42,-36\"/>\r\n<text text-anchor=\"middle\" x=\"27\" y=\"-14.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">a</text>\r\n</a>\r\n</g>\r\n</g>\r\n<!-- n879fe15631b740f7b5ccc9c7c01bff10 -->\r\n<g id=\"node2\" class=\"node\"><title>n879fe15631b740f7b5ccc9c7c01bff10</title>\r\n<g id=\"a_node2\"><a xlink:title=\"b\">\r\n<path fill=\"#aec7e8\" fill-opacity=\"0.458824\" stroke=\"black\" d=\"M42,-90C42,-90 12,-90 12,-90 6,-90 0,-84 0,-78 0,-78 0,-66 0,-66 0,-60 6,-54 12,-54 12,-54 42,-54 42,-54 48,-54 54,-60 54,-66 54,-66 54,-78 54,-78 54,-84 48,-90 42,-90\"/>\r\n<text text-anchor=\"middle\" x=\"27\" y=\"-68.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">b</text>\r\n</a>\r\n</g>\r\n</g>\r\n</g>\r\n</svg>\r\n",
"text/plain": "<pydot.Dot at 0x1e500b5c0c8>"
},
"execution_count": 40,
"metadata": {},
"output_type": "execute_result"
}
]
},
{
"metadata": {},
"cell_type": "markdown",
"source": "We'll use the former color function as our default. You can change it by simply modifying `node_defaults`."
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "#export\nnode_defaults['fillcolor'] = graph_colors1",
"execution_count": 41,
"outputs": []
},
{
"metadata": {},
"cell_type": "markdown",
"source": "## Clusters and Items"
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "#export\ncluster_defaults = dict(label=str, tooltip=str, graph_name=uniq_name, style='rounded, filled', fillcolor='#55555522')",
"execution_count": 42,
"outputs": []
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "#export\ndef Cluster(obj='', **kwargs):\n \"Create a `pydot.Cluster` with a unique name\"\n kwargs = merge(cluster_defaults, kwargs)\n return _pydot_create(pydot.Cluster, obj, **kwargs)",
"execution_count": 43,
"outputs": []
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "g = Dot()\nsg = Cluster('clus', tooltip='Cluster tooltip')\nsg.add_node(Node(['a', \"My tooltip\"]))\nsg.add_node(Node('b'))\ng.add_subgraph(sg)\ng",
"execution_count": 44,
"outputs": [
{
"data": {
"image/svg+xml": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\r\n<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\r\n \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\r\n<!-- Generated by graphviz version 2.38.0 (20140413.2041)\r\n -->\r\n<!-- Title: G Pages: 1 -->\r\n<svg width=\"94pt\" height=\"153pt\"\r\n viewBox=\"0.00 0.00 94.00 153.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\r\n<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 149)\">\r\n<title>G</title>\r\n<polygon fill=\"white\" stroke=\"none\" points=\"-4,4 -4,-149 90,-149 90,4 -4,4\"/>\r\n<g id=\"clust1\" class=\"cluster\"><title>cluster_n89051654684c4bc3aac2c6eb820a16b1</title>\r\n<g id=\"a_clust1\"><a xlink:title=\"Cluster tooltip\">\r\n<path fill=\"#555555\" fill-opacity=\"0.133333\" stroke=\"black\" d=\"M20,-8C20,-8 66,-8 66,-8 72,-8 78,-14 78,-20 78,-20 78,-125 78,-125 78,-131 72,-137 66,-137 66,-137 20,-137 20,-137 14,-137 8,-131 8,-125 8,-125 8,-20 8,-20 8,-14 14,-8 20,-8\"/>\r\n<text text-anchor=\"middle\" x=\"43\" y=\"-121.8\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">clus</text>\r\n</a>\r\n</g>\r\n</g>\r\n<!-- n120facb5f8c547d2bf34998afcaf39c7 -->\r\n<g id=\"node1\" class=\"node\"><title>n120facb5f8c547d2bf34998afcaf39c7</title>\r\n<g id=\"a_node1\"><a xlink:title=\"My tooltip\">\r\n<path fill=\"#9bfba5\" fill-opacity=\"0.423529\" stroke=\"black\" d=\"M58,-106C58,-106 28,-106 28,-106 22,-106 16,-100 16,-94 16,-94 16,-82 16,-82 16,-76 22,-70 28,-70 28,-70 58,-70 58,-70 64,-70 70,-76 70,-82 70,-82 70,-94 70,-94 70,-100 64,-106 58,-106\"/>\r\n<text text-anchor=\"middle\" x=\"43\" y=\"-84.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">a</text>\r\n</a>\r\n</g>\r\n</g>\r\n<!-- n0d69ff0a74dd48d9b4a148c459e09ef2 -->\r\n<g id=\"node2\" class=\"node\"><title>n0d69ff0a74dd48d9b4a148c459e09ef2</title>\r\n<g id=\"a_node2\"><a xlink:title=\"b\">\r\n<path fill=\"#583efd\" fill-opacity=\"0.458824\" stroke=\"black\" d=\"M58,-52C58,-52 28,-52 28,-52 22,-52 16,-46 16,-40 16,-40 16,-28 16,-28 16,-22 22,-16 28,-16 28,-16 58,-16 58,-16 64,-16 70,-22 70,-28 70,-28 70,-40 70,-40 70,-46 64,-52 58,-52\"/>\r\n<text text-anchor=\"middle\" x=\"43\" y=\"-30.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">b</text>\r\n</a>\r\n</g>\r\n</g>\r\n</g>\r\n</svg>\r\n",
"text/plain": "<pydot.Dot at 0x1e500b9b348>"
},
"execution_count": 44,
"metadata": {},
"output_type": "execute_result"
}
]
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "#export\n@patch\ndef nodes(self:pydot.Graph):\n \"`i`th node in `Graph`\"\n return L(o for o in self.get_nodes() if o.get_label() is not None)",
"execution_count": 45,
"outputs": []
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "#export\n@patch\ndef __getitem__(self:pydot.Graph, i):\n \"`i`th node in `Graph`\"\n return self.nodes()[i]",
"execution_count": 46,
"outputs": []
},
{
"metadata": {},
"cell_type": "markdown",
"source": "You can subscript into a `Graph`'s `Node`s by index:"
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "print(sg[0].get_label())",
"execution_count": 47,
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": "\"a\"\n"
}
]
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "#export\n@patch\ndef add_item(self:pydot.Graph, item, **kwargs):\n \"Add a `Cluster`, `Node`, or `Edge` to the `Graph`\"\n if not isinstance(item, (pydot.Edge,pydot.Node,pydot.Graph)): item = Node(item, **kwargs)\n f = self.add_node if isinstance(item, pydot.Node ) else \\\n self.add_subgraph if isinstance(item, pydot.Graph) else \\\n self.add_edge if isinstance(item, pydot.Edge ) else None\n f(item)\n return item",
"execution_count": 48,
"outputs": []
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "#export\n@patch\ndef __add__(self:pydot.Graph, item, **kwargs):\n \"Add a `Cluster`, `Node`, or `Edge` to the `Graph`\"\n if not isinstance(item, (pydot.Edge,pydot.Node,pydot.Graph)): item = Node(item, **kwargs)\n f = self.add_node if isinstance(item, pydot.Node ) else \\\n self.add_subgraph if isinstance(item, pydot.Graph) else \\\n self.add_edge if isinstance(item, pydot.Edge ) else None\n f(item)\n return item",
"execution_count": null,
"outputs": []
},
{
"metadata": {},
"cell_type": "markdown",
"source": "There's no good reason to have different methods for adding clusters vs nodes (as `pydot` requires), so we provide a single method."
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "a=g+sg",
"execution_count": null,
"outputs": []
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "g= Dot()",
"execution_count": null,
"outputs": []
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "sg = Cluster('clus')",
"execution_count": null,
"outputs": []
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "g",
"execution_count": null,
"outputs": []
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "g = Dot()\nsg = Cluster('clus')\ng + sg\nsg + 'a'\ng",
"execution_count": null,
"outputs": []
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "g = Dot()\nsg = Cluster('clus')\n# g.add_item(sg)\n# sg.add_item('a')\ng",
"execution_count": null,
"outputs": []
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "#export\n@patch\ndef add_items(self:pydot.Graph, *items, **kwargs):\n \"Add `items` the `Graph`\"\n return L(self.add_item(it, **kwargs) for it in items)",
"execution_count": 50,
"outputs": []
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "#export\ndef graph_items(*items, **kwargs):\n \"Add `items` to a new `pydot.Dot`\"\n g = Dot()\n g.add_items(*items, **kwargs)\n return g",
"execution_count": 51,
"outputs": []
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "sg1 = Cluster('clus')\nsg1.add_items('n1', 'n2')\nsg2 = Cluster()\nsg2.add_item('n')\ngraph_items(sg1,sg2)",
"execution_count": 52,
"outputs": [
{
"data": {
"image/svg+xml": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\r\n<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\r\n \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\r\n<!-- Generated by graphviz version 2.38.0 (20140413.2041)\r\n -->\r\n<!-- Title: G Pages: 1 -->\r\n<svg width=\"94pt\" height=\"213pt\"\r\n viewBox=\"0.00 0.00 94.00 213.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\r\n<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 209)\">\r\n<title>G</title>\r\n<polygon fill=\"white\" stroke=\"none\" points=\"-4,4 -4,-209 90,-209 90,4 -4,4\"/>\r\n<g id=\"clust1\" class=\"cluster\"><title>cluster_n712bfd598f194928bf41de3b0163b620</title>\r\n<g id=\"a_clust1\"><a xlink:title=\"clus\">\r\n<path fill=\"#555555\" fill-opacity=\"0.133333\" stroke=\"black\" d=\"M20,-8C20,-8 66,-8 66,-8 72,-8 78,-14 78,-20 78,-20 78,-125 78,-125 78,-131 72,-137 66,-137 66,-137 20,-137 20,-137 14,-137 8,-131 8,-125 8,-125 8,-20 8,-20 8,-14 14,-8 20,-8\"/>\r\n<text text-anchor=\"middle\" x=\"43\" y=\"-121.8\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">clus</text>\r\n</a>\r\n</g>\r\n</g>\r\n<g id=\"clust2\" class=\"cluster\"><title>cluster_n5a5ce4a7af0c4fac89704872c6e6c561</title>\r\n<path fill=\"#555555\" fill-opacity=\"0.133333\" stroke=\"black\" d=\"M20,-145C20,-145 66,-145 66,-145 72,-145 78,-151 78,-157 78,-157 78,-185 78,-185 78,-191 72,-197 66,-197 66,-197 20,-197 20,-197 14,-197 8,-191 8,-185 8,-185 8,-157 8,-157 8,-151 14,-145 20,-145\"/>\r\n</g>\r\n<!-- nc572d9cf687d4863ac58d6f7875bb559 -->\r\n<g id=\"node1\" class=\"node\"><title>nc572d9cf687d4863ac58d6f7875bb559</title>\r\n<g id=\"a_node1\"><a xlink:title=\"n1\">\r\n<path fill=\"#bced8f\" fill-opacity=\"0.231373\" stroke=\"black\" d=\"M58,-106C58,-106 28,-106 28,-106 22,-106 16,-100 16,-94 16,-94 16,-82 16,-82 16,-76 22,-70 28,-70 28,-70 58,-70 58,-70 64,-70 70,-76 70,-82 70,-82 70,-94 70,-94 70,-100 64,-106 58,-106\"/>\r\n<text text-anchor=\"middle\" x=\"43\" y=\"-84.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">n1</text>\r\n</a>\r\n</g>\r\n</g>\r\n<!-- n0e87fd8c3c0b4799baa79ad78794acc0 -->\r\n<g id=\"node2\" class=\"node\"><title>n0e87fd8c3c0b4799baa79ad78794acc0</title>\r\n<g id=\"a_node2\"><a xlink:title=\"n2\">\r\n<path fill=\"#54f6cb\" fill-opacity=\"0.403922\" stroke=\"black\" d=\"M58,-52C58,-52 28,-52 28,-52 22,-52 16,-46 16,-40 16,-40 16,-28 16,-28 16,-22 22,-16 28,-16 28,-16 58,-16 58,-16 64,-16 70,-22 70,-28 70,-28 70,-40 70,-40 70,-46 64,-52 58,-52\"/>\r\n<text text-anchor=\"middle\" x=\"43\" y=\"-30.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">n2</text>\r\n</a>\r\n</g>\r\n</g>\r\n<!-- n28311f03a248488aa7cec3256fd9b1ab -->\r\n<g id=\"node3\" class=\"node\"><title>n28311f03a248488aa7cec3256fd9b1ab</title>\r\n<g id=\"a_node3\"><a xlink:title=\"n\">\r\n<path fill=\"#ff8143\" fill-opacity=\"0.458824\" stroke=\"black\" d=\"M58,-189C58,-189 28,-189 28,-189 22,-189 16,-183 16,-177 16,-177 16,-165 16,-165 16,-159 22,-153 28,-153 28,-153 58,-153 58,-153 64,-153 70,-159 70,-165 70,-165 70,-177 70,-177 70,-183 64,-189 58,-189\"/>\r\n<text text-anchor=\"middle\" x=\"43\" y=\"-167.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">n</text>\r\n</a>\r\n</g>\r\n</g>\r\n</g>\r\n</svg>\r\n",
"text/plain": "<pydot.Dot at 0x1e500c313c8>"
},
"execution_count": 52,
"metadata": {},
"output_type": "execute_result"
}
]
},
{
"metadata": {},
"cell_type": "markdown",
"source": "## Edges"
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "#export\n@patch\ndef first(self:pydot.Graph):\n \"First node in `Graph`, searching subgraphs recursively as needed\"\n nodes = self.nodes()\n if nodes: return nodes[0]\n for subg in self.get_subgraphs():\n res = subg.first()\n if res: return res",
"execution_count": 53,
"outputs": []
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "#export\n@patch\ndef last(self:pydot.Graph):\n \"Lastt node in `Graph`, searching subgraphs recursively as needed\"\n nodes = self.nodes()\n if nodes: return nodes[-1]\n for subg in reversed(self.get_subgraphs()):\n res = subg.last()\n if res: return res",
"execution_count": 54,
"outputs": []
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "#export\n@patch\ndef with_compass(self:(pydot.Node,pydot.Graph), compass=None):\n r = self.get_name()\n return f'{r}:{compass}' if compass else r",
"execution_count": 55,
"outputs": []
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "# export\n@patch\ndef connect(self:(pydot.Node,pydot.Graph), item, compass1=None, compass2=None, **kwargs):\n \"Connect two nodes or clusters\"\n a,b,ltail,lhead = self,item,'',''\n if isinstance(self,pydot.Graph):\n a = self.last()\n ltail=self.get_name()\n if isinstance(item,pydot.Graph):\n b = item.first()\n lhead=item.get_name()\n a,b = a.with_compass(compass1),b.with_compass(compass2)\n return pydot.Edge(a, b, lhead=lhead, ltail=ltail, **kwargs)",
"execution_count": 56,
"outputs": []
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "sg2 = Cluster('clus2')\nn1 = sg2.add_item('n1', fillcolor='pink')\nn2 = sg2.add_item('n2', fillcolor='lightblue')\nsg2.add_item(n1.connect(n2))\n\nsg1 = Cluster('clus1')\nsg1.add_item(sg2)\n\na,b = Node('a'),Node('b')\nedges = a.connect(b),a.connect(a),sg1.connect(b),sg2[0].connect(a)\ng = Dot()\ng.add_items(sg1, a, b, *edges)\ng",
"execution_count": 57,
"outputs": [
{
"data": {
"image/svg+xml": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\r\n<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\r\n \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\r\n<!-- Generated by graphviz version 2.38.0 (20140413.2041)\r\n -->\r\n<!-- Title: G Pages: 1 -->\r\n<svg width=\"266pt\" height=\"192pt\"\r\n viewBox=\"0.00 0.00 266.00 192.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\r\n<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 188)\">\r\n<title>G</title>\r\n<polygon fill=\"white\" stroke=\"none\" points=\"-4,4 -4,-188 262,-188 262,4 -4,4\"/>\r\n<g id=\"clust1\" class=\"cluster\"><title>cluster_n26d0ab988e774275beb960519b20b318</title>\r\n<g id=\"a_clust1\"><a xlink:title=\"clus1\">\r\n<path fill=\"#555555\" fill-opacity=\"0.133333\" stroke=\"black\" d=\"M20,-62C20,-62 172,-62 172,-62 178,-62 184,-68 184,-74 184,-74 184,-164 184,-164 184,-170 178,-176 172,-176 172,-176 20,-176 20,-176 14,-176 8,-170 8,-164 8,-164 8,-74 8,-74 8,-68 14,-62 20,-62\"/>\r\n<text text-anchor=\"middle\" x=\"96\" y=\"-160.8\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">clus1</text>\r\n</a>\r\n</g>\r\n</g>\r\n<g id=\"clust2\" class=\"cluster\"><title>cluster_nd29353746aad4a099c09e0179bf6bcf6</title>\r\n<g id=\"a_clust2\"><a xlink:title=\"clus2\">\r\n<path fill=\"#555555\" fill-opacity=\"0.133333\" stroke=\"black\" d=\"M28,-70C28,-70 164,-70 164,-70 170,-70 176,-76 176,-82 176,-82 176,-133 176,-133 176,-139 170,-145 164,-145 164,-145 28,-145 28,-145 22,-145 16,-139 16,-133 16,-133 16,-82 16,-82 16,-76 22,-70 28,-70\"/>\r\n<text text-anchor=\"middle\" x=\"96\" y=\"-129.8\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">clus2</text>\r\n</a>\r\n</g>\r\n</g>\r\n<!-- n35feb868a45f4770a49f7fd2a9d07f7e -->\r\n<g id=\"node1\" class=\"node\"><title>n35feb868a45f4770a49f7fd2a9d07f7e</title>\r\n<g id=\"a_node1\"><a xlink:title=\"n1\">\r\n<path fill=\"pink\" stroke=\"black\" d=\"M66,-114C66,-114 36,-114 36,-114 30,-114 24,-108 24,-102 24,-102 24,-90 24,-90 24,-84 30,-78 36,-78 36,-78 66,-78 66,-78 72,-78 78,-84 78,-90 78,-90 78,-102 78,-102 78,-108 72,-114 66,-114\"/>\r\n<text text-anchor=\"middle\" x=\"51\" y=\"-92.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">n1</text>\r\n</a>\r\n</g>\r\n</g>\r\n<!-- n82f11263d3ea43a383e5fad417d19f79 -->\r\n<g id=\"node2\" class=\"node\"><title>n82f11263d3ea43a383e5fad417d19f79</title>\r\n<g id=\"a_node2\"><a xlink:title=\"n2\">\r\n<path fill=\"lightblue\" stroke=\"black\" d=\"M156,-114C156,-114 126,-114 126,-114 120,-114 114,-108 114,-102 114,-102 114,-90 114,-90 114,-84 120,-78 126,-78 126,-78 156,-78 156,-78 162,-78 168,-84 168,-90 168,-90 168,-102 168,-102 168,-108 162,-114 156,-114\"/>\r\n<text text-anchor=\"middle\" x=\"141\" y=\"-92.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">n2</text>\r\n</a>\r\n</g>\r\n</g>\r\n<!-- n35feb868a45f4770a49f7fd2a9d07f7e&#45;&gt;n82f11263d3ea43a383e5fad417d19f79 -->\r\n<g id=\"edge1\" class=\"edge\"><title>n35feb868a45f4770a49f7fd2a9d07f7e&#45;&gt;n82f11263d3ea43a383e5fad417d19f79</title>\r\n<path fill=\"none\" stroke=\"black\" d=\"M78.4029,-96C86.3932,-96 95.3106,-96 103.824,-96\"/>\r\n<polygon fill=\"black\" stroke=\"black\" points=\"103.919,-99.5001 113.919,-96 103.919,-92.5001 103.919,-99.5001\"/>\r\n</g>\r\n<!-- n19507a3b6bdb4827b0fd1e47252ef48c -->\r\n<g id=\"node3\" class=\"node\"><title>n19507a3b6bdb4827b0fd1e47252ef48c</title>\r\n<g id=\"a_node3\"><a xlink:title=\"a\">\r\n<path fill=\"#9bfba5\" fill-opacity=\"0.423529\" stroke=\"black\" d=\"M156,-36C156,-36 126,-36 126,-36 120,-36 114,-30 114,-24 114,-24 114,-12 114,-12 114,-6 120,-0 126,-0 126,-0 156,-0 156,-0 162,-0 168,-6 168,-12 168,-12 168,-24 168,-24 168,-30 162,-36 156,-36\"/>\r\n<text text-anchor=\"middle\" x=\"141\" y=\"-14.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">a</text>\r\n</a>\r\n</g>\r\n</g>\r\n<!-- n35feb868a45f4770a49f7fd2a9d07f7e&#45;&gt;n19507a3b6bdb4827b0fd1e47252ef48c -->\r\n<g id=\"edge5\" class=\"edge\"><title>n35feb868a45f4770a49f7fd2a9d07f7e&#45;&gt;n19507a3b6bdb4827b0fd1e47252ef48c</title>\r\n<path fill=\"none\" stroke=\"black\" d=\"M72.4102,-77.9092C84.0992,-67.5484 98.9418,-54.3925 111.739,-43.0498\"/>\r\n<polygon fill=\"black\" stroke=\"black\" points=\"114.234,-45.5152 119.396,-36.2629 109.591,-40.2768 114.234,-45.5152\"/>\r\n</g>\r\n<!-- nef33d08909e64a73b068bb38af4c10a2 -->\r\n<g id=\"node4\" class=\"node\"><title>nef33d08909e64a73b068bb38af4c10a2</title>\r\n<g id=\"a_node4\"><a xlink:title=\"b\">\r\n<path fill=\"#583efd\" fill-opacity=\"0.458824\" stroke=\"black\" d=\"M246,-75C246,-75 216,-75 216,-75 210,-75 204,-69 204,-63 204,-63 204,-51 204,-51 204,-45 210,-39 216,-39 216,-39 246,-39 246,-39 252,-39 258,-45 258,-51 258,-51 258,-63 258,-63 258,-69 252,-75 246,-75\"/>\r\n<text text-anchor=\"middle\" x=\"231\" y=\"-53.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">b</text>\r\n</a>\r\n</g>\r\n</g>\r\n<!-- n82f11263d3ea43a383e5fad417d19f79&#45;&gt;nef33d08909e64a73b068bb38af4c10a2 -->\r\n<g id=\"edge4\" class=\"edge\"><title>n82f11263d3ea43a383e5fad417d19f79&#45;&gt;nef33d08909e64a73b068bb38af4c10a2</title>\r\n<path fill=\"none\" stroke=\"black\" d=\"M183.844,-77.4555C187.464,-75.8511 191.104,-74.2381 194.665,-72.66\"/>\r\n<polygon fill=\"black\" stroke=\"black\" points=\"196.195,-75.8103 203.919,-68.5586 193.358,-69.4106 196.195,-75.8103\"/>\r\n</g>\r\n<!-- n19507a3b6bdb4827b0fd1e47252ef48c&#45;&gt;n19507a3b6bdb4827b0fd1e47252ef48c -->\r\n<g id=\"edge3\" class=\"edge\"><title>n19507a3b6bdb4827b0fd1e47252ef48c&#45;&gt;n19507a3b6bdb4827b0fd1e47252ef48c</title>\r\n<path fill=\"none\" stroke=\"black\" d=\"M124.718,-36.1527C122.213,-45.5391 127.641,-54 141,-54 149.141,-54 154.336,-50.8581 156.586,-46.2796\"/>\r\n<polygon fill=\"black\" stroke=\"black\" points=\"160.088,-46.3691 157.282,-36.1527 153.105,-45.8893 160.088,-46.3691\"/>\r\n</g>\r\n<!-- n19507a3b6bdb4827b0fd1e47252ef48c&#45;&gt;nef33d08909e64a73b068bb38af4c10a2 -->\r\n<g id=\"edge2\" class=\"edge\"><title>n19507a3b6bdb4827b0fd1e47252ef48c&#45;&gt;nef33d08909e64a73b068bb38af4c10a2</title>\r\n<path fill=\"none\" stroke=\"black\" d=\"M168.403,-29.7013C176.657,-33.3592 185.9,-37.4555 194.665,-41.34\"/>\r\n<polygon fill=\"black\" stroke=\"black\" points=\"193.358,-44.5894 203.919,-45.4414 196.195,-38.1897 193.358,-44.5894\"/>\r\n</g>\r\n</g>\r\n</svg>\r\n",
"text/plain": "<pydot.Dot at 0x1e500c80b48>"
},
"execution_count": 57,
"metadata": {},
"output_type": "execute_result"
}
]
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "#export\ndef object_connections(conns):\n \"Create connections between all pairs in `conns`\"\n return [object2graph(a).connect(object2graph(b)) for a,b in conns]",
"execution_count": 58,
"outputs": []
},
{
"metadata": {},
"cell_type": "markdown",
"source": "This is a shortcut for creating connections between objects that are already in a graph."
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "a,b = 'a','b'\ng = graph_items(a, b)\ng.add_items(*object_connections([(a,b)]))\ng",
"execution_count": 59,
"outputs": [
{
"data": {
"image/svg+xml": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\r\n<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\r\n \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\r\n<!-- Generated by graphviz version 2.38.0 (20140413.2041)\r\n -->\r\n<!-- Title: G Pages: 1 -->\r\n<svg width=\"152pt\" height=\"44pt\"\r\n viewBox=\"0.00 0.00 152.00 44.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\r\n<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 40)\">\r\n<title>G</title>\r\n<polygon fill=\"white\" stroke=\"none\" points=\"-4,4 -4,-40 148,-40 148,4 -4,4\"/>\r\n<!-- nccfd3310b4714831bafcba388a239870 -->\r\n<g id=\"node1\" class=\"node\"><title>nccfd3310b4714831bafcba388a239870</title>\r\n<g id=\"a_node1\"><a xlink:title=\"a\">\r\n<path fill=\"#9bfba5\" fill-opacity=\"0.423529\" stroke=\"black\" d=\"M42,-36C42,-36 12,-36 12,-36 6,-36 0,-30 0,-24 0,-24 0,-12 0,-12 0,-6 6,-0 12,-0 12,-0 42,-0 42,-0 48,-0 54,-6 54,-12 54,-12 54,-24 54,-24 54,-30 48,-36 42,-36\"/>\r\n<text text-anchor=\"middle\" x=\"27\" y=\"-14.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">a</text>\r\n</a>\r\n</g>\r\n</g>\r\n<!-- n934b4caaca0b49f3b14a5f9639651169 -->\r\n<g id=\"node2\" class=\"node\"><title>n934b4caaca0b49f3b14a5f9639651169</title>\r\n<g id=\"a_node2\"><a xlink:title=\"b\">\r\n<path fill=\"#583efd\" fill-opacity=\"0.458824\" stroke=\"black\" d=\"M132,-36C132,-36 102,-36 102,-36 96,-36 90,-30 90,-24 90,-24 90,-12 90,-12 90,-6 96,-0 102,-0 102,-0 132,-0 132,-0 138,-0 144,-6 144,-12 144,-12 144,-24 144,-24 144,-30 138,-36 132,-36\"/>\r\n<text text-anchor=\"middle\" x=\"117\" y=\"-14.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">b</text>\r\n</a>\r\n</g>\r\n</g>\r\n<!-- nccfd3310b4714831bafcba388a239870&#45;&gt;n934b4caaca0b49f3b14a5f9639651169 -->\r\n<g id=\"edge1\" class=\"edge\"><title>nccfd3310b4714831bafcba388a239870&#45;&gt;n934b4caaca0b49f3b14a5f9639651169</title>\r\n<path fill=\"none\" stroke=\"black\" d=\"M54.4029,-18C62.3932,-18 71.3106,-18 79.8241,-18\"/>\r\n<polygon fill=\"black\" stroke=\"black\" points=\"79.919,-21.5001 89.919,-18 79.919,-14.5001 79.919,-21.5001\"/>\r\n</g>\r\n</g>\r\n</svg>\r\n",
"text/plain": "<pydot.Dot at 0x1e500c53748>"
},
"execution_count": 59,
"metadata": {},
"output_type": "execute_result"
}
]
},
{
"metadata": {},
"cell_type": "markdown",
"source": "## Sequential"
},
{
"metadata": {},
"cell_type": "markdown",
"source": "Since it's common to want to connect a series sequentially, we provide some simple shortcuts for this functionality."
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "#export\ndef graph_edges_seq(items):\n \"Add edges between each pair of nodes in `items`\"\n return L(items[i].connect(items[i+1]) for i in range(len(items)-1))",
"execution_count": 60,
"outputs": []
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "#export\n@patch\ndef add_edges_seq(self:pydot.Graph, items):\n \"Add edges between each pair of nodes in `items`\"\n return self.add_items(*graph_edges_seq(items))",
"execution_count": 61,
"outputs": []
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "g = Dot()\nits = g.add_items('a','b','c')\ng.add_edges_seq(its)\ng",
"execution_count": 62,
"outputs": [
{
"data": {
"image/svg+xml": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\r\n<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\r\n \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\r\n<!-- Generated by graphviz version 2.38.0 (20140413.2041)\r\n -->\r\n<!-- Title: G Pages: 1 -->\r\n<svg width=\"242pt\" height=\"44pt\"\r\n viewBox=\"0.00 0.00 242.00 44.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\r\n<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 40)\">\r\n<title>G</title>\r\n<polygon fill=\"white\" stroke=\"none\" points=\"-4,4 -4,-40 238,-40 238,4 -4,4\"/>\r\n<!-- n1c597863bdeb4e95839997381c978a2a -->\r\n<g id=\"node1\" class=\"node\"><title>n1c597863bdeb4e95839997381c978a2a</title>\r\n<g id=\"a_node1\"><a xlink:title=\"a\">\r\n<path fill=\"#9bfba5\" fill-opacity=\"0.423529\" stroke=\"black\" d=\"M42,-36C42,-36 12,-36 12,-36 6,-36 0,-30 0,-24 0,-24 0,-12 0,-12 0,-6 6,-0 12,-0 12,-0 42,-0 42,-0 48,-0 54,-6 54,-12 54,-12 54,-24 54,-24 54,-30 48,-36 42,-36\"/>\r\n<text text-anchor=\"middle\" x=\"27\" y=\"-14.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">a</text>\r\n</a>\r\n</g>\r\n</g>\r\n<!-- n1798a3a935f9495cb4de66a087e7e804 -->\r\n<g id=\"node2\" class=\"node\"><title>n1798a3a935f9495cb4de66a087e7e804</title>\r\n<g id=\"a_node2\"><a xlink:title=\"b\">\r\n<path fill=\"#583efd\" fill-opacity=\"0.458824\" stroke=\"black\" d=\"M132,-36C132,-36 102,-36 102,-36 96,-36 90,-30 90,-24 90,-24 90,-12 90,-12 90,-6 96,-0 102,-0 102,-0 132,-0 132,-0 138,-0 144,-6 144,-12 144,-12 144,-24 144,-24 144,-30 138,-36 132,-36\"/>\r\n<text text-anchor=\"middle\" x=\"117\" y=\"-14.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">b</text>\r\n</a>\r\n</g>\r\n</g>\r\n<!-- n1c597863bdeb4e95839997381c978a2a&#45;&gt;n1798a3a935f9495cb4de66a087e7e804 -->\r\n<g id=\"edge1\" class=\"edge\"><title>n1c597863bdeb4e95839997381c978a2a&#45;&gt;n1798a3a935f9495cb4de66a087e7e804</title>\r\n<path fill=\"none\" stroke=\"black\" d=\"M54.4029,-18C62.3932,-18 71.3106,-18 79.8241,-18\"/>\r\n<polygon fill=\"black\" stroke=\"black\" points=\"79.919,-21.5001 89.919,-18 79.919,-14.5001 79.919,-21.5001\"/>\r\n</g>\r\n<!-- n679b040cb1c24fc8a6e8faac4cfd6815 -->\r\n<g id=\"node3\" class=\"node\"><title>n679b040cb1c24fc8a6e8faac4cfd6815</title>\r\n<g id=\"a_node3\"><a xlink:title=\"c\">\r\n<path fill=\"#ff6232\" fill-opacity=\"0.227451\" stroke=\"black\" d=\"M222,-36C222,-36 192,-36 192,-36 186,-36 180,-30 180,-24 180,-24 180,-12 180,-12 180,-6 186,-0 192,-0 192,-0 222,-0 222,-0 228,-0 234,-6 234,-12 234,-12 234,-24 234,-24 234,-30 228,-36 222,-36\"/>\r\n<text text-anchor=\"middle\" x=\"207\" y=\"-14.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">c</text>\r\n</a>\r\n</g>\r\n</g>\r\n<!-- n1798a3a935f9495cb4de66a087e7e804&#45;&gt;n679b040cb1c24fc8a6e8faac4cfd6815 -->\r\n<g id=\"edge2\" class=\"edge\"><title>n1798a3a935f9495cb4de66a087e7e804&#45;&gt;n679b040cb1c24fc8a6e8faac4cfd6815</title>\r\n<path fill=\"none\" stroke=\"black\" d=\"M144.403,-18C152.393,-18 161.311,-18 169.824,-18\"/>\r\n<polygon fill=\"black\" stroke=\"black\" points=\"169.919,-21.5001 179.919,-18 169.919,-14.5001 169.919,-21.5001\"/>\r\n</g>\r\n</g>\r\n</svg>\r\n",
"text/plain": "<pydot.Dot at 0x1e500c5ab88>"
},
"execution_count": 62,
"metadata": {},
"output_type": "execute_result"
}
]
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "#export\ndef seq_cluster(items, cluster_label='', **kwargs):\n sg = Cluster(cluster_label)\n its = sg.add_items(*items, **kwargs)\n sg.add_edges_seq(its)\n return sg",
"execution_count": 63,
"outputs": []
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "g = Dot()\ng.add_item(seq_cluster(['a','b','c'], 'clust'))\ng.add_item(seq_cluster(['1','2','c'], 'clust2'))\ng",
"execution_count": 64,
"outputs": [
{
"data": {
"image/svg+xml": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\r\n<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\r\n \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\r\n<!-- Generated by graphviz version 2.38.0 (20140413.2041)\r\n -->\r\n<!-- Title: G Pages: 1 -->\r\n<svg width=\"274pt\" height=\"182pt\"\r\n viewBox=\"0.00 0.00 274.00 182.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\r\n<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 178)\">\r\n<title>G</title>\r\n<polygon fill=\"white\" stroke=\"none\" points=\"-4,4 -4,-178 270,-178 270,4 -4,4\"/>\r\n<g id=\"clust1\" class=\"cluster\"><title>cluster_n6350c6ea2b7649d18fff3c6d5e5cdc2a</title>\r\n<g id=\"a_clust1\"><a xlink:title=\"clust\">\r\n<path fill=\"#555555\" fill-opacity=\"0.133333\" stroke=\"black\" d=\"M20,-8C20,-8 246,-8 246,-8 252,-8 258,-14 258,-20 258,-20 258,-71 258,-71 258,-77 252,-83 246,-83 246,-83 20,-83 20,-83 14,-83 8,-77 8,-71 8,-71 8,-20 8,-20 8,-14 14,-8 20,-8\"/>\r\n<text text-anchor=\"middle\" x=\"133\" y=\"-67.8\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">clust</text>\r\n</a>\r\n</g>\r\n</g>\r\n<g id=\"clust2\" class=\"cluster\"><title>cluster_n9b144468eddf4dcca0559b2f915b674e</title>\r\n<g id=\"a_clust2\"><a xlink:title=\"clust2\">\r\n<path fill=\"#555555\" fill-opacity=\"0.133333\" stroke=\"black\" d=\"M20,-91C20,-91 246,-91 246,-91 252,-91 258,-97 258,-103 258,-103 258,-154 258,-154 258,-160 252,-166 246,-166 246,-166 20,-166 20,-166 14,-166 8,-160 8,-154 8,-154 8,-103 8,-103 8,-97 14,-91 20,-91\"/>\r\n<text text-anchor=\"middle\" x=\"133\" y=\"-150.8\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">clust2</text>\r\n</a>\r\n</g>\r\n</g>\r\n<!-- n1600399bd4c74e4ba320348f157069cd -->\r\n<g id=\"node1\" class=\"node\"><title>n1600399bd4c74e4ba320348f157069cd</title>\r\n<g id=\"a_node1\"><a xlink:title=\"a\">\r\n<path fill=\"#9bfba5\" fill-opacity=\"0.423529\" stroke=\"black\" d=\"M58,-52C58,-52 28,-52 28,-52 22,-52 16,-46 16,-40 16,-40 16,-28 16,-28 16,-22 22,-16 28,-16 28,-16 58,-16 58,-16 64,-16 70,-22 70,-28 70,-28 70,-40 70,-40 70,-46 64,-52 58,-52\"/>\r\n<text text-anchor=\"middle\" x=\"43\" y=\"-30.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">a</text>\r\n</a>\r\n</g>\r\n</g>\r\n<!-- n003714d39c334b8cb4a4d131c25828d5 -->\r\n<g id=\"node2\" class=\"node\"><title>n003714d39c334b8cb4a4d131c25828d5</title>\r\n<g id=\"a_node2\"><a xlink:title=\"b\">\r\n<path fill=\"#583efd\" fill-opacity=\"0.458824\" stroke=\"black\" d=\"M148,-52C148,-52 118,-52 118,-52 112,-52 106,-46 106,-40 106,-40 106,-28 106,-28 106,-22 112,-16 118,-16 118,-16 148,-16 148,-16 154,-16 160,-22 160,-28 160,-28 160,-40 160,-40 160,-46 154,-52 148,-52\"/>\r\n<text text-anchor=\"middle\" x=\"133\" y=\"-30.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">b</text>\r\n</a>\r\n</g>\r\n</g>\r\n<!-- n1600399bd4c74e4ba320348f157069cd&#45;&gt;n003714d39c334b8cb4a4d131c25828d5 -->\r\n<g id=\"edge1\" class=\"edge\"><title>n1600399bd4c74e4ba320348f157069cd&#45;&gt;n003714d39c334b8cb4a4d131c25828d5</title>\r\n<path fill=\"none\" stroke=\"black\" d=\"M70.4029,-34C78.3932,-34 87.3106,-34 95.8241,-34\"/>\r\n<polygon fill=\"black\" stroke=\"black\" points=\"95.919,-37.5001 105.919,-34 95.919,-30.5001 95.919,-37.5001\"/>\r\n</g>\r\n<!-- nf8d52281e6a64945903495847606463d -->\r\n<g id=\"node3\" class=\"node\"><title>nf8d52281e6a64945903495847606463d</title>\r\n<g id=\"a_node3\"><a xlink:title=\"c\">\r\n<path fill=\"#ff6232\" fill-opacity=\"0.227451\" stroke=\"black\" d=\"M238,-52C238,-52 208,-52 208,-52 202,-52 196,-46 196,-40 196,-40 196,-28 196,-28 196,-22 202,-16 208,-16 208,-16 238,-16 238,-16 244,-16 250,-22 250,-28 250,-28 250,-40 250,-40 250,-46 244,-52 238,-52\"/>\r\n<text text-anchor=\"middle\" x=\"223\" y=\"-30.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">c</text>\r\n</a>\r\n</g>\r\n</g>\r\n<!-- n003714d39c334b8cb4a4d131c25828d5&#45;&gt;nf8d52281e6a64945903495847606463d -->\r\n<g id=\"edge2\" class=\"edge\"><title>n003714d39c334b8cb4a4d131c25828d5&#45;&gt;nf8d52281e6a64945903495847606463d</title>\r\n<path fill=\"none\" stroke=\"black\" d=\"M160.403,-34C168.393,-34 177.311,-34 185.824,-34\"/>\r\n<polygon fill=\"black\" stroke=\"black\" points=\"185.919,-37.5001 195.919,-34 185.919,-30.5001 185.919,-37.5001\"/>\r\n</g>\r\n<!-- n02db93d3bf86444e9b4408278f0a51cf -->\r\n<g id=\"node4\" class=\"node\"><title>n02db93d3bf86444e9b4408278f0a51cf</title>\r\n<g id=\"a_node4\"><a xlink:title=\"1\">\r\n<path fill=\"#ff562c\" fill-opacity=\"0.619608\" stroke=\"black\" d=\"M58,-135C58,-135 28,-135 28,-135 22,-135 16,-129 16,-123 16,-123 16,-111 16,-111 16,-105 22,-99 28,-99 28,-99 58,-99 58,-99 64,-99 70,-105 70,-111 70,-111 70,-123 70,-123 70,-129 64,-135 58,-135\"/>\r\n<text text-anchor=\"middle\" x=\"43\" y=\"-113.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">1</text>\r\n</a>\r\n</g>\r\n</g>\r\n<!-- n1ce890132e1d4f5499a72f7c10797f9b -->\r\n<g id=\"node5\" class=\"node\"><title>n1ce890132e1d4f5499a72f7c10797f9b</title>\r\n<g id=\"a_node5\"><a xlink:title=\"2\">\r\n<path fill=\"#3176f8\" fill-opacity=\"0.509804\" stroke=\"black\" d=\"M148,-135C148,-135 118,-135 118,-135 112,-135 106,-129 106,-123 106,-123 106,-111 106,-111 106,-105 112,-99 118,-99 118,-99 148,-99 148,-99 154,-99 160,-105 160,-111 160,-111 160,-123 160,-123 160,-129 154,-135 148,-135\"/>\r\n<text text-anchor=\"middle\" x=\"133\" y=\"-113.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">2</text>\r\n</a>\r\n</g>\r\n</g>\r\n<!-- n02db93d3bf86444e9b4408278f0a51cf&#45;&gt;n1ce890132e1d4f5499a72f7c10797f9b -->\r\n<g id=\"edge3\" class=\"edge\"><title>n02db93d3bf86444e9b4408278f0a51cf&#45;&gt;n1ce890132e1d4f5499a72f7c10797f9b</title>\r\n<path fill=\"none\" stroke=\"black\" d=\"M70.4029,-117C78.3932,-117 87.3106,-117 95.8241,-117\"/>\r\n<polygon fill=\"black\" stroke=\"black\" points=\"95.919,-120.5 105.919,-117 95.919,-113.5 95.919,-120.5\"/>\r\n</g>\r\n<!-- n19d51cac713d4fbda14b1871aa3d1636 -->\r\n<g id=\"node6\" class=\"node\"><title>n19d51cac713d4fbda14b1871aa3d1636</title>\r\n<g id=\"a_node6\"><a xlink:title=\"c\">\r\n<path fill=\"#ff6232\" fill-opacity=\"0.227451\" stroke=\"black\" d=\"M238,-135C238,-135 208,-135 208,-135 202,-135 196,-129 196,-123 196,-123 196,-111 196,-111 196,-105 202,-99 208,-99 208,-99 238,-99 238,-99 244,-99 250,-105 250,-111 250,-111 250,-123 250,-123 250,-129 244,-135 238,-135\"/>\r\n<text text-anchor=\"middle\" x=\"223\" y=\"-113.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">c</text>\r\n</a>\r\n</g>\r\n</g>\r\n<!-- n1ce890132e1d4f5499a72f7c10797f9b&#45;&gt;n19d51cac713d4fbda14b1871aa3d1636 -->\r\n<g id=\"edge4\" class=\"edge\"><title>n1ce890132e1d4f5499a72f7c10797f9b&#45;&gt;n19d51cac713d4fbda14b1871aa3d1636</title>\r\n<path fill=\"none\" stroke=\"black\" d=\"M160.403,-117C168.393,-117 177.311,-117 185.824,-117\"/>\r\n<polygon fill=\"black\" stroke=\"black\" points=\"185.919,-120.5 195.919,-117 185.919,-113.5 185.919,-120.5\"/>\r\n</g>\r\n</g>\r\n</svg>\r\n",
"text/plain": "<pydot.Dot at 0x1e500cfd188>"
},
"execution_count": 64,
"metadata": {},
"output_type": "execute_result"
}
]
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "g = Dot()\ng.add_item(seq_cluster(['a','b','c'], 'clust'))\ng",
"execution_count": 65,
"outputs": [
{
"data": {
"image/svg+xml": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\r\n<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\r\n \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\r\n<!-- Generated by graphviz version 2.38.0 (20140413.2041)\r\n -->\r\n<!-- Title: G Pages: 1 -->\r\n<svg width=\"274pt\" height=\"99pt\"\r\n viewBox=\"0.00 0.00 274.00 99.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\r\n<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 95)\">\r\n<title>G</title>\r\n<polygon fill=\"white\" stroke=\"none\" points=\"-4,4 -4,-95 270,-95 270,4 -4,4\"/>\r\n<g id=\"clust1\" class=\"cluster\"><title>cluster_n4ab5953f98f043cd92750e94f02dcc41</title>\r\n<g id=\"a_clust1\"><a xlink:title=\"clust\">\r\n<path fill=\"#555555\" fill-opacity=\"0.133333\" stroke=\"black\" d=\"M20,-8C20,-8 246,-8 246,-8 252,-8 258,-14 258,-20 258,-20 258,-71 258,-71 258,-77 252,-83 246,-83 246,-83 20,-83 20,-83 14,-83 8,-77 8,-71 8,-71 8,-20 8,-20 8,-14 14,-8 20,-8\"/>\r\n<text text-anchor=\"middle\" x=\"133\" y=\"-67.8\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">clust</text>\r\n</a>\r\n</g>\r\n</g>\r\n<!-- n757e2b243c834ad082efdaef8736ec99 -->\r\n<g id=\"node1\" class=\"node\"><title>n757e2b243c834ad082efdaef8736ec99</title>\r\n<g id=\"a_node1\"><a xlink:title=\"a\">\r\n<path fill=\"#9bfba5\" fill-opacity=\"0.423529\" stroke=\"black\" d=\"M58,-52C58,-52 28,-52 28,-52 22,-52 16,-46 16,-40 16,-40 16,-28 16,-28 16,-22 22,-16 28,-16 28,-16 58,-16 58,-16 64,-16 70,-22 70,-28 70,-28 70,-40 70,-40 70,-46 64,-52 58,-52\"/>\r\n<text text-anchor=\"middle\" x=\"43\" y=\"-30.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">a</text>\r\n</a>\r\n</g>\r\n</g>\r\n<!-- n18fe5b44dddc4410807d19d95c59d3b7 -->\r\n<g id=\"node2\" class=\"node\"><title>n18fe5b44dddc4410807d19d95c59d3b7</title>\r\n<g id=\"a_node2\"><a xlink:title=\"b\">\r\n<path fill=\"#583efd\" fill-opacity=\"0.458824\" stroke=\"black\" d=\"M148,-52C148,-52 118,-52 118,-52 112,-52 106,-46 106,-40 106,-40 106,-28 106,-28 106,-22 112,-16 118,-16 118,-16 148,-16 148,-16 154,-16 160,-22 160,-28 160,-28 160,-40 160,-40 160,-46 154,-52 148,-52\"/>\r\n<text text-anchor=\"middle\" x=\"133\" y=\"-30.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">b</text>\r\n</a>\r\n</g>\r\n</g>\r\n<!-- n757e2b243c834ad082efdaef8736ec99&#45;&gt;n18fe5b44dddc4410807d19d95c59d3b7 -->\r\n<g id=\"edge1\" class=\"edge\"><title>n757e2b243c834ad082efdaef8736ec99&#45;&gt;n18fe5b44dddc4410807d19d95c59d3b7</title>\r\n<path fill=\"none\" stroke=\"black\" d=\"M70.4029,-34C78.3932,-34 87.3106,-34 95.8241,-34\"/>\r\n<polygon fill=\"black\" stroke=\"black\" points=\"95.919,-37.5001 105.919,-34 95.919,-30.5001 95.919,-37.5001\"/>\r\n</g>\r\n<!-- n16e7fe2d761d4e8ea2bc51a62d46fe39 -->\r\n<g id=\"node3\" class=\"node\"><title>n16e7fe2d761d4e8ea2bc51a62d46fe39</title>\r\n<g id=\"a_node3\"><a xlink:title=\"c\">\r\n<path fill=\"#ff6232\" fill-opacity=\"0.227451\" stroke=\"black\" d=\"M238,-52C238,-52 208,-52 208,-52 202,-52 196,-46 196,-40 196,-40 196,-28 196,-28 196,-22 202,-16 208,-16 208,-16 238,-16 238,-16 244,-16 250,-22 250,-28 250,-28 250,-40 250,-40 250,-46 244,-52 238,-52\"/>\r\n<text text-anchor=\"middle\" x=\"223\" y=\"-30.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">c</text>\r\n</a>\r\n</g>\r\n</g>\r\n<!-- n18fe5b44dddc4410807d19d95c59d3b7&#45;&gt;n16e7fe2d761d4e8ea2bc51a62d46fe39 -->\r\n<g id=\"edge2\" class=\"edge\"><title>n18fe5b44dddc4410807d19d95c59d3b7&#45;&gt;n16e7fe2d761d4e8ea2bc51a62d46fe39</title>\r\n<path fill=\"none\" stroke=\"black\" d=\"M160.403,-34C168.393,-34 177.311,-34 185.824,-34\"/>\r\n<polygon fill=\"black\" stroke=\"black\" points=\"185.919,-37.5001 195.919,-34 185.919,-30.5001 185.919,-37.5001\"/>\r\n</g>\r\n</g>\r\n</svg>\r\n",
"text/plain": "<pydot.Dot at 0x1e500c98608>"
},
"execution_count": 65,
"metadata": {},
"output_type": "execute_result"
}
]
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "sg1 = seq_cluster(['a','b','c'], 'clust1')\nsg2 = seq_cluster(['a1','a2',sg1], 'clust2')\ng = Dot()\ng.add_item(sg2)\ng",
"execution_count": 66,
"outputs": [
{
"data": {
"image/svg+xml": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\r\n<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\r\n \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\r\n<!-- Generated by graphviz version 2.38.0 (20140413.2041)\r\n -->\r\n<!-- Title: G Pages: 1 -->\r\n<svg width=\"462pt\" height=\"138pt\"\r\n viewBox=\"0.00 0.00 462.00 138.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\r\n<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 134)\">\r\n<title>G</title>\r\n<polygon fill=\"white\" stroke=\"none\" points=\"-4,4 -4,-134 458,-134 458,4 -4,4\"/>\r\n<g id=\"clust1\" class=\"cluster\"><title>cluster_n86db42b225474bfba1a333a9859edba3</title>\r\n<g id=\"a_clust1\"><a xlink:title=\"clust2\">\r\n<path fill=\"#555555\" fill-opacity=\"0.133333\" stroke=\"black\" d=\"M20,-8C20,-8 434,-8 434,-8 440,-8 446,-14 446,-20 446,-20 446,-110 446,-110 446,-116 440,-122 434,-122 434,-122 20,-122 20,-122 14,-122 8,-116 8,-110 8,-110 8,-20 8,-20 8,-14 14,-8 20,-8\"/>\r\n<text text-anchor=\"middle\" x=\"227\" y=\"-106.8\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">clust2</text>\r\n</a>\r\n</g>\r\n</g>\r\n<g id=\"clust2\" class=\"cluster\"><title>cluster_n88a2531a72694320987f5312fb1bc4a1</title>\r\n<g id=\"a_clust2\"><a xlink:title=\"clust1\">\r\n<path fill=\"#555555\" fill-opacity=\"0.133333\" stroke=\"black\" d=\"M200,-16C200,-16 426,-16 426,-16 432,-16 438,-22 438,-28 438,-28 438,-79 438,-79 438,-85 432,-91 426,-91 426,-91 200,-91 200,-91 194,-91 188,-85 188,-79 188,-79 188,-28 188,-28 188,-22 194,-16 200,-16\"/>\r\n<text text-anchor=\"middle\" x=\"313\" y=\"-75.8\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">clust1</text>\r\n</a>\r\n</g>\r\n</g>\r\n<!-- n933863f287a94cfe95990a1697ae6d87 -->\r\n<g id=\"node1\" class=\"node\"><title>n933863f287a94cfe95990a1697ae6d87</title>\r\n<g id=\"a_node1\"><a xlink:title=\"a1\">\r\n<path fill=\"#cee184\" fill-opacity=\"0.384314\" stroke=\"black\" d=\"M58,-60C58,-60 28,-60 28,-60 22,-60 16,-54 16,-48 16,-48 16,-36 16,-36 16,-30 22,-24 28,-24 28,-24 58,-24 58,-24 64,-24 70,-30 70,-36 70,-36 70,-48 70,-48 70,-54 64,-60 58,-60\"/>\r\n<text text-anchor=\"middle\" x=\"43\" y=\"-38.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">a1</text>\r\n</a>\r\n</g>\r\n</g>\r\n<!-- n7c23dc98b71846a2a2dab760ab83129f -->\r\n<g id=\"node2\" class=\"node\"><title>n7c23dc98b71846a2a2dab760ab83129f</title>\r\n<g id=\"a_node2\"><a xlink:title=\"a2\">\r\n<path fill=\"#0ca7ef\" fill-opacity=\"0.592157\" stroke=\"black\" d=\"M148,-60C148,-60 118,-60 118,-60 112,-60 106,-54 106,-48 106,-48 106,-36 106,-36 106,-30 112,-24 118,-24 118,-24 148,-24 148,-24 154,-24 160,-30 160,-36 160,-36 160,-48 160,-48 160,-54 154,-60 148,-60\"/>\r\n<text text-anchor=\"middle\" x=\"133\" y=\"-38.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">a2</text>\r\n</a>\r\n</g>\r\n</g>\r\n<!-- n933863f287a94cfe95990a1697ae6d87&#45;&gt;n7c23dc98b71846a2a2dab760ab83129f -->\r\n<g id=\"edge3\" class=\"edge\"><title>n933863f287a94cfe95990a1697ae6d87&#45;&gt;n7c23dc98b71846a2a2dab760ab83129f</title>\r\n<path fill=\"none\" stroke=\"black\" d=\"M70.4029,-42C78.3932,-42 87.3106,-42 95.8241,-42\"/>\r\n<polygon fill=\"black\" stroke=\"black\" points=\"95.919,-45.5001 105.919,-42 95.919,-38.5001 95.919,-45.5001\"/>\r\n</g>\r\n<!-- n2649fee7b2044373a38b2c197b841c95 -->\r\n<g id=\"node3\" class=\"node\"><title>n2649fee7b2044373a38b2c197b841c95</title>\r\n<g id=\"a_node3\"><a xlink:title=\"a\">\r\n<path fill=\"#9bfba5\" fill-opacity=\"0.423529\" stroke=\"black\" d=\"M238,-60C238,-60 208,-60 208,-60 202,-60 196,-54 196,-48 196,-48 196,-36 196,-36 196,-30 202,-24 208,-24 208,-24 238,-24 238,-24 244,-24 250,-30 250,-36 250,-36 250,-48 250,-48 250,-54 244,-60 238,-60\"/>\r\n<text text-anchor=\"middle\" x=\"223\" y=\"-38.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">a</text>\r\n</a>\r\n</g>\r\n</g>\r\n<!-- n7c23dc98b71846a2a2dab760ab83129f&#45;&gt;n2649fee7b2044373a38b2c197b841c95 -->\r\n<g id=\"edge4\" class=\"edge\"><title>n7c23dc98b71846a2a2dab760ab83129f&#45;&gt;n2649fee7b2044373a38b2c197b841c95</title>\r\n<path fill=\"none\" stroke=\"black\" d=\"M160.403,-42C168.393,-42 177.311,-42 185.824,-42\"/>\r\n<polygon fill=\"black\" stroke=\"black\" points=\"178,-45.5005 188,-42 178,-38.5005 178,-45.5005\"/>\r\n</g>\r\n<!-- n1093035be3f540b1b4632f6c72124bcb -->\r\n<g id=\"node4\" class=\"node\"><title>n1093035be3f540b1b4632f6c72124bcb</title>\r\n<g id=\"a_node4\"><a xlink:title=\"b\">\r\n<path fill=\"#583efd\" fill-opacity=\"0.458824\" stroke=\"black\" d=\"M328,-60C328,-60 298,-60 298,-60 292,-60 286,-54 286,-48 286,-48 286,-36 286,-36 286,-30 292,-24 298,-24 298,-24 328,-24 328,-24 334,-24 340,-30 340,-36 340,-36 340,-48 340,-48 340,-54 334,-60 328,-60\"/>\r\n<text text-anchor=\"middle\" x=\"313\" y=\"-38.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">b</text>\r\n</a>\r\n</g>\r\n</g>\r\n<!-- n2649fee7b2044373a38b2c197b841c95&#45;&gt;n1093035be3f540b1b4632f6c72124bcb -->\r\n<g id=\"edge1\" class=\"edge\"><title>n2649fee7b2044373a38b2c197b841c95&#45;&gt;n1093035be3f540b1b4632f6c72124bcb</title>\r\n<path fill=\"none\" stroke=\"black\" d=\"M250.403,-42C258.393,-42 267.311,-42 275.824,-42\"/>\r\n<polygon fill=\"black\" stroke=\"black\" points=\"275.919,-45.5001 285.919,-42 275.919,-38.5001 275.919,-45.5001\"/>\r\n</g>\r\n<!-- nb25917515bad475ea3f1c4f3999f2b4c -->\r\n<g id=\"node5\" class=\"node\"><title>nb25917515bad475ea3f1c4f3999f2b4c</title>\r\n<g id=\"a_node5\"><a xlink:title=\"c\">\r\n<path fill=\"#ff6232\" fill-opacity=\"0.227451\" stroke=\"black\" d=\"M418,-60C418,-60 388,-60 388,-60 382,-60 376,-54 376,-48 376,-48 376,-36 376,-36 376,-30 382,-24 388,-24 388,-24 418,-24 418,-24 424,-24 430,-30 430,-36 430,-36 430,-48 430,-48 430,-54 424,-60 418,-60\"/>\r\n<text text-anchor=\"middle\" x=\"403\" y=\"-38.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">c</text>\r\n</a>\r\n</g>\r\n</g>\r\n<!-- n1093035be3f540b1b4632f6c72124bcb&#45;&gt;nb25917515bad475ea3f1c4f3999f2b4c -->\r\n<g id=\"edge2\" class=\"edge\"><title>n1093035be3f540b1b4632f6c72124bcb&#45;&gt;nb25917515bad475ea3f1c4f3999f2b4c</title>\r\n<path fill=\"none\" stroke=\"black\" d=\"M340.403,-42C348.393,-42 357.311,-42 365.824,-42\"/>\r\n<polygon fill=\"black\" stroke=\"black\" points=\"365.919,-45.5001 375.919,-42 365.919,-38.5001 365.919,-45.5001\"/>\r\n</g>\r\n</g>\r\n</svg>\r\n",
"text/plain": "<pydot.Dot at 0x1e500d3f808>"
},
"execution_count": 66,
"metadata": {},
"output_type": "execute_result"
}
]
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "sg1 = seq_cluster(['inp'], 'clust1')\nsg2 = seq_cluster(['a','b','c'], 'clust2')\nsg2.add_items(sg1.connect(sg2[-1]), sg1.connect(sg2))\ng = Dot()\ng.add_items(sg1,sg2)\ng",
"execution_count": 67,
"outputs": [
{
"data": {
"image/svg+xml": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\r\n<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\r\n \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\r\n<!-- Generated by graphviz version 2.38.0 (20140413.2041)\r\n -->\r\n<!-- Title: G Pages: 1 -->\r\n<svg width=\"364pt\" height=\"111pt\"\r\n viewBox=\"0.00 0.00 364.00 111.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\r\n<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 107)\">\r\n<title>G</title>\r\n<polygon fill=\"white\" stroke=\"none\" points=\"-4,4 -4,-107 360,-107 360,4 -4,4\"/>\r\n<g id=\"clust1\" class=\"cluster\"><title>cluster_n2a43295f85784ad587280112ec3c0e92</title>\r\n<g id=\"a_clust1\"><a xlink:title=\"clust1\">\r\n<path fill=\"#555555\" fill-opacity=\"0.133333\" stroke=\"black\" d=\"M20,-8C20,-8 66,-8 66,-8 72,-8 78,-14 78,-20 78,-20 78,-71 78,-71 78,-77 72,-83 66,-83 66,-83 20,-83 20,-83 14,-83 8,-77 8,-71 8,-71 8,-20 8,-20 8,-14 14,-8 20,-8\"/>\r\n<text text-anchor=\"middle\" x=\"43\" y=\"-67.8\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">clust1</text>\r\n</a>\r\n</g>\r\n</g>\r\n<g id=\"clust2\" class=\"cluster\"><title>cluster_n173d2165a5554c8ab6c688af8381fc73</title>\r\n<g id=\"a_clust2\"><a xlink:title=\"clust2\">\r\n<path fill=\"#555555\" fill-opacity=\"0.133333\" stroke=\"black\" d=\"M110,-20C110,-20 336,-20 336,-20 342,-20 348,-26 348,-32 348,-32 348,-83 348,-83 348,-89 342,-95 336,-95 336,-95 110,-95 110,-95 104,-95 98,-89 98,-83 98,-83 98,-32 98,-32 98,-26 104,-20 110,-20\"/>\r\n<text text-anchor=\"middle\" x=\"223\" y=\"-79.8\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">clust2</text>\r\n</a>\r\n</g>\r\n</g>\r\n<!-- n252d45a7f1484aaf800ae8574aa07ce2 -->\r\n<g id=\"node1\" class=\"node\"><title>n252d45a7f1484aaf800ae8574aa07ce2</title>\r\n<g id=\"a_node1\"><a xlink:title=\"inp\">\r\n<path fill=\"#ff8e4a\" fill-opacity=\"0.666667\" stroke=\"black\" d=\"M58,-52C58,-52 28,-52 28,-52 22,-52 16,-46 16,-40 16,-40 16,-28 16,-28 16,-22 22,-16 28,-16 28,-16 58,-16 58,-16 64,-16 70,-22 70,-28 70,-28 70,-40 70,-40 70,-46 64,-52 58,-52\"/>\r\n<text text-anchor=\"middle\" x=\"43\" y=\"-30.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">inp</text>\r\n</a>\r\n</g>\r\n</g>\r\n<!-- nb0c56ea0294843a3a6bb9969b3fb445e -->\r\n<g id=\"node2\" class=\"node\"><title>nb0c56ea0294843a3a6bb9969b3fb445e</title>\r\n<g id=\"a_node2\"><a xlink:title=\"a\">\r\n<path fill=\"#9bfba5\" fill-opacity=\"0.423529\" stroke=\"black\" d=\"M148,-64C148,-64 118,-64 118,-64 112,-64 106,-58 106,-52 106,-52 106,-40 106,-40 106,-34 112,-28 118,-28 118,-28 148,-28 148,-28 154,-28 160,-34 160,-40 160,-40 160,-52 160,-52 160,-58 154,-64 148,-64\"/>\r\n<text text-anchor=\"middle\" x=\"133\" y=\"-42.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">a</text>\r\n</a>\r\n</g>\r\n</g>\r\n<!-- n252d45a7f1484aaf800ae8574aa07ce2&#45;&gt;nb0c56ea0294843a3a6bb9969b3fb445e -->\r\n<g id=\"edge4\" class=\"edge\"><title>n252d45a7f1484aaf800ae8574aa07ce2&#45;&gt;nb0c56ea0294843a3a6bb9969b3fb445e</title>\r\n<path fill=\"none\" stroke=\"black\" d=\"M77.7296,-38.5995C83.6523,-39.4071 89.838,-40.2506 95.8241,-41.0669\"/>\r\n<polygon fill=\"black\" stroke=\"black\" points=\"87.5495,-43.1865 98,-41.4435 88.7435,-36.2891 87.5495,-43.1865\"/>\r\n</g>\r\n<!-- na35cd38fb8424e4887b45d7e28275fdc -->\r\n<g id=\"node4\" class=\"node\"><title>na35cd38fb8424e4887b45d7e28275fdc</title>\r\n<g id=\"a_node4\"><a xlink:title=\"c\">\r\n<path fill=\"#ff6232\" fill-opacity=\"0.227451\" stroke=\"black\" d=\"M328,-64C328,-64 298,-64 298,-64 292,-64 286,-58 286,-52 286,-52 286,-40 286,-40 286,-34 292,-28 298,-28 298,-28 328,-28 328,-28 334,-28 340,-34 340,-40 340,-40 340,-52 340,-52 340,-58 334,-64 328,-64\"/>\r\n<text text-anchor=\"middle\" x=\"313\" y=\"-42.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">c</text>\r\n</a>\r\n</g>\r\n</g>\r\n<!-- n252d45a7f1484aaf800ae8574aa07ce2&#45;&gt;na35cd38fb8424e4887b45d7e28275fdc -->\r\n<g id=\"edge3\" class=\"edge\"><title>n252d45a7f1484aaf800ae8574aa07ce2&#45;&gt;na35cd38fb8424e4887b45d7e28275fdc</title>\r\n<path fill=\"none\" stroke=\"black\" d=\"M77.6974,-23.1332C84.3587,-21.4144 91.3478,-19.9067 98,-19 164.937,-9.87599 183.864,-5.2242 250,-19 258.935,-20.8612 268.161,-24.082 276.678,-27.6649\"/>\r\n<polygon fill=\"black\" stroke=\"black\" points=\"275.381,-30.9189 285.938,-31.8109 278.241,-24.53 275.381,-30.9189\"/>\r\n</g>\r\n<!-- nb9676250af204f3080e1295bbf2f800d -->\r\n<g id=\"node3\" class=\"node\"><title>nb9676250af204f3080e1295bbf2f800d</title>\r\n<g id=\"a_node3\"><a xlink:title=\"b\">\r\n<path fill=\"#583efd\" fill-opacity=\"0.458824\" stroke=\"black\" d=\"M238,-64C238,-64 208,-64 208,-64 202,-64 196,-58 196,-52 196,-52 196,-40 196,-40 196,-34 202,-28 208,-28 208,-28 238,-28 238,-28 244,-28 250,-34 250,-40 250,-40 250,-52 250,-52 250,-58 244,-64 238,-64\"/>\r\n<text text-anchor=\"middle\" x=\"223\" y=\"-42.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">b</text>\r\n</a>\r\n</g>\r\n</g>\r\n<!-- nb0c56ea0294843a3a6bb9969b3fb445e&#45;&gt;nb9676250af204f3080e1295bbf2f800d -->\r\n<g id=\"edge1\" class=\"edge\"><title>nb0c56ea0294843a3a6bb9969b3fb445e&#45;&gt;nb9676250af204f3080e1295bbf2f800d</title>\r\n<path fill=\"none\" stroke=\"black\" d=\"M160.403,-46C168.393,-46 177.311,-46 185.824,-46\"/>\r\n<polygon fill=\"black\" stroke=\"black\" points=\"185.919,-49.5001 195.919,-46 185.919,-42.5001 185.919,-49.5001\"/>\r\n</g>\r\n<!-- nb9676250af204f3080e1295bbf2f800d&#45;&gt;na35cd38fb8424e4887b45d7e28275fdc -->\r\n<g id=\"edge2\" class=\"edge\"><title>nb9676250af204f3080e1295bbf2f800d&#45;&gt;na35cd38fb8424e4887b45d7e28275fdc</title>\r\n<path fill=\"none\" stroke=\"black\" d=\"M250.403,-46C258.393,-46 267.311,-46 275.824,-46\"/>\r\n<polygon fill=\"black\" stroke=\"black\" points=\"275.919,-49.5001 285.919,-46 275.919,-42.5001 275.919,-49.5001\"/>\r\n</g>\r\n</g>\r\n</svg>\r\n",
"text/plain": "<pydot.Dot at 0x1e500dc7a08>"
},
"execution_count": 67,
"metadata": {},
"output_type": "execute_result"
}
]
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "# export\ndef Point(label='pnt', **kwargs):\n \"Create a `Node` with a 'point' shape\"\n return (Node('pnt', shape='point'))",
"execution_count": 68,
"outputs": []
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "sg = Cluster('clus')\na,b,c = sg.add_items('a','b','c')\np = sg.add_item(Point())\nsg.add_item(p.connect(c))\nsg.add_items(p.connect(a), a.connect(b), b.connect(c))\n\ng = Dot()\ng.add_items(sg)\ng",
"execution_count": 69,
"outputs": [
{
"data": {
"image/svg+xml": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\r\n<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\r\n \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\r\n<!-- Generated by graphviz version 2.38.0 (20140413.2041)\r\n -->\r\n<!-- Title: G Pages: 1 -->\r\n<svg width=\"314pt\" height=\"119pt\"\r\n viewBox=\"0.00 0.00 313.60 119.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\r\n<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 115)\">\r\n<title>G</title>\r\n<polygon fill=\"white\" stroke=\"none\" points=\"-4,4 -4,-115 309.6,-115 309.6,4 -4,4\"/>\r\n<g id=\"clust1\" class=\"cluster\"><title>cluster_n2547236312244e518b99e437e53dc513</title>\r\n<g id=\"a_clust1\"><a xlink:title=\"clus\">\r\n<path fill=\"#555555\" fill-opacity=\"0.133333\" stroke=\"black\" d=\"M20,-8C20,-8 285.6,-8 285.6,-8 291.6,-8 297.6,-14 297.6,-20 297.6,-20 297.6,-91 297.6,-91 297.6,-97 291.6,-103 285.6,-103 285.6,-103 20,-103 20,-103 14,-103 8,-97 8,-91 8,-91 8,-20 8,-20 8,-14 14,-8 20,-8\"/>\r\n<text text-anchor=\"middle\" x=\"152.8\" y=\"-87.8\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">clus</text>\r\n</a>\r\n</g>\r\n</g>\r\n<!-- n7ed0fc186e5e453d85b47b0d266ef6c7 -->\r\n<g id=\"node1\" class=\"node\"><title>n7ed0fc186e5e453d85b47b0d266ef6c7</title>\r\n<g id=\"a_node1\"><a xlink:title=\"a\">\r\n<path fill=\"#9bfba5\" fill-opacity=\"0.423529\" stroke=\"black\" d=\"M97.6,-52C97.6,-52 67.6,-52 67.6,-52 61.6,-52 55.6,-46 55.6,-40 55.6,-40 55.6,-28 55.6,-28 55.6,-22 61.6,-16 67.6,-16 67.6,-16 97.6,-16 97.6,-16 103.6,-16 109.6,-22 109.6,-28 109.6,-28 109.6,-40 109.6,-40 109.6,-46 103.6,-52 97.6,-52\"/>\r\n<text text-anchor=\"middle\" x=\"82.6\" y=\"-30.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">a</text>\r\n</a>\r\n</g>\r\n</g>\r\n<!-- n04789dc84b7c448a92fa8041a1ead17f -->\r\n<g id=\"node2\" class=\"node\"><title>n04789dc84b7c448a92fa8041a1ead17f</title>\r\n<g id=\"a_node2\"><a xlink:title=\"b\">\r\n<path fill=\"#583efd\" fill-opacity=\"0.458824\" stroke=\"black\" d=\"M187.6,-52C187.6,-52 157.6,-52 157.6,-52 151.6,-52 145.6,-46 145.6,-40 145.6,-40 145.6,-28 145.6,-28 145.6,-22 151.6,-16 157.6,-16 157.6,-16 187.6,-16 187.6,-16 193.6,-16 199.6,-22 199.6,-28 199.6,-28 199.6,-40 199.6,-40 199.6,-46 193.6,-52 187.6,-52\"/>\r\n<text text-anchor=\"middle\" x=\"172.6\" y=\"-30.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">b</text>\r\n</a>\r\n</g>\r\n</g>\r\n<!-- n7ed0fc186e5e453d85b47b0d266ef6c7&#45;&gt;n04789dc84b7c448a92fa8041a1ead17f -->\r\n<g id=\"edge3\" class=\"edge\"><title>n7ed0fc186e5e453d85b47b0d266ef6c7&#45;&gt;n04789dc84b7c448a92fa8041a1ead17f</title>\r\n<path fill=\"none\" stroke=\"black\" d=\"M110.003,-34C117.993,-34 126.911,-34 135.424,-34\"/>\r\n<polygon fill=\"black\" stroke=\"black\" points=\"135.519,-37.5001 145.519,-34 135.519,-30.5001 135.519,-37.5001\"/>\r\n</g>\r\n<!-- n84a2e724d190437cbab65f20224da84a -->\r\n<g id=\"node3\" class=\"node\"><title>n84a2e724d190437cbab65f20224da84a</title>\r\n<g id=\"a_node3\"><a xlink:title=\"c\">\r\n<path fill=\"#ff6232\" fill-opacity=\"0.227451\" stroke=\"black\" d=\"M277.6,-62C277.6,-62 247.6,-62 247.6,-62 241.6,-62 235.6,-56 235.6,-50 235.6,-50 235.6,-38 235.6,-38 235.6,-32 241.6,-26 247.6,-26 247.6,-26 277.6,-26 277.6,-26 283.6,-26 289.6,-32 289.6,-38 289.6,-38 289.6,-50 289.6,-50 289.6,-56 283.6,-62 277.6,-62\"/>\r\n<text text-anchor=\"middle\" x=\"262.6\" y=\"-40.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">c</text>\r\n</a>\r\n</g>\r\n</g>\r\n<!-- n04789dc84b7c448a92fa8041a1ead17f&#45;&gt;n84a2e724d190437cbab65f20224da84a -->\r\n<g id=\"edge4\" class=\"edge\"><title>n04789dc84b7c448a92fa8041a1ead17f&#45;&gt;n84a2e724d190437cbab65f20224da84a</title>\r\n<path fill=\"none\" stroke=\"black\" d=\"M200.003,-37.0003C207.993,-37.9083 216.911,-38.9217 225.424,-39.8891\"/>\r\n<polygon fill=\"black\" stroke=\"black\" points=\"225.188,-43.3847 235.519,-41.0362 225.978,-36.4294 225.188,-43.3847\"/>\r\n</g>\r\n<!-- nba378858c2654667ba7833c20ac11bee -->\r\n<g id=\"node4\" class=\"node\"><title>nba378858c2654667ba7833c20ac11bee</title>\r\n<g id=\"a_node4\"><a xlink:title=\"pnt\">\r\n<ellipse fill=\"#ff2613\" fill-opacity=\"0.682353\" stroke=\"black\" cx=\"17.8\" cy=\"-52\" rx=\"1.8\" ry=\"1.8\"/>\r\n</a>\r\n</g>\r\n</g>\r\n<!-- nba378858c2654667ba7833c20ac11bee&#45;&gt;n7ed0fc186e5e453d85b47b0d266ef6c7 -->\r\n<g id=\"edge2\" class=\"edge\"><title>nba378858c2654667ba7833c20ac11bee&#45;&gt;n7ed0fc186e5e453d85b47b0d266ef6c7</title>\r\n<path fill=\"none\" stroke=\"black\" d=\"M19.89,-51.6876C23.2748,-50.7174 34.0781,-47.6209 45.7202,-44.284\"/>\r\n<polygon fill=\"black\" stroke=\"black\" points=\"46.9039,-47.5858 55.5525,-41.4659 44.9751,-40.8567 46.9039,-47.5858\"/>\r\n</g>\r\n<!-- nba378858c2654667ba7833c20ac11bee&#45;&gt;n84a2e724d190437cbab65f20224da84a -->\r\n<g id=\"edge1\" class=\"edge\"><title>nba378858c2654667ba7833c20ac11bee&#45;&gt;n84a2e724d190437cbab65f20224da84a</title>\r\n<path fill=\"none\" stroke=\"black\" d=\"M19.6956,-52.3041C23.7682,-53.6687 40.9729,-59.2373 55.6,-61 119.14,-68.657 136.172,-69.5382 199.6,-61 208.093,-59.8567 217.069,-57.87 225.474,-55.6486\"/>\r\n<polygon fill=\"black\" stroke=\"black\" points=\"226.694,-58.9413 235.372,-52.8635 224.798,-52.203 226.694,-58.9413\"/>\r\n</g>\r\n</g>\r\n</svg>\r\n",
"text/plain": "<pydot.Dot at 0x1e500e4e9c8>"
},
"execution_count": 69,
"metadata": {},
"output_type": "execute_result"
}
]
},
{
"metadata": {},
"cell_type": "markdown",
"source": "# Export -"
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "#hide\nfrom nbdev.export import notebook2script\nnotebook2script()",
"execution_count": 70,
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": "Converted 00_core.ipynb.\nConverted index.ipynb.\n"
}
]
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "",
"execution_count": null,
"outputs": []
}
],
"metadata": {
"kernelspec": {
"name": "python3",
"display_name": "Python 3",
"language": "python"
},
"jupytext": {
"formats": "ipynb,py:light"
},
"language_info": {
"name": "python",
"version": "3.7.4",
"mimetype": "text/x-python",
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"pygments_lexer": "ipython3",
"nbconvert_exporter": "python",
"file_extension": ".py"
},
"toc": {
"nav_menu": {},
"number_sections": true,
"sideBar": true,
"skip_h1_title": false,
"base_numbering": 1,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {},
"toc_section_display": true,
"toc_window_display": true
},
"gist": {
"id": "",
"data": {
"description": "/00_core.ipynb",
"public": true
}
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment