UNPKG

@jbrowse/plugin-wiggle

Version:

JBrowse 2 wiggle adapters, tracks, etc.

116 lines (115 loc) 3.89 kB
import { optional } from "./accessors.js"; import { Node, computeHeight } from "./hierarchy/index.js"; var preroot = { depth: -1 }, ambiguous = {}, imputed = {}; function defaultId(d) { return d.id; } function defaultParentId(d) { return d.parentId; } export default function () { var id = defaultId, parentId = defaultParentId, path; function stratify(data) { var nodes = Array.from(data), currentId = id, currentParentId = parentId, n, d, i, root, parent, node, nodeId, nodeKey, nodeByKey = new Map; if (path != null) { const I = nodes.map((d, i) => normalize(path(d, i, data))); const P = I.map(parentof); const S = new Set(I).add(""); for (const i of P) { if (!S.has(i)) { S.add(i); I.push(i); P.push(parentof(i)); nodes.push(imputed); } } currentId = (_, i) => I[i]; currentParentId = (_, i) => P[i]; } for (i = 0, n = nodes.length; i < n; ++i) { d = nodes[i], node = nodes[i] = new Node(d); if ((nodeId = currentId(d, i, data)) != null && (nodeId += "")) { nodeKey = node.id = nodeId; nodeByKey.set(nodeKey, nodeByKey.has(nodeKey) ? ambiguous : node); } if ((nodeId = currentParentId(d, i, data)) != null && (nodeId += "")) { node.parent = nodeId; } } for (i = 0; i < n; ++i) { node = nodes[i]; if (nodeId = node.parent) { parent = nodeByKey.get(nodeId); if (!parent) throw new Error("missing: " + nodeId); if (parent === ambiguous) throw new Error("ambiguous: " + nodeId); if (parent.children) parent.children.push(node); else parent.children = [node]; node.parent = parent; } else { if (root) throw new Error("multiple roots"); root = node; } } if (!root) throw new Error("no root"); if (path != null) { while (root.data === imputed && root.children.length === 1) { root = root.children[0], --n; } for (let i = nodes.length - 1; i >= 0; --i) { node = nodes[i]; if (node.data !== imputed) break; node.data = null; } } root.parent = preroot; root.eachBefore(function (node) { node.depth = node.parent.depth + 1; --n; }).eachBefore(computeHeight); root.parent = null; if (n > 0) throw new Error("cycle"); return root; } stratify.id = function (x) { return arguments.length ? (id = optional(x), stratify) : id; }; stratify.parentId = function (x) { return arguments.length ? (parentId = optional(x), stratify) : parentId; }; stratify.path = function (x) { return arguments.length ? (path = optional(x), stratify) : path; }; return stratify; } function normalize(path) { path = `${path}`; let i = path.length; if (slash(path, i - 1) && !slash(path, i - 2)) path = path.slice(0, -1); return path[0] === "/" ? path : `/${path}`; } function parentof(path) { let i = path.length; if (i < 2) return ""; while (--i > 1) if (slash(path, i)) break; return path.slice(0, i); } function slash(path, i) { if (path[i] === "/") { let k = 0; while (i > 0 && path[--i] === "\\") ++k; if ((k & 1) === 0) return true; } return false; }