rubabel 0.2.2 → 0.3.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/README.md +140 -96
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/lib/rubabel/atom.rb +14 -20
- data/lib/rubabel/bond.rb +20 -7
- data/lib/rubabel/molecule/fragmentable.rb +2 -2
- data/lib/rubabel/molecule.rb +29 -26
- data/lib/rubabel.rb +15 -6
- data/spec/chemistry_toolkit_rosetta/chemistry_toolkit_rosetta_spec.rb +12 -5
- data/spec/rubabel/atom_spec.rb +1 -0
- data/spec/rubabel/bond_spec.rb +57 -0
- data/spec/rubabel/molecule_spec.rb +39 -29
- data/spec/spec_helper.rb +2 -2
- metadata +4 -4
data/README.md
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# rubabel
|
2
2
|
|
3
|
-
Ruby interface to the
|
3
|
+
Ruby interface to the OpenBabel ruby bindings (or the openbabel gem). The
|
4
4
|
interface attempts to be a ruby-ish analogue of
|
5
|
-
[pybel](http://openbabel.org/docs/current/UseTheLibrary/Python_PybelAPI.html).
|
5
|
+
[pybel](http://openbabel.org/docs/current/UseTheLibrary/Python_PybelAPI.html). Works with ruby 1.9 and 2.0.
|
6
6
|
|
7
7
|
## Examples
|
8
8
|
|
@@ -12,150 +12,185 @@ The [Chemistry Toolkit Rosetta Wiki](http://ctr.wikia.com/wiki/Chemistry_Toolkit
|
|
12
12
|
|
13
13
|
#### From a string
|
14
14
|
|
15
|
-
|
15
|
+
```ruby
|
16
|
+
require 'rubabel'
|
16
17
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
18
|
+
# by default, reads in smiles strings
|
19
|
+
serine = Rubabel["C(C(C(=O)O)N)O"]
|
20
|
+
# more formally:
|
21
|
+
serine = Rubabel::Molecule.from_string("C(C(C(=O)O)N)O")
|
21
22
|
|
22
|
-
|
23
|
-
|
23
|
+
# also any other format openbabel supports, for example inchi
|
24
|
+
serine = Rubabel["InChI=1S/C3H7NO3/c4-2(1-5)3(6)7/h2,5H,1,4H2,(H,6,7)", :inchi]
|
24
25
|
|
25
|
-
|
26
|
-
|
26
|
+
# from the internet:
|
27
|
+
mol = Rubabel[some_molecule, Rubabel.format_from_mime(some_mime_type)]
|
27
28
|
|
28
29
|
Find out all the formats Rubabel supports (hash is format key pointing to the description):
|
29
30
|
|
30
|
-
|
31
|
-
|
31
|
+
hash = Rubabel.in_formats
|
32
|
+
hash = Rubabel.out_formats
|
33
|
+
```
|
32
34
|
|
33
35
|
#### From a file
|
34
36
|
|
35
37
|
Reading multiple entries from a file:
|
36
38
|
|
37
|
-
|
38
|
-
|
39
|
-
|
39
|
+
```ruby
|
40
|
+
Rubabel.foreach("file.sdf") do |mol|
|
41
|
+
puts mol.exact_mass
|
42
|
+
end
|
43
|
+
```
|
40
44
|
|
41
45
|
Foreach returns an enumerator that can be chained:
|
42
46
|
|
43
|
-
|
44
|
-
|
47
|
+
```ruby
|
48
|
+
# return an array of every unique atom type in the file
|
49
|
+
uniq_atom_types = Rubabel.foreach("file.mol").flat_map {|mol| mol.map(&:type) }.uniq
|
50
|
+
```
|
45
51
|
|
46
52
|
Read a single molecule from a file (reads only the first molecule)
|
47
53
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
54
|
+
```ruby
|
55
|
+
mol = Rubabel::Molecule.from_file("file.sdf")
|
56
|
+
# handles gzipped files seamlessly:
|
57
|
+
mol = Rubabel::Molecule.from_file("file.sdf.gz")
|
58
|
+
mol = Rubabel.molecule_from_file("file.sdf") # alternative
|
52
59
|
|
53
|
-
|
54
|
-
|
60
|
+
# explicit format for uninformative/wrong extensions:
|
61
|
+
mol = Rubabel::Molecule.from_file("file", :sdf)
|
62
|
+
```
|
55
63
|
|
56
64
|
### Writing/Drawing
|
57
65
|
|
58
66
|
#### create string output
|
59
67
|
|
60
|
-
|
68
|
+
```ruby
|
69
|
+
mol = Rubabel["OCC"] # ethanol
|
61
70
|
|
62
|
-
|
63
|
-
|
71
|
+
mol.to_s # canonical smiles -> "CCO"
|
72
|
+
mol.csmiles # same thing
|
64
73
|
|
65
|
-
|
66
|
-
|
74
|
+
mol.to_s(:smi) # smiles -> "OCC"
|
75
|
+
mol.smiles # same thing
|
76
|
+
```
|
67
77
|
|
68
78
|
For inclusion in a file with standard smiles formatting (SMILES\tID\n):
|
69
79
|
|
70
|
-
|
71
|
-
|
72
|
-
|
80
|
+
```ruby
|
81
|
+
can_smiles_string = mol.write_string # -> "CCO\t\n"
|
82
|
+
mol.title = "ethanol"
|
83
|
+
can_smiles_string = mol.write(:can) # -> "CCO\tethanol\n"
|
84
|
+
```
|
73
85
|
|
74
86
|
Other formats in the same manner:
|
75
87
|
|
76
|
-
|
88
|
+
```ruby
|
89
|
+
pdb_string = mol.write(:pdb)
|
90
|
+
```
|
77
91
|
|
78
92
|
Write to a file directly (single molecule only; depends on file extension for type):
|
79
93
|
|
80
|
-
|
81
|
-
|
82
|
-
|
94
|
+
```ruby
|
95
|
+
# write to a smiles file
|
96
|
+
mol.write("file.smi")
|
97
|
+
mol.write_file("file.smi")
|
98
|
+
```
|
83
99
|
|
84
100
|
Write multiple molecules to a file:
|
85
101
|
|
86
|
-
|
87
|
-
|
88
|
-
|
102
|
+
```ruby
|
103
|
+
File.open("somefile.pdb", 'w') do |out|
|
104
|
+
molecules.each {|mol| out.print mol.write(:pdb) }
|
105
|
+
end
|
106
|
+
```
|
89
107
|
|
90
108
|
#### Drawing
|
91
109
|
|
92
110
|
If you write to svg or png (png uses mini_magick to convert from svg) then the
|
93
111
|
molecule is automatically drawn in 2D:
|
94
112
|
|
95
|
-
|
96
|
-
|
113
|
+
```ruby
|
114
|
+
mol = Rubabel["NCC(O)C(=O)O"]
|
115
|
+
mol.write("file.svg")
|
97
116
|
|
98
|
-
|
99
|
-
|
117
|
+
# must have imagemagick ('convert' command) and mini_magick gem installed
|
118
|
+
mol.write("file.png")
|
119
|
+
```
|
100
120
|
|
101
121
|
### Searching and Splitting
|
102
122
|
|
103
123
|
*each_match*, *matches*, *matches?*, *smarts_indices* all take the same input (SMARTS
|
104
124
|
string or object and optional boolean specifying uniqueness of results):
|
105
125
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
126
|
+
```ruby
|
127
|
+
mol = Rubabel["NCC(O)C(=O)O"]
|
128
|
+
mol.each_match("CO") do |match|
|
129
|
+
# match is just an array of atoms that matched
|
130
|
+
match.first.el # => :C
|
131
|
+
match.last.el # => :O
|
132
|
+
end
|
133
|
+
|
134
|
+
# matches returns all the matches in an array
|
135
|
+
all_matches = mol.matches("CO")
|
136
|
+
# all the match routines take a boolean to alter uniqueness
|
137
|
+
all_matches = mol.matches("CO", false) # some matches may not be uniq
|
138
|
+
```
|
117
139
|
|
118
140
|
Have some bonds to break?, split makes new molecules split from that bond(s)
|
119
|
-
|
120
|
-
|
121
|
-
|
141
|
+
|
142
|
+
```ruby
|
143
|
+
bonds = mol.matches("CO").map {|c, o| c.get_bond(o) }
|
144
|
+
mol.split(*bonds) # splits between every carbon single bonded to oxygen
|
145
|
+
```
|
122
146
|
|
123
147
|
### Add, delete, modify atoms/bonds
|
124
148
|
|
125
149
|
#### Adding
|
126
150
|
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
151
|
+
```ruby
|
152
|
+
mol = Rubabel["OCC"]
|
153
|
+
# adds a carbon, then an oxygen to the previous carbon
|
154
|
+
mol << 6 << 8 # #<Mol "OCCCO">
|
155
|
+
mol << :C << :O # same thing
|
131
156
|
|
132
|
-
|
133
|
-
|
134
|
-
|
157
|
+
# add an ethyl group specifically to second atom (the first carbon)
|
158
|
+
mol = Rubabel["OCC"]
|
159
|
+
mol[1] << :C << :C
|
135
160
|
|
136
|
-
|
137
|
-
|
138
|
-
|
161
|
+
# add a vinyl group to second carbon (use method notation and parenthesis
|
162
|
+
# because we are going to specify 2 arguments (the bond order):
|
163
|
+
( mol[1] << :C).<<(:C, 2)
|
164
|
+
```
|
139
165
|
|
140
166
|
#### Deleting
|
141
167
|
|
142
|
-
|
143
|
-
|
144
|
-
|
168
|
+
```ruby
|
169
|
+
# delete an atom:
|
170
|
+
mol = Rubabel["NCO"]
|
171
|
+
mol.delete(mol[0])
|
172
|
+
# mol.to_s -> #<Mol CO>
|
145
173
|
|
146
|
-
|
147
|
-
|
148
|
-
|
174
|
+
# delete a bond:
|
175
|
+
bond = mol[0].get_bond(mol[1])
|
176
|
+
mol.delete(bond)
|
177
|
+
# mol.to_s -> #<Mol C.O>
|
178
|
+
```
|
149
179
|
|
150
180
|
#### Modifying
|
151
181
|
|
152
|
-
Can
|
182
|
+
Can easily change the bond order:
|
183
|
+
|
184
|
+
```ruby
|
185
|
+
mol = Rubabel["CC"]
|
186
|
+
bond = mol[0].get_bond(mol[1]) # get the bond you want
|
187
|
+
bond = mol[0].bonds.first # alternate way to get at bonds
|
153
188
|
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
189
|
+
bond += 2 # now it is a triple bond
|
190
|
+
bond.dec! # now a double bond
|
191
|
+
bond -= 1 # now a single bond
|
192
|
+
bond.inc!(2) # back to a triple bond
|
193
|
+
```
|
159
194
|
|
160
195
|
## Installing
|
161
196
|
|
@@ -165,11 +200,15 @@ First, many thanks to Andreas Maunz for packaging openbabel as a gem which makes
|
|
165
200
|
|
166
201
|
On a POSIX system, make sure you have openbabel (including header files), cmake, curl, tar, sed and make {see openbabel instructions}[https://github.com/amaunz/openbabel-gem]. On ubuntu/debian:
|
167
202
|
|
168
|
-
|
203
|
+
```bash
|
204
|
+
sudo apt-get install openbabel libopenbabel-dev cmake make curl
|
205
|
+
```
|
169
206
|
|
170
207
|
Then install the gem (which should install the openbabel gem, too):
|
171
208
|
|
172
|
-
|
209
|
+
```bash
|
210
|
+
gem install rubabel
|
211
|
+
```
|
173
212
|
|
174
213
|
### Building from Source
|
175
214
|
|
@@ -179,21 +218,26 @@ Then install the gem (which should install the openbabel gem, too):
|
|
179
218
|
|
180
219
|
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':
|
181
220
|
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
221
|
+
```bash
|
222
|
+
# install the dependencies:
|
223
|
+
sudo apt-get install libeigen2-dev cmake libwxgtk2.8-dev libxml2-dev libcairo2-dev
|
224
|
+
# unpack it:
|
225
|
+
tar -xzvf openbabel-2.3.1.tar.gz
|
226
|
+
# swap out buggy lines in ruby bindings:
|
227
|
+
sed -i 's/Init_OpenBabel/Init_openbabel/g' openbabel-2.3.1/scripts/ruby/openbabel-ruby.cpp
|
228
|
+
# make a separate build directory for building in:
|
229
|
+
mkdir build-rvmruby1.9.3
|
230
|
+
cd build-rvmruby1.9.3
|
231
|
+
mkdir ~/tools
|
232
|
+
cmake ../openbabel-2.3.1 -DRUBY_BINDINGS=ON -DCMAKE_INSTALL_PREFIX=~/tools/openbabel-rvmruby1.9.3
|
233
|
+
make && make install
|
234
|
+
```
|
235
|
+
## See also
|
236
|
+
|
237
|
+
* [Rubidium](http://rbtk.rubyforge.org/) (based on the Chemistry Development Kit [jruby])
|
238
|
+
* [ChemRuby](https://github.com/ank/chemruby) [standalone using MRI extensions]
|
239
|
+
* [Chemcaster Ruby API](https://github.com/metamolecular/chemcaster-ruby)
|
240
|
+
|
197
241
|
## Copyright
|
198
242
|
|
199
243
|
MIT License. See LICENSE for further details.
|
data/Rakefile
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.3.0
|
data/lib/rubabel/atom.rb
CHANGED
@@ -37,11 +37,6 @@ module Rubabel
|
|
37
37
|
#end
|
38
38
|
end
|
39
39
|
|
40
|
-
# adds an atom and returns the added atom (allows chaining)
|
41
|
-
def <<(atom, bond_order=1)
|
42
|
-
add_atom!(atom, bond_order)
|
43
|
-
end
|
44
|
-
|
45
40
|
# returns the molecule that is parent of this atom
|
46
41
|
def mol
|
47
42
|
@ob.get_parent.andand.upcast
|
@@ -67,24 +62,23 @@ module Rubabel
|
|
67
62
|
@ob.get_idx
|
68
63
|
end
|
69
64
|
|
70
|
-
#
|
71
|
-
def el
|
72
|
-
NUM_TO_EL[atomic_num]
|
73
|
-
end
|
74
|
-
|
75
|
-
# abbreviated name, properly capitalized and as a String
|
65
|
+
# elemental symbol, properly capitalized and returned as a Symbol
|
76
66
|
def element
|
77
67
|
NUM_TO_ELEMENT[atomic_num]
|
78
68
|
end
|
69
|
+
alias_method :el, :element
|
79
70
|
|
80
|
-
#
|
81
|
-
#
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
71
|
+
# connects the atom-like specifier to this atom through Molecule#add_atom!
|
72
|
+
# returns the atom that was just added for chaining. Takes any argument
|
73
|
+
# that Molecule#add_atom! will take.
|
74
|
+
def bond!(arg, bond_order=1)
|
75
|
+
mol.add_atom!(arg, bond_order, self)
|
76
|
+
end
|
77
|
+
alias_method :<<, :bond!
|
78
|
+
|
79
|
+
# connects a Rubabel::Atom object with a bond
|
80
|
+
def connect!(atom, bond_order=1)
|
81
|
+
@ob.get_parent.add_bond(@ob.get_idx, atom.ob.get_idx, bond_order)
|
88
82
|
end
|
89
83
|
|
90
84
|
def each_bond(&block)
|
@@ -319,7 +313,7 @@ module Rubabel
|
|
319
313
|
|
320
314
|
def carbonyl_oxygen?
|
321
315
|
ats = atoms
|
322
|
-
ats.size == 1 && ats.first.el == :
|
316
|
+
ats.size == 1 && ats.first.el == :C && double_bond?
|
323
317
|
end
|
324
318
|
|
325
319
|
def carbonyl_carbon?
|
data/lib/rubabel/bond.rb
CHANGED
@@ -59,11 +59,13 @@ module Rubabel
|
|
59
59
|
def bond_order
|
60
60
|
@ob.get_bond_order
|
61
61
|
end
|
62
|
+
alias_method :order, :bond_order
|
62
63
|
|
63
64
|
# 1 = single, 2 = double, 5 = aromatic
|
64
65
|
def bond_order=(val=1)
|
65
66
|
@ob.set_bond_order(val)
|
66
67
|
end
|
68
|
+
alias_method :order=, :bond_order=
|
67
69
|
|
68
70
|
# returns self
|
69
71
|
def set_atoms!(beg_atom, end_atom)
|
@@ -99,20 +101,31 @@ module Rubabel
|
|
99
101
|
"#{atoms.map(&:inspect).join(bond_symbol)}"
|
100
102
|
end
|
101
103
|
|
102
|
-
# returns
|
104
|
+
# Increases the bond order and returns a new Rubabel::Bond object--but it
|
105
|
+
# will still be pointing to the same underlying @ob object.
|
103
106
|
def +(val)
|
104
|
-
|
107
|
+
inc!(val)
|
108
|
+
@ob.upcast
|
109
|
+
end
|
110
|
+
|
111
|
+
# increase the bond order by val
|
112
|
+
def inc!(val=1)
|
105
113
|
newval = @ob.get_bond_order + val
|
114
|
+
newval = 0 if newval < 0
|
106
115
|
@ob.set_bond_order(newval)
|
107
116
|
self
|
108
117
|
end
|
109
118
|
|
110
|
-
#
|
119
|
+
# decrease the bond order by val
|
120
|
+
def dec!(val=1)
|
121
|
+
inc!(-val)
|
122
|
+
end
|
123
|
+
|
124
|
+
# Decreases the bond order and returns a new Rubabel::Bond object--but it
|
125
|
+
# will still be pointing to the same underlying @ob object. Won't
|
126
|
+
# decrease below zero.
|
111
127
|
def -(val)
|
112
|
-
|
113
|
-
newval = 0 if newval < 0
|
114
|
-
@ob.set_bond_order(newval)
|
115
|
-
self
|
128
|
+
self.+(-val)
|
116
129
|
end
|
117
130
|
|
118
131
|
end
|
@@ -31,7 +31,7 @@ module Rubabel
|
|
31
31
|
# oxygen (e.g., an OH or a charge) to the carbon_nbr. Returns two new
|
32
32
|
# molecules.
|
33
33
|
def carbonyl_oxygen_dump(carbon, oxygen, carbon_nbr)
|
34
|
-
appendage = oxygen.atoms.find {|a| a.el != :
|
34
|
+
appendage = oxygen.atoms.find {|a| a.el != :C }
|
35
35
|
if oxygen.charge != 0
|
36
36
|
ocharge = oxygen.charge
|
37
37
|
end
|
@@ -104,7 +104,7 @@ module Rubabel
|
|
104
104
|
|
105
105
|
if opts[:rules].any? {|r| [:cod, :codoo].include?(r) }
|
106
106
|
self.each_match("C[O;h1,O]", only_uniqs) do |carbon, oxygen|
|
107
|
-
carbon.atoms.select {|a| a.el == :
|
107
|
+
carbon.atoms.select {|a| a.el == :C }.each do |carbon_nbr|
|
108
108
|
fragment_sets << carbonyl_oxygen_dump(carbon, oxygen, carbon_nbr)
|
109
109
|
end
|
110
110
|
end
|
data/lib/rubabel/molecule.rb
CHANGED
@@ -108,25 +108,40 @@ module Rubabel
|
|
108
108
|
end
|
109
109
|
end
|
110
110
|
|
111
|
+
# arg may be a Fixnum, a Symbol (Elemental symbol that is a Symbol), or a
|
112
|
+
# Rubabel::Atom. Returns the newly associated/created atom.
|
113
|
+
def associate_atom!(arg)
|
114
|
+
if arg.is_a?(Rubabel::Atom)
|
115
|
+
@ob.add_atom(arg.ob)
|
116
|
+
arg
|
117
|
+
else
|
118
|
+
(num, is_aromatic) =
|
119
|
+
if arg.is_a?(Symbol)
|
120
|
+
[Rubabel::ELEMENT_TO_NUM[arg], (arg.to_s.capitalize != arg.to_s)]
|
121
|
+
else
|
122
|
+
[arg, false]
|
123
|
+
end
|
124
|
+
|
125
|
+
new_obatom = @ob.new_atom
|
126
|
+
new_obatom.set_atomic_num(num)
|
127
|
+
new_obatom.set_aromatic if is_aromatic
|
128
|
+
Rubabel::Atom.new(new_obatom)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
|
111
133
|
# returns the atom passed in or that was created. arg is a pre-existing
|
112
134
|
# atom, an atomic number or an element symbol (e.g. :c). default is to
|
113
135
|
# add carbon.
|
114
|
-
def add_atom!(arg=6,
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
@ob.add_atom(arg.ob)
|
120
|
-
arg
|
121
|
-
else
|
122
|
-
new_obatom = @ob.new_atom
|
123
|
-
arg = Rubabel::EL_TO_NUM[arg] if arg.is_a?(Symbol)
|
124
|
-
new_obatom.set_atomic_num(arg)
|
125
|
-
Rubabel::Atom.new(new_obatom)
|
126
|
-
end
|
127
|
-
end
|
136
|
+
def add_atom!(arg=6, bond_order=1, attach_to=nil)
|
137
|
+
attach_to ||= atoms.last
|
138
|
+
atom = associate_atom!(arg)
|
139
|
+
add_bond!(attach_to, atom, bond_order) if attach_to
|
140
|
+
atom
|
128
141
|
end
|
129
142
|
|
143
|
+
alias_method :<<, :add_atom!
|
144
|
+
|
130
145
|
# retrieves the atom by index (accepts everything an array would)
|
131
146
|
def [](*args)
|
132
147
|
atoms[*args]
|
@@ -490,18 +505,6 @@ module Rubabel
|
|
490
505
|
Rubabel::MoleculeData.new(@ob)
|
491
506
|
end
|
492
507
|
|
493
|
-
# adds the atom (takes atomic number, element symbol or preexisting atom)
|
494
|
-
# and returns self
|
495
|
-
def <<(arg, bond_order=1)
|
496
|
-
last_atom = atoms[-1]
|
497
|
-
if last_atom
|
498
|
-
last_atom.add_atom!(arg, bond_order)
|
499
|
-
else
|
500
|
-
add_atom!(arg)
|
501
|
-
end
|
502
|
-
self
|
503
|
-
end
|
504
|
-
|
505
508
|
# sensitive to add_h!
|
506
509
|
def num_atoms(count_implied_hydrogens=false)
|
507
510
|
if !count_implied_hydrogens
|
data/lib/rubabel.rb
CHANGED
@@ -113,19 +113,28 @@ module Rubabel
|
|
113
113
|
end
|
114
114
|
|
115
115
|
module Rubabel
|
116
|
-
# capitalized
|
117
|
-
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)
|
116
|
+
# capitalized Symbols
|
117
|
+
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).map(&:to_sym)
|
118
118
|
|
119
|
-
# atomic number to properly capitalized element abbreviation
|
119
|
+
# atomic number to properly capitalized element abbreviation (as Symbol)
|
120
120
|
NUM_TO_ELEMENT = Hash[ ELEMENTS.each_with_index.map {|el,i| [i+1,el] } ]
|
121
|
+
# atomic number to properly capitalized element abbreviation (as Symbol)
|
121
122
|
|
122
|
-
#
|
123
|
-
|
123
|
+
# the SMILES aromatic elements, listed in proper capitalized notation (e.g., :Se)
|
124
|
+
AROMATIC_ELEMENTS = [:C, :O, :S, :Se, :N]
|
125
|
+
# (http://esc.syrres.com/esc/docsmile.htm)
|
124
126
|
|
125
|
-
|
127
|
+
# Along with properly capitalized element symbols (e.g., :Se) ELEMENT_TO_NUM
|
128
|
+
# will include keys to lowercase versions of the AROMATIC_ELEMENTS
|
126
129
|
ELEMENT_TO_NUM = NUM_TO_ELEMENT.invert
|
130
|
+
|
131
|
+
AROMATIC_ELEMENTS.each do |el|
|
132
|
+
ELEMENT_TO_NUM[el.to_s.downcase.to_sym] = ELEMENT_TO_NUM[el]
|
133
|
+
end
|
127
134
|
end
|
128
135
|
|
136
|
+
|
137
|
+
|
129
138
|
=begin
|
130
139
|
OBConversion conv;
|
131
140
|
OBMol mol;
|
@@ -24,8 +24,12 @@ end
|
|
24
24
|
|
25
25
|
describe 'Chemistry Toolkit Rosetta Wiki' do
|
26
26
|
|
27
|
-
def
|
28
|
-
(png1.size - png2.size <
|
27
|
+
def pngs_are_about_same_size(png1, png2, delta=150)
|
28
|
+
(png1.size - png2.size < delta)
|
29
|
+
end
|
30
|
+
|
31
|
+
def pngs_have_same_header(png1, png2, check_length=60)
|
32
|
+
png1[0..check_length] == png2[0..check_length]
|
29
33
|
end
|
30
34
|
|
31
35
|
before(:each) do
|
@@ -239,7 +243,9 @@ describe 'Chemistry Toolkit Rosetta Wiki' do
|
|
239
243
|
end
|
240
244
|
png_out = IO.read(@wiki_spec_dir + "/caffeine.png")
|
241
245
|
key_out = IO.read(@keydir + "/caffeine.frozen.png")
|
242
|
-
|
246
|
+
|
247
|
+
pngs_are_about_same_size(png_out, key_out).should be_true
|
248
|
+
pngs_have_same_header(png_out, key_out).should be_true
|
243
249
|
File.unlink('caffeine.png')
|
244
250
|
end
|
245
251
|
#OR, using commandline
|
@@ -258,7 +264,8 @@ describe 'Chemistry Toolkit Rosetta Wiki' do
|
|
258
264
|
end
|
259
265
|
png_out = IO.read(@wiki_spec_dir + "/3016_highlighted.rubabel.png")
|
260
266
|
key_out = IO.read(@keydir + "/3016_highlighted.rubabel.frozen.png")
|
261
|
-
|
267
|
+
pngs_are_about_same_size(png_out, key_out).should be_true
|
268
|
+
pngs_have_same_header(png_out, key_out).should be_true
|
262
269
|
File.unlink('3016_highlighted.rubabel.png')
|
263
270
|
end
|
264
271
|
|
@@ -307,7 +314,7 @@ describe 'Chemistry Toolkit Rosetta Wiki' do
|
|
307
314
|
mol.matches(smarts).each do |atom1, atom2|
|
308
315
|
mol.delete(atom1.get_bond(atom2))
|
309
316
|
[atom1, atom2].each do |old_a|
|
310
|
-
mol.
|
317
|
+
mol.add_atom!(0, 1, old_a)
|
311
318
|
end
|
312
319
|
end
|
313
320
|
puts "#{mol.to_s.gsub('.',"\n")}"
|
data/spec/rubabel/atom_spec.rb
CHANGED
data/spec/rubabel/bond_spec.rb
CHANGED
@@ -19,4 +19,61 @@ describe Rubabel::Bond do
|
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
|
+
describe 'manipulating the bond order' do
|
23
|
+
subject {
|
24
|
+
mol = Rubabel['CC']
|
25
|
+
mol[0].get_bond(mol[1])
|
26
|
+
}
|
27
|
+
|
28
|
+
specify '#inc! increases the bond order' do
|
29
|
+
subject.order.should == 1
|
30
|
+
subject.inc!
|
31
|
+
subject.order.should == 2
|
32
|
+
end
|
33
|
+
|
34
|
+
specify '#inc!(n) increases the bond order by n' do
|
35
|
+
subject.order.should == 1
|
36
|
+
subject.inc!(2)
|
37
|
+
subject.order.should == 3
|
38
|
+
end
|
39
|
+
|
40
|
+
specify '#inc!(-n) will not go below 0' do
|
41
|
+
subject.order.should == 1
|
42
|
+
subject.inc!(-1)
|
43
|
+
subject.order.should == 0
|
44
|
+
subject.inc!(-1)
|
45
|
+
subject.order.should == 0
|
46
|
+
end
|
47
|
+
|
48
|
+
specify '#+(n) will add but not return same ruby object (underlying ob object same)' do
|
49
|
+
other = subject + 1
|
50
|
+
other.order.should == 2
|
51
|
+
subject.order.should == 2
|
52
|
+
subject.should_not equal(other)
|
53
|
+
#other.object_id.should_not == subject.object_id
|
54
|
+
end
|
55
|
+
|
56
|
+
specify '#+(n) will add but not return same ruby object (underlying ob object same)' do
|
57
|
+
another_var = subject
|
58
|
+
another_var += 1
|
59
|
+
another_var.order.should == 2
|
60
|
+
subject.order.should == 2
|
61
|
+
subject.ob.should equal(another_var.ob)
|
62
|
+
end
|
63
|
+
|
64
|
+
specify '#dec!' do
|
65
|
+
subject.dec!
|
66
|
+
subject.order.should == 0
|
67
|
+
end
|
68
|
+
|
69
|
+
specify '#-(n)' do
|
70
|
+
var = subject
|
71
|
+
var.inc!
|
72
|
+
var.order.should == 2
|
73
|
+
var -= 2
|
74
|
+
var.order.should == 0
|
75
|
+
var -= 1
|
76
|
+
var.order.should == 0
|
77
|
+
end
|
78
|
+
end
|
22
79
|
end
|
@@ -22,10 +22,10 @@ describe Rubabel::Molecule do
|
|
22
22
|
end
|
23
23
|
|
24
24
|
#xit 'can add a hydrogen to the formula' do
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
25
|
+
#mol = Rubabel["CCC"]
|
26
|
+
#p mol.formula
|
27
|
+
#mol.add_hydrogen_to_formula!
|
28
|
+
#p mol.formula
|
29
29
|
#end
|
30
30
|
|
31
31
|
describe 'png output' do
|
@@ -77,14 +77,14 @@ describe Rubabel::Molecule do
|
|
77
77
|
|
78
78
|
specify '#[] retrieves atom by index' do
|
79
79
|
mol = Rubabel["NCO"]
|
80
|
-
mol[0].el.should == :
|
81
|
-
mol[1].el.should == :
|
82
|
-
mol[2].el.should == :
|
83
|
-
mol[-1].el.should == :
|
84
|
-
mol[-2].el.should == :
|
80
|
+
mol[0].el.should == :N
|
81
|
+
mol[1].el.should == :C
|
82
|
+
mol[2].el.should == :O
|
83
|
+
mol[-1].el.should == :O
|
84
|
+
mol[-2].el.should == :C
|
85
85
|
ar = mol[1..-1]
|
86
|
-
ar.first.el.should == :
|
87
|
-
ar.last.el.should == :
|
86
|
+
ar.first.el.should == :C
|
87
|
+
ar.last.el.should == :O
|
88
88
|
ar.size.should == 2
|
89
89
|
end
|
90
90
|
|
@@ -100,34 +100,44 @@ describe Rubabel::Molecule do
|
|
100
100
|
mol.num_atoms(true).should == 11
|
101
101
|
end
|
102
102
|
|
103
|
-
describe 'adding
|
104
|
-
|
103
|
+
describe 'adding or associating atoms' do
|
104
|
+
|
105
|
+
it 'can associate atoms with the molecule' do
|
105
106
|
mol = Rubabel["CCO"]
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
107
|
+
nitrogen = mol.associate_atom!(:N)
|
108
|
+
nitrogen.el.should == :N
|
109
|
+
oxygen = mol.associate_atom!(8)
|
110
|
+
oxygen.el.should == :O
|
110
111
|
mol.csmiles.should == "CCO.N.O"
|
112
|
+
|
113
|
+
oxygen_aromatic = mol.associate_atom!(:O)
|
114
|
+
mol.csmiles.should == "CCO.N.O.O"
|
111
115
|
end
|
112
116
|
|
113
|
-
it "can be added and attached by
|
117
|
+
it "can be added and attached by element symbol or atomic number" do
|
114
118
|
mol = Rubabel["CCO"]
|
115
119
|
first_carbon = mol[0]
|
116
|
-
mol.add_atom!(:
|
120
|
+
mol.add_atom!(:N, 1, first_carbon)
|
117
121
|
mol.csmiles.should == "NCCO"
|
118
122
|
|
119
|
-
mol.add_atom!(16, first_carbon)
|
123
|
+
mol.add_atom!(16, 1, first_carbon)
|
120
124
|
mol.csmiles.should == "NC(CO)S"
|
121
125
|
end
|
122
126
|
|
123
127
|
end
|
124
|
-
|
125
|
-
specify '#<< adds atom to the last atom and returns the
|
128
|
+
|
129
|
+
specify '#<< adds atom to the last atom and returns the added atom' do
|
126
130
|
mol = Rubabel::Molecule.new
|
131
|
+
reply = (mol << :N)
|
127
132
|
# by element symbol or atomic number
|
128
|
-
reply = (mol << :
|
129
|
-
reply.should be_a(Rubabel::
|
130
|
-
reply.
|
133
|
+
reply = (mol << :N << :C)
|
134
|
+
reply.should be_a(Rubabel::Atom)
|
135
|
+
reply.el.should == :C
|
136
|
+
|
137
|
+
# properly handles aromaticity
|
138
|
+
mol.atoms.last.aromatic?.should be_false
|
139
|
+
mol << :c # aromatic specifier in SMILES
|
140
|
+
mol.atoms.last.aromatic?.should be_true
|
131
141
|
end
|
132
142
|
|
133
143
|
specify '#dup duplicates the molecule' do
|
@@ -143,7 +153,7 @@ describe Rubabel::Molecule do
|
|
143
153
|
describe '#add_bond! adds a bond (and updates atoms)' do
|
144
154
|
specify 'given two atoms' do
|
145
155
|
mol = Rubabel["CCO"]
|
146
|
-
atom = mol.
|
156
|
+
atom = mol.associate_atom!(0)
|
147
157
|
mol.add_bond!(mol[1], atom)
|
148
158
|
mol.csmiles.should == '*C(O)C'
|
149
159
|
end
|
@@ -151,7 +161,7 @@ describe Rubabel::Molecule do
|
|
151
161
|
|
152
162
|
specify '#atom(id) retrieves atom by id num' do
|
153
163
|
mol = Rubabel["CCO"]
|
154
|
-
o = mol.find {|a| a.el == :
|
164
|
+
o = mol.find {|a| a.el == :O }
|
155
165
|
mol.atom(o.id).id.should == o.id
|
156
166
|
end
|
157
167
|
|
@@ -160,7 +170,7 @@ describe Rubabel::Molecule do
|
|
160
170
|
carboxy_carbon = mol.atoms.find {|atom| atom.type == 'Cac' }
|
161
171
|
single_bonded_oxygen = mol.atoms.find {|atom| atom.type == 'O.co2' && atom.get_bond(carboxy_carbon).bond_order == 1 }
|
162
172
|
nit_carbon = mol.atoms.find {|atom| atom.atoms.any? {|nbr| nbr.type == 'N3' } }
|
163
|
-
nitrogen = mol.atoms.find {|atom| atom.el == :
|
173
|
+
nitrogen = mol.atoms.find {|atom| atom.el == :N }
|
164
174
|
swapped = mol.swap!(nit_carbon, nitrogen, carboxy_carbon, single_bonded_oxygen)
|
165
175
|
swapped.should == mol
|
166
176
|
swapped.csmiles.should == 'NC(=O)CO'
|
@@ -315,7 +325,7 @@ describe Rubabel::Molecule do
|
|
315
325
|
describe 'breaking a molecule' do
|
316
326
|
before(:each) do
|
317
327
|
@mol = Rubabel::Molecule.from_string("NC(=O)CO")
|
318
|
-
@n = @mol.find {|a| a.el == :
|
328
|
+
@n = @mol.find {|a| a.el == :N }
|
319
329
|
end
|
320
330
|
|
321
331
|
it 'num_atoms, atoms and each_atom are sensitive to #add_h!' do
|
data/spec/spec_helper.rb
CHANGED
@@ -5,14 +5,14 @@ require 'rspec/core/formatters/progress_formatter'
|
|
5
5
|
# doesn't say so much about pending guys
|
6
6
|
class QuietPendingFormatter < RSpec::Core::Formatters::ProgressFormatter
|
7
7
|
def example_pending(example)
|
8
|
-
output.print
|
8
|
+
output.print pending_color('*')
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
12
12
|
require 'rspec/core/formatters/documentation_formatter'
|
13
13
|
class QuietPendingDocFormatter < RSpec::Core::Formatters::DocumentationFormatter
|
14
14
|
def example_pending(example)
|
15
|
-
output.puts
|
15
|
+
output.puts pending_color( "<pending>: #{example.execution_result[:pending_message]}" )
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubabel
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2013-03-21 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: openbabel
|
@@ -66,7 +66,7 @@ dependencies:
|
|
66
66
|
requirements:
|
67
67
|
- - ~>
|
68
68
|
- !ruby/object:Gem::Version
|
69
|
-
version: 2.
|
69
|
+
version: 2.13.0
|
70
70
|
type: :development
|
71
71
|
prerelease: false
|
72
72
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -74,7 +74,7 @@ dependencies:
|
|
74
74
|
requirements:
|
75
75
|
- - ~>
|
76
76
|
- !ruby/object:Gem::Version
|
77
|
-
version: 2.
|
77
|
+
version: 2.13.0
|
78
78
|
- !ruby/object:Gem::Dependency
|
79
79
|
name: rdoc
|
80
80
|
requirement: !ruby/object:Gem::Requirement
|