jbrowse-plugin-graphgenomeviewer 4.0.5 → 4.0.7
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 +55 -236
- package/dist/chunks/AddTrackWorkflow-J44PELJE.js +2 -0
- package/dist/chunks/AddTrackWorkflow-J44PELJE.js.map +7 -0
- package/dist/chunks/GraphGenomeView-U4XVAEO3.js +10 -0
- package/dist/chunks/GraphGenomeView-U4XVAEO3.js.map +7 -0
- package/dist/chunks/GraphTrackSettingsDialog-6KKN5F3W.js +4 -0
- package/dist/chunks/GraphTrackSettingsDialog-6KKN5F3W.js.map +7 -0
- package/dist/chunks/LinearGraphDisplay-IBECRYKJ.js +2 -0
- package/dist/chunks/LinearGraphDisplay-IBECRYKJ.js.map +7 -0
- package/dist/chunks/chunk-C6PIPNZS.js +2 -0
- package/dist/chunks/chunk-C6PIPNZS.js.map +7 -0
- package/dist/chunks/chunk-IVUTPSHP.js +2 -0
- package/dist/chunks/chunk-IVUTPSHP.js.map +7 -0
- package/dist/chunks/chunk-J2UKZSOC.js +2 -0
- package/dist/chunks/chunk-J2UKZSOC.js.map +7 -0
- package/dist/chunks/chunk-MT25CI4U.js +4 -0
- package/dist/chunks/chunk-MT25CI4U.js.map +7 -0
- package/dist/chunks/chunk-N7EFSGPU.js +2 -0
- package/dist/chunks/chunk-N7EFSGPU.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 +1 -1
- package/src/GbzBaseSyntenyAdapter/index.ts +1 -2
- package/src/GetSubgraph.test.ts +1 -1
- package/src/GetSubgraph.ts +8 -1
- package/src/GraphAddTrackWorkflow/buildTrackConfig.test.ts +0 -4
- package/src/GraphAddTrackWorkflow/buildTrackConfig.ts +6 -14
- package/src/GraphComputeLayout.ts +7 -13
- package/src/GraphGenomeView/bubbles/bubbleHalos.test.ts +12 -1
- package/src/GraphGenomeView/bubbles/bubbleHalos.ts +16 -11
- package/src/GraphGenomeView/bubbles/classifyBubble.test.ts +47 -12
- package/src/GraphGenomeView/bubbles/classifyBubble.ts +45 -6
- package/src/GraphGenomeView/colorSchemes.ts +16 -0
- package/src/GraphGenomeView/components/BubbleHalos.tsx +10 -96
- package/src/GraphGenomeView/components/BubbleOverlay.tsx +18 -37
- package/src/GraphGenomeView/components/ColorSchemeSelect.tsx +3 -3
- package/src/GraphGenomeView/components/GenePins.tsx +7 -47
- package/src/GraphGenomeView/components/GraphCanvas.tsx +83 -66
- package/src/GraphGenomeView/components/GraphGenomeView.test.tsx +3 -3
- package/src/GraphGenomeView/components/GraphGenomeView.tsx +2 -2
- package/src/GraphGenomeView/components/GraphLoadStatus.tsx +2 -2
- package/src/GraphGenomeView/components/GraphSettingsDialog.tsx +11 -11
- package/src/GraphGenomeView/components/GraphStats.tsx +3 -4
- package/src/GraphGenomeView/components/GraphToolbar.tsx +5 -5
- package/src/GraphGenomeView/components/ImportForm.tsx +2 -2
- package/src/GraphGenomeView/components/LabelChip.tsx +1 -1
- package/src/GraphGenomeView/components/LabelLayer.tsx +106 -0
- package/src/GraphGenomeView/components/LayoutSelect.tsx +3 -3
- package/src/GraphGenomeView/components/RepeatSelect.tsx +3 -3
- package/src/GraphGenomeView/components/SettingsMenu.tsx +2 -2
- package/src/GraphGenomeView/components/WalkRowsOverlay.tsx +13 -6
- package/src/GraphGenomeView/components/WalkSelect.tsx +2 -2
- package/src/GraphGenomeView/graphLabels.ts +74 -75
- package/src/GraphGenomeView/host.ts +4 -3
- package/src/GraphGenomeView/index.ts +1 -1
- package/src/GraphGenomeView/labelLayout.test.ts +220 -0
- package/src/GraphGenomeView/labelLayout.ts +223 -0
- package/src/GraphGenomeView/layoutModes.ts +11 -10
- package/src/GraphGenomeView/model.test.ts +102 -315
- package/src/GraphGenomeView/model.ts +424 -813
- package/src/GraphGenomeView/nodeWidths.ts +21 -0
- package/src/GraphGenomeView/{components/overlayLabels.test.ts → overlayLabels.test.ts} +17 -2
- package/src/GraphGenomeView/{components/overlayLabels.ts → overlayLabels.ts} +47 -18
- package/src/GraphGenomeView/pipeline.ts +227 -0
- package/src/GraphGenomeView/renderPasses.bench.ts +31 -24
- package/src/GraphGenomeView/renderPipeline.test.ts +8 -1
- package/src/GraphGenomeView/renderer/recordingCanvas.ts +1 -2
- package/src/GraphGenomeView/subgraphLoad.test.ts +20 -12
- package/src/GraphGenomeView/viewModel.ts +135 -0
- package/src/LaunchGraphGenomeView.ts +3 -3
- package/src/LinearGraphDisplay/LinearGraphDisplay.test.ts +157 -30
- package/src/LinearGraphDisplay/components/GraphTrackSettingsDialog.tsx +22 -0
- package/src/LinearGraphDisplay/components/LinearGraphDisplay.tsx +15 -36
- package/src/{GraphGenomeView → LinearGraphDisplay}/components/SubgraphContextSelect.tsx +7 -10
- package/src/{GraphGenomeView → LinearGraphDisplay}/components/SubgraphHaplotypesField.tsx +11 -12
- package/src/LinearGraphDisplay/configSchema.ts +1 -2
- package/src/LinearGraphDisplay/model.ts +291 -234
- package/src/RgfaTabixAdapter/index.ts +1 -1
- package/src/core.test.ts +29 -0
- package/src/core.ts +111 -0
- package/src/graphTrackConfig.test.ts +20 -0
- package/src/graphTrackConfig.ts +33 -0
- package/src/graphTrackDefaults/graphTrackDefaults.test.ts +49 -0
- package/src/graphTrackDefaults/index.ts +51 -0
- package/src/hoverSync/graphViewHighlights.test.ts +2 -2
- package/src/hoverSync/graphViewHighlights.ts +16 -17
- package/src/index.ts +2 -0
- package/src/launchFromGraph/launchFromGraph.ts +7 -2
- package/src/launchFromGraph/launchTracks.ts +1 -1
- package/src/launchFromGraph/syntenyTracks.ts +1 -1
- package/src/version.ts +1 -1
- package/dist/chunks/AddTrackWorkflow-I4EPGFPJ.js +0 -2
- package/dist/chunks/AddTrackWorkflow-I4EPGFPJ.js.map +0 -7
- package/dist/chunks/GraphGenomeView-BQYWWF6Z.js +0 -10
- package/dist/chunks/GraphGenomeView-BQYWWF6Z.js.map +0 -7
- package/dist/chunks/GraphSettingsDialog-KQK4YZN5.js +0 -2
- package/dist/chunks/GraphSettingsDialog-KQK4YZN5.js.map +0 -7
- package/dist/chunks/LinearGraphDisplay-7O3VQHKU.js +0 -2
- package/dist/chunks/LinearGraphDisplay-7O3VQHKU.js.map +0 -7
- package/dist/chunks/chunk-5WJPRX4N.js +0 -2
- package/dist/chunks/chunk-5WJPRX4N.js.map +0 -7
- package/dist/chunks/chunk-FCWXYIFC.js +0 -2
- package/dist/chunks/chunk-FCWXYIFC.js.map +0 -7
- package/dist/chunks/chunk-OHT6UX4C.js +0 -4
- package/dist/chunks/chunk-OHT6UX4C.js.map +0 -7
- package/dist/chunks/chunk-OP7IRVG6.js +0 -2
- package/dist/chunks/chunk-OP7IRVG6.js.map +0 -7
- package/dist/chunks/chunk-RSAY56Y4.js +0 -4
- package/dist/chunks/chunk-RSAY56Y4.js.map +0 -7
- package/src/GraphGenomeView/laneRamp.test.ts +0 -97
- package/src/GraphGenomeView/laneRamp.ts +0 -88
- package/src/launchSubgraph/launchSubgraphView.ts +0 -132
- package/src/launchSubgraph/subgraphTracks.test.ts +0 -165
- package/src/launchSubgraph/subgraphTracks.ts +0 -151
- package/src/launchSubgraph/testEnv.ts +0 -255
package/README.md
CHANGED
|
@@ -1,267 +1,86 @@
|
|
|
1
1
|
# jbrowse-plugin-graphgenomeviewer
|
|
2
2
|
|
|
3
|
-
A JBrowse 2 plugin that draws a pangenome graph (GFA / rGFA
|
|
4
|
-
linear genome view, and as a **GraphGenomeView** of
|
|
5
|
-
|
|
6
|
-
## Screenshots
|
|
7
|
-
|
|
8
|
-
The LPA KIV-2 window of the HPRC release 2 graph in the **force-directed
|
|
9
|
-
layout**: the GRCh38 backbone runs left to right, coloured by position the way
|
|
10
|
-
the rGFA segments track above it is, and the kringle repeat array is the knot of
|
|
11
|
-
loops in the middle. Each bubble the graph holds is haloed along its own nodes
|
|
12
|
-
and labelled by what it is; the label opens the bubble on its own.
|
|
3
|
+
A JBrowse 2 plugin that draws a pangenome graph (GFA / rGFA, or a gbz-base
|
|
4
|
+
database) as a track of a linear genome view, and as a **GraphGenomeView** of
|
|
5
|
+
its own for a whole file.
|
|
13
6
|
|
|
14
7
|

|
|
15
8
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
superbubble opens level by level:
|
|
19
|
-
|
|
20
|
-

|
|
21
|
-
|
|
22
|
-
Over a gbz-base database the cut carries the haplotypes' walks. A node draws
|
|
23
|
-
thicker the more of them carry it, Bandage's depth as width, and every route
|
|
24
|
-
through a bubble is labelled at the far point of its loop for the haplotypes
|
|
25
|
-
that take it and how long it is, so the array reads as one copy count per
|
|
26
|
-
haplotype:
|
|
9
|
+
The LPA KIV-2 window of the HPRC release 2 graph: the GRCh38 backbone runs left
|
|
10
|
+
to right, and the kringle repeat array forms the loops in the middle.
|
|
27
11
|
|
|
28
|
-
|
|
12
|
+
## Core ideas
|
|
29
13
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
14
|
+
- **Six layouts, one graph.** Force-directed (Bandage's OGDF FMMM, compiled to
|
|
15
|
+
wasm) shows the graph's shape; the variant map, ordered, anchored, sample-row
|
|
16
|
+
and walk-row layouts put it on reference coordinates so it lines up under a
|
|
17
|
+
linear view.
|
|
18
|
+
- **Bubbles are the unit.** The plugin reads `gfatools bubble` output beside an
|
|
19
|
+
rGFA index, or derives bubbles from the graph itself, then marks them and
|
|
20
|
+
opens any one level by level.
|
|
21
|
+
- **Haplotypes as walks.** Over gbz-base a node draws thicker the more
|
|
22
|
+
haplotypes carry it, and picking one walk lifts its route out of the drawing
|
|
23
|
+
with its length against the reference.
|
|
33
24
|
|
|
34
25
|

|
|
35
26
|
|
|
36
|
-
|
|
37
|
-
and a run of small indels follows it. The session's gene track is drawn onto the
|
|
38
|
-
graph: exons as dark stretches along the backbone nodes that carry them, and
|
|
39
|
-
each gene's name pinned under the backbone at its midpoint, so the superbubble
|
|
40
|
-
reads as HLA-DRB5's and the indels as HLA-DRB6's and HLA-DRB1's:
|
|
41
|
-
|
|
42
|
-

|
|
43
|
-
|
|
44
|
-
The KIV-2 window as a **variant map**, the reference as one line with one typed
|
|
45
|
-
glyph per bubble:
|
|
46
|
-
|
|
47
|
-

|
|
48
|
-
|
|
49
|
-
It ships six layouts:
|
|
50
|
-
|
|
51
|
-
- **Force-directed**: the graph's shape, computed by the OGDF FMMM engine from
|
|
52
|
-
[Bandage](https://github.com/rrwick/Bandage), seeded along the reference and
|
|
53
|
-
turned to read left to right. The engine lays out unbranching runs rather than
|
|
54
|
-
nodes, so a base-level cut of 15,000 nodes draws in a few seconds. The Walk
|
|
55
|
-
picker lifts one haplotype out: its route keeps its ink, the rest fades, and a
|
|
56
|
-
readout gives its length against the reference.
|
|
57
|
-
- **Variant map** (rGFA or a reference path): the reference as a line, one typed
|
|
58
|
-
glyph per bubble, click to open a bubble's graph, and again for a bubble
|
|
59
|
-
inside it.
|
|
60
|
-
- **Ordered** (rGFA or a reference path): x is reference order rather than bp,
|
|
61
|
-
so every node gets room and a bubble reads as a lens. Scrolls sideways.
|
|
62
|
-
- **Anchored** (rGFA or a reference path): x is reference bp, one row per stable
|
|
63
|
-
rank, aligned under a linear view.
|
|
64
|
-
- **Sample rows**: x is reference bp, one row per contributing assembly.
|
|
65
|
-
- **Walk rows** (W or P lines): x is each walk's own bp, one bar per haplotype,
|
|
66
|
-
sequence the reference also carries in blue and sequence it does not in
|
|
67
|
-
purple, so a repeat expansion reads as bar length. The Repeat picker tiles the
|
|
68
|
-
bars by a repeat annotation's unit and marks the allele a genotyper called.
|
|
69
|
-
|
|
70
|
-
The bubbles come from `gfatools bubble` output beside the rGFA index
|
|
71
|
-
(`<prefix>.bubbles.bed.gz`), which HPRC's hosted graph has and
|
|
72
|
-
`scripts/build_rgfa_tabix.sh` in jbrowse-components writes, or, for a graph with
|
|
73
|
-
no index, a GBZ cut, a pggb file or a popped bubble, from the graph itself off
|
|
74
|
-
the ordered layout's layering. Every node layout marks them as halos; the
|
|
75
|
-
variant map draws them as glyphs.
|
|
76
|
-
|
|
77
|
-
### The graph as a track
|
|
78
|
-
|
|
79
|
-
A graph track's display is `LinearGraphDisplay`. It cuts the view's window plus
|
|
80
|
-
a window-width each side and re-cuts once the view leaves the cut, keeping its
|
|
81
|
-
sample rows in the order they were drawn. On a layout whose x is reference bp,
|
|
82
|
-
such as Anchored, Sample rows, Walk rows or the Variant map, the graph draws
|
|
83
|
-
under the view's own coordinates and pans and zooms with it. The force-directed
|
|
84
|
-
and ordered layouts draw in their own coordinates inside the track, fitted to
|
|
85
|
-
it, with their own zoom in the track menu, the way a variant matrix does. The
|
|
86
|
-
track menu also picks the layout, the colour, a walk to lift out, and opens the
|
|
87
|
-
settings.
|
|
27
|
+
## Usage
|
|
88
28
|
|
|
89
29
|
```json
|
|
90
30
|
{
|
|
91
|
-
"
|
|
92
|
-
"trackId": "hprc_graph",
|
|
93
|
-
"name": "HPRC release 2 graph",
|
|
94
|
-
"assemblyNames": ["hg38"],
|
|
95
|
-
"adapter": { "type": "RgfaTabixAdapter", "uri": "https://example.com/hprc" },
|
|
96
|
-
"displays": [
|
|
97
|
-
{
|
|
98
|
-
"type": "LinearGraphDisplay",
|
|
99
|
-
"displayId": "hprc_graph-LinearGraphDisplay"
|
|
100
|
-
},
|
|
31
|
+
"plugins": [
|
|
101
32
|
{
|
|
102
|
-
"
|
|
103
|
-
"
|
|
33
|
+
"name": "GraphGenomeView",
|
|
34
|
+
"esmUrl": "https://unpkg.com/jbrowse-plugin-graphgenomeviewer/dist/jbrowse-plugin-graphgenomeviewer.esm.js"
|
|
104
35
|
}
|
|
105
36
|
]
|
|
106
37
|
}
|
|
107
38
|
```
|
|
108
39
|
|
|
109
|
-
The
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
`aboveBpPerPx` in the linear view the track cuts that pair instead, with no bp
|
|
115
|
-
cap:
|
|
116
|
-
|
|
117
|
-
```json
|
|
118
|
-
{
|
|
119
|
-
"type": "RgfaTabixAdapter",
|
|
120
|
-
"uri": "https://example.com/hprc-v2.0-mc-grch38",
|
|
121
|
-
"coarse": {
|
|
122
|
-
"uri": "https://example.com/hprc-v2.0-mc-grch38.tier10000",
|
|
123
|
-
"aboveBpPerPx": 1000
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
**Add → Graph genome view** opens a whole GFA file in a view of its own, with
|
|
129
|
-
the same layouts and its own pan and zoom.
|
|
130
|
-
|
|
131
|
-
### Demonstration loci
|
|
132
|
-
|
|
133
|
-
Six HPRC release 2 windows, the ones the
|
|
134
|
-
[HPRC tutorials](https://jbrowse.org/jb2/docs/tutorials/pangenome_hprc/) walk
|
|
135
|
-
through, are the standing test set for layout screenshots. Each cuts to under
|
|
136
|
-
300 nodes and shows a different kind of variation:
|
|
137
|
-
|
|
138
|
-
| Locus | Window | What it shows |
|
|
139
|
-
| ------------ | ------------------------------ | ----------------------------------- |
|
|
140
|
-
| LPA KIV-2 | `chr6:160,525,000-160,655,000` | the kringle repeat, copy per loop |
|
|
141
|
-
| MHC class II | `chr6:32,510,000-32,600,000` | DRB haplotypes, dozens of alleles |
|
|
142
|
-
| AMY1 | `chr1:103,690,000-103,780,000` | amylase copy number |
|
|
143
|
-
| C4 | `chr6:31,980,000-32,050,000` | one bubble over the C4 duplication |
|
|
144
|
-
| CFH | `chr1:196,640,000-196,900,000` | an 84 kb deletion as a bare edge |
|
|
145
|
-
| KIR | `chr19:54,750,000-54,840,000` | the KIR cluster, densest of the six |
|
|
146
|
-
|
|
147
|
-
[docs/layout-experiments.md](docs/layout-experiments.md) draws all six in every
|
|
148
|
-
layout the plugin has and in the ones proposed to replace them, and
|
|
149
|
-
`scripts/layout-lab/` reproduces the figures.
|
|
150
|
-
|
|
151
|
-
## License (GPL-3.0)
|
|
152
|
-
|
|
153
|
-
This plugin is **GPL-3.0-or-later**. The force-directed layout is computed by a
|
|
154
|
-
WebAssembly build of Bandage's FMMM layout from [OGDF](https://ogdf.github.io/),
|
|
155
|
-
and both Bandage and OGDF are GPL-licensed, so this plugin takes the same
|
|
156
|
-
license rather than linking around it.
|
|
157
|
-
|
|
158
|
-
JBrowse itself is unaffected and stays Apache-2.0: this is a separate plugin,
|
|
159
|
-
loaded at runtime only by configs that ask for it. The anchored and sample-row
|
|
160
|
-
layouts are pure TypeScript and need no external engine.
|
|
161
|
-
|
|
162
|
-
## Developing
|
|
163
|
-
|
|
164
|
-
Requires [pnpm](https://pnpm.io/installation). The plugin builds against the
|
|
165
|
-
published `@jbrowse/*` packages at 5.0.0-beta.9 and needs a host of at least
|
|
166
|
-
that version: it hands its RPC calls an AbortSignal, which an earlier JBrowse 5
|
|
167
|
-
beta cannot post to its worker.
|
|
168
|
-
|
|
169
|
-
```console
|
|
170
|
-
pnpm install
|
|
171
|
-
pnpm start # esbuild watch, serves dist/out.js on :9000 with CORS
|
|
172
|
-
```
|
|
173
|
-
|
|
174
|
-
In another terminal, serve a JBrowse Web that points at `config.json` (its
|
|
175
|
-
`plugins` entry already targets `http://localhost:9000/dist/out.js`).
|
|
176
|
-
|
|
177
|
-
## Building
|
|
178
|
-
|
|
179
|
-
```console
|
|
180
|
-
pnpm build # native ESM bundle via esbuild (code-split)
|
|
181
|
-
pnpm typecheck # tsc, separately — esbuild strips types without checking them
|
|
182
|
-
```
|
|
183
|
-
|
|
184
|
-
This writes the plugin to `dist/`, and the **whole directory must be served
|
|
185
|
-
together** — the entry loads its sibling chunks relative to its own url:
|
|
186
|
-
|
|
187
|
-
- `jbrowse-plugin-graphgenomeviewer.esm.js` — the plugin entry
|
|
188
|
-
- `chunks/bandage-layout-<hash>.js` — the Bandage layout engine (~425kb),
|
|
189
|
-
imported on demand and named by content hash so a redeployed engine is never
|
|
190
|
-
served from cache
|
|
191
|
-
- `chunks/*.js` — other lazily-loaded code split out of the entry
|
|
192
|
-
|
|
193
|
-
Load the plugin from any JBrowse config, 5.0.0-beta.9 or later, with an
|
|
194
|
-
`esmUrl`:
|
|
40
|
+
The plugin needs a JBrowse host of 5.0.0-beta.9 or later. **File → Open track**
|
|
41
|
+
takes a `.segs.bed.gz` url from `build_rgfa_tabix.sh` and opens it as a graph
|
|
42
|
+
track with no config. A hand-written track needs only the adapter; a
|
|
43
|
+
`FeatureTrack` over an rGFA opens as `LinearGraphDisplay` unless its config
|
|
44
|
+
lists `displays`:
|
|
195
45
|
|
|
196
46
|
```json
|
|
197
47
|
{
|
|
198
|
-
"
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
48
|
+
"type": "FeatureTrack",
|
|
49
|
+
"trackId": "hprc_graph",
|
|
50
|
+
"name": "HPRC release 2 graph",
|
|
51
|
+
"assemblyNames": ["hg38"],
|
|
52
|
+
"adapter": {
|
|
53
|
+
"type": "RgfaTabixAdapter",
|
|
54
|
+
"uri": "https://example.com/hprc",
|
|
55
|
+
"coarse": {
|
|
56
|
+
"uri": "https://example.com/hprc.tier10000",
|
|
57
|
+
"aboveBpPerPx": 1000
|
|
202
58
|
}
|
|
203
|
-
|
|
59
|
+
}
|
|
204
60
|
}
|
|
205
61
|
```
|
|
206
62
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
63
|
+
The display cuts the visible window plus one window-width each side, up to 5 Mb.
|
|
64
|
+
Past `aboveBpPerPx` it cuts the optional `coarse` tier instead, one node per
|
|
65
|
+
bubble with no size cap, built by `build_bubble_tier.sh` in jbrowse-components.
|
|
66
|
+
Layouts on reference bp pan and zoom with the view; the force-directed and
|
|
67
|
+
ordered layouts fit the track and zoom from its menu. The track menu picks the
|
|
68
|
+
layout, colour and walk, and switches to the segments lane, one block per
|
|
69
|
+
segment.
|
|
212
70
|
|
|
213
|
-
|
|
214
|
-
the force-directed layout, so sessions that use the anchored or sample-row
|
|
215
|
-
layouts never download it. Its url is not configured anywhere — `loadBandage` is
|
|
216
|
-
a plain dynamic `import()`, so the browser resolves the chunk relative to the
|
|
217
|
-
plugin module's own url (`import.meta.url`, defined on the main thread and in
|
|
218
|
-
the RPC worker alike). That is why the whole `dist/` has to be served together,
|
|
219
|
-
and it is also why there is nothing to point elsewhere: to host the engine on
|
|
220
|
-
another origin, rebuild with the chunk emitted there.
|
|
71
|
+
**Add → Graph genome view** opens a whole GFA file in its own view.
|
|
221
72
|
|
|
222
|
-
|
|
73
|
+
## Docs
|
|
223
74
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
```
|
|
231
|
-
|
|
232
|
-
Emscripten is the only thing you have to install. OGDF is vendored at
|
|
233
|
-
`vendor/ogdf` (a stock checkout of it does not build for wasm at all — see
|
|
234
|
-
[`vendor/README.md`](vendor/README.md)), so this works offline from a fresh
|
|
235
|
-
clone of this repo alone. Roughly four minutes the first time, seconds after
|
|
236
|
-
that.
|
|
237
|
-
|
|
238
|
-
It compiles with `-sSINGLE_FILE=1`, embedding the wasm as base64 so the result
|
|
239
|
-
is one self-contained ES module that esbuild can copy rather than bundle.
|
|
240
|
-
|
|
241
|
-
A rebuild has to be checked against the drawing rather than against the file,
|
|
242
|
-
since the artifact's bytes move for reasons the layout does not — see
|
|
243
|
-
[`src/bandage/README.md`](src/bandage/README.md) for
|
|
244
|
-
`scripts/layout-digest.mjs`.
|
|
245
|
-
|
|
246
|
-
## Testing
|
|
247
|
-
|
|
248
|
-
```console
|
|
249
|
-
pnpm test # vitest unit tests
|
|
250
|
-
pnpm test:watch
|
|
251
|
-
pnpm test:wasm # runs the committed Bandage engine, no deps needed
|
|
252
|
-
pnpm test:e2e # puppeteer, opt-in — see test/README.md
|
|
253
|
-
pnpm host-compat # boots dist/ on the hosted JBrowse releases and cuts a graph
|
|
254
|
-
pnpm lint
|
|
255
|
-
pnpm typecheck
|
|
256
|
-
```
|
|
75
|
+
- [docs/layouts.md](docs/layouts.md) — every layout, bubbles, walks, genes on
|
|
76
|
+
the graph, and the demonstration loci
|
|
77
|
+
- [docs/developing.md](docs/developing.md) — dev server, building, the Bandage
|
|
78
|
+
engine, testing and `host-compat`
|
|
79
|
+
- [docs/layout-experiments.md](docs/layout-experiments.md) — all six loci in
|
|
80
|
+
every layout, current and proposed
|
|
257
81
|
|
|
258
|
-
|
|
259
|
-
browser, behind `RUN_E2E=1` because it needs a jbrowse-web build to serve;
|
|
260
|
-
[`test/README.md`](test/README.md) explains how to run it.
|
|
82
|
+
## License
|
|
261
83
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
the unit tests: an RPC argument a released core cannot post to its worker, or a
|
|
266
|
-
re-export the host no longer serves, shows only when the bundle runs on the
|
|
267
|
-
host.
|
|
84
|
+
GPL-3.0-or-later, because the force-directed layout runs a wasm build of
|
|
85
|
+
Bandage's FMMM layout from [OGDF](https://ogdf.github.io/), and both are GPL.
|
|
86
|
+
JBrowse stays Apache-2.0, since configs load this plugin separately at runtime.
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{a as W,b as F,c as T,f as y}from"./chunk-C6PIPNZS.js";import"./chunk-D7XFR2IV.js";import{a as N}from"./chunk-J4OLMLS5.js";import{a as C,b as B,c as H,d as _,e as O}from"./chunk-XEJ47DLD.js";import{a as w,b as t}from"./chunk-FY3BTKY4.js";var S=w((q,L)=>{L.exports=JBrowseExports["@jbrowse/core/util/tss-react"]});var s=t(O(),1),i=t(_(),1),l=t(N(),1),A=t(S(),1),R=t(W(),1),e=t(H(),1),x=t(B(),1);var o=t(C(),1),j=(0,A.makeStyles)()(n=>({paper:{margin:n.spacing(),padding:n.spacing()},field:{marginTop:n.spacing(2)},submit:{marginTop:25,marginBottom:100,display:"block"}})),D=["RgfaTabixAdapter","MinigraphBubbleAdapter"],J=(0,x.observer)(function({model:r}){let{classes:c}=j(),h=(0,l.getSession)(r),b=(0,R.getRoot)(r),[m,G]=(0,s.useState)("RgfaTabixAdapter"),[p,v]=(0,s.useState)(),[g,P]=(0,s.useState)(),[u,I]=(0,s.useState)(""),[d,M]=(0,s.useState)("Pangenome graph"),[f,k]=(0,s.useState)();function E(){if(!(!p||!r.assembly))try{k(void 0);let a=d.trim();(0,l.addTrackFromWidget)({model:r,session:h,conf:y({choice:m,loc:p,indexLoc:g,assembly:r.assembly,sample:u,trackId:(0,l.makeTrackId)({name:a}),name:a})})}catch(a){k(a)}}return(0,o.jsxs)(e.Paper,{className:c.paper,children:[f?(0,o.jsx)(i.ErrorMessage,{error:f}):null,(0,o.jsxs)(e.FormControl,{children:[(0,o.jsx)(e.FormLabel,{children:"File type"}),(0,o.jsx)(e.RadioGroup,{value:m,onChange:a=>{G(a.target.value)},children:D.map(a=>(0,o.jsx)(e.FormControlLabel,{value:a,control:(0,o.jsx)(e.Radio,{}),label:F[a]},a))})]}),(0,o.jsx)(i.FileSelector,{location:p,name:T[m],rootModel:b,setLocation:v}),(0,o.jsx)(i.FileSelector,{location:g,name:"Path to tabix index (optional; the sibling .tbi is assumed, a .csi is recognised by name)",rootModel:b,setLocation:P}),(0,o.jsx)(e.TextField,{className:c.field,value:u,onChange:a=>{I(a.target.value)},label:"Sample name in the graph",slotProps:{htmlInput:{"data-testid":"graph-sample-input"}},helperText:"Optional. The PanSN prefix the graph gives this assembly, e.g. GRCh38 for HPRC's GRCh38#0#chr1; leave blank when the graph's stable names are bare",placeholder:"GRCh38",fullWidth:!0}),(0,o.jsx)(e.TextField,{className:c.field,value:d,helperText:"Track name",slotProps:{htmlInput:{"data-testid":"graph-track-name-input"}},onChange:a=>{M(a.target.value)}}),(0,o.jsx)(i.AssemblySelector,{session:h,helperText:"Select assembly to add track to",selected:r.assembly,onChange:a=>{r.setAssembly(a)},fullWidth:!0}),(0,o.jsx)(e.Button,{variant:"contained",className:c.submit,disabled:!p||!d.trim()||!r.assembly,onClick:E,children:"Submit"})]})}),K=J;export{K as default};
|
|
2
|
+
//# sourceMappingURL=AddTrackWorkflow-J44PELJE.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["global-externals:@jbrowse/core/util/tss-react", "../../src/GraphAddTrackWorkflow/AddTrackWorkflow.tsx"],
|
|
4
|
+
"sourcesContent": ["module.exports = JBrowseExports[\"@jbrowse/core/util/tss-react\"];", "import { useState } from 'react'\n\nimport { AssemblySelector, ErrorMessage, FileSelector } from '@jbrowse/core/ui'\nimport { addTrackFromWidget, getSession, makeTrackId } from '@jbrowse/core/util'\nimport { makeStyles } from '@jbrowse/core/util/tss-react'\nimport { getRoot } from '@jbrowse/mobx-state-tree'\nimport {\n Button,\n FormControl,\n FormControlLabel,\n FormLabel,\n Paper,\n Radio,\n RadioGroup,\n TextField,\n} from '@mui/material'\nimport { observer } from 'mobx-react'\n\nimport {\n GRAPH_FILE_FIELDS,\n GRAPH_FILE_LABELS,\n buildTrackConfig,\n} from './buildTrackConfig'\n\nimport type { GraphFileChoice } from './buildTrackConfig'\nimport type {\n AbstractRootModel,\n AddTrackWorkflowModel,\n FileLocation,\n} from '@jbrowse/core/util'\n\nconst useStyles = makeStyles()(theme => ({\n paper: {\n margin: theme.spacing(),\n padding: theme.spacing(),\n },\n field: {\n marginTop: theme.spacing(2),\n },\n submit: {\n marginTop: 25,\n marginBottom: 100,\n display: 'block',\n },\n}))\n\nconst CHOICES: GraphFileChoice[] = [\n 'RgfaTabixAdapter',\n 'MinigraphBubbleAdapter',\n]\n\nconst GraphAddTrackWidget = observer(function GraphAddTrackWidget({\n model,\n}: {\n model: AddTrackWorkflowModel\n}) {\n const { classes } = useStyles()\n const session = getSession(model)\n const rootModel = getRoot<AbstractRootModel>(model)\n const [choice, setChoice] = useState<GraphFileChoice>('RgfaTabixAdapter')\n const [loc, setLoc] = useState<FileLocation>()\n const [indexLoc, setIndexLoc] = useState<FileLocation>()\n const [sample, setSample] = useState('')\n const [trackName, setTrackName] = useState('Pangenome graph')\n const [error, setError] = useState<unknown>()\n\n function handleSubmit() {\n if (!loc || !model.assembly) {\n return\n }\n try {\n setError(undefined)\n const name = trackName.trim()\n addTrackFromWidget({\n model,\n session,\n conf: buildTrackConfig({\n choice,\n loc,\n indexLoc,\n assembly: model.assembly,\n sample,\n trackId: makeTrackId({ name }),\n name,\n }),\n })\n } catch (e) {\n setError(e)\n }\n }\n\n return (\n <Paper className={classes.paper}>\n {error ? <ErrorMessage error={error} /> : null}\n <FormControl>\n <FormLabel>File type</FormLabel>\n <RadioGroup\n value={choice}\n onChange={event => {\n setChoice(event.target.value as GraphFileChoice)\n }}\n >\n {CHOICES.map(option => (\n <FormControlLabel\n key={option}\n value={option}\n control={<Radio />}\n label={GRAPH_FILE_LABELS[option]}\n />\n ))}\n </RadioGroup>\n </FormControl>\n <FileSelector\n location={loc}\n name={GRAPH_FILE_FIELDS[choice]}\n rootModel={rootModel}\n setLocation={setLoc}\n />\n <FileSelector\n location={indexLoc}\n name=\"Path to tabix index (optional; the sibling .tbi is assumed, a .csi is recognised by name)\"\n rootModel={rootModel}\n setLocation={setIndexLoc}\n />\n <TextField\n className={classes.field}\n value={sample}\n onChange={event => {\n setSample(event.target.value)\n }}\n label=\"Sample name in the graph\"\n slotProps={{ htmlInput: { 'data-testid': 'graph-sample-input' } }}\n helperText=\"Optional. The PanSN prefix the graph gives this assembly, e.g. GRCh38 for HPRC's GRCh38#0#chr1; leave blank when the graph's stable names are bare\"\n placeholder=\"GRCh38\"\n fullWidth\n />\n <TextField\n className={classes.field}\n value={trackName}\n helperText=\"Track name\"\n slotProps={{ htmlInput: { 'data-testid': 'graph-track-name-input' } }}\n onChange={event => {\n setTrackName(event.target.value)\n }}\n />\n <AssemblySelector\n session={session}\n helperText=\"Select assembly to add track to\"\n selected={model.assembly}\n onChange={arg => {\n model.setAssembly(arg)\n }}\n fullWidth\n />\n <Button\n variant=\"contained\"\n className={classes.submit}\n disabled={!loc || !trackName.trim() || !model.assembly}\n onClick={handleSubmit}\n >\n Submit\n </Button>\n </Paper>\n )\n})\n\nexport default GraphAddTrackWidget\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["require_tss_react", "__commonJSMin", "exports", "module", "import_react", "import_ui", "import_util", "import_tss_react", "import_mobx_state_tree", "import_material", "import_mobx_react", "import_jsx_runtime", "useStyles", "theme", "CHOICES", "GraphAddTrackWidget", "model", "classes", "session", "rootModel", "choice", "setChoice", "loc", "setLoc", "indexLoc", "setIndexLoc", "sample", "setSample", "trackName", "setTrackName", "error", "setError", "handleSubmit", "name", "buildTrackConfig", "e", "event", "option", "GRAPH_FILE_LABELS", "GRAPH_FILE_FIELDS", "arg", "AddTrackWorkflow_default"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import{a as x}from"./chunk-MT25CI4U.js";import"./chunk-J2UKZSOC.js";import"./chunk-ZNGDWZ6Z.js";import"./chunk-N7EFSGPU.js";import{G as L}from"./chunk-IVUTPSHP.js";import"./chunk-F4C3BEPV.js";import{a as s,b as g,c as v,d as G,e as B}from"./chunk-XEJ47DLD.js";import{b as a}from"./chunk-FY3BTKY4.js";var S=a(g(),1);var m=a(G(),1),n=a(v(),1),C=a(g(),1),P=a(L(),1),o=a(s(),1),I=(0,P.makeStyles)()({paper:{padding:16,margin:8,maxWidth:560,marginInline:"auto",display:"flex",flexDirection:"column",gap:12},row:{display:"flex",alignItems:"center",justifyContent:"space-between",gap:8}}),b=(0,C.observer)(function({model:e}){let{classes:r}=I();return e.isLoading?(0,o.jsxs)(n.Paper,{className:r.paper,"data-testid":"graph-genome-loading",children:[(0,o.jsxs)("div",{className:r.row,children:[(0,o.jsx)(m.LoadingEllipses,{variant:"h6",message:e.statusMessage}),(0,o.jsx)(n.Button,{size:"small","data-testid":"graph-genome-cancel",onClick:()=>{e.cancelLoad()},children:"Cancel"})]}),(0,o.jsx)(n.LinearProgress,{variant:"indeterminate"})]}):e.error?(0,o.jsx)(n.Paper,{className:r.paper,children:(0,o.jsx)(m.ErrorBanner,{error:e.error,onReset:()=>{e.retryLoad()}})}):(0,o.jsx)(n.Paper,{className:r.paper,"data-testid":"graph-genome-load-canceled",children:(0,o.jsxs)("div",{className:r.row,children:[(0,o.jsx)(n.Typography,{variant:"h6",children:"Loading canceled"}),(0,o.jsx)(n.Button,{variant:"contained",size:"small","data-testid":"graph-genome-retry",onClick:()=>{e.retryLoad()},children:"Retry"})]})})}),h=b;var M=a(B(),1),N=a(G(),1),i=a(v(),1),w=a(g(),1),E=a(L(),1),t=a(s(),1),k=`H VN:Z:1.0
|
|
2
|
+
S 1 ACGT
|
|
3
|
+
S 2 GGCC
|
|
4
|
+
S 3 TTAA
|
|
5
|
+
S 4 CCGG
|
|
6
|
+
L 1 + 2 + 0M
|
|
7
|
+
L 1 + 3 + 0M
|
|
8
|
+
L 2 + 4 + 0M
|
|
9
|
+
L 3 + 4 + 0M`,z=(0,E.makeStyles)()({column:{display:"flex",flexDirection:"column",gap:8},rowEnd:{display:"flex",gap:8,alignItems:"flex-end"},rowCenter:{display:"flex",gap:8,alignItems:"center"},flex1:{flex:1},paper:{padding:16,margin:8,maxWidth:560,marginInline:"auto"},header:{marginBottom:12},footer:{marginTop:12,display:"flex",justifyContent:"flex-end"}}),R=(0,w.observer)(function({model:e}){let{classes:r}=z(),[d,T]=(0,M.useState)("");function y(){d.trim()&&e.loadGFAFromLocation({uri:d,locationType:"UriLocation"})}function A(p){let c=p.target.files?.[0];c&&c.text().then(f=>e.loadGFA(f,c.name)).catch(f=>{e.setError(f)})}return(0,t.jsxs)(i.Paper,{className:r.paper,children:[(0,t.jsx)("div",{className:r.header,children:(0,t.jsx)(i.Typography,{variant:"h6",children:"Load a GFA graph"})}),(0,t.jsxs)("div",{className:r.column,children:[(0,t.jsxs)("div",{className:r.rowCenter,children:[(0,t.jsxs)(i.Button,{variant:"outlined",component:"label",size:"small",children:["Choose file",(0,t.jsx)("input",{type:"file",accept:".gfa,.gfa1,.gfa2",hidden:!0,onChange:p=>{A(p)}})]}),(0,t.jsx)(i.Typography,{variant:"caption",color:"text.secondary",children:"Whole-file GFA; best for small/medium graphs."})]}),(0,t.jsxs)("div",{className:r.rowEnd,children:[(0,t.jsx)(i.TextField,{size:"small",label:"URL",placeholder:"https://example.com/graph.gfa",value:d,onChange:p=>{T(p.target.value)},onKeyDown:p=>{p.key==="Enter"&&y()},className:r.flex1}),(0,t.jsx)(i.Button,{variant:"contained",onClick:()=>{y()},disabled:!d.trim(),children:"Open"})]})]}),(0,t.jsx)("div",{className:r.footer,children:(0,t.jsx)(i.Button,{size:"small",onClick:()=>{e.loadGFA(k,"Example graph")},children:"Load 4-node example"})}),e.error?(0,t.jsx)(N.ErrorBanner,{error:e.error}):null]})}),F=R;var l=a(s(),1),U=(0,S.observer)(function({model:e}){return e.hasGraph?(0,l.jsx)(x,{model:e}):e.canRetryLoad&&(e.error||e.loadCanceled)?(0,l.jsx)(h,{model:e}):(0,l.jsxs)(l.Fragment,{children:[e.isLoading?(0,l.jsx)(h,{model:e}):null,(0,l.jsx)("div",{hidden:e.isLoading,children:(0,l.jsx)(F,{model:e})})]})}),O=U;export{O as default};
|
|
10
|
+
//# sourceMappingURL=GraphGenomeView-U4XVAEO3.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/GraphGenomeView/components/GraphGenomeView.tsx", "../../src/GraphGenomeView/components/GraphLoadStatus.tsx", "../../src/GraphGenomeView/components/ImportForm.tsx"],
|
|
4
|
+
"sourcesContent": ["import { observer } from 'mobx-react'\n\nimport GraphCanvas from './GraphCanvas'\nimport GraphLoadStatus from './GraphLoadStatus'\nimport ImportForm from './ImportForm'\n\nimport type { GraphPaneModel } from '../model'\n\nconst GraphGenomeView = observer(function GraphGenomeView({\n model,\n}: {\n model: GraphPaneModel\n}) {\n if (model.hasGraph) {\n return <GraphCanvas model={model} />\n }\n // A launched or restored view has a source of its own, so the import form\n // has nothing to offer it when that source fails\n if (model.canRetryLoad && (model.error || model.loadCanceled)) {\n return <GraphLoadStatus model={model} />\n }\n // Hidden rather than unmounted, so a typed URL survives a failed load\n return (\n <>\n {model.isLoading ? <GraphLoadStatus model={model} /> : null}\n <div hidden={model.isLoading}>\n <ImportForm model={model} />\n </div>\n </>\n )\n})\n\nexport default GraphGenomeView\n", "import { ErrorBanner, LoadingEllipses } from '@jbrowse/core/ui'\nimport { Button, LinearProgress, Paper, Typography } from '@mui/material'\nimport { observer } from 'mobx-react'\nimport { makeStyles } from 'tss-react/mui'\n\nimport type { GraphPaneModel } from '../model'\n\nconst useStyles = makeStyles()({\n paper: {\n padding: 16,\n margin: 8,\n maxWidth: 560,\n marginInline: 'auto',\n display: 'flex',\n flexDirection: 'column',\n gap: 12,\n },\n row: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: 8,\n },\n})\n\n// What a view with no graph on screen shows while its load runs, and after a\n// load of a source it can retry was canceled or failed.\nconst GraphLoadStatus = observer(function GraphLoadStatus({\n model,\n}: {\n model: GraphPaneModel\n}) {\n const { classes } = useStyles()\n if (model.isLoading) {\n return (\n <Paper className={classes.paper} data-testid=\"graph-genome-loading\">\n <div className={classes.row}>\n <LoadingEllipses variant=\"h6\" message={model.statusMessage} />\n <Button\n size=\"small\"\n data-testid=\"graph-genome-cancel\"\n onClick={() => {\n model.cancelLoad()\n }}\n >\n Cancel\n </Button>\n </div>\n <LinearProgress variant=\"indeterminate\" />\n </Paper>\n )\n }\n if (model.error) {\n return (\n <Paper className={classes.paper}>\n <ErrorBanner\n error={model.error}\n onReset={() => {\n model.retryLoad()\n }}\n />\n </Paper>\n )\n }\n return (\n <Paper className={classes.paper} data-testid=\"graph-genome-load-canceled\">\n <div className={classes.row}>\n <Typography variant=\"h6\">Loading canceled</Typography>\n <Button\n variant=\"contained\"\n size=\"small\"\n data-testid=\"graph-genome-retry\"\n onClick={() => {\n model.retryLoad()\n }}\n >\n Retry\n </Button>\n </div>\n </Paper>\n )\n})\n\nexport default GraphLoadStatus\n", "import { useState } from 'react'\n\nimport { ErrorBanner } from '@jbrowse/core/ui'\nimport { Button, Paper, TextField, Typography } from '@mui/material'\nimport { observer } from 'mobx-react'\nimport { makeStyles } from 'tss-react/mui'\n\nimport type { GraphPaneModel } from '../model'\n\nconst EXAMPLE_GFA = `H\\tVN:Z:1.0\nS\\t1\\tACGT\nS\\t2\\tGGCC\nS\\t3\\tTTAA\nS\\t4\\tCCGG\nL\\t1\\t+\\t2\\t+\\t0M\nL\\t1\\t+\\t3\\t+\\t0M\nL\\t2\\t+\\t4\\t+\\t0M\nL\\t3\\t+\\t4\\t+\\t0M`\n\nconst useStyles = makeStyles()({\n column: { display: 'flex', flexDirection: 'column', gap: 8 },\n rowEnd: { display: 'flex', gap: 8, alignItems: 'flex-end' },\n rowCenter: { display: 'flex', gap: 8, alignItems: 'center' },\n flex1: { flex: 1 },\n paper: { padding: 16, margin: 8, maxWidth: 560, marginInline: 'auto' },\n header: { marginBottom: 12 },\n footer: { marginTop: 12, display: 'flex', justifyContent: 'flex-end' },\n})\n\nconst ImportForm = observer(function ImportForm({\n model,\n}: {\n model: GraphPaneModel\n}) {\n const { classes } = useStyles()\n const [url, setUrl] = useState('')\n\n function handleUrlLoad() {\n if (url.trim()) {\n void model.loadGFAFromLocation({ uri: url, locationType: 'UriLocation' })\n }\n }\n\n function handleFileUpload(event: React.ChangeEvent<HTMLInputElement>) {\n const file = event.target.files?.[0]\n if (file) {\n file\n .text()\n .then(text => model.loadGFA(text, file.name))\n .catch((err: unknown) => {\n model.setError(err)\n })\n }\n }\n\n return (\n <Paper className={classes.paper}>\n <div className={classes.header}>\n <Typography variant=\"h6\">Load a GFA graph</Typography>\n </div>\n\n <div className={classes.column}>\n <div className={classes.rowCenter}>\n <Button variant=\"outlined\" component=\"label\" size=\"small\">\n Choose file\n <input\n type=\"file\"\n accept=\".gfa,.gfa1,.gfa2\"\n hidden\n onChange={event => {\n handleFileUpload(event)\n }}\n />\n </Button>\n <Typography variant=\"caption\" color=\"text.secondary\">\n Whole-file GFA; best for small/medium graphs.\n </Typography>\n </div>\n\n <div className={classes.rowEnd}>\n <TextField\n size=\"small\"\n label=\"URL\"\n placeholder=\"https://example.com/graph.gfa\"\n value={url}\n onChange={e => {\n setUrl(e.target.value)\n }}\n onKeyDown={e => {\n if (e.key === 'Enter') {\n handleUrlLoad()\n }\n }}\n className={classes.flex1}\n />\n <Button\n variant=\"contained\"\n onClick={() => {\n handleUrlLoad()\n }}\n disabled={!url.trim()}\n >\n Open\n </Button>\n </div>\n </div>\n\n <div className={classes.footer}>\n <Button\n size=\"small\"\n onClick={() => {\n void model.loadGFA(EXAMPLE_GFA, 'Example graph')\n }}\n >\n Load 4-node example\n </Button>\n </div>\n\n {model.error ? <ErrorBanner error={model.error} /> : null}\n </Paper>\n )\n})\n\nexport default ImportForm\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["import_mobx_react", "import_ui", "import_material", "import_mobx_react", "import_mui", "import_jsx_runtime", "useStyles", "GraphLoadStatus", "model", "classes", "GraphLoadStatus_default", "import_react", "import_ui", "import_material", "import_mobx_react", "import_mui", "import_jsx_runtime", "EXAMPLE_GFA", "useStyles", "ImportForm", "model", "classes", "url", "setUrl", "handleUrlLoad", "handleFileUpload", "event", "file", "text", "err", "e", "ImportForm_default", "import_jsx_runtime", "GraphGenomeView", "model", "GraphCanvas_default", "GraphLoadStatus_default", "ImportForm_default", "GraphGenomeView_default"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import{a as g}from"./chunk-N7EFSGPU.js";import{G as f}from"./chunk-IVUTPSHP.js";import"./chunk-F4C3BEPV.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-6KKN5F3W.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/LinearGraphDisplay/components/SubgraphContextSelect.tsx", "../../src/LinearGraphDisplay/components/SubgraphHaplotypesField.tsx", "../../src/LinearGraphDisplay/components/GraphTrackSettingsDialog.tsx"],
|
|
4
|
+
"sourcesContent": ["import {\n FormControl,\n InputLabel,\n MenuItem,\n Select,\n Typography,\n} from '@mui/material'\nimport { observer } from 'mobx-react'\nimport { makeStyles } from 'tss-react/mui'\n\nimport type { LinearGraphCutModel } from '../model'\n\nconst useStyles = makeStyles()({\n section: {\n marginBottom: 24,\n },\n formControl: {\n minWidth: 200,\n },\n})\n\n// Hops past the region's own segments, each costing a tabix query per\n// off-reference segment already reached. One is the default: at none a single\n// detour draws as two unrelated stubs, which is a wrong picture of the graph\n// rather than a cheaper one. Two exists for a graph whose alleles have alleles\n// (HPRC's amylase window keeps growing at 2, the E. coli paa locus does not), and\n// it stops there because a frontier is still not a bubble decomposition. Cut an\n// exact slice with gfatools when that is what is wanted.\nconst SUBGRAPH_CONTEXTS = [\n { value: 0, label: 'None' },\n { value: 1, label: '1 hop' },\n { value: 2, label: '2 hops' },\n]\n\nconst SubgraphContextSelect = observer(function SubgraphContextSelect({\n model,\n}: {\n model: LinearGraphCutModel\n}) {\n const { classes } = useStyles()\n return (\n <div className={classes.section}>\n <FormControl className={classes.formControl}>\n <InputLabel>Graph context</InputLabel>\n <Select\n value={model.subgraphContext}\n label=\"Graph context\"\n data-testid=\"graph-context-select\"\n onChange={e => {\n model.setSubgraphContext(e.target.value)\n void model.cut()\n }}\n >\n {SUBGRAPH_CONTEXTS.map(({ value, label }) => (\n <MenuItem key={value} value={value}>\n {label}\n </MenuItem>\n ))}\n </Select>\n </FormControl>\n <Typography variant=\"caption\" color=\"text.secondary\">\n How far the cut follows links out of the region, one hop by default. A\n detour that leaves the reference before the window and rejoins after it\n is indexed under its own sequence, so at none its middle is missing and\n the one bubble draws as two unrelated stubs. Each hop costs a query per\n off-reference segment already reached.\n </Typography>\n </div>\n )\n})\n\nexport default SubgraphContextSelect\n", "import { useState } from 'react'\n\nimport { TextField, Typography } from '@mui/material'\nimport { observer } from 'mobx-react'\nimport { makeStyles } from 'tss-react/mui'\n\nimport type { LinearGraphCutModel } from '../model'\n\nconst useStyles = makeStyles()({\n section: {\n marginBottom: 24,\n },\n})\n\nexport function parseHaplotypeList(text: string) {\n const names = text\n .split(/[\\s,]+/)\n .map(name => name.trim())\n .filter(name => name !== '')\n return names.length === 0 ? undefined : names\n}\n\nconst HaplotypeListField = observer(function HaplotypeListField({\n model,\n}: {\n model: LinearGraphCutModel\n}) {\n const [draft, setDraft] = useState(model.chosenHaplotypes?.join(', ') ?? '')\n const apply = () => {\n const parsed = parseHaplotypeList(draft) ?? []\n const unchanged =\n parsed.join('\\n') === (model.chosenHaplotypes ?? []).join('\\n')\n if (!unchanged) {\n model.setSubgraphHaplotypes(parsed)\n void model.cut()\n }\n }\n return (\n <TextField\n fullWidth\n label=\"Haplotypes\"\n placeholder=\"every haplotype\"\n value={draft}\n slotProps={{ htmlInput: { 'data-testid': 'graph-haplotypes-field' } }}\n onChange={e => {\n setDraft(e.target.value)\n }}\n onBlur={() => {\n apply()\n }}\n onKeyDown={e => {\n if (e.key === 'Enter') {\n apply()\n }\n }}\n />\n )\n})\n\n// Only a GBZ cut reads the set. The inner field is keyed on it so an outside\n// change (a restored session, a launch) resets the draft rather than fighting\n// it.\nconst SubgraphHaplotypesField = observer(function SubgraphHaplotypesField({\n model,\n}: {\n model: LinearGraphCutModel\n}) {\n const { classes } = useStyles()\n return model.adapterConfig.type === 'GbzBaseSyntenyAdapter' ? (\n <div className={classes.section}>\n <HaplotypeListField\n key={model.chosenHaplotypes?.join(',') ?? ''}\n model={model}\n />\n <Typography variant=\"caption\" color=\"text.secondary\">\n The haplotypes the cut is for, as lane assembly names or PanSN prefixes\n (HG002#1, or HG002 for both), separated by commas. The cut keeps their\n walks and the nodes those walks visit, with the reference. Empty is\n every haplotype.\n </Typography>\n </div>\n ) : null\n})\n\nexport default SubgraphHaplotypesField\n", "import SubgraphContextSelect from './SubgraphContextSelect'\nimport SubgraphHaplotypesField from './SubgraphHaplotypesField'\nimport GraphSettingsDialog from '../../GraphGenomeView/components/GraphSettingsDialog'\n\nimport type { LinearGraphCutModel } from '../model'\n\nexport default function GraphTrackSettingsDialog({\n model,\n open,\n onClose,\n}: {\n model: LinearGraphCutModel\n open: boolean\n onClose: () => void\n}) {\n return (\n <GraphSettingsDialog model={model} open={open} onClose={onClose}>\n <SubgraphContextSelect model={model} />\n <SubgraphHaplotypesField model={model} />\n </GraphSettingsDialog>\n )\n}\n"],
|
|
5
|
+
"mappings": "iNAAA,IAAAA,EAMO,SACPC,EAAyB,SACzBC,EAA2B,SAkCrBC,EAAA,SA9BAC,KAAY,cAAW,EAAE,CAC7B,QAAS,CACP,aAAc,EAChB,EACA,YAAa,CACX,SAAU,GACZ,CACF,CAAC,EASKC,EAAoB,CACxB,CAAE,MAAO,EAAG,MAAO,MAAO,EAC1B,CAAE,MAAO,EAAG,MAAO,OAAQ,EAC3B,CAAE,MAAO,EAAG,MAAO,QAAS,CAC9B,EAEMC,KAAwB,YAAS,SAA+B,CACpE,MAAAC,CACF,EAEG,CACD,GAAM,CAAE,QAAAC,CAAQ,EAAIJ,EAAU,EAC9B,SACE,QAAC,OAAI,UAAWI,EAAQ,QACtB,qBAAC,eAAY,UAAWA,EAAQ,YAC9B,oBAAC,cAAW,yBAAa,KACzB,OAAC,UACC,MAAOD,EAAM,gBACb,MAAM,gBACN,cAAY,uBACZ,SAAUE,GAAK,CACbF,EAAM,mBAAmBE,EAAE,OAAO,KAAK,EAClCF,EAAM,IAAI,CACjB,EAEC,SAAAF,EAAkB,IAAI,CAAC,CAAE,MAAAK,EAAO,MAAAC,CAAM,OACrC,OAAC,YAAqB,MAAOD,EAC1B,SAAAC,GADYD,CAEf,CACD,EACH,GACF,KACA,OAAC,cAAW,QAAQ,UAAU,MAAM,iBAAiB,iVAMrD,GACF,CAEJ,CAAC,EAEME,EAAQN,ECvEf,IAAAO,EAAyB,SAEzBC,EAAsC,SACtCC,EAAyB,SACzBC,EAA2B,SAkCvBC,EAAA,SA9BEC,KAAY,cAAW,EAAE,CAC7B,QAAS,CACP,aAAc,EAChB,CACF,CAAC,EAEM,SAASC,EAAmBC,EAAc,CAC/C,IAAMC,EAAQD,EACX,MAAM,QAAQ,EACd,IAAIE,GAAQA,EAAK,KAAK,CAAC,EACvB,OAAOA,GAAQA,IAAS,EAAE,EAC7B,OAAOD,EAAM,SAAW,EAAI,OAAYA,CAC1C,CAEA,IAAME,KAAqB,YAAS,SAA4B,CAC9D,MAAAC,CACF,EAEG,CACD,GAAM,CAACC,EAAOC,CAAQ,KAAI,YAASF,EAAM,kBAAkB,KAAK,IAAI,GAAK,EAAE,EACrEG,EAAQ,IAAM,CAClB,IAAMC,EAAST,EAAmBM,CAAK,GAAK,CAAC,EAE3CG,EAAO,KAAK;AAAA,CAAI,KAAOJ,EAAM,kBAAoB,CAAC,GAAG,KAAK;AAAA,CAAI,IAE9DA,EAAM,sBAAsBI,CAAM,EAC7BJ,EAAM,IAAI,EAEnB,EACA,SACE,OAAC,aACC,UAAS,GACT,MAAM,aACN,YAAY,kBACZ,MAAOC,EACP,UAAW,CAAE,UAAW,CAAE,cAAe,wBAAyB,CAAE,EACpE,SAAUI,GAAK,CACbH,EAASG,EAAE,OAAO,KAAK,CACzB,EACA,OAAQ,IAAM,CACZF,EAAM,CACR,EACA,UAAWE,GAAK,CACVA,EAAE,MAAQ,SACZF,EAAM,CAEV,EACF,CAEJ,CAAC,EAKKG,KAA0B,YAAS,SAAiC,CACxE,MAAAN,CACF,EAEG,CACD,GAAM,CAAE,QAAAO,CAAQ,EAAIb,EAAU,EAC9B,OAAOM,EAAM,cAAc,OAAS,2BAClC,QAAC,OAAI,UAAWO,EAAQ,QACtB,oBAACR,EAAA,CAEC,MAAOC,GADFA,EAAM,kBAAkB,KAAK,GAAG,GAAK,EAE5C,KACA,OAAC,cAAW,QAAQ,UAAU,MAAM,iBAAiB,+OAKrD,GACF,EACE,IACN,CAAC,EAEMQ,EAAQF,ECpEX,IAAAG,EAAA,SAVW,SAARC,EAA0C,CAC/C,MAAAC,EACA,KAAAC,EACA,QAAAC,CACF,EAIG,CACD,SACE,QAACC,EAAA,CAAoB,MAAOH,EAAO,KAAMC,EAAM,QAASC,EACtD,oBAACE,EAAA,CAAsB,MAAOJ,EAAO,KACrC,OAACK,EAAA,CAAwB,MAAOL,EAAO,GACzC,CAEJ",
|
|
6
|
+
"names": ["import_material", "import_mobx_react", "import_mui", "import_jsx_runtime", "useStyles", "SUBGRAPH_CONTEXTS", "SubgraphContextSelect", "model", "classes", "e", "value", "label", "SubgraphContextSelect_default", "import_react", "import_material", "import_mobx_react", "import_mui", "import_jsx_runtime", "useStyles", "parseHaplotypeList", "text", "names", "name", "HaplotypeListField", "model", "draft", "setDraft", "apply", "parsed", "e", "SubgraphHaplotypesField", "classes", "SubgraphHaplotypesField_default", "import_jsx_runtime", "GraphTrackSettingsDialog", "model", "open", "onClose", "GraphSettingsDialog_default", "SubgraphContextSelect_default", "SubgraphHaplotypesField_default"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{a as i}from"./chunk-MT25CI4U.js";import"./chunk-J2UKZSOC.js";import"./chunk-ZNGDWZ6Z.js";import"./chunk-N7EFSGPU.js";import"./chunk-IVUTPSHP.js";import"./chunk-F4C3BEPV.js";import{a as e,b as d}from"./chunk-XEJ47DLD.js";import{a as h,b as r}from"./chunk-FY3BTKY4.js";var p=h((l,o)=>{o.exports=JBrowseExports["@jbrowse/display-kit/DisplayChrome"]});var s=r(p(),1),n=r(d(),1);var t=r(e(),1),u=(0,n.observer)(function({model:a}){return(0,t.jsx)(s.DisplayStatusChrome,{model:a,phase:a.displayPhase,drawn:a.painted,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,t.jsx)(i,{model:a,ownChrome:!1})})}),c=u;export{c as default};
|
|
2
|
+
//# sourceMappingURL=LinearGraphDisplay-IBECRYKJ.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["global-externals:@jbrowse/display-kit/DisplayChrome", "../../src/LinearGraphDisplay/components/LinearGraphDisplay.tsx"],
|
|
4
|
+
"sourcesContent": ["module.exports = JBrowseExports[\"@jbrowse/display-kit/DisplayChrome\"];", "import { DisplayStatusChrome } from '@jbrowse/display-kit/DisplayChrome'\nimport { observer } from 'mobx-react'\n\nimport GraphCanvas from '../../GraphGenomeView/components/GraphCanvas'\n\nimport type { LinearGraphDisplayModel } from '../model'\n\nconst LinearGraphDisplay = observer(function LinearGraphDisplay({\n model,\n}: {\n model: LinearGraphDisplayModel\n}) {\n return (\n <DisplayStatusChrome\n model={model}\n phase={model.displayPhase}\n drawn={model.painted}\n testid=\"linear-graph-display\"\n data-layout={model.chosenLayoutMode}\n data-cut-tier={model.cutTier}\n data-recuts={model.recuts}\n data-node-count={model.hasGraph ? model.nodeCount : undefined}\n data-loading={model.isLoading ? '' : undefined}\n style={{\n width: model.paneWidth,\n height: model.height,\n overflow: 'hidden',\n }}\n >\n <GraphCanvas model={model} ownChrome={false} />\n </DisplayStatusChrome>\n )\n})\n\nexport default LinearGraphDisplay\n"],
|
|
5
|
+
"mappings": "kRAAA,IAAAA,EAAAC,EAAA,CAAAC,EAAAC,IAAA,CAAAA,EAAO,QAAU,eAAe,oCAAoC,ICApE,IAAAC,EAAoC,SACpCC,EAAyB,SA4BnB,IAAAC,EAAA,SAtBAC,KAAqB,YAAS,SAA4B,CAC9D,MAAAC,CACF,EAEG,CACD,SACE,OAAC,uBACC,MAAOA,EACP,MAAOA,EAAM,aACb,MAAOA,EAAM,QACb,OAAO,uBACP,cAAaA,EAAM,iBACnB,gBAAeA,EAAM,QACrB,cAAaA,EAAM,OACnB,kBAAiBA,EAAM,SAAWA,EAAM,UAAY,OACpD,eAAcA,EAAM,UAAY,GAAK,OACrC,MAAO,CACL,MAAOA,EAAM,UACb,OAAQA,EAAM,OACd,SAAU,QACZ,EAEA,mBAACC,EAAA,CAAY,MAAOD,EAAO,UAAW,GAAO,EAC/C,CAEJ,CAAC,EAEME,EAAQH",
|
|
6
|
+
"names": ["require_DisplayChrome", "__commonJSMin", "exports", "module", "import_DisplayChrome", "import_mobx_react", "import_jsx_runtime", "LinearGraphDisplay", "model", "GraphCanvas_default", "LinearGraphDisplay_default"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{a as g}from"./chunk-D7XFR2IV.js";import{a as p,b as u}from"./chunk-FY3BTKY4.js";var h=p((L,c)=>{c.exports=JBrowseExports["mobx-state-tree"]});var n=u(g(),1),I={RgfaTabixAdapter:"rGFA segments (tabix BED pair)",MinigraphBubbleAdapter:"Minigraph bubbles (tabix BED)"},T={RgfaTabixAdapter:"Path to segments BED (.segs.bed.gz from build_rgfa_tabix.sh; the .links.bed.gz and both .tbi are assumed beside it)",MinigraphBubbleAdapter:"Path to bubbles BED (.bed.gz from gfatools bubble; the .tbi is assumed beside it)"},s=".segs.bed.gz";function r(e){return"uri"in e?e.uri:"localPath"in e?e.localPath:""}function m(e){return r(e).endsWith(s)}function f(e){let i=r(e);if(!m(e))throw new Error(`Expected a segments BED ending in ${s}, got ${i||"a blob"}`);let t=`${i.slice(0,-s.length)}.links.bed.gz`;return"uri"in e?{...e,uri:t}:"localPath"in e?{...e,localPath:t}:e}function d(e,i){return i?{location:i,indexType:(0,n.makeIndexType)(r(i),"CSI","TBI")}:{location:(0,n.makeIndex)(e,".tbi"),indexType:"TBI"}}function x(e,i){return i!==void 0&&r(i).endsWith(".csi")?{location:(0,n.makeIndex)(e,".csi"),indexType:"CSI"}:{location:(0,n.makeIndex)(e,".tbi"),indexType:"TBI"}}function l(e,i){let t=i.trim();return t?{assemblyNameToPanSN:{[e]:t}}:{}}function F({choice:e,loc:i,indexLoc:t,assembly:a,sample:o}){if(e==="MinigraphBubbleAdapter")return{type:"MinigraphBubbleAdapter",bubblesLocation:i,index:d(i,t),...l(a,o)};let b=f(i);return{type:"RgfaTabixAdapter",segmentsLocation:i,segmentsIndex:d(i,t),linksLocation:b,linksIndex:x(b,t),...l(a,o)}}function y(e){let{choice:i,assembly:t,trackId:a,name:o}=e;return{type:"FeatureTrack",trackId:a,name:o,assemblyNames:[t],adapter:F(e),...i==="RgfaTabixAdapter"?{displayDefaults:{showLabels:"none"}}:{}}}export{h as a,I as b,T as c,m as d,F as e,y as f};
|
|
2
|
+
//# sourceMappingURL=chunk-C6PIPNZS.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["global-externals:@jbrowse/mobx-state-tree", "../../src/GraphAddTrackWorkflow/buildTrackConfig.ts"],
|
|
4
|
+
"sourcesContent": ["module.exports = JBrowseExports[\"mobx-state-tree\"];", "import { makeIndex, makeIndexType } from '@jbrowse/core/util/tracks'\n\nimport type { FileLocation } from '@jbrowse/core/util'\n\nexport type GraphFileChoice = 'RgfaTabixAdapter' | 'MinigraphBubbleAdapter'\n\nexport const GRAPH_FILE_LABELS: Record<GraphFileChoice, string> = {\n RgfaTabixAdapter: 'rGFA segments (tabix BED pair)',\n MinigraphBubbleAdapter: 'Minigraph bubbles (tabix BED)',\n}\n\nexport const GRAPH_FILE_FIELDS: Record<GraphFileChoice, string> = {\n RgfaTabixAdapter:\n 'Path to segments BED (.segs.bed.gz from build_rgfa_tabix.sh; the .links.bed.gz and both .tbi are assumed beside it)',\n MinigraphBubbleAdapter:\n 'Path to bubbles BED (.bed.gz from gfatools bubble; the .tbi is assumed beside it)',\n}\n\nconst SEGMENTS_SUFFIX = '.segs.bed.gz'\n\nfunction locationName(loc: FileLocation) {\n return 'uri' in loc ? loc.uri : 'localPath' in loc ? loc.localPath : ''\n}\n\nexport function isSegmentsLocation(loc: FileLocation) {\n return locationName(loc).endsWith(SEGMENTS_SUFFIX)\n}\n\nfunction linksLocation(loc: FileLocation) {\n const name = locationName(loc)\n if (!isSegmentsLocation(loc)) {\n throw new Error(\n `Expected a segments BED ending in ${SEGMENTS_SUFFIX}, got ${name || 'a blob'}`,\n )\n }\n const links = `${name.slice(0, -SEGMENTS_SUFFIX.length)}.links.bed.gz`\n return 'uri' in loc\n ? { ...loc, uri: links }\n : 'localPath' in loc\n ? { ...loc, localPath: links }\n : loc\n}\n\nfunction tabixIndex(loc: FileLocation, indexLoc: FileLocation | undefined) {\n return indexLoc\n ? {\n location: indexLoc,\n indexType: makeIndexType(locationName(indexLoc), 'CSI', 'TBI'),\n }\n : { location: makeIndex(loc, '.tbi'), indexType: 'TBI' }\n}\n\n// The links file's index is assumed beside it, of the kind the segments' is.\nfunction siblingIndex(loc: FileLocation, indexLoc: FileLocation | undefined) {\n const csi = indexLoc !== undefined && locationName(indexLoc).endsWith('.csi')\n return csi\n ? { location: makeIndex(loc, '.csi'), indexType: 'CSI' }\n : { location: makeIndex(loc, '.tbi'), indexType: 'TBI' }\n}\n\nfunction panSN(assembly: string, sample: string) {\n const name = sample.trim()\n return name ? { assemblyNameToPanSN: { [assembly]: name } } : {}\n}\n\nexport function buildAdapterConfig({\n choice,\n loc,\n indexLoc,\n assembly,\n sample,\n}: {\n choice: GraphFileChoice\n loc: FileLocation\n indexLoc: FileLocation | undefined\n assembly: string\n sample: string\n}) {\n if (choice === 'MinigraphBubbleAdapter') {\n return {\n type: 'MinigraphBubbleAdapter',\n bubblesLocation: loc,\n index: tabixIndex(loc, indexLoc),\n ...panSN(assembly, sample),\n }\n }\n const links = linksLocation(loc)\n return {\n type: 'RgfaTabixAdapter',\n segmentsLocation: loc,\n segmentsIndex: tabixIndex(loc, indexLoc),\n linksLocation: links,\n linksIndex: siblingIndex(links, indexLoc),\n ...panSN(assembly, sample),\n }\n}\n\nexport function buildTrackConfig(args: {\n choice: GraphFileChoice\n loc: FileLocation\n indexLoc: FileLocation | undefined\n assembly: string\n sample: string\n trackId: string\n name: string\n}) {\n const { choice, assembly, trackId, name } = args\n return {\n type: 'FeatureTrack',\n trackId,\n name,\n assemblyNames: [assembly],\n adapter: buildAdapterConfig(args),\n ...(choice === 'RgfaTabixAdapter'\n ? { displayDefaults: { showLabels: 'none' } }\n : {}),\n }\n}\n"],
|
|
5
|
+
"mappings": "uFAAA,IAAAA,EAAAC,EAAA,CAAAC,EAAAC,IAAA,CAAAA,EAAO,QAAU,eAAe,iBAAiB,ICAjD,IAAAC,EAAyC,SAM5BC,EAAqD,CAChE,iBAAkB,iCAClB,uBAAwB,+BAC1B,EAEaC,EAAqD,CAChE,iBACE,sHACF,uBACE,mFACJ,EAEMC,EAAkB,eAExB,SAASC,EAAaC,EAAmB,CACvC,MAAO,QAASA,EAAMA,EAAI,IAAM,cAAeA,EAAMA,EAAI,UAAY,EACvE,CAEO,SAASC,EAAmBD,EAAmB,CACpD,OAAOD,EAAaC,CAAG,EAAE,SAASF,CAAe,CACnD,CAEA,SAASI,EAAcF,EAAmB,CACxC,IAAMG,EAAOJ,EAAaC,CAAG,EAC7B,GAAI,CAACC,EAAmBD,CAAG,EACzB,MAAM,IAAI,MACR,qCAAqCF,CAAe,SAASK,GAAQ,QAAQ,EAC/E,EAEF,IAAMC,EAAQ,GAAGD,EAAK,MAAM,EAAG,CAACL,EAAgB,MAAM,CAAC,gBACvD,MAAO,QAASE,EACZ,CAAE,GAAGA,EAAK,IAAKI,CAAM,EACrB,cAAeJ,EACb,CAAE,GAAGA,EAAK,UAAWI,CAAM,EAC3BJ,CACR,CAEA,SAASK,EAAWL,EAAmBM,EAAoC,CACzE,OAAOA,EACH,CACE,SAAUA,EACV,aAAW,iBAAcP,EAAaO,CAAQ,EAAG,MAAO,KAAK,CAC/D,EACA,CAAE,YAAU,aAAUN,EAAK,MAAM,EAAG,UAAW,KAAM,CAC3D,CAGA,SAASO,EAAaP,EAAmBM,EAAoC,CAE3E,OADYA,IAAa,QAAaP,EAAaO,CAAQ,EAAE,SAAS,MAAM,EAExE,CAAE,YAAU,aAAUN,EAAK,MAAM,EAAG,UAAW,KAAM,EACrD,CAAE,YAAU,aAAUA,EAAK,MAAM,EAAG,UAAW,KAAM,CAC3D,CAEA,SAASQ,EAAMC,EAAkBC,EAAgB,CAC/C,IAAMP,EAAOO,EAAO,KAAK,EACzB,OAAOP,EAAO,CAAE,oBAAqB,CAAE,CAACM,CAAQ,EAAGN,CAAK,CAAE,EAAI,CAAC,CACjE,CAEO,SAASQ,EAAmB,CACjC,OAAAC,EACA,IAAAZ,EACA,SAAAM,EACA,SAAAG,EACA,OAAAC,CACF,EAMG,CACD,GAAIE,IAAW,yBACb,MAAO,CACL,KAAM,yBACN,gBAAiBZ,EACjB,MAAOK,EAAWL,EAAKM,CAAQ,EAC/B,GAAGE,EAAMC,EAAUC,CAAM,CAC3B,EAEF,IAAMN,EAAQF,EAAcF,CAAG,EAC/B,MAAO,CACL,KAAM,mBACN,iBAAkBA,EAClB,cAAeK,EAAWL,EAAKM,CAAQ,EACvC,cAAeF,EACf,WAAYG,EAAaH,EAAOE,CAAQ,EACxC,GAAGE,EAAMC,EAAUC,CAAM,CAC3B,CACF,CAEO,SAASG,EAAiBC,EAQ9B,CACD,GAAM,CAAE,OAAAF,EAAQ,SAAAH,EAAU,QAAAM,EAAS,KAAAZ,CAAK,EAAIW,EAC5C,MAAO,CACL,KAAM,eACN,QAAAC,EACA,KAAAZ,EACA,cAAe,CAACM,CAAQ,EACxB,QAASE,EAAmBG,CAAI,EAChC,GAAIF,IAAW,mBACX,CAAE,gBAAiB,CAAE,WAAY,MAAO,CAAE,EAC1C,CAAC,CACP,CACF",
|
|
6
|
+
"names": ["require_mobx_state_tree", "__commonJSMin", "exports", "module", "import_tracks", "GRAPH_FILE_LABELS", "GRAPH_FILE_FIELDS", "SEGMENTS_SUFFIX", "locationName", "loc", "isSegmentsLocation", "linksLocation", "name", "links", "tabixIndex", "indexLoc", "siblingIndex", "panSN", "assembly", "sample", "buildAdapterConfig", "choice", "buildTrackConfig", "args", "trackId"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{a as l}from"./chunk-F4C3BEPV.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"}var G=[{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."}],re=G.map(e=>e.value),S=.3,f=3;function O(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 M(e,t){return!(t>0)||!(e.depth>0)?1:Math.min(f,Math.max(S,Math.sqrt(e.depth/t)))}function w(e,t,n,r){return t*(n==="depth"?M(e,r):1)}function y(e,t){return e*(t==="depth"?f:1)}function oe(e,t,n,r){let o=e?O(e):0;return{maxHalfWidthPx:y(n,r)/2,halfWidthPx:a=>{let s=t?.get(a);return s?w(s,n,r,o)/2:n/2}}}function se(e){return e.stable!==void 0}function P(e){return e.stable?.rank===0}function ie(e){return e.stable!==void 0&&e.stable.rank>0}function de(e){return e.nodes.filter(P)}function pe(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 ce(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 R(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 he(e,t){return t&&t.end>t.start?t.end-t.start:R(e)}var D=/:(\d+)-\d+$/;function p(e){let t=D.exec(e);return t?{name:e.slice(0,t.index),start:+t[1]}:{name:e,start:0}}function fe(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 H(e,t){return e.find(r=>r.sample===t||r.name===t)??e[0]}var I=1;function B(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:I,strand:o.strand},samples:[...new Set(t.map(a=>a.sample))].sort()}}return r}function v(e,t){let{anchorPaths:n,pathVisits:r}=e,o=n&&r?H(n,t):void 0;return o&&r?{...e,nodes:e.nodes.map(a=>B(a,r.get(a.name),o.name)),anchoredBy:"paths",referencePath:o.name}:e}function Ne(e,t){return e.anchoredBy==="tags"?e:v(e,t)}function Ee(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 C(e,t){return e*360/t}var F=.7,U=.5,k=16;function xe(e){return e>0&&e<=k}function W(e,t){return`hsl(${C(e,t)}, ${F*100}%, ${U*100}%)`}function V(e){let t=p(e).name.split("#");return[t[0],t.slice(0,2).join("#"),t.join("#")]}function $(e){return String(e).replace(/\B(?=(\d{3})+$)/g,",")}function K(e,t){let{start:n}=p(e);return t.map(r=>`${r} @${$(n)}`)}function Le(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)=>K(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:W(s,e.length)}))}export{se as a,P as b,ie as c,de as d,pe as e,ce as f,R as g,he 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,fe as r,v as s,Ne as t,G as u,re as v,O as w,w as x,oe as y,Ee as z,C as A,F as B,U as C,k as D,xe as E,Le as F,X as G};
|
|
2
|
+
//# sourceMappingURL=chunk-IVUTPSHP.js.map
|