Unlisted
Edited
Feb 15, 2024
1 fork
1 star
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
similarityMeasures = [
["Ink Ratio", "pixelRatio"],
["Ratio of Mutually Exclusive Pixels to Common Pixels", "similarityExclusive"],
["Maximum of Pixel Difference", "similarityMaxDiff"],
["Ratio of max. Pixel Difference to Common Pixels", "similarityMaxDiffToCommon"],
["Composite (Mutually Exclusive × Maximum Difference)", "similarityComposite"],
["Maximum of Eroded Difference", "similarityMaxErodedDiff"],
["Ratio of max. Eroded Difference to Common Pixels", "similarityMaxErodedDiffToCommon"],
]
Insert cell
datasets = [
{
name: "Maki (subset)",
infoURL: "https://labs.mapbox.com/maki-icons/",
similarityData: parseData(await FileAttachment("results-maki-subset_20.csv").text()),
iconURL: id => "https://cartolab.at/map-icons/maki/" + id + ".svg"
},
{
name: "Maki",
infoURL: "https://labs.mapbox.com/maki-icons/",
similarityData: parseData(await FileAttachment("results-maki_20_3.csv").text()),
iconURL: id => "https://cartolab.at/map-icons/maki/" + id + ".svg"
},
{
name: "National Park Service",
infoURL: "https://www.nps.gov/maps/tools/symbol-library/index.html",
similarityData: parseData(await FileAttachment("results-nps_20.csv").text()),
iconURL: id => "https://cartolab.at/map-icons/nps/" + id + ".svg"
},
{
name: "OpenStreetMap",
infoURL: "https://wiki.openstreetmap.org/wiki/SymbolsTab",
similarityData: parseData(await FileAttachment("results-osm_20.csv").text()),
iconURL: id => "https://cartolab.at/map-icons/osm/" + id + ".svg"
},

]
Insert cell
function parseData(raw) {
//let raw = await FileAttachment("results-maki_20.csv").text();
raw = raw.split("\n");
let resolution = +raw.splice(0,1);
raw = raw.map(s => s.split(","));
let similars = {};
let connections = [];

let i = 2;
while (!isNaN(parseFloat(raw[0][i]))) {
i++;
}

let numParams = i-1;

console.log(numParams);

raw.forEach(a => {
let icon = a[0];

if (!similars[icon]) similars[icon] = [];

for (let i=1; i<a.length-4; i+=numParams) {
let r = {
icon: a[i],
icon2: icon,
exclusive: +a[i+1],
common: +a[i+2],
pixelRatio: +a[i+3],
maxDiff: +a[i+4],
};

r.similarityExclusive = r.common / (r.common + r.exclusive);
r.similarityMaxDiff = 1 - r.maxDiff / (resolution ** 2);
r.similarityMaxDiffToCommon = r.common / (r.common + r.maxDiff);
r.similarityComposite = r.similarityExclusive * r.similarityMaxDiff;
if (numParams > 5) {
r.erodedMaxDiff = +a[i+5];
r.similarityMaxErodedDiff = 1 - r.erodedMaxDiff / (resolution ** 2);
r.similarityMaxErodedDiffToCommon = r.common / (r.common + r.erodedMaxDiff);
//r.similarity = r.similarityMaxErodedDiff;
}
else {
//r.similarity = r.similarityComposite;
}
r.exclusiveArea = r.exclusive / (resolution ** 2);
similars[icon].push(r);
connections.push(r);

// make copy for "other" icon
let r2 = Object.assign({},r,{icon: icon});
if (!similars[r.icon]) similars[r.icon] = [];
similars[r.icon].push(r2);
}
});

function rank(attributeName) {
let simName = "similarity"+attributeName;
let rankName = "rank"+attributeName;
connections.sort((a,b) => b[simName] - a[simName]);
connections.forEach((c, idx) => c[rankName] = idx+1);
}

rank("Exclusive");
rank("MaxDiff");
rank("MaxDiffToCommon");
rank("Composite");
rank("MaxErodedDiff");
rank("MaxErodedDiffToCommon");

return {
resolution: resolution,
similars: similars,
connections: connections
}

}
Insert cell
function linearRegression(data, options){
options = Object.assign({
x: (d,i) => d[i].x,
y: (d,i) => d[i].y,
length: d => d.length
}, options);

function accessor(str) { return (d,i) => d[i][str] }
if (typeof options.x == "string") options.x = accessor(options.x);
if (typeof options.y == "string") options.y = accessor(options.y);
const n = options.length(data);
let sx = 0;
let sy = 0;
let sxy = 0;
let sxx = 0;
let syy = 0;
for (let i = 0; i < n; i++) {
let x = options.x(data,i), y = options.y(data,i);
sx += x;
sy += y;
sxy += x * y;
sxx += x * x;
syy += y * y;
}
const mx = sx / n;
const my = sy / n;
const yy = n * syy - sy * sy;
const xx = n * sxx - sx * sx;
const xy = n * sxy - sx * sy;
const slope = xy / xx;
const intercept = my - slope * mx;
const r = xy / Math.sqrt(xx * yy);
const r2 = Math.pow(r,2);
let sst = 0;
for (let i = 0; i < n; i++) {
sst += Math.pow((options.y(data,i) - my), 2);
}
const sse = sst - r2 * sst;
const see = Math.sqrt(sse / (n - 2));
const ssr = sst - sse;
return {slope, intercept, r, r2, sse, ssr, sst, sy, sx, see};
}
Insert cell
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