chemruby 0.9.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (241) hide show
  1. data/README +120 -0
  2. data/Rakefile +195 -0
  3. data/ext/extconf.rb +4 -0
  4. data/ext/subcomp.c +416 -0
  5. data/lib/chem.rb +130 -0
  6. data/lib/chem/appl.rb +1 -0
  7. data/lib/chem/appl/chem3dole.rb +36 -0
  8. data/lib/chem/appl/tinker/nucleic.rb +40 -0
  9. data/lib/chem/appl/tinker/tinker_reader.rb +43 -0
  10. data/lib/chem/data.rb +4 -0
  11. data/lib/chem/data/atomic_weight.rb +124 -0
  12. data/lib/chem/data/character.rb +2 -0
  13. data/lib/chem/data/electronegativity.rb +14 -0
  14. data/lib/chem/data/periodic_table.rb +6 -0
  15. data/lib/chem/data/prime_numbers.rb +1 -0
  16. data/lib/chem/data/vdw_radii.rb +1 -0
  17. data/lib/chem/db.rb +64 -0
  18. data/lib/chem/db/cansmi.rb +234 -0
  19. data/lib/chem/db/cdx.rb +1525 -0
  20. data/lib/chem/db/eps.rb +164 -0
  21. data/lib/chem/db/g98.rb +909 -0
  22. data/lib/chem/db/gspan.rb +130 -0
  23. data/lib/chem/db/iupac.rb +5 -0
  24. data/lib/chem/db/iupac/a_1.rb +46 -0
  25. data/lib/chem/db/iupac/iuparser.rb +226 -0
  26. data/lib/chem/db/iupac/iuparser.ry +97 -0
  27. data/lib/chem/db/iupac/postfix.rb +2 -0
  28. data/lib/chem/db/kcf.rb +390 -0
  29. data/lib/chem/db/kcf_glycan.rb +19 -0
  30. data/lib/chem/db/kegg.rb +516 -0
  31. data/lib/chem/db/linucs/linparser.rb +144 -0
  32. data/lib/chem/db/linucs/linucs.ry +53 -0
  33. data/lib/chem/db/mdl.rb +379 -0
  34. data/lib/chem/db/molconnz.rb +12 -0
  35. data/lib/chem/db/mopac.rb +88 -0
  36. data/lib/chem/db/msi.rb +107 -0
  37. data/lib/chem/db/pdb_dic.rb +115 -0
  38. data/lib/chem/db/pdf.rb +131 -0
  39. data/lib/chem/db/pubchem.rb +113 -0
  40. data/lib/chem/db/rmagick.rb +70 -0
  41. data/lib/chem/db/sdf.rb +37 -0
  42. data/lib/chem/db/smbl.rb +88 -0
  43. data/lib/chem/db/smiles.rb +2 -0
  44. data/lib/chem/db/smiles/smiles.ry +203 -0
  45. data/lib/chem/db/smiles/smiparser.rb +375 -0
  46. data/lib/chem/db/swf.rb +74 -0
  47. data/lib/chem/db/sybyl.rb +150 -0
  48. data/lib/chem/db/tinker.rb +77 -0
  49. data/lib/chem/db/types/type_cansmi.rb +9 -0
  50. data/lib/chem/db/types/type_cdx.rb +24 -0
  51. data/lib/chem/db/types/type_gspan.rb +31 -0
  52. data/lib/chem/db/types/type_kcf.rb +28 -0
  53. data/lib/chem/db/types/type_kcf_glycan.rb +26 -0
  54. data/lib/chem/db/types/type_kegg.rb +92 -0
  55. data/lib/chem/db/types/type_mdl.rb +31 -0
  56. data/lib/chem/db/types/type_pdf.rb +33 -0
  57. data/lib/chem/db/types/type_png.rb +31 -0
  58. data/lib/chem/db/types/type_rxn.rb +25 -0
  59. data/lib/chem/db/types/type_sdf.rb +25 -0
  60. data/lib/chem/db/types/type_sybyl.rb +30 -0
  61. data/lib/chem/db/types/type_xyz.rb +26 -0
  62. data/lib/chem/db/vector.rb +128 -0
  63. data/lib/chem/db/xyz.rb +39 -0
  64. data/lib/chem/model.rb +119 -0
  65. data/lib/chem/model/skeleton.rb +37 -0
  66. data/lib/chem/utils.rb +11 -0
  67. data/lib/chem/utils/geometry.rb +27 -0
  68. data/lib/chem/utils/graph_db.rb +146 -0
  69. data/lib/chem/utils/math.rb +17 -0
  70. data/lib/chem/utils/prop.rb +123 -0
  71. data/lib/chem/utils/sssr.rb +101 -0
  72. data/lib/chem/utils/sub.rb +78 -0
  73. data/lib/chem/utils/transform.rb +110 -0
  74. data/lib/chem/utils/traverse.rb +37 -0
  75. data/lib/chem/utils/ullmann.rb +134 -0
  76. data/lib/graph.rb +41 -0
  77. data/lib/graph/cluster.rb +20 -0
  78. data/lib/graph/morgan.rb +38 -0
  79. data/sample/frequent_subgraph.rb +46 -0
  80. data/sample/images/ex1.rb +11 -0
  81. data/sample/images/ex2.rb +4 -0
  82. data/sample/images/ex3.rb +5 -0
  83. data/sample/images/ex4.rb +17 -0
  84. data/sample/images/ex5.rb +10 -0
  85. data/sample/images/mol/adenine.mol +26 -0
  86. data/sample/images/mol/atp.mol +69 -0
  87. data/sample/images/temp/ex5.mol +344 -0
  88. data/sample/kegg_db.rb +116 -0
  89. data/setup.rb +1551 -0
  90. data/test/all.rb +6 -0
  91. data/test/coord_test.rb +17 -0
  92. data/test/ctab_test.rb +31 -0
  93. data/test/data/A_21.tar.gz +0 -0
  94. data/test/data/A_21/aceanthrylene.cdx +0 -0
  95. data/test/data/A_21/aceanthrylene.mol +40 -0
  96. data/test/data/A_21/acenaphthylene.cdx +0 -0
  97. data/test/data/A_21/acenaphthylene.mol +31 -0
  98. data/test/data/A_21/acephenanthrylene.cdx +0 -0
  99. data/test/data/A_21/acephenanthrylene.mol +40 -0
  100. data/test/data/A_21/anthracene.cdx +0 -0
  101. data/test/data/A_21/anthracene.mol +35 -0
  102. data/test/data/A_21/as-indacene.cdx +0 -0
  103. data/test/data/A_21/as-indacene.mol +31 -0
  104. data/test/data/A_21/azulene.cdx +0 -0
  105. data/test/data/A_21/azulene.mol +26 -0
  106. data/test/data/A_21/biphenylene.cdx +0 -0
  107. data/test/data/A_21/biphenylene.mol +31 -0
  108. data/test/data/A_21/chrysene.cdx +0 -0
  109. data/test/data/A_21/chrysene.mol +44 -0
  110. data/test/data/A_21/coronen.cdx +0 -0
  111. data/test/data/A_21/coronen.mol +59 -0
  112. data/test/data/A_21/fluoranthene.cdx +0 -0
  113. data/test/data/A_21/fluoranthene.mol +40 -0
  114. data/test/data/A_21/fluorene.cdx +0 -0
  115. data/test/data/A_21/fluorene.mol +33 -0
  116. data/test/data/A_21/heptacene.cdx +0 -0
  117. data/test/data/A_21/heptacene.mol +71 -0
  118. data/test/data/A_21/heptalene.cdx +0 -0
  119. data/test/data/A_21/heptalene.mol +30 -0
  120. data/test/data/A_21/heptaphene.cdx +0 -0
  121. data/test/data/A_21/heptaphene.mol +71 -0
  122. data/test/data/A_21/hexacene.cdx +0 -0
  123. data/test/data/A_21/hexacene.mol +62 -0
  124. data/test/data/A_21/hexaphene.cdx +0 -0
  125. data/test/data/A_21/hexaphene.mol +62 -0
  126. data/test/data/A_21/indene.cdx +0 -0
  127. data/test/data/A_21/indene.mol +24 -0
  128. data/test/data/A_21/iupac.txt +41 -0
  129. data/test/data/A_21/naphthacene.cdx +0 -0
  130. data/test/data/A_21/naphthacene.mol +44 -0
  131. data/test/data/A_21/naphthalene.cdx +0 -0
  132. data/test/data/A_21/naphthalene.mol +26 -0
  133. data/test/data/A_21/ovalene.cdx +0 -0
  134. data/test/data/A_21/ovalene.mol +78 -0
  135. data/test/data/A_21/pentacene.cdx +0 -0
  136. data/test/data/A_21/pentacene.mol +53 -0
  137. data/test/data/A_21/pentalene.cdx +0 -0
  138. data/test/data/A_21/pentalene.mol +22 -0
  139. data/test/data/A_21/pentaphene.cdx +0 -0
  140. data/test/data/A_21/pentaphene.mol +53 -0
  141. data/test/data/A_21/perylene.cdx +0 -0
  142. data/test/data/A_21/perylene.mol +49 -0
  143. data/test/data/A_21/phenalene.cdx +0 -0
  144. data/test/data/A_21/phenalene.mol +33 -0
  145. data/test/data/A_21/phenanthrene.cdx +0 -0
  146. data/test/data/A_21/phenanthrene.mol +35 -0
  147. data/test/data/A_21/picene.cdx +0 -0
  148. data/test/data/A_21/picene.mol +53 -0
  149. data/test/data/A_21/pleiadene.cdx +0 -0
  150. data/test/data/A_21/pleiadene.mol +44 -0
  151. data/test/data/A_21/pyranthrene.cdx +0 -0
  152. data/test/data/A_21/pyranthrene.mol +72 -0
  153. data/test/data/A_21/pyrene.cdx +0 -0
  154. data/test/data/A_21/pyrene.mol +40 -0
  155. data/test/data/A_21/rubicene.cdx +0 -0
  156. data/test/data/A_21/rubicene.mol +63 -0
  157. data/test/data/A_21/s-indacene.cdx +0 -0
  158. data/test/data/A_21/s-indacene.mol +31 -0
  159. data/test/data/A_21/tetraphenylene.cdx +0 -0
  160. data/test/data/A_21/tetraphenylene.mol +57 -0
  161. data/test/data/A_21/trinaphthylene.cdx +0 -0
  162. data/test/data/A_21/trinaphthylene.mol +71 -0
  163. data/test/data/A_21/triphenylene.cdx +0 -0
  164. data/test/data/A_21/triphenylene.mol +44 -0
  165. data/test/data/C00147.kcf +25 -0
  166. data/test/data/G00147.kcf +13 -0
  167. data/test/data/atp.mol +69 -0
  168. data/test/data/cyclohexane.mol +17 -0
  169. data/test/data/cyclohexane.ps +485 -0
  170. data/test/data/fullerene.mol +155 -0
  171. data/test/data/glycan +33 -0
  172. data/test/data/hypericin.cdx +0 -0
  173. data/test/data/hypericin.cdxml +596 -0
  174. data/test/data/hypericin.chm +0 -0
  175. data/test/data/hypericin.ct +85 -0
  176. data/test/data/hypericin.f1d +0 -0
  177. data/test/data/hypericin.f1q +0 -0
  178. data/test/data/hypericin.gif +0 -0
  179. data/test/data/hypericin.mol +88 -0
  180. data/test/data/hypericin.mol2 +159 -0
  181. data/test/data/hypericin.msm +123 -0
  182. data/test/data/hypericin.pdf +359 -0
  183. data/test/data/hypericin.png +0 -0
  184. data/test/data/hypericin.ps +0 -0
  185. data/test/data/hypericin.skc +0 -0
  186. data/test/data/hypericin2.gif +0 -0
  187. data/test/data/hypericin2.ps +0 -0
  188. data/test/data/kegg/genomes/hsa/hsa_enzyme.list +4 -0
  189. data/test/data/kegg/genomes/hsa/hsa_pfam.list +4 -0
  190. data/test/data/kegg/ligand/mol/C00147.mol +26 -0
  191. data/test/data/kegg/ligand/reaction +14 -0
  192. data/test/data/kegg/ligand/reaction.lst +1 -0
  193. data/test/data/kegg/ligand/reaction_mapformula.lst +3 -0
  194. data/test/data/reaction +14 -0
  195. data/test/data/reaction.lst +1 -0
  196. data/test/data/reaction_mapformula.lst +3 -0
  197. data/test/data/rxn/C00001.mol +6 -0
  198. data/test/data/rxn/C00011.mol +10 -0
  199. data/test/data/rxn/C00014.mol +6 -0
  200. data/test/data/rxn/C01010.mol +18 -0
  201. data/test/data/rxn/sample.rxn +50 -0
  202. data/test/data/rxn/substitution.rxn +45 -0
  203. data/test/data/test.eps +0 -0
  204. data/test/data/test.mol +28 -0
  205. data/test/data/test.sdf +143 -0
  206. data/test/data/test.skc +0 -0
  207. data/test/data/test.xyz +4 -0
  208. data/test/data/test_lf.sdf +143 -0
  209. data/test/heavy_test_pubchem.rb +16 -0
  210. data/test/multiple_test.rb +22 -0
  211. data/test/test_adj.rb +54 -0
  212. data/test/test_canonical_smiles.rb +46 -0
  213. data/test/test_cdx.rb +32 -0
  214. data/test/test_chem.rb +18 -0
  215. data/test/test_cluster.rb +19 -0
  216. data/test/test_db.rb +11 -0
  217. data/test/test_eps.rb +24 -0
  218. data/test/test_geometry.rb +11 -0
  219. data/test/test_gspan.rb +28 -0
  220. data/test/test_iupac.rb +36 -0
  221. data/test/test_kcf.rb +24 -0
  222. data/test/test_kcf_glycan.rb +10 -0
  223. data/test/test_kegg.rb +118 -0
  224. data/test/test_linucs.rb +21 -0
  225. data/test/test_mdl.rb +45 -0
  226. data/test/test_mol2.rb +62 -0
  227. data/test/test_morgan.rb +21 -0
  228. data/test/test_pdf.rb +12 -0
  229. data/test/test_prop.rb +86 -0
  230. data/test/test_rmagick.rb +15 -0
  231. data/test/test_sbdb.rb +23 -0
  232. data/test/test_sdf.rb +30 -0
  233. data/test/test_smiles.rb +84 -0
  234. data/test/test_sssr.rb +18 -0
  235. data/test/test_sub.rb +47 -0
  236. data/test/test_subcomp.rb +37 -0
  237. data/test/test_traverse.rb +29 -0
  238. data/test/test_writer.rb +13 -0
  239. data/test/test_xyz.rb +15 -0
  240. data/test/type_test.rb +25 -0
  241. metadata +290 -0
@@ -0,0 +1,17 @@
1
+
2
+ require 'matrix'
3
+
4
+ class Vector
5
+
6
+ def []=(i,x) ; @elements[i]=x ; end
7
+
8
+ def x ; @elements[0] ; end
9
+ def y ; @elements[1] ; end
10
+ def z ; @elements[2] ; end
11
+
12
+ def x= x_val ; @elements[0] = x_val ; end
13
+ def y= y_val ; @elements[1] = y_val ; end
14
+ def z= z_val ; @elements[2] = z_val ; end
15
+
16
+ end
17
+
@@ -0,0 +1,123 @@
1
+ #
2
+ # module for calculating properties
3
+ #
4
+
5
+ module Chem
6
+
7
+ module Atom
8
+
9
+ # Returns electro negativity
10
+ # see chem/data/electronegativity.rb
11
+ def electro_negativity
12
+ ElectroNegativity[self.element]
13
+ end
14
+
15
+ # Returns Natural Bond Order of this atom
16
+ # :C => 4, :H => 1...
17
+ # see chem/data/character.rb
18
+ def natural_bond_order
19
+ NaturalBondOrder[self.element]
20
+ end
21
+
22
+ # Returns Atomic weight
23
+ # see chem/data/atomic_weight.rb
24
+ def weight
25
+ AtomicWeight[self.element]
26
+ end
27
+
28
+ end
29
+
30
+ module Molecule
31
+
32
+ # Returns number of hydrogen
33
+ # this method may be overrided
34
+ def n_hydrogen node
35
+ n_h = node.natural_bond_order
36
+ adjacent_to(node).each do |bond, atom|
37
+ n_h -= bond.v
38
+ end
39
+ n_h
40
+ end
41
+
42
+ # Returns molecular weight
43
+ # mol.molecular_weight :unknown_atom => true
44
+ def molecular_weight prop = {}
45
+ comp = self.composition()
46
+ comp.inject(0.0){|ret, (el, n)|
47
+ if AtomicWeight[el]
48
+ ret + AtomicWeight[el] * n
49
+ elsif prop[:neglect_unknown_atom]
50
+ ret
51
+ else
52
+ return nil
53
+ end
54
+ }
55
+ end
56
+
57
+ alias mw molecular_weight
58
+
59
+ # Returns oxidation number of node
60
+ # this method can be moved to Atom module
61
+ def oxidation_number node
62
+ en = 0
63
+ adjacent_to(node).each do |bond, atom|
64
+ case node.electro_negativity <=> atom.electro_negativity
65
+ when -1
66
+ en += bond.v
67
+ when 1
68
+ en -= bond.v
69
+ end
70
+ end
71
+ # implicit hydrogen
72
+ if ElectroNegativity[:H] < node.electro_negativity
73
+ en -= n_hydrogen(node)
74
+ else
75
+ en += n_hydrogen(node)
76
+ end
77
+ en
78
+ end
79
+
80
+ # Returns composition
81
+ # Chem.open_mol("benzene").composition # {:C => 6, :H => 6}
82
+ def composition
83
+
84
+ composition = {}
85
+ @nodes.each do |atom|
86
+ composition[atom.element] ||= 0
87
+ composition[atom.element] += 1
88
+ end
89
+ composition
90
+ end
91
+
92
+ # return 1 if self.composition > to.composition
93
+ # return 0 if self.composition == to.composition
94
+ # return -1 if self.composition < to.composition
95
+ # return false if self.composition <> to.composition
96
+ def subset_in_composition?(to)
97
+ self_is_sub = false
98
+ to_is_sub = false
99
+ all = (to.composition.keys + composition.keys).uniq
100
+ return false if all.length == 0
101
+ if (all - composition.keys).length > 0 && (all - to.composition.keys).length > 0
102
+ return false
103
+ elsif (all - composition.keys).length > 0
104
+ return -1 if composition.all?{|k, v| v <= to.composition[k]}
105
+ return false
106
+ elsif (all - to.composition.keys).length > 0
107
+ return 1 if to.composition.all?{|k, v| v <= composition[k]}
108
+ return false
109
+ elsif all.length == composition.keys.length && all.length == to.composition.length
110
+ # then compare number of nodes ?
111
+ if all.all? { |node| composition[node] == to.composition[node]}
112
+ return 0
113
+ elsif all.all?{ |node| composition[node] >= to.composition[node]}
114
+ return 1
115
+ elsif all.all?{ |node| composition[node] <= to.composition[node]}
116
+ return -1
117
+ end
118
+ end
119
+ return false
120
+ end
121
+
122
+ end
123
+ end
@@ -0,0 +1,101 @@
1
+ #!/usr/bin/ruby
2
+
3
+ module Chem
4
+ class Ring
5
+ end
6
+
7
+ module Molecule
8
+ # J. Chem. Inf. Comput. Sci. 1996, 36, 986-991
9
+ # John Figueras
10
+ # Ring Perception Using Breadth-First Search
11
+
12
+ # J. Chem. Inf. Comput. Sci. 1994, 34, 822-831
13
+ # Renzo Balducci and Robert S. Pearlman
14
+ # Efficient Exact Solution of the Ring Perception Problem
15
+ #
16
+
17
+ def find_smallest_ring root
18
+ path = {}
19
+ path[root] = [root]
20
+
21
+ bfs(root) do |from, to|
22
+ if visit = !path.keys.include?(to)
23
+ path[to] = path[from].clone
24
+ path[to].push(to)
25
+ elsif path[from][-2] != to
26
+ if 1 == (path[from] & path[to]).length
27
+ return path[from] + path[to][1..-1].reverse
28
+ end
29
+ end
30
+ visit
31
+ end
32
+ end
33
+
34
+ def canonical_ring ring
35
+ # ring.sort # Fix me! This is not sufficient
36
+ ring.sort{|a, b| @atoms.index(a) <=> @atoms.index(b)}
37
+ end
38
+
39
+ def find_sssr
40
+ return @sssr if @sssr
41
+ fullSet = []
42
+ trimSet = []
43
+ rings = []
44
+ @mol = {}
45
+ # mol = {1=>[2, 5], 2=> [1, 3], 3=> [2, 4], 4=>[3, 5], 5=>[4,1]}
46
+ # @nodes.each do |k, atom|
47
+ # atom.set_neighbor
48
+ # @mol[atom] = atom.neighbor
49
+ # end
50
+
51
+ loop do
52
+ nodesN2 = []
53
+ smallest_degree = 10
54
+ smallest = nil
55
+ @mol.each do |k, a|
56
+ case a.length
57
+ when 0
58
+ @mol.delete(k)# Is this OK?
59
+ trimSet.push(k)
60
+ when 2
61
+ nodesN2.push(k)
62
+ end
63
+ if a.length > 0 && a.length < smallest_degree
64
+ smallest = k
65
+ smallest_degree = a.length
66
+ end
67
+ end
68
+ case smallest_degree
69
+ when 1
70
+ trim(smallest)
71
+ when 2
72
+ nodesN2.each do |k|
73
+ ring = find_smallest_ring(k)
74
+ # rings.push(canonical_ring(ring)) if !rings.include?(canonical_ring(ring))
75
+ rings.push(canonical_ring(ring)) if ring && !rings.include?(canonical_ring(ring))
76
+ end
77
+ nodesN2.each do |k|
78
+ trim(k)
79
+ end
80
+ when 3
81
+ ring = find_smallest_ring(smallest)
82
+ trim(smallest)
83
+ end
84
+ break if @mol.length == 0
85
+ end
86
+ @sssr = rings
87
+ end
88
+
89
+ def trim smallest
90
+ if @mol.length > 0 && @mol.include?(smallest)
91
+ @mol[smallest].each do |n|
92
+ @mol[n] = @mol[n] - [smallest]
93
+ @mol.delete(smallest)
94
+ @mol.delete(n) if @mol[n].length == 0
95
+ end
96
+ end
97
+ end
98
+
99
+ end
100
+ end
101
+
@@ -0,0 +1,78 @@
1
+
2
+ module Chem
3
+ module Molecule
4
+
5
+ def induced_sub ary
6
+ sub = deep_dup
7
+ (sub.nodes - ary).each do |node|
8
+ sub.delete(node)
9
+ end
10
+ sub
11
+ end
12
+
13
+ def connected?
14
+ traversed = []
15
+ start = @nodes[0]
16
+ traversed << start
17
+ dfs(start) do |from, to|
18
+ traversed << to
19
+ end
20
+ traversed.length == @nodes.length
21
+ end
22
+
23
+ # divide compounds by connectivity
24
+ # e.g. washing salts.
25
+ def divide
26
+ traversed = []
27
+ start = @nodes[0]
28
+ divided_compound = []
29
+
30
+ while traversed.length != @nodes.length
31
+ part = []
32
+ traversed << start
33
+ part << start
34
+ dfs(start) do |from, to, bond|
35
+ unless part.include?(to)
36
+ traversed << to
37
+ part << to
38
+ end
39
+ end
40
+
41
+ start = @nodes.find{|node| !traversed.include?(node)}
42
+ divided_compound << induced_sub(part)
43
+ end
44
+ divided_compound
45
+ end
46
+
47
+ def delete_bond(bond)
48
+ @edges.delete(bond)
49
+ @adjacencies.each do |v, k|
50
+ k.delete_if{ |b, atom_a, atom_b| bond == b}
51
+ end
52
+ end
53
+
54
+ def delete(atom)
55
+ @nodes.delete(atom)
56
+ adjacent_to(atom).each do |adj_edge, adj_node|
57
+ @edges.delete_if{|bond, atom_a, atom_b| bond == adj_edge}
58
+ end
59
+ end
60
+
61
+ def deep_dup
62
+ ret = dup
63
+ ret.nodes = @nodes.dup
64
+ #ret.adjacencies = @adjacencies.dup if @adjacencies
65
+ ret.edges = @edges.dup
66
+ ret
67
+ end
68
+
69
+ def - (other)
70
+ if other.instance_of?(Array)
71
+ induced_sub(@nodes - other)
72
+ else
73
+ induced_sub(@nodes - other.nodes)
74
+ end
75
+ end
76
+
77
+ end
78
+ end
@@ -0,0 +1,110 @@
1
+ #!/usr/local/bin/ruby
2
+
3
+ require 'matrix'
4
+
5
+ module Chem
6
+
7
+ module Transform
8
+
9
+ module TwoDimension
10
+
11
+ def initialize
12
+ super
13
+ @pos = Vector[0.0, 0.0]
14
+ end
15
+
16
+ def pos ; @pos ||= Vector[@x, @y, @z] ; end
17
+ def x ; pos[0] ; end
18
+ def y ; pos[1] ; end
19
+ def x=(x_val) ; pos[0] = x_val ; end
20
+ def y=(y_val) ; pos[1] = y_val ; end
21
+ end
22
+
23
+ module ThreeDimension
24
+ include TwoDimension
25
+
26
+ def initialize
27
+ super
28
+ @pos = Vector[0.0, 0.0]
29
+ end
30
+
31
+ def z ; pos[2] ; end
32
+ def z=(z_val) ; pos[2] = z_val ; end
33
+
34
+ end
35
+
36
+ end
37
+ end
38
+
39
+ class Transform
40
+
41
+ def initialize m = Matrix.new
42
+ @m = m
43
+ end
44
+
45
+ def * (t)
46
+ @m * t
47
+ end
48
+
49
+ def transform(v)
50
+ v * @m
51
+ end
52
+
53
+ def Transform::translate(x, y, z)
54
+ Matrix[[1, 0, 0, 0],
55
+ [0, 1, 0, 0],
56
+ [0, 0, 1, 0],
57
+ [x, y, z, 1]].transpose
58
+ end
59
+
60
+ def Transform::scale(x, y, z)
61
+ Matrix[[x, 0, 0, 0],
62
+ [0, y, 0, 0],
63
+ [0, 0, z, 0],
64
+ [0, 0, 0, 1]].transpose
65
+ end
66
+
67
+ def Transform::rotate_x(theta)
68
+ Matrix[[1.0, 0.0, 0.0, 0.0],
69
+ [0.0, Math.cos(theta), Math.sin(theta), 0.0],
70
+ [0.0, - Math.sin(theta), Math.cos(theta), 0.0],
71
+ [0.0, 0.0, 0.0, 1.0]].transpose
72
+ end
73
+
74
+ def Transform::rotate_y(theta)
75
+ Matrix[[Math.cos(theta), 0.0, - Math.sin(theta), 0.0],
76
+ [0.0, 1.0, 0.0, 0.0],
77
+ [Math.sin(theta), 0.0, Math.cos(theta), 0.0],
78
+ [0.0, 0.0, 0.0, 1.0]].transpose
79
+ end
80
+
81
+ def Transform::rotate_z(theta)
82
+ Matrix[[ Math.cos(theta), Math.sin(theta), 0.0, 0.0],
83
+ [- Math.sin(theta), Math.cos(theta), 0.0, 0.0],
84
+ [ 0.0, 0.0, 1.0, 0.0],
85
+ [ 0.0, 0.0, 0.0, 1.0]].transpose
86
+ end
87
+
88
+ def Transform::inverse_x
89
+ Matrix[[ -1, 0, 0, 0],
90
+ [ 0, 1, 0, 0],
91
+ [ 0, 0, -1, 0],
92
+ [ 0, 0, 0, 1]].transpose
93
+ end
94
+
95
+ def Transform::inverse_y
96
+ Matrix[[ 1, 0, 0, 0],
97
+ [ 0, -1, 0, 0],
98
+ [ 0, 0, 1, 0],
99
+ [ 0, 0, 0, 1]].transpose
100
+ end
101
+
102
+ def Transform::inverse_z
103
+ Matrix[[ 1, 0, 0, 0],
104
+ [ 0, 1, 0, 0],
105
+ [ 0, 0, -1, 0],
106
+ [ 0, 0, 0, 1]].transpose
107
+ end
108
+
109
+ end
110
+
@@ -0,0 +1,37 @@
1
+
2
+ module Chem
3
+ module Molecule
4
+ # Breadth first search solves steps and path to the each node and forms
5
+ # a tree contains all reachable vertices from the root node.
6
+
7
+ def breadth_first_search(root = @nodes[0])
8
+
9
+ queue = [ root ]
10
+
11
+ traversed = []
12
+
13
+ while from = queue.shift
14
+ adjacent_to(from).each do |bond, to|
15
+ next if traversed.include?(bond)
16
+ traversed.push(bond)
17
+ queue.push(to) if yield(from, to)
18
+ end
19
+ end
20
+ end
21
+
22
+ alias :bfs :breadth_first_search
23
+
24
+ def depth_first_search(from = @nodes[0], traversed = [], &block)
25
+ adjacent_to(from).each do |bond, to|
26
+ next if traversed.include?(bond)
27
+ traversed.push(bond)
28
+ yield(from, to, bond)
29
+ depth_first_search(to, traversed, &block)
30
+ end
31
+ end
32
+
33
+ alias :dfs :depth_first_search
34
+
35
+ end
36
+ end
37
+