Mandelbrot set: Difference between revisions
Content added Content deleted
(adding lambdatalk answer) |
(→Normalized Iteration Count, Distance Estimation and Mercator Maps: Added: e^(-|z|)-smoothing) |
||
Line 7,461: | Line 7,461: | ||
===Normalized Iteration Count, Distance Estimation and Mercator Maps=== |
===Normalized Iteration Count, Distance Estimation and Mercator Maps=== |
||
Actually the same, but without optimizations and therefore better suited for teaching. |
Actually the same, but without optimizations and therefore better suited for teaching. |
||
The ''escape time'', ''normalized iteration count'' and ''exterior distance estimation'' algorithms are used with NumPy and complex matrices (see |
The ''escape time'', ''e^(-|z|)-smoothing '', ''normalized iteration count'' and ''exterior distance estimation'' algorithms are used with NumPy and complex matrices (see Francisco Garcia, Angel Fernandez, Javier Barrallo, Luis Martin: [http://math.unipa.it/~grim/Jbarrallo.PDF ''Coloring Dynamical Systems in the Complex Plane''] and Mikael Hvidtfeldt Christensen: [http://blog.hvidtfeldts.net/index.php/2011/09/distance-estimated-3d-fractals-v-the-mandelbulb-different-de-approximations ''Distance Estimated 3D Fractals (V): The Mandelbulb & Different DE Approximations'']). |
||
Finally, the Mandelbrot set is also printed with a scatter plot which will be misused later for a nice effect. |
Finally, the Mandelbrot set is also printed with a scatter plot which will be misused later for a nice effect. |
||
<lang python>import numpy as np |
<lang python>import numpy as np |
||
Line 7,476: | Line 7,476: | ||
Z, dZ = np.zeros_like(C), np.zeros_like(C) |
Z, dZ = np.zeros_like(C), np.zeros_like(C) |
||
T, D = np.zeros(C.shape), np.zeros(C.shape) |
T, S, D = np.zeros(C.shape), np.zeros(C.shape), np.zeros(C.shape) |
||
for k in range(n): |
for k in range(n): |
||
M = abs(Z) < r |
M = abs(Z) < r |
||
T[M], S[M] = T[M] + 1, S[M] + np.exp(-abs(Z[M])) |
|||
Z[M], dZ[M] = Z[M] ** 2 + C[M], 2 * Z[M] * dZ[M] + 1 |
Z[M], dZ[M] = Z[M] ** 2 + C[M], 2 * Z[M] * dZ[M] + 1 |
||
T[M] = T[M] + 1 |
|||
plt.imshow(T ** 0.1, cmap=plt.cm.twilight_shifted) |
plt.imshow(T ** 0.1, cmap=plt.cm.twilight_shifted) |
||
plt.savefig("Mandelbrot_set_1.png", dpi=250) |
plt.savefig("Mandelbrot_set_1.png", dpi=250) |
||
plt.imshow(S ** 0.1, cmap=plt.cm.twilight_shifted) |
|||
plt.savefig("Mandelbrot_set_2.png", dpi=250) |
|||
N = abs(Z) > r # normalized iteration count |
N = abs(Z) > r # normalized iteration count |
||
Line 7,490: | Line 7,493: | ||
plt.imshow(T ** 0.1, cmap=plt.cm.twilight_shifted) |
plt.imshow(T ** 0.1, cmap=plt.cm.twilight_shifted) |
||
plt.savefig(" |
plt.savefig("Mandelbrot_set_3.png", dpi=250) |
||
N = abs(Z) > 2 # exterior distance estimation |
N = abs(Z) > 2 # exterior distance estimation |
||
Line 7,496: | Line 7,499: | ||
plt.imshow(D ** 0.1, cmap=plt.cm.twilight_shifted) |
plt.imshow(D ** 0.1, cmap=plt.cm.twilight_shifted) |
||
plt.savefig(" |
plt.savefig("Mandelbrot_set_4.png", dpi=250) |
||
X, Y = C.real, C.imag |
X, Y = C.real, C.imag |
||
R = 150 * 2 / d # scaling depends on figsize |
|||
fig, ax = plt.subplots(figsize=(8, 6)) |
fig, ax = plt.subplots(figsize=(8, 6)) |
||
ax.scatter(X, Y, s= |
ax.scatter(X, Y, s=R**2, c=D**0.1, cmap=plt.cm.twilight_shifted) |
||
plt.savefig("Mandelbrot_plot.png", dpi=250)</lang> |
plt.savefig("Mandelbrot_plot.png", dpi=250)</lang> |
||
A small change in the |
A small change in the code above creates Mercator maps of the Mandelbrot set (see David Madore: [http://www.madore.org/~david/math/mandelbrot.html ''Mandelbrot set images and videos''] and Anders Sandberg: [https://www.flickr.com/photos/arenamontanus/sets/72157615740829949 ''Mercator Mandelbrot Maps'']). |
||
The maximum magnification is exp(2*pi*h/d) = exp(2*pi*5.5) = 535.5^5.5 = 10^15, which is also the maximum for 64-bit arithmetic. |
The maximum magnification is exp(2*pi*h/d) = exp(2*pi*5.5) = 535.5^5.5 = 10^15, which is also the maximum for 64-bit arithmetic. |
||
Note that Anders Sandberg uses a different scaling. |
Note that Anders Sandberg uses a different scaling. |
||
Line 7,523: | Line 7,526: | ||
Z, dZ = np.zeros_like(C), np.zeros_like(C) |
Z, dZ = np.zeros_like(C), np.zeros_like(C) |
||
T, D = np.zeros(C.shape), np.zeros(C.shape) |
T, S, D = np.zeros(C.shape), np.zeros(C.shape), np.zeros(C.shape) |
||
for k in range(n): |
for k in range(n): |
||
M = abs(Z) < r |
M = abs(Z) < r |
||
T[M], S[M] = T[M] + 1, S[M] + np.exp(-abs(Z[M])) |
|||
Z[M], dZ[M] = Z[M] ** 2 + C[M], 2 * Z[M] * dZ[M] + 1 |
Z[M], dZ[M] = Z[M] ** 2 + C[M], 2 * Z[M] * dZ[M] + 1 |
||
T[M] = T[M] + 1 |
|||
plt.imshow(T.T ** 0.1, cmap=plt.cm.nipy_spectral_r) |
plt.imshow(T.T ** 0.1, cmap=plt.cm.nipy_spectral_r) |
||
plt.savefig("Mercator_map_1.png", dpi=250) |
plt.savefig("Mercator_map_1.png", dpi=250) |
||
plt.imshow(S.T ** 0.1, cmap=plt.cm.nipy_spectral_r) |
|||
plt.savefig("Mercator_map_2.png.png", dpi=250) |
|||
N = abs(Z) > r # normalized iteration count |
N = abs(Z) > r # normalized iteration count |
||
Line 7,537: | Line 7,543: | ||
plt.imshow(T.T ** 0.1, cmap=plt.cm.nipy_spectral_r) |
plt.imshow(T.T ** 0.1, cmap=plt.cm.nipy_spectral_r) |
||
plt.savefig(" |
plt.savefig("Mercator_map_3.png", dpi=250) |
||
N = abs(Z) > 2 # exterior distance estimation |
N = abs(Z) > 2 # exterior distance estimation |
||
Line 7,543: | Line 7,549: | ||
plt.imshow(D.T ** 0.1, cmap=plt.cm.nipy_spectral) |
plt.imshow(D.T ** 0.1, cmap=plt.cm.nipy_spectral) |
||
plt.savefig(" |
plt.savefig("Mercator_map_4.png", dpi=250) |
||
X, Y = C.real, C.imag |
X, Y = C.real, C.imag |
||
R = 150 * 2 / d * np.pi * np.exp(-B) # scaling depends on figsize |
|||
fig, ax = plt.subplots(2, 2, figsize=(16, 16)) |
fig, ax = plt.subplots(2, 2, figsize=(16, 16)) |
||
ax[0, 0].scatter(X[0:300], Y[0:300], s= |
ax[0, 0].scatter(X[0:300], Y[0:300], s=R[0:300]**2, c=D[0:300]**0.5, cmap=plt.cm.nipy_spectral) |
||
ax[0, 1].scatter(X[100:400], Y[100:400], s= |
ax[0, 1].scatter(X[100:400], Y[100:400], s=R[0:300]**2, c=D[100:400]**0.4, cmap=plt.cm.nipy_spectral) |
||
ax[1, 0].scatter(X[200:500], Y[200:500], s= |
ax[1, 0].scatter(X[200:500], Y[200:500], s=R[0:300]**2, c=D[200:500]**0.3, cmap=plt.cm.nipy_spectral) |
||
ax[1, 1].scatter(X[300:600], Y[300:600], s= |
ax[1, 1].scatter(X[300:600], Y[300:600], s=R[0:300]**2, c=D[300:600]**0.2, cmap=plt.cm.nipy_spectral) |
||
plt.savefig("Mandelbrot_zoom.png", dpi=250)</lang> |
plt.savefig("Mandelbrot_zoom.png", dpi=250)</lang> |
||