rubabel 0.2.2 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|