Mathematics
Complex Analysis · Visualisation · ⌛ ~16 min read · Last updated: 22 June 2026

Complex Functions and Domain Colouring: Visualising the Invisible

A complex function maps one pair of numbers to another, living in a four-dimensional space that defies direct plotting. Domain colouring is an elegant solution: encode the output as a colour and paint the input plane. Suddenly poles become rosettes of cycling hues, zeros collapse to darkness, branch cuts appear as colour cliffs, and the Riemann zeta function's critical zeros glow like beads on a line. This article explains the mathematics behind the technique and explores what it reveals about some of the most profound functions in mathematics.

1. Complex Numbers and Functions

A complex number z = x + iy combines a real part x and an imaginary part y, where i = √(−1). Its polar form z = r e = r(cosθ + i sinθ) expresses the same information as modulus r = |z| = √(x² + y²) and argument θ = arg(z) = arctan(y/x). Euler's formula e = cosθ + i sinθ unifies trigonometry and exponential growth in a single equation and underlies all of domain colouring.

Complex number: z = x + iy = r·e^(iθ) Modulus: |z| = r = √(x² + y²) Argument: θ = arg(z) = atan2(y, x) ∈ (−π, π] Conjugate: z̄ = x − iy, z·z̄ = |z|² = r² Arithmetic: (a+ib)(c+id) = (ac−bd) + i(ad+bc) 1/z = z̄ / |z|² = (x − iy) / (x² + y²) z^n = r^n · e^(inθ) (De Moivre's theorem) |z₁·z₂| = |z₁|·|z₂|, arg(z₁z₂) = arg(z₁) + arg(z₂) mod 2π A complex function f: ℂ → ℂ assigns a complex value to each point: f(z) = u(x,y) + i·v(x,y) Examples: f(z) = z² = (x²−y²) + i(2xy) f(z) = e^z = eˣ(cos y + i sin y) f(z) = sin z = sin x·cosh y + i·cos x·sinh y f(z) = 1/z = x/(x²+y²) − i·y/(x²+y²)

Complex functions are far richer than their real counterparts. A function of a real variable can only grow, shrink, or oscillate; a complex function rotates, stretches, contracts, and folds the plane in patterns controlled by its analytic structure. The derivative f'(z) = limh→0(f(z+h) − f(z))/h must be the same regardless of the direction of approach in the complex plane — a far stronger requirement than real differentiability, leading to the Cauchy–Riemann equations and, ultimately, to remarkably rigid geometric behaviour.

2. The Domain Colouring Method

Domain colouring, introduced by Frank Farris and popularised by Hans Lundmark and Elias Wegert, converts each output value f(z) into a colour. The canonical scheme uses HSV (hue, saturation, value):

For each pixel at position z in the complex plane, compute w = f(z): Hue: H = arg(w) / (2π) ∈ [0, 1) Maps argument 0 → red, π/3 → yellow, 2π/3 → green, π → cyan, 4π/3 → blue, 5π/3 → magenta → red Value (brightness) options: (a) Modulus rings: V = (log|w| mod 1)^0.5 — logarithmic contours (b) Continuous: V = |w| / (1 + |w|) — bounded 0→1 (c) Checkerboard: overlay grid lines for |Im(z)| or |Re(z)| mod 1 Saturation: S = 1 (fully saturated, vivid colours) Reading the plot: Colour cycling anticlockwise around a point → zero of f at that point Colour cycling clockwise → pole n full colour cycles → order-n zero or pole Line of colour discontinuity → branch cut All colours converging with no net cycling → regular point Uniform colour → constant function in that region JavaScript implementation (fragment): function domainColour(re, im, f) { const [wr, wi] = f(re, im); // evaluate f(z) const arg = Math.atan2(wi, wr); // argument of w const mod = Math.hypot(wr, wi); // modulus of w const hue = ((arg / (2*Math.PI)) + 1) % 1; const logMod = Math.log(mod + 1e-12); const val = 0.5 + 0.5 * Math.sin(Math.PI * (logMod % 1)); return hslToRgb(hue, 1.0, val); }

The logarithmic brightness contours are key. Because |f(z)| can range from 0 to ∞, a linear brightness scale would show only a tiny fraction of the structure. Taking log|w| and applying a sinusoidal modulation produces rings of alternating brightness that count the order of magnitude of the modulus, much as contour lines count altitude. Each complete brightness cycle represents a factor of e (≈ 2.718) in modulus.

Enhanced domain colouring (Wegert's “phase portraits”) sometimes uses only the argument, discarding modulus entirely, to produce the purest possible view of phase structure. Phase portraits are particularly striking for functions with many zeros and poles, such as the Riemann zeta function, where the zeros align in a row on the critical line like beads on a wire.

3. Poles, Zeros, and Winding Numbers

The most important features of a complex function are its zeros and poles. Domain colouring makes them immediately visible without computation.

Zeros of f(z): Simple zero at z₀: f(z) ≈ a(z − z₀) near z₀ → colour makes one anticlockwise rotation as z circles z₀ Order-n zero: f(z) ≈ a(z − z₀)ⁿ → n anticlockwise colour rotations Poles of f(z): Simple pole at z₀: f(z) ≈ A/(z − z₀) → one clockwise colour rotation (modulus → ∞) Order-n pole: f(z) ≈ A/(z − z₀)ⁿ → n clockwise rotations Winding number W(C, z₀) = (1/2πi) ∮_C dz/(z − z₀) Counts net anticlockwise revolutions of the curve C around z₀. Argument principle: (1/2πi) ∮_C f'(z)/f(z) dz = N − P where N = zeros inside C (with multiplicity), P = poles Example: f(z) = (z² − 1)(z + 2i) / ((z − i)³(z + 1)) Zeros: z = ±1 (order 1), z = −2i (order 1) → N = 3 Poles: z = i (order 3), z = −1 (order 1) → P = 4 Contour integral result: N − P = 3 − 4 = −1 (net one clockwise colour cycle around a large contour) Essential singularity (Picard's great theorem): Near an essential singularity, f takes every complex value (with at most one exception) infinitely often. Domain colouring: infinitely many colour cycles compressed near the point. Example: f(z) = e^(1/z) at z = 0

The residue theorem is the crowning result of this structure. For a meromorphic function with poles at zk inside a simple closed contour C, the contour integral equals 2πi times the sum of residues. In domain colouring terms, the integral “counts” the net winding of the output colour as we trace C. This geometric interpretation makes the otherwise abstract theorem visually obvious: if you walk along C and the output colour winds once anticlockwise, there must be exactly one more zero than pole inside.

4. Conformal Mapping and Analytic Continuation

Holomorphic functions (complex-differentiable everywhere in a domain) are conformal where their derivative is non-zero: they preserve angles between curves, though they stretch and rotate local neighbourhoods.

Cauchy–Riemann equations (necessary for holomorphicity): f(z) = u(x,y) + iv(x,y) ∂u/∂x = ∂v/∂y and ∂u/∂y = −∂v/∂x → both u and v satisfy Laplace's equation: ∇²u = ∇²v = 0 → u and v are harmonic conjugates Conformal maps and their applications: Möbius transform: w = (az+b)/(cz+d), ad−bc ≠ 0 Maps circles/lines to circles/lines; used in signal processing (bilinear transform) Joukowski transform: w = z + 1/z Maps unit circle to a flat plate; maps near-circles to aerofoil shapes Schwarz–Christoffel: maps upper half-plane to polygon interiors Used in electrostatics, fluid dynamics, heat conduction Logarithm: w = log(z) = ln|z| + i·arg(z) Maps annulus to rectangle; used in conformal antenna design Analytic continuation: A holomorphic function on domain D uniquely extends to any connected domain D': if f₁ on D₁ and f₂ on D₂ agree on D₁ ∩ D₂ ≠ ∅, they are the same function Example: ζ(s) = Σn^(−s) for Re(s)>1, continued to all ℂ \ {1} Domain colouring visualises this: the colour pattern on D extends smoothly into D' Branch cuts are the seams where continuation is blocked by multivaluedness.

Analytic continuation is one of the most remarkable facts in mathematics: a function known on an arbitrarily small open set is uniquely determined everywhere it can be analytically extended. This rigidity has no parallel in real analysis — a real smooth function can be modified on a compact set without affecting its behaviour outside. For complex functions, the entire global structure is encoded in any small patch, a property that makes complex analysis extraordinarily powerful in number theory, physics, and engineering.

5. Special Functions: Gamma, Zeta, and Elliptic

Domain colouring transforms abstract special functions into vivid images that immediately reveal their structure.

Gamma function Γ(z): Definition: Γ(z) = ∫₀^∞ t^(z−1) e^(−t) dt for Re(z) > 0 Functional equation: Γ(z+1) = z·Γ(z) Poles: simple poles at z = 0, −1, −2, … with residue (−1)ⁿ/n! at z = −n Reflection formula: Γ(z)Γ(1−z) = π / sin(πz) Duplication: Γ(z)Γ(z+½) = √π · 2^(1−2z) · Γ(2z) Domain colouring: infinite row of poles on negative real axis, each with a single-cycle colour rosette; entire left half-plane tiled by these features. Riemann zeta function ζ(s): ζ(s) = Σₙ₌₁^∞ n^(−s) = ∏_p (1 − p^(−s))^(−1) for Re(s) > 1 Analytic continuation to ℂ \ {1}; simple pole at s=1 (residue 1) Functional equation: ζ(s) = 2^s π^(s−1) sin(πs/2) Γ(1−s) ζ(1−s) Trivial zeros: s = −2, −4, −6, … (cancelled by sin(πs/2)) Non-trivial zeros: Re(s) = ½ conjectured (Riemann Hypothesis, 1859) Known: first 10¹³ zeros all lie on Re(s) = ½ Domain colouring: zeros appear as dark colour-meeting points on s = ½+it First zeros at t ≈ 14.1, 21.0, 25.0, 30.4, 32.9, … Elliptic functions (Weierstrass ℘): ℘(z; ω₁, ω₂) = 1/z² + Σ'_{m,n} [1/(z−mω₁−nω₂)² − 1/(mω₁+nω₂)²] Doubly periodic: ℘(z + ω₁) = ℘(z + ω₂) = ℘(z) Two poles per period parallelogram (order 2 at z=0) Domain colouring: perfectly repeating lattice pattern; fundamental domain tiles the plane like wallpaper — makes periodicity visually obvious.

The Riemann Hypothesis is the most famous unsolved problem in mathematics: are all non-trivial zeros of ζ(s) on the line Re(s) = 1/2? Domain colouring of ζ near the critical strip makes this visually intuitive — the colour-meeting dark points appear to march precisely along the vertical line, forming a sequence that encodes the distribution of prime numbers via the explicit formula ψ(x) = x − Σρ xρ/ρ − log(2π) − ½ log(1 − x−2).

6. Real-World Applications

Complex analysis and domain colouring are not purely aesthetic pursuits; they underpin engineering, physics, and computation in fundamental ways.

Frequently Asked Questions

Why can we not simply plot a complex function as a 3D surface?

A complex function f: ℂ → ℂ takes a 2D input (the complex plane) and produces a 2D output (another complex plane). To graph it faithfully we would need four real dimensions — two for the input, two for the output — which is impossible to display directly. Common partial solutions include: graphing only |f(z)| as a height above the input plane (losing argument information), graphing only arg(f(z)) (losing modulus), or — best of all — using domain colouring to encode both simultaneously in a single 2D image.

What does it mean for a complex function to be “analytic”?

A function is analytic (or holomorphic) at a point if it is complex-differentiable in some open neighbourhood of that point. This is a far stronger condition than real differentiability: it implies the function equals its Taylor series, is infinitely differentiable, satisfies the Cauchy–Riemann equations, has harmonic real and imaginary parts, and is conformal wherever its derivative is non-zero. In domain colouring, analytic regions show smooth, continuous colour variation; isolated singularities stand out as colour-cycling anomalies.

How does domain colouring reveal branch cuts?

Branch cuts are lines along which a multivalued function must be made single-valued by choosing one branch, introducing a discontinuity. In domain colouring, they appear as sharp lines where the hue jumps abruptly, typically by half the colour wheel (a sudden shift from one colour to its complement). For √z with the standard branch cut along the negative real axis, the colour jumps from cyan to red across the negative axis, reflecting the jump in argument of √z from −π/2 to +π/2 as one crosses the cut.