Spaces:
Running
Running
Download app.js from AngelinaZ/vase-framework: direct link, hf CLI and curl.
- Browser
- Download file 17.5 kB
-
https://huggingface.co/spaces/AngelinaZ/vase-framework/resolve/main/app.js
- Command line
-
hf download hf://spaces/AngelinaZ/vase-framework/app.js
-
curl -L -o app.js https://huggingface.co/spaces/AngelinaZ/vase-framework/resolve/main/app.js
17.5 kB
| ; | |
| const PAPER = 'https://arxiv.org/html/2506.17346v1'; | |
| const layers = { | |
| data: {name:'Data',accent:'#395d47',tint:'#eaf0e4',question:'What do we observe?',definition:'The inputs available to the system, collected from multiple sources and represented in different modalities.',connection:'Data → Data Quality',why:'Before deciding whether an input is useful, identify its source, representation, and intended use.',examples:[ | |
| ['Cameras','Several sources, one modality','Front and side cameras provide different viewpoints as images. Two cameras are multiple sources, even when both produce the same modality.','camera'], | |
| ['LiDAR','A different representation','A point cloud describes spatial structure. Pairing it with camera imagery gives the system different representations of the surroundings.','lidar'], | |
| ['Connected inputs','Beyond onboard sensors','Imagine a vehicle receiving a roadwork notice from infrastructure. The message adds context that may be outside its sensors’ current view.','network']],section:'#S2.SS1.SSS0.Px1'}, | |
| quality: {name:'Data Quality',accent:'#596a3f',tint:'#eef1df',question:'Is the data fit for purpose?',definition:'Dimensions describe aspects of quality; metrics make those aspects measurable for a particular use.',connection:'Data Quality ↔ Task',why:'Choose quality checks for the task, then examine how changing the data affects its results.',examples:[ | |
| ['Completeness','Is something needed missing?','Illustration: a pedestrian is visible, but has no annotation. Checking label coverage could reveal missing supervision.','missing'], | |
| ['Consistency','Do observations agree?','Illustration: two aligned sensors assign conflicting labels to one object. A consistency check flags the disagreement.','consistency'], | |
| ['Correctness','Does the record match reality?','Illustration: a cyclist is labeled as a car. Correcting the category changes the supervision provided to a detector.','correct'], | |
| ['Noise level','How much is the signal distorted?','Illustration: image noise obscures a small obstacle. Inspect signal quality before attributing a detection error only to the model.','noise'], | |
| ['Redundancy','Does overlap add useful information?','Illustration: two views contain the same car. Compare their usefulness for the task before deciding whether to retain both.','camera'], | |
| ['Relevance','Does this input serve the task?','Illustration: details of a distant building may have little value for an immediate obstacle decision, but can help a localization task.','relevance'], | |
| ['Timeliness','Does the input arrive in time?','Illustration: an accurate object position arrives after the decision deadline. Its age matters alongside its spatial accuracy.','clock']],section:'#S2.T1'}, | |
| task: {name:'Task',accent:'#85651f',tint:'#f5edce',question:'What must the system do?',definition:'A specific operation connects data-quality needs with the result being evaluated.',connection:'The center of the Vase',why:'A quality improvement matters when it helps the selected task meet its requirements.',examples:[ | |
| ['Object detection','Find and identify objects','Imagine a perception module identifying a cyclist ahead. Relevant checks include whether the cyclist is labeled correctly and sufficiently represented.','detect'], | |
| ['Tracking','Follow an object over time','Imagine following that cyclist across frames. Stable identities and aligned timestamps become important checks.','track'], | |
| ['Path planning','Choose a way forward','Imagine choosing a route around an obstruction. Recent, relevant observations help define the inputs the planner needs.','path']],section:'#S2.SS1.SSS0.Px3'}, | |
| application: {name:'Application',accent:'#91612f',tint:'#f6e7d3',question:'How do tasks work together?',definition:'An application combines tasks within a broader operating context.',connection:'Task ↔ Application',why:'One task can serve several applications; each application brings its own context and requirements.',examples:[ | |
| ['Perception','Build an understanding of the scene','Detection, segmentation, and tracking can contribute different pieces of a scene description. Consider how an error in one piece affects the others.','network'], | |
| ['Prediction','Anticipate what happens next','An illustrative workflow uses tracked positions to estimate future motion. Earlier data problems can propagate into later outputs.','track'], | |
| ['Planning & control','Turn understanding into action','An illustrative workflow connects a chosen trajectory to steering and braking commands. Its tasks need compatible timing and shared context.','path']],section:'#S2.SS1.SSS0.Px4'}, | |
| goal: {name:'Goal',accent:'#92594e',tint:'#f4e3df',question:'What counts as success?',definition:'Objectives guide evaluation through measures such as accuracy, efficiency, and latency.',connection:'Goal ↔ Data Quality',why:'The intended outcome guides which quality metrics to use; evaluation feeds back into data selection and improvement.',examples:[ | |
| ['Accuracy','Evaluate the task result','For a detection experiment, compare predictions with reference annotations. Define the evaluation protocol before judging a data intervention.','detect'], | |
| ['Efficiency','Account for resources','A smaller dataset and a faster system are different outcomes. Measure the resource you care about rather than assuming one implies the other.','efficiency'], | |
| ['Latency','Meet a response deadline','Illustration: two methods produce similar detections, but one responds too late for the application. A timing objective changes the decision.','clock']],section:'#S2.SS1.SSS0.Px5'} | |
| }; | |
| const keys=Object.keys(layers); | |
| const relations=[ | |
| {ids:['quality','task'],title:'Quality depends on the task.',body:'Start with the operation you need to perform. Select relevant quality checks, then evaluate whether improving the data helps that operation.',example:'For example: missing annotations matter when training a detector; timestamp alignment matters when following motion.'}, | |
| {ids:['task','application'],title:'Tasks gain meaning in context.',body:'A task can be reused across applications. The surrounding workflow determines what it needs to produce and when it must deliver.',example:'For example: detecting an object can support both scene understanding and a downstream planning workflow.'}, | |
| {ids:['goal','quality','task'],title:'Outcomes close the loop.',body:'Set the objective, choose quality measures that support it, and evaluate the task. If the outcome is insufficient, revisit the data decision.',example:'For example: after pruning candidate duplicates, evaluate detection on a fixed reference set. Revise the pruning choice if the result misses your objective.'} | |
| ]; | |
| const scenarios=[ | |
| {summary:'A vehicle approaches an obstacle. The immediate question is whether the relevant object can be identified in time.',items:[['Camera + LiDAR','Observe the road ahead.'],['Correctness · Timeliness','Check labels and input freshness.'],['Object detection','Locate and identify the obstacle.'],['Perception','Update the scene description.'],['Accurate, timely output','Evaluate detection and response time.']],feedback:'If the obstacle is missed, inspect the input and annotations, revise the data handling, and evaluate again.'}, | |
| {summary:'The vehicle needs a path around an obstruction. The information must remain relevant as the scene changes.',items:[['Sensor observations + map','Describe the surroundings and road.'],['Relevance · Consistency','Check useful coverage and alignment.'],['Path planning','Choose a feasible trajectory.'],['Planning','Coordinate the intended movement.'],['A usable, timely plan','Evaluate the trajectory and deadline.']],feedback:'If the plan uses outdated positions, revisit synchronization and input age before repeating the task.'}, | |
| {summary:'An engineer reviews a recorded incident. Reconstructing what happened changes which quality checks receive attention.',items:[['Recorded sensor logs','Gather the available observations.'],['Completeness · Consistency','Check gaps and shared timestamps.'],['Event reconstruction','Arrange the observations in time.'],['Post-event analysis','Review the sequence of events.'],['A traceable explanation','Evaluate evidence coverage and gaps.']],feedback:'If the record cannot explain an event, identify missing observations and improve the logging process for future reviews.'} | |
| ]; | |
| let selected='data', example=0, mode='layers', relation=0, touring=false; | |
| const $=s=>document.querySelector(s); | |
| const $$=s=>[...document.querySelectorAll(s)]; | |
| function art(type,color){ | |
| const car=(x,y)=>`<rect x="${x}" y="${y}" width="44" height="22" rx="6" fill="${color}" fill-opacity=".15" stroke="${color}"/><path d="M${x+9} ${y+4}h26v8H${x+9}z" fill="${color}" fill-opacity=".2"/><circle cx="${x+10}" cy="${y+23}" r="3" fill="${color}"/><circle cx="${x+34}" cy="${y+23}" r="3" fill="${color}"/>`; | |
| let shape=''; | |
| if(['camera','detect','missing','correct','consistency'].includes(type)) shape=`<rect x="39" y="15" width="103" height="62" rx="5" fill="white" fill-opacity=".4" stroke="${color}" stroke-opacity=".35"/><rect x="188" y="15" width="103" height="62" rx="5" fill="white" fill-opacity=".4" stroke="${color}" stroke-opacity=".35"/>${car(68,38)}${car(218,38)}<path d="M62 64V29h57v35z" fill="none" stroke="${color}" stroke-dasharray="${type==='missing'?'3 4':'0'}"/><path d="M211 64V29h57v35z" fill="none" stroke="${color}"/><path d="M146 47h35m-5-5 5 5-5 5" fill="none" stroke="${color}"/><text x="90" y="25" text-anchor="middle" font-size="6" fill="${color}">${type==='correct'?'CHECK LABEL':'VIEW A'}</text><text x="240" y="25" text-anchor="middle" font-size="6" fill="${color}">${type==='consistency'?'COMPARE LABEL':'VIEW B'}</text>`; | |
| else if(type==='lidar'||type==='noise') shape=Array.from({length:90},(_,i)=>`<circle cx="${45+(i*47)%240}" cy="${17+(i*19)%60}" r="${i%3===0?1.9:1}" fill="${color}" opacity="${.15+(i%5)*.15}"/>`).join('')+`<path d="M135 59V32l30-14 35 14v27l-35 15zM135 32l30 16 35-16M165 48v26" stroke="${color}" fill="none"/>`; | |
| else if(type==='clock') shape=`<circle cx="125" cy="46" r="28" fill="white" fill-opacity=".3" stroke="${color}"/><path d="M125 27v20l14 9M166 35h70M166 46h49M166 57h60" stroke="${color}" stroke-width="2" fill="none"/><circle cx="125" cy="46" r="3" fill="${color}"/>`; | |
| else if(type==='path'||type==='track') shape=`<path d="M58 72C98 72 109 23 163 24S239 73 276 27" fill="none" stroke="${color}" stroke-width="2" stroke-dasharray="5 5"/>${[58,108,162,220,276].map((x,i)=>`<circle cx="${x}" cy="${[72,49,24,44,27][i]}" r="6" fill="${color}" fill-opacity="${.3+i*.15}"/>`).join('')}`; | |
| else if(type==='efficiency') shape=`${[0,1,2,3].map(i=>`<rect x="${85+i*43}" y="${24+i*8}" width="25" height="${48-i*8}" rx="3" fill="${color}" opacity="${.3+i*.16}"/>`).join('')}<path d="M76 76h188" stroke="${color}"/>`; | |
| else shape=`<path d="M79 26 165 46 250 25M79 70 165 46 250 69" stroke="${color}" stroke-opacity=".5" fill="none"/>${[[79,26],[79,70],[165,46],[250,25],[250,69]].map(([x,y],i)=>`<rect x="${x-14}" y="${y-11}" width="28" height="22" rx="5" stroke="${color}" fill="${i===2?color:'white'}" fill-opacity="${i===2?'.65':'.6'}"/>`).join('')}`; | |
| return `<svg viewBox="0 0 330 92" aria-hidden="true">${shape}</svg>`; | |
| } | |
| function animate(el){el.style.animation='none';void el.offsetWidth;el.style.animation='';} | |
| function renderLayer(){const l=layers[selected], n=keys.indexOf(selected)+1; $('#detail-area').style.setProperty('--accent',l.accent);$('#detail-area').style.setProperty('--tint',l.tint); | |
| $('#layer-content').innerHTML=`<div class="detail-heading"><span class="layer-kicker">LAYER 0${n} / ${l.name.toUpperCase()}</span><span class="detail-count">0${n}</span></div><h2>${l.question}</h2><p class="detail-intro">${l.definition}</p><span class="example-label">LOOK INSIDE · SELECT AN EXAMPLE</span><div class="example-tabs" role="group" aria-label="${l.name} examples">${l.examples.map((e,i)=>`<button data-example="${i}" aria-pressed="${i===example}">${e[0]}</button>`).join('')}</div><div id="example-content"></div><div class="connection"><span class="connection-icon" aria-hidden="true">↳</span><p><strong>${l.connection}</strong>${l.why}</p></div><p class="detail-source"><a href="${PAPER+l.section}" target="_blank" rel="noopener">Based on §II${selected==='quality'?' and Table I':''} · View source ↗</a></p>`; | |
| renderExample();animate($('#layer-content'));updateButtons(); | |
| } | |
| function renderExample(){const l=layers[selected],e=l.examples[example];$('#example-content').innerHTML=`<div class="example-card"><div class="example-art">${art(e[3],l.accent)}</div><div class="example-body"><h3>${e[1]}</h3><p>${e[2]}</p></div></div>`;$$('[data-example]').forEach(b=>b.setAttribute('aria-pressed',Number(b.dataset.example)===example));} | |
| function updateButtons(){$$('[data-layer]').forEach(b=>{b.setAttribute('aria-pressed',mode==='layers'&&b.dataset.layer===selected);b.classList.toggle('related',mode==='relations'&&relations[relation].ids.includes(b.dataset.layer));b.classList.toggle('dimmed',mode==='relations'&&!relations[relation].ids.includes(b.dataset.layer));});} | |
| function setLayer(key){selected=key;example=0;setMode('layers');renderLayer();if(touring)renderTour();} | |
| function setMode(next){mode=next;$('#layer-content').hidden=mode!=='layers';$('#relationship-content').hidden=mode!=='relations';$('#mode-layers').setAttribute('aria-pressed',mode==='layers');$('#mode-relations').setAttribute('aria-pressed',mode==='relations');$('#explorer-hint').textContent=mode==='layers'?'Select a layer to look inside ↓':'Select a relationship to trace its connections';if(mode==='relations'){touring=false;$('#tour').hidden=true;renderRelation();}updateButtons();} | |
| function renderRelation(){const r=relations[relation];$('#relation-detail').innerHTML=`<div class="relation-note"><h3>${r.title}</h3><p>${r.body}</p><p>${r.example}</p></div><p class="detail-source"><a href="${PAPER}#S2.SS2" target="_blank" rel="noopener">Relationships & feedback · §II-B ↗</a></p>`;$$('[data-relation]').forEach(b=>b.setAttribute('aria-pressed',Number(b.dataset.relation)===relation));updateButtons();animate($('#relation-detail'));} | |
| function renderScenario(index){const s=scenarios[index];$('#scenario-content').innerHTML=`<div class="scenario-summary"><p>${s.summary}</p><span class="illustrative">ILLUSTRATIVE WALKTHROUGH</span></div><div class="scenario-trace">${s.items.map((item,i)=>`<article class="trace-card" style="--trace:${layers[keys[i]].accent}"><span class="tiny-label">0${i+1} / ${layers[keys[i]].name.toUpperCase()}</span><h3>${item[0]}</h3><p>${item[1]}</p></article>`).join('')}</div><div class="feedback"><span aria-hidden="true">↺</span><p><strong>Close the loop.</strong> ${s.feedback}</p></div>`;$$('[data-scenario]').forEach(b=>b.setAttribute('aria-pressed',Number(b.dataset.scenario)===index));animate($('#scenario-content'));} | |
| const tourPrompts=['Begin with the available inputs. Select Cameras or LiDAR to compare sources and representations.','Quality has several dimensions. Explore a few checks, then ask which ones the task needs.','The task is the center: it determines what useful data means in this setting.','Place the task in an application. Consider how its output affects the rest of the workflow.','Define success, evaluate the result, and let the outcome guide the next data-quality decision.']; | |
| function renderTour(){const i=keys.indexOf(selected);$('#tour').hidden=!touring;$('#tour-progress').textContent=`STEP ${i+1} OF 5`;$('#tour-prompt').textContent=tourPrompts[i];$('#tour-prev').disabled=i===0;$('#tour-next').textContent=i===4?'Explore relationships →':'Next layer →';} | |
| $('#start-tour').addEventListener('click',()=>{touring=true;setLayer('data');$('#explorer').scrollIntoView({behavior:'smooth',block:'start'});$('#tour-next').focus({preventScroll:true});}); | |
| $('#tour-prev').addEventListener('click',()=>{const i=keys.indexOf(selected);if(i>0)setLayer(keys[i-1]);}); | |
| $('#tour-next').addEventListener('click',()=>{const i=keys.indexOf(selected);if(i<4)setLayer(keys[i+1]);else{relation=2;setMode('relations');$('#mode-relations').focus({preventScroll:true});}}); | |
| $('#tour-exit').addEventListener('click',()=>{touring=false;$('#tour').hidden=true;$('#start-tour').focus({preventScroll:true});}); | |
| $('#mode-layers').addEventListener('click',()=>setMode('layers')); | |
| $('#mode-relations').addEventListener('click',()=>setMode('relations')); | |
| $$('[data-layer]').forEach(b=>b.addEventListener('click',()=>setLayer(b.dataset.layer))); | |
| $('#layer-content').addEventListener('click',e=>{const b=e.target.closest('[data-example]');if(b){example=Number(b.dataset.example);renderExample();}}); | |
| $$('[data-relation]').forEach(b=>b.addEventListener('click',()=>{relation=Number(b.dataset.relation);renderRelation();})); | |
| $$('[data-scenario]').forEach(b=>b.addEventListener('click',()=>renderScenario(Number(b.dataset.scenario)))); | |
| // Arrow keys supplement standard Tab/Enter/Space navigation within button groups. | |
| document.addEventListener('keydown',e=>{const group=e.target.closest('[role="group"]');if(!group)return;if(!['ArrowRight','ArrowLeft','ArrowDown','ArrowUp','Home','End'].includes(e.key))return;const buttons=[...group.querySelectorAll('button')];const i=buttons.indexOf(document.activeElement);if(i<0)return;e.preventDefault();let n=e.key==='Home'?0:e.key==='End'?buttons.length-1:(i+(['ArrowRight','ArrowDown'].includes(e.key)?1:-1)+buttons.length)%buttons.length;buttons[n].focus();buttons[n].click();}); | |
| renderLayer();renderScenario(0); | |