Skip to content

Commit b49f034

Browse files
authored
Domain Coloring in Python using Matplotlib (algorithm-archivists#788)
* Added domain coloring in Python * Some cleanup
1 parent f9a6eda commit b49f034

File tree

2 files changed

+85
-0
lines changed

2 files changed

+85
-0
lines changed
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
2+
import numpy as np
3+
import matplotlib.pyplot as plt
4+
import matplotlib.colors
5+
from matplotlib.cm import ScalarMappable
6+
7+
8+
def f(z):
9+
return z**2
10+
11+
12+
def magnitude_shading(f_val):
13+
f_val_abs = np.abs(f_val)
14+
return 0.5 + 0.5 * (f_val_abs - np.floor(f_val_abs))
15+
16+
17+
def gridlines(f_val, threshold):
18+
return (np.abs(np.sin(np.pi * np.real(f_val))) ** threshold
19+
* np.abs(np.sin(np.pi * np.imag(f_val))) ** threshold)
20+
21+
22+
def color(f_val, threshold):
23+
hue = (np.pi - np.angle(f_val)) / (2.0 * np.pi)
24+
saturation = magnitude_shading(f_val)
25+
value = gridlines(f_val, threshold)
26+
27+
# Currently we have a tuple of 2D-arrays (hue, saturation, value).
28+
# This makes it a 2D-array of tuples, which the conversion function requires.
29+
hsv = np.moveaxis((hue, saturation, value), 0, -1)
30+
return matplotlib.colors.hsv_to_rgb(hsv)
31+
32+
33+
if __name__ == "__main__":
34+
# Create a new figure containing a single plot
35+
fig, axes = plt.subplots(1, 1)
36+
37+
# Set the title for the plot
38+
axes.set_title("$f(x)=z^2$")
39+
40+
# Create color bar
41+
cbar = fig.colorbar(
42+
ScalarMappable(matplotlib.colors.Normalize(0.0, 2.0 * np.pi), "hsv"),
43+
ax=axes,
44+
label="Phase Angle")
45+
46+
# Set x and y labels
47+
axes.set_xlabel("$Re(z)$")
48+
axes.set_ylabel("$Im(z)$")
49+
50+
# Set color bar tick locations and labels
51+
cbar.set_ticks([0.0, np.pi, 2.0 * np.pi])
52+
cbar.set_ticklabels(["$0.0$", "$\pi$", "$2\pi$"])
53+
54+
# Hide x and y ticks
55+
for tick in axes.get_xticklines():
56+
tick.set_visible(False)
57+
58+
for tick in axes.get_yticklines():
59+
tick.set_visible(False)
60+
61+
# Create a 500x500 input grid
62+
coords = np.linspace(-2.0, 2.0, 500)
63+
z_real, z_imag = np.meshgrid(coords, coords)
64+
z = z_real + 1j * z_imag
65+
66+
# Calculate function values
67+
f_val = f(z)
68+
69+
# Map function values to colors
70+
colors = color(f_val, 0.1)
71+
72+
# Plot the colors
73+
# extent=(-2.0, 2.0, -2.0, 2.0) sets the x and y ranges
74+
# origin="lower" places index (0,0) of the color array in the lower-left corner
75+
# aspect="equal" ensures that the plot is square
76+
axes.imshow(
77+
colors,
78+
extent=(-2.0, 2.0, -2.0, 2.0),
79+
origin="lower",
80+
aspect="equal")
81+
82+
# Save output
83+
fig.savefig("domain.png")

contents/domain_coloring/domain_coloring.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,8 @@ Here is the full script to generate a domain colored output of $$f(z)=z^2$$.
174174
{% method %}
175175
{% sample lang="gnuplot" %}
176176
[import, lang:"gnuplot"](code/gnuplot/domain_coloring.gp)
177+
{% sample lang="python & matplotlib" %}
178+
[import, lang:"python"](code/python/domain_coloring.py)
177179
{% endmethod %}
178180

179181
### Bibliography

0 commit comments

Comments
 (0)