ZeyuLing commited on
Commit
1e48036
·
verified ·
1 Parent(s): 3814b4c

Clarify metric directions in consolidated table

Browse files
Files changed (1) hide show
  1. index.html +2 -2
index.html CHANGED
@@ -43,11 +43,11 @@
43
  <script>
44
  const DATA=JSON.parse(document.getElementById("leaderboard-data").textContent);
45
  const rows=Object.freeze(DATA.rows.map(row=>({method:row.method,version:row.input,coverage:row.coverage,status:row.status,rankExcluded:!row.ranked||row.status!=="complete",isReference:row.method_id==="source_input",fid:row.metrics["FID"],r1:row.metrics["M2M Batch R@1"],r2:row.metrics["M2M Batch R@2"],r3:row.metrics["M2M Batch R@3"],m2m:row.metrics["M2M-Dist"],diversity:row.metrics["Diversity"]})));
46
- const groups={all:[{key:"fid",label:"FID",direction:"min",digits:4},{key:"r1",label:"R@1₃₂",direction:"max",digits:2},{key:"r2",label:"R@2₃₂",direction:"max",digits:2},{key:"r3",label:"R@3₃₂",direction:"max",digits:2},{key:"m2m",label:"M2M-Dist",direction:"min",digits:4},{key:"diversity",label:"Diversity",direction:"max",digits:2,referenceStatistic:true}]};
47
  const baseColumns=[{key:"method",label:"Method"},{key:"version",label:"Native input"},{key:"coverage",label:"Coverage"}];const colors=["#087d72","#315f9d","#c7563f","#ad6d00","#6e5aa5"];const state={view:"all",query:"",sortKey:"fid",sortDirection:"asc"};let barChart=null,radarChart=null;
48
  function rankable(row){return !row.rankExcluded}function chartable(row){return !row.isReference}function colorFor(row){const i=rows.filter(chartable).indexOf(row);return colors[(i<0?0:i)%colors.length]}function metric(key){return groups[state.view].find(item=>item.key===key)}function format(value,spec){if(value===null||value===undefined||Number.isNaN(Number(value)))return"–";if(spec&&spec.digits!==undefined)return Number(value).toFixed(spec.digits);return String(value)}function ranking(spec){if(spec.referenceStatistic)return[];return rows.filter(rankable).filter(row=>Number.isFinite(Number(row[spec.key]))).sort((a,b)=>spec.direction==="min"?a[spec.key]-b[spec.key]:b[spec.key]-a[spec.key])}function classFor(row,spec){if(!rankable(row))return"";const ranked=ranking(spec);if(ranked[0]===row)return"best";if(ranked[1]===row)return"second-best";return""}
49
  function filteredRows(){const q=state.query.trim().toLowerCase();const values=rows.filter(row=>!q||`${row.method} ${row.version}`.toLowerCase().includes(q));const spec=metric(state.sortKey);return values.sort((a,b)=>{const av=a[state.sortKey],bv=b[state.sortKey];if(typeof av==="number"&&typeof bv==="number")return state.sortDirection==="asc"?av-bv:bv-av;return String(av||"").localeCompare(String(bv||""))*(state.sortDirection==="asc"?1:-1)})}
50
- function renderTable(){const metrics=groups[state.view],columns=[...baseColumns,...metrics];document.getElementById("table-head").innerHTML=`<tr>${columns.map(col=>`<th data-key="${col.key}">${col.label}${state.sortKey===col.key?(state.sortDirection==="asc"?" ":" "):""}</th>`).join("")}</tr>`;const visible=filteredRows();document.getElementById("table-body").innerHTML=visible.map(row=>{const ranked=ranking(metrics.find(spec=>spec.key==="r3"));const place=rankable(row)&&ranked.indexOf(row)>=0?`<span class="rank${ranked.indexOf(row)===1?" second":""}">#${ranked.indexOf(row)+1}</span>`:row.isReference?`<span class="rank reference">REF</span>`:"";return`<tr><td class="method">${place}${row.method}</td><td class="version">${row.version}</td><td>${row.coverage}</td>${metrics.map(spec=>`<td class="${classFor(row,spec)}">${format(row[spec.key],spec)}</td>`).join("")}</tr>`}).join("");document.querySelectorAll("th[data-key]").forEach(head=>head.addEventListener("click",()=>{const key=head.dataset.key;if(state.sortKey===key)state.sortDirection=state.sortDirection==="asc"?"desc":"asc";else{state.sortKey=key;state.sortDirection=metric(key)?.direction==="min"?"asc":"desc"}renderTable()}))}
51
  function normalized(row,spec,ranked){const values=ranked.map(item=>Number(item[spec.key])).filter(Number.isFinite);if(!values.length)return 0;const min=Math.min(...values),max=Math.max(...values);if(max===min)return 100;return spec.direction==="min"?100*(max-row[spec.key])/(max-min):100*(row[spec.key]-min)/(max-min)}
52
  function renderCharts(){if(typeof Chart==="undefined")return;const specs=groups[state.view].filter(item=>!item.referenceStatistic),key=document.getElementById("chart-metric").value||specs[0].key,spec=specs.find(item=>item.key===key)||specs[0],measured=rows.filter(chartable).filter(row=>specs.some(item=>Number.isFinite(Number(row[item.key])))),ordered=[...measured].filter(row=>Number.isFinite(Number(row[spec.key]))).sort((a,b)=>spec.direction==="min"?a[spec.key]-b[spec.key]:b[spec.key]-a[spec.key]);document.getElementById("bar-note").textContent=`${spec.label}; ${spec.direction==="min"?"lower":"higher"} is better.`;barChart?.destroy();radarChart?.destroy();barChart=new Chart(document.getElementById("bar-chart"),{type:"bar",data:{labels:ordered.map(row=>row.method),datasets:[{data:ordered.map(row=>row[spec.key]),backgroundColor:ordered.map(colorFor),borderRadius:4}]},options:{animation:false,indexAxis:"y",responsive:true,maintainAspectRatio:false,plugins:{legend:{display:false}},scales:{x:{beginAtZero:true,grid:{color:"#e7ebe9"}},y:{grid:{display:false},ticks:{font:{size:13,weight:"600"},color:"#34413d"}}}}});radarChart=new Chart(document.getElementById("radar-chart"),{type:"radar",data:{labels:specs.map(item=>item.label),datasets:measured.map(row=>({label:row.method,data:specs.map(item=>normalized(row,item,measured)),borderColor:colorFor(row),backgroundColor:colorFor(row)+"18",pointRadius:2,borderWidth:2}))},options:{animation:false,responsive:true,maintainAspectRatio:false,scales:{r:{min:0,max:100,ticks:{display:false},pointLabels:{font:{size:12,weight:"600"},color:"#46534f"},grid:{color:"#e0e6e3"},angleLines:{color:"#e0e6e3"}}},plugins:{legend:{position:"bottom",labels:{boxWidth:12,boxHeight:12,padding:14,color:"#34413d"}}}}})}
53
  function configureMetrics(){const select=document.getElementById("chart-metric"),specs=groups[state.view].filter(item=>!item.referenceStatistic);select.innerHTML=specs.map(item=>`<option value="${item.key}">${item.label}</option>`).join("");state.sortKey=specs[0].key;state.sortDirection=specs[0].direction==="min"?"asc":"desc";renderTable();renderCharts()}
 
43
  <script>
44
  const DATA=JSON.parse(document.getElementById("leaderboard-data").textContent);
45
  const rows=Object.freeze(DATA.rows.map(row=>({method:row.method,version:row.input,coverage:row.coverage,status:row.status,rankExcluded:!row.ranked||row.status!=="complete",isReference:row.method_id==="source_input",fid:row.metrics["FID"],r1:row.metrics["M2M Batch R@1"],r2:row.metrics["M2M Batch R@2"],r3:row.metrics["M2M Batch R@3"],m2m:row.metrics["M2M-Dist"],diversity:row.metrics["Diversity"]})));
46
+ const groups={all:[{key:"fid",label:"FID",direction:"min",digits:4},{key:"r1",label:"R@1₃₂",direction:"max",digits:2},{key:"r2",label:"R@2₃₂",direction:"max",digits:2},{key:"r3",label:"R@3₃₂",direction:"max",digits:2},{key:"m2m",label:"M2M-Dist",direction:"min",digits:4},{key:"diversity",label:"Diversity",direction:"max",digits:2,referenceStatistic:true}]};
47
  const baseColumns=[{key:"method",label:"Method"},{key:"version",label:"Native input"},{key:"coverage",label:"Coverage"}];const colors=["#087d72","#315f9d","#c7563f","#ad6d00","#6e5aa5"];const state={view:"all",query:"",sortKey:"fid",sortDirection:"asc"};let barChart=null,radarChart=null;
48
  function rankable(row){return !row.rankExcluded}function chartable(row){return !row.isReference}function colorFor(row){const i=rows.filter(chartable).indexOf(row);return colors[(i<0?0:i)%colors.length]}function metric(key){return groups[state.view].find(item=>item.key===key)}function format(value,spec){if(value===null||value===undefined||Number.isNaN(Number(value)))return"–";if(spec&&spec.digits!==undefined)return Number(value).toFixed(spec.digits);return String(value)}function ranking(spec){if(spec.referenceStatistic)return[];return rows.filter(rankable).filter(row=>Number.isFinite(Number(row[spec.key]))).sort((a,b)=>spec.direction==="min"?a[spec.key]-b[spec.key]:b[spec.key]-a[spec.key])}function classFor(row,spec){if(!rankable(row))return"";const ranked=ranking(spec);if(ranked[0]===row)return"best";if(ranked[1]===row)return"second-best";return""}
49
  function filteredRows(){const q=state.query.trim().toLowerCase();const values=rows.filter(row=>!q||`${row.method} ${row.version}`.toLowerCase().includes(q));const spec=metric(state.sortKey);return values.sort((a,b)=>{const av=a[state.sortKey],bv=b[state.sortKey];if(typeof av==="number"&&typeof bv==="number")return state.sortDirection==="asc"?av-bv:bv-av;return String(av||"").localeCompare(String(bv||""))*(state.sortDirection==="asc"?1:-1)})}
50
+ function renderTable(){const metrics=groups[state.view],columns=[...baseColumns,...metrics];document.getElementById("table-head").innerHTML=`<tr>${columns.map(col=>`<th data-key="${col.key}">${col.label}${state.sortKey===col.key?(state.sortDirection==="asc"?" ":" "):""}</th>`).join("")}</tr>`;const visible=filteredRows();document.getElementById("table-body").innerHTML=visible.map(row=>{const ranked=ranking(metrics.find(spec=>spec.key==="r3"));const place=rankable(row)&&ranked.indexOf(row)>=0?`<span class="rank${ranked.indexOf(row)===1?" second":""}">#${ranked.indexOf(row)+1}</span>`:row.isReference?`<span class="rank reference">REF</span>`:"";return`<tr><td class="method">${place}${row.method}</td><td class="version">${row.version}</td><td>${row.coverage}</td>${metrics.map(spec=>`<td class="${classFor(row,spec)}">${format(row[spec.key],spec)}</td>`).join("")}</tr>`}).join("");document.querySelectorAll("th[data-key]").forEach(head=>head.addEventListener("click",()=>{const key=head.dataset.key;if(state.sortKey===key)state.sortDirection=state.sortDirection==="asc"?"desc":"asc";else{state.sortKey=key;state.sortDirection=metric(key)?.direction==="min"?"asc":"desc"}renderTable()}))}
51
  function normalized(row,spec,ranked){const values=ranked.map(item=>Number(item[spec.key])).filter(Number.isFinite);if(!values.length)return 0;const min=Math.min(...values),max=Math.max(...values);if(max===min)return 100;return spec.direction==="min"?100*(max-row[spec.key])/(max-min):100*(row[spec.key]-min)/(max-min)}
52
  function renderCharts(){if(typeof Chart==="undefined")return;const specs=groups[state.view].filter(item=>!item.referenceStatistic),key=document.getElementById("chart-metric").value||specs[0].key,spec=specs.find(item=>item.key===key)||specs[0],measured=rows.filter(chartable).filter(row=>specs.some(item=>Number.isFinite(Number(row[item.key])))),ordered=[...measured].filter(row=>Number.isFinite(Number(row[spec.key]))).sort((a,b)=>spec.direction==="min"?a[spec.key]-b[spec.key]:b[spec.key]-a[spec.key]);document.getElementById("bar-note").textContent=`${spec.label}; ${spec.direction==="min"?"lower":"higher"} is better.`;barChart?.destroy();radarChart?.destroy();barChart=new Chart(document.getElementById("bar-chart"),{type:"bar",data:{labels:ordered.map(row=>row.method),datasets:[{data:ordered.map(row=>row[spec.key]),backgroundColor:ordered.map(colorFor),borderRadius:4}]},options:{animation:false,indexAxis:"y",responsive:true,maintainAspectRatio:false,plugins:{legend:{display:false}},scales:{x:{beginAtZero:true,grid:{color:"#e7ebe9"}},y:{grid:{display:false},ticks:{font:{size:13,weight:"600"},color:"#34413d"}}}}});radarChart=new Chart(document.getElementById("radar-chart"),{type:"radar",data:{labels:specs.map(item=>item.label),datasets:measured.map(row=>({label:row.method,data:specs.map(item=>normalized(row,item,measured)),borderColor:colorFor(row),backgroundColor:colorFor(row)+"18",pointRadius:2,borderWidth:2}))},options:{animation:false,responsive:true,maintainAspectRatio:false,scales:{r:{min:0,max:100,ticks:{display:false},pointLabels:{font:{size:12,weight:"600"},color:"#46534f"},grid:{color:"#e0e6e3"},angleLines:{color:"#e0e6e3"}}},plugins:{legend:{position:"bottom",labels:{boxWidth:12,boxHeight:12,padding:14,color:"#34413d"}}}}})}
53
  function configureMetrics(){const select=document.getElementById("chart-metric"),specs=groups[state.view].filter(item=>!item.referenceStatistic);select.innerHTML=specs.map(item=>`<option value="${item.key}">${item.label}</option>`).join("");state.sortKey=specs[0].key;state.sortDirection=specs[0].direction==="min"?"asc":"desc";renderTable();renderCharts()}