JuliaSet optimized version

Georgy Mokshantsev

Import libraries


In [35]:
# Math libraries
import numpy as np
import math
from math import sqrt

# Matplotlib plotting libraries
import matplotlib.pyplot as plt
%matplotlib inline

# Bokeh plotting libraries
import bokeh.plotting as blt
blt.output_notebook()


BokehJS successfully loaded.

Create JuliaSet class to generate Julias sets. Using meshgrid instead internal python loop improve performance significantly.


In [43]:
import cmath;
import numpy;
import time;

class JuliaSet(object):
  
    def __init__(self, c, n=100, _d=0.001):
        self.c=c;
        self.set=numpy.array([]);
        self._d=_d;
        if(n>0):
            self.n=n;
        else:
            print "Reset n to 100";
        self._complexplane = numpy.array([]);
        
        
    def juliamap(self, z):
        return self.c+(z**2);
    
    
    def iterate(self, z):
        m=0;
        while(1>0):
            z=self.juliamap(z);
            m+=1;
            if(abs(z)>2):
                return m;
            elif(m>=self.n):
                return 0;
        
    def setcomplexplane(self, d=0, t=-2,t1=2):
        i =-2;
        if(d==self._d and len(self._complexplane)>1):
            return;

        if(d>0):
            self._d=d;
            increment = d;
        else:
            increment = self._d;
    
        arr = numpy.arange(t,t1,increment);
        arr = numpy.append(arr,2);
        q = numpy.ones(len(arr));
        x, y = np.meshgrid(arr,arr)
        j = x+y*1j      
        self._complexplane =j;
            
    def set_spacing(self, d, t=-2, t1=2):
        self.setcomplexplane(d, t,t1);
        
        
    def generate(self):
        f =numpy.vectorize(self.iterate);
        self.set =f(self._complexplane);
        return self.set;

Create plot class inheritant from JuliaSet class to operate with a plot


In [44]:
class JuliaSetPlot(JuliaSet):
    """Extend JuliaSet to add plotting functionality"""
    
    def __init__(self, *args, **kwargs):
        # Invoke constructor for JuliaSet first, unaltered
        super(JuliaSetPlot, self).__init__(*args, **kwargs)
        # Add one more attribute: a rendered image array
        self.img = np.array([])
    
    def get_dim(self):
        # get what should be an attribute
        return int(math.sqrt(self.set.size))
    
    def render(self):
        if not self.set: self.generate()
        # Convert inefficient list to efficient numpy array
        dim = int(math.sqrt(self.set.size))
        self.img = numpy.reshape(self.set,  (dim,dim)).T
   

        
    def show(self):
        if not self.img.size: self.render()
        # Specify complex plane axes efficiently
        xy = np.linspace(-2,2,self.get_dim())
        # Use matplotlib to plot image as an efficient mesh
        plt.figure(1, figsize=(12,9))
  
        plt.pcolormesh(xy,xy,self.img, cmap=plt.cm.hot)
        plt.colorbar()
        plt.show()
        
    def interact(self):
        from matplotlib.colors import rgb2hex
        if not self.img.size: self.render()
        # Mimic matplotlib "hot" color palette
        colormap = plt.cm.get_cmap("hot")
        bokehpalette = [rgb2hex(m) for m in colormap(np.arange(colormap.N))]
        # Use bokeh to plot an interactive image
        f = blt.figure(x_range=[-2,2], y_range=[-2,2], plot_width=600, plot_height=600)
        f.image(image=[self.img], x=[-2,2], y=[-2,2], dw=[4], dh=[4], palette=bokehpalette)
        blt.show(f)

Generate a plot with inisial value -1.037 + 0.17j and space 0.006


In [46]:
j = JuliaSetPlot(-1.037 + 0.17j)
%time j.set_spacing(0.006,-0.5,0.5)
j.interact()


ERROR:/projects/sage/sage-6.9/local/lib/python2.7/site-packages/bokeh/validation/check.pyc:E-1000 (COLUMN_LENGTHS): ColumnDataSource column lengths are not all the same: ColumnDataSource, ViewModel:ColumnDataSource, ref _id: 203d5ea8-a812-448a-9894-4298d9b97657
CPU times: user 4 ms, sys: 4 ms, total: 8 ms
Wall time: 138 ms

In [40]:
j = JuliaSetPlot(-0.624 + 0.435j)
%time j.set_spacing(0.006)
%time j.interact()


ERROR:/projects/sage/sage-6.9/local/lib/python2.7/site-packages/bokeh/validation/check.pyc:E-1000 (COLUMN_LENGTHS): ColumnDataSource column lengths are not all the same: ColumnDataSource, ViewModel:ColumnDataSource, ref _id: 3f47973a-d25c-45f0-9321-417f6f997fa6
CPU times: user 8 ms, sys: 4 ms, total: 12 ms
Wall time: 10.4 ms
CPU times: user 4.05 s, sys: 40 ms, total: 4.09 s
Wall time: 5.11 s

In [ ]: