| 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 | #
|
|---|
| 8 | def 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 |
|
|---|
| 19 | def 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.
|
|---|
| 29 | def 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 |
|
|---|
| 47 | def path_coordinate_frames(pt):
|
|---|
| 48 |
|
|---|
| 49 | from VolumePath import tube
|
|---|
| 50 | f = tube.extrusion_transforms(pt)
|
|---|
| 51 | return f
|
|---|
| 52 |
|
|---|
| 53 | def 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 |
|
|---|
| 70 | if '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)
|
|---|
| 78 | else:
|
|---|
| 79 | from chimera import replyobj
|
|---|
| 80 | replyobj.status('Need 3 arguments: runscript filament.py <path> <spacing> <molecule>')
|
|---|