-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathtopoangles.tcl
More file actions
205 lines (170 loc) · 6.88 KB
/
topoangles.tcl
File metadata and controls
205 lines (170 loc) · 6.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
#!/usr/bin/tclsh
# This file is part of TopoTools, a VMD package to simplify
# manipulating bonds other topology related properties.
#
# Copyright (c) 2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020 by Axel Kohlmeyer <akohlmey@gmail.com>
# $Id: topoangles.tcl,v 1.13 2020/05/29 19:47:40 johns Exp $
# return info about angles
# we list and count only angles that are entirely within the selection.
proc ::TopoTools::angleinfo {infotype sel {flag none}} {
set numangles 0
array set angletypes {}
set atomindex [$sel list]
set anglelist {}
foreach angle [join [molinfo [$sel molid] get angles]] {
lassign $angle t a b c
if {([lsearch -sorted -integer $atomindex $a] >= 0) \
&& ([lsearch -sorted -integer $atomindex $b] >= 0) \
&& ([lsearch -sorted -integer $atomindex $c] >= 0) } {
set angletypes($t) 1
incr numangles
lappend anglelist $angle
}
}
switch $infotype {
numangles { return $numangles }
numangletypes { return [array size angletypes] }
angletypenames { return [lsort -ascii [array names angletypes]] }
getanglelist { return $anglelist }
default { return "bug! shoot the programmer?"}
}
}
# delete all fully contained angles of the selection.
proc ::TopoTools::clearangles {sel} {
set mol [$sel molid]
set atomindex [$sel list]
set anglelist {}
foreach angle [join [molinfo $mol get angles]] {
lassign $angle t a b c
if {([lsearch -sorted -integer $atomindex $a] < 0) \
|| ([lsearch -sorted -integer $atomindex $b] < 0) \
|| ([lsearch -sorted -integer $atomindex $c] < 0) } {
lappend anglelist $angle
}
}
molinfo $mol set angles [list $anglelist]
}
# reset angles to data in anglelist
proc ::TopoTools::setanglelist {sel anglelist} {
set mol [$sel molid]
set atomindex [$sel list]
set newanglelist {}
# set defaults
set t unknown; set a -1; set b -1; set c -1
# preserve all angles definitions that are not contained in $sel
foreach angle [join [molinfo $mol get angles]] {
lassign $angle t a b c
if {([lsearch -sorted -integer $atomindex $a] < 0) \
|| ([lsearch -sorted -integer $atomindex $b] < 0) \
|| ([lsearch -sorted -integer $atomindex $c] < 0) } {
lappend newanglelist $angle
}
}
# append new ones, but only those fully contained in $sel
foreach angle $anglelist {
lassign $angle t a b c
if {([lsearch -sorted -integer $atomindex $a] >= 0) \
&& ([lsearch -sorted -integer $atomindex $b] >= 0) \
&& ([lsearch -sorted -integer $atomindex $c] >= 0) } {
lappend newanglelist $angle
}
}
molinfo $mol set angles [list $newanglelist]
}
# reset angles to data in anglelist
proc ::TopoTools::retypeangles {sel} {
set mol [$sel molid]
set anglelist [angleinfo getanglelist $sel]
set atomtypes [$sel get type]
set atomindex [$sel list]
set newanglelist {}
foreach angle $anglelist {
lassign $angle type i1 i2 i3
set idx [lsearch -sorted -integer $atomindex $i1]
set a [lindex $atomtypes $idx]
set idx [lsearch -sorted -integer $atomindex $i2]
set b [lindex $atomtypes $idx]
set idx [lsearch -sorted -integer $atomindex $i3]
set c [lindex $atomtypes $idx]
if { [string compare $a $c] > 0 } { set t $a; set a $c; set c $t }
set type [join [list $a $b $c] "-"]
lappend newanglelist [list $type $i1 $i2 $i3]
}
setanglelist $sel $newanglelist
}
# reset angles to definitions derived from bonds.
# this includes retyping of the angles.
proc ::TopoTools::guessangles {sel} {
set mol [$sel molid]
set atomtypes [$sel get type]
set atomindex [$sel list]
set newanglelist {}
set bonddata [$sel getbonds]
# preserve all angles definitions that are not fully contained in $sel
foreach angle [angleinfo getanglelist $sel] {
lassign $angle t a b c
if {([lsearch -sorted -integer $atomindex $a] < 0) \
|| ([lsearch -sorted -integer $atomindex $b] < 0) \
|| ([lsearch -sorted -integer $atomindex $c] < 0) } {
lappend newanglelist $angle
}
}
# a topological angle is defined by two bonds that share an atom
# bound to it that are not the bond itself
foreach bonds $bonddata aidx $atomindex atyp $atomtypes {
set nbnd [llength $bonds]
for {set i 0} {$i < $nbnd-1} {incr i} {
for {set j [expr {$i+1}]} {$j < $nbnd} {incr j} {
set b1idx [lindex $bonds $i]
set idx [lsearch -sorted -integer $atomindex $b1idx]
set b1typ [lindex $atomtypes $idx]
set b2idx [lindex $bonds $j]
set idx [lsearch -sorted -integer $atomindex $b2idx]
set b2typ [lindex $atomtypes $idx]
if { ([string compare $b1typ $b2typ] > 0) } {
set t1 $b1typ; set b1typ $b2typ; set b2typ $t1
set t2 $b1idx; set b1idx $b2idx; set b2idx $t2
}
set type [join [list $b1typ $atyp $b2typ] "-"]
# append only angles that are full contained in $sel
if {([lsearch -sorted -integer $atomindex $b1idx] >= 0) \
&& ([lsearch -sorted -integer $atomindex $aidx] >= 0) \
&& ([lsearch -sorted -integer $atomindex $b2idx] >= 0) } {
lappend newanglelist [list $type $b1idx $aidx $b2idx]
}
}
}
}
molinfo $mol set angles [list $newanglelist]
}
# define a new angle or change an existing one.
proc ::TopoTools::addangle {mol id1 id2 id3 {type unknown}} {
if {[catch {atomselect $mol "index $id1 $id2 $id3"} sel]} {
vmdcon -err "topology addangle: Invalid atom indices: $sel"
return
}
# canonicalize indices
if {$id1 > $id3} {set t $id1 ; set id1 $id3 ; set id3 $t }
set angles [join [molinfo $mol get angles]]
lappend angles [list $type $id1 $id2 $id3]
$sel delete
molinfo $mol set angles [list $angles]
}
# delete an angle.
proc ::TopoTools::delangle {mol id1 id2 id3 {type unknown}} {
if {[catch {atomselect $mol "index $id1 $id2 $id3"} sel]} {
vmdcon -err "topology delangle: Invalid atom indices: $sel"
return
}
# canonicalize indices
if {$id1 > $id3} {set t $id1 ; set id1 $id3 ; set id3 $t }
set newanglelist {}
foreach angle [join [molinfo $mol get angles]] {
lassign $angle t a b c
if { ($a != $id1) || ($b != $id2) || ($c != $id3) } {
lappend newanglelist $angle
}
}
$sel delete
molinfo $mol set angles [list $newanglelist]
}