jbrowse-plugin-graphgenomeviewer 7.1.13 → 7.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. package/dist/chunks/GbzBaseSyntenyAdapter-FXMGIM7Z.js +2 -0
  2. package/dist/chunks/{GbzBaseSyntenyAdapter-NB6WBBZH.js.map → GbzBaseSyntenyAdapter-FXMGIM7Z.js.map} +3 -3
  3. package/dist/chunks/{GraphGenomeView-4O5F5I37.js → GraphGenomeView-WJ3FIDY2.js} +2 -2
  4. package/dist/chunks/{GraphTrackSettingsDialog-WZEJAF7F.js → GraphTrackSettingsDialog-ZW7ALMDV.js} +2 -2
  5. package/dist/chunks/{HighlightColorDialog-SRT2FPXP.js → HighlightColorDialog-VBZRUKD5.js} +2 -2
  6. package/dist/chunks/{LinearGraphDisplay-Z33PVCJL.js → LinearGraphDisplay-SPOPTJEN.js} +2 -2
  7. package/dist/chunks/MinigraphBubbleAdapter-QCOMFPLL.js +2 -0
  8. package/dist/chunks/{MinigraphBubbleAdapter-HDLUZ6YF.js.map → MinigraphBubbleAdapter-QCOMFPLL.js.map} +1 -1
  9. package/dist/chunks/RgfaTabixAdapter-O3NMNRZ2.js +2 -0
  10. package/dist/chunks/RgfaTabixAdapter-O3NMNRZ2.js.map +7 -0
  11. package/dist/chunks/WalkTabixSyntenyAdapter-I3PY6HJ2.js +2 -0
  12. package/dist/chunks/{WalkTabixSyntenyAdapter-WBHOZLAN.js.map → WalkTabixSyntenyAdapter-I3PY6HJ2.js.map} +1 -1
  13. package/dist/chunks/chunk-2M4XYSLG.js +2 -0
  14. package/dist/chunks/chunk-2M4XYSLG.js.map +7 -0
  15. package/dist/chunks/{chunk-JLGPQO5L.js → chunk-2O3YVA2I.js} +2 -2
  16. package/dist/chunks/{chunk-CWNJR5XB.js → chunk-44CJ2N3N.js} +1 -1
  17. package/dist/chunks/{chunk-CWNJR5XB.js.map → chunk-44CJ2N3N.js.map} +1 -1
  18. package/dist/chunks/chunk-6KUHGRHU.js +2 -0
  19. package/dist/chunks/chunk-6KUHGRHU.js.map +7 -0
  20. package/dist/chunks/chunk-6MUBJVBG.js +2 -0
  21. package/dist/chunks/chunk-6MUBJVBG.js.map +7 -0
  22. package/dist/chunks/{chunk-GUXZESDR.js → chunk-7HWHWPRW.js} +1 -1
  23. package/dist/chunks/{chunk-GUXZESDR.js.map → chunk-7HWHWPRW.js.map} +1 -1
  24. package/dist/chunks/chunk-B2EP6FOQ.js +3 -0
  25. package/dist/chunks/chunk-B2EP6FOQ.js.map +7 -0
  26. package/dist/chunks/{chunk-44HZPYGC.js → chunk-BXRTG7FU.js} +2 -2
  27. package/dist/chunks/{chunk-44HZPYGC.js.map → chunk-BXRTG7FU.js.map} +1 -1
  28. package/dist/chunks/{chunk-HLKZCTQ3.js → chunk-DBPEUVUC.js} +1 -1
  29. package/dist/chunks/{chunk-HLKZCTQ3.js.map → chunk-DBPEUVUC.js.map} +1 -1
  30. package/dist/chunks/{chunk-FME624X3.js → chunk-DUR437TH.js} +2 -2
  31. package/dist/chunks/{chunk-FME624X3.js.map → chunk-DUR437TH.js.map} +1 -1
  32. package/dist/chunks/{chunk-6WA6WF6A.js → chunk-FIRQAKMX.js} +1 -1
  33. package/dist/chunks/{chunk-6WA6WF6A.js.map → chunk-FIRQAKMX.js.map} +1 -1
  34. package/dist/chunks/chunk-JCAZTNYG.js +2 -0
  35. package/dist/chunks/chunk-JCAZTNYG.js.map +7 -0
  36. package/dist/chunks/chunk-N74HGPAW.js +3 -0
  37. package/dist/chunks/chunk-N74HGPAW.js.map +7 -0
  38. package/dist/chunks/chunk-PEDWEPNK.js +2 -0
  39. package/dist/chunks/chunk-PEDWEPNK.js.map +7 -0
  40. package/dist/chunks/chunk-PYQG3JHP.js +3 -0
  41. package/dist/chunks/chunk-PYQG3JHP.js.map +7 -0
  42. package/dist/chunks/chunk-RFDSEB2X.js +4 -0
  43. package/dist/chunks/chunk-RFDSEB2X.js.map +7 -0
  44. package/dist/chunks/{chunk-O7Y7LYN6.js → chunk-RW775LQN.js} +2 -2
  45. package/dist/chunks/{chunk-O7Y7LYN6.js.map → chunk-RW775LQN.js.map} +1 -1
  46. package/dist/chunks/{chunk-N4WBX2OS.js → chunk-VQ77X5QU.js} +2 -2
  47. package/dist/chunks/{chunk-N4WBX2OS.js.map → chunk-VQ77X5QU.js.map} +1 -1
  48. package/dist/chunks/{chunk-LXCMWL7B.js → chunk-WUSKVEA6.js} +2 -2
  49. package/dist/chunks/{chunk-LXCMWL7B.js.map → chunk-WUSKVEA6.js.map} +1 -1
  50. package/dist/chunks/{chunk-ZNT7TQLN.js → chunk-YKSUKPYY.js} +2 -2
  51. package/dist/chunks/chunk-YKSUKPYY.js.map +7 -0
  52. package/dist/chunks/{renderSvg-RRWCAEGF.js → renderSvg-WD6YDV2I.js} +2 -2
  53. package/dist/jbrowse-plugin-graphgenomeviewer.esm.js +4 -4
  54. package/dist/jbrowse-plugin-graphgenomeviewer.esm.js.map +4 -4
  55. package/package.json +3 -3
  56. package/src/GbzBaseSyntenyAdapter/GbzBaseSyntenyAdapter.test.ts +2 -2
  57. package/src/GbzBaseSyntenyAdapter/GbzBaseSyntenyAdapter.ts +1 -1
  58. package/src/GetSubgraph.ts +1 -1
  59. package/src/GraphGenomeView/genes/genes.test.ts +20 -2
  60. package/src/GraphGenomeView/legendSections.test.ts +1 -1
  61. package/src/GraphGenomeView/legendSections.ts +1 -7
  62. package/src/GraphGenomeView/model.test.ts +1 -2
  63. package/src/GraphGenomeView/pane/graphViews.ts +24 -35
  64. package/src/GraphGenomeView/pane/loadActions.ts +4 -3
  65. package/src/GraphGenomeView/pane/paneBase.ts +1 -1
  66. package/src/GraphGenomeView/pane/renderingActions.ts +5 -3
  67. package/src/GraphGenomeView/subgraphLoad.test.ts +41 -1
  68. package/src/GraphGenomeView/walkRowsCut.ts +10 -44
  69. package/src/LinearGraphDisplay/LinearGraphDisplay.test.ts +15 -0
  70. package/src/LinearGraphDisplay/configSchema.ts +5 -0
  71. package/src/RgfaTabixAdapter/RgfaTabixAdapter.test.ts +23 -4
  72. package/src/RgfaTabixAdapter/RgfaTabixAdapter.ts +2 -3
  73. package/src/RgfaTabixAdapter/bubbleTier.test.ts +1 -1
  74. package/src/RgfaTabixAdapter/walkCut.ts +20 -0
  75. package/src/RgfaTabixAdapter/walkFiles.test.ts +2 -2
  76. package/src/RgfaTabixAdapter/walkReader.ts +1 -1
  77. package/src/WalkTabixSyntenyAdapter/WalkTabixSyntenyAdapter.test.ts +1 -1
  78. package/src/version.ts +1 -1
  79. package/dist/chunks/GbzBaseSyntenyAdapter-NB6WBBZH.js +0 -2
  80. package/dist/chunks/MinigraphBubbleAdapter-HDLUZ6YF.js +0 -2
  81. package/dist/chunks/RgfaTabixAdapter-XZRTWQMZ.js +0 -3
  82. package/dist/chunks/RgfaTabixAdapter-XZRTWQMZ.js.map +0 -7
  83. package/dist/chunks/WalkTabixSyntenyAdapter-WBHOZLAN.js +0 -2
  84. package/dist/chunks/chunk-BWP3XYKD.js +0 -2
  85. package/dist/chunks/chunk-BWP3XYKD.js.map +0 -7
  86. package/dist/chunks/chunk-EDSIYH4H.js +0 -2
  87. package/dist/chunks/chunk-EDSIYH4H.js.map +0 -7
  88. package/dist/chunks/chunk-III4GT4G.js +0 -2
  89. package/dist/chunks/chunk-III4GT4G.js.map +0 -7
  90. package/dist/chunks/chunk-N5GYTUIL.js +0 -3
  91. package/dist/chunks/chunk-N5GYTUIL.js.map +0 -7
  92. package/dist/chunks/chunk-PA4HKAUJ.js +0 -2
  93. package/dist/chunks/chunk-PA4HKAUJ.js.map +0 -7
  94. package/dist/chunks/chunk-PFAHNHMM.js +0 -2
  95. package/dist/chunks/chunk-PFAHNHMM.js.map +0 -7
  96. package/dist/chunks/chunk-UFQTIWSN.js +0 -4
  97. package/dist/chunks/chunk-UFQTIWSN.js.map +0 -7
  98. package/dist/chunks/chunk-VDHDEEMF.js +0 -2
  99. package/dist/chunks/chunk-VDHDEEMF.js.map +0 -7
  100. package/dist/chunks/chunk-WGVATZLM.js +0 -3
  101. package/dist/chunks/chunk-WGVATZLM.js.map +0 -7
  102. package/dist/chunks/chunk-ZNT7TQLN.js.map +0 -7
  103. package/src/RgfaTabixAdapter/rgfaBed.test.ts +0 -254
  104. package/src/RgfaTabixAdapter/rgfaBed.ts +0 -314
  105. package/src/RgfaTabixAdapter/rgfaCut.ts +0 -139
  106. package/src/RgfaTabixAdapter/walkRowRuns.test.ts +0 -192
  107. package/src/RgfaTabixAdapter/walkRowRuns.ts +0 -520
  108. /package/dist/chunks/{GraphGenomeView-4O5F5I37.js.map → GraphGenomeView-WJ3FIDY2.js.map} +0 -0
  109. /package/dist/chunks/{GraphTrackSettingsDialog-WZEJAF7F.js.map → GraphTrackSettingsDialog-ZW7ALMDV.js.map} +0 -0
  110. /package/dist/chunks/{HighlightColorDialog-SRT2FPXP.js.map → HighlightColorDialog-VBZRUKD5.js.map} +0 -0
  111. /package/dist/chunks/{LinearGraphDisplay-Z33PVCJL.js.map → LinearGraphDisplay-SPOPTJEN.js.map} +0 -0
  112. /package/dist/chunks/{chunk-JLGPQO5L.js.map → chunk-2O3YVA2I.js.map} +0 -0
  113. /package/dist/chunks/{renderSvg-RRWCAEGF.js.map → renderSvg-WD6YDV2I.js.map} +0 -0
@@ -1,520 +0,0 @@
1
- import { gapParts, stopAt } from '@jbrowse/bandage-core/gfa/walkStops'
2
- import {
3
- panSNContig,
4
- panSNHaplotype,
5
- panSNSample,
6
- } from '@jbrowse/bandage-core/pansn'
7
-
8
- import type { GraphTables } from '@jbrowse/bandage-core/gfa/graphTables'
9
- import type { GapCause, GapPart } from '@jbrowse/bandage-core/gfa/walkStops'
10
- import type {
11
- WalkAxis,
12
- WalkRow,
13
- WalkRows,
14
- WalkRun,
15
- WalkStop,
16
- } from '@jbrowse/bandage-core/layout/walkRows'
17
- import type { PathStop, StopChunk } from '@jbrowse/bandage-core/types'
18
-
19
- const RUN_ON_REFERENCE = 1
20
- const RUN_REVERSED = 2
21
- const RUN_GAP = 4
22
- // a gap's cause, by index from bit 3
23
- const GAP_CAUSES = [undefined, 'missing', 'elsewhere', 'unknown'] as const
24
- const CAUSE_SHIFT = 3
25
-
26
- const causeFlags = (cause: GapCause | undefined) =>
27
- GAP_CAUSES.indexOf(cause) << CAUSE_SHIFT
28
-
29
- type WalkRowMeta = Omit<WalkRow, 'runs'>
30
-
31
- /**
32
- * A cut for walk rows: the tables, and the rows' runs over the window, which
33
- * the main thread draws without a Graph of the walks' steps
34
- */
35
- export type WalkCut = GraphTables & { walkRowRuns?: WalkRowRuns }
36
-
37
- export function walkCutFor(
38
- tables: GraphTables,
39
- region: { start: number; end: number },
40
- walkRows: boolean | undefined,
41
- ): WalkCut {
42
- return walkRows
43
- ? { ...tables, walkRowRuns: walkRowRuns(tables, region) }
44
- : tables
45
- }
46
-
47
- /**
48
- * bandage-core's `walkRows` over a cut's tables, each row's runs as typed
49
- * arrays that cross from the worker beside the tables. Row 0 is the
50
- * reference.
51
- */
52
- export interface WalkRowRuns {
53
- origin: number
54
- rows: WalkRowMeta[]
55
- offsets: Uint32Array
56
- start: Float64Array
57
- bp: Float64Array
58
- referenceStart: Float64Array
59
- flags: Uint8Array
60
- // a gap's chunk elsewhere, as an index into `chunks`, -1 for none
61
- chunk: Int32Array
62
- chunks: StopChunk[]
63
- }
64
-
65
- /**
66
- * A walk's PanSN fields: `HG002#1#chr1`, or a pggb P-line's `chm13#chr1`,
67
- * which has no haplotype
68
- */
69
- export function walkPath(name: string) {
70
- const sample = panSNSample(name)
71
- const haplotype = panSNHaplotype(name)
72
- return {
73
- name,
74
- sample,
75
- haplotype:
76
- haplotype === undefined ? undefined : +haplotype.slice(sample.length + 1),
77
- contig: panSNContig(name),
78
- }
79
- }
80
-
81
- type Path = ReturnType<typeof walkPath> & {
82
- start: number
83
- from: number
84
- to: number
85
- before?: PathStop
86
- after?: PathStop
87
- }
88
-
89
- class RunWriter {
90
- start: number[] = []
91
- bp: number[] = []
92
- referenceStart: number[] = []
93
- flags: number[] = []
94
- chunk: number[] = []
95
- chunks: StopChunk[] = []
96
- offsets = [0]
97
- private chunkIndex = new Map<string, number>()
98
-
99
- get length() {
100
- return this.bp.length
101
- }
102
-
103
- push(
104
- start: number,
105
- bp: number,
106
- flags: number,
107
- referenceStart: number,
108
- chunk?: StopChunk,
109
- ) {
110
- this.start.push(start)
111
- this.bp.push(bp)
112
- this.flags.push(flags)
113
- this.referenceStart.push(referenceStart)
114
- this.chunk.push(chunk ? this.chunkOf(chunk) : -1)
115
- }
116
-
117
- private chunkOf(chunk: StopChunk) {
118
- const key = `${chunk.refName}:${chunk.start}`
119
- let i = this.chunkIndex.get(key)
120
- if (i === undefined) {
121
- i = this.chunks.length
122
- this.chunkIndex.set(key, i)
123
- this.chunks.push(chunk)
124
- }
125
- return i
126
- }
127
-
128
- endRow() {
129
- this.offsets.push(this.bp.length)
130
- }
131
- }
132
-
133
- /**
134
- * `walkRows(graphFromTables(tables), region)` for a cut whose first walk is
135
- * the reference, which every walk-file and GBZ cut is, in as many pieces as
136
- * the cut breaks it into; a step is a node index. A gap between two pieces of
137
- * one haplotype is a step of `-bp`, split into its parts by the pieces' stops
138
- * as walkRows splits it. One difference: a walk reaching only one
139
- * of the region's flanks measures from that flank, where walkRows takes the
140
- * whole walk the cut holds, so its length is a lower bound that no longer
141
- * grows with the cut's context.
142
- */
143
- export function walkRowRuns(
144
- { nodes: n, walks: w }: GraphTables,
145
- region?: { start: number; end: number },
146
- ): WalkRowRuns | undefined {
147
- const declared = n.lengths.length
148
- const lengthOf = (node: number) => (node < declared ? n.lengths[node]! : 0)
149
- const paths: Path[] = []
150
- for (let p = 0; p < w.names.length; p++) {
151
- if (w.offsets[p + 1]! > w.offsets[p]!) {
152
- const before = w.before && stopAt(w.before, p)
153
- const after = w.after && stopAt(w.after, p)
154
- paths.push({
155
- ...walkPath(w.names[p]!),
156
- start: w.starts[p]!,
157
- from: w.offsets[p]!,
158
- to: w.offsets[p + 1]!,
159
- ...(before ? { before } : {}),
160
- ...(after ? { after } : {}),
161
- })
162
- }
163
- }
164
- const referencePieces = paths
165
- .filter(p => p.name === paths[0]?.name)
166
- .sort((a, b) => a.start - b.start)
167
- const first = referencePieces[0]
168
- const others = paths.filter(p => p.name !== first?.name)
169
- if (!first || others.length === 0) {
170
- return undefined
171
- }
172
- const walks = new Map<string, Path[]>()
173
- for (const path of others) {
174
- const list = walks.get(path.name)
175
- if (list) {
176
- list.push(path)
177
- } else {
178
- walks.set(path.name, [path])
179
- }
180
- }
181
-
182
- const spanStart = new Float64Array(n.names.length).fill(Number.NaN)
183
- const spanEnd = new Float64Array(n.names.length)
184
- let flankedBefore = false
185
- let flankedAfter = false
186
- const cut = region && region.end > region.start ? region : undefined
187
- for (const piece of referencePieces) {
188
- let pos = piece.start
189
- for (let s = piece.from; s < piece.to; s++) {
190
- const node = w.steps[s]!
191
- const len = lengthOf(node)
192
- if (Number.isNaN(spanStart[node]!)) {
193
- spanStart[node] = pos
194
- spanEnd[node] = pos + len
195
- if (cut) {
196
- flankedBefore ||= pos + len <= cut.start
197
- flankedAfter ||= pos >= cut.end
198
- }
199
- }
200
- pos += len
201
- }
202
- }
203
- const flanked = cut === undefined || (flankedBefore && flankedAfter)
204
-
205
- const out = new RunWriter()
206
- let steps = new Int32Array(0)
207
- let stepStart = new Float64Array(0)
208
- const rowOf = (pieces: Path[]): WalkRowMeta => {
209
- const path = pieces[0]!
210
- const ordered = [...pieces].sort((a, b) => a.start - b.start)
211
- // the walk's steps, each piece's gap from the last as a step of -bp
212
- let count = ordered.length - 1
213
- for (const piece of ordered) {
214
- count += piece.to - piece.from
215
- }
216
- if (count > steps.length) {
217
- steps = new Int32Array(count * 2)
218
- stepStart = new Float64Array(count * 2)
219
- }
220
- let length = 0
221
- let overlaps = false
222
- let end: number | undefined
223
- let previous: Path | undefined
224
- // each gap step's parts, by step index
225
- const partsAt = new Map<number, GapPart[]>()
226
- for (const piece of ordered) {
227
- if (end !== undefined && piece.start < end) {
228
- overlaps = true
229
- }
230
- if (end !== undefined && piece.start > end) {
231
- partsAt.set(
232
- length,
233
- gapParts(piece.start - end, previous?.after, piece.before),
234
- )
235
- steps[length] = -(piece.start - end)
236
- stepStart[length++] = end
237
- }
238
- let pos = piece.start
239
- for (let s = piece.from; s < piece.to; s++) {
240
- const node = w.steps[s]!
241
- steps[length] = node
242
- stepStart[length++] = pos
243
- pos += node < declared ? n.lengths[node]! : 0
244
- }
245
- end = pos
246
- previous = piece
247
- }
248
- // A walk with one flank, whose contig ends inside the window: the steps
249
- // past that flank, read in the reference's direction. Which side is
250
- // inside follows the walk's direction along the reference at the
251
- // flank, from the nearest other step on it.
252
- const partialSide = (i0: number, i1: number) => {
253
- const flank = i0 >= 0 ? i0 : i1
254
- let near = -1
255
- for (let d = 1; near < 0 && d < length; d++) {
256
- for (const j of [flank - d, flank + d]) {
257
- const id = j >= 0 && j < length ? steps[j]! : -1
258
- if (near < 0 && id >= 0 && !Number.isNaN(spanStart[id]!)) {
259
- near = j
260
- }
261
- }
262
- }
263
- if (near < 0) {
264
- return undefined
265
- }
266
- const forward =
267
- near > flank === spanStart[steps[near]!]! > spanStart[steps[flank]!]!
268
- const after = forward === (flank === i0)
269
- const end = after ? length - 1 : 0
270
- const endId = steps[end]!
271
- const contigEnds = endId >= 0 && !Number.isNaN(spanStart[endId]!)
272
- const stop: WalkStop = {
273
- contigEnds,
274
- shortBp: contigEnds
275
- ? Math.max(
276
- 0,
277
- cut!.start - spanEnd[endId]!,
278
- spanStart[endId]! - cut!.end,
279
- )
280
- : 0,
281
- }
282
- return {
283
- stop,
284
- lo: after ? flank + 1 : 0,
285
- hi: after ? length : flank,
286
- backward: !forward,
287
- axisStart: forward
288
- ? after
289
- ? stepEnd(flank)
290
- : stepStart[0]!
291
- : after
292
- ? stepEnd(length - 1)
293
- : stepStart[flank]!,
294
- }
295
- }
296
- const stepEnd = (i: number) => {
297
- const id = steps[i]!
298
- return stepStart[i]! + (id < 0 ? -id : lengthOf(id))
299
- }
300
-
301
- let lo = 0
302
- let hi = length
303
- let backward = false
304
- let complete = true
305
- let from = -1
306
- let to = -1
307
- let axisStart: number | undefined
308
- let stop: WalkStop | undefined
309
- if (cut && flanked) {
310
- let i0 = -1
311
- let i1 = -1
312
- let bestEnd = -Infinity
313
- let bestStart = Infinity
314
- for (let i = 0; i < length; i++) {
315
- const id = steps[i]!
316
- if (id >= 0 && !Number.isNaN(spanStart[id]!)) {
317
- if (spanEnd[id]! <= cut.start && spanEnd[id]! > bestEnd) {
318
- bestEnd = spanEnd[id]!
319
- i0 = i
320
- }
321
- if (spanStart[id]! >= cut.end && spanStart[id]! < bestStart) {
322
- bestStart = spanStart[id]!
323
- i1 = i
324
- }
325
- }
326
- }
327
- if (i0 < 0 || i1 < 0) {
328
- complete = false
329
- const inside = i0 >= 0 || i1 >= 0 ? partialSide(i0, i1) : undefined
330
- if (inside) {
331
- ;({ lo, hi, backward, axisStart, stop } = inside)
332
- }
333
- } else {
334
- lo = Math.min(i0, i1) + 1
335
- hi = Math.max(i0, i1)
336
- backward = i0 > i1
337
- from = i0
338
- to = i1
339
- }
340
- }
341
- const axis: WalkAxis | undefined =
342
- overlaps || length === 0
343
- ? undefined
344
- : axisStart !== undefined
345
- ? { contig: path.contig, start: axisStart, reversed: backward }
346
- : from < 0
347
- ? { contig: path.contig, start: stepStart[0]!, reversed: false }
348
- : from < to
349
- ? { contig: path.contig, start: stepEnd(from), reversed: false }
350
- : { contig: path.contig, start: stepStart[from]!, reversed: true }
351
-
352
- let bp = 0
353
- let offReferenceBp = 0
354
- let gapBp = 0
355
- let step = 0
356
- let lastAt = -1
357
- let lastFlags = 0
358
- let lastRef = Number.NaN
359
- for (let k = lo; k < hi; k++) {
360
- const index = backward ? hi - 1 - (k - lo) : k
361
- const id = steps[index]!
362
- if (id < 0) {
363
- const parts = partsAt.get(index) ?? [{ bp: -id }]
364
- // a row read backwards meets a gap's parts last first
365
- for (const part of backward ? [...parts].reverse() : parts) {
366
- out.push(
367
- bp,
368
- part.bp,
369
- RUN_GAP | causeFlags(part.cause),
370
- Number.NaN,
371
- part.chunk,
372
- )
373
- bp += part.bp
374
- }
375
- lastAt = out.length - 1
376
- lastFlags = RUN_GAP
377
- lastRef = Number.NaN
378
- gapBp += -id
379
- step = 0
380
- continue
381
- }
382
- const len = lengthOf(id)
383
- const sStart = spanStart[id]!
384
- const onRef = !Number.isNaN(sStart)
385
- const at = lastRef
386
- const hasAt = lastAt >= 0 && !Number.isNaN(at)
387
- const forward =
388
- onRef && hasAt && step >= 0 && at + (out.bp[lastAt] ?? 0) === sStart
389
- const back = onRef && hasAt && step <= 0 && spanEnd[id] === at
390
- if (
391
- !onRef &&
392
- lastAt >= 0 &&
393
- !(lastFlags & RUN_ON_REFERENCE) &&
394
- !(lastFlags & RUN_GAP)
395
- ) {
396
- out.bp[lastAt]! += len
397
- } else if (forward || back) {
398
- out.bp[lastAt]! += len
399
- if (!forward) {
400
- lastRef = sStart
401
- out.referenceStart[lastAt] = sStart
402
- lastFlags |= RUN_REVERSED
403
- out.flags[lastAt] = lastFlags
404
- }
405
- step = forward ? 1 : -1
406
- } else {
407
- lastFlags = onRef ? RUN_ON_REFERENCE : 0
408
- lastRef = onRef ? sStart : Number.NaN
409
- out.push(bp, len, lastFlags, lastRef)
410
- lastAt = out.length - 1
411
- step = 0
412
- }
413
- bp += len
414
- if (!onRef) {
415
- offReferenceBp += len
416
- }
417
- }
418
- out.endRow()
419
- return {
420
- name: path.name,
421
- label:
422
- path.haplotype === undefined
423
- ? path.sample
424
- : `${path.sample}#${path.haplotype}`,
425
- sample: path.sample,
426
- haplotype: path.haplotype,
427
- bp,
428
- offReferenceBp,
429
- gapBp,
430
- complete,
431
- ...(stop ? { stop } : {}),
432
- axis,
433
- }
434
- }
435
-
436
- const reference = rowOf(referencePieces)
437
- const rowList = [...walks.values()].map(pieces => ({
438
- meta: rowOf(pieces),
439
- row: out.offsets.length - 2,
440
- }))
441
- rowList.sort(
442
- (a, b) =>
443
- Number(b.meta.complete) - Number(a.meta.complete) ||
444
- b.meta.bp - a.meta.bp ||
445
- a.meta.label.localeCompare(b.meta.label),
446
- )
447
- // rows in drawn order: the reference, then the sorted walks
448
- const order = [0, ...rowList.map(r => r.row)]
449
- const total = out.length
450
- const offsets = new Uint32Array(order.length + 1)
451
- const start = new Float64Array(total)
452
- const bpOut = new Float64Array(total)
453
- const referenceStart = new Float64Array(total)
454
- const flags = new Uint8Array(total)
455
- const chunk = new Int32Array(total)
456
- let at = 0
457
- order.forEach((row, i) => {
458
- const a = out.offsets[row]!
459
- const b = out.offsets[row + 1]!
460
- for (let k = a; k < b; k++, at++) {
461
- start[at] = out.start[k]!
462
- bpOut[at] = out.bp[k]!
463
- referenceStart[at] = out.referenceStart[k]!
464
- flags[at] = out.flags[k]!
465
- chunk[at] = out.chunk[k]!
466
- }
467
- offsets[i + 1] = at
468
- })
469
- return {
470
- origin: cut ? cut.start : first.start,
471
- rows: [reference, ...rowList.map(r => r.meta)],
472
- offsets,
473
- start,
474
- bp: bpOut,
475
- referenceStart,
476
- flags,
477
- chunk,
478
- chunks: out.chunks,
479
- }
480
- }
481
-
482
- function runAt(t: WalkRowRuns, k: number): WalkRun {
483
- const f = t.flags[k]!
484
- const run: WalkRun = {
485
- start: t.start[k]!,
486
- bp: t.bp[k]!,
487
- onReference: (f & RUN_ON_REFERENCE) !== 0,
488
- }
489
- if (f & RUN_GAP) {
490
- run.gap = true
491
- const cause = GAP_CAUSES[(f >> CAUSE_SHIFT) & 3]
492
- if (cause) {
493
- run.cause = cause
494
- }
495
- const chunk = t.chunks[t.chunk[k]!]
496
- if (chunk) {
497
- run.chunk = chunk
498
- }
499
- } else {
500
- run.referenceStart = Number.isNaN(t.referenceStart[k]!)
501
- ? undefined
502
- : t.referenceStart[k]
503
- }
504
- if (f & RUN_REVERSED) {
505
- run.reversed = true
506
- }
507
- return run
508
- }
509
-
510
- /** The rows as bandage-core's `WalkRows`, a run object per run */
511
- export function walkRowsOf(t: WalkRowRuns, unit?: number): WalkRows {
512
- const rows = t.rows.map((meta, i) => {
513
- const runs: WalkRun[] = []
514
- for (let k = t.offsets[i]!; k < t.offsets[i + 1]!; k++) {
515
- runs.push(runAt(t, k))
516
- }
517
- return { ...meta, runs }
518
- })
519
- return { origin: t.origin, unit, reference: rows[0]!, rows: rows.slice(1) }
520
- }