HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

Mandelbrot Set Fractal

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
setmandelbrotfractal

Problem

I thought I would give this months community challenge a try. This is my first time using Python.
It does take quite a while to run and it's not very colourful but it works.

from PIL import Image, ImageDraw

img = Image.new("RGB", (2400, 2400), "white")
draw = ImageDraw.Draw(img)

max_count = 200
width = img.size[0]
height = img.size[1]

for row in range(height):
    for col in range(width):
        str_output = ""
        c = complex(
            (col - float(width)/2.0)*5.0/float(width),
            (row - float(height)/2.0)*5.0/float(height)
        )
        iteration = 0
        z = 0
        while abs(z) < 2 and iteration < max_count:
            z = z**2 + c
            iteration += 1
        if abs(z) < 2:
            draw.point((col, row), fill="black")
        else:
            draw.point((col, row), fill=(255 - iteration,255 - iteration,255 - iteration))

img.save('mandelbrot.png')

Solution

Your constants should be in UPPER_SNAKE_CASE

MAX_COUNT = 200
WIDTH = img.size[0]
HEIGHT = img.size[1]


Instead of nested for loops, you can use itertools.product which basically will perform the nested iteration you need:

from itertools import product

for row, col in product(range(height), range(width))


You don't use str_output, you should clean up unused values.

You should have whitespace either side of your mathematical operators and have a space after each comma in a comma separated list of values:

(col - float(width) / 2.0) * 5.0 / float(width),
draw.point((col, row), fill=(255 - iteration, 255 - iteration, 255 - iteration))


You should also keep lines below 79 characters as the Python style guide dictates. You can split lines quite easily when they're in paretheses:

draw.point((col, row), fill=(255 - iteration, 255 - iteration,
                                 255 - iteration))


Also your mileage may vary on whether or not this is more readable but you could use a ternary for your final if condition. Like this:

draw.point((col, row), fill=("black" if abs(z) < 2 else 
                                 (255 - iteration, 255 - iteration,
                                  255 - iteration))


The formatting is definitely more awkward, but I personally like these structures because it makes it clear that the only difference in the two results is that one condition.

Code Snippets

MAX_COUNT = 200
WIDTH = img.size[0]
HEIGHT = img.size[1]
from itertools import product

for row, col in product(range(height), range(width))
(col - float(width) / 2.0) * 5.0 / float(width),
draw.point((col, row), fill=(255 - iteration, 255 - iteration, 255 - iteration))
draw.point((col, row), fill=(255 - iteration, 255 - iteration,
                                 255 - iteration))
draw.point((col, row), fill=("black" if abs(z) < 2 else 
                                 (255 - iteration, 255 - iteration,
                                  255 - iteration))

Context

StackExchange Code Review Q#107316, answer score: 3

Revisions (0)

No revisions yet.