The Julia fractal is a mathematical set generated by the iterative equation
zn+1 = (zn)² + c
where c is a chosen complex number and z a is point of the complex plane.
Steps to determine if given c, a point z belongs to the set:
Choose a complex number c
Take z0 in the complex plane
Iterate the equation until ∣zn∣>2 (meaning the point escapes the set) or until reaching a maximum number of iterations Maxiter.
If after Maxiter iterations we have ∣zn∣≤2, we consider z0 to belong to the filled-in Julia set.
Repeat this process for all points z0 in the complex plane that you wish to evaluate.
To visualize the fractal:
Points that do not belong to the set can be colored based on how many iterations they took to escape, creating gradient patterns that show the "distance" to the set.
Points that belong to the set are usually represented in black.
A very simple Python code for this could be the following:
import numpy as np
import matplotlib.pyplot as plt
# Parameters for the Julia set visualization
width, height = 800, 800
max_iter = 300
c = complex(-0.8, 0.156)
# Complex plane
x = np.linspace(-1.5, 1.5, width)
y = np.linspace(-1.5, 1.5, height)
img = np.zeros((height, width))
for i in range(height):
for j in range(width):
z = complex(x[j], y[i])
n = 0
while abs(z) <= 2 andn < max_iter:
z = z*z + c
n += 1
img[i, j] = n
# show the set
plt.figure(figsize=(8, 8))
plt.imshow(img, cmap='inferno', extent=(-1.5, 1.5, -1.5, 1.5))
plt.title(f"Conjunto de Julia para c = {c}")
plt.axis("off")
plt.show()
Here, some outputs with different values of c:
c=-0.81 + 0.156i
c=0.279
c=0.687+0.312i
c=-1
c=1
c=-0.4+0.6i
c=0.285-0.01i
c=-0.835-0.231i
c=0.4+0.4i
We can modify the code in order to obtain a vide of the Julia set when changing the value of c.
import matplotlib.pyplot as plt
from matplotlib.colors import LinearSegmentedColormap
from matplotlib.animation import FuncAnimation
# Parameters
width, height = 600, 600
max_iter = 50
frames = 150
r = 0.7885
r=0.77
# Complex plane
x = np.linspace(-1.5, 1.5, width)
y = np.linspace(-1.5, 1.5, height)
X, Y = np.meshgrid(x, y)
Z0 = X + 1j * Y
fig, ax = plt.subplots(figsize=(6, 6))
img = ax.imshow(np.zeros((height, width)), cmap="turbo", extent=(-1.5, 1.5, -1.5, 1.5), vmin=0, vmax=max_iter)
ax.axis("off")
# Animation
def update(frame):
t = 2 * np.pi * frame / frames
c = r * np.exp(1.2j * t)
Z = Z0.copy()
M = np.zeros_like(Z0, dtype=int)
for i in range(max_iter):
for m in range(height):
for n in range(width):
if M[m, n] == 0:
Z[m, n] = Z[m, n] ** 2 + c
if abs(Z[m, n]) > 2:
M[m, n] = i
M[M == 0] = max_iter
img.set_data(M)
ax.set_title(f"Julia set\nc = {c.real:.4f} + {c.imag:.4f}i")
return [img]
ani = FuncAnimation(fig, update, frames=frames, blit=True)
ani.save("julia_animation1.gif", writer="pillow", fps=30)
Animation of the Julia set when changing the value of c as c=0.7885eit with t in [0,2π] using the palette of coulors "turbo":
Animation of the Julia set when changing the value of c as c=0.7885eit with t in [0,2π] using the palette of coulors "plasma":