Home > Graphics, Python, Strange Attractors > Even Stranger Attractors

## Even Stranger Attractors

Today I attempted  to improve on my previous strange attractor script.

One of the drawbacks of the previous script was the high number of false positives. Thousands of images were being saved to my hard drive but only a few of those were truly strange attractors. The rest were loops, spots, or spiral patterns. I solved this problem by only saving images where at least 1% of the pixels have been visited.

The other drawback was the system of simply painting each visited pixel white directly on an image object, allowing for only a vague silhouette of the strange attractor. A better technique is to record how often each pixel has been visited in an array, and then create an image where the colour of each pixel corresponds to how often it has been visited. This results in much more attractive images reminiscent wispy smoke.

Coming along nicely I think, although more work is needed on the coloring. Source code for this version follows. Note that if you would like to try running this Python script you will need to have both Numpy and Python Imaging Library installed. Also please note that this is not yet the most tidy or efficient code… I’ve left plenty of room for improvement!

```import Image
import random
from math import floor
import numpy as np

SIZE = 400

img_index = 0

class Formula(object):
def __init__(self, seed):
self.seed = seed
random.seed(seed)

self.coefficients = [random.choice([random.random()*4-2,
0,
1])for x in range(6)]

self.a, self.b, self.c, self.d, self.e, self.f = tuple(self.coefficients)

def __call__(self, x, y):

# return a*(x**2) + b*x*y + c*(y**2) + d*x + e*y + f
return self.a*(x**2)\
+ self.b*x*y\
+ self.c*(y**2)\
+ self.d*x\
+ self.e*y\
+ self.f

def plotmap(x):
# scales the x or y up to an integer that fits in our image array

catchSize = 1

return int((x+catchSize)*(SIZE/(catchSize*2)))

MAXVAL = 1000

while True:

random.seed()

seed = int(random.random() * 10000000)
f = Formula(seed)

seed = int(random.random() * 10000000)
g = Formula(seed)

x, y = random.random(), random.random()

imgarray = np.zeros([SIZE, SIZE], int)

while imgarray[plotmap(x), plotmap(y)] < MAXVAL:

x, y = f(x, y), g(x, y)
if not(plotmap(x) and plotmap(y)):
#print "break"
break
# catch negative numbers... the "IndexError" won't
# do this resulting in "wrap-around" images

try:
imgarray[plotmap(x), plotmap(y)] += 1

except IndexError:
#print "break!"
break

else:
#print sum(imgarray[imgarray==True].flatten()), SIZE **2
imgarray = np.array(imgarray / (MAXVAL/256.), np.uint8)

if sum(imgarray[imgarray==True].flatten()) > (SIZE **2) * .01:
## only save image if a certain percentage of the total area
## has been coloured.

img = Image.fromarray(imgarray, "L")
img.save("a_%06d_%d_%d.png" % (img_index, f.seed, g.seed), "PNG")
img_index += 1
print "SAVED!"
```