Public
Edited
Nov 27, 2019
3 forks
9 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
layers = [{id: '1891-1892', title: 'De la double Essence du langage'}, {id: '1899-1903', title: 'Notes Item'}, {id: '1910-1911', title: 'III Cours de linguistique générale'}]
Insert cell
present = (datum, lid) => !('layers' in datum) || datum.layers.includes(lid)
Insert cell
data = {
var levels = [
[
{id: 'Entity', type: 'Concept'},
{id: 'Telic', type: 'Concept'},
{id: 'Agentive', type: 'Concept'},
{id: 'Constitutive', type: 'Concept'}
],
[
{id: 'Linguistic Entity', type: 'Concept', parents: ['Entity']}
],
[
{id: 'Relational Entity', type: 'Concept', parents: ['Linguistic Entity']},
{id: 'Concrete Element', type: 'Concept', parents: ['Linguistic Entity']},
{id: 'Mental Element', type: 'Concept', parents: ['Linguistic Entity']}
],
[
{id: 'SIGN', type: 'Concept Instance', parents: ['Relational Entity'], layers: ['1891-1892', '1899-1903', '1910-1911']},
{id: 'SIGNIFIER', type: 'Concept Instance', parents: ['Concrete Element'], layers: ['1891-1892', '1899-1903', '1910-1911']},
{id: 'SOUND', type: 'Concept Instance', parents: ['Concrete Element'], layers: ['1891-1892', '1899-1903', '1910-1911']},
{id: 'SIGNIFIED', type: 'Concept Instance', parents: ['Mental Element'], layers: ['1891-1892', '1899-1903', '1910-1911']},
{id: 'VALUE', type: 'Concept Instance', parents: ['Mental Element'], layers: ['1891-1892', '1910-1911']},
{id: 'USAGE', type: 'Concept Instance', parents: ['Mental Element'], layers: ['1891-1892']}
],
[
{id: 'sème', type: 'Term', parents: ['SIGN'], layers: ['1899-1903']},
{id: 'terme', type: 'Term', parents: ['SIGN'], layers: ['1910-1911']},
{id: 'mot', type: 'Term', parents: ['SIGN'], layers: ['1910-1911']},
{id: 'signe', type: 'Term', parents: ['SIGNIFIER','SIGN'], layers: ['1891-1892', '1899-1903','1910-1911']},
{id: 'signifiant ', type: 'Term', parents: ['SIGNIFIER'], layers: ['1910-1911']},
{id: 'image vocale ', type: 'Term', parents: ['SIGNIFIER'], layers: ['1910-1911']},
{id: 'image acoustique ', type: 'Term', parents: ['SIGNIFIER'], layers: ['1910-1911']},
{id: 'signe vocal ', type: 'Term', parents: ['SIGNIFIER'], layers: ['1910-1911']},
{id: 'signe acoustique ', type: 'Term', parents: ['SIGNIFIER'], layers: ['1910-1911']},
{id: 'figure acoustique ', type: 'Term', parents: ['SIGNIFIER'], layers: ['1910-1911']},
{id: 'sensation auditive ', type: 'Term', parents: ['SIGNIFIER'], layers: ['1910-1911']},
{id: 'son', type: 'Term', parents: ['SIGNIFIER'], layers: ['1891-1892']},
{id: 'forme', type: 'Term', parents: ['SIGNIFIER'], layers: ['1891-1892', '1899-1903']},
{id: 'sôme', type: 'Term', parents: ['SIGNIFIER'], layers: ['1899-1903']},
{id: 'côté vocal', type: 'Term', parents: ['SIGNIFIER'], layers: ['1899-1903']},
{id: 'aposème', type: 'Term', parents: ['SIGNIFIER','SOUND'], layers: ['1899-1903']},
{id: 'son ', type: 'Term', parents: ['SOUND'], layers: ['1910-1911']},
{id: 'son matériel', type: 'Term', parents: ['SOUND'], layers: ['1891-1892', '1910-1911']},
{id: 'figure vocale', type: 'Term', parents: ['SOUND'], layers: ['1891-1892', '1899-1903']},
{id: 'idée', type: 'Term', parents: ['SIGNIFIED'], layers: ['1891-1892', '1899-1903', '1910-1911']},
{id: 'sens', type: 'Term', parents: ['SIGNIFIED'], layers: ['1891-1892','1899-1903', '1910-1911']},
{id: 'signification', type: 'Term', parents: ['SIGNIFIED'], layers: ['1891-1892', '1899-1903', '1910-1911']},
{id: 'côte idéologique', type: 'Term', parents: ['SIGNIFIED'], layers: ['1899-1903']},
{id: 'concept', type: 'Term', parents: ['SIGNIFIED'], layers: ['1910-1911']},
{id: 'signifié', type: 'Term', parents: ['SIGNIFIED'], layers: ['1910-1911']},
{id: 'fonction', type: 'Term', parents: ['VALUE'], layers: ['1891-1892', '1910-1911']},
{id: 'valeur', type: 'Term', parents: ['VALUE'], layers: ['1891-1892', '1910-1911']},
{id: 'emploi', type: 'Term', parents: ['USAGE'], layers: ['1891-1892']}
],
[
{id: 'signe-idée', type: 'Term', parents: ['signe','idée','SIGN'], layers: ['1891-1892']},
{id: 'son-idée', type: 'Term', parents: ['son','idée','SIGN'], layers: ['1891-1892']},
{id: 'forme-sens', type: 'Term', parents: ['forme','sens','SIGN'], layers: ['1891-1892']}
]
]
// precompute level depth
levels.forEach((l,i) => l.forEach(n => n.level = i))
var nodes = levels.reduce( ((a,x) => a.concat(x)), [] )
var nodes_index = {}
nodes.forEach(d => nodes_index[d.id] = d)
// objectification
nodes.forEach(d => {
d.parents = (d.parents === undefined ? [] : d.parents).map(p => nodes_index[p])
})
// precompute bundles
levels.forEach((l, i) => {
var index = {}
l.forEach(n => {
if(n.parents.length == 0) {
return
}
var id = n.parents.map(d => d.id).sort().join('--')
if (id in index) {
index[id].parents = index[id].parents.concat(n.parents)
}
else {
index[id] = {id: id, parents: n.parents.slice(), level: i}
}
n.bundle = index[id]
})
l.bundles = Object.keys(index).map(k => index[k])
l.bundles.forEach((b, i) => b.i = i)
})
var links = []
nodes.forEach(d => {
d.parents.forEach(p => links.push({source: d, bundle: d.bundle, target: p}))
})
var bundles = levels.reduce( ((a,x) => a.concat(x.bundles)), [] )
// reverse pointer from parent to bundles
bundles.forEach(b => b.parents.forEach(p => {
if(p.bundles_index === undefined) {
p.bundles_index = {}
}
if(!(b.id in p.bundles_index)) {
p.bundles_index[b.id] = []
}
p.bundles_index[b.id].push(b)
}))
nodes.forEach(n => {
if(n.bundles_index !== undefined) {
n.bundles = Object.keys(n.bundles_index).map(k => n.bundles_index[k])
}
else {
n.bundles_index = {}
n.bundles = []
}
n.bundles.forEach((b, i) => b.i = i)
})
links.forEach(l => {
if(l.bundle.links === undefined) {
l.bundle.links = []
}
l.bundle.links.push(l)
})
// layout
const padding = 8
const node_height = 22
const node_width = 100
const bundle_width = 14
const level_y_padding = 16
const metro_d = 4
const c = 16
const min_family_height = 16
nodes.forEach(n => n.height = (Math.max(1, n.bundles.length)-1)*metro_d)
var x_offset = padding
var y_offset = padding
levels.forEach(l => {
x_offset += l.bundles.length*bundle_width
y_offset += level_y_padding
l.forEach((n, i) => {
n.x = n.level*node_width + x_offset
n.y = node_height + y_offset + n.height/2
y_offset += node_height + n.height
})
})
var i = 0
levels.forEach(l => {
l.bundles.forEach(b => {
b.x = b.parents[0].x + node_width + (l.bundles.length-1-b.i)*bundle_width
b.y = i*node_height
})
i += l.length
})
links.forEach(l => {
l.xt = l.target.x
l.yt = l.target.y + l.target.bundles_index[l.bundle.id].i*metro_d - l.target.bundles.length*metro_d/2 + metro_d/2
l.xb = l.bundle.x
l.xs = l.source.x
l.ys = l.source.y
})
// compress vertical space
var y_negative_offset = 0
levels.forEach(l => {
y_negative_offset += -min_family_height + d3.min(l.bundles, b => d3.min(b.links, link => (link.ys-c)-(link.yt+c))) || 0
l.forEach(n => n.y -= y_negative_offset)
})
// very ugly, I know
links.forEach(l => {
l.yt = l.target.y + l.target.bundles_index[l.bundle.id].i*metro_d - l.target.bundles.length*metro_d/2 + metro_d/2
l.ys = l.source.y
l.c1 = l.source.level-l.target.level > 1 ? node_width/2+c : c
l.c2 = c
})
var layout = {
height: d3.max(nodes, n => n.y) + node_height/2 + 2*padding,
node_height,
node_width,
bundle_width,
level_y_padding,
metro_d
}
return {levels, nodes, nodes_index, links, bundles, layout}
}
Insert cell
Insert cell
Insert cell
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