luisvalenzuelav commited on
Commit
0bd7232
·
verified ·
1 Parent(s): 920ccd2

Fix static explorer rendering: assets/app.js

Browse files
Files changed (1) hide show
  1. assets/app.js +21 -2
assets/app.js CHANGED
@@ -50,6 +50,23 @@ function csvDownload(filename, rows, columns){
50
  }
51
  function fmt(n){return Number(n).toLocaleString('en-US')}
52
  function pFmt(n){n=Number(n);return Number.isFinite(n)?(n<.001?n.toExponential(2):n.toPrecision(3)):'NA'}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
 
54
  function renderOverview(){
55
  table('assembly-table', state.data.assemblySummary, Object.keys(state.data.assemblySummary[0]));
@@ -97,8 +114,10 @@ async function renderDE(){
97
  const method=$('de-method').value, loaded=await loadDe(), rows=deFiltered(loaded.rows,method), entry=loaded.entry;
98
  if(!entry){$('de-summary').textContent='No differential-expression result is available for this selection.';return;}
99
  const foldCol=method==='DESeq2'?'log2FoldChange':'logFC', pCol=$('de-y').value==='pvalue'?(method==='DESeq2'?'pvalue':'PValue'):(method==='DESeq2'?'padj':'FDR');
100
- const traces=['down','up'].map(direction=>{const x=rows.filter(r=>r.direction===direction);return {type:'scatter',mode:'markers',name:direction,x:x.map(r=>r[foldCol]),y:x.map(r=>-Math.log10(Math.max(Number(r[pCol]),1e-300))),customdata:x.map(r=>r.gene_id),hovertemplate:'%{customdata}<br>Fold change: %{x:.3f}<br>-log10 probability: %{y:.2f}<extra></extra>',marker:{size:6}}});
101
- Plotly.newPlot('de-plot',traces,{template:'plotly_white',paper_bgcolor:'#fff',plot_bgcolor:'#f7fbfd',font:{color:'#123b5d'},height:620,title:`Volcano plot: ${method}`,xaxis:{title:foldCol},yaxis:{title:`-log10(${pCol})`},shapes:[{type:'line',x0:0,x1:0,y0:0,y1:1,yref:'paper',line:{dash:'dot',color:'#7890a0'}}]},{responsive:true});
 
 
102
  $('de-summary').innerHTML=`<strong>${method}</strong> compared <code>${esc(entry.group_a)}</code> (<strong>n = ${entry.n_group_a}</strong>) with <code>${esc(entry.group_b)}</code> (<strong>n = ${entry.n_group_b}</strong>). Of the <strong>${fmt(entry.n_genes_input)} genes</strong> in the expression matrix, <strong>${fmt(entry.n_genes_tested)}</strong> were retained for statistical testing. Using p-value &le; ${$('de-pvalue').value}, adjusted p-value / FDR &le; ${$('de-adjusted').value}, and absolute fold change &ge; ${$('de-fold').value}, <strong>${fmt(rows.length)} DEGs</strong> remain.`;
103
  const cols=method==='DESeq2'?['gene_id','baseMean','log2FoldChange','lfcSE','stat','pvalue','padj','direction']:['gene_id','logFC','logCPM','F','PValue','FDR','direction'];
104
  table('de-table',rows.slice(0,500),cols);$('de-download').onclick=()=>csvDownload(`${slugSafe($('de-species').value)}_de_filtered.csv`,rows,cols);
 
50
  }
51
  function fmt(n){return Number(n).toLocaleString('en-US')}
52
  function pFmt(n){n=Number(n);return Number.isFinite(n)?(n<.001?n.toExponential(2):n.toPrecision(3)):'NA'}
53
+ function plotLogP(rows, column){
54
+ const positive=rows.map(r=>Number(r[column])).filter(x=>Number.isFinite(x)&&x>0);
55
+ const observedMax=positive.length?Math.max(...positive.map(x=>-Math.log10(x))):0;
56
+ // Keep underflowed values visible without allowing them to create a 300-high axis.
57
+ const cap=Math.min(Math.max(5, observedMax+1),50);
58
+ return {
59
+ value:n=>{n=Number(n);return Number.isFinite(n)&&n>0?Math.min(-Math.log10(n),cap):cap},
60
+ cap,
61
+ capped:n=>{n=Number(n);return !Number.isFinite(n)||n<=0||-Math.log10(n)>=cap}
62
+ };
63
+ }
64
+ function plotPText(value, label, capped){
65
+ const n=Number(value);
66
+ if(!Number.isFinite(n))return `${label}: unavailable`;
67
+ if(n<=0)return `${label}: 0 (reported as 0; plotted at finite cap)`;
68
+ return `${label}: ${pFmt(n)}${capped?' (finite display cap)':''}`;
69
+ }
70
 
71
  function renderOverview(){
72
  table('assembly-table', state.data.assemblySummary, Object.keys(state.data.assemblySummary[0]));
 
114
  const method=$('de-method').value, loaded=await loadDe(), rows=deFiltered(loaded.rows,method), entry=loaded.entry;
115
  if(!entry){$('de-summary').textContent='No differential-expression result is available for this selection.';return;}
116
  const foldCol=method==='DESeq2'?'log2FoldChange':'logFC', pCol=$('de-y').value==='pvalue'?(method==='DESeq2'?'pvalue':'PValue'):(method==='DESeq2'?'padj':'FDR');
117
+ const yLabel=$('de-y').value==='pvalue'?'p-value':(method==='DESeq2'?'padj':'FDR');
118
+ const yTitle=`-log10(${yLabel})`, logP=plotLogP(rows,pCol);
119
+ const traces=['down','up'].map(direction=>{const x=rows.filter(r=>r.direction===direction);return {type:'scatter',mode:'markers',name:direction,x:x.map(r=>r[foldCol]),y:x.map(r=>logP.value(r[pCol])),customdata:x.map(r=>[r.gene_id,plotPText(r[pCol],yLabel,logP.capped(r[pCol]))]),hovertemplate:'%{customdata[0]}<br>Fold change: %{x:.3f}<br>'+yTitle+': %{y:.2f}<br>%{customdata[1]}<extra></extra>',marker:{size:6}}});
120
+ Plotly.newPlot('de-plot',traces,{template:'plotly_white',paper_bgcolor:'#fff',plot_bgcolor:'#f7fbfd',font:{color:'#123b5d'},height:620,title:`Volcano plot: ${method}`,xaxis:{title:foldCol},yaxis:{title:yTitle,range:[0,Math.max(logP.cap*1.08,1)]},shapes:[{type:'line',x0:0,x1:0,y0:0,y1:1,yref:'paper',line:{dash:'dot',color:'#7890a0'}}]},{responsive:true});
121
  $('de-summary').innerHTML=`<strong>${method}</strong> compared <code>${esc(entry.group_a)}</code> (<strong>n = ${entry.n_group_a}</strong>) with <code>${esc(entry.group_b)}</code> (<strong>n = ${entry.n_group_b}</strong>). Of the <strong>${fmt(entry.n_genes_input)} genes</strong> in the expression matrix, <strong>${fmt(entry.n_genes_tested)}</strong> were retained for statistical testing. Using p-value &le; ${$('de-pvalue').value}, adjusted p-value / FDR &le; ${$('de-adjusted').value}, and absolute fold change &ge; ${$('de-fold').value}, <strong>${fmt(rows.length)} DEGs</strong> remain.`;
122
  const cols=method==='DESeq2'?['gene_id','baseMean','log2FoldChange','lfcSE','stat','pvalue','padj','direction']:['gene_id','logFC','logCPM','F','PValue','FDR','direction'];
123
  table('de-table',rows.slice(0,500),cols);$('de-download').onclick=()=>csvDownload(`${slugSafe($('de-species').value)}_de_filtered.csv`,rows,cols);