Mandelbrot set: Difference between revisions

Content added Content deleted
(adding lambdatalk answer)
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 Wikipedia: [https://en.wikipedia.org/wiki/Plotting_algorithms_for_the_Mandelbrot_set ''Plotting algorithms for the Mandelbrot set''] and Syntopia: [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'']).
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("Mandelbrot_set_2.png", dpi=250)
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("Mandelbrot_set_3.png", dpi=250)
plt.savefig("Mandelbrot_set_4.png", dpi=250)


X, Y = C.real, C.imag
X, Y = C.real, C.imag
S = 150 * 2 / d # scaling depends on figsize
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=S**2, c=D**0.1, cmap=plt.cm.twilight_shifted)
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 above code allows 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'']).
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("Mercator_map_2.png", dpi=250)
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("Mercator_map_3.png", dpi=250)
plt.savefig("Mercator_map_4.png", dpi=250)


X, Y = C.real, C.imag
X, Y = C.real, C.imag
S = 150 * 2 / d * np.pi * np.exp(-B) # scaling depends on figsize
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=S[0:300]**2, c=D[0:300]**0.5, cmap=plt.cm.nipy_spectral)
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=S[0:300]**2, c=D[100:400]**0.4, cmap=plt.cm.nipy_spectral)
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=S[0:300]**2, c=D[200:500]**0.3, cmap=plt.cm.nipy_spectral)
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=S[0:300]**2, c=D[300:600]**0.2, cmap=plt.cm.nipy_spectral)
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>