Published
Edited
Jun 6, 2020
1 fork
2 stars
Insert cell
Insert cell
Insert cell
file = FileAttachment('schema-types.csv')
Insert cell
csv = d3.csvParse(await file.text())
Insert cell
typeRows = csv.filter(rowIsType)
Insert cell
uriIndex = typeRows.reduce(uriIndexReducer, {})
Insert cell
nodes = typeRows.map(nodesMapper)
Insert cell
Insert cell
depths = {
const v = nodes.map(() => 0)
yield v
await Promises.delay(1000)
markDepth([nodes[uriIndex['http://schema.org/Thing']]], 0, v)
yield v
}
Insert cell
Insert cell
color = d3.scaleSequential([5, 0], d3.interpolateViridis)
Insert cell
getNodeSize = d => 4 + (d.numParents < 2 ? 0 : d.numParents * 2)
Insert cell
samplePaths = getAncestryPaths(uriIndex['http://schema.org/TVSeries'])
Insert cell
samplePathLabels = pathsToLabels(samplePaths)
Insert cell
sampleAncestors = pathsToAncestorSet(samplePaths)
Insert cell
pathsToLabels = paths => paths
.map(row => row
.map(n => typeRows[n].label)
.reverse())
Insert cell
pathsToAncestorSet = paths => new Set(paths.reduce((acc, path) => ([...acc, ...path]), []))
Insert cell
getAncestryPaths = n => {
const expandPaths = (n, paths) => {
const nextPaths = paths.map(path => [...path, n])
const parents = findParents(n)
return parents.length > 0 ?
parents.reduce((acc, parent) => ([...acc, ...expandPaths(parent, nextPaths)]), []) :
nextPaths
}
const paths = [[n]]
return findParents(n).reduce((acc, parent) => ([...acc, ...expandPaths(parent, paths)]), [])
}
Insert cell
findParents = n => links.filter(l => l.target.id === n).map(l => l.source.id)
Insert cell
function markDepth(ns, d, value) {
const children = []
for(let i = 0; i < ns.length; i++){
const nn = ns[i]
value[nn.id] = d
children.push(...findSubTypes(nn))
}
if(children.length) markDepth(children, d + 1, value)
}
Insert cell
findSubTypes = node => links.filter(l => l.source === node).map(l => l.target)
Insert cell
updateNode = node => node.attr('transform', d => `translate(${d.x}, ${d.y})`)
Insert cell
Insert cell
drag = simulation => {
function dragStart(d) {
if (!d3.event.active) simulation.alphaTarget(0.3).restart()
d.fx = d.x
d.fy = d.y
}
function dragMove(d) {
d.fx = d3.event.x
d.fy = d3.event.y
}
function dragEnd(d) {
if (!d3.event.active) simulation.alphaTarget(0)
d.fx = null
d.fy = null
}
return d3.drag()
.on('start', dragStart)
.on('drag', dragMove)
.on('end', dragEnd)
}
Insert cell
nodesMapper = ({id, label, subTypeOf}) => ({
id: uriIndex[id],
label,
x: Math.random() * width,
y: Math.random() * height,
numParents: subTypeOf.split(',').length,
})
Insert cell
linksReducer = (acc, row, i) => ([
...acc,
...(row.subTypes.split(',')
.map(uri => {
const target = uriIndex[uri.trim()]
return target ? {
source: i,
target,
} : undefined
})
.filter(i => i !== undefined)
)
])
Insert cell
typeIndexReducer = (acc, row, i) => ({...acc, [row.label]: i})
Insert cell
uriIndexReducer = (acc, row, i) => ({...acc, [row.id]: i})
Insert cell
rowIsType = row => !row.comment.startsWith('Data type') && (row.subTypeOf !== '' || row.subTypes !== '')
Insert cell
d3 = require('d3')
Insert cell
width = 800
Insert cell
height = 900
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