jbrowse-plugin-graphgenomeviewer 4.8.0 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/README.md +4 -0
  2. package/dist/chunks/GbzBaseSyntenyAdapter-CKKVHC2R.js +4 -0
  3. package/dist/chunks/GbzBaseSyntenyAdapter-CKKVHC2R.js.map +7 -0
  4. package/dist/chunks/LinearGraphDisplay-7YE624D5.js +2 -0
  5. package/dist/chunks/LinearGraphDisplay-7YE624D5.js.map +7 -0
  6. package/dist/chunks/chunk-2H7GDQ3R.js +6 -0
  7. package/dist/chunks/chunk-2H7GDQ3R.js.map +7 -0
  8. package/dist/chunks/chunk-BZOIENU5.js +2 -0
  9. package/dist/chunks/chunk-BZOIENU5.js.map +7 -0
  10. package/dist/jbrowse-plugin-graphgenomeviewer.esm.js +5 -5
  11. package/dist/jbrowse-plugin-graphgenomeviewer.esm.js.map +4 -4
  12. package/package.json +3 -3
  13. package/src/GbzBaseSyntenyAdapter/GbzBaseSyntenyAdapter.test.ts +36 -2
  14. package/src/GbzBaseSyntenyAdapter/GbzBaseSyntenyAdapter.ts +67 -1
  15. package/src/GbzBaseSyntenyAdapter/test_data/fragmented.haplotype-index.db +0 -0
  16. package/src/GbzBaseSyntenyAdapter/test_data/micb-kir3dl1.haplotype-index.db +0 -0
  17. package/src/GbzBaseSyntenyAdapter/test_data/micb-kir3dl1.sampled.haplotype-index.db +0 -0
  18. package/src/GetHaplotypeOverview.ts +77 -0
  19. package/src/GraphGenomeView/host.ts +6 -0
  20. package/src/HaplotypeOverview/HaplotypeOverviewCanvas.tsx +203 -0
  21. package/src/HaplotypeOverview/draw.test.ts +136 -0
  22. package/src/HaplotypeOverview/draw.ts +433 -0
  23. package/src/HaplotypeOverview/model.ts +163 -0
  24. package/src/LinearGraphDisplay/LinearGraphDisplay.test.ts +184 -0
  25. package/src/LinearGraphDisplay/components/LinearGraphDisplay.tsx +12 -2
  26. package/src/LinearGraphDisplay/model.ts +107 -3
  27. package/src/index.ts +2 -0
  28. package/src/version.ts +1 -1
  29. package/dist/chunks/GbzBaseSyntenyAdapter-VOGKGHQ6.js +0 -8
  30. package/dist/chunks/GbzBaseSyntenyAdapter-VOGKGHQ6.js.map +0 -7
  31. package/dist/chunks/LinearGraphDisplay-4HYL7PDU.js +0 -2
  32. package/dist/chunks/LinearGraphDisplay-4HYL7PDU.js.map +0 -7
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../node_modules/.pnpm/@gmod+gbz-base@7.0.0/node_modules/@gmod/gbz-base/src/gbwt/node.ts", "../../node_modules/.pnpm/@gmod+gbz-base@7.0.0/node_modules/@gmod/gbz-base/src/gbwt/bytecode.ts", "../../node_modules/.pnpm/@gmod+gbz-base@7.0.0/node_modules/@gmod/gbz-base/src/gbwt/record.ts", "../../node_modules/.pnpm/@gmod+gbz-base@7.0.0/node_modules/@gmod/gbz-base/src/gbwt/sequence.ts", "../../node_modules/.pnpm/@gmod+gbz-base@7.0.0/node_modules/@gmod/gbz-base/src/sha256.ts", "../../node_modules/.pnpm/@gmod+gbz-base@7.0.0/node_modules/@gmod/gbz-base/src/graphName.ts", "../../node_modules/.pnpm/@gmod+gbz-base@7.0.0/node_modules/@gmod/gbz-base/src/pathName.ts", "../../node_modules/.pnpm/@gmod+gbz-base@7.0.0/node_modules/@gmod/gbz-base/src/chosenPaths.ts", "../../node_modules/.pnpm/@gmod+gbz-base@7.0.0/node_modules/@gmod/gbz-base/src/lcs.ts", "../../node_modules/.pnpm/@gmod+gbz-base@7.0.0/node_modules/@gmod/gbz-base/src/pairAlignment.ts", "../../node_modules/.pnpm/@gmod+gbz-base@7.0.0/node_modules/@gmod/gbz-base/src/subgraph.ts", "../../node_modules/.pnpm/@gmod+gbz-base@7.0.0/node_modules/@gmod/gbz-base/src/query.ts", "../../node_modules/.pnpm/@gmod+gbz-base@7.0.0/node_modules/@gmod/gbz-base/src/sqlite/record.ts", "../../node_modules/.pnpm/@gmod+gbz-base@7.0.0/node_modules/@gmod/gbz-base/src/sqlite/btree.ts", "../../node_modules/.pnpm/@gmod+gbz-base@7.0.0/node_modules/@gmod/gbz-base/src/sqlite/pager.ts", "../../node_modules/.pnpm/@gmod+gbz-base@7.0.0/node_modules/@gmod/gbz-base/src/sqlite/database.ts", "../../node_modules/.pnpm/@gmod+gbz-base@7.0.0/node_modules/@gmod/gbz-base/src/db.ts"],
4
+ "sourcesContent": ["export const ENDMARKER = 0\n\nexport type Orientation = 'forward' | 'reverse'\n\nexport function encodeNode(id: number, orientation: Orientation) {\n return 2 * id + (orientation === 'reverse' ? 1 : 0)\n}\n\nexport function nodeId(handle: number) {\n return Math.floor(handle / 2)\n}\n\nexport function nodeOrientation(handle: number): Orientation {\n return handle % 2 === 0 ? 'forward' : 'reverse'\n}\n\nexport function isReverse(handle: number) {\n return handle % 2 === 1\n}\n\nexport function flipNode(handle: number) {\n return handle % 2 === 0 ? handle + 1 : handle - 1\n}\n\nexport type NodeSide = 'left' | 'right'\n\nexport function flipSide(side: NodeSide): NodeSide {\n return side === 'left' ? 'right' : 'left'\n}\n\nexport function entrySide(orientation: Orientation): NodeSide {\n return orientation === 'forward' ? 'left' : 'right'\n}\n\nexport function exitSide(orientation: Orientation): NodeSide {\n return orientation === 'forward' ? 'right' : 'left'\n}\n\nexport function entryOrientation(side: NodeSide): Orientation {\n return side === 'left' ? 'forward' : 'reverse'\n}\n\nexport function exitOrientation(side: NodeSide): Orientation {\n return side === 'right' ? 'forward' : 'reverse'\n}\n\nexport function edgeIsCanonical(from: number, to: number) {\n const fromId = nodeId(from)\n const toId = nodeId(to)\n return isReverse(from)\n ? toId > fromId || (toId === fromId && !isReverse(to))\n : toId >= fromId\n}\n\nexport function pathIsCanonical(path: number[]) {\n return pathEndsAreCanonical(path[0], path[path.length - 1])\n}\n\nexport function pathEndsAreCanonical(\n first: number | undefined,\n last: number | undefined,\n) {\n if (first === undefined || last === undefined) {\n return true\n }\n return isReverse(first) === isReverse(last)\n ? !isReverse(first)\n : edgeIsCanonical(first, last)\n}\n", "export class ByteCodeReader {\n offset = 0\n private bytes: Uint8Array\n\n constructor(bytes: Uint8Array) {\n this.bytes = bytes\n }\n\n get done() {\n return this.offset >= this.bytes.length\n }\n\n byte() {\n const value = this.bytes[this.offset]\n if (value === undefined) {\n return undefined\n }\n this.offset += 1\n return value\n }\n\n int() {\n let shift = 1\n let result = 0\n while (this.offset < this.bytes.length) {\n const value = this.bytes[this.offset]!\n this.offset += 1\n result += (value & 0x7f) * shift\n shift *= 128\n if ((value & 0x80) === 0) {\n return result\n }\n }\n return undefined\n }\n}\n\nexport interface Run {\n value: number\n len: number\n}\n\nconst RLE_THRESHOLD = 255\nconst RLE_UNIVERSE = 256\n\nexport class RunReader {\n private source: ByteCodeReader\n private sigma: number\n private threshold: number\n\n constructor(bytes: Uint8Array, sigma: number) {\n this.source = new ByteCodeReader(bytes)\n this.sigma = sigma === 0 ? Number.MAX_SAFE_INTEGER : sigma\n this.threshold =\n this.sigma < RLE_THRESHOLD ? Math.floor(RLE_UNIVERSE / this.sigma) : 0\n }\n\n next(): Run | undefined {\n if (this.sigma >= RLE_THRESHOLD) {\n const value = this.source.int()\n const len = this.source.int()\n return value === undefined || len === undefined\n ? undefined\n : { value, len: len + 1 }\n }\n const byte = this.source.byte()\n if (byte === undefined) {\n return undefined\n }\n const value = byte % this.sigma\n let len = Math.floor(byte / this.sigma) + 1\n if (len === this.threshold) {\n const extra = this.source.int()\n if (extra === undefined) {\n return undefined\n }\n len += extra\n }\n return { value, len }\n }\n\n *[Symbol.iterator]() {\n for (let run = this.next(); run !== undefined; run = this.next()) {\n yield run\n }\n }\n}\n", "import { ByteCodeReader, RunReader } from './bytecode.ts'\nimport { ENDMARKER, flipNode, nodeId } from './node.ts'\n\nexport interface Pos {\n node: number\n offset: number\n}\n\nexport function decompressEdges(bytes: Uint8Array): Pos[] {\n const reader = new ByteCodeReader(bytes)\n const sigma = reader.int()\n if (sigma === undefined || sigma === 0) {\n return []\n }\n const edges: Pos[] = []\n let prev = 0\n for (let i = 0; i < sigma; i++) {\n const delta = reader.int()\n const offset = reader.int()\n if (delta === undefined || offset === undefined) {\n throw new Error('GBWT edge list ends early')\n }\n prev += delta\n edges.push({ node: prev, offset })\n }\n return edges\n}\n\nexport class GbwtRecord {\n readonly edges: Pos[]\n readonly bwt: Uint8Array\n\n constructor(edges: Pos[], bwt: Uint8Array) {\n this.edges = edges\n this.bwt = bwt\n }\n\n runs() {\n return new RunReader(this.bwt, this.edges.length)\n }\n\n private edge(rank: number) {\n const edge = this.edges[rank]\n if (edge === undefined) {\n throw new Error(\n `GBWT run refers to edge rank ${rank} of ${this.edges.length}`,\n )\n }\n return edge\n }\n\n lf(i: number): Pos | undefined {\n const offsets = this.edges.map(e => e.offset)\n let offset = 0\n for (const run of this.runs()) {\n const edge = this.edge(run.value)\n const soFar = offsets[run.value]!\n if (offset + run.len > i) {\n return edge.node === ENDMARKER\n ? undefined\n : { node: edge.node, offset: soFar + (i - offset) }\n }\n offsets[run.value] = soFar + run.len\n offset += run.len\n }\n return undefined\n }\n\n private edgeTo(node: number) {\n let low = 0\n let high = this.edges.length\n while (low < high) {\n const mid = (low + high) >> 1\n const edge = this.edges[mid]!\n if (edge.node === node) {\n return mid\n }\n if (edge.node < node) {\n low = mid + 1\n } else {\n high = mid\n }\n }\n return undefined\n }\n\n offsetTo(pos: Pos): number | undefined {\n if (pos.node === ENDMARKER) {\n return undefined\n }\n const rank = this.edgeTo(pos.node)\n if (rank === undefined) {\n return undefined\n }\n let succRank = this.edges[rank]!.offset\n if (succRank > pos.offset) {\n return undefined\n }\n let offset = 0\n for (const run of this.runs()) {\n offset += run.len\n if (run.value !== rank) {\n continue\n }\n succRank += run.len\n if (succRank > pos.offset) {\n return offset - (succRank - pos.offset)\n }\n }\n return undefined\n }\n\n predecessorAt(i: number): number | undefined {\n const counts = this.edges.map(e => ({\n node: e.node === ENDMARKER ? ENDMARKER : flipNode(e.node),\n count: 0,\n }))\n for (const run of this.runs()) {\n const entry = counts[run.value]\n if (entry) {\n entry.count += run.len\n }\n }\n for (let rank = 1; rank < counts.length; rank++) {\n const prev = counts[rank - 1] as { node: number; count: number }\n const curr = counts[rank] as { node: number; count: number }\n if (nodeId(prev.node) === nodeId(curr.node)) {\n counts[rank - 1] = curr\n counts[rank] = prev\n }\n }\n let offset = 0\n for (const entry of counts) {\n offset += entry.count\n if (offset > i) {\n return entry.node === ENDMARKER ? undefined : entry.node\n }\n }\n return undefined\n }\n\n decompressArrays() {\n const offsets = this.edges.map(e => e.offset)\n let total = 0\n for (const run of this.runs()) {\n total += run.len\n }\n const nodes = new Int32Array(total)\n const nextOffsets = new Int32Array(total)\n let i = 0\n for (const run of this.runs()) {\n const edge = this.edge(run.value)\n let offset = offsets[run.value]!\n for (let k = 0; k < run.len; k++) {\n nodes[i] = edge.node\n nextOffsets[i] = offset\n offset += 1\n i += 1\n }\n offsets[run.value] = offset\n }\n return { nodes, offsets: nextOffsets }\n }\n\n decompress(): Pos[] {\n const offsets = this.edges.map(e => e.offset)\n const result: Pos[] = []\n for (const run of this.runs()) {\n const edge = this.edge(run.value)\n for (let k = 0; k < run.len; k++) {\n result.push({ node: edge.node, offset: offsets[run.value]! })\n offsets[run.value] = offsets[run.value]! + 1\n }\n }\n return result\n }\n}\n", "const DECODE = ['', 'A', 'C', 'G', 'T', 'N']\n\nexport function encodedSequenceLength(encoded: Uint8Array) {\n const last = encoded[encoded.length - 1]\n if (last === undefined) {\n return 0\n }\n let value = last\n let inLast = 0\n for (let i = 0; i < 3; i++) {\n if (value % 6 === 0) {\n break\n }\n value = Math.floor(value / 6)\n inLast += 1\n }\n return 3 * (encoded.length - 1) + inLast\n}\n\nexport function decodeSequence(encoded: Uint8Array) {\n let result = ''\n for (const byte of encoded) {\n let value = byte\n for (let i = 0; i < 3; i++) {\n const base = DECODE[value % 6]!\n if (base === '') {\n return result\n }\n value = Math.floor(value / 6)\n result += base\n }\n }\n return result\n}\n\nconst COMPLEMENT: Record<string, string> = {\n A: 'T',\n C: 'G',\n G: 'C',\n T: 'A',\n N: 'N',\n}\n\nexport function reverseComplement(sequence: string) {\n let result = ''\n for (let i = sequence.length - 1; i >= 0; i--) {\n result += COMPLEMENT[sequence[i]!] ?? 'N'\n }\n return result\n}\n", "const K = Uint32Array.from([\n 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,\n 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,\n 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,\n 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,\n 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,\n 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,\n 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,\n 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,\n 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,\n 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,\n 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,\n])\n\nconst rotr = (x: number, n: number) => (x >>> n) | (x << (32 - n))\n\n// FIPS 180-4, for pages without crypto.subtle (insecure contexts)\nexport function sha256(bytes: Uint8Array) {\n const blocks = Math.ceil((bytes.length + 9) / 64)\n const padded = new Uint8Array(blocks * 64)\n padded.set(bytes)\n padded[bytes.length] = 0x80\n const view = new DataView(padded.buffer)\n const bits = bytes.length * 8\n view.setUint32(padded.length - 8, Math.floor(bits / 2 ** 32))\n view.setUint32(padded.length - 4, bits >>> 0)\n const h = Uint32Array.from([\n 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c,\n 0x1f83d9ab, 0x5be0cd19,\n ])\n const w = new Uint32Array(64)\n for (let block = 0; block < blocks; block++) {\n for (let t = 0; t < 16; t++) {\n w[t] = view.getUint32(block * 64 + t * 4)\n }\n for (let t = 16; t < 64; t++) {\n const a = w[t - 15]!\n const b = w[t - 2]!\n const s0 = rotr(a, 7) ^ rotr(a, 18) ^ (a >>> 3)\n const s1 = rotr(b, 17) ^ rotr(b, 19) ^ (b >>> 10)\n w[t] = w[t - 16]! + s0 + w[t - 7]! + s1\n }\n let a = h[0]!\n let b = h[1]!\n let c = h[2]!\n let d = h[3]!\n let e = h[4]!\n let f = h[5]!\n let g = h[6]!\n let hh = h[7]!\n for (let t = 0; t < 64; t++) {\n const s1 = rotr(e, 6) ^ rotr(e, 11) ^ rotr(e, 25)\n const ch = (e & f) ^ (~e & g)\n const t1 = (hh + s1 + ch + K[t]! + w[t]!) | 0\n const s0 = rotr(a, 2) ^ rotr(a, 13) ^ rotr(a, 22)\n const maj = (a & b) ^ (a & c) ^ (b & c)\n hh = g\n g = f\n f = e\n e = (d + t1) | 0\n d = c\n c = b\n b = a\n a = (t1 + s0 + maj) | 0\n }\n ;[a, b, c, d, e, f, g, hh].forEach((value, i) => {\n h[i] = h[i]! + value\n })\n }\n const out = new Uint8Array(32)\n const outView = new DataView(out.buffer)\n for (let i = 0; i < 8; i++) {\n outView.setUint32(i * 4, h[i]!)\n }\n return out\n}\n", "import { sha256 } from './sha256.ts'\n\nexport interface GraphName {\n name: string | undefined\n subgraph: Map<string, Set<string>>\n translation: Map<string, Set<string>>\n}\n\nfunction parseRelationships(field: string | undefined, what: string) {\n const relationships = new Map<string, Set<string>>()\n if (field !== undefined) {\n for (const rel of field.split(';')) {\n const parts = rel.split(',')\n const [from, to] = parts\n if (parts.length !== 2 || !from || !to) {\n throw new Error(`Invalid ${what} relationship: ${rel}`)\n }\n let targets = relationships.get(from)\n if (!targets) {\n targets = new Set()\n relationships.set(from, targets)\n }\n targets.add(to)\n }\n }\n return relationships\n}\n\nexport function graphNameFromTags(tags: Map<string, string>): GraphName {\n return {\n name: tags.get('pggname'),\n subgraph: parseRelationships(tags.get('subgraph'), 'subgraph'),\n translation: parseRelationships(tags.get('translation'), 'translation'),\n }\n}\n\nfunction merge(into: Map<string, Set<string>>, from: Map<string, Set<string>>) {\n for (const [key, values] of from) {\n let targets = into.get(key)\n if (!targets) {\n targets = new Set()\n into.set(key, targets)\n }\n for (const value of values) {\n targets.add(value)\n }\n }\n}\n\nexport function subgraphName(name: string, parent: GraphName): GraphName {\n const result: GraphName = {\n name,\n subgraph: new Map(),\n translation: new Map(),\n }\n if (parent.name !== undefined) {\n result.subgraph.set(name, new Set([parent.name]))\n merge(result.subgraph, parent.subgraph)\n merge(result.translation, parent.translation)\n }\n return result\n}\n\nfunction sortedEntries(relationships: Map<string, Set<string>>) {\n return [...relationships.entries()]\n .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))\n .flatMap(([from, tos]) => [...tos].sort().map(to => [from, to] as const))\n}\n\nexport function gfaHeaderLines(graphName: GraphName) {\n const lines: string[] = []\n if (graphName.name !== undefined) {\n lines.push(`H\\tNM:Z:${graphName.name}`)\n }\n for (const [subgraph, supergraph] of sortedEntries(graphName.subgraph)) {\n lines.push(`H\\tSG:Z:${subgraph},${supergraph}`)\n }\n for (const [from, to] of sortedEntries(graphName.translation)) {\n lines.push(`H\\tTL:Z:${from},${to}`)\n }\n return lines\n}\n\nexport async function sha256Hex(chunks: Uint8Array[]) {\n const total = chunks.reduce((sum, chunk) => sum + chunk.length, 0)\n const bytes = new Uint8Array(total)\n let offset = 0\n for (const chunk of chunks) {\n bytes.set(chunk, offset)\n offset += chunk.length\n }\n const subtle = (globalThis.crypto as Crypto | undefined)?.subtle\n const digest = subtle\n ? new Uint8Array(await subtle.digest('SHA-256', bytes))\n : sha256(bytes)\n return [...digest].map(byte => byte.toString(16).padStart(2, '0')).join('')\n}\n", "export interface PathName {\n sample: string\n contig: string\n haplotype: number\n fragment: number\n}\n\nexport interface PathQuery {\n sample?: string | undefined\n contig: string\n haplotype?: number | undefined\n}\n\nexport type PathRef = string | PathQuery\n\nexport const GENERIC_SAMPLE = '_gbwt_ref'\n\nexport function formatPathName(name: PathName & { end?: number | undefined }) {\n const base = `${name.sample}#${name.haplotype}#${name.contig}`\n return name.end === undefined ? base : `${base}[${name.fragment}-${name.end}]`\n}\n\nconst PAN_SN = /^([^#]+)#(\\d+)#([^#]+?)(?:\\[\\d+-\\d+\\])?$/\nconst BARE_CONTIG = /^([^#]+?)(?:\\[\\d+-\\d+\\])?$/\n\nexport function parsePathName(name: string): PathQuery {\n const panSn = PAN_SN.exec(name)\n if (panSn) {\n return {\n sample: panSn[1]!,\n haplotype: Number(panSn[2]),\n contig: panSn[3]!,\n }\n }\n const bare = BARE_CONTIG.exec(name)\n if (bare) {\n return { contig: bare[1]! }\n }\n throw new Error(\n `\"${name}\" is not a path name; expected \"sample#haplotype#contig\" or a bare contig`,\n )\n}\n\nexport function toPathQuery(ref: PathRef) {\n return typeof ref === 'string' ? parsePathName(ref) : ref\n}\n\nexport function pathNameFor(query: PathQuery, fragment: number): PathName {\n return {\n sample: query.sample ?? GENERIC_SAMPLE,\n contig: query.contig,\n haplotype: query.haplotype ?? 0,\n fragment,\n }\n}\n", "import {\n ENDMARKER,\n flipNode,\n isReverse,\n nodeId,\n pathEndsAreCanonical,\n} from './gbwt/node.ts'\n\nimport type {\n GBZBase,\n GbzRecord,\n HaplotypeAnchorRow,\n HaplotypeSample,\n HaplotypeStrayOptions,\n} from './db.ts'\nimport type { Orientation } from './gbwt/node.ts'\nimport type { Pos } from './gbwt/record.ts'\nimport type { PathName } from './pathName.ts'\nimport type { SnarlFill, SnarlOutput } from './subgraph.ts'\n\nconst SCAN_GAP = 4096\n\n// Runs of sorted handles close enough to read the haplotype index samples on\n// them with one scan each.\nexport function handleRuns(sortedHandles: number[]) {\n const runs: [number, number][] = []\n for (const handle of sortedHandles) {\n const last = runs[runs.length - 1]\n if (last && handle - last[1] <= SCAN_GAP) {\n last[1] = handle\n } else {\n runs.push([handle, handle])\n }\n }\n return runs\n}\n\n// How far a chain from a twin piece goes outside the subgraph before it stops.\nexport const CHAIN_BOUND = 32768\n\n// Above this many chosen paths at the anchors, extracting and identifying\n// every walk took less time than walking the chosen ones, on HPRC chr22 windows\n// with 42 haplotypes. Tests raise it to run the walks on large sets.\nexport const keepTuning = { mostChosenPaths: 32 }\n\nexport type ChosenPieceSource =\n 'reference' | 'section' | 'stray' | 'chain' | 'twin'\n\nexport interface ChosenPiece {\n pathHandle: number\n orientation: Orientation\n handles: number[]\n offsets: number[]\n len: number\n hapStart: number\n hapEnd: number\n canonical: boolean\n source: ChosenPieceSource\n}\n\nexport type KeepWalkEnd =\n 'merge' | 'landed' | 'bound' | 'endmarker' | 'past the far anchor'\n\nexport interface KeepStats {\n spacing: number | undefined\n // The anchors before and after the window.\n anchors: [number, number] | undefined\n // The anchors within the walks' bound of the bins the window touches, and\n // one beyond on each side.\n anchorsRead: number\n chosenPaths: number\n scans: [number, number][]\n scanRows: number\n // The bins the window touches, the stray rows read in them, those of chosen\n // paths walked, and the bases all walks took outside the subgraph.\n strays:\n | { bins: number; rows: number; walked: number; outsideBp: number }\n | undefined\n pieces: number\n sources: Record<ChosenPieceSource, number>\n walks: Record<string, number>\n twins: { tried: number; found: number }\n graphFetches: number\n // Why the query extracted and identified every walk instead, when it did.\n fallback: string | undefined\n ms: {\n scan: number\n walks: number\n check: number\n twins: number\n }\n}\n\nexport interface ChosenPathsInput {\n db: GBZBase\n records: Map<number, GbzRecord>\n referenceHandle: number\n referencePos: Pos\n referenceLeft: number\n window: { start: number; end: number }\n context: number\n // The snarls the subgraph filled and the nodes those fills added.\n snarls: { mode: SnarlOutput; fills: SnarlFill[]; inserted: Set<number> }\n keep: (name: PathName) => boolean\n signal: AbortSignal | undefined\n prefetchReferenceRange: (\n pathHandle: number,\n fromOffset: number,\n toOffset: number,\n ) => Promise<unknown>\n}\n\ninterface Cursor {\n pos: Pos\n left: number\n}\n\nclass PositionIndex {\n private byNode = new Map<number, Map<number, number>>()\n\n get(pos: Pos) {\n return this.byNode.get(pos.node)?.get(pos.offset)\n }\n\n set(pos: Pos, id: number) {\n let offsets = this.byNode.get(pos.node)\n if (!offsets) {\n offsets = new Map()\n this.byNode.set(pos.node, offsets)\n }\n offsets.set(pos.offset, id)\n }\n}\n\nclass Fallback extends Error {}\n\nfunction forwardLeft(\n orientation: Orientation,\n left: number,\n currentLen: number,\n nextLen: number,\n) {\n return orientation === 'forward' ? left + currentLen : left - nextLen\n}\n\nfunction backwardLeft(\n orientation: Orientation,\n left: number,\n currentLen: number,\n previousLen: number,\n) {\n return orientation === 'forward' ? left - previousLen : left + currentLen\n}\n\nfunction twinIsCanonical(piece: ChosenPiece) {\n return pathEndsAreCanonical(\n flipNode(piece.handles[piece.handles.length - 1]!),\n flipNode(piece.handles[0]!),\n )\n}\n\nfunction pieceKey(piece: ChosenPiece) {\n return `${piece.pathHandle}:${piece.hapStart}:${piece.hapEnd}`\n}\n\n// The pieces a chosen set of haplotypes leaves in a subgraph: every maximal\n// run of one path's positions whose nodes all lie in the subgraph, the pieces\n// extractPaths and identifyPaths find by walking and naming every haplotype.\n// When the haplotype index cannot show that the walks below pass every such\n// piece, the result carries a fallback reason and no pieces, and the caller\n// identifies every walk.\nexport async function findChosenPieces(input: ChosenPathsInput) {\n const { db, records, signal } = input\n let clock = performance.now()\n const lap = () => {\n const now = performance.now()\n const elapsed = now - clock\n clock = now\n return elapsed\n }\n const stats: KeepStats = {\n spacing: await db.haplotypeAnchorSpacing(),\n anchors: undefined,\n anchorsRead: 0,\n chosenPaths: 0,\n scans: [],\n scanRows: 0,\n strays: undefined,\n pieces: 0,\n sources: {\n reference: 0,\n section: 0,\n stray: 0,\n chain: 0,\n twin: 0,\n },\n walks: {},\n twins: { tried: 0, found: 0 },\n graphFetches: 0,\n fallback: undefined,\n ms: { scan: 0, walks: 0, check: 0, twins: 0 },\n }\n const countWalk = (kind: string, end: KeepWalkEnd) => {\n const key = `${kind}: ${end}`\n stats.walks[key] = (stats.walks[key] ?? 0) + 1\n }\n const interval = (await db.haplotypeSampleInterval()) ?? 4096\n const outside = new Map<number, GbzRecord>()\n const record = async (handle: number) => {\n const inside = records.get(handle) ?? outside.get(handle)\n if (inside) {\n return inside\n }\n const fetched = await db.getRecord(handle)\n stats.graphFetches += 1\n if (!fetched) {\n throw new Error(`Node record ${handle} is missing from the database`)\n }\n outside.set(handle, fetched)\n return fetched\n }\n const lengthIn = (handle: number) => records.get(handle)!.sequenceLen\n const pathsByHandle = await db.pathsByHandle()\n const chosen = (pathHandle: number) => {\n const path = pathsByHandle.get(pathHandle)\n return path !== undefined && input.keep(path.name)\n }\n\n const pieces: ChosenPiece[] = []\n const pieceAt = new PositionIndex()\n const piecesOfPath = new Map<number, number[]>()\n const forwardDone = new Set<number>()\n const backwardDone = new Set<number>()\n\n const next = async (pos: Pos): Promise<Pos | undefined> => {\n const successor = (await record(pos.node)).gbwt().lf(pos.offset)\n return successor === undefined || successor.node === ENDMARKER\n ? undefined\n : successor\n }\n const previous = async (\n pos: Pos,\n within?: Map<number, GbzRecord>,\n ): Promise<Pos | undefined> => {\n const predecessor = (await record(flipNode(pos.node)))\n .gbwt()\n .predecessorAt(pos.offset)\n if (\n predecessor === undefined ||\n (within !== undefined && !within.has(predecessor))\n ) {\n return undefined\n }\n const offset = (await record(predecessor)).gbwt().offsetTo(pos)\n if (offset === undefined) {\n throw new Error(\n `No offset in ${predecessor} leads to ${pos.node}:${pos.offset}`,\n )\n }\n return { node: predecessor, offset }\n }\n\n const addPiece = (\n pathHandle: number,\n orientation: Orientation,\n cursors: Cursor[],\n source: ChosenPieceSource,\n ) => {\n const handles = cursors.map(c => c.pos.node)\n const offsets = cursors.map(c => c.pos.offset)\n let len = 0\n for (const handle of handles) {\n len += lengthIn(handle)\n }\n const hapStart =\n orientation === 'forward'\n ? cursors[0]!.left\n : cursors[cursors.length - 1]!.left\n const id = pieces.length\n pieces.push({\n pathHandle,\n orientation,\n handles,\n offsets,\n len,\n hapStart,\n hapEnd: hapStart + len,\n canonical: pathEndsAreCanonical(handles[0], handles[handles.length - 1]),\n source,\n })\n for (const cursor of cursors) {\n pieceAt.set(cursor.pos, id)\n }\n const ofPath = piecesOfPath.get(pathHandle)\n if (ofPath) {\n ofPath.push(id)\n } else {\n piecesOfPath.set(pathHandle, [id])\n }\n return id\n }\n\n // The piece through a position in the subgraph, in that position's\n // orientation of its path.\n const pieceThrough = async (\n seed: Cursor,\n pathHandle: number,\n orientation: Orientation,\n source: ChosenPieceSource,\n ) => {\n const before: Cursor[] = []\n let cursor = seed\n for (;;) {\n signal?.throwIfAborted()\n const pos = await previous(cursor.pos, records)\n if (!pos) {\n break\n }\n cursor = {\n pos,\n left: backwardLeft(\n orientation,\n cursor.left,\n lengthIn(cursor.pos.node),\n lengthIn(pos.node),\n ),\n }\n before.push(cursor)\n }\n before.reverse()\n const after: Cursor[] = [seed]\n cursor = seed\n for (;;) {\n signal?.throwIfAborted()\n const pos = await next(cursor.pos)\n if (!pos || !records.has(pos.node)) {\n break\n }\n cursor = {\n pos,\n left: forwardLeft(\n orientation,\n cursor.left,\n lengthIn(cursor.pos.node),\n lengthIn(pos.node),\n ),\n }\n after.push(cursor)\n }\n return addPiece(pathHandle, orientation, [...before, ...after], source)\n }\n const pieceAtOrThrough = async (\n cursor: Cursor,\n pathHandle: number,\n orientation: Orientation,\n source: ChosenPieceSource,\n ) =>\n pieces[\n pieceAt.get(cursor.pos) ??\n (await pieceThrough(cursor, pathHandle, orientation, source))\n ]!\n\n const lastCursor = (piece: ChosenPiece): Cursor => {\n const node = piece.handles[piece.handles.length - 1]!\n return {\n pos: { node, offset: piece.offsets[piece.offsets.length - 1]! },\n left:\n piece.orientation === 'forward'\n ? piece.hapEnd - lengthIn(node)\n : piece.hapStart,\n }\n }\n const firstCursor = (piece: ChosenPiece): Cursor => {\n const node = piece.handles[0]!\n return {\n pos: { node, offset: piece.offsets[0]! },\n left:\n piece.orientation === 'forward'\n ? piece.hapStart\n : piece.hapEnd - lengthIn(node),\n }\n }\n\n const referenceId = await pieceThrough(\n { pos: input.referencePos, left: input.referenceLeft },\n input.referenceHandle,\n 'forward',\n 'reference',\n )\n const reference = pieces[referenceId]!\n const result = () => {\n if (stats.fallback !== undefined) {\n return { reference, pieces: [], stats }\n }\n // What extractPaths keeps: the canonical twin of each piece, and both twins\n // when both are canonical.\n const byKey = new Map<string, ChosenPiece[]>()\n pieces.forEach((piece, id) => {\n if (id !== referenceId) {\n byKey.set(pieceKey(piece), [\n ...(byKey.get(pieceKey(piece)) ?? []),\n piece,\n ])\n }\n })\n const emitted: ChosenPiece[] = []\n for (const group of byKey.values()) {\n const orientations = new Set<Orientation>()\n for (const piece of group) {\n if (piece.canonical && !orientations.has(piece.orientation)) {\n orientations.add(piece.orientation)\n emitted.push(piece)\n stats.sources[piece.source] += 1\n }\n }\n }\n stats.sources.reference = 1\n stats.pieces = emitted.length + 1\n return { reference, pieces: emitted, stats }\n }\n\n // A chain from a piece, forward or backward, through every piece it lands\n // in, until it meets a known position or runs CHAIN_BOUND bp outside the\n // subgraph.\n const chain = async (id: number, forward: boolean) => {\n const done = forward ? forwardDone : backwardDone\n const other = forward ? backwardDone : forwardDone\n let current = id\n for (;;) {\n if (done.has(current)) {\n return\n }\n done.add(current)\n const piece = pieces[current]!\n let cursor = forward ? lastCursor(piece) : firstCursor(piece)\n let bp = 0\n let end: KeepWalkEnd | undefined\n while (end === undefined) {\n signal?.throwIfAborted()\n const pos = forward\n ? await next(cursor.pos)\n : await previous(cursor.pos)\n if (!pos) {\n end = 'endmarker'\n break\n }\n const currentLen = (await record(cursor.pos.node)).sequenceLen\n const len = (await record(pos.node)).sequenceLen\n const left = forward\n ? forwardLeft(piece.orientation, cursor.left, currentLen, len)\n : backwardLeft(piece.orientation, cursor.left, currentLen, len)\n if (records.has(pos.node)) {\n const known = pieceAt.get(pos)\n if (known === undefined) {\n current = await pieceThrough(\n { pos, left },\n piece.pathHandle,\n piece.orientation,\n 'chain',\n )\n other.add(current)\n end = 'landed'\n } else {\n other.add(known)\n end = 'merge'\n }\n } else if (bp > CHAIN_BOUND) {\n end = 'bound'\n } else {\n bp += len\n cursor = { pos, left }\n }\n }\n countWalk('chain', end)\n if (end !== 'landed') {\n return\n }\n }\n }\n\n // With HaplotypeStrays and HaplotypeBinNodes. The haplotype index lists the\n // nodes of each bin of the reference path, and for each bin the stretches of\n // each path whose visits to those nodes the section walks below can miss.\n // The subgraph is checked against the bins the window touches, so every\n // visit of a chosen path to it lies on a section walk or in a stray row,\n // except inside a filled snarl, where the piece through a boundary node runs\n // on into the snarl, and a path that stays inside the snarl has a row.\n const strayRoute = async (strays: HaplotypeStrayOptions) => {\n if (input.context > strays.context) {\n throw new Fallback(\n `the context of ${input.context} bp exceeds the ${strays.context} bp the haplotype index's stray rows cover`,\n )\n }\n const spacing = stats.spacing\n if (spacing === undefined) {\n throw new Fallback('the haplotype index has no anchors')\n }\n const { bin, bound } = strays\n const { fills, inserted } = input.snarls\n if (input.snarls.mode === 'overlapping' && fills.length > 0) {\n throw new Fallback(\n \"the haplotype index's stray rows cover contained snarls only\",\n )\n }\n for (const fill of fills) {\n if (fill.inserted > 0 && fill.low === fill.high) {\n throw new Fallback(\n `the haplotype index's stray rows leave out the snarl bounded by node ${fill.low} at both ends`,\n )\n }\n if (\n fill.inserted > 0 &&\n (strays.snarlNodes === undefined || fill.nodes > strays.snarlNodes)\n ) {\n throw new Fallback(\n strays.snarlNodes === undefined\n ? \"the haplotype index's stray rows leave snarls out\"\n : `a snarl of ${fill.nodes} nodes exceeds the ${strays.snarlNodes} the haplotype index's stray rows cover`,\n )\n }\n }\n const firstBin = Math.floor(input.window.start / bin)\n const lastBin = Math.floor((input.window.end - 1) / bin)\n const lo = firstBin * bin\n const hi = (lastBin + 1) * bin\n\n // Every anchor within `bound` of the bins, and one beyond on each side.\n // The indexer counts a section whose anchor lies exactly `bound` outside\n // the bins as reaching the visits around it, so the anchor past that one\n // must be read too, or the section between them is never planned. An\n // anchor's node can start far before its multiple, so the first read\n // does not settle it. The bins' node lists and stray rows come in the\n // same round trip.\n const anchorOf = new Map<number, HaplotypeAnchorRow>()\n const readAnchors = async (fromK: number, toK: number) => {\n const rows = await db.haplotypeAnchorsBetween(\n input.referenceHandle,\n fromK * spacing,\n toK * spacing,\n )\n for (const row of rows) {\n anchorOf.set(row.anchorOffset / spacing, row)\n }\n }\n let lowest = Math.max(0, Math.floor((lo - bound) / spacing) - 1)\n let highest = Math.ceil((hi + bound) / spacing) + 1\n const [{ listed, strays: found }] = await Promise.all([\n db.haplotypeBinData(input.referenceHandle, firstBin, lastBin),\n readAnchors(lowest, highest),\n ])\n for (const handle of records.keys()) {\n const id = nodeId(handle)\n if (!isReverse(handle) && !listed(id) && !inserted.has(id)) {\n throw new Fallback(\n `the haplotype index lists node ${id} of the subgraph in no bin that the window touches`,\n )\n }\n }\n // The samples on the subgraph's nodes, for the check after the walks,\n // read while the walks run.\n stats.scans = handleRuns([...records.keys()].sort((x, y) => x - y))\n const scanning = Promise.all(\n stats.scans.map(([first, last]) =>\n db.haplotypeSamplesInRange(first, last),\n ),\n )\n scanning.catch(() => undefined)\n while (\n lowest > 0 &&\n (anchorOf.get(lowest)?.pathOffset ?? Number.POSITIVE_INFINITY) >=\n lo - bound\n ) {\n lowest -= 1\n await readAnchors(lowest, lowest)\n }\n while (\n anchorOf.has(highest) &&\n anchorOf.get(highest)!.pathOffset <= hi + bound\n ) {\n highest += 1\n await readAnchors(highest, highest)\n }\n const multiples = [...anchorOf.keys()].sort((x, y) => x - y)\n const own = anchorOf.get(multiples[0] ?? -1)\n if (!own) {\n throw new Fallback('the haplotype index has no anchors on this path')\n }\n const anchorOffset = (k: number) => anchorOf.get(k)!.pathOffset\n // A node that is the anchor of two multiples ends no section.\n const multiplesOf = new Map<number, number[]>()\n for (const k of multiples) {\n const id = nodeId(anchorOf.get(k)!.node)\n multiplesOf.set(id, [...(multiplesOf.get(id) ?? []), k])\n }\n const anchorNodes = [...multiplesOf.keys()]\n const anchorRows = anchorNodes.map(\n id => anchorOf.get(multiplesOf.get(id)![0]!)!.visits,\n )\n if (\n !anchorRows[anchorNodes.indexOf(nodeId(own.node))]!.some(\n row =>\n row.pathHandle === input.referenceHandle &&\n row.orientation === 'forward' &&\n row.pathOffset === own.pathOffset,\n )\n ) {\n throw new Error(\n `The haplotype index has no anchor row for the reference path ${input.referenceHandle} at offset ${own.pathOffset} (node ${nodeId(own.node)}); it does not match this graph`,\n )\n }\n const before = multiples.filter(k => anchorOffset(k) <= input.window.start)\n const after = multiples.filter(k => anchorOffset(k) >= input.window.end)\n stats.anchors = [\n anchorOffset(before[before.length - 1] ?? multiples[0]!),\n anchorOffset(after[0] ?? multiples[multiples.length - 1]!),\n ]\n stats.anchorsRead = multiples.length\n const visits = new Map<\n number,\n { k: number | undefined; row: HaplotypeSample }[]\n >()\n const atAnchors = new Set<number>()\n anchorNodes.forEach((id, i) => {\n const ks = multiplesOf.get(id)!\n const k = ks.length === 1 ? ks[0] : undefined\n for (const row of anchorRows[i]!) {\n atAnchors.add(row.pathHandle)\n if (row.orientation === 'forward' && chosen(row.pathHandle)) {\n visits.set(row.pathHandle, [\n ...(visits.get(row.pathHandle) ?? []),\n { k, row },\n ])\n }\n }\n })\n stats.chosenPaths = [...atAnchors].filter(chosen).length\n if (stats.chosenPaths > keepTuning.mostChosenPaths) {\n throw new Fallback(\n `${stats.chosenPaths} chosen paths pass the anchors, more than ${keepTuning.mostChosenPaths}`,\n )\n }\n\n // A section between visits to adjacent anchors whose span meets the bins\n // is walked whole, `bound` past both visits. One whose span ends up to\n // `bound` outside the bins is walked `bound` to each side of the visit at\n // that end. These are the walks the stray rows count on.\n interface Plan {\n pathHandle: number\n from: HaplotypeSample\n to: HaplotypeSample | undefined\n }\n const plans: Plan[] = []\n let prefetchLo = Number.POSITIVE_INFINITY\n let prefetchHi = 0\n for (const [pathHandle, list] of visits) {\n list.sort((x, y) => x.row.pathOffset - y.row.pathOffset)\n for (let i = 0; i + 1 < list.length; i++) {\n const from = list[i]!\n const to = list[i + 1]!\n if (\n from.k === undefined ||\n to.k === undefined ||\n Math.abs(from.k - to.k) !== 1\n ) {\n continue\n }\n const [low, high] =\n anchorOffset(from.k) <= anchorOffset(to.k) ? [from, to] : [to, from]\n const a = anchorOffset(low.k!)\n const b = anchorOffset(high.k!)\n if (a < hi && b >= lo) {\n plans.push({ pathHandle, from: from.row, to: to.row })\n prefetchLo = Math.min(prefetchLo, a - bound)\n prefetchHi = Math.max(prefetchHi, b + bound)\n } else if (a >= hi && a - hi <= bound) {\n plans.push({ pathHandle, from: low.row, to: undefined })\n prefetchLo = Math.min(prefetchLo, a - bound)\n prefetchHi = Math.max(prefetchHi, a + bound)\n } else if (b < lo && lo - b <= bound) {\n plans.push({ pathHandle, from: high.row, to: undefined })\n prefetchLo = Math.min(prefetchLo, b - bound)\n prefetchHi = Math.max(prefetchHi, b + bound)\n }\n }\n }\n const filled = new Set(fills.map(fill => `${fill.low}:${fill.high}`))\n const rows = found\n .filter(\n row =>\n chosen(row.pathHandle) &&\n (row.snarl === undefined ||\n filled.has(`${row.snarl[0]}:${row.snarl[1]}`)),\n )\n .sort((x, y) => x.pathHandle - y.pathHandle || x.pathStart - y.pathStart)\n stats.strays = {\n bins: lastBin - firstBin + 1,\n rows: found.length,\n walked: 0,\n outsideBp: 0,\n }\n if (prefetchHi > 0) {\n await input.prefetchReferenceRange(\n input.referenceHandle,\n Math.max(0, prefetchLo),\n prefetchHi + 1,\n )\n }\n stats.ms.scan = lap()\n\n // A cap on each walk's bases outside the subgraph.\n const cap = 8 * spacing + 2 * (input.window.end - input.window.start)\n const counted = stats.strays\n let walkBp = 0\n const outside = (len: number) => {\n counted.outsideBp += len\n walkBp += len\n if (walkBp > cap) {\n throw new Fallback(\n `a walk of a chosen path near the window went past its cap of ${cap} bp`,\n )\n }\n }\n // The stretches of each path that walks passed: every node that starts in\n // [x, y). A visit is named by its node's start, so one at `to` is covered\n // when the stretch ends past it.\n const walkedRanges = new Map<number, [number, number][]>()\n const covered = (pathHandle: number, from: number, to: number) =>\n (walkedRanges.get(pathHandle) ?? []).some(([x, y]) => x <= from && to < y)\n const markWalked = (pathHandle: number, from: number, to: number) => {\n walkedRanges.set(pathHandle, [\n ...(walkedRanges.get(pathHandle) ?? []),\n [from, to],\n ])\n }\n // Forward along a path from a position through every node that starts at\n // or before `until`, jumping over the pieces it lands in; returns the\n // offset it reached.\n const walkForward = async (\n pathHandle: number,\n start: Pos,\n startLeft: number,\n until: number,\n source: ChosenPieceSource,\n ) => {\n let pos: Pos | undefined = start\n let left = startLeft\n let reached = left\n while (pos && left <= until) {\n signal?.throwIfAborted()\n let len: number\n if (records.has(pos.node)) {\n const piece = await pieceAtOrThrough(\n { pos, left },\n pathHandle,\n 'forward',\n source,\n )\n const last = lastCursor(piece)\n pos = last.pos\n left = last.left\n len = lengthIn(pos.node)\n reached = Math.max(reached, piece.hapEnd)\n } else {\n len = (await record(pos.node)).sequenceLen\n outside(len)\n reached = Math.max(reached, left + len)\n }\n pos = await next(pos)\n left += len\n }\n return reached\n }\n // Backward from a position through every node that ends after `until`;\n // returns the offset reached.\n const walkBackward = async (\n pathHandle: number,\n start: Pos,\n startLeft: number,\n until: number,\n ) => {\n let cursor: Cursor = { pos: start, left: startLeft }\n let reached = startLeft\n while (cursor.left > until) {\n signal?.throwIfAborted()\n const earlier = await previous(cursor.pos)\n if (!earlier) {\n break\n }\n const len = (await record(earlier.node)).sequenceLen\n const earlierLeft = cursor.left - len\n if (records.has(earlier.node)) {\n const piece = await pieceAtOrThrough(\n { pos: earlier, left: earlierLeft },\n pathHandle,\n 'forward',\n 'section',\n )\n cursor = firstCursor(piece)\n reached = Math.min(reached, piece.hapStart)\n } else {\n outside(len)\n cursor = { pos: earlier, left: earlierLeft }\n reached = Math.min(reached, earlierLeft)\n }\n }\n return reached\n }\n\n for (const { pathHandle, from, to } of plans) {\n const start = from.pathOffset\n const stop = (to ?? from).pathOffset + bound\n if (covered(pathHandle, start - bound, stop)) {\n continue\n }\n const pos = { node: from.node, offset: from.offset }\n walkBp = 0\n const reachedEnd = await walkForward(\n pathHandle,\n pos,\n start,\n stop,\n 'section',\n )\n walkBp = 0\n const reachedStart = await walkBackward(\n pathHandle,\n pos,\n start,\n start - bound,\n )\n markWalked(\n pathHandle,\n Math.min(reachedStart, start - bound),\n Math.max(reachedEnd, stop + 1),\n )\n countWalk(to ? 'section' : 'visit', to ? 'past the far anchor' : 'bound')\n }\n for (const row of rows) {\n if (covered(row.pathHandle, row.pathStart, row.pathEnd)) {\n continue\n }\n walkBp = 0\n const reachedEnd = await walkForward(\n row.pathHandle,\n { node: row.node, offset: row.offset },\n row.pathStart,\n row.pathEnd,\n 'stray',\n )\n markWalked(\n row.pathHandle,\n row.pathStart,\n Math.max(reachedEnd, row.pathEnd + 1),\n )\n counted.walked += 1\n }\n stats.ms.walks = lap()\n\n // A sample of a chosen path on the subgraph's nodes outside every piece\n // would contradict the haplotype index's rows. A sample of the reverse\n // orientation gives a position of the piece's twin.\n const reversed: HaplotypeSample[] = []\n for (const samples of await scanning) {\n for (const sample of samples) {\n stats.scanRows += 1\n if (records.has(sample.node) && chosen(sample.pathHandle)) {\n if (\n !(piecesOfPath.get(sample.pathHandle) ?? []).some(id => {\n const piece = pieces[id]!\n return (\n piece.hapStart <= sample.pathOffset &&\n sample.pathOffset < piece.hapEnd\n )\n })\n ) {\n throw new Fallback(\n `chosen path ${sample.pathHandle} has a sample at ${sample.pathOffset} on the window's nodes that no walk reached`,\n )\n }\n if (sample.orientation === 'reverse') {\n reversed.push(sample)\n }\n }\n }\n }\n for (const sample of reversed) {\n await pieceAtOrThrough(\n {\n pos: { node: sample.node, offset: sample.offset },\n left: sample.pathOffset,\n },\n sample.pathHandle,\n 'reverse',\n 'twin',\n )\n }\n stats.ms.check = lap()\n }\n\n const canonicalTwins = async () => {\n // Canonical twins: a piece found only in the orientation extractPaths\n // drops, or in one of two orientations it keeps, is walked on in that\n // orientation while the samples of the other orientation at each node are\n // read by coordinate. A matching sample gives a position of the other\n // orientation, which is walked forward into the subgraph.\n const orientationsOf = new Map<string, Set<Orientation>>()\n const note = (piece: ChosenPiece) => {\n const key = pieceKey(piece)\n const seen = orientationsOf.get(key)\n if (seen) {\n seen.add(piece.orientation)\n } else {\n orientationsOf.set(key, new Set([piece.orientation]))\n }\n }\n let noted = 0\n const noteNew = () => {\n for (; noted < pieces.length; noted++) {\n note(pieces[noted]!)\n }\n }\n noteNew()\n const hasTwin = (piece: ChosenPiece) =>\n (orientationsOf.get(pieceKey(piece))?.size ?? 0) > 1\n const twinBound = 2 * interval\n // extractPaths keeps the reference walk in either orientation, and its\n // twin like any other walk, which matters when the reference is chosen.\n const needsTwin = (piece: ChosenPiece, id: number) =>\n id === referenceId\n ? chosen(input.referenceHandle) && twinIsCanonical(piece)\n : !piece.canonical || twinIsCanonical(piece)\n for (let id = 0; id < pieces.length; id++) {\n const piece = pieces[id]!\n if (hasTwin(piece) || !needsTwin(piece, id)) {\n continue\n }\n stats.twins.tried += 1\n const other: Orientation =\n piece.orientation === 'forward' ? 'reverse' : 'forward'\n let cursor = lastCursor(piece)\n let walkedBp = 0\n let hit: HaplotypeSample | undefined\n while (!hit && walkedBp <= twinBound) {\n signal?.throwIfAborted()\n const pos = await next(cursor.pos)\n if (!pos) {\n break\n }\n const len = (await record(pos.node)).sequenceLen\n const left = forwardLeft(\n piece.orientation,\n cursor.left,\n (await record(cursor.pos.node)).sequenceLen,\n len,\n )\n const flipped = flipNode(pos.node)\n hit = (await db.haplotypeSamplesInRange(flipped, flipped)).find(\n s =>\n s.pathHandle === piece.pathHandle &&\n s.orientation === other &&\n s.pathOffset === left,\n )\n walkedBp += len\n cursor = { pos, left }\n }\n let walk: Cursor | undefined = hit && {\n pos: { node: hit.node, offset: hit.offset },\n left: hit.pathOffset,\n }\n let toPiece = 0\n while (walk && !hasTwin(piece) && toPiece <= twinBound + piece.len) {\n signal?.throwIfAborted()\n if (records.has(walk.pos.node)) {\n const landed = await pieceAtOrThrough(\n walk,\n piece.pathHandle,\n other,\n 'twin',\n )\n const landedId = pieces.indexOf(landed)\n await chain(landedId, true)\n await chain(landedId, false)\n noteNew()\n walk = lastCursor(landed)\n }\n if (!hasTwin(piece)) {\n const len: number = (await record(walk.pos.node)).sequenceLen\n toPiece += len\n const pos = await next(walk.pos)\n walk = pos\n ? {\n pos,\n left: forwardLeft(\n other,\n walk.left,\n len,\n (await record(pos.node)).sequenceLen,\n ),\n }\n : undefined\n }\n }\n noteNew()\n if (!hasTwin(piece)) {\n throw new Fallback(\n `piece ${pieceKey(piece)} was found in one orientation where extractPaths keeps the other`,\n )\n }\n stats.twins.found += 1\n }\n stats.ms.twins = lap()\n }\n\n try {\n const strays = await db.haplotypeStrayOptions()\n if (strays === undefined) {\n throw new Fallback(\n 'the haplotype index has no stray rows; gbz-haplotype-index 0.2.0 writes them',\n )\n }\n await strayRoute(strays)\n await canonicalTwins()\n } catch (error) {\n if (!(error instanceof Fallback)) {\n throw error\n }\n stats.fallback = error.message\n }\n return result()\n}\n\n// extractPaths's order, which is upstream's: by the walk's start position,\n// handle then offset.\nexport function extractionOrder(a: ChosenPiece, b: ChosenPiece) {\n return a.handles[0]! - b.handles[0]! || a.offsets[0]! - b.offsets[0]!\n}\n", "type Weight = (x: number) => number\n\nfunction lowerBound(ascending: number[], value: number) {\n let lo = 0\n let hi = ascending.length\n while (lo < hi) {\n const mid = (lo + hi) >> 1\n if (ascending[mid]! < value) {\n lo = mid + 1\n } else {\n hi = mid\n }\n }\n return lo\n}\n\nclass ColumnMax {\n readonly ending: Float64Array\n private readonly tree: Int32Array\n\n constructor(columns: number) {\n this.ending = new Float64Array(columns)\n this.tree = new Int32Array(columns + 1).fill(-1)\n }\n\n bestBefore(column: number) {\n let best = -1\n for (let p = column; p > 0; p -= p & -p) {\n const candidate = this.tree[p]!\n if (\n candidate !== -1 &&\n (best === -1 || this.ending[candidate]! > this.ending[best]!)\n ) {\n best = candidate\n }\n }\n return best\n }\n\n raise(column: number, value: number) {\n this.ending[column] = value\n for (let p = column + 1; p < this.tree.length; p += p & -p) {\n const holder = this.tree[p]!\n if (holder === -1 || value > this.ending[holder]!) {\n this.tree[p] = column\n }\n }\n }\n}\n\ninterface Trace {\n row: Int32Array\n column: Int32Array\n previous: Int32Array\n endingMatch: Int32Array\n count: number\n}\n\nclass SparseLcs {\n readonly pairs: [number, number][] = []\n total = 0\n private readonly a: number[]\n private readonly b: number[]\n private readonly weight: Weight\n private readonly occurrences = new Map<number, number[]>()\n\n constructor(a: number[], b: number[], weight: Weight) {\n this.a = a\n this.b = b\n this.weight = weight\n b.forEach((x, j) => {\n const list = this.occurrences.get(x)\n if (list) {\n list.push(j)\n } else {\n this.occurrences.set(x, [j])\n }\n })\n }\n\n solve(a0: number, a1: number, b0: number, b1: number) {\n let prefix = 0\n while (\n a0 + prefix < a1 &&\n b0 + prefix < b1 &&\n this.a[a0 + prefix] === this.b[b0 + prefix]\n ) {\n this.match(a0 + prefix, b0 + prefix)\n prefix += 1\n }\n let suffix = 0\n while (\n a1 - suffix > a0 + prefix &&\n b1 - suffix > b0 + prefix &&\n this.a[a1 - suffix - 1] === this.b[b1 - suffix - 1]\n ) {\n suffix += 1\n }\n this.solveMiddle(a0 + prefix, a1 - suffix, b0 + prefix, b1 - suffix)\n for (let k = suffix; k > 0; k--) {\n this.match(a1 - k, b1 - k)\n }\n }\n\n private match(i: number, j: number) {\n this.pairs.push([i, j])\n this.total += this.weight(this.a[i]!)\n }\n\n private solveMiddle(a0: number, a1: number, b0: number, b1: number) {\n if (a0 === a1 || b0 === b1) {\n return\n }\n const matches = this.matchCount(a0, a1, b0, b1)\n if (matches === 0) {\n return\n }\n if (matches <= a1 - a0 + (b1 - b0)) {\n this.chain(a0, a1, b0, b1, matches)\n return\n }\n const mid = (a0 + a1) >> 1\n const split = this.split(a0, mid, a1, b0, b1)\n this.solve(a0, mid, b0, split)\n this.solve(mid, a1, split, b1)\n }\n\n private matchCount(a0: number, a1: number, b0: number, b1: number) {\n let count = 0\n for (let i = a0; i < a1; i++) {\n const list = this.occurrences.get(this.a[i]!)\n if (list) {\n count += lowerBound(list, b1) - lowerBound(list, b0)\n }\n }\n return count\n }\n\n private sweep(\n from: number,\n to: number,\n step: 1 | -1,\n b0: number,\n b1: number,\n columns: ColumnMax,\n trace?: Trace,\n ) {\n for (let i = from; i !== to; i += step) {\n const list = this.occurrences.get(this.a[i]!)\n if (!list) {\n continue\n }\n const w = this.weight(this.a[i]!)\n const lo = lowerBound(list, b0)\n const hi = lowerBound(list, b1)\n for (let k = 0; k < hi - lo; k++) {\n const column =\n step === 1 ? list[hi - 1 - k]! - b0 : b1 - 1 - list[lo + k]!\n const before = columns.bestBefore(column)\n const value = (before === -1 ? 0 : columns.ending[before]!) + w\n if (value > columns.ending[column]!) {\n columns.raise(column, value)\n if (trace) {\n const match = trace.count++\n trace.row[match] = i\n trace.column[match] = column\n trace.previous[match] =\n before === -1 ? -1 : trace.endingMatch[before]!\n trace.endingMatch[column] = match\n }\n }\n }\n }\n }\n\n private chain(\n a0: number,\n a1: number,\n b0: number,\n b1: number,\n matches: number,\n ) {\n const columns = new ColumnMax(b1 - b0)\n const trace: Trace = {\n row: new Int32Array(matches),\n column: new Int32Array(matches),\n previous: new Int32Array(matches),\n endingMatch: new Int32Array(b1 - b0),\n count: 0,\n }\n this.sweep(a0, a1, 1, b0, b1, columns, trace)\n const last = columns.bestBefore(b1 - b0)\n if (last === -1) {\n return\n }\n this.total += columns.ending[last]!\n const chained: [number, number][] = []\n for (\n let match = trace.endingMatch[last]!;\n match !== -1;\n match = trace.previous[match]!\n ) {\n chained.push([trace.row[match]!, b0 + trace.column[match]!])\n }\n for (let k = chained.length - 1; k >= 0; k--) {\n this.pairs.push(chained[k]!)\n }\n }\n\n private frontier(\n from: number,\n to: number,\n step: 1 | -1,\n b0: number,\n b1: number,\n ) {\n const columns = new ColumnMax(b1 - b0)\n this.sweep(from, to, step, b0, b1, columns)\n const best = new Float64Array(b1 - b0 + 1)\n for (let column = 0; column < b1 - b0; column++) {\n best[column + 1] = Math.max(best[column]!, columns.ending[column]!)\n }\n return best\n }\n\n private split(a0: number, mid: number, a1: number, b0: number, b1: number) {\n const width = b1 - b0\n const before = this.frontier(a0, mid, 1, b0, b1)\n const after = this.frontier(a1 - 1, mid - 1, -1, b0, b1)\n let split = 0\n let best = -1\n for (let s = 0; s <= width; s++) {\n const combined = before[s]! + after[width - s]!\n if (combined > best) {\n best = combined\n split = s\n }\n }\n return b0 + split\n }\n}\n\nexport function weightedLcs(\n a: number[],\n b: number[],\n weight: Weight,\n): [pairs: [number, number][], weight: number] {\n const lcs = new SparseLcs(a, b, weight)\n lcs.solve(0, a.length, 0, b.length)\n return [lcs.pairs, lcs.total]\n}\n", "import { isReverse, nodeId } from './gbwt/node.ts'\nimport { reverseComplement } from './gbwt/sequence.ts'\n\nexport type PairOp = '=' | 'X' | 'I' | 'D'\nexport type PairEdit = [PairOp, number]\n\nexport interface PairChain {\n queryStart: number\n queryEnd: number\n targetStart: number\n targetEnd: number\n strand: '+' | '-'\n edits: PairEdit[]\n // bases on nodes both walks visit; the other `=` came from comparing bases\n sharedBases: number\n}\n\nexport interface PairOptions {\n query: number[]\n target: number[]\n sequenceOf: (id: number) => string\n maxGap?: number | undefined\n minMatch?: number | undefined\n bases?: boolean | undefined\n}\n\n// An exact match: query [qs, qe) against target [ts, te), the target read\n// backwards when flipped.\ninterface Run {\n qs: number\n qe: number\n ts: number\n te: number\n flipped: boolean\n}\n\nconst DEFAULT_MIN_MATCH = 100\nconst MAX_ALIGNED_CELLS = 4_000_000\nconst CHAIN_LOOKBACK = 5000\nconst KMER = 15\nconst MAX_KMER_OCCURRENCES = 64\n// each level's gaps lie strictly inside the last, so this only bounds the work\nconst MAX_FILL_DEPTH = 8\n\n// vg's scoring, the model the reference CIGARs in subgraph.ts are scored by\nconst MATCH = 1\nconst MISMATCH = -4\nconst GAP_OPEN = -6\nconst GAP_EXTEND = -1\nconst UNREACHABLE = -(2 ** 30)\n\nconst DIAGONAL = 0\nconst INSERTION = 1\nconst DELETION = 2\n\nfunction appendEdit(edits: PairEdit[], op: PairOp, len: number) {\n const last = edits.at(-1)\n if (len > 0) {\n if (last?.[0] === op) {\n last[1] += len\n } else {\n edits.push([op, len])\n }\n }\n}\n\nfunction best(diagonal: number, insertion: number, deletion: number) {\n return diagonal >= deletion && diagonal >= insertion\n ? DIAGONAL\n : deletion >= insertion\n ? DELETION\n : INSERTION\n}\n\n// The highest-scoring global alignment of a on b under affine gaps. Each cell\n// of `trace` packs, two bits apiece, the state each of the three states came\n// from. A tie goes to the diagonal, then to the deletion, so two stretches\n// with nothing in common read as an insertion followed by a deletion.\nfunction affineAlignment(a: string, b: string, edits: PairEdit[]) {\n const la = a.length\n const lb = b.length\n const width = lb + 1\n const trace = new Uint8Array((la + 1) * width)\n let diagonal = new Int32Array(width).fill(UNREACHABLE)\n let insertion = new Int32Array(width).fill(UNREACHABLE)\n let deletion = new Int32Array(width).fill(UNREACHABLE)\n diagonal[0] = 0\n for (let j = 1; j <= lb; j++) {\n deletion[j] = GAP_OPEN + (j - 1) * GAP_EXTEND\n trace[j] = (j === 1 ? DIAGONAL : DELETION) << 4\n }\n for (let i = 1; i <= la; i++) {\n const nextDiagonal = new Int32Array(width).fill(UNREACHABLE)\n const nextInsertion = new Int32Array(width).fill(UNREACHABLE)\n const nextDeletion = new Int32Array(width).fill(UNREACHABLE)\n nextInsertion[0] = GAP_OPEN + (i - 1) * GAP_EXTEND\n trace[i * width] = (i === 1 ? DIAGONAL : INSERTION) << 2\n const ai = a.charCodeAt(i - 1)\n for (let j = 1; j <= lb; j++) {\n const fromDiagonal = best(\n diagonal[j - 1]!,\n insertion[j - 1]!,\n deletion[j - 1]!,\n )\n nextDiagonal[j] =\n Math.max(diagonal[j - 1]!, insertion[j - 1]!, deletion[j - 1]!) +\n (ai === b.charCodeAt(j - 1) ? MATCH : MISMATCH)\n const fromInsertion = best(\n diagonal[j]! + GAP_OPEN,\n insertion[j]! + GAP_EXTEND,\n deletion[j]! + GAP_OPEN,\n )\n nextInsertion[j] = Math.max(\n diagonal[j]! + GAP_OPEN,\n insertion[j]! + GAP_EXTEND,\n deletion[j]! + GAP_OPEN,\n )\n const fromDeletion = best(\n nextDiagonal[j - 1]! + GAP_OPEN,\n nextInsertion[j - 1]! + GAP_OPEN,\n nextDeletion[j - 1]! + GAP_EXTEND,\n )\n nextDeletion[j] = Math.max(\n nextDiagonal[j - 1]! + GAP_OPEN,\n nextInsertion[j - 1]! + GAP_OPEN,\n nextDeletion[j - 1]! + GAP_EXTEND,\n )\n trace[i * width + j] =\n fromDiagonal | (fromInsertion << 2) | (fromDeletion << 4)\n }\n diagonal = nextDiagonal\n insertion = nextInsertion\n deletion = nextDeletion\n }\n const ops: PairOp[] = []\n let i = la\n let j = lb\n let state = best(diagonal[lb]!, insertion[lb]!, deletion[lb]!)\n while (i > 0 || j > 0) {\n const from = (trace[i * width + j]! >> (2 * state)) & 3\n if (state === DIAGONAL) {\n ops.push(a[i - 1] === b[j - 1] ? '=' : 'X')\n i -= 1\n j -= 1\n } else if (state === INSERTION) {\n ops.push('I')\n i -= 1\n } else {\n ops.push('D')\n j -= 1\n }\n state = from\n }\n for (const op of ops.reverse()) {\n appendEdit(edits, op, 1)\n }\n}\n\n// What a chain of walk steps pays to go from one run to the next over dq\n// private query bases and dt target ones. Those runs lie outside both walks'\n// repeats, so each has one place to go and the cost only has to let a chain\n// hold through a structural variant of any size: vg's charge for a short\n// indel, growing with the logarithm past it.\nfunction stepJumpCost(dq: number, dt: number) {\n const indel = Math.abs(dq - dt)\n const indelCost =\n indel === 0\n ? 0\n : Math.min(\n -GAP_OPEN - (indel - 1) * GAP_EXTEND,\n -GAP_OPEN + 10 * Math.log2(indel),\n )\n return indelCost + (Math.min(dq, dt) > 0 ? -MISMATCH : 0)\n}\n\n// What a chain of k-mer matches pays, which is minimap2's gap cost. Inside a\n// tandem array every copy offers a match, and the term that grows with the\n// indel is what keeps a chain in one register instead of hopping between\n// copies for a slightly longer match.\nfunction kmerJumpCost(dq: number, dt: number) {\n const indel = Math.abs(dq - dt)\n return indel === 0 ? 0 : 0.01 * KMER * indel + 0.5 * Math.log2(indel)\n}\n\ntype JumpCost = (dq: number, dt: number) => number\n\ninterface Link {\n run: Run\n trim: number\n}\n\ntype Interval = [number, number]\n\n// The stretch of a run from offset `from` to `to` along it\nfunction sliceRun(run: Run, from: number, to: number): Run {\n return {\n qs: run.qs + from,\n qe: run.qs + to,\n ts: run.flipped ? run.te - to : run.ts + from,\n te: run.flipped ? run.te - from : run.ts + to,\n flipped: run.flipped,\n }\n}\n\n// What is left of a run once taken bases are cut out of it, as the pieces a\n// k-mer long or more. An exact match divides at any base, so a flank that runs\n// one base into an inversion by chance costs the inversion one base, not all\n// of it.\nfunction untakenPieces(run: Run, query: Interval[], target: Interval[]) {\n const len = run.qe - run.qs\n const blocked: Interval[] = []\n for (const [s, e] of query) {\n const lo = Math.max(0, s - run.qs)\n const hi = Math.min(len, e - run.qs)\n if (lo < hi) {\n blocked.push([lo, hi])\n }\n }\n for (const [s, e] of target) {\n const lo = Math.max(0, run.flipped ? run.te - e : s - run.ts)\n const hi = Math.min(len, run.flipped ? run.te - s : e - run.ts)\n if (lo < hi) {\n blocked.push([lo, hi])\n }\n }\n if (blocked.length === 0) {\n return [run]\n }\n blocked.sort((x, y) => x[0] - y[0])\n const pieces: Run[] = []\n let from = 0\n for (const [lo, hi] of blocked) {\n if (lo - from >= KMER) {\n pieces.push(sliceRun(run, from, lo))\n }\n from = Math.max(from, hi)\n }\n if (len - from >= KMER) {\n pieces.push(sliceRun(run, from, len))\n }\n return pieces\n}\n\n// The best-scoring collinear chain of runs matching minMatch bases or more,\n// then the best over the runs that overlap no accepted run on either sequence,\n// and so on: a second copy of a repeat finds its target taken and an inversion\n// finds its target free. A run that overlaps its predecessor is trimmed from\n// the front, which an exact match allows at any base.\nfunction chainRuns(\n runs: Run[],\n maxGap: number,\n minMatch: number,\n jumpCost: JumpCost,\n maxChains = Infinity,\n) {\n const chains: Link[][] = []\n const basesTaken = { query: [] as Interval[], target: [] as Interval[] }\n const spanTaken = {\n forward: { query: [] as Interval[], target: [] as Interval[] },\n flipped: { query: [] as Interval[], target: [] as Interval[] },\n }\n let pool = [...runs].sort((a, b) => a.qs - b.qs || a.ts - b.ts)\n while (pool.length > 0 && chains.length < maxChains) {\n const score = pool.map(run => run.qe - run.qs)\n const back = new Int32Array(pool.length).fill(-1)\n const trims = new Int32Array(pool.length)\n for (let j = 0; j < pool.length; j++) {\n const b = pool[j]!\n const len = b.qe - b.qs\n for (let i = j - 1; i >= Math.max(0, j - CHAIN_LOOKBACK); i--) {\n if (score[i]! + len <= score[j]!) {\n continue\n }\n const a = pool[i]!\n const advances =\n a.flipped === b.flipped &&\n a.qs < b.qs &&\n (b.flipped ? b.te < a.te : a.ts < b.ts)\n if (advances) {\n const trim = Math.max(\n 0,\n a.qe - b.qs,\n b.flipped ? b.te - a.ts : a.te - b.ts,\n )\n const dq = b.qs + trim - a.qe\n const dt = b.flipped ? a.ts - (b.te - trim) : b.ts + trim - a.te\n if (trim < len && dq <= maxGap && dt <= maxGap) {\n const candidate = score[i]! + len - trim - jumpCost(dq, dt)\n if (candidate > score[j]!) {\n score[j] = candidate\n back[j] = i\n trims[j] = trim\n }\n }\n }\n }\n }\n const matched = new Int32Array(pool.length)\n let end = -1\n for (let j = 0; j < pool.length; j++) {\n const run = pool[j]!\n matched[j] = (matched[back[j]!] ?? 0) + run.qe - run.qs - trims[j]!\n if (matched[j]! >= minMatch && (end < 0 || score[j]! > score[end]!)) {\n end = j\n }\n }\n if (end < 0) {\n break\n }\n const chain: Link[] = []\n for (let j = end; j >= 0; j = back[j]!) {\n chain.push({ run: pool[j]!, trim: trims[j]! })\n }\n chain.reverse()\n chains.push(chain)\n // A record's CIGAR accounts for every base between its ends in its own\n // orientation, so a later chain of that orientation may not nest in its\n // gaps: taking only the runs let one re-claim an earlier record's bases on\n // a paralog. An inversion is what a forward CIGAR cannot account for, so\n // across orientations only the bases themselves are taken.\n const first = chain[0]!\n const last = chain.at(-1)!\n const { flipped } = first.run\n const spans = flipped ? spanTaken.flipped : spanTaken.forward\n spans.query.push([first.run.qs + first.trim, last.run.qe])\n spans.target.push(\n flipped\n ? [last.run.ts, first.run.te - first.trim]\n : [first.run.ts + first.trim, last.run.te],\n )\n for (const { run, trim } of chain) {\n basesTaken.query.push([run.qs + trim, run.qe])\n basesTaken.target.push(\n run.flipped ? [run.ts, run.te - trim] : [run.ts + trim, run.te],\n )\n }\n pool = pool\n .flatMap(run => {\n const same = run.flipped ? spanTaken.flipped : spanTaken.forward\n return untakenPieces(\n run,\n [...basesTaken.query, ...same.query],\n [...basesTaken.target, ...same.target],\n )\n })\n .sort((x, y) => x.qs - y.qs || x.ts - y.ts)\n }\n return chains\n}\n\n// Exact matches of KMER bases or more between a and b, as runs along a\n// diagonal. A k-mer the target holds many times over seeds nothing.\nfunction forwardKmerRuns(a: string, b: string) {\n const index = new Map<string, number[]>()\n for (let p = 0; p + KMER <= b.length; p++) {\n const kmer = b.slice(p, p + KMER)\n const seen = index.get(kmer)\n if (seen) {\n seen.push(p)\n } else {\n index.set(kmer, [p])\n }\n }\n const runs: Run[] = []\n const open = new Map<number, Run>()\n for (let i = 0; i + KMER <= a.length; i++) {\n const hits = index.get(a.slice(i, i + KMER))\n if (hits && hits.length <= MAX_KMER_OCCURRENCES) {\n for (const p of hits) {\n const diagonal = p - i\n const run = open.get(diagonal)\n if (run && i <= run.qe) {\n run.qe = i + KMER\n run.te = p + KMER\n } else {\n const started = {\n qs: i,\n qe: i + KMER,\n ts: p,\n te: p + KMER,\n flipped: false,\n }\n open.set(diagonal, started)\n runs.push(started)\n }\n }\n }\n }\n return runs\n}\n\nfunction kmerRuns(a: string, b: string) {\n return [\n ...forwardKmerRuns(a, b),\n ...forwardKmerRuns(a, reverseComplement(b)).map(run => ({\n ...run,\n ts: b.length - run.te,\n te: b.length - run.ts,\n flipped: true,\n })),\n ]\n}\n\ntype GapFill = (\n a: string,\n b: string,\n edits: PairEdit[],\n queryFrom: number,\n targetFrom: number,\n) => void\n\n// The edits of one chain: each run is a run of `=`, and what lies between two\n// runs goes to `between`. Edits read along the query; the caller reverses a\n// flipped chain's so they read along the target.\nfunction chainEdits(\n chain: Link[],\n a: string,\n b: string,\n edits: PairEdit[],\n between: GapFill,\n) {\n let previous: Run | undefined\n for (const { run, trim } of chain) {\n const qs = run.qs + trim\n if (previous) {\n const targetFrom = run.flipped ? run.te - trim : previous.te\n const targetTo = run.flipped ? previous.ts : run.ts + trim\n const target = b.slice(targetFrom, targetTo)\n between(\n a.slice(previous.qe, qs),\n run.flipped ? reverseComplement(target) : target,\n edits,\n previous.qe,\n targetFrom,\n )\n }\n appendEdit(edits, '=', run.qe - qs)\n previous = run\n }\n}\n\n// An insertion and a deletion, which claims no homology\nfunction unaligned(a: string, b: string, edits: PairEdit[]) {\n appendEdit(edits, 'I', a.length)\n appendEdit(edits, 'D', b.length)\n}\n\nfunction alignExact(a: string, b: string, edits: PairEdit[]) {\n if (a.length * b.length <= MAX_ALIGNED_CELLS) {\n affineAlignment(a, b, edits)\n } else {\n unaligned(a, b, edits)\n }\n}\n\n// The private bases between two runs of one chain, whose orientation the chain\n// has already fixed. Past the cell budget they are seeded on forward k-mers and\n// chained again, recursing into the gaps that chain leaves. It finds no\n// inversions, since the stretch has an orientation already.\nfunction fillGap(a: string, b: string, edits: PairEdit[], depth = 0) {\n const [chain] =\n a.length * b.length > MAX_ALIGNED_CELLS && depth < MAX_FILL_DEPTH\n ? chainRuns(forwardKmerRuns(a, b), Infinity, KMER, kmerJumpCost, 1)\n : []\n if (!chain) {\n alignExact(a, b, edits)\n return\n }\n const deeper = (qa: string, tb: string, into: PairEdit[]) => {\n fillGap(qa, tb, into, depth + 1)\n }\n const first = chain[0]!.run\n const last = chain.at(-1)!.run\n deeper(a.slice(0, first.qs), b.slice(0, first.ts), edits)\n chainEdits(chain, a, b, edits, deeper)\n deeper(a.slice(last.qe), b.slice(last.te), edits)\n}\n\nfunction fill(a: string, b: string, edits: PairEdit[]) {\n fillGap(a, b, edits)\n}\n\n// A chain as a record in the coordinates of the two strings it was made on\nfunction recordOf(chain: Link[], a: string, b: string): PairChain {\n const edits: PairEdit[] = []\n chainEdits(chain, a, b, edits, fill)\n const first = chain[0]!\n const last = chain.at(-1)!\n const { flipped } = first.run\n return {\n queryStart: first.run.qs + first.trim,\n queryEnd: last.run.qe,\n targetStart: flipped ? last.run.ts : first.run.ts + first.trim,\n targetEnd: flipped ? first.run.te - first.trim : last.run.te,\n strand: flipped ? '-' : '+',\n edits: flipped ? edits.reverse() : edits,\n sharedBases: 0,\n }\n}\n\n// The private bases between two shared nodes. A pair too large for the exact\n// alignment is seeded on shared k-mers in both orientations and chained the\n// way the walks are, which aligns two long copies of one sequence the graph\n// left apart. The best forward chain becomes edits. A flipped chain is an\n// inversion, which no CIGAR holds, so it comes back as a record of its own in\n// the coordinates of a and b. What no chain reaches is an insertion and a\n// deletion, which claims no homology.\nfunction alignPrivate(\n a: string,\n b: string,\n edits: PairEdit[],\n minMatch: number,\n): PairChain[] {\n let inversions: PairChain[] = []\n if (a.length * b.length <= MAX_ALIGNED_CELLS) {\n affineAlignment(a, b, edits)\n } else {\n const chains = chainRuns(\n kmerRuns(a, b),\n Infinity,\n Math.max(minMatch, KMER),\n kmerJumpCost,\n )\n const forward = chains.find(chain => !chain[0]!.run.flipped)\n inversions = chains\n .filter(chain => chain[0]!.run.flipped)\n .map(chain => recordOf(chain, a, b))\n if (forward) {\n // The forward record holds no inversion, so an inversion's bases stay\n // unaligned in it. A gap that hides one is not seeded again: at a tandem\n // array that finds only a neighbouring copy, matched forward over bases\n // the inversion's own record already claims.\n const forwardFill: GapFill = (qa, tb, into, queryFrom, targetFrom) => {\n const hidesInversion = inversions.some(\n inversion =>\n (queryFrom < inversion.queryEnd &&\n inversion.queryStart < queryFrom + qa.length) ||\n (targetFrom < inversion.targetEnd &&\n inversion.targetStart < targetFrom + tb.length),\n )\n if (hidesInversion) {\n alignExact(qa, tb, into)\n } else {\n fillGap(qa, tb, into)\n }\n }\n const first = forward[0]!.run\n const last = forward.at(-1)!.run\n forwardFill(a.slice(0, first.qs), b.slice(0, first.ts), edits, 0, 0)\n chainEdits(forward, a, b, edits, forwardFill)\n forwardFill(a.slice(last.qe), b.slice(last.te), edits, last.qe, last.te)\n } else {\n unaligned(a, b, edits)\n }\n }\n return inversions\n}\n\ninterface Claimed extends PairChain {\n // query stretches on nodes both walks visit\n shared: Interval[]\n}\n\ntype Side = 'query' | 'target'\n\n// Each edit of a record with the query and target position it sits at. A `-`\n// record's edits read along the target, so its query runs down from queryEnd.\nfunction forEachEdit(\n r: PairChain,\n visit: (op: PairOp, len: number, query: number, target: number) => void,\n) {\n const flipped = r.strand === '-'\n let qi = 0\n let ti = 0\n for (const [op, len] of r.edits) {\n visit(\n op,\n len,\n flipped ? r.queryEnd - 1 - qi : r.queryStart + qi,\n r.targetStart + ti,\n )\n if (op !== 'D') {\n qi += len\n }\n if (op !== 'I') {\n ti += len\n }\n }\n}\n\n// A record's score under vg's model over [lo, hi) on one side: a column counts\n// where its base on that side does, and a gap where it opens on that side.\nfunction scoreOver(r: PairChain, side: Side, lo: number, hi: number) {\n const step = side === 'query' && r.strand === '-' ? -1 : 1\n let score = 0\n forEachEdit(r, (op, len, query, target) => {\n const from = side === 'query' ? query : target\n const inside = (k: number) => {\n const at = from + step * k\n return at >= lo && at < hi\n }\n if (op === '=' || op === 'X') {\n for (let k = 0; k < len; k++) {\n if (inside(k)) {\n score += op === '=' ? MATCH : MISMATCH\n }\n }\n } else if ((op === 'I') === (side === 'query')) {\n for (let k = 0; k < len; k++) {\n if (inside(k)) {\n score += k === 0 ? GAP_OPEN : GAP_EXTEND\n }\n }\n } else if (inside(0)) {\n score += GAP_OPEN + (len - 1) * GAP_EXTEND\n }\n })\n return score\n}\n\nfunction spanOf(r: PairChain, side: Side): Interval {\n return side === 'query'\n ? [r.queryStart, r.queryEnd]\n : [r.targetStart, r.targetEnd]\n}\n\n// A record's edits with the aligned columns `lost` marks turned into an\n// insertion and a deletion, and its ends trimmed to the columns it keeps.\nfunction withoutColumns(r: Claimed, lost: Uint8Array): Claimed | undefined {\n const flipped = r.strand === '-'\n const edits: PairEdit[] = []\n let pendingQuery = 0\n let pendingTarget = 0\n let column = 0\n let sharedLost = 0\n const sharedMask = new Uint8Array(r.queryEnd - r.queryStart)\n for (const [s, e] of r.shared) {\n sharedMask.fill(1, s - r.queryStart, e - r.queryStart)\n }\n const inShared = (at: number) => sharedMask[at - r.queryStart] === 1\n const flush = () => {\n appendEdit(edits, 'I', pendingQuery)\n appendEdit(edits, 'D', pendingTarget)\n pendingQuery = 0\n pendingTarget = 0\n }\n forEachEdit(r, (op, len, query) => {\n if (op === 'I') {\n pendingQuery += len\n } else if (op === 'D') {\n pendingTarget += len\n } else {\n for (let k = 0; k < len; k++) {\n if (lost[column + k]) {\n pendingQuery += 1\n pendingTarget += 1\n if (inShared(flipped ? query - k : query + k)) {\n sharedLost += 1\n }\n } else {\n if (pendingQuery > 0 || pendingTarget > 0) {\n flush()\n }\n appendEdit(edits, op, 1)\n }\n }\n column += len\n }\n })\n flush()\n const lead = { I: 0, D: 0 }\n while (edits[0]?.[0] === 'I' || edits[0]?.[0] === 'D') {\n const [op, len] = edits.shift()!\n lead[op as 'I' | 'D'] += len\n }\n const tail = { I: 0, D: 0 }\n while (edits.at(-1)?.[0] === 'I' || edits.at(-1)?.[0] === 'D') {\n const [op, len] = edits.pop()!\n tail[op as 'I' | 'D'] += len\n }\n return edits.length === 0\n ? undefined\n : {\n ...r,\n queryStart: r.queryStart + (flipped ? tail.I : lead.I),\n queryEnd: r.queryEnd - (flipped ? lead.I : tail.I),\n targetStart: r.targetStart + lead.D,\n targetEnd: r.targetEnd - tail.D,\n edits,\n sharedBases: r.sharedBases - sharedLost,\n }\n}\n\n// A base aligns in one record at most. Where two records align the same bases\n// on either walk, the one scoring higher over the stretch their spans share\n// keeps them, and the other gives them up as an insertion and a deletion. In a\n// tandem array whose copies run both ways, one query copy aligns forward to one\n// target copy and inverted to another, and both are homology; the scoring\n// decides which one the pair's picture shows. A tie goes to the record with\n// more bases on shared nodes: alignPrivate finds an inversion a walk takes\n// through shared nodes again, base for base, in the gap of the forward record\n// spanning it.\nfunction claimOnce(\n records: Claimed[],\n queryLength: number,\n targetLength: number,\n minMatch: number,\n) {\n const claims = {\n query: new Uint8Array(queryLength),\n target: new Uint8Array(targetLength),\n }\n const columnsOf = records.map(r => {\n const columns: [number, number][] = []\n forEachEdit(r, (op, len, query, target) => {\n if (op === '=' || op === 'X') {\n for (let k = 0; k < len; k++) {\n columns.push([r.strand === '-' ? query - k : query + k, target + k])\n }\n }\n })\n for (const [query, target] of columns) {\n claims.query[query] = Math.min(255, claims.query[query]! + 1)\n claims.target[target] = Math.min(255, claims.target[target]! + 1)\n }\n return columns\n })\n const holders = {\n query: new Map<number, number[]>(),\n target: new Map<number, number[]>(),\n }\n columnsOf.forEach((columns, i) => {\n for (const [query, target] of columns) {\n for (const [side, at] of [\n ['query', query],\n ['target', target],\n ] as const) {\n if (claims[side][at]! > 1) {\n const held = holders[side].get(at)\n if (!held) {\n holders[side].set(at, [i])\n } else if (held.at(-1) !== i) {\n held.push(i)\n }\n }\n }\n }\n })\n const beaten = new Map<string, boolean>()\n const losesTo = (i: number, j: number, side: Side) => {\n const key = `${side}:${i}:${j}`\n let loses = beaten.get(key)\n if (loses === undefined) {\n const [si, ei] = spanOf(records[i]!, side)\n const [sj, ej] = spanOf(records[j]!, side)\n const lo = Math.max(si, sj)\n const hi = Math.min(ei, ej)\n const [mine, theirs] = [records[i]!, records[j]!]\n const margins = [\n scoreOver(theirs, side, lo, hi) - scoreOver(mine, side, lo, hi),\n theirs.sharedBases - mine.sharedBases,\n i - j,\n ]\n loses = margins.find(margin => margin !== 0)! > 0\n beaten.set(key, loses)\n }\n return loses\n }\n return records.flatMap((r, i) => {\n const columns = columnsOf[i]!\n const lost = new Uint8Array(columns.length)\n columns.forEach(([query, target], c) => {\n for (const [side, at] of [\n ['query', query],\n ['target', target],\n ] as const) {\n if (\n !lost[c] &&\n holders[side].get(at)?.some(j => j !== i && losesTo(i, j, side))\n ) {\n lost[c] = 1\n }\n }\n })\n if (!lost.includes(1)) {\n return [r]\n }\n const kept = withoutColumns(r, lost)\n const matched =\n kept?.edits.reduce((sum, [op, len]) => sum + (op === '=' ? len : 0), 0) ??\n 0\n return kept && matched >= minMatch ? [kept] : []\n })\n}\n\nfunction walkSequence(walk: number[], sequenceOf: (id: number) => string) {\n return walk\n .map(handle => {\n const sequence = sequenceOf(nodeId(handle))\n return isReverse(handle) ? reverseComplement(sequence) : sequence\n })\n .join('')\n}\n\nfunction walkOffsets(walk: number[], sequenceOf: (id: number) => string) {\n const offsets = [0]\n for (const handle of walk) {\n offsets.push(offsets.at(-1)! + sequenceOf(nodeId(handle)).length)\n }\n return offsets\n}\n\n// The steps between a walk's first and last visit to any node it visits more\n// than once. Copies of a repeat folded onto one node say nothing about which\n// copy of one haplotype pairs with which copy of the other, and a graph can\n// pair them out of register, so there the bases decide.\nfunction repeatSteps(walk: number[]) {\n const first = new Map<number, number>()\n const last = new Map<number, number>()\n walk.forEach((handle, i) => {\n const id = nodeId(handle)\n if (first.has(id)) {\n last.set(id, i)\n } else {\n first.set(id, i)\n }\n })\n const change = new Int32Array(walk.length + 1)\n for (const [id, end] of last) {\n change[first.get(id)!]! += 1\n change[end + 1]! -= 1\n }\n const inside = new Uint8Array(walk.length)\n let depth = 0\n for (let i = 0; i < walk.length; i++) {\n depth += change[i]!\n inside[i] = depth > 0 ? 1 : 0\n }\n return inside\n}\n\n// Every stretch of steps the two walks take through the same nodes, in the\n// same order or the opposite one, outside both walks' repeats.\nfunction sharedRuns(\n query: number[],\n target: number[],\n queryOffsets: number[],\n targetOffsets: number[],\n) {\n const queryRepeat = repeatSteps(query)\n const targetRepeat = repeatSteps(target)\n const visits = new Map<number, number[]>()\n target.forEach((handle, rank) => {\n if (!targetRepeat[rank]) {\n visits.set(nodeId(handle), [rank])\n }\n })\n const width = 2 * target.length\n const key = (i: number, rank: number, flipped: boolean) =>\n i * width + 2 * rank + (flipped ? 1 : 0)\n const seeds = new Set<number>()\n query.forEach((handle, i) => {\n for (const rank of queryRepeat[i]\n ? []\n : (visits.get(nodeId(handle)) ?? [])) {\n seeds.add(key(i, rank, isReverse(handle) !== isReverse(target[rank]!)))\n }\n })\n const runs: Run[] = []\n query.forEach((handle, i) => {\n for (const rank of queryRepeat[i]\n ? []\n : (visits.get(nodeId(handle)) ?? [])) {\n const flipped = isReverse(handle) !== isReverse(target[rank]!)\n const step = flipped ? -1 : 1\n const previous = rank - step\n const continues =\n i > 0 &&\n previous >= 0 &&\n previous < target.length &&\n seeds.has(key(i - 1, previous, flipped))\n if (!continues) {\n let j = i\n let r = rank\n while (\n j < query.length &&\n r >= 0 &&\n r < target.length &&\n seeds.has(key(j, r, flipped))\n ) {\n j += 1\n r += step\n }\n const lastRank = r - step\n runs.push({\n qs: queryOffsets[i]!,\n qe: queryOffsets[j]!,\n ts: targetOffsets[Math.min(rank, lastRank)]!,\n te: targetOffsets[Math.max(rank, lastRank) + 1]!,\n flipped,\n })\n }\n }\n })\n return runs\n}\n\n// A query walk's alignments to a target walk. A stretch of nodes both walks\n// visit is a run of `=`, a record is the best collinear chain of those\n// stretches, and what lies between two of them is aligned base by base under\n// vg's scoring, an inversion there coming back as a record of its own. With\n// bases false it is an insertion and a deletion instead. A chain pays for the\n// gap it spans, so by default nothing bounds how far it reaches but the window;\n// maxGap caps that to bound the work. A record matching under minMatch bases is\n// dropped. Coordinates count from each walk's first base; a `-` record's edits\n// read along the target, the way minimap2 writes a reverse-strand row.\nexport function pairAlignments(opts: PairOptions): PairChain[] {\n const { query, target, sequenceOf } = opts\n const a = walkSequence(query, sequenceOf)\n const b = walkSequence(target, sequenceOf)\n const runs = sharedRuns(\n query,\n target,\n walkOffsets(query, sequenceOf),\n walkOffsets(target, sequenceOf),\n )\n const minMatch = opts.minMatch ?? DEFAULT_MIN_MATCH\n const bases = opts.bases ?? true\n const records: Claimed[] = []\n for (const chain of chainRuns(\n runs,\n opts.maxGap ?? Infinity,\n minMatch,\n stepJumpCost,\n )) {\n const edits: PairEdit[] = []\n const first = chain[0]!\n const last = chain.at(-1)!\n const { flipped } = first.run\n const alignBetween: GapFill = (qa, tb, into, queryFrom, targetFrom) => {\n for (const inversion of alignPrivate(qa, tb, into, minMatch)) {\n const targetTo = targetFrom + tb.length\n records.push({\n ...inversion,\n queryStart: queryFrom + inversion.queryStart,\n queryEnd: queryFrom + inversion.queryEnd,\n targetStart: flipped\n ? targetTo - inversion.targetEnd\n : targetFrom + inversion.targetStart,\n targetEnd: flipped\n ? targetTo - inversion.targetStart\n : targetFrom + inversion.targetEnd,\n strand: flipped ? '+' : '-',\n edits: flipped ? inversion.edits.reverse() : inversion.edits,\n shared: [],\n })\n }\n }\n chainEdits(chain, a, b, edits, bases ? alignBetween : unaligned)\n records.push({\n queryStart: first.run.qs + first.trim,\n queryEnd: last.run.qe,\n targetStart: flipped ? last.run.ts : first.run.ts + first.trim,\n targetEnd: flipped ? first.run.te - first.trim : last.run.te,\n strand: flipped ? '-' : '+',\n edits: flipped ? edits.reverse() : edits,\n sharedBases: chain.reduce(\n (sum, { run, trim }) => sum + run.qe - run.qs - trim,\n 0,\n ),\n shared: chain.map(({ run, trim }) => [run.qs + trim, run.qe]),\n })\n }\n return claimOnce(records, a.length, b.length, minMatch)\n .map(({ shared: _, ...record }) => record)\n .sort((x, y) => x.queryStart - y.queryStart)\n}\n\nexport function pairCigar(edits: PairEdit[]) {\n return edits.map(([op, len]) => `${len}${op}`).join('')\n}\n", "import { extractionOrder, findChosenPieces, handleRuns } from './chosenPaths.ts'\nimport {\n ENDMARKER,\n edgeIsCanonical,\n encodeNode,\n entryOrientation,\n entrySide,\n exitOrientation,\n exitSide,\n flipNode,\n flipSide,\n isReverse,\n nodeId,\n nodeOrientation,\n pathEndsAreCanonical,\n pathIsCanonical,\n} from './gbwt/node.ts'\nimport { gfaHeaderLines, sha256Hex, subgraphName } from './graphName.ts'\nimport { weightedLcs } from './lcs.ts'\nimport { pairAlignments, pairCigar } from './pairAlignment.ts'\nimport { formatPathName } from './pathName.ts'\n\nimport type { ChosenPiece, KeepStats } from './chosenPaths.ts'\nimport type { GBZBase, GbzPath, GbzRecord, HaplotypeSample } from './db.ts'\nimport type { NodeSide, Orientation } from './gbwt/node.ts'\nimport type { Pos } from './gbwt/record.ts'\nimport type { PathName } from './pathName.ts'\n\nexport type HaplotypeOutput = 'all' | 'distinct' | 'reference-only' | 'none'\n\nexport type SnarlOutput = 'none' | 'contained' | 'overlapping'\n\ntype HandleType =\n | { kind: 'snarl-exit'; snarl: [number, number] }\n | { kind: 'chain' }\n | { kind: 'regular' }\n\n// A snarl filled between two boundary nodes: their ids, lower first, the\n// nodes between them, and how many of those the fill added to the subgraph.\nexport interface SnarlFill {\n low: number\n high: number\n nodes: number\n inserted: number\n}\n\nexport interface PathPosition {\n seqOffset: number\n handle: number\n nodeOffset: number\n gbwtOffset: number\n}\n\nexport interface ReferencePath {\n position: PathPosition\n name: PathName\n handle: number\n}\n\nexport interface PathIdentity {\n pathHandle: number\n name: PathName\n orientation: Orientation\n hapStart: number\n hapEnd: number\n}\n\ninterface PathInfo {\n path: number[]\n offsets: number[]\n len: number\n weight: number | undefined\n identity: PathIdentity | undefined\n}\n\ntype EditOp = 'M' | 'I' | 'D'\ntype Edit = [EditOp, number]\n\nexport interface SubgraphPath {\n name: string\n weight?: number\n cigar?: string\n path: { id: string; is_reverse: boolean }[]\n}\n\nexport interface SubgraphJson {\n nodes: { id: string; sequence: string }[]\n edges: {\n from: string\n from_is_reverse: boolean\n to: string\n to_is_reverse: boolean\n }[]\n paths: SubgraphPath[]\n}\n\n// A step, and either end of an edge, is a GBWT handle: 2 * nodeId for the\n// forward orientation and 2 * nodeId + 1 for the reverse, which is how the\n// GBWT itself numbers them. nodeId and isReverse read the two halves back.\nexport interface CompactPath {\n name: string\n weight: number | undefined\n cigar: string | undefined\n steps: Int32Array\n}\n\nexport interface CompactSubgraph {\n // Ascending, one entry per node; nodeSequences runs parallel to it.\n nodeIds: Int32Array\n nodeSequences: string[]\n // Handle pairs laid end to end: edges[2i] -> edges[2i + 1].\n edges: Int32Array\n paths: CompactPath[]\n}\n\nexport interface AlignmentSpan {\n strand: '+' | '-'\n refStart: number\n refEnd: number\n cigar: string\n weight: number | undefined\n path: number[]\n start: Pos\n}\n\nexport type HaplotypeAlignment = AlignmentSpan &\n (\n | {\n resolved: true\n name: PathName\n label: string\n pathHandle: number\n hapStart: number\n hapEnd: number\n }\n | { resolved: false }\n )\n\nexport interface HaplotypeRef {\n sample: string\n haplotype: number\n}\n\nexport interface PairAlignmentOptions {\n target: HaplotypeRef\n query?: HaplotypeRef | undefined\n maxGap?: number | undefined\n minMatch?: number | undefined\n bases?: boolean | undefined\n}\n\nexport interface PairAlignment {\n query: PathName\n queryStart: number\n queryEnd: number\n strand: '+' | '-'\n target: PathName\n targetStart: number\n targetEnd: number\n cigar: string\n matches: number\n columns: number\n sharedBases: number\n}\n\nexport interface SubgraphOutputOptions {\n cigar?: boolean | undefined\n names?: 'anonymous' | 'resolved' | undefined\n}\n\nexport interface SubgraphOptions {\n limit?: number | undefined\n signal?: AbortSignal | undefined\n}\n\nexport class SubgraphLimitError extends Error {\n override name = 'SubgraphLimitError'\n readonly limit: number\n readonly windowBp: number | undefined\n readonly walkedBp: number | undefined\n\n constructor(limit: number, walk?: { windowBp: number; walkedBp: number }) {\n super(\n walk === undefined\n ? `Subgraph size limit of ${limit} nodes exceeded`\n : `Subgraph size limit of ${limit} nodes exceeded ${walk.walkedBp} bp into a ${walk.windowBp} bp window`,\n )\n this.limit = limit\n this.windowBp = walk?.windowBp\n this.walkedBp = walk?.walkedBp\n }\n}\n\nfunction sideBefore(\n a: [number, number, NodeSide],\n b: [number, number, NodeSide],\n) {\n return (\n a[0] < b[0] ||\n (a[0] === b[0] && (a[1] < b[1] || (a[1] === b[1] && a[2] < b[2])))\n )\n}\n\nclass SideQueue {\n private heap: [number, number, NodeSide][] = []\n\n push(distance: number, node: number, side: NodeSide) {\n const heap = this.heap\n heap.push([distance, node, side])\n let i = heap.length - 1\n while (i > 0) {\n const parent = (i - 1) >> 1\n if (sideBefore(heap[i]!, heap[parent]!)) {\n ;[heap[i], heap[parent]] = [heap[parent]!, heap[i]!]\n i = parent\n } else {\n break\n }\n }\n }\n\n pop() {\n const heap = this.heap\n const top = heap[0]\n const last = heap.pop()\n if (heap.length > 0 && last !== undefined) {\n heap[0] = last\n let i = 0\n for (;;) {\n const left = 2 * i + 1\n const right = left + 1\n let smallest = i\n if (left < heap.length && sideBefore(heap[left]!, heap[smallest]!)) {\n smallest = left\n }\n if (right < heap.length && sideBefore(heap[right]!, heap[smallest]!)) {\n smallest = right\n }\n if (smallest === i) {\n break\n }\n ;[heap[i], heap[smallest]] = [heap[smallest]!, heap[i]!]\n i = smallest\n }\n }\n return top\n }\n\n get size() {\n return this.heap.length\n }\n}\n\n// Which step of a walk matches which step of the reference, as two parallel\n// arrays rather than a list of pairs: there is one entry per step of every\n// walk being aligned, and a window at HPRC scale has millions of them.\ninterface Matches {\n pathAt: Int32Array\n refAt: Int32Array\n count: number\n}\n\nfunction asMatches(pairs: [number, number][]): Matches {\n const pathAt = new Int32Array(pairs.length)\n const refAt = new Int32Array(pairs.length)\n pairs.forEach(([a, b], i) => {\n pathAt[i] = a\n refAt[i] = b\n })\n return { pathAt, refAt, count: pairs.length }\n}\n\n// The first entry above `bound` of an ascending list, or undefined. Called\n// once per step of every walk being aligned, which is where `Array.find` hurt:\n// it allocated a closure over the bound each time, and scanned from the front\n// of a reference node's occurrence list, which a repeat locus makes long.\nfunction firstAbove(ascending: number[], bound: number) {\n let lo = 0\n let hi = ascending.length\n while (lo < hi) {\n const mid = (lo + hi) >> 1\n if (ascending[mid]! > bound) {\n hi = mid\n } else {\n lo = mid + 1\n }\n }\n return ascending[lo]\n}\n\nfunction posKey(pos: Pos) {\n return `${pos.node}:${pos.offset}`\n}\n\ninterface FragmentAlignment {\n strand: '+' | '-'\n refStart: number\n refEnd: number\n edits: Edit[]\n weight: number | undefined\n path: number[]\n start: Pos\n // Indices into the subgraph's paths, in walk order, and the bases of each\n // that the CIGAR aligns when the piece is aligned alone.\n pieces: number[]\n soloAligned: number[]\n identity:\n | {\n pathHandle: number\n name: PathName\n hapStart: number\n hapEnd: number\n walkForward: boolean\n }\n | undefined\n}\n\nfunction flipPath(path: number[]) {\n return path.map(handle => flipNode(handle)).reverse()\n}\n\nfunction joinable(a: FragmentAlignment, b: FragmentAlignment) {\n const insertion = b.identity!.hapStart - a.identity!.hapEnd\n const deletion =\n a.strand === '+' ? b.refStart - a.refEnd : a.refStart - b.refEnd\n return a.strand === b.strand && insertion >= 0 && deletion >= 0\n ? { insertion, deletion }\n : undefined\n}\n\nfunction joinPair(\n a: FragmentAlignment,\n b: FragmentAlignment,\n gap: { insertion: number; deletion: number },\n): FragmentAlignment {\n const [left, right] = a.strand === '+' ? [a, b] : [b, a]\n const edits = left.edits.map(([op, len]): Edit => [op, len])\n appendGap(edits, gap.insertion, gap.deletion)\n for (const [op, len] of right.edits) {\n appendEdit(edits, op, len)\n }\n const walkForward = a.identity!.walkForward\n const [first, second] = walkForward ? [a, b] : [b, a]\n return {\n strand: a.strand,\n refStart: left.refStart,\n refEnd: right.refEnd,\n edits,\n weight: undefined,\n path: [...first.path, ...second.path],\n start: first.start,\n pieces: [...first.pieces, ...second.pieces],\n soloAligned: [...first.soloAligned, ...second.soloAligned],\n identity: {\n pathHandle: a.identity!.pathHandle,\n name: a.identity!.name,\n hapStart: a.identity!.hapStart,\n hapEnd: b.identity!.hapEnd,\n walkForward,\n },\n }\n}\n\n// Pieces of one path in haplotype order, joined where they are colinear on\n// the reference, and otherwise aligned again as one walk. A piece aligned over\n// less than half its length joins only between two that are.\nfunction joinSiblings(\n fragments: FragmentAlignment[],\n mostlyAligned: (fragment: FragmentAlignment) => boolean,\n alignJointly: (parts: FragmentAlignment[]) => FragmentAlignment | undefined,\n) {\n if (fragments.some(f => f.weight !== undefined)) {\n return fragments\n }\n const byPath = new Map<number, number[]>()\n fragments.forEach((fragment, index) => {\n if (fragment.identity) {\n const siblings = byPath.get(fragment.identity.pathHandle)\n if (siblings) {\n siblings.push(index)\n } else {\n byPath.set(fragment.identity.pathHandle, [index])\n }\n }\n })\n const joined = new Map<number, FragmentAlignment>()\n const consumed = new Set<number>()\n for (const siblings of byPath.values()) {\n siblings.sort(\n (x, y) =>\n fragments[x]!.identity!.hapStart - fragments[y]!.identity!.hapStart,\n )\n let head = siblings[0]!\n let current = fragments[head]!\n let between: number[] = []\n for (const index of siblings.slice(1)) {\n const next = fragments[index]!\n const gap = between.length === 0 ? joinable(current, next) : undefined\n if (gap) {\n current = joinPair(current, next, gap)\n consumed.add(index)\n continue\n }\n if (!mostlyAligned(next)) {\n between.push(index)\n continue\n }\n const joint = mostlyAligned(current)\n ? alignJointly([current, ...between.map(i => fragments[i]!), next])\n : undefined\n if (joint) {\n current = joint\n for (const i of [...between, index]) {\n consumed.add(i)\n }\n } else {\n joined.set(head, current)\n head = index\n current = next\n }\n between = []\n }\n joined.set(head, current)\n }\n return fragments.flatMap((fragment, index) =>\n consumed.has(index) ? [] : [joined.get(index) ?? fragment],\n )\n}\n\nfunction pathPosition(info: PathInfo, k: number): Pos {\n return { node: info.path[k]!, offset: info.offsets[k]! }\n}\n\ninterface Anchor {\n pathHandle: number\n orientation: Orientation\n base: number\n}\n\nexport type ChainEnd =\n | 'in-fragment sample'\n | 'identified sibling'\n | 'out-of-window sample'\n | 'bound'\n | 'endmarker'\n | 'cycle'\n\nexport interface ChainRecord {\n fragments: number\n steps: number\n seeks: number\n reentries: number\n twinLandings: number\n end: ChainEnd\n pathHandle: number | undefined\n}\n\nexport interface IdentificationStats {\n interval: number\n scans: [number, number][]\n windowSamples: number\n fragmentLengths: number[]\n companionSeeks: number\n companionMisses: number\n graphLookups: number\n graphFetches: number\n chains: ChainRecord[]\n}\n\ninterface SubgraphStats {\n orderedAlignments: number\n lcsAlignments: number\n identificationSteps: number\n identificationFetches: number\n identification: IdentificationStats\n // the top-level snarls the query filled, and the nodes those fills added\n snarls: { fills: number; inserted: number }\n keep: KeepStats | undefined\n}\n\nconst PREFETCH_RUN_GAP = 32768\n\nfunction rowidRuns(handles: number[]) {\n const sorted = [...handles].sort((a, b) => a - b)\n const runs: [number, number][] = []\n for (const handle of sorted) {\n const last = runs[runs.length - 1]\n if (last && handle - last[1] <= PREFETCH_RUN_GAP) {\n last[1] = handle\n } else {\n runs.push([handle, handle])\n }\n }\n return runs\n}\n\nexport class Subgraph {\n private records = new Map<number, GbzRecord>()\n private paths: PathInfo[] = []\n private twinStarts = new Set<string>()\n private twinDeferred = false\n private unsettled:\n { paths: PathInfo[]; refId: number | undefined } | undefined\n private refId: number | undefined\n private refPath: PathName | undefined\n private refHandle: number | undefined\n private refInterval: [number, number] | undefined\n private refIndexCache: Map<number, number[]> | undefined\n private refPrefixCache: number[] | undefined\n private walkedBp: number | undefined\n private snarlMode: SnarlOutput = 'none'\n private snarlFills: SnarlFill[] = []\n private snarlNodes = new Set<number>()\n /** @internal */\n readonly stats: SubgraphStats = {\n orderedAlignments: 0,\n lcsAlignments: 0,\n snarls: { fills: 0, inserted: 0 },\n identificationSteps: 0,\n identificationFetches: 0,\n identification: {\n interval: 0,\n scans: [],\n windowSamples: 0,\n fragmentLengths: [],\n companionSeeks: 0,\n companionMisses: 0,\n graphLookups: 0,\n graphFetches: 0,\n chains: [],\n },\n keep: undefined,\n }\n\n private db: GBZBase\n private readonly limit: number | undefined\n private readonly signal: AbortSignal | undefined\n\n private constructor(db: GBZBase, opts: SubgraphOptions) {\n this.db = db\n this.limit = opts.limit\n this.signal = opts.signal\n }\n\n /** @internal */\n static create(db: GBZBase, opts: SubgraphOptions = {}) {\n return new Subgraph(db, opts)\n }\n\n get nodeCount() {\n return this.records.size / 2\n }\n\n get pathCount() {\n this.settleDeferred()\n return this.paths.length\n }\n\n get referenceInterval() {\n return this.refInterval && this.refPath\n ? {\n name: this.refPath,\n start: this.refPath.fragment + this.refInterval[0],\n end: this.refPath.fragment + this.refInterval[1],\n }\n : undefined\n }\n\n hasNode(id: number) {\n return this.records.has(encodeNode(id, 'forward'))\n }\n\n hasHandle(handle: number) {\n return this.records.has(handle)\n }\n\n private record(handle: number) {\n const record = this.records.get(handle)\n if (!record) {\n throw new Error(`Subgraph has no record for handle ${handle}`)\n }\n return record\n }\n\n private sortedHandles() {\n return [...this.records.keys()].sort((a, b) => a - b)\n }\n\n private async addNode(id: number) {\n this.signal?.throwIfAborted()\n if (this.limit !== undefined && this.nodeCount >= this.limit) {\n throw new SubgraphLimitError(this.limit)\n }\n const forward = await this.db.getRecord(encodeNode(id, 'forward'))\n const reverse = await this.db.getRecord(encodeNode(id, 'reverse'))\n if (!forward || !reverse) {\n throw new Error(`Node ${id} does not exist in the graph`)\n }\n this.records.set(forward.handle, forward)\n this.records.set(reverse.handle, reverse)\n }\n\n private async ensureNode(id: number) {\n if (!this.hasNode(id)) {\n await this.addNode(id)\n }\n }\n\n private clearPaths() {\n this.paths = []\n this.twinStarts.clear()\n this.twinDeferred = false\n this.unsettled = undefined\n this.refId = undefined\n this.refPath = undefined\n this.refHandle = undefined\n this.refInterval = undefined\n this.refIndexCache = undefined\n this.refPrefixCache = undefined\n }\n\n /** @internal */\n async pathPosition(query: PathName): Promise<ReferencePath> {\n const path = await this.db.findPath(query)\n if (!path) {\n throw new Error(\n `Cannot find a path covering offset ${query.fragment} of ${formatPathName(query)}`,\n )\n }\n if (!path.isIndexed) {\n throw new Error(\n `The fragment of ${formatPathName(path.name)} at ${path.name.fragment} has not been indexed for random access`,\n )\n }\n const queryOffset = query.fragment - path.name.fragment\n const indexed = await this.db.indexedPosition(path.handle, queryOffset)\n if (!indexed) {\n throw new Error(\n `The fragment of ${formatPathName(path.name)} at ${path.name.fragment} has not been indexed for random access`,\n )\n }\n return this.findPathPosition(\n path,\n queryOffset,\n indexed.pathOffset,\n indexed.pos,\n )\n }\n\n private async findPathPosition(\n path: GbzPath,\n queryOffset: number,\n startOffset: number,\n start: Pos,\n ): Promise<ReferencePath> {\n let pathOffset = startOffset\n let pos = start\n for (;;) {\n await this.ensureNode(nodeId(pos.node))\n const record = this.record(pos.node)\n if (pathOffset + record.sequenceLen > queryOffset) {\n return {\n position: {\n seqOffset: queryOffset,\n handle: pos.node,\n nodeOffset: queryOffset - pathOffset,\n gbwtOffset: pos.offset,\n },\n name: path.name,\n handle: path.handle,\n }\n }\n pathOffset += record.sequenceLen\n const next = record.gbwt().lf(pos.offset)\n if (!next) {\n throw new Error(\n `The fragment of ${formatPathName(path.name)} at ${path.name.fragment} does not contain offset ${queryOffset}`,\n )\n }\n pos = next\n }\n }\n\n /** @internal */\n async aroundPosition(handle: number, nodeOffset: number, context: number) {\n const id = nodeId(handle)\n await this.ensureNode(id)\n const record = this.record(handle)\n const orientation = nodeOrientation(handle)\n const active = new SideQueue()\n active.push(nodeOffset, id, entrySide(orientation))\n active.push(record.sequenceLen - nodeOffset - 1, id, exitSide(orientation))\n return this.insertContext(active, context)\n }\n\n /** @internal */\n prefetchReferenceWalk(reference: ReferencePath, len: number) {\n return this.prefetchReferenceRange(\n reference.handle,\n reference.position.seqOffset,\n reference.position.seqOffset + len,\n )\n }\n\n // One request for the reference walk's node records where their rowids are\n // close, and one prefetch over the runs of them where the walk crosses a gap\n // in node ids (AMY1's reference walk spans two gaps of millions), so the walk\n // after it never fetches leaf pages one at a time.\n private async prefetchReferenceRange(\n pathHandle: number,\n fromOffset: number,\n toOffset: number,\n ) {\n const [first, last] = await Promise.all([\n this.db.indexedPosition(pathHandle, fromOffset),\n this.db.indexedPosition(pathHandle, toOffset),\n ])\n if (first && last) {\n const a = first.pos.node\n const b = last.pos.node\n const whole = await this.db.prefetchRecords([\n [Math.min(a, b), Math.max(a, b) + 1],\n ])\n if (!whole) {\n const positions = await this.db.indexedPositionsBetween(\n pathHandle,\n fromOffset,\n toOffset,\n )\n await this.db.prefetchRecords(\n rowidRuns(positions.map(p => p.pos.node)).map(([lo, hi]) => [\n lo,\n hi + 2,\n ]),\n true,\n )\n }\n }\n return first\n }\n\n /** @internal */\n async aroundInterval(start: PathPosition, len: number, context: number) {\n if (!(len > 0)) {\n throw new Error('Interval length must be greater than 0')\n }\n this.walkedBp = 0\n try {\n return await this.walkInterval(start, len, context)\n } catch (error) {\n throw error instanceof SubgraphLimitError && error.windowBp === undefined\n ? new SubgraphLimitError(error.limit, {\n windowBp: len,\n walkedBp: this.walkedBp,\n })\n : error\n }\n }\n\n /** @internal */\n get referenceWalkedBp() {\n return this.walkedBp\n }\n\n private async walkInterval(\n start: PathPosition,\n len: number,\n context: number,\n ) {\n let pos: Pos = { node: start.handle, offset: start.gbwtOffset }\n let offset = start.nodeOffset\n let remaining = len\n const active = new SideQueue()\n for (;;) {\n const id = nodeId(pos.node)\n const orientation = nodeOrientation(pos.node)\n this.walkedBp = len - remaining\n await this.ensureNode(id)\n const record = this.record(pos.node)\n if (offset >= record.sequenceLen) {\n throw new Error(\n `Offset ${offset} in node ${id} of length ${record.sequenceLen}`,\n )\n }\n active.push(offset, id, entrySide(orientation))\n const distanceToNext = record.sequenceLen - offset\n if (remaining <= distanceToNext) {\n active.push(\n remaining === distanceToNext ? 0 : distanceToNext - remaining - 1,\n id,\n exitSide(orientation),\n )\n break\n }\n active.push(0, id, exitSide(orientation))\n const next = record.gbwt().lf(pos.offset)\n if (!next) {\n throw new Error(\n `No successor for GBWT position (${pos.node}, ${pos.offset})`,\n )\n }\n pos = next\n offset = 0\n remaining -= distanceToNext\n }\n this.walkedBp = len\n return this.insertContext(active, context)\n }\n\n /** @internal */\n async aroundNodes(nodes: Iterable<number>, context: number) {\n const active = new SideQueue()\n for (const id of nodes) {\n await this.ensureNode(id)\n active.push(0, id, 'left')\n active.push(0, id, 'right')\n }\n return this.insertContext(active, context)\n }\n\n private async insertContext(active: SideQueue, context: number) {\n this.clearPaths()\n this.snarlMode = 'none'\n this.snarlFills = []\n this.snarlNodes.clear()\n this.stats.snarls = { fills: 0, inserted: 0 }\n const visited = new Set<string>()\n const toRemove = new Set<number>()\n for (const handle of this.records.keys()) {\n toRemove.add(nodeId(handle))\n }\n let inserted = 0\n while (active.size > 0) {\n const [distance, id, side] = active.pop()!\n const key = `${id}:${side}`\n if (visited.has(key)) {\n continue\n }\n visited.add(key)\n toRemove.delete(id)\n if (!this.hasNode(id)) {\n await this.addNode(id)\n inserted += 1\n }\n const otherSide = flipSide(side)\n if (!visited.has(`${id}:${otherSide}`)) {\n const record = this.record(encodeNode(id, entryOrientation(side)))\n const nextDistance = distance + record.sequenceLen - 1\n if (nextDistance <= context) {\n active.push(nextDistance, id, otherSide)\n }\n }\n const record = this.record(encodeNode(id, exitOrientation(side)))\n const nextDistance = distance + 1\n if (nextDistance <= context) {\n for (const successor of record.successors()) {\n const successorId = nodeId(successor)\n const successorSide = entrySide(nodeOrientation(successor))\n if (!visited.has(`${successorId}:${successorSide}`)) {\n active.push(nextDistance, successorId, successorSide)\n }\n }\n }\n }\n for (const id of toRemove) {\n this.records.delete(encodeNode(id, 'forward'))\n this.records.delete(encodeNode(id, 'reverse'))\n }\n return { inserted, removed: toRemove.size }\n }\n\n /** @internal */\n async betweenNodes(start: number, end: number) {\n return (await this.fillBetween(start, end)).inserted.length\n }\n\n private async fillBetween(start: number, end: number) {\n this.clearPaths()\n const active = [start, flipNode(end)]\n const visited = new Set([nodeId(start), nodeId(end)])\n const inserted: number[] = []\n while (active.length > 0) {\n const curr = active.pop()!\n const id = nodeId(curr)\n if (!this.hasNode(id)) {\n await this.addNode(id)\n inserted.push(id)\n }\n for (const successor of this.record(curr).successors()) {\n const successorId = nodeId(successor)\n if (!visited.has(successorId)) {\n active.push(successor, flipNode(successor))\n visited.add(successorId)\n }\n }\n }\n return { inserted, nodes: visited.size - 2 }\n }\n\n /** @internal */\n async extractSnarls(snarls: SnarlOutput) {\n let total = 0\n this.snarlMode = snarls\n for (const [start, end] of await this.overlappingSnarls(snarls)) {\n const { inserted, nodes } = await this.fillBetween(start, end)\n const a = nodeId(start)\n const b = nodeId(end)\n this.snarlFills.push({\n low: Math.min(a, b),\n high: Math.max(a, b),\n nodes,\n inserted: inserted.length,\n })\n for (const id of inserted) {\n this.snarlNodes.add(id)\n }\n total += inserted.length\n }\n this.stats.snarls = {\n fills: this.snarlFills.length,\n inserted: this.snarlNodes.size,\n }\n return total\n }\n\n private async overlappingSnarls(snarls: SnarlOutput) {\n const result: [number, number][] = []\n if (snarls !== 'none') {\n let foundLink = false\n for (const handle of this.sortedHandles()) {\n const record = this.record(handle)\n const next = record.next\n if (next !== undefined) {\n foundLink = true\n if (this.hasHandle(next)) {\n if (edgeIsCanonical(handle, next)) {\n result.push([handle, next])\n }\n } else if (\n snarls === 'overlapping' &&\n this.isSnarlEntryInSubgraph(record)\n ) {\n result.push([handle, next])\n }\n }\n }\n if (\n !foundLink &&\n snarls === 'overlapping' &&\n (await this.db.hasChainLinks())\n ) {\n const covering = await this.findCoveringSnarl()\n if (covering) {\n result.push(covering)\n }\n }\n }\n return result\n }\n\n private isSnarlEntryInSubgraph(record: GbzRecord) {\n const successors = record.successors()\n const first = successors.find(handle => this.hasHandle(handle))\n return first === undefined\n ? false\n : successors.length > 1 ||\n this.record(flipNode(first)).successors().length > 1\n }\n\n private recordReader(onFetch?: () => void) {\n const outside = new Map<number, GbzRecord>()\n return async (handle: number) => {\n const inside = this.records.get(handle)\n if (inside) {\n return inside\n }\n let record = outside.get(handle)\n if (!record) {\n record = await this.db.getRecord(handle)\n onFetch?.()\n if (!record) {\n throw new Error(`Node record ${handle} is missing from the database`)\n }\n outside.set(handle, record)\n }\n return record\n }\n }\n\n private async findCoveringSnarl() {\n const read = this.recordReader()\n const isSnarlEntry = async (record: GbzRecord) => {\n const successors = record.successors()\n const first = successors[0]\n return first === undefined\n ? false\n : successors.length > 1 ||\n (await read(flipNode(first))).successors().length > 1\n }\n const classify = async (handle: number): Promise<HandleType> => {\n const reverse = await read(flipNode(handle))\n return reverse.next !== undefined\n ? (await isSnarlEntry(reverse))\n ? { kind: 'snarl-exit', snarl: [flipNode(handle), reverse.next] }\n : { kind: 'chain' }\n : (await read(handle)).next !== undefined\n ? { kind: 'chain' }\n : { kind: 'regular' }\n }\n const visited = new Set<number>()\n const queue = this.sortedHandles().flatMap(handle =>\n this.record(handle).successors(),\n )\n let result: [number, number] | undefined\n let done = false\n while (!done && queue.length > 0) {\n const handle = queue.shift()!\n const id = nodeId(handle)\n if (!this.hasHandle(handle) && !visited.has(id)) {\n visited.add(id)\n const type = await classify(handle)\n if (type.kind === 'snarl-exit') {\n result = type.snarl\n done = true\n } else if (type.kind === 'chain') {\n done = true\n } else {\n for (const orientation of ['forward', 'reverse'] as const) {\n queue.push(\n ...(await read(encodeNode(id, orientation))).successors(),\n )\n }\n }\n }\n }\n return result\n }\n\n /** @internal */\n extractPaths(reference: ReferencePath | undefined, output: HaplotypeOutput) {\n this.clearPaths()\n if (output === 'none') {\n return\n }\n const refPos = reference?.position\n this.refPath = reference?.name\n this.refHandle = reference?.handle\n const handles = this.sortedHandles()\n const count = handles.length\n const indexOf = new Map<number, number>()\n handles.forEach((handle, i) => indexOf.set(handle, i))\n // One flat pair for the whole subgraph, indexed by rowStart[node] + offset,\n // rather than an Int32Array per node. walk() reads a successor on every one\n // of a window's steps \u2014 9.9M of them at MHC class II \u2014 and through an array\n // of forty thousand small buffers each of those is a pointer chase into\n // scattered memory. The per-node arrays die before the walking starts.\n const rowStart = new Int32Array(count + 1)\n const seqLen = new Int32Array(count)\n const rows: { nodes: Int32Array; offsets: Int32Array }[] = []\n for (let i = 0; i < count; i++) {\n const record = this.record(handles[i]!)\n const row = record.gbwt().decompressArrays()\n seqLen[i] = record.sequenceLen\n rows.push(row)\n rowStart[i + 1] = rowStart[i]! + row.nodes.length\n }\n const positions = rowStart[count]!\n const nextIndex = new Int32Array(positions)\n const nextOffset = new Int32Array(positions)\n const hasPredecessor = new Uint8Array(positions)\n for (let i = 0; i < count; i++) {\n const row = rows[i]!\n nextIndex.set(row.nodes, rowStart[i])\n nextOffset.set(row.offsets, rowStart[i])\n }\n rows.length = 0\n for (let k = 0; k < positions; k++) {\n const j = indexOf.get(nextIndex[k]!)\n if (j === undefined) {\n nextIndex[k] = -1\n } else {\n nextIndex[k] = j\n hasPredecessor[rowStart[j]! + nextOffset[k]!] = 1\n }\n }\n const refIndex =\n refPos === undefined ? undefined : indexOf.get(refPos.handle)\n const refGbwtOffset = refPos?.gbwtOffset\n let refOffset: number | undefined\n const walk = (i: number, offset: number, path: number[] | undefined) => {\n const offsets: number[] = []\n let steps = 0\n let len = 0\n let refAt = -1\n let cur = i\n let off = offset\n for (;;) {\n if (cur === refIndex && off === refGbwtOffset) {\n refAt = steps\n }\n if (path) {\n path.push(handles[cur]!)\n offsets.push(off)\n }\n steps += 1\n len += seqLen[cur]!\n const at = rowStart[cur]! + off\n const next = nextIndex[at]!\n if (next < 0) {\n break\n }\n off = nextOffset[at]!\n cur = next\n }\n return { offsets, len, refAt, last: cur }\n }\n const keep = (\n path: number[],\n offsets: number[],\n len: number,\n refAt: number,\n ) => {\n if (refAt >= 0) {\n this.refId = this.paths.length\n refOffset = refAt\n }\n this.paths.push({\n path,\n offsets,\n len,\n weight: undefined,\n identity: undefined,\n })\n }\n const twinsExpected = new Int32Array(count)\n for (let i = 0; i < count; i++) {\n const first = handles[i]!\n if (!isReverse(first)) {\n const from = rowStart[i]!\n const degree = rowStart[i + 1]! - from\n for (let offset = 0; offset < degree; offset++) {\n if (hasPredecessor[from + offset] === 0) {\n const path: number[] = []\n const { offsets, len, refAt, last } = walk(i, offset, path)\n const lastHandle = handles[last]!\n if (refAt >= 0 || pathEndsAreCanonical(first, lastHandle)) {\n keep(path, offsets, len, refAt)\n if (!isReverse(lastHandle)) {\n const twinRecord = indexOf.get(flipNode(lastHandle))!\n twinsExpected[twinRecord] = twinsExpected[twinRecord]! + 1\n }\n } else {\n this.twinStarts.add(posKey({ node: first, offset }))\n }\n }\n }\n }\n }\n for (let i = 0; i < count; i++) {\n const first = handles[i]!\n if (isReverse(first)) {\n const from = rowStart[i]!\n const degree = rowStart[i + 1]! - from\n let startCount = 0\n for (let offset = 0; offset < degree; offset++) {\n if (hasPredecessor[from + offset] === 0) {\n startCount += 1\n }\n }\n // Until the reference walk is found, it can be one of these starts,\n // with its twin kept above as a walk like any other.\n const allTwins =\n (refIndex === undefined || refOffset !== undefined) &&\n startCount === twinsExpected[i]\n for (let offset = 0; offset < degree; offset++) {\n if (hasPredecessor[from + offset] === 0) {\n const bare = allTwins ? undefined : walk(i, offset, undefined)\n if (\n bare &&\n (bare.refAt >= 0 ||\n pathEndsAreCanonical(first, handles[bare.last]))\n ) {\n const path: number[] = []\n const { offsets, len, refAt } = walk(i, offset, path)\n keep(path, offsets, len, refAt)\n } else {\n this.twinStarts.add(posKey({ node: first, offset }))\n }\n }\n }\n }\n }\n // Upstream lists walks by start position, handle then offset; the two\n // passes above find the forward-start walks first.\n const refInfo =\n this.refId === undefined ? undefined : this.paths[this.refId]\n this.paths.sort(\n (x, y) => x.path[0]! - y.path[0]! || x.offsets[0]! - y.offsets[0]!,\n )\n if (refInfo) {\n this.refId = this.paths.indexOf(refInfo)\n }\n if (refPos) {\n if (refOffset === undefined || this.refId === undefined) {\n this.clearPaths()\n throw new Error('Could not find the reference path')\n }\n const info = this.paths[this.refId]!\n let before = refPos.nodeOffset\n for (const handle of info.path.slice(0, refOffset)) {\n before += this.record(handle).sequenceLen\n }\n const start = refPos.seqOffset - before\n this.refInterval = [start, start + info.len]\n info.identity = {\n pathHandle: reference.handle,\n name: reference.name,\n orientation: 'forward',\n hapStart: start,\n hapEnd: start + info.len,\n }\n }\n if (output === 'distinct') {\n this.distinctPaths(true)\n } else if (output === 'reference-only') {\n if (this.refId === undefined) {\n throw new Error('Reference path is required for reference-only output')\n }\n this.paths = [this.paths[this.refId]!]\n this.refId = 0\n }\n }\n\n // Identical walks become one record whose weight counts them, and the\n // reference walk stands for its own group, since the outputs read its\n // offsets and identity. Walks that identification will drop as twins\n // (dropTwins) stay apart until then, so that the record they would have\n // merged into keeps a name and a weight of its own: the twin of a reference\n // walk that is not canonical, which a haplotype stored against the reference\n // walks handle for handle, and a walk canonical in both orientations, as\n // through a hairpin, which extractPaths keeps twice.\n private distinctPaths(deferTwins: boolean) {\n const refInfo =\n this.refId === undefined ? undefined : this.paths[this.refId]\n const refPath = refInfo?.path\n const referenceTwin =\n refPath && !pathIsCanonical(refPath) ? flipPath(refPath) : undefined\n const deferred = (path: number[]) =>\n (referenceTwin !== undefined &&\n comparePaths(path, referenceTwin) === 0) ||\n pathIsCanonical(flipPath(path))\n const defer = deferTwins && this.db.hasHaplotypeIndex\n this.twinDeferred = false\n this.paths.sort(\n (x, y) =>\n comparePaths(x.path, y.path) ||\n x.len - y.len ||\n (x === refInfo ? -1 : y === refInfo ? 1 : 0),\n )\n const merged: PathInfo[] = []\n let refId: number | undefined\n for (const info of this.paths) {\n const last = merged[merged.length - 1]\n const apart = defer && info !== refInfo && deferred(info.path)\n this.twinDeferred ||= apart\n if (last && comparePaths(last.path, info.path) === 0 && !apart) {\n last.weight = (last.weight ?? 1) + (info.weight ?? 1)\n } else {\n if (info === refInfo) {\n refId = merged.length\n }\n merged.push({ ...info, weight: info.weight ?? 1 })\n }\n }\n this.paths = merged\n this.refId = refId\n }\n\n // Merges identical walks into one record with a weight, as extractPaths does\n // for 'distinct'. After keepHaplotypes the weights count kept haplotypes.\n mergeDistinct() {\n if (this.twinDeferred) {\n this.settleDeferred()\n } else {\n this.distinctPaths(false)\n }\n }\n\n // Output read before identifyPaths sees the walks merged as they would be\n // without a haplotype index; identifyPaths takes them apart again.\n private settleDeferred() {\n if (this.twinDeferred) {\n this.unsettled = { paths: [...this.paths], refId: this.refId }\n this.distinctPaths(false)\n }\n }\n\n // extractPaths keeps the canonical orientation of each walk, and both\n // orientations are canonical when a walk starts and ends at one node in\n // opposite orientations, as through a hairpin; the twin of a reference walk\n // that is not canonical is kept too. Named, a twin is the same stretch of\n // the same path as another walk, read the other way, and the reverse one\n // goes.\n private dropTwins() {\n const refInfo =\n this.refId === undefined ? undefined : this.paths[this.refId]\n const interval = this.refInterval\n const span = (identity: PathIdentity) =>\n `${identity.pathHandle}:${identity.hapStart}-${identity.hapEnd}`\n const forward = new Set<string>()\n if (refInfo?.identity && interval) {\n forward.add(\n span({\n ...refInfo.identity,\n hapStart: interval[0],\n hapEnd: interval[1],\n }),\n )\n }\n for (const info of this.paths) {\n if (info !== refInfo && info.identity?.orientation === 'forward') {\n forward.add(span(info.identity))\n }\n }\n const kept = this.paths.filter(\n info =>\n info === refInfo ||\n info.identity?.orientation !== 'reverse' ||\n !forward.has(span(info.identity)),\n )\n if (kept.length < this.paths.length) {\n this.paths = kept\n this.refId = refInfo === undefined ? undefined : kept.indexOf(refInfo)\n }\n if (this.twinDeferred) {\n this.distinctPaths(false)\n }\n }\n\n // Narrows an identified subgraph to the reference walk and the named walks\n // `wanted` accepts, and drops every node only the discarded walks visited,\n // so a cut for a chosen set draws that set's private sequence and nothing\n // else's. It needs a name for every walk, since a walk without one could\n // belong to a wanted haplotype, and one walk per haplotype, since a record\n // of merged walks carries the name of one of them.\n keepHaplotypes(wanted: (name: PathName) => boolean) {\n if (this.paths.some(info => info.weight !== undefined)) {\n throw new Error(\n \"keepHaplotypes needs one walk per haplotype: extract with haplotypes 'all', then call mergeDistinct()\",\n )\n }\n const unnamed = this.paths.filter(\n (info, index) => index !== this.refId && info.identity === undefined,\n ).length\n if (unnamed > 0) {\n throw new Error(\n `${unnamed} of the window's ${this.paths.length} walks have no name, so the haplotypes to keep cannot be told from the rest; call identifyPaths() first, and check that the haplotype index was built for this graph`,\n )\n }\n const refInfo =\n this.refId === undefined ? undefined : this.paths[this.refId]\n const kept = this.paths.filter(\n (info, index) =>\n index === this.refId ||\n (info.identity !== undefined && wanted(info.identity.name)),\n )\n const visited = new Set<number>()\n for (const info of kept) {\n for (const handle of info.path) {\n visited.add(nodeId(handle))\n }\n }\n for (const handle of [...this.records.keys()]) {\n if (!visited.has(nodeId(handle))) {\n this.records.delete(handle)\n }\n }\n this.paths = kept\n this.refId = refInfo === undefined ? undefined : kept.indexOf(refInfo)\n }\n\n // The walks extractPaths and identifyPaths would give this subgraph for the\n // haplotypes `keep` accepts, found from the haplotype index without walking\n // the others. Returns false, leaving no walks, when the haplotype index\n // cannot show that the walks it found are all of them; the caller then\n // extracts and identifies every walk, and stats.keep.fallback says why.\n /** @internal */\n async extractChosenPaths(\n reference: ReferencePath,\n len: number,\n keep: (name: PathName) => boolean,\n context: number,\n ) {\n this.clearPaths()\n const start = reference.position.seqOffset\n const found = await findChosenPieces({\n db: this.db,\n records: this.records,\n referenceHandle: reference.handle,\n referencePos: {\n node: reference.position.handle,\n offset: reference.position.gbwtOffset,\n },\n referenceLeft: start - reference.position.nodeOffset,\n window: { start, end: start + len },\n context,\n snarls: {\n mode: this.snarlMode,\n fills: this.snarlFills,\n inserted: this.snarlNodes,\n },\n keep,\n signal: this.signal,\n prefetchReferenceRange: (pathHandle, fromOffset, toOffset) =>\n this.prefetchReferenceRange(pathHandle, fromOffset, toOffset),\n })\n this.stats.keep = found.stats\n if (found.stats.fallback !== undefined) {\n return false\n }\n const pathsByHandle = await this.db.pathsByHandle()\n const infoOf = (piece: ChosenPiece): PathInfo => ({\n path: piece.handles,\n offsets: piece.offsets,\n len: piece.len,\n weight: undefined,\n identity: {\n pathHandle: piece.pathHandle,\n name:\n piece === found.reference\n ? reference.name\n : pathsByHandle.get(piece.pathHandle)!.name,\n orientation: piece.orientation,\n hapStart: piece.hapStart,\n hapEnd: piece.hapEnd,\n },\n })\n const ordered = [found.reference, ...found.pieces].sort(extractionOrder)\n this.paths = ordered.map(infoOf)\n this.refId = ordered.indexOf(found.reference)\n this.refPath = reference.name\n this.refHandle = reference.handle\n this.refInterval = [found.reference.hapStart, found.reference.hapEnd]\n this.dropTwins()\n return true\n }\n\n async identifyPaths() {\n if (!this.db.hasHaplotypeIndex) {\n throw new Error(\n 'The database has no HaplotypeSamples table; run gbz-haplotype-index on it',\n )\n }\n if (this.unsettled) {\n ;({ paths: this.paths, refId: this.refId } = this.unsettled)\n this.unsettled = undefined\n this.twinDeferred = true\n }\n const interval = (await this.db.haplotypeSampleGap()) ?? 4096\n const runs = handleRuns(this.sortedHandles())\n if (runs.length === 0) {\n return\n }\n const samples = new Map<string, HaplotypeSample>()\n const fetched = await Promise.all(\n runs.map(([first, last]) => this.db.haplotypeSamplesInRange(first, last)),\n )\n for (const sample of fetched.flat()) {\n samples.set(posKey(sample), sample)\n }\n const scanned = (handle: number) => {\n let lo = 0\n let hi = runs.length - 1\n while (lo < hi) {\n const mid = (lo + hi + 1) >> 1\n if (runs[mid]![0] <= handle) {\n lo = mid\n } else {\n hi = mid - 1\n }\n }\n const run = runs[lo]!\n return run[0] <= handle && handle <= run[1]\n }\n const starts = new Map<string, number>()\n this.paths.forEach((info, index) => {\n if (info.path.length > 0 && index !== this.refId) {\n starts.set(posKey(pathPosition(info, 0)), index)\n }\n })\n const identification = this.stats.identification\n identification.interval = interval\n identification.scans = runs\n identification.windowSamples = samples.size\n this.paths.forEach((info, index) => {\n if (index !== this.refId) {\n identification.fragmentLengths.push(info.len)\n }\n })\n const readRecord = this.recordReader(() => {\n this.stats.identificationFetches += 1\n identification.graphFetches += 1\n })\n const recordAt = (handle: number) => {\n identification.graphLookups += 1\n return readRecord(handle)\n }\n const sampleAt = async (pos: Pos, chain: ChainRecord) => {\n if (scanned(pos.node)) {\n return samples.get(posKey(pos))\n }\n this.stats.identificationFetches += 1\n identification.companionSeeks += 1\n chain.seeks += 1\n const sample = await this.db.haplotypeSampleAt(pos.node, pos.offset)\n if (!sample) {\n identification.companionMisses += 1\n }\n return sample\n }\n const names = new Map<number, PathName>()\n const nameOf = async (pathHandle: number) => {\n let name = names.get(pathHandle)\n if (!name) {\n const path = await this.db.getPath(pathHandle)\n if (!path) {\n throw new Error(`Path ${pathHandle} is missing from the database`)\n }\n name = path.name\n names.set(pathHandle, name)\n }\n return name\n }\n const anchorFromSample = (\n sample: HaplotypeSample,\n counter: number,\n nodeLen: number,\n ): Anchor =>\n sample.orientation === 'forward'\n ? {\n pathHandle: sample.pathHandle,\n orientation: 'forward',\n base: sample.pathOffset - counter,\n }\n : {\n pathHandle: sample.pathHandle,\n orientation: 'reverse',\n base: sample.pathOffset + counter + nodeLen,\n }\n const anchorFromIdentity = (\n identity: PathIdentity,\n counter: number,\n ): Anchor =>\n identity.orientation === 'forward'\n ? {\n pathHandle: identity.pathHandle,\n orientation: 'forward',\n base: identity.hapStart - counter,\n }\n : {\n pathHandle: identity.pathHandle,\n orientation: 'reverse',\n base: identity.hapEnd + counter,\n }\n\n for (let start = 0; start < this.paths.length; start++) {\n const startInfo = this.paths[start]!\n if (start === this.refId || startInfo.identity) {\n continue\n }\n const chain: { index: number; startBp: number }[] = []\n const visited = new Set<number>()\n const record: ChainRecord = {\n fragments: 0,\n steps: 0,\n seeks: 0,\n reentries: 0,\n twinLandings: 0,\n end: 'endmarker',\n pathHandle: undefined,\n }\n identification.chains.push(record)\n let anchor: Anchor | undefined\n let counter = 0\n let current: number | undefined = start\n let pos: Pos | undefined\n while (anchor === undefined) {\n this.signal?.throwIfAborted()\n if (current !== undefined) {\n if (visited.has(current)) {\n record.end = 'cycle'\n break\n }\n visited.add(current)\n const info = this.paths[current]!\n chain.push({ index: current, startBp: counter })\n record.fragments += 1\n let bp = counter\n for (let k = 0; k < info.path.length; k++) {\n const position = pathPosition(info, k)\n const sample = samples.get(posKey(position))\n const nodeLen = this.record(position.node).sequenceLen\n if (sample) {\n anchor = anchorFromSample(sample, bp, nodeLen)\n break\n }\n bp += nodeLen\n }\n counter += info.len\n if (anchor) {\n record.end = 'in-fragment sample'\n break\n }\n const last = pathPosition(info, info.path.length - 1)\n pos = this.record(last.node).gbwt().lf(last.offset)\n current = undefined\n }\n if (pos === undefined || pos.node === ENDMARKER) {\n record.end = 'endmarker'\n break\n }\n const key = posKey(pos)\n const known = starts.get(key)\n if (known !== undefined) {\n const identity = this.paths[known]!.identity\n if (identity) {\n anchor = anchorFromIdentity(identity, counter)\n record.end = 'identified sibling'\n break\n }\n current = known\n continue\n }\n if (this.records.has(pos.node)) {\n record.reentries += 1\n }\n if (this.twinStarts.has(key)) {\n record.twinLandings += 1\n }\n const sample = await sampleAt(pos, record)\n const node = await recordAt(pos.node)\n if (sample) {\n anchor = anchorFromSample(sample, counter, node.sequenceLen)\n record.end = 'out-of-window sample'\n break\n }\n this.stats.identificationSteps += 1\n record.steps += 1\n if (\n counter - (chain[chain.length - 1] as { startBp: number }).startBp >\n 4 * interval + 4 * node.sequenceLen\n ) {\n record.end = 'bound'\n break\n }\n counter += node.sequenceLen\n pos = node.gbwt().lf(pos.offset)\n }\n if (anchor) {\n record.pathHandle = anchor.pathHandle\n const name = await nameOf(anchor.pathHandle)\n for (const { index, startBp } of chain) {\n const info = this.paths[index]!\n info.identity =\n anchor.orientation === 'forward'\n ? {\n pathHandle: anchor.pathHandle,\n name,\n orientation: 'forward',\n hapStart: anchor.base + startBp,\n hapEnd: anchor.base + startBp + info.len,\n }\n : {\n pathHandle: anchor.pathHandle,\n name,\n orientation: 'reverse',\n hapStart: anchor.base - startBp - info.len,\n hapEnd: anchor.base - startBp,\n }\n }\n }\n }\n this.dropTwins()\n }\n\n private refIndex(ref: number[]) {\n if (this.refIndexCache === undefined) {\n const index = new Map<number, number[]>()\n ref.forEach((handle, i) => {\n const occurrences = index.get(handle)\n if (occurrences) {\n occurrences.push(i)\n } else {\n index.set(handle, [i])\n }\n })\n this.refIndexCache = index\n }\n return this.refIndexCache\n }\n\n private refPrefix(ref: number[]) {\n if (this.refPrefixCache === undefined) {\n const prefix = [0]\n ref.forEach((handle, i) => {\n prefix.push(prefix[i]! + this.record(handle).sequenceLen)\n })\n this.refPrefixCache = prefix\n }\n return this.refPrefixCache\n }\n\n private orderedMatches(path: number[], ref: number[]): Matches | undefined {\n const index = this.refIndex(ref)\n const pathAt = new Int32Array(path.length)\n const refAt = new Int32Array(path.length)\n let count = 0\n let last = -1\n for (let i = 0; i < path.length; i++) {\n const occurrences = index.get(path[i]!)\n if (occurrences) {\n const j = firstAbove(occurrences, last)\n if (j === undefined) {\n return undefined\n }\n pathAt[count] = i\n refAt[count] = j\n count += 1\n last = j\n }\n }\n return { pathAt, refAt, count }\n }\n\n private pathLen(path: number[]) {\n let total = 0\n for (const handle of path) {\n total += this.record(handle).sequenceLen\n }\n return total\n }\n\n private prefixMatches(path: number[], ref: number[]) {\n let result = 0\n let pi = 0\n let ri = 0\n let pb = 0\n let rb = 0\n while (pi < path.length && ri < ref.length) {\n const a = this.record(path[pi]!).sequence\n const b = this.record(ref[ri]!).sequence\n while (pb < a.length && rb < b.length) {\n if (a[pb] !== b[rb]) {\n return result\n }\n pb += 1\n rb += 1\n result += 1\n }\n if (pb === a.length) {\n pi += 1\n pb = 0\n }\n if (rb === b.length) {\n ri += 1\n rb = 0\n }\n }\n return result\n }\n\n private suffixMatches(path: number[], ref: number[]) {\n let result = 0\n let pi = 0\n let ri = 0\n let pb = 0\n let rb = 0\n while (pi < path.length && ri < ref.length) {\n const a = this.record(path[path.length - pi - 1]!).sequence\n const b = this.record(ref[ref.length - ri - 1]!).sequence\n while (pb < a.length && rb < b.length) {\n if (a[a.length - pb - 1] !== b[b.length - rb - 1]) {\n return result\n }\n pb += 1\n rb += 1\n result += 1\n }\n if (pb === a.length) {\n pi += 1\n pb = 0\n }\n if (rb === b.length) {\n ri += 1\n rb = 0\n }\n }\n return result\n }\n\n private align(path: number[], ref: number[], edits: Edit[]) {\n const pathLen = this.pathLen(path)\n const refLen = this.pathLen(ref)\n const prefix = this.prefixMatches(path, ref)\n let suffix = this.suffixMatches(path, ref)\n if (prefix + suffix > pathLen) {\n suffix = pathLen - prefix\n }\n if (prefix + suffix > refLen) {\n suffix = refLen - prefix\n }\n appendEdit(edits, 'M', prefix)\n appendGap(edits, pathLen - prefix - suffix, refLen - prefix - suffix)\n appendEdit(edits, 'M', suffix)\n }\n\n private sharedWeight(path: number[], ref: number[]) {\n const index = this.refIndex(ref)\n let weight = 0\n for (const handle of path) {\n if (index.has(handle)) {\n weight += this.record(handle).sequenceLen\n }\n }\n return weight\n }\n\n private editsAgainst(path: number[], ref: number[]) {\n const ordered = this.orderedMatches(path, ref)\n if (ordered) {\n this.stats.orderedAlignments += 1\n } else {\n this.stats.lcsAlignments += 1\n }\n const lcs =\n ordered ??\n asMatches(\n weightedLcs(path, ref, handle => this.record(handle).sequenceLen)[0],\n )\n const edits: Edit[] = []\n const refPrefix = this.refPrefix(ref)\n const alignGap = (\n pathFrom: number,\n pathTo: number,\n refFrom: number,\n refTo: number,\n ) => {\n if (pathFrom === pathTo) {\n appendEdit(edits, 'D', refPrefix[refTo]! - refPrefix[refFrom]!)\n } else if (refFrom === refTo) {\n appendEdit(edits, 'I', this.pathLen(path.slice(pathFrom, pathTo)))\n } else {\n this.align(\n path.slice(pathFrom, pathTo),\n ref.slice(refFrom, refTo),\n edits,\n )\n }\n }\n let matched = 0\n let pathOffset = 0\n let refOffset = 0\n for (let m = 0; m < lcs.count; m++) {\n const nextPath = lcs.pathAt[m]!\n const nextRef = lcs.refAt[m]!\n // Adjacent matches are the overwhelming majority of a walk's steps, and\n // for those alignGap has nothing to append; only the gaps are worth a\n // call.\n if (pathOffset !== nextPath || refOffset !== nextRef) {\n alignGap(pathOffset, nextPath, refOffset, nextRef)\n }\n const nodeLen = this.record(path[nextPath]!).sequenceLen\n appendEdit(edits, 'M', nodeLen)\n matched += nodeLen\n pathOffset = nextPath + 1\n refOffset = nextRef + 1\n }\n alignGap(pathOffset, path.length, refOffset, ref.length)\n return { edits, matched, matches: lcs }\n }\n\n private alignment(pathIndex: number) {\n const info = this.paths[pathIndex]\n if (this.refId === undefined || pathIndex === this.refId || !info) {\n return undefined\n }\n const ref = this.paths[this.refId]!.path\n let result: { edits: Edit[]; matched: number; flipped: boolean }\n if (\n pathIsCanonical(ref) &&\n (info.identity === undefined || !pathIsCanonical(flipPath(info.path)))\n ) {\n // A canonical walk against a canonical reference has nothing to gain\n // from being flipped, so neither bound is worth the pass over its steps\n // that measuring one costs. A walk through a hairpin is canonical both\n // ways and either way aligns about half of it; once named, dropTwins\n // has left one of them, and it takes the better way. Unnamed, both are\n // walks as upstream prints them, each aligned as it stands.\n result = { ...this.editsAgainst(info.path, ref), flipped: false }\n } else {\n const flippedPath = flipPath(info.path)\n const forwardBound = this.sharedWeight(info.path, ref)\n const flippedBound = this.sharedWeight(flippedPath, ref)\n if (flippedBound === 0) {\n result = { ...this.editsAgainst(info.path, ref), flipped: false }\n } else if (forwardBound === 0) {\n result = { ...this.editsAgainst(flippedPath, ref), flipped: true }\n } else {\n const forward = this.editsAgainst(info.path, ref)\n const flipped = this.editsAgainst(flippedPath, ref)\n result =\n flipped.matched > forward.matched\n ? { ...flipped, flipped: true }\n : { ...forward, flipped: false }\n }\n }\n return result\n }\n\n /** @internal */\n alignToRef(pathIndex: number) {\n this.settleDeferred()\n return this.alignment(pathIndex)\n ?.edits.map(([op, len]) => `${len}${op}`)\n .join('')\n }\n\n alignments(): HaplotypeAlignment[] {\n this.settleDeferred()\n const reference = this.referenceInterval\n if (this.refId === undefined || !reference) {\n throw new Error('Alignments need a reference path')\n }\n const ref = this.paths[this.refId]!.path\n const refTotal = this.refPrefix(ref)[ref.length]!\n const fragment = (\n edits: Edit[],\n strand: '+' | '-',\n pieces: number[],\n soloAligned: number[],\n ): FragmentAlignment => {\n const trimmed = trimEnds(edits)\n const first = this.paths[pieces[0]!]!\n const last = this.paths[pieces[pieces.length - 1]!]!\n const identity = first.identity\n const walkForward = identity?.orientation === 'forward'\n const [low, high] = walkForward ? [first, last] : [last, first]\n return {\n strand,\n refStart: reference.start + trimmed.leading,\n refEnd: reference.start + refTotal - trimmed.trailing,\n edits: trimmed.edits,\n weight: first.weight,\n path: pieces.flatMap(index => this.paths[index]!.path),\n start: pathPosition(first, 0),\n pieces,\n soloAligned,\n identity:\n identity === undefined\n ? undefined\n : {\n pathHandle: identity.pathHandle,\n name: identity.name,\n hapStart: identity.name.fragment + low.identity!.hapStart,\n hapEnd: identity.name.fragment + high.identity!.hapEnd,\n walkForward,\n },\n }\n }\n // A walk that leaves the subgraph and comes back is two pieces here, and a\n // piece whose tail touches reference nodes past where the next piece\n // aligns cannot be joined after the fact. Aligned as one walk, with the\n // bases outside the subgraph as an insertion between the pieces, they read\n // as the detour they are. Each end of the join must be aligned over at\n // least half its length alone, which keeps out a pass hundreds of kb away\n // that the context reached through a rare edge, and must keep at least half\n // its aligned bases jointly, which keeps out the second pass of a collapsed\n // paralog. Pieces between the ends, often most of the detour, join with\n // them whatever their alignment.\n const aligned = (f: FragmentAlignment) =>\n f.soloAligned.reduce((sum, bases) => sum + bases, 0)\n const length = (f: FragmentAlignment) =>\n f.pieces.reduce((sum, index) => sum + this.paths[index]!.len, 0)\n const mostlyAligned = (f: FragmentAlignment) => 2 * aligned(f) >= length(f)\n const alignJointly = (parts: FragmentAlignment[]) => {\n const first = parts[0]!\n const last = parts[parts.length - 1]!\n const walkForward = first.identity!.walkForward\n if (\n parts.some(\n (part, k) =>\n part.strand !== first.strand ||\n part.identity!.walkForward !== walkForward ||\n (k > 0 && part.identity!.hapStart < parts[k - 1]!.identity!.hapEnd),\n )\n ) {\n return undefined\n }\n const inWalkOrder = walkForward ? parts : [...parts].reverse()\n const pieces = inWalkOrder.flatMap(part => part.pieces)\n const soloAligned = inWalkOrder.flatMap(part => part.soloAligned)\n const flipped = (first.strand === '+') !== walkForward\n const infos = pieces.map(index => this.paths[index]!)\n const gaps = infos.slice(1).map((info, k) => {\n const before = infos[k]!.identity!\n return walkForward\n ? info.identity!.hapStart - before.hapEnd\n : before.hapStart - info.identity!.hapEnd\n })\n const alignedInfos = flipped ? [...infos].reverse() : infos\n const alignedGaps = flipped ? [...gaps].reverse() : gaps\n const steps = alignedInfos.flatMap(info =>\n flipped ? flipPath(info.path) : info.path,\n )\n const { edits } = this.editsAgainst(steps, ref)\n const keptInOrder = alignedIn(\n edits,\n alignedInfos.map(info => info.len),\n )\n const kept = new Map(\n (flipped ? [...pieces].reverse() : pieces).map((index, k) => [\n index,\n keptInOrder[k]!,\n ]),\n )\n const keeps = (part: FragmentAlignment) =>\n 2 * part.pieces.reduce((sum, index) => sum + kept.get(index)!, 0) >=\n aligned(part)\n if (!keeps(first) || !keeps(last)) {\n return undefined\n }\n const insertions: [number, number][] = []\n let walked = 0\n alignedInfos.slice(0, -1).forEach((info, k) => {\n walked += info.len\n insertions.push([walked, alignedGaps[k]!])\n })\n return fragment(\n spliceInsertions(edits, insertions),\n first.strand,\n pieces,\n soloAligned,\n )\n }\n const fragments: FragmentAlignment[] = []\n this.paths.forEach((info, index) => {\n if (index === this.refId) {\n return\n }\n const { edits, flipped } = this.alignment(index)!\n const identity = info.identity\n const alongReference = identity\n ? (identity.orientation === 'forward') !== flipped\n : !flipped\n fragments.push(\n fragment(\n edits,\n alongReference ? '+' : '-',\n [index],\n alignedIn(edits, [info.len]),\n ),\n )\n })\n return joinSiblings(fragments, mostlyAligned, alignJointly).map(joined => {\n const { edits, identity, pieces, soloAligned, ...rest } = joined\n const span: AlignmentSpan = { ...rest, cigar: cigarOf(edits) }\n return identity\n ? {\n ...span,\n resolved: true,\n name: identity.name,\n label: formatPathName({\n ...identity.name,\n fragment: identity.hapStart,\n end: identity.hapEnd,\n }),\n pathHandle: identity.pathHandle,\n hapStart: identity.hapStart,\n hapEnd: identity.hapEnd,\n }\n : { ...span, resolved: false }\n })\n }\n\n // One haplotype's walks aligned to another's, on both haplotypes' own\n // coordinates, with the bases between two shared nodes compared unless bases\n // is false. The reference path is a named walk like any other, on either\n // side. With no query, every other named walk in the window is one.\n pairAlignments(opts: PairAlignmentOptions): PairAlignment[] {\n const { target, query, ...pairOptions } = opts\n const walks = this.paths.flatMap(info => {\n const { identity } = info\n return identity\n ? [\n {\n name: identity.name,\n start: identity.name.fragment + identity.hapStart,\n steps: haplotypeOrderedPath(info, identity),\n },\n ]\n : []\n })\n const names = (haplotype: HaplotypeRef) => (name: PathName) =>\n name.sample === haplotype.sample && name.haplotype === haplotype.haplotype\n const isTarget = names(target)\n const isQuery = query ? names(query) : (name: PathName) => !isTarget(name)\n const sequenceOf = (id: number) =>\n this.record(encodeNode(id, 'forward')).sequence\n return walks\n .filter(walk => isTarget(walk.name))\n .flatMap(targetWalk =>\n walks\n .filter(walk => isQuery(walk.name))\n .flatMap(queryWalk =>\n pairAlignments({\n ...pairOptions,\n query: queryWalk.steps,\n target: targetWalk.steps,\n sequenceOf,\n }).map(chain => ({\n query: queryWalk.name,\n queryStart: queryWalk.start + chain.queryStart,\n queryEnd: queryWalk.start + chain.queryEnd,\n strand: chain.strand,\n target: targetWalk.name,\n targetStart: targetWalk.start + chain.targetStart,\n targetEnd: targetWalk.start + chain.targetEnd,\n cigar: pairCigar(chain.edits),\n matches: chain.edits.reduce(\n (sum, [op, len]) => sum + (op === '=' ? len : 0),\n 0,\n ),\n columns: chain.edits.reduce((sum, [, len]) => sum + len, 0),\n sharedBases: chain.sharedBases,\n })),\n ),\n )\n }\n\n private canonicalEdges(id: number) {\n const edges: [number, number, number][] = []\n for (const orientation of ['forward', 'reverse'] as const) {\n const handle = encodeNode(id, orientation)\n for (const successor of this.record(handle).successors()) {\n if (this.hasHandle(successor) && edgeIsCanonical(handle, successor)) {\n edges.push([\n orientation === 'reverse' ? 1 : 0,\n nodeId(successor),\n isReverse(successor) ? 1 : 0,\n ])\n }\n }\n }\n edges.sort((a, b) => a[0] - b[0] || a[1] - b[1] || a[2] - b[2])\n return edges.filter(\n (edge, i) =>\n i === 0 ||\n edge[0] !== edges[i - 1]![0] ||\n edge[1] !== edges[i - 1]![1] ||\n edge[2] !== edges[i - 1]![2],\n )\n }\n\n async stableName() {\n const encoder = new TextEncoder()\n const chunks: Uint8Array[] = []\n for (const handle of this.sortedHandles()) {\n if (!isReverse(handle)) {\n const id = nodeId(handle)\n let text = `S\\t${id}\\t${this.record(handle).sequence}\\n`\n for (const [fromReverse, toId, toReverse] of this.canonicalEdges(id)) {\n text += `L\\t${id}\\t${fromReverse ? '-' : '+'}\\t${toId}\\t${toReverse ? '-' : '+'}\\n`\n }\n chunks.push(encoder.encode(text))\n }\n }\n return sha256Hex(chunks)\n }\n\n async toGFA(opts: SubgraphOutputOptions = {}) {\n this.settleDeferred()\n const cigar = opts.cigar ?? false\n const lines = [\n this.refPath ? `H\\tVN:Z:1.1\\tRS:Z:${this.refPath.sample}` : 'H\\tVN:Z:1.1',\n ...gfaHeaderLines(\n subgraphName(await this.stableName(), await this.db.graphName()),\n ),\n ]\n const handles = this.sortedHandles()\n for (const handle of handles) {\n if (!isReverse(handle)) {\n lines.push(`S\\t${nodeId(handle)}\\t${this.record(handle).sequence}`)\n }\n }\n const sign = (handle: number) => (isReverse(handle) ? '-' : '+')\n for (const handle of handles) {\n for (const successor of this.record(handle).successors()) {\n if (this.hasHandle(successor) && edgeIsCanonical(handle, successor)) {\n lines.push(\n `L\\t${nodeId(handle)}\\t${sign(handle)}\\t${nodeId(successor)}\\t${sign(successor)}\\t0M`,\n )\n }\n }\n }\n const walk = (\n info: PathInfo,\n identity: PathIdentity | undefined,\n name: PathName,\n end: number,\n cigarString: string | undefined,\n ) => {\n const steps = haplotypeOrderedPath(info, identity)\n .map(handle => `${isReverse(handle) ? '<' : '>'}${nodeId(handle)}`)\n .join('')\n const weight = info.weight === undefined ? '' : `\\tWT:i:${info.weight}`\n const cg = cigarString === undefined ? '' : `\\tCG:Z:${cigarString}`\n return `W\\t${name.sample}\\t${name.haplotype}\\t${name.contig}\\t${name.fragment}\\t${end}\\t${steps}${weight}${cg}`\n }\n const contig = this.refPath?.contig ?? 'unknown'\n if (this.refId !== undefined && this.refPath && this.refInterval) {\n lines.push(\n walk(\n this.paths[this.refId]!,\n undefined,\n {\n ...this.refPath,\n fragment: this.refPath.fragment + this.refInterval[0],\n },\n this.refPath.fragment + this.refInterval[1],\n undefined,\n ),\n )\n }\n let haplotype = 1\n this.paths.forEach((info, index) => {\n if (index !== this.refId) {\n const resolved = opts.names !== 'anonymous' ? info.identity : undefined\n const cigarString = cigar ? this.alignToRef(index) : undefined\n lines.push(\n resolved\n ? walk(\n info,\n resolved,\n {\n ...resolved.name,\n fragment: resolved.name.fragment + resolved.hapStart,\n },\n resolved.name.fragment + resolved.hapEnd,\n cigarString,\n )\n : walk(\n info,\n undefined,\n { sample: 'unknown', contig, haplotype, fragment: 0 },\n info.len,\n cigarString,\n ),\n )\n haplotype += 1\n }\n })\n return `${lines.join('\\n')}\\n`\n }\n\n // The reference walk first under the interval it covers, then one entry per\n // haplotype in extraction order. Both outputs read this so a name, a weight\n // or a CIGAR cannot mean one thing in the upstream JSON and another in the\n // compact form.\n private outputPaths(opts: SubgraphOutputOptions) {\n this.settleDeferred()\n const cigar = opts.cigar ?? false\n const entries: {\n info: PathInfo\n identity: PathIdentity | undefined\n name: string\n cigar: string | undefined\n }[] = []\n const contig = this.refPath?.contig ?? 'unknown'\n if (this.refId !== undefined && this.refPath && this.refInterval) {\n const start = {\n ...this.refPath,\n fragment: this.refPath.fragment + this.refInterval[0],\n }\n entries.push({\n info: this.paths[this.refId]!,\n identity: undefined,\n name: formatPathName({\n ...start,\n end: this.refPath.fragment + this.refInterval[1],\n }),\n cigar: undefined,\n })\n }\n let haplotype = 1\n this.paths.forEach((info, index) => {\n if (index === this.refId) {\n return\n }\n const identity = opts.names !== 'anonymous' ? info.identity : undefined\n entries.push({\n info,\n identity,\n name: identity\n ? formatPathName({\n ...identity.name,\n fragment: identity.name.fragment + identity.hapStart,\n end: identity.name.fragment + identity.hapEnd,\n })\n : formatPathName({\n sample: 'unknown',\n contig,\n haplotype,\n fragment: 0,\n end: info.len,\n }),\n cigar: cigar ? this.alignToRef(index) : undefined,\n })\n haplotype += 1\n })\n return entries\n }\n\n private *outputEdges() {\n for (const handle of this.sortedHandles()) {\n for (const successor of this.record(handle).successors()) {\n if (this.hasHandle(successor) && edgeIsCanonical(handle, successor)) {\n yield [handle, successor] as const\n }\n }\n }\n }\n\n toSubgraphJson(opts: SubgraphOutputOptions = {}): SubgraphJson {\n const nodes = this.sortedHandles()\n .filter(handle => !isReverse(handle))\n .map(handle => ({\n id: String(nodeId(handle)),\n sequence: this.record(handle).sequence,\n }))\n const edges: SubgraphJson['edges'] = []\n for (const [from, to] of this.outputEdges()) {\n edges.push({\n from: String(nodeId(from)),\n from_is_reverse: isReverse(from),\n to: String(nodeId(to)),\n to_is_reverse: isReverse(to),\n })\n }\n const paths = this.outputPaths(opts).map(entry =>\n jsonPath(entry.info, entry.identity, entry.name, entry.cigar),\n )\n return { nodes, edges, paths }\n }\n\n // The same subgraph as typed arrays of GBWT handles. toSubgraphJson spends\n // an object and a stringified id on every step of every walk, which a\n // 200 kb human window has about 350,000 of; this hands back the numbers the\n // extraction already holds, so it survives a structured clone into a worker\n // for about the cost of the memcpy rather than of rebuilding the objects.\n // Measured on HPRC chr20 CHM13#0#chr20 30.0-30.2 Mb, 5,943 nodes and 178\n // haplotypes: 295 ms to clone the upstream shape against 1.9 ms for this one.\n //\n // Packing the other two fields the way bam-js packs NUMERIC_SEQ and\n // NUMERIC_CIGAR was measured on the same window and rejected, because what\n // pays there is a long per-record field and both of these are short. Node\n // sequences average 34 bp: base-6 bytes plus offsets are 2.86x smaller but\n // cost more to build than to hand over the cached strings (1.07 ms against\n // 0.95 ms all in), and a consumer drawing the graph wants the strings for\n // every node anyway. CIGARs average 323 chars over 17,555 total ops: packing\n // them into one Int32Array per path is 1.7 ms against 2.4 ms to join the\n // strings, but then clones SLOWER (0.20 ms against 0.09 ms) because 178 small\n // typed arrays cost more than 178 strings. Steps are the only field here long\n // enough to be worth it. The CIGAR phase is 103 ms of edit computation and\n // 2 ms of string building, so neither field is where that time goes.\n toCompactSubgraph(opts: SubgraphOutputOptions = {}): CompactSubgraph {\n const forward = this.sortedHandles().filter(handle => !isReverse(handle))\n const nodeIds = new Int32Array(forward.length)\n const nodeSequences: string[] = []\n forward.forEach((handle, i) => {\n nodeIds[i] = nodeId(handle)\n nodeSequences.push(this.record(handle).sequence)\n })\n const edgeHandles: number[] = []\n for (const [from, to] of this.outputEdges()) {\n edgeHandles.push(from, to)\n }\n return {\n nodeIds,\n nodeSequences,\n edges: Int32Array.from(edgeHandles),\n paths: this.outputPaths(opts).map(entry => ({\n name: entry.name,\n weight: entry.info.weight,\n cigar: entry.cigar,\n steps: Int32Array.from(\n haplotypeOrderedPath(entry.info, entry.identity),\n ),\n })),\n }\n }\n}\n\n// The buffers a CompactSubgraph owns outright, for the transfer list of a\n// postMessage that hands it to another thread. Transferring detaches them, so\n// the sending side must not read the subgraph afterwards.\nexport function compactSubgraphTransferables(subgraph: CompactSubgraph) {\n return [\n subgraph.nodeIds.buffer,\n subgraph.edges.buffer,\n ...subgraph.paths.map(path => path.steps.buffer),\n ]\n}\n\n// A named walk lists its steps in the haplotype's own direction, as the W line\n// spec and the start..end coordinates beside it require. extractPaths keeps\n// whichever twin of a walk is canonical, which is a property of the handles\n// and not of the haplotype, so the kept walk runs against the haplotype for\n// about half of them; identification records which.\nfunction haplotypeOrderedPath(\n info: PathInfo,\n identity: PathIdentity | undefined,\n) {\n return identity?.orientation === 'reverse'\n ? info.path.map(handle => flipNode(handle)).reverse()\n : info.path\n}\n\nfunction jsonPath(\n info: PathInfo,\n identity: PathIdentity | undefined,\n name: string,\n cigar: string | undefined,\n): SubgraphPath {\n return {\n name,\n ...(info.weight === undefined ? {} : { weight: info.weight }),\n ...(cigar === undefined ? {} : { cigar }),\n path: haplotypeOrderedPath(info, identity).map(handle => ({\n id: String(nodeId(handle)),\n is_reverse: isReverse(handle),\n })),\n }\n}\n\nfunction comparePaths(a: number[], b: number[]) {\n const n = Math.min(a.length, b.length)\n for (let i = 0; i < n; i++) {\n const x = a[i]!\n const y = b[i]!\n if (x !== y) {\n return x < y ? -1 : 1\n }\n }\n return a.length - b.length\n}\n\nfunction appendEdit(edits: Edit[], op: EditOp, len: number) {\n if (len === 0) {\n return\n }\n const last = edits[edits.length - 1]\n if (last?.[0] === op) {\n last[1] += len\n } else {\n edits.push([op, len])\n }\n}\n\nfunction gapPenalty(len: number) {\n return len === 0 ? 0 : 6 + (len - 1)\n}\n\nfunction appendGap(edits: Edit[], pathMiddle: number, refMiddle: number) {\n if (pathMiddle === 0) {\n appendEdit(edits, 'D', refMiddle)\n } else if (refMiddle === 0) {\n appendEdit(edits, 'I', pathMiddle)\n } else {\n const mismatch = Math.min(pathMiddle, refMiddle)\n const mismatchIndel =\n 4 * mismatch +\n gapPenalty(pathMiddle - mismatch) +\n gapPenalty(refMiddle - mismatch)\n const insertionDeletion = gapPenalty(pathMiddle) + gapPenalty(refMiddle)\n if (mismatchIndel <= insertionDeletion) {\n appendEdit(edits, 'M', mismatch)\n appendEdit(edits, 'I', pathMiddle - mismatch)\n appendEdit(edits, 'D', refMiddle - mismatch)\n } else {\n appendEdit(edits, 'I', pathMiddle)\n appendEdit(edits, 'D', refMiddle)\n }\n }\n}\n\n// A record starts and ends at an aligned base: the deletions in a run of\n// insertions and deletions at either end move its reference start or end, and\n// the insertions stay. An alignment with no aligned base keeps its insertion at\n// the reference start.\nfunction trimEnds(edits: Edit[]) {\n let first = 0\n while (first < edits.length && edits[first]![0] !== 'M') {\n first += 1\n }\n if (first === edits.length) {\n const inserted = edits.filter(([op]) => op === 'I')\n const trailing = edits\n .filter(([op]) => op === 'D')\n .reduce((sum, [, len]) => sum + len, 0)\n return {\n edits: inserted.map(([op, len]): Edit => [op, len]),\n leading: 0,\n trailing,\n }\n }\n let last = edits.length\n while (edits[last - 1]![0] !== 'M') {\n last -= 1\n }\n const ends = (run: Edit[]) => ({\n inserted: run.reduce((sum, [op, len]) => sum + (op === 'I' ? len : 0), 0),\n deleted: run.reduce((sum, [op, len]) => sum + (op === 'D' ? len : 0), 0),\n })\n const head = ends(edits.slice(0, first))\n const tail = ends(edits.slice(last))\n const trimmed: Edit[] = []\n appendEdit(trimmed, 'I', head.inserted)\n for (const [op, len] of edits.slice(first, last)) {\n appendEdit(trimmed, op, len)\n }\n appendEdit(trimmed, 'I', tail.inserted)\n return { edits: trimmed, leading: head.deleted, trailing: tail.deleted }\n}\n\n// The bases the CIGAR aligns within each of consecutive stretches of the walk.\nfunction alignedIn(edits: Edit[], lengths: number[]) {\n const aligned = lengths.map(() => 0)\n const last = lengths.length - 1\n let piece = 0\n let pieceEnd = lengths[0]!\n let walked = 0\n for (const [op, len] of edits) {\n if (op === 'D') {\n continue\n }\n let rest = len\n while (rest > 0) {\n while (piece < last && walked >= pieceEnd) {\n piece += 1\n pieceEnd += lengths[piece]!\n }\n const step = piece < last ? Math.min(rest, pieceEnd - walked) : rest\n if (op === 'M') {\n aligned[piece]! += step\n }\n walked += step\n rest -= step\n }\n }\n return aligned\n}\n\n// Insertions at walk offsets, after any deletions that end at the same offset.\nfunction spliceInsertions(edits: Edit[], insertions: [number, number][]) {\n const spliced: Edit[] = []\n let walked = 0\n let next = 0\n for (const [op, len] of edits) {\n if (op === 'D') {\n appendEdit(spliced, op, len)\n continue\n }\n let from = walked\n while (next < insertions.length && insertions[next]![0] < walked + len) {\n const [at, inserted] = insertions[next]!\n appendEdit(spliced, op, at - from)\n appendEdit(spliced, 'I', inserted)\n from = at\n next += 1\n }\n appendEdit(spliced, op, walked + len - from)\n walked += len\n }\n for (; next < insertions.length; next++) {\n appendEdit(spliced, 'I', insertions[next]![1])\n }\n return spliced\n}\n\nfunction cigarOf(edits: Edit[]) {\n return edits.map(([op, len]) => `${len}${op}`).join('')\n}\n", "import { pathNameFor, toPathQuery } from './pathName.ts'\nimport { Subgraph, SubgraphLimitError } from './subgraph.ts'\n\nimport type { GBZBase } from './db.ts'\nimport type { PathName, PathRef } from './pathName.ts'\nimport type { HaplotypeOutput, SnarlOutput } from './subgraph.ts'\n\nexport interface QueryOptions {\n context?: number | undefined\n haplotypes?: HaplotypeOutput | undefined\n snarls?: SnarlOutput | undefined\n limit?: number | undefined\n signal?: AbortSignal | undefined\n}\n\nexport interface PathWindow {\n path: PathRef\n start: number\n end: number\n}\n\nexport interface IntervalQuery extends PathWindow, QueryOptions {\n keep?: ((name: PathName) => boolean) | undefined\n}\n\nexport interface OffsetQuery extends QueryOptions {\n path: PathRef\n offset: number\n}\n\nexport type NodeHaplotypeOutput = Exclude<HaplotypeOutput, 'reference-only'>\n\nexport interface NodesQuery extends Omit<QueryOptions, 'haplotypes'> {\n nodeIds: number[]\n haplotypes?: NodeHaplotypeOutput | undefined\n}\n\nexport interface BetweenQuery {\n startHandle: number\n endHandle: number\n haplotypes?: NodeHaplotypeOutput | undefined\n limit?: number | undefined\n signal?: AbortSignal | undefined\n}\n\nfunction wholeNumber(name: string, value: number, min = 0) {\n if (!Number.isSafeInteger(value) || value < min) {\n throw new Error(\n `${name} must be a whole number${min > 0 ? ` of at least ${min}` : ''}, not ${value}`,\n )\n }\n return value\n}\n\nfunction contextOf(opts: QueryOptions) {\n return wholeNumber('context', opts.context ?? 100)\n}\n\nfunction createSubgraph(db: GBZBase, opts: QueryOptions | BetweenQuery) {\n if (opts.limit !== undefined) {\n wholeNumber('limit', opts.limit)\n }\n return Subgraph.create(db, opts)\n}\n\nexport async function subgraphAtOffset(db: GBZBase, opts: OffsetQuery) {\n const context = contextOf(opts)\n const subgraph = createSubgraph(db, opts)\n const reference = await subgraph.pathPosition(\n pathNameFor(toPathQuery(opts.path), wholeNumber('offset', opts.offset)),\n )\n await subgraph.aroundPosition(\n reference.position.handle,\n reference.position.nodeOffset,\n context,\n )\n await subgraph.extractSnarls(opts.snarls ?? 'none')\n subgraph.extractPaths(reference, opts.haplotypes ?? 'all')\n return subgraph\n}\n\n// The subgraph both routes read a window from: the reference walk through it,\n// `context` bp around that, and the snarls `snarls` selects.\nasync function aroundWindow(db: GBZBase, opts: IntervalQuery) {\n const start = wholeNumber('start', opts.start)\n const end = wholeNumber('end', opts.end)\n const context = contextOf(opts)\n const subgraph = createSubgraph(db, opts)\n try {\n const reference = await subgraph.pathPosition(\n pathNameFor(toPathQuery(opts.path), start),\n )\n await subgraph.prefetchReferenceWalk(reference, end - start)\n await subgraph.aroundInterval(reference.position, end - start, context)\n await subgraph.extractSnarls(opts.snarls ?? 'none')\n return { subgraph, reference }\n } catch (error) {\n throw error instanceof SubgraphLimitError && error.windowBp === undefined\n ? new SubgraphLimitError(error.limit, {\n windowBp: end - start,\n walkedBp: subgraph.referenceWalkedBp ?? 0,\n })\n : error\n }\n}\n\n// With `keep`, the window for a chosen set of haplotypes: the same subgraph and\n// the same walks as the sampled route narrowed by keepHaplotypes, found from\n// the haplotype index without walking the haplotypes `keep` rejects, or by\n// extracting and identifying every walk when the index cannot show those walks\n// complete. 'distinct' merges the kept walks afterwards, so its weights count\n// kept haplotypes.\nexport async function subgraphInInterval(db: GBZBase, opts: IntervalQuery) {\n const { keep } = opts\n const haplotypes = opts.haplotypes ?? 'all'\n const named = haplotypes === 'all' || haplotypes === 'distinct'\n if (keep !== undefined && named && !db.hasHaplotypeIndex) {\n throw new Error(\n 'keep needs the haplotype index: this database cannot name its walks',\n )\n }\n const { subgraph, reference } = await aroundWindow(db, opts)\n if (keep === undefined || !named) {\n subgraph.extractPaths(reference, haplotypes)\n return subgraph\n }\n if (\n !(await subgraph.extractChosenPaths(\n reference,\n opts.end - opts.start,\n keep,\n contextOf(opts),\n ))\n ) {\n subgraph.extractPaths(reference, 'all')\n await subgraph.identifyPaths()\n }\n subgraph.keepHaplotypes(keep)\n if (haplotypes === 'distinct') {\n subgraph.mergeDistinct()\n }\n return subgraph\n}\n\nexport async function subgraphAroundNodes(db: GBZBase, opts: NodesQuery) {\n const haplotypes = (opts.haplotypes ?? 'all') as HaplotypeOutput\n const snarls = opts.snarls ?? 'none'\n if (haplotypes === 'reference-only') {\n throw new Error('Cannot output a reference path in a node-based query')\n }\n if (snarls === 'overlapping' && new Set(opts.nodeIds).size > 1) {\n throw new Error(\n 'Overlapping snarls cannot be extracted for a node-based query with multiple nodes',\n )\n }\n const context = contextOf(opts)\n for (const id of opts.nodeIds) {\n wholeNumber('node id', id, 1)\n }\n const subgraph = createSubgraph(db, opts)\n await subgraph.aroundNodes(opts.nodeIds, context)\n await subgraph.extractSnarls(snarls)\n subgraph.extractPaths(undefined, haplotypes)\n return subgraph\n}\n\nexport async function subgraphBetween(db: GBZBase, opts: BetweenQuery) {\n const haplotypes = (opts.haplotypes ?? 'all') as HaplotypeOutput\n if (haplotypes === 'reference-only') {\n throw new Error('Cannot output a reference path in a node-based query')\n }\n const subgraph = createSubgraph(db, opts)\n await subgraph.betweenNodes(\n wholeNumber('startHandle', opts.startHandle, 2),\n wholeNumber('endHandle', opts.endHandle, 2),\n )\n subgraph.extractPaths(undefined, haplotypes)\n return subgraph\n}\n", "export type SqlValue = null | number | string | Uint8Array\n\nexport function readVarint(\n bytes: Uint8Array,\n offset: number,\n): [value: number, next: number] {\n let value = 0\n for (let i = 0; i < 8; i++) {\n const byte = bytes[offset + i]\n if (byte === undefined) {\n throw new Error('SQLite varint runs past the end of the buffer')\n }\n value = value * 128 + (byte & 0x7f)\n if ((byte & 0x80) === 0) {\n if (i === 7 && !Number.isSafeInteger(value)) {\n throw new Error('SQLite varint exceeds the safe integer range')\n }\n return [value, offset + i + 1]\n }\n }\n const last = bytes[offset + 8]\n if (last === undefined) {\n throw new Error('SQLite varint runs past the end of the buffer')\n }\n value = value * 256 + last\n if (!Number.isSafeInteger(value)) {\n throw new Error('SQLite varint exceeds the safe integer range')\n }\n return [value, offset + 9]\n}\n\nfunction readSignedInt(view: DataView, offset: number, width: number) {\n switch (width) {\n case 1:\n return view.getInt8(offset)\n case 2:\n return view.getInt16(offset)\n case 3:\n return (view.getInt8(offset) << 16) | view.getUint16(offset + 1)\n case 4:\n return view.getInt32(offset)\n case 6:\n return view.getInt16(offset) * 4294967296 + view.getUint32(offset + 2)\n default: {\n const big = view.getBigInt64(offset)\n if (\n big > BigInt(Number.MAX_SAFE_INTEGER) ||\n big < BigInt(Number.MIN_SAFE_INTEGER)\n ) {\n throw new Error(`SQLite integer ${big} exceeds the safe integer range`)\n }\n return Number(big)\n }\n }\n}\n\nconst decoder = new TextDecoder()\n\nexport function decodeRecord(payload: Uint8Array): SqlValue[] {\n const [headerSize, firstType] = readVarint(payload, 0)\n const types: number[] = []\n let offset = firstType\n while (offset < headerSize) {\n const [type, next] = readVarint(payload, offset)\n types.push(type)\n offset = next\n }\n const view = new DataView(\n payload.buffer,\n payload.byteOffset,\n payload.byteLength,\n )\n let body = headerSize\n return types.map(type => {\n if (type === 0) {\n return null\n }\n if (type >= 1 && type <= 6) {\n const width = type <= 4 ? type : type === 5 ? 6 : 8\n const value = readSignedInt(view, body, width)\n body += width\n return value\n }\n if (type === 7) {\n const value = view.getFloat64(body)\n body += 8\n return value\n }\n if (type === 8) {\n return 0\n }\n if (type === 9) {\n return 1\n }\n if (type >= 12) {\n const length = (type - 12) >> 1\n const slice = payload.subarray(body, body + length)\n body += length\n return type % 2 === 0 ? slice : decoder.decode(slice)\n }\n throw new Error(`SQLite serial type ${type} is reserved`)\n })\n}\n", "import { decodeRecord, readVarint } from './record.ts'\n\nimport type { Pager } from './pager.ts'\nimport type { SqlValue } from './record.ts'\n\nconst INTERIOR_INDEX = 0x02\nconst INTERIOR_TABLE = 0x05\nconst LEAF_INDEX = 0x0a\nconst LEAF_TABLE = 0x0d\n\ninterface PageHeader {\n type: number\n cellCount: number\n rightChild: number\n cellPointers: number\n}\n\nfunction readUint16(page: Uint8Array, offset: number) {\n return page[offset]! * 256 + page[offset + 1]!\n}\n\nfunction readUint32(page: Uint8Array, offset: number) {\n return (\n page[offset]! * 16777216 +\n page[offset + 1]! * 65536 +\n page[offset + 2]! * 256 +\n page[offset + 3]!\n )\n}\n\nfunction readHeader(page: Uint8Array, start: number): PageHeader {\n const type = page[start]\n if (\n type !== INTERIOR_INDEX &&\n type !== INTERIOR_TABLE &&\n type !== LEAF_INDEX &&\n type !== LEAF_TABLE\n ) {\n throw new Error(`SQLite page has unknown b-tree type ${type}`)\n }\n const interior = type === INTERIOR_INDEX || type === INTERIOR_TABLE\n return {\n type,\n cellCount: readUint16(page, start + 3),\n rightChild: interior ? readUint32(page, start + 8) : 0,\n cellPointers: start + (interior ? 12 : 8),\n }\n}\n\nfunction cellOffset(page: Uint8Array, header: PageHeader, index: number) {\n return readUint16(page, header.cellPointers + 2 * index)\n}\n\ninterface IndexCell {\n values: SqlValue[]\n leftChild: number\n}\n\nconst MAX_DECODED_INDEX_PAGES = 4096\n\nexport class BTree {\n private readonly usable: number\n private pager: Pager\n private decodedIndexPages = new Map<number, (IndexCell | undefined)[]>()\n private tableDepths = new Map<number, Promise<number>>()\n\n constructor(pager: Pager, reservedBytes: number) {\n this.pager = pager\n this.usable = pager.pageSize - reservedBytes\n }\n\n private localPayloadSize(total: number, isIndex: boolean) {\n const usable = this.usable\n const maxLocal = isIndex\n ? Math.floor(((usable - 12) * 64) / 255) - 23\n : usable - 35\n if (total <= maxLocal) {\n return total\n }\n const minLocal = Math.floor(((usable - 12) * 32) / 255) - 23\n const spill = minLocal + ((total - minLocal) % (usable - 4))\n return spill <= maxLocal ? spill : minLocal\n }\n\n private async payload(\n page: Uint8Array,\n offset: number,\n total: number,\n isIndex: boolean,\n ) {\n const local = this.localPayloadSize(total, isIndex)\n if (local === total) {\n return page.subarray(offset, offset + total)\n }\n const result = new Uint8Array(total)\n result.set(page.subarray(offset, offset + local), 0)\n let filled = local\n let next = readUint32(page, offset + local)\n while (next !== 0 && filled < total) {\n const overflow = await this.pager.page(next)\n const chunk = overflow.subarray(\n 4,\n 4 + Math.min(this.usable - 4, total - filled),\n )\n result.set(chunk, filled)\n filled += chunk.length\n next = readUint32(overflow, 0)\n }\n if (filled !== total) {\n throw new Error(\n 'SQLite overflow chain ended before the payload was complete',\n )\n }\n return result\n }\n\n private async pageAt(pageNumber: number) {\n const page = await this.pager.page(pageNumber)\n return { page, header: readHeader(page, pageNumber === 1 ? 100 : 0) }\n }\n\n private tableDepth(root: number, towards: number) {\n let depth = this.tableDepths.get(root)\n if (!depth) {\n depth = (async () => {\n let pageNumber = root\n for (let level = 0; ; level++) {\n const { page, header } = await this.pageAt(pageNumber)\n if (header.type === LEAF_TABLE) {\n return level\n }\n if (header.type !== INTERIOR_TABLE) {\n throw new Error('SQLite table b-tree contains an index page')\n }\n const child = this.childIndexFor(page, header, towards)\n pageNumber =\n child === header.cellCount\n ? header.rightChild\n : readUint32(page, cellOffset(page, header, child))\n }\n })()\n this.tableDepths.set(root, depth)\n depth.catch(() => this.tableDepths.delete(root))\n }\n return depth\n }\n\n private childIndexFor(page: Uint8Array, header: PageHeader, rowid: number) {\n let low = 0\n let high = header.cellCount\n while (low < high) {\n const mid = (low + high) >> 1\n const [key] = readVarint(page, cellOffset(page, header, mid) + 4)\n if (key < rowid) {\n low = mid + 1\n } else {\n high = mid\n }\n }\n return low\n }\n\n // Fetches the pages that hold the rows of the ranges, level by level. Up to\n // the pager's budget they come at once; past it a strict prefetch gives up\n // and returns false, and a streaming one fetches the leading blocks now and\n // the rest in chunks as reads approach them.\n async prefetchRowidRanges(\n root: number,\n ranges: [number, number][],\n stream = false,\n ) {\n if (ranges.length === 0) {\n return true\n }\n const leafLevel = await this.tableDepth(root, ranges[0]![0])\n let frontiers = ranges.map(() => [root])\n for (let level = 0; level < leafLevel; level++) {\n frontiers = await Promise.all(\n frontiers.map((pages, r) => this.childrenInRange(pages, ...ranges[r]!)),\n )\n const pages = frontiers.flat()\n if (stream) {\n this.pager.prefetchLeading(pages)\n } else if (!this.pager.prefetch(pages)) {\n return false\n }\n }\n return true\n }\n\n private async childrenInRange(pages: number[], lo: number, hi: number) {\n const decoded = await Promise.all(pages.map(n => this.pageAt(n)))\n const children: number[] = []\n decoded.forEach(({ page, header }, i) => {\n const from = i === 0 ? this.childIndexFor(page, header, lo) : 0\n const to =\n i === decoded.length - 1\n ? this.childIndexFor(page, header, hi)\n : header.cellCount\n for (let c = from; c <= to; c++) {\n children.push(\n c === header.cellCount\n ? header.rightChild\n : readUint32(page, cellOffset(page, header, c)),\n )\n }\n })\n return children\n }\n\n async tableRowid(\n root: number,\n rowid: number,\n ): Promise<SqlValue[] | undefined> {\n let pageNumber = root\n for (;;) {\n const { page, header } = await this.pageAt(pageNumber)\n if (header.type === LEAF_TABLE) {\n let low = 0\n let high = header.cellCount\n while (low < high) {\n const mid = (low + high) >> 1\n const offset = cellOffset(page, header, mid)\n const [size, afterSize] = readVarint(page, offset)\n const [key, afterKey] = readVarint(page, afterSize)\n if (key === rowid) {\n return decodeRecord(await this.payload(page, afterKey, size, false))\n }\n if (key < rowid) {\n low = mid + 1\n } else {\n high = mid\n }\n }\n return undefined\n }\n if (header.type !== INTERIOR_TABLE) {\n throw new Error('SQLite table b-tree contains an index page')\n }\n let low = 0\n let high = header.cellCount\n while (low < high) {\n const mid = (low + high) >> 1\n const offset = cellOffset(page, header, mid)\n const [key] = readVarint(page, offset + 4)\n if (key < rowid) {\n low = mid + 1\n } else {\n high = mid\n }\n }\n pageNumber =\n low === header.cellCount\n ? header.rightChild\n : readUint32(page, cellOffset(page, header, low))\n }\n }\n\n async *tableScan(\n root: number,\n ): AsyncGenerator<{ rowid: number; values: SqlValue[] }> {\n yield* this.scanPage(root, await this.tableDepth(root, 0))\n }\n\n // Prefetches only leaves: interior pages prefetched a level up would be\n // evicted by the leaf prefetches below them before they were read\n private async *scanPage(\n pageNumber: number,\n depth: number,\n ): AsyncGenerator<{ rowid: number; values: SqlValue[] }> {\n const { page, header } = await this.pageAt(pageNumber)\n if (header.type === LEAF_TABLE) {\n for (let i = 0; i < header.cellCount; i++) {\n const offset = cellOffset(page, header, i)\n const [size, afterSize] = readVarint(page, offset)\n const [rowid, afterKey] = readVarint(page, afterSize)\n yield {\n rowid,\n values: decodeRecord(await this.payload(page, afterKey, size, false)),\n }\n }\n } else {\n const children: number[] = []\n for (let i = 0; i < header.cellCount; i++) {\n children.push(readUint32(page, cellOffset(page, header, i)))\n }\n children.push(header.rightChild)\n if (depth === 1) {\n this.pager.prefetchLeading(children)\n }\n for (const child of children) {\n yield* this.scanPage(child, depth - 1)\n }\n }\n }\n\n private decodedCells(pageNumber: number, header: PageHeader) {\n let cells = this.decodedIndexPages.get(pageNumber)\n if (cells) {\n this.decodedIndexPages.delete(pageNumber)\n } else {\n cells = new Array<IndexCell | undefined>(header.cellCount)\n if (this.decodedIndexPages.size >= MAX_DECODED_INDEX_PAGES) {\n const oldest = this.decodedIndexPages.keys().next().value\n if (oldest !== undefined) {\n this.decodedIndexPages.delete(oldest)\n }\n }\n }\n this.decodedIndexPages.set(pageNumber, cells)\n return cells\n }\n\n private async indexCell(\n pageNumber: number,\n page: Uint8Array,\n header: PageHeader,\n index: number,\n ): Promise<IndexCell> {\n const cells = this.decodedCells(pageNumber, header)\n let cell = cells[index]\n if (!cell) {\n const offset = cellOffset(page, header, index)\n const interior = header.type === INTERIOR_INDEX\n const [size, afterSize] = readVarint(page, interior ? offset + 4 : offset)\n cell = {\n values: decodeRecord(await this.payload(page, afterSize, size, true)),\n leftChild: interior ? readUint32(page, offset) : 0,\n }\n cells[index] = cell\n }\n return cell\n }\n\n // The first cell at or past `key`, by binary search from `from`.\n private async lowerBound(\n pageNumber: number,\n page: Uint8Array,\n header: PageHeader,\n key: number[],\n from: number,\n inclusive: boolean,\n ) {\n let low = from\n let high = header.cellCount\n while (low < high) {\n const mid = (low + high) >> 1\n const cell = await this.indexCell(pageNumber, page, header, mid)\n const order = compareKey(cell.values, key)\n if (order < 0 || (inclusive && order === 0)) {\n low = mid + 1\n } else {\n high = mid\n }\n }\n return low\n }\n\n // The entries from `low` on in key order, and with `high` only those up to\n // it, their pages read ahead.\n async *indexScanFrom(\n root: number,\n low: number[],\n high?: number[],\n ): AsyncGenerator<SqlValue[]> {\n const { page, header } = await this.pageAt(root)\n const first = await this.lowerBound(root, page, header, low, 0, false)\n const interior = header.type === INTERIOR_INDEX\n if (interior && high) {\n const past = await this.lowerBound(root, page, header, high, first, true)\n const children: number[] = []\n for (let c = first; c <= past; c++) {\n children.push(\n c === header.cellCount\n ? header.rightChild\n : (await this.indexCell(root, page, header, c)).leftChild,\n )\n }\n this.pager.prefetchLeading(children)\n }\n for (let i = first; i < header.cellCount; i++) {\n const cell = await this.indexCell(root, page, header, i)\n if (interior) {\n yield* this.indexScanFrom(cell.leftChild, low, high)\n }\n if (high && compareKey(cell.values, high) > 0) {\n return\n }\n yield cell.values\n }\n if (interior) {\n yield* this.indexScanFrom(header.rightChild, low, high)\n }\n }\n\n async indexSeekLE(\n root: number,\n key: number[],\n ): Promise<SqlValue[] | undefined> {\n let best: SqlValue[] | undefined\n let pageNumber = root\n for (;;) {\n const { page, header } = await this.pageAt(pageNumber)\n let low = 0\n let high = header.cellCount\n let child = 0\n while (low < high) {\n const mid = (low + high) >> 1\n const cell = await this.indexCell(pageNumber, page, header, mid)\n if (compareKey(cell.values, key) <= 0) {\n best = cell.values\n low = mid + 1\n } else {\n child = cell.leftChild\n high = mid\n }\n }\n if (header.type === LEAF_INDEX) {\n return best\n }\n pageNumber = low === header.cellCount ? header.rightChild : child\n }\n }\n}\n\nfunction compareKey(values: SqlValue[], key: number[]) {\n for (let i = 0; i < key.length; i++) {\n const a = values[i]\n const b = key[i]\n if (typeof a !== 'number' || b === undefined) {\n throw new Error('SQLite index key is not numeric')\n }\n if (a !== b) {\n return a < b ? -1 : 1\n }\n }\n return 0\n}\n", "import type { ByteSource } from '../filehandle.ts'\n\nexport interface PagerOptions {\n blockSize?: number | undefined\n maxBlocks?: number | undefined\n}\n\nexport function checkPagerOptions({ blockSize, maxBlocks }: PagerOptions) {\n if (\n blockSize !== undefined &&\n !(Number.isSafeInteger(blockSize) && blockSize > 0)\n ) {\n throw new Error(`blockSize must be a positive integer, not ${blockSize}`)\n }\n if (\n maxBlocks !== undefined &&\n !(Number.isSafeInteger(maxBlocks) && maxBlocks > 0)\n ) {\n throw new Error(`maxBlocks must be a positive integer, not ${maxBlocks}`)\n }\n}\n\n// Blocks a reader asked for ahead of time, fetched in chunks as its reads\n// approach the end of what has been fetched.\ninterface Plan {\n blocks: number[]\n position: Map<number, number>\n next: number\n}\n\nexport class Pager {\n private blocks = new Map<number, Promise<Uint8Array>>()\n private readonly blockSize: number\n private readonly maxBlocks: number\n private plan: Plan | undefined\n bytesFetched = 0\n fetches = 0\n\n private source: ByteSource\n readonly pageSize: number\n private fileSize: number\n\n constructor(\n source: ByteSource,\n pageSize: number,\n fileSize: number,\n opts: PagerOptions = {},\n ) {\n this.source = source\n this.pageSize = pageSize\n this.fileSize = fileSize\n const requested = opts.blockSize ?? 65536\n this.blockSize = Math.max(\n pageSize,\n Math.ceil(requested / pageSize) * pageSize,\n )\n this.maxBlocks = opts.maxBlocks ?? 256\n }\n\n private async read(length: number, start: number) {\n const bytes = await this.readRetrying(length, start)\n this.bytesFetched += bytes.length\n if (bytes.length < length) {\n throw new Error(\n `the file ends at byte ${start + bytes.length}, short of the ${this.fileSize} bytes its SQLite header gives`,\n )\n }\n return bytes\n }\n\n private async readRetrying(length: number, start: number) {\n let attempt = 0\n for (;;) {\n try {\n return await this.source.read(length, start)\n } catch (error) {\n attempt += 1\n if (attempt >= 3) {\n throw error\n }\n await new Promise(resolve => setTimeout(resolve, 200 * attempt))\n }\n }\n }\n\n seed(index: number, bytes: Uint8Array) {\n if (\n bytes.length ===\n Math.min(this.blockSize, this.fileSize - index * this.blockSize)\n ) {\n this.blocks.set(index, Promise.resolve(bytes))\n }\n }\n\n private block(index: number) {\n this.follow(index)\n const cached = this.touch(index)\n if (cached) {\n return cached\n }\n const start = index * this.blockSize\n const length = Math.min(this.blockSize, this.fileSize - start)\n const pending = this.read(length, start)\n this.fetches += 1\n this.store(index, pending)\n this.evict()\n return pending\n }\n\n private touch(index: number) {\n const cached = this.blocks.get(index)\n if (cached) {\n this.blocks.delete(index)\n this.blocks.set(index, cached)\n }\n return cached\n }\n\n private blockOf(pageNumber: number) {\n return Math.floor(((pageNumber - 1) * this.pageSize) / this.blockSize)\n }\n\n // half the cache, so a prefetch cannot evict its own blocks\n private get prefetchBudget() {\n return Math.max(1, Math.floor(this.maxBlocks / 2))\n }\n\n private get chunk() {\n return Math.max(1, Math.floor(this.prefetchBudget / 2))\n }\n\n // Fetches the pages' blocks when they fit the budget together.\n prefetch(pageNumbers: number[]) {\n const indexes = new Set(pageNumbers.map(n => this.blockOf(n)))\n if (indexes.size > this.prefetchBudget) {\n return false\n }\n this.fetchBlocks(indexes)\n return true\n }\n\n // Fetches the first pages' blocks now, up to the budget, and plans the rest\n // in the pages' order, to be fetched chunk by chunk as reads approach them.\n prefetchLeading(pageNumbers: number[]) {\n const blocks: number[] = []\n const position = new Map<number, number>()\n for (const pageNumber of pageNumbers) {\n const index = this.blockOf(pageNumber)\n if (!position.has(index)) {\n position.set(index, blocks.length)\n blocks.push(index)\n }\n }\n this.plan = { blocks, position, next: 0 }\n this.advance(this.prefetchBudget)\n }\n\n private advance(count: number) {\n const plan = this.plan\n if (!plan) {\n return\n }\n const slice = plan.blocks.slice(plan.next, plan.next + count)\n plan.next += slice.length\n if (plan.next >= plan.blocks.length) {\n this.plan = undefined\n }\n this.fetchBlocks(new Set(slice))\n }\n\n // A read within half a chunk of the end of the fetched part of the plan\n // brings in the next chunk.\n private follow(index: number) {\n const plan = this.plan\n const at = plan?.position.get(index)\n if (\n plan &&\n at !== undefined &&\n at >= plan.next - Math.ceil(this.chunk / 2)\n ) {\n this.advance(this.chunk)\n }\n }\n\n private fetchBlocks(indexes: Set<number>) {\n const wanted = [...indexes]\n .filter(index => !this.touch(index))\n .sort((a, b) => a - b)\n let runStart = 0\n while (runStart < wanted.length) {\n let runEnd = runStart + 1\n while (\n runEnd < wanted.length &&\n wanted[runEnd] === wanted[runEnd - 1]! + 1\n ) {\n runEnd += 1\n }\n this.fetchRun(wanted[runStart]!, runEnd - runStart)\n runStart = runEnd\n }\n }\n\n private fetchRun(firstIndex: number, count: number) {\n const start = firstIndex * this.blockSize\n const length = Math.min(count * this.blockSize, this.fileSize - start)\n const pending = this.read(length, start)\n this.fetches += 1\n for (let i = 0; i < count; i++) {\n const within = i * this.blockSize\n this.store(\n firstIndex + i,\n pending.then(bytes => bytes.subarray(within, within + this.blockSize)),\n )\n }\n this.evict()\n }\n\n private store(index: number, block: Promise<Uint8Array>) {\n this.blocks.set(index, block)\n block.catch(() => {\n if (this.blocks.get(index) === block) {\n this.blocks.delete(index)\n }\n })\n }\n\n private evict() {\n while (this.blocks.size > this.maxBlocks) {\n const oldest = this.blocks.keys().next().value\n if (oldest === undefined) {\n break\n }\n this.blocks.delete(oldest)\n }\n }\n\n async page(pageNumber: number) {\n const offset = (pageNumber - 1) * this.pageSize\n if (pageNumber < 1 || offset + this.pageSize > this.fileSize) {\n throw new Error(`SQLite page ${pageNumber} is outside the file`)\n }\n const bytes = await this.block(Math.floor(offset / this.blockSize))\n const within = offset % this.blockSize\n return bytes.subarray(within, within + this.pageSize)\n }\n}\n", "import { BTree } from './btree.ts'\nimport { Pager, checkPagerOptions } from './pager.ts'\n\nimport type { ByteSource } from '../filehandle.ts'\nimport type { PagerOptions } from './pager.ts'\nimport type { SqlValue } from './record.ts'\n\nexport interface SqliteObject {\n type: string\n name: string\n tableName: string\n rootPage: number\n sql: string\n}\n\nexport class SqliteDatabase {\n readonly pager: Pager\n readonly btree: BTree\n readonly objects: Map<string, SqliteObject>\n\n private constructor(\n pager: Pager,\n btree: BTree,\n objects: Map<string, SqliteObject>,\n ) {\n this.pager = pager\n this.btree = btree\n this.objects = objects\n }\n\n static async open(source: ByteSource, opts: PagerOptions = {}) {\n checkPagerOptions(opts)\n const firstBlock = await source.read(\n Math.max(512, opts.blockSize ?? 65536),\n 0,\n )\n const header = firstBlock.subarray(0, 100)\n const magic = new TextDecoder().decode(header.subarray(0, 15))\n if (magic !== 'SQLite format 3' || header.length < 100) {\n throw new Error('Not a SQLite database')\n }\n const view = new DataView(\n header.buffer,\n header.byteOffset,\n header.byteLength,\n )\n const rawPageSize = view.getUint16(16)\n const pageSize = rawPageSize === 1 ? 65536 : rawPageSize\n const reserved = header[20] ?? 0\n const encoding = view.getUint32(56)\n if (encoding !== 1) {\n throw new Error(`SQLite text encoding ${encoding} is not UTF-8`)\n }\n const pageCount = view.getUint32(28)\n if (pageCount === 0 || view.getUint32(24) !== view.getUint32(92)) {\n throw new Error(\n 'SQLite header has no valid database size; the file was written by SQLite older than 3.7.0',\n )\n }\n const size = pageCount * pageSize\n const pager = new Pager(source, pageSize, size, opts)\n pager.seed(0, firstBlock)\n pager.fetches += 1\n pager.bytesFetched += firstBlock.length\n const btree = new BTree(pager, reserved)\n const objects = new Map<string, SqliteObject>()\n for await (const { values } of btree.tableScan(1)) {\n const [type, name, tableName, rootPage, sql] = values\n if (\n typeof type === 'string' &&\n typeof name === 'string' &&\n typeof tableName === 'string' &&\n typeof rootPage === 'number'\n ) {\n objects.set(name, {\n type,\n name,\n tableName,\n rootPage,\n sql: typeof sql === 'string' ? sql : '',\n })\n }\n }\n return new SqliteDatabase(pager, btree, objects)\n }\n\n rootPage(name: string) {\n const object = this.objects.get(name)\n if (!object) {\n throw new Error(`SQLite database has no object named ${name}`)\n }\n return object.rootPage\n }\n\n // Whether a table keeps its whole rows in the b-tree of its primary key.\n withoutRowid(tableName: string) {\n const table = this.objects.get(tableName)\n return table?.type === 'table' && /without\\s+rowid/i.test(table.sql)\n }\n\n // The b-tree keyed by a table's primary key: its automatic index, or the\n // table itself when it is WITHOUT ROWID.\n indexOn(tableName: string) {\n const index = [...this.objects.values()].find(\n o => o.type === 'index' && o.tableName === tableName,\n )\n if (index) {\n return index.rootPage\n }\n if (this.withoutRowid(tableName)) {\n return this.rootPage(tableName)\n }\n throw new Error(`SQLite table ${tableName} has no index`)\n }\n\n byRowid(table: string, rowid: number) {\n return this.btree.tableRowid(this.rootPage(table), rowid)\n }\n\n prefetchRows(table: string, ranges: [number, number][], stream = false) {\n return this.btree.prefetchRowidRanges(this.rootPage(table), ranges, stream)\n }\n\n scan(table: string) {\n return this.btree.tableScan(this.rootPage(table))\n }\n\n indexSeekLE(table: string, key: number[]): Promise<SqlValue[] | undefined> {\n return this.btree.indexSeekLE(this.indexOn(table), key)\n }\n\n // The entries of a table's primary key from `low` on, or up to `high`.\n indexScanFrom(table: string, low: number[], high?: number[]) {\n return this.btree.indexScanFrom(this.indexOn(table), low, high)\n }\n\n has(name: string) {\n return this.objects.has(name)\n }\n}\n", "import { ENDMARKER, nodeId, nodeOrientation } from './gbwt/node.ts'\nimport { GbwtRecord, decompressEdges } from './gbwt/record.ts'\nimport { decodeSequence, encodedSequenceLength } from './gbwt/sequence.ts'\nimport { graphNameFromTags } from './graphName.ts'\nimport { formatPathName, pathNameFor, toPathQuery } from './pathName.ts'\nimport {\n subgraphAroundNodes,\n subgraphAtOffset,\n subgraphBetween,\n subgraphInInterval,\n} from './query.ts'\nimport { SqliteDatabase } from './sqlite/database.ts'\nimport { SubgraphLimitError } from './subgraph.ts'\n\nimport type { ByteSource } from './filehandle.ts'\nimport type { Pos } from './gbwt/record.ts'\nimport type { GraphName } from './graphName.ts'\nimport type { PathName, PathRef } from './pathName.ts'\nimport type {\n BetweenQuery,\n IntervalQuery,\n NodesQuery,\n OffsetQuery,\n PathWindow,\n} from './query.ts'\nimport type { PagerOptions } from './sqlite/pager.ts'\nimport type { SqlValue } from './sqlite/record.ts'\nimport type { HaplotypeAlignment, Subgraph } from './subgraph.ts'\n\nexport const SCHEMA_VERSION = 'GBZ-base version 4'\n\nexport interface PathFragment {\n path: GbzPath\n start: number\n end: number\n}\n\nexport type WindowQuery = IntervalQuery\n\nexport interface AlignmentQuery extends Omit<\n WindowQuery,\n 'haplotypes' | 'snarls'\n> {\n haplotypes?: 'all' | 'distinct' | undefined\n}\n\nexport class UnknownPathError extends Error {\n override name = 'UnknownPathError'\n\n readonly path: PathName\n\n constructor(path: PathName) {\n super(`the graph has no path named ${formatPathName(path)}`)\n this.path = path\n }\n}\n\nexport class ForwardOnlyIndexError extends Error {\n override name = 'ForwardOnlyIndexError'\n\n constructor() {\n super(\n 'the haplotype index was written with --forward-only, which cannot name the walks stored against their reference (about half of them); rebuild it with gbz-haplotype-index without --forward-only',\n )\n }\n}\n\nexport class SchemaVersionError extends Error {\n override name = 'SchemaVersionError'\n\n readonly found: string | undefined\n\n constructor(found: string | undefined) {\n super(\n found === undefined\n ? `not a gbz-base database: it has no version tag`\n : `unsupported database schema \"${found}\"; this reader understands \"${SCHEMA_VERSION}\"`,\n )\n this.found = found\n }\n}\n\nexport interface IndexedPosition {\n pathOffset: number\n pos: Pos\n}\n\nexport interface HaplotypeSample {\n node: number\n offset: number\n pathHandle: number\n orientation: 'forward' | 'reverse'\n pathOffset: number\n}\n\nexport interface HaplotypeAnchor {\n node: number\n pathOffset: number\n}\n\n// An anchor of a reference path with the forward samples at its node: one\n// visit of every haplotype that passes it, each with its GBWT position and\n// its offset along its own path.\nexport interface HaplotypeAnchorRow extends HaplotypeAnchor {\n anchorOffset: number\n visits: HaplotypeSample[]\n}\n\n// One bin of a reference path in the haplotype index's overview: how many\n// haplotypes fall in each class there, and the excursions from the reference\n// that start in it.\nexport interface OverviewBin {\n start: number\n end: number\n // haplotypes that are absent, reference-like, partial and variant\n classes: [number, number, number, number]\n excursions: number\n variants: number\n longestExcursion: number\n}\n\nexport const OVERVIEW_ABSENT = 0\nexport const OVERVIEW_REFERENCE = 1\nexport const OVERVIEW_PARTIAL = 2\nexport const OVERVIEW_VARIANT = 3\n\n// A binned summary of every haplotype along a stretch of a reference path,\n// at one zoom level. `cells` holds bins.length \u00D7 haplotypes.length entries,\n// bin by bin: the class in the low two bits, and for a variant cell a bucket\n// of the bin's variant marks in the next two (1, 2 to 3, 4 to 15, 16 or\n// more).\nexport interface HaplotypeOverview {\n level: number\n bin: number\n haplotypes: { sample: string; haplotype: number }[]\n bins: OverviewBin[]\n cells: Uint8Array\n}\n\nexport interface OverviewQuery extends PathWindow {\n // The zoom level, clamped to those the index holds, or the bp per pixel to\n // choose the coarsest level whose bins are no larger than it. Level 0\n // without either.\n level?: number | undefined\n bpPerPixel?: number | undefined\n}\n\nfunction concatBytes(parts: Uint8Array[]) {\n if (parts.length === 1) {\n return parts[0]!\n }\n const whole = new Uint8Array(parts.reduce((n, p) => n + p.length, 0))\n let at = 0\n for (const part of parts) {\n whole.set(part, at)\n at += part.length\n }\n return whole\n}\n\n// The format of the haplotype index this reader understands: the samples in\n// their key b-tree, each anchor's visits with the anchor and each bin's stray\n// rows with its node list, which gbz-haplotype-index 0.3 writes.\nconst INDEX_FORMAT = 3\n\nclass Varints {\n private at = 0\n private bytes: Uint8Array\n\n constructor(bytes: Uint8Array) {\n this.bytes = bytes\n }\n\n get done() {\n return this.at >= this.bytes.length\n }\n\n next() {\n let value = 0\n let scale = 1\n for (;;) {\n const byte = this.bytes[this.at++]\n if (byte === undefined) {\n throw new Error('a haplotype index blob ends inside a number')\n }\n value += (byte & 0x7f) * scale\n scale *= 128\n if ((byte & 0x80) === 0) {\n return value\n }\n }\n }\n}\n\n// Appends the runs of node ids a HaplotypeBins node-list part encodes: per\n// run, the gap from the previous run's last id and the length less one.\nfunction decodeRuns(bytes: Uint8Array, runs: [number, number][]) {\n const reader = new Varints(bytes)\n let previous = 0\n while (!reader.done) {\n const start = previous + reader.next()\n previous = start + reader.next()\n runs.push([start, previous])\n }\n}\n\n// A test of membership in the union of the runs.\nfunction runTester(runs: [number, number][]) {\n runs.sort((x, y) => x[0] - y[0])\n const starts: number[] = []\n const ends: number[] = []\n for (const [start, end] of runs) {\n const last = ends.length - 1\n if (last >= 0 && start <= ends[last]! + 1) {\n ends[last] = Math.max(ends[last]!, end)\n } else {\n starts.push(start)\n ends.push(end)\n }\n }\n return (id: number) => {\n let lo = 0\n let hi = starts.length\n while (lo < hi) {\n const mid = (lo + hi) >> 1\n if (starts[mid]! <= id) {\n lo = mid + 1\n } else {\n hi = mid\n }\n }\n return lo > 0 && id <= ends[lo - 1]!\n }\n}\n\nfunction decodeStrays(bin: number, bytes: Uint8Array, rows: HaplotypeStray[]) {\n const reader = new Varints(bytes)\n while (!reader.done) {\n const pathHandle = reader.next()\n const pathStart = reader.next()\n const pathEnd = reader.next()\n const low = reader.next()\n const high = reader.next()\n rows.push({\n bin,\n pathHandle,\n pathStart,\n pathEnd,\n snarl: high > 0 ? [low, high] : undefined,\n node: reader.next(),\n offset: reader.next(),\n })\n }\n}\n\n// The visits of a format 3 anchor row: per visit, the path handle doubled\n// plus the orientation bit of the node handle, the node offset and the path\n// offset.\nfunction decodeVisits(\n anchorNode: number,\n parts: Uint8Array[],\n visits: HaplotypeSample[],\n) {\n const id = nodeId(anchorNode)\n for (const part of parts) {\n const reader = new Varints(part)\n while (!reader.done) {\n const pathAndBit = reader.next()\n const bit = pathAndBit % 2\n visits.push({\n node: 2 * id + bit,\n offset: reader.next(),\n pathHandle: (pathAndBit - bit) / 2,\n orientation: 'forward',\n pathOffset: reader.next(),\n })\n }\n }\n}\n\n// A row of HaplotypeStrays: a stretch of one path, from pathStart to the visit\n// at pathEnd, holding visits to nodes of one bin that the walks from anchor\n// visits can miss. `node` and `offset` are the GBWT position of its first\n// visit in the path's forward orientation. A row with a snarl names a path\n// that lies between those two boundary nodes from end to end.\nexport interface HaplotypeStray {\n bin: number\n pathHandle: number\n pathStart: number\n pathEnd: number\n snarl: [number, number] | undefined\n node: number\n offset: number\n}\n\nexport interface HaplotypeStrayOptions {\n // The largest query context the rows cover.\n context: number\n bin: number\n bound: number\n // The most nodes between a filled snarl's boundaries for the rows to cover\n // it, or undefined when the rows leave snarls out.\n snarlNodes: number | undefined\n}\n\nexport interface GbzPath {\n handle: number\n /** @internal */\n fwStart: Pos\n /** @internal */\n revStart: Pos\n name: PathName\n isIndexed: boolean\n}\n\nexport class GbzRecord {\n readonly sequenceLen: number\n readonly handle: number\n readonly edges: Pos[]\n readonly bwt: Uint8Array\n readonly encodedSequence: Uint8Array\n readonly next: number | undefined\n private decoded: string | undefined\n\n constructor(\n handle: number,\n edges: Pos[],\n bwt: Uint8Array,\n encodedSequence: Uint8Array,\n next: number | undefined,\n ) {\n this.handle = handle\n this.edges = edges\n this.bwt = bwt\n this.encodedSequence = encodedSequence\n this.next = next\n this.sequenceLen = encodedSequenceLength(encodedSequence)\n }\n\n get id() {\n return nodeId(this.handle)\n }\n\n get orientation() {\n return nodeOrientation(this.handle)\n }\n\n get sequence() {\n this.decoded ??= decodeSequence(this.encodedSequence)\n return this.decoded\n }\n\n successors() {\n return this.edges.filter(e => e.node !== ENDMARKER).map(e => e.node)\n }\n\n gbwt() {\n if (this.edges.length === 0) {\n throw new Error(`GBWT record for handle ${this.handle} is empty`)\n }\n return new GbwtRecord(this.edges, this.bwt)\n }\n}\n\nfunction num(value: SqlValue | undefined, what: string) {\n if (typeof value !== 'number') {\n throw new Error(`${what} is not a number in the database`)\n }\n return value\n}\n\nfunction str(value: SqlValue | undefined, what: string) {\n if (typeof value !== 'string') {\n throw new Error(`${what} is not text in the database`)\n }\n return value\n}\n\nfunction blob(value: SqlValue | undefined, what: string) {\n if (!(value instanceof Uint8Array)) {\n throw new Error(`${what} is not a blob in the database`)\n }\n return value\n}\n\nfunction rowToPath(rowid: number, values: SqlValue[]): GbzPath {\n return {\n handle: rowid,\n fwStart: {\n node: num(values[1], 'Paths.fw_node'),\n offset: num(values[2], 'Paths.fw_offset'),\n },\n revStart: {\n node: num(values[3], 'Paths.rev_node'),\n offset: num(values[4], 'Paths.rev_offset'),\n },\n name: {\n sample: str(values[5], 'Paths.sample'),\n contig: str(values[6], 'Paths.contig'),\n haplotype: num(values[7], 'Paths.haplotype'),\n fragment: num(values[8], 'Paths.fragment'),\n },\n isIndexed: num(values[9], 'Paths.is_indexed') !== 0,\n }\n}\n\nexport interface OpenOptions {\n source: ByteSource\n haplotypeIndex?: ByteSource | undefined\n blockSize?: number | undefined\n maxBlocks?: number | undefined\n}\n\nexport interface FetchStats {\n fetches: number\n bytesFetched: number\n}\n\nfunction forgetOnRejection<T>(pending: Promise<T>, forget: () => void) {\n pending.catch(forget)\n return pending\n}\n\nasync function readTags(sqlite: SqliteDatabase) {\n const tags = new Map<string, string>()\n for await (const { values } of sqlite.scan('Tags')) {\n tags.set(str(values[0], 'Tags.key'), str(values[1], 'Tags.value'))\n }\n return tags\n}\n\nexport class GBZBase {\n private pathCache: Promise<GbzPath[]> | undefined\n private pathMapCache: Promise<Map<number, GbzPath>> | undefined\n private indexTags = new Map<string, string>()\n private overviewRowsCache:\n Promise<{ sample: string; haplotype: number }[]> | undefined\n\n /** @internal */\n readonly sqlite: SqliteDatabase\n /** @internal */\n readonly index: SqliteDatabase | undefined\n private readonly tagMap: Map<string, string>\n\n private constructor(\n sqlite: SqliteDatabase,\n index: SqliteDatabase | undefined,\n tags: Map<string, string>,\n ) {\n this.sqlite = sqlite\n this.index = index\n this.tagMap = tags\n }\n\n static async open(opts: OpenOptions) {\n const { source, haplotypeIndex } = opts\n const pagerOptions: PagerOptions = {\n blockSize: opts.blockSize,\n maxBlocks: opts.maxBlocks,\n }\n const sqlite = await SqliteDatabase.open(source, pagerOptions)\n const tags = sqlite.objects.has('Tags')\n ? await readTags(sqlite)\n : new Map<string, string>()\n const version = tags.get('version')\n if (version !== SCHEMA_VERSION) {\n throw new SchemaVersionError(version)\n }\n for (const table of ['Nodes', 'Paths', 'ReferenceIndex']) {\n sqlite.rootPage(table)\n }\n const index = haplotypeIndex\n ? await SqliteDatabase.open(haplotypeIndex, pagerOptions)\n : undefined\n const db = new GBZBase(sqlite, index, tags)\n if (index) {\n for (const table of ['Tags', 'HaplotypeSamples', 'HaplotypeLengths']) {\n if (!index.objects.has(table)) {\n throw new Error(\n `haplotypeIndex is not a gbz-base haplotype index: it has no ${table} table`,\n )\n }\n }\n db.indexTags = await readTags(index)\n const indexed = db.indexTags.get('haplotype_index_paths')\n const paths = await db.tag('paths')\n if (indexed !== paths) {\n throw new Error(\n `haplotype index was built for ${indexed ?? 'an unknown number of'} paths but the graph has ${paths}`,\n )\n }\n const indexedNodes = db.indexTags.get('haplotype_index_nodes')\n const nodes = await db.tag('nodes')\n if (indexedNodes !== undefined && indexedNodes !== nodes) {\n throw new Error(\n `haplotype index was built for a graph with ${indexedNodes} nodes but this one has ${nodes}`,\n )\n }\n if (db.indexTags.get('haplotype_index_orientations') === 'forward') {\n throw new ForwardOnlyIndexError()\n }\n const format = db.indexTags.get('haplotype_index_format')\n if (Number(format) !== INDEX_FORMAT) {\n throw new Error(\n format === undefined\n ? `the haplotype index predates format ${INDEX_FORMAT}; rebuild it with gbz-haplotype-index 0.3`\n : `the haplotype index has format ${format}; this version of @gmod/gbz-base reads format ${INDEX_FORMAT}`,\n )\n }\n }\n return db\n }\n\n async tags() {\n return this.tagMap\n }\n\n async tag(key: string) {\n return this.tagMap.get(key)\n }\n\n /** @internal */\n prefetchRecords(ranges: [number, number][], stream = false) {\n return this.sqlite.prefetchRows('Nodes', ranges, stream)\n }\n\n /** @internal */\n async getRecord(handle: number) {\n const row = await this.sqlite.byRowid('Nodes', handle)\n if (!row) {\n return undefined\n }\n const next = row[4]\n return new GbzRecord(\n handle,\n decompressEdges(blob(row[1], 'Nodes.edges')),\n blob(row[2], 'Nodes.bwt'),\n blob(row[3], 'Nodes.sequence'),\n typeof next === 'number' ? next : undefined,\n )\n }\n\n paths() {\n this.pathCache ??= forgetOnRejection(this.scanPaths(), () => {\n this.pathCache = undefined\n })\n return this.pathCache\n }\n\n private async scanPaths() {\n const paths: GbzPath[] = []\n for await (const { rowid, values } of this.sqlite.scan('Paths')) {\n paths.push(rowToPath(rowid, values))\n }\n return paths\n }\n\n /** @internal */\n async getPath(handle: number) {\n const row = await this.sqlite.byRowid('Paths', handle)\n return row ? rowToPath(handle, row) : undefined\n }\n\n /** @internal */\n pathsByHandle() {\n this.pathMapCache ??= forgetOnRejection(\n this.paths().then(\n paths => new Map(paths.map(path => [path.handle, path])),\n ),\n () => {\n this.pathMapCache = undefined\n },\n )\n return this.pathMapCache\n }\n\n /** @internal */\n async findPath(name: PathName) {\n const candidates = (await this.paths()).filter(\n p =>\n p.name.sample === name.sample &&\n p.name.contig === name.contig &&\n p.name.haplotype === name.haplotype &&\n p.name.fragment <= name.fragment,\n )\n return candidates.sort((a, b) => b.name.fragment - a.name.fragment)[0]\n }\n\n private async pathsNamed(ref: PathRef) {\n const name = pathNameFor(toPathQuery(ref), 0)\n return (await this.paths())\n .filter(\n p =>\n p.name.sample === name.sample &&\n p.name.contig === name.contig &&\n p.name.haplotype === name.haplotype,\n )\n .sort((a, b) => a.name.fragment - b.name.fragment)\n }\n\n async hasPath(ref: PathRef) {\n return (await this.pathsNamed(ref)).length > 0\n }\n\n private pathLengths = new Map<number, Promise<number>>()\n\n /** @internal */\n pathLength(handle: number) {\n let length = this.pathLengths.get(handle)\n if (!length) {\n length = this.walkPathLength(handle)\n this.pathLengths.set(handle, length)\n length.catch(() => this.pathLengths.delete(handle))\n }\n return length\n }\n\n private async walkPathLength(handle: number) {\n const indexed = this.hasHaplotypeIndex\n ? await this.haplotypeLength(handle)\n : undefined\n if (indexed === undefined) {\n const last = await this.indexedPosition(handle, Number.MAX_SAFE_INTEGER)\n if (!last) {\n const path = await this.getPath(handle)\n throw new Error(\n `${path ? `The fragment of ${formatPathName(path.name)} at ${path.name.fragment}` : `Path ${handle}`} has not been indexed for random access`,\n )\n }\n let length = last.pathOffset\n let pos = last.pos\n for (;;) {\n const record = await this.getRecord(pos.node)\n if (!record) {\n throw new Error(`Node ${pos.node} does not exist in the graph`)\n }\n length += record.sequenceLen\n const next = record.gbwt().lf(pos.offset)\n if (!next || next.node === ENDMARKER) {\n return length\n }\n pos = next\n }\n }\n return indexed\n }\n\n async getPathFragments(opts: PathWindow): Promise<PathFragment[]> {\n const { start, end } = opts\n if (Number.isNaN(start) || Number.isNaN(end)) {\n throw new Error(`The window ${start}..${end} is not a number range`)\n }\n const ordered = await this.pathsNamed(opts.path)\n if (ordered.length === 0) {\n throw new UnknownPathError(pathNameFor(toPathQuery(opts.path), 0))\n }\n if (end <= start) {\n return []\n }\n const covering = ordered.filter(p => p.name.fragment <= start).slice(-1)\n const within = ordered.filter(\n p => p.name.fragment > start && p.name.fragment < end,\n )\n const fragments = await Promise.all(\n [...covering, ...within].map(async path => ({\n path,\n start: path.name.fragment,\n end: path.name.fragment + (await this.pathLength(path.handle)),\n })),\n )\n return fragments.filter(f => start < f.end)\n }\n\n private async subgraphForFragment(fragment: PathFragment, opts: WindowQuery) {\n const { sample, contig, haplotype } = fragment.path.name\n const start = Math.max(opts.start, fragment.start)\n const haplotypes = opts.haplotypes ?? 'all'\n try {\n const subgraph = await subgraphInInterval(this, {\n ...opts,\n path: { sample, contig, haplotype },\n start,\n end: Math.min(opts.end, fragment.end),\n })\n if (\n opts.keep === undefined &&\n this.hasHaplotypeIndex &&\n (haplotypes === 'all' || haplotypes === 'distinct')\n ) {\n await subgraph.identifyPaths()\n }\n return subgraph\n } catch (error) {\n throw error instanceof SubgraphLimitError && error.walkedBp !== undefined\n ? new SubgraphLimitError(error.limit, {\n windowBp: opts.end - opts.start,\n walkedBp: start - opts.start + error.walkedBp,\n })\n : error\n }\n }\n\n async getSubgraphs(opts: WindowQuery): Promise<Subgraph[]> {\n const fragments = await this.getPathFragments(opts)\n const settled = await Promise.allSettled(\n fragments.map(fragment => this.subgraphForFragment(fragment, opts)),\n )\n return settled.map(result => {\n if (result.status === 'rejected') {\n throw result.reason\n }\n return result.value\n })\n }\n\n async getAlignments(opts: AlignmentQuery): Promise<HaplotypeAlignment[]> {\n return (await this.getSubgraphs(opts)).flatMap(subgraph =>\n subgraph.alignments(),\n )\n }\n\n subgraphInInterval(opts: IntervalQuery) {\n return subgraphInInterval(this, opts)\n }\n\n subgraphAtOffset(opts: OffsetQuery) {\n return subgraphAtOffset(this, opts)\n }\n\n subgraphAroundNodes(opts: NodesQuery) {\n return subgraphAroundNodes(this, opts)\n }\n\n subgraphBetween(opts: BetweenQuery) {\n return subgraphBetween(this, opts)\n }\n\n fetchStats(): { graph: FetchStats; haplotypeIndex: FetchStats | undefined } {\n const stats = ({ pager }: SqliteDatabase) => ({\n fetches: pager.fetches,\n bytesFetched: pager.bytesFetched,\n })\n return {\n graph: stats(this.sqlite),\n haplotypeIndex: this.index ? stats(this.index) : undefined,\n }\n }\n\n async graphName() {\n const gbzTags = new Map<string, string>()\n for (const [key, value] of await this.tags()) {\n if (key.startsWith('gbz_')) {\n gbzTags.set(key.slice('gbz_'.length), value)\n }\n }\n let name: GraphName = {\n name: undefined,\n subgraph: new Map(),\n translation: new Map(),\n }\n try {\n name = graphNameFromTags(gbzTags)\n } catch {\n // upstream falls back to an empty name when the tags do not parse\n }\n return name\n }\n\n async hasChainLinks() {\n const links = await this.tag('chain_links')\n return links !== undefined && Number(links) > 0\n }\n\n get hasHaplotypeIndex() {\n return this.index !== undefined\n }\n\n private get companion() {\n if (!this.index) {\n throw new Error('no haplotype index was opened with this database')\n }\n return this.index\n }\n\n /** @internal */\n async haplotypeSampleInterval() {\n const value = this.indexTags.get('haplotype_index_interval')\n return value === undefined ? undefined : Number(value)\n }\n\n // The most bp between two samples of any path: the reference paths take\n // --reference-interval, which can exceed --interval.\n /** @internal */\n async haplotypeSampleGap() {\n const interval = await this.haplotypeSampleInterval()\n const reference = this.indexTags.get('haplotype_index_reference_interval')\n return interval === undefined\n ? undefined\n : Math.max(interval, reference === undefined ? 0 : Number(reference))\n }\n\n /** @internal */\n async haplotypeAnchorSpacing() {\n const value = this.index?.has('HaplotypeAnchors')\n ? this.indexTags.get('haplotype_index_anchor_spacing')\n : undefined\n return value === undefined ? undefined : Number(value)\n }\n\n // How the bins' node lists and stray rows were built, or undefined without\n // them.\n /** @internal */\n async haplotypeStrayOptions(): Promise<HaplotypeStrayOptions | undefined> {\n const tag = (key: string) =>\n this.indexTags.get(`haplotype_index_stray_${key}`)\n if (!this.index?.has('HaplotypeBins') || tag('format') !== '2') {\n return undefined\n }\n const snarls =\n tag('snarls') === 'modeled' &&\n tag('chain_links') === ((await this.tag('chain_links')) ?? '0')\n return {\n context: Number(tag('context')),\n bin: Number(tag('bin')),\n bound: Number(tag('bound')),\n snarlNodes: snarls ? Number(tag('snarl_nodes')) : undefined,\n }\n }\n\n // The rows of a table with blobs whose keys lie in low..high: a key scan of\n // its index, then its rows, which the indexer wrote in key order, prefetched\n // as one range.\n private async blobRows(table: string, low: number[], high: number[]) {\n const rows: SqlValue[][] = []\n const rowids: number[] = []\n for await (const key of this.companion.indexScanFrom(table, low, high)) {\n rowids.push(num(key[key.length - 1], `${table} rowid`))\n }\n if (rowids.length > 1) {\n await this.companion.prefetchRows(\n table,\n [[Math.min(...rowids), Math.max(...rowids) + 1]],\n true,\n )\n }\n for (const rowid of rowids) {\n const row = await this.companion.byRowid(table, rowid)\n if (row) {\n rows.push(row)\n }\n }\n return rows\n }\n\n // The node lists and stray rows of the bins firstBin..lastBin of one\n // reference path: a test of whether a node id is listed, and the rows.\n /** @internal */\n async haplotypeBinData(\n referenceHandle: number,\n firstBin: number,\n lastBin: number,\n ): Promise<{ listed: (id: number) => boolean; strays: HaplotypeStray[] }> {\n const runs: [number, number][] = []\n const strays: HaplotypeStray[] = []\n for (const row of await this.blobRows(\n 'HaplotypeBins',\n [referenceHandle, firstBin],\n [referenceHandle, lastBin],\n )) {\n const bin = num(row[1], 'HaplotypeBins.bin')\n decodeRuns(blob(row[3], 'HaplotypeBins.nodes'), runs)\n decodeStrays(bin, blob(row[4], 'HaplotypeBins.strays'), strays)\n }\n return { listed: runTester(runs), strays }\n }\n\n // The anchors of one reference path at offsets from lowOffset to\n // highOffset, each with the forward samples at its node.\n /** @internal */\n async haplotypeAnchorsBetween(\n pathHandle: number,\n lowOffset: number,\n highOffset: number,\n ): Promise<HaplotypeAnchorRow[]> {\n const rows: HaplotypeAnchorRow[] = []\n let parts: Uint8Array[] = []\n const flush = () => {\n const last = rows[rows.length - 1]\n if (last) {\n decodeVisits(last.node, parts, last.visits)\n }\n parts = []\n }\n for (const row of await this.blobRows(\n 'HaplotypeAnchors',\n [pathHandle, lowOffset],\n [pathHandle, highOffset],\n )) {\n const anchorOffset = num(row[1], 'HaplotypeAnchors.anchor_offset')\n if (rows[rows.length - 1]?.anchorOffset !== anchorOffset) {\n flush()\n rows.push({\n anchorOffset,\n node: num(row[3], 'HaplotypeAnchors.node_handle'),\n pathOffset: num(row[4], 'HaplotypeAnchors.path_offset'),\n visits: [],\n })\n }\n parts.push(blob(row[5], 'HaplotypeAnchors.visits'))\n }\n flush()\n return rows\n }\n\n /** @internal */\n async haplotypeAnchor(\n pathHandle: number,\n anchorOffset: number,\n ): Promise<HaplotypeAnchor | undefined> {\n const [row] = await this.haplotypeAnchorsBetween(\n pathHandle,\n anchorOffset,\n anchorOffset,\n )\n return row && { node: row.node, pathOffset: row.pathOffset }\n }\n\n /** @internal */\n haplotypeSamplesAtNode(handle: number) {\n return this.haplotypeSamplesInRange(handle, handle)\n }\n\n private sampleFromRow(values: SqlValue[]): HaplotypeSample {\n return {\n node: num(values[0], 'HaplotypeSamples.node_handle'),\n offset: num(values[1], 'HaplotypeSamples.node_offset'),\n pathHandle: num(values[2], 'HaplotypeSamples.path_handle'),\n orientation:\n num(values[3], 'HaplotypeSamples.orientation') === 0\n ? 'forward'\n : 'reverse',\n pathOffset: num(values[4], 'HaplotypeSamples.path_offset'),\n }\n }\n\n // The samples at the node handles minHandle..maxHandle, from the b-tree of\n // their key.\n /** @internal */\n async haplotypeSamplesInRange(minHandle: number, maxHandle: number) {\n const samples: HaplotypeSample[] = []\n for await (const row of this.companion.indexScanFrom(\n 'HaplotypeSamples',\n [minHandle, 0],\n [maxHandle, Number.MAX_SAFE_INTEGER],\n )) {\n samples.push(this.sampleFromRow(row))\n }\n return samples\n }\n\n /** @internal */\n async haplotypeSampleAt(node: number, offset: number) {\n const row = await this.companion.indexSeekLE('HaplotypeSamples', [\n node,\n offset,\n ])\n return row?.[0] === node && row[1] === offset\n ? this.sampleFromRow(row)\n : undefined\n }\n\n private overviewRows() {\n this.overviewRowsCache ??= forgetOnRejection(\n (async () => {\n const rows: { sample: string; haplotype: number }[] = []\n for await (const { rowid, values } of this.companion.scan(\n 'HaplotypeOverviewRows',\n )) {\n rows[rowid] = {\n sample: str(values[1], 'HaplotypeOverviewRows.sample'),\n haplotype: num(values[2], 'HaplotypeOverviewRows.haplotype'),\n }\n }\n return rows\n })(),\n () => {\n this.overviewRowsCache = undefined\n },\n )\n return this.overviewRowsCache\n }\n\n // The parts of one overview table for the chunks firstChunk..lastChunk of\n // one reference path at one level, joined per chunk.\n private async overviewChunks(\n table: string,\n pathHandle: number,\n level: number,\n firstChunk: number,\n lastChunk: number,\n ) {\n const parts = new Map<number, Uint8Array[]>()\n for (const row of await this.blobRows(\n table,\n [pathHandle, level, firstChunk],\n [pathHandle, level, lastChunk],\n )) {\n const chunk = num(row[2], `${table}.chunk`)\n const list = parts.get(chunk) ?? []\n list.push(blob(row[4], `${table} blob`))\n parts.set(chunk, list)\n }\n return new Map(\n [...parts].map(([chunk, list]) => [chunk, concatBytes(list)]),\n )\n }\n\n // The haplotype index's binned summary of every haplotype over a window of\n // a reference path, or undefined when the index has no overview or none for\n // this path, which is not a reference path of a sample with anchors.\n async haplotypeOverview(\n opts: OverviewQuery,\n ): Promise<HaplotypeOverview | undefined> {\n const tag = (key: string) =>\n this.indexTags.get(`haplotype_index_overview_${key}`)\n if (!this.index?.has('HaplotypeOverviewClasses') || tag('format') !== '1') {\n return undefined\n }\n const baseBin = Number(tag('bin'))\n const chunkBins = Number(tag('chunk'))\n const levels = Number(tag('levels'))\n let level = Math.max(\n 0,\n Math.min(Math.floor(opts.level ?? 0) || 0, levels - 1),\n )\n if (opts.level === undefined && opts.bpPerPixel !== undefined) {\n while (\n level + 1 < levels &&\n baseBin * 4 ** (level + 1) <= opts.bpPerPixel\n ) {\n level += 1\n }\n }\n const bin = baseBin * 4 ** level\n const [fragments, haplotypes] = await Promise.all([\n this.getPathFragments(opts),\n this.overviewRows(),\n ])\n const bytesPerBin = Math.ceil(haplotypes.length / 2)\n const bins: OverviewBin[] = []\n const cellRows: Uint8Array[] = []\n for (const fragment of fragments) {\n const length = fragment.end - fragment.start\n const from = Math.max(opts.start, fragment.start) - fragment.start\n const to = Math.min(opts.end, fragment.end) - fragment.start\n const firstBin = Math.floor(from / bin)\n const lastBin = Math.floor((to - 1) / bin)\n const firstChunk = Math.floor(firstBin / chunkBins)\n const lastChunk = Math.floor(lastBin / chunkBins)\n const [summaries, cells] = await Promise.all([\n this.overviewChunks(\n 'HaplotypeOverviewBins',\n fragment.path.handle,\n level,\n firstChunk,\n lastChunk,\n ),\n this.overviewChunks(\n 'HaplotypeOverviewClasses',\n fragment.path.handle,\n level,\n firstChunk,\n lastChunk,\n ),\n ])\n for (let chunk = firstChunk; chunk <= lastChunk; chunk++) {\n const reader = new Varints(summaries.get(chunk) ?? new Uint8Array())\n const packed = cells.get(chunk) ?? new Uint8Array()\n for (let b = chunk * chunkBins; !reader.done; b++) {\n const values = Array.from({ length: 7 }, () => reader.next())\n if (b < firstBin || b > lastBin) {\n continue\n }\n bins.push({\n start: fragment.start + b * bin,\n end: fragment.start + Math.min((b + 1) * bin, length),\n classes: [values[0]!, values[1]!, values[2]!, values[3]!],\n excursions: values[4]!,\n variants: values[5]!,\n longestExcursion: values[6]!,\n })\n const at = (b - chunk * chunkBins) * bytesPerBin\n cellRows.push(packed.subarray(at, at + bytesPerBin))\n }\n }\n }\n if (bins.length === 0) {\n return undefined\n }\n const cells = new Uint8Array(bins.length * haplotypes.length)\n cellRows.forEach((packed, b) => {\n for (let row = 0; row < haplotypes.length; row++) {\n cells[b * haplotypes.length + row] =\n ((packed[row >> 1] ?? 0) >> (4 * (row % 2))) & 0xf\n }\n })\n return { level, bin, haplotypes, bins, cells }\n }\n\n /** @internal */\n async haplotypeLength(pathHandle: number) {\n const row = await this.companion.byRowid('HaplotypeLengths', pathHandle)\n return row ? num(row[1], 'HaplotypeLengths.length') : undefined\n }\n\n private async indexedRow(rowid: number): Promise<IndexedPosition> {\n const row = await this.sqlite.byRowid('ReferenceIndex', rowid)\n if (!row) {\n throw new Error('ReferenceIndex row referenced by its index is missing')\n }\n return {\n pathOffset: num(row[1], 'ReferenceIndex.path_offset'),\n pos: {\n node: num(row[2], 'ReferenceIndex.node_handle'),\n offset: num(row[3], 'ReferenceIndex.node_offset'),\n },\n }\n }\n\n private async indexedRowid(pathHandle: number, pathOffset: number) {\n const key = await this.sqlite.indexSeekLE('ReferenceIndex', [\n pathHandle,\n pathOffset,\n ])\n return key?.[0] === pathHandle\n ? num(key[2], 'ReferenceIndex rowid')\n : undefined\n }\n\n /** @internal */\n async indexedPosition(\n pathHandle: number,\n pathOffset: number,\n ): Promise<IndexedPosition | undefined> {\n const rowid = await this.indexedRowid(pathHandle, pathOffset)\n return rowid === undefined ? undefined : this.indexedRow(rowid)\n }\n\n /** @internal */\n async indexedPositionsBetween(\n pathHandle: number,\n fromOffset: number,\n toOffset: number,\n ) {\n const [first, last] = await Promise.all([\n this.indexedRowid(pathHandle, fromOffset),\n this.indexedRowid(pathHandle, toOffset),\n ])\n const positions: IndexedPosition[] = []\n if (first !== undefined && last !== undefined) {\n await this.sqlite.prefetchRows('ReferenceIndex', [[first, last + 1]])\n for (let rowid = first; rowid <= last; rowid++) {\n positions.push(await this.indexedRow(rowid))\n }\n }\n return positions\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["encodeNode", "id", "orientation", "nodeId", "handle", "nodeOrientation", "isReverse", "flipNode", "flipSide", "side", "entrySide", "exitSide", "entryOrientation", "exitOrientation", "edgeIsCanonical", "from", "to", "fromId", "toId", "pathIsCanonical", "path", "pathEndsAreCanonical", "first", "last", "ByteCodeReader", "bytes", "value", "shift", "result", "RLE_THRESHOLD", "RLE_UNIVERSE", "RunReader", "sigma", "len", "byte", "extra", "run", "decompressEdges", "bytes", "reader", "ByteCodeReader", "sigma", "edges", "prev", "i", "delta", "offset", "GbwtRecord", "bwt", "RunReader", "rank", "edge", "offsets", "e", "run", "soFar", "node", "low", "high", "mid", "pos", "succRank", "counts", "flipNode", "entry", "curr", "nodeId", "total", "nodes", "nextOffsets", "k", "result", "DECODE", "encodedSequenceLength", "encoded", "last", "value", "inLast", "i", "decodeSequence", "result", "byte", "base", "COMPLEMENT", "reverseComplement", "sequence", "K", "rotr", "x", "n", "sha256", "bytes", "blocks", "padded", "view", "bits", "h", "w", "block", "t", "a", "s0", "s1", "b", "c", "d", "e", "f", "g", "hh", "ch", "t1", "maj", "value", "i", "out", "outView", "parseRelationships", "field", "what", "relationships", "rel", "parts", "from", "to", "targets", "graphNameFromTags", "tags", "merge", "into", "key", "values", "value", "subgraphName", "name", "parent", "result", "sortedEntries", "a", "b", "tos", "gfaHeaderLines", "graphName", "lines", "subgraph", "supergraph", "sha256Hex", "chunks", "total", "sum", "chunk", "bytes", "offset", "subtle", "sha256", "byte", "GENERIC_SAMPLE", "formatPathName", "name", "base", "PAN_SN", "BARE_CONTIG", "parsePathName", "panSn", "bare", "toPathQuery", "ref", "pathNameFor", "query", "fragment", "SCAN_GAP", "handleRuns", "sortedHandles", "runs", "handle", "last", "CHAIN_BOUND", "keepTuning", "PositionIndex", "pos", "id", "offsets", "Fallback", "forwardLeft", "orientation", "left", "currentLen", "nextLen", "backwardLeft", "previousLen", "twinIsCanonical", "piece", "pathEndsAreCanonical", "flipNode", "pieceKey", "findChosenPieces", "input", "db", "records", "signal", "clock", "lap", "now", "elapsed", "stats", "countWalk", "kind", "end", "key", "interval", "outside", "record", "inside", "fetched", "lengthIn", "pathsByHandle", "chosen", "pathHandle", "path", "pieces", "pieceAt", "piecesOfPath", "forwardDone", "backwardDone", "next", "successor", "previous", "within", "predecessor", "offset", "addPiece", "cursors", "source", "handles", "c", "len", "hapStart", "cursor", "ofPath", "pieceThrough", "seed", "before", "after", "pieceAtOrThrough", "lastCursor", "node", "firstCursor", "referenceId", "reference", "result", "byKey", "emitted", "group", "orientations", "chain", "forward", "done", "other", "current", "bp", "known", "strayRoute", "strays", "spacing", "bin", "bound", "fills", "inserted", "fill", "firstBin", "lastBin", "lo", "hi", "anchorOf", "readAnchors", "fromK", "toK", "rows", "row", "lowest", "highest", "listed", "found", "nodeId", "isReverse", "y", "scanning", "first", "multiples", "own", "anchorOffset", "k", "multiplesOf", "anchorNodes", "anchorRows", "visits", "atAnchors", "i", "ks", "plans", "prefetchLo", "prefetchHi", "list", "x", "from", "to", "low", "high", "a", "b", "filled", "cap", "counted", "walkBp", "walkedRanges", "covered", "markWalked", "walkForward", "start", "startLeft", "until", "reached", "walkBackward", "earlier", "earlierLeft", "stop", "reachedEnd", "reachedStart", "reversed", "samples", "sample", "canonicalTwins", "orientationsOf", "note", "seen", "noted", "noteNew", "hasTwin", "twinBound", "needsTwin", "walkedBp", "hit", "flipped", "s", "walk", "toPiece", "landed", "landedId", "error", "extractionOrder", "lowerBound", "ascending", "value", "lo", "hi", "mid", "ColumnMax", "columns", "column", "best", "p", "candidate", "holder", "SparseLcs", "a", "b", "weight", "x", "j", "list", "a0", "a1", "b0", "b1", "prefix", "suffix", "k", "i", "matches", "split", "count", "from", "to", "step", "trace", "w", "before", "match", "last", "chained", "width", "after", "s", "combined", "weightedLcs", "lcs", "DEFAULT_MIN_MATCH", "MAX_ALIGNED_CELLS", "CHAIN_LOOKBACK", "KMER", "MAX_KMER_OCCURRENCES", "MAX_FILL_DEPTH", "MATCH", "MISMATCH", "GAP_OPEN", "GAP_EXTEND", "UNREACHABLE", "DIAGONAL", "INSERTION", "DELETION", "appendEdit", "edits", "op", "len", "last", "best", "diagonal", "insertion", "deletion", "affineAlignment", "a", "b", "la", "lb", "width", "trace", "j", "i", "nextDiagonal", "nextInsertion", "nextDeletion", "ai", "fromDiagonal", "fromInsertion", "fromDeletion", "ops", "state", "from", "stepJumpCost", "dq", "dt", "indel", "kmerJumpCost", "sliceRun", "run", "to", "untakenPieces", "query", "target", "blocked", "s", "e", "lo", "hi", "x", "y", "pieces", "chainRuns", "runs", "maxGap", "minMatch", "jumpCost", "maxChains", "chains", "basesTaken", "spanTaken", "pool", "score", "back", "trims", "trim", "candidate", "matched", "end", "chain", "first", "flipped", "spans", "same", "forwardKmerRuns", "index", "p", "kmer", "seen", "open", "hits", "started", "kmerRuns", "reverseComplement", "chainEdits", "between", "previous", "qs", "targetFrom", "targetTo", "unaligned", "alignExact", "fillGap", "depth", "deeper", "qa", "tb", "into", "fill", "recordOf", "alignPrivate", "inversions", "forward", "forwardFill", "queryFrom", "inversion", "forEachEdit", "r", "visit", "qi", "ti", "scoreOver", "side", "step", "inside", "k", "at", "spanOf", "withoutColumns", "lost", "pendingQuery", "pendingTarget", "column", "sharedLost", "sharedMask", "inShared", "flush", "lead", "tail", "claimOnce", "records", "queryLength", "targetLength", "claims", "columnsOf", "columns", "holders", "held", "beaten", "losesTo", "key", "loses", "si", "ei", "sj", "ej", "mine", "theirs", "margin", "c", "kept", "sum", "walkSequence", "walk", "sequenceOf", "handle", "sequence", "nodeId", "isReverse", "walkOffsets", "offsets", "repeatSteps", "id", "change", "sharedRuns", "queryOffsets", "targetOffsets", "queryRepeat", "targetRepeat", "visits", "rank", "seeds", "lastRank", "pairAlignments", "opts", "bases", "_", "record", "pairCigar", "SubgraphLimitError", "limit", "walk", "sideBefore", "a", "b", "SideQueue", "distance", "node", "side", "heap", "i", "parent", "top", "last", "left", "right", "smallest", "asMatches", "pairs", "pathAt", "refAt", "firstAbove", "ascending", "bound", "lo", "hi", "mid", "posKey", "pos", "flipPath", "path", "handle", "flipNode", "joinable", "insertion", "deletion", "joinPair", "gap", "edits", "op", "len", "appendGap", "appendEdit", "walkForward", "first", "second", "joinSiblings", "fragments", "mostlyAligned", "alignJointly", "f", "byPath", "fragment", "index", "siblings", "joined", "consumed", "x", "y", "head", "current", "between", "next", "joint", "pathPosition", "info", "k", "PREFETCH_RUN_GAP", "rowidRuns", "handles", "sorted", "runs", "Subgraph", "_Subgraph", "db", "opts", "id", "encodeNode", "record", "forward", "reverse", "query", "formatPathName", "queryOffset", "indexed", "startOffset", "start", "pathOffset", "nodeId", "nodeOffset", "context", "orientation", "nodeOrientation", "active", "entrySide", "exitSide", "reference", "pathHandle", "fromOffset", "toOffset", "positions", "p", "error", "offset", "remaining", "distanceToNext", "nodes", "visited", "toRemove", "inserted", "key", "otherSide", "flipSide", "entryOrientation", "nextDistance", "exitOrientation", "successor", "successorId", "successorSide", "end", "curr", "snarls", "total", "result", "foundLink", "edgeIsCanonical", "covering", "successors", "onFetch", "outside", "inside", "read", "isSnarlEntry", "classify", "queue", "done", "type", "output", "refPos", "count", "indexOf", "rowStart", "seqLen", "rows", "row", "nextIndex", "nextOffset", "hasPredecessor", "j", "refIndex", "refGbwtOffset", "refOffset", "offsets", "steps", "cur", "off", "at", "keep", "twinsExpected", "isReverse", "from", "degree", "lastHandle", "pathEndsAreCanonical", "twinRecord", "startCount", "allTwins", "bare", "refInfo", "before", "deferTwins", "refPath", "referenceTwin", "pathIsCanonical", "deferred", "comparePaths", "defer", "merged", "refId", "apart", "interval", "span", "identity", "kept", "wanted", "unnamed", "found", "findChosenPieces", "pathsByHandle", "infoOf", "piece", "ordered", "extractionOrder", "handleRuns", "samples", "fetched", "sample", "scanned", "run", "starts", "identification", "readRecord", "recordAt", "sampleAt", "chain", "names", "nameOf", "name", "anchorFromSample", "counter", "nodeLen", "anchorFromIdentity", "startInfo", "anchor", "bp", "position", "known", "startBp", "ref", "occurrences", "prefix", "pi", "ri", "pb", "rb", "pathLen", "refLen", "suffix", "weight", "lcs", "weightedLcs", "refPrefix", "alignGap", "pathFrom", "pathTo", "refFrom", "refTo", "matched", "m", "nextPath", "nextRef", "pathIndex", "flippedPath", "forwardBound", "flipped", "refTotal", "strand", "pieces", "soloAligned", "trimmed", "trimEnds", "low", "high", "aligned", "sum", "bases", "length", "parts", "part", "inWalkOrder", "infos", "gaps", "alignedInfos", "alignedGaps", "keptInOrder", "alignedIn", "keeps", "insertions", "walked", "spliceInsertions", "alongReference", "rest", "cigarOf", "target", "pairOptions", "walks", "haplotypeOrderedPath", "haplotype", "isTarget", "isQuery", "sequenceOf", "targetWalk", "queryWalk", "pairAlignments", "pairCigar", "edges", "edge", "encoder", "chunks", "text", "fromReverse", "toId", "toReverse", "sha256Hex", "cigar", "lines", "gfaHeaderLines", "subgraphName", "sign", "cigarString", "cg", "contig", "resolved", "entries", "to", "paths", "entry", "jsonPath", "nodeIds", "nodeSequences", "edgeHandles", "haplotypeOrderedPath", "info", "identity", "handle", "flipNode", "jsonPath", "name", "cigar", "nodeId", "isReverse", "comparePaths", "a", "b", "n", "i", "x", "y", "appendEdit", "edits", "op", "len", "last", "gapPenalty", "appendGap", "pathMiddle", "refMiddle", "mismatch", "mismatchIndel", "insertionDeletion", "trimEnds", "first", "inserted", "trailing", "sum", "ends", "run", "head", "tail", "trimmed", "alignedIn", "lengths", "aligned", "piece", "pieceEnd", "walked", "rest", "step", "spliceInsertions", "insertions", "spliced", "next", "from", "at", "cigarOf", "wholeNumber", "name", "value", "min", "contextOf", "opts", "createSubgraph", "db", "Subgraph", "subgraphAtOffset", "context", "subgraph", "reference", "pathNameFor", "toPathQuery", "aroundWindow", "start", "end", "error", "SubgraphLimitError", "subgraphInInterval", "keep", "haplotypes", "named", "subgraphAroundNodes", "snarls", "id", "subgraphBetween", "readVarint", "bytes", "offset", "value", "i", "byte", "last", "readSignedInt", "view", "width", "big", "decoder", "decodeRecord", "payload", "headerSize", "firstType", "types", "type", "next", "body", "length", "slice", "INTERIOR_INDEX", "INTERIOR_TABLE", "LEAF_INDEX", "LEAF_TABLE", "readUint16", "page", "offset", "readUint32", "readHeader", "start", "type", "interior", "cellOffset", "header", "index", "MAX_DECODED_INDEX_PAGES", "BTree", "pager", "reservedBytes", "total", "isIndex", "usable", "maxLocal", "minLocal", "spill", "local", "result", "filled", "next", "overflow", "chunk", "pageNumber", "root", "towards", "depth", "level", "child", "rowid", "low", "high", "mid", "key", "readVarint", "ranges", "stream", "leafLevel", "frontiers", "pages", "r", "lo", "hi", "decoded", "n", "children", "i", "from", "to", "c", "size", "afterSize", "afterKey", "decodeRecord", "cells", "oldest", "cell", "inclusive", "order", "compareKey", "first", "past", "best", "values", "a", "b", "checkPagerOptions", "blockSize", "maxBlocks", "Pager", "source", "pageSize", "fileSize", "opts", "requested", "length", "start", "bytes", "attempt", "error", "resolve", "index", "cached", "pending", "pageNumber", "pageNumbers", "indexes", "blocks", "position", "count", "plan", "slice", "at", "wanted", "a", "b", "runStart", "runEnd", "firstIndex", "i", "within", "block", "oldest", "offset", "SqliteDatabase", "_SqliteDatabase", "pager", "btree", "objects", "source", "opts", "checkPagerOptions", "firstBlock", "header", "view", "rawPageSize", "pageSize", "reserved", "encoding", "pageCount", "size", "Pager", "BTree", "values", "type", "name", "tableName", "rootPage", "sql", "object", "table", "index", "o", "rowid", "ranges", "stream", "key", "low", "high", "SCHEMA_VERSION", "UnknownPathError", "path", "formatPathName", "ForwardOnlyIndexError", "SchemaVersionError", "found", "OVERVIEW_ABSENT", "OVERVIEW_REFERENCE", "OVERVIEW_PARTIAL", "OVERVIEW_VARIANT", "concatBytes", "parts", "whole", "p", "at", "part", "INDEX_FORMAT", "Varints", "bytes", "value", "scale", "byte", "decodeRuns", "runs", "reader", "previous", "start", "runTester", "x", "y", "starts", "ends", "end", "last", "id", "lo", "hi", "mid", "decodeStrays", "bin", "rows", "pathHandle", "pathStart", "pathEnd", "low", "high", "decodeVisits", "anchorNode", "visits", "nodeId", "pathAndBit", "bit", "GbzRecord", "handle", "edges", "bwt", "encodedSequence", "next", "encodedSequenceLength", "nodeOrientation", "decodeSequence", "GbwtRecord", "num", "what", "str", "blob", "rowToPath", "rowid", "values", "forgetOnRejection", "pending", "forget", "readTags", "sqlite", "tags", "GBZBase", "_GBZBase", "index", "opts", "source", "haplotypeIndex", "pagerOptions", "SqliteDatabase", "version", "table", "db", "indexed", "paths", "indexedNodes", "nodes", "format", "key", "ranges", "stream", "row", "decompressEdges", "name", "a", "b", "ref", "pathNameFor", "toPathQuery", "length", "pos", "record", "ordered", "covering", "within", "f", "fragment", "sample", "contig", "haplotype", "haplotypes", "subgraph", "subgraphInInterval", "error", "SubgraphLimitError", "fragments", "result", "subgraphAtOffset", "subgraphAroundNodes", "subgraphBetween", "stats", "pager", "gbzTags", "graphNameFromTags", "links", "interval", "reference", "tag", "snarls", "rowids", "referenceHandle", "firstBin", "lastBin", "strays", "lowOffset", "highOffset", "flush", "anchorOffset", "minHandle", "maxHandle", "samples", "node", "offset", "level", "firstChunk", "lastChunk", "chunk", "list", "baseBin", "chunkBins", "levels", "bytesPerBin", "bins", "cellRows", "from", "to", "summaries", "cells", "packed", "pathOffset", "fromOffset", "toOffset", "first", "positions"]
7
+ }