Initial commit
This commit is contained in:
commit
a7f08162c1
178
matrix.py
Normal file
178
matrix.py
Normal file
@ -0,0 +1,178 @@
|
||||
import numpy as np
|
||||
import svg
|
||||
|
||||
rgen = np.random.default_rng()
|
||||
|
||||
# the following functions are taken from Ben Southgate:
|
||||
# https://bsouthga.dev/posts/colour-gradients-with-python
|
||||
|
||||
|
||||
def hex_to_RGB(hex):
|
||||
""" "#FFFFFF" -> [255,255,255]"""
|
||||
# Pass 16 to the integer function for change of base
|
||||
return [int(hex[i : i + 2], 16) for i in range(1, 6, 2)]
|
||||
|
||||
|
||||
def RGB_to_hex(RGB):
|
||||
"""[255,255,255] -> "#FFFFFF" """
|
||||
# Components need to be integers for hex to make sense
|
||||
RGB = [int(x) for x in RGB]
|
||||
return "#" + "".join(
|
||||
["0{0:x}".format(v) if v < 16 else "{0:x}".format(v) for v in RGB]
|
||||
)
|
||||
|
||||
|
||||
def colour_dict(gradient):
|
||||
"""Takes in a list of RGB sub-lists and returns dictionary of
|
||||
colours in RGB and hex form for use in a graphing function
|
||||
defined later on."""
|
||||
return {
|
||||
"hex": [RGB_to_hex(RGB) for RGB in gradient],
|
||||
"r": [RGB[0] for RGB in gradient],
|
||||
"g": [RGB[1] for RGB in gradient],
|
||||
"b": [RGB[2] for RGB in gradient],
|
||||
}
|
||||
|
||||
|
||||
def linear_gradient(start_hex, finish_hex="#FFFFFF", n=10):
|
||||
"""returns a gradient list of (n) colours between
|
||||
two hex colours. start_hex and finish_hex
|
||||
should be the full six-digit colour string,
|
||||
inlcuding the number sign ("#FFFFFF")"""
|
||||
# Starting and ending colours in RGB form
|
||||
s = hex_to_RGB(start_hex)
|
||||
f = hex_to_RGB(finish_hex)
|
||||
# Initilize a list of the output colours with the starting colour
|
||||
RGB_list = [s]
|
||||
# Calcuate a colour at each evenly spaced value of t from 1 to n
|
||||
for t in range(0, n):
|
||||
# Interpolate RGB vector for colour at the current value of t
|
||||
curr_vector = [
|
||||
int(s[j] + (float(t) / (n - 1)) * (f[j] - s[j])) for j in range(3)
|
||||
]
|
||||
# Add it to our list of output colours
|
||||
RGB_list.append(curr_vector)
|
||||
|
||||
return colour_dict(RGB_list)
|
||||
|
||||
|
||||
def rand_hex_colour(num=1):
|
||||
"""Generate random hex colours, default is one,
|
||||
returning a string. If num is greater than
|
||||
1, an array of strings is returned."""
|
||||
colours = [RGB_to_hex([x * 255 for x in rgen.rand(3)]) for i in range(num)]
|
||||
if num == 1:
|
||||
return colours[0]
|
||||
else:
|
||||
return colours
|
||||
|
||||
|
||||
def polylinear_gradient(colours, n):
|
||||
"""returns a list of colours forming linear gradients between
|
||||
all sequential pairs of colours. "n" specifies the total
|
||||
number of desired output colours"""
|
||||
# The number of colours per individual linear gradient
|
||||
n_out = int(float(n) / (len(colours) - 1))
|
||||
# returns dictionary defined by colour_dict()
|
||||
gradient_dict = linear_gradient(colours[0], colours[1], n_out)
|
||||
|
||||
if len(colours) > 1:
|
||||
for col in range(1, len(colours) - 1):
|
||||
next = linear_gradient(colours[col], colours[col + 1], n_out)
|
||||
for k in ("hex", "r", "g", "b"):
|
||||
# Exclude first point to avoid duplicates
|
||||
gradient_dict[k] += next[k][1:]
|
||||
|
||||
return gradient_dict
|
||||
|
||||
|
||||
class LinearGradientColourMap:
|
||||
def __init__(
|
||||
self,
|
||||
colours: list[str] | None = ["#ff0000", "#ffffff", "#0000ff"],
|
||||
min_value: float | None = 0,
|
||||
max_value: float | None = 1,
|
||||
bins: int = 100,
|
||||
):
|
||||
self.colours = polylinear_gradient(colours, bins)
|
||||
self.min, self.max = min_value, max_value
|
||||
|
||||
def __call__(self, v: float):
|
||||
v = max(0, int((v - self.min) / (self.max - self.min) * 100) - 1)
|
||||
if v >= len(self.colours["hex"]):
|
||||
breakpoint()
|
||||
return self.colours["hex"][v]
|
||||
|
||||
|
||||
class RandomColourMap:
|
||||
def __init__(self, random_state: int | list[int] | None = [2, 3, 4, 5, 6]):
|
||||
self.rgen = np.random.default_rng([2, 3, 4, 5, 6])
|
||||
|
||||
def __call__(self, v: float):
|
||||
return RGB_to_hex([x * 255 for x in self.rgen.random(3)])
|
||||
|
||||
|
||||
def colourbar(
|
||||
cmap,
|
||||
min_value: float | None = 0,
|
||||
max_value: float | None = 1,
|
||||
height=100,
|
||||
width=10,
|
||||
resolution=256,
|
||||
):
|
||||
items = [
|
||||
svg.Rect(fill=cmap(v), x=0, y=i, width=width, height=1, stroke="none")
|
||||
for i, v in enumerate(np.linspace(min_value, max_value, resolution))
|
||||
]
|
||||
return svg.G(elements=items, transform=[svg.Scale(1, height / resolution)])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
m, n = 20, 20
|
||||
width = 20
|
||||
height = 20
|
||||
gap = 1
|
||||
text = False
|
||||
total_width = (gap + width) * n + gap
|
||||
total_height = (gap + height) * m + gap
|
||||
|
||||
filename = "matrix.svg"
|
||||
matrix = rgen.random(size=(m, n))
|
||||
colours = ["#f5d72a", "#ffffff", "#2182af"]
|
||||
# colours = ["#ff0000", "#00ff00", "#0000ff"]
|
||||
cmap = LinearGradientColourMap(colours, matrix.min(), matrix.max())
|
||||
# cmap = RandomColourMap()
|
||||
|
||||
items = []
|
||||
items.append(svg.Style(text=".mono { font: monospace; text-align: center;}"))
|
||||
items.append(svg.Style(text=".small { font-size: 25%; }"))
|
||||
|
||||
for i, y in enumerate(range(gap, total_height, gap + height)):
|
||||
for j, x in enumerate(range(gap, total_width, gap + width)):
|
||||
items.append(
|
||||
svg.Rect(
|
||||
x=x,
|
||||
y=y,
|
||||
width=width,
|
||||
height=height,
|
||||
stroke="transparent",
|
||||
fill=cmap(matrix[i, j]),
|
||||
)
|
||||
)
|
||||
if text:
|
||||
items.append(
|
||||
svg.Text(
|
||||
x=x + width / 5,
|
||||
y=y + 3 * height / 4,
|
||||
textLength=width / 2,
|
||||
lengthAdjust="spacingAndGlyphs",
|
||||
class_=["mono"],
|
||||
text=f"{matrix[i, j]:.02f}",
|
||||
)
|
||||
)
|
||||
|
||||
items.append(colourbar(cmap, matrix.min(), matrix.max(), height=100))
|
||||
|
||||
content = svg.SVG(width=total_width, height=total_height, elements=items)
|
||||
with open(filename, "w") as f:
|
||||
f.write(str(content))
|
10
pyproject.toml
Normal file
10
pyproject.toml
Normal file
@ -0,0 +1,10 @@
|
||||
[project]
|
||||
name = "newplot"
|
||||
version = "0.1.0"
|
||||
description = "Add your description here"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.12"
|
||||
dependencies = [
|
||||
"numpy>=2.1.3",
|
||||
"svg-py>=1.5.0",
|
||||
]
|
64
uv.lock
Normal file
64
uv.lock
Normal file
@ -0,0 +1,64 @@
|
||||
version = 1
|
||||
requires-python = ">=3.12"
|
||||
|
||||
[[package]]
|
||||
name = "newplot"
|
||||
version = "0.1.0"
|
||||
source = { virtual = "." }
|
||||
dependencies = [
|
||||
{ name = "numpy" },
|
||||
{ name = "svg-py" },
|
||||
]
|
||||
|
||||
[package.metadata]
|
||||
requires-dist = [
|
||||
{ name = "numpy", specifier = ">=2.1.3" },
|
||||
{ name = "svg-py", specifier = ">=1.5.0" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "numpy"
|
||||
version = "2.1.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/25/ca/1166b75c21abd1da445b97bf1fa2f14f423c6cfb4fc7c4ef31dccf9f6a94/numpy-2.1.3.tar.gz", hash = "sha256:aa08e04e08aaf974d4458def539dece0d28146d866a39da5639596f4921fd761", size = 20166090 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/8a/f0/385eb9970309643cbca4fc6eebc8bb16e560de129c91258dfaa18498da8b/numpy-2.1.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f55ba01150f52b1027829b50d70ef1dafd9821ea82905b63936668403c3b471e", size = 20849658 },
|
||||
{ url = "https://files.pythonhosted.org/packages/54/4a/765b4607f0fecbb239638d610d04ec0a0ded9b4951c56dc68cef79026abf/numpy-2.1.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:13138eadd4f4da03074851a698ffa7e405f41a0845a6b1ad135b81596e4e9958", size = 13492258 },
|
||||
{ url = "https://files.pythonhosted.org/packages/bd/a7/2332679479c70b68dccbf4a8eb9c9b5ee383164b161bee9284ac141fbd33/numpy-2.1.3-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:a6b46587b14b888e95e4a24d7b13ae91fa22386c199ee7b418f449032b2fa3b8", size = 5090249 },
|
||||
{ url = "https://files.pythonhosted.org/packages/c1/67/4aa00316b3b981a822c7a239d3a8135be2a6945d1fd11d0efb25d361711a/numpy-2.1.3-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:0fa14563cc46422e99daef53d725d0c326e99e468a9320a240affffe87852564", size = 6621704 },
|
||||
{ url = "https://files.pythonhosted.org/packages/5e/da/1a429ae58b3b6c364eeec93bf044c532f2ff7b48a52e41050896cf15d5b1/numpy-2.1.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8637dcd2caa676e475503d1f8fdb327bc495554e10838019651b76d17b98e512", size = 13606089 },
|
||||
{ url = "https://files.pythonhosted.org/packages/9e/3e/3757f304c704f2f0294a6b8340fcf2be244038be07da4cccf390fa678a9f/numpy-2.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2312b2aa89e1f43ecea6da6ea9a810d06aae08321609d8dc0d0eda6d946a541b", size = 16043185 },
|
||||
{ url = "https://files.pythonhosted.org/packages/43/97/75329c28fea3113d00c8d2daf9bc5828d58d78ed661d8e05e234f86f0f6d/numpy-2.1.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a38c19106902bb19351b83802531fea19dee18e5b37b36454f27f11ff956f7fc", size = 16410751 },
|
||||
{ url = "https://files.pythonhosted.org/packages/ad/7a/442965e98b34e0ae9da319f075b387bcb9a1e0658276cc63adb8c9686f7b/numpy-2.1.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:02135ade8b8a84011cbb67dc44e07c58f28575cf9ecf8ab304e51c05528c19f0", size = 14082705 },
|
||||
{ url = "https://files.pythonhosted.org/packages/ac/b6/26108cf2cfa5c7e03fb969b595c93131eab4a399762b51ce9ebec2332e80/numpy-2.1.3-cp312-cp312-win32.whl", hash = "sha256:e6988e90fcf617da2b5c78902fe8e668361b43b4fe26dbf2d7b0f8034d4cafb9", size = 6239077 },
|
||||
{ url = "https://files.pythonhosted.org/packages/a6/84/fa11dad3404b7634aaab50733581ce11e5350383311ea7a7010f464c0170/numpy-2.1.3-cp312-cp312-win_amd64.whl", hash = "sha256:0d30c543f02e84e92c4b1f415b7c6b5326cbe45ee7882b6b77db7195fb971e3a", size = 12566858 },
|
||||
{ url = "https://files.pythonhosted.org/packages/4d/0b/620591441457e25f3404c8057eb924d04f161244cb8a3680d529419aa86e/numpy-2.1.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:96fe52fcdb9345b7cd82ecd34547fca4321f7656d500eca497eb7ea5a926692f", size = 20836263 },
|
||||
{ url = "https://files.pythonhosted.org/packages/45/e1/210b2d8b31ce9119145433e6ea78046e30771de3fe353f313b2778142f34/numpy-2.1.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f653490b33e9c3a4c1c01d41bc2aef08f9475af51146e4a7710c450cf9761598", size = 13507771 },
|
||||
{ url = "https://files.pythonhosted.org/packages/55/44/aa9ee3caee02fa5a45f2c3b95cafe59c44e4b278fbbf895a93e88b308555/numpy-2.1.3-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:dc258a761a16daa791081d026f0ed4399b582712e6fc887a95af09df10c5ca57", size = 5075805 },
|
||||
{ url = "https://files.pythonhosted.org/packages/78/d6/61de6e7e31915ba4d87bbe1ae859e83e6582ea14c6add07c8f7eefd8488f/numpy-2.1.3-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:016d0f6f5e77b0f0d45d77387ffa4bb89816b57c835580c3ce8e099ef830befe", size = 6608380 },
|
||||
{ url = "https://files.pythonhosted.org/packages/3e/46/48bdf9b7241e317e6cf94276fe11ba673c06d1fdf115d8b4ebf616affd1a/numpy-2.1.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c181ba05ce8299c7aa3125c27b9c2167bca4a4445b7ce73d5febc411ca692e43", size = 13602451 },
|
||||
{ url = "https://files.pythonhosted.org/packages/70/50/73f9a5aa0810cdccda9c1d20be3cbe4a4d6ea6bfd6931464a44c95eef731/numpy-2.1.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5641516794ca9e5f8a4d17bb45446998c6554704d888f86df9b200e66bdcce56", size = 16039822 },
|
||||
{ url = "https://files.pythonhosted.org/packages/ad/cd/098bc1d5a5bc5307cfc65ee9369d0ca658ed88fbd7307b0d49fab6ca5fa5/numpy-2.1.3-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ea4dedd6e394a9c180b33c2c872b92f7ce0f8e7ad93e9585312b0c5a04777a4a", size = 16411822 },
|
||||
{ url = "https://files.pythonhosted.org/packages/83/a2/7d4467a2a6d984549053b37945620209e702cf96a8bc658bc04bba13c9e2/numpy-2.1.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:b0df3635b9c8ef48bd3be5f862cf71b0a4716fa0e702155c45067c6b711ddcef", size = 14079598 },
|
||||
{ url = "https://files.pythonhosted.org/packages/e9/6a/d64514dcecb2ee70bfdfad10c42b76cab657e7ee31944ff7a600f141d9e9/numpy-2.1.3-cp313-cp313-win32.whl", hash = "sha256:50ca6aba6e163363f132b5c101ba078b8cbd3fa92c7865fd7d4d62d9779ac29f", size = 6236021 },
|
||||
{ url = "https://files.pythonhosted.org/packages/bb/f9/12297ed8d8301a401e7d8eb6b418d32547f1d700ed3c038d325a605421a4/numpy-2.1.3-cp313-cp313-win_amd64.whl", hash = "sha256:747641635d3d44bcb380d950679462fae44f54b131be347d5ec2bce47d3df9ed", size = 12560405 },
|
||||
{ url = "https://files.pythonhosted.org/packages/a7/45/7f9244cd792e163b334e3a7f02dff1239d2890b6f37ebf9e82cbe17debc0/numpy-2.1.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:996bb9399059c5b82f76b53ff8bb686069c05acc94656bb259b1d63d04a9506f", size = 20859062 },
|
||||
{ url = "https://files.pythonhosted.org/packages/b1/b4/a084218e7e92b506d634105b13e27a3a6645312b93e1c699cc9025adb0e1/numpy-2.1.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:45966d859916ad02b779706bb43b954281db43e185015df6eb3323120188f9e4", size = 13515839 },
|
||||
{ url = "https://files.pythonhosted.org/packages/27/45/58ed3f88028dcf80e6ea580311dc3edefdd94248f5770deb980500ef85dd/numpy-2.1.3-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:baed7e8d7481bfe0874b566850cb0b85243e982388b7b23348c6db2ee2b2ae8e", size = 5116031 },
|
||||
{ url = "https://files.pythonhosted.org/packages/37/a8/eb689432eb977d83229094b58b0f53249d2209742f7de529c49d61a124a0/numpy-2.1.3-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:a9f7f672a3388133335589cfca93ed468509cb7b93ba3105fce780d04a6576a0", size = 6629977 },
|
||||
{ url = "https://files.pythonhosted.org/packages/42/a3/5355ad51ac73c23334c7caaed01adadfda49544f646fcbfbb4331deb267b/numpy-2.1.3-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7aac50327da5d208db2eec22eb11e491e3fe13d22653dce51b0f4109101b408", size = 13575951 },
|
||||
{ url = "https://files.pythonhosted.org/packages/c4/70/ea9646d203104e647988cb7d7279f135257a6b7e3354ea6c56f8bafdb095/numpy-2.1.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4394bc0dbd074b7f9b52024832d16e019decebf86caf909d94f6b3f77a8ee3b6", size = 16022655 },
|
||||
{ url = "https://files.pythonhosted.org/packages/14/ce/7fc0612903e91ff9d0b3f2eda4e18ef9904814afcae5b0f08edb7f637883/numpy-2.1.3-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:50d18c4358a0a8a53f12a8ba9d772ab2d460321e6a93d6064fc22443d189853f", size = 16399902 },
|
||||
{ url = "https://files.pythonhosted.org/packages/ef/62/1d3204313357591c913c32132a28f09a26357e33ea3c4e2fe81269e0dca1/numpy-2.1.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:14e253bd43fc6b37af4921b10f6add6925878a42a0c5fe83daee390bca80bc17", size = 14067180 },
|
||||
{ url = "https://files.pythonhosted.org/packages/24/d7/78a40ed1d80e23a774cb8a34ae8a9493ba1b4271dde96e56ccdbab1620ef/numpy-2.1.3-cp313-cp313t-win32.whl", hash = "sha256:08788d27a5fd867a663f6fc753fd7c3ad7e92747efc73c53bca2f19f8bc06f48", size = 6291907 },
|
||||
{ url = "https://files.pythonhosted.org/packages/86/09/a5ab407bd7f5f5599e6a9261f964ace03a73e7c6928de906981c31c38082/numpy-2.1.3-cp313-cp313t-win_amd64.whl", hash = "sha256:2564fbdf2b99b3f815f2107c1bbc93e2de8ee655a69c261363a1172a79a257d4", size = 12644098 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "svg-py"
|
||||
version = "1.5.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/b9/6d/4680d284924d66082b39e7508b70346a8132c06a4bac497ef4d2c05430ec/svg_py-1.5.0.tar.gz", hash = "sha256:a036d0118176c2498601fab33b9b68dd9754e6a5fa12e4d36cce071b307b5c11", size = 40710 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/51/2b/a541bed029de9ac6a558d3eeeeb0fff5046687651e61d38df3dc43f48e2a/svg_py-1.5.0-py3-none-any.whl", hash = "sha256:5c467efd5a43e8df4dd6f6d078063f195a04966721d36c43d62f5d7529f908d1", size = 13443 },
|
||||
]
|
Loading…
Reference in New Issue
Block a user