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.
- data/README +120 -0
- data/Rakefile +195 -0
- data/ext/extconf.rb +4 -0
- data/ext/subcomp.c +416 -0
- data/lib/chem.rb +130 -0
- data/lib/chem/appl.rb +1 -0
- data/lib/chem/appl/chem3dole.rb +36 -0
- data/lib/chem/appl/tinker/nucleic.rb +40 -0
- data/lib/chem/appl/tinker/tinker_reader.rb +43 -0
- data/lib/chem/data.rb +4 -0
- data/lib/chem/data/atomic_weight.rb +124 -0
- data/lib/chem/data/character.rb +2 -0
- data/lib/chem/data/electronegativity.rb +14 -0
- data/lib/chem/data/periodic_table.rb +6 -0
- data/lib/chem/data/prime_numbers.rb +1 -0
- data/lib/chem/data/vdw_radii.rb +1 -0
- data/lib/chem/db.rb +64 -0
- data/lib/chem/db/cansmi.rb +234 -0
- data/lib/chem/db/cdx.rb +1525 -0
- data/lib/chem/db/eps.rb +164 -0
- data/lib/chem/db/g98.rb +909 -0
- data/lib/chem/db/gspan.rb +130 -0
- data/lib/chem/db/iupac.rb +5 -0
- data/lib/chem/db/iupac/a_1.rb +46 -0
- data/lib/chem/db/iupac/iuparser.rb +226 -0
- data/lib/chem/db/iupac/iuparser.ry +97 -0
- data/lib/chem/db/iupac/postfix.rb +2 -0
- data/lib/chem/db/kcf.rb +390 -0
- data/lib/chem/db/kcf_glycan.rb +19 -0
- data/lib/chem/db/kegg.rb +516 -0
- data/lib/chem/db/linucs/linparser.rb +144 -0
- data/lib/chem/db/linucs/linucs.ry +53 -0
- data/lib/chem/db/mdl.rb +379 -0
- data/lib/chem/db/molconnz.rb +12 -0
- data/lib/chem/db/mopac.rb +88 -0
- data/lib/chem/db/msi.rb +107 -0
- data/lib/chem/db/pdb_dic.rb +115 -0
- data/lib/chem/db/pdf.rb +131 -0
- data/lib/chem/db/pubchem.rb +113 -0
- data/lib/chem/db/rmagick.rb +70 -0
- data/lib/chem/db/sdf.rb +37 -0
- data/lib/chem/db/smbl.rb +88 -0
- data/lib/chem/db/smiles.rb +2 -0
- data/lib/chem/db/smiles/smiles.ry +203 -0
- data/lib/chem/db/smiles/smiparser.rb +375 -0
- data/lib/chem/db/swf.rb +74 -0
- data/lib/chem/db/sybyl.rb +150 -0
- data/lib/chem/db/tinker.rb +77 -0
- data/lib/chem/db/types/type_cansmi.rb +9 -0
- data/lib/chem/db/types/type_cdx.rb +24 -0
- data/lib/chem/db/types/type_gspan.rb +31 -0
- data/lib/chem/db/types/type_kcf.rb +28 -0
- data/lib/chem/db/types/type_kcf_glycan.rb +26 -0
- data/lib/chem/db/types/type_kegg.rb +92 -0
- data/lib/chem/db/types/type_mdl.rb +31 -0
- data/lib/chem/db/types/type_pdf.rb +33 -0
- data/lib/chem/db/types/type_png.rb +31 -0
- data/lib/chem/db/types/type_rxn.rb +25 -0
- data/lib/chem/db/types/type_sdf.rb +25 -0
- data/lib/chem/db/types/type_sybyl.rb +30 -0
- data/lib/chem/db/types/type_xyz.rb +26 -0
- data/lib/chem/db/vector.rb +128 -0
- data/lib/chem/db/xyz.rb +39 -0
- data/lib/chem/model.rb +119 -0
- data/lib/chem/model/skeleton.rb +37 -0
- data/lib/chem/utils.rb +11 -0
- data/lib/chem/utils/geometry.rb +27 -0
- data/lib/chem/utils/graph_db.rb +146 -0
- data/lib/chem/utils/math.rb +17 -0
- data/lib/chem/utils/prop.rb +123 -0
- data/lib/chem/utils/sssr.rb +101 -0
- data/lib/chem/utils/sub.rb +78 -0
- data/lib/chem/utils/transform.rb +110 -0
- data/lib/chem/utils/traverse.rb +37 -0
- data/lib/chem/utils/ullmann.rb +134 -0
- data/lib/graph.rb +41 -0
- data/lib/graph/cluster.rb +20 -0
- data/lib/graph/morgan.rb +38 -0
- data/sample/frequent_subgraph.rb +46 -0
- data/sample/images/ex1.rb +11 -0
- data/sample/images/ex2.rb +4 -0
- data/sample/images/ex3.rb +5 -0
- data/sample/images/ex4.rb +17 -0
- data/sample/images/ex5.rb +10 -0
- data/sample/images/mol/adenine.mol +26 -0
- data/sample/images/mol/atp.mol +69 -0
- data/sample/images/temp/ex5.mol +344 -0
- data/sample/kegg_db.rb +116 -0
- data/setup.rb +1551 -0
- data/test/all.rb +6 -0
- data/test/coord_test.rb +17 -0
- data/test/ctab_test.rb +31 -0
- data/test/data/A_21.tar.gz +0 -0
- data/test/data/A_21/aceanthrylene.cdx +0 -0
- data/test/data/A_21/aceanthrylene.mol +40 -0
- data/test/data/A_21/acenaphthylene.cdx +0 -0
- data/test/data/A_21/acenaphthylene.mol +31 -0
- data/test/data/A_21/acephenanthrylene.cdx +0 -0
- data/test/data/A_21/acephenanthrylene.mol +40 -0
- data/test/data/A_21/anthracene.cdx +0 -0
- data/test/data/A_21/anthracene.mol +35 -0
- data/test/data/A_21/as-indacene.cdx +0 -0
- data/test/data/A_21/as-indacene.mol +31 -0
- data/test/data/A_21/azulene.cdx +0 -0
- data/test/data/A_21/azulene.mol +26 -0
- data/test/data/A_21/biphenylene.cdx +0 -0
- data/test/data/A_21/biphenylene.mol +31 -0
- data/test/data/A_21/chrysene.cdx +0 -0
- data/test/data/A_21/chrysene.mol +44 -0
- data/test/data/A_21/coronen.cdx +0 -0
- data/test/data/A_21/coronen.mol +59 -0
- data/test/data/A_21/fluoranthene.cdx +0 -0
- data/test/data/A_21/fluoranthene.mol +40 -0
- data/test/data/A_21/fluorene.cdx +0 -0
- data/test/data/A_21/fluorene.mol +33 -0
- data/test/data/A_21/heptacene.cdx +0 -0
- data/test/data/A_21/heptacene.mol +71 -0
- data/test/data/A_21/heptalene.cdx +0 -0
- data/test/data/A_21/heptalene.mol +30 -0
- data/test/data/A_21/heptaphene.cdx +0 -0
- data/test/data/A_21/heptaphene.mol +71 -0
- data/test/data/A_21/hexacene.cdx +0 -0
- data/test/data/A_21/hexacene.mol +62 -0
- data/test/data/A_21/hexaphene.cdx +0 -0
- data/test/data/A_21/hexaphene.mol +62 -0
- data/test/data/A_21/indene.cdx +0 -0
- data/test/data/A_21/indene.mol +24 -0
- data/test/data/A_21/iupac.txt +41 -0
- data/test/data/A_21/naphthacene.cdx +0 -0
- data/test/data/A_21/naphthacene.mol +44 -0
- data/test/data/A_21/naphthalene.cdx +0 -0
- data/test/data/A_21/naphthalene.mol +26 -0
- data/test/data/A_21/ovalene.cdx +0 -0
- data/test/data/A_21/ovalene.mol +78 -0
- data/test/data/A_21/pentacene.cdx +0 -0
- data/test/data/A_21/pentacene.mol +53 -0
- data/test/data/A_21/pentalene.cdx +0 -0
- data/test/data/A_21/pentalene.mol +22 -0
- data/test/data/A_21/pentaphene.cdx +0 -0
- data/test/data/A_21/pentaphene.mol +53 -0
- data/test/data/A_21/perylene.cdx +0 -0
- data/test/data/A_21/perylene.mol +49 -0
- data/test/data/A_21/phenalene.cdx +0 -0
- data/test/data/A_21/phenalene.mol +33 -0
- data/test/data/A_21/phenanthrene.cdx +0 -0
- data/test/data/A_21/phenanthrene.mol +35 -0
- data/test/data/A_21/picene.cdx +0 -0
- data/test/data/A_21/picene.mol +53 -0
- data/test/data/A_21/pleiadene.cdx +0 -0
- data/test/data/A_21/pleiadene.mol +44 -0
- data/test/data/A_21/pyranthrene.cdx +0 -0
- data/test/data/A_21/pyranthrene.mol +72 -0
- data/test/data/A_21/pyrene.cdx +0 -0
- data/test/data/A_21/pyrene.mol +40 -0
- data/test/data/A_21/rubicene.cdx +0 -0
- data/test/data/A_21/rubicene.mol +63 -0
- data/test/data/A_21/s-indacene.cdx +0 -0
- data/test/data/A_21/s-indacene.mol +31 -0
- data/test/data/A_21/tetraphenylene.cdx +0 -0
- data/test/data/A_21/tetraphenylene.mol +57 -0
- data/test/data/A_21/trinaphthylene.cdx +0 -0
- data/test/data/A_21/trinaphthylene.mol +71 -0
- data/test/data/A_21/triphenylene.cdx +0 -0
- data/test/data/A_21/triphenylene.mol +44 -0
- data/test/data/C00147.kcf +25 -0
- data/test/data/G00147.kcf +13 -0
- data/test/data/atp.mol +69 -0
- data/test/data/cyclohexane.mol +17 -0
- data/test/data/cyclohexane.ps +485 -0
- data/test/data/fullerene.mol +155 -0
- data/test/data/glycan +33 -0
- data/test/data/hypericin.cdx +0 -0
- data/test/data/hypericin.cdxml +596 -0
- data/test/data/hypericin.chm +0 -0
- data/test/data/hypericin.ct +85 -0
- data/test/data/hypericin.f1d +0 -0
- data/test/data/hypericin.f1q +0 -0
- data/test/data/hypericin.gif +0 -0
- data/test/data/hypericin.mol +88 -0
- data/test/data/hypericin.mol2 +159 -0
- data/test/data/hypericin.msm +123 -0
- data/test/data/hypericin.pdf +359 -0
- data/test/data/hypericin.png +0 -0
- data/test/data/hypericin.ps +0 -0
- data/test/data/hypericin.skc +0 -0
- data/test/data/hypericin2.gif +0 -0
- data/test/data/hypericin2.ps +0 -0
- data/test/data/kegg/genomes/hsa/hsa_enzyme.list +4 -0
- data/test/data/kegg/genomes/hsa/hsa_pfam.list +4 -0
- data/test/data/kegg/ligand/mol/C00147.mol +26 -0
- data/test/data/kegg/ligand/reaction +14 -0
- data/test/data/kegg/ligand/reaction.lst +1 -0
- data/test/data/kegg/ligand/reaction_mapformula.lst +3 -0
- data/test/data/reaction +14 -0
- data/test/data/reaction.lst +1 -0
- data/test/data/reaction_mapformula.lst +3 -0
- data/test/data/rxn/C00001.mol +6 -0
- data/test/data/rxn/C00011.mol +10 -0
- data/test/data/rxn/C00014.mol +6 -0
- data/test/data/rxn/C01010.mol +18 -0
- data/test/data/rxn/sample.rxn +50 -0
- data/test/data/rxn/substitution.rxn +45 -0
- data/test/data/test.eps +0 -0
- data/test/data/test.mol +28 -0
- data/test/data/test.sdf +143 -0
- data/test/data/test.skc +0 -0
- data/test/data/test.xyz +4 -0
- data/test/data/test_lf.sdf +143 -0
- data/test/heavy_test_pubchem.rb +16 -0
- data/test/multiple_test.rb +22 -0
- data/test/test_adj.rb +54 -0
- data/test/test_canonical_smiles.rb +46 -0
- data/test/test_cdx.rb +32 -0
- data/test/test_chem.rb +18 -0
- data/test/test_cluster.rb +19 -0
- data/test/test_db.rb +11 -0
- data/test/test_eps.rb +24 -0
- data/test/test_geometry.rb +11 -0
- data/test/test_gspan.rb +28 -0
- data/test/test_iupac.rb +36 -0
- data/test/test_kcf.rb +24 -0
- data/test/test_kcf_glycan.rb +10 -0
- data/test/test_kegg.rb +118 -0
- data/test/test_linucs.rb +21 -0
- data/test/test_mdl.rb +45 -0
- data/test/test_mol2.rb +62 -0
- data/test/test_morgan.rb +21 -0
- data/test/test_pdf.rb +12 -0
- data/test/test_prop.rb +86 -0
- data/test/test_rmagick.rb +15 -0
- data/test/test_sbdb.rb +23 -0
- data/test/test_sdf.rb +30 -0
- data/test/test_smiles.rb +84 -0
- data/test/test_sssr.rb +18 -0
- data/test/test_sub.rb +47 -0
- data/test/test_subcomp.rb +37 -0
- data/test/test_traverse.rb +29 -0
- data/test/test_writer.rb +13 -0
- data/test/test_xyz.rb +15 -0
- data/test/type_test.rb +25 -0
- 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
|
+
|