Public
Edited
Feb 2, 2023
Insert cell
Insert cell
{
const figHeight = width * 0.4;
const svg = d3.create("svg").attr("viewBox", [0, 0, width, figHeight]);

const arrow = svg
.append("defs")
.append("marker")
.attr("id", "arrow")
.attr("viewBox", [0, 0, 10, 10])
.attr("refX", 5)
.attr("refY", 5)
.attr("markerWidth", 10)
.attr("markerHeight", 10)
.attr("orient", "auto-start-reverse")
.append("path")
.attr(
"d",
d3.line()([
[0, 0],
[0, 10],
[10, 5]
])
)
.attr("stroke", "#333");

const edges = svg
.selectAll("line")
.data(change_user_graph.edges)
.join("line")
.attr("marker-start", "url(#arrow)")
.style("stroke", "#333")
.style("stroke-width", 1);

const text = svg
.selectAll("text")
.data(change_user_graph.nodes)
.join("text")
.text((d) => d.id)
.style("font-size", "8pt")
.style("text-anchor", "middle")
.style("fill", "#333");

const simulation = d3
.forceSimulation(change_user_graph.nodes)
.force("charge", d3.forceManyBody())
.force("center", d3.forceCenter(width / 2, figHeight / 2))
.force(
"links",
d3.forceLink(edges).id((d) => d.id)
)
.force("boundary", forceBoundary(0, 0, width, figHeight))
.on("tick", () => {
text.attr("x", (node) => node.x).attr("y", (node) => node.y);

edges
.attr("x1", (edge) => edge.source.x)
.attr("y1", (edge) => edge.source.y)
.attr("x2", (edge) => edge.target.x)
.attr("y2", (edge) => edge.target.y);
});

return svg.node();
}
Insert cell
Insert cell
{
const figHeight = width;
const svg = d3.create("svg").attr("viewBox", [0, 0, width, figHeight]);

const arrow = svg
.append("defs")
.append("marker")
.attr("id", "arrow")
.attr("viewBox", [0, 0, 10, 10])
.attr("refX", 5)
.attr("refY", 5)
.attr("markerWidth", 10)
.attr("markerHeight", 10)
.attr("orient", "auto-start-reverse")
.append("path")
.attr(
"d",
d3.line()([
[0, 0],
[0, 10],
[10, 5]
])
)
.attr("stroke", "#333");

const edges = svg
.selectAll("line")
.data(change_comp_graph.edges)
.join("line")
.attr("marker-start", "url(#arrow)")
.style("stroke", "#333")
.style("stroke-width", 1);

const text = svg
.selectAll("text")
.data(change_comp_graph.nodes)
.join("text")
.text((d) => d.id)
.style("font-size", "8pt")
.style("text-anchor", "middle")
.style("fill", "#333");

const simulation = d3
.forceSimulation(change_comp_graph.nodes)
.force("charge", d3.forceManyBody())
.force("center", d3.forceCenter(width / 2, figHeight / 2))
.force(
"links",
d3.forceLink(edges).id((d) => d.id)
)
.force("boundary", forceBoundary(0, 0, width, figHeight))
.on("tick", () => {
text.attr("x", (node) => node.x).attr("y", (node) => node.y);

edges
.attr("x1", (edge) => edge.source.x)
.attr("y1", (edge) => edge.source.y)
.attr("x2", (edge) => edge.target.x)
.attr("y2", (edge) => edge.target.y);
});

return svg.node();
}
Insert cell
This third diagram shows the graph of users logging into computers, e.g. "johndoe@dom1" logging into "C1000". As in the previous diagram, this one offers almost no insight.
Insert cell
{
const figHeight = width;
const svg = d3.create("svg").attr("viewBox", [0, 0, width, figHeight]);

const arrow = svg
.append("defs")
.append("marker")
.attr("id", "arrow")
.attr("viewBox", [0, 0, 10, 10])
.attr("refX", 5)
.attr("refY", 5)
.attr("markerWidth", 10)
.attr("markerHeight", 10)
.attr("orient", "auto-start-reverse")
.append("path")
.attr(
"d",
d3.line()([
[0, 0],
[0, 10],
[10, 5]
])
)
.attr("stroke", "#333");

const edges = svg
.selectAll("line")
.data(user_comp_graph.edges)
.join("line")
.attr("marker-start", "url(#arrow)")
.style("stroke", "#333")
.style("stroke-width", 1);

const text = svg
.selectAll("text")
.data(user_comp_graph.nodes)
.join("text")
.text((d) => d.id)
.style("font-size", "8pt")
.style("text-anchor", "middle")
.style("fill", "#333");

const simulation = d3
.forceSimulation(user_comp_graph.nodes)
.force("charge", d3.forceManyBody())
.force("center", d3.forceCenter(width / 2, figHeight / 2))
.force(
"links",
d3.forceLink(edges).id((d) => d.id)
)
.force("boundary", forceBoundary(0, 0, width, figHeight))
.on("tick", () => {
text.attr("x", (node) => node.x).attr("y", (node) => node.y);

edges
.attr("x1", (edge) => edge.source.x)
.attr("y1", (edge) => edge.source.y)
.attr("x2", (edge) => edge.target.x)
.attr("y2", (edge) => edge.target.y);
});

return svg.node();
}
Insert cell
Insert cell
height = width
Insert cell
margin = ({ top: 100, right: 0, bottom: 0, left: 100 })
Insert cell
x = d3.scaleOrdinal().range([0, width])
Insert cell
z = d3.scaleLinear().domain([0, 4]).clamp(true)
Insert cell
c = d3.scaleSequential(d3.schemeCategory10).domain(d3.range(10))
Insert cell
Insert cell
data
Insert cell
change_user_graph = {
const nodeMap = new Map();
const edgeMap = new Map();

for (let event of data) {
if (event.src_user_name != event.dst_user_name) {
const key = `${event.src_user_name}-${event.dst_user_name}`;
nodeMap.set(event.src_user_name, { id: event.src_user_name });
nodeMap.set(event.dst_user_name, { id: event.dst_user_name });
if (!(key in edgeMap)) {
edgeMap[key] = 0;
}
edgeMap[key]++;
}
}

const edges = [];

for (let [key, count] of Object.entries(edgeMap)) {
const [source, target] = key.split("-");
edges.push({
source: nodeMap.get(source),
target: nodeMap.get(target),
count
});
}

const nodes = Array.from(nodeMap.values());

return { nodes, edges };
}
Insert cell
change_comp_graph = {
const nodeMap = new Map();
const edgeMap = new Map();

for (let event of data) {
if (event.src_comp != event.dst_comp) {
const key = `${event.src_comp}-${event.dst_comp}`;
nodeMap.set(event.src_comp, { id: event.src_comp });
nodeMap.set(event.dst_comp, { id: event.dst_comp });
if (!(key in edgeMap)) {
edgeMap[key] = 0;
}
edgeMap[key]++;
}
}

const edges = [];

for (let [key, count] of Object.entries(edgeMap)) {
const [source, target] = key.split("-");
edges.push({
source: nodeMap.get(source),
target: nodeMap.get(target),
count
});
}

const nodes = Array.from(nodeMap.values());

return { nodes, edges };
}
Insert cell
user_comp_graph = {
const nodeMap = new Map();
const edgeMap = new Map();

for (let event of data) {
const source = `${event.src_user_name}@${event.src_user_domain}`;
const target = event.dst_comp;
const key = `${source}-${target}`;
nodeMap.set(source, { id: source });
nodeMap.set(target, { id: target });
if (!(key in edgeMap)) {
edgeMap[key] = 0;
}
edgeMap[key]++;
}

const edges = [];

for (let [key, count] of Object.entries(edgeMap)) {
const [source, target] = key.split("-");
edges.push({
source: nodeMap.get(source),
target: nodeMap.get(target),
count
});
}

const nodes = Array.from(nodeMap.values());

return { nodes, edges };
}
Insert cell
import { data } from "@mehaase/w209-data-loading"
Insert cell
Insert cell
forceBoundary = require("d3-force-boundary")
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