Skip to content

Commit 5bdec15

Browse files
authored
Convert docs to Antora plus Sphinx (#255)
* Change Sphinx preview port * Add base Antora configuration * Add skeleton for other pages * Update Sphinx build and view conf * Add content to Antora docs * Add Getting started as Asciidoc; remove Sphinx content * Rename doc attributes * Fix doc attribute name * Change docs URI * Temporarily update links * Update Antora conf files * Update link in Sphinx docs * Update version * Bump docs version to 1 * Update package version
1 parent 3fb8148 commit 5bdec15

27 files changed

+957
-1129
lines changed

docs/.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,5 @@
11
build
2+
3+
# Antora docs
4+
antora/package-lock.json
5+
antora/node_modules/

docs/Makefile

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
# You can set these variables from the command line, and also
55
# from the environment for the first two.
6-
SPHINXOPTS ?=
6+
SPHINXOPTS ?= -b dirhtml
77
SPHINXBUILD ?= sphinx-build
88
SOURCEDIR = source
99
BUILDDIR = build
@@ -14,7 +14,6 @@ help:
1414

1515
.PHONY: help Makefile
1616

17-
# Catch-all target: route all unknown targets to Sphinx using the new
18-
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
17+
# Use this format to make use of the "-b dirhtml" switch
1918
%: Makefile
20-
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
19+
@$(SPHINXBUILD) $(SPHINXOPTS) "$(SOURCEDIR)" "$(BUILDDIR)"

docs/antora/antora.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
name: python-graph-visualization
2+
title: Neo4j Python Graph Visualization
3+
version: '1'
4+
start_page: ROOT:index.adoc
5+
nav:
6+
- modules/ROOT/content-nav.adoc
7+
asciidoc:
8+
attributes:
9+
# Version needs to be updated manually for now
10+
docs-version: '1'
11+
api-docs-uri: '{neo4j-docs-base-uri}/python-graph-visualization/{docs-version}/reference/api-reference'
12+
tutorials-docs-uri: '{neo4j-docs-base-uri}/python-graph-visualization/{docs-version}/reference/tutorials'
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
* xref:index.adoc[]
2+
* xref:installation.adoc[]
3+
* xref:getting-started.adoc[]
4+
* xref:integration.adoc[]
5+
* xref:rendering.adoc[]
6+
* xref:customizing.adoc[]
7+
* link:{tutorials-docs-uri}[Tutorials]
8+
* link:{api-docs-uri}[API reference]
237 KB
Loading
236 KB
Loading
Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
= Customizing the visualization
2+
3+
Once created, a link:{api-docs-uri}/visualization-graph[`VisualizationGraph` object] can be modified in various ways
4+
to adjust what the visualization looks like the next time you render it.
5+
In this section we will discuss how to color, size, and pin nodes, as well as how to directly modify nodes and
6+
relationships of existing `VisualizationGraph` objects.
7+
8+
If you have not yet created a `VisualizationGraph` object, refer to one of the following sections:
9+
10+
* xref:getting-started.adoc[Getting started] for creating a visualization graph from scratch using `neo4j-viz`
11+
primitives like link:{api-docs-uri}/node/[Node] and link:{api-docs-uri}/relationship/[Relationship] and
12+
link:{api-docs-uri}/visualization-graph[`VisualizationGraph`] directly.
13+
* xref:integration.adoc[] for importing data from a Pandas DataFrame or Neo4j GDS projection.
14+
15+
== Setting node captions
16+
17+
Node captions are the text labels displayed on nodes in the visualization.
18+
19+
=== The `set_node_captions` method
20+
21+
By calling the `neo4j_viz.VisualizationGraph.set_node_captions()` method, you can set node captions based on a node field (like `id`, `size`, etc.) or a node property (members of the `Node.properties` map).
22+
23+
The method accepts an `override` parameter (default `True`) that controls whether to replace existing captions.
24+
If `override=False`, only nodes without captions will be updated.
25+
26+
Here is an example of setting node captions from a property:
27+
28+
[source, python]
29+
----
30+
# VG is a VisualizationGraph object with nodes that have a "name" property
31+
VG.set_node_captions(property="name")
32+
----
33+
34+
You can also set captions from a node field, and choose not to override existing captions:
35+
36+
[source, python]
37+
----
38+
# VG is a VisualizationGraph object
39+
VG.set_node_captions(field="id", override=False)
40+
----
41+
42+
For more complex scenarios where you need fallback logic or want to combine multiple properties, you can iterate over nodes directly:
43+
44+
[source, python]
45+
----
46+
# VG is a VisualizationGraph object
47+
for node in VG.nodes:
48+
caption = node.properties.get("name") or node.properties.get("title") or node.id
49+
node.caption = str(caption)
50+
----
51+
52+
== Coloring nodes
53+
54+
Nodes can be colored directly by providing them with a color field, upon creation.
55+
This can for example be done by passing a color as a string to the `color` parameter of the
56+
link:{api-docs-uri}/node[Node] object.
57+
58+
Alternatively, you can color nodes based on a field or property of the nodes after a `VisualizationGraph` object has been
59+
created.
60+
61+
=== The `color_nodes` method
62+
63+
By calling the link:{api-docs-uri}/visualization-graph/#neo4j_viz.VisualizationGraph.color_nodes[`neo4j_viz.VisualizationGraph.color_nodes()`] method, you can color nodes based on a node field or property (members of the `Node.properties` map).
64+
65+
It's possible to color the nodes based on a discrete or continuous color space (see link:{api-docs-uri}/colors[`ColorSpace`]).
66+
In the discrete case, a new color from the `colors` provided is assigned to each unique value of the node field/property.
67+
In the continuous case, the `colors` should be a list of colors representing a range that are used to
68+
create a gradient of colors based on the values of the node field/property.
69+
70+
By default the Neo4j color palette, that works for both light and dark mode, will be used.
71+
If you want to use a different color palette, you can pass a dictionary or iterable of colors as the `colors`
72+
parameter.
73+
A color value can for example be either strings like "blue", or hexadecimal color codes like "#FF0000", or even a tuple of RGB values like (255, 0, 255).
74+
75+
If some nodes already have a `color` set, you can choose whether or not to override it with the `override`
76+
parameter.
77+
78+
==== By discrete color space
79+
80+
To not use the default colors, we can provide a list of custom colors based on the discrete node field "caption" to the `color_nodes` method:
81+
82+
[source, python]
83+
----
84+
from neo4j_viz.colors import ColorSpace
85+
86+
# VG is a VisualizationGraph object
87+
VG.color_nodes(
88+
field="caption",
89+
["red", "#7fffd4", (255, 255, 255, 0.5), "hsl(270, 60%, 70%)"],
90+
color_space=ColorSpace.DISCRETE
91+
)
92+
----
93+
94+
The full set of allowed values for colors are listed link:https://docs.pydantic.dev/2.0/usage/types/extra_types/color_types/[here].
95+
96+
Instead of defining your own colors, you could also for example use the color palettes from the link:https://jiffyclub.github.io/palettable/[`palettable` library] as in this snippet:
97+
98+
[source, python]
99+
----
100+
from palettable.wesanderson import Moonrise1_5
101+
102+
# VG is a VisualizationGraph object
103+
VG.color_nodes(field="caption", Moonrise1_5.colors) # PropertyType.DISCRETE is default
104+
----
105+
106+
In theses cases, all nodes with the same caption will get the same color.
107+
108+
If there are fewer colors than unique values for the node `field` or `property` provided, the colors will be reused in a cycle.
109+
To avoid that, you could use a larger palette or extend one with additional colors.
110+
Refer to the link:/tutorials/gds-example[Visualizing Neo4j Graph Data Science (GDS) Graphs tutorial] for an example on how
111+
to do the latter.
112+
113+
==== By continuous color space
114+
115+
To not use the default colors, we can provide a list of custom colors representing a range to the `color_nodes` method:
116+
117+
[source, python]
118+
----
119+
from neo4j_viz.colors import PropertyType
120+
121+
# VG is a VisualizationGraph object
122+
VG.color_nodes(
123+
property="centrality_score",
124+
[(255, 0, 0), (191, 64, 0), (128, 128, 0), (64, 191, 0), (0, 255, 0)] # From red to green
125+
color_space=ColorSpace.CONTINUOUS
126+
)
127+
----
128+
129+
In this case, the nodes will be colored based on the value of the "centrality_score" property, with the lowest values being colored red and the highest values being colored green.
130+
Since we only provided five colors in the range, the granularity of the gradient will be limited to five steps.
131+
132+
`palettable` and `matplotlib` are great libraries to use to create custom color gradients.
133+
134+
== Sizing nodes
135+
136+
Nodes can be given a size directly by providing them with a size field, upon creation.
137+
This can for example be done by passing a size as an integer to the `size` parameter of the link:{api-docs-uri}/node[Node] object.
138+
139+
Alternatively, you can size nodes after a `VisualizationGraph` object has been created.
140+
141+
=== The `resize_nodes` method
142+
143+
By calling the link:{api-docs-uri}/visualization-graph/#neo4j_viz.VisualizationGraph.resize_nodes[`neo4j_viz.VisualizationGraph.resize_nodes()`] method, you can resize nodes by:
144+
145+
* passing new nodes sizes as a dictionary `sizes`, mapping node IDs to sizes in pixels, or
146+
* providing a tuple of two numbers `node_radius_min_max`: minimum and maximum radii (sizes) in pixels to which the
147+
nodes will be scaled.
148+
149+
Or you could provide both `sizes` and `node_radius_min_max`, in which case the dictionary will be used to first set
150+
the sizes of the nodes, and then the minimum and maximum values of the tuple will be subsequently used to scale the
151+
sizes to the provided range.
152+
153+
If you provide only the `node_radius_min_max` parameter, the sizes of the nodes will be scaled such that the smallest
154+
node will have the size of the first value, and the largest node will have the size of the second value.
155+
The other nodes will be scaled linearly between these two values according to their relative size.
156+
This can be useful if node sizes vary a lot, or are all very small or very big.
157+
158+
In the following example, we resize the node with ID 42 to have a size of 88 pixels, and then scales all nodes to have
159+
sizes between 5 and 20 pixels:
160+
161+
[source, python]
162+
----
163+
# VG is a VisualizationGraph object
164+
VG.resize_nodes(sizes={42: 88}, node_radius_min_max=(5, 20))
165+
----
166+
167+
Note that means that also the node with ID 42 will be scaled to be between 5 and 20 pixels in size.
168+
169+
== Pinning nodes
170+
171+
Nodes can be pinned to their current position in the visualization, so that they will not be moved by the force-directed
172+
layout algorithm.
173+
This can be useful if you want to keep a node in a specific position, for example to highlight it.
174+
175+
Nodes can be pinned directly upon creation.
176+
This can for example be done by passing `pinned=True` to the link:{api-docs-uri}/node[Node] object.
177+
178+
Alternatively, you can toggle node pinning after a `VisualizationGraph` object has been created.
179+
180+
=== The `toggle_nodes_pinned` method
181+
182+
By calling the link:{api-docs-uri}/visualization-graph/#neo4j_viz.VisualizationGraph.toggle_nodes_pinned[`neo4j_viz.VisualizationGraph.toggle_nodes_pinned()`] method, you can toggle whether nodes should be
183+
pinned or not.
184+
This method takes dictionary that maps node IDs to boolean values, where `True` means that the node is pinned, and
185+
`False` means that the node is not pinned.
186+
187+
In the following example, we pin the node with ID 1337 and unpin the node with ID 42:
188+
189+
[source, python]
190+
----
191+
# VG is a VisualizationGraph object
192+
VG.toggle_nodes_pinned(1337: True, 42: False)})
193+
----
194+
195+
== Direct modification of nodes and relationships
196+
197+
Nodes and relationships can also be modified directly by accessing the `nodes` and `relationships` fields of an
198+
existing `VisualizationGraph` object.
199+
These fields list of all the link:{api-docs-uri}/node[Nodes] and link:{api-docs-uri}/relationship[Relationships] in the graph, respectively.
200+
201+
Each node and relationship has attributes that can be accessed and modified directly, as in the following example:
202+
203+
[source, python]
204+
----
205+
# VG is a VisualizationGraph object
206+
207+
# Modify the first node and fifth relationship
208+
VG.nodes[0].size = 10
209+
VG.nodes[0].properties["height"] = 170
210+
VG.relationships[4].caption = "BUYS"
211+
212+
# Set the coordinates for all nodes from an existing property
213+
for node in VG.nodes:
214+
node.x = node.properties.get("x")
215+
node.y = node.properties.get("y")
216+
217+
# Change the caption size for all relationships
218+
for relationship in VG.relationships:
219+
relationship.caption_size = 15
220+
----
221+
222+
Any changes made to the nodes and relationships will be reflected in the next rendering of the graph.
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
= Getting started
2+
3+
In this section, we will cover the very basics of creating a visualization graph using the `neo4j-viz` library.
4+
We will use a small toy graph representing the purchase history of a few people and products.
5+
6+
To follow along with the example below, please make sure you have xref:installation.adoc[installed the library] first.
7+
8+
We start by instantiating the link:{api-docs-uri}/node/[Nodes] and link:{api-docs-uri}/relationship[Relationships] we want in our graph.
9+
The only mandatory fields for a node are the “id”, and “source” and “target” for a relationship.
10+
But the other fields can optionally be used to customize the appearance of the nodes and relationships in the visualization.
11+
12+
Lastly we create a link:{api-docs-uri}/visualization-graph/[VisualizationGraph] object with the nodes and relationships we created, and call its `render` method to display the graph.
13+
14+
[source, python, role=nocollapse]
15+
----
16+
from neo4j_viz import Node, Relationship, VisualizationGraph
17+
18+
nodes = [
19+
Node(id=0, size=10, caption="Person"),
20+
Node(id=1, size=10, caption="Product"),
21+
Node(id=2, size=20, caption="Product"),
22+
Node(id=3, size=10, caption="Person"),
23+
Node(id=4, size=10, caption="Product"),
24+
]
25+
26+
relationships = [
27+
Relationship(
28+
source=0,
29+
target=1,
30+
caption="BUYS",
31+
),
32+
Relationship(
33+
source=0,
34+
target=2,
35+
caption="BUYS",
36+
),
37+
Relationship(
38+
source=3,
39+
target=2,
40+
caption="BUYS",
41+
),
42+
]
43+
44+
VG = VisualizationGraph(nodes=nodes, relationships=relationships)
45+
46+
VG.render(initial_zoom=2)
47+
----
48+
49+
[TIP]
50+
====
51+
See the link:{tutorials-docs-uri}/getting-started/[Jupyter notebook] to interact with the graph.
52+
====
53+
54+
image::graph_2120034f.png["Graph"]
55+
56+
As we can see in the graph above, the radius of one of the nodes is larger than the others.
57+
This is because we set the “size” field of the node to 20, while the others are set to 10.
58+
59+
At this time all nodes have the same color.
60+
If we want to distinguish between the different types of nodes, we can color them differently with the `color_nodes` method.
61+
We can pass the field we want to use to color the nodes as an argument.
62+
In this case, we will use the "caption" field.
63+
Nodes with the same "caption" will have the same color.
64+
We will use the default color scheme, which is the Neo4j color scheme.
65+
66+
[source, python]
67+
----
68+
VG.color_nodes(field="caption")
69+
70+
VG.render(initial_zoom=2)
71+
----
72+
73+
[TIP]
74+
====
75+
See the link:{tutorials-docs-uri}/getting-started/[Jupyter notebook] to interact with the graph.
76+
====
77+
78+
image::graph_00ff5513.png["Graph with colors"]
79+
80+
We are now easily able to distinguish between the different types of nodes in the graph.
81+
82+
== Next steps
83+
84+
Now that we have covered the basics of creating and rendering a visualization graph, we can move on to more advanced topics.
85+
86+
Here are some suggestions for what to do next:
87+
88+
* Browse the link:{tutorials-docs-uri}[notebook examples] for more examples and use cases
89+
* Learn about the xref:integration.adoc[integrations] with other libraries such as Neo4j GDS and Pandas
90+
* Check out the xref:rendering.adoc[rendering options] and convenience methods of `VisualizationGraph`
91+
* Read about our link:{api-docs-uri}/[API reference]
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
= Introduction
2+
3+
This is the documentation for the `neo4j-viz` Python library by Neo4j.
4+
The library allows you to visualize graph data interactively in Python using a simple API.
5+
6+
The library wraps the link:https://neo4j.com/docs/nvl/current/[Neo4j Visualization JavaScript library (NVL)], and provides additional features for working with graph data in Python.
7+
Notably, there are convenience methods for importing data from source such as link:https://pandas.pydata.org/[Pandas DataFrames], link:https://neo4j.com/docs/graph-data-science/current/[Neo4j Graph Data Science], link:https://neo4j.com/docs/python-manual/current/[Neo4j Database], and link:https://docs.snowflake.com/[Snowflake tables].
8+
9+
The source code is available on link:https://github.com/neo4j/python-graph-visualization[GitHub].
10+
If you have a suggestion on how we can improve the library or want to report a problem, you can create a link:https://github.com/neo4j/python-graph-visualization/issues/new[new issue].

0 commit comments

Comments
 (0)