Three concentric spherical surfaces, with a randomly-connected graph overlaid on each one, spinning.

http://www.youtube.com/watch?v=bXOTCZXkUjk ... born of an idea I wanted to explore. Python + Mayavi = rapid gratification! Thought I'd post the code for anyone who's interested. I'm trialling the use of the Enthought Python Distribution, it certainly provides a nice technology stack to work with. All the components could be installed separately, but I'm very happy to have something where things "just work" (at least, so far).

from enthought.mayavi import mlab

from random import random

from math import sin

from math import cos

import math

radius = 1

azimuth = 0

inclination = 0

x, y = 0, 0

RAD1 = 1

RAD2 = 2

RAD3 = 3

def coord_from_rai((r, a, i)):

x = round(r * sin(i) * cos(a), 4)

y = round(r * sin(i) * sin(a), 4)

z = round(r * cos(i), 4)

return ((x,y,z))

def rai_from_coord((x, y, z)):

rad = math.sqrt((x**2 + y**2 + z**2))

azimuth = math.atan(y/max(x,0.00000000000000001))

inclination = math.acos(z/rad)

return((rad, azimuth, inclination))

def test_point_spherical_conversions():

points = [(1.,0.,0.),

(0., 1., 0.),

(0., 0., 1.),

(1., 1., 1.),

(0.3,0.5,0.9),

(2.6,2.2,2.3),

(2.,3.,4.),

(5.,7.,8.),

]

for point in points:

try:

assert coord_from_rai(rai_from_coord(point)) == point

except:

print "Original Point: ", point

print "Rad, Az, Inc: ", rai_from_coord(point)

print "Converted Coord: ", coord_from_rai(rai_from_coord(point))

raise

def frange(start, stop, inc):

stop = stop * 100

for i in range(start, stop, inc * 100):

return float(i) / 100.

def points_for_line_arc(point1, point2, coords):

rad1, azimuth1, inclination1 = point1

rad2, azimuth2, inclination2 = point2

delta_rad = (rad2 - rad1) / 15.

delta_az = (azimuth2 - azimuth1) / 15.

delta_inc = (inclination2 - inclination1) / 15.

line = []

line.append(point1)

for i in range(1, 15):

(rad, az, inc) = line[-1]

rai = (rad + delta_rad, az + delta_az, inc + delta_inc)

line.append(rai)

if line[-1] != point2:

line.append(point2)

return line

def get_unique_random_point(radius, coords):

azimuth = 2 * math.pi * random()

inclination = 2 * math.pi * random()

return ((radius, azimuth, inclination))

def plot_randomly_connected(radius, count, color=(1., 1., 1.)):

'''

Plot

points on a sphere distance from the origin
Points will be connected by an arc line with 70% probability, with 5

subpoints on the arc line

'''

coords = []

for _ in range(0, count):

coord = get_unique_random_point(radius, coords)

coords.append(coord)

if len(coords) > 1 and random() > .001:

line = coords[-2:]

line = points_for_line_arc(line[0], line[1], coords)

cartesianLine = [coord_from_rai(point) for point in line]

(x, y, z) = zip(*cartesianLine)

mlab.plot3d(x, y, z, opacity=0.05, tube_radius=0.025, color=color)

cartesianPoints = [coord_from_rai(point) for point in coords]

(x, y, z) = zip(*cartesianPoints)

mlab.points3d(x, y, z, color=color, opacity=0.8/radius, scale_factor =1./(2*radius))

plot_randomly_connected(1, 4, color=(.7,.2,.2))

plot_randomly_connected(2, 16, color=(.2,.7,.2))

plot_randomly_connected(3, 32, color=(.2,.2,.7))

#test_point_spherical_conversions()

#mlab.show()

from enthought.mayavi import mlab

@mlab.animate

def anim():

f = mlab.gcf()

while 1:

f.scene.camera.azimuth(4)

f.scene.render()

yield

a = anim() # Starts the animation.

mlab.show()