chemruby 0.9.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|