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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jbrowse-plugin-graphgenomeviewer",
3
- "version": "7.1.13",
3
+ "version": "7.2.1",
4
4
  "description": "JBrowse 2 graph genome (pangenome) view: rGFA reference-anchored layouts, the Bandage force-directed engine, and haplotype lanes read from a gbz-base database",
5
5
  "license": "GPL-3.0-or-later",
6
6
  "repository": {
@@ -32,7 +32,7 @@
32
32
  "@jbrowse/core": "5.0.0-beta.11",
33
33
  "@jbrowse/display-kit": "5.0.0-beta.11",
34
34
  "@jbrowse/display-ui": "5.0.0-beta.11",
35
- "@jbrowse/graph-walks": "^2.0.0",
35
+ "@jbrowse/graph-walks": "^2.1.0",
36
36
  "@jbrowse/render-core": "5.0.0-beta.11",
37
37
  "@jbrowse/synteny-core": "5.0.0-beta.11"
38
38
  },
@@ -40,7 +40,7 @@
40
40
  "@emotion/react": "^11.14.0",
41
41
  "@emotion/styled": "^11.14.1",
42
42
  "@eslint/js": "^10.0.1",
43
- "@jbrowse/bandage-core": "^11.0.0",
43
+ "@jbrowse/bandage-core": "^11.4.0",
44
44
  "@jbrowse/cli": "^4.3.0",
45
45
  "@jbrowse/mobx-state-tree": "^6.9.0",
46
46
  "@jbrowse/plugin-linear-genome-view": "5.0.0-beta.11",
@@ -12,6 +12,7 @@ import {
12
12
  } from '@jbrowse/bandage-core/gbzWindow'
13
13
  import { gfaTables } from '@jbrowse/bandage-core/gfa/gfaTables'
14
14
  import { graphTablesGFA } from '@jbrowse/bandage-core/gfa/graphTables'
15
+ import { walkRowsOf } from '@jbrowse/bandage-core/layout/walkRowRuns'
15
16
  import { walkRows } from '@jbrowse/bandage-core/layout/walkRows'
16
17
  import { loadGraph } from '@jbrowse/bandage-core/pipeline'
17
18
  import { numericCigarToString } from '@jbrowse/cigar-utils'
@@ -27,10 +28,9 @@ import Adapter, {
27
28
  } from './GbzBaseSyntenyAdapter.ts'
28
29
  import configSchema from './configSchema.ts'
29
30
  import GbzBaseSyntenyAdapterF from './index.ts'
30
- import { walkRowsOf } from '../RgfaTabixAdapter/walkRowRuns.ts'
31
31
  import { laneAssemblyName } from '../synteny/lanePairs.ts'
32
32
 
33
- import type { WalkCut } from '../RgfaTabixAdapter/walkRowRuns.ts'
33
+ import type { WalkCut } from '../RgfaTabixAdapter/walkCut.ts'
34
34
  import type { GBZBase } from '@gmod/gbz-base'
35
35
  import type { GraphTables } from '@jbrowse/bandage-core/gfa/graphTables'
36
36
  import type { SyntenyMate } from '@jbrowse/synteny-core'
@@ -20,7 +20,7 @@ import { openLocation } from '@jbrowse/core/util/io'
20
20
  import { ObservableCreate } from '@jbrowse/core/util/rxjs'
21
21
 
22
22
  import { findCompanion } from './companion.ts'
23
- import { walkCutFor } from '../RgfaTabixAdapter/walkRowRuns.ts'
23
+ import { walkCutFor } from '../RgfaTabixAdapter/walkCut.ts'
24
24
  import { GafFile } from '../gaf/gafFile.ts'
25
25
  import { locationIsSet } from '../locationName.ts'
26
26
  import { openTabixSlot } from '../panSNTabix.ts'
@@ -4,7 +4,7 @@ import { rpcResultWithArrayBuffers } from '@jbrowse/core/util/librpc'
4
4
 
5
5
  import { adapterImplementing } from './adapterImplementing'
6
6
 
7
- import type { WalkCut } from './RgfaTabixAdapter/walkRowRuns.ts'
7
+ import type { WalkCut } from './RgfaTabixAdapter/walkCut.ts'
8
8
  import type { RpcExecuteArgs } from '@jbrowse/core/rpc/RpcRegistry'
9
9
  import type { Region } from '@jbrowse/core/util'
10
10
 
@@ -232,8 +232,26 @@ test('exons land on the backbone stretch they cover, and the name at the midpoin
232
232
  const [pin] = genePins(graph, geneModelsFrom([gene]), positions)
233
233
  expect(pin!.exons).toBe('M20,0L60,0M100,20L100,80')
234
234
  expect(pin!.exonsByNode).toEqual([
235
- { nodeId: 'v1+', d: 'M20,0L60,0' },
236
- { nodeId: 'v2+', d: 'M100,20L100,80' },
235
+ {
236
+ nodeId: 'v1+',
237
+ d: 'M20,0L60,0',
238
+ stretches: [
239
+ [
240
+ { x: 20, y: 0 },
241
+ { x: 60, y: 0 },
242
+ ],
243
+ ],
244
+ },
245
+ {
246
+ nodeId: 'v2+',
247
+ d: 'M100,20L100,80',
248
+ stretches: [
249
+ [
250
+ { x: 100, y: 20 },
251
+ { x: 100, y: 80 },
252
+ ],
253
+ ],
254
+ },
237
255
  ])
238
256
  expect(pin!.at).toEqual({ x: 100, y: 0 })
239
257
  expect(pin!.covered).toBe(1)
@@ -39,7 +39,7 @@ test("the ramp key's bp read the same in every locale", () => {
39
39
  const model = {
40
40
  walkLift: undefined,
41
41
  referenceRampDomain: { start: 999.5, end: 123_456.5 },
42
- referenceRampOffKeys: { offReference: false, unplaced: false },
42
+ referenceRampDrawsOffReference: false,
43
43
  bubbleHalos: [],
44
44
  genePins: [],
45
45
  pathLegend: [],
@@ -39,8 +39,6 @@ import type { LiftedWalk } from '@jbrowse/bandage-core/walkHighlight'
39
39
  export const SWATCH_PX = 18
40
40
  const BAR_PX = 48
41
41
 
42
- // getNodeColor's grey for a node the ramp cannot place
43
- const UNPLACED_SWATCH = 'rgb(160, 160, 160)'
44
42
  // LIFT_BACKDROP_CSS reads paler alone than faded strokes do where they
45
43
  // overlap, so the key samples it darker
46
44
  const FADED_SWATCH = 'rgba(160, 160, 160, 0.45)'
@@ -147,19 +145,15 @@ function rampRows(model: GraphPaneModel): LegendRow[] {
147
145
  // a measured domain runs between node midpoints, which can fall on a half bp
148
146
  const start = Math.round(domain.start)
149
147
  const end = Math.round(domain.end)
150
- const { offReference, unplaced } = model.referenceRampOffKeys
151
148
  return [
152
149
  {
153
150
  key: 'ramp',
154
151
  label: `${start.toLocaleString('en-US')}-${end.toLocaleString('en-US')} (${formatBp(end - start)})`,
155
152
  swatch: { kind: 'fill', stops: RAMP_GRADIENT_STOPS, width: BAR_PX },
156
153
  },
157
- ...(offReference
154
+ ...(model.referenceRampDrawsOffReference
158
155
  ? [fillRow('off', REFERENCE_RAMP_ALT_CSS, 'off the reference', BAR_PX)]
159
156
  : []),
160
- ...(unplaced
161
- ? [fillRow('unplaced', UNPLACED_SWATCH, 'no reference position', BAR_PX)]
162
- : []),
163
157
  ]
164
158
  }
165
159
 
@@ -40,7 +40,7 @@ import { EMPTY_BATCH, SELECT_BRIGHTEN } from './pane/paneBase'
40
40
  import { PANEL_REFERENCE_TUBE, PANEL_TUBES } from './tubeMapPanels'
41
41
  import stateModelFactory from './viewModel'
42
42
  import { SECTION_HEADER_PX, walkRowTrees } from './walkRowGroups'
43
- import { walkCutFor } from '../RgfaTabixAdapter/walkRowRuns.ts'
43
+ import { walkCutFor } from '../RgfaTabixAdapter/walkCut.ts'
44
44
 
45
45
  import type { GraphLayers } from './graphLayers'
46
46
  import type { SubgraphCutOptions } from '../GetSubgraph'
@@ -1903,7 +1903,6 @@ describe('zoomToFit on a tube map', () => {
1903
1903
  const { nodes } = model.tubeMapPicture!
1904
1904
  expect(nodes.length).toBeGreaterThan(0)
1905
1905
  expect(nodes.every(n => model.tubeMapNodeColors!.has(n.name))).toBe(true)
1906
- expect(model.referenceRampOffKeys.unplaced).toBe(false)
1907
1906
  })
1908
1907
 
1909
1908
  test('a fold change lays the tube map out again', async () => {
@@ -1,3 +1,4 @@
1
+ import { isBackbone } from '@jbrowse/bandage-core/anchoredNodes'
1
2
  import { bubbleHalos } from '@jbrowse/bandage-core/bubbles/bubbleHalos'
2
3
  import { bubbleKey, sameBubble } from '@jbrowse/bandage-core/bubbles/bubbleLine'
3
4
  import { bubbleSegmentIds } from '@jbrowse/bandage-core/bubbles/classifyBubble'
@@ -11,6 +12,10 @@ import {
11
12
  import { facetSettingOf } from '@jbrowse/bandage-core/facetGrid'
12
13
  import { genePins } from '@jbrowse/bandage-core/genes/genePins'
13
14
  import { formatBp } from '@jbrowse/bandage-core/graphLabels'
15
+ import {
16
+ walkRowRuns,
17
+ walkRowsOf,
18
+ } from '@jbrowse/bandage-core/layout/walkRowRuns'
14
19
  import { filterSamples, walkRows } from '@jbrowse/bandage-core/layout/walkRows'
15
20
  import {
16
21
  layoutModeByValue,
@@ -51,7 +56,6 @@ import {
51
56
  import { computed } from 'mobx'
52
57
 
53
58
  import { TUBE_MAP_MODES, dependOn, geometryPainted, paneBase } from './paneBase'
54
- import { walkRowRuns, walkRowsOf } from '../../RgfaTabixAdapter/walkRowRuns.ts'
55
59
  import {
56
60
  canonicalAssemblyName,
57
61
  trackAssemblies,
@@ -82,7 +86,7 @@ import {
82
86
  import { groupByOf, groupWalkRows, metadataColumns } from '../walkRowGroups'
83
87
 
84
88
  import type { ScreenTransform } from './keepInView'
85
- import type { WalkCut } from '../../RgfaTabixAdapter/walkRowRuns.ts'
89
+ import type { WalkCut } from '../../RgfaTabixAdapter/walkCut.ts'
86
90
  import type { GraphLayers } from '../graphLayers'
87
91
  import type { HoverHighlight } from '../hoverHighlight'
88
92
  import type { NodeColor } from '../nodeColor'
@@ -471,16 +475,11 @@ export const withGraphViews = paneBase
471
475
  // Whether a lifted lane paints a node charcoal, the colour a lane coloured
472
476
  // by reference position gives what is off the reference
473
477
  get liftPaintsOffReference() {
474
- for (const w of this.walkLift?.walks ?? []) {
475
- if (w.encoding.field !== 'walk') {
476
- for (const color of w.colors.values()) {
477
- if (color === NO_VALUE_COLOR) {
478
- return true
479
- }
480
- }
481
- }
482
- }
483
- return false
478
+ return !!this.walkLift?.walks.some(
479
+ w =>
480
+ w.encoding.field !== 'walk' &&
481
+ [...w.colors.values()].includes(NO_VALUE_COLOR),
482
+ )
484
483
  },
485
484
  // what the faded rest of the drawing is not on
486
485
  get liftedWalksLabel() {
@@ -1086,29 +1085,19 @@ export const withGraphViews = paneBase
1086
1085
  ? { start: ramp.start, end: ramp.start + ramp.span }
1087
1086
  : undefined
1088
1087
  },
1089
- // The ramp's two colours for nodes off it, as getNodeColor paints them:
1090
- // charcoal where an rGFA rank puts a node off the reference, grey where
1091
- // a node has no reference position at all. A tube map draws the window
1092
- // alone (trimToWindow), so there only the boxes it drew count.
1093
- get referenceRampOffKeys() {
1094
- const ramp = self.referenceRamp
1095
- const layout = self.layoutResult
1096
- const drawn = layout?.tubeMap ? layout.nodePositions : undefined
1097
- let offReference = false
1098
- let unplaced = false
1099
- if (ramp && self.drawnGraph) {
1100
- for (const node of self.drawnGraph.nodes) {
1101
- if (drawn && !drawn[node.id]) {
1102
- continue
1103
- }
1104
- if (!ramp.midpoints.has(node.id)) {
1105
- unplaced = true
1106
- } else if (node.stable && node.stable.rank > 0) {
1107
- offReference = true
1108
- }
1109
- }
1110
- }
1111
- return { offReference, unplaced }
1088
+ // Whether nodes take their scheme's colour: the drawing's own, or a tube
1089
+ // map's boxes. Walk rows draw bars with a key of their own.
1090
+ get paintsNodeColors() {
1091
+ return self.drawsNodes || !!self.layoutResult?.tubeMap
1092
+ },
1093
+ // Whether the ramp paints a drawn node charcoal, as getNodeColor does
1094
+ // every node off the backbone
1095
+ get referenceRampDrawsOffReference() {
1096
+ return (
1097
+ !!self.referenceRamp &&
1098
+ this.paintsNodeColors &&
1099
+ !!self.drawnGraph?.nodes.some(node => !isBackbone(node))
1100
+ )
1112
1101
  },
1113
1102
  // Each tube map box in its node's colour, where the scheme paints one
1114
1103
  get tubeMapNodeColors() {
@@ -6,6 +6,8 @@ import {
6
6
  clipToWindow,
7
7
  trimToWindow,
8
8
  } from '@jbrowse/bandage-core/layout/trimToWindow'
9
+ import { walkRowLayoutOf } from '@jbrowse/bandage-core/layout/walkRowLayout'
10
+ import { walkRowsOf } from '@jbrowse/bandage-core/layout/walkRowRuns'
9
11
  import { layoutModeByValue } from '@jbrowse/bandage-core/layoutModes'
10
12
  import {
11
13
  anchorFromPaths,
@@ -33,7 +35,6 @@ import {
33
35
  } from './paneBase'
34
36
  import { withSettingActions } from './settingActions'
35
37
  import { namesReads } from '../../GetGraphReads'
36
- import { walkRowsOf } from '../../RgfaTabixAdapter/walkRowRuns.ts'
37
38
  import { geneModelsFrom } from '../genes/geneFeatures'
38
39
  import { gfaText } from '../gfaText'
39
40
  import { repeatArraysFrom } from '../repeats/repeatFeatures'
@@ -43,10 +44,10 @@ import {
43
44
  withTubeMapPanels,
44
45
  } from '../tubeMapPanels'
45
46
  import { parseSamplesTsv } from '../walkRowGroups'
46
- import { walkRowLayoutOf, walkRowsGraph } from '../walkRowsCut.ts'
47
+ import { walkRowsGraph } from '../walkRowsCut.ts'
47
48
 
48
49
  import type { SubgraphCutOptions, SubgraphRegion } from '../../GetSubgraph'
49
- import type { WalkCut } from '../../RgfaTabixAdapter/walkRowRuns.ts'
50
+ import type { WalkCut } from '../../RgfaTabixAdapter/walkCut.ts'
50
51
  import type { GafReads } from '../../gaf/gafFile'
51
52
  import type { PaneLayout } from '../tubeMapPanels'
52
53
  import type { MinigraphBubble } from '@jbrowse/bandage-core/bubbles/bubbleLine'
@@ -12,7 +12,7 @@ import { lenientOptionalEnum } from '../lenientEnum'
12
12
 
13
13
  import type { MorphEntering } from './morph'
14
14
  import type { SubgraphRegion } from '../../GetSubgraph'
15
- import type { WalkCut } from '../../RgfaTabixAdapter/walkRowRuns.ts'
15
+ import type { WalkCut } from '../../RgfaTabixAdapter/walkCut.ts'
16
16
  import type { RepeatArray } from '../repeats/repeatFeatures'
17
17
  import type { PaneLayout } from '../tubeMapPanels'
18
18
  import type { SampleRow } from '../walkRowGroups'
@@ -107,12 +107,14 @@ export const withRenderingActions = withLoadActions
107
107
  { fireImmediately: true },
108
108
  ),
109
109
  )
110
- // A host fits the rows once, when it takes the pane over, which is
111
- // before the legend measures the room it needs above them
110
+ // A host fits the rows when it takes the pane over, which is before
111
+ // the legend measures the room it needs above them and before a split
112
+ // into panels changes how tall the drawing is
112
113
  addDisposer(
113
114
  self,
114
115
  reaction(
115
- () => self.fitPadTop,
116
+ () =>
117
+ `${self.fitPadTop} ${self.layoutBounds?.h} ${self.usableHeight}`,
116
118
  () => {
117
119
  if (self.viewportOwner === 'host') {
118
120
  self.zoomToFit()
@@ -494,9 +494,49 @@ describe('reads', () => {
494
494
  const drawn = model.tubeMapPicture!.nodes.map(n => n.name)
495
495
  const h0 = model.graph!.nodes.find(n => n.name === 'h0')!
496
496
  expect(drawn).not.toContain(h0.id)
497
- expect(model.referenceRampOffKeys.offReference).toBe(false)
497
+ expect(model.referenceRampDrawsOffReference).toBe(false)
498
498
  })
499
499
 
500
+ // a chain of six alleles runs past the flanking walk's reach, which once
501
+ // keyed its middle as a second, lighter grey
502
+ const DEEP = [
503
+ 'H\tVN:Z:1.0',
504
+ 'S\ts0\t*\tLN:i:1000\tSN:Z:GRCh38#0#chr6\tSO:i:32000000\tSR:i:0',
505
+ 'S\ts1\t*\tLN:i:1000\tSN:Z:GRCh38#0#chr6\tSO:i:32001000\tSR:i:0',
506
+ ...Array.from(
507
+ { length: 6 },
508
+ (_, i) =>
509
+ `S\th${i}\t*\tLN:i:50\tSN:Z:NA20809#2#CM094351.1\tSO:i:${i * 50}\tSR:i:1`,
510
+ ),
511
+ 'L\ts0\t+\ts1\t+\t0M',
512
+ 'L\ts0\t+\th0\t+\t0M',
513
+ ...Array.from({ length: 5 }, (_, i) => `L\th${i}\t+\th${i + 1}\t+\t0M`),
514
+ 'L\th5\t+\ts1\t+\t0M',
515
+ ].join('\n')
516
+
517
+ test.each([
518
+ ['force', true],
519
+ ['walkrows', false],
520
+ ])(
521
+ 'a %s layout keys deep alleles as off the reference: %s',
522
+ async (layoutMode, keyed) => {
523
+ mockRpcCall.mockImplementation((_sid: unknown, method: string) =>
524
+ method === 'GetSubgraph'
525
+ ? Promise.resolve(DEEP)
526
+ : Promise.reject(new Error(`Unexpected RPC: ${method}`)),
527
+ )
528
+ const model = createView({
529
+ layoutMode,
530
+ color: { field: 'position' },
531
+ loadedTrackId: TRACK.trackId,
532
+ loadedRegion: ON_HG38,
533
+ })
534
+ await model.load()
535
+
536
+ expect(model.referenceRampDrawsOffReference).toBe(keyed)
537
+ },
538
+ )
539
+
500
540
  // `flank` walks only s0, before the window, so the tube map draws no tube
501
541
  // for it, and the legend and a hover pair names with the tubes drawn
502
542
  test("a walk the window trims away takes no tube's colour", async () => {
@@ -1,20 +1,9 @@
1
- import {
2
- backboneNodes,
3
- backbonePositions,
4
- overlapsWindow,
5
- } from '@jbrowse/bandage-core/anchoredNodes'
6
- import {
7
- walkRowLabels,
8
- walkRowsExtent,
9
- } from '@jbrowse/bandage-core/layout/walkRowLayout'
1
+ import { tablePath } from '@jbrowse/bandage-core/gfa/graphTables'
10
2
  import { loadGraph } from '@jbrowse/bandage-core/pipeline'
11
3
 
12
- import { walkPath } from '../RgfaTabixAdapter/walkRowRuns.ts'
13
-
14
- import type { WalkCut } from '../RgfaTabixAdapter/walkRowRuns.ts'
4
+ import type { WalkCut } from '../RgfaTabixAdapter/walkCut.ts'
15
5
  import type { GraphTables } from '@jbrowse/bandage-core/gfa/graphTables'
16
- import type { WalkRows } from '@jbrowse/bandage-core/layout/walkRows'
17
- import type { Graph, LayoutResult } from '@jbrowse/bandage-core/types'
6
+ import type { Graph } from '@jbrowse/bandage-core/types'
18
7
 
19
8
  /**
20
9
  * The Graph a walk-rows cut parses to: nodes with their depth over every
@@ -49,36 +38,13 @@ export function walkRowsGraph(
49
38
  graph.nodes.forEach((node, i) => {
50
39
  node.depth = Math.max(depth[i]!, 1)
51
40
  })
52
- const stubs = w.names.slice(1).flatMap((walk, i) => {
53
- if (w.offsets[i + 2]! <= w.offsets[i + 1]!) {
54
- return []
55
- }
56
- return [{ ...walkPath(walk), nodeIds: [], start: w.starts[i + 1]! }]
57
- })
41
+ const stubs = w.names
42
+ .slice(1)
43
+ .flatMap((_, i) =>
44
+ w.offsets[i + 2]! > w.offsets[i + 1]!
45
+ ? [{ ...tablePath(w, i + 1), nodeIds: [] }]
46
+ : [],
47
+ )
58
48
  graph.paths = [...(graph.paths ?? []), ...stubs]
59
49
  return graph
60
50
  }
61
-
62
- /** bandage-core's walkRowLayout, over rows already made */
63
- export function walkRowLayoutOf(
64
- graph: Graph,
65
- walks: WalkRows,
66
- region?: { start: number; end: number },
67
- ): LayoutResult | undefined {
68
- const backbone = backboneNodes(graph)
69
- if (backbone.length === 0) {
70
- return undefined
71
- }
72
- const overWindow = region
73
- ? backbone.filter(n => overlapsWindow(n, region))
74
- : backbone
75
- return {
76
- nodePositions: backbonePositions(
77
- overWindow.length > 0 ? overWindow : backbone,
78
- ),
79
- rowLabels: walkRowLabels(walks),
80
- referenceAxis: true,
81
- pixelRows: true,
82
- extent: walkRowsExtent(walks),
83
- }
84
- }
@@ -1,3 +1,4 @@
1
+ import { fittedTranslateY } from '@jbrowse/bandage-core/pipeline'
1
2
  import PluginManager from '@jbrowse/core/PluginManager'
2
3
  import {
3
4
  ConfigurationReference,
@@ -770,6 +771,20 @@ test('a tube map on its own axis ties each reference box to its bp in the linear
770
771
  expect(pane.tubeMapConnectors).toEqual([])
771
772
  })
772
773
 
774
+ test('a hosted drawing whose height changes after the host took the pane is placed again', async () => {
775
+ const { pane } = await shownGraph({ paths: true })
776
+ await pane.switchLayout('tubemapref')
777
+ await wait(SETTLE_MS)
778
+ const expected = fittedTranslateY(
779
+ pane.layoutBounds!,
780
+ pane.usableHeight,
781
+ pane.scaleY,
782
+ pane.fitPads.top,
783
+ )
784
+ expect(pane.viewportOwner).toBe('host')
785
+ expect(pane.translateY).toBeCloseTo(expected, 6)
786
+ })
787
+
773
788
  test("a folded tube map draws the cut's reference as merged nodes, and the rest as ticks or routes", async () => {
774
789
  const { pane } = await shownGraph({ paths: true })
775
790
  const labels = () =>
@@ -38,6 +38,7 @@ export function configSchemaFactory() {
38
38
  color: {
39
39
  type: 'frozen',
40
40
  defaultValue: {},
41
+ plot: true,
41
42
  },
42
43
  /**
43
44
  * #slot
@@ -48,6 +49,7 @@ export function configSchemaFactory() {
48
49
  size: {
49
50
  type: 'frozen',
50
51
  defaultValue: { field: 'depth', value: 6 },
52
+ plot: true,
51
53
  },
52
54
  /**
53
55
  * #slot
@@ -61,6 +63,7 @@ export function configSchemaFactory() {
61
63
  layers: {
62
64
  type: 'frozen',
63
65
  defaultValue: {},
66
+ plot: true,
64
67
  },
65
68
  /**
66
69
  * #slot
@@ -71,6 +74,7 @@ export function configSchemaFactory() {
71
74
  facet: {
72
75
  type: 'frozen',
73
76
  defaultValue: {},
77
+ plot: true,
74
78
  },
75
79
  /**
76
80
  * #slot
@@ -79,6 +83,7 @@ export function configSchemaFactory() {
79
83
  rows: {
80
84
  type: 'frozen',
81
85
  defaultValue: {},
86
+ plot: true,
82
87
  },
83
88
  /**
84
89
  * #slot
@@ -5,18 +5,24 @@ import { join } from 'node:path'
5
5
  import { gunzipSync } from 'node:zlib'
6
6
 
7
7
  import { TabixIndexedFile } from '@gmod/tabix'
8
+ import { convertGFAToGraph } from '@jbrowse/bandage-core/gfa/gfaConverter'
8
9
  import { parseGFA } from '@jbrowse/bandage-core/gfa-core/index'
9
10
  import PluginManager from '@jbrowse/core/PluginManager'
10
11
  import { readConfObject } from '@jbrowse/core/configuration'
12
+ import {
13
+ formatSubgraph,
14
+ linkKey,
15
+ parseLinkLine,
16
+ parseSegmentLine,
17
+ } from '@jbrowse/graph-walks'
11
18
  import { firstValueFrom } from 'rxjs'
12
19
  import { toArray } from 'rxjs/operators'
13
20
 
14
21
  import Adapter from './RgfaTabixAdapter.ts'
15
22
  import configSchema from './configSchema.ts'
16
23
  import RgfaTabixAdapterF from './index.ts'
17
- import { linkKey, parseLinkLine } from './rgfaBed.ts'
18
24
 
19
- import type { WalkCut } from './walkRowRuns.ts'
25
+ import type { WalkCut } from './walkCut.ts'
20
26
 
21
27
  // Built by `gfa-to-tabix --layout contig` from the minigraph rGFA of four E. coli
22
28
  // strains at jbrowse.org/demos/ecoli_pangenome/ecoli_rgfa_slice.gfa (the
@@ -333,8 +339,7 @@ test('getFeatures carries SM:Z: onto the feature', async () => {
333
339
  })
334
340
 
335
341
  // The other half of the same fixture: the graph route reads the samples off the
336
- // synthesized S-line, and rgfaBed.test.ts asserts that from a hand-written row.
337
- // This is the same claim against a real indexed file.
342
+ // synthesized S-line
338
343
  test('getSubgraph keeps the tag on the S-line it synthesizes', async () => {
339
344
  const gfa = gfaText(await makePggbAdapter().getSubgraph(is5))
340
345
  expect(gfa.split('\n')).toContain(
@@ -342,6 +347,20 @@ test('getSubgraph keeps the tag on the S-line it synthesizes', async () => {
342
347
  )
343
348
  })
344
349
 
350
+ // An indexed cut has no P/W lines, so this tag is its only record of which
351
+ // haplotypes visit a segment, and the node popup shows GraphNode.samples
352
+ test('SM:Z: on a segs row reaches GraphNode.samples', () => {
353
+ const segment = parseSegmentLine(
354
+ 'K12#1#chr\t1004477\t1004500\ts119690\t0\tSM:Z:K12.1,Sakai.1,NCTC86.1',
355
+ )
356
+ const gfa = formatSubgraph(new Map([[segment.id, segment]]), new Map())
357
+ expect(convertGFAToGraph(parseGFA(gfa)).nodes[0]!.samples).toEqual([
358
+ 'K12.1',
359
+ 'Sakai.1',
360
+ 'NCTC86.1',
361
+ ])
362
+ })
363
+
345
364
  // An rGFA has no sixth column, so the attribute is absent rather than 0: a
346
365
  // color expression reading `sampleCount` on such a track gets undefined, not a
347
366
  // count of zero.
@@ -1,6 +1,7 @@
1
1
  import { BaseFeatureDataAdapter } from '@jbrowse/core/data_adapters/BaseAdapter'
2
2
  import { SimpleFeature, updateStatus } from '@jbrowse/core/util'
3
3
  import { ObservableCreate } from '@jbrowse/core/util/rxjs'
4
+ import { parseSegmentRow, rgfaCut, segmentSamples } from '@jbrowse/graph-walks'
4
5
 
5
6
  import { locationIsSet } from '../locationName.ts'
6
7
  import {
@@ -9,13 +10,11 @@ import {
9
10
  unmappedRegionMessage,
10
11
  } from '../panSNTabix.ts'
11
12
  import { getLines } from '../tabixRange.ts'
12
- import { parseSegmentRow, segmentSamples } from './rgfaBed.ts'
13
- import { rgfaCut } from './rgfaCut.ts'
14
13
  import { WalkIndex } from './walkReader.ts'
15
14
 
16
15
  import type { RgfaTabixAdapterConfig } from './configSchema.ts'
17
16
  import type { SubgraphAdapterOptions, SubgraphTier } from '../GetSubgraph.ts'
18
- import type { WalkCut } from './walkRowRuns.ts'
17
+ import type { WalkCut } from './walkCut.ts'
19
18
  import type { TabixIndexedFile } from '@gmod/tabix'
20
19
  import type { BaseOptions } from '@jbrowse/core/data_adapters/BaseAdapter'
21
20
  import type { Feature } from '@jbrowse/core/util'
@@ -3,7 +3,7 @@ import { parseGFA } from '@jbrowse/bandage-core/gfa-core/index'
3
3
  import Adapter from './RgfaTabixAdapter.ts'
4
4
  import configSchema from './configSchema.ts'
5
5
 
6
- import type { WalkCut } from './walkRowRuns.ts'
6
+ import type { WalkCut } from './walkCut.ts'
7
7
 
8
8
  // A level-of-detail tier: the same two files the adapter always reads, but one
9
9
  // node per bubble instead of one per GFA segment. Built by
@@ -0,0 +1,20 @@
1
+ import { walkRowRuns } from '@jbrowse/bandage-core/layout/walkRowRuns'
2
+
3
+ import type { GraphTables } from '@jbrowse/bandage-core/gfa/graphTables'
4
+ import type { WalkRowRuns } from '@jbrowse/bandage-core/layout/walkRowRuns'
5
+
6
+ /**
7
+ * A cut for walk rows: the tables, and the rows' runs over the window, which
8
+ * the main thread draws without a Graph of the walks' steps
9
+ */
10
+ export type WalkCut = GraphTables & { walkRowRuns?: WalkRowRuns }
11
+
12
+ export function walkCutFor(
13
+ tables: GraphTables,
14
+ region: { start: number; end: number },
15
+ walkRows: boolean | undefined,
16
+ ): WalkCut {
17
+ return walkRows
18
+ ? { ...tables, walkRowRuns: walkRowRuns(tables, region) }
19
+ : tables
20
+ }
@@ -5,15 +5,15 @@ import {
5
5
  graphFromTables,
6
6
  graphTablesGFA,
7
7
  } from '@jbrowse/bandage-core/gfa/graphTables'
8
+ import { walkRowsOf } from '@jbrowse/bandage-core/layout/walkRowRuns'
8
9
  import { readConfObject } from '@jbrowse/core/configuration'
9
10
  import { firstValueFrom } from 'rxjs'
10
11
  import { toArray } from 'rxjs/operators'
11
12
 
12
13
  import Adapter from './RgfaTabixAdapter.ts'
13
14
  import configSchema from './configSchema.ts'
14
- import { walkRowsOf } from './walkRowRuns.ts'
15
15
 
16
- import type { WalkCut } from './walkRowRuns.ts'
16
+ import type { WalkCut } from './walkCut.ts'
17
17
  import type { GraphTables } from '@jbrowse/bandage-core/gfa/graphTables'
18
18
 
19
19
  // chr22 of HPRC v2.1 at base level, one walk file per reference in walk
@@ -2,7 +2,7 @@ import { resolvePanSNPrefix } from '@jbrowse/bandage-core/pansn'
2
2
  import { WalkReader, referenceNodes, walksKept } from '@jbrowse/graph-walks'
3
3
 
4
4
  import { getLines } from '../tabixRange.ts'
5
- import { walkCutFor } from './walkRowRuns.ts'
5
+ import { walkCutFor } from './walkCut.ts'
6
6
 
7
7
  import type { SubgraphAdapterOptions } from '../GetSubgraph.ts'
8
8
  import type { TabixIndexedFile } from '@gmod/tabix'
@@ -1,4 +1,5 @@
1
1
  import { graphTablesGFA } from '@jbrowse/bandage-core/gfa/graphTables'
2
+ import { walkRowsOf } from '@jbrowse/bandage-core/layout/walkRowRuns'
2
3
  import { walkRows } from '@jbrowse/bandage-core/layout/walkRows'
3
4
  import { loadGraph } from '@jbrowse/bandage-core/pipeline'
4
5
  import PluginManager from '@jbrowse/core/PluginManager'
@@ -14,7 +15,6 @@ import {
14
15
  referenceAligner,
15
16
  walkAligner,
16
17
  } from './walkLanes.ts'
17
- import { walkRowsOf } from '../RgfaTabixAdapter/walkRowRuns.ts'
18
18
  import { PairTargetError } from '../synteny/lanePairs.ts'
19
19
 
20
20
  import type { PairChain } from '@gmod/gbz-base/pairAlignment'