-
-
Notifications
You must be signed in to change notification settings - Fork 46.9k
Drawing Julia sets #4382
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Drawing Julia sets #4382
Changes from 15 commits
Commits
Show all changes
24 commits
Select commit
Hold shift + click to select a range
1cdf899
Added Julia sets drawing
alexn11 1b473f2
Merge pull request #1 from alexn11/alexn11-julia-sets
alexn11 f1fe663
Forgot the .py extension
alexn11 45c1351
Update julia_sets.py
alexn11 0490d58
Added doctest example for "show_results"
alexn11 f69ee2a
Filtering Nan's and infinites
alexn11 e9bcc3e
added 1 missing type hint
alexn11 75797b1
in iterate_function, convert to dtype=complex64
alexn11 1ffbd3d
RuntimeWarning (fine) filtering
alexn11 1a1ece8
Type hint, test for ignore_warnings function, typo in header
alexn11 f14bb43
Update julia_sets.py
alexn11 3c85914
Update julia_sets.py
alexn11 36d4dd1
Merge branch 'TheAlgorithms:master' into master
alexn11 4513127
Function def formatting
alexn11 59013f1
Update julia_sets.py
alexn11 2137469
Update fractals/julia_sets.py
alexn11 c3eac86
Update fractals/julia_sets.py
alexn11 75fda09
Update fractals/julia_sets.py
alexn11 f8cb35c
Update fractals/julia_sets.py
alexn11 e149ac5
Update fractals/julia_sets.py
alexn11 8e972e9
Update fractals/julia_sets.py
alexn11 ca7a56b
Update fractals/julia_sets.py
alexn11 f8d0123
added more doctests for eval_exponential
alexn11 1834643
Update fractals/julia_sets.py
alexn11 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,214 @@ | ||
"""Author Alexandre De Zotti | ||
|
||
Draws Julia sets of quadratic polynomials and exponential maps. | ||
More specifically, this iterates the function a fixed number of times | ||
then plots whether the absolute value of the last iterate is greater than | ||
a fixed threshold (named "escape radius"). For the exponential map this is not | ||
really an escape radius but rather a convenient way to approximate the Julia | ||
set with bounded orbits. | ||
|
||
The examples presented here are: | ||
- The Cauliflower Julia set, see e.g. | ||
https://en.wikipedia.org/wiki/File:Julia_z2%2B0,25.png | ||
- Other examples from https://en.wikipedia.org/wiki/Julia_set | ||
- An exponential map Julia set, ambiantly homeomorphic to the examples in | ||
http://www.math.univ-toulouse.fr/~cheritat/GalII/galery.html | ||
and | ||
https://ddd.uab.cat/pub/pubmat/02141493v43n1/02141493v43n1p27.pdf | ||
|
||
Remark: Some overflow runtime warnings are suppressed. This is because of the | ||
way the iteration loop is implemented, using numpy's efficient computations. | ||
Overflows and infinites are replaced after each step by a large number. | ||
""" | ||
|
||
import warnings | ||
from typing import Any, Callable | ||
|
||
import numpy | ||
from matplotlib import pyplot | ||
|
||
c_cauliflower = 0.25 + 0.0j | ||
c_polynomial_1 = -0.4 + 0.6j | ||
c_polynomial_2 = -0.1 + 0.651j | ||
c_exponential = -2.0 | ||
nb_iterations = 56 | ||
window_size = 2.0 | ||
nb_pixels = 666 | ||
|
||
|
||
def eval_exponential(c_parameter: complex, z_values: numpy.ndarray) -> numpy.ndarray: | ||
""" | ||
>>> eval_exponential(0, 0) | ||
1.0 | ||
""" | ||
return numpy.exp(z_values) + c_parameter | ||
|
||
|
||
def eval_quadratic_polynomial( | ||
c_parameter: complex, z_values: numpy.ndarray | ||
) -> numpy.ndarray: | ||
""" | ||
>>> eval_quadratic_polynomial(0, 2) | ||
4 | ||
>>> eval_quadratic_polynomial(-1, 1) | ||
0 | ||
>>> round(eval_quadratic_polynomial(1.j, 0).imag) | ||
1 | ||
>>> round(eval_quadratic_polynomial(1.j, 0).real) | ||
0 | ||
""" | ||
return z_values * z_values + c_parameter | ||
|
||
|
||
def prepare_grid(window_size: float, nb_pixels: int) -> numpy.ndarray: | ||
""" | ||
Create a grid of complex values of size nb_pixels*nb_pixels with real and | ||
imaginary parts ranging from -window_size to window_size (inclusive). | ||
Returns a numpy array. | ||
|
||
>>> prepare_grid(1,3) | ||
array([[-1.-1.j, -1.+0.j, -1.+1.j], | ||
[ 0.-1.j, 0.+0.j, 0.+1.j], | ||
[ 1.-1.j, 1.+0.j, 1.+1.j]]) | ||
""" | ||
x = numpy.linspace(-window_size, window_size, nb_pixels) | ||
x = x.reshape((nb_pixels, 1)) | ||
y = numpy.linspace(-window_size, window_size, nb_pixels) | ||
y = y.reshape((1, nb_pixels)) | ||
return x + 1.0j * y | ||
|
||
|
||
def iterate_function( | ||
eval_function: Callable[[Any, numpy.ndarray], numpy.ndarray], | ||
function_params: Any, | ||
nb_iterations: int, | ||
z_0: numpy.ndarray, | ||
infinity: float = None, | ||
) -> numpy.ndarray: | ||
""" | ||
Iterate the function "eval_function" exactly nb_iterations times. | ||
The first argument of the function is a parameter which is contained in | ||
function_params. The variable z_0 is an array that contains the initial | ||
values to iterate from. | ||
This function returns the final iterates. | ||
|
||
>>> iterate_function(eval_quadratic_polynomial, 0, 3, numpy.array([0,1,2])).shape | ||
(3,) | ||
>>> numpy.round(iterate_function(eval_quadratic_polynomial, | ||
0, | ||
3, | ||
numpy.array([0,1,2]))[0]) | ||
alexn11 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
0j | ||
>>> numpy.round(iterate_function(eval_quadratic_polynomial, | ||
0, | ||
3, | ||
numpy.array([0,1,2]))[1]) | ||
(1+0j) | ||
>>> numpy.round(iterate_function(eval_quadratic_polynomial, | ||
0, | ||
3, | ||
numpy.array([0,1,2]))[2]) | ||
alexn11 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
(256+0j) | ||
""" | ||
|
||
z_n = z_0.astype("complex64") | ||
for i in range(nb_iterations): | ||
z_n = eval_function(function_params, z_n) | ||
if infinity is not None: | ||
numpy.nan_to_num(z_n, copy=False, nan=infinity) | ||
z_n[abs(z_n) == numpy.inf] = infinity | ||
return z_n | ||
|
||
|
||
def show_results( | ||
poyea marked this conversation as resolved.
Show resolved
Hide resolved
|
||
function_label: str, | ||
function_params: Any, | ||
escape_radius: float, | ||
z_final: numpy.ndarray, | ||
) -> None: | ||
""" | ||
Plots of whether the absolute value of z_final is greater than | ||
the value of escape_radius. Adds the function_label and function_params to | ||
the title. | ||
|
||
>>> show_results('80', 0, 1, numpy.array([[0,1,.5],[.4,2,1.1],[.2,1,1.3]])) | ||
""" | ||
|
||
abs_z_final = (abs(z_final)).transpose() | ||
abs_z_final[:, :] = abs_z_final[::-1, :] | ||
pyplot.matshow(abs_z_final < escape_radius) | ||
pyplot.title(f"Julia set of {function_label}\n c={function_params}") | ||
alexn11 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
pyplot.show() | ||
|
||
|
||
def ignore_overflow_warnings() -> None: | ||
""" | ||
Ignore some overflow and invalid value warnings. | ||
|
||
>>> ignore_overflow_warnings() | ||
""" | ||
warnings.filterwarnings( | ||
"ignore", category=RuntimeWarning, message="overflow encountered in multiply" | ||
) | ||
warnings.filterwarnings( | ||
"ignore", | ||
category=RuntimeWarning, | ||
message="invalid value encountered in multiply", | ||
) | ||
warnings.filterwarnings( | ||
"ignore", category=RuntimeWarning, message="overflow encountered in absolute" | ||
) | ||
warnings.filterwarnings( | ||
"ignore", category=RuntimeWarning, message="overflow encountered in exp" | ||
) | ||
|
||
|
||
if __name__ == "__main__": | ||
|
||
z_0 = prepare_grid(window_size, nb_pixels) | ||
|
||
ignore_overflow_warnings() # See file header for explanations | ||
|
||
nb_iterations = 24 | ||
escape_radius = 2 * abs(c_cauliflower) + 1 | ||
z_final = iterate_function( | ||
eval_quadratic_polynomial, | ||
c_cauliflower, | ||
nb_iterations, | ||
z_0, | ||
infinity=1.1 * escape_radius, | ||
) | ||
show_results("z²+c", c_cauliflower, escape_radius, z_final) | ||
alexn11 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
nb_iterations = 64 | ||
escape_radius = 2 * abs(c_polynomial_1) + 1 | ||
z_final = iterate_function( | ||
eval_quadratic_polynomial, | ||
c_polynomial_1, | ||
nb_iterations, | ||
z_0, | ||
infinity=1.1 * escape_radius, | ||
) | ||
show_results("z²+c", c_polynomial_1, escape_radius, z_final) | ||
alexn11 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
nb_iterations = 161 | ||
escape_radius = 2 * abs(c_polynomial_2) + 1 | ||
z_final = iterate_function( | ||
eval_quadratic_polynomial, | ||
c_polynomial_2, | ||
nb_iterations, | ||
z_0, | ||
infinity=1.1 * escape_radius, | ||
) | ||
show_results("z²+c", c_polynomial_2, escape_radius, z_final) | ||
alexn11 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
nb_iterations = 12 | ||
escape_radius = 10000.0 | ||
z_final = iterate_function( | ||
eval_exponential, | ||
c_exponential, | ||
nb_iterations, | ||
z_0 + 2, | ||
infinity=1.0e10, | ||
) | ||
show_results("exp(z)+c", c_exponential, escape_radius, z_final) | ||
alexn11 marked this conversation as resolved.
Show resolved
Hide resolved
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.