Public
Edited
Oct 3, 2023
Insert cell
Insert cell
height = 800
Insert cell

container = {

return html `<div id='the-container' style="height:${height}px; border-style:solid; border-color:#d3d3d3; border-width:1px; position: relative;"></div>`
}

// container = html `<div style="height:800px; border-style:solid; border-color:#d3d3d3; border-width:1px"></div>`
Insert cell
dashboard = html`

<div style="display: flex;">

<div id="meta_dropdown", style="margin-right: 1px; border:1px; text-align:left;">${viewof select_gene_dropdown} </div>


<div style="margin-left: 2px; margin-right: -100px; border:1px; text_align:left;">${viewof show_image}</div>
<div style="margin-left: -100px; margin-right: 5px; border:1px; text_align:center;">${viewof polygon_opacity}</div>
<div style="margin-left: 5px; margin-right: 1px; border:1px; text_align:left;">${viewof transcript_size}</div>
</div>

<div>
${container}
</div>

`

// <div id="meta_dropdown", style="margin-right: 10px; border:1px; text-align:left;">${viewof select_cell_dropdown} </div>
// <div style="margin-left: -100px; margin-right: 1px; border:1px; text_align:left;">${viewof zlayer}</div>
Insert cell
ini_view_type = '3D'
Insert cell
mutable view_type = view_type_toggle
Insert cell
viewof view_type_toggle = Inputs.radio(['2D','3D'], {value: ini_view_type})
Insert cell
Object.keys(cat_colors).sort()
Insert cell
viewof select_gene_dropdown = select({'options':['none'].concat(Object.keys(cat_colors).sort()), value: init_gene})
Insert cell
mutable select_gene = select_gene_dropdown
Insert cell
viewof select_cell_dropdown = select({'options':['none'].concat(Object.keys(cell_colors).sort()), value : 'none'})
Insert cell
mutable select_cell = select_cell_dropdown
Insert cell
viewof transcript_size = slider({
value: 1,
min : 0,
max : 5,
step : .5,
description: "Trx Size"
})
Insert cell
init_gene = 'tiger'
Insert cell
scale_z = 15
Insert cell
cat_colors = ({
'dog': 'blue',
'elephant': 'purple',
'tiger': 'orange'
})
Insert cell
cell_colors = ({
'neuron': 'blue',
'immune': 'purple',
'other': 'orange'
})
Insert cell
frame_colors = ({
'tuna': 'red',
'octopus': 'blue'
})
Insert cell
// height = 800
Insert cell
// blue square image
image = '"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAIAAAAC64paAAAAHUlEQVR4nGNkYPjPQC5gIlvnqOZRzaOaRzVTRTMAIJ4BJ6WiocQAAAAASUVORK5CYII="'
Insert cell
image_proc = image.slice(1,-1)
Insert cell
radius
Insert cell
poly_line_width = 3
Insert cell
ini_opacity = .5
Insert cell
import {slider, select} from '@jashkenas/inputs'
Insert cell
viewof polygon_opacity = slider({
value: ini_opacity,
min : 0,
max : 1,
step : .1,
description: "Polygon Opacity"
})
Insert cell
viewof transcripts_paritioned = Inputs.toggle({
label : "Partitioned Transcripts Only",
// value : false,
values :[1,0]
})
Insert cell
viewof show_image = Inputs.toggle({label: "Image", value: true})
Insert cell
viewof zlayer = Inputs.select(
new Map([['All',[0,1,2,3,4,5,6]],["0",[0]],["1",[1]],["2",[2]],["3",[3]],["4",[4]],["5",[5]],["6",[6]],['None',[]]]),
{
value : [0,1,2,3,4,5,6],
label : 'Transcripts Z-level'}
)
Insert cell
// this way we can perform a filtering of the scattered data using the selected gene
scatter_data_proc = scatter_data.filter(item => zlayer.includes(item.z))
.filter(d => {
if (select_gene === 'none'){
return d
} else {
return d.name === select_gene
}
})
Insert cell
polygon_data3d
Insert cell
zlayer
Insert cell
// this way we can perform a filtering of the scattered data using the selected gene
polygon_data_proc = polygon_data3d.filter(d => {
if (select_cell === 'none'){
return d
} else {
return d.cell_type === select_cell
}
})
Insert cell
select_gene
Insert cell
filtered_scatter_data = scatter_data.filter(item => item.partition !== -1)
.filter(d => {
if (select_gene === 'none'){
return d
} else {
return d.name === select_gene
}
})
// .filter(d => {
// if (select_gene !== 'none'){
// return d
// }
// })
Insert cell
bitmap_layer = new deck.BitmapLayer({
id: 'bitmap_layer',
bounds:image_bounds,
image:image_proc,
visible: show_image
});
Insert cell
pointcloud_layer = new deck.PointCloudLayer({
id: 'pointcloud_layer',
data: transcripts_paritioned === 0? scatter_data_proc: filtered_scatter_data.filter(item => zlayer.includes(item.z)),
getPosition: d => {
return [d.x, d.y, scale_z * d.z + 1/2*scale_z]
},
getColor: d => {
var inst_color
var unselected_color = [0, 0, 0, 1]

var rgb = d3.color(cat_colors[d.name])
if (select_gene === 'none'){
inst_color = [rgb.r, rgb.g, rgb.b, 255]
} else {
inst_color = unselected_color
if (d.name === select_gene){
inst_color = [rgb.r, rgb.g, rgb.b, 255]
}
}
return inst_color
},
getRadius: transcript_size,
pickable: true,
pointSize:transcript_size,
sizeUnits:'meters',
// autoHighlight: true,
highlightColor: d => [50, 50, 50],
radiusMinPixels: radius_min_pixels,
updateTriggers: {
getColor: [select_gene]
},
onClick: (info, event) => {
if (select_gene !== info.object.name){
mutable select_gene = info.object.name
d3.select('#meta_dropdown').select('select').node().value = info.object.name
} else {
mutable select_gene = 'none'
d3.select('#meta_dropdown').select('select').node().value = 'none'
}
}
})
Insert cell
scatter_layer = new deck.ScatterplotLayer({
id: 'scatter_layer',
data: transcripts_paritioned === 0? scatter_data_proc: filtered_scatter_data.filter(item => zlayer.includes(item.z)),
getPosition: d => {
return [d.x, d.y]
},
getFillColor: d => {
var inst_color
var unselected_color = [0, 0, 0, 1]

var rgb = d3.color(cat_colors[d.name])
if (select_gene === 'none'){
inst_color = [rgb.r, rgb.g, rgb.b, 255]
} else {
inst_color = unselected_color
if (d.name === select_gene){
inst_color = [rgb.r, rgb.g, rgb.b, 255]
}
}
return inst_color
},
getRadius: transcript_size,
pickable: true,
pointSize:transcript_size,
sizeUnits:'meters',
// autoHighlight: true,
highlightColor: d => [50, 50, 50],
radiusMinPixels: radius_min_pixels,
updateTriggers: {
getColor: [select_gene]
},
onClick: (info, event) => {
if (select_gene !== info.object.name){
mutable select_gene = info.object.name
d3.select('#meta_dropdown').select('select').node().value = info.object.name
} else {
mutable select_gene = 'none'
d3.select('#meta_dropdown').select('select').node().value = 'none'
}
}
})
Insert cell
opacity_255 = d3.scaleLinear().domain([0, 1]).range([0, 255])
Insert cell
[x.r, x.g, x.b,255]
Insert cell
x = d3.color(frame_colors[polygon_frame['features'][0].properties.group])

Insert cell
polyframe_layer = new deck.GeoJsonLayer({
id: 'polyframe_layer',
data: polygon_frame,
opacity: 1,
getFillColor: d => {
var inst_color
var rgb = d3.color(frame_colors[d.properties.group])
inst_color = [rgb.r, rgb.g, rgb.b, 255]
return inst_color
},
stroked: false,
filled: true,
pickable: true,
});
Insert cell
cell_colors
Insert cell
polygon_data3d
Insert cell
polygon_layer3d = new deck.PolygonLayer({
id: 'polygon_layer3d',
data: polygon_data_proc,
getFillColor: d => {
var inst_color
var rgb = d3.color(cell_colors[d.cell_type])
inst_color = [rgb.r, rgb.g, rgb.b, opacity_255(polygon_opacity)]
return inst_color
},
getLineColor: d => {
var inst_color
var rgb = d3.color(cell_colors[d.cell_type])
inst_color = [rgb.r, rgb.g, rgb.b, opacity_255(polygon_opacity)]
return inst_color
},
getLineWidth: d => 100,
getPolygon: d => d.coordinates,
getElevation: d => scale_z,
lineWidthMinPixels: 30,
stroked: true,
filled: false, // nick-working
extruded : true,
wireframe: true,
pickable: true,
visible: polygon_opacity !== 0,
updateTriggers: {
getFillColor: polygon_opacity,
getLineColor: polygon_opacity,
visible: polygon_opacity
},
});
Insert cell
polygon_data_proc[0].coordinates[0]
Insert cell
polygon_layer2d = new deck.PolygonLayer({
id: 'polygon_layer2d',
data: polygon_data_proc,
// getFillColor: d => {
// var inst_color
// var rgb = d3.color(cell_colors[d.cell_type])
// inst_color = [rgb.r, rgb.g, rgb.b, opacity_255(polygon_opacity)]
// return inst_color
// },
getLineColor: d => {
var inst_color
var rgb = d3.color(cell_colors[d.cell_type])
inst_color = [rgb.r, rgb.g, rgb.b, opacity_255(polygon_opacity)]
return inst_color
},
getLineWidth: d => 1,
getPolygon: d => d.coordinates,
// lineWidthMinPixels: 30,
stroked: true,
filled: false, // nick-working
pickable: true,
// visible: polygon_opacity !== 0,
updateTriggers: {
getFillColor: polygon_opacity,
getLineColor: polygon_opacity,
visible: polygon_opacity
},
});
Insert cell
{
if (view_type === '3D'){
deckgl.setProps({layers: [bitmap_layer, polygon_layer3d, pointcloud_layer, polyframe_layer]})
}
else{
deckgl.setProps({layers: [bitmap_layer, polyframe_layer, polygon_layer2d, scatter_layer]})
}
}
Insert cell
deck = require.alias({
// optional dependencies
h3: {},
s2Geometry: {}
})('deck.gl@8.3.7/dist.min.js')
Insert cell
// image_bounds = [[0, -image_size], [0, 0], [image_size, 0], [image_size, -image_size]]

// [[left, bottom], [left, top], [right, top], [right, bottom]]
image_bounds = [[0, -image_size], [0, 0], [image_size, 0], [image_size, -image_size]]
Insert cell
image_size = 10
Insert cell
radius = 1
Insert cell
radius_min_pixels = 0.5
Insert cell
center_x = 0
Insert cell
center_y = 0
Insert cell
deckgl = {
container.innerHTML = '';

if (view_type == '3D'){
var view = new deck.OrbitView({id: 'orbit'})
var INITIAL_VIEW_STATE = INITIAL_VIEW_STATE_3D
}else{
var view = new deck.OrthographicView({id: 'ortho'})
var INITIAL_VIEW_STATE = INITIAL_VIEW_STATE_2D
}
return new deck.DeckGL({
container,
views:[view],
initialViewState:INITIAL_VIEW_STATE,
controller: true,
getTooltip: ({object, layer}) => {
if (object){
if (layer.id === 'polygon_layer3d'){
return object && ` ${object.name}\n${object.cell_type} `
}
if (layer.id === 'polygon_layer2d'){
return object && ` ${object.name}\n${object.cell_type} `
}
else if (layer.id === 'polyframe_layer'){
return object && ` ${object.properties.name}\n${object.properties.group}`
}
else{
return object && `${object.name}`
}
} },
});
}
Insert cell
Type JavaScript, then Shift-Enter. Ctrl-space for more options. Arrow ↑/↓ to switch modes.

Insert cell
INITIAL_VIEW_STATE_3D = ({
target: [center_x, center_y, 0],
rotationX: 90,
// rotationOrbit: -720,
// minRotationX: -720,
// minRotationOrbit: -720,
zoom: zoom,
minZoom:min_zoom
})
Insert cell
INITIAL_VIEW_STATE_2D = ({
target: [center_x, center_y, 0],
zoom: zoom,
minZoom:min_zoom
})
Insert cell
min_zoom = -1.5
Insert cell
zoom = 0
Insert cell
d3 = require("d3@5")
Insert cell
Insert cell
pako = require('pako/dist/pako.min.js')
Insert cell
function decode_zipped_string(b64Data){
// Get some base64 encoded binary data from the server. Imagine we got this:
// Decode base64 (convert ascii to binary)
var strData = atob(b64Data);
// Convert binary string to character-number array
var charData = strData.split('').map(function(x){return x.charCodeAt(0);});
// Turn number array into byte-array
var binData = new Uint8Array(charData);
// Pako magic
var data = pako.inflate(binData);
// // Convert gunzipped byteArray back to ascii string:
// var strData = String.fromCharCode.apply(null, new Uint16Array(data));

// https://stackoverflow.com/questions/8936984/uint8array-to-string-in-javascript
var strData = new TextDecoder().decode(data);
// Output to console
return strData
}
Insert cell
// geojson_string = decode_zipped_string(zip_geojson_string)
Insert cell
Insert cell
polygon_frame = JSON.parse(decode_zipped_string(zip_polygon_frame))
Insert cell
zip_polygon_data3d = 'eJxtjcEKwjAMhl8l5JxD282Lr1KKDBe0sKaydQcV331dDirbIIH/I+T//BulS4xnwCknLvcoNyTAa85jH6UrPNWb94bAEjQmEHj7lx2B0xzWJx6GS3k+tE54HrOsXa+KzYfgQOWOXC1BHXtSl9mArlL7hZ07pjQL/9xhAXupP1k='
Insert cell
polygon_data3d = JSON.parse(decode_zipped_string(zip_polygon_data3d))
Insert cell
polygon_data3d
Insert cell
zip_scatter_data = 'eJyLrlbKS8xNVbJSUErJT1fSUVCqALINgHQlkDYE0lVQuiCxqCSzJDM/DyRfq6OA0Jiak1qQkZhXAtNtBNVtBNVthKbbEEV3SWZ6ahFMqwlUqylUqzGG1lgAgEsvhQ=='
Insert cell
scatter_data = JSON.parse(decode_zipped_string(zip_scatter_data))
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