UNPKG

taxonium-component

Version:

React component for exploring large phylogenetic trees in the browser

197 lines (196 loc) 6.05 kB
import { A as L } from "./AbortablePromiseCache-CcuMrnn7.js"; import "./unzip-NIBF0hze.js"; import { L as d } from "./browser-BpRiKmO-.js"; import { B as F } from "./index-CpJXUZUB.js"; import { a1 as h, u as x, O as I } from "./JBrowsePanel-BNE3gNW1.js"; import { Q as k } from "./QuickLRU-BaqKky94.js"; import { r as A } from "./rxjs-L4bS73F7.js"; function q(r, e) { return r.offset + r.lineBytes * Math.floor(e / r.lineLength) + e % r.lineLength; } async function E(r, e = {}) { const s = new TextDecoder("utf8"); return Object.fromEntries(s.decode(await r.readFile(e)).split(/\r?\n/).map((t) => t.trim()).filter((t) => !!t).map((t) => t.split(" ")).map((t) => { var n; if ((n = t[0]) != null && n.startsWith(">")) throw new Error("found > in sequence name, might have supplied FASTA file for the FASTA index"); return [ t[0], { name: t[0], length: +t[1], start: 0, end: +t[1], offset: +t[2], lineLength: +t[3], lineBytes: +t[4] } ]; })); } class O { constructor({ fasta: e, fai: s, path: t, faiPath: n }) { if (e) this.fasta = e; else if (t) this.fasta = new d(t); else throw new Error("Need to pass filehandle for fasta or path to localfile"); if (s) this.fai = s; else if (n) this.fai = new d(n); else if (t) this.fai = new d(`${t}.fai`); else throw new Error("Need to pass filehandle for or path to localfile"); } async _getIndexes(e) { return this.indexes || (this.indexes = E(this.fai, e).catch((s) => { throw this.indexes = void 0, s; })), this.indexes; } /** * @returns array of string sequence names that are present in the index, in * which the array index indicates the sequence ID, and the value is the * sequence name */ async getSequenceNames(e) { return Object.keys(await this._getIndexes(e)); } /** * @returns array of string sequence names that are present in the index, in * which the array index indicates the sequence ID, and the value is the * sequence name */ async getSequenceSizes(e) { const s = {}, t = await this._getIndexes(e); for (const n of Object.values(t)) s[n.name] = n.length; return s; } /** * @returns array of string sequence names that are present in the index, in * which the array index indicates the sequence ID, and the value is the * sequence name */ async getSequenceSize(e, s) { var n; return (n = (await this._getIndexes(s))[e]) == null ? void 0 : n.length; } /** * @param name * * @returns true if the file contains the given reference sequence name */ async hasReferenceSequence(e, s) { return !!(await this._getIndexes(s))[e]; } /** * @param seqName * @param min * @param max */ async getResiduesByName(e, s, t, n) { const a = (await this._getIndexes(n))[e]; return a ? this._fetchFromIndexEntry(a, s, t, n) : void 0; } //alias for getResiduesByName async getSequence(e, s, t, n) { return this.getResiduesByName(e, s, t, n); } async _fetchFromIndexEntry(e, s = 0, t, n) { let a = t; if (s < 0) throw new TypeError("regionStart cannot be less than 0"); if ((a === void 0 || a > e.length) && (a = e.length), s >= a) return ""; const i = q(e, s), o = q(e, a) - i; return new TextDecoder("utf8").decode(await this.fasta.read(o, i, n)).replace(/\s+/g, ""); } } class j extends F.BaseSequenceAdapter { constructor() { super(...arguments), this.seqCache = new L({ cache: new k({ maxSize: 200 }), fill: async (e) => { const { refName: s, start: t, end: n, fasta: a } = e; return a.getSequence(s, t, n); } }); } async getRefNames(e) { const { fasta: s } = await this.setup(); return s.getSequenceNames(); } async getRegions(e) { const { fasta: s } = await this.setup(), t = await s.getSequenceSizes(); return Object.keys(t).map((n) => ({ refName: n, start: 0, end: t[n] })); } async setupPre() { const e = this.getConf("fastaLocation"), s = this.getConf("faiLocation"); return { fasta: new O({ fasta: h.openLocation(e, this.pluginManager), fai: h.openLocation(s, this.pluginManager) }) }; } async getHeader() { const e = this.getConf("metadataLocation"); return e.uri === "" || e.uri === "/path/to/fa.metadata.yaml" ? null : h.openLocation(e, this.pluginManager).readFile("utf8"); } async setup() { return this.setupP || (this.setupP = this.setupPre().catch((e) => { throw this.setupP = void 0, e; })), this.setupP; } getFeatures(e, s) { const { statusCallback: t = () => { }, stopToken: n } = s || {}, { refName: a, start: i, end: o } = e; return A.ObservableCreate(async (u) => { await x.updateStatus2("Downloading sequence", t, n, async () => { const { fasta: l } = await this.setup(), b = await l.getSequenceSize(a), p = Math.min(b || 0, o), g = [], f = 128e3, m = i - i % f, _ = o + (f - o % f); for (let c = m; c < _; c += f) { const w = { refName: a, start: c, end: c + f }; I.checkStopToken(n); const S = await this.seqCache.get(JSON.stringify(w), { ...w, fasta: l }); if (!S) break; g.push(S); } const y = g.filter((c) => !!c).join("").slice(i - m).slice(0, o - i); y && u.next(new x.SimpleFeature({ id: `${a}-${i}-${p}`, data: { refName: a, start: i, end: p, seq: y } })); }), u.complete(); }); } } const R = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({ __proto__: null, default: j }, Symbol.toStringTag, { value: "Module" })); export { O as I, j as a, R as b }; //# sourceMappingURL=IndexedFastaAdapter-CqEccOzJ.js.map