Public
Edited
Oct 17, 2024
Paused
2 forks
Importers
1 star
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
xAxis = (g, scale) =>
g
.attr("transform", `translate(0, ${visHeight*canvas_mult_size})`)
.call(d3.axisBottom(scale))
.call((g) => g.select(".domain").remove()) // remove baseline
// add label
.selectAll('text')
.attr('dy', 10)
.attr('dx', 13)
.attr('transform', 'scale(-1,1) rotate(45)')
.attr('font-size', 10)
Insert cell
Insert cell
Insert cell
yAxis = (g, scale) =>
// add axis
g
.call(d3.axisRight(scale))
.call((g) => g.select(".domain").remove())
.attr("transform", `translate(${visHeight*canvas_mult_size}, 0) scale(-1, 1)`)
.selectAll('text')
.attr('dx', -28) // fiddling with ticks for Left system
.attr('dy', 15) // fiddling with ticks for Left system
.attr('transform', 'rotate(45)')
.attr('font-size', 10)
Insert cell
Insert cell
yGrid = (g, scale) =>
g
.append("g")
.call(d3.axisRight(scale).ticks(ncells/2).tickFormat(""))
.call((g) => g.select(".domain").remove())
.call((g) =>
g
.selectAll(".tick line")
.attr("stroke", "#d3d3d3")
.style("stroke-dasharray", ("3, 3"))
.attr("x1", visWidth+7)
.attr("x2", 10)
)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
canvas_mult_size = 1.02
Insert cell
function rank_turbulence(x, y, alpha) {
if (alpha === Infinity) {
return x == y ? 0 : Math.max(x)
} else if (alpha == 0) {
// cheating a little bit
return (1+1) / 1 * Math.abs(x**1 - y**1)**(1. / (1+1))
} else {
return (alpha+1) / alpha * Math.abs(x**alpha - y**alpha)**(1. / (alpha+1))
}
}
Insert cell
contours = function contour(isLeft) {
// see https://observablehq.com/@d3/contours
const q = 4; // The level of detail, e.g., sample every 4 pixels in x and y.
const x0 = -1, x1 = 510 + q - 2;
const y0 = -1, y1 = visHeight + q - 2;
const n = Math.ceil((x1 - x0) / q);
const m = Math.ceil((y1 - y0) / q);
const grid_right = new Array(n * m);
const grid_left = new Array(n * m);

// evaluate function across grid
for (let j = 0; j < m; ++j) {
for (let i = 0; i < n; ++i) {
if (i - j > 0) {
grid_left[j * n + i] = rank_turbulence(i, j, alpha);
} else {
grid_right[j * n + i] = rank_turbulence(i, j, alpha);
}
}
}
grid_left.x = grid_right.x = -q;
grid_left.y = grid_right.y = -q;
grid_left.k = grid_right.k = q;
grid_left.n = grid_right.n = n;
grid_left.m = grid_right.m = m;
const grid = {'left': grid_left.reverse(), 'right':grid_right.reverse()};
let chosen_grid = grid[isLeft ? 'left' : 'right']
// Converts from grid coordinates (indexes) to screen coordinates (pixels).
const transform = ({type, value, coordinates, isLeft}) => {
return {type, value, coordinates: coordinates.map(rings => {
return rings.map(points => {
return points.map(([x, y]) => ([
chosen_grid.x + chosen_grid.k * x + 3,
chosen_grid.y + chosen_grid.k * y + 3
]));
});
})};
}
let contour = d3.contours().size([chosen_grid.n, chosen_grid.m]).thresholds(10)
return contour(chosen_grid).map(d => transform(d, isLeft ? true : false));
}
Insert cell
Insert cell
Insert cell
wordshift_dat = () => {
const out = []
for (let i=0; i < me[0]['types'].length; i++) {
const rank_diff = me[0]['ranks'][i]-me[1]['ranks'][i]
out.push({
'type': `${me[0]['types'][i]} (${me[0]['ranks'][i]} ⇋ ${me[1]['ranks'][i]})` ,
'rank_diff': rank_diff,
'metric': rank_diff < 0 ? -dat.deltas[i] : dat.deltas[i],
})
}
return out.slice().sort((a, b) => d3.descending(Math.abs(a.metric), Math.abs(b.metric)))
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
function ExempleData(x) {
switch (x) {
case 'Girl babynames': { return FileAttachment("elem_girls@2.json").json() }
case 'Boy babynames': { return FileAttachment("elem_boys.json").json(); }
case 'Twitter': { return FileAttachment("twitter_data@15.json").json(); }
case 'Species Abundance': { return FileAttachment("tree_species_counts@1.json").json(); }
}
}
Insert cell
// default dict example where key is filenames and values are dataframe
elem = {
if (uploaded_json_file !== "") { // if uploaded json file use that
return uploaded_json_file
} else if (ExempleData(sel_data) === false) { // if no default example are selected just use elem_boys
return FileAttachment("elem_boys.json").json()
} else {
return ExempleData(sel_data) // if one of the default examples is selected use that
}
}
Insert cell
elem_names = Object.keys(elem)
Insert cell
sel_sys1 = elem_names[(form[0][0]+clicks) % elem_names.length]
Insert cell
sel_sys2 = elem_names[(form[1][0]+clicks) % elem_names.length]
Insert cell
Insert cell
Insert cell
elems1 = form1[0] === undefined ? elem[sel_sys1] : uploaded_csv_file_1 // json vs csv file
Insert cell
elems2 = form1[1] === undefined ? elem[sel_sys2] : uploaded_csv_file_2
Insert cell
Insert cell
me_class = new mixedElems(elems1, elems2)
Insert cell
me = me_class.combElems()
Insert cell
rtd = rank_turbulence_divergence(me, alphas[alpha])
Insert cell
dat = diamond(me, rtd)
Insert cell
diamond_dat = dat.counts
Insert cell
diamond_dat_f = diamond_dat.filter(d => d.types !== "")
Insert cell
Insert cell
import { sum, diamond, mixedElems, rank_turbulence_divergence, rank_maxlog10, which, matlab_sort, zeros, rin, tiedrank, } from '@jstonge/allotax-helpers'
Insert cell
import { DivergingBarChartWordShift } from "@jstonge/bar-chart-diverging-wordshift"
Insert cell
import { DivergingBarChartBalance } from "@jstonge/bar-chart-diverging-balance"
Insert cell
import { myLegend } from "@jstonge/legend-diamond-plot"
Insert cell
import { button } from "@bartok32/diy-inputs"
Insert cell
plot_diamond()
Insert cell
plot_balance()
Insert cell
plot_legend()
Insert cell
plot_word_shift()
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