From 2af3aae7f08b9ae8c996b9c39663ba9a0183f5f1 Mon Sep 17 00:00:00 2001 From: "Nicolas P. Rougier" Date: Sat, 12 Nov 2016 11:49:15 +0100 Subject: [PATCH 1/8] Added the (kind of mandatory) Mandelbrot set --- examples/showcase/mandelbrot.py | 65 +++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 examples/showcase/mandelbrot.py diff --git a/examples/showcase/mandelbrot.py b/examples/showcase/mandelbrot.py new file mode 100644 index 000000000000..65600482e1d0 --- /dev/null +++ b/examples/showcase/mandelbrot.py @@ -0,0 +1,65 @@ +# The mandelbrot set rendered with shading and renormalized count +# for better rendering +import numpy as np + + +def mandelbrot(C, maxiter, horizon=4.0): + N = np.zeros(C.shape, dtype=int) + Z = np.zeros(C.shape, np.complex64) + for n in range(maxiter): + I = np.less(abs(Z), horizon) + N[I] = n + Z[I] = Z[I]**2 + C[I] + N[N == maxiter-1] = 0 + return Z, N + + +def mandelbrot_set(xmin, xmax, ymin, ymax, xn, yn, maxiter, horizon=2.0): + X = np.linspace(xmin, xmax, xn, dtype=np.float32) + Y = np.linspace(ymin, ymax, yn, dtype=np.float32) + C = X + Y[:, None]*1j + return mandelbrot(C, maxiter, horizon) + + +if __name__ == '__main__': + from matplotlib import colors + import matplotlib.pyplot as plt + + xmin, xmax, xn = -2.25, +0.75, 3000/2 + ymin, ymax, yn = -1.25, +1.25, 2500/2 + maxiter = 200 + horizon = 2.0 ** 40 + log_horizon = np.log(np.log(horizon))/np.log(2) + Z, N = mandelbrot_set(xmin, xmax, ymin, ymax, xn, yn, maxiter, horizon) + + # Normalized recount as explained in: + # http://linas.org/art-gallery/escape/smooth.html + # https://www.ibm.com/developerworks/community/blogs/jfp/entry/My_Christmas_Gift + + # This line will generate warnings for null values but it is faster to + # process them afterwards using the nan_to_num + M = np.nan_to_num(N + 1 - np.log(np.log(abs(Z)))/np.log(2) + log_horizon) + + dpi = 72 + width = 10 + height = 10*yn/xn + fig = plt.figure(figsize=(width, height), dpi=dpi) + ax = fig.add_axes([0.0, 0.0, 1.0, 1.0], frameon=False, aspect=1) + + # Shaded rendering + light = colors.LightSource(azdeg=315, altdeg=10) + M = light.shade(M, cmap=plt.cm.hot, vert_exag=1.5, + norm=colors.PowerNorm(0.3), blend_mode='hsv') + plt.imshow(M, extent=[xmin, xmax, ymin, ymax], interpolation="bicubic") + ax.set_xticks([]) + ax.set_yticks([]) + + # Some advertisement for matplotlib + ax.text(xmin+0.025, ymin+0.025, + "The Mandelbrot fractal set\n" + "Rendered with matplotlib 2.0, 2016 — http://www.matplotlib.org", + color="white", fontsize=12, alpha=0.5, + family="Source Sans Pro Light") + + # plt.savefig("mandelbrot.png") + plt.show() From 7fe373966c09be5a241eab4d4db26c2bf75cdda9 Mon Sep 17 00:00:00 2001 From: "Nicolas P. Rougier" Date: Sat, 12 Nov 2016 19:02:41 +0100 Subject: [PATCH 2/8] Removed font family specification --- examples/showcase/mandelbrot.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/examples/showcase/mandelbrot.py b/examples/showcase/mandelbrot.py index 65600482e1d0..ed31621d2877 100644 --- a/examples/showcase/mandelbrot.py +++ b/examples/showcase/mandelbrot.py @@ -58,8 +58,7 @@ def mandelbrot_set(xmin, xmax, ymin, ymax, xn, yn, maxiter, horizon=2.0): ax.text(xmin+0.025, ymin+0.025, "The Mandelbrot fractal set\n" "Rendered with matplotlib 2.0, 2016 — http://www.matplotlib.org", - color="white", fontsize=12, alpha=0.5, - family="Source Sans Pro Light") + color="white", fontsize=12, alpha=0.5) # plt.savefig("mandelbrot.png") plt.show() From 7c0d92afb4c6b0d040878ee8631a8106842df8d4 Mon Sep 17 00:00:00 2001 From: "Nicolas P. Rougier" Date: Sat, 12 Nov 2016 22:28:23 +0100 Subject: [PATCH 3/8] Dynamic version and year in displayed text + code simplification --- examples/showcase/mandelbrot.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/examples/showcase/mandelbrot.py b/examples/showcase/mandelbrot.py index ed31621d2877..5680ea202190 100644 --- a/examples/showcase/mandelbrot.py +++ b/examples/showcase/mandelbrot.py @@ -3,7 +3,10 @@ import numpy as np -def mandelbrot(C, maxiter, horizon=4.0): +def mandelbrot_set(xmin, xmax, ymin, ymax, xn, yn, maxiter, horizon=2.0): + X = np.linspace(xmin, xmax, xn, dtype=np.float32) + Y = np.linspace(ymin, ymax, yn, dtype=np.float32) + C = X + Y[:, None]*1j N = np.zeros(C.shape, dtype=int) Z = np.zeros(C.shape, np.complex64) for n in range(maxiter): @@ -14,14 +17,9 @@ def mandelbrot(C, maxiter, horizon=4.0): return Z, N -def mandelbrot_set(xmin, xmax, ymin, ymax, xn, yn, maxiter, horizon=2.0): - X = np.linspace(xmin, xmax, xn, dtype=np.float32) - Y = np.linspace(ymin, ymax, yn, dtype=np.float32) - C = X + Y[:, None]*1j - return mandelbrot(C, maxiter, horizon) - - if __name__ == '__main__': + import time + import matplotlib from matplotlib import colors import matplotlib.pyplot as plt @@ -55,10 +53,12 @@ def mandelbrot_set(xmin, xmax, ymin, ymax, xn, yn, maxiter, horizon=2.0): ax.set_yticks([]) # Some advertisement for matplotlib - ax.text(xmin+0.025, ymin+0.025, - "The Mandelbrot fractal set\n" - "Rendered with matplotlib 2.0, 2016 — http://www.matplotlib.org", - color="white", fontsize=12, alpha=0.5) + year = time.strftime("%Y") + major, minor, micro = matplotlib.__version__.split('.') + text = ("The Mandelbrot fractal set\n" + "Rendered with matplotlib %s.%s, %s — http://matplotlib.org" + % (major, minor, year)) + ax.text(xmin+.025, ymin+.025, text, color="white", fontsize=12, alpha=0.5) # plt.savefig("mandelbrot.png") plt.show() From 9542a8eace5b4fe76b4d84ecbb9d9c7b0775e66c Mon Sep 17 00:00:00 2001 From: "Nicolas P. Rougier" Date: Sun, 13 Nov 2016 06:39:22 +0100 Subject: [PATCH 4/8] Added docstring --- examples/showcase/mandelbrot.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/examples/showcase/mandelbrot.py b/examples/showcase/mandelbrot.py index 5680ea202190..25e233ca475c 100644 --- a/examples/showcase/mandelbrot.py +++ b/examples/showcase/mandelbrot.py @@ -1,5 +1,15 @@ -# The mandelbrot set rendered with shading and renormalized count -# for better rendering +""" +=================================== +Shaded & power normalized rendering +=================================== + +The Mandelbrot set rendering can be improved by using a normalized recount +associated with a power normalized colormap (gamma=0.3). Rendering can be +further enhanced thanks to shading. + +The `maxiter` gives the precision of the computation. `maxiter=200` should take +a few seconds on most modern laptops. +""" import numpy as np From 68247ea4480116d69b871c07f8ad6b81e679f79e Mon Sep 17 00:00:00 2001 From: "Nicolas P. Rougier" Date: Sun, 13 Nov 2016 07:08:45 +0100 Subject: [PATCH 5/8] Added info about computation time --- examples/showcase/mandelbrot.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/showcase/mandelbrot.py b/examples/showcase/mandelbrot.py index 25e233ca475c..35992252a708 100644 --- a/examples/showcase/mandelbrot.py +++ b/examples/showcase/mandelbrot.py @@ -7,8 +7,8 @@ associated with a power normalized colormap (gamma=0.3). Rendering can be further enhanced thanks to shading. -The `maxiter` gives the precision of the computation. `maxiter=200` should take -a few seconds on most modern laptops. +The `maxiter` gives the precision of the computation. `maxiter=200` should +take a few seconds on most modern laptops. """ import numpy as np From fc5668fe119c55cf0e7d764918beed751ae80236 Mon Sep 17 00:00:00 2001 From: "Nicolas P. Rougier" Date: Sun, 13 Nov 2016 07:55:50 +0100 Subject: [PATCH 6/8] Small modifications --- examples/showcase/mandelbrot.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/showcase/mandelbrot.py b/examples/showcase/mandelbrot.py index 35992252a708..18a358438e29 100644 --- a/examples/showcase/mandelbrot.py +++ b/examples/showcase/mandelbrot.py @@ -46,7 +46,8 @@ def mandelbrot_set(xmin, xmax, ymin, ymax, xn, yn, maxiter, horizon=2.0): # This line will generate warnings for null values but it is faster to # process them afterwards using the nan_to_num - M = np.nan_to_num(N + 1 - np.log(np.log(abs(Z)))/np.log(2) + log_horizon) + with np.errstate(invalid='ignore'): + M = np.nan_to_num(N + 1 - np.log(np.log(abs(Z)))/np.log(2) + log_horizon) dpi = 72 width = 10 @@ -64,11 +65,10 @@ def mandelbrot_set(xmin, xmax, ymin, ymax, xn, yn, maxiter, horizon=2.0): # Some advertisement for matplotlib year = time.strftime("%Y") - major, minor, micro = matplotlib.__version__.split('.') + major, minor, micro = matplotlib.__version__.split('.', maxsplit=3) text = ("The Mandelbrot fractal set\n" "Rendered with matplotlib %s.%s, %s — http://matplotlib.org" % (major, minor, year)) ax.text(xmin+.025, ymin+.025, text, color="white", fontsize=12, alpha=0.5) - # plt.savefig("mandelbrot.png") plt.show() From 30c894d2f8028709b40c876554adbb3c761bc49f Mon Sep 17 00:00:00 2001 From: "Nicolas P. Rougier" Date: Sun, 13 Nov 2016 07:56:47 +0100 Subject: [PATCH 7/8] Small typo --- examples/showcase/mandelbrot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/showcase/mandelbrot.py b/examples/showcase/mandelbrot.py index 18a358438e29..836c0ce345f0 100644 --- a/examples/showcase/mandelbrot.py +++ b/examples/showcase/mandelbrot.py @@ -41,7 +41,7 @@ def mandelbrot_set(xmin, xmax, ymin, ymax, xn, yn, maxiter, horizon=2.0): Z, N = mandelbrot_set(xmin, xmax, ymin, ymax, xn, yn, maxiter, horizon) # Normalized recount as explained in: - # http://linas.org/art-gallery/escape/smooth.html + # https://linas.org/art-gallery/escape/smooth.html # https://www.ibm.com/developerworks/community/blogs/jfp/entry/My_Christmas_Gift # This line will generate warnings for null values but it is faster to From 78fc1fa2aae4e95e8f72928517da3d666299a04d Mon Sep 17 00:00:00 2001 From: "Nicolas P. Rougier" Date: Tue, 15 Nov 2016 17:39:44 +0100 Subject: [PATCH 8/8] Fix maxsplit=2 --- examples/showcase/mandelbrot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/showcase/mandelbrot.py b/examples/showcase/mandelbrot.py index 836c0ce345f0..4df9881a9537 100644 --- a/examples/showcase/mandelbrot.py +++ b/examples/showcase/mandelbrot.py @@ -65,7 +65,7 @@ def mandelbrot_set(xmin, xmax, ymin, ymax, xn, yn, maxiter, horizon=2.0): # Some advertisement for matplotlib year = time.strftime("%Y") - major, minor, micro = matplotlib.__version__.split('.', maxsplit=3) + major, minor, micro = matplotlib.__version__.split('.', maxsplit=2) text = ("The Mandelbrot fractal set\n" "Rendered with matplotlib %s.%s, %s — http://matplotlib.org" % (major, minor, year))