Public
Edited
Apr 16, 2023
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Tree(find(searchterm ? searchterm.pango : "omicron"), {
width: controls.value.modifiers.width * width,
heightCoefficent: controls.value.modifiers.height,
fontFamily: "monospace",
fontSize: 11,

label: (d) => d.data.lineage.pango,
nodeFill: dateIndicator(scale, ["#D52322", "lightgray", "lightgray"], {
nextCladeIndicator: controls.value.indicators.nextClade,
predicateRange: ["black", "lightgray"]
}),
nodeRadius: dateIndicator(scale, [7, 4, 4], { defaultValue: 4 }),
nodeTextOffsetX: dateIndicator(scale, [10, 6, 6], { defaultValue: 6 }),
nodeFontWeight: dateIndicator(scale, [1000, 500, 400]),
nodeFontStyle: dateIndicator(predicate, ["normal", "italic"], {
predicate: (d) =>
available_nextclade_lineages.includes(d.data.lineage.pango),
enable: controls.value.indicators.nextClade
}),

nodeTextColor: dateIndicator(scale, ["#D52322", "#A5A5A5", "#A5A5A5"], {
nextCladeIndicator: controls.value.indicators.nextClade,
overriddenRange: ["#D52322", "black", "black"]
})
})
Insert cell
controls.value.nextclade
Insert cell
scale.range(["#D52322", "black", "black"])(weeksSince("2023-04-10"))
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
viewof controls = wrapGUI(
State.Tabs({
indicators: State.Section({
recency: State.Checkbox(true, { label: "Recently Added" }),
nextClade: State.Checkbox(true, {
label: "NextClade"
})
}),
// nextclade: State.Section(
// {
// instructions: State.Raw((h) =>
// h("p", null, `Show lineages available within NextClade`)
// ),
// enabled: State.Checkbox(true, { label: "Enable" })
// },
// { label: "NextClade" }
// ),
// recency: State.Section(
// {
// instructions: State.Raw((h) =>
// h("p", null, `Show lineages that have been added recently`)
// ),
// enabled: State.Checkbox(true, { label: "Enable" }),
// color: "#D52322"
// },
// { label: "Recently Added" }
// ),
modifiers: State.Section(
{
width: State.Slider(1, {
min: 0.2,
max: 1,
step: 0.05,
label: "Width Multiplier"
}),
height: State.Slider(1, {
min: 0.6,
max: 4,
step: 0.05,
label: "Height Multiplier"
})
},
{ label: "Chart Size" }
)
})
)
Insert cell
viewof modifier = Inputs.form(
{
width: Inputs.range([0.2, 1], {
label: "Width Multiplier",
value: 1,
step: 0.1,
width: 140
}),
height: Inputs.range([0.6, 4], {
label: "Height Coefficient",
value: 1,
step: 0.1,
width: 140
}),
indicatorEnabled: Inputs.toggle({
label: html`<strong>Enable Indicators</strong>`,
value: preset.indicator ?? 1,
width: 140
}),
date: Inputs.date({
label: "Since Week Including:",
min: "2021-11-24",
max: new Date(),
value: preset.date ?? new Date(Date.now() - 7 * 24 * 60 * 60 * 1000),
width: 140,
required: true
})
},
{
template: ({ width, height, indicatorEnabled, date }) =>
htl.html`
<div style="display: flex; gap: 20px; flex-direction: row;">
<div style="display: flex; flex-direction: column; flex-basis: 50%; align-items: flex-start;">
<div>${width}</div>
<div>${height}</div>
</div>
<div style="display: flex; flex-direction: column; flex-basis: 50%; align-items: flex-start;">
<div>${indicatorEnabled}</div>
<div>${date}</div>
</div>
</div>`
}
)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
function divergingDomainOn(week) {
const today = new Date(Date.now());
const weeks = Span("2021-11-24", today).numberWeeks;
return [1, week + 1, weeks];
}
Insert cell
scale = d3.scaleDiverging().domain(divergingDomainOn(weeksSince(modifier.date)))
Insert cell
predicate = d3.scaleOrdinal().domain([true, false])
Insert cell
dateIndicator = (scale, range, options = {}) => {
const {
enable = controls.value.indicators.recency,
nextCladeIndicator = false,
domain = scale.domain(),
defaultValue,
node,
predicate,
predicateRange = ["black", "gray"],
overriddenRange = range
} = options || {};

const recency = (map) => (node) =>
map(weeksSince(node.data.lineage.designation_date));
const nextcladePredicate = (node) =>
available_nextclade_lineages.includes(node.data.lineage.pango)
? predicateRange[0]
: predicateRange[1];

scale = scale.copy().domain(domain).range(range);

if (predicate) {
return (d) => (enable ? scale(predicate(d)) : defaultValue);
}
if (node) {
return enable ? scale(node) : defaultValue;
}

console.log(`${enable}, ${nextCladeIndicator}`);
if (nextCladeIndicator && enable) {
return (node) =>
available_nextclade_lineages.includes(node.data.lineage.pango)
? predicateRange[0]
: recency(scale)(node);
} else if (nextCladeIndicator) {
return (node) => nextcladePredicate(node);
} else if (enable) {
return (node) => recency(scale.copy().range(overriddenRange))(node);
}

return defaultValue;

// return modifier.indicatorEnabled ? recency(scale) : (node) => nextclade(node);
// : defaultValue === undefined
// ? undefined
// : defaultValue;
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
GUI = require("https://unpkg.com/controls-gui@1.2.1/dist/controls-gui.min.js")
Insert cell
State = require("https://unpkg.com/controls-state@1.1.1/dist/controls-state.min.js")
Insert cell
function wrapGUI(state, options) {
const root = document.createElement("div");
const gui = GUI(
state,
Object.assign(
{
root: root,
containerCSS: "max-width:600px",
theme: Object.assign({}, (options || {}).theme, {
fontFamily: "'Helvetica', sans-serif",
fontSize: "12px",
fontColor: "black",
controlBgColor: "white",
controlBorderRadius: "2px",
controlBorderColor: "#aaa",
fieldBgColor: "white",
fieldHoverColor: "#f8f8f8",
fieldActiveColor: "#ddd",
fieldBorderColor: "#ccc",
fieldHeight: 35,
sectionHeadingColor: "white",
sectionHeadingBgColor: "#005F87",
sectionHeadingHoverColor: "#005F87",
sectionHeadingBorderColor: "#005F87",
sectionHeadingHeight: 30,
visibilityFontColor: "#fff",
sliderThumbColor: "#005F87",
focusBorderColor: "#888"
})
},
options || {}
)
).$field.onChanges((e) => root.dispatchEvent(new CustomEvent("input")));
root.value = state;

const checkboxInputs = root.querySelectorAll(
'[class|="controlPanel"] input[type="checkbox" i]'
);

function handleInputChange(e) {
let target = e.target;
let label = document.querySelector(`label[for="${target.id}"]`);
label.textContent = `${target.checked ? "Enabled" : "Disabled"}`;
target.insertAdjacentElement("afterend", label);
}

checkboxInputs.forEach((input) => {
const label = document.createElement("label");
label.setAttribute("for", input.id);
label.innerText = `${input.checked ? "Enabled" : "Disabled"}`;
input.parentNode.insertBefore(label, input.parentNode.nextSibling);
input.addEventListener("change", (event) => {
const label = event.target.parentNode.querySelector("label");
label.textContent = event.target.checked ? "Enabled" : "Disabled";
});
});

return root;
}
Insert cell
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