@jbrowse/plugin-variants 2.2.1 → 2.3.0
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/dist/ChordVariantDisplay/index.js +1 -0
- package/dist/ChordVariantDisplay/index.js.map +1 -1
- package/dist/ChordVariantDisplay/models/stateModelFactory.d.ts +4 -2
- package/dist/ChordVariantDisplay/models/stateModelFactory.js +1 -2
- package/dist/ChordVariantDisplay/models/stateModelFactory.js.map +1 -1
- package/dist/LinearVariantDisplay/index.js +1 -0
- package/dist/LinearVariantDisplay/index.js.map +1 -1
- package/dist/LinearVariantDisplay/model.d.ts +3 -7
- package/dist/StructuralVariantChordRenderer/Chord.d.ts +32 -0
- package/dist/StructuralVariantChordRenderer/Chord.js +88 -0
- package/dist/StructuralVariantChordRenderer/Chord.js.map +1 -0
- package/dist/StructuralVariantChordRenderer/ReactComponent.d.ts +1 -17
- package/dist/StructuralVariantChordRenderer/ReactComponent.js +11 -93
- package/dist/StructuralVariantChordRenderer/ReactComponent.js.map +1 -1
- package/dist/StructuralVariantChordRenderer/index.d.ts +2 -2
- package/dist/StructuralVariantChordRenderer/index.js +2 -2
- package/dist/StructuralVariantChordRenderer/index.js.map +1 -1
- package/dist/VariantFeatureWidget/BreakendOptionDialog.js +13 -22
- package/dist/VariantFeatureWidget/BreakendOptionDialog.js.map +1 -1
- package/dist/VariantTrack/index.js +1 -0
- package/dist/VariantTrack/index.js.map +1 -1
- package/dist/VcfAdapter/VcfAdapter.js +1 -0
- package/dist/VcfAdapter/VcfAdapter.js.map +1 -1
- package/dist/VcfAdapter/index.js +1 -0
- package/dist/VcfAdapter/index.js.map +1 -1
- package/dist/VcfTabixAdapter/VcfTabixAdapter.js +8 -11
- package/dist/VcfTabixAdapter/VcfTabixAdapter.js.map +1 -1
- package/dist/VcfTabixAdapter/index.js +1 -0
- package/dist/VcfTabixAdapter/index.js.map +1 -1
- package/esm/ChordVariantDisplay/index.js +1 -0
- package/esm/ChordVariantDisplay/index.js.map +1 -1
- package/esm/ChordVariantDisplay/models/stateModelFactory.d.ts +4 -2
- package/esm/ChordVariantDisplay/models/stateModelFactory.js +1 -2
- package/esm/ChordVariantDisplay/models/stateModelFactory.js.map +1 -1
- package/esm/LinearVariantDisplay/index.js +1 -0
- package/esm/LinearVariantDisplay/index.js.map +1 -1
- package/esm/LinearVariantDisplay/model.d.ts +3 -7
- package/esm/StructuralVariantChordRenderer/Chord.d.ts +32 -0
- package/esm/StructuralVariantChordRenderer/Chord.js +83 -0
- package/esm/StructuralVariantChordRenderer/Chord.js.map +1 -0
- package/esm/StructuralVariantChordRenderer/ReactComponent.d.ts +1 -17
- package/esm/StructuralVariantChordRenderer/ReactComponent.js +7 -92
- package/esm/StructuralVariantChordRenderer/ReactComponent.js.map +1 -1
- package/esm/StructuralVariantChordRenderer/index.d.ts +2 -2
- package/esm/StructuralVariantChordRenderer/index.js +2 -2
- package/esm/StructuralVariantChordRenderer/index.js.map +1 -1
- package/esm/VariantFeatureWidget/BreakendOptionDialog.js +14 -20
- package/esm/VariantFeatureWidget/BreakendOptionDialog.js.map +1 -1
- package/esm/VariantTrack/index.js +1 -0
- package/esm/VariantTrack/index.js.map +1 -1
- package/esm/VcfAdapter/VcfAdapter.js +1 -0
- package/esm/VcfAdapter/VcfAdapter.js.map +1 -1
- package/esm/VcfAdapter/index.js +1 -0
- package/esm/VcfAdapter/index.js.map +1 -1
- package/esm/VcfTabixAdapter/VcfTabixAdapter.js +8 -11
- package/esm/VcfTabixAdapter/VcfTabixAdapter.js.map +1 -1
- package/esm/VcfTabixAdapter/index.js +1 -0
- package/esm/VcfTabixAdapter/index.js.map +1 -1
- package/package.json +5 -6
- package/src/ChordVariantDisplay/index.ts +1 -0
- package/src/ChordVariantDisplay/models/stateModelFactory.ts +1 -3
- package/src/LinearVariantDisplay/configSchema.test.js +1 -1
- package/src/LinearVariantDisplay/index.ts +1 -0
- package/src/StructuralVariantChordRenderer/Chord.tsx +141 -0
- package/src/StructuralVariantChordRenderer/ReactComponent.tsx +10 -149
- package/src/StructuralVariantChordRenderer/index.ts +2 -3
- package/src/VariantFeatureWidget/BreakendOptionDialog.tsx +16 -32
- package/src/VariantTrack/index.ts +1 -0
- package/src/VcfAdapter/VcfAdapter.ts +2 -0
- package/src/VcfAdapter/index.ts +1 -0
- package/src/VcfTabixAdapter/VcfTabixAdapter.ts +10 -15
- package/src/VcfTabixAdapter/index.ts +1 -0
- package/dist/ChordVariantDisplay/models/ChordVariantDisplay.d.ts +0 -117
- package/dist/ChordVariantDisplay/models/ChordVariantDisplay.js +0 -62
- package/dist/ChordVariantDisplay/models/ChordVariantDisplay.js.map +0 -1
- package/esm/ChordVariantDisplay/models/ChordVariantDisplay.d.ts +0 -117
- package/esm/ChordVariantDisplay/models/ChordVariantDisplay.js +0 -57
- package/esm/ChordVariantDisplay/models/ChordVariantDisplay.js.map +0 -1
- package/src/ChordVariantDisplay/models/ChordVariantDisplay.ts +0 -69
|
@@ -4,23 +4,20 @@ import { bytesForRegions } from '@jbrowse/core/util';
|
|
|
4
4
|
import { ObservableCreate } from '@jbrowse/core/util/rxjs';
|
|
5
5
|
import { TabixIndexedFile } from '@gmod/tabix';
|
|
6
6
|
import VcfParser from '@gmod/vcf';
|
|
7
|
-
|
|
7
|
+
// local
|
|
8
8
|
import VcfFeature from './VcfFeature';
|
|
9
9
|
export default class extends BaseFeatureDataAdapter {
|
|
10
10
|
async configurePre() {
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
const
|
|
14
|
-
const
|
|
11
|
+
const pm = this.pluginManager;
|
|
12
|
+
const vcfGzLocation = this.getConf('vcfGzLocation');
|
|
13
|
+
const location = this.getConf(['index', 'location']);
|
|
14
|
+
const indexType = this.getConf(['index', 'indexType']);
|
|
15
|
+
const filehandle = openLocation(vcfGzLocation, pm);
|
|
15
16
|
const isCSI = indexType === 'CSI';
|
|
16
17
|
const vcf = new TabixIndexedFile({
|
|
17
18
|
filehandle,
|
|
18
|
-
csiFilehandle: isCSI
|
|
19
|
-
|
|
20
|
-
: undefined,
|
|
21
|
-
tbiFilehandle: !isCSI
|
|
22
|
-
? openLocation(location, this.pluginManager)
|
|
23
|
-
: undefined,
|
|
19
|
+
csiFilehandle: isCSI ? openLocation(location, pm) : undefined,
|
|
20
|
+
tbiFilehandle: !isCSI ? openLocation(location, pm) : undefined,
|
|
24
21
|
chunkCacheSize: 50 * 2 ** 20,
|
|
25
22
|
chunkSizeLimit: 1000000000,
|
|
26
23
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VcfTabixAdapter.js","sourceRoot":"","sources":["../../src/VcfTabixAdapter/VcfTabixAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sBAAsB,GAEvB,MAAM,yCAAyC,CAAA;AAMhD,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAA;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAE1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAC9C,OAAO,SAAS,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"VcfTabixAdapter.js","sourceRoot":"","sources":["../../src/VcfTabixAdapter/VcfTabixAdapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,6 +4,7 @@ export { default as configSchema } from './configSchema';
|
|
|
4
4
|
export default (pluginManager) => {
|
|
5
5
|
pluginManager.addAdapterType(() => new AdapterType({
|
|
6
6
|
name: 'VcfTabixAdapter',
|
|
7
|
+
displayName: 'VCF tabix adapter',
|
|
7
8
|
configSchema,
|
|
8
9
|
getAdapterClass: () => import('./VcfTabixAdapter').then(r => r.default),
|
|
9
10
|
}));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/VcfTabixAdapter/index.ts"],"names":[],"mappings":"AACA,OAAO,WAAW,MAAM,iDAAiD,CAAA;AACzE,OAAO,YAAY,MAAM,gBAAgB,CAAA;AAEzC,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAExD,eAAe,CAAC,aAA4B,EAAE,EAAE;IAC9C,aAAa,CAAC,cAAc,CAC1B,GAAG,EAAE,CACH,IAAI,WAAW,CAAC;QACd,IAAI,EAAE,iBAAiB;QACvB,YAAY;QACZ,eAAe,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;KACxE,CAAC,CACL,CAAA;AACH,CAAC,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/VcfTabixAdapter/index.ts"],"names":[],"mappings":"AACA,OAAO,WAAW,MAAM,iDAAiD,CAAA;AACzE,OAAO,YAAY,MAAM,gBAAgB,CAAA;AAEzC,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAExD,eAAe,CAAC,aAA4B,EAAE,EAAE;IAC9C,aAAa,CAAC,cAAc,CAC1B,GAAG,EAAE,CACH,IAAI,WAAW,CAAC;QACd,IAAI,EAAE,iBAAiB;QACvB,WAAW,EAAE,mBAAmB;QAChC,YAAY;QACZ,eAAe,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;KACxE,CAAC,CACL,CAAA;AACH,CAAC,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jbrowse/plugin-variants",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.3.0",
|
|
4
4
|
"description": "JBrowse 2 variant adapters, tracks, etc.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"jbrowse",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"build": "npm-run-all build:*",
|
|
28
28
|
"test": "cd ../..; jest plugins/variants",
|
|
29
29
|
"prepublishOnly": "yarn test",
|
|
30
|
-
"prepack": "yarn build
|
|
30
|
+
"prepack": "yarn build && yarn useDist",
|
|
31
31
|
"postpack": "yarn useSrc",
|
|
32
32
|
"useDist": "node ../../scripts/useDist.js",
|
|
33
33
|
"useSrc": "node ../../scripts/useSrc.js",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"@flatten-js/interval-tree": "^1.0.15",
|
|
41
41
|
"@gmod/bgzf-filehandle": "^1.4.3",
|
|
42
42
|
"@gmod/tabix": "^1.5.2",
|
|
43
|
-
"@gmod/vcf": "^5.0.
|
|
43
|
+
"@gmod/vcf": "^5.0.9",
|
|
44
44
|
"@mui/icons-material": "^5.0.2",
|
|
45
45
|
"@mui/x-data-grid": "^5.0.1",
|
|
46
46
|
"generic-filehandle": "^3.0.0"
|
|
@@ -54,10 +54,9 @@
|
|
|
54
54
|
"mobx": "^6.0.0",
|
|
55
55
|
"mobx-react": "^7.0.0",
|
|
56
56
|
"mobx-state-tree": "^5.0.0",
|
|
57
|
-
"prop-types": "^15.0.0",
|
|
58
57
|
"react": ">=16.8.0",
|
|
59
58
|
"rxjs": "^6.0.0",
|
|
60
|
-
"tss-react": "^
|
|
59
|
+
"tss-react": "^4.0.0"
|
|
61
60
|
},
|
|
62
61
|
"publishConfig": {
|
|
63
62
|
"access": "public"
|
|
@@ -65,5 +64,5 @@
|
|
|
65
64
|
"distModule": "esm/index.js",
|
|
66
65
|
"srcModule": "src/index.ts",
|
|
67
66
|
"module": "esm/index.js",
|
|
68
|
-
"gitHead": "
|
|
67
|
+
"gitHead": "a85b280a8af4d1a11e81ab42913f5f6049e6e580"
|
|
69
68
|
}
|
|
@@ -46,9 +46,7 @@ const stateModelFactory = (configSchema: AnyConfigurationSchemaType) => {
|
|
|
46
46
|
displayModel: self,
|
|
47
47
|
bezierRadius: view.radiusPx * self.bezierRadiusRatio,
|
|
48
48
|
radius: view.radiusPx,
|
|
49
|
-
|
|
50
|
-
// @ts-ignore
|
|
51
|
-
blockDefinitions: this.blockDefinitions,
|
|
49
|
+
blockDefinitions: self.blockDefinitions,
|
|
52
50
|
config: self.configuration.renderer,
|
|
53
51
|
onChordClick: self.onChordClick,
|
|
54
52
|
}
|
|
@@ -9,6 +9,7 @@ export default (pluginManager: PluginManager) => {
|
|
|
9
9
|
const configSchema = configSchemaF(pluginManager)
|
|
10
10
|
return new DisplayType({
|
|
11
11
|
name: 'LinearVariantDisplay',
|
|
12
|
+
displayName: 'Variant display',
|
|
12
13
|
configSchema,
|
|
13
14
|
stateModel: stateModelFactory(configSchema),
|
|
14
15
|
trackType: 'VariantTrack',
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { observer } from 'mobx-react'
|
|
3
|
+
import { polarToCartesian, Feature } from '@jbrowse/core/util'
|
|
4
|
+
import {
|
|
5
|
+
AnyConfigurationModel,
|
|
6
|
+
readConfObject,
|
|
7
|
+
} from '@jbrowse/core/configuration'
|
|
8
|
+
import { parseBreakend } from '@gmod/vcf'
|
|
9
|
+
|
|
10
|
+
export interface Region {
|
|
11
|
+
end: number
|
|
12
|
+
start: number
|
|
13
|
+
refName: string
|
|
14
|
+
elided?: false
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface ElidedRegion {
|
|
18
|
+
elided: true
|
|
19
|
+
regions: Region[]
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export type AnyRegion = Region | ElidedRegion
|
|
23
|
+
|
|
24
|
+
export interface Block {
|
|
25
|
+
flipped: boolean
|
|
26
|
+
bpPerRadian: number
|
|
27
|
+
startRadians: number
|
|
28
|
+
region: AnyRegion
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function bpToRadians(block: Block, pos: number) {
|
|
32
|
+
const blockStart = block.region.elided ? 0 : block.region.start
|
|
33
|
+
const blockEnd = block.region.elided ? 0 : block.region.end
|
|
34
|
+
const bpOffset = block.flipped ? blockEnd - pos : pos - blockStart
|
|
35
|
+
return bpOffset / block.bpPerRadian + block.startRadians
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const Chord = observer(function Chord({
|
|
39
|
+
feature,
|
|
40
|
+
blocksForRefs,
|
|
41
|
+
radius,
|
|
42
|
+
config,
|
|
43
|
+
bezierRadius,
|
|
44
|
+
selected,
|
|
45
|
+
onClick,
|
|
46
|
+
}: {
|
|
47
|
+
feature: Feature
|
|
48
|
+
blocksForRefs: { [key: string]: Block }
|
|
49
|
+
radius: number
|
|
50
|
+
config: AnyConfigurationModel
|
|
51
|
+
bezierRadius: number
|
|
52
|
+
selected: boolean
|
|
53
|
+
onClick: (
|
|
54
|
+
feature: Feature,
|
|
55
|
+
reg: AnyRegion,
|
|
56
|
+
endBlock: AnyRegion,
|
|
57
|
+
evt: unknown,
|
|
58
|
+
) => void
|
|
59
|
+
}) {
|
|
60
|
+
// find the blocks that our start and end points belong to
|
|
61
|
+
const startBlock = blocksForRefs[feature.get('refName')]
|
|
62
|
+
if (!startBlock) {
|
|
63
|
+
return null
|
|
64
|
+
}
|
|
65
|
+
let svType
|
|
66
|
+
if (feature.get('INFO')) {
|
|
67
|
+
;[svType] = feature.get('INFO').SVTYPE || []
|
|
68
|
+
} else if (feature.get('mate')) {
|
|
69
|
+
svType = 'mate'
|
|
70
|
+
}
|
|
71
|
+
let endPosition
|
|
72
|
+
let endBlock: Block | undefined
|
|
73
|
+
const alt = feature.get('ALT')?.[0]
|
|
74
|
+
const bnd = alt && parseBreakend(alt)
|
|
75
|
+
if (bnd) {
|
|
76
|
+
// VCF BND
|
|
77
|
+
const matePosition = bnd.MatePosition.split(':')
|
|
78
|
+
endPosition = +matePosition[1]
|
|
79
|
+
endBlock = blocksForRefs[matePosition[0]]
|
|
80
|
+
} else if (alt === '<TRA>') {
|
|
81
|
+
// VCF TRA
|
|
82
|
+
const chr2 = feature.get('INFO')?.CHR2?.[0]
|
|
83
|
+
const end = feature.get('INFO')?.END?.[0]
|
|
84
|
+
endPosition = parseInt(end, 10)
|
|
85
|
+
endBlock = blocksForRefs[chr2]
|
|
86
|
+
} else if (svType === 'mate') {
|
|
87
|
+
// generic simplefeatures arcs
|
|
88
|
+
const mate = feature.get('mate')
|
|
89
|
+
const chr2 = mate.refName
|
|
90
|
+
endPosition = mate.start
|
|
91
|
+
endBlock = blocksForRefs[chr2]
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (endBlock) {
|
|
95
|
+
const startPos = feature.get('start')
|
|
96
|
+
const startRadians = bpToRadians(startBlock, startPos)
|
|
97
|
+
const endRadians = bpToRadians(endBlock, endPosition)
|
|
98
|
+
const startXY = polarToCartesian(radius, startRadians)
|
|
99
|
+
const endXY = polarToCartesian(radius, endRadians)
|
|
100
|
+
const controlXY = polarToCartesian(
|
|
101
|
+
bezierRadius,
|
|
102
|
+
(endRadians + startRadians) / 2,
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
const strokeColor = selected
|
|
106
|
+
? readConfObject(config, 'strokeColorSelected', { feature })
|
|
107
|
+
: readConfObject(config, 'strokeColor', { feature })
|
|
108
|
+
|
|
109
|
+
const hoverStrokeColor = readConfObject(config, 'strokeColorHover', {
|
|
110
|
+
feature,
|
|
111
|
+
})
|
|
112
|
+
return (
|
|
113
|
+
<path
|
|
114
|
+
data-testid={`chord-${feature.id()}`}
|
|
115
|
+
d={['M', ...startXY, 'Q', ...controlXY, ...endXY].join(' ')}
|
|
116
|
+
style={{ stroke: strokeColor }}
|
|
117
|
+
onClick={evt => {
|
|
118
|
+
if (endBlock && startBlock) {
|
|
119
|
+
onClick(feature, startBlock.region, endBlock.region, evt)
|
|
120
|
+
}
|
|
121
|
+
}}
|
|
122
|
+
onMouseOver={evt => {
|
|
123
|
+
if (!selected) {
|
|
124
|
+
evt.currentTarget.style.stroke = hoverStrokeColor
|
|
125
|
+
evt.currentTarget.style.strokeWidth = '3px'
|
|
126
|
+
}
|
|
127
|
+
}}
|
|
128
|
+
onMouseOut={evt => {
|
|
129
|
+
if (!selected) {
|
|
130
|
+
evt.currentTarget.style.stroke = strokeColor
|
|
131
|
+
evt.currentTarget.style.strokeWidth = '1px'
|
|
132
|
+
}
|
|
133
|
+
}}
|
|
134
|
+
/>
|
|
135
|
+
)
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return null
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
export default Chord
|
|
@@ -1,146 +1,10 @@
|
|
|
1
1
|
import React, { useMemo } from 'react'
|
|
2
2
|
import { observer } from 'mobx-react'
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
AnyConfigurationModel,
|
|
6
|
-
readConfObject,
|
|
7
|
-
} from '@jbrowse/core/configuration'
|
|
8
|
-
import { parseBreakend } from '@gmod/vcf'
|
|
3
|
+
import { Feature } from '@jbrowse/core/util'
|
|
4
|
+
import { AnyConfigurationModel } from '@jbrowse/core/configuration'
|
|
9
5
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
start: number
|
|
13
|
-
refName: string
|
|
14
|
-
elided?: false
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
interface ElidedRegion {
|
|
18
|
-
elided: true
|
|
19
|
-
regions: Region[]
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
type AnyRegion = Region | ElidedRegion
|
|
23
|
-
|
|
24
|
-
interface Block {
|
|
25
|
-
flipped: boolean
|
|
26
|
-
bpPerRadian: number
|
|
27
|
-
startRadians: number
|
|
28
|
-
region: AnyRegion
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
function bpToRadians(block: Block, pos: number) {
|
|
32
|
-
const blockStart = block.region.elided ? 0 : block.region.start
|
|
33
|
-
const blockEnd = block.region.elided ? 0 : block.region.end
|
|
34
|
-
const bpOffset = block.flipped ? blockEnd - pos : pos - blockStart
|
|
35
|
-
return bpOffset / block.bpPerRadian + block.startRadians
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const Chord = observer(function Chord({
|
|
39
|
-
feature,
|
|
40
|
-
blocksForRefs,
|
|
41
|
-
radius,
|
|
42
|
-
config,
|
|
43
|
-
bezierRadius,
|
|
44
|
-
selected,
|
|
45
|
-
onClick,
|
|
46
|
-
}: {
|
|
47
|
-
feature: Feature
|
|
48
|
-
blocksForRefs: { [key: string]: Block }
|
|
49
|
-
radius: number
|
|
50
|
-
config: AnyConfigurationModel
|
|
51
|
-
bezierRadius: number
|
|
52
|
-
selected: boolean
|
|
53
|
-
onClick: (
|
|
54
|
-
feature: Feature,
|
|
55
|
-
reg: AnyRegion,
|
|
56
|
-
endBlock: AnyRegion,
|
|
57
|
-
evt: unknown,
|
|
58
|
-
) => void
|
|
59
|
-
}) {
|
|
60
|
-
// find the blocks that our start and end points belong to
|
|
61
|
-
const startBlock = blocksForRefs[feature.get('refName')]
|
|
62
|
-
if (!startBlock) {
|
|
63
|
-
return null
|
|
64
|
-
}
|
|
65
|
-
let svType
|
|
66
|
-
if (feature.get('INFO')) {
|
|
67
|
-
;[svType] = feature.get('INFO').SVTYPE || []
|
|
68
|
-
} else if (feature.get('mate')) {
|
|
69
|
-
svType = 'mate'
|
|
70
|
-
}
|
|
71
|
-
let endPosition
|
|
72
|
-
let endBlock: Block | undefined
|
|
73
|
-
const alt = feature.get('ALT')?.[0]
|
|
74
|
-
const bnd = alt && parseBreakend(alt)
|
|
75
|
-
if (bnd) {
|
|
76
|
-
// VCF BND
|
|
77
|
-
const matePosition = bnd.MatePosition.split(':')
|
|
78
|
-
endPosition = +matePosition[1]
|
|
79
|
-
endBlock = blocksForRefs[matePosition[0]]
|
|
80
|
-
} else if (alt === '<TRA>') {
|
|
81
|
-
// VCF TRA
|
|
82
|
-
const chr2 = feature.get('INFO')?.CHR2?.[0]
|
|
83
|
-
const end = feature.get('INFO')?.END?.[0]
|
|
84
|
-
endPosition = parseInt(end, 10)
|
|
85
|
-
endBlock = blocksForRefs[chr2]
|
|
86
|
-
} else if (svType === 'mate') {
|
|
87
|
-
// generic simplefeatures arcs
|
|
88
|
-
const mate = feature.get('mate')
|
|
89
|
-
const chr2 = mate.refName
|
|
90
|
-
endPosition = mate.start
|
|
91
|
-
endBlock = blocksForRefs[chr2]
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
if (endBlock) {
|
|
95
|
-
const startPos = feature.get('start')
|
|
96
|
-
const startRadians = bpToRadians(startBlock, startPos)
|
|
97
|
-
const endRadians = bpToRadians(endBlock, endPosition)
|
|
98
|
-
const startXY = polarToCartesian(radius, startRadians)
|
|
99
|
-
const endXY = polarToCartesian(radius, endRadians)
|
|
100
|
-
const controlXY = polarToCartesian(
|
|
101
|
-
bezierRadius,
|
|
102
|
-
(endRadians + startRadians) / 2,
|
|
103
|
-
)
|
|
104
|
-
|
|
105
|
-
const strokeColor = selected
|
|
106
|
-
? readConfObject(config, 'strokeColorSelected', { feature })
|
|
107
|
-
: readConfObject(config, 'strokeColor', { feature })
|
|
108
|
-
|
|
109
|
-
const hoverStrokeColor = readConfObject(config, 'strokeColorHover', {
|
|
110
|
-
feature,
|
|
111
|
-
})
|
|
112
|
-
return (
|
|
113
|
-
<path
|
|
114
|
-
data-testid={`chord-${feature.id()}`}
|
|
115
|
-
d={['M', ...startXY, 'Q', ...controlXY, ...endXY].join(' ')}
|
|
116
|
-
style={{ stroke: strokeColor }}
|
|
117
|
-
onClick={evt => {
|
|
118
|
-
if (endBlock && startBlock) {
|
|
119
|
-
onClick(feature, startBlock.region, endBlock.region, evt)
|
|
120
|
-
}
|
|
121
|
-
}}
|
|
122
|
-
onMouseOver={evt => {
|
|
123
|
-
if (!selected) {
|
|
124
|
-
// @ts-ignore
|
|
125
|
-
evt.target.style.stroke = hoverStrokeColor
|
|
126
|
-
// @ts-ignore
|
|
127
|
-
evt.target.style.strokeWidth = 3
|
|
128
|
-
}
|
|
129
|
-
}}
|
|
130
|
-
onMouseOut={evt => {
|
|
131
|
-
if (!selected) {
|
|
132
|
-
// @ts-ignore
|
|
133
|
-
evt.target.style.stroke = strokeColor
|
|
134
|
-
// @ts-ignore
|
|
135
|
-
evt.target.style.strokeWidth = 1
|
|
136
|
-
}
|
|
137
|
-
}}
|
|
138
|
-
/>
|
|
139
|
-
)
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
return null
|
|
143
|
-
})
|
|
6
|
+
// locals
|
|
7
|
+
import Chord, { Block, AnyRegion } from './Chord'
|
|
144
8
|
|
|
145
9
|
function StructuralVariantChords(props: {
|
|
146
10
|
features: Map<string, Feature>
|
|
@@ -170,19 +34,16 @@ function StructuralVariantChords(props: {
|
|
|
170
34
|
const blocksForRefsMemo = useMemo(() => {
|
|
171
35
|
const blocksForRefs = {} as { [key: string]: Block }
|
|
172
36
|
blockDefinitions.forEach(block => {
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
regions.forEach(region => {
|
|
177
|
-
blocksForRefs[region.refName] = block
|
|
178
|
-
})
|
|
37
|
+
;(block.region.elided ? block.region.regions : [block.region]).forEach(
|
|
38
|
+
r => (blocksForRefs[r.refName] = block),
|
|
39
|
+
)
|
|
179
40
|
})
|
|
180
41
|
return blocksForRefs
|
|
181
42
|
}, [blockDefinitions])
|
|
182
|
-
// console.log(blocksForRefs)
|
|
183
43
|
const chords = []
|
|
184
|
-
for (const
|
|
185
|
-
const
|
|
44
|
+
for (const feature of features.values()) {
|
|
45
|
+
const id = feature.id()
|
|
46
|
+
const selected = String(selectedFeatureId) === String(id)
|
|
186
47
|
chords.push(
|
|
187
48
|
<Chord
|
|
188
49
|
key={id}
|
|
@@ -3,16 +3,15 @@ import PluginManager from '@jbrowse/core/PluginManager'
|
|
|
3
3
|
import configSchema from './configSchema'
|
|
4
4
|
import ReactComponent from './ReactComponent'
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
export default (pluginManager: PluginManager) => {
|
|
7
7
|
pluginManager.addRendererType(
|
|
8
8
|
() =>
|
|
9
9
|
new ChordRendererType({
|
|
10
10
|
name: 'StructuralVariantChordRenderer',
|
|
11
|
+
displayName: 'SV chord renderer',
|
|
11
12
|
ReactComponent,
|
|
12
13
|
configSchema,
|
|
13
14
|
pluginManager,
|
|
14
15
|
}),
|
|
15
16
|
)
|
|
16
17
|
}
|
|
17
|
-
|
|
18
|
-
export default ChordRendererConfigF
|
|
@@ -4,30 +4,21 @@ import { observer } from 'mobx-react'
|
|
|
4
4
|
import {
|
|
5
5
|
Button,
|
|
6
6
|
Checkbox,
|
|
7
|
-
Dialog,
|
|
8
7
|
DialogActions,
|
|
9
8
|
DialogContent,
|
|
10
|
-
DialogTitle,
|
|
11
|
-
Divider,
|
|
12
9
|
FormControlLabel,
|
|
13
|
-
IconButton,
|
|
14
10
|
} from '@mui/material'
|
|
15
11
|
import { makeStyles } from 'tss-react/mui'
|
|
16
|
-
import CloseIcon from '@mui/icons-material/Close'
|
|
17
12
|
import { getSnapshot } from 'mobx-state-tree'
|
|
13
|
+
// jbrowse
|
|
14
|
+
import { Dialog } from '@jbrowse/core/ui'
|
|
18
15
|
import { getSession, Feature } from '@jbrowse/core/util'
|
|
19
16
|
|
|
20
|
-
const useStyles = makeStyles()(
|
|
21
|
-
closeButton: {
|
|
22
|
-
position: 'absolute',
|
|
23
|
-
right: theme.spacing(1),
|
|
24
|
-
top: theme.spacing(1),
|
|
25
|
-
color: theme.palette.grey[500],
|
|
26
|
-
},
|
|
17
|
+
const useStyles = makeStyles()({
|
|
27
18
|
block: {
|
|
28
19
|
display: 'block',
|
|
29
20
|
},
|
|
30
|
-
})
|
|
21
|
+
})
|
|
31
22
|
|
|
32
23
|
function BreakendOptionDialog({
|
|
33
24
|
model,
|
|
@@ -45,20 +36,7 @@ function BreakendOptionDialog({
|
|
|
45
36
|
const [mirrorTracks, setMirrorTracks] = useState(true)
|
|
46
37
|
|
|
47
38
|
return (
|
|
48
|
-
<Dialog open onClose={handleClose}>
|
|
49
|
-
<DialogTitle>
|
|
50
|
-
Breakpoint split view options
|
|
51
|
-
{handleClose ? (
|
|
52
|
-
<IconButton
|
|
53
|
-
className={classes.closeButton}
|
|
54
|
-
onClick={() => handleClose()}
|
|
55
|
-
>
|
|
56
|
-
<CloseIcon />
|
|
57
|
-
</IconButton>
|
|
58
|
-
) : null}
|
|
59
|
-
</DialogTitle>
|
|
60
|
-
<Divider />
|
|
61
|
-
|
|
39
|
+
<Dialog open onClose={handleClose} title="Breakpoint split view options">
|
|
62
40
|
<DialogContent>
|
|
63
41
|
<FormControlLabel
|
|
64
42
|
className={classes.block}
|
|
@@ -92,14 +70,20 @@ function BreakendOptionDialog({
|
|
|
92
70
|
feature,
|
|
93
71
|
view,
|
|
94
72
|
)
|
|
73
|
+
function remapIds(arr: any[]) {
|
|
74
|
+
return arr.map((v: any) => ({
|
|
75
|
+
...v,
|
|
76
|
+
id: v.trackId + '-' + Math.random(),
|
|
77
|
+
}))
|
|
78
|
+
}
|
|
95
79
|
viewSnapshot.views[0].offsetPx -= view.width / 2 + 100
|
|
96
80
|
viewSnapshot.views[1].offsetPx -= view.width / 2 + 100
|
|
97
81
|
viewSnapshot.featureData = feature
|
|
98
|
-
const viewTracks
|
|
99
|
-
viewSnapshot.views[0].tracks = viewTracks
|
|
100
|
-
viewSnapshot.views[1].tracks =
|
|
101
|
-
? viewTracks.slice().reverse()
|
|
102
|
-
|
|
82
|
+
const viewTracks = getSnapshot(view.tracks) as any
|
|
83
|
+
viewSnapshot.views[0].tracks = remapIds(viewTracks)
|
|
84
|
+
viewSnapshot.views[1].tracks = remapIds(
|
|
85
|
+
mirrorTracks ? viewTracks.slice().reverse() : viewTracks,
|
|
86
|
+
)
|
|
103
87
|
|
|
104
88
|
session.addView('BreakpointSplitView', viewSnapshot)
|
|
105
89
|
} catch (e) {
|
|
@@ -9,6 +9,8 @@ import { Feature } from '@jbrowse/core/util/simpleFeature'
|
|
|
9
9
|
import IntervalTree from '@flatten-js/interval-tree'
|
|
10
10
|
import { unzip } from '@gmod/bgzf-filehandle'
|
|
11
11
|
import VCF from '@gmod/vcf'
|
|
12
|
+
|
|
13
|
+
// local
|
|
12
14
|
import VcfFeature from '../VcfTabixAdapter/VcfFeature'
|
|
13
15
|
|
|
14
16
|
const readVcf = (f: string) => {
|
package/src/VcfAdapter/index.ts
CHANGED
|
@@ -14,10 +14,11 @@ import { Feature } from '@jbrowse/core/util/simpleFeature'
|
|
|
14
14
|
import { TabixIndexedFile } from '@gmod/tabix'
|
|
15
15
|
import VcfParser from '@gmod/vcf'
|
|
16
16
|
import { Observer } from 'rxjs'
|
|
17
|
-
import { readConfObject } from '@jbrowse/core/configuration'
|
|
18
|
-
import VcfFeature from './VcfFeature'
|
|
19
17
|
import { GenericFilehandle } from 'generic-filehandle'
|
|
20
18
|
|
|
19
|
+
// local
|
|
20
|
+
import VcfFeature from './VcfFeature'
|
|
21
|
+
|
|
21
22
|
export default class extends BaseFeatureDataAdapter {
|
|
22
23
|
private configured?: Promise<{
|
|
23
24
|
filehandle: GenericFilehandle
|
|
@@ -26,23 +27,17 @@ export default class extends BaseFeatureDataAdapter {
|
|
|
26
27
|
}>
|
|
27
28
|
|
|
28
29
|
private async configurePre() {
|
|
29
|
-
const
|
|
30
|
-
const
|
|
31
|
-
const
|
|
30
|
+
const pm = this.pluginManager
|
|
31
|
+
const vcfGzLocation = this.getConf('vcfGzLocation')
|
|
32
|
+
const location = this.getConf(['index', 'location'])
|
|
33
|
+
const indexType = this.getConf(['index', 'indexType'])
|
|
32
34
|
|
|
33
|
-
const filehandle = openLocation(
|
|
34
|
-
vcfGzLocation as FileLocation,
|
|
35
|
-
this.pluginManager,
|
|
36
|
-
)
|
|
35
|
+
const filehandle = openLocation(vcfGzLocation as FileLocation, pm)
|
|
37
36
|
const isCSI = indexType === 'CSI'
|
|
38
37
|
const vcf = new TabixIndexedFile({
|
|
39
38
|
filehandle,
|
|
40
|
-
csiFilehandle: isCSI
|
|
41
|
-
|
|
42
|
-
: undefined,
|
|
43
|
-
tbiFilehandle: !isCSI
|
|
44
|
-
? openLocation(location, this.pluginManager)
|
|
45
|
-
: undefined,
|
|
39
|
+
csiFilehandle: isCSI ? openLocation(location, pm) : undefined,
|
|
40
|
+
tbiFilehandle: !isCSI ? openLocation(location, pm) : undefined,
|
|
46
41
|
chunkCacheSize: 50 * 2 ** 20,
|
|
47
42
|
chunkSizeLimit: 1000000000,
|
|
48
43
|
})
|