Published
Edited
Mar 11, 2021
Insert cell
Insert cell
Insert cell
{
const tileWidth = 30;
const svg = d3.select(DOM.svg(7 * tileWidth, 7 * tileWidth));
const n = ['c', 'd', 'e', 'f', 'g', 'a', 'b'];
const data = [];
for (let i = 0; i < 7; ++i) {
for (let j = 0; j < 7; ++j) {
data.push({
i: i,
j: j,
value: 0,
text: n[i] + n[j]
});
}
}
const tile = svg
.selectAll("g")
.data(data)
.enter()
.append("g")
.attr("transform", function(d, i) {
return `translate(${d.j * tileWidth},${(6 - d.i) * tileWidth})`;
});
tile
.append("rect")
.attr("x", 0)
.attr("y", 0)
.attr("width", tileWidth)
.attr("height", tileWidth)
.attr("fill", d => d3.interpolateReds(Math.abs(d.value)))
.attr("stroke", "white")
.attr("stroke-width", 2);
tile
.append("text")
.attr('x', 5)
.attr('y', (tileWidth * 2) / 3)
.text(d => d.text);
const A = orbitals.map(o => o.orbital[0][2]);
while (true) {
const re = d3.range(7).map(i => d3.range(7).map(j => 0));
const im = d3.range(7).map(i => d3.range(7).map(j => 0));
const de = d3.range(7).map(i => d3.range(7).map(j => 0));
const t = Date.now();
for (let i = 0; i < 7; ++i) {
for (let j = 0; j < 7; ++j) {
for (let n = 0; n < 49; ++n) {
re[i][j] +=
A[n] * orbitals[n].orbital[i][j] * Math.cos(orbitals[n].energy * t);
im[i][j] +=
A[n] * orbitals[n].orbital[i][j] * Math.cos(orbitals[n].energy * t);
}
}
}
let s = 0;
for (let i = 0; i < 7; ++i) {
for (let j = 0; j < 7; ++j) {
de[i][j] = re[i][j] * re[i][j] + im[i][j] * im[i][j];
s += de[i][j];
}
}
for (let i = 0; i < 7; ++i) {
for (let j = 0; j < 7; ++j) {
de[i][j] /= s;
}
}
for (let l = 0; l < 49; ++l) {
data[l].value = de[data[l].i][data[l].j];
}
svg
.selectAll("rect")
.attr("fill", d => d3.interpolateReds(Math.abs(d.value)));
yield Promises.delay(200, svg.node());
}
}
Insert cell
orbitals = {
const g = (i, j) => 7 * ((i + 7) % 7) + ((j + 7) % 7);
const l = k => [Math.floor(k / 7), k % 7];
const L = d3.range(49).map(i => d3.range(49).map(j => 0));
const factor = 1.0;
for (let i = 0; i < 7; ++i) {
for (let j = 0; j < 7; ++j) {
L[g(i, j)][g(i, j)] = 4 + factor * V(i, j);
L[g(i, j)][g(i + 1, j)] = -1;
L[g(i, j)][g(i - 1, j)] = -1;
L[g(i, j)][g(i, j + 1)] = -1;
L[g(i, j)][g(i, j - 1)] = -1;
}
}
const r = matrixEig.eig(L);
const eig = [];
for (let k = 0; k < 49; ++k) {
const e = {};
e.energy = r.eigenvalues.real[k];
const v = r.eigenvectors.right.slice(49 * k, 49 * (k + 1));
e.orbital = d3.range(7).map(i => d3.range(7).map(j => v[g(i, j)]));
eig.push(e);
}
return eig.sort((ea, eb) => (ea.energy < eb.energy ? -1 : 1));
}
Insert cell
V = function(i, j) {
const n = [0, 2, 4, 5, 7, 9, 11];
const int = (i, j) => (n[j] - n[i] + 12) % 12;
const intNameEnergy = [
['unison', 3],
['semitone', 7],
['tone', 5],
['minor third', 3],
['major third', 2],
['fourth', 4],
['tritone', 7],
['fifth', 1],
['minor sixth', 2],
['major sixth', 3],
['minor seventh', 6],
['major seventh', 5]
];
return intNameEnergy[int(i, j)][1];
}
Insert cell
import { matrixEig } from '@fil/hello-matrix-eig'
Insert cell
import { pt } from '@fil/pt'
Insert cell
d3 = require('d3')
Insert cell
require("d3-scale-chromatic@1", "d3-interpolate@1")
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more