Skip to content

Commit a9f6c71

Browse files
authored
Merge pull request #273 from neo4j/main
Update v1 branch
2 parents 0c15a7e + b0a49f2 commit a9f6c71

File tree

16 files changed

+519
-80
lines changed

16 files changed

+519
-80
lines changed

changelog.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1-
# Changes in 1.0.1
1+
# Changes in 1.1.0
22

33
## Breaking changes
44

55

66
## New features
77

8+
* Added a new utility function to color relationships `VisualizationGraph.color_relationships`
9+
* Added a new utility function to resize relationships `VisualizationGraph.resize_relationships`
10+
811

912
## Bug fixes
1013

docs/antora/modules/ROOT/pages/customizing.adoc

Lines changed: 62 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -49,35 +49,35 @@ for node in VG.nodes:
4949
node.caption = str(caption)
5050
----
5151

52-
== Coloring nodes
52+
== Coloring the graph
5353

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.
54+
Nodes and relationships can be colored directly by providing them with a color field, upon creation.
55+
This can be done by passing a color as a string to the `color` parameter of the
56+
link:{api-docs-uri}/node[Node] or link:{api-docs-uri}/relationship[Relationship] object.
5757

58-
Alternatively, you can color nodes based on a field or property of the nodes after a `VisualizationGraph` object has been
58+
Alternatively, you can color nodes or relationships based on a field or property after a `VisualizationGraph` object has been
5959
created.
6060

61-
=== The `color_nodes` method
61+
=== The `color_nodes` and `color_relationships` methods
6262

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).
63+
By calling the link:{api-docs-uri}/visualization-graph/#neo4j_viz.VisualizationGraph.color_nodes[`neo4j_viz.VisualizationGraph.color_nodes()`] or link:{api-docs-uri}/visualization-graph/#neo4j_viz.VisualizationGraph.color_relationships[`neo4j_viz.VisualizationGraph.color_relationships()`] method, you can color nodes or relationships based on a field or property (members of the `Node.properties` or `Relationship.properties` map).
6464

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.
65+
It's possible to color them 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 field/property.
6767
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.
68+
create a gradient of colors based on the values of the field/property.
6969

7070
By default the Neo4j color palette, that works for both light and dark mode, will be used.
7171
If you want to use a different color palette, you can pass a dictionary or iterable of colors as the `colors`
7272
parameter.
7373
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).
7474

75-
If some nodes already have a `color` set, you can choose whether or not to override it with the `override`
75+
If some nodes or relationships already have a `color` set, you can choose whether or not to override it with the `override`
7676
parameter.
7777

7878
==== By discrete color space
7979

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:
80+
To not use the default colors, we can provide a list of custom colors based on a discrete field to the coloring methods:
8181

8282
[source, python]
8383
----
@@ -86,9 +86,12 @@ from neo4j_viz.colors import ColorSpace
8686
# VG is a VisualizationGraph object
8787
VG.color_nodes(
8888
field="caption",
89-
["red", "#7fffd4", (255, 255, 255, 0.5), "hsl(270, 60%, 70%)"],
89+
colors=["red", "#7fffd4", (255, 255, 255, 0.5), "hsl(270, 60%, 70%)"],
9090
color_space=ColorSpace.DISCRETE
9191
)
92+
93+
# Color relationships based on their caption
94+
VG.color_relationships(field="caption")
9295
----
9396

9497
The full set of allowed values for colors are listed link:https://docs.pydantic.dev/2.0/usage/types/extra_types/color_types/[here].
@@ -100,43 +103,54 @@ Instead of defining your own colors, you could also for example use the color pa
100103
from palettable.wesanderson import Moonrise1_5
101104
102105
# VG is a VisualizationGraph object
103-
VG.color_nodes(field="caption", Moonrise1_5.colors) # PropertyType.DISCRETE is default
106+
VG.color_nodes(field="caption", colors=Moonrise1_5.colors) # ColorSpace.DISCRETE is default
104107
----
105108

106-
In theses cases, all nodes with the same caption will get the same color.
109+
In theses cases, all items with the same field value will get the same color.
107110

108-
If there are fewer colors than unique values for the node `field` or `property` provided, the colors will be reused in a cycle.
111+
If there are fewer colors than unique values for the `field` or `property` provided, the colors will be reused in a cycle.
109112
To avoid that, you could use a larger palette or extend one with additional colors.
110113
Refer to the link:{tutorials-docs-uri}/gds-example[Visualizing Neo4j Graph Data Science (GDS) Graphs tutorial] for an example on how
111114
to do the latter.
112115

113116
==== By continuous color space
114117

115-
To not use the default colors, we can provide a list of custom colors representing a range to the `color_nodes` method:
118+
To not use the default colors, we can provide a list of custom colors representing a range:
116119

117120
[source, python]
118121
----
119-
from neo4j_viz.colors import PropertyType
122+
from neo4j_viz.colors import ColorSpace
120123
121124
# VG is a VisualizationGraph object
122125
VG.color_nodes(
123126
property="centrality_score",
124-
[(255, 0, 0), (191, 64, 0), (128, 128, 0), (64, 191, 0), (0, 255, 0)] # From red to green
127+
colors=[(255, 0, 0), (191, 64, 0), (128, 128, 0), (64, 191, 0), (0, 255, 0)], # From red to green
128+
color_space=ColorSpace.CONTINUOUS
129+
)
130+
131+
# Color relationships based on a "weight" property
132+
VG.color_relationships(
133+
property="weight",
134+
colors=["#E0E0E0", "#000000"], # From light grey to black
125135
color_space=ColorSpace.CONTINUOUS
126136
)
127137
----
128138

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.
139+
In these cases, the nodes or relationships will be colored based on the value of the property, with the lowest values being colored with the first color and the highest values being colored with the last color.
130140
Since we only provided five colors in the range, the granularity of the gradient will be limited to five steps.
131141

132142
`palettable` and `matplotlib` are great libraries to use to create custom color gradients.
133143

134-
== Sizing nodes
144+
== Sizing nodes and relationships
135145

136146
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.
147+
This can be done by passing a size as an integer to the `size` parameter of the link:{api-docs-uri}/node[Node] object.
148+
138149

139-
Alternatively, you can size nodes after a `VisualizationGraph` object has been created.
150+
Relationships can be given a width directly by providing them with a width field, upon creation.
151+
This can be done by passing a size as an integer to the `width` parameter of the link:{api-docs-uri}/relationship[Relationship] object.
152+
153+
Alternatively, you can resize them after a `VisualizationGraph` object has been created.
140154

141155
=== The `resize_nodes` method
142156

@@ -166,6 +180,31 @@ VG.resize_nodes(sizes={42: 88}, node_radius_min_max=(5, 20))
166180

167181
Note that means that also the node with ID 42 will be scaled to be between 5 and 20 pixels in size.
168182

183+
=== The `resize_relationships` method
184+
185+
By calling the link:{api-docs-uri}/visualization-graph/#neo4j_viz.VisualizationGraph.resize_relationships[`neo4j_viz.VisualizationGraph.resize_relationships()`] method, you can resize relationship widths by:
186+
187+
* passing new widths as a dictionary `widths`, mapping relationship IDs to widths in pixels, or
188+
* providing a `property` name of the relationships to use for sizing.
189+
190+
In the following example, we resize the relationship with ID "r1" to have a width of 5:
191+
192+
[source, python]
193+
----
194+
# VG is a VisualizationGraph object
195+
VG.resize_relationships(widths={"r1": 5})
196+
----
197+
198+
You can also resize relationships based on a property:
199+
200+
[source, python]
201+
----
202+
# VG is a VisualizationGraph object
203+
VG.resize_relationships(property="weight")
204+
----
205+
206+
Unlike `resize_nodes`, relationship widths are used as-is and are not scaled to a specific range.
207+
169208
== Pinning nodes
170209

171210
Nodes can be pinned to their current position in the visualization, so that they will not be moved by the force-directed

python-wrapper/README.md

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,6 @@ Alternatively, you can export the output to a file and view it in a web browser.
1515

1616
The package wraps the [Neo4j Visualization JavaScript library (NVL)](https://neo4j.com/docs/nvl/current/).
1717

18-
> [!WARNING]
19-
> This package is still in development and the API is subject to change.
20-
2118

2219
![Example Graph](https://github.com/neo4j/python-graph-visualization/blob/main/examples/example_cora_graph.png)
2320

python-wrapper/pyproject.toml

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "neo4j-viz"
7-
version = "1.0.1"
7+
version = "1.1.0"
88
description = "A simple graph visualization tool"
99
readme = "README.md"
1010
authors = [{ name = "Neo4j", email = "team-gds@neo4j.org" }]
@@ -47,15 +47,15 @@ snowflake = ["snowflake-snowpark-python>=1, <2"]
4747

4848
[dependency-groups]
4949
dev = [
50-
"ruff==0.14.1",
51-
"mypy==1.18.2",
50+
"ruff==0.14.13",
51+
"mypy==1.19.1",
5252
"pytest==8.4.2",
53-
"selenium==4.38.0",
54-
"ipykernel==6.30.1",
53+
"selenium==4.40.0",
54+
"ipykernel==7.1.0",
5555
"palettable==3.3.3",
5656
"pytest-mock==3.15.1",
5757
"nbconvert==7.16.6",
58-
"streamlit==1.51.0",
58+
"streamlit==1.53.0",
5959
"matplotlib>=3.9.4",
6060
]
6161
docs = [
@@ -72,6 +72,7 @@ notebook = [
7272
"palettable>=3.3.3",
7373
"matplotlib>=3.9.4",
7474
"snowflake-snowpark-python==1.42.0",
75+
"dotenv"
7576
]
7677

7778
[project.urls]
@@ -100,6 +101,14 @@ neo4j_viz = [
100101

101102
[tool.pytest.ini_options]
102103
addopts = ["--import-mode=importlib"]
104+
markers = [
105+
"requires_neo4j_and_gds: mark a test as a requiring a Neo4j instance with GDS running",
106+
"requires_snowflake: mark a test as a requiring a Snowflake connection"
107+
]
108+
filterwarnings = [
109+
"error",
110+
"ignore:Jupyter is migrating its paths to use standard platformdirs:DeprecationWarning"
111+
]
103112

104113
[tool.ruff]
105114
line-length = 120

python-wrapper/src/neo4j_viz/relationship.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ class Relationship(
6464
caption_size: Optional[Union[int, float]] = Field(None, gt=0.0, description="The size of the caption text")
6565
#: The color of the relationship. Allowed input is for example "#FF0000", "red" or (255, 0, 0)
6666
color: Optional[ColorType] = Field(None, description="The color of the relationship")
67+
# The width of the relationship
68+
width: Optional[int | float] = Field(None, gt=0.0, description="The width of the relationship")
6769
#: Additional properties of the relationship that do not directly impact the visualization
6870
properties: dict[str, Any] = Field(
6971
default_factory=dict,

python-wrapper/src/neo4j_viz/resources/nvl_entrypoint/base.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)