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 CHANGED
@@ -1,8 +1,8 @@
1
1
  # rubabel
2
2
 
3
- Ruby interface to the openbabel ruby bindings (or the openbabel gem). 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
- require 'rubabel'
15
+ ```ruby
16
+ require 'rubabel'
16
17
 
17
- # by default, reads in smiles strings
18
- serine = Rubabel["C(C(C(=O)O)N)O"]
19
- # more formally:
20
- serine = Rubabel::Molecule.from_string("C(C(C(=O)O)N)O")
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
- # also any other format openbabel supports, for example inchi
23
- serine = Rubabel["InChI=1S/C3H7NO3/c4-2(1-5)3(6)7/h2,5H,1,4H2,(H,6,7)", :inchi]
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
- # from the internet:
26
- mol = Rubabel[some_molecule, Rubabel.format_from_mime(some_mime_type)]
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
- hash = Rubabel.in_formats
31
- hash = Rubabel.out_formats
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
- Rubabel.foreach("file.sdf") do |mol|
38
- puts mol.exact_mass
39
- end
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
- # return an array of every unique atom type in the file
44
- uniq_atom_types = Rubabel.foreach("file.mol").flat_map {|mol| mol.map(&:type) }.uniq
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
- mol = Rubabel::Molecule.from_file("file.sdf")
49
- # handles gzipped files seamlessly:
50
- mol = Rubabel::Molecule.from_file("file.sdf.gz")
51
- mol = Rubabel.molecule_from_file("file.sdf") # alternative
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
- # explicit format for uninformative/wrong extensions:
54
- mol = Rubabel::Molecule.from_file("file", :sdf)
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
- mol = Rubabel["OCC"] # ethanol
68
+ ```ruby
69
+ mol = Rubabel["OCC"] # ethanol
61
70
 
62
- mol.to_s # canonical smiles -> "CCO"
63
- mol.csmiles # same thing
71
+ mol.to_s # canonical smiles -> "CCO"
72
+ mol.csmiles # same thing
64
73
 
65
- mol.to_s(:smi) # smiles -> "OCC"
66
- mol.smiles # same thing
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
- can_smiles_string = mol.write_string # -> "CCO\t\n"
71
- mol.title = "ethanol"
72
- can_smiles_string = mol.write(:can) # -> "CCO\tethanol\n"
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
- pdb_string = mol.write(:pdb)
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
- # write to a smiles file
81
- mol.write("file.smi")
82
- mol.write_file("file.smi")
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
- File.open("somefile.pdb", 'w') do |out|
87
- molecules.each {|mol| out.print mol.write(:pdb) }
88
- end
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
- mol = Rubabel["NCC(O)C(=O)O"]
96
- mol.write("file.svg")
113
+ ```ruby
114
+ mol = Rubabel["NCC(O)C(=O)O"]
115
+ mol.write("file.svg")
97
116
 
98
- # must have imagemagick ('convert' command) and mini_magick gem installed
99
- mol.write("file.png")
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
- mol = Rubabel["NCC(O)C(=O)O"]
107
- mol.each_match("CO") do |match|
108
- # match is just an array of atoms that matched
109
- match.first.el # => :c
110
- match.last.el # => :o
111
- end
112
-
113
- # matches returns all the matches in an array
114
- all_matches = mol.matches("CO")
115
- # all the match routines take a boolean to alter uniqueness
116
- all_matches = mol.matches("CO", false) # some matches may not be uniq
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
- bonds = mol.matches("CO").map {|c, o| c.get_bond(o) }
121
- mol.split(*bonds) # splits between every carbon single bonded to oxygen
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
- mol = Rubabel["OCC"]
128
- # adds a carbon, then an oxygen to last indexed atom by atomic number
129
- mol << 6 << 8 # #<Mol "OCCCO">
130
- mol << :c << :o # same thing
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
- # add an ethyl group specifically to second carbon
133
- mol = Rubabel["OCC"]
134
- mol[1] << :c << :c
157
+ # add an ethyl group specifically to second atom (the first carbon)
158
+ mol = Rubabel["OCC"]
159
+ mol[1] << :C << :C
135
160
 
136
- # add a vinyl group to second carbon (use method notation and parenthesis
137
- # because we are going to specify 2 arguments (the bond order):
138
- ( mol[1] << :c).<<(:c, 2)
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
- # delete an atom:
143
- mol = Rubabel["NCO"]
144
- mol.delete(mol[0]) # -> #<Mol CO>
168
+ ```ruby
169
+ # delete an atom:
170
+ mol = Rubabel["NCO"]
171
+ mol.delete(mol[0])
172
+ # mol.to_s -> #<Mol CO>
145
173
 
146
- # delete a bond:
147
- bond = mol[0].get_bond(mol[1])
148
- mol.delete(bond) # -> #<Mol C.O>
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 add or subtract from bonds to change bond order:
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
- mol = Rubabel["CC"]
155
- mol[0].get_bond(mol[1]) + 1 # now it is a double bond
156
- bond = mol[0].bonds.first
157
- bond - 1
158
- bond.bond_order # => 1
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
- sudo apt-get install openbabel libopenbabel-dev cmake make curl
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
- gem install rubabel
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
- # install the dependencies:
183
- sudo apt-get install libeigen2-dev cmake libwxgtk2.8-dev libxml2-dev libcairo2-dev
184
- # unpack it:
185
- tar -xzvf openbabel-2.3.1.tar.gz
186
- # swap out buggy lines in ruby bindings:
187
- sed -i 's/Init_OpenBabel/Init_openbabel/g' openbabel-2.3.1/scripts/ruby/openbabel-ruby.cpp
188
- # make a separate build directory for building in:
189
- mkdir build-rvmruby1.9.3
190
- cd build-rvmruby1.9.3
191
- mkdir ~/tools
192
- cmake ../openbabel-2.3.1 -DRUBY_BINDINGS=ON -DCMAKE_INSTALL_PREFIX=~/tools/openbabel-rvmruby1.9.3
193
- make && make install
194
-
195
- [[Still need directions to install the gem on top of a build from source]]
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
@@ -23,7 +23,7 @@ interface attempts to be a ruby-ish analogue of pybel.}
23
23
  end
24
24
 
25
25
  [
26
- ["rspec", "~> 2.8.0"],
26
+ ["rspec", "~> 2.13.0"],
27
27
  ["rdoc", "~> 3.12"],
28
28
  ["jeweler", "~> 1.8.3"]
29
29
  ].each do |args|
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.2
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
- # abbreviated name, all lowercase as a Symbol
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
- # creates a bond and adds it to both atoms. Returns the passed in or
81
- # newly created atom.
82
- def add_atom!(arg, bond_order=1)
83
- unless arg.is_a?(Rubabel::Atom)
84
- arg = mol.add_atom!(arg)
85
- end
86
- @ob.get_parent.add_bond(self.ob.get_idx, arg.ob.get_idx, bond_order)
87
- arg
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 == :c && double_bond?
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 self
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
- # do we need to check the bounds here?
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
- # won't decrease below zero. returns self
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
- newval = @ob.get_bond_order - val
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 != :c }
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 == :c }.each do |carbon_nbr|
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
@@ -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, attach_to=nil, bond_order=1)
115
- if attach_to
116
- attach_to.add_atom!(arg, bond_order)
117
- else
118
- if arg.is_a?(Rubabel::Atom)
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 strings
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
- # atomic number to lowercase symbol abbreviation
123
- NUM_TO_EL = Hash[ ELEMENTS.each_with_index.map {|el,i| [i+1,el.downcase.to_sym] } ]
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
- EL_TO_NUM = NUM_TO_EL.invert
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 equivalent_pngs(png1, png2)
28
- (png1.size - png2.size < 50) && (png1[0..100] == png2[0..100])
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
- equivalent_pngs(png_out, key_out).should be_true
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
- equivalent_pngs(png_out, key_out)
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.add_bond!(old_a, mol.add_atom!(0))
317
+ mol.add_atom!(0, 1, old_a)
311
318
  end
312
319
  end
313
320
  puts "#{mol.to_s.gsub('.',"\n")}"
@@ -23,6 +23,7 @@ describe Rubabel::Atom do
23
23
  end
24
24
 
25
25
  it 'attaches given an atomic number' do
26
+
26
27
  end
27
28
 
28
29
  it 'attaches given an element symbol' do
@@ -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
- #mol = Rubabel["CCC"]
26
- #p mol.formula
27
- #mol.add_hydrogen_to_formula!
28
- #p mol.formula
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 == :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
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 == :c
87
- ar.last.el.should == :o
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 an atom' do
104
- it 'can be added but not attached' do
103
+ describe 'adding or associating atoms' do
104
+
105
+ it 'can associate atoms with the molecule' do
105
106
  mol = Rubabel["CCO"]
106
- atom = mol.add_atom!(:n)
107
- atom.el.should == :n
108
- atom = mol.add_atom!(8)
109
- atom.el.should == :o
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 el symbol or atomic number" do
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!(:n, first_carbon)
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 mol' do
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 << :n << :c)
129
- reply.should be_a(Rubabel::Molecule)
130
- reply.csmiles.should == 'CN'
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.add_atom!(0)
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 == :o }
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 == :n }
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 == :n }
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 yellow('*')
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 yellow( "<pending>: #{example.execution_result[:pending_message]}" )
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.2.2
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: 2012-10-18 00:00:00.000000000 Z
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.8.0
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.8.0
77
+ version: 2.13.0
78
78
  - !ruby/object:Gem::Dependency
79
79
  name: rdoc
80
80
  requirement: !ruby/object:Gem::Requirement