Published
Edited
Apr 23, 2020
2 forks
Insert cell
Insert cell
Insert cell
gene_list
Insert cell
viewof cgm = {

// Clustergrammer-GL uses query selectors to re-find the container, so if we
// might want multiple instances of Clustergrammer-GL on the page, they’ll
// need unique identifiers! (It’d be better if Clustergrammer-GL used
// element.querySelector instead of document.querySelector and didn’t depend
// on these identifiers.)
const containerId = DOM.uid("container");
const container = html`<div style="height: 1025px;" id='${containerId.id}'></div>`;

// Clustergrammer-GL depends on the container having been inserted into the
// document before it’s initialized. We can do this by yielding! However,
// since we’re defining this cell as a view, we don’t want the view’s value
// to resolve until CGM has initialized. Hence we define the view’s value as
// a promise that resolves immediately after. We could simplify this if
// Clustergrammer-GL allowed you to pass in a detached container.
let resolve;
container.value = new Promise(r => resolve = r);
yield container;

// Initialize CGM.
// (We might want to use Observable’s reactive width here?)
const cgm = CGM({
network,
viz_width: 900,
viz_height: 900,
container
});

// Redefine the order parameters as getters and setters, so that we can intercept
// when these change and emit an event. That will allow other cells to listen for
// these changes are react accordingly.
Object.defineProperties(cgm.params.order.new, {
row: reactiveValue(container, "row", cgm.params.order.new.row),
col: reactiveValue(container, "col", cgm.params.order.new.col)
});

// Resolve the view’s value so that downstream cells can run.
resolve(cgm);
}
Insert cell
function reactiveValue(container, name, value) {
return {
get() {
return value;
},
set(v) {
value = v;
container.dispatchEvent(new CustomEvent("input", {detail: {name, value}}));
return value;
}
};
}
Insert cell
cgm.params.order.new // This is now updates on interaction!
Insert cell
Insert cell
mouseover_row_name = Generators.observe(notify => {
const mousemove = () => notify(cgm.params.int.mouseover.row.name);
viewof cgm.addEventListener("mousemove", mousemove);
notify(cgm.params.int.mouseover.row.name);
return () => viewof cgm.removeEventListener("mousemove", mousemove);
})
Insert cell
mouseover_col_name = Generators.observe(notify => {
const mousemove = () => notify(cgm.params.int.mouseover.col.name);
viewof cgm.addEventListener("mousemove", mousemove);
notify(cgm.params.int.mouseover.col.name);
return () => viewof cgm.removeEventListener("mousemove", mousemove);
})
Insert cell
// cgm.params.dendro.selected_clust_names

gene_list = Generators.observe(notify => {
const mousemove = () => notify(cgm.params.dendro.selected_clust_names);
viewof cgm.addEventListener("click", mousemove);
notify(cgm.params.dendro.selected_clust_names);
return () => viewof cgm.removeEventListener("mousemove", mousemove);
})
Insert cell
Insert cell
network = FileAttachment("pre-calc-viz.json").json()
Insert cell
Insert cell
CGM = require(await FileAttachment("clustergrammer-gl-0.11.9.js").url())
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