UNPKG

taxonium-component

Version:

React component for exploring large phylogenetic trees in the browser

189 lines (188 loc) 5.9 kB
import { A as b } from "./AbortablePromiseCache-CcuMrnn7.js"; import "./unzip-ASAuJ12U.js"; import { aX as d, a4 as h, u as S, R as F } from "./JBrowsePanel-uJIA-L6s.js"; import { B as I } from "./index-BnQfM3Nw.js"; import { Q as L } from "./QuickLRU-DcNaxluI.js"; import { r as k } from "./rxjs-BnZkaVAs.js"; function x(r, e) { return r.offset + r.lineBytes * Math.floor(e / r.lineLength) + e % r.lineLength; } async function A(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 E { 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 = A(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 = x(e, s), o = x(e, a) - i; return new TextDecoder("utf8").decode(await this.fasta.read(o, i, n)).replace(/\s+/g, ""); } } class O extends I.BaseSequenceAdapter { constructor() { super(...arguments), this.seqCache = new b({ cache: new L({ 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 E({ 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 k.ObservableCreate(async (f) => { await S.updateStatus2("Downloading sequence", t, n, async () => { const { fasta: l } = await this.setup(), q = await l.getSequenceSize(a), p = Math.min(q || 0, o), g = [], u = 128e3, m = i - i % u, _ = o + (u - o % u); for (let c = m; c < _; c += u) { const w = { refName: a, start: c, end: c + u }; F.checkStopToken(n), g.push(await this.seqCache.get(JSON.stringify(w), { ...w, fasta: l })); } const y = g.filter((c) => !!c).join("").slice(i - m).slice(0, o - i); y && f.next(new S.SimpleFeature({ id: `${a}-${i}-${p}`, data: { refName: a, start: i, end: p, seq: y } })); }), f.complete(); }); } } const P = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({ __proto__: null, default: O }, Symbol.toStringTag, { value: "Module" })); export { E as I, O as a, P as b }; //# sourceMappingURL=IndexedFastaAdapter-3PsrnaWp.js.map