Skip to content

Commit bde9d29

Browse files
authored
Merge pull request #4 from yamada-lab/develop
Addition of an annotation section to the TSV reference tree format
2 parents 38c7163 + 2ca25be commit bde9d29

File tree

8 files changed

+111
-51
lines changed

8 files changed

+111
-51
lines changed
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
Annotation-start
2+
VALUE1 Value one
3+
VALUE2 Value two
4+
VALUE_A Value A
5+
VALUE_AA Value AA
6+
VALUE_C Value C
7+
LEAF_1 LEAF one
8+
LEAF_2 LEAF two
9+
LEAF_7 LEAF seven
10+
Annotation-end
11+
L1 L2 L3 L4 LEAF
12+
VALUE1 VALUE_A VALUE_B VALUE_C LEAF_1
13+
VALUE1 VALUE_A VALUE_B VALUE_C LEAF_2
14+
VALUE1 VALUE_A VALUE_B VALUE_D LEAF_3
15+
VALUE1 VALUE_A VALUE_B VALUE_D LEAF_4
16+
VALUE1 VALUE_A VALUE_B VALUE_E LEAF_5
17+
VALUE1 VALUE_A VALUE_B - LEAF_6
18+
VALUE1 VALUE_A - - LEAF_7
19+
VALUE2 VALUE_AA VALUE_BB VALUE_AD LEAF_8
20+
VALUE2 - VALUE_BC VALUE_AD LEAF_9
21+
VALUE2 VALUE_AA VALUE_BC VALUE_AE LEAF_10

functree/static/src/js/functree.js

Lines changed: 44 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ const DEFAULT_CONFIG = {
1010
'duration': 1000,
1111
'normalize': true,
1212
'percentage': false,
13+
'labelMinDepth': 3,
1314
'maxDepth': 4,
1415
'colorizeBy': 'layer',
1516
'colorSet': {
@@ -337,11 +338,14 @@ const FuncTree = class {
337338
.selectAll('path')
338339
.attr('style', null);
339340
}).on('contextmenu', (d) => {
341+
console.log(d.depth)
340342
if (this.config.external.entry) {
341343
eval(this.config.external.entry + ' = d.entry');
342344
}
343345
// get a pointer to the FuncTree instance
344346
const self = this
347+
// get the id of the triggering node
348+
const nodeId = d3.event.target.id
345349
// create an array of actions for the context menu
346350
const actions = [{
347351
name: 'Copy',
@@ -357,7 +361,44 @@ const FuncTree = class {
357361
$("#form-entry-detail").submit();
358362
}
359363
}]
360-
const nodeId = d3.event.target.id
364+
// Toggle/Untoggle labels for unlabeled nodes
365+
if (d.depth >= this.config.labelMinDepth) {
366+
actions.push({
367+
name: 'Toggle label',
368+
iconClass: 'fa-toggle-off',
369+
onClick: function() {
370+
const selectedLabel = d3.select('#label-' + nodeId)
371+
if (selectedLabel.empty()) {
372+
const selectedNode = d3.select('#' + nodeId)
373+
const text = d3.select("#labels")
374+
.append('g')
375+
.attr('id', 'label-' + nodeId)
376+
.attr('transform', selectedNode .attr("transform"))
377+
.append('text')
378+
.attr('text-anchor', 'middle')
379+
.attr('font-family', 'arial, sans-serif')
380+
.attr('font-size', 4)
381+
.attr('fill', '#555')
382+
.text(selectedNode.attr("data-original-title").replace(/\[.*\] /, ''))
383+
// add drag behavior
384+
text.call(d3.behavior.drag()
385+
.on('dragstart', () => {
386+
d3.event.sourceEvent.stopPropagation();
387+
})
388+
.on('drag', function(d) {
389+
d3.select(this)
390+
.attr('y', 0)
391+
.attr('transform', 'translate(' + d3.event.x + ',' + d3.event.y + ')');
392+
})
393+
);
394+
395+
} else {
396+
selectedLabel.remove()
397+
}
398+
}
399+
})
400+
}
401+
361402
// check node id eligible for View Details actions
362403
if (hasMoreDetails(nodeId, "KEGG")) {
363404
actions.push({
@@ -386,43 +427,7 @@ const FuncTree = class {
386427
var url = resolveExternalURL(nodeId, "KEGG")
387428
window.open(url, '_blank');
388429
}
389-
})
390-
// Toggle/Untoggle labels
391-
actions.push({
392-
name: 'Toggle label',
393-
iconClass: 'fa-toggle-off',
394-
onClick: function() {
395-
const selectedLabel = d3.select('#label-' + nodeId)
396-
if (selectedLabel.empty()) {
397-
const selectedNode = d3.select('#' + nodeId)
398-
const text = d3.select("#labels")
399-
.append('g')
400-
.attr('id', 'label-' + nodeId)
401-
.attr('transform', selectedNode .attr("transform"))
402-
.append('text')
403-
.attr('text-anchor', 'middle')
404-
.attr('font-family', 'arial, sans-serif')
405-
.attr('font-size', 4)
406-
.attr('fill', '#555')
407-
.text(selectedNode.attr("data-original-title").replace(/\[.*\] /, ''))
408-
// add drag behavior
409-
text.call(d3.behavior.drag()
410-
.on('dragstart', () => {
411-
d3.event.sourceEvent.stopPropagation();
412-
})
413-
.on('drag', function(d) {
414-
d3.select(this)
415-
.attr('y', 0)
416-
.attr('transform', 'translate(' + d3.event.x + ',' + d3.event.y + ')');
417-
})
418-
);
419-
420-
} else {
421-
selectedLabel.remove()
422-
}
423-
}
424-
})
425-
430+
})
426431
}
427432
//escape space in the selector
428433
const menu = new BootstrapMenu("#"+nodeId.replace(/([ &,;:\+\*\(\)\[\]])/g, '\\$1'), {
@@ -695,7 +700,7 @@ const FuncTree = class {
695700
_updateLabels(nodes, source, maxValue, maxSumOfValues) {
696701
const data = nodes
697702
.filter((d) => {
698-
return 0 < d.depth && d.depth < 3;
703+
return 0 < d.depth && d.depth < this.config.labelMinDepth;
699704
})
700705
.filter((d) => {
701706
return !d.name.startsWith('*');

functree/templates/about.html

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,15 @@ <h3>Publications</h3>
2525
<hr />
2626
<h3>Change log</h3>
2727
<br />
28+
<h5>Version 0.7.6.3 (2019-02-25)</h5>
29+
<ul>
30+
<li>Addition of an annotation section to the TSV reference tree format.
31+
</ul>
2832
<h5>Version 0.7.6.2 (2019-02-15)</h5>
2933
<ul>
30-
<li>Addition of a toggle action to show/hide node labels
31-
<li>Addition of a description to the database selection
32-
<li>Upgrade of Flask
34+
<li>Addition of a toggle action to show/hide node labels.
35+
<li>Addition of a description to the database selection.
36+
<li>Upgrade of Flask.
3337
</ul>
3438
<h5>Version 0.7.6.1 (2019-01-18)</h5>
3539
<ul>

functree/templates/functree.html

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,15 @@ <h5><i class="fa fa-question-circle" aria-hidden="true"></i> Help <a id="help" h
103103
<ul>
104104
<li><b>Mouse gestures</b> enable zooming (middle button) and panning (click + drag)</li>
105105
<li><b>Click</b> on a node collapses or reveals its children nodes</li>
106-
<li><b>Right-click</b> on a node offers these options: set as root, view details, copy to clipboard, or view in KEGG.</li>
106+
<li><b>Right-click</b> on a node offers these options:
107+
<ul>
108+
<li>set as root</li>
109+
<li>view details</li>
110+
<li>toggle label</li>
111+
<li>copy to clipboard</li>
112+
<li>view in KEGG</li>
113+
</ul>
114+
</li>
107115
</ul>
108116
</div>
109117
<hr>

functree/templates/help.html

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -266,10 +266,10 @@ <h3>Tab separated matrix</h3>
266266
A tab separated matrix containing the ontology. Each line should
267267
start with the highest level of the ontology followed by the rest
268268
of the levels all the way down to the leaves. Missing level entries should
269-
be replaced by an empty string or a dash ["-", ""]. Please check
270-
this <a
271-
href="{{ url_for('static', filename='data/example/reference_tree.tsv') }}"
272-
target="_blank"> example file</a> for reference.
269+
be replaced by an empty string or a dash ["-", ""]. Optionally, the file could have
270+
an annotation section containing labels for the entries. These labels will drawn on top of the visualized entries.
271+
Please check the <a href="{{ url_for('static', filename='data/example/reference_tree.tsv') }}" target="_blank"> matrix file</a>
272+
and the <a href="{{ url_for('static', filename='data/example/reference_tree_annotated.tsv') }}" target="_blank"> annotated-matrix file</a> for reference.
273273
</p>
274274
</div>
275275
</div>

functree/templates/list.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
<div class="page-header">
1212
<h2>{{title}}</h2>
1313
</div>
14-
<p>This is a listing of all available profiles. To hide your profile from this list, check <b>"Keep the result private"</b> before the submission.</p>
14+
<p>To hide your profile from this list, check <b>"Keep the result private"</b> before the submission.</p>
1515
<table id="table-profile" class="table table-hover table-striped" width="100%">
1616
<thead>
1717
<tr>

functree/templates/upload.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ <h2>Upload reference Tree</h2>
2020
{{ form.input_file(class_='form-control-file') }}
2121
<span class="help-block">Example: <a href="{{ url_for('static', filename='data/example/reference_tree.json') }}" target="_blank"><i class="fa fa-download" aria-hidden="true"></i> JSON</a>
2222
<a href="{{ url_for('static', filename='data/example/reference_tree.tsv') }}" target="_blank"><i class="fa fa-download" aria-hidden="true"></i> TSV</a>
23+
<a href="{{ url_for('static', filename='data/example/reference_tree_annotated.tsv') }}" target="_blank"><i class="fa fa-download" aria-hidden="true"></i> TSV (annotated)</a>
2324
</span>
2425
{% if form.input_file.errors %}
2526
<span class="help-block">

functree/tree.py

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -136,12 +136,28 @@ def from_tsv(path, name):
136136
'''
137137
root = Node(entry=name, name=name, layer='root')
138138

139+
# process annoatation if available
140+
entry_label = {}
141+
line = path.readline()
142+
143+
if line.strip().decode() == 'Annotation-start':
144+
#populate annotation table
145+
line = path.readline()
146+
while line:
147+
line = line.strip().decode()
148+
while line != 'Annotation-end':
149+
entry, label = line.split('\t')
150+
entry_label[entry] = label
151+
line = path.readline()
152+
139153
levels = path.readline().strip().decode().split('\t')
140154
levels.insert(0, 'root')
141155
nodes_layer = {key: {} for key in levels}
142156
nodes_layer['root'] = {'root': root}
143-
144-
for line in path:
157+
158+
line = path.readline()
159+
160+
while line:
145161
entries = line.strip().decode().split('\t')
146162
# prefix empty cells by parent id
147163
for index, entry in enumerate(entries):
@@ -157,12 +173,17 @@ def from_tsv(path, name):
157173
layer = levels[index + 1]
158174
if entry not in nodes_layer[layer]:
159175
parent_layer = levels[index]
160-
node = Node(entry=entry, name=entry, layer=layer)
176+
name_label = entry
177+
if entry in entry_label:
178+
name_label = entry_label[entry]
179+
node = Node(entry=entry, name=name_label, layer=layer)
161180
if index > 0:
162181
nodes_layer[parent_layer][entries[index - 1]].add_child(node)
163182
else:
164183
nodes_layer[parent_layer]['root'].add_child(node)
165184
nodes_layer[layer][entry] = node
185+
line = path.readline()
186+
#path.close()
166187
return root
167188

168189
def download_htext(htext, format='htext'):

0 commit comments

Comments
 (0)