Spaces:
Running
Running
Download assets/pareto.js from SimWorld-AI/Code4Scene: direct link, hf CLI and curl.
- Browser
- Download file 6.16 kB
-
https://huggingface.co/spaces/SimWorld-AI/Code4Scene/resolve/main/assets/pareto.js
- Command line
-
hf download hf://spaces/SimWorld-AI/Code4Scene/assets/pareto.js
-
curl -L -o pareto.js https://huggingface.co/spaces/SimWorld-AI/Code4Scene/resolve/main/assets/pareto.js
6.16 kB
| import {bindChartTooltip} from "./chart-interactions.js?v=20261004kit"; | |
| // Adapted from BuildingBench's figure-kit/pareto-frontier/render.py and live SVG. | |
| // Domain, costs and scores are exclusively Code4Scene's historical paper evaluation. | |
| const NS='http://www.w3.org/2000/svg'; | |
| const colors={openai:'#10A37F',claude:'#D97757',gemini:'#7b1fa2',meta:'#42a5f5',deepseek:'#3f51e0',zai:'#96650b',grok:'#111111',qwen:'#fe7016',thinkingmachines:'#686868'}; | |
| const data=await fetch('data/pareto.json?v=20261001b').then(r=>r.json()); | |
| await Promise.all([document.fonts.load('400 13px Inter'),document.fonts.load('700 16px Inter')]); | |
| const measure=document.createElement('canvas').getContext('2d'); | |
| function node(tag,attrs,text){const n=document.createElementNS(NS,tag);for(const[k,v]of Object.entries(attrs))n.setAttribute(k,v);if(text!==undefined)n.textContent=text;return n;} | |
| const lum=c=>{const a=c.match(/\w\w/g).map(x=>parseInt(x,16)/255).map(x=>x<=.03928?x/12.92:((x+.055)/1.055)**2.4);return .2126*a[0]+.7152*a[1]+.0722*a[2];}; | |
| function labelColor(hex,front){let a=hex.slice(1).match(/../g).map(x=>parseInt(x,16)/255),max=Math.max(...a),min=Math.min(...a),l=(max+min)/2,h=0,s=0,d=max-min;if(d){s=d/(1-Math.abs(2*l-1));h=max===a[0]?((a[1]-a[2])/d)%6:max===a[1]?(a[2]-a[0])/d+2:(a[0]-a[1])/d+4;h=(h/6+1)%1;}s=Math.min(s,front?.92:.55);const rgb=l=>{const c=(1-Math.abs(2*l-1))*s,x=c*(1-Math.abs(h*6%2-1)),m=l-c/2;const q=h<1/6?[c,x,0]:h<2/6?[x,c,0]:h<3/6?[0,c,x]:h<4/6?[0,x,c]:h<5/6?[x,0,c]:[c,0,x];return '#'+q.map(v=>Math.round((v+m)*255).toString(16).padStart(2,'0')).join('');};const target=front?4.6:2.9;if(front&&(lum('fffefb')+.05)/(lum(hex.slice(1))+.05)>=target)return hex;let lo=0,hi=1;for(let i=0;i<26;i++){let mid=(lo+hi)/2;if((lum('fffefb')+.05)/(lum(rgb(mid).slice(1))+.05)>target)lo=mid;else hi=mid;}return rgb((lo+hi)/2);} | |
| for(const svg of document.querySelectorAll('.pareto-svg')){ | |
| const rows=data[svg.dataset.mode],front=rows.filter(a=>!rows.some(b=>b.cost<=a.cost&&b.score>=a.score&&(b.cost<a.cost||b.score>a.score))).sort((a,b)=>b.cost-a.cost),on=new Set(front.map(d=>d.key)); | |
| const lo=Math.min(...rows.map(d=>-Math.log10(d.cost)))-.30,hi=Math.max(...rows.map(d=>-Math.log10(d.cost)))+.30; | |
| const x=c=>96+(-Math.log10(c)-lo)/(hi-lo)*1074,y=s=>473.2-s/.96*448; | |
| const add=(tag,attrs,text)=>{const n=node(tag,attrs,text);svg.append(n);return n;}; | |
| add('rect',{x:0,y:0,width:1200,height:560,fill:'#fffefb'}); | |
| for(const t of [0,.24,.48,.72,.96]){add('line',{x1:96,x2:1170,y1:y(t),y2:y(t),class:'grid'});add('text',{x:84,y:y(t)+4,class:'tick','text-anchor':'end'},t.toFixed(2));} | |
| for(const c of [100,50,20,10,5,2,1,.5,.2,.1,.05,.02,.01,.005,.002,.001])if(-Math.log10(c)>lo&&-Math.log10(c)<hi){add('line',{x1:x(c),x2:x(c),y1:25.2,y2:473.2,class:'grid vertical'});add('text',{x:x(c),y:499,class:'tick','text-anchor':'middle'},'$'+c);} | |
| add('line',{x1:96,x2:1170,y1:473.2,y2:473.2,class:'axis'}); | |
| add('text',{x:633,y:539,class:'axis-title','text-anchor':'middle'},'Mean Cost per Case (USD) · cheaper →'); | |
| add('text',{x:27,y:249,transform:'rotate(-90 27 249)',class:'axis-title','text-anchor':'middle'},{t2s:'Text-to-Scene Score',i2s:'Image-to-Scene Score'}[svg.dataset.mode]); | |
| const path=front.map((d,i)=>(i?'L':'M')+x(d.cost)+','+y(d.score)).join(' '); | |
| add('path',{d:path,class:'frontier-halo'});add('path',{d:path,class:'frontier-line'}); | |
| const points=rows.map(d=>({x:x(d.cost),y:y(d.score)}));const boxes=points.map(p=>[p.x-9,p.y-9,p.x+9,p.y+9]); | |
| const linePoints=[];for(let i=1;i<front.length;i++){const a=front[i-1],b=front[i],n=Math.max(2,Math.ceil(Math.hypot(x(b.cost)-x(a.cost),y(b.score)-y(a.score))/5));for(let j=0;j<=n;j++)linePoints.push([x(a.cost)+(x(b.cost)-x(a.cost))*j/n,y(a.score)+(y(b.score)-y(a.score))*j/n]);} | |
| for(const d of [...rows].sort((a,b)=>(on.has(b.key)-on.has(a.key))||b.score-a.score)){ | |
| const isFront=on.has(d.key),cx=x(d.cost),cy=y(d.score),font=isFront?16:12.5,name=d.name.replace(/^Claude /,'').replace(/\((.*?)\)/,(_,s)=>'('+s.replace(/\b\w/g,c=>c.toUpperCase())+')'),size=font; | |
| measure.font=`${isFront?700:400} ${size}px Inter`;const tw=measure.measureText(name).width,th=size*.78,r=9,gap=5,pad=2.5,up=r+gap,dn=r+gap+th; | |
| const candidates=[];for(let k=0;k<5;k++){const lift=k*th*1.55;candidates.push([0,-up-lift,'middle'],[0,dn+lift,'middle'],[r+gap,th*.4-lift,'start'],[-r-gap,th*.4-lift,'end'],[r+gap,th*.4+lift,'start'],[-r-gap,th*.4+lift,'end'],[r*.6,-up*.82-lift,'start'],[-r*.6,-up*.82-lift,'end'],[r*.6,dn*.9+lift,'start'],[-r*.6,dn*.9+lift,'end']);} | |
| const hard=[...boxes,...linePoints.filter(p=>Math.hypot(p[0]-cx,p[1]-cy)>r*2.4).map(p=>[p[0]-4,p[1]-4,p[0]+4,p[1]+4])];let best,bestCost=Infinity; | |
| for(let i=0;i<candidates.length;i++){const[dx,dy,anchor]=candidates[i],tx=cx+dx,ty=cy+dy,x0=anchor==='middle'?tx-tw/2:anchor==='end'?tx-tw:tx,b=[x0-pad,ty-th-pad,x0+tw+pad,ty+pad];let cost=i*.6;if(b[0]<58)cost+=400+58-b[0];if(b[2]>1180)cost+=400+b[2]-1180;if(b[1]<9)cost+=400+9-b[1];if(b[3]>475)cost+=400+b[3]-475;let overlap=0;for(const q of hard){const w=Math.min(b[2],q[2])-Math.max(b[0],q[0]),h=Math.min(b[3],q[3])-Math.max(b[1],q[1]);if(w>0&&h>0)overlap+=w*h;}cost+=overlap*4;if(cost<bestCost){bestCost=cost;best={dx,dy,anchor,b};}if(!overlap&&cost<400)break;} | |
| boxes.push(best.b);const color=colors[d.logo]||'#686868',label=labelColor(color,isFront); | |
| const g=add('g',{class:'pareto-node'+(isFront?' is-frontier':''),tabindex:0,role:'img','aria-label':`${d.name}, score ${d.score.toFixed(6)}, mean cost $${d.cost.toFixed(6)}${isFront?', Pareto frontier':''}`,'data-name':d.name,'data-score':d.score,'data-cost':d.cost,'data-frontier':isFront}); | |
| if(isFront)g.append(node('circle',{cx,cy,r:9,fill:'none',stroke:color,'stroke-width':1.3})); | |
| g.append(node('rect',{x:cx-5,y:cy-5,width:10,height:10,rx:1,fill:color,stroke:'#fffefb','stroke-width':1.7,class:'chip'})); | |
| g.append(node('text',{x:cx+best.dx,y:cy+best.dy,'text-anchor':best.anchor,fill:label,'font-size':font,'font-weight':isFront?700:400,class:'model-label'},name)); | |
| g.append(node('circle',{cx,cy,r:14,fill:'transparent'})); | |
| bindChartTooltip(g,svg,d.key,svg.dataset.mode,'.chip'); | |
| } | |
| svg.dataset.ready='true'; | |
| } | |