| 1 | # Make a spherical harmonic surface.
|
|---|
| 2 |
|
|---|
| 3 | from math import sin, cos, pi, sqrt
|
|---|
| 4 |
|
|---|
| 5 | def spherical_surface(session,
|
|---|
| 6 | radius_function,
|
|---|
| 7 | theta_steps = 100,
|
|---|
| 8 | phi_steps = 50,
|
|---|
| 9 | positive_color = (255,100,100,255), # red, green, blue, alpha, 0-255
|
|---|
| 10 | negative_color = (100,100,255,255)):
|
|---|
| 11 |
|
|---|
| 12 | # Compute vertices and vertex colors
|
|---|
| 13 | vertices = []
|
|---|
| 14 | colors = []
|
|---|
| 15 | for t in range(theta_steps):
|
|---|
| 16 | theta = (t/theta_steps) * 2*pi
|
|---|
| 17 | ct, st = cos(theta), sin(theta)
|
|---|
| 18 | for p in range(phi_steps):
|
|---|
| 19 | phi = (p/(phi_steps-1)) * pi
|
|---|
| 20 | cp, sp = cos(phi), sin(phi)
|
|---|
| 21 | r = radius_function(theta, phi)
|
|---|
| 22 | xyz = (r*sp*ct, r*sp*st, r*cp)
|
|---|
| 23 | vertices.append(xyz)
|
|---|
| 24 | color = positive_color if r >= 0 else negative_color
|
|---|
| 25 | colors.append(color)
|
|---|
| 26 |
|
|---|
| 27 | # Compute triangles, triples of vertex indices
|
|---|
| 28 | triangles = []
|
|---|
| 29 | for t in range(theta_steps):
|
|---|
| 30 | for p in range(phi_steps-1):
|
|---|
| 31 | i = t*phi_steps + p
|
|---|
| 32 | t1 = (t+1)%theta_steps
|
|---|
| 33 | i1 = t1*phi_steps + p
|
|---|
| 34 | triangles.append((i,i+1,i1+1))
|
|---|
| 35 | triangles.append((i,i1+1,i1))
|
|---|
| 36 |
|
|---|
| 37 | # Create numpy arrays
|
|---|
| 38 | from numpy import array, float32, uint8, int32
|
|---|
| 39 | va = array(vertices, float32)
|
|---|
| 40 | ca = array(colors, uint8)
|
|---|
| 41 | ta = array(triangles, int32)
|
|---|
| 42 |
|
|---|
| 43 | # Compute average vertex normal vectors
|
|---|
| 44 | from chimerax.surface import calculate_vertex_normals
|
|---|
| 45 | na = calculate_vertex_normals(va, ta)
|
|---|
| 46 |
|
|---|
| 47 | # Create ChimeraX surface model
|
|---|
| 48 | from chimerax.core.models import Surface
|
|---|
| 49 | s = Surface('surface', session)
|
|---|
| 50 | s.set_geometry(va, na, ta)
|
|---|
| 51 | s.vertex_colors = ca
|
|---|
| 52 | session.models.add([s])
|
|---|
| 53 |
|
|---|
| 54 | return s
|
|---|
| 55 |
|
|---|
| 56 | # Example spherical harmonic function Y(l=2,m=0) real part.
|
|---|
| 57 | def y20_re(theta, phi):
|
|---|
| 58 | return 0.25*sqrt(5/pi) * (3*cos(phi)**2 - 1)
|
|---|
| 59 | def y21_re(theta, phi):
|
|---|
| 60 | return -0.5*sqrt(15/(2*pi)) * sin(phi)*cos(phi) * cos(theta)
|
|---|
| 61 | def y22_re(theta, phi):
|
|---|
| 62 | return 0.25*sqrt(15/(2*pi)) * sin(phi)**2 * cos(2*theta)
|
|---|
| 63 |
|
|---|
| 64 | # Create 3 surfaces
|
|---|
| 65 | spherical_surface(session, y20_re)
|
|---|
| 66 |
|
|---|
| 67 | s1 = spherical_surface(session, y21_re)
|
|---|
| 68 | from chimerax.geometry import translation
|
|---|
| 69 | s1.position = translation((1,0,0))
|
|---|
| 70 |
|
|---|
| 71 | s2 = spherical_surface(session, y22_re)
|
|---|
| 72 | s2.position = translation((2,0,0))
|
|---|