Created
May 2, 2024 18:31
-
-
Save jelder/4c41b326612de21f15bc0f7b030eaed9 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import hashlib | |
class NodeColor: | |
""" | |
Assign a random but deterministic color to a string, suitable for coloring a graph. | |
""" | |
def __init__(self, tag): | |
self.hue = self.__get_hue(tag) | |
def __get_hue(self, tag): | |
""" | |
In HSL space, the hue represents the color itself as an angle on the | |
color wheel, where red is both 0° and 360° and cyan is at 180°. We use a | |
hash function to map the tag to a hue. This is deterministic, so the | |
same tag will always get the same hue. | |
This uses `hashlib.sha256`, which is available in the Python standard | |
library. Some of the values I've seen in this project are subjectively a | |
little close together, and MurmurHash3 would be a beter choice. | |
We then convert the hue to a value between 0 and 1, which is the format | |
used by GraphViz. | |
""" | |
hash_object = hashlib.sha256(tag.encode()) | |
hash_value = int(hash_object.hexdigest(), 16) | |
return hash_value % 1000 / 1000 | |
def format(self, h, s, l): | |
""" | |
See https://graphviz.org/docs/attr-types/color/ | |
""" | |
return '"{:02} {:02} {:02}"'.format(h, s, l) | |
def edge(self): | |
""" | |
Returns a color as hue/saturation/value in floating point format for | |
GraphViz. | |
Edge colors are more saturated than fill colors. Here "edge" means both | |
the border of the node and the lines connecting nodes. | |
""" | |
return self.format(self.hue, 0.80, 0.75) | |
def fill(self): | |
""" | |
Returns a color as hue/saturation/value in floating point format for | |
GraphViz. | |
Fill colors are less saturated than edge colors. | |
""" | |
return self.format(self.hue, 0.30, 0.75) | |
def text(self): | |
""" | |
Returns a color as hue/saturation/value in floating point format for | |
GraphViz. | |
Text colors have a low lightness to contrast with the fill color, but | |
the same high saturation as the edge color. | |
""" | |
return self.format(self.hue, 0.80, 0.35) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment