Scripts: removecross.py

File removecross.py, 1.7 KB (added by goddard, 9 years ago)
Line 
1# When one selected pseudobond crosses another in the current camera view
2# remove the longer one.
3
4# Keep every pseudobond that is not crossed by a shorter one
5# as viewed along z axis.
6def crossing_pbonds(pbonds):
7 spbonds = list(pbonds)
8 spbonds.sort(key = lambda b: b.length())
9 pb_cross = []
10 segments = [] # Segments not crossed by shorter one.
11 for pb in spbonds:
12 a1,a2 = pb.atoms
13 xy1 = a1.xformCoord().data()[:2]
14 xy2 = a2.xformCoord().data()[:2]
15 segment = (xy1,xy2)
16 if any_cross(segment, segments):
17 pb_cross.append(pb)
18 else:
19 segments.append(segment)
20 return pb_cross
21
22def any_cross(segment, segments):
23 for seg2 in segments:
24 if crossing(seg2, segment):
25 return True
26 return False
27
28def crossing(segment1, segment2):
29 (p1,p2),(p3,p4) = segment1,segment2
30 if p1 == p3 or p1 == p4 or p2 == p3 or p2 == p4:
31 return False # Endpoints match, no crossing
32 return opposite_sides(p1, p2, segment2) and opposite_sides(p3, p4, segment1)
33
34# Are two points on opposite sides of a line.
35def opposite_sides(p1, p2, segment):
36 x1,y1 = p1
37 x2,y2 = p2
38 (x3,y3),(x4,y4) = segment
39 dx,dy = (x4-x3, y4-y3)
40 nx,ny = (-dy,dx) # Normal vector to segment
41 side1 = nx*(x1-x3) + ny*(y1-y3)
42 side2 = nx*(x2-x3) + ny*(y2-y3)
43 return (side1 < 0 and side2 > 0) or (side1 > 0 and side2 < 0)
44
45
46# Use currently selected pseudobonds
47from chimera import selection
48pbonds = selection.currentPseudobonds()
49
50# Delete longer crossing pseudobonds
51cpbonds = crossing_pbonds(pbonds)
52for pb in cpbonds:
53 pb.pseudoBondGroup.deletePseudoBond(pb)
54
55print ('%d of %d pseudobonds deleted' % (len(cpbonds), len(pbonds)))