Published
Edited
Apr 29, 2020
2 forks
Importers
3 stars
Insert cell
md`# UpSet.js`
Insert cell
md`This is an interactive implementation of the core of the [UpsetR R package](https://github.com/hms-dbmi/UpSetR) using [UpSet.js](https://upset.js.org)`
Insert cell
UpSetJS = require('@upsetjs/bundle')
Insert cell
extractSets = UpSetJS.extractSets
Insert cell
generateCombinations = UpSetJS.generateCombinations
Insert cell
generateIntersections = (sets, options = {}) =>
generateCombinations(sets, { type: 'intersection', ...options })
Insert cell
generateUnions = (sets, options = {}) => generateCombinations(sets, {type: 'union', ...options})
Insert cell
asSets = UpSetJS.asSets
Insert cell
function UpSetJSElement(sets, combinations = undefined, extras = {}) {
const props = {
sets,
height: 500,
width,
selection: null,
...extras
};
if (combinations) {
props.combinations = combinations;
}
const root = html`<div></div`;

const render = () => {
UpSetJS.renderUpSet(root, props);
};
const handler = set => {
props.selection = set;
render();
root.dispatchEvent(new CustomEvent('input'));
};
if (!extras.mode || extras.mode === 'hover') {
props.onHover = handler;
} else {
props.onClick = handler;
}

render();

// fulfill value contract
Object.defineProperty(root, 'value', {
get: () => props.selection,
set: value => {
props.selection = value || null;
render();
root.dispatchEvent(new CustomEvent('input'));
}
});

return root;
}
Insert cell
baseUrlV1 = 'https://vcg.github.io/upset/'
Insert cell
baseUrlV2 = 'https://vdl.sci.utah.edu/upset2'
Insert cell
baseServerUrl = 'https://us-central1-upset2-eaf80.cloudfunctions.net/api/datasets'
Insert cell
async function listUpSetDatasets(file=`${baseUrlV1}/datasets.json`, baseUrl=baseUrlV1) {
const dss = await fetch(file).then((r) => r.json());
const datasets = await Promise.all(dss.map((d) => fetch(`${baseUrl}/${d}`).then((r) => r.json())));
datasets.forEach((ds) => (ds.file = ds.file.startsWith('https') ? ds.file : `${baseUrl}/${ds.file}`));
return datasets;
}
Insert cell
async function listUpSet2Datasets() {
const base = await listUpSetDatasets(`${baseUrlV2}/data/datasets.json`, baseUrlV2);
const server = (await fetch(baseServerUrl).then((r) => r.json())).datasets.filter(d => d.sets.length > 0);
server.forEach((d) => d.file = `${d.file}?alt=media`);
return base.concat(server);
}
Insert cell
function datasetChooser(datasets) {
return html`<select>${datasets.map((v, i) => `<option value="${i}">${v.name} (${v.sets[0].end - v.sets[0].start} sets)</option>`).join()}</select>`;
}
Insert cell
d3 = require('d3')
Insert cell
async function elementsFromDataset(ds) {
const raw = await fetch(ds.file).then(r => r.text());
const csv = d3.dsvFormat(ds.separator).parseRows(raw);
const set = { start: ds.sets[0].start, end: ds.sets[0].end };
const idColumnIndex = ds.meta.find(d => d.type === 'id')
? ds.meta.find(d => d.type === 'id').index
: 0;

const [header, ...data] = csv;

const setNames = header.slice(set.start, set.end);
return data.map(row => {
// find the indices of the sets this element is part of
const sets = row
.slice(set.start, set.end)
.map((v, i) => [v, setNames[i]])
.filter(([v, _]) => v === "1")
.map(([_, s]) => s);
return {
name: row[idColumnIndex],
sets
};
});
}
Insert cell
async function setsFromDataset(ds) {
const elements = await elementsFromDataset(ds);
return extractSets(elements);
}
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