hydrogen_bondifier 0.0.2 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/VERSION +1 -1
- data/bin/hydrogen_bondifier.rb +2 -2
- data/spec/pymol_spec.rb +0 -1
- metadata +33 -47
- data/.gitignore +0 -3
- data/History +0 -9
- data/Rakefile +0 -54
- data/lib/hydrogen_bondifier/utils.rb +0 -39
- data/lib/pymol.rb +0 -93
- data/lib/pymol/connections.rb +0 -55
- data/lib/pymol/hydrogen_bonds.rb +0 -157
- data/lib/pymol/orientation.rb +0 -23
- data/lib/pymol/surface.rb +0 -35
- data/reference/all_connections.py +0 -24
- data/reference/campbell_find_hb.py +0 -18
- data/reference/list_hbonds.py +0 -47
- data/reference/test_pymol.rb +0 -125
- data/spec/testfiles/1YQS.pdb +0 -6655
- data/spec/testfiles/1YQS_h_added.pdb +0 -7924
- data/spec/testfiles/2ERK_Hbond.out +0 -302
- data/spec/testfiles/2pERK2_HBOND.out +0 -303
- data/spec/testfiles/2pERK2_Hadded.pdb +0 -5767
- data/spec/testfiles/2pERK2_dis-surf.txt +0 -330
- data/spec/testfiles/little.pdb +0 -210
- data/validation/jtp_vs_insight_angles.png +0 -0
- data/validation/jtp_vs_insight_distances.png +0 -0
- data/validation/jtp_vs_insight_surface_distances.png +0 -0
- data/validation/jtp_vs_insight_surface_distances_aa_geometric.png +0 -0
- data/validation/jtp_vs_insight_surface_distances_center_of_grav.png +0 -0
- data/validation/jtp_vs_insight_surface_distances_closest_atom.png +0 -0
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.0.
|
|
1
|
+
0.0.3
|
data/bin/hydrogen_bondifier.rb
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
# see this on hydrogen bond finding in pymol:
|
|
7
7
|
# http://www.mail-archive.com/pymol-users@lists.sourceforge.net/msg06680.html
|
|
8
8
|
|
|
9
|
+
|
|
9
10
|
require 'yaml'
|
|
10
11
|
require 'narray'
|
|
11
12
|
require 'optparse'
|
|
@@ -60,13 +61,12 @@ if ARGV.size == 0
|
|
|
60
61
|
exit
|
|
61
62
|
end
|
|
62
63
|
|
|
63
|
-
files = ARGV.
|
|
64
|
+
files = ARGV.dup
|
|
64
65
|
ARGV.clear
|
|
65
66
|
|
|
66
67
|
categories = %w(D_id H_id A_id H_name D_res D_res_id D_name A_res A_res_id A_name angle D_A_dist H_A_dist H_dist_to_surf)
|
|
67
68
|
|
|
68
69
|
files.each do |file|
|
|
69
|
-
|
|
70
70
|
####################
|
|
71
71
|
# need to implement copying of file, etc......
|
|
72
72
|
####################
|
data/spec/pymol_spec.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: hydrogen_bondifier
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
|
|
4
|
+
prerelease: false
|
|
5
|
+
segments:
|
|
6
|
+
- 0
|
|
7
|
+
- 0
|
|
8
|
+
- 3
|
|
9
|
+
version: 0.0.3
|
|
5
10
|
platform: ruby
|
|
6
11
|
authors:
|
|
7
12
|
- John T. Prince
|
|
@@ -9,19 +14,22 @@ autorequire:
|
|
|
9
14
|
bindir: bin
|
|
10
15
|
cert_chain: []
|
|
11
16
|
|
|
12
|
-
date: 2010-
|
|
17
|
+
date: 2010-11-30 00:00:00 -07:00
|
|
13
18
|
default_executable: hydrogen_bondifier.rb
|
|
14
19
|
dependencies:
|
|
15
20
|
- !ruby/object:Gem::Dependency
|
|
16
21
|
name: spec-more
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
22
|
+
prerelease: false
|
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
|
24
|
+
none: false
|
|
20
25
|
requirements:
|
|
21
26
|
- - ">="
|
|
22
27
|
- !ruby/object:Gem::Version
|
|
28
|
+
segments:
|
|
29
|
+
- 0
|
|
23
30
|
version: "0"
|
|
24
|
-
|
|
31
|
+
type: :development
|
|
32
|
+
version_requirements: *id001
|
|
25
33
|
description: uses pymol
|
|
26
34
|
email: jtprince@gmail.com
|
|
27
35
|
executables:
|
|
@@ -32,46 +40,20 @@ extra_rdoc_files:
|
|
|
32
40
|
- LICENSE
|
|
33
41
|
- README.rdoc
|
|
34
42
|
files:
|
|
35
|
-
-
|
|
36
|
-
- History
|
|
43
|
+
- VERSION
|
|
37
44
|
- LICENSE
|
|
38
45
|
- README.rdoc
|
|
39
|
-
- Rakefile
|
|
40
|
-
- VERSION
|
|
41
|
-
- bin/hydrogen_bondifier.rb
|
|
42
|
-
- lib/hydrogen_bondifier/utils.rb
|
|
43
|
-
- lib/pymol.rb
|
|
44
|
-
- lib/pymol/connections.rb
|
|
45
|
-
- lib/pymol/hydrogen_bonds.rb
|
|
46
|
-
- lib/pymol/orientation.rb
|
|
47
|
-
- lib/pymol/surface.rb
|
|
48
|
-
- reference/all_connections.py
|
|
49
|
-
- reference/campbell_find_hb.py
|
|
50
|
-
- reference/list_hbonds.py
|
|
51
|
-
- reference/test_pymol.rb
|
|
52
|
-
- spec/pymol/connections_spec.rb
|
|
53
|
-
- spec/pymol/hydrogen_bonds_spec.rb
|
|
54
|
-
- spec/pymol/surface_spec.rb
|
|
55
|
-
- spec/pymol_spec.rb
|
|
56
|
-
- spec/scripts/confirm_angle_and_h_dist.rb
|
|
57
|
-
- spec/scripts/confirm_distances.rb
|
|
58
46
|
- spec/scripts/mins.rb
|
|
47
|
+
- spec/scripts/confirm_distances.rb
|
|
48
|
+
- spec/scripts/confirm_angle_and_h_dist.rb
|
|
59
49
|
- spec/scripts/obj_ranges.rb
|
|
60
50
|
- spec/scripts/pdb_ranges.rb
|
|
51
|
+
- spec/pymol_spec.rb
|
|
52
|
+
- spec/pymol/hydrogen_bonds_spec.rb
|
|
53
|
+
- spec/pymol/connections_spec.rb
|
|
54
|
+
- spec/pymol/surface_spec.rb
|
|
61
55
|
- spec/spec_helper.rb
|
|
62
|
-
-
|
|
63
|
-
- spec/testfiles/1YQS_h_added.pdb
|
|
64
|
-
- spec/testfiles/2ERK_Hbond.out
|
|
65
|
-
- spec/testfiles/2pERK2_HBOND.out
|
|
66
|
-
- spec/testfiles/2pERK2_Hadded.pdb
|
|
67
|
-
- spec/testfiles/2pERK2_dis-surf.txt
|
|
68
|
-
- spec/testfiles/little.pdb
|
|
69
|
-
- validation/jtp_vs_insight_angles.png
|
|
70
|
-
- validation/jtp_vs_insight_distances.png
|
|
71
|
-
- validation/jtp_vs_insight_surface_distances.png
|
|
72
|
-
- validation/jtp_vs_insight_surface_distances_aa_geometric.png
|
|
73
|
-
- validation/jtp_vs_insight_surface_distances_center_of_grav.png
|
|
74
|
-
- validation/jtp_vs_insight_surface_distances_closest_atom.png
|
|
56
|
+
- bin/hydrogen_bondifier.rb
|
|
75
57
|
has_rdoc: true
|
|
76
58
|
homepage: http://jtprince.github.com/hydrogen_bondifier
|
|
77
59
|
licenses: []
|
|
@@ -82,32 +64,36 @@ rdoc_options:
|
|
|
82
64
|
require_paths:
|
|
83
65
|
- lib
|
|
84
66
|
required_ruby_version: !ruby/object:Gem::Requirement
|
|
67
|
+
none: false
|
|
85
68
|
requirements:
|
|
86
69
|
- - ">="
|
|
87
70
|
- !ruby/object:Gem::Version
|
|
71
|
+
segments:
|
|
72
|
+
- 0
|
|
88
73
|
version: "0"
|
|
89
|
-
version:
|
|
90
74
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
75
|
+
none: false
|
|
91
76
|
requirements:
|
|
92
77
|
- - ">="
|
|
93
78
|
- !ruby/object:Gem::Version
|
|
79
|
+
segments:
|
|
80
|
+
- 0
|
|
94
81
|
version: "0"
|
|
95
|
-
version:
|
|
96
82
|
requirements: []
|
|
97
83
|
|
|
98
84
|
rubyforge_project:
|
|
99
|
-
rubygems_version: 1.3.
|
|
85
|
+
rubygems_version: 1.3.7
|
|
100
86
|
signing_key:
|
|
101
87
|
specification_version: 3
|
|
102
88
|
summary: finds hydrogen bonds using pymol
|
|
103
89
|
test_files:
|
|
104
|
-
- spec/scripts/obj_ranges.rb
|
|
105
|
-
- spec/scripts/pdb_ranges.rb
|
|
106
90
|
- spec/scripts/mins.rb
|
|
107
|
-
- spec/scripts/confirm_angle_and_h_dist.rb
|
|
108
91
|
- spec/scripts/confirm_distances.rb
|
|
92
|
+
- spec/scripts/confirm_angle_and_h_dist.rb
|
|
93
|
+
- spec/scripts/obj_ranges.rb
|
|
94
|
+
- spec/scripts/pdb_ranges.rb
|
|
109
95
|
- spec/pymol_spec.rb
|
|
110
|
-
- spec/spec_helper.rb
|
|
111
96
|
- spec/pymol/hydrogen_bonds_spec.rb
|
|
112
97
|
- spec/pymol/connections_spec.rb
|
|
113
98
|
- spec/pymol/surface_spec.rb
|
|
99
|
+
- spec/spec_helper.rb
|
data/.gitignore
DELETED
data/History
DELETED
data/Rakefile
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
require 'rubygems'
|
|
3
|
-
require 'rake'
|
|
4
|
-
require 'jeweler'
|
|
5
|
-
require 'rake/testtask'
|
|
6
|
-
# require 'rcov/rcovtask'
|
|
7
|
-
|
|
8
|
-
NAME = "hydrogen_bondifier"
|
|
9
|
-
WEBSITE_BASE = "website"
|
|
10
|
-
WEBSITE_OUTPUT = WEBSITE_BASE + "/output"
|
|
11
|
-
|
|
12
|
-
gemspec = Gem::Specification.new do |s|
|
|
13
|
-
s.name = NAME
|
|
14
|
-
s.authors = ["John T. Prince"]
|
|
15
|
-
s.email = "jtprince@gmail.com"
|
|
16
|
-
s.homepage = "http://jtprince.github.com/" + NAME
|
|
17
|
-
s.summary = "finds hydrogen bonds using pymol"
|
|
18
|
-
s.description = "uses pymol"
|
|
19
|
-
#s.rubyforge_project = 'mspire'
|
|
20
|
-
# s.add_dependency("ms-core", ">= 0.0.2")
|
|
21
|
-
# s.add_development_dependency("ms-testdata", ">= 0.18.0")
|
|
22
|
-
s.add_development_dependency("spec-more")
|
|
23
|
-
s.files << "VERSION"
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
Jeweler::Tasks.new(gemspec)
|
|
27
|
-
|
|
28
|
-
Rake::TestTask.new(:spec) do |spec|
|
|
29
|
-
spec.libs << 'lib' << 'spec'
|
|
30
|
-
spec.pattern = 'spec/**/*_spec.rb'
|
|
31
|
-
spec.verbose = true
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
#Rcov::RcovTask.new do |spec|
|
|
35
|
-
# spec.libs << 'spec'
|
|
36
|
-
# spec.pattern = 'spec/**/*_spec.rb'
|
|
37
|
-
# spec.verbose = true
|
|
38
|
-
#end
|
|
39
|
-
|
|
40
|
-
require 'rake/rdoctask'
|
|
41
|
-
Rake::RDocTask.new do |rdoc|
|
|
42
|
-
base_rdoc_output_dir = WEBSITE_OUTPUT + '/rdoc'
|
|
43
|
-
version = File.read('VERSION')
|
|
44
|
-
rdoc.rdoc_dir = base_rdoc_output_dir + "/#{version}"
|
|
45
|
-
rdoc.title = NAME + ' ' + version
|
|
46
|
-
rdoc.rdoc_files.include('README*')
|
|
47
|
-
rdoc.rdoc_files.include('lib/**/*.rb')
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
task :default => :spec
|
|
51
|
-
|
|
52
|
-
task :build => :gemspec
|
|
53
|
-
|
|
54
|
-
# credit: Rakefile modeled after Jeweler's
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
require 'narray'
|
|
2
|
-
|
|
3
|
-
module Bio
|
|
4
|
-
class PDB
|
|
5
|
-
module Utils
|
|
6
|
-
|
|
7
|
-
module_function
|
|
8
|
-
# calculates the angle between 2 Narray vecs (in radians)
|
|
9
|
-
def angle_between_vectors(vec1, vec2)
|
|
10
|
-
vec1 = NArray.to_na(vec1.to_a) unless vec1.is_a?(NArray)
|
|
11
|
-
vec2 = NArray.to_na(vec2.to_a) unless vec2.is_a?(NArray)
|
|
12
|
-
nil_vec = NArray[0.0, 0.0, 0.0]
|
|
13
|
-
return nil if (vec1 == nil_vec or vec2 == nil_vec)
|
|
14
|
-
(mag_a, mag_b) = [vec1,vec2].map {|vec| Math::sqrt((vec*vec).sum) }
|
|
15
|
-
# acos(dotprod / |a||b|)
|
|
16
|
-
Bio::PDB::Utils.acos( (vec1 * vec2).sum.to_f / (mag_a * mag_b) )
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def angle_from_coords(triplet)
|
|
20
|
-
a = triplet.last - triplet[1]
|
|
21
|
-
b = triplet.first - triplet[1]
|
|
22
|
-
angle_between_vectors(a,b)
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
# other is 3 parallel NArray objects with the x, y and z coordinates
|
|
26
|
-
# or a triplet like coord
|
|
27
|
-
def distance_to_many(coord, other)
|
|
28
|
-
# distance may be another narray or an array of vecs
|
|
29
|
-
sq_diffs = []
|
|
30
|
-
(0...(coord.size)).each do |i|
|
|
31
|
-
pos = coord[i]
|
|
32
|
-
oth = other[i]
|
|
33
|
-
sq_diffs << (oth - pos)**2
|
|
34
|
-
end
|
|
35
|
-
NMath.sqrt(sq_diffs.inject {|sum, vec| sum + vec })
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
end
|
|
39
|
-
end
|
data/lib/pymol.rb
DELETED
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
require 'tempfile'
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
class Pymol
|
|
5
|
-
|
|
6
|
-
TMP_PYTHON_SCRIPT_FILENAME = "python_script_for_pymol"
|
|
7
|
-
TMP_PYMOL_SCRIPT_FILENAME = "pymol_script"
|
|
8
|
-
TMP_PYMOL_REPLY_FILENAME = "pymol_reply"
|
|
9
|
-
|
|
10
|
-
PYMOL_SCRIPT_POSTFIX = '.pml' # <- very freaking important
|
|
11
|
-
PYTHON_SCRIPT_POSTFIX = '.py' # <- very freaking important
|
|
12
|
-
|
|
13
|
-
attr_accessor :cmds
|
|
14
|
-
|
|
15
|
-
def self.run(opt={}, &block)
|
|
16
|
-
self.new.run(opt, &block)
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def initialize
|
|
20
|
-
@cmds = []
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def cmd(string)
|
|
24
|
-
@cmds << string
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
def tmp_file(base, postfix)
|
|
28
|
-
[base, $$, Time.now.to_f].join('-') << postfix
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
# you can add your path to pymol to this array if you need to
|
|
32
|
-
# or with a commandline flag
|
|
33
|
-
PYMOL_EXE_TO_TRY = ['PyMOL.exe', 'pymol']
|
|
34
|
-
|
|
35
|
-
####################################################
|
|
36
|
-
# determine if we have pymol and how to execute it
|
|
37
|
-
####################################################
|
|
38
|
-
PYMOL_EXE_TO_TRY.unshift(ENV['PYMOL_EXE']) if ENV['PYMOL_EXE']
|
|
39
|
-
to_use = false
|
|
40
|
-
PYMOL_EXE_TO_TRY.each do |name|
|
|
41
|
-
begin
|
|
42
|
-
_cmd = "#{name} -cq"
|
|
43
|
-
if system(_cmd)
|
|
44
|
-
to_use = _cmd
|
|
45
|
-
break
|
|
46
|
-
end
|
|
47
|
-
rescue
|
|
48
|
-
end
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
if to_use
|
|
52
|
-
PYMOL_QUIET = to_use
|
|
53
|
-
puts "pymol executable looks good: '#{PYMOL_QUIET}'" if $VERBOSE
|
|
54
|
-
else
|
|
55
|
-
abort "pymol not installed or can't find path, specify with --path-to-pymol" if !to_use
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
def run(opt={}, &block)
|
|
59
|
-
puts( "[working in pymol]: " + opt[:msg] + " ...") if (opt[:msg] && $VERBOSE)
|
|
60
|
-
|
|
61
|
-
block.call(self)
|
|
62
|
-
|
|
63
|
-
cmds_to_run = self.cmds.map
|
|
64
|
-
|
|
65
|
-
tmpfiles = []
|
|
66
|
-
if script = opt[:script]
|
|
67
|
-
script_tmpfn = tmp_file TMP_PYTHON_SCRIPT_FILENAME, PYTHON_SCRIPT_POSTFIX
|
|
68
|
-
File.open(script_tmpfn, 'w') {|out| out.print script }
|
|
69
|
-
tmpfiles << script_tmpfn
|
|
70
|
-
cmds_to_run.unshift( "run #{script_tmpfn}" )
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
to_run = cmds_to_run.map {|v| v + "\n" }.join
|
|
74
|
-
|
|
75
|
-
pymol_tmpfn = tmp_file TMP_PYMOL_SCRIPT_FILENAME, PYMOL_SCRIPT_POSTFIX
|
|
76
|
-
File.open(pymol_tmpfn, 'w') {|out| out.print to_run }
|
|
77
|
-
tmpfiles << pymol_tmpfn
|
|
78
|
-
|
|
79
|
-
# much more suave to open a pipe, but python does not play well with pipes
|
|
80
|
-
# and this is *MUCH* more compatible with windows
|
|
81
|
-
pymol_reply_tmpfn = tmp_file TMP_PYMOL_REPLY_FILENAME, '.pmolreply'
|
|
82
|
-
tmpfiles << pymol_reply_tmpfn
|
|
83
|
-
system_cmd = "#{PYMOL_QUIET} #{pymol_tmpfn} > #{pymol_reply_tmpfn}"
|
|
84
|
-
system system_cmd
|
|
85
|
-
|
|
86
|
-
reply = IO.read(pymol_reply_tmpfn)
|
|
87
|
-
|
|
88
|
-
tmpfiles.each {|tmpf| File.unlink tmpf }
|
|
89
|
-
self.cmds.clear
|
|
90
|
-
reply
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
end
|
data/lib/pymol/connections.rb
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
require 'pymol'
|
|
2
|
-
|
|
3
|
-
class Pymol
|
|
4
|
-
module Connections
|
|
5
|
-
module Script
|
|
6
|
-
module_function
|
|
7
|
-
|
|
8
|
-
def all_connections_script
|
|
9
|
-
%Q{
|
|
10
|
-
from pymol import cmd
|
|
11
|
-
|
|
12
|
-
def all_connections(selection):
|
|
13
|
-
"""
|
|
14
|
-
USAGE
|
|
15
|
-
|
|
16
|
-
all_connections selection
|
|
17
|
-
|
|
18
|
-
returns lines: "CONNECTION: id - id"
|
|
19
|
-
"""
|
|
20
|
-
stored.xs = []
|
|
21
|
-
cmd.iterate(selection, 'stored.xs.append( index )')
|
|
22
|
-
for i in stored.xs:
|
|
23
|
-
selName = "neighbor%s" % i
|
|
24
|
-
ids = cmd.select(selName, ("%s and neighbor id %s" % (selection, i)))
|
|
25
|
-
base = "CONNECTION: %s - " % i
|
|
26
|
-
to_print = base + "%s"
|
|
27
|
-
print_string = 'print "' + to_print + '" % index'
|
|
28
|
-
cmd.iterate(selName, print_string )
|
|
29
|
-
|
|
30
|
-
cmd.extend("all_connections", all_connections)
|
|
31
|
-
}
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
# returns an array of all pairs of atom IDs with no redundancy
|
|
35
|
-
def all_connections_parser(reply_from_all_connections, flag=/^CONNECTION: /)
|
|
36
|
-
pairs = reply_from_all_connections.split("\n").select {|v| v =~ flag }.map do |line|
|
|
37
|
-
line.split(':').last.split(' - ').map {|v| v.to_i }.sort
|
|
38
|
-
end
|
|
39
|
-
pairs.uniq
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
module_function
|
|
45
|
-
|
|
46
|
-
# returns all connections as pairs of ID's (all uniq)
|
|
47
|
-
def from_pdb(pdb)
|
|
48
|
-
reply = Pymol.run(:msg => 'getting all atom connections', :script => Pymol::Connections::Script.all_connections_script) do |pm|
|
|
49
|
-
pm.cmd "load #{pdb}, mymodel"
|
|
50
|
-
pm.cmd "all_connections mymodel"
|
|
51
|
-
end
|
|
52
|
-
Pymol::Connections::Script.all_connections_parser(reply)
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
end
|
data/lib/pymol/hydrogen_bonds.rb
DELETED
|
@@ -1,157 +0,0 @@
|
|
|
1
|
-
require 'pymol'
|
|
2
|
-
require 'pymol/connections'
|
|
3
|
-
|
|
4
|
-
require 'bio/db/pdb'
|
|
5
|
-
require 'hydrogen_bondifier/utils'
|
|
6
|
-
|
|
7
|
-
class Pymol
|
|
8
|
-
EXCLUDE_WATER_FILTER = " &! resn hoh"
|
|
9
|
-
module HydrogenBonds
|
|
10
|
-
|
|
11
|
-
DEFAULT_FIND_PAIRS_OPTS = {:max_dist => 3.2, :max_angle => 60, :exclude_water => true }
|
|
12
|
-
DEFAULT_H_BOND_OPTS = {
|
|
13
|
-
:select_donor => "and (elem n,o and (neighbor hydro))",
|
|
14
|
-
:select_acceptor => "and (elem o or (elem n and not (neighbor hydro)))",
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
module_function
|
|
18
|
-
|
|
19
|
-
def pdb_with_hydrogens(pdb_filename, newname=nil)
|
|
20
|
-
pfile = pdb_filename
|
|
21
|
-
newname = pfile.chomp(File.extname(pfile)) + "_plus_h.pdb" unless newname
|
|
22
|
-
Pymol.run(:msg => 'creating pdb with hydrogens') do |pm|
|
|
23
|
-
pm.cmd "load #{pfile}, mymodel"
|
|
24
|
-
pm.cmd "h_add"
|
|
25
|
-
pm.cmd "save #{newname}"
|
|
26
|
-
end
|
|
27
|
-
newname
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
# returns [id1, id2, distance] for each atom
|
|
31
|
-
def find_pairs(file, sel1, sel2, opt={})
|
|
32
|
-
opt = DEFAULT_FIND_PAIRS_OPTS.merge( opt )
|
|
33
|
-
exclude_water_command = opt[:exclude_water] ? EXCLUDE_WATER_FILTER : ""
|
|
34
|
-
hbond_script = Pymol::HydrogenBonds.list_hb_script(sel1, sel2)
|
|
35
|
-
reply = Pymol.run(:msg => "getting hydrogen bonds", :script => hbond_script) do |pm|
|
|
36
|
-
pm.cmd "load #{file}, mymodel"
|
|
37
|
-
pm.cmd "list_hb mymodel#{exclude_water_command}, cutoff=#{opt[:max_dist]}, angle=#{opt[:max_angle]}"
|
|
38
|
-
end
|
|
39
|
-
Pymol::HydrogenBonds.list_hb_parser(reply)
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
# returns [donor, hydrogen, acceptor, angle, don_to_acc_dist, h_to_acc_dist]
|
|
44
|
-
# The first three are Bio::PDB::Record::ATOM structs.
|
|
45
|
-
# respects DEFAULT_FIND_PAIRS_OPTS and DEFAULT_H_BOND_OPTS
|
|
46
|
-
# expects that hydrogen bonds are already specified in the PDB file
|
|
47
|
-
# returns an array triplet atom IDs [donor, hydrogen, acceptor]
|
|
48
|
-
# :connections can be passed in (an array of arrays of all unique pairwise
|
|
49
|
-
# connections [by ID])
|
|
50
|
-
def from_pdb(file, opt={})
|
|
51
|
-
opt = DEFAULT_H_BOND_OPTS.merge(opt)
|
|
52
|
-
|
|
53
|
-
pairs = find_pairs(file, opt[:select_donor], opt[:select_acceptor], opt)
|
|
54
|
-
|
|
55
|
-
connection_pairs = Pymol::Connections.from_pdb(file)
|
|
56
|
-
connection_index = Hash.new {|h,k| h[k] = [] }
|
|
57
|
-
connection_pairs.each do |pair|
|
|
58
|
-
connection_index[pair.first] << pair.last
|
|
59
|
-
connection_index[pair.last] << pair.first
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
# make an index of the atoms
|
|
63
|
-
pdb = Bio::PDB.new(IO.read(file))
|
|
64
|
-
pdb.extend(Bio::PDB::AtomFinder)
|
|
65
|
-
atom_index = []
|
|
66
|
-
pdb.each_atom do |atom|
|
|
67
|
-
atom_index[atom.serial] = atom
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
max_angle = opt[:max_angle] || DEFAULT_FIND_PAIRS_OPTS[:max_angle]
|
|
71
|
-
cutoff_in_degress = max_angle
|
|
72
|
-
|
|
73
|
-
hbonds = []
|
|
74
|
-
puts "calculating angles and distances" if $VERBOSE
|
|
75
|
-
pairs.each do |don_id, acc_id, don_to_acc_dist|
|
|
76
|
-
donor = atom_index[don_id]
|
|
77
|
-
acceptor = atom_index[acc_id]
|
|
78
|
-
next if (acceptor.element == 'H' or donor.element == 'H') # check for sloppy queries
|
|
79
|
-
acceptor_xyz = acceptor.xyz
|
|
80
|
-
donor_xyz = donor.xyz
|
|
81
|
-
connection_index[don_id].each do |id|
|
|
82
|
-
hydrogen = atom_index[id]
|
|
83
|
-
next if hydrogen.element != 'H'
|
|
84
|
-
|
|
85
|
-
#puts "ACCEPT ID: "
|
|
86
|
-
#puts acc_id
|
|
87
|
-
#p acceptor_xyz
|
|
88
|
-
#puts "HYDRO ID: "
|
|
89
|
-
#p id
|
|
90
|
-
#p hydrogen.xyz
|
|
91
|
-
|
|
92
|
-
angle = Bio::PDB::Utils.angle_from_coords([donor_xyz, hydrogen.xyz, acceptor_xyz])
|
|
93
|
-
h_to_acc_dist = Bio::PDB::Utils.distance(hydrogen.xyz, acceptor_xyz)
|
|
94
|
-
|
|
95
|
-
#puts "DISTANCES: "
|
|
96
|
-
#p don_to_acc_dist
|
|
97
|
-
#p h_to_acc_dist
|
|
98
|
-
# abort 'here'
|
|
99
|
-
|
|
100
|
-
# I'm not sure why the angle cutoff is not being respected, but we
|
|
101
|
-
# can enforce it right here since we want the angles anyway
|
|
102
|
-
if (180.0 - Bio::PDB::Utils.rad2deg(angle)) <= cutoff_in_degress
|
|
103
|
-
hbonds << [donor, hydrogen, acceptor, angle, don_to_acc_dist, h_to_acc_dist]
|
|
104
|
-
end
|
|
105
|
-
end
|
|
106
|
-
end
|
|
107
|
-
hbonds
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
def list_hb_script(select1, select2)
|
|
111
|
-
%Q{
|
|
112
|
-
# modified by JTP from here:
|
|
113
|
-
# Dr. Robert L. Campbell
|
|
114
|
-
# http://pldserver1.biochem.queensu.ca/~rlc/work/pymol/
|
|
115
|
-
# find_pairs is an undocumented method but mode==1 is hydrogen bond finding
|
|
116
|
-
|
|
117
|
-
from pymol import cmd
|
|
118
|
-
|
|
119
|
-
def list_hb(selection,cutoff=3.2,angle=55,hb_list_name='hbonds'):
|
|
120
|
-
"""
|
|
121
|
-
USAGE
|
|
122
|
-
|
|
123
|
-
list_hb selection, [cutoff (default=3.2)], [angle (default=55)], [hb_list_name]
|
|
124
|
-
|
|
125
|
-
e.g.
|
|
126
|
-
list_hb 1abc & c. a &! r. hoh, cutoff=3.2, hb_list_name=abc-hbonds
|
|
127
|
-
"""
|
|
128
|
-
cutoff=float(cutoff)
|
|
129
|
-
angle=float(angle)
|
|
130
|
-
hb = cmd.find_pairs("((byres "+selection+") #{select1})","((byres "+selection+") #{select2})",mode=1,cutoff=cutoff,angle=angle)
|
|
131
|
-
# sort the list for easier reading
|
|
132
|
-
hb.sort(lambda x,y:(cmp(x[0][1],y[0][1])))
|
|
133
|
-
|
|
134
|
-
for pairs in hb:
|
|
135
|
-
print "PAIR:",
|
|
136
|
-
for ind in [0,1]:
|
|
137
|
-
cmd.iterate("%s and index %s" % (pairs[ind][0],pairs[ind][1]), 'print "%s/%3s`%s/%s/%s " % (chain,resn,resi,name,index),')
|
|
138
|
-
print "%.2f" % cmd.distance(hb_list_name,"%s and index %s" % (pairs[0][0],pairs[0][1]),"%s and index %s" % (pairs[1][0],pairs[1][1]))
|
|
139
|
-
|
|
140
|
-
cmd.extend("list_hb",list_hb)
|
|
141
|
-
}
|
|
142
|
-
end
|
|
143
|
-
|
|
144
|
-
# takes output of hb_script and returns an array of triplets [id1, id2, distance]
|
|
145
|
-
def list_hb_parser(pymol_hb_script_reply, flag=/^PAIR: /)
|
|
146
|
-
# grab each line of output with specified header, then remove the header
|
|
147
|
-
hbond_lines = pymol_hb_script_reply.split("\n").select {|line| line =~ flag }.map {|line| line.sub(flag,'') }
|
|
148
|
-
|
|
149
|
-
ids_and_distances = hbond_lines.map do |line|
|
|
150
|
-
# A/THR`325/N/2478 A/ALA`323/O/2468 3.05
|
|
151
|
-
(first, second, dist) = line.split(/\s+/)
|
|
152
|
-
(id1, id2) = [first, second].map {|v| v.split('/').last.to_i }
|
|
153
|
-
[id1, id2, dist.to_f]
|
|
154
|
-
end
|
|
155
|
-
end
|
|
156
|
-
end
|
|
157
|
-
end
|