lvwerra HF Staff commited on
Commit
3869686
路
verified 路
1 Parent(s): fb408b6

Add radial locus bars and Genome Atlas node silhouettes

Browse files
app.js CHANGED
@@ -58,7 +58,7 @@ function draw(){if(!gl)return;let dpr=canvas.width/W;gl.viewport(0,0,canvas.widt
58
  ctx.setTransform(dpr,0,0,dpr,0,0);ctx.clearRect(0,0,W,H);drawLoci();
59
  if(zoom<2){let c=screen([0,0]);ctx.textAlign='center';ctx.fillStyle='#14221c';ctx.font='700 17px Manrope';ctx.fillText(fmt(leaves.length),c[0],c[1]+1);ctx.fillStyle='#748078';ctx.font='9px Inter';ctx.fillText('assembly strands',c[0],c[1]+18);}
60
  const labels=zoom<2.5?groups:[...nodes.values()].filter(n=>['family','order','genus'].includes(n.rank)&&n.count>10&&n.count<leaves.length/zoom*.6);
61
- let placed=[];for(const n of labels){let angle=START+SPAN*(n.mid+.5)/leaves.length;let [x,y]=screen(polar(R+BAR_HEIGHT+42,angle));if(x<35||x>W-35||y<25||y>H-25)continue;let name=n.common||n.name;if(name.length>27)name=n.name;ctx.font=(zoom<2.5?'500 13px':'500 12px')+' Inter';let tw=ctx.measureText(name).width,anchor=Math.cos(angle)>.25?'left':Math.cos(angle)<-.25?'right':'center';let bx=anchor==='left'?x:anchor==='right'?x-tw:x-tw/2;if(bx<8){x+=8-bx;bx=8}if(bx+tw>W-8){x-=bx+tw-W+8;bx=W-8-tw}if(placed.some(b=>bx<b.x+b.w+8&&bx+tw>b.x-8&&Math.abs(y-b.y)<32))continue;placed.push({x:bx,y,w:tw});ctx.textAlign=anchor;ctx.fillStyle='#273b30';ctx.strokeStyle='#fff';ctx.lineWidth=4;ctx.strokeText(name,x,y);ctx.fillText(name,x,y);ctx.font='10px Inter';ctx.fillStyle='#7a857f';ctx.strokeText(fmt(n.count)+' assemblies',x,y+15);ctx.fillText(fmt(n.count)+' assemblies',x,y+15);}
62
  drawAtlasIcons();
63
  if(selected){const a=selected;ctx.strokeStyle='#15392c';ctx.lineWidth=1.8;ctx.beginPath();let p=screen(a.points[0]);ctx.moveTo(...p);for(let j=1;j<a.points.length;j++){let [c,d]=controls(a.points[j-1],a.points[j]);ctx.bezierCurveTo(...screen(c),...screen(d),...screen(a.points[j]));}ctx.stroke();let q=screen(a.tip);ctx.fillStyle='#15392c';ctx.beginPath();ctx.arc(...q,4,0,TAU);ctx.fill();}
64
  $('#zoom-readout').textContent=zoom.toFixed(1)+'脳';$('#zoomout').disabled=zoom<=1;$('#zoomin').disabled=zoom>=320;
 
58
  ctx.setTransform(dpr,0,0,dpr,0,0);ctx.clearRect(0,0,W,H);drawLoci();
59
  if(zoom<2){let c=screen([0,0]);ctx.textAlign='center';ctx.fillStyle='#14221c';ctx.font='700 17px Manrope';ctx.fillText(fmt(leaves.length),c[0],c[1]+1);ctx.fillStyle='#748078';ctx.font='9px Inter';ctx.fillText('assembly strands',c[0],c[1]+18);}
60
  const labels=zoom<2.5?groups:[...nodes.values()].filter(n=>['family','order','genus'].includes(n.rank)&&n.count>10&&n.count<leaves.length/zoom*.6);
61
+ let placed=locusMode!=='off'&&zoom<1.6?[{x:W/2+pan.x-36,y:screen(polar(R+BAR_GAP+BAR_HEIGHT,START))[1]-14,w:72}]:[];for(const n of labels){let angle=START+SPAN*(n.mid+.5)/leaves.length;let [x,y]=screen(polar(R+BAR_HEIGHT+42,angle));if(x<35||x>W-35||y<25||y>H-25)continue;let name=n.common||n.name;if(name.length>27)name=n.name;ctx.font=(zoom<2.5?'500 13px':'500 12px')+' Inter';ctx.save();ctx.font='10px Inter';let cw=ctx.measureText(fmt(n.count)+' assemblies').width;ctx.restore();let tw=Math.max(ctx.measureText(name).width,cw),anchor=Math.cos(angle)>.25?'left':Math.cos(angle)<-.25?'right':'center';let bx=anchor==='left'?x:anchor==='right'?x-tw:x-tw/2;if(bx<8){x+=8-bx;bx=8}if(bx+tw>W-8){x-=bx+tw-W+8;bx=W-8-tw}if(placed.some(b=>bx<b.x+b.w+8&&bx+tw>b.x-8&&Math.abs(y-b.y)<32))continue;placed.push({x:bx,y,w:tw});ctx.textAlign=anchor;ctx.fillStyle='#273b30';ctx.strokeStyle='#fff';ctx.lineWidth=4;ctx.strokeText(name,x,y);ctx.fillText(name,x,y);ctx.font='10px Inter';ctx.fillStyle='#7a857f';ctx.strokeText(fmt(n.count)+' assemblies',x,y+15);ctx.fillText(fmt(n.count)+' assemblies',x,y+15);}
62
  drawAtlasIcons();
63
  if(selected){const a=selected;ctx.strokeStyle='#15392c';ctx.lineWidth=1.8;ctx.beginPath();let p=screen(a.points[0]);ctx.moveTo(...p);for(let j=1;j<a.points.length;j++){let [c,d]=controls(a.points[j-1],a.points[j]);ctx.bezierCurveTo(...screen(c),...screen(d),...screen(a.points[j]));}ctx.stroke();let q=screen(a.tip);ctx.fillStyle='#15392c';ctx.beginPath();ctx.arc(...q,4,0,TAU);ctx.fill();}
64
  $('#zoom-readout').textContent=zoom.toFixed(1)+'脳';$('#zoomout').disabled=zoom<=1;$('#zoomin').disabled=zoom>=320;
carbon-a-strand-poc.png CHANGED

Git LFS Details

  • SHA256: 2d8c0ec92386b246470d45388ccea8d8f1a3d5717198be0ead202bc5613fa1e2
  • Pointer size: 132 Bytes
  • Size of remote file: 2.88 MB

Git LFS Details

  • SHA256: 29e293a77927226c3f523e7a552f16cd7f868adca757003ba3c76a29a3ff8d59
  • Pointer size: 132 Bytes
  • Size of remote file: 2.88 MB
carbon-a-strand-source.zip CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:cf7b4abb7fe337a230bd69e3cb29159f6807ae2c2f225dd537683279c4adee12
3
- size 15045565
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:e48117ae3d5d95dd78e08ac29ad37d431d0429095b423bf4d6c10d56e9afadf0
3
+ size 15045655
export_still.py CHANGED
@@ -8,6 +8,6 @@ with sync_playwright() as p:
8
  page=b.new_page(viewport={'width':1200,'height':1420},device_scale_factor=2)
9
  page.goto((R/'index.html').as_uri());page.wait_for_function('window.POC && !document.querySelector("#loading")')
10
  page.add_style_tag(content='''header{height:90px;padding:0 50px}.brand{font-size:29px}.header-right button{display:none}main{display:block;height:1330px;min-height:1330px}aside,.topbar,.controls,.help,#selection{display:none!important}.stage-wrap{height:100%}#stage{inset:132px 22px 120px}.poster-heading{position:absolute;left:50px;top:35px}.poster-heading h1{font-size:39px;letter-spacing:-1.5px;margin-bottom:11px}.poster-heading p{font-size:15px;color:#6e7b73;margin:0}.poster-footer{position:absolute;bottom:20px;left:50px;right:50px;border-top:1px solid #e6ece8;padding-top:22px}.poster-key{display:flex;justify-content:space-between;font-size:16px;font-weight:500}.poster-key span{display:flex;align-items:center;gap:12px}.poster-key i{width:34px;height:2px;background:#00b86b;display:inline-block}.poster-key i.blue{background:#4167ec}.poster-footer p{font-size:11px;line-height:1.7;color:#6e7b73;margin-top:18px}''')
11
- page.evaluate('''() => {document.querySelector('.stage-wrap').insertAdjacentHTML('beforeend',`<div class="poster-heading"><h1>One assembly. One strand.</h1><p>33,588 assemblies 路 outer bars sum predicted coding loci across 50 adjacent strands.</p></div><div class="poster-footer"><div class="poster-key"><span><i></i>29,350 with no annotation record listed</span><span><i class="blue"></i>4,238 with existing annotation records</span></div><p>Proof of concept: 33,588 of the release鈥檚 48,167 assemblies. Colours reflect GenBank annotation records in the 7 October 2026 snapshot.<br>Locus bars use available counts; grey base marks show missing counts. Branch length is not evolutionary time.<br>Genome Atlas silhouettes: PhyloPic. Original image credits and licences are included in the interactive preview.</p></div>`)}''')
12
- page.evaluate("document.querySelector('.poster-heading p').textContent='33,588 assemblies 路 '+shortCount(POC.locusTotal)+' loci across '+fmt(POC.locusAvailable)+' assemblies with counts.'");page.wait_for_timeout(800);page.screenshot(path=str(R/'carbon-a-strand-poc.png'));b.close()
13
  print(R/'carbon-a-strand-poc.png')
 
8
  page=b.new_page(viewport={'width':1200,'height':1420},device_scale_factor=2)
9
  page.goto((R/'index.html').as_uri());page.wait_for_function('window.POC && !document.querySelector("#loading")')
10
  page.add_style_tag(content='''header{height:90px;padding:0 50px}.brand{font-size:29px}.header-right button{display:none}main{display:block;height:1330px;min-height:1330px}aside,.topbar,.controls,.help,#selection{display:none!important}.stage-wrap{height:100%}#stage{inset:132px 22px 120px}.poster-heading{position:absolute;left:50px;top:35px}.poster-heading h1{font-size:39px;letter-spacing:-1.5px;margin-bottom:11px}.poster-heading p{font-size:15px;color:#6e7b73;margin:0}.poster-footer{position:absolute;bottom:20px;left:50px;right:50px;border-top:1px solid #e6ece8;padding-top:22px}.poster-key{display:flex;justify-content:space-between;font-size:16px;font-weight:500}.poster-key span{display:flex;align-items:center;gap:12px}.poster-key i{width:34px;height:2px;background:#00b86b;display:inline-block}.poster-key i.blue{background:#4167ec}.poster-footer p{font-size:11px;line-height:1.7;color:#6e7b73;margin-top:18px}''')
11
+ page.evaluate('''() => {document.querySelector('.stage-wrap').insertAdjacentHTML('beforeend',`<div class="poster-heading"><h1>One assembly. One strand.</h1><p>33,588 assemblies 路 outer bars sum predicted coding loci across 50 adjacent strands.</p></div><div class="poster-footer"><div class="poster-key"><span><i></i>29,350 with no annotation record listed</span><span><i class="blue"></i>4,238 with existing annotation records</span></div><p>Proof of concept: 33,588 of the release鈥檚 48,167 assemblies. Colours reflect GenBank annotation records in the 7 October 2026 snapshot.<br>Outer bars sum available loci across up to 50 assembly strands; grey base marks show missing counts. Branch length is not evolutionary time.<br>Genome Atlas silhouettes: PhyloPic. Original image credits and licences are included in the interactive preview.</p></div>`)}''')
12
+ page.evaluate("document.querySelector('.poster-heading p').textContent='33,588 assemblies 路 '+shortCount(POC.locusTotal)+' predicted loci across '+fmt(POC.locusAvailable)+' assemblies with counts.'");page.wait_for_timeout(800);page.screenshot(path=str(R/'carbon-a-strand-poc.png'));b.close()
13
  print(R/'carbon-a-strand-poc.png')
index.html CHANGED
@@ -141,7 +141,7 @@ function draw(){if(!gl)return;let dpr=canvas.width/W;gl.viewport(0,0,canvas.widt
141
  ctx.setTransform(dpr,0,0,dpr,0,0);ctx.clearRect(0,0,W,H);drawLoci();
142
  if(zoom<2){let c=screen([0,0]);ctx.textAlign='center';ctx.fillStyle='#14221c';ctx.font='700 17px Manrope';ctx.fillText(fmt(leaves.length),c[0],c[1]+1);ctx.fillStyle='#748078';ctx.font='9px Inter';ctx.fillText('assembly strands',c[0],c[1]+18);}
143
  const labels=zoom<2.5?groups:[...nodes.values()].filter(n=>['family','order','genus'].includes(n.rank)&&n.count>10&&n.count<leaves.length/zoom*.6);
144
- let placed=[];for(const n of labels){let angle=START+SPAN*(n.mid+.5)/leaves.length;let [x,y]=screen(polar(R+BAR_HEIGHT+42,angle));if(x<35||x>W-35||y<25||y>H-25)continue;let name=n.common||n.name;if(name.length>27)name=n.name;ctx.font=(zoom<2.5?'500 13px':'500 12px')+' Inter';let tw=ctx.measureText(name).width,anchor=Math.cos(angle)>.25?'left':Math.cos(angle)<-.25?'right':'center';let bx=anchor==='left'?x:anchor==='right'?x-tw:x-tw/2;if(bx<8){x+=8-bx;bx=8}if(bx+tw>W-8){x-=bx+tw-W+8;bx=W-8-tw}if(placed.some(b=>bx<b.x+b.w+8&&bx+tw>b.x-8&&Math.abs(y-b.y)<32))continue;placed.push({x:bx,y,w:tw});ctx.textAlign=anchor;ctx.fillStyle='#273b30';ctx.strokeStyle='#fff';ctx.lineWidth=4;ctx.strokeText(name,x,y);ctx.fillText(name,x,y);ctx.font='10px Inter';ctx.fillStyle='#7a857f';ctx.strokeText(fmt(n.count)+' assemblies',x,y+15);ctx.fillText(fmt(n.count)+' assemblies',x,y+15);}
145
  drawAtlasIcons();
146
  if(selected){const a=selected;ctx.strokeStyle='#15392c';ctx.lineWidth=1.8;ctx.beginPath();let p=screen(a.points[0]);ctx.moveTo(...p);for(let j=1;j<a.points.length;j++){let [c,d]=controls(a.points[j-1],a.points[j]);ctx.bezierCurveTo(...screen(c),...screen(d),...screen(a.points[j]));}ctx.stroke();let q=screen(a.tip);ctx.fillStyle='#15392c';ctx.beginPath();ctx.arc(...q,4,0,TAU);ctx.fill();}
147
  $('#zoom-readout').textContent=zoom.toFixed(1)+'脳';$('#zoomout').disabled=zoom<=1;$('#zoomin').disabled=zoom>=320;
 
141
  ctx.setTransform(dpr,0,0,dpr,0,0);ctx.clearRect(0,0,W,H);drawLoci();
142
  if(zoom<2){let c=screen([0,0]);ctx.textAlign='center';ctx.fillStyle='#14221c';ctx.font='700 17px Manrope';ctx.fillText(fmt(leaves.length),c[0],c[1]+1);ctx.fillStyle='#748078';ctx.font='9px Inter';ctx.fillText('assembly strands',c[0],c[1]+18);}
143
  const labels=zoom<2.5?groups:[...nodes.values()].filter(n=>['family','order','genus'].includes(n.rank)&&n.count>10&&n.count<leaves.length/zoom*.6);
144
+ let placed=locusMode!=='off'&&zoom<1.6?[{x:W/2+pan.x-36,y:screen(polar(R+BAR_GAP+BAR_HEIGHT,START))[1]-14,w:72}]:[];for(const n of labels){let angle=START+SPAN*(n.mid+.5)/leaves.length;let [x,y]=screen(polar(R+BAR_HEIGHT+42,angle));if(x<35||x>W-35||y<25||y>H-25)continue;let name=n.common||n.name;if(name.length>27)name=n.name;ctx.font=(zoom<2.5?'500 13px':'500 12px')+' Inter';ctx.save();ctx.font='10px Inter';let cw=ctx.measureText(fmt(n.count)+' assemblies').width;ctx.restore();let tw=Math.max(ctx.measureText(name).width,cw),anchor=Math.cos(angle)>.25?'left':Math.cos(angle)<-.25?'right':'center';let bx=anchor==='left'?x:anchor==='right'?x-tw:x-tw/2;if(bx<8){x+=8-bx;bx=8}if(bx+tw>W-8){x-=bx+tw-W+8;bx=W-8-tw}if(placed.some(b=>bx<b.x+b.w+8&&bx+tw>b.x-8&&Math.abs(y-b.y)<32))continue;placed.push({x:bx,y,w:tw});ctx.textAlign=anchor;ctx.fillStyle='#273b30';ctx.strokeStyle='#fff';ctx.lineWidth=4;ctx.strokeText(name,x,y);ctx.fillText(name,x,y);ctx.font='10px Inter';ctx.fillStyle='#7a857f';ctx.strokeText(fmt(n.count)+' assemblies',x,y+15);ctx.fillText(fmt(n.count)+' assemblies',x,y+15);}
145
  drawAtlasIcons();
146
  if(selected){const a=selected;ctx.strokeStyle='#15392c';ctx.lineWidth=1.8;ctx.beginPath();let p=screen(a.points[0]);ctx.moveTo(...p);for(let j=1;j<a.points.length;j++){let [c,d]=controls(a.points[j-1],a.points[j]);ctx.bezierCurveTo(...screen(c),...screen(d),...screen(a.points[j]));}ctx.stroke();let q=screen(a.tip);ctx.fillStyle='#15392c';ctx.beginPath();ctx.arc(...q,4,0,TAU);ctx.fill();}
147
  $('#zoom-readout').textContent=zoom.toFixed(1)+'脳';$('#zoomout').disabled=zoom<=1;$('#zoomin').disabled=zoom>=320;
overview.png CHANGED

Git LFS Details

  • SHA256: 21d2f7663a426565185b2a4972fd6fc8fe71854f91923ef2b38a815c9d8740c6
  • Pointer size: 131 Bytes
  • Size of remote file: 631 kB

Git LFS Details

  • SHA256: d2ef01db280db99ef0dfeba0e288166f7dcf4b429c38aee9483fab4c5292a91e
  • Pointer size: 131 Bytes
  • Size of remote file: 631 kB