iroki 0.0.15 → 0.0.16
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.
- checksums.yaml +4 -4
- data/README.md +5 -0
- data/assets/images/iroki_text.graffle +0 -0
- data/assets/images/iroki_text.idraw +0 -0
- data/assets/images/iroki_text.pdf +0 -0
- data/assets/images/iroki_text.png +0 -0
- data/assets/images/iroki_text.svg +16 -0
- data/assets/images/iroki_text_omni.pdf +0 -0
- data/assets/images/iroki_text_omni.svg +3 -0
- data/lib/iroki.rb +1 -0
- data/lib/iroki/core_ext/file/file.rb +92 -3
- data/lib/iroki/core_ext/string/string.rb +30 -6
- data/lib/iroki/main/main.rb +223 -41
- data/lib/iroki/tree.rb +92 -0
- data/lib/iroki/utils/utils.rb +12 -6
- data/lib/iroki/version.rb +1 -1
- metadata +10 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1fb677d25e56e8cd82079e8a1d910c62432f24e6
|
|
4
|
+
data.tar.gz: 6a18a69751a71d0947f630ef3eabe276d1cc0d6c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 381d8fb761e14bbd4f6be2746a4b6747964c77c80611988efa1e068da7699fbe8cac6416808d0c975a96daebd49563af97678a10b67e26c061a5dbb02d0c76c8
|
|
7
|
+
data.tar.gz: d28bee6b62b0973de7da3daefa58da5883363f913451628c40350a5f77ec2e7ac6228b928d1a78bf6edaf431c65cdf54e689e30878bc1f0731404fc55a0df63b
|
data/README.md
CHANGED
|
@@ -139,3 +139,8 @@ Add `reorder_nodes` script.
|
|
|
139
139
|
### 0.0.15 ###
|
|
140
140
|
|
|
141
141
|
- `.ruby-version` file was being weird when user didn't have the correct ruby
|
|
142
|
+
|
|
143
|
+
### 0.0.16 ###
|
|
144
|
+
|
|
145
|
+
- Allow unusual characters in label names ([GitHub issue](https://github.com/mooreryan/iroki/issues/2))
|
|
146
|
+
- Fix no method `clean` bug ([GitHub issue](https://github.com/mooreryan/iroki/issues/3))
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
|
3
|
+
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" width="362.268" height="256" viewBox="0, 0, 362.268, 256">
|
|
4
|
+
<g id="Layer_1">
|
|
5
|
+
<g>
|
|
6
|
+
<text transform="matrix(1, 0, 0, 1, 181.134, 212.5)">
|
|
7
|
+
<tspan x="-144.702" y="-9.5" font-family="Raleway-Thin" font-size="36" fill="#000000">Phylogenetic Tree</tspan>
|
|
8
|
+
<tspan x="-91.458" y="32.5" font-family="Raleway-Thin" font-size="36" fill="#000000">Customizer</tspan>
|
|
9
|
+
</text>
|
|
10
|
+
<text transform="matrix(1, 0, 0, 1, 181.134, 84.5)">
|
|
11
|
+
<tspan x="-129.384" y="50.5" font-family="Raleway-Thin" font-size="144" fill="#000000">Iroki</tspan>
|
|
12
|
+
</text>
|
|
13
|
+
<path d="M14.634,160 L348.634,160" fill-opacity="0" stroke="#000000" stroke-width="1.5"/>
|
|
14
|
+
</g>
|
|
15
|
+
</g>
|
|
16
|
+
</svg>
|
|
Binary file
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
2
|
+
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
|
3
|
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xl="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 -18 362 274" width="362pt" height="274pt" xmlns:dc="http://purl.org/dc/elements/1.1/"><metadata> Produced by OmniGraffle 6.6 <dc:date>2016-08-08 18:14:28 +0000</dc:date></metadata><defs><font-face font-family="Raleway" font-size="36" panose-1="2 11 2 3 3 1 1 6 0 3" units-per-em="1000" underline-position="-75" underline-thickness="50" slope="0" x-height="528" cap-height="715" ascent="940.00244" descent="-233.99353" font-weight="300" font-stretch="condensed"><font-face-src><font-face-name name="Raleway-Thin"/></font-face-src></font-face><font-face font-family="Raleway" font-size="144" panose-1="2 11 2 3 3 1 1 6 0 3" units-per-em="1000" underline-position="-75" underline-thickness="50" slope="0" x-height="528" cap-height="715" ascent="940.00244" descent="-233.99353" font-weight="300" font-stretch="condensed"><font-face-src><font-face-name name="Raleway-Thin"/></font-face-src></font-face></defs><g stroke="none" stroke-opacity="1" stroke-dasharray="none" fill="none" fill-opacity="1"><title>Canvas 1</title><g><title>Layer 1</title><text transform="translate(31.63405 161.5)" fill="black"><tspan font-family="Raleway" font-size="36" font-weight="300" font-stretch="condensed" fill="black" x="0" y="34" textLength="42.624">Ph</tspan><tspan font-family="Raleway" font-size="36" font-weight="300" font-stretch="condensed" fill="black" x="42.12" y="34" textLength="132.48">ylogene</tspan><tspan font-family="Raleway" font-size="36" font-weight="300" font-stretch="condensed" fill="black" x="174.456" y="34" textLength="46.152">tic </tspan><tspan font-family="Raleway" font-size="36" font-weight="300" font-stretch="condensed" fill="black" x="219.6" y="34" textLength="21.6">T</tspan><tspan font-family="Raleway" font-size="36" font-weight="300" font-stretch="condensed" fill="black" x="237.24" y="34" textLength="11.628">r</tspan><tspan font-family="Raleway" font-size="36" font-weight="300" font-stretch="condensed" fill="black" x="247.932" y="34" textLength="50.868">ee </tspan></text><text transform="translate(84.87805 203.5)" fill="black"><tspan font-family="Raleway" font-size="36" font-weight="300" font-stretch="condensed" fill="black" x="0" y="34" textLength="73.404">Cust</tspan><tspan font-family="Raleway" font-size="36" font-weight="300" font-stretch="condensed" fill="black" x="72.936" y="34" textLength="78.12">omiz</tspan><tspan font-family="Raleway" font-size="36" font-weight="300" font-stretch="condensed" fill="black" x="150.552" y="34" textLength="32.364">er</tspan></text><text transform="translate(51.63405 -8.5)" fill="black"><tspan font-family="Raleway" font-size="144" font-weight="300" font-stretch="condensed" fill="black" x="0" y="135" textLength="77.904">Ir</tspan><tspan font-family="Raleway" font-size="144" font-weight="300" font-stretch="condensed" fill="black" x="74.16" y="135" textLength="184.608">oki</tspan></text><line x1="14.17608" y1="153" x2="348.17604" y2="153" stroke="black" stroke-linecap="round" stroke-linejoin="miter" stroke-width="1"/></g></g></svg>
|
data/lib/iroki.rb
CHANGED
|
@@ -67,7 +67,7 @@ module Iroki
|
|
|
67
67
|
assert pattern, "found no pattern"
|
|
68
68
|
|
|
69
69
|
if exact_matching # TODO should this really be everytime?
|
|
70
|
-
pattern = pattern
|
|
70
|
+
pattern = pattern#.clean_name
|
|
71
71
|
else
|
|
72
72
|
# TODO flag bad regexp
|
|
73
73
|
pattern = Regexp.new pattern
|
|
@@ -127,6 +127,95 @@ module Iroki
|
|
|
127
127
|
patterns
|
|
128
128
|
end
|
|
129
129
|
|
|
130
|
+
def parse_color_map_iroki( fname,
|
|
131
|
+
iroki_to_name,
|
|
132
|
+
exact_matching: true,
|
|
133
|
+
auto_color: false)
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
check_file fname, :color_map
|
|
137
|
+
|
|
138
|
+
name_to_iroki = iroki_to_name.invert
|
|
139
|
+
|
|
140
|
+
patterns = {}
|
|
141
|
+
Object::File.open(fname, "rt").each_line do |line|
|
|
142
|
+
unless line.start_with? "#"
|
|
143
|
+
label_tag = ""
|
|
144
|
+
branch_tag = ""
|
|
145
|
+
|
|
146
|
+
pattern, label_color, branch_color = line.chomp.split "\t"
|
|
147
|
+
|
|
148
|
+
# color = "black" if color.nil? || color.empty?
|
|
149
|
+
|
|
150
|
+
assert pattern, "found no pattern"
|
|
151
|
+
|
|
152
|
+
if exact_matching # TODO should this really be everytime?
|
|
153
|
+
# pattern = pattern.clean_name
|
|
154
|
+
if name_to_iroki.has_key? pattern
|
|
155
|
+
pattern = name_to_iroki[pattern]
|
|
156
|
+
else
|
|
157
|
+
assert false, "String '#{pattern}' has no match in #{name_to_iroki.inspect}"
|
|
158
|
+
end
|
|
159
|
+
else
|
|
160
|
+
# TODO flag bad regexp
|
|
161
|
+
pattern = Regexp.new pattern
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
if color_given?(label_color) && color_given?(branch_color)
|
|
165
|
+
abort_if(has_label_tag?(label_color) &&
|
|
166
|
+
has_label_tag?(branch_color),
|
|
167
|
+
"Label tag specified twice for '#{line}'")
|
|
168
|
+
|
|
169
|
+
abort_if(has_branch_tag?(label_color) &&
|
|
170
|
+
has_branch_tag?(branch_color),
|
|
171
|
+
"Branch tag specified twice for '#{line}'")
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
if color_given?(label_color) && !color_given?(branch_color)
|
|
175
|
+
if (color = has_label_tag? label_color)
|
|
176
|
+
label_tag = Iroki::Color.get_tag color, auto_color
|
|
177
|
+
elsif (color = has_branch_tag? label_color)
|
|
178
|
+
branch_tag = Iroki::Color.get_tag color, auto_color
|
|
179
|
+
else
|
|
180
|
+
label_tag = Iroki::Color.get_tag label_color, auto_color
|
|
181
|
+
branch_tag = Iroki::Color.get_tag label_color, auto_color
|
|
182
|
+
end
|
|
183
|
+
else
|
|
184
|
+
if color_given? label_color
|
|
185
|
+
if (color = has_label_tag? label_color)
|
|
186
|
+
label_tag = Iroki::Color.get_tag color, auto_color
|
|
187
|
+
elsif (color = has_branch_tag? label_color)
|
|
188
|
+
branch_tag = Iroki::Color.get_tag color, auto_color
|
|
189
|
+
else
|
|
190
|
+
label_tag = Iroki::Color.get_tag label_color, auto_color
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
if color_given? branch_color
|
|
195
|
+
if (color = has_branch_tag? branch_color)
|
|
196
|
+
branch_tag = Iroki::Color.get_tag color, auto_color
|
|
197
|
+
elsif (color = has_label_tag? branch_color)
|
|
198
|
+
label_tag = Iroki::Color.get_tag color, auto_color
|
|
199
|
+
else
|
|
200
|
+
branch_tag = Iroki::Color.get_tag branch_color, auto_color
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
# if auto_color
|
|
206
|
+
# patterns[pattern] = "[&!color=\"#{auto_colors[color]}\"]"
|
|
207
|
+
# else
|
|
208
|
+
# patterns[pattern] = Iroki::Color.get_tag color, auto_color
|
|
209
|
+
# end
|
|
210
|
+
|
|
211
|
+
patterns[pattern] = { label: label_tag, branch: branch_tag }
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
patterns
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
|
|
130
219
|
def parse_name_map fname
|
|
131
220
|
check_file fname, :name_map
|
|
132
221
|
|
|
@@ -142,8 +231,8 @@ module Iroki
|
|
|
142
231
|
abort_if newname.nil? || newname.empty?,
|
|
143
232
|
"Column 2 missing for line: #{line.inspect}"
|
|
144
233
|
|
|
145
|
-
oldname = oldname.
|
|
146
|
-
newname = newname.
|
|
234
|
+
# oldname = oldname.clean_name
|
|
235
|
+
# newname = newname.clean_name
|
|
147
236
|
|
|
148
237
|
abort_if name_map.has_key?(oldname),
|
|
149
238
|
"#{oldname} is repeated in column 1"
|
|
@@ -2,29 +2,53 @@ module Iroki
|
|
|
2
2
|
module CoreExt
|
|
3
3
|
module String
|
|
4
4
|
|
|
5
|
+
def has_color?
|
|
6
|
+
self.match(/(.*)(\[&!color="#[0-9A-Fa-f]{6}"\])/)
|
|
7
|
+
end
|
|
8
|
+
alias already_checked? has_color?
|
|
9
|
+
|
|
5
10
|
def hex?
|
|
6
11
|
self.match(/^#[0-9A-Fa-f]{6}$/)
|
|
7
12
|
end
|
|
8
13
|
|
|
9
14
|
def clean
|
|
10
|
-
self
|
|
15
|
+
# puts %Q{clean: #{self}, #{self.gsub(/'/, '"')}}
|
|
16
|
+
self.gsub(/'/, '"')
|
|
11
17
|
end
|
|
12
18
|
|
|
13
|
-
def
|
|
14
|
-
self.match
|
|
19
|
+
def single_quote
|
|
20
|
+
if self.match /\A'.*'\Z/
|
|
21
|
+
# puts %Q{single_quote if: #{self}, outputing #{self.dup}}
|
|
22
|
+
self.dup
|
|
23
|
+
else
|
|
24
|
+
# puts %Q{single_quote else: #{self}, returning '#{self.clean}'}
|
|
25
|
+
%Q['#{self.clean}']
|
|
26
|
+
end
|
|
15
27
|
end
|
|
16
|
-
alias already_checked? has_color?
|
|
17
28
|
|
|
18
29
|
def clean_name
|
|
19
30
|
if (match = self.has_color?)
|
|
20
31
|
name = match[1]
|
|
21
32
|
color = match[2]
|
|
22
33
|
|
|
23
|
-
name.
|
|
34
|
+
# puts %Q{clean_name if: #{self}, returning #{name.single_quote + color}}
|
|
35
|
+
name.single_quote + color
|
|
36
|
+
# name + color
|
|
24
37
|
else
|
|
25
|
-
self.
|
|
38
|
+
# puts %Q{clean_name else: #{self}, returning #{self.single_quote}}
|
|
39
|
+
self.single_quote
|
|
26
40
|
end
|
|
27
41
|
end
|
|
42
|
+
|
|
43
|
+
def clean_strict
|
|
44
|
+
self.strip.gsub(/[^\p{Alnum}_]+/, "_").gsub(/_+/, "_")
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def has_single_quote?
|
|
49
|
+
self.match(/'/)
|
|
50
|
+
end
|
|
51
|
+
|
|
28
52
|
end
|
|
29
53
|
end
|
|
30
54
|
end
|
data/lib/iroki/main/main.rb
CHANGED
|
@@ -20,6 +20,121 @@ require "bio"
|
|
|
20
20
|
require "set"
|
|
21
21
|
require "trollop"
|
|
22
22
|
|
|
23
|
+
module Bio
|
|
24
|
+
class Tree
|
|
25
|
+
# formats Newick label (unquoted_label or quoted_label)
|
|
26
|
+
def __to_newick_format_label(str, options)
|
|
27
|
+
if __get_option(:parser, options) == :naive then
|
|
28
|
+
return str.to_s
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
str = str.to_s
|
|
32
|
+
if /([\(\)\,\:\[\]\_\'\x00-\x1f\x7f])/ =~ str then
|
|
33
|
+
# quoted_label
|
|
34
|
+
if __get_option(:parser, options) == :iroki
|
|
35
|
+
return str
|
|
36
|
+
else
|
|
37
|
+
return "\'" + str.gsub(/\'/, "\'\'") + "\'"
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
# unquoted_label
|
|
41
|
+
return str.gsub(/ /, '_')
|
|
42
|
+
end
|
|
43
|
+
private :__to_newick_format_label
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
class Newick
|
|
47
|
+
# splits string to tokens
|
|
48
|
+
def __parse_newick_tokenize(str, options)
|
|
49
|
+
str = str.chop if str[-1..-1] == ';'
|
|
50
|
+
# http://evolution.genetics.washington.edu/phylip/newick_doc.html
|
|
51
|
+
# quoted_label ==> ' string_of_printing_characters '
|
|
52
|
+
# single quote in quoted_label is '' (two single quotes)
|
|
53
|
+
#
|
|
54
|
+
|
|
55
|
+
if __get_option(:parser, options) == :naive then
|
|
56
|
+
ary = str.split(/([\(\)\,\:\[\]])/)
|
|
57
|
+
ary.collect! { |x| x.strip!; x.empty? ? nil : x }
|
|
58
|
+
ary.compact!
|
|
59
|
+
ary.collect! do |x|
|
|
60
|
+
if /\A([\(\)\,\:\[\]])\z/ =~ x then
|
|
61
|
+
x.intern
|
|
62
|
+
else
|
|
63
|
+
x
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
return ary
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
tokens = []
|
|
70
|
+
ss = StringScanner.new(str)
|
|
71
|
+
|
|
72
|
+
while !(ss.eos?)
|
|
73
|
+
if ss.scan(/\s+/) then
|
|
74
|
+
# do nothing
|
|
75
|
+
|
|
76
|
+
elsif ss.scan(/[\(\)\,\:\[\]]/) then
|
|
77
|
+
# '(' or ')' or ',' or ':' or '[' or ']'
|
|
78
|
+
t = ss.matched
|
|
79
|
+
tokens.push t.intern
|
|
80
|
+
|
|
81
|
+
elsif ss.scan(/\'/) then
|
|
82
|
+
# quoted_label
|
|
83
|
+
t = ''
|
|
84
|
+
while true
|
|
85
|
+
if ss.scan(/([^\']*)\'/) then
|
|
86
|
+
t.concat ss[1]
|
|
87
|
+
if ss.scan(/\'/) then
|
|
88
|
+
# single quote in quoted_label
|
|
89
|
+
t.concat ss.matched
|
|
90
|
+
else
|
|
91
|
+
break
|
|
92
|
+
end
|
|
93
|
+
else
|
|
94
|
+
# incomplete quoted_label?
|
|
95
|
+
break
|
|
96
|
+
end
|
|
97
|
+
end #while true
|
|
98
|
+
unless ss.match?(/\s*[\(\)\,\:\[\]]/) or ss.match?(/\s*\z/) then
|
|
99
|
+
# label continues? (illegal, but try to rescue)
|
|
100
|
+
if ss.scan(/[^\(\)\,\:\[\]]+/) then
|
|
101
|
+
t.concat ss.matched.lstrip
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
tokens.push t
|
|
105
|
+
|
|
106
|
+
elsif ss.scan(/[^\(\)\,\:\[\]]+/) then
|
|
107
|
+
# unquoted_label
|
|
108
|
+
t = ss.matched.strip
|
|
109
|
+
t.gsub!(/[\r\n]/, '')
|
|
110
|
+
|
|
111
|
+
unless __get_option(:parser, options) == :iroki then
|
|
112
|
+
# unquoted underscore should be converted to blank
|
|
113
|
+
t.gsub!(/\_/, ' ')
|
|
114
|
+
end
|
|
115
|
+
tokens.push t unless t.empty?
|
|
116
|
+
|
|
117
|
+
else
|
|
118
|
+
# unquoted_label in end of string
|
|
119
|
+
t = ss.rest.strip
|
|
120
|
+
t.gsub!(/[\r\n]/, '')
|
|
121
|
+
|
|
122
|
+
unless __get_option(:parser, options) == :iroki then
|
|
123
|
+
# unquoted underscore should be converted to blank
|
|
124
|
+
t.gsub!(/\_/, ' ')
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
tokens.push t unless t.empty?
|
|
128
|
+
ss.terminate
|
|
129
|
+
|
|
130
|
+
end
|
|
131
|
+
end #while !(ss.eos?)
|
|
132
|
+
|
|
133
|
+
tokens
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
23
138
|
module Iroki
|
|
24
139
|
module Main
|
|
25
140
|
def self.main(color_branches: nil,
|
|
@@ -56,6 +171,7 @@ module Iroki
|
|
|
56
171
|
abort_if single_color && biom_f.nil?,
|
|
57
172
|
"--single-color was passed but no biom file was given"
|
|
58
173
|
|
|
174
|
+
# this should be allowed
|
|
59
175
|
abort_if biom_f && color_map_f,
|
|
60
176
|
"--color-map and --biom-file cannot both be specified. Try iroki --help for help."
|
|
61
177
|
|
|
@@ -92,12 +208,50 @@ module Iroki
|
|
|
92
208
|
name_map_f.nil?,
|
|
93
209
|
"Newick file was given but no other files were given")
|
|
94
210
|
|
|
95
|
-
#
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
211
|
+
# treeio = Bio::FlatFile.open(Bio::Newick, newick)
|
|
212
|
+
|
|
213
|
+
# newick = treeio.next_entry
|
|
214
|
+
str = File.read newick
|
|
215
|
+
newick = Bio::Newick.new str, parser: :iroki
|
|
216
|
+
tree = newick.tree
|
|
217
|
+
|
|
218
|
+
# puts [:tree_first_parsed, tree.newick(indent: false)]
|
|
219
|
+
|
|
220
|
+
iroki_to_name = Iroki::Tree.change_names tree
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
#################################################################
|
|
224
|
+
# parse name map
|
|
225
|
+
################
|
|
226
|
+
|
|
227
|
+
if name_map_f
|
|
228
|
+
name_map = parse_name_map name_map_f
|
|
100
229
|
else
|
|
230
|
+
name_map = nil
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
if name_map_f && color_map_f.nil? && biom_f.nil? # just name map
|
|
234
|
+
# put node names back
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
################
|
|
238
|
+
# parse name map
|
|
239
|
+
#################################################################
|
|
240
|
+
|
|
241
|
+
if name_map_f && color_map_f.nil? && biom_f.nil?
|
|
242
|
+
AbortIf.logger.info "Only renaming was requested."
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
#################################################################
|
|
246
|
+
# get color patterns
|
|
247
|
+
####################
|
|
248
|
+
|
|
249
|
+
if color_f
|
|
250
|
+
patterns = parse_color_map_iroki color_f,
|
|
251
|
+
iroki_to_name,
|
|
252
|
+
exact_matching: exact,
|
|
253
|
+
auto_color: auto_color_hash
|
|
254
|
+
elsif biom_f
|
|
101
255
|
samples, counts, is_single_group = Biom.open(biom_f, "rt").parse
|
|
102
256
|
|
|
103
257
|
if is_single_group
|
|
@@ -107,45 +261,59 @@ module Iroki
|
|
|
107
261
|
g2_counts = counts.map(&:last)
|
|
108
262
|
patterns = TwoGroupGradient.new(samples, g1_counts, g2_counts).patterns
|
|
109
263
|
end
|
|
264
|
+
|
|
265
|
+
# these patterns have the original name for the key, so change
|
|
266
|
+
# the key to the iroki name
|
|
267
|
+
name_to_iroki = iroki_to_name.invert
|
|
268
|
+
h = {}
|
|
269
|
+
patterns.each do |name, val|
|
|
270
|
+
h[name_to_iroki[name]] = val
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
patterns = h
|
|
274
|
+
else
|
|
275
|
+
patterns = nil
|
|
110
276
|
end
|
|
111
277
|
|
|
112
|
-
|
|
278
|
+
####################
|
|
279
|
+
# get color patterns
|
|
280
|
+
#################################################################
|
|
113
281
|
|
|
114
|
-
|
|
115
|
-
|
|
282
|
+
|
|
283
|
+
# puts [:tree_after_change_names, tree.newick(indent: false)]
|
|
284
|
+
nil_val = { label: "", branch: "" }
|
|
116
285
|
|
|
117
286
|
# do this first cos everything after will use the "new" names
|
|
118
|
-
if name_map_f
|
|
119
|
-
|
|
287
|
+
# if name_map_f
|
|
288
|
+
# name_map = parse_name_map name_map_f
|
|
120
289
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
290
|
+
# tree.collect_node! do |node|
|
|
291
|
+
# unless node.name.nil?
|
|
292
|
+
# # every name is cleaned no matter what
|
|
293
|
+
# # node.name = node.name.clean_name
|
|
125
294
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
295
|
+
# if name_map.has_key?(node.name)
|
|
296
|
+
# node.name = name_map[node.name]
|
|
297
|
+
# end
|
|
298
|
+
# end
|
|
130
299
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
end
|
|
300
|
+
# node
|
|
301
|
+
# end
|
|
302
|
+
# end
|
|
134
303
|
|
|
135
304
|
leaves_with_names = tree.leaves.reject { |leaf| leaf.name.nil? }
|
|
136
305
|
if color_taxa_names
|
|
137
306
|
leaves = leaves_with_names.map do |n|
|
|
138
|
-
name = n.name
|
|
307
|
+
name = n.name#.clean_name
|
|
139
308
|
|
|
140
|
-
if (color = add_color_to_leaf_branch(patterns, name, exact))
|
|
141
|
-
name + color[:label]
|
|
309
|
+
if (color = add_color_to_leaf_branch(patterns, name, exact, iroki_to_name))
|
|
310
|
+
name.single_quote + color[:label]
|
|
142
311
|
else
|
|
143
|
-
name
|
|
312
|
+
name.single_quote
|
|
144
313
|
end
|
|
145
314
|
end
|
|
146
315
|
else
|
|
147
|
-
leaves = leaves_with_names.
|
|
148
|
-
map { |n| n.name.clean_name }
|
|
316
|
+
leaves = leaves_with_names.map { |n| n.name.single_quote }
|
|
149
317
|
end
|
|
150
318
|
|
|
151
319
|
if color_branches
|
|
@@ -155,35 +323,49 @@ module Iroki
|
|
|
155
323
|
n += 1
|
|
156
324
|
$stderr.printf "Node: %d of %d\r", n, total
|
|
157
325
|
|
|
158
|
-
color_nodes patterns, tree, node, exact
|
|
326
|
+
color_nodes patterns, tree, node, exact, iroki_to_name
|
|
159
327
|
end
|
|
160
328
|
end
|
|
161
329
|
$stderr.puts
|
|
162
330
|
|
|
163
|
-
if remove_bootstraps_below
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
331
|
+
# if remove_bootstraps_below
|
|
332
|
+
# tree.collect_node! do |node|
|
|
333
|
+
# if node.bootstrap && node.bootstrap < remove_bootstraps_below
|
|
334
|
+
# node.bootstrap_string = ""
|
|
335
|
+
# end
|
|
336
|
+
|
|
337
|
+
# node
|
|
338
|
+
# end
|
|
339
|
+
# end
|
|
340
|
+
|
|
341
|
+
tre_str = tree.newick(indent: false)
|
|
342
|
+
# tree.each_node do |node|
|
|
343
|
+
# p [:node, node.name]
|
|
344
|
+
# end
|
|
345
|
+
# puts [:tree_str, tre_str]
|
|
346
|
+
# puts [:iroki_to_name, iroki_to_name]
|
|
347
|
+
# puts [:after_change, Iroki::Tree.gsub_iroki_newick_string(tre_str, iroki_to_name)]
|
|
348
|
+
|
|
349
|
+
# this hash can be used regardless of whether a name map was used
|
|
350
|
+
silly_iroki_to_name = {}
|
|
351
|
+
iroki_to_name.each do |iname, oldname|
|
|
352
|
+
if name_map && name_map.has_key?(oldname)
|
|
353
|
+
silly_iroki_to_name[iname] = name_map[oldname]
|
|
354
|
+
else
|
|
355
|
+
silly_iroki_to_name[iname] = oldname
|
|
170
356
|
end
|
|
171
357
|
end
|
|
172
358
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
tre_str = tree.newick(indent: false).gsub(/'/, '')
|
|
176
|
-
|
|
177
359
|
nexus = "#NEXUS
|
|
178
360
|
begin taxa;
|
|
179
361
|
dimensions ntax=#{leaves.count};
|
|
180
362
|
taxlabels
|
|
181
|
-
#{leaves.join("\n")}
|
|
363
|
+
#{leaves.join("\n").gsub(/iroki[0-9]+iroki/, silly_iroki_to_name)}
|
|
182
364
|
;
|
|
183
365
|
end;
|
|
184
366
|
|
|
185
367
|
begin trees;
|
|
186
|
-
tree tree_1 = [&R] #{tre_str}
|
|
368
|
+
tree tree_1 = [&R] #{Iroki::Tree.gsub_iroki_newick_string tre_str, silly_iroki_to_name}
|
|
187
369
|
end;
|
|
188
370
|
|
|
189
371
|
#{FIG}"
|
data/lib/iroki/tree.rb
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
module Iroki
|
|
2
|
+
class Tree
|
|
3
|
+
def self.iroki_name idx
|
|
4
|
+
"iroki#{idx}iroki"
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
# @note The newick standard changes unquoted underscores to spaces
|
|
8
|
+
#
|
|
9
|
+
# @note The reason we have to bother with this is because when the
|
|
10
|
+
# bioruby parser calls the __to_newick method, it does some
|
|
11
|
+
# annoying things to the output and changes the names. Making
|
|
12
|
+
# the names like this lets us easily gsub the names to what they
|
|
13
|
+
# should be after the name map.
|
|
14
|
+
#
|
|
15
|
+
# @param [Bio::Tree] a bio ruby tree object
|
|
16
|
+
#
|
|
17
|
+
# @return [Hash] iroki_name (string) => quoted_orig_name (string)
|
|
18
|
+
def self.change_names tree
|
|
19
|
+
idx = -1
|
|
20
|
+
realname = {}
|
|
21
|
+
tree.each_node do |node|
|
|
22
|
+
if node.name && !node.name.empty?
|
|
23
|
+
idx += 1
|
|
24
|
+
|
|
25
|
+
realname[iroki_name(idx)] = %Q{#{node.name}}
|
|
26
|
+
|
|
27
|
+
node.name = iroki_name(idx)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
realname
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def self.combine_hashes h1, h2, nil_val=nil
|
|
35
|
+
h_new = {}
|
|
36
|
+
h1.each do |h1_key, h1_val|
|
|
37
|
+
if h2.has_key? h1_val
|
|
38
|
+
h_new[h1_key] = h2[h1_val]
|
|
39
|
+
else
|
|
40
|
+
h_new[h1_key] = nil_val
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
h_new
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def self.quoted_vals hash
|
|
48
|
+
# p [:a, hash.values]
|
|
49
|
+
# p [:b, hash.values.map(&:single_quote)]
|
|
50
|
+
hash.values.map(&:single_quote)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def self.gsub_iroki_newick_string tre_str, iroki_to_name, name_map=nil
|
|
54
|
+
if name_map
|
|
55
|
+
vals = self.quoted_vals name_map
|
|
56
|
+
name_map_quoted = Hash[name_map.keys.zip(vals)]
|
|
57
|
+
|
|
58
|
+
iroki_to_new_name = self.combine_hashes iroki_to_name, name_map_quoted
|
|
59
|
+
else
|
|
60
|
+
vals = self.quoted_vals iroki_to_name
|
|
61
|
+
|
|
62
|
+
iroki_to_new_name = Hash[iroki_to_name.keys.zip(vals)]
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
tre_str.gsub(/iroki[0-9]+iroki/, iroki_to_new_name)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def self.iroki_to_color iroki_to_name, color_map, name_map, nil_val=nil
|
|
69
|
+
if name_map
|
|
70
|
+
old_names = name_map.keys
|
|
71
|
+
new_names = name_map.values
|
|
72
|
+
|
|
73
|
+
color_map_is_for_old_names = color_map.keys.all? { |key| old_names.include? key }
|
|
74
|
+
color_map_is_for_new_names = color_map.keys.all? { |key| new_names.include? key }
|
|
75
|
+
|
|
76
|
+
if color_map_is_for_old_names
|
|
77
|
+
iroki_to_color = self.combine_hashes iroki_to_name, color_map, nil_val
|
|
78
|
+
elsif color_map_is_for_new_names
|
|
79
|
+
iroki_to_new_name = self.combine_hashes iroki_to_name, name_map
|
|
80
|
+
|
|
81
|
+
iroki_to_color = self.combine_hashes iroki_to_new_name, color_map, nil_val
|
|
82
|
+
else # some old, some new
|
|
83
|
+
abort_if true, "The color map has both old and new names in the first column."
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
iroki_to_color
|
|
87
|
+
else # no name map
|
|
88
|
+
self.combine_hashes iroki_to_name, color_map, nil_val
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
data/lib/iroki/utils/utils.rb
CHANGED
|
@@ -22,7 +22,7 @@ module Iroki
|
|
|
22
22
|
tree.children(node).empty?
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
-
def add_color_to_leaf_branch patterns, node, exact
|
|
25
|
+
def add_color_to_leaf_branch patterns, node, exact, iroki_to_name=nil
|
|
26
26
|
num_matches = 0
|
|
27
27
|
color = nil
|
|
28
28
|
already_matched = false
|
|
@@ -37,7 +37,9 @@ module Iroki
|
|
|
37
37
|
return nil
|
|
38
38
|
end
|
|
39
39
|
else
|
|
40
|
-
|
|
40
|
+
assert iroki_to_name, "iroki_to_name arg is nil"
|
|
41
|
+
assert iroki_to_name[node.to_s], "iroki_to_name is missing #{node.to_s}"
|
|
42
|
+
node_s = iroki_to_name[node.to_s]
|
|
41
43
|
|
|
42
44
|
patterns.each do |pattern, this_color|
|
|
43
45
|
if node_s =~ pattern
|
|
@@ -61,13 +63,15 @@ module Iroki
|
|
|
61
63
|
end
|
|
62
64
|
end
|
|
63
65
|
|
|
64
|
-
def color_nodes patterns, tree, node, exact
|
|
66
|
+
def color_nodes patterns, tree, node, exact, iroki_to_name
|
|
65
67
|
# # check if it needs color, if so set the color
|
|
66
68
|
# color = add_color_to_leaf_branch patterns, node, exact
|
|
67
69
|
|
|
68
70
|
# clean the name no matter what
|
|
69
71
|
if node.name
|
|
70
|
-
|
|
72
|
+
# puts "before haha: #{node.name}"
|
|
73
|
+
node.name = node.name #.clean_name
|
|
74
|
+
# puts "after haha: #{node.name}"
|
|
71
75
|
else
|
|
72
76
|
node.name = nil
|
|
73
77
|
end
|
|
@@ -82,16 +86,18 @@ module Iroki
|
|
|
82
86
|
|
|
83
87
|
# NOTE: this was originally before cleaning the node name a
|
|
84
88
|
# couple lines up, does it matter that it is after?
|
|
85
|
-
color = add_color_to_leaf_branch patterns, node, exact
|
|
89
|
+
color = add_color_to_leaf_branch patterns, node, exact, iroki_to_name
|
|
86
90
|
|
|
87
91
|
# add color to the name
|
|
92
|
+
# p [:before, node.name]
|
|
88
93
|
node.name = node.name + color[:branch] if color
|
|
94
|
+
# p [:after, node.name]
|
|
89
95
|
elsif !leaf?(tree, node)
|
|
90
96
|
children = tree.children(node) # get the children
|
|
91
97
|
children_colors = []
|
|
92
98
|
children.each do |child|
|
|
93
99
|
# recurse to color the child if needed
|
|
94
|
-
color_nodes patterns, tree, child, exact
|
|
100
|
+
color_nodes patterns, tree, child, exact, iroki_to_name
|
|
95
101
|
children_colors << get_color(child) # add color of the child
|
|
96
102
|
end
|
|
97
103
|
|
data/lib/iroki/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: iroki
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.16
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ryan Moore
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2016-08-
|
|
11
|
+
date: 2016-08-15 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -187,6 +187,13 @@ files:
|
|
|
187
187
|
- assets/images/iroki_logo2.idraw
|
|
188
188
|
- assets/images/iroki_logo2.png
|
|
189
189
|
- assets/images/iroki_logo2.svg
|
|
190
|
+
- assets/images/iroki_text.graffle
|
|
191
|
+
- assets/images/iroki_text.idraw
|
|
192
|
+
- assets/images/iroki_text.pdf
|
|
193
|
+
- assets/images/iroki_text.png
|
|
194
|
+
- assets/images/iroki_text.svg
|
|
195
|
+
- assets/images/iroki_text_omni.pdf
|
|
196
|
+
- assets/images/iroki_text_omni.svg
|
|
190
197
|
- bin/console
|
|
191
198
|
- bin/iroki_docker
|
|
192
199
|
- bin/setup
|
|
@@ -207,6 +214,7 @@ files:
|
|
|
207
214
|
- lib/iroki/core_ext/hash/hash.rb
|
|
208
215
|
- lib/iroki/core_ext/string/string.rb
|
|
209
216
|
- lib/iroki/main/main.rb
|
|
217
|
+
- lib/iroki/tree.rb
|
|
210
218
|
- lib/iroki/utils/utils.rb
|
|
211
219
|
- lib/iroki/version.rb
|
|
212
220
|
homepage: https://github.com/mooreryan/iroki
|