Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 42 additions & 8 deletions docs/source/customizing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -36,19 +36,34 @@ The ``color_nodes`` method

By calling the :meth:`neo4j_viz.VisualizationGraph.color_nodes` method, you can color nodes based on a
node property (field).
This method will give a distinct color (if possible) to each unique value of the node ``property`` that you provide as
the first positional argument.
It's possible to color the nodes based on a discrete or continuous property.
In the discrete case, a new color from the ``colors`` provided is assigned to each unique value of the node property.
In the continuous case, the ``colors`` should be a list of colors representing a range that are used to create a gradient of colors based on the values of the node property.

By default the Neo4j color palette that works for both light and dark mode will be used.
If you want to use a different color palette, you can pass a dictionary or iterable of colors as the ``colors``
parameter.
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).
Here is an example of providing a list of custom colors to the ``color_nodes`` method:

If some nodes already have a ``color`` set, you can choose whether or not to override it with the ``override``
parameter.


By discrete node property (field)
*********************************

To not use the default colors, we can provide a list of custom colors based on the discrete node property (field) "caption" to the ``color_nodes`` method:

.. code-block:: python

from neo4j_viz.colors import PropertyType

# VG is a VisualizationGraph object
VG.color_nodes("caption", ["red", "#7fffd4", (255, 255, 255, 0.5), "hsl(270, 60%, 70%)"])
VG.color_nodes(
"caption",
["red", "#7fffd4", (255, 255, 255, 0.5), "hsl(270, 60%, 70%)"],
property_type=PropertyType.DISCRETE
)

The full set of allowed values for colors are listed `here <https://docs.pydantic.dev/2.0/usage/types/extra_types/color_types/>`_.

Expand All @@ -60,7 +75,7 @@ this snippet:
from palettable.wesanderson import Moonrise1_5

# VG is a VisualizationGraph object
VG.color_nodes("caption", Moonrise1_5.colors)
VG.color_nodes("caption", Moonrise1_5.colors) # PropertyType.DISCRETE is default

In this case, all nodes with the same caption will get the same color.

Expand All @@ -69,12 +84,31 @@ To avoid that, you could use another palette or extend one with additional color
:doc:`Visualizing Neo4j Graph Data Science (GDS) Graphs tutorial <./tutorials/gds-example>` for an example on how
to do the latter.

If some nodes already have a ``color`` set, you can choose whether or not to override it with the ``override``
parameter.

By continuous node property (field)
***********************************

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

.. code-block:: python

from neo4j_viz.colors import PropertyType

# VG is a VisualizationGraph object
VG.color_nodes(
"centrality_score",
[(255, 0, 0), (191, 64, 0), (128, 128, 0), (64, 191, 0), (0, 255, 0)] # From red to green
property_type=PropertyType.CONTINUOUS
)

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.
Since we only provided five colors in the range, the granularity of the gradient will be limited to five steps.

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


Sizing nodes
--------------
------------

Nodes can be given a size directly by providing them with a size property, upon creation.
This can for example be done by passing a size as an integer to the ``size`` parameter of the
Expand Down
122 changes: 88 additions & 34 deletions examples/gds-example.ipynb

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions python-wrapper/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ dev = [
"pytest-mock==3.14.0",
"nbconvert==7.16.6",
"streamlit==1.42.0",
"matplotlib==3.9.4",
]
docs = [
"sphinx==8.1.3",
Expand Down
268 changes: 267 additions & 1 deletion python-wrapper/src/neo4j_viz/colors.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
from collections.abc import Iterable
from enum import Enum
from typing import Any, Union

from pydantic_extra_types.color import ColorType

ColorsType = Union[dict[Any, ColorType], Iterable[ColorType]]


class PropertyType(Enum):
DISCRETE = "discrete"
CONTINUOUS = "continuous"


# Comes from https://neo4j.design/40a8cff71/p/5639c0-color/t/page-5639c0-79109681-33
neo4j_colors = [
NEO4J_COLORS_DISCRETE = [
"#FFDF81",
"#C990C0",
"#F79767",
Expand All @@ -20,3 +27,262 @@
"#DA7294",
"#579380",
]
_NEO4J_COLORS_CONTINUOUS_BASE = ["#FFDF81", "#C990C0"]
NEO4J_COLORS_CONTINUOUS = [
(255, 223, 129),
(255, 223, 129),
(255, 222, 129),
(254, 222, 130),
(254, 222, 130),
(254, 221, 130),
(254, 221, 130),
(254, 221, 131),
(253, 221, 131),
(253, 220, 131),
(253, 220, 131),
(253, 220, 132),
(252, 219, 132),
(252, 219, 132),
(252, 219, 132),
(252, 218, 133),
(252, 218, 133),
(251, 218, 133),
(251, 217, 133),
(251, 217, 134),
(251, 217, 134),
(251, 216, 134),
(250, 216, 134),
(250, 216, 135),
(250, 216, 135),
(250, 215, 135),
(249, 215, 135),
(249, 215, 136),
(249, 214, 136),
(249, 214, 136),
(249, 214, 136),
(248, 213, 137),
(248, 213, 137),
(248, 213, 137),
(248, 212, 137),
(248, 212, 138),
(247, 212, 138),
(247, 212, 138),
(247, 211, 138),
(247, 211, 139),
(247, 211, 139),
(246, 210, 139),
(246, 210, 139),
(246, 210, 140),
(246, 209, 140),
(245, 209, 140),
(245, 209, 140),
(245, 208, 141),
(245, 208, 141),
(245, 208, 141),
(244, 208, 141),
(244, 207, 142),
(244, 207, 142),
(244, 207, 142),
(244, 206, 142),
(243, 206, 143),
(243, 206, 143),
(243, 205, 143),
(243, 205, 143),
(243, 205, 144),
(242, 204, 144),
(242, 204, 144),
(242, 204, 144),
(242, 203, 145),
(241, 203, 145),
(241, 203, 145),
(241, 203, 145),
(241, 202, 146),
(241, 202, 146),
(240, 202, 146),
(240, 201, 146),
(240, 201, 147),
(240, 201, 147),
(240, 200, 147),
(239, 200, 147),
(239, 200, 148),
(239, 199, 148),
(239, 199, 148),
(238, 199, 148),
(238, 199, 149),
(238, 198, 149),
(238, 198, 149),
(238, 198, 149),
(237, 197, 150),
(237, 197, 150),
(237, 197, 150),
(237, 196, 150),
(237, 196, 150),
(236, 196, 151),
(236, 195, 151),
(236, 195, 151),
(236, 195, 151),
(236, 194, 152),
(235, 194, 152),
(235, 194, 152),
(235, 194, 152),
(235, 193, 153),
(234, 193, 153),
(234, 193, 153),
(234, 192, 153),
(234, 192, 154),
(234, 192, 154),
(233, 191, 154),
(233, 191, 154),
(233, 191, 155),
(233, 190, 155),
(233, 190, 155),
(232, 190, 155),
(232, 190, 156),
(232, 189, 156),
(232, 189, 156),
(231, 189, 156),
(231, 188, 157),
(231, 188, 157),
(231, 188, 157),
(231, 187, 157),
(230, 187, 158),
(230, 187, 158),
(230, 186, 158),
(230, 186, 158),
(230, 186, 159),
(229, 186, 159),
(229, 185, 159),
(229, 185, 159),
(229, 185, 160),
(229, 184, 160),
(228, 184, 160),
(228, 184, 160),
(228, 183, 161),
(228, 183, 161),
(227, 183, 161),
(227, 182, 161),
(227, 182, 162),
(227, 182, 162),
(227, 181, 162),
(226, 181, 162),
(226, 181, 163),
(226, 181, 163),
(226, 180, 163),
(226, 180, 163),
(225, 180, 164),
(225, 179, 164),
(225, 179, 164),
(225, 179, 164),
(225, 178, 165),
(224, 178, 165),
(224, 178, 165),
(224, 177, 165),
(224, 177, 166),
(223, 177, 166),
(223, 177, 166),
(223, 176, 166),
(223, 176, 167),
(223, 176, 167),
(222, 175, 167),
(222, 175, 167),
(222, 175, 168),
(222, 174, 168),
(222, 174, 168),
(221, 174, 168),
(221, 173, 169),
(221, 173, 169),
(221, 173, 169),
(220, 173, 169),
(220, 172, 170),
(220, 172, 170),
(220, 172, 170),
(220, 171, 170),
(219, 171, 171),
(219, 171, 171),
(219, 170, 171),
(219, 170, 171),
(219, 170, 171),
(218, 169, 172),
(218, 169, 172),
(218, 169, 172),
(218, 168, 172),
(218, 168, 173),
(217, 168, 173),
(217, 168, 173),
(217, 167, 173),
(217, 167, 174),
(216, 167, 174),
(216, 166, 174),
(216, 166, 174),
(216, 166, 175),
(216, 165, 175),
(215, 165, 175),
(215, 165, 175),
(215, 164, 176),
(215, 164, 176),
(215, 164, 176),
(214, 164, 176),
(214, 163, 177),
(214, 163, 177),
(214, 163, 177),
(213, 162, 177),
(213, 162, 178),
(213, 162, 178),
(213, 161, 178),
(213, 161, 178),
(212, 161, 179),
(212, 160, 179),
(212, 160, 179),
(212, 160, 179),
(212, 159, 180),
(211, 159, 180),
(211, 159, 180),
(211, 159, 180),
(211, 158, 181),
(211, 158, 181),
(210, 158, 181),
(210, 157, 181),
(210, 157, 182),
(210, 157, 182),
(209, 156, 182),
(209, 156, 182),
(209, 156, 183),
(209, 155, 183),
(209, 155, 183),
(208, 155, 183),
(208, 155, 184),
(208, 154, 184),
(208, 154, 184),
(208, 154, 184),
(207, 153, 185),
(207, 153, 185),
(207, 153, 185),
(207, 152, 185),
(207, 152, 186),
(206, 152, 186),
(206, 151, 186),
(206, 151, 186),
(206, 151, 187),
(205, 151, 187),
(205, 150, 187),
(205, 150, 187),
(205, 150, 188),
(205, 149, 188),
(204, 149, 188),
(204, 149, 188),
(204, 148, 189),
(204, 148, 189),
(204, 148, 189),
(203, 147, 189),
(203, 147, 190),
(203, 147, 190),
(203, 146, 190),
(202, 146, 190),
(202, 146, 191),
(202, 146, 191),
(202, 145, 191),
(202, 145, 191),
(201, 145, 192),
(201, 144, 192),
(201, 144, 192),
]
Loading