UNPKG

taxonium-component

Version:

React component for exploring large phylogenetic trees in the browser

407 lines (405 loc) 12.5 kB
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