Published
Edited
May 23, 2022
1 fork
Importers
68 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
// munsell = yaml.safeLoad(await d3.text(munsell_url))
munsell = yaml.safeLoad(await FileAttachment("real.yaml").text())
Insert cell
Insert cell
xyY_to_XYZ = ([x, y, Y]) => {
Y *= 0.9749629514078465;
return [x*Y/y, Y, (1 - x - y)*Y/y]; }
Insert cell
Insert cell
adapt_C_D65_bradford = ([X, Y, Z]) =>
[+0.9904476*X -0.0071683*Y -0.0116156*Z,
-0.0123712*X +1.0155950*Y -0.0029282*Z,
-0.0035635*X +0.0067697*Y +0.9181569*Z]
Insert cell
Insert cell
munsell_XYZ_D65 = {
const xyY = zip(munsell.x, munsell.y, munsell.Y);
const XYZ_C = map(xyY_to_XYZ, xyY);
return Array.from(XYZ_C, adapt_C_D65_bradford); }
Insert cell
Insert cell
munsell_in_gamut = Int8Array.from(munsell_XYZ_D65, in_gamut)
Insert cell
Insert cell
munsell_XYZ_D65_in_gamut = [...compress(munsell_XYZ_D65, munsell_in_gamut)]
Insert cell
Insert cell
munsell_hex_in_gamut = {
const srgb = map(xyz_to_srgb, munsell_XYZ_D65_in_gamut);
return Array.from(srgb, to_hex); }
Insert cell
Insert cell
hue_names = Array.from(
product(
['R', 'YR', 'Y', 'GY', 'G', 'BG', 'B', 'PB', 'P', 'RP'],
['2.5', '5', '7.5', '10']),
([H, num]) => `${num}${H}`)
Insert cell
Insert cell
munsell_h_to_radians = {
const hue_radians = map(i => i*2*Math.PI/40, range(40));
const names_radians_map = Object.fromEntries(zip(hue_names, hue_radians));
return H => names_radians_map[H]; }
Insert cell
Insert cell
cylindrical_to_cartesian = ([height, angle, radius]) =>
[height, Math.cos(angle)*radius, Math.sin(angle)*radius]
Insert cell
Insert cell
munsell_Vab_in_gamut = {
const angle = map(munsell_h_to_radians, munsell.h);
const VangleC = zip(munsell.V, angle, munsell.C);
const VangleC_in_gamut = compress(VangleC, munsell_in_gamut);
return Array.from(VangleC_in_gamut, cylindrical_to_cartesian); }
Insert cell
Insert cell
Y_for_V = (V) =>
V * (1.2219 + V * (-0.23111 + V * (0.23951 + V * (-0.021009 + V * (0.0008404)))))
Insert cell
hex_for_neutral_V = function XYZ_for_V(V) {
const
[Xw, Yw, Zw] = standard_whitepoints.C,
Y = Y_for_V(V) * 0.9749629514078465,
X = Xw * Y / Yw,
Z = Zw * Y / Yw,
XYZ_D65 = adapt_C_D65_bradford([X, Y, Z]),
sRGB = xyz_to_srgb(XYZ_D65);
return to_hex(sRGB); }
Insert cell
neutral_V_hex = Array.from(zip(count(), map(hex_for_neutral_V, range(11))))
Insert cell
neutral_Vab_hex = Array.from(neutral_V_hex, ([i, hex]) => [[i, 0, 0], hex])
Insert cell
Insert cell
static_zdog_picture = {
const element = DOM.canvas(width, width * 10/16);
const illo = new Zdog.Illustration({element,
zoom: width/55, scale: {y: 2.5},
rotate: {x: -Math.PI/5} });
const shapes = Array.from(
chain(zip(munsell_Vab_in_gamut, munsell_hex_in_gamut), neutral_Vab_hex),
([[V, a, b], hex]) =>
new Zdog.Shape({
addTo: illo,
translate: {x: b, y: 5-V, z: a},
color: hex,
stroke: 1.2 }));
illo.updateRenderGraph();
return element; }
Insert cell
Insert cell
munsell_h_to_paired_indices = {
const hue_indices = chain(range(1, 21), range(-1, -21, -1));
const names_indices_map = Object.fromEntries(zip(hue_names, hue_indices));
return H => names_indices_map[H]; }
Insert cell
neutral_VChex = Array.from(neutral_V_hex, ([i, hex]) => [i, 0, hex])
Insert cell
munsell_VChex_in_gamut_in_hue_groups = {
const Hi = map(munsell_h_to_paired_indices, munsell.h)
const iVC = zip(Hi, munsell.V, munsell.C);
const iVC_in_gamut = compress(iVC, munsell_in_gamut);
const i_VChex_in_gamut = map(
([[i, V, C], hex]) => [i, [V, C, hex]],
zip(iVC_in_gamut, munsell_hex_in_gamut));
const igroups = groupby(
sorted(i_VChex_in_gamut, ([i]) => Math.abs(i)),
([i]) => Math.abs(i));
const sign = (i) => (i > 0) - (i < 0);
return Array.from(igroups,
([group_key, i_VCh]) => Array.from(i_VCh,
([i, [V, C, hex]]) => [V, C*sign(i), hex]).concat(neutral_VChex)); }
Insert cell
zdog_hue_slices = {
const canvases = Array.from(munsell_VChex_in_gamut_in_hue_groups,
(VChex, k) => {
const right = k % 2, left = !right;
const w = width/2;
const element = DOM.canvas(w, w * .55);
Object.assign(element.style, {background: '#555'});
const illo = new Zdog.Illustration({element,
zoom: w/47, scale: {y: 2},
rotate: {x: 0} });
const shapes = Array.from(VChex,
([V, C, hex]) =>
new Zdog.Shape({
addTo: illo,
translate: {y: 5 - V, x: C + 3*left + 3.5*right, z: 0},
color: hex,
stroke: 1.7 }));
illo.updateRenderGraph();
return element; });
return html`${canvases}`; }
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
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