Published
Edited
Nov 6, 2021
Importers
1 star
Insert cell
Insert cell
limit = 1000;
Insert cell
base = 0;
Insert cell
width = 500
Insert cell
height = Math.min(640, width)
Insert cell
computeChart()
Insert cell
computeChart = function(data = contentComputed) {
const svg = d3.create("svg")
.attr("viewBox", [-width, -height, width*2, height*2])
.attr("font-size", 10)
.attr("font-family", "sans-serif");

const chords = chord(data.matrix);

const group = svg.append("g")
.selectAll("g")
.data(chords.groups)
.join("g");

group.append("path")
.attr("fill", d => color(d.index))
.attr("stroke", d => d3.rgb(color(d.index)).darker())
.attr("d", arc);

group.append("text")
.each(d => { d.angle = (d.startAngle + d.endAngle) / 2; })
.attr("dy", ".35em")
.attr("transform", d => `
rotate(${(d.angle * 180 / Math.PI - 90)})
translate(${innerRadius + 26})
${d.angle > Math.PI ? "rotate(180)" : ""}
`)
.attr("text-anchor", d => d.angle > Math.PI ? "end" : null)
.text(d => { var text = data.nameByIndex.get(d.index);
console.log("data text: ", text)
return(text);})

svg.append("g")
.attr("fill-opacity", 0.67)
.selectAll("path")
.data(chords)
.join("path")
.attr("d", ribbon)
.attr("fill", d => color(d.target.index))
.attr("stroke", d => d3.rgb(color(d.target.index)).darker());

return svg.node();
}
Insert cell
function groupTicks(d, step) {
const k = (d.endAngle - d.startAngle) / d.value;
return d3.range(0, d.value, step).map(value => {
return {value: value, angle: value * k + d.startAngle};
});
}
Insert cell
formatValue = d3.formatPrefix(",.0", 1e3)
Insert cell
chord = d3.chord()
.padAngle(0.05)
.sortSubgroups(d3.descending)
Insert cell
arc = d3.arc()
.innerRadius(innerRadius)
.outerRadius(outerRadius)
Insert cell
ribbon = d3.ribbon()
.radius(innerRadius)
Insert cell
color = d3.scaleOrdinal()
.domain(d3.range(4))
.range(["#000000", "#FFDD89", "#957244", "#F26223"])
Insert cell
outerRadius = Math.min(width, height) * 0.5 - 30
Insert cell
innerRadius = outerRadius - 20
Insert cell
d3 = require("d3@5")
Insert cell
resource = "https://dydra.com/test/tblf"
Insert cell
import { resourceAPI } from "@datagenous/resource-protocol-library"
Insert cell
sparqlPost = resourceAPI(resource, "POST");
Insert cell
gspGet = resourceAPI(resource+".nt", "GET");
Insert cell
knownTypes = ["http://xmlns.com/foaf/0.1/Person"];
Insert cell
requestResults =
// getRepresentationAsNT();
getRepresentationAsSparqlResults();
Insert cell
getRepresentationAsNT = function() {
return( gspGet({"Accept": "application/n-triples"}) );
}
Insert cell
getRepresentationAsSparqlResults = function() {
return( sparqlPost("select ?s ?p ?o where { ?s ?p ?o }",
{"Content-Type": "application/sparql-query",
"Accept": "application/sparql-results+json"}) );
}
Insert cell
components = translateGraphDocument(requestResults)
Insert cell
context = ({"type": "http://www.w3.org/1999/02/22-rdf-syntax-ns#type",
"href": ["http://www.w3.org/2000/01/rdf-schema#seeAlso",
"http://www.w3.org/2002/07/owl#sameAs"],
"link": "http://xmlns.com/foaf/0.1/knows",
"title": "http://xmlns.com/foaf/0.1/name"})
Insert cell
iriFieldMap = { var map = new Map();
for (const [name, value] of Object.entries(context)) {
console.log(name, value);
if (typeof(value) == "string") {map.set(value, name);}
else { value.forEach(function(iri) { map.set(iri, name); })}
}
return ( map );
}
Insert cell
translateNextGraphDocument = function(document) {
var contentType = document.contentType || document.mediaType;
console.log(contentType, document);
switch (contentType) {
case "application/sparql-results+json":
return (translateSparqlResultsToGraph(document));
case "application/n-triples":
case "application/n-quad":
case "text/turtle":
case "application/turtle":
return (translateRDFTriplesToGraph(document));
default:
throw ( new Error(`translateGraphDocument: no implementation for '${contentType}'`) );
}
}
Insert cell
translateGraphDocument = function(document) {
nodeMap.clear();
return ( translateNextGraphDocument(document) );
}

Insert cell
translateRDFTriplesToGraph = function(representation = requestResults) {
var data = representation.statements;
if (!data) { throw new Error("invalid rdf document: ", representation); }

function interpretStatement(stmt) {
var subject = stmt.subject.lexicalForm || stmt.subject.label || stmt.subject.value;
var predicate = stmt.predicate.lexicalForm || stmt.subject.value;
var object = stmt.object;
object = (typeof(object) == "object"
? (object.lexicalForm || object.label || object.value)
: object);
addAssertion(subject, predicate, object);
}
for (var stmt of data.slice(0,limit)) {interpretStatement(stmt)};
var nodes = Array.from(nodeMap.values()).filter(testNode).reverse();
nodes.forEach(canonicalizeNode);
links.length = 0;
nodes.forEach(addLinks);
return ({nodes, links});
}
Insert cell
/** chord occurrence matrix requires cross reference between node objects in
order the use the index numbers.
*/
translateSparqlResultsToGraph = function(representation = requestResults) {
var data = representation.results.bindings;
if (!data) { throw new Error("invalid sparql results document: ", representation); }

function interpretSolution(solution) {
var subject = solutionSubjectValue(solution);
var predicate = solutionPredicateValue(solution);
var object = solutionObjectValue(solution);
addAssertion(subject, predicate, object);
}
for (var stmt of data.slice(0,limit)) {interpretSolution(stmt)};
var nodes = Array.from(nodeMap.values()).filter(testNode).reverse();
nodes.forEach(canonicalizeNode);
links.length = 0;
nodes.forEach(addLinks);
return ({nodes, links});
}

Insert cell
Insert cell
nodeMap = new Map();
Insert cell
Insert cell
solutionObjectValue = function(solution) {
var term = solution.o;
return (typeof(term) == "object"
? (term.lexicalForm || term.label || term.value)
: term);
}
Insert cell
solutionPredicateValue = function(solution) {
var term = solution.p;
if (typeof(term) == "object") {
return (term.lexicalForm || term.value);
} else {
throw new Error("invalid predicate: ", term);
}
}
Insert cell
solutionSubjectValue = function(solution) {
var term = solution.s;
if (typeof(term) == "object") {
return ( term.lexicalForm || term.label || term.value );
} else {
throw new Error("invalid subject: ", term);
}
}
Insert cell
ensureNode = function (id) {
// console.log("ensure: ", id);
var n = nodeMap.get(id);
if (!n) {
n = {id: id,
group: ((typeof(id) == "number") ? id : id.replace(RegExp("^([^:]+):(.+)$"), "$1"))};
nodeMap.set(id, n);
}
return (n);
}

Insert cell
addAssertion = function(subject, predicate, object) {
var node = ensureNode(subject);
// augment fields
var fieldName = iriFieldMap.get(predicate);
if (fieldName) {
var fieldValue = node[fieldName];
if (undefined == fieldValue) {
node[fieldName] = object;
} else if (Array.isArray(fieldValue)) {
if (!fieldValue.includes(object)) {
fieldValue.push(object);
}
} else {
node[fieldName] = [fieldValue, object];
}
console.log("fieldValue after", node[fieldName]);
} else {
// skip
}
}
Insert cell
Insert cell
testNode = function (node) {
// console.log("known type: ", node.type);
var type = node.type;
if (typeof(type) == "string") {
return (knownTypes.includes(type));
} else if (Array.isArray(type)) {
for (type of type) { if (knownTypes.includes(type)) { return(true); } }
}
return (false);
}
Insert cell
contentStatic = [
[11975, 5871, 8916, 2868],
[ 1951, 10048, 2060, 6171],
[ 8010, 16145, 8090, 8045],
[ 1013, 990, 940, 6907]
]
Insert cell
contentComputed = computeContent(translateGraphDocument(requestResults))

Insert cell
computeContent = function(components = translateGraphDocument(requestResults)) {
console.log("computeContent", components)
var {nodes, links} = components;
var count = nodes.length;
var matrix = new Array(count);
const indexByName = new Map;
const nameByIndex = new Map;
nodes.forEach(function(node, index) {node.index = index});
for (var index = 0; index < count; index ++) {
matrix[index] = Array.from({length: count}).fill(0);;
}
// console.log("matrix", matrix);
for (var node of nodes) {
indexByName.set(node.title, node.index);
nameByIndex.set(node.index, node.title);
}
// console.log("links: ", links);
for (var link of links) {
// console.log(link);
var source = link.source;
var target = link.target;
var vector = matrix[source.index];
vector[target.index] = vector[target.index]+1;
}
return ( {matrix, indexByName, nameByIndex} );
}

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