rubabel 0.1.0
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/.document +5 -0
- data/.rspec +1 -0
- data/LICENSE +21 -0
- data/README.rdoc +52 -0
- data/Rakefile +43 -0
- data/VERSION +1 -0
- data/lib/rubabel.rb +116 -0
- data/lib/rubabel/atom.rb +143 -0
- data/lib/rubabel/bond.rb +47 -0
- data/lib/rubabel/fingerprint.rb +0 -0
- data/lib/rubabel/fragmentation.rb +23 -0
- data/lib/rubabel/molecule.rb +305 -0
- data/lib/rubabel/molecule_data.rb +0 -0
- data/lib/rubabel/pm.rb +38 -0
- data/lib/rubabel/smarts.rb +27 -0
- data/reference/OBConversion_methods.txt +47 -0
- data/reference/arity_method_list.txt +3553 -0
- data/reference/arity_method_list_CLASS.txt +337 -0
- data/reference/atom_methods.txt +145 -0
- data/reference/bond_methods.txt +79 -0
- data/reference/get_methods.rb +52 -0
- data/reference/mol_methods.txt +183 -0
- data/spec/rubabel/atom_spec.rb +49 -0
- data/spec/rubabel/bond_spec.rb +19 -0
- data/spec/rubabel/molecule_spec.rb +91 -0
- data/spec/rubabel_spec.rb +67 -0
- data/spec/spec_helper.rb +12 -0
- data/spec/testfiles/7-oxocholesterol-d7.mol +97 -0
- data/spec/testfiles/7-oxocholesterol-d7.sdf +155 -0
- data/spec/testfiles/Samples.sdf +2441 -0
- data/spec/testfiles/cholesterol.mol +74 -0
- data/spec/testfiles/cholesterol.sdf +132 -0
- data/spec/testfiles/two.sdf +287 -0
- metadata +130 -0
data/.document
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
Copyright (c) 2012 Brigham Young University
|
2
|
+
authored by: John T. Prince
|
3
|
+
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
a copy of this software and associated documentation files (the
|
6
|
+
"Software"), to deal in the Software without restriction, including
|
7
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be
|
13
|
+
included in all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
= rubabel
|
2
|
+
|
3
|
+
Ruby interface to the openbabel ruby bindings (or the openbabel gem). The
|
4
|
+
interface attempts to be a ruby-ish analogue of
|
5
|
+
{pybel}[http://openbabel.org/docs/current/UseTheLibrary/Python_PybelAPI.html].
|
6
|
+
|
7
|
+
== Examples
|
8
|
+
|
9
|
+
Rubabel.foreach("file.sdf") do |mol|
|
10
|
+
print mol.write # -> canonical smiles: "smiles_string\tname\n"
|
11
|
+
puts mol # .to_s -> canonical smiles string with no name or newline
|
12
|
+
puts mol.exact_mass
|
13
|
+
end
|
14
|
+
|
15
|
+
uniq_atom_types = Rubabel.foreach("file.mol").map(&:type).uniq
|
16
|
+
|
17
|
+
== Installing
|
18
|
+
|
19
|
+
=== Install openbabel
|
20
|
+
|
21
|
+
First, make sure you have the ruby openbabel bindings properly installed. You can do this by {properly installing the gem][https://github.com/amaunz/openbabel-gem]. Alternatively, you can following these instructions to build from source:
|
22
|
+
|
23
|
+
1. download openbabel
|
24
|
+
2. swap out Init_OpenBabel for Init_openbabel in scripts/ruby/openbabel-ruby.cpp (see here[http://forums.openbabel.org/Ruby-Open-Babel-in-2-1-1-td957640.html]). Some versions have this fixed already, apparently.
|
25
|
+
3. make sure you have the right {dependencies to compile}(http://openbabel.org/docs/2.3.1/Installation/install.html#compiling-open-babel)
|
26
|
+
|
27
|
+
Here's a complete example of compiling for a single user on Ubuntu 11.10 and probably will be generally forward compatible for some time. This will compile bindings on whichever ruby comes up with '/usr/bin/env ruby':
|
28
|
+
|
29
|
+
# install the dependencies:
|
30
|
+
sudo apt-get install libeigen2-dev cmake libwxgtk2.8-dev libxml2-dev libcairo2-dev
|
31
|
+
# unpack it:
|
32
|
+
tar -xzvf openbabel-2.3.1.tar.gz
|
33
|
+
# swap out buggy lines in ruby bindings:
|
34
|
+
sed -i 's/Init_OpenBabel/Init_openbabel/g' openbabel-2.3.1/scripts/ruby/openbabel-ruby.cpp
|
35
|
+
# make a separate build directory for building in:
|
36
|
+
mkdir build-rvmruby1.9.3
|
37
|
+
cd build-rvmruby1.9.3
|
38
|
+
mkdir ~/tools
|
39
|
+
cmake ../openbabel-2.3.1 -DRUBY_BINDINGS=ON -DCMAKE_INSTALL_PREFIX=~/tools/openbabel-rvmruby1.9.3
|
40
|
+
make && make install
|
41
|
+
|
42
|
+
=== Install the gem
|
43
|
+
|
44
|
+
gem install rubabel
|
45
|
+
|
46
|
+
Assuming you have the {dependencies for the openbabel gem}[https://github.com/amaunz/openbabel-gem], you could install in one go like this:
|
47
|
+
|
48
|
+
gem install openbabel rubabel
|
49
|
+
|
50
|
+
== Copyright
|
51
|
+
|
52
|
+
MIT License. See LICENSE for further details.
|
data/Rakefile
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'rake'
|
5
|
+
|
6
|
+
require 'jeweler'
|
7
|
+
Jeweler::Tasks.new do |gem|
|
8
|
+
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
9
|
+
gem.name = "rubabel"
|
10
|
+
gem.homepage = "http://github.com/princelab/rubabel"
|
11
|
+
gem.license = "MIT"
|
12
|
+
gem.summary = %Q{Ruby interface to the OpenBabel ruby bindings similar to pybel}
|
13
|
+
gem.description = %Q{Ruby interface to the openbabel ruby bindings (or the openbabel gem). The
|
14
|
+
interface attempts to be a ruby-ish analogue of pybel.}
|
15
|
+
gem.email = "jtprince@gmail.com"
|
16
|
+
gem.authors = ["John T. Prince"]
|
17
|
+
[
|
18
|
+
["rspec", "~> 2.8.0"],
|
19
|
+
["rdoc", "~> 3.12"],
|
20
|
+
["jeweler", "~> 1.8.3"]
|
21
|
+
].each do |name, version_string|
|
22
|
+
gem.add_development_dependency(name, version_string)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
Jeweler::RubygemsDotOrgTasks.new
|
26
|
+
|
27
|
+
require 'rspec/core'
|
28
|
+
require 'rspec/core/rake_task'
|
29
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
30
|
+
spec.pattern = FileList['spec/**/*_spec.rb']
|
31
|
+
end
|
32
|
+
|
33
|
+
task :default => :spec
|
34
|
+
|
35
|
+
require 'rdoc/task'
|
36
|
+
Rake::RDocTask.new do |rdoc|
|
37
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
38
|
+
|
39
|
+
rdoc.rdoc_dir = 'rdoc'
|
40
|
+
rdoc.title = "rubabel #{version}"
|
41
|
+
rdoc.rdoc_files.include('README*')
|
42
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
43
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
data/lib/rubabel.rb
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'openbabel'
|
2
|
+
|
3
|
+
%w(atom molecule fingerprint smarts molecule_data).each do |klass|
|
4
|
+
require "rubabel/#{klass}"
|
5
|
+
end
|
6
|
+
|
7
|
+
module Rubabel
|
8
|
+
# the command to execute the utility. They are initialized to be eponymous.
|
9
|
+
CMD = {
|
10
|
+
babel: 'babel',
|
11
|
+
obabel: 'obabel',
|
12
|
+
}
|
13
|
+
|
14
|
+
class << self
|
15
|
+
|
16
|
+
# returns a hash keyed by type (Symbol) pointing to a description of the
|
17
|
+
# format
|
18
|
+
def in_formats
|
19
|
+
@in_formats ||= formats_to_hash(OpenBabel::OBConversion.new.get_supported_input_format)
|
20
|
+
end
|
21
|
+
|
22
|
+
# returns a hash keyed by type (Symbol) pointing to a description of the
|
23
|
+
# format
|
24
|
+
def out_formats
|
25
|
+
@out_formats ||= formats_to_hash(OpenBabel::OBConversion.new.get_supported_output_format)
|
26
|
+
end
|
27
|
+
|
28
|
+
# determines the extension from filename if type is nil
|
29
|
+
def foreach(filename, type=nil, &block)
|
30
|
+
block or return enum_for(__method__, filename, type)
|
31
|
+
(obmol, obconv, not_at_end) = read_first_obmol(filename, type)
|
32
|
+
# the obmol is not valid if we are already at the end!
|
33
|
+
while not_at_end
|
34
|
+
block.call Rubabel::Molecule.new(obmol)
|
35
|
+
obmol = OpenBabel::OBMol.new
|
36
|
+
not_at_end = obconv.read(obmol)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# returns a Rubabel::Molecule (the first in the file if there are
|
41
|
+
# multiples). See ::foreach for accessing all molecules in a file
|
42
|
+
# determines the type from the extension if type is nil.
|
43
|
+
def read_file(filename, type=nil)
|
44
|
+
obmol = read_first_obmol(filename, type).first
|
45
|
+
Rubabel::Molecule.new(obmol)
|
46
|
+
end
|
47
|
+
|
48
|
+
# reads one molecule from the string
|
49
|
+
def read_string(string, type=:smi)
|
50
|
+
obmol = OpenBabel::OBMol.new
|
51
|
+
obconv = OpenBabel::OBConversion.new
|
52
|
+
obconv.set_in_format(type.to_s) || raise(ArgumentError, "invalid format #{type}")
|
53
|
+
success = obconv.read_string(obmol, string)
|
54
|
+
Rubabel::Molecule.new(obmol)
|
55
|
+
end
|
56
|
+
|
57
|
+
# returns a filetype symbol based on the extension
|
58
|
+
def filetype(filename)
|
59
|
+
# should use the openbabel method in the future
|
60
|
+
File.extname(filename)[1..-1].to_sym
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
# reads the first entry and returns the OBMol object, the OBConversion object,
|
65
|
+
# and the boolean not_at_end. This method is not intended for public usage
|
66
|
+
# but is necessary based on discrepancies between accessing the first
|
67
|
+
# molecule and subsequent molecules.
|
68
|
+
def read_first_obmol(filename, type=nil)
|
69
|
+
type ||= filetype(filename)
|
70
|
+
obconv = OpenBabel::OBConversion.new
|
71
|
+
obconv.set_in_format(type.to_s) || raise(ArgumentError, "invalid format #{type}")
|
72
|
+
obmol = OpenBabel::OBMol.new
|
73
|
+
not_at_end = obconv.read_file(obmol, filename)
|
74
|
+
[obmol, obconv, not_at_end]
|
75
|
+
end
|
76
|
+
|
77
|
+
def formats_to_hash(format_strings)
|
78
|
+
Hash[
|
79
|
+
format_strings.map do |str|
|
80
|
+
pair = str.split(/\s+--\s+/)
|
81
|
+
[pair[0].to_sym, pair[1]]
|
82
|
+
end
|
83
|
+
]
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
#protected_class_method :read_first_obmol
|
88
|
+
|
89
|
+
end
|
90
|
+
|
91
|
+
module Rubabel
|
92
|
+
# capitalized strings
|
93
|
+
ELEMENTS = %w(H He Li Be B C N O F Ne Na Mg Al Si P S Cl Ar K Ca Sc Ti V Cr Mn Fe Co Ni Cu Zn Ga Ge As Se Br Kr Rb Sr Y Zr Nb Mo Tc Ru Rh Pd Ag Cd In Sn Sb Te I Xe Cs Ba La Ce Pr Nd Pm Sm Eu Gd Tb Dy Ho Er Tm Yb Lu Hf Ta W Re Os Ir Pt Au Hg Tl Pb Bi Po At Rn Fr Ra Ac Th Pa U Np Pu Am Cm Bk Cf Es Fm Md No Lr Rf Db Sg Bh Hs Mt Ds Rg Cn Uut Fl Uup Lv Uus Uuo)
|
94
|
+
|
95
|
+
# atomic number to properly capitalized element abbreviation
|
96
|
+
NUM_TO_ELEMENT = Hash[ ELEMENTS.each_with_index.map {|el,i| [i+1,el] } ]
|
97
|
+
|
98
|
+
# atomic number to lowercase symbol abbreviation
|
99
|
+
NUM_TO_EL = Hash[ ELEMENTS.each_with_index.map {|el,i| [i+1,el.downcase.to_sym] } ]
|
100
|
+
end
|
101
|
+
|
102
|
+
=begin
|
103
|
+
OBConversion conv;
|
104
|
+
OBMol mol;
|
105
|
+
bool success = conv.SetInFormat("sdf");
|
106
|
+
if(success)
|
107
|
+
{
|
108
|
+
bool notatend = conv.ReadFile(&mol, "myfile.sdf");
|
109
|
+
// Do something with mol
|
110
|
+
while(notatend)
|
111
|
+
{
|
112
|
+
notatend = conv.Read(&mol);
|
113
|
+
// Do something with mol
|
114
|
+
}
|
115
|
+
}
|
116
|
+
=end
|
data/lib/rubabel/atom.rb
ADDED
@@ -0,0 +1,143 @@
|
|
1
|
+
require 'matrix'
|
2
|
+
|
3
|
+
require 'rubabel/bond'
|
4
|
+
|
5
|
+
class OpenBabel::OBAtom
|
6
|
+
def upcast
|
7
|
+
Rubabel::Atom.new(self)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
module Rubabel
|
12
|
+
class Atom
|
13
|
+
include Enumerable
|
14
|
+
|
15
|
+
# the OpenBabel::OBAtom object
|
16
|
+
attr_accessor :ob
|
17
|
+
|
18
|
+
def initialize(obatom)
|
19
|
+
@ob = obatom
|
20
|
+
end
|
21
|
+
|
22
|
+
def id
|
23
|
+
@ob.get_id
|
24
|
+
end
|
25
|
+
|
26
|
+
def id=(val)
|
27
|
+
@ob.set_id(val)
|
28
|
+
end
|
29
|
+
|
30
|
+
# index of the atom (begins with 1)
|
31
|
+
def idx
|
32
|
+
@ob.get_idx
|
33
|
+
end
|
34
|
+
|
35
|
+
# abbreviated name, all lowercase as a Symbol
|
36
|
+
def el
|
37
|
+
NUM_TO_EL[atomic_num]
|
38
|
+
end
|
39
|
+
|
40
|
+
# abbreviated name, properly capitalized and as a String
|
41
|
+
def element
|
42
|
+
NUM_TO_ELEMENT[atomic_num]
|
43
|
+
end
|
44
|
+
|
45
|
+
def each_bond(&block)
|
46
|
+
block or return enum_for(__method__)
|
47
|
+
iter = @ob.begin_bonds
|
48
|
+
_bond = @ob.begin_bond(iter)
|
49
|
+
while _bond
|
50
|
+
block.call _bond.upcast
|
51
|
+
_bond = @ob.next_bond(iter)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
alias_method :each, :each_bond
|
56
|
+
|
57
|
+
# returns the bonds. Consider using each_bond.
|
58
|
+
def bonds
|
59
|
+
each_bond.map.to_a
|
60
|
+
end
|
61
|
+
|
62
|
+
# iterates through each neighboring atom
|
63
|
+
def each_atom(&block)
|
64
|
+
block or return enum_for(__method__)
|
65
|
+
iter = @ob.begin_bonds
|
66
|
+
_atom = @ob.begin_nbr_atom(iter)
|
67
|
+
while _atom
|
68
|
+
block.call _atom.upcast
|
69
|
+
_atom = @ob.next_nbr_atom(iter)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# returns the neighboring atoms. Consider using each_atom.
|
74
|
+
def atoms
|
75
|
+
each_atom.map.to_a
|
76
|
+
end
|
77
|
+
|
78
|
+
def atomic_mass
|
79
|
+
@ob.get_atomic_mass
|
80
|
+
end
|
81
|
+
|
82
|
+
def atomic_num
|
83
|
+
@ob.get_atomic_num
|
84
|
+
end
|
85
|
+
|
86
|
+
def exact_mass
|
87
|
+
@ob.get_exact_mass
|
88
|
+
end
|
89
|
+
|
90
|
+
def formal_charge
|
91
|
+
@ob.get_formal_charge
|
92
|
+
end
|
93
|
+
alias_method :charge, :formal_charge
|
94
|
+
|
95
|
+
def heavy_valence
|
96
|
+
@ob.get_heavy_valence
|
97
|
+
end
|
98
|
+
|
99
|
+
def hetero_valence
|
100
|
+
@ob.get_hetero_valence
|
101
|
+
end
|
102
|
+
|
103
|
+
def hyb
|
104
|
+
@ob.get_hybridization
|
105
|
+
end
|
106
|
+
|
107
|
+
def implicit_valence
|
108
|
+
@ob.get_implicit_valence
|
109
|
+
end
|
110
|
+
|
111
|
+
def isotope
|
112
|
+
@ob.get_isotope
|
113
|
+
end
|
114
|
+
|
115
|
+
def partial_charge
|
116
|
+
@ob.get_partial_charge
|
117
|
+
end
|
118
|
+
|
119
|
+
def spin
|
120
|
+
@ob.get_spin_multiplicity
|
121
|
+
end
|
122
|
+
|
123
|
+
def type
|
124
|
+
@ob.get_type
|
125
|
+
end
|
126
|
+
|
127
|
+
def valence
|
128
|
+
@ob.get_valence
|
129
|
+
end
|
130
|
+
|
131
|
+
def vector
|
132
|
+
@ob.get_vector
|
133
|
+
end
|
134
|
+
|
135
|
+
def coords
|
136
|
+
Vector[@ob.x, @ob.y, @ob.z]
|
137
|
+
end
|
138
|
+
|
139
|
+
def inspect
|
140
|
+
"<#{type} id:#{id}>"
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
data/lib/rubabel/bond.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'rubabel/atom'
|
2
|
+
|
3
|
+
class OpenBabel::OBBond
|
4
|
+
def upcast
|
5
|
+
Rubabel::Bond.new(self)
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
|
10
|
+
module Rubabel
|
11
|
+
|
12
|
+
# delegates to obbond object if the method is missing
|
13
|
+
class Bond
|
14
|
+
include Enumerable
|
15
|
+
|
16
|
+
attr_accessor :ob
|
17
|
+
|
18
|
+
def initialize(obbond)
|
19
|
+
@ob = obbond
|
20
|
+
end
|
21
|
+
|
22
|
+
# considered included if the atom ids match
|
23
|
+
def include?(atom)
|
24
|
+
# atoms.any? {|atm| atom.id == atm.id }
|
25
|
+
(@ob.get_begin_atom.get_id == atom.id) || (@ob.get_end_atom.get_id == atom.id)
|
26
|
+
end
|
27
|
+
|
28
|
+
def each_atom(&block)
|
29
|
+
block or return enum_for(__method__)
|
30
|
+
block.call @ob.get_begin_atom.upcast
|
31
|
+
block.call @ob.get_end_atom.upcast
|
32
|
+
self
|
33
|
+
end
|
34
|
+
|
35
|
+
alias_method :each, :each_atom
|
36
|
+
|
37
|
+
# returns an array of Rubabel::Atoms
|
38
|
+
def atoms
|
39
|
+
[@ob.get_begin_atom.upcast, @ob.get_end_atom.upcast]
|
40
|
+
end
|
41
|
+
|
42
|
+
def inspect
|
43
|
+
"[#{atoms.map(&:inspect).join('-')}]"
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
File without changes
|
@@ -0,0 +1,23 @@
|
|
1
|
+
|
2
|
+
module Rubabel
|
3
|
+
class Fragmentation
|
4
|
+
|
5
|
+
ADDUCTS = [:lioh, :nh4cl, :nh4oh]
|
6
|
+
|
7
|
+
DEFAULTS = {
|
8
|
+
ph: 7.4,
|
9
|
+
adducts: [],
|
10
|
+
}
|
11
|
+
|
12
|
+
def initialize(mol, options)
|
13
|
+
@mol = mol
|
14
|
+
@options = options
|
15
|
+
end
|
16
|
+
|
17
|
+
def fragment(rules=[:co])
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|