taxonium-component
Version:
React component for exploring large phylogenetic trees in the browser
407 lines (405 loc) • 12.5 kB
JavaScript
import { bZ as I, a4 as A, u as y, t as O, s as g } from "./JBrowsePanel-uJIA-L6s.js";
class L {
constructor(e = [], c) {
this.data = {};
const { checkIndent: o = !0, skipValidation: d = !1 } = c ?? {}, s = typeof e == "string" ? e.trimEnd().split(/\r?\n/) : e;
let i, t;
for (const l of s) {
if (l === "")
throw new Error("Invalid stanza, contained blank lines");
if (l.trim().startsWith("#"))
continue;
if (l.trimEnd().endsWith("\\")) {
const f = l.trimEnd().slice(0, -1);
t ? t += f.trimStart() : t = f;
continue;
}
let m = l;
if (t && (m = t + m.trimStart(), t = void 0), i ?? o) {
const f = /^([ \t]+)/.exec(m);
if (i === void 0)
f ? [, i] = f : i = "";
else if (i === "" && f !== null || i && f && i !== f[1])
throw new Error("Inconsistent indentation of stanza");
} else
i = "";
const n = m.trim(), h = n.indexOf(" ");
if (h === -1) {
if (!this.nameKey)
throw new Error("First line in a stanza must have both a key and a value");
if (this.data[n])
continue;
this.data[n] = "";
continue;
}
const r = n.slice(0, h), u = n.slice(h + 1);
if (this.data[r] && u !== this.data[r])
throw new Error(`Got duplicate key with a different value in stanza: "${r}" key has both ${this.data[r]} and ${u}`);
this.nameKey || (this.nameKey = r, this.name = n.slice(h + 1)), this.data[r] = u;
}
d || this.validate();
}
validate() {
}
}
class C {
constructor(e = [], c) {
this.data = {};
const { checkIndent: o = !0, skipValidation: d = !1 } = c ?? {}, s = typeof e == "string" ? e.trimEnd().split(/(?:[\t ]*\r?\n){2,}/) : e;
for (const i of s) {
if (i === "")
throw new Error("Invalid stanza, was empty");
if (i.startsWith("include") || i.trim().startsWith("#") && i.trimEnd().split(/\r?\n/).map((m) => m.trim()).every((m) => m.startsWith("#")))
continue;
const t = new L(i, { checkIndent: o });
if (!this.nameKey)
this.nameKey = t.nameKey;
else if (t.nameKey !== this.nameKey)
throw new Error(`The first line in each stanza must have the same key. Saw both ${this.nameKey} and ${t.nameKey}`);
if (!t.name)
throw new Error(`No stanza name: ${t.name}`);
if (this.data[t.name])
throw new Error(`Got duplicate stanza name: ${t.name}`);
this.data[t.name] = t;
}
d || this.validate();
}
validate() {
}
}
function T(a, e, c = "") {
const o = [];
for (const d of e)
a.data[d] || o.push(d);
if (o.length > 0)
throw new Error(`${c} is missing required entr${o.length === 1 ? "y" : "ies"}: ${o.join(", ")}`);
}
class P extends C {
constructor(e, c) {
super(e, { ...c, checkIndent: !1 });
}
validate() {
var e;
if (this.nameKey !== "track")
throw new Error(`trackDb has "${this.nameKey}" instead of "track" as the first line in each track`);
for (const [c, o] of Object.entries(this.data)) {
const d = Object.keys(o.data);
T(o, ["track", "shortLabel"], `Track ${c}`);
const s = /* @__PURE__ */ new Set([
"superTrack",
"compositeTrack",
"container",
"view"
]);
if (!d.some((l) => s.has(l))) {
if (!d.includes("bigDataUrl"))
throw new Error(`Track ${c} is missing required key "bigDataUrl"`);
if (!d.includes("type") && !Object.keys(this.settings(c)).includes("type"))
throw new Error(`Neither track ${c} nor any of its parent tracks have the required key "type"`);
}
let i = c;
do
i = (e = this.data[i]) == null ? void 0 : e.parent, i && ([i] = i.split(" "));
while (i);
const t = this.data[c];
t && (this.data[c] = t);
}
}
/**
* Gets all track entries including those of parent tracks, with closer
* entries overriding more distant ones
* @param {string} trackName The name of a track
* @throws {Error} Throws if track name does not exist in the trackDb
*/
settings(e) {
var s;
if (!this.data[e])
throw new Error(`Track ${e} does not exist`);
const c = [e];
let o = e;
do
o = (s = this.data[o]) == null ? void 0 : s.parent, o && c.push(o);
while (o);
const d = {};
c.reverse();
for (const i of c) {
const t = this.data[i];
if (t)
for (const [l, m] of Object.entries(t))
d[l] = m;
}
return d;
}
}
class G extends C {
validate(e = ["genome", "trackDb"]) {
if (this.nameKey !== "genome")
throw new Error('Genomes file must begin with a line like "genome <genome_name>"');
for (const [c, o] of Object.entries(this.data))
T(o, e, `genome ${c}`);
}
}
class W extends L {
validate() {
T(this, ["hub", "shortLabel", "longLabel", "genomesFile", "email"], "Hub file");
}
}
class H {
constructor(e) {
const [c, o, ...d] = e.trimEnd().split(/(?:[\t ]*\r?\n){2,}/);
this.hubData = new L(c), this.validateHub(), this.genome = new L(o), this.validateGenomeSection(), this.tracks = new P(d.join(`
`), {
skipValidation: !1
});
}
validateHub() {
if (this.hubData.nameKey !== "hub")
throw new Error('Hub file must begin with a line like "hub <hub_name>"');
T(this.hubData, [
"hub",
"shortLabel",
"longLabel",
"email",
"descriptionUrl"
]);
}
validateGenomeSection() {
if (this.genome.nameKey !== "genome")
throw new Error('Genomes file must begin with a line like "genome <genome_name>"');
}
}
var R = I();
async function V(a) {
const e = await A.openLocation(a).readFile("utf8");
return new G(e);
}
async function _(a) {
const e = await A.openLocation(a).readFile("utf8");
return new P(e);
}
function U(a, e) {
return {
uri: new URL(a, new URL(e.uri, e.baseUri)).href,
locationType: "UriLocation"
};
}
function F(a, e, c) {
return U(a || e, c);
}
function k(a, e) {
return a ? {
uri: a,
locationType: "LocalPath"
} : {
uri: e,
locationType: "UriLocation"
};
}
function b(a, e) {
return new URL(a, e).href;
}
function N({ trackDb: a, trackDbLoc: e, assemblyName: c, sequenceAdapter: o, baseUrl: d }) {
const s = /* @__PURE__ */ new Set([
"superTrack",
"compositeTrack",
"container",
"view"
]);
return Object.entries(a.data).map(([i, t]) => {
var l;
const { data: m } = t;
if (!Object.keys(m).some((n) => s.has(n))) {
const n = [];
let h = i;
do
h = ((l = a.data[h]) === null || l === void 0 ? void 0 : l.data.parent) || "", h && (h = h.split(" ")[0], n.push(a.data[h]));
while (h);
return n.reverse(), {
metadata: {
...t.data,
...t.data.html ? {
html: `<a href="${b(t.data.html, d)}">${t.data.html}</a>`
} : {}
},
category: [
t.data.group,
...n.map((r) => r == null ? void 0 : r.data.group).filter((r) => !!r)
].filter((r) => !!r),
...M({
track: t,
trackDbLoc: e,
trackDb: a,
sequenceAdapter: o
})
};
}
}).filter(y.notEmpty).map((i) => ({
...i,
trackId: `ucsc-trackhub-${y.objectHash(i)}`,
assemblyNames: [c]
}));
}
function M({ track: a, trackDbLoc: e, trackDb: c, sequenceAdapter: o }) {
var d;
const { data: s } = a, i = s.parent || "", t = s.bigDataUrl || "", l = s.bigDataIndex || "", m = s.type || ((d = c.data[i]) === null || d === void 0 ? void 0 : d.data.type) || "", n = (s.shortLabel || "") + (t.includes("xeno") ? " (xeno)" : ""), h = y.isUriLocation(e);
let r = m.split(" ")[0] || "";
r === "bam" && t.toLowerCase().endsWith("cram") && (r = "cram");
const u = h ? U(t, e) : k(t);
return r === "bam" ? {
type: "AlignmentsTrack",
name: n,
description: s.longLabel,
adapter: {
type: "BamAdapter",
bamLocation: u,
index: {
location: h ? F(l, `${t}.bai`, e) : k(l, `${t}.bai`)
}
}
} : r === "cram" ? {
type: "AlignmentsTrack",
name: n,
description: s.longLabel,
adapter: {
type: "CramAdapter",
cramLocation: u,
craiLocation: h ? F(l, `${t}.crai`, e) : k(l, `${t}.crai`),
sequenceAdapter: o
}
} : r === "bigWig" ? {
type: "QuantitativeTrack",
name: n,
description: s.longLabel,
adapter: {
type: "BigWigAdapter",
bigWigLocation: u
}
} : r.startsWith("big") ? {
type: "FeatureTrack",
name: n,
description: s.longLabel,
adapter: {
type: "BigBedAdapter",
bigBedLocation: u
}
} : r === "vcfTabix" ? {
type: "VariantTrack",
name: n,
description: s.longLabel,
adapter: {
type: "VcfTabixAdapter",
vcfGzLocation: u,
index: {
location: h ? F(l, `${t}.tbi`, e) : k(l, `${t}.tbi`)
}
}
} : r === "hic" ? {
type: "HicTrack",
name: n,
description: s.longLabel,
adapter: {
type: "HicAdapter",
hicLocation: u
}
} : O.generateUnknownTrackConf(n, r);
}
async function Z(a) {
var e;
const { pluginManager: c } = y.getEnv(a), o = y.getSession(a), d = [];
try {
const s = g.getConf(a, "hubTxtLocation"), i = await A.openLocation(s).readFile("utf8"), t = b(s.uri, s.baseUri), { assemblyManager: l } = o;
if (i.includes("useOneFile on")) {
const m = new H(i), { genome: n, tracks: h } = m, r = n.name, u = n.data.description;
l.get(r) || o.addSessionAssembly({
name: r,
displayName: u,
sequence: {
type: "ReferenceSequenceTrack",
metadata: {
...n.data,
...n.data.htmlPath ? {
htmlPath: `<a href="${b(n.data.htmlPath, t)}">${n.data.htmlPath}</a>`
} : {}
},
trackId: `${r}-${R.nanoid()}`,
adapter: {
type: "TwoBitAdapter",
twoBitLocation: {
uri: b(n.data.twoBitPath, t)
},
chromSizesLocation: {
uri: b(n.data.chromSizes, t)
}
}
},
...n.data.chromAliasBb ? {
refNameAliases: {
adapter: {
type: "BigBedAdapter",
uri: b(n.data.chromAliasBb, t)
}
}
} : {}
});
const w = l.get(r), v = g.getConf(w, ["sequence", "adapter"]), $ = N({
trackDb: h,
trackDbLoc: s,
assemblyName: r,
sequenceAdapter: v,
baseUrl: t
});
a.addTrackConfs($), c.evaluateExtensionPoint("LaunchView-LinearGenomeView", {
session: o,
assembly: r,
tracklist: !0,
loc: n.data.defaultPos
});
} else {
const n = new W(i).data.genomesFile;
if (!n)
throw new Error("genomesFile not found on hub");
const h = b(s.uri, s.baseUri), r = h ? {
uri: b(n, h),
locationType: "UriLocation"
} : {
localPath: n,
locationType: "LocalPathLocation"
}, u = await V(r), f = {};
for (const [p, E] of Object.entries(u.data)) {
const K = g.getConf(a, "assemblyNames");
if (K.length > 0 && !K.includes(p))
continue;
const S = l.get(p);
if (!S) {
d.push(p);
continue;
}
const x = E.data.trackDb;
if (!x)
throw new Error("genomesFile not found on hub");
const B = new URL(n, h), z = h ? {
uri: new URL(x, B).href,
locationType: "UriLocation"
} : {
localPath: x,
locationType: "LocalPathLocation"
}, D = await _(z), q = g.getConf(S, ["sequence", "adapter"]), j = N({
trackDb: D,
trackDbLoc: z,
assemblyName: p,
sequenceAdapter: q,
baseUrl: h
});
a.addTrackConfs(j), f[p] = j.length;
}
const w = Object.entries(f), v = w.length ? `Loaded data from these assemblies: ${w.map(([p, E]) => `${p} (${E} tracks)`).join(", ")}` : "", $ = d.length ? `Skipped data from these assemblies: ${d.join(", ")}` : "";
o.notify([v, $].filter((p) => !!p).join(". "), "success");
}
} catch (s) {
console.error(s), o.notifyError(`${g.getConf(a, "name")}: "${s}"`, s), (e = o.breakConnection) === null || e === void 0 || e.call(o, a.configuration);
}
}
export {
Z as doConnect
};
//# sourceMappingURL=doConnect-BIGIRTf-.js.map