jbrowse-plugin-graphgenomeviewer 7.1.0 → 7.1.2
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 +17 -8
- package/dist/chunks/AddTrackWorkflow-RPH4ZFSX.js +2 -0
- package/dist/chunks/{AddTrackWorkflow-Q6RY23LF.js.map → AddTrackWorkflow-RPH4ZFSX.js.map} +2 -2
- package/dist/chunks/{ChooseSamplesDialog-BNVYBGJQ.js → ChooseSamplesDialog-JRN4YLBY.js} +2 -2
- package/dist/chunks/{ChooseWalksDialog-EN3C6AQA.js → ChooseWalksDialog-UXLFZTZJ.js} +2 -2
- package/dist/chunks/GbzBaseSyntenyAdapter-LRECKL74.js +2 -0
- package/dist/chunks/GbzBaseSyntenyAdapter-LRECKL74.js.map +7 -0
- package/dist/chunks/{GraphGenomeView-Z2WZKEEO.js → GraphGenomeView-NJ5XCREB.js} +2 -2
- package/dist/chunks/GraphTrackSettingsDialog-47PQ6LM7.js +6 -0
- package/dist/chunks/GraphTrackSettingsDialog-47PQ6LM7.js.map +7 -0
- package/dist/chunks/{HighlightColorDialog-EYBKFSJU.js → HighlightColorDialog-UK5VDDV6.js} +2 -2
- package/dist/chunks/{LinearGraphDisplay-WIBVWRQE.js → LinearGraphDisplay-TXTKAACH.js} +2 -2
- package/dist/chunks/MinigraphBubbleAdapter-HW7XQMAI.js +2 -0
- package/dist/chunks/MinigraphBubbleAdapter-HW7XQMAI.js.map +7 -0
- package/dist/chunks/RgfaTabixAdapter-PSKYWD2X.js +3 -0
- package/dist/chunks/RgfaTabixAdapter-PSKYWD2X.js.map +7 -0
- package/dist/chunks/{TrackWarningsDialog-QT4YEXGD.js → TrackWarningsDialog-TRYBOIHX.js} +2 -2
- package/dist/chunks/WalkTabixSyntenyAdapter-U53JLYVU.js +2 -0
- package/dist/chunks/WalkTabixSyntenyAdapter-U53JLYVU.js.map +7 -0
- package/dist/chunks/chunk-2MCOY3YG.js +3 -0
- package/dist/chunks/chunk-2MCOY3YG.js.map +7 -0
- package/dist/chunks/{chunk-EWFJBQDV.js → chunk-5O6YRJHL.js} +2 -2
- package/dist/chunks/{chunk-EWFJBQDV.js.map → chunk-5O6YRJHL.js.map} +1 -1
- package/dist/chunks/chunk-BUY2PV7D.js +2 -0
- package/dist/chunks/chunk-BUY2PV7D.js.map +7 -0
- package/dist/chunks/chunk-DVCZ3BOC.js +2 -0
- package/dist/chunks/chunk-DVCZ3BOC.js.map +7 -0
- package/dist/chunks/{chunk-SAMJE6GH.js → chunk-EGDLEQ47.js} +3 -3
- package/dist/chunks/{chunk-SAMJE6GH.js.map → chunk-EGDLEQ47.js.map} +4 -4
- package/dist/chunks/chunk-FHZXW7IG.js +2 -0
- package/dist/chunks/chunk-FHZXW7IG.js.map +7 -0
- package/dist/chunks/{chunk-DZ4OUKQV.js → chunk-FITPB5X6.js} +2 -2
- package/dist/chunks/{chunk-DZ4OUKQV.js.map → chunk-FITPB5X6.js.map} +1 -1
- package/dist/chunks/chunk-FVK2THE4.js +2 -0
- package/dist/chunks/chunk-FVK2THE4.js.map +7 -0
- package/dist/chunks/{chunk-AHFQHYJI.js → chunk-IBWORBGY.js} +2 -2
- package/dist/chunks/chunk-MND7GAOG.js +2 -0
- package/dist/chunks/chunk-MND7GAOG.js.map +7 -0
- package/dist/chunks/chunk-MURN3JPK.js +2 -0
- package/dist/chunks/chunk-MURN3JPK.js.map +7 -0
- package/dist/chunks/{chunk-3Q4RBDCL.js → chunk-N6PQZSAX.js} +1 -1
- package/dist/chunks/{chunk-3Q4RBDCL.js.map → chunk-N6PQZSAX.js.map} +1 -1
- package/dist/chunks/chunk-NWJYLP6Z.js +4 -0
- package/dist/chunks/chunk-NWJYLP6Z.js.map +7 -0
- package/dist/chunks/{chunk-YJHYBDYF.js → chunk-S75W27NT.js} +2 -2
- package/dist/chunks/{chunk-YJHYBDYF.js.map → chunk-S75W27NT.js.map} +1 -1
- package/dist/chunks/{chunk-IXQK7JAW.js → chunk-T4HOC6O3.js} +1 -1
- package/dist/chunks/{chunk-IXQK7JAW.js.map → chunk-T4HOC6O3.js.map} +1 -1
- package/dist/chunks/{chunk-AU73K7LX.js → chunk-TUKJRVBS.js} +1 -1
- package/dist/chunks/{chunk-AU73K7LX.js.map → chunk-TUKJRVBS.js.map} +1 -1
- package/dist/chunks/chunk-UGCNPRKC.js +2 -0
- package/dist/chunks/{chunk-E3WYW7Z6.js.map → chunk-UGCNPRKC.js.map} +2 -2
- package/dist/chunks/{chunk-YSTMDXXX.js → chunk-VJ3SO4CH.js} +1 -1
- package/dist/chunks/{chunk-YSTMDXXX.js.map → chunk-VJ3SO4CH.js.map} +1 -1
- package/dist/chunks/{chunk-XT766CZ5.js → chunk-W6EQLQ6H.js} +1 -1
- package/dist/chunks/{chunk-XT766CZ5.js.map → chunk-W6EQLQ6H.js.map} +1 -1
- package/dist/chunks/chunk-WAMBI7OX.js +2 -0
- package/dist/chunks/chunk-WAMBI7OX.js.map +7 -0
- package/dist/chunks/chunk-WCGVUZWP.js +2 -0
- package/dist/chunks/chunk-WCGVUZWP.js.map +7 -0
- package/dist/chunks/chunk-WEGWTC52.js +2 -0
- package/dist/chunks/chunk-WEGWTC52.js.map +7 -0
- package/dist/chunks/chunk-YU7T5WOQ.js +2 -0
- package/dist/chunks/{chunk-6OPB7FOJ.js.map → chunk-YU7T5WOQ.js.map} +2 -2
- package/dist/chunks/{chunk-446RWIA3.js → chunk-ZMOMFU2B.js} +1 -1
- package/dist/chunks/{chunk-446RWIA3.js.map → chunk-ZMOMFU2B.js.map} +1 -1
- package/dist/chunks/renderSvg-KSQI5DH6.js +2 -0
- package/dist/chunks/renderSvg-KSQI5DH6.js.map +7 -0
- package/dist/jbrowse-plugin-graphgenomeviewer.esm.js +4 -4
- package/dist/jbrowse-plugin-graphgenomeviewer.esm.js.map +4 -4
- package/package.json +8 -9
- package/src/GbzBaseSyntenyAdapter/GbzBaseSyntenyAdapter.test.ts +12 -10
- package/src/GbzBaseSyntenyAdapter/GbzBaseSyntenyAdapter.ts +31 -39
- package/src/GbzBaseSyntenyAdapter/configSchema.ts +5 -29
- package/src/GetGraphHaplotypes.ts +6 -15
- package/src/GetGraphReads.ts +7 -14
- package/src/GetSubgraph.ts +11 -20
- package/src/GraphAddTrackWorkflow/AddTrackWorkflow.test.tsx +73 -0
- package/src/GraphAddTrackWorkflow/AddTrackWorkflow.tsx +1 -0
- package/src/GraphAddTrackWorkflow/buildTrackConfig.test.ts +3 -2
- package/src/GraphAddTrackWorkflow/buildTrackConfig.ts +2 -11
- package/src/GraphAddTrackWorkflow/graphManifest.ts +15 -3
- package/src/GraphGenomeView/components/BubbleHalos.tsx +5 -24
- package/src/GraphGenomeView/components/ElTree.tsx +6 -1
- package/src/GraphGenomeView/components/FacetPanels.test.tsx +65 -0
- package/src/GraphGenomeView/components/FacetPanels.tsx +17 -12
- package/src/GraphGenomeView/components/GenePins.tsx +5 -22
- package/src/GraphGenomeView/components/GraphCanvas.tsx +40 -234
- package/src/GraphGenomeView/components/GraphSettingsDialog.tsx +102 -108
- package/src/GraphGenomeView/components/GraphToolbar.tsx +5 -6
- package/src/GraphGenomeView/components/HoverLayer.tsx +3 -7
- package/src/GraphGenomeView/components/HoverTooltip.test.tsx +39 -0
- package/src/GraphGenomeView/components/HoverTooltip.tsx +122 -0
- package/src/GraphGenomeView/components/LabelChip.tsx +3 -5
- package/src/GraphGenomeView/components/LabelLayer.tsx +4 -17
- package/src/GraphGenomeView/components/LabelledSelect.tsx +1 -1
- package/src/GraphGenomeView/components/Legend.tsx +14 -23
- package/src/GraphGenomeView/components/PaneContextMenu.test.tsx +48 -0
- package/src/GraphGenomeView/components/PaneContextMenu.tsx +144 -0
- package/src/GraphGenomeView/components/PaneLayer.tsx +91 -0
- package/src/GraphGenomeView/components/PaneSvg.tsx +32 -50
- package/src/GraphGenomeView/components/ReferenceStripOverlay.test.tsx +48 -0
- package/src/GraphGenomeView/components/ReferenceStripOverlay.tsx +13 -42
- package/src/GraphGenomeView/components/SettingsMenu.test.tsx +29 -0
- package/src/GraphGenomeView/components/SettingsMenu.tsx +56 -65
- package/src/GraphGenomeView/components/TubeMapOverlay.tsx +15 -46
- package/src/GraphGenomeView/components/WalkRowsOverlay.tsx +58 -132
- package/src/GraphGenomeView/components/WalkStrip.tsx +17 -20
- package/src/GraphGenomeView/components/WalkStripLocator.tsx +8 -15
- package/src/GraphGenomeView/components/usePaneGestures.test.tsx +35 -0
- package/src/GraphGenomeView/components/usePaneGestures.ts +88 -91
- package/src/GraphGenomeView/genes/geneFeatures.ts +27 -45
- package/src/GraphGenomeView/graphLayers.ts +4 -4
- package/src/GraphGenomeView/host.ts +1 -1
- package/src/GraphGenomeView/legendSections.test.ts +23 -1
- package/src/GraphGenomeView/legendSections.ts +68 -74
- package/src/GraphGenomeView/model.test.ts +373 -39
- package/src/GraphGenomeView/model.ts +67 -11
- package/src/GraphGenomeView/pane/fitViews.ts +57 -514
- package/src/GraphGenomeView/pane/graphViews.ts +219 -160
- package/src/GraphGenomeView/pane/hostViews.ts +2 -10
- package/src/GraphGenomeView/pane/keepInView.ts +5 -4
- package/src/GraphGenomeView/pane/launchActions.ts +117 -139
- package/src/GraphGenomeView/pane/launchViews.ts +8 -27
- package/src/GraphGenomeView/pane/loadActions.ts +208 -187
- package/src/GraphGenomeView/pane/morph.ts +3 -9
- package/src/GraphGenomeView/pane/paneBase.ts +22 -11
- package/src/GraphGenomeView/pane/renderingActions.ts +65 -11
- package/src/GraphGenomeView/pane/settingActions.ts +17 -42
- package/src/GraphGenomeView/pane/tubeMapViews.ts +445 -0
- package/src/GraphGenomeView/pane/walkRowViews.ts +29 -37
- package/src/GraphGenomeView/renderPipeline.test.ts +1 -1
- package/src/GraphGenomeView/repeats/repeatFeatures.test.ts +23 -0
- package/src/GraphGenomeView/repeats/repeatFeatures.ts +16 -23
- package/src/GraphGenomeView/repeats/walkCalls.test.ts +18 -0
- package/src/GraphGenomeView/repeats/walkCalls.ts +46 -38
- package/src/GraphGenomeView/subgraphLoad.test.ts +67 -3
- package/src/GraphGenomeView/trackFeatures.ts +24 -0
- package/src/GraphGenomeView/tubeMapPanels.ts +28 -36
- package/src/GraphGenomeView/viewModel.ts +8 -56
- package/src/GraphGenomeView/walkRowGroups.ts +104 -30
- package/src/GraphGenomeView/walkRowSpans.test.ts +6 -0
- package/src/GraphGenomeView/walkRowSpans.ts +22 -31
- package/src/GraphGenomeView/walkRowsCut.ts +8 -17
- package/src/LinearGraphDisplay/LinearGraphDisplay.test.ts +173 -26
- package/src/LinearGraphDisplay/components/SubgraphContextSelect.test.tsx +1 -1
- package/src/LinearGraphDisplay/components/SubgraphContextSelect.tsx +3 -3
- package/src/LinearGraphDisplay/components/SubgraphHaplotypesField.test.tsx +3 -3
- package/src/LinearGraphDisplay/components/SubgraphHaplotypesField.tsx +7 -10
- package/src/LinearGraphDisplay/configSchema.ts +0 -3
- package/src/LinearGraphDisplay/denseWindow.ts +8 -11
- package/src/LinearGraphDisplay/model.ts +89 -82
- package/src/MinigraphBubbleAdapter/MinigraphBubbleAdapter.test.ts +21 -0
- package/src/MinigraphBubbleAdapter/MinigraphBubbleAdapter.ts +6 -14
- package/src/MinigraphBubbleAdapter/configSchema.ts +3 -9
- package/src/MinigraphBubbleAdapter/index.ts +1 -2
- package/src/RgfaTabixAdapter/RgfaTabixAdapter.test.ts +45 -1
- package/src/RgfaTabixAdapter/RgfaTabixAdapter.ts +111 -276
- package/src/RgfaTabixAdapter/configSchema.ts +15 -49
- package/src/RgfaTabixAdapter/index.ts +1 -2
- package/src/RgfaTabixAdapter/rgfaBed.ts +25 -15
- package/src/RgfaTabixAdapter/rgfaCut.ts +139 -0
- package/src/RgfaTabixAdapter/test_data/walks2_twopart.GRCh38.walks.bed.gz +0 -0
- package/src/RgfaTabixAdapter/test_data/walks2_twopart.GRCh38.walks.bed.gz.tbi +0 -0
- package/src/RgfaTabixAdapter/walkFiles.test.ts +33 -0
- package/src/RgfaTabixAdapter/walkReader.ts +103 -27
- package/src/RgfaTabixAdapter/walkRowRuns.test.ts +53 -0
- package/src/RgfaTabixAdapter/walkRowRuns.ts +42 -24
- package/src/WalkTabixSyntenyAdapter/WalkTabixSyntenyAdapter.test.ts +37 -6
- package/src/WalkTabixSyntenyAdapter/WalkTabixSyntenyAdapter.ts +23 -45
- package/src/WalkTabixSyntenyAdapter/configSchema.ts +11 -24
- package/src/WalkTabixSyntenyAdapter/index.ts +1 -2
- package/src/WalkTabixSyntenyAdapter/walkLanes.ts +35 -43
- package/src/adapterImplementing.ts +27 -0
- package/src/graphTrackDefaults/index.ts +14 -20
- package/src/hoverSync/lgvHover.ts +2 -4
- package/src/launchFromGraph/contributors.ts +1 -5
- package/src/launchFromGraph/graphMenuItems.ts +3 -4
- package/src/launchFromGraph/launchFromGraph.test.ts +0 -1
- package/src/launchFromGraph/launchFromGraph.ts +8 -13
- package/src/panSNTabix.test.ts +1 -26
- package/src/panSNTabix.ts +54 -51
- package/src/synteny/lanePairs.ts +8 -0
- package/src/synteny/matchFeature.ts +52 -0
- package/src/tabixRange.ts +13 -10
- package/src/version.ts +1 -1
- package/dist/chunks/AddTrackWorkflow-Q6RY23LF.js +0 -2
- package/dist/chunks/GbzBaseSyntenyAdapter-TIXR4Y3J.js +0 -2
- package/dist/chunks/GbzBaseSyntenyAdapter-TIXR4Y3J.js.map +0 -7
- package/dist/chunks/GraphTrackSettingsDialog-TAM6PMXD.js +0 -6
- package/dist/chunks/GraphTrackSettingsDialog-TAM6PMXD.js.map +0 -7
- package/dist/chunks/MinigraphBubbleAdapter-AGI2UYQR.js +0 -2
- package/dist/chunks/MinigraphBubbleAdapter-AGI2UYQR.js.map +0 -7
- package/dist/chunks/RgfaTabixAdapter-2OL5X3HF.js +0 -3
- package/dist/chunks/RgfaTabixAdapter-2OL5X3HF.js.map +0 -7
- package/dist/chunks/WalkTabixSyntenyAdapter-UKFHCFOF.js +0 -2
- package/dist/chunks/WalkTabixSyntenyAdapter-UKFHCFOF.js.map +0 -7
- package/dist/chunks/chunk-5SFGHDQA.js +0 -2
- package/dist/chunks/chunk-5SFGHDQA.js.map +0 -7
- package/dist/chunks/chunk-6OPB7FOJ.js +0 -2
- package/dist/chunks/chunk-AMFIBQVR.js +0 -2
- package/dist/chunks/chunk-AMFIBQVR.js.map +0 -7
- package/dist/chunks/chunk-BJMRBVG3.js +0 -2
- package/dist/chunks/chunk-BJMRBVG3.js.map +0 -7
- package/dist/chunks/chunk-E3WYW7Z6.js +0 -2
- package/dist/chunks/chunk-EHCF6AXH.js +0 -2
- package/dist/chunks/chunk-EHCF6AXH.js.map +0 -7
- package/dist/chunks/chunk-GOFS7BXK.js +0 -3
- package/dist/chunks/chunk-GOFS7BXK.js.map +0 -7
- package/dist/chunks/chunk-IJQTSJGT.js +0 -4
- package/dist/chunks/chunk-IJQTSJGT.js.map +0 -7
- package/dist/chunks/chunk-J6NZIAZF.js +0 -2
- package/dist/chunks/chunk-J6NZIAZF.js.map +0 -7
- package/dist/chunks/chunk-LUTMKRXY.js +0 -2
- package/dist/chunks/chunk-LUTMKRXY.js.map +0 -7
- package/dist/chunks/chunk-MHPJB22Z.js +0 -2
- package/dist/chunks/chunk-MHPJB22Z.js.map +0 -7
- package/dist/chunks/chunk-TXI43PEN.js +0 -2
- package/dist/chunks/chunk-TXI43PEN.js.map +0 -7
- package/dist/chunks/chunk-WRH2EJKX.js +0 -2
- package/dist/chunks/chunk-WRH2EJKX.js.map +0 -7
- package/dist/chunks/chunk-WX26KTZM.js +0 -2
- package/dist/chunks/chunk-WX26KTZM.js.map +0 -7
- package/dist/chunks/renderSvg-ST2GBBOC.js +0 -2
- package/dist/chunks/renderSvg-ST2GBBOC.js.map +0 -7
- package/src/GraphGenomeView/components/WalkRowContextMenu.tsx +0 -105
- /package/dist/chunks/{ChooseSamplesDialog-BNVYBGJQ.js.map → ChooseSamplesDialog-JRN4YLBY.js.map} +0 -0
- /package/dist/chunks/{ChooseWalksDialog-EN3C6AQA.js.map → ChooseWalksDialog-UXLFZTZJ.js.map} +0 -0
- /package/dist/chunks/{GraphGenomeView-Z2WZKEEO.js.map → GraphGenomeView-NJ5XCREB.js.map} +0 -0
- /package/dist/chunks/{HighlightColorDialog-EYBKFSJU.js.map → HighlightColorDialog-UK5VDDV6.js.map} +0 -0
- /package/dist/chunks/{LinearGraphDisplay-WIBVWRQE.js.map → LinearGraphDisplay-TXTKAACH.js.map} +0 -0
- /package/dist/chunks/{TrackWarningsDialog-QT4YEXGD.js.map → TrackWarningsDialog-TRYBOIHX.js.map} +0 -0
- /package/dist/chunks/{chunk-AHFQHYJI.js.map → chunk-IBWORBGY.js.map} +0 -0
|
@@ -52,6 +52,10 @@ import { computed } from 'mobx'
|
|
|
52
52
|
|
|
53
53
|
import { TUBE_MAP_MODES, dependOn, geometryPainted, paneBase } from './paneBase'
|
|
54
54
|
import { walkRowRuns, walkRowsOf } from '../../RgfaTabixAdapter/walkRowRuns.ts'
|
|
55
|
+
import {
|
|
56
|
+
canonicalAssemblyName,
|
|
57
|
+
trackAssemblies,
|
|
58
|
+
} from '../../launchFromGraph/launchFromGraph'
|
|
55
59
|
import { locationIsSet } from '../../locationName.ts'
|
|
56
60
|
import { trackAdapterConfig } from '../../panSNAliases/trackAdapterConfig'
|
|
57
61
|
import {
|
|
@@ -77,6 +81,7 @@ import {
|
|
|
77
81
|
} from '../tubeMapPanels'
|
|
78
82
|
import { groupByOf, groupWalkRows, metadataColumns } from '../walkRowGroups'
|
|
79
83
|
|
|
84
|
+
import type { ScreenTransform } from './keepInView'
|
|
80
85
|
import type { WalkCut } from '../../RgfaTabixAdapter/walkRowRuns.ts'
|
|
81
86
|
import type { GraphLayers } from '../graphLayers'
|
|
82
87
|
import type { HoverHighlight } from '../hoverHighlight'
|
|
@@ -93,7 +98,7 @@ import type { FacetInput, FacetSetting } from '@jbrowse/bandage-core/facetGrid'
|
|
|
93
98
|
import type { LayoutModeValue } from '@jbrowse/bandage-core/layoutModes'
|
|
94
99
|
import type { NodeWidth } from '@jbrowse/bandage-core/nodeWidths'
|
|
95
100
|
import type { AssemblyNames } from '@jbrowse/bandage-core/reference'
|
|
96
|
-
import type { GraphNode } from '@jbrowse/bandage-core/types'
|
|
101
|
+
import type { Graph, GraphNode } from '@jbrowse/bandage-core/types'
|
|
97
102
|
import type { NodeInk } from '@jbrowse/bandage-core/util/hitDetection'
|
|
98
103
|
import type { WalkLayer } from '@jbrowse/bandage-core/walkEncoding'
|
|
99
104
|
import type { WalkLift } from '@jbrowse/bandage-core/walkHighlight'
|
|
@@ -110,6 +115,34 @@ function walkRowsFromCut(
|
|
|
110
115
|
return runs ? walkRowsOf(runs, unit) : undefined
|
|
111
116
|
}
|
|
112
117
|
|
|
118
|
+
// undefined for a pane outside any track or view, as a test makes one
|
|
119
|
+
function orUndefined<T>(get: () => T) {
|
|
120
|
+
try {
|
|
121
|
+
return get()
|
|
122
|
+
} catch {
|
|
123
|
+
return undefined
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function nodeMapOf(graph: Graph) {
|
|
128
|
+
const m = new Map<string, GraphNode>()
|
|
129
|
+
for (const n of graph.nodes) {
|
|
130
|
+
m.set(n.id, n)
|
|
131
|
+
}
|
|
132
|
+
return m
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// A node's reference interval, an allele's between its flanks
|
|
136
|
+
function spanIn(
|
|
137
|
+
nodeId: string,
|
|
138
|
+
nodeById: Map<string, GraphNode> | undefined,
|
|
139
|
+
neighbors: ReturnType<typeof buildNeighbors> | undefined,
|
|
140
|
+
) {
|
|
141
|
+
return nodeById && neighbors
|
|
142
|
+
? nodeReferenceSpan({ nodeId, nodeById, neighbors })
|
|
143
|
+
: undefined
|
|
144
|
+
}
|
|
145
|
+
|
|
113
146
|
// The layout, node color and hover as a host stores them: a view of its own
|
|
114
147
|
// as props, a track display in its config
|
|
115
148
|
export interface GraphGrammar {
|
|
@@ -122,6 +155,8 @@ export interface GraphGrammar {
|
|
|
122
155
|
hover?: HoverHighlight
|
|
123
156
|
}
|
|
124
157
|
|
|
158
|
+
type TubeColorKind = 'value' | 'tinted' | 'role' | 'path'
|
|
159
|
+
|
|
125
160
|
// The rows walk rows draw: `kept` names the samples whose walks show, by the
|
|
126
161
|
// name before the haplotype number; unset shows every walk the cut holds
|
|
127
162
|
export interface GraphRows {
|
|
@@ -133,11 +168,6 @@ export const withGraphViews = paneBase
|
|
|
133
168
|
get grammar(): GraphGrammar {
|
|
134
169
|
return {}
|
|
135
170
|
},
|
|
136
|
-
// Light paper even under a dark theme: Bandage's deletion edges, the
|
|
137
|
-
// deletion labels and the gene ink are near-black, and vanish on dark
|
|
138
|
-
get darkMode() {
|
|
139
|
-
return false
|
|
140
|
-
},
|
|
141
171
|
// a source declared but not yet loaded
|
|
142
172
|
get hasPendingSource() {
|
|
143
173
|
return false
|
|
@@ -147,11 +177,10 @@ export const withGraphViews = paneBase
|
|
|
147
177
|
},
|
|
148
178
|
// the track the graph is cut from: the one the pane is a display of
|
|
149
179
|
get sourceTrack(): AnyConfigurationModel | undefined {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
}
|
|
180
|
+
return orUndefined(() => getContainingTrack(self).configuration)
|
|
181
|
+
},
|
|
182
|
+
get containingView(): object | undefined {
|
|
183
|
+
return orUndefined(() => getContainingView(self))
|
|
155
184
|
},
|
|
156
185
|
}))
|
|
157
186
|
.views(self => {
|
|
@@ -254,14 +283,7 @@ export const withGraphViews = paneBase
|
|
|
254
283
|
}))
|
|
255
284
|
.views(self => ({
|
|
256
285
|
get nodeById() {
|
|
257
|
-
|
|
258
|
-
const m = new Map<string, GraphNode>()
|
|
259
|
-
for (const n of self.drawnGraph.nodes) {
|
|
260
|
-
m.set(n.id, n)
|
|
261
|
-
}
|
|
262
|
-
return m
|
|
263
|
-
}
|
|
264
|
-
return undefined
|
|
286
|
+
return self.drawnGraph && nodeMapOf(self.drawnGraph)
|
|
265
287
|
},
|
|
266
288
|
// bp per node id, which is all the label overlay needs of a GraphNode.
|
|
267
289
|
// Held here rather than rebuilt in the component: that render runs on
|
|
@@ -356,13 +378,21 @@ export const withGraphViews = paneBase
|
|
|
356
378
|
? { start: open.start, end: open.end }
|
|
357
379
|
: (self.statedColorDomain ?? self.graphRegion)
|
|
358
380
|
},
|
|
359
|
-
//
|
|
360
|
-
//
|
|
381
|
+
// Every node's midpoint on the reference plus the interval the hue ramps
|
|
382
|
+
// over, on the drawn graph, whose ids a folded tube map's boxes carry.
|
|
383
|
+
// Deriving it is a bounded neighbour walk per node (referenceMidpoints):
|
|
384
|
+
// 1.6 ms at 1.5k nodes, 45 ms at 30k. It depends on nothing the
|
|
385
|
+
// transform touches, so a pan or drag frame reuses it, and the nodes and
|
|
386
|
+
// the lanes share it. Read only behind walkRamp's and referenceRamp's
|
|
387
|
+
// gates, so a colouring that ignores it never runs the walk.
|
|
388
|
+
get drawnReferenceRamp() {
|
|
389
|
+
const graph = self.drawnGraph
|
|
390
|
+
return graph ? computeReferenceRamp(graph, this.rampDomain) : undefined
|
|
391
|
+
},
|
|
392
|
+
// the ramp a lane coloured by reference position reads
|
|
361
393
|
get walkRamp() {
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
self.walkLayers.some(layer => layer.color?.field === 'reference')
|
|
365
|
-
? computeReferenceRamp(graph, this.rampDomain)
|
|
394
|
+
return self.walkLayers.some(layer => layer.color?.field === 'reference')
|
|
395
|
+
? this.drawnReferenceRamp
|
|
366
396
|
: undefined
|
|
367
397
|
},
|
|
368
398
|
// Whether the chosen layout draws the graph's nodes, which a facet
|
|
@@ -470,8 +500,13 @@ export const withGraphViews = paneBase
|
|
|
470
500
|
? 'uniform'
|
|
471
501
|
: resolveColorScheme(self.chosenColorScheme, self.graph)
|
|
472
502
|
},
|
|
503
|
+
// Panels lay their walks out without the reads
|
|
473
504
|
get tubeMapReads() {
|
|
474
|
-
|
|
505
|
+
const layout = self.layoutResult
|
|
506
|
+
return (
|
|
507
|
+
!layout?.tubeMapPanels &&
|
|
508
|
+
(layout?.tubeMap?.layout.reads.length ?? 0) > 0
|
|
509
|
+
)
|
|
475
510
|
},
|
|
476
511
|
// Why no node scheme is on screen to pick, for every control that
|
|
477
512
|
// offers one: lifted walks colour their own lanes and grey the rest,
|
|
@@ -496,14 +531,9 @@ export const withGraphViews = paneBase
|
|
|
496
531
|
get labelsNodeSizes() {
|
|
497
532
|
return !self.layoutResult?.tubeMap && !this.walkLift
|
|
498
533
|
},
|
|
499
|
-
//
|
|
500
|
-
//
|
|
501
|
-
|
|
502
|
-
return self.layoutResult?.rowLabels ?? []
|
|
503
|
-
},
|
|
504
|
-
// Deletions the layout found inside an allele, empty for the same reason
|
|
505
|
-
// rowLabels is: a layout drawn at sequence scale states none, because
|
|
506
|
-
// there a node's drawn extent already IS its length. `deletions` beside
|
|
534
|
+
// Deletions the layout found inside an allele, empty rather than
|
|
535
|
+
// undefined: a layout drawn at sequence scale states none, because there
|
|
536
|
+
// a node's drawn extent already IS its length. `deletions` beside
|
|
507
537
|
// this one is the bare-edge kind, which every layout has.
|
|
508
538
|
get alleleDeletions() {
|
|
509
539
|
return self.layoutResult?.alleleDeletions ?? []
|
|
@@ -634,22 +664,26 @@ export const withGraphViews = paneBase
|
|
|
634
664
|
const track = self.sourceTrack
|
|
635
665
|
return track ? (readConfObject(track, 'trackId') as string) : undefined
|
|
636
666
|
},
|
|
667
|
+
// The session's tracks, each with the assemblies it covers by canonical
|
|
668
|
+
// name, since a track may name one by an alias
|
|
669
|
+
get sessionTracks() {
|
|
670
|
+
const session = getSession(self)
|
|
671
|
+
return session.tracks.map(t => ({
|
|
672
|
+
trackId: t.trackId as string,
|
|
673
|
+
name: readConfObject(t, 'name') as string,
|
|
674
|
+
adapterType: (readConfObject(t, 'adapter') as { type: string }).type,
|
|
675
|
+
assemblies: trackAssemblies(session, t),
|
|
676
|
+
}))
|
|
677
|
+
},
|
|
678
|
+
}))
|
|
679
|
+
.views(self => ({
|
|
637
680
|
get assemblyTrackChoices() {
|
|
638
681
|
const region = self.graphRegion
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
(readConfObject(t, 'assemblyNames') as string[]).includes(
|
|
645
|
-
region.assemblyName,
|
|
646
|
-
),
|
|
647
|
-
)
|
|
648
|
-
.map(t => ({
|
|
649
|
-
trackId: t.trackId as string,
|
|
650
|
-
name: readConfObject(t, 'name') as string,
|
|
651
|
-
adapterType: (readConfObject(t, 'adapter') as { type: string }).type,
|
|
652
|
-
}))
|
|
682
|
+
const assembly =
|
|
683
|
+
region && canonicalAssemblyName(getSession(self), region.assemblyName)
|
|
684
|
+
return assembly
|
|
685
|
+
? self.sessionTracks.filter(t => t.assemblies.includes(assembly))
|
|
686
|
+
: []
|
|
653
687
|
},
|
|
654
688
|
}))
|
|
655
689
|
.views(self => ({
|
|
@@ -733,10 +767,8 @@ export const withGraphViews = paneBase
|
|
|
733
767
|
},
|
|
734
768
|
// the filter of the gene track's lane in the view the pane draws in
|
|
735
769
|
get geneLaneFilter() {
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
view = getContainingView(self)
|
|
739
|
-
} catch {
|
|
770
|
+
const view = self.containingView
|
|
771
|
+
if (!view) {
|
|
740
772
|
return undefined
|
|
741
773
|
}
|
|
742
774
|
const filters = laneFilters(view, self.geneTrack?.trackId)
|
|
@@ -755,14 +787,13 @@ export const withGraphViews = paneBase
|
|
|
755
787
|
? geneModelsFrom(lane ? features.filter(f => lane.passes(f)) : features)
|
|
756
788
|
: undefined
|
|
757
789
|
},
|
|
758
|
-
}))
|
|
759
|
-
.views(self => ({
|
|
760
790
|
// The genes on the drawn backbone under its own refNames. The track's
|
|
761
791
|
// config puts its reference on the cut's assembly, whatever the walk's
|
|
762
792
|
// name. After "Draw x along" another walk, the backbone takes the genes
|
|
763
793
|
// only where its PanSN prefix names their assembly.
|
|
764
794
|
get backboneGenes() {
|
|
765
|
-
const { backbone
|
|
795
|
+
const { backbone } = self
|
|
796
|
+
const { geneAssembly, geneFeatures } = this
|
|
766
797
|
const binds =
|
|
767
798
|
self.drawsLoadedReference ||
|
|
768
799
|
(geneAssembly !== undefined &&
|
|
@@ -858,46 +889,47 @@ export const withGraphViews = paneBase
|
|
|
858
889
|
unvalued: walks.some(w => valueOf(w) === ''),
|
|
859
890
|
}
|
|
860
891
|
},
|
|
892
|
+
// The grouping by a sample table column, once the table is read and
|
|
893
|
+
// has that column
|
|
894
|
+
get tableGroupBy() {
|
|
895
|
+
const groupBy = self.walkRowGroupBy
|
|
896
|
+
const table = self.walkRowSampleTable
|
|
897
|
+
return groupBy && table && this.walkRowGroupFields.includes(groupBy.field)
|
|
898
|
+
? { groupBy, table }
|
|
899
|
+
: undefined
|
|
900
|
+
},
|
|
861
901
|
// How a tube map splits into panels: by sample or walk, or by a sample
|
|
862
|
-
// table column
|
|
902
|
+
// table column
|
|
863
903
|
get tubeMapPanelSplit(): TubeMapPanelSplit | undefined {
|
|
864
904
|
const { field, domain } = self.facetSetting
|
|
865
|
-
const
|
|
866
|
-
const table = self.walkRowSampleTable
|
|
905
|
+
const grouped = this.tableGroupBy
|
|
867
906
|
return field !== ''
|
|
868
907
|
? { by: field, domain }
|
|
869
|
-
:
|
|
870
|
-
? { by: 'column', ...groupBy, table }
|
|
908
|
+
: grouped
|
|
909
|
+
? { by: 'column', ...grouped.groupBy, table: grouped.table }
|
|
871
910
|
: undefined
|
|
872
911
|
},
|
|
873
|
-
//
|
|
912
|
+
// the cohort's rows the sample filter keeps
|
|
913
|
+
get keptCohortRows() {
|
|
914
|
+
const bars = this.cohortWalkRows
|
|
915
|
+
return bars && filterSamples(bars.rows, self.walkRowSamples)
|
|
916
|
+
},
|
|
917
|
+
// The kept rows in a section per value of the grouped column, or
|
|
874
918
|
// undefined while ungrouped or the table lacks that column
|
|
875
919
|
get walkRowGroups() {
|
|
876
|
-
const
|
|
877
|
-
const
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
table &&
|
|
881
|
-
groupBy &&
|
|
882
|
-
this.walkRowGroupFields.includes(groupBy.field)
|
|
883
|
-
? groupWalkRows(
|
|
884
|
-
filterSamples(bars.rows, self.walkRowSamples),
|
|
885
|
-
table,
|
|
886
|
-
groupBy,
|
|
887
|
-
)
|
|
920
|
+
const rows = this.keptCohortRows
|
|
921
|
+
const grouped = this.tableGroupBy
|
|
922
|
+
return rows && grouped
|
|
923
|
+
? groupWalkRows(rows, grouped.table, grouped.groupBy)
|
|
888
924
|
: undefined
|
|
889
925
|
},
|
|
890
926
|
// The bars the overlay draws: the cohort's, narrowed by the sample
|
|
891
927
|
// filter, and stacked section by section while grouped
|
|
892
928
|
get walkRowBars() {
|
|
893
929
|
const bars = this.cohortWalkRows
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
rows:
|
|
898
|
-
this.walkRowGroups?.rows ??
|
|
899
|
-
filterSamples(bars.rows, self.walkRowSamples),
|
|
900
|
-
}
|
|
930
|
+
const rows = this.keptCohortRows
|
|
931
|
+
return bars && rows
|
|
932
|
+
? { ...bars, rows: this.walkRowGroups?.rows ?? rows }
|
|
901
933
|
: undefined
|
|
902
934
|
},
|
|
903
935
|
// Whether the canvas draws the graph's nodes. A tube map and walk rows
|
|
@@ -933,23 +965,11 @@ export const withGraphViews = paneBase
|
|
|
933
965
|
}
|
|
934
966
|
return bubbleHalos(self.graph, self.bubbles, positions, self.repeatArrays)
|
|
935
967
|
},
|
|
936
|
-
//
|
|
937
|
-
//
|
|
938
|
-
// other scheme so the walk is never run for a colouring that ignores it.
|
|
939
|
-
//
|
|
940
|
-
// Here for the same reason `deletions` is, only more so: deriving it is a
|
|
941
|
-
// bounded neighbour walk PER NODE (referenceMidpoints), it depends on
|
|
942
|
-
// nothing the transform touches, and it was being redone inside every
|
|
943
|
-
// geometry rebuild — 1.6 ms at 1.5k nodes, 45 ms at 30k, on a pass that
|
|
944
|
-
// reruns on each debounced pan and each drag frame. `reference-position`
|
|
945
|
-
// is also what `auto` resolves to on any anchored graph, so this was the
|
|
946
|
-
// default path rather than an opt-in one.
|
|
947
|
-
//
|
|
948
|
-
// On the drawn graph, whose ids a folded tube map's boxes carry
|
|
968
|
+
// What `reference-position` paints from, which is also what `auto`
|
|
969
|
+
// resolves to on any anchored graph
|
|
949
970
|
get referenceRamp() {
|
|
950
|
-
return self.effectiveColorScheme === 'reference-position'
|
|
951
|
-
self.
|
|
952
|
-
? computeReferenceRamp(self.drawnGraph, self.rampDomain)
|
|
971
|
+
return self.effectiveColorScheme === 'reference-position'
|
|
972
|
+
? self.drawnReferenceRamp
|
|
953
973
|
: undefined
|
|
954
974
|
},
|
|
955
975
|
// The assemblies this view is showing, which is the interface every
|
|
@@ -979,12 +999,7 @@ export const withGraphViews = paneBase
|
|
|
979
999
|
//
|
|
980
1000
|
// Everything that mixes the two axes takes their ratio as `yToX`
|
|
981
1001
|
// (scaleY / scaleX) — see computeEdgeCurves.
|
|
982
|
-
|
|
983
|
-
return axisScaleOf(self.scale, self.pixelRows).scaleX
|
|
984
|
-
},
|
|
985
|
-
get scaleY() {
|
|
986
|
-
return axisScaleOf(self.scale, self.pixelRows).scaleY
|
|
987
|
-
},
|
|
1002
|
+
//
|
|
988
1003
|
// The pair, for everything that draws or hit-tests. Handed over as one
|
|
989
1004
|
// value on purpose: every consumer needs both, and passing them separately
|
|
990
1005
|
// let a caller supply the x scale and default y, which compiles and draws
|
|
@@ -992,8 +1007,29 @@ export const withGraphViews = paneBase
|
|
|
992
1007
|
get axisScale() {
|
|
993
1008
|
return axisScaleOf(self.scale, self.pixelRows)
|
|
994
1009
|
},
|
|
1010
|
+
get scaleX() {
|
|
1011
|
+
return this.axisScale.scaleX
|
|
1012
|
+
},
|
|
1013
|
+
get scaleY() {
|
|
1014
|
+
return this.axisScale.scaleY
|
|
1015
|
+
},
|
|
995
1016
|
}))
|
|
996
1017
|
.views(self => ({
|
|
1018
|
+
// layout units to pane px
|
|
1019
|
+
get screenTransform(): ScreenTransform {
|
|
1020
|
+
return {
|
|
1021
|
+
scaleX: self.scaleX,
|
|
1022
|
+
scaleY: self.scaleY,
|
|
1023
|
+
translateX: self.translateX,
|
|
1024
|
+
translateY: self.translateY,
|
|
1025
|
+
}
|
|
1026
|
+
},
|
|
1027
|
+
toScreen(p: { x: number; y: number }) {
|
|
1028
|
+
return {
|
|
1029
|
+
x: p.x * self.scaleX + self.translateX,
|
|
1030
|
+
y: p.y * self.scaleY + self.translateY,
|
|
1031
|
+
}
|
|
1032
|
+
},
|
|
997
1033
|
get deletionDrawing() {
|
|
998
1034
|
return self.graph
|
|
999
1035
|
? deletionDrawing(self.graph, self.allDeletions, self.showDeletionEdges)
|
|
@@ -1060,43 +1096,79 @@ export const withGraphViews = paneBase
|
|
|
1060
1096
|
)
|
|
1061
1097
|
: undefined
|
|
1062
1098
|
},
|
|
1063
|
-
//
|
|
1064
|
-
//
|
|
1065
|
-
//
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
const
|
|
1099
|
+
// How a tube map colours its tubes: a hue per value of the column
|
|
1100
|
+
// picked; grey by role beside tinted boxes, which a hue per walk would
|
|
1101
|
+
// share; the reference charcoal and the haplotypes blue in a panel, whose
|
|
1102
|
+
// title names its walks, and past the walks a key can name; else a hue
|
|
1103
|
+
// per walk. Beside reads, which take the reds and blues, that hue is grey.
|
|
1104
|
+
get tubeColorKind(): TubeColorKind | undefined {
|
|
1105
|
+
const layout = self.layoutResult
|
|
1106
|
+
const paths = self.drawnGraph?.paths ?? []
|
|
1107
|
+
const reads = self.tubeMapReads
|
|
1108
|
+
return !layout?.tubeMap
|
|
1109
|
+
? undefined
|
|
1110
|
+
: self.tubeMapColoring && !reads
|
|
1111
|
+
? 'value'
|
|
1112
|
+
: layout.tubeMapPanels
|
|
1113
|
+
? 'role'
|
|
1114
|
+
: this.tubeMapNodeColors
|
|
1115
|
+
? 'tinted'
|
|
1116
|
+
: !reads &&
|
|
1117
|
+
(!pathColorsLegible(paths.length) ||
|
|
1118
|
+
paths.some(p => p.members))
|
|
1119
|
+
? 'role'
|
|
1120
|
+
: 'path'
|
|
1121
|
+
},
|
|
1122
|
+
// `graph`'s tubes as tubeColorKind colours them, `pathColors` being
|
|
1123
|
+
// its drawing's hue per walk
|
|
1124
|
+
tubeColorsOf(graph: Graph, pathColors: readonly string[]) {
|
|
1125
|
+
const paths = graph.paths ?? []
|
|
1126
|
+
const kind = this.tubeColorKind
|
|
1070
1127
|
const coloring = self.tubeMapColoring
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1128
|
+
return kind === 'value' && coloring
|
|
1129
|
+
? valueTubeColors(
|
|
1130
|
+
paths,
|
|
1131
|
+
graph.referencePath,
|
|
1132
|
+
coloring.valueOf,
|
|
1133
|
+
coloring.palette,
|
|
1134
|
+
)
|
|
1135
|
+
: kind === 'tinted'
|
|
1136
|
+
? roleTubeColors(paths, graph.referencePath, TINTED_TUBES)
|
|
1137
|
+
: kind === 'role'
|
|
1138
|
+
? roleTubeColors(paths, graph.referencePath)
|
|
1139
|
+
: pathColors
|
|
1140
|
+
},
|
|
1141
|
+
// While a lane row is hovered, every tube but its walks' and `kept`'s
|
|
1142
|
+
// fades. A panel keeps its reference to compare against; the unsplit map
|
|
1143
|
+
// fades it with the rest.
|
|
1144
|
+
fadeUnhovered(
|
|
1145
|
+
colors: readonly string[],
|
|
1146
|
+
paths: readonly { name: string }[],
|
|
1147
|
+
kept?: string,
|
|
1148
|
+
) {
|
|
1087
1149
|
const hovered = new Set(self.hoveredRowWalks)
|
|
1088
|
-
return
|
|
1089
|
-
?
|
|
1090
|
-
|
|
1150
|
+
return hovered.size > 0
|
|
1151
|
+
? colors.map((color, i) => {
|
|
1152
|
+
const name = paths[i]?.name ?? ''
|
|
1153
|
+
return hovered.has(name) ||
|
|
1154
|
+
(kept !== undefined && pathOrigin(name).name === kept)
|
|
1155
|
+
? color
|
|
1156
|
+
: LIFT_BACKDROP_CSS
|
|
1157
|
+
})
|
|
1158
|
+
: colors
|
|
1159
|
+
},
|
|
1160
|
+
get tubeMapTubeColors() {
|
|
1161
|
+
const drawing = self.layoutResult?.tubeMap
|
|
1162
|
+
const graph = self.drawnGraph
|
|
1163
|
+
return drawing && graph
|
|
1164
|
+
? this.fadeUnhovered(
|
|
1165
|
+
this.tubeColorsOf(graph, drawing.pathColors),
|
|
1166
|
+
graph.paths ?? [],
|
|
1091
1167
|
)
|
|
1092
|
-
:
|
|
1168
|
+
: undefined
|
|
1093
1169
|
},
|
|
1094
|
-
// A node's reference interval, an allele's between its flanks
|
|
1095
1170
|
nodeSpan(nodeId: string) {
|
|
1096
|
-
|
|
1097
|
-
return nodeById && neighbors
|
|
1098
|
-
? nodeReferenceSpan({ nodeId, nodeById, neighbors })
|
|
1099
|
-
: undefined
|
|
1171
|
+
return spanIn(nodeId, self.nodeById, self.nodeNeighbors)
|
|
1100
1172
|
},
|
|
1101
1173
|
// The drawing the pointer is over: its panel's while a tube map is split,
|
|
1102
1174
|
// each panel laid out alone and merging its own runs
|
|
@@ -1109,22 +1181,18 @@ export const withGraphViews = paneBase
|
|
|
1109
1181
|
self.layoutResult?.tubeMap
|
|
1110
1182
|
)
|
|
1111
1183
|
},
|
|
1112
|
-
}))
|
|
1113
|
-
.views(self => ({
|
|
1114
1184
|
// the graph whose ids the hover names
|
|
1115
1185
|
get hoverGraph() {
|
|
1116
|
-
return
|
|
1186
|
+
return this.hoverDrawing?.graph ?? self.drawnGraph
|
|
1117
1187
|
},
|
|
1118
|
-
}))
|
|
1119
|
-
.views(self => ({
|
|
1120
1188
|
get hoverNodeById() {
|
|
1121
|
-
const graph =
|
|
1189
|
+
const graph = this.hoverGraph
|
|
1122
1190
|
return graph === self.drawnGraph
|
|
1123
1191
|
? self.nodeById
|
|
1124
|
-
: graph &&
|
|
1192
|
+
: graph && nodeMapOf(graph)
|
|
1125
1193
|
},
|
|
1126
1194
|
get hoverNeighbors() {
|
|
1127
|
-
const graph =
|
|
1195
|
+
const graph = this.hoverGraph
|
|
1128
1196
|
return graph === self.drawnGraph
|
|
1129
1197
|
? self.nodeNeighbors
|
|
1130
1198
|
: graph && buildNeighbors(graph)
|
|
@@ -1137,20 +1205,17 @@ export const withGraphViews = paneBase
|
|
|
1137
1205
|
// Empty unless the ribbons are actually on: a colour key beside a drawing
|
|
1138
1206
|
// with no colours in it is a legend for nothing.
|
|
1139
1207
|
// The tube map colours its tubes whether or not paths are drawn on the
|
|
1140
|
-
// nodes, so under it the key follows the tubes
|
|
1141
|
-
// the
|
|
1208
|
+
// nodes, so under it the key follows the tubes: walk by walk where each
|
|
1209
|
+
// has a hue, and otherwise the tube map's own key names the colours.
|
|
1142
1210
|
get pathLegend() {
|
|
1143
1211
|
const paths = self.drawnGraph?.paths
|
|
1144
|
-
const
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
return
|
|
1212
|
+
const keyed = self.layoutResult?.tubeMap
|
|
1213
|
+
? self.tubeColorKind === 'path'
|
|
1214
|
+
: self.drawPaths
|
|
1215
|
+
return keyed &&
|
|
1148
1216
|
paths &&
|
|
1149
1217
|
pathColorsLegible(paths.length) &&
|
|
1150
|
-
!
|
|
1151
|
-
!self.tubeMapNodeColors &&
|
|
1152
|
-
!paths.some(p => p.members) &&
|
|
1153
|
-
!self.tubeMapColoring
|
|
1218
|
+
!paths.some(p => p.members)
|
|
1154
1219
|
? pathLegend(paths, self.tubeMapTubeColors)
|
|
1155
1220
|
: []
|
|
1156
1221
|
},
|
|
@@ -1159,24 +1224,18 @@ export const withGraphViews = paneBase
|
|
|
1159
1224
|
get hoveredSpan() {
|
|
1160
1225
|
const nodeId = self.hoveredNode
|
|
1161
1226
|
const bubble = self.hoveredBubble
|
|
1162
|
-
const nodeById = self.hoverNodeById
|
|
1163
|
-
const neighbors = self.hoverNeighbors
|
|
1164
1227
|
return nodeId !== null
|
|
1165
|
-
?
|
|
1166
|
-
? nodeReferenceSpan({ nodeId, nodeById, neighbors })
|
|
1167
|
-
: undefined
|
|
1228
|
+
? spanIn(nodeId, self.hoverNodeById, self.hoverNeighbors)
|
|
1168
1229
|
: bubble && !bubble.offReference
|
|
1169
1230
|
? { start: bubble.start, end: bubble.end }
|
|
1170
1231
|
: undefined
|
|
1171
1232
|
},
|
|
1172
|
-
}))
|
|
1173
|
-
.views(self => ({
|
|
1174
1233
|
// The hovered span, for a connected linear view to highlight. Only a
|
|
1175
1234
|
// graph cut from a track has one: a whole-file import has no region, and
|
|
1176
1235
|
// its stable names need not name anything in a loaded assembly.
|
|
1177
1236
|
get hoverHighlight() {
|
|
1178
1237
|
const region = self.graphRegion
|
|
1179
|
-
const span =
|
|
1238
|
+
const span = this.hoveredSpan
|
|
1180
1239
|
return region && span && self.chosenHover !== 'off'
|
|
1181
1240
|
? {
|
|
1182
1241
|
refName: region.refName,
|
|
@@ -14,7 +14,6 @@ import { tubeMapPicture } from '@jbrowse/bandage-core/tubeMap/draw'
|
|
|
14
14
|
import { tubeMapGenes } from '@jbrowse/bandage-core/tubeMap/genes'
|
|
15
15
|
|
|
16
16
|
import { hostFrame } from '../host'
|
|
17
|
-
import { PAPER_DARK, PAPER_LIGHT, paperCss } from './paneBase'
|
|
18
17
|
import { withWalkRowViews } from './walkRowViews'
|
|
19
18
|
|
|
20
19
|
export const withHostViews = withWalkRowViews
|
|
@@ -166,17 +165,13 @@ export const withHostViews = withWalkRowViews
|
|
|
166
165
|
if (!self.referenceStripShown) {
|
|
167
166
|
return undefined
|
|
168
167
|
}
|
|
169
|
-
const toScreen = (p: { x: number; y: number }) => ({
|
|
170
|
-
x: p.x * self.scaleX + self.translateX,
|
|
171
|
-
y: p.y * self.scaleY + self.translateY,
|
|
172
|
-
})
|
|
173
168
|
const bubble = self.hoveredNode === null ? self.hoveredBubble : null
|
|
174
169
|
if (bubble && !bubble.offReference) {
|
|
175
170
|
const halo = self.bubbleHalos.find(h => sameBubble(h.bubble, bubble))
|
|
176
171
|
return {
|
|
177
172
|
start: bubble.start,
|
|
178
173
|
end: bubble.end,
|
|
179
|
-
anchor: halo ? toScreen(halo.labelAt) : undefined,
|
|
174
|
+
anchor: halo ? self.toScreen(halo.labelAt) : undefined,
|
|
180
175
|
}
|
|
181
176
|
}
|
|
182
177
|
const nodeId = self.hoveredNode ?? self.selectedNode
|
|
@@ -184,7 +179,7 @@ export const withHostViews = withWalkRowViews
|
|
|
184
179
|
return span && nodeId !== null
|
|
185
180
|
? {
|
|
186
181
|
...span,
|
|
187
|
-
anchor: nodeAnchor(self.nodePositions?.[nodeId], toScreen),
|
|
182
|
+
anchor: nodeAnchor(self.nodePositions?.[nodeId], self.toScreen),
|
|
188
183
|
}
|
|
189
184
|
: undefined
|
|
190
185
|
},
|
|
@@ -194,9 +189,6 @@ export const withHostViews = withWalkRowViews
|
|
|
194
189
|
? stripBlockAt(self.referenceStripBlocks, frame, sx, sy)
|
|
195
190
|
: undefined
|
|
196
191
|
},
|
|
197
|
-
get paperCss() {
|
|
198
|
-
return paperCss(self.darkMode ? PAPER_DARK : PAPER_LIGHT)
|
|
199
|
-
},
|
|
200
192
|
// the strip, and the gap the fit leaves under it
|
|
201
193
|
get referenceStripZonePx() {
|
|
202
194
|
return self.referenceStripShown ? REFERENCE_STRIP_ZONE_PX : 0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// How much of the drawing a pan or zoom leaves on screen in each axis, or
|
|
2
2
|
// all of it when it is smaller
|
|
3
|
-
|
|
3
|
+
const KEEP_IN_VIEW_PX = 48
|
|
4
4
|
|
|
5
5
|
// The shift that brings a span starting at `lo`, `size` px long, back to
|
|
6
6
|
// overlapping [0, extent] by `margin` px
|
|
@@ -16,7 +16,8 @@ interface DrawingBox {
|
|
|
16
16
|
h: number
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
// layout units to pane px, per axis
|
|
20
|
+
export interface ScreenTransform {
|
|
20
21
|
scaleX: number
|
|
21
22
|
scaleY: number
|
|
22
23
|
translateX: number
|
|
@@ -25,7 +26,7 @@ interface Placement {
|
|
|
25
26
|
|
|
26
27
|
export function keepInView(
|
|
27
28
|
bounds: DrawingBox,
|
|
28
|
-
t:
|
|
29
|
+
t: ScreenTransform,
|
|
29
30
|
view: { width: number; height: number },
|
|
30
31
|
) {
|
|
31
32
|
return {
|
|
@@ -48,7 +49,7 @@ export function keepInView(
|
|
|
48
49
|
|
|
49
50
|
export function onScreen(
|
|
50
51
|
bounds: DrawingBox,
|
|
51
|
-
t:
|
|
52
|
+
t: ScreenTransform,
|
|
52
53
|
view: { width: number; height: number },
|
|
53
54
|
) {
|
|
54
55
|
const left = bounds.minX * t.scaleX + t.translateX
|