Scripts: filament.py

File filament.py, 2.6 KB (added by goddard, 12 years ago)
Line 
1#
2# Make a filament by copying a molecule along a path which is a cubic spline through some points.
3#
4# runscript filament.py #1 42.5 #2
5#
6# where #1 is path points and #2 is molecule model positioned as desired at start of path.
7#
8def make_filament(path, # points used for cubic spline, scene coordinates
9 monomer_spacing, # distance along filament (Angstroms)
10 molecule # Make copies starting with this molecule
11 ):
12
13 spt = smooth_path(path, monomer_spacing) # points and tangents
14 pt = equispaced_points(spt, monomer_spacing)
15 f = path_coordinate_frames(pt)
16 mlist = place_molecules(f, molecule)
17 return mlist
18
19def smooth_path(path, spacing):
20
21 from Matrix import distance
22 seg_lengths = [distance(path[i],path[i+1]) for i in range(len(path)-1)]
23 subdiv = max(0, int(max(seg_lengths) / spacing) - 1)
24 from VolumePath import spline
25 pt = spline.natural_cubic_spline(path, subdiv, return_tangents = True)
26 return pt
27
28# Modified code from VolumeFilter/unbend.py to also intepolate tangents.
29def equispaced_points(points_and_tangents, spacing):
30
31 pt = points_and_tangents
32 ept = [pt[0]]
33 from VolumePath import spline
34 arcs = spline.arc_lengths([p for p,t in pt])
35 d = spacing
36 from Matrix import linear_combination, normalize_vector
37 for i, a in enumerate(arcs):
38 while a > d:
39 f = (d - arcs[i-1]) / (arcs[i] - arcs[i-1])
40 (p0,t0),(p1,t1) = pt[i-1],pt[i]
41 p = linear_combination((1-f), p0, f, p1)
42 t = normalize_vector(linear_combination((1-f), t0, f, t1))
43 ept.append((p,t))
44 d += spacing
45 return ept
46
47def path_coordinate_frames(pt):
48
49 from VolumePath import tube
50 f = tube.extrusion_transforms(pt)
51 return f
52
53def place_molecules(f, molecule):
54
55 import Molecule
56 import Matrix as M
57 clist = [Molecule.copy_molecule(molecule) for tf in f[1:]]
58
59 from chimera import openModels
60 openModels.add(clist)
61
62 tf0inv = M.invert_matrix(f[0])
63 for i,tf in enumerate(f[1:]):
64 xf = M.chimera_xform(M.multiply_matrices(tf, tf0inv))
65 xf.multiply(m.openState.xform)
66 clist[i].openState.xform = xf
67
68 return clist
69
70if 'arguments' in globals() and len(arguments) == 3:
71 from chimera.specifier import evalSpec
72 path_atoms = evalSpec(arguments[0]).atoms()
73 path_points = tuple(a.xformCoord() for a in path_atoms)
74 spacing = float(arguments[1])
75 mlist = evalSpec(arguments[2]).molecules()
76 for m in mlist:
77 make_filament(path_points, spacing, m)
78else:
79 from chimera import replyobj
80 replyobj.status('Need 3 arguments: runscript filament.py <path> <spacing> <molecule>')