Published unlisted
Edited
Jun 29, 2021
Insert cell
Insert cell
spectralDecompositionsAll = html`
<div id="specDecompAll">
${inputsRadio}
${body}
${inputsSlider}
</div>
`
Insert cell
inputsRadio = html`
<div id="specDecompInputsRadio">
${baseImageRadio}
</div>
`
Insert cell
inputsSlider = html`
<div id="specDecompInputsSlider">
${numComponentsSlider}
</div>
`
Insert cell
body = html`
<div id="specDecompBody">
<div id="orig">
${origCanvas}
${origCaption}
</div>
${arrow}
<div id="upd">
${updCanvas}
${updCaption}
</div>
</div>
`
Insert cell
Insert cell
updCaption = html`
<figcaption id="updCaption">
Transformed Image
${tex`x'`}
</figcaption>
`
Insert cell
updateArrowCaption = {
const text = (numComponents == maxComponents ? `All ${maxComponents}` : `First ${numComponents}`);
d3.select(arrow).select('#caption').text(`Keep ${text} Spectral Components`);
}
Insert cell
arrow = html`
<svg id="svgArrow" width=320 height=50 viewBox="0 0 320 50">
<g>
<text id="caption"></text>
</g>
</svg>`
Insert cell
drawArrow = {
const group = d3.select(arrow).select('g');
group
.append('defs')
.append('marker')
.attr('id', 'arrow')
.attr('viewBox', [0, 0, 20, 20])
.attr('refX', 10)
.attr('refY', 10)
.attr('markerWidth', 10)
.attr('markerHeight', 10)
.attr('orient', 'auto-start-reverse')
.append('path')
.attr('d', d3.line()([[0, 0], [0, 20], [20, 10]]))
.attr('stroke', 'black');

const xOffset = 10;
const arrowLen = 300;
group
.append('path')
.attr('d', d3.line()([[xOffset, 25], [xOffset + arrowLen, 25]]))
.attr('stroke', 'black')
.attr('marker-end', 'url(#arrow)')
.attr('fill', 'none');
group
.select('#caption')
.text(`Keep Top Spectral Components`)
.attr('text-anchor', 'middle')
.attr('dominant-baseline', 'central')
.attr('x', xOffset + (arrowLen / 2))
.attr('y', 40);
}
Insert cell
Insert cell
baseImage = Generators.input(baseImageRadio);
Insert cell
numComponentsSlider = {
var allowedVals = [1, 5, 10, 20, 50, 100, 200, 500, 750, 1000, 1500, 2000];
return slider({
min: 0,
max: allowedVals.length - 1,
step: 1,
title: "Number of Spectral Components (m)",
value: 6,
getValue: n => allowedVals[n.value],
});
}
Insert cell
numComponents = Generators.input(numComponentsSlider);
Insert cell
allAttachments = [
FileAttachment('spectral-chicken-1.png'),
FileAttachment('spectral-chicken-5.png'),
FileAttachment('spectral-chicken-10.png'),
FileAttachment('spectral-chicken-20.png'),
FileAttachment('spectral-chicken-50.png'),
FileAttachment('spectral-chicken-100.png'),
FileAttachment('spectral-chicken-200.png'),
FileAttachment('spectral-chicken-500.png'),
FileAttachment('spectral-chicken-750.png'),
FileAttachment('spectral-chicken-1000.png'),
FileAttachment('spectral-chicken-1500.png'),
FileAttachment('spectral-chicken-2000.png'),
FileAttachment('spectral-fish-1.png'),
FileAttachment('spectral-fish-5.png'),
FileAttachment('spectral-fish-10.png'),
FileAttachment('spectral-fish-20.png'),
FileAttachment('spectral-fish-50.png'),
FileAttachment('spectral-fish-100.png'),
FileAttachment('spectral-fish-200.png'),
FileAttachment('spectral-fish-500.png'),
FileAttachment('spectral-fish-750.png'),
FileAttachment('spectral-fish-1000.png'),
FileAttachment('spectral-fish-1500.png'),
FileAttachment('spectral-fish-2000.png'),
FileAttachment('spectral-frog-1.png'),
FileAttachment('spectral-frog-5.png'),
FileAttachment('spectral-frog-10.png'),
FileAttachment('spectral-frog-20.png'),
FileAttachment('spectral-frog-50.png'),
FileAttachment('spectral-frog-100.png'),
FileAttachment('spectral-frog-200.png'),
FileAttachment('spectral-frog-500.png'),
FileAttachment('spectral-frog-750.png'),
FileAttachment('spectral-frog-1000.png'),
FileAttachment('spectral-frog-1500.png'),
FileAttachment('spectral-frog-2000.png'),
FileAttachment('spectral-spider-1.png'),
FileAttachment('spectral-spider-5.png'),
FileAttachment('spectral-spider-10.png'),
FileAttachment('spectral-spider-20.png'),
FileAttachment('spectral-spider-50.png'),
FileAttachment('spectral-spider-100.png'),
FileAttachment('spectral-spider-200.png'),
FileAttachment('spectral-spider-500.png'),
FileAttachment('spectral-spider-750.png'),
FileAttachment('spectral-spider-1000.png'),
FileAttachment('spectral-spider-1500.png'),
FileAttachment('spectral-spider-2000.png'),
];
Insert cell
allImages = {
var images = await Promise.all(allAttachments.map(file => file.image()));
var dict = {};
for(const [i, f] of allAttachments.entries()){
dict[f.name] = images[i];
}
return dict;
}
Insert cell
function getImageByName(imglabel, numcomponents){
return allImages[`spectral-${imglabel}-${numcomponents}.png`];
}
Insert cell
function drawImage(baseImage) {
const image = getImageByName(baseImage, `${maxComponents}`);
const ctx = origCanvas.getContext('2d');
ctx.drawImage(image, 0, 0);
}
Insert cell
drawCurrBaseImg = drawImage(baseImage)
Insert cell
function drawUpdImage(baseImage, numComponents) {
const image = getImageByName(baseImage, numComponents);
const ctx = updCanvas.getContext('2d');
ctx.drawImage(image, 0, 0);
}
Insert cell
drawCurrUpdImg =drawUpdImage(baseImage, numComponents)
Insert cell
imageExample = getImageByName('chicken', 100);
Insert cell
canvasWidth = imageExample.width;
Insert cell
canvasHeight = imageExample.height;
Insert cell
origCanvas = html`<canvas width=${canvasWidth} height=${canvasHeight}></canvas>`
Insert cell
updCanvas = html`<canvas width=${canvasWidth} height=${canvasHeight}></canvas>`
Insert cell
maxComponents = 2000
Insert cell
style = html`
<style>
#specDecompBody {
display: flex;
justify-content: center;
}
#svgArrow {
margin-top: 83px;
margin-left: 2em;
margin-right: 2em;
}
#specDecompAll {
display: flex;
flex-direction: column;
text-align: center;
height: 350px;
justify-content: space-evenly;
}
#specDecompInputsRadio input {
margin-top: 0.5em;
vertical-align: unset !important;
}
#origCaption {
margin-top: 1em;
}
#updCaption {
margin-top: 1em;
}
`
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more