Skip to content

Commit 734bade

Browse files
Merge pull request #100 from snjlee58/master
Addition of show/hide toggle and fixes to hits filtering feature
2 parents 23dd4c0 + 93b639d commit 734bade

File tree

2 files changed

+52
-61
lines changed

2 files changed

+52
-61
lines changed

frontend/ResultView.vue

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -93,13 +93,13 @@
9393
</v-tabs>
9494
<div v-for="(entry, index) in hits.results" :key="entry.db" v-if="selectedDatabases == 0 || (index + 1) == selectedDatabases">
9595
<v-flex class="d-flex" :style="{ 'flex-direction' : $vuetify.breakpoint.xsOnly ? 'column' : null, 'align-items': 'center' }">
96-
<h2 style="margin-top: 0.5em; margin-bottom: 1em; display: inline-block;">
96+
<h2 style="margin-top: 0.5em; margin-bottom: 1em; display: inline-block;" class="mr-auto">
9797
<span style="text-transform: uppercase;">{{ entry.db }}</span> <small>{{ entry.alignments ? Object.values(entry.alignments).length : 0 }} hits</small>
9898
</h2>
9999

100100
<!-- Button to toggle Sankey Diagram visibility -->
101-
<v-btn @click="isSankeyVisible = !isSankeyVisible" class="ml-auto mr-2" large>
102-
{{ isSankeyVisible ? 'Hide Sankey' : 'Show Sankey' }}
101+
<v-btn v-if="entry.hasTaxonomy" @click="toggleSankeyVisibility(entry.db)" class="mr-2" large>
102+
{{ isSankeyVisible[entry.db] ? 'Hide Taxonomy' : 'Show Taxonomy' }}
103103
</v-btn>
104104

105105
<v-btn-toggle mandatory v-model="tableMode" >
@@ -112,8 +112,8 @@
112112
</v-btn>
113113
</v-btn-toggle>
114114
</v-flex>
115-
<v-flex v-if="isSankeyVisible && entry.taxonomyreport" class="mb-2">
116-
<SankeyDiagram :rawData="entry.taxonomyreport" :currentSelectedNodeId="selectedTaxId" @selectTaxon="handleSankeySelect"></SankeyDiagram>
115+
<v-flex v-if="entry.hasTaxonomy && isSankeyVisible[entry.db]" class="mb-2">
116+
<SankeyDiagram :rawData="entry.taxonomyreport" :db="entry.db" :currentSelectedNodeId="selectedTaxId" :currentSelectedDb="selectedDb" @selectTaxon="handleSankeySelect"></SankeyDiagram>
117117
</v-flex>
118118
<table class="v-table result-table" style="position:relativ; margin-bottom: 3em;">
119119
<colgroup>
@@ -185,7 +185,7 @@
185185
</tr>
186186
</thead>
187187
<tbody>
188-
<template v-for="(group, groupidx) in filteredAlignments(entry.alignments)" >
188+
<template v-for="(group, groupidx) in filteredAlignments(entry.alignments, entry.db)" >
189189
<tr v-for="(item, index) in group" :class="['hit', { 'active' : item.active }]">
190190
<template v-if="index == 0 && isComplex">
191191
<td class="thin" data-label="Query TM-score" :rowspan="group.length">{{ group[0].complexqtm.toFixed(2) }}</td>
@@ -281,7 +281,8 @@ export default {
281281
activeTarget: null,
282282
alnBoxOffset: 0,
283283
selectedDatabases: 0,
284-
isSankeyVisible: false,
284+
isSankeyVisible: {}, // Track visibility for each entry.db
285+
selectedDb: null,
285286
selectedTaxId: null,
286287
filteredHitsTaxIds: [],
287288
tableMode: 0,
@@ -376,20 +377,30 @@ export default {
376377
this.menuActivator.click(event);
377378
}
378379
},
379-
handleSankeySelect({ nodeId, descendantIds }) {
380+
toggleSankeyVisibility(db) {
381+
// Toggle visibility for the specific entry.db
382+
this.$set(this.isSankeyVisible, db, !this.isSankeyVisible[db]);
383+
},
384+
handleSankeySelect({ nodeId, descendantIds, db }) {
380385
this.selectedTaxId = nodeId;
381386
this.filteredHitsTaxIds = descendantIds ? descendantIds.map(Number) : null;
387+
this.selectedDb = db;
382388
},
383-
filteredAlignments(alignments) {
389+
filteredAlignments(alignments, db) {
384390
// Convert alignments to an array if it is an object
385391
if (alignments && !Array.isArray(alignments)) {
386392
alignments = Object.values(alignments);
387393
}
388-
394+
389395
if (!Array.isArray(alignments)) {
390396
return []; // Return an empty array if conversion fails
391397
}
392398
399+
if (db !== this.selectedDb) {
400+
// Reset filteredHitsTaxIds if db changes
401+
return alignments;
402+
}
403+
393404
if (!this.filteredHitsTaxIds || this.filteredHitsTaxIds.length === 0) {
394405
return alignments; // Return all groups if no filteredAlignments
395406
}

frontend/SankeyDiagram.vue

Lines changed: 31 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<template>
22
<div class="sankey-container">
3-
<svg ref="sankeyContainer"></svg>
3+
<svg ref="sankeyContainer" class="hide"></svg>
44
</div>
55
</template>
66

@@ -20,6 +20,14 @@ export default {
2020
type: String,
2121
default: null,
2222
},
23+
db: {
24+
type: String,
25+
required: true,
26+
},
27+
currentSelectedDb: {
28+
type: String,
29+
default: null,
30+
}
2331
},
2432
data: () => ({
2533
currentSelectedNode: null, // Track the currently selected node
@@ -66,6 +74,16 @@ export default {
6674
});
6775
},
6876
},
77+
currentSelectedDb: {
78+
immediate: true,
79+
handler(newValue) {
80+
if (newValue !== this.db) {
81+
// Reset the selected node when switching databases
82+
this.currentSelectedNode = null;
83+
this.createSankey(this.rawData);
84+
}
85+
}
86+
}
6987
},
7088
methods: {
7189
// Function for processing/parsing data
@@ -89,7 +107,7 @@ export default {
89107
});
90108
},
91109
// Function for processing/parsing data
92-
parseData(data, isFullGraph = true) {
110+
parseData(data, isFullGraph = false) {
93111
const nodes = [];
94112
const unclassifiedNodes = [];
95113
const allNodes = [];
@@ -151,49 +169,6 @@ export default {
151169
currentLineage.push(node);
152170
node.lineage = [...currentLineage];
153171
}
154-
} else if (this.isUnclassifiedTaxa(d)) {
155-
// lineage tracking for unclassified taxa
156-
let currentLineageCopy = [...currentLineage];
157-
const parentName = d.name.replace("unclassified ", "");
158-
let lastLineageNode = currentLineageCopy[currentLineageCopy.length - 1];
159-
160-
if (lastLineageNode) {
161-
while (lastLineageNode && lastLineageNode.name !== parentName) {
162-
currentLineageCopy.pop();
163-
lastLineageNode = currentLineageCopy[currentLineageCopy.length - 1];
164-
}
165-
}
166-
167-
// Find the previous node in the lineage that is in rankOrder
168-
const parentNode = currentLineageCopy.find((n) => n.name === parentName);
169-
if (parentNode && parentNode === lastLineageNode) {
170-
const lineage = currentLineageCopy;
171-
172-
let previousNode = null;
173-
for (let i = lineage.length - 1; i >= 0; i--) {
174-
// Start from the last item
175-
if (this.rankOrder.includes(lineage[i].rank)) {
176-
previousNode = lineage[i];
177-
break;
178-
}
179-
}
180-
181-
// Determine the rank immediately to the right of this node
182-
const parentRankIndex = this.rankOrder.indexOf(previousNode.rank);
183-
184-
// Edit properties for unclassified taxa
185-
const nextRank = this.rankOrder[parentRankIndex + 1];
186-
187-
node.id = `dummy-${d.taxon_id}`;
188-
node.rank = nextRank;
189-
node.type = "unclassified";
190-
191-
// Add unclassified node to currentLineage and save lineage data
192-
currentLineageCopy.push(node);
193-
node.lineage = [...currentLineageCopy];
194-
195-
unclassifiedNodes.push(node);
196-
}
197172
}
198173
});
199174
@@ -277,6 +252,10 @@ export default {
277252
}
278253
279254
const container = this.$refs.sankeyContainer;
255+
if (!container || !container.parentElement) {
256+
// Ensure the container and its parent are accessible
257+
return;
258+
}
280259
d3.select(container).selectAll("*").remove(); // Clear the previous diagram
281260
282261
const nodeWidth = 30;
@@ -290,7 +269,8 @@ export default {
290269
const svg = d3.select(container)
291270
.attr("viewBox", `0 0 ${width} ${height}`)
292271
.attr("width", "100%")
293-
.attr("height", height);
272+
.attr("height", height)
273+
.classed("hide", false);
294274
295275
const sankeyGenerator = sankey()
296276
.nodeId((d) => d.id)
@@ -431,7 +411,7 @@ export default {
431411
.style("opacity", 1)
432412
.html(`
433413
<div style="padding-top: 4px; padding-bottom: 4px; padding-left: 8px; padding-right: 8px;">
434-
<p style="font-size: 0.6rem; margin-bottom: 0px;">#${d.id}</p>
414+
<p style="font-size: 0.6rem; margin-bottom: 0px;">#${d.taxon_id}</p>
435415
<div style="display: flex; justify-content: space-between; align-items: center;">
436416
<div style="font-weight: bold; font-size: 0.875rem;">${d.name}</div>
437417
<span style="background-color: rgba(255, 167, 38, 0.25); color: #ffa726; font-weight: bold; padding: 4px 8px; border-radius: 12px; font-size: 0.875rem; margin-left: 10px;">${d.rank}</span>
@@ -468,7 +448,7 @@ export default {
468448
// If the same node is clicked again, deselect it
469449
if (this.currentSelectedNode && this.currentSelectedNode.id === d.id) {
470450
this.currentSelectedNode = null;
471-
this.$emit("selectTaxon", { nodeId: null, descendantIds: null }); // Emit an empty array to show all IDs
451+
this.$emit("selectTaxon", { nodeId: null, descendantIds: null, db: this.db }); // Emit an empty array to show all IDs
472452
return;
473453
}
474454
@@ -483,7 +463,7 @@ export default {
483463
484464
// Function to collect all IDs of the current node and its descendants
485465
const collectIds = (node) => {
486-
let childrenIds = [node.id];
466+
let childrenIds = [node.taxon_id];
487467
childrenIds = childrenIds.concat(this.findChildren(this.rawData, node));
488468
return childrenIds;
489469
};
@@ -495,7 +475,7 @@ export default {
495475
this.currentSelectedNode = d;
496476
497477
// Emit the IDs array
498-
this.$emit("selectTaxon", { nodeId: d.id, descendantIds: allNodeIds });
478+
this.$emit("selectTaxon", { nodeId: d.taxon_id, descendantIds: allNodeIds, db: this.db });
499479
});
500480
;
501481
@@ -574,7 +554,7 @@ export default {
574554
for (let i = 0; i < rawData.length; i++) {
575555
const d = rawData[i];
576556
577-
if (d.taxon_id === selectedNode.id) {
557+
if (d.taxon_id === selectedNode.taxon_id) {
578558
// Start adding child nodes from here
579559
startAdding = true;
580560
continue; // Move to the next iteration to skip the current node

0 commit comments

Comments
 (0)