Escape Time calculation for different fractals

This notebook can be used to calculate the escape time for different fractals. I have used this mainly to get values I can use in unit tests.


In [214]:
import math
import numpy as np
from enum import Enum

In [215]:
# set start values
zstart = np.complex(-2.5,-1.5)
zend = np.complex(1.0, 1.5)

bailout = np.int(100)

image_width = np.int(50)
image_height = np.int(50)

# enum of fractals that are supported
class FractalType(Enum):
    mandelbrot = 1
    julia = 2
    tricorn = 3
    burning_ship = 4

In [216]:
def calc_complex_pos(xpos, ypos):
    print (zstart + np.complex(xpos * ((zend.real - zstart.real) / image_width), ypos * ((zend.imag - zstart.imag) / image_height)))

In [217]:
# basic fractal escape time algorithm. i am using a similar approach like in the c++ code 
# so this is not very pythonic
def fractal_calc (xpos, ypos, frac_type=FractalType.mandelbrot, julia_c=np.complex(0.285, 0.01), print_fractal=False):
    """ 
    Method to calculate escape time for different fractals
    
    Args:
        x (int): Real part as image coordinate
        y (int): Imaginary part as image coordinate
        frac_type (FractalType): The fractal that should be calculated
        julia_c (numpy.Complex): Complex number representing the julia set constant
        print_fractal (bool): Print an ascii art fractal
    """
    #z = np.complex(0.0, 0.0)
    c = zstart + np.complex(xpos * ((zend.real - zstart.real) / image_width),
                            ypos * ((zend.imag - zstart.imag) / image_height))
    z = c
    if (frac_type == FractalType.julia):
        c = julia_c
    print("zO " + str(z))
    # using an extra iterations variable here because this is essentially what we are doing in c++ as well. 
    iterations = 0
    for i in range(bailout):
        if (abs(z) >= 2.0): # check the radius
            break
        if (frac_type == FractalType.tricorn):
            z = np.power(z, -2) + c # this doesn't work, but why?
        elif (frac_type == FractalType.burning_ship):
            z = np.power(np.complex(abs(z.real), abs(z.imag)), 2) + c
        else:
            z = z*z + c
        iterations += 1
    #print(str(iterations) + ", ", end="",flush=True) # this generates a nice list that we can use with c++ 
    print(str(xpos) + "/" + str(ypos) + " Escape time: " + str(iterations) + " - Z " + str(z))
    # print("Z:           " + str(z))
    if (print_fractal):
        # print ascii fractal
        if (iterations == bailout):
            print("*", end="", flush=True)
        else:
            print(".", end="", flush=True)

In [218]:
def continuous_index (its, z):
    print ("Continuous index " + str(its + 1 - (math.log(2) / abs(z)) / math.log(2.0)))

In [219]:
# calculate all complex numbers for the whole range
for y in range(image_height):
    for x in range(image_width):
        #fractal_calc(x, y, FractalType.burning_ship, np.complex(-0.8, 0.156), False)
        pass
    #print("")

# calculate single points
fractal_calc(10, 15, FractalType.burning_ship, np.complex(-0.8, 0.156), False)
# continuous_index(55, np.complex(2.3637850846657784, -2.264372597523388))


zO (-1.7999999999999998-0.6000000000000001j)
10/15 Escape time: 2 - Z (-3.0672+2.7696j)