Skip to content
Sample of Hyphae Network

nervous_system_hansmeyer · HyphaeNetwork

Hyphae Network

A 2D port of Nervous System's Hyphae generative jewelry. Hyphae are root-like rhizome networks that fuse Nervous System's two favourite algorithms: an L-system defines the branching skeleton, and a space-colonization pass (Runions et al., 2005) fills the interior with a venation pattern attracted to a cloud of 'auxin' points. We collapse the L-system into a single radial array of root tips and run the space-colonization loop directly. Each tip samples attractors within an attraction radius, averages their directions, advances along that vector, and removes any attractor that falls inside the kill radius. Stochastic side-branches are spawned with a small probability per tip per step, building a hierarchical root-like mesh.

Original: https://n-e-r-v-o-u-s.com/blog/?p=1392

▶ Try the live demo (JS port) ▶ Run reference.py via Pyodide 10 formulas have instant JS ports. The Pyodide path runs the actual Python in your browser — first load is ~6 MB, then instant.

Family
nervous_system_hansmeyer
Source
nervous system × hansmeyer
Evolution
network
Render
line_painting
Complexity
high
Agents
600
Year
2014
Author
Nervous System (Jessica Rosenkrantz & Jesse Louis-Rosenberg)

Math essence

For each tip i and attractor a_j with |p_i - a_j| < d_attract, accumulate diff = (a_j - p_i). The new direction d = normalize(sum diffs). New tip p_i' = p_i + d * L_segment. Attractor a_j is removed when |p_i - a_j| < d_kill. With probability p_branch a tip spawns two rotated clones, yielding the rhizome-like hierarchy.

Parameters

Name Type Default Range Description
dim int 600 200–1200 Square canvas side length
n_attractors int 600 30–4000 Number of auxin/attractor points scattered inside the disk
attractor_radius float 0.42 0.1–0.5 Radius of the attractor cloud as a fraction of dim
n_roots int 4 1–12 Number of initial root tips
segment_length float 0.0085 0.001–0.05 Per-step tip advance as a fraction of dim
attract_distance float 0.18 0.02–0.5 Maximum distance at which an attractor influences a tip
kill_distance float 0.012 0.001–0.1 Distance below which an attractor is consumed
branch_prob float 0.1 0–0.5 Per-tip probability of spawning a side-branch per step
branch_angle float 0.65 0.05–1.6 Side-branch angle (radians)
thickness_growth float 0.018 0–0.1 Reserved for future thickness-from-flux canalization
max_tips int 1200 30–8000 Hard cap on live tips to bound memory
max_steps int 240 20–1000 Number of simulation ticks
bg_color tuple 12,14,22 null–null Background RGB
vein_color tuple 200,230,220 null–null Primary vein RGB
core_color tuple 255,200,130 null–null Thick-root RGB
seed int null 0–999999 RNG seed

Reference

First 60 lines of reference.py. Full source: library_external/nervous_system_hansmeyer/HyphaeNetwork/reference.py

from __future__ import annotations

from typing import ClassVar

import imageio.v2 as imageio
import numpy as np


class HyphaeNetwork:
    family: ClassVar[str] = "nervous_system_hansmeyer"
    sketch: ClassVar[str] = "HyphaeNetwork"

    def __init__(
        self,
        dim: int = 600,
        n_attractors: int = 600,
        attractor_radius: float = 0.42,
        n_roots: int = 4,
        root_radius: float = 0.05,
        segment_length: float = 0.0085,
        attract_distance: float = 0.18,
        kill_distance: float = 0.012,
        branch_prob: float = 0.10,
        branch_angle: float = 0.65,
        thickness_growth: float = 0.018,
        max_tips: int = 1200,
        max_steps: int = 240,
        bg_color: tuple[int, int, int] = (12, 14, 22),
        vein_color: tuple[int, int, int] = (200, 230, 220),
        core_color: tuple[int, int, int] = (255, 200, 130),
        seed: int | None = None,
    ) -> None:
        self.dim = dim
        self.n_attractors = n_attractors
        self.attractor_radius = attractor_radius
        self.n_roots = n_roots
        self.root_radius = root_radius
        self.segment_length = segment_length
        self.attract_distance = attract_distance
        self.kill_distance = kill_distance
        self.branch_prob = branch_prob
        self.branch_angle = branch_angle
        self.thickness_growth = thickness_growth
        self.max_tips = max_tips
        self.max_steps = max_steps
        self.bg_color = np.array(bg_color, dtype=np.uint8)
        self.vein_color = np.array(vein_color, dtype=np.uint8)
        self.core_color = np.array(core_color, dtype=np.uint8)
        self._seed = seed
        self.rng = np.random.default_rng(seed)
        self.canvas = np.full((dim, dim, 3), self.bg_color, dtype=np.uint8)
        self._stage = 0
        self.time = 0
        self._nodes: list[np.ndarray] = []
        self._parents: list[int] = []
        self._thickness: list[float] = []
        self._tips: list[int] = []
        self._attractors: np.ndarray = np.zeros((0, 2), dtype=np.float32)
        self.reset()

Try running it locally

The reference implementation is self-contained Python with numpy. Install the package and run:

python library_external/nervous_system_hansmeyer/HyphaeNetwork/reference.py

Need help? See Learn for the standard environment setup, or Playground for an in-browser sketchbook.

More from nervous system × hansmeyer

See all nervous_system_hansmeyer artworks →