PoonLab / covizu

Rapid analysis and visualization of coronavirus genome variation
https://filogeneti.ca/CoVizu/
MIT License
45 stars 20 forks source link

Mutation table does not display all mutations #386

Closed ArtPoon closed 2 years ago

ArtPoon commented 2 years ago

For example, BA.1.1 has 10 consensus mutations "and 41 others", but there are only 14 mutations listed in the table.

ArtPoon commented 2 years ago
>>> import json
>>> dbstats = json.load(open('dbstats.json'))
>>> len(dbstats)
3
>>> dbstats.keys()
dict_keys(['lastupdate', 'noseqs', 'lineages'])
>>> dbstats['lineages']['BA.1.1']
{'nsamples': 390400, 'lastcoldate': '2022-03-05', 'residual': 1.7059504314225222, 'max_ndiffs': 77, 'mean_ndiffs': 64.82966444672131, 'mutations': {'aa:orf1a:K856R': 0.9789421106557377, 'del:6513:3': 0.9930558401639344, 'aa:orf1a:A2710T': 0.9966649590163934, 'aa:orf1a:T3255I': 0.999436475409836, 'aa:orf1a:P3395H': 0.9801818647540984, 'del:11283:9': 0.9826793032786886, 'aa:orf1a:I3758V': 0.9988498975409836, 'aa:orf1b:P314L': 0.9998642418032787, 'aa:orf1b:I1566V': 0.9969313524590164, 'aa:S:A67V': 0.9952356557377049, 'del:21765:6': 0.9840676229508196, 'aa:S:T95I': 0.9869159836065574, 'del:21987:9': 0.9883145491803279, 'del:22194:3': 0.9782146516393443, 'ins:22205:9': 0.8729559426229508, 'aa:S:G339D': 0.9987115778688525, 'aa:S:R346K': 0.9981813524590164, 'aa:S:S371P': 0.9829918032786885, 'aa:S:S371F': 0.9841290983606558, 'aa:S:S373P': 0.9885835040983607, 'aa:S:S375F': 0.9901741803278689, 'aa:S:K417N': 0.8953329918032787, 'aa:S:N440K': 0.9339395491803278, 'aa:S:G446S': 0.9446644467213114, 'aa:S:S477N': 0.9842725409836065, 'aa:S:T478K': 0.9845594262295082, 'aa:S:E484A': 0.9809272540983607, 'aa:S:Q493R': 0.9805199795081967, 'aa:S:G496S': 0.9738934426229509, 'aa:S:Q498R': 0.9688037909836066, 'aa:S:N501Y': 0.9733478483606557, 'aa:S:Y505H': 0.9732684426229509, 'aa:S:T547K': 0.9988345286885246, 'aa:S:D614G': 0.99953125, 'aa:S:H655Y': 0.9994441598360656, 'aa:S:N679K': 0.999592725409836, 'aa:S:P681H': 0.9962961065573771, 'aa:S:N764K': 0.9867802254098361, 'aa:S:D796Y': 0.9962218237704918, 'aa:S:N856K': 0.9989856557377049, 'aa:S:Q954H': 0.9991726434426229, 'aa:S:N969K': 0.9988831967213114, 'aa:S:L981F': 0.9977074795081967, 'aa:E:T9I': 0.9969287909836065, 'aa:M:D3G': 0.9565701844262295, 'aa:M:Q19E': 0.9850537909836066, 'aa:M:A63T': 0.9925640368852459, 'aa:N:P13L': 0.996063012295082, 'del:28362:9': 0.9633965163934426, 'aa:N:R203K': 0.9917366803278689, 'aa:N:G204R': 0.9918032786885246}}
>>> len(dbstats['lineages']['BA.1.1']['mutations'])
51

Problem is not in the data

ArtPoon commented 2 years ago
> lineage = tips.filter(x => x.label1=='BA.1.1')[0]
> Object.keys(lineage['mutations']).length
51

it's loaded too

bonnielu commented 2 years ago

I think the problem is that the mutations table doesn't reload after a search; clicking on the lineage directly should yield the correct number of mutations. Will push a fix for this later today!

ArtPoon commented 2 years ago

You're right, I ran into this problem after searching for a specific lineage. Thanks!

ArtPoon commented 2 years ago

Yeah search needs to trigger a redraw of the table. Here's a suggested patch:

diff --git a/js/beadplot.js b/js/beadplot.js
index 5adf6e8..75508d3 100644
--- a/js/beadplot.js
+++ b/js/beadplot.js
@@ -1292,9 +1292,9 @@ function gen_mut_table(obj) {
     for (let j = 0; j < obj.length; j++) {

       // "zip" the sequence details of each sample
-      for (let i = 0; i < obj[j].mutations.length; i++) {
+      for (let i = 0; i < obj[j].mutation.length; i++) {
         let sample_details = [
-          obj[j].mutations[i],
+          obj[j].mutation[i],
           obj[j].frequency[i],
           []
           // obj[j].phenotype[i]  
@@ -1305,9 +1305,9 @@ function gen_mut_table(obj) {
   }
   else {
     // "zip" the sequence details of each sample
-    for (let i = 0; i < obj.mutations.length; i++) {
+    for (let i = 0; i < obj.mutation.length; i++) {
       let sample_details = [
-        obj.mutations[i],
+        obj.mutation[i],
         obj.frequency[i],
         []
         // obj.phenotype[i]  
diff --git a/js/covizu.js b/js/covizu.js
index 44373b9..dc7075e 100644
--- a/js/covizu.js
+++ b/js/covizu.js
@@ -264,7 +264,7 @@ req.done(function() {
     gentable(node.__data__);
     draw_region_distribution(node.__data__.allregions);
     gen_details_table(beaddata[node.__data__.cluster_idx].points);  // update details table with all samples
-    gen_mut_table({'mutations': mutations[cindex].mutation, 'frequency': mutations[cindex].frequency, 'phenotype': mutations[cindex].phenotype}) 
+    gen_mut_table(mutations[cindex]);
     draw_cluster_box(d3.select(node));
     draw_cluster_box(d3.select(node));
     draw_cluster_box(d3.select(node));
   }

diff --git a/js/drawtree.js b/js/drawtree.js
index 4244873..2f9540d 100644
--- a/js/drawtree.js
+++ b/js/drawtree.js
@@ -738,7 +738,7 @@ function click_cluster(d, cluster_info) {
     gentable(d);
     draw_region_distribution(d.allregions);
     gen_details_table(beaddata[d.cluster_idx].points);  // update details table with all samples
-    gen_mut_table({'mutations': mutations[d.cluster_idx].mutation, 'frequency': mutations[d.cluster_idx].frequency, 'phenotype': mutations[d.cluster_idx].phenotype})
+    gen_mut_table(mutations[d.cluster_idx]);

     // FIXME: this is the same div used for making barplot SVG
     $("#text-node").html(`Number of cases: ${d.count}<br/>Number of variants: ${d.varcount}<br/>`);
diff --git a/js/search.js b/js/search.js
index dc31600..f89a41e 100644
--- a/js/search.js
+++ b/js/search.js
@@ -246,7 +246,8 @@ function lineage_search(text_query) {
   beadplot(cluster_info.cluster_idx);
   gentable(cluster_info);
   draw_region_distribution(cluster_info.allregions);
-  gen_details_table(beaddata[cluster_info.cluster_idx].points); 
+  gen_details_table(beaddata[cluster_info.cluster_idx].points);
+  gen_mut_table(mutations[cluster_info.cluster_idx]);
 }

@@ -385,9 +386,9 @@ function select_clusters(rects) {
     cluster = d3.select(rects.nodes().pop());  // last element in array
     cluster.attr("class", "clicked");
     d3.select("#cidx-"+cidx).attr("class", "clicked");
-    
-    draw_cluster_box(cluster);

+    draw_cluster_box(cluster);
+    
     // switch to beadplot for this cluster
     beadplot(cluster.datum().cluster_idx);

Note this also tidies up calls to gen_mut_table, we shouldn't have to assemble a new Object every time.

ArtPoon commented 2 years ago

In the future we need to clean up this code, there's a lot of redundancy in calling functions.

bonnielu commented 2 years ago

Refactored it with your earlier suggestion and added a few lines so that it works with bead searching as well! Pushed the changes to dev for now

ArtPoon commented 2 years ago

Looks good, thanks @bonnielu . Let's do a quick, short PR with the language changes #384