taxonium-component
Version:
React component for exploring large phylogenetic trees in the browser
260 lines (259 loc) • 9.37 kB
JavaScript
function m(c) {
return c.replaceAll(/%([0-9A-Fa-f]{2})/g, (e, r) => String.fromCharCode(parseInt(r, 16)));
}
function y(c) {
if (!c.length || c === ".")
return {};
const e = {};
return c.replace(/\r?\n$/, "").split(";").forEach((r) => {
var t;
const i = r.split("=", 2);
if (!(!((t = i[1]) === null || t === void 0) && t.length))
return;
i[0] = i[0].trim();
let n = e[i[0].trim()];
n || (n = [], e[i[0]] = n), n.push(...i[1].split(",").map((a) => a.trim()).map(m));
}), e;
}
function F(c) {
const e = c.split(" ").map((t) => t === "." || t === "" ? null : t);
return {
seq_id: e[0] && m(e[0]),
source: e[1] && m(e[1]),
type: e[2] && m(e[2]),
start: e[3] === null ? null : parseInt(e[3], 10),
end: e[4] === null ? null : parseInt(e[4], 10),
score: e[5] === null ? null : parseFloat(e[5]),
strand: e[6],
phase: e[7],
attributes: e[8] === null ? null : y(e[8])
};
}
function D(c) {
var e, r;
const t = /^\s*##\s*(\S+)\s*(.*)/.exec(c);
if (!t)
return null;
const [, i] = t;
let [, , n] = t;
const a = { directive: i };
if (n.length && (n = n.replace(/\r?\n$/, ""), a.value = n), i === "sequence-region") {
const s = n.split(/\s+/, 3);
return {
...a,
seq_id: s[0],
start: (e = s[1]) === null || e === void 0 ? void 0 : e.replaceAll(/\D/g, ""),
end: (r = s[2]) === null || r === void 0 ? void 0 : r.replaceAll(/\D/g, "")
};
} else if (i === "genome-build") {
const [s, o] = n.split(/\s+/, 2);
return {
...a,
source: s,
buildName: o
};
}
return a;
}
const C = {
Parent: "child_features",
Derives_from: "derived_features"
};
class A {
constructor(e) {
this.seqCallback = e, this.currentSequence = void 0;
}
addLine(e) {
const r = /^>\s*(\S+)\s*(.*)/.exec(e);
r ? (this._flush(), this.currentSequence = { id: r[1], sequence: "" }, r[2] && (this.currentSequence.description = r[2].trim())) : this.currentSequence && /\S/.test(e) && (this.currentSequence.sequence += e.replaceAll(/\s/g, ""));
}
_flush() {
this.currentSequence && this.seqCallback(this.currentSequence);
}
finish() {
this._flush();
}
}
class S {
constructor(e) {
this.fastaParser = void 0, this.eof = !1, this.lineNumber = 0, this._underConstructionTopLevel = [], this._underConstructionById = {}, this._completedReferences = {}, this._underConstructionOrphans = {};
const r = () => {
};
this.featureCallback = e.featureCallback || r, this.endCallback = e.endCallback || r, this.commentCallback = e.commentCallback || r, this.errorCallback = e.errorCallback || r, this.directiveCallback = e.directiveCallback || r, this.sequenceCallback = e.sequenceCallback || r, this.disableDerivesFromReferences = e.disableDerivesFromReferences || !1, this.bufferSize = e.bufferSize === void 0 ? 1e3 : e.bufferSize;
}
addLine(e) {
if (this.fastaParser) {
this.fastaParser.addLine(e);
return;
}
if (this.eof)
return;
if (this.lineNumber += 1, /^\s*[^#\s>]/.test(e)) {
this._bufferLine(e);
return;
}
const r = /^\s*(#+)(.*)/.exec(e);
if (r) {
const [, t] = r;
let [, , i] = r;
if (t.length === 3)
this._emitAllUnderConstructionFeatures();
else if (t.length === 2) {
const n = D(e);
n && (n.directive === "FASTA" ? (this._emitAllUnderConstructionFeatures(), this.eof = !0, this.fastaParser = new A(this.sequenceCallback)) : this._emitItem(n));
} else
i = i.replace(/\s*/, ""), this._emitItem({ comment: i });
} else if (!/^\s*$/.test(e)) if (/^\s*>/.test(e))
this._emitAllUnderConstructionFeatures(), this.eof = !0, this.fastaParser = new A(this.sequenceCallback), this.fastaParser.addLine(e);
else {
const t = e.replaceAll(/\r?\n?$/g, "");
throw new Error(`GFF3 parse error. Cannot parse '${t}'.`);
}
}
finish() {
this._emitAllUnderConstructionFeatures(), this.fastaParser && this.fastaParser.finish(), this.endCallback();
}
_emitItem(e) {
Array.isArray(e) ? this.featureCallback(e) : "directive" in e ? this.directiveCallback(e) : "comment" in e && this.commentCallback(e);
}
_enforceBufferSizeLimit(e = 0) {
const r = (t) => {
var i, n;
t && Array.isArray(t) && (!((n = (i = t[0].attributes) === null || i === void 0 ? void 0 : i.ID) === null || n === void 0) && n[0]) && (t[0].attributes.ID.forEach((s) => {
delete this._underConstructionById[s], delete this._completedReferences[s];
}), t.forEach((s) => {
s.child_features && s.child_features.forEach((o) => r(o)), s.derived_features && s.derived_features.forEach((o) => r(o));
}));
};
for (; this._underConstructionTopLevel.length + e > this.bufferSize; ) {
const t = this._underConstructionTopLevel.shift();
t && (this._emitItem(t), r(t));
}
}
/**
* return all under-construction features, called when we know
* there will be no additional data to attach to them
*/
_emitAllUnderConstructionFeatures() {
if (this._underConstructionTopLevel.forEach(this._emitItem.bind(this)), this._underConstructionTopLevel = [], this._underConstructionById = {}, this._completedReferences = {}, Array.from(Object.values(this._underConstructionOrphans)).length)
throw new Error(`some features reference other features that do not exist in the file (or in the same '###' scope). ${Object.keys(this._underConstructionOrphans).join(",")}`);
}
// do the right thing with a newly-parsed feature line
_bufferLine(e) {
var r, t, i;
const a = {
...F(e),
child_features: [],
derived_features: []
}, s = ((r = a.attributes) === null || r === void 0 ? void 0 : r.ID) || [], o = ((t = a.attributes) === null || t === void 0 ? void 0 : t.Parent) || [], h = this.disableDerivesFromReferences ? [] : ((i = a.attributes) === null || i === void 0 ? void 0 : i.Derives_from) || [];
if (!s.length && !o.length && !h.length) {
this._emitItem([a]);
return;
}
let l;
s.forEach((f) => {
const u = this._underConstructionById[f];
u ? (u[u.length - 1].type !== a.type && this._parseError(`multi-line feature "${f}" has inconsistent types: "${a.type}", "${u[u.length - 1].type}"`), u.push(a), l = u) : (l = [a], this._enforceBufferSizeLimit(1), !o.length && !h.length && this._underConstructionTopLevel.push(l), this._underConstructionById[f] = l, this._resolveReferencesTo(l, f));
}), this._resolveReferencesFrom(l || [a], { Parent: o, Derives_from: h }, s);
}
_resolveReferencesTo(e, r) {
const t = this._underConstructionOrphans[r];
t && (e.forEach((i) => {
i.child_features.push(...t.Parent);
}), e.forEach((i) => {
i.derived_features.push(...t.Derives_from);
}), delete this._underConstructionOrphans[r]);
}
_parseError(e) {
this.eof = !0, this.errorCallback(`${this.lineNumber}: ${e}`);
}
_resolveReferencesFrom(e, r, t) {
function i(n, a, s) {
let o = n[a];
o || (o = {}, n[a] = o);
const h = o[s] || !1;
return o[s] = !0, h;
}
r.Parent.forEach((n) => {
const a = this._underConstructionById[n];
if (a) {
const s = C.Parent;
t.filter((o) => i(this._completedReferences, o, `Parent,${n}`)).length || a.forEach((o) => {
o[s].push(e);
});
} else {
let s = this._underConstructionOrphans[n];
s || (s = {
Parent: [],
Derives_from: []
}, this._underConstructionOrphans[n] = s), s.Parent.push(e);
}
}), r.Derives_from.forEach((n) => {
const a = this._underConstructionById[n];
if (a) {
const s = C.Derives_from;
t.filter((o) => i(this._completedReferences, o, `Derives_from,${n}`)).length || a.forEach((o) => {
o[s].push(e);
});
} else {
let s = this._underConstructionOrphans[n];
s || (s = {
Parent: [],
Derives_from: []
}, this._underConstructionOrphans[n] = s), s.Derives_from.push(e);
}
});
}
}
function L(c) {
const e = [], r = new S({
featureCallback: (t) => e.push(t),
disableDerivesFromReferences: !0,
errorCallback: (t) => {
throw t;
}
});
for (const t of c.split(/\r?\n/))
r.addLine(t);
return r.finish(), e;
}
function q(c) {
const { end: e, start: r, child_features: t, derived_features: i, attributes: n, type: a, source: s, phase: o, seq_id: h, score: l, strand: f } = c;
let u;
f === "+" ? u = 1 : f === "-" ? u = -1 : f === "." && (u = 0);
const k = /* @__PURE__ */ new Set([
"start",
"end",
"seq_id",
"score",
"type",
"source",
"phase",
"strand"
]), v = n || {}, b = {};
for (const d of Object.keys(v)) {
let _ = d.toLowerCase();
if (k.has(_) && (_ += "2"), v[d] && d !== "_lineHash") {
let p = v[d];
Array.isArray(p) && p.length === 1 && ([p] = p), b[_] = p;
}
}
return {
...b,
start: r - 1,
end: e,
strand: u,
type: a,
source: s,
refName: h,
derived_features: i,
phase: o === null ? void 0 : Number(o),
score: l === null ? void 0 : l,
subfeatures: t.flatMap((d) => d.map((_) => q(_)))
};
}
export {
q as f,
L as p
};
//# sourceMappingURL=featureData-Bm8gwGZK.js.map