Skip to content

Instantly share code, notes, and snippets.

@tomhartley
Created January 22, 2011 16:38
Show Gist options
  • Save tomhartley/791228 to your computer and use it in GitHub Desktop.
Save tomhartley/791228 to your computer and use it in GitHub Desktop.
Generates and renders the Mandelbrot Set using the matplotlib library
from pylab import *
from math import log
from Tkinter import Tk
from tkFileDialog import *
import csv
H = 500
iterations = 30
ColorList = []
#Majority of processing work completed here.
#Calculates how close a point is to the mandelbrot set
def mandelbrot(real, imag):
#z = complex(-0.726895347709114071439, 0.188887129043845954792)
z = complex(0,0)
c = complex(real, imag)
dropOutLevel = 0
for i in range(0, iterations):
if abs(z) < 2:
z = z**2 + c
dropOutLevel += 1
else:
break
z = z**2 + c
z = z**2 + c
z = z**2 + c
z = z**2 + c
return dropOutLevel,z
#Interpolates (Smooths) between 2 different colours
def interpolateC(color,endColor,left):
if left == 0:
return color
rStart = color[0]
gStart = color[1]
bStart = color[2]
rEnd = endColor[0]
gEnd = endColor[1]
bEnd = endColor[2]
rDiff = rEnd-rStart
gDiff = gEnd-gStart
bDiff = bEnd-bStart
rInc = float(rDiff)/left
gInc = float(gDiff)/left
bInc = float(bDiff)/left
#print (str(left))
return [rStart+rInc,gStart+gInc,bStart+bInc]
#Reads colour stops from a file chosen by the user using the tkinter library
def getPoints():
Tk().withdraw() # we don't want a full GUI, so keep the root window from appearing
filename = askopenfilename() # show an "Open" dialog box and return the path to the selected file
reader = csv.reader(open(filename, "rb"), delimiter=',')
pointsList = []
for row in reader:
colorList = []
for a in row:
colorList.append(float(a)/255)
pointsList.append(colorList)
backwards = pointsList[0:-1]
backwards.reverse()
return pointsList+backwards
#Gets the location to save the file
def getSaveLocation():
Tk().withdraw()
savefile = asksaveasfilename(defaultextension='.png')
return savefile
#Sets up a list of colours for the rendering to use from the points file
def colorList():
cols = []
points = getPoints()
eachLength = H/(len(points)-1)
howmanytogo = eachLength
for a in range(1,len(points)):
cols.append(points[a-1])
for i in range (0,eachLength):
cols.append(interpolateC(cols[-1],points[a],howmanytogo))
howmanytogo += -1
howmanytogo = eachLength
global ColorList
ColorList = cols
#Turns a number from v() into a colour for the renderer to display
def toColor(a):
a=a*85
a = int(a)%H
try:
return ColorList[int(a)]
except IndexError:
print a
print len(ColorList)
return ColorList[0]
#Smooths the numbers from mandelbrot() to create an even gradient
def v(z,n):
try:
x = n + 1 - log2(log2(abs(z)))/log2(2)
return x
except ValueError:
print(str(z))
return 0
#Initialise, get inputs
colorList()
saveFile = getSaveLocation()
wDensity = int(raw_input("What width?"))
hDensity = int(raw_input("What height?"))
x_ords = []
y_ords = []
colors = []
left = float(raw_input("What is the leftmost value? "))
right = float(raw_input("What is the rightmost value? "))
bottom = float(raw_input("What is the bottommost value? "))
top = float(raw_input("What is the topmost value? "))
print "Calculating... "
w = right - left
h = top - bottom
wGap = w/wDensity
hGap = h/hDensity
wPercentageGap = w/100
a = left
perc = 0
print "0%"
#Calculate for each value and add to a list for rendering
while a < right:
b = bottom
while b < top:
x_ords.append(a)
y_ords.append(b)
n, z = mandelbrot(a,b)
if (n == iterations):
col = [0.0,0.0,0.0]
else:
col = toColor(v(z,n))
#print col
colors.append(col)
b += hGap
a += wGap
#Print percentage
curPerc = ((right-a)/w) * 100
if curPerc > perc+10:
perc += 10
print str(perc),"%"
if curPerc > perc+5:
perc += 5
print str(perc),"%"
#render and save the image
print "Rendering... "
autoscale(tight=True)
scatter(x_ords, y_ords, s=1, c=colors, linewidths=0)
F = gcf()
F.set_size_inches(wDensity/80,hDensity/80)
F.savefig(saveFile)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment