Skip to content

About

Reproducible GitHub avatars from real mathematical objects: Hopf fibration, Calabi-Yau, twisted-bilayer moire, Hamiltonian cycles (NumPy + VTK)

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Latest commit

 

History

4 Commits

Folders and files

Repository files navigation

math-avatars

CI License: MIT Python 3.10–3.13

Profile pictures that are computed, not drawn: the Hopf fibration, a Calabi–Yau cross-section, twisted bilayer graphene as a scanning tunnelling microscope would see it, and Hamilton's Icosian game. Every image comes out of a few hundred lines of NumPy (the 3D ones are shaded off-screen with VTK through PyVista), so an avatar is a command plus a palette, and changing the palette is changing a list of hex colours. Everything is composed for GitHub's circular crop, checked down to 20 px, and saved below GitHub's 1 MB upload limit.

Twelve avatars: Hopf fibrations in six palettes, two Calabi-Yau surfaces, a moire pattern, a quasicrystal and a Hamiltonian cycle

Gallery

Avatar What you are looking at Command
Hopf fibration Circles of $S^3$, one over each point of $S^2$, stereographically projected. Fibres over a circle of latitude sweep out a torus; three latitudes give three nested tori, and the fibres cover a 243° arc of longitude so that the nesting shows. Any two of the circles are linked exactly once. mathavatars hopf celadon
Calabi–Yau The complex curve $z_1^5 + z_2^5 = 1$, a two-dimensional slice of the quintic threefold, in Hanson's 25-patch construction, projected from $\mathbb{C}^2=\mathbb{R}^4$ to $\mathbb{R}^3$ and viewed along one of its mirror planes. mathavatars calabi-yau sunset
Moiré Two graphene layers twisted by 6.01°, the commensurate $(5,6)$ structure with a $\sqrt{91},a$ moiré cell, rendered like an STM topograph: bright AA-stacked sites with the atomic lattice inside them. mathavatars moire ember
Quasicrystal The same bilayer twisted by 30°. The lattices never realign; the pattern is a dodecagonal (12-fold) quasicrystal. mathavatars quasicrystal gold
Icosian game A Hamiltonian cycle on the dodecahedron, on its Schlegel diagram. The cycle is not hand-placed: all 30 are found by exhaustive search and reduced to the 3 classes that differ under the symmetries of the diagram. mathavatars hamilton

The 512 px files in gallery/ can be used as they are.

Install

pip install git+https://github.com/HamsterPark/math-avatars

or clone the repository and pip install -e .. Python ≥ 3.10; the dependencies are NumPy, Pillow and PyVista. The two 3D avatars need an OpenGL context (any desktop GPU, or Mesa/xvfb on a headless machine); the moiré, quasicrystal and Icosian avatars are pure NumPy.

Usage

mathavatars palettes                      # what is available
mathavatars hopf celadon copper           # -> hopf_celadon.png, hopf_copper.png (1024 px)
mathavatars hopf --all --outdir out       # all 15 palettes; the tube mesh is built once
mathavatars calabi-yau aurora --size 512
mathavatars moire gold
mathavatars quasicrystal
mathavatars hamilton --cycle 1            # the three symmetry classes are 0, 1, 2
mathavatars preview out/*.png -o preview.png

python -m mathavatars … works too. Then: GitHub → Settings → Public profile → Profile picture.

preview shows each avatar the way GitHub does – cropped to a circle at 260, 64, 40 and 20 px, on the dark and the light theme. If it does not read at 20 px it is not an avatar yet:

Contact sheet of four avatars at four sizes on GitHub's dark and light theme

Palettes

The fifteen Hopf palettes

Most palettes are taken from a material rather than from a colour wheel, which keeps the hue range narrow and lets lightness do the work: celadon glaze with a cinnabar seal, bronze patina, polished and oxidised copper, amber, persimmon dye with indigo, malachite and azurite with old gold, a deep-sea chart, a lithograph, instrument brass, an old chemistry lab. dusk, twilight, berry and rainbow are the spectral ones. The Calabi–Yau palettes are sunset, aurora and the view-dependent pearl; the graphene palettes are ember, lagoon and gold.

Your own palette

A Hopf palette is a gradient along the family of fibres (position 0 is the first fibre of the arc, 1 the last) plus the badge colours and a surface finish:

from mathavatars import hopf

mine = dict(
    # colour stops, interpolated in OKLab, and where each one sits along the arc
    stops=["#f2e9d8", "#d9a441", "#8c3b2a", "#2b1d2a", "#2f6f6a"],
    pos=[0.00, 0.20, 0.60, 0.956, 1.00],
    # past 0.956 only torus 2 (the outer one) keeps following the gradient
    warm_from=0.956,
    warm_layers=(2,),
    # badge colour and the glow behind the object
    bg="#10151d",
    halo="#1d3146",
    # "satin" or "gloss", see mathavatars.render.FINISHES
    finish="satin",
)
hopf.make(mine, "hopf_mine.png")

warm_from / warm_layers keep an accent on the outer torus: the inner tori stop following the gradient at warm_from and hold that colour. With 24 fibres the last-but-one sits at 22/23 = 0.956, so a stop there followed by the accent at 1.0 gives exactly one accent ring.

Design rules

  • The circle comes first. The camera is fitted to the smallest circle enclosing the projected mesh and the object fills 90 % of it, so nothing is lost to GitHub's crop.
  • One colour per fibre. Colour encodes where a fibre sits in the family and never varies along a tube, so at small sizes the eye sees bundles of circles instead of coloured plastic.
  • Gradients live in OKLab, where a straight line between two colours keeps an even lightness ramp instead of sagging into grey; stops are placed so that lightness, not hue, carries the form at 20 px.
  • One accent, on the outer torus only, and the fibre before it takes the darkest shade of the main hue: mixing complementary colours (pine → cinnabar, cognac → petrol) would otherwise put a muddy ring right next to the accent.
  • The badge is #111827-ish, close to GitHub's dark canvas #0d1117 but not equal to it: the disc stays faintly visible in dark mode and is a complete dark badge in light mode. The halo fades out before the rim, so the rim is exactly that colour.
  • Satin, not plastic: a broad, faint, slightly warm highlight with a warm key and a cool fill light reads as glaze, stone or metal.
  • Under 1 MB. GitHub rejects larger profile pictures; save_avatar steps the edge length down until the PNG fits.

The mathematics

Hopf fibration. Over the point $(\theta,\varphi)$ of $S^2$ lies the great circle

$$z_1=\cos\tfrac{\theta}{2},e^{i(t+\varphi)},\qquad z_2=\sin\tfrac{\theta}{2},e^{it},\qquad t\in[0,2\pi)$$

of $S^3\subset\mathbb{C}^2$; indeed $z_1/z_2=\cot\tfrac{\theta}{2},e^{i\varphi}$ does not depend on $t$. Stereographic projection from $(0,0,0,1)$ maps it to a circle in $\mathbb{R}^3$. The tube radius is multiplied by the conformal factor $1/(1-x_4)$, so every fibre has constant thickness as measured in $S^3$ – that is why the tubes swell away from the centre.

Calabi–Yau. Hanson's parametrisation of $z_1^n+z_2^n=1$ with $n=5$:

$$z_1=e^{2\pi i k_1/5}\cosh(w)^{2/5},\qquad z_2=e^{i\pi/5},e^{2\pi i k_2/5}\sinh(w)^{2/5},$$

$w=x+iy$, $x\in[-1,1]$, $y\in[0,\pi/2]$, $k_1,k_2=0,\dots,4$, projected by $(\mathrm{Re},z_1,\ \mathrm{Re},z_2,\ \cos\alpha,\mathrm{Im},z_1+\sin\alpha,\mathrm{Im},z_2)$ with $\alpha=\pi/4$. Normals are exact: the holomorphic tangent $(z_1',z_2')$ is rescaled by a common complex factor to $(c_1\sinh(w)^{8/5},\ c_2\cosh(w)^{8/5})$, which stays finite at the branch points $w=0,\ i\pi/2$ where the derivative itself diverges. The surface is smooth in $\mathbb{C}^2$; its shadow in $\mathbb{R}^3$ is not (it crosses itself and has five pinch points on the mirror plane).

Twisted bilayer graphene. Each layer is the first-harmonic honeycomb density $h(\mathbf r)=-\tfrac23\sum_{j=1}^{3}\cos(\mathbf G_j\cdot\mathbf r)$ with $|\mathbf G_j|=4\pi/(\sqrt3,a)$: $+1$ on the atoms, $-2$ in the hexagon centres. Rotating two copies by $\pm\theta/2$ about a common hexagon centre puts an AA site at the origin. The commensurate angles used are

$$\cos\theta=\frac{n^2+4nm+m^2}{2,(n^2+nm+m^2)},\qquad n=m+1,\qquad L=a\sqrt{3m^2+3m+1},$$

so $m=5$ gives $\theta=6.009^\circ$ and $L=\sqrt{91},a$. At $\theta=30^\circ$ no such cell exists and the sum of the two layers is invariant under rotation by 30°: a dodecagonal quasicrystal.

Icosian game. The dodecahedral graph has 30 Hamiltonian cycles. The symmetry group of its Schlegel diagram ($D_5$, ten elements) splits them into 3 orbits of 10, i.e. no Hamiltonian cycle has a symmetry that is visible in the diagram – which is why the drawing looks lopsided however you turn it.

The test-suite checks this mathematics rather than pixels: every fibre lies over one point of $S^2$ and is a planar circle, two fibres have Gauss linking number 1, all 25 patches satisfy the quintic and share their seams, the regularised tangent is parallel to the numerical derivative, the honeycomb is lattice periodic, the 30° bilayer is 12-fold symmetric, and the search finds 30 cycles in 3 classes.

Rendering notes

Three pitfalls worth knowing about:

  • SSAO banding. VTK's ambient-occlusion pass keeps view-space positions in half floats. With the camera far from the mesh the depth is quantised and the occlusion term shows wood-grain contours. The camera projection is parallel, so its distance is free – keep it just outside the bounding sphere.
  • Seams. smooth_shading=True in PyVista recomputes normals per mesh piece, which shows the seams between the 25 Calabi–Yau patches. Set the exact normals as the active normals and switch the actor to Phong interpolation instead.
  • Pinholes. The parameter grid must contain the branch points as vertices (odd grid size, grid refined towards them), otherwise every branch point is a small hole in the mesh.

Development

pip install -e ".[dev]"
ruff check . && ruff format --check .
pytest                                          # mathematics, palettes, CLI, image output
MATHAVATARS_RENDER_TESTS=1 pytest -m render      # end-to-end VTK renders, needs OpenGL
python docs/make_figures.py                     # rebuild the README figures from gallery/

References

  • H. Hopf, Über die Abbildungen der dreidimensionalen Sphäre auf die Kugelfläche, Math. Ann. 104 (1931). The layout – fibres over circles of latitude, coloured by longitude – follows the well-known visualisation by Niles Johnson.
  • A. J. Hanson, A construction for computer visualization of certain complex curves, Notices of the AMS 41 (9), 1156–1163 (1994).
  • S. J. Ahn et al., Dirac electrons in a dodecagonal quasicrystal, Science 361, 782–786 (2018).
  • W. R. Hamilton, The Icosian Game (1857).
  • B. Ottosson, A perceptual color space for image processing (2020).

License

MIT, images included – use one as your avatar if you like, or better, make your own palette.

About

Reproducible GitHub avatars from real mathematical objects: Hopf fibration, Calabi-Yau, twisted-bilayer moire, Hamiltonian cycles (NumPy + VTK)

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages