Published
Edited
Aug 22, 2021
3 forks
Importers
2 stars
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

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