iroki 0.0.15 → 0.0.16
Sign up to get free protection for your applications and to get access to all the features.
- 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
|