| 1 | #
|
|---|
| 2 | # Make a geometric model of a microtubule in Chimera 1.8
|
|---|
| 3 | #
|
|---|
| 4 | def microtubule_model(path, # points used for cubic spline
|
|---|
| 5 | radius = 90.0, # microtubule center to tubulin center (Angstroms)
|
|---|
| 6 | monomer_spacing = 40.0, # distance along protofilament (Angstroms)
|
|---|
| 7 | number_of_protofilaments = 13,
|
|---|
| 8 | rise_per_turn = -3, # number of monomers (negative for left hand helix)
|
|---|
| 9 | colors = ((.7,.7,.6,1),(.4,.4,.5,1))):
|
|---|
| 10 |
|
|---|
| 11 | spt = smooth_path(path, monomer_spacing) # points and tangents
|
|---|
| 12 | pt = equispaced_points(spt, monomer_spacing)
|
|---|
| 13 | f = path_coordinate_frames(pt)
|
|---|
| 14 | pl = helix_subunit_placements(f, radius, monomer_spacing, number_of_protofilaments, rise_per_turn)
|
|---|
| 15 | r = 0.5*monomer_spacing
|
|---|
| 16 | col = [colors[0]]*number_of_protofilaments + [colors[1]]*number_of_protofilaments
|
|---|
| 17 | s = place_spheres(pl, r, col)
|
|---|
| 18 | s.name = 'microtubule'
|
|---|
| 19 | return s
|
|---|
| 20 |
|
|---|
| 21 | def smooth_path(path, spacing):
|
|---|
| 22 |
|
|---|
| 23 | from Matrix import distance
|
|---|
| 24 | seg_lengths = [distance(path[i],path[i+1]) for i in range(len(path)-1)]
|
|---|
| 25 | subdiv = max(0, int(max(seg_lengths) / spacing) - 1)
|
|---|
| 26 | from VolumePath import spline
|
|---|
| 27 | pt = spline.natural_cubic_spline(path, subdiv, return_tangents = True)
|
|---|
| 28 | return pt
|
|---|
| 29 |
|
|---|
| 30 | # Modified code from VolumeFilter/unbend.py to also intepolate tangents.
|
|---|
| 31 | def equispaced_points(points_and_tangents, spacing):
|
|---|
| 32 |
|
|---|
| 33 | pt = points_and_tangents
|
|---|
| 34 | ept = [pt[0]]
|
|---|
| 35 | from VolumePath import spline
|
|---|
| 36 | arcs = spline.arc_lengths([p for p,t in pt])
|
|---|
| 37 | d = spacing
|
|---|
| 38 | from Matrix import linear_combination, normalize_vector
|
|---|
| 39 | for i, a in enumerate(arcs):
|
|---|
| 40 | while a > d:
|
|---|
| 41 | f = (d - arcs[i-1]) / (arcs[i] - arcs[i-1])
|
|---|
| 42 | (p0,t0),(p1,t1) = pt[i-1],pt[i]
|
|---|
| 43 | p = linear_combination((1-f), p0, f, p1)
|
|---|
| 44 | t = normalize_vector(linear_combination((1-f), t0, f, t1))
|
|---|
| 45 | ept.append((p,t))
|
|---|
| 46 | d += spacing
|
|---|
| 47 | return ept
|
|---|
| 48 |
|
|---|
| 49 | def path_coordinate_frames(pt):
|
|---|
| 50 |
|
|---|
| 51 | from VolumePath import tube
|
|---|
| 52 | f = tube.extrusion_transforms(pt)
|
|---|
| 53 | return f
|
|---|
| 54 |
|
|---|
| 55 | def helix_subunit_placements(f, radius, subunit_spacing, subunits_per_turn, rise_per_turn):
|
|---|
| 56 |
|
|---|
| 57 | pl = []
|
|---|
| 58 | import Matrix as M
|
|---|
| 59 | for tf in f:
|
|---|
| 60 | for i in range(subunits_per_turn):
|
|---|
| 61 | a = i * (360.0/subunits_per_turn) # degrees
|
|---|
| 62 | dz = subunit_spacing*i*float(rise_per_turn)/subunits_per_turn
|
|---|
| 63 | stf = M.multiply_matrices(tf,
|
|---|
| 64 | M.translation_matrix((0,0,dz)),
|
|---|
| 65 | M.rotation_transform((0,0,1),a),
|
|---|
| 66 | M.translation_matrix((radius,0,0)))
|
|---|
| 67 | pl.append(stf)
|
|---|
| 68 | return pl
|
|---|
| 69 |
|
|---|
| 70 | def place_spheres(pl, radius, colors = [(.7,.7,.7,1)]):
|
|---|
| 71 |
|
|---|
| 72 | from _surface import SurfaceModel
|
|---|
| 73 | s = SurfaceModel()
|
|---|
| 74 |
|
|---|
| 75 | # Sphere geometry
|
|---|
| 76 | from Icosahedron import icosahedron_triangulation
|
|---|
| 77 | va, ta = icosahedron_triangulation(radius, subdivision_levels = 2, sphere_factor = 1)
|
|---|
| 78 | na = va.copy()
|
|---|
| 79 | import Matrix
|
|---|
| 80 | Matrix.normalize_vectors(na)
|
|---|
| 81 | # va[:,0] *= 0.5 # Flatten
|
|---|
| 82 | va[:,1] *= 1.1
|
|---|
| 83 |
|
|---|
| 84 | for i,tf in enumerate(pl):
|
|---|
| 85 | rgba = colors[i%len(colors)]
|
|---|
| 86 | p = s.addPiece(va, ta, rgba)
|
|---|
| 87 | p.normals = na
|
|---|
| 88 | p.placement = tf
|
|---|
| 89 |
|
|---|
| 90 | return s
|
|---|
| 91 |
|
|---|
| 92 | def test():
|
|---|
| 93 | path = ((0,0,0), (0,0,500), (50,0,1000), (0,50,1500))
|
|---|
| 94 | s = microtubule_model(path)
|
|---|
| 95 | from chimera import openModels
|
|---|
| 96 | openModels.add([s])
|
|---|
| 97 |
|
|---|
| 98 | test()
|
|---|