Published
Edited
Aug 22, 2021
3 forks
Importers
2 stars
Also listed in…
Clustergrammer-GL
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
container = html `<div style="height:${inst_height}px"></div>`
Insert cell
mutable is_fullscreen = false
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);
d3.select('.row_search_container').remove()
}
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
mutable color_type = 'category'
Insert cell
mutable selected_row = Generators.observe(notify => {
const mouse_click = () => {

if (cgm.params.tooltip.tooltip_type === 'row-label'){
var inst_name = cgm.params.int.mouseover.row.name
if (selection != inst_name){
mutable selection = inst_name
} else {
mutable selection = 'category'
}
}
notify(cgm.params.int.mouseover.row.name)
}
viewof cgm.addEventListener("click", mouse_click);
notify(cgm.params.int.mouseover.row.name);

return () => viewof cgm.removeEventListener("mousemove", mouse_click);
})
Insert cell
umap_data_ini = d3.csvParse(await FileAttachment("usda_foods_umap.csv").text())
Insert cell
Insert cell
Insert cell
Insert cell
umap_data = umap_data_ini.map(
x => {
var inst_long = umap_x_scale(parseFloat(x['x']))
var inst_lat = umap_y_scale(parseFloat(x['y']))
var inst_food_type = food_type[x['']].split(': ')[1]
var rgb = d3.color(cat_colors[inst_food_type])
var inst_color
if (selection === 'category'){
// color by category
var inst_alpha
if (selection_type == 'col-dendro'){
if (dendro_selections.includes(x[''])){
inst_alpha = 255
} else {
inst_alpha = 25
}
} else {
inst_alpha = 255
}
inst_color = [rgb.r, rgb.g, rgb.b, inst_alpha]
} else {
// color by dimension
var inst_index = network.col_node_names.indexOf(x[''])
var inst_data = dimension_data[inst_index]
var inst_opacity = opacity_scale(Math.abs(inst_data))
if (inst_data > 0){
inst_color = [255, 0, 0, inst_opacity]
} else {
inst_color = [0, 0, 255, inst_opacity]
}
}
var inst_obj = ({
name: x[''],
position: [inst_long, inst_lat],
food_type: inst_food_type,
color: inst_color
})

return inst_obj
}
)
Insert cell
d3 = require("d3@5")
Insert cell
inst_lat = 40.5
Insert cell
inst_lng = -73.5
Insert cell
inst_zoom = 8.75
Insert cell
inst_height = {
var inst_height
if (orientation === 'Portrait'){
inst_height = 850
} else {
inst_height = 850
}
return inst_height
}
Insert cell
umap_data[0]
Insert cell
umap_x_min = Math.min.apply(Math, umap_data_ini.map(function(o) { return parseFloat(o['x']) }))
Insert cell
umap_x_max = Math.max.apply(Math, umap_data_ini.map(function(o) { return parseFloat(o['x']) }))
Insert cell
umap_y_min = Math.min.apply(Math, umap_data_ini.map(function(o) { return parseFloat(o['y']) }))
Insert cell
umap_y_max = Math.max.apply(Math, umap_data_ini.map(function(o) { return parseFloat(o['y']) }))
Insert cell
umap_x_scale = d3.scaleLinear()
.domain([umap_x_min, umap_x_max])
.range([-74, -73]);
Insert cell
umap_y_scale = d3.scaleLinear()
.domain([umap_y_min, umap_y_max])
.range([40, 41]);
Insert cell
umap_data[0]
Insert cell
scatter_layer_rename = {

const scatterLayer = new deck.ScatterplotLayer({
data: umap_data,
getPosition: d => d.position,
getFillColor: d => d.color,
getRadius: 300,
opacity: 0.75,
pickable: true,
autoHighlight: true,
highlightColor: d => [50, 50, 50, 200],
// stroked: true,
// lineWidthMinPixels: 0.05,
onHover: function(info, event){
// if ('object' in info){
// mutable inst_neighborhood = info.object.Neighborhood
// }
},
onClick: function(info, event){
// if ('object' in info){
// if (info.object.name !== selected_station.name){
// // select stations to view paths
// mutable path_types = 'all'
// mutable selected_station = info.object
// } else {
// // turn off paths
// mutable selected_station = {}
// }
// }
}
})

deckgl.setProps({layers: [ scatterLayer]});

return scatterLayer
}
Insert cell
deckgl = {
// // reference for below https://observablehq.com/@tomvantilburg/deckgl-mapbox-and-3d-tiles
// // This is an Observable hack: clear previously generated content
container.innerHTML = '';
return new deck.DeckGL({
container,
initialViewState: {
longitude: inst_lng,
latitude: inst_lat,
zoom: inst_zoom,
minZoom: 8,
maxZoom: 15,
},
controller: true,

getTooltip: ({object}) => {
// return object && `${object.Neighborhood} \n ${object['cross-x']} and ${object['cross-y']}
return object && `${object.name}\n Food Type: ${object.food_type}` },
// Mapbox settings
// set `map: false` to turn off Mapbox base map
// map: mapboxgl,
// This token is for demo-purpose only and rotated regularly. Get your token at https://www.mapbox.com
// mapboxApiAccessToken: mapbox_token,
mapStyle: 'mapbox://styles/mapbox/light-v9',
});
}
Insert cell
// deck = require.alias({
// // optional dependencies
// h3: {},
// s2Geometry: {}
// })('deck.gl@8.3.7/dist.min.js')

deck = require.alias({
// optional dependencies
h3: {},
s2Geometry: {}
})('deck.gl@8.4.6/dist.min.js')
Insert cell
Insert cell
Insert cell
import {slider, select} from '@jashkenas/inputs'
Insert cell
// set table style to full width
html`
<style>
p {
min-width: 100%;
}
`
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