jbrowse-plugin-graphgenomeviewer 4.0.12 → 4.0.13
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.
- package/README.md +21 -5
- package/dist/chunks/GbzBaseSyntenyAdapter-Y5NBXK7P.js +8 -0
- package/dist/chunks/{GbzBaseSyntenyAdapter-5ZQ2IPHJ.js.map → GbzBaseSyntenyAdapter-Y5NBXK7P.js.map} +3 -3
- package/dist/chunks/{GraphGenomeView-SRR7EJFX.js → GraphGenomeView-TTQEJJQD.js} +2 -2
- package/dist/chunks/{GraphGenomeView-SRR7EJFX.js.map → GraphGenomeView-TTQEJJQD.js.map} +1 -1
- package/dist/chunks/GraphTrackSettingsDialog-3A2PKZRI.js +4 -0
- package/dist/chunks/{GraphTrackSettingsDialog-LZITZ3VD.js.map → GraphTrackSettingsDialog-3A2PKZRI.js.map} +1 -1
- package/dist/chunks/LinearGraphDisplay-MJ5XZFE5.js +2 -0
- package/dist/chunks/{LinearGraphDisplay-J3KVTK4C.js.map → LinearGraphDisplay-MJ5XZFE5.js.map} +1 -1
- package/dist/chunks/{MinigraphBubbleAdapter-QTXGK7DW.js → MinigraphBubbleAdapter-APC7JYOM.js} +2 -2
- package/dist/chunks/{RgfaTabixAdapter-O3ERR2GY.js → RgfaTabixAdapter-4E365PXO.js} +2 -2
- package/dist/chunks/{chunk-LGGAXAS6.js → chunk-5DP7IXD3.js} +2 -2
- package/dist/chunks/chunk-CJ56O2VG.js +2 -0
- package/dist/chunks/chunk-CJ56O2VG.js.map +7 -0
- package/dist/chunks/chunk-EFVAQ2KM.js +2 -0
- package/dist/chunks/chunk-EFVAQ2KM.js.map +7 -0
- package/dist/chunks/chunk-IFRDWMQ2.js +2 -0
- package/dist/chunks/chunk-IFRDWMQ2.js.map +7 -0
- package/dist/chunks/chunk-JAQ2RQAE.js +2 -0
- package/dist/chunks/{chunk-QRVREF7H.js.map → chunk-JAQ2RQAE.js.map} +4 -4
- package/dist/chunks/{chunk-WETM2CD7.js → chunk-LA7MQS33.js} +2 -2
- package/dist/chunks/chunk-M4YEAXSR.js +2 -0
- package/dist/chunks/chunk-M4YEAXSR.js.map +7 -0
- package/dist/chunks/chunk-XDOIZTY6.js +4 -0
- package/dist/chunks/chunk-XDOIZTY6.js.map +7 -0
- package/dist/jbrowse-plugin-graphgenomeviewer.esm.js +2 -2
- package/dist/jbrowse-plugin-graphgenomeviewer.esm.js.map +4 -4
- package/package.json +3 -3
- package/src/GraphGenomeView/components/GraphCanvas.tsx +4 -11
- package/src/GraphGenomeView/components/TubeMapOverlay.tsx +117 -4
- package/src/GraphGenomeView/components/WalkRowsOverlay.tsx +261 -44
- package/src/GraphGenomeView/components/referenceRampCss.test.ts +27 -0
- package/src/GraphGenomeView/components/referenceRampCss.ts +39 -0
- package/src/GraphGenomeView/genes/genes.test.ts +9 -2
- package/src/GraphGenomeView/host.test.ts +25 -2
- package/src/GraphGenomeView/host.ts +9 -7
- package/src/GraphGenomeView/model.test.ts +383 -4
- package/src/GraphGenomeView/model.ts +413 -88
- package/src/GraphGenomeView/repeats/repeatFeatures.test.ts +75 -0
- package/src/GraphGenomeView/repeats/repeatFeatures.ts +156 -8
- package/src/GraphGenomeView/repeats/walkCalls.test.ts +18 -0
- package/src/GraphGenomeView/repeats/walkCalls.ts +35 -18
- package/src/GraphGenomeView/subgraphLoad.test.ts +1 -0
- package/src/LinearGraphDisplay/LinearGraphDisplay.test.ts +165 -6
- package/src/LinearGraphDisplay/model.ts +61 -1
- package/src/gaf/gafFile.test.ts +18 -0
- package/src/version.ts +1 -1
- package/dist/chunks/GbzBaseSyntenyAdapter-5ZQ2IPHJ.js +0 -8
- package/dist/chunks/GraphTrackSettingsDialog-LZITZ3VD.js +0 -4
- package/dist/chunks/LinearGraphDisplay-J3KVTK4C.js +0 -2
- package/dist/chunks/chunk-ADEBM7AA.js +0 -2
- package/dist/chunks/chunk-ADEBM7AA.js.map +0 -7
- package/dist/chunks/chunk-J7CABMMI.js +0 -2
- package/dist/chunks/chunk-J7CABMMI.js.map +0 -7
- package/dist/chunks/chunk-LBHU3DHN.js +0 -4
- package/dist/chunks/chunk-LBHU3DHN.js.map +0 -7
- package/dist/chunks/chunk-QRVREF7H.js +0 -2
- /package/dist/chunks/{MinigraphBubbleAdapter-QTXGK7DW.js.map → MinigraphBubbleAdapter-APC7JYOM.js.map} +0 -0
- /package/dist/chunks/{RgfaTabixAdapter-O3ERR2GY.js.map → RgfaTabixAdapter-4E365PXO.js.map} +0 -0
- /package/dist/chunks/{chunk-LGGAXAS6.js.map → chunk-5DP7IXD3.js.map} +0 -0
- /package/dist/chunks/{chunk-WETM2CD7.js.map → chunk-LA7MQS33.js.map} +0 -0
|
@@ -3,6 +3,7 @@ import { lazy } from 'react'
|
|
|
3
3
|
import { layoutModeByValue } from '@jbrowse/bandage-core/layoutModes'
|
|
4
4
|
import { ConfigurationReference, getConf } from '@jbrowse/core/configuration'
|
|
5
5
|
import { BaseDisplay } from '@jbrowse/core/pluggableElementTypes'
|
|
6
|
+
import { pushLaunchViewMenuItem } from '@jbrowse/core/ui'
|
|
6
7
|
import { getSession } from '@jbrowse/core/util'
|
|
7
8
|
import TrackHeightMixin from '@jbrowse/display-kit/TrackHeightMixin'
|
|
8
9
|
import { addDisposer, types } from '@jbrowse/mobx-state-tree'
|
|
@@ -10,6 +11,7 @@ import {
|
|
|
10
11
|
computeActivityPhase,
|
|
11
12
|
computeDisplayStatusPhase,
|
|
12
13
|
} from '@jbrowse/render-core/displayPhase'
|
|
14
|
+
import BubbleChartIcon from '@mui/icons-material/BubbleChart'
|
|
13
15
|
import SettingsIcon from '@mui/icons-material/Settings'
|
|
14
16
|
import { reaction } from 'mobx'
|
|
15
17
|
|
|
@@ -28,12 +30,15 @@ import {
|
|
|
28
30
|
import type { LinearGraphDisplayConfigModel } from './configSchema'
|
|
29
31
|
import type { SubgraphRegion, SubgraphTier } from '../GetSubgraph'
|
|
30
32
|
import type { HostWindow } from '../GraphGenomeView/host'
|
|
33
|
+
import type { LaunchGraphGenomeViewArgs } from '../LaunchGraphGenomeView'
|
|
31
34
|
import type { ColorScheme } from '@jbrowse/bandage-core/colorSchemes'
|
|
32
35
|
import type { LayoutModeValue } from '@jbrowse/bandage-core/layoutModes'
|
|
33
36
|
import type { MenuItem } from '@jbrowse/core/ui'
|
|
34
37
|
import type { Instance } from '@jbrowse/mobx-state-tree'
|
|
35
38
|
import type { DisplayStatusPhase } from '@jbrowse/render-core/displayPhase'
|
|
36
39
|
|
|
40
|
+
type GraphViewSpec = Omit<LaunchGraphGenomeViewArgs, 'session'>
|
|
41
|
+
|
|
37
42
|
const GraphTrackSettingsDialog = lazy(
|
|
38
43
|
() => import('./components/GraphTrackSettingsDialog'),
|
|
39
44
|
)
|
|
@@ -334,8 +339,63 @@ export function stateModelFactory(configSchema: LinearGraphDisplayConfigModel) {
|
|
|
334
339
|
)
|
|
335
340
|
},
|
|
336
341
|
}))
|
|
342
|
+
.views(self => ({
|
|
343
|
+
// The window on screen as a view of its own, drawn as the track draws
|
|
344
|
+
// it: the cut less the margins it holds for panning. A window forced
|
|
345
|
+
// past the cap carries its own span as the cap.
|
|
346
|
+
get graphViewSpec() {
|
|
347
|
+
const seen = self.host ? hostWindow(self.host) : undefined
|
|
348
|
+
const trackId = self.sourceTrackId
|
|
349
|
+
if (
|
|
350
|
+
!seen ||
|
|
351
|
+
!trackId ||
|
|
352
|
+
!self.hasGraph ||
|
|
353
|
+
self.coarseCut ||
|
|
354
|
+
self.regionTooLarge
|
|
355
|
+
) {
|
|
356
|
+
return undefined
|
|
357
|
+
}
|
|
358
|
+
const start = Math.floor(seen.start)
|
|
359
|
+
const end = Math.ceil(seen.end)
|
|
360
|
+
return {
|
|
361
|
+
loadedTrackId: trackId,
|
|
362
|
+
loadedRegion: {
|
|
363
|
+
refName: seen.refName,
|
|
364
|
+
assemblyName: seen.assemblyName,
|
|
365
|
+
start,
|
|
366
|
+
end,
|
|
367
|
+
},
|
|
368
|
+
subgraphContext: self.subgraphContext,
|
|
369
|
+
subgraphHaplotypes: self.chosenHaplotypes,
|
|
370
|
+
maxRegionBp: Math.max(self.maxRegionBp, end - start),
|
|
371
|
+
layoutMode: self.chosenLayoutMode,
|
|
372
|
+
colorScheme: self.chosenColorScheme,
|
|
373
|
+
referencePath: self.referencePath,
|
|
374
|
+
geneTrackId: self.geneTrackId,
|
|
375
|
+
showGenes: self.showGenes,
|
|
376
|
+
} satisfies GraphViewSpec
|
|
377
|
+
},
|
|
378
|
+
}))
|
|
379
|
+
.actions(self => ({
|
|
380
|
+
openGraphView() {
|
|
381
|
+
const spec = self.graphViewSpec
|
|
382
|
+
if (spec) {
|
|
383
|
+
getSession(self).addView('GraphGenomeView', spec)
|
|
384
|
+
}
|
|
385
|
+
},
|
|
386
|
+
}))
|
|
337
387
|
.views(self => ({
|
|
338
388
|
trackMenuItems(): MenuItem[] {
|
|
389
|
+
const launches = self.launchMenuItems()
|
|
390
|
+
pushLaunchViewMenuItem(launches, {
|
|
391
|
+
label: 'Graph genome view',
|
|
392
|
+
icon: BubbleChartIcon,
|
|
393
|
+
disabled: !self.graphViewSpec,
|
|
394
|
+
disabledHelpText: 'Zoom in until the track cuts a graph',
|
|
395
|
+
onClick: () => {
|
|
396
|
+
self.openGraphView()
|
|
397
|
+
},
|
|
398
|
+
})
|
|
339
399
|
return [
|
|
340
400
|
...self.graphMenuItems(),
|
|
341
401
|
{
|
|
@@ -348,7 +408,7 @@ export function stateModelFactory(configSchema: LinearGraphDisplayConfigModel) {
|
|
|
348
408
|
])
|
|
349
409
|
},
|
|
350
410
|
},
|
|
351
|
-
...
|
|
411
|
+
...launches,
|
|
352
412
|
]
|
|
353
413
|
},
|
|
354
414
|
}))
|
package/src/gaf/gafFile.test.ts
CHANGED
|
@@ -3,6 +3,8 @@ import fs from 'fs'
|
|
|
3
3
|
import path from 'path'
|
|
4
4
|
import zlib from 'zlib'
|
|
5
5
|
|
|
6
|
+
import { TabixIndexedFile } from '@gmod/tabix'
|
|
7
|
+
|
|
6
8
|
import { GafFile, MAX_READS, UnindexedGafTooLargeError } from './gafFile.ts'
|
|
7
9
|
|
|
8
10
|
const dir = path.join(__dirname, '../../test_data/cactus')
|
|
@@ -42,6 +44,22 @@ test('gzipped and bgzipped GAF read the same as plain', async () => {
|
|
|
42
44
|
).toEqual(plain)
|
|
43
45
|
})
|
|
44
46
|
|
|
47
|
+
test('an indexed GAF answers the same reads as reading it whole', async () => {
|
|
48
|
+
const gz = path.join(dir, 'cactus_240_280.gaf.gz')
|
|
49
|
+
const indexed = new GafFile(
|
|
50
|
+
inMemory(fs.readFileSync(gz)),
|
|
51
|
+
new TabixIndexedFile({ path: gz, tbiPath: `${gz}.tbi` }),
|
|
52
|
+
)
|
|
53
|
+
const whole = new GafFile(inMemory(bytes))
|
|
54
|
+
for (const ids of [names(249), names(250, 251, 260), names(1, 2)]) {
|
|
55
|
+
const { records } = await indexed.readsOver(ids)
|
|
56
|
+
expect(unordered(records)).toEqual(
|
|
57
|
+
unordered((await whole.readsOver(ids)).records),
|
|
58
|
+
)
|
|
59
|
+
}
|
|
60
|
+
expect((await indexed.readsOver(names(249))).total).toBeGreaterThan(0)
|
|
61
|
+
})
|
|
62
|
+
|
|
45
63
|
test('a large unindexed GAF asks for an index instead', async () => {
|
|
46
64
|
const gaf = new GafFile(inMemory(bytes, 60 * 2 ** 20))
|
|
47
65
|
await expect(gaf.readsOver(names(250))).rejects.toThrow(
|
package/src/version.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = '4.0.
|
|
1
|
+
export const version = '4.0.13'
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import{a as Cn,b as Rn,c as _n,d as Ao}from"./chunk-QRVREF7H.js";import{a as Mn}from"./chunk-KWAXLUPQ.js";import"./chunk-LGKM2PZH.js";import{a as Eo,e as kn,f as Ln}from"./chunk-XK7OPCRQ.js";import{a as Ce}from"./chunk-J4OLMLS5.js";import{a as On,b as Tn}from"./chunk-SCMIJAAX.js";import{a as Pn,d as ue,e as me,f as $t}from"./chunk-MUK3KYB4.js";import{a as Io,b as W}from"./chunk-FY3BTKY4.js";var mo=Io((al,uo)=>{uo.exports=JBrowseExports["@jbrowse/core/util/installClearHoverOnSurfaceMove"]});function V(r,e){return 2*r+(e==="reverse"?1:0)}function A(r){return Math.floor(r/2)}function ge(r){return r%2===0?"forward":"reverse"}function O(r){return r%2===1}function B(r){return r%2===0?r+1:r-1}function Nn(r){return r==="left"?"right":"left"}function He(r){return r==="forward"?"left":"right"}function Ge(r){return r==="forward"?"right":"left"}function Fn(r){return r==="left"?"forward":"reverse"}function qn(r){return r==="right"?"forward":"reverse"}function we(r,e){let t=A(r),n=A(e);return O(r)?n>t||n===t&&!O(e):n>=t}function $n(r){return Be(r[0],r[r.length-1])}function Be(r,e){return r===void 0||e===void 0?!0:O(r)===O(e)?!O(r):we(r,e)}var Re=class{offset=0;bytes;constructor(e){this.bytes=e}get done(){return this.offset>=this.bytes.length}byte(){let e=this.bytes[this.offset];if(e!==void 0)return this.offset+=1,e}int(){let e=1,t=0;for(;this.offset<this.bytes.length;){let n=this.bytes[this.offset];if(this.offset+=1,t+=(n&127)*e,e*=128,(n&128)===0)return t}}},Hn=255,Ro=256,De=class{source;sigma;threshold;constructor(e,t){this.source=new Re(e),this.sigma=t===0?Number.MAX_SAFE_INTEGER:t,this.threshold=this.sigma<Hn?Math.floor(Ro/this.sigma):0}next(){if(this.sigma>=Hn){let o=this.source.int(),s=this.source.int();return o===void 0||s===void 0?void 0:{value:o,len:s+1}}let e=this.source.byte();if(e===void 0)return;let t=e%this.sigma,n=Math.floor(e/this.sigma)+1;if(n===this.threshold){let o=this.source.int();if(o===void 0)return;n+=o}return{value:t,len:n}}*[Symbol.iterator](){for(let e=this.next();e!==void 0;e=this.next())yield e}};function Gn(r){let e=new Re(r),t=e.int();if(t===void 0||t===0)return[];let n=[],o=0;for(let s=0;s<t;s++){let i=e.int(),a=e.int();if(i===void 0||a===void 0)throw new Error("GBWT edge list ends early");o+=i,n.push({node:o,offset:a})}return n}var ze=class{edges;bwt;constructor(e,t){this.edges=e,this.bwt=t}runs(){return new De(this.bwt,this.edges.length)}edge(e){let t=this.edges[e];if(t===void 0)throw new Error(`GBWT run refers to edge rank ${e} of ${this.edges.length}`);return t}lf(e){let t=this.edges.map(o=>o.offset),n=0;for(let o of this.runs()){let s=this.edge(o.value),i=t[o.value];if(n+o.len>e)return s.node===0?void 0:{node:s.node,offset:i+(e-n)};t[o.value]=i+o.len,n+=o.len}}edgeTo(e){let t=0,n=this.edges.length;for(;t<n;){let o=t+n>>1,s=this.edges[o];if(s.node===e)return o;s.node<e?t=o+1:n=o}}offsetTo(e){if(e.node===0)return;let t=this.edgeTo(e.node);if(t===void 0)return;let n=this.edges[t].offset;if(n>e.offset)return;let o=0;for(let s of this.runs())if(o+=s.len,s.value===t&&(n+=s.len,n>e.offset))return o-(n-e.offset)}predecessorAt(e){let t=this.edges.map(o=>({node:o.node===0?0:B(o.node),count:0}));for(let o of this.runs()){let s=t[o.value];s&&(s.count+=o.len)}for(let o=1;o<t.length;o++){let s=t[o-1],i=t[o];A(s.node)===A(i.node)&&(t[o-1]=i,t[o]=s)}let n=0;for(let o of t)if(n+=o.count,n>e)return o.node===0?void 0:o.node}decompressArrays(){let e=this.edges.map(i=>i.offset),t=0;for(let i of this.runs())t+=i.len;let n=new Int32Array(t),o=new Int32Array(t),s=0;for(let i of this.runs()){let a=this.edge(i.value),f=e[i.value];for(let c=0;c<i.len;c++)n[s]=a.node,o[s]=f,f+=1,s+=1;e[i.value]=f}return{nodes:n,offsets:o}}decompress(){let e=this.edges.map(n=>n.offset),t=[];for(let n of this.runs()){let o=this.edge(n.value);for(let s=0;s<n.len;s++)t.push({node:o.node,offset:e[n.value]}),e[n.value]=e[n.value]+1}return t}};var Po=["","A","C","G","T","N"];function Bn(r){let e=r[r.length-1];if(e===void 0)return 0;let t=e,n=0;for(let o=0;o<3&&t%6!==0;o++)t=Math.floor(t/6),n+=1;return 3*(r.length-1)+n}function Dn(r){let e="";for(let t of r){let n=t;for(let o=0;o<3;o++){let s=Po[n%6];if(s==="")return e;n=Math.floor(n/6),e+=s}}return e}var _o={A:"T",C:"G",G:"C",T:"A",N:"N"};function je(r){let e="";for(let t=r.length-1;t>=0;t--)e+=_o[r[t]]??"N";return e}function zn(r,e){let t=new Map;if(r!==void 0)for(let n of r.split(";")){let o=n.split(","),[s,i]=o;if(o.length!==2||!s||!i)throw new Error(`Invalid ${e} relationship: ${n}`);let a=t.get(s);a||(a=new Set,t.set(s,a)),a.add(i)}return t}function Wn(r){return{name:r.get("pggname"),subgraph:zn(r.get("subgraph"),"subgraph"),translation:zn(r.get("translation"),"translation")}}function jn(r,e){for(let[t,n]of e){let o=r.get(t);o||(o=new Set,r.set(t,o));for(let s of n)o.add(s)}}function Qn(r,e){let t={name:r,subgraph:new Map,translation:new Map};return e.name!==void 0&&(t.subgraph.set(r,new Set([e.name])),jn(t.subgraph,e.subgraph),jn(t.translation,e.translation)),t}function Un(r){return[...r.entries()].sort(([e],[t])=>e<t?-1:e>t?1:0).flatMap(([e,t])=>[...t].sort().map(n=>[e,n]))}function Yn(r){let e=[];r.name!==void 0&&e.push(`H NM:Z:${r.name}`);for(let[t,n]of Un(r.subgraph))e.push(`H SG:Z:${t},${n}`);for(let[t,n]of Un(r.translation))e.push(`H TL:Z:${t},${n}`);return e}async function Vn(r){let e=r.reduce((s,i)=>s+i.length,0),t=new Uint8Array(e),n=0;for(let s of r)t.set(s,n),n+=s.length;let o=await globalThis.crypto.subtle.digest("SHA-256",t);return[...new Uint8Array(o)].map(s=>s.toString(16).padStart(2,"0")).join("")}var Mo="_gbwt_ref";function $(r,e){return`${r.sample}#${r.haplotype}#${r.contig}[${r.fragment}-${e}]`}var ko=/^([^#]+)#(\d+)#([^#]+?)(?:\[\d+-\d+\])?$/,Lo=/^([^#]+?)(?:\[\d+-\d+\])?$/;function Oo(r){let e=ko.exec(r);if(e)return{sample:e[1],haplotype:Number(e[2]),contig:e[3]};let t=Lo.exec(r);if(t)return{contig:t[1]};throw new Error(`"${r}" is not a path name; expected "sample#haplotype#contig" or a bare contig`)}function Kn(r){return typeof r=="string"?Oo(r):r}function Pe(r,e){return{sample:r.sample??Mo,contig:r.contig,haplotype:r.haplotype??0,fragment:e}}function Ue(r,e){let t=0,n=r.length;for(;t<n;){let o=t+n>>1;r[o]<e?t=o+1:n=o}return t}var We=class{ending;tree;constructor(e){this.ending=new Float64Array(e),this.tree=new Int32Array(e+1).fill(-1)}bestBefore(e){let t=-1;for(let n=e;n>0;n-=n&-n){let o=this.tree[n];o!==-1&&(t===-1||this.ending[o]>this.ending[t])&&(t=o)}return t}raise(e,t){this.ending[e]=t;for(let n=e+1;n<this.tree.length;n+=n&-n){let o=this.tree[n];(o===-1||t>this.ending[o])&&(this.tree[n]=e)}}},Ht=class{pairs=[];total=0;a;b;weight;occurrences=new Map;constructor(e,t,n){this.a=e,this.b=t,this.weight=n,t.forEach((o,s)=>{let i=this.occurrences.get(o);i?i.push(s):this.occurrences.set(o,[s])})}solve(e,t,n,o){let s=0;for(;e+s<t&&n+s<o&&this.a[e+s]===this.b[n+s];)this.match(e+s,n+s),s+=1;let i=0;for(;t-i>e+s&&o-i>n+s&&this.a[t-i-1]===this.b[o-i-1];)i+=1;this.solveMiddle(e+s,t-i,n+s,o-i);for(let a=i;a>0;a--)this.match(t-a,o-a)}match(e,t){this.pairs.push([e,t]),this.total+=this.weight(this.a[e])}solveMiddle(e,t,n,o){if(e===t||n===o)return;let s=this.matchCount(e,t,n,o);if(s===0)return;if(s<=t-e+(o-n)){this.chain(e,t,n,o,s);return}let i=e+t>>1,a=this.split(e,i,t,n,o);this.solve(e,i,n,a),this.solve(i,t,a,o)}matchCount(e,t,n,o){let s=0;for(let i=e;i<t;i++){let a=this.occurrences.get(this.a[i]);a&&(s+=Ue(a,o)-Ue(a,n))}return s}sweep(e,t,n,o,s,i,a){for(let f=e;f!==t;f+=n){let c=this.occurrences.get(this.a[f]);if(!c)continue;let l=this.weight(this.a[f]),p=Ue(c,o),h=Ue(c,s);for(let d=0;d<h-p;d++){let u=n===1?c[h-1-d]-o:s-1-c[p+d],m=i.bestBefore(u),w=(m===-1?0:i.ending[m])+l;if(w>i.ending[u]&&(i.raise(u,w),a)){let x=a.count++;a.row[x]=f,a.column[x]=u,a.previous[x]=m===-1?-1:a.endingMatch[m],a.endingMatch[u]=x}}}}chain(e,t,n,o,s){let i=new We(o-n),a={row:new Int32Array(s),column:new Int32Array(s),previous:new Int32Array(s),endingMatch:new Int32Array(o-n),count:0};this.sweep(e,t,1,n,o,i,a);let f=i.bestBefore(o-n);if(f===-1)return;this.total+=i.ending[f];let c=[];for(let l=a.endingMatch[f];l!==-1;l=a.previous[l])c.push([a.row[l],n+a.column[l]]);for(let l=c.length-1;l>=0;l--)this.pairs.push(c[l])}frontier(e,t,n,o,s){let i=new We(s-o);this.sweep(e,t,n,o,s,i);let a=new Float64Array(s-o+1);for(let f=0;f<s-o;f++)a[f+1]=Math.max(a[f],i.ending[f]);return a}split(e,t,n,o,s){let i=s-o,a=this.frontier(e,t,1,o,s),f=this.frontier(n-1,t-1,-1,o,s),c=0,l=-1;for(let p=0;p<=i;p++){let h=a[p]+f[i-p];h>l&&(l=h,c=p)}return o+c}};function Xn(r,e,t){let n=new Ht(r,e,t);return n.solve(0,r.length,0,e.length),[n.pairs,n.total]}var To=100,Dt=4e6,No=5e3,D=15,Fo=64,qo=8,or=1,zt=-4,G=-6,te=-1,ye=-(2**30),Ye=0,Gt=1,sr=2;function ae(r,e,t){let n=r.at(-1);t>0&&(n?.[0]===e?n[1]+=t:r.push([e,t]))}function Qe(r,e,t){return r>=t&&r>=e?Ye:t>=e?sr:Gt}function ir(r,e,t){let n=r.length,o=e.length,s=o+1,i=new Uint8Array((n+1)*s),a=new Int32Array(s).fill(ye),f=new Int32Array(s).fill(ye),c=new Int32Array(s).fill(ye);a[0]=0;for(let u=1;u<=o;u++)c[u]=G+(u-1)*te,i[u]=(u===1?Ye:sr)<<4;for(let u=1;u<=n;u++){let m=new Int32Array(s).fill(ye),w=new Int32Array(s).fill(ye),x=new Int32Array(s).fill(ye);w[0]=G+(u-1)*te,i[u*s]=(u===1?Ye:Gt)<<2;let S=r.charCodeAt(u-1);for(let g=1;g<=o;g++){let b=Qe(a[g-1],f[g-1],c[g-1]);m[g]=Math.max(a[g-1],f[g-1],c[g-1])+(S===e.charCodeAt(g-1)?or:zt);let y=Qe(a[g]+G,f[g]+te,c[g]+G);w[g]=Math.max(a[g]+G,f[g]+te,c[g]+G);let v=Qe(m[g-1]+G,w[g-1]+G,x[g-1]+te);x[g]=Math.max(m[g-1]+G,w[g-1]+G,x[g-1]+te),i[u*s+g]=b|y<<2|v<<4}a=m,f=w,c=x}let l=[],p=n,h=o,d=Qe(a[o],f[o],c[o]);for(;p>0||h>0;){let u=i[p*s+h]>>2*d&3;d===Ye?(l.push(r[p-1]===e[h-1]?"=":"X"),p-=1,h-=1):d===Gt?(l.push("I"),p-=1):(l.push("D"),h-=1),d=u}for(let u of l.reverse())ae(t,u,1)}function $o(r,e){let t=Math.abs(r-e);return(t===0?0:Math.min(-G-(t-1)*te,-G+10*Math.log2(t)))+(Math.min(r,e)>0?-zt:0)}function ar(r,e){let t=Math.abs(r-e);return t===0?0:.01*D*t+.5*Math.log2(t)}function Zn(r,e,t){return{qs:r.qs+e,qe:r.qs+t,ts:r.flipped?r.te-t:r.ts+e,te:r.flipped?r.te-e:r.ts+t,flipped:r.flipped}}function Ho(r,e,t){let n=r.qe-r.qs,o=[];for(let[a,f]of e){let c=Math.max(0,a-r.qs),l=Math.min(n,f-r.qs);c<l&&o.push([c,l])}for(let[a,f]of t){let c=Math.max(0,r.flipped?r.te-f:a-r.ts),l=Math.min(n,r.flipped?r.te-a:f-r.ts);c<l&&o.push([c,l])}if(o.length===0)return[r];o.sort((a,f)=>a[0]-f[0]);let s=[],i=0;for(let[a,f]of o)a-i>=D&&s.push(Zn(r,i,a)),i=Math.max(i,f);return n-i>=D&&s.push(Zn(r,i,n)),s}function jt(r,e,t,n,o=1/0){let s=[],i={query:[],target:[]},a={forward:{query:[],target:[]},flipped:{query:[],target:[]}},f=[...r].sort((c,l)=>c.qs-l.qs||c.ts-l.ts);for(;f.length>0&&s.length<o;){let c=f.map(g=>g.qe-g.qs),l=new Int32Array(f.length).fill(-1),p=new Int32Array(f.length);for(let g=0;g<f.length;g++){let b=f[g],y=b.qe-b.qs;for(let v=g-1;v>=Math.max(0,g-No);v--){if(c[v]+y<=c[g])continue;let I=f[v];if(I.flipped===b.flipped&&I.qs<b.qs&&(b.flipped?b.te<I.te:I.ts<b.ts)){let C=Math.max(0,I.qe-b.qs,b.flipped?b.te-I.ts:I.te-b.ts),P=b.qs+C-I.qe,E=b.flipped?I.ts-(b.te-C):b.ts+C-I.te;if(C<y&&P<=e&&E<=e){let M=c[v]+y-C-n(P,E);M>c[g]&&(c[g]=M,l[g]=v,p[g]=C)}}}}let h=0;for(let g=1;g<f.length;g++)c[g]>c[h]&&(h=g);let d=[];for(let g=h;g>=0;g=l[g])d.push({run:f[g],trim:p[g]});if(d.reverse(),d.reduce((g,{run:b,trim:y})=>g+b.qe-b.qs-y,0)<t)break;s.push(d);let m=d[0],w=d.at(-1),{flipped:x}=m.run,S=x?a.flipped:a.forward;S.query.push([m.run.qs+m.trim,w.run.qe]),S.target.push(x?[w.run.ts,m.run.te-m.trim]:[m.run.ts+m.trim,w.run.te]);for(let{run:g,trim:b}of d)i.query.push([g.qs+b,g.qe]),i.target.push(g.flipped?[g.ts,g.te-b]:[g.ts+b,g.te]);f=f.flatMap(g=>{let b=g.flipped?a.flipped:a.forward;return Ho(g,[...i.query,...b.query],[...i.target,...b.target])}).sort((g,b)=>g.qs-b.qs||g.ts-b.ts)}return s}function Bt(r,e){let t=new Map;for(let s=0;s+D<=e.length;s++){let i=e.slice(s,s+D),a=t.get(i);a?a.push(s):t.set(i,[s])}let n=[],o=new Map;for(let s=0;s+D<=r.length;s++){let i=t.get(r.slice(s,s+D));if(i&&i.length<=Fo)for(let a of i){let f=a-s,c=o.get(f);if(c&&s<=c.qe)c.qe=s+D,c.te=a+D;else{let l={qs:s,qe:s+D,ts:a,te:a+D,flipped:!1};o.set(f,l),n.push(l)}}}return n}function Go(r,e){return[...Bt(r,e),...Bt(r,je(e)).map(t=>({...t,ts:e.length-t.te,te:e.length-t.ts,flipped:!0}))]}function Ve(r,e,t,n,o){let s;for(let{run:i,trim:a}of r){let f=i.qs+a;if(s){let c=i.flipped?i.te-a:s.te,l=i.flipped?s.ts:i.ts+a,p=t.slice(c,l);o(e.slice(s.qe,f),i.flipped?je(p):p,n,s.qe,c)}ae(n,"=",i.qe-f),s=i}}function Ut(r,e,t){ae(t,"I",r.length),ae(t,"D",e.length)}function fr(r,e,t){r.length*e.length<=Dt?ir(r,e,t):Ut(r,e,t)}function Wt(r,e,t,n=0){let[o]=r.length*e.length>Dt&&n<qo?jt(Bt(r,e),1/0,D,ar,1):[];if(!o){fr(r,e,t);return}let s=(f,c,l)=>{Wt(f,c,l,n+1)},i=o[0].run,a=o.at(-1).run;s(r.slice(0,i.qs),e.slice(0,i.ts),t),Ve(o,r,e,t,s),s(r.slice(a.qe),e.slice(a.te),t)}function Bo(r,e,t){Wt(r,e,t)}function Do(r,e,t){let n=[];Ve(r,e,t,n,Bo);let o=r[0],s=r.at(-1),{flipped:i}=o.run;return{queryStart:o.run.qs+o.trim,queryEnd:s.run.qe,targetStart:i?s.run.ts:o.run.ts+o.trim,targetEnd:i?o.run.te-o.trim:s.run.te,strand:i?"-":"+",edits:i?n.reverse():n,sharedBases:0}}function zo(r,e,t,n){let o=[];if(r.length*e.length<=Dt)ir(r,e,t);else{let s=jt(Go(r,e),1/0,Math.max(n,D),ar),i=s.find(a=>!a[0].run.flipped);if(o=s.filter(a=>a[0].run.flipped).map(a=>Do(a,r,e)),i){let a=(l,p,h,d,u)=>{o.some(w=>d<w.queryEnd&&w.queryStart<d+l.length||u<w.targetEnd&&w.targetStart<u+p.length)?fr(l,p,h):Wt(l,p,h)},f=i[0].run,c=i.at(-1).run;a(r.slice(0,f.qs),e.slice(0,f.ts),t,0,0),Ve(i,r,e,t,a),a(r.slice(c.qe),e.slice(c.te),t,c.qe,c.te)}else Ut(r,e,t)}return o}function Qt(r,e){let t=r.strand==="-",n=0,o=0;for(let[s,i]of r.edits)e(s,i,t?r.queryEnd-1-n:r.queryStart+n,r.targetStart+o),s!=="D"&&(n+=i),s!=="I"&&(o+=i)}function Jn(r,e,t,n){let o=e==="query"&&r.strand==="-"?-1:1,s=0;return Qt(r,(i,a,f,c)=>{let l=e==="query"?f:c,p=h=>{let d=l+o*h;return d>=t&&d<n};if(i==="="||i==="X")for(let h=0;h<a;h++)p(h)&&(s+=i==="="?or:zt);else if(i==="I"==(e==="query"))for(let h=0;h<a;h++)p(h)&&(s+=h===0?G:te);else p(0)&&(s+=G+(a-1)*te)}),s}function er(r,e){return e==="query"?[r.queryStart,r.queryEnd]:[r.targetStart,r.targetEnd]}function jo(r,e){let t=r.strand==="-",n=[],o=0,s=0,i=0,a=0,f=new Uint8Array(r.queryEnd-r.queryStart);for(let[d,u]of r.shared)f.fill(1,d-r.queryStart,u-r.queryStart);let c=d=>f[d-r.queryStart]===1,l=()=>{ae(n,"I",o),ae(n,"D",s),o=0,s=0};Qt(r,(d,u,m)=>{if(d==="I")o+=u;else if(d==="D")s+=u;else{for(let w=0;w<u;w++)e[i+w]?(o+=1,s+=1,c(t?m-w:m+w)&&(a+=1)):((o>0||s>0)&&l(),ae(n,d,1));i+=u}}),l();let p={I:0,D:0};for(;n[0]?.[0]==="I"||n[0]?.[0]==="D";){let[d,u]=n.shift();p[d]+=u}let h={I:0,D:0};for(;n.at(-1)?.[0]==="I"||n.at(-1)?.[0]==="D";){let[d,u]=n.pop();h[d]+=u}return n.length===0?void 0:{...r,queryStart:r.queryStart+(t?h.I:p.I),queryEnd:r.queryEnd-(t?p.I:h.I),targetStart:r.targetStart+p.D,targetEnd:r.targetEnd-h.D,edits:n,sharedBases:r.sharedBases-a}}function Uo(r,e,t,n){let o={query:new Uint8Array(e),target:new Uint8Array(t)},s=r.map(c=>{let l=[];Qt(c,(p,h,d,u)=>{if(p==="="||p==="X")for(let m=0;m<h;m++)l.push([c.strand==="-"?d-m:d+m,u+m])});for(let[p,h]of l)o.query[p]=Math.min(255,o.query[p]+1),o.target[h]=Math.min(255,o.target[h]+1);return l}),i={query:new Map,target:new Map};s.forEach((c,l)=>{for(let[p,h]of c)for(let[d,u]of[["query",p],["target",h]])if(o[d][u]>1){let m=i[d].get(u);m?m.at(-1)!==l&&m.push(l):i[d].set(u,[l])}});let a=new Map,f=(c,l,p)=>{let h=`${p}:${c}:${l}`,d=a.get(h);if(d===void 0){let[u,m]=er(r[c],p),[w,x]=er(r[l],p),S=Math.max(u,w),g=Math.min(m,x),[b,y]=[r[c],r[l]];d=[Jn(y,p,S,g)-Jn(b,p,S,g),y.sharedBases-b.sharedBases,c-l].find(I=>I!==0)>0,a.set(h,d)}return d};return r.flatMap((c,l)=>{let p=s[l],h=new Uint8Array(p.length);if(p.forEach(([m,w],x)=>{for(let[S,g]of[["query",m],["target",w]])!h[x]&&i[S].get(g)?.some(b=>b!==l&&f(l,b,S))&&(h[x]=1)}),!h.includes(1))return[c];let d=jo(c,h),u=d?.edits.reduce((m,[w,x])=>m+(w==="="?x:0),0)??0;return d&&u>=n?[d]:[]})}function tr(r,e){return r.map(t=>{let n=e(A(t));return O(t)?je(n):n}).join("")}function nr(r,e){let t=[0];for(let n of r)t.push(t.at(-1)+e(A(n)).length);return t}function rr(r){let e=new Map,t=new Map;r.forEach((i,a)=>{let f=A(i);e.has(f)?t.set(f,a):e.set(f,a)});let n=new Int32Array(r.length+1);for(let[i,a]of t)n[e.get(i)]+=1,n[a+1]-=1;let o=new Uint8Array(r.length),s=0;for(let i=0;i<r.length;i++)s+=n[i],o[i]=s>0?1:0;return o}function Wo(r,e,t,n){let o=rr(r),s=rr(e),i=new Map;e.forEach((p,h)=>{s[h]||i.set(A(p),[h])});let a=2*e.length,f=(p,h,d)=>p*a+2*h+(d?1:0),c=new Set;r.forEach((p,h)=>{for(let d of o[h]?[]:i.get(A(p))??[])c.add(f(h,d,O(p)!==O(e[d])))});let l=[];return r.forEach((p,h)=>{for(let d of o[h]?[]:i.get(A(p))??[]){let u=O(p)!==O(e[d]),m=u?-1:1;if(!c.has(f(h-1,d-m,u))){let w=h,x=d;for(;w<r.length&&x>=0&&x<e.length&&c.has(f(w,x,u));)w+=1,x+=m;let S=x-m;l.push({qs:t[h],qe:t[w],ts:n[Math.min(d,S)],te:n[Math.max(d,S)+1],flipped:u})}}}),l}function cr(r,e,t,n={}){let o=tr(r,t),s=tr(e,t),i=Wo(r,e,nr(r,t),nr(e,t)),a=n.minMatch??To,f=n.bases??!0,c=[];for(let l of jt(i,n.maxGap??1/0,a,$o)){let p=[],h=l[0],d=l.at(-1),{flipped:u}=h.run;Ve(l,o,s,p,f?(w,x,S,g,b)=>{for(let y of zo(w,x,S,a)){let v=b+x.length;c.push({...y,queryStart:g+y.queryStart,queryEnd:g+y.queryEnd,targetStart:u?v-y.targetEnd:b+y.targetStart,targetEnd:u?v-y.targetStart:b+y.targetEnd,strand:u?"+":"-",edits:u?y.edits.reverse():y.edits,shared:[]})}}:Ut),c.push({queryStart:h.run.qs+h.trim,queryEnd:d.run.qe,targetStart:u?d.run.ts:h.run.ts+h.trim,targetEnd:u?h.run.te-h.trim:d.run.te,strand:u?"-":"+",edits:u?p.reverse():p,sharedBases:l.reduce((w,{run:x,trim:S})=>w+x.qe-x.qs-S,0),shared:l.map(({run:w,trim:x})=>[w.qs+x,w.qe])})}return Uo(c,o.length,s.length,a).map(({shared:l,...p})=>p).sort((l,p)=>l.queryStart-p.queryStart)}function lr(r){return r.map(([e,t])=>`${t}${e}`).join("")}var X=class extends Error{name="SubgraphLimitError";limit;windowBp;walkedBp;constructor(e,t){super(t===void 0?`Subgraph size limit of ${e} nodes exceeded`:`Subgraph size limit of ${e} nodes exceeded ${t.walkedBp} bp into a ${t.windowBp} bp window`),this.limit=e,this.windowBp=t?.windowBp,this.walkedBp=t?.walkedBp}};function Yt(r,e){return r[0]<e[0]||r[0]===e[0]&&(r[1]<e[1]||r[1]===e[1]&&r[2]<e[2])}var _e=class{heap=[];push(e,t,n){let o=this.heap;o.push([e,t,n]);let s=o.length-1;for(;s>0;){let i=s-1>>1;if(Yt(o[s],o[i]))[o[s],o[i]]=[o[i],o[s]],s=i;else break}}pop(){let e=this.heap,t=e[0],n=e.pop();if(e.length>0&&n!==void 0){e[0]=n;let o=0;for(;;){let s=2*o+1,i=s+1,a=o;if(s<e.length&&Yt(e[s],e[a])&&(a=s),i<e.length&&Yt(e[i],e[a])&&(a=i),a===o)break;[e[o],e[a]]=[e[a],e[o]],o=a}}return t}get size(){return this.heap.length}};function Qo(r){let e=new Int32Array(r.length),t=new Int32Array(r.length);return r.forEach(([n,o],s)=>{e[s]=n,t[s]=o}),{pathAt:e,refAt:t,count:r.length}}function Yo(r,e){let t=0,n=r.length;for(;t<n;){let o=t+n>>1;r[o]>e?n=o:t=o+1}return r[t]}function fe(r){return`${r.node}:${r.offset}`}function Vo(r,e){let t=e.identity.hapStart-r.identity.hapEnd,n=r.strand==="+"?e.refStart-r.refEnd:r.refStart-e.refEnd;return r.strand===e.strand&&t>=0&&n>=0?{insertion:t,deletion:n}:void 0}function Ko(r,e,t){let[n,o]=r.strand==="+"?[r,e]:[e,r],s=n.edits.map(([c,l])=>[c,l]);hr(s,t.insertion,t.deletion);for(let[c,l]of o.edits)z(s,c,l);let i=r.identity.walkForward,[a,f]=i?[r,e]:[e,r];return{strand:r.strand,refStart:n.refStart,refEnd:o.refEnd,edits:s,weight:void 0,path:[...a.path,...f.path],start:a.start,identity:{pathHandle:r.identity.pathHandle,name:r.identity.name,hapStart:r.identity.hapStart,hapEnd:e.identity.hapEnd,walkForward:i}}}function Xo(r){if(r.some(o=>o.weight!==void 0))return r;let e=new Map;r.forEach((o,s)=>{if(o.identity){let i=e.get(o.identity.pathHandle);i?i.push(s):e.set(o.identity.pathHandle,[s])}});let t=new Map,n=new Set;for(let o of e.values()){o.sort((a,f)=>r[a].identity.hapStart-r[f].identity.hapStart);let s=o[0],i=r[s];for(let a of o.slice(1)){let f=r[a],c=Vo(i,f);c?(i=Ko(i,f,c),n.add(a)):(t.set(s,i),s=a,i=f)}t.set(s,i)}return r.flatMap((o,s)=>n.has(s)?[]:[t.get(s)??o])}function Ke(r,e){return{node:r.path[e],offset:r.offsets[e]}}var Zo=4096;function pr(r){let e=[];for(let t of r){let n=e[e.length-1];n&&t-n[1]<=Zo?n[1]=t:e.push([t,t])}return e}var Jo=32768,es=65536;function ts(r){let e=[...r].sort((n,o)=>n-o),t=[];for(let n of e){let o=t[t.length-1];o&&n-o[1]<=Jo?o[1]=n:t.push([n,n])}return t}var Me=class{records=new Map;paths=[];twinStarts=new Set;refId;refPath;refHandle;refInterval;refIndexCache;refPrefixCache;walkedBp;stats={orderedAlignments:0,lcsAlignments:0,identificationSteps:0,identificationFetches:0,identification:{interval:0,scans:[],windowSamples:0,fragmentLengths:[],companionSeeks:0,companionMisses:0,graphLookups:0,graphFetches:0,chains:[]},anchorWalk:void 0};db;limit;signal;constructor(e,t={}){this.db=e,this.limit=t.limit,this.signal=t.signal}get nodeCount(){return this.records.size/2}get pathCount(){return this.paths.length}get referenceInterval(){return this.refInterval&&this.refPath?{name:this.refPath,start:this.refPath.fragment+this.refInterval[0],end:this.refPath.fragment+this.refInterval[1]}:void 0}hasNode(e){return this.records.has(V(e,"forward"))}hasHandle(e){return this.records.has(e)}record(e){let t=this.records.get(e);if(!t)throw new Error(`Subgraph has no record for handle ${e}`);return t}sortedHandles(){return[...this.records.keys()].sort((e,t)=>e-t)}async addNode(e){if(this.signal?.throwIfAborted(),this.limit!==void 0&&this.nodeCount>=this.limit)throw new X(this.limit);let t=await this.db.getRecord(V(e,"forward")),n=await this.db.getRecord(V(e,"reverse"));if(!t||!n)throw new Error(`Node ${e} does not exist in the graph`);this.records.set(t.handle,t),this.records.set(n.handle,n)}async ensureNode(e){this.hasNode(e)||await this.addNode(e)}clearPaths(){this.paths=[],this.twinStarts.clear(),this.refId=void 0,this.refPath=void 0,this.refHandle=void 0,this.refInterval=void 0,this.refIndexCache=void 0,this.refPrefixCache=void 0}async pathPosition(e){let t=await this.db.findPath(e);if(!t)throw new Error(`Cannot find a path covering ${$(e,e.fragment)}`);if(!t.isIndexed)throw new Error(`Path ${$(t.name,t.name.fragment)} has not been indexed for random access`);let n=e.fragment-t.name.fragment,o=await this.db.indexedPosition(t.handle,n);if(!o)throw new Error(`Path ${$(t.name,t.name.fragment)} has not been indexed for random access`);return this.findPathPosition(t,n,o.pathOffset,o.pos)}async findPathPosition(e,t,n,o){let s=n,i=o;for(;;){await this.ensureNode(A(i.node));let a=this.record(i.node);if(s+a.sequenceLen>t)return{position:{seqOffset:t,handle:i.node,nodeOffset:t-s,gbwtOffset:i.offset},name:e.name,handle:e.handle};s+=a.sequenceLen;let f=a.gbwt().lf(i.offset);if(!f)throw new Error(`Path ${$(e.name,e.name.fragment)} does not contain offset ${t}`);i=f}}async aroundPosition(e,t,n){let o=A(e);await this.ensureNode(o);let s=this.record(e),i=ge(e),a=new _e;return a.push(t,o,He(i)),a.push(s.sequenceLen-t-1,o,Ge(i)),this.insertContext(a,n)}prefetchReferenceWalk(e,t){return this.prefetchReferenceRange(e.handle,e.position.seqOffset,e.position.seqOffset+t)}async prefetchReferenceRange(e,t,n){let[o,s]=await Promise.all([this.db.indexedPosition(e,t),this.db.indexedPosition(e,n)]);if(o&&s){let i=o.pos.node,a=s.pos.node;if(!await this.db.prefetchRecords(Math.min(i,a),Math.max(i,a)+1)){let c=await this.db.indexedPositionsBetween(e,t,n),l=ts(c.map(p=>p.pos.node));await Promise.all(l.map(([p,h])=>this.db.prefetchRecords(p,h+2)))}}return o}async aroundInterval(e,t,n){if(t===0)throw new Error("Interval length must be greater than 0");this.walkedBp=0;try{return await this.walkInterval(e,t,n)}catch(o){throw o instanceof X&&o.windowBp===void 0?new X(o.limit,{windowBp:t,walkedBp:this.walkedBp}):o}}get referenceWalkedBp(){return this.walkedBp}async walkInterval(e,t,n){let o={node:e.handle,offset:e.gbwtOffset},s=e.nodeOffset,i=t,a=new _e;for(;;){let f=A(o.node),c=ge(o.node);this.walkedBp=t-i,await this.ensureNode(f);let l=this.record(o.node);if(s>=l.sequenceLen)throw new Error(`Offset ${s} in node ${f} of length ${l.sequenceLen}`);a.push(s,f,He(c));let p=l.sequenceLen-s;if(i<=p){a.push(i===p?0:p-i-1,f,Ge(c));break}a.push(0,f,Ge(c));let h=l.gbwt().lf(o.offset);if(!h)throw new Error(`No successor for GBWT position (${o.node}, ${o.offset})`);o=h,s=0,i-=p}return this.walkedBp=t,this.insertContext(a,n)}async aroundNodes(e,t){let n=new _e;for(let o of e)await this.ensureNode(o),n.push(0,o,"left"),n.push(0,o,"right");return this.insertContext(n,t)}async insertContext(e,t){this.clearPaths();let n=new Set,o=new Set;for(let i of this.records.keys())o.add(A(i));let s=0;for(;e.size>0;){let[i,a,f]=e.pop(),c=`${a}:${f}`;if(n.has(c))continue;n.add(c),o.delete(a),this.hasNode(a)||(await this.addNode(a),s+=1);let l=Nn(f);if(!n.has(`${a}:${l}`)){let d=this.record(V(a,Fn(f))),u=i+d.sequenceLen-1;u<=t&&e.push(u,a,l)}let p=this.record(V(a,qn(f))),h=i+1;if(h<=t)for(let d of p.successors()){let u=A(d),m=He(ge(d));n.has(`${u}:${m}`)||e.push(h,u,m)}}for(let i of o)this.records.delete(V(i,"forward")),this.records.delete(V(i,"reverse"));return{inserted:s,removed:o.size}}async betweenNodes(e,t){this.clearPaths();let n=[e,B(t)],o=new Set([A(e),A(t)]),s=0;for(;n.length>0;){let i=n.pop(),a=A(i);this.hasNode(a)||(await this.addNode(a),s+=1);for(let f of this.record(i).successors()){let c=A(f);o.has(c)||(n.push(f,B(f)),o.add(c))}}return s}async extractSnarls(e){let t=0;for(let[n,o]of await this.overlappingSnarls(e))t+=await this.betweenNodes(n,o);return t}async overlappingSnarls(e){let t=[];if(e!=="none"){let n=!1;for(let o of this.sortedHandles()){let s=this.record(o),i=s.next;i!==void 0&&(n=!0,this.hasHandle(i)?we(o,i)&&t.push([o,i]):e==="overlapping"&&this.isSnarlEntryInSubgraph(s)&&t.push([o,i]))}if(!n&&e==="overlapping"&&await this.db.hasChainLinks()){let o=await this.findCoveringSnarl();o&&t.push(o)}}return t}isSnarlEntryInSubgraph(e){let t=e.successors(),n=t.find(o=>this.hasHandle(o));return n===void 0?!1:t.length>1||this.record(B(n)).successors().length>1}recordReader(e){let t=new Map;return async n=>{let o=this.records.get(n);if(o)return o;let s=t.get(n);if(!s){if(s=await this.db.getRecord(n),e?.(),!s)throw new Error(`Node record ${n} is missing from the database`);t.set(n,s)}return s}}async findCoveringSnarl(){let e=this.recordReader(),t=async f=>{let c=f.successors(),l=c[0];return l===void 0?!1:c.length>1||(await e(B(l))).successors().length>1},n=async f=>{let c=await e(B(f));return c.next!==void 0?await t(c)?{kind:"snarl-exit",snarl:[B(f),c.next]}:{kind:"chain"}:(await e(f)).next!==void 0?{kind:"chain"}:{kind:"regular"}},o=new Set,s=this.sortedHandles().flatMap(f=>this.record(f).successors()),i,a=!1;for(;!a&&s.length>0;){let f=s.shift(),c=A(f);if(!this.hasHandle(f)&&!o.has(c)){o.add(c);let l=await n(f);if(l.kind==="snarl-exit")i=l.snarl,a=!0;else if(l.kind==="chain")a=!0;else for(let p of["forward","reverse"])s.push(...(await e(V(c,p))).successors())}}return i}extractPaths(e,t){if(this.clearPaths(),t==="none")return;let n=e?.position;this.refPath=e?.name,this.refHandle=e?.handle;let o=this.sortedHandles(),s=o.length,i=new Map;o.forEach((y,v)=>i.set(y,v));let a=new Int32Array(s+1),f=new Int32Array(s),c=[];for(let y=0;y<s;y++){let v=this.record(o[y]),I=v.gbwt().decompressArrays();f[y]=v.sequenceLen,c.push(I),a[y+1]=a[y]+I.nodes.length}let l=a[s],p=new Int32Array(l),h=new Int32Array(l),d=new Uint8Array(l);for(let y=0;y<s;y++){let v=c[y];p.set(v.nodes,a[y]),h.set(v.offsets,a[y])}c.length=0;for(let y=0;y<l;y++){let v=i.get(p[y]);v===void 0?p[y]=-1:(p[y]=v,d[a[v]+h[y]]=1)}let u=n===void 0?void 0:i.get(n.handle),m=n?.gbwtOffset,w,x=(y,v,I)=>{let R=[],C=0,P=0,E=-1,M=y,L=v;for(;;){M===u&&L===m&&(E=C),I&&(I.push(o[M]),R.push(L)),C+=1,P+=f[M];let N=a[M]+L,F=p[N];if(F<0)break;L=h[N],M=F}return{offsets:R,len:P,refAt:E,last:M}},S=(y,v,I,R)=>{R>=0&&(this.refId=this.paths.length,w=R),this.paths.push({path:y,offsets:v,len:I,weight:void 0,identity:void 0})},g=new Int32Array(s),b=u!==void 0&&O(o[u]);for(let y=0;y<s;y++){let v=o[y];if(!O(v)){let I=a[y],R=a[y+1]-I;for(let C=0;C<R;C++)if(d[I+C]===0){let P=[],{offsets:E,len:M,refAt:L,last:N}=x(y,C,P),F=o[N];if(L>=0||Be(v,F)){if(S(P,E,M,L),!O(F)){let q=i.get(B(F));g[q]=g[q]+1}}else this.twinStarts.add(fe({node:v,offset:C}))}}}for(let y=0;y<s;y++){let v=o[y];if(O(v)){let I=a[y],R=a[y+1]-I,C=0;for(let E=0;E<R;E++)d[I+E]===0&&(C+=1);let P=!b&&C===g[y];for(let E=0;E<R;E++)if(d[I+E]===0){let M=P?void 0:x(y,E,void 0);if(M&&(M.refAt>=0||Be(v,o[M.last]))){let L=[],{offsets:N,len:F,refAt:q}=x(y,E,L);S(L,N,F,q)}else this.twinStarts.add(fe({node:v,offset:E}))}}}if(n){if(w===void 0||this.refId===void 0)throw this.clearPaths(),new Error("Could not find the reference path");let y=this.paths[this.refId],v=n.nodeOffset;for(let R of y.path.slice(0,w))v+=this.record(R).sequenceLen;let I=n.seqOffset-v;this.refInterval=[I,I+y.len],y.identity={pathHandle:e.handle,name:e.name,orientation:"forward",hapStart:I,hapEnd:I+y.len}}if(t==="distinct")this.distinctPaths();else if(t==="reference-only"){if(this.refId===void 0)throw new Error("Reference path is required for reference-only output");this.paths=[this.paths[this.refId]],this.refId=0}}distinctPaths(){let e=this.refId===void 0?void 0:this.paths[this.refId].path;this.paths.sort((o,s)=>Vt(o.path,s.path)||o.len-s.len);let t=[],n;for(let o of this.paths){let s=t[t.length-1];s&&Vt(s.path,o.path)===0?s.weight=(s.weight??0)+1:(e&&Vt(o.path,e)===0&&(n=t.length),t.push({...o,weight:1}))}this.paths=t,this.refId=n}keepHaplotypes(e){let t=this.refId===void 0?void 0:this.paths[this.refId],n=this.paths.filter((s,i)=>i===this.refId||s.identity!==void 0&&e(s.identity.name)),o=new Set;for(let s of n)for(let i of s.path)o.add(A(i));for(let s of[...this.records.keys()])o.has(A(s))||this.records.delete(s);this.paths=n,this.refId=t===void 0?void 0:n.indexOf(t)}async walkHaplotypesFromAnchor(e,t,n,o,s){let i=e.position.seqOffset,a=i+t,f=Math.floor(i/n)*n,c=Math.min(n,es),l=4*(n+t)+c,p={spacing:n,anchorOffset:f,anchorNodeOffset:-1,anchorHandle:-1,referenceSteps:0,rows:0,walks:[],graphFetches:0,scans:[],scanRows:0,fallback:void 0,ms:{reference:0,rows:0,walks:0,scan:0,sampled:0}};this.stats.anchorWalk=p;let h=performance.now(),d=()=>{let k=performance.now(),U=k-h;return h=k,U};this.clearPaths(),this.records.clear();let u=this.recordReader(()=>{p.graphFetches+=1}),m=await this.db.haplotypeAnchor(e.handle,f);if(m===void 0)throw new Error(`The haplotype index names no anchor for ${$(e.name,e.name.fragment)} at offset ${f}; it was not built with anchors at ${n} bp for this graph`);p.anchorNodeOffset=m.pathOffset;let w=await this.prefetchReferenceRange(e.handle,m.pathOffset,a+c);if(!w)throw new Error(`Path ${$(e.name,e.name.fragment)} has not been indexed for random access`);let x=await this.walkReference(u,w,m,i,a,a+c),{anchor:S,refOffsetOf:g,refHandles:b,windowSteps:y}=x;p.anchorHandle=S.pos.node,p.referenceSteps=x.steps,this.walkedBp=t;let v=[],I=[],R=0;for(let k of y)await this.ensureNode(A(k.pos.node)),v.push(k.pos.node),I.push(k.pos.offset),R+=this.record(k.pos.node).sequenceLen;let C=y[0];if(C===void 0)throw new Error("The reference walk has no node in the window");this.refPath=e.name,this.refHandle=e.handle,this.refInterval=[C.refOffset,C.refOffset+R],this.refId=0,this.paths.push({path:v,offsets:I,len:R,weight:void 0,identity:{pathHandle:e.handle,name:e.name,orientation:"forward",hapStart:C.refOffset,hapEnd:C.refOffset+R}}),p.ms.reference=d();let P=await this.db.haplotypeSamplesAtNode(S.pos.node);p.rows=P.length,p.ms.rows=d();let E=P.find(k=>k.offset===S.pos.offset&&k.pathHandle===e.handle&&k.pathOffset===S.offset);if(E===void 0)throw new Error(`The haplotype index has no anchor row for ${$(e.name,e.name.fragment)} at offset ${S.offset} (node ${A(S.pos.node)}); it was not built with anchors at ${n} bp for this graph`);let M=await this.db.pathsByHandle(),L=k=>{let U=M.get(k);if(!U)throw new Error(`Path ${k} is missing from the database`);return U.name},N=new Set([e.handle]),F=new Map;for(let k of P)if(k!==E&&o(L(k.pathHandle))){let U=F.get(k.pathHandle);U?U.push(k):F.set(k.pathHandle,[k])}let q;for(let[k,U]of F)if(q===void 0){let he=ie=>Math.abs(ie.offset-E.offset);U.sort((ie,vo)=>he(ie)-he(vo));let de;for(let ie of U)N.has(k)||(de=await this.walkAndKeep(u,ie,"anchor",L(k),g,a,l,s,N,p));N.has(k)||(q=de)}p.ms.walks=d();let Ee=q===void 0?await this.samplesOfUnwalkedContigs(v,g,b,o,N,L,p):new Map;if(p.ms.scan=d(),Ee.size>0){await this.mapReferenceBefore(u,e.handle,Math.max(0,m.pathOffset-2*n),m.pathOffset,g,b);for(let[k,U]of Ee)if(q===void 0){let he=L(k),de;for(let ie of U)de??=await this.entryBefore(u,ie,g,b,this.refInterval[0],l);q=de===void 0?`no sample of ${$(he,he.fragment)} on the window's nodes runs with the reference`:await this.walkAndKeep(u,de,"sample",he,g,a,l,s,N,p)}p.ms.sampled=d()}return p.fallback=q,q}async walkAndKeep(e,t,n,o,s,i,a,f,c,l){let p=await this.walkFromRow(e,t,o,s,this.refInterval[0],i,a,f);l.walks.push({pathHandle:t.pathHandle,from:n,steps:p.steps,pieces:p.infos.length,end:p.end});let h;return p.end==="bound"||p.infos.length===0?h=`${$(o,t.pathOffset)} walked ${p.steps} steps from its ${n} without writing a walk through the window (${p.end})`:(c.add(t.pathHandle),this.paths.push(...p.infos)),h}async mapReferenceBefore(e,t,n,o,s,i){let a=await this.prefetchReferenceRange(t,n,o),f=a?.pos,c=a?.pathOffset??o;for(;f!==void 0&&f.node!==0&&c<o;){this.signal?.throwIfAborted();let l=await e(f.node),p=A(f.node);s.has(p)||(s.set(p,c),i.add(f.node)),c+=l.sequenceLen,f=l.gbwt().lf(f.offset)}}async runsWithReference(e,t,n,o,s){let i={node:t.node,offset:t.offset},a=0,f;for(;f===void 0;)if(this.signal?.throwIfAborted(),i===void 0||i.node===0||a>s)f=!1;else if(n.has(A(i.node)))f=o.has(i.node);else{let c=await e(i.node);a+=c.sequenceLen,i=c.gbwt().lf(i.offset)}return f}async entryBefore(e,t,n,o,s,i){let a=(await e(t.node)).sequenceLen,f=async(d,u)=>{let m=(await e(d.node)).sequenceLen;return{node:d.node,offset:d.offset,pathHandle:t.pathHandle,orientation:t.orientation,pathOffset:t.orientation==="forward"?t.pathOffset-u:t.pathOffset+a+u-m}},c={node:t.node,offset:t.offset},l=0,p,h=!await this.runsWithReference(e,t,n,o,i);for(;!h;){this.signal?.throwIfAborted();let d=n.get(A(c.node));if(d!==void 0&&d<s)p=await f(c,l),h=!0;else if(l>i)p={...t},h=!0;else{let m=(await e(B(c.node))).gbwt().predecessorAt(c.offset);if(m===void 0)p=await f(c,l),h=!0;else{let w=await e(m),x=w.gbwt().offsetTo(c);if(x===void 0)throw new Error(`No offset in ${m} leads to ${c.node}:${c.offset}`);c={node:m,offset:x},l+=w.sequenceLen}}}return p}async walkReference(e,t,n,o,s,i){let a=new Map,f=new Set,c=[],l,p=t.pos,h=t.pathOffset,d=0;for(;p!==void 0&&p.node!==0&&h<i;){this.signal?.throwIfAborted();let u=await e(p.node),m=h+u.sequenceLen;if(l===void 0&&h===n.pathOffset){if(p.node!==n.node)throw new Error(`The reference walk reaches node ${A(p.node)} at offset ${h} where the haplotype index names node ${A(n.node)} as the anchor`);l={pos:p,offset:h}}if(l!==void 0){d+=1;let w=A(p.node);a.has(w)||(a.set(w,h),f.add(p.node)),h<s&&m>o&&c.push({pos:p,refOffset:h})}h=m,p=u.gbwt().lf(p.offset)}if(l===void 0)throw new Error(`The reference walk from offset ${t.pathOffset} never starts a node at the anchor offset ${n.pathOffset}`);return{anchor:l,refOffsetOf:a,refHandles:f,windowSteps:c,steps:d}}async walkFromRow(e,t,n,o,s,i,a,f){let c=(await e(t.node)).sequenceLen,l=t.orientation==="forward"?t.pathOffset:t.pathOffset+c,p=[],h=[],d=[],u=0,m=0,w=0,x,S,g={node:t.node,offset:t.offset};for(;S===void 0;)if(this.signal?.throwIfAborted(),g===void 0||g.node===0)S=x===void 0?"before the window":"ended in the window";else if(m>a)S="bound";else{let y=o.get(A(g.node)),v=x!==void 0;if(y!==void 0&&y>=i)S=v?"through the window":"past the window";else{!v&&y!==void 0&&y>=s&&(x=m);let I=await e(g.node);if(x!==void 0){let R={pos:g,at:m,len:I.sequenceLen};y===void 0?(d.push(R),u+=R.len):(u>f&&y<s?(p.push(h),h=[]):h.push(...d),d=[],u=0,h.push(R))}w+=1,m+=I.sequenceLen,g=I.gbwt().lf(g.offset)}}p.push(h);let b=[];for(let y of p){let v=y[0],I=y[y.length-1];if(v!==void 0&&I!==void 0){let R=[],C=[],P=0;for(let L of y)await this.ensureNode(A(L.pos.node)),R.push(L.pos.node),C.push(L.pos.offset),P+=L.len;let E=v.at,M=I.at+I.len;b.push({path:R,offsets:C,len:P,weight:void 0,identity:t.orientation==="forward"?{pathHandle:t.pathHandle,name:n,orientation:"forward",hapStart:l+E,hapEnd:l+M}:{pathHandle:t.pathHandle,name:n,orientation:"reverse",hapStart:l-M,hapEnd:l-E}})}}return{steps:w,end:S,infos:b}}async samplesOfUnwalkedContigs(e,t,n,o,s,i,a){let f=pr([...e].sort((l,p)=>l-p));a.scans=f;let c=new Map;for(let[l,p]of f){let h=await this.db.haplotypeSamplesInRange(l,p);a.scanRows+=h.length;for(let d of h){let u=t.has(A(d.node));if(!s.has(d.pathHandle)&&(!u||n.has(d.node))&&o(i(d.pathHandle))){let m=c.get(d.pathHandle)??[];u?m.unshift(d):m.push(d),c.set(d.pathHandle,m)}}}return c}async identifyPaths(){if(!this.db.hasHaplotypeIndex)throw new Error("The database has no HaplotypeSamples table; run gbz-haplotype-index on it");let e=await this.db.haplotypeSampleInterval()??4096,t=pr(this.sortedHandles());if(t.length===0)return;let n=new Map;for(let[u,m]of t)for(let w of await this.db.haplotypeSamplesInRange(u,m))n.set(fe(w),w);let o=u=>{let m=0,w=t.length-1;for(;m<w;){let S=m+w+1>>1;t[S][0]<=u?m=S:w=S-1}let x=t[m];return x[0]<=u&&u<=x[1]},s=new Map;this.paths.forEach((u,m)=>{u.path.length>0&&m!==this.refId&&s.set(fe(Ke(u,0)),m)});let i=this.stats.identification;i.interval=e,i.scans=t,i.windowSamples=n.size,this.paths.forEach((u,m)=>{m!==this.refId&&i.fragmentLengths.push(u.len)});let a=this.recordReader(()=>{this.stats.identificationFetches+=1,i.graphFetches+=1}),f=u=>(i.graphLookups+=1,a(u)),c=async(u,m)=>{if(o(u.node))return n.get(fe(u));this.stats.identificationFetches+=1,i.companionSeeks+=1,m.seeks+=1;let w=await this.db.haplotypeSampleAt(u.node,u.offset);return w||(i.companionMisses+=1),w},l=new Map,p=async u=>{let m=l.get(u);if(!m){let w=await this.db.getPath(u);if(!w)throw new Error(`Path ${u} is missing from the database`);m=w.name,l.set(u,m)}return m},h=(u,m,w)=>u.orientation==="forward"?{pathHandle:u.pathHandle,orientation:"forward",base:u.pathOffset-m}:{pathHandle:u.pathHandle,orientation:"reverse",base:u.pathOffset+m+w},d=(u,m)=>u.orientation==="forward"?{pathHandle:u.pathHandle,orientation:"forward",base:u.hapStart-m}:{pathHandle:u.pathHandle,orientation:"reverse",base:u.hapEnd+m};for(let u=0;u<this.paths.length;u++){let m=this.paths[u];if(u===this.refId||m.identity)continue;let w=[],x=new Set,S={fragments:0,steps:0,seeks:0,reentries:0,twinLandings:0,end:"endmarker",pathHandle:void 0};i.chains.push(S);let g,b=0,y=u,v;for(;g===void 0;){if(this.signal?.throwIfAborted(),y!==void 0){if(x.has(y)){S.end="cycle";break}x.add(y);let E=this.paths[y];w.push({index:y,startBp:b}),S.fragments+=1;let M=b;for(let N=0;N<E.path.length;N++){let F=Ke(E,N),q=n.get(fe(F)),Ee=this.record(F.node).sequenceLen;if(q){g=h(q,M,Ee);break}M+=Ee}if(b+=E.len,g){S.end="in-fragment sample";break}let L=Ke(E,E.path.length-1);v=this.record(L.node).gbwt().lf(L.offset),y=void 0}if(v===void 0||v.node===0){S.end="endmarker";break}let I=fe(v),R=s.get(I);if(R!==void 0){let E=this.paths[R].identity;if(E){g=d(E,b),S.end="identified sibling";break}y=R;continue}this.records.has(v.node)&&(S.reentries+=1),this.twinStarts.has(I)&&(S.twinLandings+=1);let C=await c(v,S),P=await f(v.node);if(C){g=h(C,b,P.sequenceLen),S.end="out-of-window sample";break}if(this.stats.identificationSteps+=1,S.steps+=1,b-w[w.length-1].startBp>4*e+4*P.sequenceLen){S.end="bound";break}b+=P.sequenceLen,v=P.gbwt().lf(v.offset)}if(g){S.pathHandle=g.pathHandle;let I=await p(g.pathHandle);for(let{index:R,startBp:C}of w){let P=this.paths[R];P.identity=g.orientation==="forward"?{pathHandle:g.pathHandle,name:I,orientation:"forward",hapStart:g.base+C,hapEnd:g.base+C+P.len}:{pathHandle:g.pathHandle,name:I,orientation:"reverse",hapStart:g.base-C-P.len,hapEnd:g.base-C}}}}}refIndex(e){if(this.refIndexCache===void 0){let t=new Map;e.forEach((n,o)=>{let s=t.get(n);s?s.push(o):t.set(n,[o])}),this.refIndexCache=t}return this.refIndexCache}refPrefix(e){if(this.refPrefixCache===void 0){let t=[0];e.forEach((n,o)=>{t.push(t[o]+this.record(n).sequenceLen)}),this.refPrefixCache=t}return this.refPrefixCache}orderedMatches(e,t){let n=this.refIndex(t),o=new Int32Array(e.length),s=new Int32Array(e.length),i=0,a=-1;for(let f=0;f<e.length;f++){let c=n.get(e[f]);if(c){let l=Yo(c,a);if(l===void 0)return;o[i]=f,s[i]=l,i+=1,a=l}}return{pathAt:o,refAt:s,count:i}}pathLen(e){let t=0;for(let n of e)t+=this.record(n).sequenceLen;return t}prefixMatches(e,t){let n=0,o=0,s=0,i=0,a=0;for(;o<e.length&&s<t.length;){let f=this.record(e[o]).sequence,c=this.record(t[s]).sequence;for(;i<f.length&&a<c.length;){if(f[i]!==c[a])return n;i+=1,a+=1,n+=1}i===f.length&&(o+=1,i=0),a===c.length&&(s+=1,a=0)}return n}suffixMatches(e,t){let n=0,o=0,s=0,i=0,a=0;for(;o<e.length&&s<t.length;){let f=this.record(e[e.length-o-1]).sequence,c=this.record(t[t.length-s-1]).sequence;for(;i<f.length&&a<c.length;){if(f[f.length-i-1]!==c[c.length-a-1])return n;i+=1,a+=1,n+=1}i===f.length&&(o+=1,i=0),a===c.length&&(s+=1,a=0)}return n}align(e,t,n){let o=this.pathLen(e),s=this.pathLen(t),i=this.prefixMatches(e,t),a=this.suffixMatches(e,t);i+a>o&&(a=o-i),i+a>s&&(a=s-i),z(n,"M",i),hr(n,o-i-a,s-i-a),z(n,"M",a)}sharedWeight(e,t){let n=this.refIndex(t),o=0;for(let s of e)n.has(s)&&(o+=this.record(s).sequenceLen);return o}editsAgainst(e,t){let n=this.orderedMatches(e,t);n?this.stats.orderedAlignments+=1:this.stats.lcsAlignments+=1;let o=n??Qo(Xn(e,t,p=>this.record(p).sequenceLen)[0]),s=[],i=this.refPrefix(t),a=(p,h,d,u)=>{p===h?z(s,"D",i[u]-i[d]):d===u?z(s,"I",this.pathLen(e.slice(p,h))):this.align(e.slice(p,h),t.slice(d,u),s)},f=0,c=0,l=0;for(let p=0;p<o.count;p++){let h=o.pathAt[p],d=o.refAt[p];(c!==h||l!==d)&&a(c,h,l,d);let u=this.record(e[h]).sequenceLen;z(s,"M",u),f+=u,c=h+1,l=d+1}return a(c,e.length,l,t.length),{edits:s,matched:f}}alignment(e){let t=this.paths[e];if(this.refId===void 0||e===this.refId||!t)return;let n=this.paths[this.refId].path,o;if($n(n))o={edits:this.editsAgainst(t.path,n).edits,flipped:!1};else{let s=t.path.map(f=>B(f)).reverse(),i=this.sharedWeight(t.path,n);if(this.sharedWeight(s,n)===0)o={edits:this.editsAgainst(t.path,n).edits,flipped:!1};else if(i===0)o={edits:this.editsAgainst(s,n).edits,flipped:!0};else{let f=this.editsAgainst(t.path,n),c=this.editsAgainst(s,n);o=c.matched>f.matched?{edits:c.edits,flipped:!0}:{edits:f.edits,flipped:!1}}}return o}alignToRef(e){return this.alignment(e)?.edits.map(([t,n])=>`${n}${t}`).join("")}alignments(){let e=this.referenceInterval;if(this.refId===void 0||!e)throw new Error("Alignments need a reference path");let t=this.paths[this.refId].path,n=this.refPrefix(t)[t.length],o=[];return this.paths.forEach((s,i)=>{if(i===this.refId)return;let{edits:a,flipped:f}=this.alignment(i),c=0,l=0;for(;c<a.length&&a[c][0]==="D";)l+=a[c][1],c+=1;let p=a.length,h=0;for(;p>c&&a[p-1][0]==="D";)h+=a[p-1][1],p-=1;let d=s.identity,u=d?d.orientation==="forward"!==f:!f;o.push({strand:u?"+":"-",refStart:e.start+l,refEnd:e.start+n-h,edits:a.slice(c,p),weight:s.weight,path:s.path,start:Ke(s,0),identity:d===void 0?void 0:{pathHandle:d.pathHandle,name:d.name,hapStart:d.name.fragment+d.hapStart,hapEnd:d.name.fragment+d.hapEnd,walkForward:d.orientation==="forward"}})}),Xo(o).map(s=>{let{edits:i,identity:a,...f}=s,c={...f,cigar:rs(i)};return a?{...c,resolved:!0,name:a.name,label:$({...a.name,fragment:a.hapStart},a.hapEnd),pathHandle:a.pathHandle,hapStart:a.hapStart,hapEnd:a.hapEnd}:{...c,resolved:!1}})}pairAlignments(e){let{target:t,query:n,...o}=e,s=this.paths.flatMap(l=>{let{identity:p}=l;return p?[{name:p.name,start:p.name.fragment+p.hapStart,steps:Ze(l,p)}]:[]}),i=l=>p=>p.sample===l.sample&&p.haplotype===l.haplotype,a=i(t),f=n?i(n):l=>!a(l),c=l=>this.record(V(l,"forward")).sequence;return s.filter(l=>a(l.name)).flatMap(l=>s.filter(p=>f(p.name)).flatMap(p=>cr(p.steps,l.steps,c,o).map(h=>({query:p.name,queryStart:p.start+h.queryStart,queryEnd:p.start+h.queryEnd,strand:h.strand,target:l.name,targetStart:l.start+h.targetStart,targetEnd:l.start+h.targetEnd,cigar:lr(h.edits),matches:h.edits.reduce((d,[u,m])=>d+(u==="="?m:0),0),columns:h.edits.reduce((d,[,u])=>d+u,0),sharedBases:h.sharedBases}))))}canonicalEdges(e){let t=[];for(let n of["forward","reverse"]){let o=V(e,n);for(let s of this.record(o).successors())this.hasHandle(s)&&we(o,s)&&t.push([n==="reverse"?1:0,A(s),O(s)?1:0])}return t.sort((n,o)=>n[0]-o[0]||n[1]-o[1]||n[2]-o[2]),t.filter((n,o)=>o===0||n[0]!==t[o-1][0]||n[1]!==t[o-1][1]||n[2]!==t[o-1][2])}async stableName(){let e=new TextEncoder,t=[];for(let n of this.sortedHandles())if(!O(n)){let o=A(n),s=`S ${o} ${this.record(n).sequence}
|
|
2
|
-
`;for(let[i,a,f]of this.canonicalEdges(o))s+=`L ${o} ${i?"-":"+"} ${a} ${f?"-":"+"}
|
|
3
|
-
`;t.push(e.encode(s))}return Vn(t)}async toGFA(e={}){let t=e.cigar??!1,n=[this.refPath?`H VN:Z:1.1 RS:Z:${this.refPath.sample}`:"H VN:Z:1.1",...Yn(Qn(await this.stableName(),await this.db.graphName()))],o=this.sortedHandles();for(let c of o)O(c)||n.push(`S ${A(c)} ${this.record(c).sequence}`);let s=c=>O(c)?"-":"+";for(let c of o)for(let l of this.record(c).successors())this.hasHandle(l)&&we(c,l)&&n.push(`L ${A(c)} ${s(c)} ${A(l)} ${s(l)} 0M`);let i=(c,l,p,h,d)=>{let u=Ze(c,l).map(x=>`${O(x)?"<":">"}${A(x)}`).join(""),m=c.weight===void 0?"":` WT:i:${c.weight}`,w=d===void 0?"":` CG:Z:${d}`;return`W ${p.sample} ${p.haplotype} ${p.contig} ${p.fragment} ${h} ${u}${m}${w}`},a=this.refPath?.contig??"unknown";this.refId!==void 0&&this.refPath&&this.refInterval&&n.push(i(this.paths[this.refId],void 0,{...this.refPath,fragment:this.refPath.fragment+this.refInterval[0]},this.refPath.fragment+this.refInterval[1],void 0));let f=1;return this.paths.forEach((c,l)=>{if(l!==this.refId){let p=e.names==="resolved"?c.identity:void 0,h=t?this.alignToRef(l):void 0;n.push(p?i(c,p,{...p.name,fragment:p.name.fragment+p.hapStart},p.name.fragment+p.hapEnd,h):i(c,void 0,{sample:"unknown",contig:a,haplotype:f,fragment:0},c.len,h)),f+=1}}),`${n.join(`
|
|
4
|
-
`)}
|
|
5
|
-
`}outputPaths(e){let t=e.cigar??!1,n=[],o=this.refPath?.contig??"unknown";if(this.refId!==void 0&&this.refPath&&this.refInterval){let i={...this.refPath,fragment:this.refPath.fragment+this.refInterval[0]};n.push({info:this.paths[this.refId],identity:void 0,name:$(i,this.refPath.fragment+this.refInterval[1]),cigar:void 0})}let s=1;return this.paths.forEach((i,a)=>{if(a===this.refId)return;let f=e.names==="resolved"?i.identity:void 0;n.push({info:i,identity:f,name:f?$({...f.name,fragment:f.name.fragment+f.hapStart},f.name.fragment+f.hapEnd):$({sample:"unknown",contig:o,haplotype:s,fragment:0},i.len),cigar:t?this.alignToRef(a):void 0}),s+=1}),n}*outputEdges(){for(let e of this.sortedHandles())for(let t of this.record(e).successors())this.hasHandle(t)&&we(e,t)&&(yield[e,t])}toSubgraphJson(e={}){let t=this.sortedHandles().filter(s=>!O(s)).map(s=>({id:String(A(s)),sequence:this.record(s).sequence})),n=[];for(let[s,i]of this.outputEdges())n.push({from:String(A(s)),from_is_reverse:O(s),to:String(A(i)),to_is_reverse:O(i)});let o=this.outputPaths(e).map(s=>ns(s.info,s.identity,s.name,s.cigar));return{nodes:t,edges:n,paths:o}}toCompactSubgraph(e={}){let t=this.sortedHandles().filter(i=>!O(i)),n=new Int32Array(t.length),o=[];t.forEach((i,a)=>{n[a]=A(i),o.push(this.record(i).sequence)});let s=[];for(let[i,a]of this.outputEdges())s.push(i,a);return{nodeIds:n,nodeSequences:o,edges:Int32Array.from(s),paths:this.outputPaths(e).map(i=>({name:i.name,weight:i.info.weight,cigar:i.cigar,steps:Int32Array.from(Ze(i.info,i.identity))}))}}};function Ze(r,e){return e?.orientation==="reverse"?r.path.map(t=>B(t)).reverse():r.path}function ns(r,e,t,n){return{name:t,...r.weight===void 0?{}:{weight:r.weight},...n===void 0?{}:{cigar:n},path:Ze(r,e).map(o=>({id:String(A(o)),is_reverse:O(o)}))}}function Vt(r,e){let t=Math.min(r.length,e.length);for(let n=0;n<t;n++){let o=r[n],s=e[n];if(o!==s)return o<s?-1:1}return r.length-e.length}function z(r,e,t){if(t===0)return;let n=r[r.length-1];n?.[0]===e?n[1]+=t:r.push([e,t])}function Xe(r){return r===0?0:6+(r-1)}function hr(r,e,t){if(e===0)z(r,"D",t);else if(t===0)z(r,"I",e);else{let n=Math.min(e,t),o=4*n+Xe(e-n)+Xe(t-n),s=Xe(e)+Xe(t);o<=s?(z(r,"M",n),z(r,"I",e-n),z(r,"D",t-n)):(z(r,"I",e),z(r,"D",t))}}function rs(r){return r.map(([e,t])=>`${t}${e}`).join("")}async function Je(r,e,t,n,o={}){let s=new Me(r,o);try{let i=await s.pathPosition(Pe(e,t));await s.prefetchReferenceWalk(i,n-t),await s.aroundInterval(i.position,n-t,o.context??100),await s.extractSnarls(o.snarls??"none"),s.extractPaths(i,o.haplotypes??"all")}catch(i){throw i instanceof X&&i.windowBp===void 0?new X(i.limit,{windowBp:n-t,walkedBp:s.referenceWalkedBp??0}):i}return s}async function dr(r,e,t,n,o){if(!r.hasHaplotypeIndex)throw new Error("keep needs the haplotype index: this database cannot name its walks");let s=await r.haplotypeAnchorSpacing(),i,a;if(s!==void 0&&(o.haplotypes??"all")==="all"){let f=new Me(r,o);try{let c=await f.pathPosition(Pe(e,t));a=await f.walkHaplotypesFromAnchor(c,n-t,s,o.keep,o.context??100)}catch(c){throw c instanceof X&&c.windowBp===void 0?new X(c.limit,{windowBp:n-t,walkedBp:f.referenceWalkedBp??0}):c}if(a===void 0)i=f;else{a=`${a}; identified from the per-path samples instead`;let c=await Je(r,e,t,n,o);await c.identifyPaths(),c.keepHaplotypes(o.keep),c.stats.anchorWalk=f.stats.anchorWalk,c.stats.anchorWalk&&(c.stats.anchorWalk.fallback=a),i=c}}else i=await Je(r,e,t,n,o),await i.identifyPaths(),i.keepHaplotypes(o.keep);return i}function Z(r,e){let t=0;for(let o=0;o<8;o++){let s=r[e+o];if(s===void 0)throw new Error("SQLite varint runs past the end of the buffer");if(t=t*128+(s&127),(s&128)===0)return[t,e+o+1]}let n=r[e+8];if(n===void 0)throw new Error("SQLite varint runs past the end of the buffer");if(t=t*256+n,!Number.isSafeInteger(t))throw new Error("SQLite varint exceeds the safe integer range");return[t,e+9]}function os(r,e,t){switch(t){case 1:return r.getInt8(e);case 2:return r.getInt16(e);case 3:return r.getInt8(e)<<16|r.getUint16(e+1);case 4:return r.getInt32(e);case 6:return r.getInt16(e)*4294967296+r.getUint32(e+2);default:{let n=r.getBigInt64(e);if(n>BigInt(Number.MAX_SAFE_INTEGER)||n<BigInt(Number.MIN_SAFE_INTEGER))throw new Error(`SQLite integer ${n} exceeds the safe integer range`);return Number(n)}}}var ss=new TextDecoder;function et(r){let[e,t]=Z(r,0),n=[],o=t;for(;o<e;){let[a,f]=Z(r,o);n.push(a),o=f}let s=new DataView(r.buffer,r.byteOffset,r.byteLength),i=e;return n.map(a=>{if(a===0)return null;if(a>=1&&a<=6){let f=a<=4?a:a===5?6:8,c=os(s,i,f);return i+=f,c}if(a===7){let f=s.getFloat64(i);return i+=8,f}if(a===8)return 0;if(a===9)return 1;if(a>=12){let f=a-12>>1,c=r.subarray(i,i+f);return i+=f,a%2===0?c:ss.decode(c)}throw new Error(`SQLite serial type ${a} is reserved`)})}var ke=2,nt=5,mr=10,tt=13;function gr(r,e){return r[e]*256+r[e+1]}function oe(r,e){return r[e]*16777216+r[e+1]*65536+r[e+2]*256+r[e+3]}function is(r,e){let t=r[e];if(t!==ke&&t!==nt&&t!==mr&&t!==tt)throw new Error(`SQLite page has unknown b-tree type ${t}`);let n=t===ke||t===nt;return{type:t,cellCount:gr(r,e+3),rightChild:n?oe(r,e+8):0,cellPointers:e+(n?12:8)}}function ne(r,e,t){return gr(r,e.cellPointers+2*t)}var as=4096,fs=4096,rt=class{usable;pager;decodedIndexPages=new Map;tableDepths=new Map;constructor(e,t){this.pager=e,this.usable=e.pageSize-t}localPayloadSize(e,t){let n=this.usable,o=t?Math.floor((n-12)*64/255)-23:n-35;if(e<=o)return e;let s=Math.floor((n-12)*32/255)-23,i=s+(e-s)%(n-4);return i<=o?i:s}async payload(e,t,n,o){let s=this.localPayloadSize(n,o);if(s===n)return e.subarray(t,t+n);let i=new Uint8Array(n);i.set(e.subarray(t,t+s),0);let a=s,f=oe(e,t+s);for(;f!==0&&a<n;){let c=await this.pager.page(f),l=c.subarray(4,4+Math.min(this.usable-4,n-a));i.set(l,a),a+=l.length,f=oe(c,0)}if(a!==n)throw new Error("SQLite overflow chain ended before the payload was complete");return i}async pageAt(e){let t=await this.pager.page(e);return{page:t,header:is(t,e===1?100:0)}}tableDepth(e,t){let n=this.tableDepths.get(e);return n||(n=(async()=>{let o=e;for(let s=0;;s++){let{page:i,header:a}=await this.pageAt(o);if(a.type===tt)return s;if(a.type!==nt)throw new Error("SQLite table b-tree contains an index page");let f=this.childIndexFor(i,a,t);o=f===a.cellCount?a.rightChild:oe(i,ne(i,a,f))}})(),this.tableDepths.set(e,n),n.catch(()=>this.tableDepths.delete(e))),n}childIndexFor(e,t,n){let o=0,s=t.cellCount;for(;o<s;){let i=o+s>>1,[a]=Z(e,ne(e,t,i)+4);a<n?o=i+1:s=i}return o}async prefetchRowidRange(e,t,n){let o=await this.tableDepth(e,t),s=[e];for(let i=0;i<o;i++){let a=await Promise.all(s.map(c=>this.pageAt(c))),f=[];if(a.forEach(({page:c,header:l},p)=>{let h=p===0?this.childIndexFor(c,l,t):0,d=p===a.length-1?this.childIndexFor(c,l,n):l.cellCount;for(let u=h;u<=d;u++)f.push(u===l.cellCount?l.rightChild:oe(c,ne(c,l,u)))}),f.length>fs)return!1;this.pager.prefetch(f),s=f}return!0}async tableRowid(e,t){let n=e;for(;;){let{page:o,header:s}=await this.pageAt(n);if(s.type===tt){let f=0,c=s.cellCount;for(;f<c;){let l=f+c>>1,p=ne(o,s,l),[h,d]=Z(o,p),[u,m]=Z(o,d);if(u===t)return et(await this.payload(o,m,h,!1));u<t?f=l+1:c=l}return}if(s.type!==nt)throw new Error("SQLite table b-tree contains an index page");let i=0,a=s.cellCount;for(;i<a;){let f=i+a>>1,c=ne(o,s,f),[l]=Z(o,c+4);l<t?i=f+1:a=f}n=i===s.cellCount?s.rightChild:oe(o,ne(o,s,i))}}async*tableScan(e){let{page:t,header:n}=await this.pageAt(e);if(n.type===tt)for(let o=0;o<n.cellCount;o++){let s=ne(t,n,o),[i,a]=Z(t,s),[f,c]=Z(t,a);yield{rowid:f,values:et(await this.payload(t,c,i,!1))}}else{let o=[];for(let s=0;s<n.cellCount;s++)o.push(oe(t,ne(t,n,s)));o.push(n.rightChild),this.pager.prefetch(o);for(let s of o)yield*this.tableScan(s)}}decodedCells(e,t){let n=this.decodedIndexPages.get(e);if(n)this.decodedIndexPages.delete(e);else if(n=new Array(t.cellCount),this.decodedIndexPages.size>=as){let o=this.decodedIndexPages.keys().next().value;o!==void 0&&this.decodedIndexPages.delete(o)}return this.decodedIndexPages.set(e,n),n}async indexCell(e,t,n,o){let s=this.decodedCells(e,n),i=s[o];if(!i){let a=ne(t,n,o),f=n.type===ke,[c,l]=Z(t,f?a+4:a);i={values:et(await this.payload(t,l,c,!0)),leftChild:f?oe(t,a):0},s[o]=i}return i}async*indexScanFrom(e,t){let{page:n,header:o}=await this.pageAt(e),s=0,i=o.cellCount;for(;s<i;){let a=s+i>>1,f=await this.indexCell(e,n,o,a);ur(f.values,t)<0?s=a+1:i=a}for(let a=s;a<o.cellCount;a++){let f=await this.indexCell(e,n,o,a);o.type===ke&&(yield*this.indexScanFrom(f.leftChild,t)),yield f.values}o.type===ke&&(yield*this.indexScanFrom(o.rightChild,t))}async indexSeekLE(e,t){let n,o=e;for(;;){let{page:s,header:i}=await this.pageAt(o),a=0,f=i.cellCount,c=0;for(;a<f;){let l=a+f>>1,p=await this.indexCell(o,s,i,l);ur(p.values,t)<=0?(n=p.values,a=l+1):(c=p.leftChild,f=l)}if(i.type===mr)return n;o=a===i.cellCount?i.rightChild:c}}};function ur(r,e){for(let t=0;t<e.length;t++){let n=r[t],o=e[t];if(typeof n!="number"||o===void 0)throw new Error("SQLite index key is not numeric");if(n!==o)return n<o?-1:1}return 0}var ot=class{blocks=new Map;blockSize;maxBlocks;bytesFetched=0;fetches=0;source;pageSize;fileSize;constructor(e,t,n,o={}){this.source=e,this.pageSize=t,this.fileSize=n;let s=o.blockSize??65536;this.blockSize=Math.max(t,Math.ceil(s/t)*t),this.maxBlocks=o.maxBlocks??256}async read(e,t){let n=0;for(;;)try{let o=await this.source.read(e,t);return this.bytesFetched+=o.length,o}catch(o){if(n+=1,n>=3)throw o;await new Promise(s=>setTimeout(s,200*n))}}seed(e,t){t.length===Math.min(this.blockSize,this.fileSize-e*this.blockSize)&&this.blocks.set(e,Promise.resolve(t))}block(e){let t=this.blocks.get(e);if(t)return this.blocks.delete(e),this.blocks.set(e,t),t;let n=e*this.blockSize,o=Math.min(this.blockSize,this.fileSize-n),s=this.read(o,n);return this.fetches+=1,this.blocks.set(e,s),this.forgetOnFailure(s,[e]),this.evict(),s}prefetch(e){let t=[...new Set(e.map(o=>Math.floor((o-1)*this.pageSize/this.blockSize)))].filter(o=>!this.blocks.has(o)).sort((o,s)=>o-s),n=0;for(;n<t.length;){let o=n+1;for(;o<t.length&&t[o]===t[o-1]+1;)o+=1;this.fetchRun(t[n],o-n),n=o}}fetchRun(e,t){let n=e*this.blockSize,o=Math.min(t*this.blockSize,this.fileSize-n),s=this.read(o,n);this.fetches+=1;let i=[];for(let a=0;a<t;a++){let f=a*this.blockSize;i.push(e+a),this.blocks.set(e+a,s.then(c=>c.subarray(f,f+this.blockSize)))}this.forgetOnFailure(s,i),this.evict()}forgetOnFailure(e,t){e.catch(()=>{for(let n of t)this.blocks.delete(n)})}evict(){for(;this.blocks.size>this.maxBlocks;){let e=this.blocks.keys().next().value;if(e===void 0)break;this.blocks.delete(e)}}async page(e){let t=(e-1)*this.pageSize;if(e<1||t+this.pageSize>this.fileSize)throw new Error(`SQLite page ${e} is outside the file`);let n=await this.block(Math.floor(t/this.blockSize)),o=t%this.blockSize;return n.subarray(o,o+this.pageSize)}};var Le=class r{pager;btree;objects;constructor(e,t,n){this.pager=e,this.btree=t,this.objects=n}static async open(e,t={}){let{size:n}=await e.stat(),o=await e.read(Math.min(t.blockSize??65536,n),0),s=o.subarray(0,100);if(new TextDecoder().decode(s.subarray(0,15))!=="SQLite format 3")throw new Error("Not a SQLite database");let a=new DataView(s.buffer,s.byteOffset,s.byteLength),f=a.getUint16(16),c=f===1?65536:f,l=s[20]??0,p=a.getUint32(56);if(p!==1)throw new Error(`SQLite text encoding ${p} is not UTF-8`);let h=new ot(e,c,n,t);h.seed(0,o),h.fetches+=1,h.bytesFetched+=o.length;let d=new rt(h,l),u=new Map;for await(let{values:m}of d.tableScan(1)){let[w,x,S,g,b]=m;typeof w=="string"&&typeof x=="string"&&typeof S=="string"&&typeof g=="number"&&u.set(x,{type:w,name:x,tableName:S,rootPage:g,sql:typeof b=="string"?b:""})}return new r(h,d,u)}rootPage(e){let t=this.objects.get(e);if(!t)throw new Error(`SQLite database has no object named ${e}`);return t.rootPage}indexOn(e){let t=[...this.objects.values()].find(n=>n.type==="index"&&n.tableName===e);if(!t)throw new Error(`SQLite table ${e} has no index`);return t.rootPage}byRowid(e,t){return this.btree.tableRowid(this.rootPage(e),t)}prefetchRows(e,t,n){return this.btree.prefetchRowidRange(this.rootPage(e),t,n)}scan(e){return this.btree.tableScan(this.rootPage(e))}indexSeekLE(e,t){return this.btree.indexSeekLE(this.indexOn(e),t)}indexScanFrom(e,t){return this.btree.indexScanFrom(this.indexOn(e),t)}has(e){return this.objects.has(e)}};var Xt="GBZ-base version 4",st=class extends Error{name="ForwardOnlyIndexError";constructor(){super("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")}},it=class extends Error{name="SchemaVersionError";found;constructor(e){super(e===void 0?"not a gbz-base database: its Tags table has no version":`unsupported database schema "${e}"; this reader understands "${Xt}"`),this.found=e}},at=class{sequenceLen;handle;edges;bwt;encodedSequence;next;decoded;constructor(e,t,n,o,s){this.handle=e,this.edges=t,this.bwt=n,this.encodedSequence=o,this.next=s,this.sequenceLen=Bn(o)}get id(){return A(this.handle)}get orientation(){return ge(this.handle)}get sequence(){return this.decoded??=Dn(this.encodedSequence),this.decoded}successors(){return this.edges.filter(e=>e.node!==0).map(e=>e.node)}gbwt(){if(this.edges.length===0)throw new Error(`GBWT record for handle ${this.handle} is empty`);return new ze(this.edges,this.bwt)}};function T(r,e){if(typeof r!="number")throw new Error(`${e} is not a number in the database`);return r}function ft(r,e){if(typeof r!="string")throw new Error(`${e} is not text in the database`);return r}function Kt(r,e){if(!(r instanceof Uint8Array))throw new Error(`${e} is not a blob in the database`);return r}function wr(r,e){return{handle:r,fwStart:{node:T(e[1],"Paths.fw_node"),offset:T(e[2],"Paths.fw_offset")},revStart:{node:T(e[3],"Paths.rev_node"),offset:T(e[4],"Paths.rev_offset")},name:{sample:ft(e[5],"Paths.sample"),contig:ft(e[6],"Paths.contig"),haplotype:T(e[7],"Paths.haplotype"),fragment:T(e[8],"Paths.fragment")},isIndexed:T(e[9],"Paths.is_indexed")!==0}}async function yr(r){let e=new Map;for await(let{values:t}of r.scan("Tags"))e.set(ft(t[0],"Tags.key"),ft(t[1],"Tags.value"));return e}var Oe=class r{tagCache;pathCache;pathMapCache;indexTags=new Map;sqlite;index;constructor(e,t){this.sqlite=e,this.index=t}static async open(e,t={}){let{haplotypeIndex:n,...o}=t,s=await Le.open(e,o);for(let c of["Tags","Nodes","Paths","ReferenceIndex"])s.rootPage(c);let i=n?await Le.open(n,o):void 0,a=new r(s,i),f=await a.tag("version");if(f!==Xt)throw new it(f);if(i){for(let d of["Tags","HaplotypeSamples","HaplotypeLengths"])i.rootPage(d);a.indexTags=await yr(i);let c=a.indexTags.get("haplotype_index_paths"),l=await a.tag("paths");if(c!==l)throw new Error(`haplotype index was built for ${c??"an unknown number of"} paths but the graph has ${l}`);let p=a.indexTags.get("haplotype_index_nodes"),h=await a.tag("nodes");if(p!==void 0&&p!==h)throw new Error(`haplotype index was built for a graph with ${p} nodes but this one has ${h}`);if(a.indexTags.get("haplotype_index_orientations")==="forward")throw new st}return a}tags(){return this.tagCache??=yr(this.sqlite),this.tagCache}async tag(e){return(await this.tags()).get(e)}prefetchRecords(e,t){return this.sqlite.prefetchRows("Nodes",e,t)}async getRecord(e){let t=await this.sqlite.byRowid("Nodes",e);if(!t)return;let n=t[4];return new at(e,Gn(Kt(t[1],"Nodes.edges")),Kt(t[2],"Nodes.bwt"),Kt(t[3],"Nodes.sequence"),typeof n=="number"?n:void 0)}paths(){return this.pathCache??=(async()=>{let e=[];for await(let{rowid:t,values:n}of this.sqlite.scan("Paths"))e.push(wr(t,n));return e})(),this.pathCache}async getPath(e){let t=await this.sqlite.byRowid("Paths",e);return t?wr(e,t):void 0}pathsByHandle(){return this.pathMapCache??=this.paths().then(e=>new Map(e.map(t=>[t.handle,t]))),this.pathMapCache}async findPath(e){return(await this.paths()).filter(n=>n.name.sample===e.sample&&n.name.contig===e.contig&&n.name.haplotype===e.haplotype&&n.name.fragment<=e.fragment).sort((n,o)=>o.name.fragment-n.name.fragment)[0]}async pathsForSample(e){return(await this.paths()).filter(t=>t.name.sample===e)}async pathsNamed(e){let t=Pe(Kn(e),0);return(await this.paths()).filter(n=>n.name.sample===t.sample&&n.name.contig===t.contig&&n.name.haplotype===t.haplotype).sort((n,o)=>n.name.fragment-o.name.fragment)}async hasPath(e){return(await this.pathsNamed(e)).length>0}pathLengths=new Map;pathLength(e){let t=this.pathLengths.get(e);return t||(t=this.walkPathLength(e),this.pathLengths.set(e,t),t.catch(()=>this.pathLengths.delete(e))),t}async walkPathLength(e){let t=this.hasHaplotypeIndex?await this.haplotypeLength(e):void 0;if(t===void 0){let n=await this.indexedPosition(e,Number.MAX_SAFE_INTEGER);if(!n){let i=await this.getPath(e);throw new Error(`Path ${i?$(i.name,i.name.fragment):e} has not been indexed for random access`)}let o=n.pathOffset,s=n.pos;for(;;){let i=await this.getRecord(s.node);if(!i)throw new Error(`Node ${s.node} does not exist in the graph`);o+=i.sequenceLen;let a=i.gbwt().lf(s.offset);if(!a||a.node===0)return o;s=a}}return t}async pathFragmentsForRange(e,t,n){if(n<=t)return[];let o=await this.pathsNamed(e),s=o.filter(f=>f.name.fragment<=t).slice(-1),i=o.filter(f=>f.name.fragment>t&&f.name.fragment<n);return(await Promise.all([...s,...i].map(async f=>({path:f,start:f.name.fragment,end:f.name.fragment+await this.pathLength(f.handle)})))).filter(f=>t<f.end)}async subgraphForFragment(e,t,n,o){let{keep:s,...i}=o;if(s!==void 0&&!this.hasHaplotypeIndex)throw new Error("keep needs the haplotype index: this database cannot name its walks");let{sample:a,contig:f,haplotype:c}=e.path.name,l={sample:a,contig:f,haplotype:c},p=Math.max(t,e.start),h=Math.min(n,e.end),d=o.haplotypes??"all",u=d==="all"||d==="distinct",m;return s!==void 0&&d==="all"?m=await dr(this,l,p,h,{...i,keep:s}):(m=await Je(this,l,p,h,i),this.hasHaplotypeIndex&&u&&(await m.identifyPaths(),s!==void 0&&m.keepHaplotypes(s))),m}async getSubgraphForRange(e,t,n,o={}){let[s]=await this.pathFragmentsForRange(e,t,n);return s?this.subgraphForFragment(s,t,n,o):void 0}async getAlignmentsForRange(e,t,n,o={}){let s=[];for(let i of await this.pathFragmentsForRange(e,t,n)){let a=await this.subgraphForFragment(i,t,n,o);s.push(...a.alignments())}return s}async graphName(){let e=new Map;for(let[n,o]of await this.tags())n.startsWith("gbz_")&&e.set(n.slice(4),o);let t={name:void 0,subgraph:new Map,translation:new Map};try{t=Wn(e)}catch{}return t}async hasChainLinks(){let e=await this.tag("chain_links");return e!==void 0&&Number(e)>0}get hasHaplotypeIndex(){return this.index!==void 0}get companion(){if(!this.index)throw new Error("no haplotype index was opened with this database");return this.index}async haplotypeSampleInterval(){let e=this.indexTags.get("haplotype_index_interval");return e===void 0?void 0:Number(e)}async haplotypeAnchorSpacing(){let e=this.index?.has("HaplotypeAnchors")?this.indexTags.get("haplotype_index_anchor_spacing"):void 0;return e===void 0?void 0:Number(e)}async haplotypeAnchor(e,t){let n=await this.companion.indexSeekLE("HaplotypeAnchors",[e,t]),o=n?.[0]===e&&n[1]===t?await this.companion.byRowid("HaplotypeAnchors",T(n[2],"HaplotypeAnchors rowid")):void 0;return o?{node:T(o[2],"HaplotypeAnchors.node_handle"),pathOffset:T(o[3],"HaplotypeAnchors.path_offset")}:void 0}haplotypeSamplesAtNode(e){return this.haplotypeSamplesInRange(e,e)}sampleFromRow(e){return{node:T(e[0],"HaplotypeSamples.node_handle"),offset:T(e[1],"HaplotypeSamples.node_offset"),pathHandle:T(e[2],"HaplotypeSamples.path_handle"),orientation:T(e[3],"HaplotypeSamples.orientation")===0?"forward":"reverse",pathOffset:T(e[4],"HaplotypeSamples.path_offset")}}async haplotypeSamplesInRange(e,t){let n=[];for await(let o of this.companion.indexScanFrom("HaplotypeSamples",[e,0])){if(T(o[0],"HaplotypeSamples.node_handle")>t)break;let i=await this.companion.byRowid("HaplotypeSamples",T(o[2],"HaplotypeSamples rowid"));i&&n.push(this.sampleFromRow(i))}return n}async haplotypeSampleAt(e,t){let n=await this.companion.indexSeekLE("HaplotypeSamples",[e,t]);if(n?.[0]!==e||n[1]!==t)return;let o=await this.companion.byRowid("HaplotypeSamples",T(n[2],"HaplotypeSamples rowid"));return o?this.sampleFromRow(o):void 0}async haplotypeLength(e){let t=await this.companion.byRowid("HaplotypeLengths",e);return t?T(t[1],"HaplotypeLengths.length"):void 0}async indexedRow(e){let t=await this.sqlite.byRowid("ReferenceIndex",e);if(!t)throw new Error("ReferenceIndex row referenced by its index is missing");return{pathOffset:T(t[1],"ReferenceIndex.path_offset"),pos:{node:T(t[2],"ReferenceIndex.node_handle"),offset:T(t[3],"ReferenceIndex.node_offset")}}}async indexedRowid(e,t){let n=await this.sqlite.indexSeekLE("ReferenceIndex",[e,t]);return n?.[0]===e?T(n[2],"ReferenceIndex rowid"):void 0}async indexedPosition(e,t){let n=await this.indexedRowid(e,t);return n===void 0?void 0:this.indexedRow(n)}async indexedPositionsBetween(e,t,n){let[o,s]=await Promise.all([this.indexedRowid(e,t),this.indexedRowid(e,n)]),i=[];if(o!==void 0&&s!==void 0){await this.sqlite.prefetchRows("ReferenceIndex",o,s+1);for(let a=o;a<=s;a++)i.push(await this.indexedRow(a))}return i}};var ct=class extends Error{constructor(t,n){super(n.length===0?`the graph names no reference sample (gbwt_reference_samples) and the anchor "${t}" maps to none; set referenceSample`:`the anchor "${t}" is none of the graph's reference samples (${n.join(", ")}); set referenceSample or map it through assemblyNameToPanSN`);this.name="NoReferenceSampleError"}},lt=class extends Error{constructor(t,n,o){super(`this ${n.toLocaleString()} bp window reads more than nodeLimit (${t.toLocaleString()}) graph nodes; zoom in to about ${o.toLocaleString()} bp or raise nodeLimit`);this.name="NodeLimitError"}};function J(r){return`${r.sample}#${r.haplotype}`}function xr(r,e){let t=J(r);return e===void 0||e.some(n=>ue(t,n))}async function br(r){return(await r.tag("gbwt_reference_samples")??"").split(/\s+/).filter(e=>e!=="")}var cs={hg38:"grch38",hg19:"grch37",hs1:"chm13","t2t-chm13":"chm13",chm13v2:"chm13"};function ls(r,e){let t=r.toLowerCase(),n=cs[t];return e.find(o=>o===r)??e.find(o=>o.toLowerCase()===t)??e.find(o=>o.toLowerCase()===n)}function Zt({configured:r,anchorPrefix:e,referenceSamples:t}){if(r!=="")return r;let n=ls(Pn(e),t)??(t.length===1?t[0]:void 0);if(n===void 0)throw new ct(e,t);return n}async function Sr(r,e,t){let n=(await r.paths()).find(o=>o.isIndexed&&o.name.sample===e&&o.name.contig===t);return n?{sample:n.name.sample,contig:t,haplotype:n.name.haplotype}:void 0}function Te(r,e,t){if(r instanceof Error&&(r.name==="SubgraphLimitError"||/^Subgraph size limit of \d+ nodes exceeded/.test(r.message))){let o=r.walkedBp,s=typeof o=="number"&&o>0?Math.floor(o*.8):Math.floor(t/2);return new lt(e,t,Math.max(s,1))}else return}async function vr(r,e,t,n,{keep:o,...s}){let i=e?await r.getSubgraphForRange(e,t,n,{...s,haplotypes:"all",...o===void 0?{}:{keep:o}}).catch(a=>{throw Te(a,s.limit,n-t)??a}):void 0;return i?i.toGFA({names:"resolved"}):""}var bn=W(_n(),1),Sn=W(Ce(),1),Ae=W(Mn(),1),So=W(Ao(),1);var Ar=W(Mn(),1);var Ir=/\.gbz\.db$/i;function ps(r){return Ir.test(kn(r))?Ln(r,e=>e.replace(Ir,".haplotype-index.db")):void 0}async function Er(r,e){let t=ps(r);if(t)try{return await(0,Ar.openLocation)(t,e).stat(),t}catch{return}}var hs=5e3,ds=50*2**20,Jt=class extends Error{constructor(t){super(`this GAF is ${(t/2**20).toFixed(0)} MB without an index; bgzip it and index it with tabix -p gaf`);this.name="UnindexedGafTooLargeError"}};function us(r,e){if(r.length<=e)return r;let t=r.length/e;return Array.from({length:e},(n,o)=>r[Math.floor(o*t)])}var Cr=(r,e)=>r.path.some(t=>e.has(t.name)),pt=class{constructor(e,t){this.file=e;this.tabix=t}readWhole(e){return this.whole??=(async()=>{let{size:t}=await this.file.stat();if(t>ds)throw new Jt(t);let n=await this.file.readFile({signal:e}),o=new TextDecoder().decode(n[0]===31&&n[1]===139?await Cn(n):n);return Tn(o)})().catch(t=>{throw this.whole=void 0,t}),this.whole}async readIndexed(e,t,n){let o=1/0,s=-1/0;for(let a of t){let f=Number(a);Number.isInteger(f)&&(o=Math.min(o,f),s=Math.max(s,f))}let i=[];return o<=s&&await e.getLines("{node}",o,s+1,{signal:n,lineCallback:a=>{let f=On(a);f&&Cr(f,t)&&i.push(f)}}),i}async readsOver(e,{signal:t}={}){let n=this.tabix?await this.readIndexed(this.tabix,e,t):(await this.readWhole(t)).filter(o=>Cr(o,e));return{records:us(n,hs),total:n.length}}};var yo=W(_n(),1),xo=W(Ce(),1);var en=function(r,e){return en=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,n){t.__proto__=n}||function(t,n){for(var o in n)Object.prototype.hasOwnProperty.call(n,o)&&(t[o]=n[o])},en(r,e)};function Ne(r,e){if(typeof e!="function"&&e!==null)throw new TypeError("Class extends value "+String(e)+" is not a constructor or null");en(r,e);function t(){this.constructor=r}r.prototype=e===null?Object.create(e):(t.prototype=e.prototype,new t)}function Rr(r,e,t,n){function o(s){return s instanceof t?s:new t(function(i){i(s)})}return new(t||(t=Promise))(function(s,i){function a(l){try{c(n.next(l))}catch(p){i(p)}}function f(l){try{c(n.throw(l))}catch(p){i(p)}}function c(l){l.done?s(l.value):o(l.value).then(a,f)}c((n=n.apply(r,e||[])).next())})}function ht(r,e){var t={label:0,sent:function(){if(s[0]&1)throw s[1];return s[1]},trys:[],ops:[]},n,o,s,i=Object.create((typeof Iterator=="function"?Iterator:Object).prototype);return i.next=a(0),i.throw=a(1),i.return=a(2),typeof Symbol=="function"&&(i[Symbol.iterator]=function(){return this}),i;function a(c){return function(l){return f([c,l])}}function f(c){if(n)throw new TypeError("Generator is already executing.");for(;i&&(i=0,c[0]&&(t=0)),t;)try{if(n=1,o&&(s=c[0]&2?o.return:c[0]?o.throw||((s=o.return)&&s.call(o),0):o.next)&&!(s=s.call(o,c[1])).done)return s;switch(o=0,s&&(c=[c[0]&2,s.value]),c[0]){case 0:case 1:s=c;break;case 4:return t.label++,{value:c[1],done:!1};case 5:t.label++,o=c[1],c=[0];continue;case 7:c=t.ops.pop(),t.trys.pop();continue;default:if(s=t.trys,!(s=s.length>0&&s[s.length-1])&&(c[0]===6||c[0]===2)){t=0;continue}if(c[0]===3&&(!s||c[1]>s[0]&&c[1]<s[3])){t.label=c[1];break}if(c[0]===6&&t.label<s[1]){t.label=s[1],s=c;break}if(s&&t.label<s[2]){t.label=s[2],t.ops.push(c);break}s[2]&&t.ops.pop(),t.trys.pop();continue}c=e.call(r,t)}catch(l){c=[6,l],o=0}finally{n=s=0}if(c[0]&5)throw c[1];return{value:c[0]?c[1]:void 0,done:!0}}}function ce(r){var e=typeof Symbol=="function"&&Symbol.iterator,t=e&&r[e],n=0;if(t)return t.call(r);if(r&&typeof r.length=="number")return{next:function(){return r&&n>=r.length&&(r=void 0),{value:r&&r[n++],done:!r}}};throw new TypeError(e?"Object is not iterable.":"Symbol.iterator is not defined.")}function xe(r,e){var t=typeof Symbol=="function"&&r[Symbol.iterator];if(!t)return r;var n=t.call(r),o,s=[],i;try{for(;(e===void 0||e-- >0)&&!(o=n.next()).done;)s.push(o.value)}catch(a){i={error:a}}finally{try{o&&!o.done&&(t=n.return)&&t.call(n)}finally{if(i)throw i.error}}return s}function be(r,e,t){if(t||arguments.length===2)for(var n=0,o=e.length,s;n<o;n++)(s||!(n in e))&&(s||(s=Array.prototype.slice.call(e,0,n)),s[n]=e[n]);return r.concat(s||Array.prototype.slice.call(e))}function le(r){return this instanceof le?(this.v=r,this):new le(r)}function Pr(r,e,t){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var n=t.apply(r,e||[]),o,s=[];return o=Object.create((typeof AsyncIterator=="function"?AsyncIterator:Object).prototype),a("next"),a("throw"),a("return",i),o[Symbol.asyncIterator]=function(){return this},o;function i(d){return function(u){return Promise.resolve(u).then(d,p)}}function a(d,u){n[d]&&(o[d]=function(m){return new Promise(function(w,x){s.push([d,m,w,x])>1||f(d,m)})},u&&(o[d]=u(o[d])))}function f(d,u){try{c(n[d](u))}catch(m){h(s[0][3],m)}}function c(d){d.value instanceof le?Promise.resolve(d.value.v).then(l,p):h(s[0][2],d)}function l(d){f("next",d)}function p(d){f("throw",d)}function h(d,u){d(u),s.shift(),s.length&&f(s[0][0],s[0][1])}}function _r(r){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var e=r[Symbol.asyncIterator],t;return e?e.call(r):(r=typeof ce=="function"?ce(r):r[Symbol.iterator](),t={},n("next"),n("throw"),n("return"),t[Symbol.asyncIterator]=function(){return this},t);function n(s){t[s]=r[s]&&function(i){return new Promise(function(a,f){i=r[s](i),o(a,f,i.done,i.value)})}}function o(s,i,a,f){Promise.resolve(f).then(function(c){s({value:c,done:a})},i)}}function _(r){return typeof r=="function"}function Mr(r){var e=function(n){Error.call(n),n.stack=new Error().stack},t=r(e);return t.prototype=Object.create(Error.prototype),t.prototype.constructor=t,t}var dt=Mr(function(r){return function(t){r(this),this.message=t?t.length+` errors occurred during unsubscription:
|
|
6
|
-
`+t.map(function(n,o){return o+1+") "+n.toString()}).join(`
|
|
7
|
-
`):"",this.name="UnsubscriptionError",this.errors=t}});function tn(r,e){if(r){var t=r.indexOf(e);0<=t&&r.splice(t,1)}}var ut=(function(){function r(e){this.initialTeardown=e,this.closed=!1,this._parentage=null,this._finalizers=null}return r.prototype.unsubscribe=function(){var e,t,n,o,s;if(!this.closed){this.closed=!0;var i=this._parentage;if(i)if(this._parentage=null,Array.isArray(i))try{for(var a=ce(i),f=a.next();!f.done;f=a.next()){var c=f.value;c.remove(this)}}catch(m){e={error:m}}finally{try{f&&!f.done&&(t=a.return)&&t.call(a)}finally{if(e)throw e.error}}else i.remove(this);var l=this.initialTeardown;if(_(l))try{l()}catch(m){s=m instanceof dt?m.errors:[m]}var p=this._finalizers;if(p){this._finalizers=null;try{for(var h=ce(p),d=h.next();!d.done;d=h.next()){var u=d.value;try{kr(u)}catch(m){s=s??[],m instanceof dt?s=be(be([],xe(s)),xe(m.errors)):s.push(m)}}}catch(m){n={error:m}}finally{try{d&&!d.done&&(o=h.return)&&o.call(h)}finally{if(n)throw n.error}}}if(s)throw new dt(s)}},r.prototype.add=function(e){var t;if(e&&e!==this)if(this.closed)kr(e);else{if(e instanceof r){if(e.closed||e._hasParent(this))return;e._addParent(this)}(this._finalizers=(t=this._finalizers)!==null&&t!==void 0?t:[]).push(e)}},r.prototype._hasParent=function(e){var t=this._parentage;return t===e||Array.isArray(t)&&t.includes(e)},r.prototype._addParent=function(e){var t=this._parentage;this._parentage=Array.isArray(t)?(t.push(e),t):t?[t,e]:e},r.prototype._removeParent=function(e){var t=this._parentage;t===e?this._parentage=null:Array.isArray(t)&&tn(t,e)},r.prototype.remove=function(e){var t=this._finalizers;t&&tn(t,e),e instanceof r&&e._removeParent(this)},r.EMPTY=(function(){var e=new r;return e.closed=!0,e})(),r})();var Ji=ut.EMPTY;function mt(r){return r instanceof ut||r&&"closed"in r&&_(r.remove)&&_(r.add)&&_(r.unsubscribe)}function kr(r){_(r)?r():r.unsubscribe()}var K={onUnhandledError:null,onStoppedNotification:null,Promise:void 0,useDeprecatedSynchronousErrorHandling:!1,useDeprecatedNextContext:!1};var Se={setTimeout:function(r,e){for(var t=[],n=2;n<arguments.length;n++)t[n-2]=arguments[n];var o=Se.delegate;return o?.setTimeout?o.setTimeout.apply(o,be([r,e],xe(t))):setTimeout.apply(void 0,be([r,e],xe(t)))},clearTimeout:function(r){var e=Se.delegate;return(e?.clearTimeout||clearTimeout)(r)},delegate:void 0};function gt(r){Se.setTimeout(function(){var e=K.onUnhandledError;if(e)e(r);else throw r})}function nn(){}var Lr=(function(){return rn("C",void 0,void 0)})();function Or(r){return rn("E",void 0,r)}function Tr(r){return rn("N",r,void 0)}function rn(r,e,t){return{kind:r,value:e,error:t}}var pe=null;function Nr(r){if(K.useDeprecatedSynchronousErrorHandling){var e=!pe;if(e&&(pe={errorThrown:!1,error:null}),r(),e){var t=pe,n=t.errorThrown,o=t.error;if(pe=null,n)throw o}}else r()}function Fr(r){K.useDeprecatedSynchronousErrorHandling&&pe&&(pe.errorThrown=!0,pe.error=r)}var Fe=(function(r){Ne(e,r);function e(t){var n=r.call(this)||this;return n.isStopped=!1,t?(n.destination=t,mt(t)&&t.add(n)):n.destination=ys,n}return e.create=function(t,n,o){return new yt(t,n,o)},e.prototype.next=function(t){this.isStopped?sn(Tr(t),this):this._next(t)},e.prototype.error=function(t){this.isStopped?sn(Or(t),this):(this.isStopped=!0,this._error(t))},e.prototype.complete=function(){this.isStopped?sn(Lr,this):(this.isStopped=!0,this._complete())},e.prototype.unsubscribe=function(){this.closed||(this.isStopped=!0,r.prototype.unsubscribe.call(this),this.destination=null)},e.prototype._next=function(t){this.destination.next(t)},e.prototype._error=function(t){try{this.destination.error(t)}finally{this.unsubscribe()}},e.prototype._complete=function(){try{this.destination.complete()}finally{this.unsubscribe()}},e})(ut);var ms=Function.prototype.bind;function on(r,e){return ms.call(r,e)}var gs=(function(){function r(e){this.partialObserver=e}return r.prototype.next=function(e){var t=this.partialObserver;if(t.next)try{t.next(e)}catch(n){wt(n)}},r.prototype.error=function(e){var t=this.partialObserver;if(t.error)try{t.error(e)}catch(n){wt(n)}else wt(e)},r.prototype.complete=function(){var e=this.partialObserver;if(e.complete)try{e.complete()}catch(t){wt(t)}},r})(),yt=(function(r){Ne(e,r);function e(t,n,o){var s=r.call(this)||this,i;if(_(t)||!t)i={next:t??void 0,error:n??void 0,complete:o??void 0};else{var a;s&&K.useDeprecatedNextContext?(a=Object.create(t),a.unsubscribe=function(){return s.unsubscribe()},i={next:t.next&&on(t.next,a),error:t.error&&on(t.error,a),complete:t.complete&&on(t.complete,a)}):i=t}return s.destination=new gs(i),s}return e})(Fe);function wt(r){K.useDeprecatedSynchronousErrorHandling?Fr(r):gt(r)}function ws(r){throw r}function sn(r,e){var t=K.onStoppedNotification;t&&Se.setTimeout(function(){return t(r,e)})}var ys={closed:!0,next:nn,error:ws,complete:nn};var ve=(function(){return typeof Symbol=="function"&&Symbol.observable||"@@observable"})();function qr(r){return r}function $r(r){return r.length===0?qr:r.length===1?r[0]:function(t){return r.reduce(function(n,o){return o(n)},t)}}var j=(function(){function r(e){e&&(this._subscribe=e)}return r.prototype.lift=function(e){var t=new r;return t.source=this,t.operator=e,t},r.prototype.subscribe=function(e,t,n){var o=this,s=bs(e)?e:new yt(e,t,n);return Nr(function(){var i=o,a=i.operator,f=i.source;s.add(a?a.call(s,f):f?o._subscribe(s):o._trySubscribe(s))}),s},r.prototype._trySubscribe=function(e){try{return this._subscribe(e)}catch(t){e.error(t)}},r.prototype.forEach=function(e,t){var n=this;return t=Hr(t),new t(function(o,s){var i=new yt({next:function(a){try{e(a)}catch(f){s(f),i.unsubscribe()}},error:s,complete:o});n.subscribe(i)})},r.prototype._subscribe=function(e){var t;return(t=this.source)===null||t===void 0?void 0:t.subscribe(e)},r.prototype[ve]=function(){return this},r.prototype.pipe=function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];return $r(e)(this)},r.prototype.toPromise=function(e){var t=this;return e=Hr(e),new e(function(n,o){var s;t.subscribe(function(i){return s=i},function(i){return o(i)},function(){return n(s)})})},r.create=function(e){return new r(e)},r})();function Hr(r){var e;return(e=r??K.Promise)!==null&&e!==void 0?e:Promise}function xs(r){return r&&_(r.next)&&_(r.error)&&_(r.complete)}function bs(r){return r&&r instanceof Fe||xs(r)&&mt(r)}function Ss(r){return _(r?.lift)}function Q(r){return function(e){if(Ss(e))return e.lift(function(t){try{return r(t,this)}catch(n){this.error(n)}});throw new TypeError("Unable to lift unknown Observable type")}}function re(r,e,t,n,o){return new vs(r,e,t,n,o)}var vs=(function(r){Ne(e,r);function e(t,n,o,s,i,a){var f=r.call(this,t)||this;return f.onFinalize=i,f.shouldUnsubscribe=a,f._next=n?function(c){try{n(c)}catch(l){t.error(l)}}:r.prototype._next,f._error=s?function(c){try{s(c)}catch(l){t.error(l)}finally{this.unsubscribe()}}:r.prototype._error,f._complete=o?function(){try{o()}catch(c){t.error(c)}finally{this.unsubscribe()}}:r.prototype._complete,f}return e.prototype.unsubscribe=function(){var t;if(!this.shouldUnsubscribe||this.shouldUnsubscribe()){var n=this.closed;r.prototype.unsubscribe.call(this),!n&&((t=this.onFinalize)===null||t===void 0||t.call(this))}},e})(Fe);var xt=(function(r){return r&&typeof r.length=="number"&&typeof r!="function"});function bt(r){return _(r?.then)}function St(r){return _(r[ve])}function vt(r){return Symbol.asyncIterator&&_(r?.[Symbol.asyncIterator])}function It(r){return new TypeError("You provided "+(r!==null&&typeof r=="object"?"an invalid object":"'"+r+"'")+" where a stream was expected. You can provide an Observable, Promise, ReadableStream, Array, AsyncIterable, or Iterable.")}function Is(){return typeof Symbol!="function"||!Symbol.iterator?"@@iterator":Symbol.iterator}var At=Is();function Et(r){return _(r?.[At])}function Ct(r){return Pr(this,arguments,function(){var t,n,o,s;return ht(this,function(i){switch(i.label){case 0:t=r.getReader(),i.label=1;case 1:i.trys.push([1,,9,10]),i.label=2;case 2:return[4,le(t.read())];case 3:return n=i.sent(),o=n.value,s=n.done,s?[4,le(void 0)]:[3,5];case 4:return[2,i.sent()];case 5:return[4,le(o)];case 6:return[4,i.sent()];case 7:return i.sent(),[3,2];case 8:return[3,10];case 9:return t.releaseLock(),[7];case 10:return[2]}})})}function Rt(r){return _(r?.getReader)}function ee(r){if(r instanceof j)return r;if(r!=null){if(St(r))return As(r);if(xt(r))return Es(r);if(bt(r))return Cs(r);if(vt(r))return Gr(r);if(Et(r))return Rs(r);if(Rt(r))return Ps(r)}throw It(r)}function As(r){return new j(function(e){var t=r[ve]();if(_(t.subscribe))return t.subscribe(e);throw new TypeError("Provided object does not correctly implement Symbol.observable")})}function Es(r){return new j(function(e){for(var t=0;t<r.length&&!e.closed;t++)e.next(r[t]);e.complete()})}function Cs(r){return new j(function(e){r.then(function(t){e.closed||(e.next(t),e.complete())},function(t){return e.error(t)}).then(null,gt)})}function Rs(r){return new j(function(e){var t,n;try{for(var o=ce(r),s=o.next();!s.done;s=o.next()){var i=s.value;if(e.next(i),e.closed)return}}catch(a){t={error:a}}finally{try{s&&!s.done&&(n=o.return)&&n.call(o)}finally{if(t)throw t.error}}e.complete()})}function Gr(r){return new j(function(e){_s(r,e).catch(function(t){return e.error(t)})})}function Ps(r){return Gr(Ct(r))}function _s(r,e){var t,n,o,s;return Rr(this,void 0,void 0,function(){var i,a;return ht(this,function(f){switch(f.label){case 0:f.trys.push([0,5,6,11]),t=_r(r),f.label=1;case 1:return[4,t.next()];case 2:if(n=f.sent(),!!n.done)return[3,4];if(i=n.value,e.next(i),e.closed)return[2];f.label=3;case 3:return[3,1];case 4:return[3,11];case 5:return a=f.sent(),o={error:a},[3,11];case 6:return f.trys.push([6,,9,10]),n&&!n.done&&(s=t.return)?[4,s.call(t)]:[3,8];case 7:f.sent(),f.label=8;case 8:return[3,10];case 9:if(o)throw o.error;return[7];case 10:return[7];case 11:return e.complete(),[2]}})})}function Y(r,e,t,n,o){n===void 0&&(n=0),o===void 0&&(o=!1);var s=e.schedule(function(){t(),o?r.add(this.schedule(null,n)):this.unsubscribe()},n);if(r.add(s),!o)return s}function Pt(r,e){return e===void 0&&(e=0),Q(function(t,n){t.subscribe(re(n,function(o){return Y(n,r,function(){return n.next(o)},e)},function(){return Y(n,r,function(){return n.complete()},e)},function(o){return Y(n,r,function(){return n.error(o)},e)}))})}function _t(r,e){return e===void 0&&(e=0),Q(function(t,n){n.add(r.schedule(function(){return t.subscribe(n)},e))})}function Br(r,e){return ee(r).pipe(_t(e),Pt(e))}function Dr(r,e){return ee(r).pipe(_t(e),Pt(e))}function zr(r,e){return new j(function(t){var n=0;return e.schedule(function(){n===r.length?t.complete():(t.next(r[n++]),t.closed||this.schedule())})})}function jr(r,e){return new j(function(t){var n;return Y(t,e,function(){n=r[At](),Y(t,e,function(){var o,s,i;try{o=n.next(),s=o.value,i=o.done}catch(a){t.error(a);return}i?t.complete():t.next(s)},0,!0)}),function(){return _(n?.return)&&n.return()}})}function Mt(r,e){if(!r)throw new Error("Iterable cannot be null");return new j(function(t){Y(t,e,function(){var n=r[Symbol.asyncIterator]();Y(t,e,function(){n.next().then(function(o){o.done?t.complete():t.next(o.value)})},0,!0)})})}function Ur(r,e){return Mt(Ct(r),e)}function Wr(r,e){if(r!=null){if(St(r))return Br(r,e);if(xt(r))return zr(r,e);if(bt(r))return Dr(r,e);if(vt(r))return Mt(r,e);if(Et(r))return jr(r,e);if(Rt(r))return Ur(r,e)}throw It(r)}function an(r,e){return e?Wr(r,e):ee(r)}function qe(r,e){return Q(function(t,n){var o=0;t.subscribe(re(n,function(s){n.next(r.call(e,s,o++))}))})}function Qr(r,e,t,n,o,s,i,a){var f=[],c=0,l=0,p=!1,h=function(){p&&!f.length&&!c&&e.complete()},d=function(m){return c<n?u(m):f.push(m)},u=function(m){s&&e.next(m),c++;var w=!1;ee(t(m,l++)).subscribe(re(e,function(x){o?.(x),s?d(x):e.next(x)},function(){w=!0},void 0,function(){if(w)try{c--;for(var x=function(){var S=f.shift();i?Y(e,i,function(){return u(S)}):u(S)};f.length&&c<n;)x();h()}catch(S){e.error(S)}}))};return r.subscribe(re(e,d,function(){p=!0,h()})),function(){a?.()}}function Ie(r,e,t){return t===void 0&&(t=1/0),_(e)?Ie(function(n,o){return qe(function(s,i){return e(n,s,o,i)})(ee(r(n,o)))},t):(typeof e=="number"&&(t=e),Q(function(n,o){return Qr(n,o,r,t)}))}function Yr(r,e,t,n,o){return function(s,i){var a=t,f=e,c=0;s.subscribe(re(i,function(l){var p=c++;f=a?r(f,l,p):(a=!0,l),n&&i.next(f)},o&&(function(){a&&i.next(f),i.complete()})))}}function Vr(r,e){return Q(Yr(r,e,arguments.length>=2,!1,!0))}var Ms=function(r,e){return r.push(e),r};function kt(){return Q(function(r,e){Vr(Ms,[])(r).subscribe(e)})}function Kr(r){let e=[],t=0,n;for(let o=0,s=r.length;o<s;o++){let i=r.charCodeAt(o);if(i>=48&&i<=57)t=t*10+i-48;else if(i===58)n=t,t=0;else{let a=r[o];a==="M"||a==="="||a==="X"?e.push({own:n===void 0?t:n,mate:t,op:"M"}):a==="I"?e.push({own:0,mate:t,op:a}):(a==="D"||a==="N")&&e.push({own:t,mate:0,op:a}),n=void 0,t=0}}return e}function ln(r){let e="";for(let{own:t,mate:n,op:o}of Kr(r))e+=o==="M"?t===0?`${n}I`:n===0?`${t}D`:`${t}M`:`${o==="I"?n:t}${o}`;return e}var fn=2**28-1;function cn(r,e,t){for(let n=e;n>0;n-=fn)r.push((Math.min(n,fn)<<4|t)>>>0)}function ks(r,e,t){if(e===t)cn(r,e,0);else{let n=Math.ceil(Math.max(e,t)/fn);for(let o=0;o<n;o++){let s=Math.floor(e*(o+1)/n)-Math.floor(e*o/n),i=Math.floor(t*(o+1)/n)-Math.floor(t*o/n);r.push((s<<4|9)>>>0,(i<<4|9)>>>0)}}}function pn(r){let e=[];for(let{own:t,mate:n,op:o}of Kr(r))o==="M"?ks(e,t,n):o==="I"?cn(e,n,1):cn(e,t,o==="N"?3:2);return Uint32Array.from(e)}function Ls(r){return r>=48&&r<=57}function Os(r){return r!==void 0&&/[A-Za-z]/.test(r)}function Xr(r,e){let t=e;for(;t<r.length&&Os(r[t]);)t++;return t}function Zr(r,e){let t=e,n=0;for(;t<r.length&&Ls(r.charCodeAt(t));)n=n*10+(r.charCodeAt(t)-48),t++;return{value:n,next:t}}function ro(r,e){let t=0;for(;t<r.length;){let n=r[t];if(n===":"){let{value:o,next:s}=Zr(r,t+1);e(":",o,o,t+1,s),t=s}else if(n==="="){let o=Xr(r,t+1),s=o-t-1;e("=",s,s,t+1,o),t=o}else if(n==="*")e("*",1,1,t+1,Math.min(t+3,r.length)),t+=3;else if(n==="+"||n==="-"){let o=Xr(r,t+1),s=o-t-1;e(n,n==="-"?s:0,n==="+"?s:0,t+1,o),t=o}else if(n==="~"){let{value:o,next:s}=Zr(r,t+3),i=Math.min(s+2,r.length);e("~",o,0,t+1,i),t=i}else t++}}function hn(r,e,t,n){let o=t??Number.NEGATIVE_INFINITY,s=n??Number.POSITIVE_INFINITY,i=0;ro(r,(a,f,c,l,p)=>{if(a==="*")i>=o&&i<s&&e(88,i,1,r[l+1]??"",-1,0,0);else if(a==="+"){if(i>=o&&i<=s){let h=r.slice(l,p);e(73,i,c,h,-1,0,c)}}else(a==="-"||a==="~")&&i<s&&i+f>o&&e(a==="-"?68:78,i,f,"",-1,0,0);i+=f})}function oo(r,e,t,n){let o=0,s=0,i=[],a=t&&e;for(let f=0,c=r.length;f<c;f++){let l=r[f],p=l>>>4,h=l&15;if(h===0||h===7){if(a)for(let d=0;d<p;d++)(e.charCodeAt(s+d)|32)!==(t.charCodeAt(o+d)|32)&&i.push({start:o+d,type:"mismatch",base:e[s+d],altbase:t[o+d],length:1});s+=p,o+=p}else if(h===1)i.push({start:o,type:"insertion",insertlen:p,insertedBases:e?.slice(s,s+p),length:0}),s+=p;else if(h===2)i.push({start:o,type:"deletion",length:p}),o+=p;else if(h===3)i.push({start:o,type:"skip",length:p}),o+=p;else if(h===8){for(let d=0;d<p;d++)i.push({start:o+d,type:"mismatch",base:e?.[s+d]||"X",qual:n?.[s+d],length:1});s+=p,o+=p}else h===5?i.push({start:o,type:"hardclip",cliplen:p,length:1}):h===4&&(i.push({start:o,type:"softclip",cliplen:p,length:1}),s+=p)}return i}function so(r,e,t,n,o){if(!e)return[];let s=[],i=e.length,a=n.length,f=o!==void 0,c=t.length,l=!1;for(let S=0;S<c;S++)if(t[S].type==="skip"){l=!0;break}let p=0,h=0,d=0,u=0,m=0,w=0,x=r.length;for(;w<x;){let S=r.charCodeAt(w);if(S>=48&&S<=57){let g=0;for(;w<x;){let b=r.charCodeAt(w);if(b>=48&&b<=57)g=g*10+(b-48),w++;else break}p+=g}else if(S===94)for(w++;w<x&&r.charCodeAt(w)>=65;)w++,p++;else if(S>=65){let g=r[w];if(w++,l&&c>0)for(let R=m;R<c;R++){let C=t[R];C.type==="skip"&&p>=C.start&&(p+=C.length,m=R+1)}let b=d,y=u;for(let R=h;R<i&&y<=p;R++,h=R){let C=e[R],P=C>>>4,E=C&15;E===4||E===1?b+=P:E===2||E===6||E===3?y+=P:E!==5&&(b+=P,y+=P)}d=b,u=y;let v=b-(y-p),I=v<a?n[v]:"X";s.push({start:p,base:I,qual:f?o[v]:void 0,altbase:g,length:1,type:"mismatch"}),p++}else w++}return s}var io={77:0,73:1,68:2,78:3,83:4,72:5,80:6,61:7,88:8};function ao(r=""){let e=0,t=[];for(let n=0,o=r.length;n<o;n++){let s=r.charCodeAt(n);if(s>=48&&s<=57)e=e*10+(s-48);else{let i=io[s];t.push(e<<4|i),e=0}}return t}function mn(r=""){let e=0;for(let s=0,i=r.length;s<i;s++){let a=r.charCodeAt(s);(a<48||a>57)&&e++}let t=new Uint32Array(e),n=0,o=0;for(let s=0,i=r.length;s<i;s++){let a=r.charCodeAt(s);a>=48&&a<=57?n=n*10+(a-48):(t[o++]=n<<4|io[a],n=0)}return t}function Ft(r,e,t,n,o){let s=ao(r),i=r?oo(s,t,n,o):[];return e&&t?i.concat(so(e,s,i,t,o)):i}var Fs=397,qs=387,$s=385;function fo(r){return(1<<r&Fs)!==0}function co(r){return(1<<r&qs)!==0}function lo(r){return(1<<r&$s)!==0}function gn(r,e,t,n,o,s,i){let a=o===-1?-1:1,f=e,c=o===-1?n:t,l=[],p=1/0,h=-1/0,d=1/0,u=-1/0,m=(w,x)=>{d=Math.min(d,w,x),u=Math.max(u,w,x)};for(let w=0;w<r.length;w++){let x=r[w],S=x>>>4,g=x&15,b=g===9,y=b||fo(g)?S:0,v=b?r[++w]>>>4:co(g)?S:0,I=f+y,R=c+v*a,C=f,P=I;if(P>=s&&C<=i)if(y>0){let E=Math.max(C,s),M=Math.min(P,i);if(M>E)if(p=Math.min(p,E),h=Math.max(h,M),b){let L=v/S,N=M-E,F=Math.round(N*L),q=Math.round(c+(E-f)*L*a);l.push(N<<4|9,F<<4|9),m(q,q+F*a)}else l.push(M-E<<4|g),lo(g)?m(c+(E-f)*a,c+(M-f)*a):m(c,c)}else v>0&&(b?l.push(x,r[w]):l.push(x),p=Math.min(p,f),h=Math.max(h,f),m(c,R));if(f=I,c=R,f>i)break}if(l.length!==0)return{start:p,end:h,mateStart:d,mateEnd:u,cigar:Uint32Array.from(l)}}function Hs(r){return r===1||r===2||r===3}function wn(r,e,t,n,o,s){let i=o===-1?-1:1,a=[],f=e,c=o===-1?n:t,l,p=!1,h=()=>{l!==void 0&&p&&l.qHi>l.qLo&&a.push({start:l.qLo,end:l.qHi,mateStart:l.tLo,mateEnd:l.tHi,cigar:Uint32Array.from(l.ops)}),l=void 0,p=!1};for(let d=0;d<r.length;d++){let u=r[d],m=u>>>4,w=u&15,x=w===9,S=x?r[++d]:void 0,g=x||fo(w)?m:0,b=S!==void 0?S>>>4:co(w)?m:0,y=c+b*i;Hs(w)&&m>=s?h():(g>0||b>0)&&(l===void 0&&(l={qLo:f,qHi:f,tLo:c,tHi:c,ops:[]}),l.qHi=f+g,l.tLo=Math.min(l.tLo,c,y),l.tHi=Math.max(l.tHi,c,y),l.ops.push(u),S!==void 0&&l.ops.push(S),p=p||x||lo(w)),f+=g,c=y}return h(),a}function po(r){let e=r.get("CIGAR");return typeof e=="string"?e:void 0}function ho(r){let e=r.get("coarseCigar");return typeof e=="string"?e:void 0}function yn(r){let e=po(r),t=e===void 0?ho(r):void 0;return e!==void 0?mn(e):t!==void 0?pn(t):void 0}var Gs=W(Ce(),1),Bs=W(mo(),1);var Ds=W(Ce(),1);var zs=W(Eo(),1);var go=W(Ce(),1),se=class extends go.SimpleFeature{get(e){return e==="mismatches"?Ft(this.walkableCigar):e==="clipLengthAtStartOfRead"?this.clipLengthAtStartOfRead:e==="name"?super.get("name")??this.mate?.refName:super.get(e)}get mate(){return super.get("mate")}get walkableCigar(){let e=super.get("CIGAR"),t=super.get("coarseCigar");return typeof e=="string"?e:typeof t=="string"?ln(t):void 0}get clipLengthAtStartOfRead(){return this.mate?.start??0}forEachMismatch(e,t){let n=this.get("start"),o=t?.start===void 0?void 0:t.start-n,s=t?.end===void 0?void 0:t.end-n,i=this.get("cs");if(i)hn(i,e,o,s);else{let a=o??Number.NEGATIVE_INFINITY,f=s??Number.POSITIVE_INFINITY;for(let c of Ft(this.walkableCigar))(c.type==="deletion"||c.type==="skip"?c.start<f&&c.start+c.length>a:c.start>=a&&c.start<=f)&&(c.type==="mismatch"?e(88,c.start,c.length,c.base,c.qual??-1,0,0):c.type==="insertion"?e(73,c.start,c.length,c.insertedBases??"",-1,0,c.insertlen):c.type==="deletion"?e(68,c.start,c.length,"",-1,0,0):c.type==="skip"&&e(78,c.start,c.length,"",-1,0,0))}}};var js=["CIGAR","cs","coarseCigar","cg","cr"];function Us(r){return typeof r=="object"&&r!==null&&"refName"in r&&"start"in r&&"end"in r&&typeof r.refName=="string"&&typeof r.start=="number"&&typeof r.end=="number"}function Ws(r){let e=r.get("mate");return Us(e)?e:void 0}function Qs(r,e,t,n){let o=Math.max(r.start,n.start),s=Math.min(r.end,n.end),i=(e.end-e.start)/Math.max(r.end-r.start,1),a=l=>t===-1?e.end-(l-r.start)*i:e.start+(l-r.start)*i,f=Math.round(a(o)),c=Math.round(a(s));return s>o?{start:o,end:s,mateStart:Math.min(f,c),mateEnd:Math.max(f,c)}:void 0}function Ys(r,e,t,n,o){let s={start:r.get("start"),end:r.get("end")},i=r.get("strand")===-1?-1:1,a=s.start>=t.start&&s.end<=t.end,f=a&&n===void 0&&!o?void 0:yn(r);if(f===void 0){let c=a?{...s,mateStart:e.start,mateEnd:e.end}:Qs(s,e,i,t);return c===void 0?[]:[c]}else return(n===void 0?[{...s,mateStart:e.start,mateEnd:e.end,cigar:f}]:wn(f,s.start,e.start,e.end,i,n)).flatMap(l=>{let p=gn(l.cigar,l.start,l.mateStart,l.mateEnd,i,t.start,t.end);return p===void 0?[]:[p]})}function Vs(r,e,t,n,o,s){let i=`:${n.start}-${n.end}${o}`,a=r.toJSON(),f={...a,uniqueId:`${r.id()}${i}`,start:t.start,end:t.end,mate:{...e,start:t.mateStart,end:t.mateEnd}};a.syntenyId!==void 0&&(f.syntenyId=`${String(a.syntenyId)}${i}`);for(let c of js)delete f[c];return s&&t.cigar&&(f.alignmentOps=t.cigar),new se(f)}function wo(r,e,t,n=!1){let o=Ws(r);if(o===void 0)return[r];{let s=Ys(r,o,e,t,n);return s.map((i,a)=>Vs(r,o,i,e,s.length>1?`/${a}`:"",n))}}var qt=class extends yo.BaseFeatureDataAdapter{constructor(){super(...arguments);this.recordsAreAlignments=!0}static{this.capabilities=["getFeatures","getRefNames"]}async hasDataForRefName(){return!0}getFeaturesInMultipleRegions(t,n={}){let{clipToRegion:o,splitAtGapBp:s,keepAlignment:i,...a}=n,f=o&&this.recordsAreAlignments,c=(0,xo.createStatusFanOut)(a.statusCallback);return an(t).pipe(Ie((l,p)=>this.getFeatures(l,{...a,statusCallback:c()}).pipe(Ie(h=>f?wo(h,h.get("assemblyName")===l.assemblyName?l:{start:h.get("start"),end:h.get("end")},s,i):[h]),kt(),qe(h=>({index:p,features:h})))),kt(),Ie(l=>l.sort((p,h)=>p.index-h.index).flatMap(p=>p.features)))}};var vn=class extends Error{constructor(){super("no haplotype index is set, so the walks cannot be named; build one with gbz-haplotype-index (cargo install gbz-haplotype-index) and set it as haplotypeIndexLocation");this.name="NoHaplotypeIndexError"}},In=class extends Error{constructor(t){super(`a pair query names both lanes: queryAssemblyName ${t} came without a targetAssemblyName`);this.name="PairTargetError"}},An=class extends Error{constructor(t,n){super(`the graph is cut on its reference, ${n}; a window on ${t} has no reference coordinates to cut at. Open the graph from a ${n} view, and find this haplotype's lane there`);this.name="HaplotypeWindowError"}};function bo(r,e){let t=J(e);return r[t]??r[e.sample]??t}function Ks(r,e){return`${J(r)}#${r.contig}@${e.start.node}.${e.start.offset}`}function Xs({alignment:r,assemblyName:e,refName:t,lane:n}){let{refStart:o,refEnd:s,strand:i,cigar:a}=r;if(!(!r.resolved||s<=o)){let{name:f,hapStart:c,hapEnd:l}=r,p=Ks(f,r),h={uniqueId:p,assemblyName:e,refName:t,start:o,end:s,type:"match",strand:i==="-"?-1:1,CIGAR:a,syntenyId:p,mate:{refName:f.contig,start:c,end:l,assemblyName:n}};return new se(h)}}function Zs({pair:r,lane:e,mateLane:t}){let n=`${J(r.target)}#${r.target.contig}:${r.targetStart}-${r.targetEnd}|${J(r.query)}#${r.query.contig}:${r.queryStart}-${r.queryEnd}`;return new se({uniqueId:n,assemblyName:e,refName:r.target.contig,start:r.targetStart,end:r.targetEnd,type:"match",strand:r.strand==="-"?-1:1,CIGAR:r.cigar,syntenyId:n,identity:r.matches/Math.max(r.columns,1),numMatches:r.matches,blockLen:r.columns,mate:{refName:r.query.contig,start:r.queryStart,end:r.queryEnd,assemblyName:t}})}var xn=r=>!("uri"in r)||r.uri!=="",En=class extends qt{constructor(){super(...arguments);this.graph=(0,bn.cachedSetup)({label:"Opening pangenome database",setup:async()=>{let t=this.getConf("gbzDbLocation"),n=this.getConf("haplotypeIndexLocation"),o=xn(n)?n:await Er(t,this.pluginManager),s=await Oe.open((0,Ae.openLocation)(t,this.pluginManager),o?{haplotypeIndex:(0,Ae.openLocation)(o,this.pluginManager)}:{}),i=this.getConf("assemblyNames")[0];if(i===void 0)throw new Error("GbzBaseSyntenyAdapter needs assemblyNames: its first entry is the assembly the reference sample is loaded as");let a=await br(s),f=Zt({configured:this.getConf("referenceSample"),anchorPrefix:me(this,i),referenceSamples:a});return{db:s,anchor:i,referenceSample:f,referenceSamples:a}}});this.gaf=(0,bn.cachedSetup)({label:"Opening reads",setup:async()=>{let t=this.getConf("readsLocation"),n=this.getConf(["readsIndex","location"]),o=this.pluginManager;if(!xn(t))return;let s=(0,Ae.openLocation)(t,o);return new pt(s,xn(n)?new Rn({filehandle:s,...(0,Ae.openTabixIndexFilehandle)(n,this.getConf(["readsIndex","indexType"]),o)}):void 0)}})}async referenceQuery(t,n){let{db:o,referenceSample:s}=await this.graph(n);return Sr(o,s,t)}async getHaplotypes(t={}){let{db:n,referenceSamples:o}=await this.graph(t),s=new Map;for(let i of await n.paths()){let a=J(i.name),f=s.get(a);f?f.contigs.includes(i.name.contig)||f.contigs.push(i.name.contig):s.set(a,{prefix:a,sample:i.name.sample,haplotype:i.name.haplotype,contigs:[i.name.contig],isReference:o.includes(i.name.sample)})}return[...s.values()]}async getHeader(t={}){let{anchor:n,referenceSample:o,referenceSamples:s}=await this.graph(t),i=$t(this),a=[];for(let f of await this.getHaplotypes(t))f.sample!==o&&a.push({name:bo(i,f),label:f.prefix,group:f.sample});return{hasCoarseTier:!1,anchorAssemblyName:n,referenceSample:o,referenceSamples:s,lanes:a}}async getRefNames(t={}){let{db:n,anchor:o,referenceSample:s}=await this.graph(t),{assemblyName:i}=t,a=i===o?void 0:me(this,i),f=(await n.paths()).filter(c=>i===o?c.isIndexed&&c.name.sample===s:ue(J(c.name),a)).map(c=>c.name.contig);return[...new Set(f)]}keepPredicate(t,n){let o=t===void 0||t.length===0?void 0:t.map(s=>me(this,s));return o===void 0&&n===void 0?void 0:s=>xr(s,o)&&(n===void 0||ue(J(s),n))}async getSubgraph(t,n={}){let{db:o,anchor:s}=await this.graph(),{assemblyName:i,refName:a,start:f,end:c}=t;if(i!==s)throw new An(i,s);let l=await this.referenceQuery(a,{}),p=this.keepPredicate(n.haplotypes);return vr(o,l,f,c,{context:this.getConf("context"),snarls:this.getConf("subgraphSnarls"),limit:this.getConf("nodeLimit"),signal:n.signal,...p===void 0?{}:{keep:p}})}async getReads(t,n={}){let o=await this.gaf(n);return o?o.readsOver(new Set(t),n):{records:[],total:0}}async laneHaplotypes(t,n){let o=me(this,t);return(await this.getHaplotypes(n)).filter(s=>ue(s.prefix,o))}async referencePieces(t,n,o,s){let{db:i,referenceSample:a}=await this.graph(s),f=(await i.paths()).filter(l=>l.isIndexed&&l.name.sample===a&&l.name.contig===t&&l.name.fragment>n&&l.name.fragment<o).map(l=>l.name.fragment),c=[n,...[...new Set(f)].sort((l,p)=>l-p),o];return c.slice(1).map((l,p)=>({start:c[p],end:l}))}async anchorFeatures(t,n){let{db:o}=await this.graph(n),{assemblyName:s,refName:i,start:a,end:f}=t,c=me(this,n.targetAssemblyName),l=$t(this),p=this.keepPredicate(n.haplotypes,c),h=await this.referenceQuery(i,n),d=this.getConf("nodeLimit");return(h?await(0,Sn.updateStatus)(`Reading graph ${i}:${a.toLocaleString()}-${f.toLocaleString()}`,n.statusCallback,()=>o.getAlignmentsForRange(h,a,f,{context:this.getConf("context"),haplotypes:"all",limit:d,signal:n.signal,...p===void 0?{}:{keep:p}}).catch(m=>{throw Te(m,d,f-a)??m})):[]).flatMap(m=>{let w=m.resolved?Xs({alignment:m,assemblyName:s,refName:i,lane:bo(l,m.name)}):void 0;return w===void 0?[]:[w]})}async pairFeatures(t,n,o){let{targetAssemblyName:s}=o;if(s===void 0)throw new In(n);let{db:i}=await this.graph(o),{refName:a,start:f,end:c}=t,l=await this.laneHaplotypes(n,o),p=await this.laneHaplotypes(s,o),h=[...l,...p],d=await this.referenceQuery(a,o),u=this.getConf("nodeLimit"),m=await i.haplotypeAnchorSpacing()!==void 0,w=(g,b)=>i.getSubgraphForRange(g,b.start,b.end,{context:this.getConf("context"),haplotypes:"all",limit:u,signal:o.signal,keep:y=>h.some(v=>v.sample===y.sample&&v.haplotype===y.haplotype)}).catch(y=>{throw Te(y,u,c-f)??y}),x=d&&m&&l.length>0&&p.length>0?(await(0,Sn.updateStatus)(`Reading ${n} against ${s}`,o.statusCallback,async()=>Promise.all((await this.referencePieces(a,f,c,o)).map(g=>w(d,g))))).filter(g=>g!==void 0):[];return x.every(g=>{let b=g.stats.anchorWalk;return b!==void 0&&b.fallback===void 0})?x.flatMap(g=>l.flatMap(b=>p.flatMap(y=>g.pairAlignments({target:b,query:y,bases:!1}).map(v=>Zs({pair:v,lane:n,mateLane:s}))))):[]}getFeatures(t,n={}){return(0,So.ObservableCreate)(async o=>{let{db:s,anchor:i}=await this.graph(n);if(!s.hasHaplotypeIndex)throw new vn;if(t.assemblyName===i){let a=n.queryAssemblyName===void 0?await this.anchorFeatures(t,n):await this.pairFeatures(t,n.queryAssemblyName,n);for(let f of a)o.next(f)}o.complete()},n.signal)}};export{An as HaplotypeWindowError,vn as NoHaplotypeIndexError,ct as NoReferenceSampleError,lt as NodeLimitError,In as PairTargetError,En as default,Xs as fragmentFeature,J as haplotypePrefix,bo as laneAssemblyName,Te as nodeLimitError,Zs as pairFeature,Zt as resolveReferenceSample};
|
|
8
|
-
//# sourceMappingURL=GbzBaseSyntenyAdapter-5ZQ2IPHJ.js.map
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import{a as g}from"./chunk-WETM2CD7.js";import{H as f}from"./chunk-ADEBM7AA.js";import"./chunk-MUK3KYB4.js";import{a as l,b as m,c as y,e as x}from"./chunk-XEJ47DLD.js";import{b as o}from"./chunk-FY3BTKY4.js";var a=o(y(),1),b=o(m(),1),S=o(f(),1),n=o(l(),1),L=(0,S.makeStyles)()({section:{marginBottom:24},formControl:{minWidth:200}}),w=[{value:0,label:"None"},{value:1,label:"1 hop"},{value:2,label:"2 hops"}],k=(0,b.observer)(function({model:e}){let{classes:t}=L();return(0,n.jsxs)("div",{className:t.section,children:[(0,n.jsxs)(a.FormControl,{className:t.formControl,children:[(0,n.jsx)(a.InputLabel,{children:"Graph context"}),(0,n.jsx)(a.Select,{value:e.subgraphContext,label:"Graph context","data-testid":"graph-context-select",onChange:p=>{e.setSubgraphContext(p.target.value),e.cut()},children:w.map(({value:p,label:u})=>(0,n.jsx)(a.MenuItem,{value:p,children:u},p))})]}),(0,n.jsx)(a.Typography,{variant:"caption",color:"text.secondary",children:"How far the cut follows links out of the region, one hop by default. A detour that leaves the reference before the window and rejoins after it is indexed under its own sequence, so at none its middle is missing and the one bubble draws as two unrelated stubs. Each hop costs a query per off-reference segment already reached."})]})}),v=k;var C=o(x(),1),d=o(y(),1),c=o(m(),1),G=o(f(),1),i=o(l(),1),T=(0,G.makeStyles)()({section:{marginBottom:24}});function M(r){let e=r.split(/[\s,]+/).map(t=>t.trim()).filter(t=>t!=="");return e.length===0?void 0:e}var F=(0,c.observer)(function({model:e}){let[t,p]=(0,C.useState)(e.chosenHaplotypes?.join(", ")??""),u=()=>{let s=M(t)??[];s.join(`
|
|
2
|
-
`)===(e.chosenHaplotypes??[]).join(`
|
|
3
|
-
`)||(e.setSubgraphHaplotypes(s),e.cut())};return(0,i.jsx)(d.TextField,{fullWidth:!0,label:"Haplotypes",placeholder:"every haplotype",value:t,slotProps:{htmlInput:{"data-testid":"graph-haplotypes-field"}},onChange:s=>{p(s.target.value)},onBlur:()=>{u()},onKeyDown:s=>{s.key==="Enter"&&u()}})}),N=(0,c.observer)(function({model:e}){let{classes:t}=T();return e.adapterConfig.type==="GbzBaseSyntenyAdapter"?(0,i.jsxs)("div",{className:t.section,children:[(0,i.jsx)(F,{model:e},e.chosenHaplotypes?.join(",")??""),(0,i.jsx)(d.Typography,{variant:"caption",color:"text.secondary",children:"The haplotypes the cut is for, as lane assembly names or PanSN prefixes (HG002#1, or HG002 for both), separated by commas. The cut keeps their walks and the nodes those walks visit, with the reference. Empty is every haplotype."})]}):null}),H=N;var h=o(l(),1);function B({model:r,open:e,onClose:t}){return(0,h.jsxs)(g,{model:r,open:e,onClose:t,children:[(0,h.jsx)(v,{model:r}),(0,h.jsx)(H,{model:r})]})}export{B as default};
|
|
4
|
-
//# sourceMappingURL=GraphTrackSettingsDialog-LZITZ3VD.js.map
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{a as i}from"./chunk-LBHU3DHN.js";import"./chunk-J7CABMMI.js";import"./chunk-VAGPKHHS.js";import"./chunk-SCMIJAAX.js";import"./chunk-FCWXYIFC.js";import"./chunk-WETM2CD7.js";import"./chunk-ADEBM7AA.js";import"./chunk-MUK3KYB4.js";import{a as e,b as d}from"./chunk-XEJ47DLD.js";import{a as h,b as t}from"./chunk-FY3BTKY4.js";var p=h((l,o)=>{o.exports=JBrowseExports["@jbrowse/display-kit/DisplayChrome"]});var s=t(p(),1),n=t(d(),1);var r=t(e(),1),y=(0,n.observer)(function({model:a}){return(0,r.jsx)(s.DisplayStatusChrome,{model:a,phase:a.displayPhase,drawn:a.painted&&a.geometryPainted,testid:"linear-graph-display","data-layout":a.chosenLayoutMode,"data-cut-tier":a.cutTier,"data-recuts":a.recuts,"data-node-count":a.hasGraph?a.nodeCount:void 0,"data-loading":a.isLoading?"":void 0,style:{width:a.paneWidth,height:a.height,overflow:"hidden"},children:(0,r.jsx)(i,{model:a,ownChrome:!1})})}),c=y;export{c as default};
|
|
2
|
-
//# sourceMappingURL=LinearGraphDisplay-J3KVTK4C.js.map
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{a as l}from"./chunk-MUK3KYB4.js";import{a as g}from"./chunk-FY3BTKY4.js";var X=g((Ae,N)=>{N.exports=JBrowseExports["tss-react/mui"]});function j(e,t){return Math.max(e.nodeLengthPerMegabase*t/1e6,e.minimumNodeLength)}function b(e,t=5){let r=e.nodes.reduce((a,s)=>a+s.length,0)/1e6,o=Math.max(e.nodes.length*40,500);return{nodeLengthPerMegabase:r>0?o/r:1e4,minimumNodeLength:Math.max(5,t),edgeLength:5,nodeSegmentLength:20}}var d={power:1,effect:1};function E(e){return e.power===1&&e.effect===1}function x(e,t){let n=e.nodes.length,r=e.nodes.reduce((s,i)=>s+i.length,0),o=n>0?r/n:0,a=n>0?Math.max(n*40,500)/n:40;return s=>{if(o<=0)return a;let i=(s/o)**t.power;return Math.max(a*((i-1)*t.effect+1),5)}}var u=1e3,L={law:d,minNodeLength:0};function q(e,t=L){let{law:n,minNodeLength:r}=t,o=b(e,r);if(E(n))return{nodes:e.nodes,opts:o};let a=x(e,n);return{nodes:e.nodes.map(s=>({...s,length:Math.round(a(s.length)*u)})),opts:{...o,nodeLengthPerMegabase:1e6/u,minimumNodeLength:5}}}var m=[{value:"auto",label:"Proportional",description:"Bandage's own scale: a node draws proportional to its length, so a 1 bp allele is a speck.",law:d,minNodeFactor:0},{value:"open",label:"Open bubbles",description:"Give every allele a drawn length, so a bubble reads as two arms rather than a knot.",law:d,minNodeFactor:2.5},{value:"wide",label:"Wide bubbles",description:"As open, spread further. Best on a window of a dozen bubbles.",law:d,minNodeFactor:10},{value:"compress",label:"Compress lengths",description:"Pull the longest and shortest nodes towards the graph\u2019s mean, so a cut spanning kb and bp fits one pane.",law:{power:.5,effect:.5},minNodeFactor:0}],Y=m.map(e=>e.value);function Q(e){let t=m.find(n=>n.value===e);return{law:t?.law??d,minNodeLength:(t?.minNodeFactor??0)*40}}var A=[{value:"auto",label:"Auto"},{value:"uniform",label:"Uniform"},{value:"random",label:"Random"},{value:"rainbow",label:"Rainbow"},{value:"depth",label:"Depth"},{value:"node-length",label:"Node Length"},{value:"stable-rank",label:"Stable rank"},{value:"reference-position",label:"Reference position"},{value:"grey",label:"Grey"}],ee=A.map(e=>e.value);function te(e,t){return e!=="auto"?e:t?.anchoredBy?"reference-position":"uniform"}function re(e){return e.stable!==void 0}function G(e){return e.stable?.rank===0}function oe(e){return e.stable!==void 0&&e.stable.rank>0}function ae(e){return e.nodes.filter(G)}function se(e){let t={};for(let n of e)t[n.id]=[{x:n.stable.start,y:0},{x:n.stable.start+n.length,y:0}];return t}function ie(e,t){let n=0,r=e.length;for(;n<r;){let o=n+r>>1;e[o].stable.start<t?n=o+1:r=o}return n}function S(e){let t=1/0,n=-1/0;for(let r of e)t=Math.min(t,r.stable.start),n=Math.max(n,r.stable.start+r.length);return n-t}function de(e,t){return t&&t.end>t.start?t.end-t.start:S(e)}var M=/:(\d+)-\d+$/;function p(e){let t=M.exec(e);return t?{name:e.slice(0,t.index),start:+t[1]}:{name:e,start:0}}function le(e,t){let n=[],r=new Map;for(let o of e){let a=l(o.name),s=o.start;for(let i of o.steps){let c={path:o.name,sample:a,start:s,strand:i.strand},h=r.get(i.id);h?h.push(c):r.set(i.id,[c]),s+=t(i.id)}n.push({name:o.name,sample:a,start:o.start,length:s-o.start})}return{anchorPaths:n,pathVisits:r}}function w(e,t){return e.find(r=>r.sample===t||r.name===t)??e[0]}var y=1;function P(e,t,n){let r=e;if(t&&t.length>0){let o=t.find(a=>a.path===n)??t[0];r={...e,stable:{refName:o.path,start:o.start,rank:o.path===n?0:y,strand:o.strand},samples:[...new Set(t.map(a=>a.sample))].sort()}}return r}function R(e,t){let{anchorPaths:n,pathVisits:r}=e,o=n&&r?w(n,t):void 0;return o&&r?{...e,nodes:e.nodes.map(a=>P(a,r.get(a.name),o.name)),anchoredBy:"paths",referencePath:o.name}:e}function ue(e,t){return e.anchoredBy==="tags"?e:R(e,t)}function Ne(e){let t=0;for(let n=0;n<e.length;n++)t=e.charCodeAt(n)+((t<<5)-t);return Math.abs(t%360)}function T(e,t){return e*360/t}var D=.7,H=.5,I=16;function ge(e){return e>0&&e<=I}function B(e,t){return`hsl(${T(e,t)}, ${D*100}%, ${H*100}%)`}function v(e){let t=p(e).name.split("#");return[t[0],t.slice(0,2).join("#"),t.join("#")]}function C(e){return String(e).replace(/\B(?=(\d{3})+$)/g,",")}function F(e,t){let{start:n}=p(e);return t.map(r=>`${r} @${C(n)}`)}function be(e){let t=e.map(a=>v(a.name)),n=[0,1,2].flatMap(a=>[e.map((s,i)=>t[i][a]),e.map((s,i)=>F(s.name,t[i])[a])]),o=n.find(a=>new Set(a).size===e.length)??n.at(-1);return e.map((a,s)=>({name:a.name,label:o[s],color:B(s,e.length)}))}var U=[{value:"depth",label:"By depth",description:"Thicker the more paths carry a node, on the square root of its depth against the mean. A graph with one depth everywhere draws uniform."},{value:"uniform",label:"Uniform",description:"Every node the same thickness."}],xe=U.map(e=>e.value),k=.3,f=3;function W(e){let t=0,n=0;for(let r of e.nodes)t+=r.depth*r.length,n+=r.length;return n>0?t/n:0}function V(e,t){return!(t>0)||!(e.depth>0)?1:Math.min(f,Math.max(k,Math.sqrt(e.depth/t)))}function $(e,t,n,r){return t*(n==="depth"?V(e,r):1)}function K(e,t){return e*(t==="depth"?f:1)}function Le(e,t,n,r){let o=e?W(e):0;return{maxHalfWidthPx:K(n,r)/2,halfWidthPx:a=>{let s=t?.get(a);return s?$(s,n,r,o)/2:n/2}}}export{re as a,G as b,oe as c,ae as d,se as e,ie as f,S as g,de as h,j as i,q as j,m as k,Y as l,Q as m,A as n,ee as o,te as p,p as q,le as r,R as s,ue as t,Ne as u,T as v,D as w,H as x,I as y,ge as z,B as A,be as B,U as C,xe as D,W as E,$ as F,Le as G,X as H};
|
|
2
|
-
//# sourceMappingURL=chunk-ADEBM7AA.js.map
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["global-externals:tss-react/mui", "../../packages/core/src/layout/drawnScale.ts", "../../packages/core/src/bubbleSpreads.ts", "../../packages/core/src/colorSchemes.ts", "../../packages/core/src/anchoredNodes.ts", "../../packages/core/src/pathAnchoring.ts", "../../packages/core/src/pathColors.ts", "../../packages/core/src/nodeWidths.ts"],
|
|
4
|
-
"sourcesContent": ["module.exports = JBrowseExports[\"tss-react/mui\"];", "import type { Graph, GraphNode } from '../types'\n\nexport interface BandageScaleOpts {\n nodeLengthPerMegabase: number\n minimumNodeLength: number\n nodeSegmentLength: number\n edgeLength: number\n}\n\n// Node drawn length, in FMMM units, as a function of bp. Used both by the layouts\n// that run here and by the options handed to the WASM engine, so a graph is drawn\n// at the same scale whichever one draws it. Bandage's own auto rule\n// (`AssemblyGraph::determineGraphInfo`):\n// pick units-per-megabase so the *mean* drawn node length lands on 40, with a\n// floor on total drawn length so a small graph doesn't collapse to a speck.\n//\n// This has to be derived per graph, not fixed. The scale that suits a bacterial\n// assembly's 10-100 kb contigs is wrong by orders of magnitude for a minigraph\n// pangenome window, whose nodes run 300 bp to a few kb: a fixed 1000 units/Mbp\n// makes every node shorter than the edges between them and the graph reads as\n// beads on a string, while 1 unit/bp makes each node a long sweeping curve and\n// the graph sprawls. For the 53-node E. coli window this lands near 35,000.\n//\n// It matters most at the small end. The WASM wrapper's own default of 1000\n// units/Mbp puts *every* node in a 400 bp pggb window below minimumNodeLength,\n// so all 31 clamp to the floor and a 1 bp SNP allele draws the same size as the\n// 164 bp backbone segment beside it \u2014 which is what made that figure read as a\n// chain of same-sized two-node bubbles. Bandage draws the same file with a 75:1\n// length ratio, the SNP alleles as specks.\n//\n// The remaining three are upstream Bandage's shipped defaults\n// (`program/settings.cpp`), which the WASM wrapper's own header does not match \u2014\n// it defaults all of them to 1.0, so they have to be passed explicitly.\nconst MEAN_NODE_LENGTH = 40\nconst MIN_TOTAL_GRAPH_LENGTH = 500\n\n// Bandage's own floor on a node's drawn length. Right for an assembly graph,\n// whose nodes are kb to Mb, and the reason a variation graph draws as a rope:\n// see BUBBLE_SPREADS, which is how a view asks for more.\nconst BANDAGE_MINIMUM_NODE_LENGTH = 5\n\n// The engine's own rule (`settings.h`, `getDrawnNodeLength`), so a seed computed\n// here spans exactly the chain the engine builds from the same numbers.\nexport function drawnNodeLength(opts: BandageScaleOpts, length: number) {\n return Math.max(\n (opts.nodeLengthPerMegabase * length) / 1_000_000,\n opts.minimumNodeLength,\n )\n}\n\nexport function bandageAutoScale(\n graph: Graph,\n // Floor on a node's drawn length, in the same FMMM units as the scale below.\n // Anything at or under Bandage's own floor leaves the drawing exactly as it\n // was, which is what keeps `'auto'` byte-identical to the shipped behaviour.\n minNodeLength = BANDAGE_MINIMUM_NODE_LENGTH,\n): BandageScaleOpts {\n const totalLength = graph.nodes.reduce((sum, n) => sum + n.length, 0)\n const megabases = totalLength / 1_000_000\n const target = Math.max(\n graph.nodes.length * MEAN_NODE_LENGTH,\n MIN_TOTAL_GRAPH_LENGTH,\n )\n return {\n nodeLengthPerMegabase: megabases > 0 ? target / megabases : 10_000,\n minimumNodeLength: Math.max(BANDAGE_MINIMUM_NODE_LENGTH, minNodeLength),\n edgeLength: 5,\n nodeSegmentLength: 20,\n }\n}\n\n// How a node's bp becomes its drawn length, as a power law against the graph's\n// own mean. The idiom is Bandage's, moved onto the axis a pangenome needs it on:\n// upstream derives a node's *width* from its depth exactly this way\n// (`graph/graphicsitemnode.cpp`, `getNodeWidth`), at a `depthPower` of 0.5 and a\n// `depthEffectOnWidth` of 0.5, because depth in an assembly graph spans orders\n// of magnitude and drawing it linearly is unreadable.\n//\n// drawn = meanDrawn * (((bp / meanBp) ^ power - 1) * effect + 1)\n//\n// Length in a *variation* graph spans those same orders of magnitude \u2014 a 1 bp\n// allele beside a 16 kb backbone segment \u2014 and upstream still maps it linearly,\n// because its own nodes are assembled contigs where that range does not arise.\n// That linear map is what draws a pggb window as one rope: past the small end\n// every allele falls under `minimumNodeLength` and clamps, so both arms of a\n// bubble land inside one node thickness of each other.\n//\n// power 1 with effect 1 is exactly proportional, so Bandage's shipped behaviour\n// is a point in this family rather than a mechanism sitting beside it. See\n// BUBBLE_SPREADS for the points a view can ask for.\nexport interface DrawnLengthLaw {\n // exponent applied to a node's length relative to the graph's mean\n power: number\n // how much of that relative length survives. 0 draws every node at the mean,\n // 1 applies the power law undamped.\n effect: number\n}\n\nexport const PROPORTIONAL_LENGTH: DrawnLengthLaw = { power: 1, effect: 1 }\n\nexport function isProportional(law: DrawnLengthLaw) {\n return law.power === 1 && law.effect === 1\n}\n\n// Drawn length in FMMM units for one node of `graph`, under `law`.\nexport function drawnLengthFor(graph: Graph, law: DrawnLengthLaw) {\n const count = graph.nodes.length\n const totalLength = graph.nodes.reduce((sum, n) => sum + n.length, 0)\n const meanBp = count > 0 ? totalLength / count : 0\n // The mean drawn length `bandageAutoScale` already targets, small-graph floor\n // included, so a compressed drawing comes out the same overall size as the\n // proportional one it replaces. That is the property a per-node floor does\n // not have, and the reason raising one is unusable at scale: it lifts the\n // hundreds of non-branching chain nodes along with the alleles, which on a\n // 521-node cut inflates the drawing past what zoom-to-fit can frame.\n const meanDrawn =\n count > 0\n ? Math.max(count * MEAN_NODE_LENGTH, MIN_TOTAL_GRAPH_LENGTH) / count\n : MEAN_NODE_LENGTH\n return (bp: number) => {\n if (meanBp <= 0) {\n return meanDrawn\n }\n const relative = (bp / meanBp) ** law.power\n return Math.max(\n meanDrawn * ((relative - 1) * law.effect + 1),\n BANDAGE_MINIMUM_NODE_LENGTH,\n )\n }\n}\n\n// The engine's own length rule is linear with a floor and takes two numbers\n// (`settings.h`, `getDrawnNodeLength`), so a non-linear law cannot be expressed\n// through them. It can be expressed in the lengths themselves: node length\n// crosses the RPC boundary only to become a drawn length \u2014 `getLength()` has\n// exactly two call sites upstream, both inside that rule \u2014 so handing the engine\n// pre-transformed lengths and a 1:1 scale draws the law without touching the\n// WASM build. Scaled by this factor first because the binding reads a node's\n// length as an `unsigned`, and rounding drawn units straight to integers would\n// quantise the small end where the whole point is legibility.\nconst LAYOUT_LENGTH_PRECISION = 1000\n\n// How a view asks for its node lengths: a law, plus Bandage's own per-node\n// floor. Orthogonal on purpose \u2014 see BUBBLE_SPREADS for which does what.\nexport interface NodeLengthSpread {\n law: DrawnLengthLaw\n // in the same FMMM units as the drawn lengths. At or under Bandage's own\n // floor this leaves the drawing exactly as it was.\n minNodeLength: number\n}\n\nexport const PROPORTIONAL_SPREAD: NodeLengthSpread = {\n law: PROPORTIONAL_LENGTH,\n minNodeLength: 0,\n}\n\nexport interface LayoutScaling {\n // the nodes to hand the engine. Under any law but the proportional one their\n // `length` is a scaled drawn length rather than a bp count, which is why this\n // is a separate array and never the graph's own nodes.\n nodes: GraphNode[]\n opts: BandageScaleOpts\n}\n\nexport function layoutScaling(\n graph: Graph,\n spread: NodeLengthSpread = PROPORTIONAL_SPREAD,\n): LayoutScaling {\n const { law, minNodeLength } = spread\n const opts = bandageAutoScale(graph, minNodeLength)\n // The proportional law is what every committed force figure was drawn\n // against, and it is already exactly what `bandageAutoScale` expresses, so it\n // keeps the untransformed path rather than round-tripping through a rounding\n // step FMMM would be free to amplify. Every floor-based spread comes through\n // here too, unchanged.\n if (isProportional(law)) {\n return { nodes: graph.nodes, opts }\n }\n const drawn = drawnLengthFor(graph, law)\n return {\n nodes: graph.nodes.map(node => ({\n ...node,\n length: Math.round(drawn(node.length) * LAYOUT_LENGTH_PRECISION),\n })),\n opts: {\n ...opts,\n nodeLengthPerMegabase: 1_000_000 / LAYOUT_LENGTH_PRECISION,\n // Bandage's own floor only. A law and a raised floor are alternatives\n // rather than a stack: the law has already lifted the small end, and a\n // floor on top of it would flatten exactly what it just spread.\n minimumNodeLength: BANDAGE_MINIMUM_NODE_LENGTH,\n },\n }\n}\n\n// The mean drawn node length `bandageAutoScale` targets, exported so\n// BUBBLE_SPREADS can state its laws against it rather than against unanchored\n// constants.\nexport { MEAN_NODE_LENGTH }\n", "import { MEAN_NODE_LENGTH, PROPORTIONAL_LENGTH } from './layout/drawnScale'\n\nimport type { NodeLengthSpread } from './layout/drawnScale'\n\n// How far apart the force layout draws the two arms of a bubble, as the law\n// turning a node's bp into its drawn length. One table drives the persisted\n// enum, the dropdown and the value handed to the engine, the same way\n// LAYOUT_MODES and COLOR_SCHEMES do.\n//\n// Why this needs to be a control rather than a better default: the drawn-length\n// law is the one thing standing between a variation graph and a legible force\n// layout, and compressing it costs the property that node length is proportional\n// to bp. Bandage maps length linearly, which suits an assembly graph whose nodes\n// are kb to Mb. In a pangenome an allele is 1-50 bp against a backbone segment\n// of several kb, so on that map every alt clamps to the engine's 5-unit floor,\n// both arms of a bubble land inside one node thickness of each other, and FMMM\n// has nothing to spread \u2014 zoom-to-fit then delivers a single rope with the\n// variation invisible inside it. Compressing the law opens the bubbles and\n// flattens the length ratio, and which of those a reader wants depends on the\n// figure, so the view asks rather than assumes.\n//\n// The compression is Bandage's own, taken off the axis upstream uses it on: it\n// draws node *width* from depth as a power law against the mean, at power 0.5\n// and effect 0.5, for the same reason. 'open' is those two numbers. See\n// DrawnLengthLaw.\n//\n// Measured on an odgi extract of GRCh38#0#chrM:8,200-8,400 from HPRC release 2's\n// chrM pggb graph (61 nodes, 84 edges, 234 haplotype paths), fitted to a 900x560\n// pane: proportional is one squiggle with a single knot in it, and the bubbles\n// come apart into legible lenses once the law compresses.\n//\n// The floor and the law are different instruments and both are kept, because\n// neither does the other's job:\n//\n// - a FLOOR lifts the small end and leaves everything above it proportional. It\n// is what a figure wants when one long node has to stay long \u2014 the ribbons in\n// `pangenome/pggb_haplotype_paths` separate along a 1.2 kb deletion arc, and\n// shortening that arc towards the mean piles them up. Its cost is that it is a\n// per-node minimum, so it lifts a graph's non-branching chain nodes along with\n// its alleles and the drawing inflates with node count: on the 521-node pggb\n// cut in `pangenome/graph_resolution` it reached ~52,000 units and a 1.4% fit,\n// which is why that figure could once afford a spread on its 7-node half only.\n// - the LAW compresses both ends towards the mean, so the drawing stays the size\n// it already was whatever the node count, and a cut spanning 6 bp to 16 kb\n// fits one pane. Its cost is the top end: a node that has to read as long no\n// longer does.\n//\n// So a figure about bubble shape at scale takes 'compress', and a figure about\n// what is drawn along one long edge takes 'open'.\n//\n// 'auto' is the proportional map, unchanged, so every existing figure and the\n// `bandageAutoScale` length-proportionality test are untouched by this existing.\nexport const BUBBLE_SPREADS = [\n {\n value: 'auto',\n label: 'Proportional',\n description:\n \"Bandage's own scale: a node draws proportional to its length, so a 1 bp allele is a speck.\",\n law: PROPORTIONAL_LENGTH,\n minNodeFactor: 0,\n },\n {\n value: 'open',\n label: 'Open bubbles',\n description:\n 'Give every allele a drawn length, so a bubble reads as two arms rather than a knot.',\n law: PROPORTIONAL_LENGTH,\n minNodeFactor: 2.5,\n },\n {\n value: 'wide',\n label: 'Wide bubbles',\n description:\n 'As open, spread further. Best on a window of a dozen bubbles.',\n law: PROPORTIONAL_LENGTH,\n minNodeFactor: 10,\n },\n {\n value: 'compress',\n label: 'Compress lengths',\n description:\n 'Pull the longest and shortest nodes towards the graph\\u2019s mean, so a cut spanning kb and bp fits one pane.',\n law: { power: 0.5, effect: 0.5 },\n minNodeFactor: 0,\n },\n] as const\n\nexport type BubbleSpread = (typeof BUBBLE_SPREADS)[number]['value']\n\nexport const BUBBLE_SPREAD_VALUES = BUBBLE_SPREADS.map(s => s.value)\n\n// The law and floor behind a spread, resolved so the model has one place that\n// knows how a spread becomes numbers. An unknown value draws proportionally\n// rather than throwing, which is what a session persisted by a newer build\n// degrades to.\nexport function spreadFor(spread: string): NodeLengthSpread {\n const entry = BUBBLE_SPREADS.find(s => s.value === spread)\n return {\n law: entry?.law ?? PROPORTIONAL_LENGTH,\n minNodeLength: (entry?.minNodeFactor ?? 0) * MEAN_NODE_LENGTH,\n }\n}\n", "import type { Graph } from './types'\n\n// One table drives the persisted enum and both colour dropdowns, the same way\n// LAYOUT_MODES drives the layout enum and its menu. The values and their labels\n// used to live in two lists in two directories, so adding a scheme meant editing\n// both and a mismatch showed up as a dropdown entry that selected nothing.\n//\n// Kept out of the components directory because the model needs it too.\nexport const COLOR_SCHEMES = [\n // Mirrors `layoutModes`' 'auto': a value the model resolves rather than a\n // colour of its own. It exists because 'uniform' was the default, so a\n // launched graph opened flat grey and both tutorials spent a step saying \"now\n // pick a colour\" \u2014 one figure literally drives that click. A graph with\n // reference coordinates resolves to 'reference-position', which is the one\n // ramp a linear track beside it can be painted with too; a graph with none\n // keeps 'uniform', because there the ramp would be a hue nothing earned.\n //\n // Resolve through `effectiveColorScheme`; the dropdown reads the raw prop, so\n // \"Auto\" stays selectable and visible as what it is.\n { value: 'auto', label: 'Auto' },\n { value: 'uniform', label: 'Uniform' },\n { value: 'random', label: 'Random' },\n { value: 'rainbow', label: 'Rainbow' },\n { value: 'depth', label: 'Depth' },\n { value: 'node-length', label: 'Node Length' },\n { value: 'stable-rank', label: 'Stable rank' },\n { value: 'reference-position', label: 'Reference position' },\n { value: 'grey', label: 'Grey' },\n] as const\n\nexport type ColorScheme = (typeof COLOR_SCHEMES)[number]['value']\n\n// What the renderer can actually paint with: every scheme except the one that\n// stands for \"work it out\". Stated as its own type so `getNodeColor`'s switch\n// has no 'auto' arm to forget.\nexport type ResolvedColorScheme = Exclude<ColorScheme, 'auto'>\n\nexport const COLOR_SCHEME_VALUES = COLOR_SCHEMES.map(s => s.value)\n\n// 'auto' asks the GRAPH, not the layout: a hue along the reference means\n// something whenever the segments have reference coordinates, force-directed\n// drawings included.\nexport function resolveColorScheme(\n scheme: ColorScheme,\n graph: Graph | undefined,\n): ResolvedColorScheme {\n return scheme !== 'auto'\n ? scheme\n : graph?.anchoredBy\n ? 'reference-position'\n : 'uniform'\n}\n", "import type { StableCoordinate } from './gfa-core/index'\nimport type { Graph, GraphNode, NodeSegment } from './types'\n\n// A node whose stable coordinate is known to be present. rGFA states SN/SO/SR\n// on every segment and a path walk derives the same for every segment a path\n// visits (pathAnchoring.ts), so the anchored layouts and the allele projection\n// all work with nodes whose `stable` is a fact rather than an optional \u2014\n// narrowing once here keeps them from asserting it at every use.\nexport type AnchoredNode = GraphNode & { stable: StableCoordinate }\n\n// Stable rank: 0 is the reference backbone, higher ranks are the sequence that\n// diverges from it. rGFA counts those up in build order; a path-derived graph\n// has only the one distinction its paths support, on the reference or off it.\nexport const REFERENCE_RANK = 0\n\nexport function isAnchored(node: GraphNode): node is AnchoredNode {\n return node.stable !== undefined\n}\n\n// Narrows to AnchoredNode so `filter` yields nodes whose coordinate is a fact.\n// Only use it on nodes that may be unanchored: negating a type predicate on an\n// AnchoredNode narrows the other branch to `never`, which is not what \"off the\n// backbone\" means. Where a node is already anchored, compare the rank directly.\nexport function isBackbone(node: GraphNode): node is AnchoredNode {\n return node.stable?.rank === REFERENCE_RANK\n}\n\n// Anchored and above rank 0: sequence that diverges from the reference. Not\n// simply `!isBackbone`, which would also admit nodes carrying no coordinate.\nexport function isOffReference(node: GraphNode): node is AnchoredNode {\n return node.stable !== undefined && node.stable.rank > REFERENCE_RANK\n}\n\nexport function backboneNodes(graph: Graph) {\n return graph.nodes.filter(isBackbone)\n}\n\n// The backbone on row 0 at its declared offsets: the x axis of every layout\n// whose x is reference bp.\nexport function backbonePositions(backbone: AnchoredNode[]) {\n const positions: Record<string, NodeSegment[]> = {}\n for (const node of backbone) {\n positions[node.id] = [\n { x: node.stable.start, y: 0 },\n { x: node.stable.start + node.length, y: 0 },\n ]\n }\n return positions\n}\n\n// Index of the first node starting at or after `bp`, in a list sorted by start.\nexport function firstNodeAtOrAfter(nodes: AnchoredNode[], bp: number) {\n let lo = 0\n let hi = nodes.length\n while (lo < hi) {\n const mid = (lo + hi) >> 1\n if (nodes[mid]!.stable.start < bp) {\n lo = mid + 1\n } else {\n hi = mid\n }\n }\n return lo\n}\n\n// bp the backbone covers in this subgraph. Both anchored layouts scale their row\n// spacing and their minimum drawn allele length off it.\n//\n// A fold rather than Math.max(...starts): the subgraph path is capped at 100 kb\n// but a whole-file GFA import is not, and spreading a backbone of more than\n// ~130k segments into an argument list throws RangeError.\nexport function backboneSpan(backbone: AnchoredNode[]) {\n let min = Infinity\n let max = -Infinity\n for (const node of backbone) {\n min = Math.min(min, node.stable.start)\n max = Math.max(max, node.stable.start + node.length)\n }\n return max - min\n}\n\n// The reference interval the drawing is scaled against: the region the cut was\n// made for, when there is one.\n//\n// Not the same as the backbone's own extent, and the difference is not small. A\n// hop reaches the far anchor of a long-range allele, and that anchor is a rank-0\n// segment: in the E. coli pggb graph a 75 bp CFT073 segment bridges K12:997,574\n// and K12:1,004,667, so a 484 bp window's backbone measured 7,395 bp. Everything\n// scaled off that span went with it \u2014 rows 15x too far apart, and an off-\n// reference floor of 111 bp inside a 484 bp window.\n//\n// A whole-file import has no region, and there the measured extent is the only\n// answer available.\nexport function referenceSpan(\n backbone: AnchoredNode[],\n region?: { start: number; end: number },\n) {\n return region && region.end > region.start\n ? region.end - region.start\n : backboneSpan(backbone)\n}\n", "import { REFERENCE_RANK } from './anchoredNodes'\nimport { panSNSample } from './pansn'\n\nimport type { Graph, GraphNode, PathOrigin, PathVisit } from './types'\n\n// Reference coordinates for a GFA that tags none of its segments with one.\n//\n// rGFA writes the fact per segment (SN/SO/SR). A pggb / odgi / Minigraph-Cactus\n// graph writes the same fact once per path and leaves the arithmetic to the\n// reader: walking a path's steps in order, accumulating segment lengths,\n// assigns every segment that path visits an interval on the path's own\n// sequence. Same information, different encoding \u2014 so a general GFA is not a\n// degraded rGFA, and the anchored layouts work on it once the walk is done.\n//\n// It carries one thing rGFA cannot: a segment's *carriage*, the set of\n// assemblies that actually traverse it. rGFA's SR is build order, so there the\n// most a segment can say is which assembly first contributed it.\n\n// `odgi extract` names an extracted path for the interval it covers on its own\n// sequence: `K12#1#chr:1004500-1004961`. That suffix is the only place a cut\n// subgraph states where in the genome it sits, so it is split off here rather\n// than carried around as part of the name \u2014 no assembly has a sequence called\n// `K12#1#chr:1004500-1004961`, and PanSN parsing of it yields a contig no\n// linear view can open.\n//\n// Anchored on the digits rather than on a trailing colon, because a stable name\n// may legitimately contain one (the same hazard gfaParser's tag splitting has).\nconst RANGE_SUFFIX = /:(\\d+)-\\d+$/\n\nexport function pathOrigin(pathName: string) {\n const match = RANGE_SUFFIX.exec(pathName)\n return match\n ? { name: pathName.slice(0, match.index), start: +match[1]! }\n : { name: pathName, start: 0 }\n}\n\nexport interface PathSteps {\n name: string\n start: number\n steps: { id: string; strand: '+' | '-' }[]\n}\n\n// The single walk. Every segment visit lands in `pathVisits` at the bp its own\n// path reaches it at; `anchorPaths` is what the walk learned about the paths\n// themselves, which is what a reference-path picker lists.\nexport function surveyPaths(\n paths: PathSteps[],\n lengthOf: (segmentId: string) => number,\n) {\n const anchorPaths: PathOrigin[] = []\n const pathVisits = new Map<string, PathVisit[]>()\n for (const path of paths) {\n const sample = panSNSample(path.name)\n let pos = path.start\n for (const step of path.steps) {\n const visit = {\n path: path.name,\n sample,\n start: pos,\n strand: step.strand,\n }\n const existing = pathVisits.get(step.id)\n if (existing) {\n existing.push(visit)\n } else {\n pathVisits.set(step.id, [visit])\n }\n pos += lengthOf(step.id)\n }\n anchorPaths.push({\n name: path.name,\n sample,\n start: path.start,\n length: pos - path.start,\n })\n }\n return { anchorPaths, pathVisits }\n}\n\n// Which path x is drawn on. This is a choice, not a fact: a general GFA's path\n// names are arbitrary and nothing in the file marks one of them as the\n// reference, so a preference is matched against a path's PanSN sample name (the\n// assembly a subgraph was cut against, which is how the launch path knows) and\n// then against its full name. With no preference the first path in the file\n// wins, which is where pggb and odgi leave the reference.\nexport function chooseReferencePath(\n anchorPaths: PathOrigin[],\n preferred: string | undefined,\n) {\n const named = anchorPaths.find(\n p => p.sample === preferred || p.name === preferred,\n )\n return named ?? anchorPaths[0]\n}\n\n// Rank on a path-derived graph is the one distinction the paths support: on the\n// reference path or off it. rGFA's higher ranks are minigraph's build order,\n// which a path GFA has no equivalent of, so drawing more rows than this would\n// be drawing structure the file does not state.\nconst OFF_REFERENCE_RANK = 1\n\n// A segment the reference path visits sits on the backbone at the offset that\n// visit reaches it. One it never visits is an alternate allele, placed on the\n// coordinates of the first path that does carry it \u2014 the same asymmetry rGFA\n// has, where a rank>0 segment's SO is an offset on the assembly that\n// contributed the sequence rather than on the reference.\n//\n// **First visit wins** when a path reaches the same segment more than once, and\n// collapsed repeats make that real rather than hypothetical: pggb folds the\n// E. coli rRNA operons into shared segments, so every strain's path walks them\n// twice (`odgi depth` reaches 10 over a five-strain graph at chr:4,167,000 and\n// chr:3,942,000). A node draws as one tube at one x, so the alternative to\n// picking a copy is one tube spanning both, claiming reference the segment does\n// not occupy. The repeat stays visible as depth: such a node's traversal count\n// is a multiple of the path count.\nfunction anchorNode(\n node: GraphNode,\n visits: PathVisit[] | undefined,\n reference: string,\n): GraphNode {\n let anchored = node\n if (visits && visits.length > 0) {\n const anchor = visits.find(v => v.path === reference) ?? visits[0]!\n anchored = {\n ...node,\n stable: {\n refName: anchor.path,\n start: anchor.start,\n rank: anchor.path === reference ? REFERENCE_RANK : OFF_REFERENCE_RANK,\n strand: anchor.strand,\n },\n samples: [...new Set(visits.map(v => v.sample))].sort(),\n }\n }\n return anchored\n}\n\n// Re-runnable against a different reference path at no parsing cost, which is\n// what the picker needs: the walk is already recorded in `pathVisits`, and only\n// which path counts as rank 0 changes.\nexport function anchorFromPaths(graph: Graph, preferred: string | undefined) {\n const { anchorPaths, pathVisits } = graph\n const reference =\n anchorPaths && pathVisits\n ? chooseReferencePath(anchorPaths, preferred)\n : undefined\n return reference && pathVisits\n ? ({\n ...graph,\n nodes: graph.nodes.map(node =>\n anchorNode(node, pathVisits.get(node.name), reference.name),\n ),\n anchoredBy: 'paths',\n referencePath: reference.name,\n } satisfies Graph)\n : graph\n}\n\n// rGFA states coordinates on every segment, so only a graph that states none\n// has to derive them. A GFA with neither tags nor paths comes back untouched\n// and falls through to the force layout, which is the honest answer for it.\nexport function anchorGraph(graph: Graph, preferred: string | undefined) {\n return graph.anchoredBy === 'tags' ? graph : anchorFromPaths(graph, preferred)\n}\n", "import { pathOrigin } from './pathAnchoring'\n\nimport type { GraphPath } from './types'\n\n// Deterministic colour from a string (djb2-style hash to an HSL hue). Fine for\n// the `random` node scheme, where a collision between two of thousands of nodes\n// means nothing. NOT what the path ribbons use: see pathHueAt.\nexport function nameHue(name: string) {\n let hash = 0\n for (let i = 0; i < name.length; i++) {\n hash = name.charCodeAt(i) + ((hash << 5) - hash)\n }\n return Math.abs(hash % 360)\n}\n\n// Ribbon hues are spread evenly over the wheel by position in the path list,\n// not hashed from the path name. A hash draws from the wheel at random, and at\n// five paths two of them landing on the same hue is common rather than\n// unlucky: `Sakai#1#chr:1983339-1983535` and `NCTC86#1#chr:1709109-1710286`\n// hash 26 degrees apart, which is two purples and a legend that cannot be read\n// off the drawing. Evenly spaced, the worst case is the best available.\n//\n// The cost is that a path's colour depends on how many paths there are, so it\n// moves when the cut changes. That is what the legend is for, and it is the\n// same trade the Bandage demo this was ported from made.\nexport function pathHueAt(index: number, count: number) {\n return (index * 360) / count\n}\n\nexport const PATH_SATURATION = 0.7\nexport const PATH_LIGHTNESS = 0.5\n\n// Past this many paths a graph cannot be drawn per path at all, and the WHOLE\n// of `drawPaths` goes off with it: the node stripes, the edge ribbons and the\n// key naming them.\n//\n// One number for all three because they are one statement, and they used to\n// disagree. Only the stripes were capped. So a Minigraph-Cactus cut, which\n// writes one W record per haplotype and walks every backbone link with all of\n// them, drew: no stripes at all, a key hundreds of rows tall, and one bezier\n// stroke per path per edge \u2014 measured at 99,800 strokes and 64 ms of geometry\n// for 200 paths over 499 links, against 2,495 strokes for the five-path pggb\n// cut the figures use. Every one of those is its own `beginPath`/`stroke` on\n// the Canvas2D backend, every frame.\n//\n// 16 is where the drawing stops SAYING anything, not where it stops being fast.\n// `pathHueAt` spreads the wheel evenly, so 16 hues are 22 degrees apart and\n// still tellable and 200 are one degree; the ribbon fan is PATH_RIBBON_SPACING\n// per path, so 16 of them is a legible fan and 200 is a band wider than the\n// nodes; and a key past about 16 rows is taller than the drawing beside it.\n// Above the cap the honest picture is the plain one \u2014 which is exactly what a\n// graph carrying no paths at all already draws.\nexport const MAX_PATH_COLORS = 16\n\n// Whether this graph's paths can be drawn as colours. Resolve it once and hand\n// the answer down: the geometry, the hit index and the key each used to decide\n// for themselves, which is how they came to disagree.\nexport function pathColorsLegible(pathCount: number) {\n return pathCount > 0 && pathCount <= MAX_PATH_COLORS\n}\n\nexport function pathCssColor(index: number, count: number) {\n return `hsl(${pathHueAt(index, count)}, ${PATH_SATURATION * 100}%, ${\n PATH_LIGHTNESS * 100\n }%)`\n}\n\n// A path is named the way its file names it \u2014 `K12#1#chr:1004500-1004961` for a\n// P record `odgi extract` wrote, `HG00738#1` for a W record \u2014 and neither is a\n// legend entry. The label is the least of that name which still tells the paths\n// apart: the sample where samples are unique, the haplotype too where they are\n// not, the whole stable name where even that repeats. Widening it for every row\n// rather than only for the colliding ones, because a legend where one entry is\n// `HG00738#1` and its neighbour is `HG01071` reads as two kinds of thing.\nfunction labelTiers(name: string) {\n const parts = pathOrigin(name).name.split('#')\n return [parts[0]!, parts.slice(0, 2).join('#'), parts.join('#')]\n}\n\n// Locale-independent, unlike toLocaleString: a figure regenerated on a machine\n// with a different locale would otherwise differ from the committed one.\nfunction groupDigits(n: number) {\n return String(n).replace(/\\B(?=(\\d{3})+$)/g, ',')\n}\n\n// A collapsed repeat puts one sequence through the same segments more than\n// once, and `odgi extract` emits one path per visit \u2014 nine visits over five\n// E. coli chromosomes at the rRNA operons, where every name tier above collides\n// because the sequence really is the same one. What separates those is the\n// offset each name carried, which is the one thing pathOrigin strips off.\nfunction offsetTiers(name: string, tiers: string[]) {\n const { start } = pathOrigin(name)\n return tiers.map(t => `${t} @${groupDigits(start)}`)\n}\n\nexport interface PathLegendEntry {\n name: string\n label: string\n color: string\n}\n\nexport function pathLegend(paths: GraphPath[]): PathLegendEntry[] {\n const named = paths.map(p => labelTiers(p.name))\n // narrowest first, and the offset is tried before the next name tier: two\n // copies of one operon are told apart by where they are, not by widening a\n // name that is genuinely identical\n const candidates = [0, 1, 2].flatMap(t => [\n paths.map((_, i) => named[i]![t]!),\n paths.map((p, i) => offsetTiers(p.name, named[i]!)[t]!),\n ])\n const distinct = candidates.find(\n labels => new Set(labels).size === paths.length,\n )\n // Nothing separates two paths with the same name and the same offset, so the\n // widest labelling is as close as any can get.\n const labels = distinct ?? candidates.at(-1)!\n return paths.map((path, i) => ({\n name: path.name,\n label: labels[i]!,\n color: pathCssColor(i, paths.length),\n }))\n}\n", "import type { Graph, GraphNode } from './types'\nimport type { NodeInk } from './util/hitDetection'\n\n// How thick a node draws. Bandage widens a node by its depth, the square root\n// of its depth against the graph's mean, so a contig every read covers is fat\n// and a spurious one is a hair. In a pangenome cut depth is carriage, how many\n// walks go through the node, and the same rule makes the reference thick and a\n// private allele thin. One table drives the persisted enum and the dropdown,\n// the way BUBBLE_SPREADS does.\nexport const NODE_WIDTHS = [\n {\n value: 'depth',\n label: 'By depth',\n description:\n 'Thicker the more paths carry a node, on the square root of its depth against the mean. A graph with one depth everywhere draws uniform.',\n },\n {\n value: 'uniform',\n label: 'Uniform',\n description: 'Every node the same thickness.',\n },\n] as const\n\nexport type NodeWidth = (typeof NODE_WIDTHS)[number]['value']\n\nexport const NODE_WIDTH_VALUES = NODE_WIDTHS.map(w => w.value)\n\nconst MIN_FACTOR = 0.3\nconst MAX_FACTOR = 3\n\n// Length-weighted, as Bandage's mean depth is, so a cut's long reference nodes\n// set the norm and the alleles read against it.\nexport function meanDepth(graph: Graph) {\n let weighted = 0\n let length = 0\n for (const node of graph.nodes) {\n weighted += node.depth * node.length\n length += node.length\n }\n return length > 0 ? weighted / length : 0\n}\n\nexport function depthWidthFactor(node: GraphNode, mean: number) {\n if (!(mean > 0) || !(node.depth > 0)) {\n return 1\n }\n return Math.min(\n MAX_FACTOR,\n Math.max(MIN_FACTOR, Math.sqrt(node.depth / mean)),\n )\n}\n\n// How wide a node is drawn, in screen px. One function for the geometry and\n// for the hit test, so the pointer finds a node exactly where its ink is.\nexport function nodeWidthPx(\n node: GraphNode,\n contigThickness: number,\n nodeWidth: NodeWidth,\n mean: number,\n) {\n return (\n contigThickness * (nodeWidth === 'depth' ? depthWidthFactor(node, mean) : 1)\n )\n}\n\nexport function maxNodeWidthPx(contigThickness: number, nodeWidth: NodeWidth) {\n return contigThickness * (nodeWidth === 'depth' ? MAX_FACTOR : 1)\n}\n\n// How far each node's ink reaches from its centreline, for the hit test: the\n// widths the geometry draws with, from the same function.\nexport function nodeInk(\n graph: Graph | undefined,\n nodeById: ReadonlyMap<string, GraphNode> | undefined,\n contigThickness: number,\n nodeWidth: NodeWidth,\n): NodeInk {\n const mean = graph ? meanDepth(graph) : 0\n return {\n maxHalfWidthPx: maxNodeWidthPx(contigThickness, nodeWidth) / 2,\n halfWidthPx: id => {\n const node = nodeById?.get(id)\n return node\n ? nodeWidthPx(node, contigThickness, nodeWidth, mean) / 2\n : contigThickness / 2\n },\n }\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["require_mui", "__commonJSMin", "exports", "module", "drawnNodeLength", "opts", "length", "bandageAutoScale", "graph", "minNodeLength", "megabases", "sum", "n", "target", "PROPORTIONAL_LENGTH", "isProportional", "law", "drawnLengthFor", "count", "totalLength", "meanBp", "meanDrawn", "bp", "relative", "LAYOUT_LENGTH_PRECISION", "PROPORTIONAL_SPREAD", "layoutScaling", "spread", "drawn", "node", "BUBBLE_SPREADS", "PROPORTIONAL_LENGTH", "BUBBLE_SPREAD_VALUES", "s", "spreadFor", "spread", "entry", "COLOR_SCHEMES", "COLOR_SCHEME_VALUES", "s", "resolveColorScheme", "scheme", "graph", "isAnchored", "node", "isBackbone", "isOffReference", "backboneNodes", "graph", "backbonePositions", "backbone", "positions", "firstNodeAtOrAfter", "nodes", "bp", "lo", "hi", "mid", "backboneSpan", "min", "max", "referenceSpan", "region", "RANGE_SUFFIX", "pathOrigin", "pathName", "match", "surveyPaths", "paths", "lengthOf", "anchorPaths", "pathVisits", "path", "sample", "panSNSample", "pos", "step", "visit", "existing", "chooseReferencePath", "preferred", "p", "OFF_REFERENCE_RANK", "anchorNode", "node", "visits", "reference", "anchored", "anchor", "v", "anchorFromPaths", "graph", "anchorGraph", "nameHue", "name", "hash", "i", "pathHueAt", "index", "count", "PATH_SATURATION", "PATH_LIGHTNESS", "MAX_PATH_COLORS", "pathColorsLegible", "pathCount", "pathCssColor", "labelTiers", "parts", "pathOrigin", "groupDigits", "n", "offsetTiers", "tiers", "start", "t", "pathLegend", "paths", "named", "p", "candidates", "_", "labels", "path", "NODE_WIDTHS", "NODE_WIDTH_VALUES", "w", "MIN_FACTOR", "MAX_FACTOR", "meanDepth", "graph", "weighted", "length", "node", "depthWidthFactor", "mean", "nodeWidthPx", "contigThickness", "nodeWidth", "maxNodeWidthPx", "nodeInk", "nodeById", "id"]
|
|
7
|
-
}
|