Press "Enter" to skip to content

Buddhabrot and anti-Buddhabrot in Python

Last updated on 26/12/2022

A Buddhabrot is the visual representation of the probability density distribution that a point in the Gauss plane belongs to a divergent sequence initiated by a number that does not belong to the Mandelbrot set.

Similarly, an anti-Buddhabrot is the probability density distribution that a complex number does belong to a sequence generated from an element of the Mandelbrot set.

BuddhabrotAnti-Buddhabrot

An example of a Buddhabrot, on top, and of an anti-Buddhabrot, below, both obtained at once using 2000 iterations

The Python code used is reported below.

# Computing, showing and saving raw data for Buddhabrot and anti-BBrot
# Dino Accoto 8/10 Oct 2021
# Credits: my starting point was the code published by prof. Susan Stepney, 
# (retrieved on 8 Oct 2021) available here:
# http://susan-stepney.blogspot.com/2020/05/the-buddhabrot.html
# It needed some minor modifications
#to make it run on my Anaconda/Windows distribution. 
# I added some image and file management functions to enable post-processing.
# With the following settings: Image_Size = 2048, Iterations = 2000, 
# how_many_more = 20, the computation time on a PC with
# Intel Core i7-1065G7 CPU @ 1.30GHz - 1.50GHz, 16 Gb RAM 
# is about 6 hours and 10 min.
# The code has been also tested on an Android smartphone with Pydroid 3.  


import numpy  as np
import matplotlib.pyplot as plt
from datetime import datetime # to create unique file names using timestamp

Image_Size = 2048  # Image Width and heigth (2048)
Iterations = 2000   # at least 500
resolution = 600  # image DPI (at least 300)
# The number of seed points is equal to the number 
# of pixels (i.e. Image_Size**2) times 'how_many_more':
how_many_more = 20 # at least 10

def mandelbrot(c): 
    exp=2 # can play with exponent to get other shapes
    z = c
    sequence = [c]
    for i in range(1, Iterations): 
        z = z ** exp + c 
        sequence += [z]
        if abs(z) > 2: # the sequence escaped: can stop and record for Bud
            return sequence, [] 
    return [], sequence # sequence did not escape: recorded for ABud
    
def updateimage(img, seq):   
    for z in seq:
        x, y = z.real, z.imag
        ix, iy = int((x+2)/4*Image_Size), int((2-y)/4*Image_Size)
        # Increment only if (ix,iy) is inside the image:
        if (ix >= 0) and (ix < Image_Size) and (iy >= 0) and (iy < Image_Size):   
            img[ix,iy] += 1    

def file_name(start_string):
    filename = str(start_string)+'S'+str(Image_Size)+'I'+str(Iterations)+'R'+str(resolution)+'-'+str(datetime.now())
    filename = filename.replace(':','-')
    filename = filename.replace(' ','-')
    filename = filename.replace('.','-')
    return filename

def show_save(theimage,start_str): #show and save image
    plt.axis('off')
    plt.imshow(theimage, cmap='bone') #gist_earth cubehelix ocean plasma
    plt.savefig(file_name(start_str), bbox_inches="tight", dpi=resolution)
    plt.show()

################### Main Program ###########################

# Initialize the two images with 1s, so we can use log later, if needed
buddha = np.ones([Image_Size,Image_Size]) 
abuddha = np.ones([Image_Size,Image_Size])
 
for i in range(Image_Size*Image_Size*how_many_more):
    # Option 1: seeds randomly picked in 
    # the 4x4 rectangle:
    z = complex(np.random.uniform()*4-2, np.random.uniform()*4-2)
    # Option 2: seeds randomly picked in a R=2 circle using polar coords
    # (!but this option picks more seeds from near (0,0)):
    # rho = np.random.uniform()*2
    # theta = np.random.uniform()*2*np.pi
    # z = complex(rho*np.cos(theta), rho*np.sin(theta))
    # Option 3 to be used with Option 1: of all the seeds, just those in the
    # R=2 circle are used. This highlights a circle around Bud/aBud:
    # if (np.abs(z)<2):
    traj, traja = mandelbrot(z) 
    updateimage(buddha,traj)
    updateimage(abuddha,traja)
            
# Now the image has been created. Let's save it as a .npy binary file
# before further processing. This allows to experiment different cmaps 
# and figure enhancing features.
# ==> To load the matrix from file: matr = np.load(file-name.pny)
    
np.save(file_name('B'),buddha)
np.save(file_name('A'),abuddha)

# Now some visual adjustments:
buddha = np.square(np.log(buddha))
abuddha = np.log(abuddha)

# Finally, let's show on screen and save on file as .png:
show_save(buddha,'B-')
show_save(abuddha,'a-')

Be First to Comment

Leave a Reply

Your email address will not be published. Required fields are marked *