Public
Edited
Jun 26, 2024
Paused
1 fork
2 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
chart = {
const zoom = d3.zoom()
.scaleExtent([0.5, 32])
.on("zoom", zoomed);

const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height]);

const gGrid = svg.append("g");
const x = d3.scaleLinear()
.domain([extent_x[0]-3, extent_x[1]+3])
.range([0, width])

const y = d3.scaleLinear()
.domain([(extent_y[0] * k)-3, (extent_y[1] * k)+3])
.range([height, 0])

const z = d3.scaleOrdinal()
.domain(umap_embedding2.map(d => d[sel_col]))
.range(d3.schemeTableau10)

const yAxis = (g, y) => g
.call(d3.axisRight(y).ticks(12 * k))
.call(g => g.select(".domain").attr("display", "none"))

const xAxis = (g, x) => g
.attr("transform", `translate(0,${height})`)
const gDot = svg.append("g")
.attr("fill", "none")
.attr("class", "circles")
.attr("stroke-linecap", "round");

gDot.append("style").text(`
.circles {
stroke: transparent;
stroke-width: 0.1px;
}
.circles circle:hover {
stroke: black;
}
`);
gDot.selectAll("circle")
.data(umap_embedding2)
.join("circle")
.attr("cx", d => x(d.x))
.attr("cy", d => y(d.y))
.attr("fill", d => sel_field === "" ? z(d[sel_col]) : 'grey')
.attr("opacity", d => sel_field === "" ? 0.5 : 0.3)
.attr("r", 1.5)
.append("title")
.text(d => `${d.title} (${d.field})\n# citations: ${d.citationCount}\nYear: ${d.year}\ntopic: ${d.topic}`);;


const gDotF = svg.append("g")
.attr("fill", "none")
.attr("class", "circles")
.attr("stroke-linecap", "round");

gDotF.append("style").text(`
.circles {
stroke: transparent;
stroke-width: 0.1px;
}
.circles circle:hover {
stroke: black;
}
`);
if (sel_field !== '') {
gDotF.selectAll("circle")
.data(field_data)
.join("circle")
.attr("cx", d => x(d.x))
.attr("cy", d => y(d.y))
.attr("fill", d => sel_field === "" ? 'black' : 'red')
.attr("opacity", d => sel_field === "" ? 0 : 0.4)
.attr("r", 1.5)
.append("title")
.text(d => `${d.title} (${d.field})\n# citations: ${d.citationCount}\nYear: ${d.year}\ntopic: ${d.topic}`);
}

const gx = svg.append("g");

const gy = svg.append("g");

svg.call(zoom).call(zoom.transform, d3.zoomIdentity);

function zoomed({transform}) {
const zx = transform.rescaleX(x).interpolate(d3.interpolateRound);
const zy = transform.rescaleY(y).interpolate(d3.interpolateRound);
gDot.attr("transform", transform).attr("stroke-width", 2 / transform.k);
gDotF.attr("transform", transform).attr("stroke-width", 2 / transform.k);
gx.call(xAxis, zx);
gy.call(yAxis, zy);
gGrid.call(grid, zx, zy);
}

const tooltip = d3
.select("body")
.append("div")
.style("position", "absolute")
.style("visibility", "hidden")
.style("opacity", 0.9)
.style("background", "white");
// sel_field === '' ? gDot.call(Tooltips, tooltip) : gDotF.call(Tooltips, tooltip)
return Object.assign(svg.node(), {
reset() {
svg.transition()
.duration(750)
.call(zoom.transform, d3.zoomIdentity);
}
});
}
Insert cell
title_search_subset
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
subset_db = {
if (title_search_subset == undefined) {
return DuckDBClient.of({
simple: [{x: '', y: '', topic: '', field: '', title: '', year: '', citationCount: ''}]
})
} else {
return DuckDBClient.of({
simple: await db.query(`SELECT * FROM umap WHERE ( contains(lower(title), lower('${title_search}')))`)
})
}
}
Insert cell
function getTitleCase(str) {
return str.split('-').map(d => d.charAt(0).toUpperCase() + d.slice(1).toLowerCase()).join('-')
}
Insert cell
import {debounce} from "@mbostock/debouncing-input"
Insert cell
Insert cell
// Tooltips = (g, tooltip) =>
// g
// .on("mouseover", (event, d) => {
// d3.select(event.target)
// .style("stroke-width", "2px");
// tooltip.style("visibility", "visible");
// tooltip.html(d => `Top types: ${d.title}`);

// })
// .on("mousemove", (event, d) => {
// tooltip
// .style("top", event.clientY - 10 + "px")
// .style("left", event.clientX + 10 + "px");
// })
// .on("mouseout", (event, d) => {
// d3.select(event.target)
// .style("stroke-width", 0.3);
// tooltip.style("visibility", "hidden");
// })
Insert cell
reset, chart.reset()
Insert cell
umap_embedding2
Insert cell
grid = (g, x, y) => g
.attr("stroke", "currentColor")
.attr("stroke-opacity", 0.1)
.call(g => g
.selectAll(".x")
.data(x.ticks(12))
.join(
enter => enter.append("line").attr("class", "x").attr("y2", height),
update => update,
exit => exit.remove()
)
.attr("x1", d => 0.5 + x(d))
.attr("x2", d => 0.5 + x(d)))
.call(g => g
.selectAll(".y")
.data(y.ticks(12 * k))
.join(
enter => enter.append("line").attr("class", "y").attr("x2", width),
update => update,
exit => exit.remove()
)
.attr("y1", d => 0.5 + y(d))
.attr("y2", d => 0.5 + y(d)));
Insert cell
k = height / width
Insert cell
height = 600
Insert cell
lookup = {
const unique_field = _.uniqBy(umap_embedding2, d => d.field).map(d => d.field)
const out = {}
for (let i=0; i < unique_field.length; i++) {
out[unique_field[i]] = i
}
return out
}
Insert cell
db2 = DuckDBClient.of({
data: FileAttachment("umap_embedding@2.parquet")
})
Insert cell
sel_field_dat = {return {'field': sel_field}}
Insert cell
umap_embedding2 = db2.sql`
SELECT *
FROM data
USING SAMPLE 10000
`
Insert cell
field_data = db2.sql`
SELECT *
FROM data
WHERE field = ${sel_field}
`
Insert cell
extent_x = d3.extent(umap_embedding2, d => d.x)
Insert cell
extent_y = d3.extent(umap_embedding2, d => d.y)
Insert cell
classifyCompProj = FileAttachment("classify-comp-proj.csv").csv()
Insert cell
paperIds = classifyCompProj.map(d => d.Notes.split(";")[0].split("paper_id.")[1])
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