Skip to content

Instantly share code, notes, and snippets.

@Nick3523
Created January 5, 2025 09:41
Show Gist options
  • Save Nick3523/3dee47c35441b5372d6435b272400f95 to your computer and use it in GitHub Desktop.
Save Nick3523/3dee47c35441b5372d6435b272400f95 to your computer and use it in GitHub Desktop.
Random simulation of fractales using pyfracgen
#!/usr/bin/env python
# coding: utf-8
import pyfracgen as pf
import numpy as np
from matplotlib import pyplot as plt
import random
from pathlib import Path
import time
import itertools as itt
from matplotlib import cm
# Function to generate random bounds
def random_bounds():
center_x = random.uniform(0.3602404434376143632361252444495 - 0.00000000000003, 0.3602404434376143632361252444495 + 0.00000000000025)
center_y = random.uniform(-0.6413130610648031748603750151793 - 0.00000000000006, -0.6413130610648031748603750151793 + 0.00000000000013)
zoom = random.uniform(0.005, 2)
width = random.uniform(0.5, 1.5) / zoom
height = random.uniform(0.5, 1.5) / zoom
return (
(center_x - width/2, center_x + width/2),
(center_y - height/2, center_y + height/2)
)
# List of available colormaps
colormaps = [
"viridis", "plasma", "inferno", "magma", "cividis", "Greys", "Purples", "Blues",
"Greens", "Oranges", "Reds", "YlOrBr", "YlOrRd", "OrRd", "PuRd", "RdPu", "BuPu",
"GnBu", "PuBu", "YlGnBu", "PuBuGn", "BuGn", "YlGn", "PiYG", "PRGn", "BrBG",
"PuOr", "RdGy", "RdBu", "RdYlBu", "RdYlGn", "Spectral", "coolwarm", "bwr",
"seismic", "Pastel1", "Pastel2", "Paired", "Accent", "Dark2", "Set1", "Set2",
"Set3", "tab10", "tab20", "tab20b", "tab20c", "flag", "prism", "ocean",
"gist_earth", "terrain", "gist_stern", "gnuplot", "gnuplot2", "CMRmap",
"cubehelix", "brg", "hsv", "gist_rainbow", "rainbow", "jet", "nipy_spectral",
"gist_ncar"
]
def get_colormap():
return plt.get_cmap(random.choice(colormaps))
# In the context of generating the Mandelbrot set, transforming each point refers to iteratively applying a mathematical function to each point in the complex plane to determine whether it belongs to the Mandelbrot set. Here's a step-by-step explanation of why and how this transformation is done:
#
# Step-by-Step Explanation
# Complex Plane Representation:
#
# The Mandelbrot set is defined in the complex plane, where each point represents a complex number ( c = x + yi ) (with ( x ) and ( y ) being real numbers and ( i ) being the imaginary unit).
# Initial Setup:
#
# For each point ( c ) in the complex plane, we start with an initial value ( z_0 = 0 ).
# Iterative Transformation:
#
# We iteratively apply the transformation function ( z_{n+1} = z_n^2 + c ) (or a more general form ( z_{n+1} = f(z_n, c) )) to each point.
# Here, ( z_n ) is the value of the complex number after ( n ) iterations.
# Escape Condition:
#
# After each iteration, we check the magnitude (absolute value) of ( z_n ). If ( |z_n| ) exceeds a certain threshold (commonly 2), the point ( c ) is considered to escape to infinity, and it is not part of the Mandelbrot set.
# If the point does not escape after a predefined number of iterations (e.g., 5000), it is considered to be part of the Mandelbrot set.
# Color Mapping:
#
# Points that escape are colored based on the number of iterations it took for them to escape. This creates the fractal's intricate and colorful boundary.
# Points that do not escape are typically colored black.
# Why Transform Each Point?
# Determine Membership:
#
# The iterative transformation helps determine whether each point ( c ) belongs to the Mandelbrot set or not.
# Fractal Boundary:
#
# The boundary of the Mandelbrot set is where the interesting fractal patterns emerge. The iterative process reveals these patterns by showing how quickly points escape to infinity.
def generate_and_save_images(n):
"""Generate `n` random Mandelbrot images."""
current_time = time.strftime("%Y%m%d_%H%M%S")
for i in range(n):
xbound = (
0.3602404434376143632361252444495 - 0.00000000000003,
0.3602404434376143632361252444495 + 0.00000000000025,
)
ybound = (
-0.6413130610648031748603750151793 - 0.00000000000006,
-0.6413130610648031748603750151793 + 0.00000000000013,
)
xbound, ybound = random_bounds()
res = pf.mandelbrot(
xbound, ybound, pf.funcs.power, width=4, height=4, dpi=300, maxiter=5000
)
filename = f"{current_time}_{i}.png"
stacked = pf.images.get_stacked_cmap(get_colormap(), 50)
pf.images.image(res, cmap=stacked, gamma=0.8)
plt.savefig("mandelbrot/"+filename)
plt.clf() # Clear the current figure to avoid overlapping images
def get_colormap_julia():
"""Get a random colormap for the animation."""
colormaps = [cm.viridis, cm.plasma, cm.inferno, cm.magma, cm.cividis]
return random.choice(colormaps)
def generate_random_julia_animation(n):
"""Generate `n` random Julia animations."""
output_dir = Path("julia")
output_dir.mkdir(exist_ok=True)
for i in range(n):
# Generate random bounds and parameters
xbound = (-random.uniform(0.5, 2), random.uniform(0.5, 2))
ybound = (-random.uniform(0.5, 2), random.uniform(0.5, 2))
maxiter = random.randint(200, 400)
width = 5
height = 4
dpi = 200 # Reduced to avoid excessive memory usage
reals = itt.chain(np.linspace(-1, 2, 60)[0:-1], np.linspace(2, 3, 40))
series = pf.julia(
(complex(real, random.uniform(0.5, 1.5)) for real in reals),
xbound=xbound,
ybound=ybound,
update_func=pf.funcs.magnetic_2,
maxiter=maxiter,
width=width,
height=height,
dpi=dpi,
)
output_file = output_dir / f"julia_animation4_{i + 1}.gif"
pf.images.save_animation(
list(series),
cmap=get_colormap(),
gamma=random.uniform(0.5, 1.0),
file=output_file,
)
print(f"Generated animation {i + 1} at {output_file}")
def get_colormap_lyapunov():
"""Get a random colormap."""
colormaps = [cm.viridis, cm.plasma, cm.inferno, cm.magma, cm.cividis]
return random.choice(colormaps)
def generate_random_lyapunov_images(n):
"""Generate `n` random Lyapunov fractal images."""
output_dir = Path("lyapunov_images")
output_dir.mkdir(exist_ok=True)
for i in range(n):
# Generate random sequence string (A and B of random lengths)
string = "".join(random.choice("AB") for _ in range(random.randint(10, 20)))
# Generate random bounds
xbound = (random.uniform(2.5, 3.0), random.uniform(3.0, 3.5))
ybound = (random.uniform(3.4, 3.6), random.uniform(3.6, 4.0))
# Generate random image parameters
width = 4
height = 5
dpi = 300 # Reduced to avoid excessive memory usage
ninit = random.randint(1000, 2000)
niter = random.randint(1000, 2000)
# Generate the Lyapunov fractal
res = pf.lyapunov(
string, xbound, ybound, width=width, height=height, dpi=dpi, ninit=ninit, niter=niter
)
# Save the image
output_file = output_dir / f"lyapunov_image_{i + 1}.png"
pf.images.markus_lyapunov_image(
res, get_colormap(), get_colormap(), gammas=(random.uniform(5, 10), random.uniform(0.5, 2))
)
plt.savefig(output_file, dpi=dpi)
plt.clf() # Clear the figure for the next image
print(f"Generated Lyapunov image {i + 1} at {output_file}")
def generate_random_buddhabrot_images(n):
"""Generate `n` random Buddhabrot images."""
output_dir = Path("buddhabrot_images")
output_dir.mkdir(exist_ok=True)
for i in range(n):
# Generate random bounds and parameters
xbound = (
-random.uniform(1.5, 2.0),
random.uniform(0.5, 1.0),
)
ybound = (
-random.uniform(1.0, 1.5),
random.uniform(1.0, 1.5),
)
ncvals = random.randint(1_000_000, 10_000_000) # Number of c-values
maxiters = (
random.randint(50, 200),
random.randint(200, 500),
random.randint(500, 1500),
)
width = 4
height = 3
dpi = 300 # Reduced to avoid excessive memory usage
horizon = random.uniform(1.0e5, 1.0e6)
# Generate the Buddhabrot
res = pf.buddhabrot(
xbound,
ybound,
ncvals=ncvals,
update_func=pf.funcs.power,
horizon=horizon,
maxiters=maxiters,
width=width,
height=height,
dpi=dpi,
)
# Save the image
output_file = output_dir / f"buddhabrot_image_{i + 1}.png"
pf.images.nebula_image(tuple(res), gamma=random.uniform(0.3, 0.6)) # Adjust gamma for variation
plt.savefig(output_file, dpi=dpi)
plt.clf() # Clear the figure for the next image
print(f"Generated Buddhabrot image {i + 1} at {output_file}")
#Run :
generate_and_save_images(100)
generate_random_lyapunov_images(100)
generate_random_buddhabrot_images(100)
generate_random_julia_animation(100)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment