{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# heterograph: visualisation\n", "\n", "HGraph can be visualized using a built-in web app. As an example, consider the following graph:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "tags": [ "nbval-ignore-output" ] }, "outputs": [], "source": [ "from heterograph import *\n", "\n", "g=HGraph()\n", "g.add_vx(6)\n", "g.add_edge(0, [1,2,3])\n", "g.add_edge([1, 2, 3], 4)\n", "g.add_edge(4, 5);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## rendering\n", "\n", "### single graph\n", "To simplest way to visualise a graph, is to use the `view(host='0.0.0.0', port='8888')` method. This launches a web app that can be accessed at `http://localhost:8888`. The web app allows zooming and panning. Note that, when this method is invoked inside a Jupyter Notebook, the graph is displayed directly within the notebook." ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "tags": [ "nbval-ignore-output" ] }, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "0\n", "\n", "0\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "\n", "\n", "\n", "2\n", "\n", "2\n", "\n", "\n", "\n", "0->2\n", "\n", "\n", "\n", "\n", "\n", "3\n", "\n", "3\n", "\n", "\n", "\n", "0->3\n", "\n", "\n", "\n", "\n", "\n", "4\n", "\n", "4\n", "\n", "\n", "\n", "1->4\n", "\n", "\n", "\n", "\n", "\n", "2->4\n", "\n", "\n", "\n", "\n", "\n", "3->4\n", "\n", "\n", "\n", "\n", "\n", "5\n", "\n", "5\n", "\n", "\n", "\n", "4->5\n", "\n", "\n", "\n", "\n", "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "g.view()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### multiple graphs\n", "\n", "The web application is capable of visualizing multiple graphs. To do this, we first need to create an instance of the `WebView` object, and then proceed to add the graphs to it." ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "tags": [ "nbval-ignore-output" ] }, "outputs": [ { "data": { "text/html": [ "

graph g

" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "0\n", "\n", "0\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "\n", "\n", "\n", "2\n", "\n", "2\n", "\n", "\n", "\n", "0->2\n", "\n", "\n", "\n", "\n", "\n", "3\n", "\n", "3\n", "\n", "\n", "\n", "0->3\n", "\n", "\n", "\n", "\n", "\n", "4\n", "\n", "4\n", "\n", "\n", "\n", "1->4\n", "\n", "\n", "\n", "\n", "\n", "2->4\n", "\n", "\n", "\n", "\n", "\n", "3->4\n", "\n", "\n", "\n", "\n", "\n", "5\n", "\n", "5\n", "\n", "\n", "\n", "4->5\n", "\n", "\n", "\n", "\n", "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "

graph h

" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "0\n", "\n", "0\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "\n", "\n", "\n", "2\n", "\n", "2\n", "\n", "\n", "\n", "0->2\n", "\n", "\n", "\n", "\n", "\n", "3\n", "\n", "3\n", "\n", "\n", "\n", "0->3\n", "\n", "\n", "\n", "\n", "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# copy part of the graph\n", "h = g.copy(vs=[0, 1, 2, 3])\n", "\n", "viewer=WebView()\n", "viewer.add_graph(g, title=\"graph g\")\n", "viewer.add_graph(h, title=\"graph h\")\n", "viewer.run()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "When running this code on a web browser (default: http://localhost:8888), the following screen appears:\n", "\n", "\n", "\n", "## graph styles\n", "\n", "We can customize the rendering of the graphs by modifying the style attributes of the graph, vertex, and edge elements. Since the graphs are rendered using Graphviz, most of the attributes described in the [Graphviz documentation](https://graphviz.org/doc/info/attrs.html) are supported.\n", "\n", "Styles can be directly encoded in an `HGraph` instance using the following properties:\n", " - `g.style`: This property controls the style attributes of the graph.\n", " - `g.vstyle`: This property controls the style attributes of the vertices.\n", " - `g.estyle`: This property controls the style attributes of the edges.\n", "\n", "Each of these properties is a key-value pair structure similar to a `dict` (however, behaves differently when updating), where the key is the attribute name and the value is the corresponding attribute value. It is important to note that unlike property maps, there is only one global `vstyle` and `estyle` data structure that applies to all vertices and edges. However, as we shall see later, it is possible to customize these for specific vertices and edges.\n", "\n", "### getting and setting styles" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "tags": [ "nbval-ignore-output" ] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "default graph styles:\n", "\t=> {'layout': 'dot', 'rankdir': 'TD', 'nclusters': '2', 'cluster': at 0x7fbd1a0c2700>}\n", "default vertex styles:\n", "\t=> {'shape': 'Mrecord', 'style': 'filled', 'fillcolor': '#99CCFF', 'label': at 0x7fbd1a2723e0>, 'cluster': at 0x7fbd1a0c27a0>}\n", "default edge styles:\n", "\t=> {'color': None, 'arrowhead': 'open', 'penwidth': '1', 'label': None}\n" ] } ], "source": [ "print(f\"default graph styles:\\n\\t=> {g.style}\")\n", "print(f\"default vertex styles:\\n\\t=> {g.vstyle}\")\n", "print(f\"default edge styles:\\n\\t=> {g.estyle}\")\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "These three properties function similarly to a `dict`. However, when you set a property using a `dict`, it doesn't overwrite the existing values. Instead, it updates the value if the key already exists, or adds a new key-value pair if it doesn't. Let's add an edge [penwidth](https://graphviz.org/docs/attrs/penwidth/) of \"2\" and change the color to red.\n", "\n", "**Notes**:\n", "- to set the [v|e]style properties to empty (`{}`), you must set them to `None`.\n", "- setting an attribute value to '' or `None` will apply the default Graphviz attribute value (refer to the [manual](https://graphviz.org/doc/info/attrs.html) for more details)." ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "tags": [ "nbval-ignore-output" ] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'color': 'red', 'arrowhead': 'open', 'penwidth': '3', 'label': None}\n" ] }, { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "cluster_0\n", "\n", "cluster: 0\n", "\n", "\n", "cluster_1\n", "\n", "cluster: 1\n", "\n", "\n", "\n", "0\n", "\n", "A\n", "\n", "in:0\n", "\n", "out:3\n", "\n", "id:0\n", "\n", "\n", "\n", "1\n", "\n", "B\n", "\n", "in:1\n", "\n", "out:1\n", "\n", "id:1\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "\n", "\n", "\n", "2\n", "\n", "C\n", "\n", "in:1\n", "\n", "out:1\n", "\n", "id:2\n", "\n", "\n", "\n", "0->2\n", "\n", "\n", "\n", "\n", "\n", "3\n", "\n", "D\n", "\n", "in:1\n", "\n", "out:1\n", "\n", "id:3\n", "\n", "\n", "\n", "0->3\n", "\n", "\n", "\n", "\n", "\n", "4\n", "\n", "E\n", "\n", "in:3\n", "\n", "out:1\n", "\n", "id:4\n", "\n", "\n", "\n", "1->4\n", "\n", "\n", "\n", "\n", "\n", "2->4\n", "\n", "\n", "\n", "\n", "\n", "3->4\n", "\n", "\n", "\n", "\n", "\n", "5\n", "\n", "F\n", "\n", "in:1\n", "\n", "out:0\n", "\n", "id:5\n", "\n", "\n", "\n", "4->5\n", "\n", "\n", "\n", "\n", "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "g.estyle = {'color':'red', 'penwidth': '3'}\n", "print(g.estyle) # arrowhead is still present\n", "g.view()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### static attribute values\n", "\n", "Static attribute values are **string** constants. When used for vertex or edge styles, they apply to all vertices and edges, respectively. In the example above, `penwidth` has a static value. Note that all static values must be defined as strings, even when considering integer and floating-point values.\n", "\n", "Let us change the label of the vertex to \"node\" using a static attribute value, and set the edge color back to the default (`None`)." ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "tags": [ "nbval-ignore-output" ] }, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "cluster_0\n", "\n", "cluster: 0\n", "\n", "\n", "cluster_1\n", "\n", "cluster: 1\n", "\n", "\n", "\n", "0\n", "\n", "node\n", "\n", "\n", "\n", "1\n", "\n", "node\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "\n", "\n", "\n", "2\n", "\n", "node\n", "\n", "\n", "\n", "0->2\n", "\n", "\n", "\n", "\n", "\n", "3\n", "\n", "node\n", "\n", "\n", "\n", "0->3\n", "\n", "\n", "\n", "\n", "\n", "4\n", "\n", "node\n", "\n", "\n", "\n", "1->4\n", "\n", "\n", "\n", "\n", "\n", "2->4\n", "\n", "\n", "\n", "\n", "\n", "3->4\n", "\n", "\n", "\n", "\n", "\n", "5\n", "\n", "node\n", "\n", "\n", "\n", "4->5\n", "\n", "\n", "\n", "\n", "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "g.vstyle = {'label':'node'}\n", "g.estyle = {'color': None, 'penwidth': \"1\"}\n", "g.view()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### dynamic attribute values\n", "\n", "As demonstrated, it can be beneficial to modify attribute values based on specific vertex or edge elements, such as the `label` attribute mentioned above. In these cases, instead of setting a static string, we assign a function that is evaluated when the graph is rendered. These function values are known as dynamic attribute values, and they must return a string that corresponds to the attribute value.\n", "\n", "The signature of these functions varies depending on the style element:\n", "- For graph style: `fn(g: HGraph) -> str`\n", "- For vertex style: `fn(g: HGraph, vx: int) -> str`\n", "- For edge style: `fn(g: HGraph, edge: (int, int)) -> str`\n", "\n", "In the following example, we modify the vertex label to follow the pattern A->B->C, where A represents vertex 0, and so on. We also set the label for the edge." ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "tags": [ "nbval-ignore-output" ] }, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "cluster_0\n", "\n", "cluster: 0\n", "\n", "\n", "cluster_1\n", "\n", "cluster: 1\n", "\n", "\n", "\n", "0\n", "\n", "A\n", "\n", "\n", "\n", "1\n", "\n", "B\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "A→B\n", "\n", "\n", "\n", "2\n", "\n", "C\n", "\n", "\n", "\n", "0->2\n", "\n", "\n", "A→C\n", "\n", "\n", "\n", "3\n", "\n", "D\n", "\n", "\n", "\n", "0->3\n", "\n", "\n", "A→D\n", "\n", "\n", "\n", "4\n", "\n", "E\n", "\n", "\n", "\n", "1->4\n", "\n", "\n", "B→E\n", "\n", "\n", "\n", "2->4\n", "\n", "\n", "C→E\n", "\n", "\n", "\n", "3->4\n", "\n", "\n", "D→E\n", "\n", "\n", "\n", "5\n", "\n", "F\n", "\n", "\n", "\n", "4->5\n", "\n", "\n", "E→F\n", "\n", "\n", "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "def id_to_label(vx):\n", " return chr(vx+ord('A'))\n", "\n", "g.vstyle = {'label': lambda g, vx: id_to_label(vx)}\n", "g.estyle = {'label': lambda g, e: f\"{id_to_label(e[0])}→{id_to_label(e[1])}\"}\n", "\n", "g.view()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### multi-part vertex labels \n", "\n", "By default, vertices use `Mrecord` style to support multi-part labels. More specifically, in Graphviz, the `Mrecord` shape is used to create nodes that can have multiple rectangular regions, each containing a label. This is useful to display multiple pieces of information in a single node. One can switch between horizontal and vertical layouts by enclosing fields in braces `{...}`. By default, the top-level orientation in a `Mrecord` is horizontal. For instance, a `Mrecord` with the label `\"A | B | C | D\"` will display four fields from left to right. However, if these fields are enclosed in braces, like `\"{A | B | C | D}\"`, they will be displayed from top to bottom. " ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "tags": [ "nbval-ignore-output" ] }, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "cluster_0\n", "\n", "cluster: 0\n", "\n", "\n", "cluster_1\n", "\n", "cluster: 1\n", "\n", "\n", "\n", "0\n", "\n", "A\n", "\n", "in:0\n", "\n", "out:3\n", "\n", "id:0\n", "\n", "\n", "\n", "1\n", "\n", "B\n", "\n", "in:1\n", "\n", "out:1\n", "\n", "id:1\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "A→B\n", "\n", "\n", "\n", "2\n", "\n", "C\n", "\n", "in:1\n", "\n", "out:1\n", "\n", "id:2\n", "\n", "\n", "\n", "0->2\n", "\n", "\n", "A→C\n", "\n", "\n", "\n", "3\n", "\n", "D\n", "\n", "in:1\n", "\n", "out:1\n", "\n", "id:3\n", "\n", "\n", "\n", "0->3\n", "\n", "\n", "A→D\n", "\n", "\n", "\n", "4\n", "\n", "E\n", "\n", "in:3\n", "\n", "out:1\n", "\n", "id:4\n", "\n", "\n", "\n", "1->4\n", "\n", "\n", "B→E\n", "\n", "\n", "\n", "2->4\n", "\n", "\n", "C→E\n", "\n", "\n", "\n", "3->4\n", "\n", "\n", "D→E\n", "\n", "\n", "\n", "5\n", "\n", "F\n", "\n", "in:1\n", "\n", "out:0\n", "\n", "id:5\n", "\n", "\n", "\n", "4->5\n", "\n", "\n", "E→F\n", "\n", "\n", "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "g.vstyle = {'label': lambda g, vx: \"%s|{in:%d|out:%d}|id:%d\" %\n", " (id_to_label(vx), g.num_in_vx(vx), g.num_out_vx(vx), vx)}\n", "g.view()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### clustering\n", "\n", "Clustering allows grouping vertices into distinct rectangular sections. To set up clustering, three style elements need to be configured:\n", "\n", "- `g.style['nclusters']`: This sets the number of clusters.\n", "- `g.style['cluster']`: This defines the style format of the clusters.\n", "- `g.vstyle['cluster']`: This determines which cluster a vertex belongs to. The first cluster is identified as \"0\". If a vertex is set to `None`, it means the vertex does not belong to any cluster." ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "tags": [ "nbval-ignore-output" ] }, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "cluster_0\n", "\n", "cluster: 0\n", "\n", "\n", "cluster_1\n", "\n", "cluster: 1\n", "\n", "\n", "\n", "0\n", "\n", "A\n", "\n", "in:0\n", "\n", "out:3\n", "\n", "id:0\n", "\n", "\n", "\n", "1\n", "\n", "B\n", "\n", "in:1\n", "\n", "out:1\n", "\n", "id:1\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "A→B\n", "\n", "\n", "\n", "2\n", "\n", "C\n", "\n", "in:1\n", "\n", "out:1\n", "\n", "id:2\n", "\n", "\n", "\n", "0->2\n", "\n", "\n", "A→C\n", "\n", "\n", "\n", "3\n", "\n", "D\n", "\n", "in:1\n", "\n", "out:1\n", "\n", "id:3\n", "\n", "\n", "\n", "0->3\n", "\n", "\n", "A→D\n", "\n", "\n", "\n", "4\n", "\n", "E\n", "\n", "in:3\n", "\n", "out:1\n", "\n", "id:4\n", "\n", "\n", "\n", "1->4\n", "\n", "\n", "B→E\n", "\n", "\n", "\n", "2->4\n", "\n", "\n", "C→E\n", "\n", "\n", "\n", "3->4\n", "\n", "\n", "D→E\n", "\n", "\n", "\n", "5\n", "\n", "F\n", "\n", "in:1\n", "\n", "out:0\n", "\n", "id:5\n", "\n", "\n", "\n", "4->5\n", "\n", "\n", "E→F\n", "\n", "\n", "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "g.style['nclusters'] = '2'\n", "# cluster 0: bgcolor: gray\n", "# cluster 1: bgcolor: red\n", "g.style['cluster'] = lambda g, c: {\"label\": f'cluster: {c}', \"bgcolor\": \"gray\" if c == 0 else \"red\"}\n", "# 0: None\n", "# 1--4: cluster 0\n", "# 5: cluster 1\n", "g.vstyle['cluster'] = lambda g, vx: None if vx == 0 else 0 if vx <= 4 else 1\n", "g.view()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## custom rendering\n", "\n", "As demonstrated, HGraphs can internally encode visual styles. However, there may be instances where we want to modify the rendering—for example, during an analysis—without altering the graph's internal style.\n", "\n", "In such cases, the renderer supports `gstyle`, `vstyle`, and `estyle` parameters. These parameters can be used to update the internal graph styles without permanently changing them. You can use these parameters in the `g.view(...)` or `viewer.add_graph(...)` methods.\n", "\n", "In the following example, we render the graph without clusters. It is important to note that while the visual representation changes, the underlying graph style remains clustered." ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "tags": [ "nbval-ignore-output" ] }, "outputs": [ { "data": { "text/html": [ "

custom rendering

" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "0\n", "\n", "A\n", "\n", "in:0\n", "\n", "out:3\n", "\n", "id:0\n", "\n", "\n", "\n", "1\n", "\n", "B\n", "\n", "in:1\n", "\n", "out:1\n", "\n", "id:1\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "A→B\n", "\n", "\n", "\n", "2\n", "\n", "C\n", "\n", "in:1\n", "\n", "out:1\n", "\n", "id:2\n", "\n", "\n", "\n", "0->2\n", "\n", "\n", "A→C\n", "\n", "\n", "\n", "3\n", "\n", "D\n", "\n", "in:1\n", "\n", "out:1\n", "\n", "id:3\n", "\n", "\n", "\n", "0->3\n", "\n", "\n", "A→D\n", "\n", "\n", "\n", "4\n", "\n", "E\n", "\n", "in:3\n", "\n", "out:1\n", "\n", "id:4\n", "\n", "\n", "\n", "1->4\n", "\n", "\n", "B→E\n", "\n", "\n", "\n", "2->4\n", "\n", "\n", "C→E\n", "\n", "\n", "\n", "3->4\n", "\n", "\n", "D→E\n", "\n", "\n", "\n", "5\n", "\n", "F\n", "\n", "in:1\n", "\n", "out:0\n", "\n", "id:5\n", "\n", "\n", "\n", "4->5\n", "\n", "\n", "E→F\n", "\n", "\n", "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "

internal style rendering

" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "cluster_0\n", "\n", "cluster: 0\n", "\n", "\n", "cluster_1\n", "\n", "cluster: 1\n", "\n", "\n", "\n", "0\n", "\n", "A\n", "\n", "in:0\n", "\n", "out:3\n", "\n", "id:0\n", "\n", "\n", "\n", "1\n", "\n", "B\n", "\n", "in:1\n", "\n", "out:1\n", "\n", "id:1\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "A→B\n", "\n", "\n", "\n", "2\n", "\n", "C\n", "\n", "in:1\n", "\n", "out:1\n", "\n", "id:2\n", "\n", "\n", "\n", "0->2\n", "\n", "\n", "A→C\n", "\n", "\n", "\n", "3\n", "\n", "D\n", "\n", "in:1\n", "\n", "out:1\n", "\n", "id:3\n", "\n", "\n", "\n", "0->3\n", "\n", "\n", "A→D\n", "\n", "\n", "\n", "4\n", "\n", "E\n", "\n", "in:3\n", "\n", "out:1\n", "\n", "id:4\n", "\n", "\n", "\n", "1->4\n", "\n", "\n", "B→E\n", "\n", "\n", "\n", "2->4\n", "\n", "\n", "C→E\n", "\n", "\n", "\n", "3->4\n", "\n", "\n", "D→E\n", "\n", "\n", "\n", "5\n", "\n", "F\n", "\n", "in:1\n", "\n", "out:0\n", "\n", "id:5\n", "\n", "\n", "\n", "4->5\n", "\n", "\n", "E→F\n", "\n", "\n", "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "g.view(gstyle={'nclusters': 0}, title='custom rendering')\n", "g.view(title='internal style rendering')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Moreover, original attribute values can be modified using `wrapper` attributes. These attributes are prefixed with a `#`, and are defined by a function that takes a string value as input. This function can then alter the string value. To demonstrate this, let us include the cluster number in each vertex's label, using the original label value." ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "tags": [ "nbval-ignore-output" ] }, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "cluster_0\n", "\n", "\n", "\n", "cluster_1\n", "\n", "\n", "\n", "\n", "0\n", "\n", "A\n", "\n", "in:0\n", "\n", "out:3\n", "\n", "id:0\n", "\n", "cluster: -\n", "\n", "\n", "\n", "1\n", "\n", "B\n", "\n", "in:1\n", "\n", "out:1\n", "\n", "id:1\n", "\n", "cluster: 0\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "\n", "\n", "\n", "2\n", "\n", "C\n", "\n", "in:1\n", "\n", "out:1\n", "\n", "id:2\n", "\n", "cluster: 0\n", "\n", "\n", "\n", "0->2\n", "\n", "\n", "\n", "\n", "\n", "3\n", "\n", "D\n", "\n", "in:1\n", "\n", "out:1\n", "\n", "id:3\n", "\n", "cluster: 0\n", "\n", "\n", "\n", "0->3\n", "\n", "\n", "\n", "\n", "\n", "4\n", "\n", "E\n", "\n", "in:3\n", "\n", "out:1\n", "\n", "id:4\n", "\n", "cluster: 0\n", "\n", "\n", "\n", "1->4\n", "\n", "\n", "\n", "\n", "\n", "2->4\n", "\n", "\n", "\n", "\n", "\n", "3->4\n", "\n", "\n", "\n", "\n", "\n", "5\n", "\n", "F\n", "\n", "in:1\n", "\n", "out:0\n", "\n", "id:5\n", "\n", "cluster: 1\n", "\n", "\n", "\n", "4->5\n", "\n", "\n", "\n", "\n", "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "g.view(gstyle={'cluster': lambda g, c: {}}, # remove cluster style\n", " estyle={'label': None }, # remove label from edges\n", " vstyle={'#label': lambda g, v, s: f'{s} | cluster: %s' % (\"-\" if v == 0 else \"0\" if v <= 4 else \"1\")})" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## subgraph\n", "\n", "Specific parts of the graph can be rendered by using the following parameters:\n", "- `vs`: This is a list of vertices that should be included in the rendering. By default, all vertices are included.\n", "- `induced`: This parameter determines whether to include edges that connect two vertices in the `vs` list. By default, this is set to `True`, meaning all edges are included." ] }, { "cell_type": "code", "execution_count": 21, "metadata": { "tags": [ "nbval-ignore-output" ] }, "outputs": [ { "data": { "text/html": [ "

subgraph (induced=False)

" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "cluster_0\n", "\n", "cluster: 0\n", "\n", "\n", "\n", "0\n", "\n", "A\n", "\n", "in:0\n", "\n", "out:3\n", "\n", "id:0\n", "\n", "\n", "\n", "1\n", "\n", "B\n", "\n", "in:1\n", "\n", "out:1\n", "\n", "id:1\n", "\n", "\n", "\n", "2\n", "\n", "C\n", "\n", "in:1\n", "\n", "out:1\n", "\n", "id:2\n", "\n", "\n", "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "

subgraph (induced=True)

" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "cluster_0\n", "\n", "cluster: 0\n", "\n", "\n", "\n", "0\n", "\n", "A\n", "\n", "in:0\n", "\n", "out:3\n", "\n", "id:0\n", "\n", "\n", "\n", "1\n", "\n", "B\n", "\n", "in:1\n", "\n", "out:1\n", "\n", "id:1\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "\n", "\n", "\n", "2\n", "\n", "C\n", "\n", "in:1\n", "\n", "out:1\n", "\n", "id:2\n", "\n", "\n", "\n", "0->2\n", "\n", "\n", "\n", "\n", "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "viewer = WebView()\n", "g.estyle = {'label': None}\n", "viewer.add_graph(g, vs=[0, 1, 2], induced=False, title=\"subgraph (induced=False)\")\n", "viewer.add_graph(g, vs=[0, 1, 2], induced=True, title=\"subgraph (induced=True)\")\n", "\n", "viewer.run()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## outputs\n", "An HGraph can be rendered into various formats using the `g.render()` method. In addition to all the rendering parameters mentioned above, it also accepts the following parameters to control the output:\n", "- `format`: specifies the output format. Options include `pdf`, `png`, `dot`, and `svg`.\n", "- `pipe`: if set to True, this returns a string containing the output in the desired format. If False, the output is written to a file.\n", "- `filename`: defines the name of the file where the output is stored when `pipe` is set to False." ] } ], "metadata": { "kernelspec": { "display_name": "metaml", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.9" } }, "nbformat": 4, "nbformat_minor": 2 }