@jbrowse/plugin-variants 1.4.3 → 1.5.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/dist/ChordVariantDisplay/index.d.ts +1 -1
- package/dist/LinearVariantDisplay/model.d.ts +11 -8
- package/dist/VcfAdapter/VcfAdapter.d.ts +13 -7
- package/dist/plugin-variants.cjs.development.js +243 -168
- package/dist/plugin-variants.cjs.development.js.map +1 -1
- package/dist/plugin-variants.cjs.production.min.js +1 -1
- package/dist/plugin-variants.cjs.production.min.js.map +1 -1
- package/dist/plugin-variants.esm.js +243 -168
- package/dist/plugin-variants.esm.js.map +1 -1
- package/package.json +8 -7
- package/src/LinearVariantDisplay/configSchema.test.js +2 -13
- package/src/LinearVariantDisplay/configSchema.ts +2 -1
- package/src/StructuralVariantChordRenderer/ReactComponent.js +2 -1
- package/src/VariantFeatureWidget/VariantFeatureWidget.tsx +5 -9
- package/src/VcfAdapter/VcfAdapter.test.ts +1 -0
- package/src/VcfAdapter/VcfAdapter.ts +72 -65
- package/src/VcfAdapter/__snapshots__/VcfAdapter.test.ts.snap +5 -5
- package/src/VcfAdapter/configSchema.ts +1 -1
- package/src/VcfTabixAdapter/VcfTabixAdapter.test.ts +4 -0
- package/src/VcfTabixAdapter/VcfTabixAdapter.ts +10 -3
- package/src/VcfTabixAdapter/configSchema.ts +5 -2
- package/src/index.ts +69 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jbrowse/plugin-variants",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.2",
|
|
4
4
|
"description": "JBrowse 2 variant adapters, tracks, etc.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"jbrowse",
|
|
@@ -35,12 +35,13 @@
|
|
|
35
35
|
"useSrc": "node ../../scripts/useSrc.js"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@
|
|
39
|
-
"@gmod/
|
|
40
|
-
"@gmod/
|
|
41
|
-
"@
|
|
38
|
+
"@flatten-js/interval-tree": "^1.0.14",
|
|
39
|
+
"@gmod/bgzf-filehandle": "^1.4.1",
|
|
40
|
+
"@gmod/tabix": "^1.5.2",
|
|
41
|
+
"@gmod/vcf": "^5.0.3",
|
|
42
42
|
"@material-ui/icons": "^4.11.2",
|
|
43
|
-
"
|
|
43
|
+
"@mui/x-data-grid": "^4.0.1",
|
|
44
|
+
"generic-filehandle": "^2.2.2"
|
|
44
45
|
},
|
|
45
46
|
"peerDependencies": {
|
|
46
47
|
"@jbrowse/core": "^1.0.0",
|
|
@@ -57,5 +58,5 @@
|
|
|
57
58
|
"publishConfig": {
|
|
58
59
|
"access": "public"
|
|
59
60
|
},
|
|
60
|
-
"gitHead": "
|
|
61
|
+
"gitHead": "94fdfbc34787ab8f12a87e00038da74b247b42fa"
|
|
61
62
|
}
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import BoxRendererType from '@jbrowse/core/pluggableElementTypes/renderers/BoxRendererType'
|
|
2
2
|
import Plugin from '@jbrowse/core/Plugin'
|
|
3
3
|
import PluginManager from '@jbrowse/core/PluginManager'
|
|
4
|
-
import PileupRenderer
|
|
5
|
-
configSchema as pileupRendererConfigSchema,
|
|
6
|
-
ReactComponent as PileupRendererReactComponent,
|
|
7
|
-
} from '@jbrowse/plugin-alignments/src/PileupRenderer'
|
|
4
|
+
import PileupRenderer from '@jbrowse/plugin-alignments/src/PileupRenderer'
|
|
8
5
|
import {
|
|
9
6
|
configSchema as svgFeatureRendererConfigSchema,
|
|
10
7
|
ReactComponent as SvgFeatureRendererReactComponent,
|
|
@@ -22,15 +19,7 @@ afterEach(() => {
|
|
|
22
19
|
|
|
23
20
|
class PileupRendererPlugin extends Plugin {
|
|
24
21
|
install(pluginManager) {
|
|
25
|
-
pluginManager
|
|
26
|
-
() =>
|
|
27
|
-
new PileupRenderer({
|
|
28
|
-
name: 'PileupRenderer',
|
|
29
|
-
ReactComponent: PileupRendererReactComponent,
|
|
30
|
-
configSchema: pileupRendererConfigSchema,
|
|
31
|
-
pluginManager,
|
|
32
|
-
}),
|
|
33
|
-
)
|
|
22
|
+
PileupRenderer(pluginManager)
|
|
34
23
|
}
|
|
35
24
|
}
|
|
36
25
|
|
|
@@ -18,4 +18,5 @@ export function LinearVariantDisplayConfigFactory(
|
|
|
18
18
|
export type LinearVariantDisplayConfigModel = ReturnType<
|
|
19
19
|
typeof LinearVariantDisplayConfigFactory
|
|
20
20
|
>
|
|
21
|
-
export type LinearVariantDisplayConfig =
|
|
21
|
+
export type LinearVariantDisplayConfig =
|
|
22
|
+
Instance<LinearVariantDisplayConfigModel>
|
|
@@ -37,7 +37,7 @@ const Chord = observer(function Chord({
|
|
|
37
37
|
let endPosition
|
|
38
38
|
let endBlock
|
|
39
39
|
const alt = feature.get('ALT')?.[0]
|
|
40
|
-
const bnd = parseBreakend(alt)
|
|
40
|
+
const bnd = alt && parseBreakend(alt)
|
|
41
41
|
if (bnd) {
|
|
42
42
|
// VCF BND
|
|
43
43
|
const matePosition = bnd.MatePosition.split(':')
|
|
@@ -92,6 +92,7 @@ const Chord = observer(function Chord({
|
|
|
92
92
|
onMouseOut={evt => {
|
|
93
93
|
if (!selected) {
|
|
94
94
|
evt.target.style.stroke = strokeColor
|
|
95
|
+
evt.target.style.strokeWidth = 1
|
|
95
96
|
}
|
|
96
97
|
}}
|
|
97
98
|
/>
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
import SimpleFeature, {
|
|
13
13
|
SimpleFeatureSerialized,
|
|
14
14
|
} from '@jbrowse/core/util/simpleFeature'
|
|
15
|
-
import { DataGrid } from '@
|
|
15
|
+
import { DataGrid } from '@mui/x-data-grid'
|
|
16
16
|
import { observer } from 'mobx-react'
|
|
17
17
|
import { getSession } from '@jbrowse/core/util'
|
|
18
18
|
import { getEnv } from 'mobx-state-tree'
|
|
@@ -204,14 +204,10 @@ function VariantFeatureDetails(props: any) {
|
|
|
204
204
|
const { samples, ...rest } = feat
|
|
205
205
|
const basicDescriptions = {
|
|
206
206
|
CHROM: 'chromosome: An identifier from the reference genome',
|
|
207
|
-
POS:
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
REF:
|
|
212
|
-
'reference base(s): Each base must be one of A,C,G,T,N (case insensitive).',
|
|
213
|
-
ALT:
|
|
214
|
-
'alternate base(s): Comma-separated list of alternate non-reference alleles',
|
|
207
|
+
POS: 'position: The reference position, with the 1st base having position 1',
|
|
208
|
+
ID: 'identifier: Semi-colon separated list of unique identifiers where available',
|
|
209
|
+
REF: 'reference base(s): Each base must be one of A,C,G,T,N (case insensitive).',
|
|
210
|
+
ALT: 'alternate base(s): Comma-separated list of alternate non-reference alleles',
|
|
215
211
|
QUAL: 'quality: Phred-scaled quality score for the assertion made in ALT',
|
|
216
212
|
FILTER:
|
|
217
213
|
'filter status: PASS if this position has passed all filters, otherwise a semicolon-separated list of codes for filters that fail',
|
|
@@ -2,116 +2,123 @@ import {
|
|
|
2
2
|
BaseFeatureDataAdapter,
|
|
3
3
|
BaseOptions,
|
|
4
4
|
} from '@jbrowse/core/data_adapters/BaseAdapter'
|
|
5
|
-
import {
|
|
5
|
+
import { Region } from '@jbrowse/core/util/types'
|
|
6
6
|
import { openLocation } from '@jbrowse/core/util/io'
|
|
7
7
|
import { ObservableCreate } from '@jbrowse/core/util/rxjs'
|
|
8
8
|
import { Feature } from '@jbrowse/core/util/simpleFeature'
|
|
9
9
|
import { readConfObject } from '@jbrowse/core/configuration'
|
|
10
|
-
import
|
|
11
|
-
import VcfFeature from '../VcfTabixAdapter/VcfFeature'
|
|
12
|
-
import VCF from '@gmod/vcf'
|
|
10
|
+
import IntervalTree from '@flatten-js/interval-tree'
|
|
13
11
|
import { unzip } from '@gmod/bgzf-filehandle'
|
|
12
|
+
import VCF from '@gmod/vcf'
|
|
13
|
+
import VcfFeature from '../VcfTabixAdapter/VcfFeature'
|
|
14
14
|
|
|
15
15
|
const readVcf = (f: string) => {
|
|
16
16
|
const lines = f.split('\n')
|
|
17
17
|
const header: string[] = []
|
|
18
|
-
const refNames: string[] = []
|
|
19
18
|
const rest: string[] = []
|
|
20
19
|
lines.forEach(line => {
|
|
21
|
-
if (line.startsWith('
|
|
22
|
-
refNames.push(line.split('##contig=<ID=')[1].split(',')[0])
|
|
23
|
-
} else if (line.startsWith('#')) {
|
|
20
|
+
if (line.startsWith('#')) {
|
|
24
21
|
header.push(line)
|
|
25
22
|
} else if (line) {
|
|
26
23
|
rest.push(line)
|
|
27
24
|
}
|
|
28
25
|
})
|
|
29
|
-
return { header: header.join('\n'), lines: rest
|
|
26
|
+
return { header: header.join('\n'), lines: rest }
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function isGzip(buf: Buffer) {
|
|
30
|
+
return buf[0] === 31 && buf[1] === 139 && buf[2] === 8
|
|
30
31
|
}
|
|
31
32
|
|
|
32
33
|
export default class VcfAdapter extends BaseFeatureDataAdapter {
|
|
33
34
|
public static capabilities = ['getFeatures', 'getRefNames']
|
|
34
35
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
private async decodeFileContents() {
|
|
42
|
-
const vcfLocation = readConfObject(
|
|
43
|
-
this.config,
|
|
44
|
-
'vcfLocation',
|
|
45
|
-
) as FileLocation
|
|
46
|
-
|
|
47
|
-
let fileContents = await openLocation(vcfLocation).readFile()
|
|
48
|
-
|
|
49
|
-
if (
|
|
50
|
-
typeof fileContents[0] === 'number' &&
|
|
51
|
-
fileContents[0] === 31 &&
|
|
52
|
-
typeof fileContents[1] === 'number' &&
|
|
53
|
-
fileContents[1] === 139 &&
|
|
54
|
-
typeof fileContents[2] === 'number' &&
|
|
55
|
-
fileContents[2] === 8
|
|
56
|
-
) {
|
|
57
|
-
fileContents = new TextDecoder().decode(await unzip(fileContents))
|
|
58
|
-
} else {
|
|
59
|
-
fileContents = fileContents.toString()
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
return readVcf(fileContents)
|
|
63
|
-
}
|
|
36
|
+
protected vcfFeatures?: Promise<{
|
|
37
|
+
header: string
|
|
38
|
+
intervalTree: Record<string, IntervalTree>
|
|
39
|
+
}>
|
|
64
40
|
|
|
65
41
|
public async getHeader() {
|
|
66
|
-
const { header } = await this.
|
|
42
|
+
const { header } = await this.setup()
|
|
67
43
|
return header
|
|
68
44
|
}
|
|
69
45
|
|
|
70
46
|
async getMetadata() {
|
|
71
|
-
const { header } = await this.
|
|
47
|
+
const { header } = await this.setup()
|
|
72
48
|
const parser = new VCF({ header: header })
|
|
73
49
|
return parser.getMetadata()
|
|
74
50
|
}
|
|
75
51
|
|
|
76
|
-
|
|
77
|
-
|
|
52
|
+
// converts lines into an interval tree
|
|
53
|
+
public async setupP() {
|
|
54
|
+
const buffer = await openLocation(
|
|
55
|
+
readConfObject(this.config, 'vcfLocation'),
|
|
56
|
+
this.pluginManager,
|
|
57
|
+
).readFile()
|
|
78
58
|
|
|
79
|
-
const
|
|
59
|
+
const buf = isGzip(buffer as Buffer) ? await unzip(buffer) : buffer
|
|
60
|
+
|
|
61
|
+
// 512MB max chrome string length is 512MB
|
|
62
|
+
if (buf.length > 536_870_888) {
|
|
63
|
+
throw new Error('Data exceeds maximum string length (512MB)')
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const str = new TextDecoder().decode(buf)
|
|
67
|
+
const { header, lines } = readVcf(str)
|
|
80
68
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
69
|
+
const intervalTree = lines
|
|
70
|
+
.map((line, id) => {
|
|
71
|
+
const [refName, startP, , ref, , , , info] = line.split('\t')
|
|
72
|
+
const start = +startP - 1
|
|
73
|
+
const end = +(info.match(/END=(\d+)/)?.[1].trim() || start + ref.length)
|
|
74
|
+
return { line, refName, start, end, id }
|
|
86
75
|
})
|
|
87
|
-
|
|
76
|
+
.reduce((acc, obj) => {
|
|
77
|
+
const key = obj.refName
|
|
78
|
+
if (!acc[key]) {
|
|
79
|
+
acc[key] = new IntervalTree()
|
|
80
|
+
}
|
|
81
|
+
acc[key].insert([obj.start, obj.end], obj)
|
|
82
|
+
return acc
|
|
83
|
+
}, {} as Record<string, IntervalTree>)
|
|
84
|
+
|
|
85
|
+
return { header, intervalTree }
|
|
88
86
|
}
|
|
89
87
|
|
|
90
88
|
public async setup() {
|
|
91
|
-
if (!this.
|
|
92
|
-
this.
|
|
89
|
+
if (!this.vcfFeatures) {
|
|
90
|
+
this.vcfFeatures = this.setupP().catch(e => {
|
|
91
|
+
this.vcfFeatures = undefined
|
|
92
|
+
throw e
|
|
93
|
+
})
|
|
93
94
|
}
|
|
94
|
-
return this.
|
|
95
|
+
return this.vcfFeatures
|
|
95
96
|
}
|
|
96
97
|
|
|
97
98
|
public async getRefNames(_: BaseOptions = {}) {
|
|
98
|
-
const {
|
|
99
|
-
return
|
|
99
|
+
const { intervalTree } = await this.setup()
|
|
100
|
+
return Object.keys(intervalTree)
|
|
100
101
|
}
|
|
101
102
|
|
|
102
103
|
public getFeatures(region: Region, opts: BaseOptions = {}) {
|
|
103
104
|
return ObservableCreate<Feature>(async observer => {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
105
|
+
try {
|
|
106
|
+
const { start, end, refName } = region
|
|
107
|
+
const { header, intervalTree } = await this.setup()
|
|
108
|
+
const parser = new VCF({ header: header })
|
|
109
|
+
intervalTree[refName]?.search([start, end]).forEach(f =>
|
|
110
|
+
observer.next(
|
|
111
|
+
new VcfFeature({
|
|
112
|
+
variant: parser.parseLine(f.line),
|
|
113
|
+
parser,
|
|
114
|
+
id: `${this.id}-${f.id}`,
|
|
115
|
+
}),
|
|
116
|
+
),
|
|
117
|
+
)
|
|
118
|
+
observer.complete()
|
|
119
|
+
} catch (e) {
|
|
120
|
+
observer.error(e)
|
|
121
|
+
}
|
|
115
122
|
}, opts.signal)
|
|
116
123
|
}
|
|
117
124
|
|
|
@@ -66,7 +66,7 @@ Array [
|
|
|
66
66
|
},
|
|
67
67
|
"start": 276,
|
|
68
68
|
"type": "SNV",
|
|
69
|
-
"uniqueId": "test-
|
|
69
|
+
"uniqueId": "test-0",
|
|
70
70
|
},
|
|
71
71
|
Object {
|
|
72
72
|
"ALT": Array [
|
|
@@ -132,7 +132,7 @@ Array [
|
|
|
132
132
|
},
|
|
133
133
|
"start": 1693,
|
|
134
134
|
"type": "SNV",
|
|
135
|
-
"uniqueId": "test-
|
|
135
|
+
"uniqueId": "test-1",
|
|
136
136
|
},
|
|
137
137
|
Object {
|
|
138
138
|
"ALT": Array [
|
|
@@ -198,7 +198,7 @@ Array [
|
|
|
198
198
|
},
|
|
199
199
|
"start": 2643,
|
|
200
200
|
"type": "SNV",
|
|
201
|
-
"uniqueId": "test-
|
|
201
|
+
"uniqueId": "test-2",
|
|
202
202
|
},
|
|
203
203
|
Object {
|
|
204
204
|
"ALT": Array [
|
|
@@ -258,7 +258,7 @@ Array [
|
|
|
258
258
|
},
|
|
259
259
|
"start": 3212,
|
|
260
260
|
"type": "SNV",
|
|
261
|
-
"uniqueId": "test-
|
|
261
|
+
"uniqueId": "test-3",
|
|
262
262
|
},
|
|
263
263
|
Object {
|
|
264
264
|
"ALT": Array [
|
|
@@ -319,7 +319,7 @@ Array [
|
|
|
319
319
|
},
|
|
320
320
|
"start": 3857,
|
|
321
321
|
"type": "deletion",
|
|
322
|
-
"uniqueId": "test-
|
|
322
|
+
"uniqueId": "test-4",
|
|
323
323
|
},
|
|
324
324
|
]
|
|
325
325
|
`;
|
|
@@ -7,11 +7,13 @@ test('adapter can fetch variants from volvox.vcf.gz', async () => {
|
|
|
7
7
|
configSchema.create({
|
|
8
8
|
vcfGzLocation: {
|
|
9
9
|
localPath: require.resolve('./test_data/volvox.filtered.vcf.gz'),
|
|
10
|
+
locationType: 'LocalPathLocation',
|
|
10
11
|
},
|
|
11
12
|
index: {
|
|
12
13
|
indexType: 'TBI',
|
|
13
14
|
location: {
|
|
14
15
|
localPath: require.resolve('./test_data/volvox.filtered.vcf.gz.tbi'),
|
|
16
|
+
locationType: 'LocalPathLocation',
|
|
15
17
|
},
|
|
16
18
|
},
|
|
17
19
|
}),
|
|
@@ -21,11 +23,13 @@ test('adapter can fetch variants from volvox.vcf.gz', async () => {
|
|
|
21
23
|
configSchema.create({
|
|
22
24
|
vcfGzLocation: {
|
|
23
25
|
localPath: require.resolve('./test_data/volvox.filtered.vcf.gz'),
|
|
26
|
+
locationType: 'LocalPathLocation',
|
|
24
27
|
},
|
|
25
28
|
index: {
|
|
26
29
|
indexType: 'CSI',
|
|
27
30
|
location: {
|
|
28
31
|
localPath: require.resolve('./test_data/volvox.filtered.vcf.gz.csi'),
|
|
32
|
+
locationType: 'LocalPathLocation',
|
|
29
33
|
},
|
|
30
34
|
},
|
|
31
35
|
}),
|
|
@@ -30,12 +30,19 @@ export default class extends BaseFeatureDataAdapter {
|
|
|
30
30
|
const location = readConfObject(this.config, ['index', 'location'])
|
|
31
31
|
const indexType = readConfObject(this.config, ['index', 'indexType'])
|
|
32
32
|
|
|
33
|
-
const filehandle = openLocation(
|
|
33
|
+
const filehandle = openLocation(
|
|
34
|
+
vcfGzLocation as FileLocation,
|
|
35
|
+
this.pluginManager,
|
|
36
|
+
)
|
|
34
37
|
const isCSI = indexType === 'CSI'
|
|
35
38
|
const vcf = new TabixIndexedFile({
|
|
36
39
|
filehandle,
|
|
37
|
-
csiFilehandle: isCSI
|
|
38
|
-
|
|
40
|
+
csiFilehandle: isCSI
|
|
41
|
+
? openLocation(location, this.pluginManager)
|
|
42
|
+
: undefined,
|
|
43
|
+
tbiFilehandle: !isCSI
|
|
44
|
+
? openLocation(location, this.pluginManager)
|
|
45
|
+
: undefined,
|
|
39
46
|
chunkCacheSize: 50 * 2 ** 20,
|
|
40
47
|
chunkSizeLimit: 1000000000,
|
|
41
48
|
})
|
|
@@ -6,7 +6,7 @@ export default ConfigurationSchema(
|
|
|
6
6
|
{
|
|
7
7
|
vcfGzLocation: {
|
|
8
8
|
type: 'fileLocation',
|
|
9
|
-
defaultValue: { uri: '/path/to/my.vcf.gz' },
|
|
9
|
+
defaultValue: { uri: '/path/to/my.vcf.gz', locationType: 'UriLocation' },
|
|
10
10
|
},
|
|
11
11
|
index: ConfigurationSchema('VcfIndex', {
|
|
12
12
|
indexType: {
|
|
@@ -16,7 +16,10 @@ export default ConfigurationSchema(
|
|
|
16
16
|
},
|
|
17
17
|
location: {
|
|
18
18
|
type: 'fileLocation',
|
|
19
|
-
defaultValue: {
|
|
19
|
+
defaultValue: {
|
|
20
|
+
uri: '/path/to/my.vcf.gz.tbi',
|
|
21
|
+
locationType: 'UriLocation',
|
|
22
|
+
},
|
|
20
23
|
},
|
|
21
24
|
}),
|
|
22
25
|
},
|
package/src/index.ts
CHANGED
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
createBaseTrackConfig,
|
|
7
7
|
createBaseTrackModel,
|
|
8
8
|
} from '@jbrowse/core/pluggableElementTypes/models'
|
|
9
|
+
import { FileLocation } from '@jbrowse/core/util/types'
|
|
9
10
|
import TrackType from '@jbrowse/core/pluggableElementTypes/TrackType'
|
|
10
11
|
import WidgetType from '@jbrowse/core/pluggableElementTypes/WidgetType'
|
|
11
12
|
import Plugin from '@jbrowse/core/Plugin'
|
|
@@ -23,6 +24,13 @@ import {
|
|
|
23
24
|
} from './VariantFeatureWidget'
|
|
24
25
|
import { configSchema as vcfTabixAdapterConfigSchema } from './VcfTabixAdapter'
|
|
25
26
|
import { configSchema as vcfAdapterConfigSchema } from './VcfAdapter'
|
|
27
|
+
import {
|
|
28
|
+
makeIndex,
|
|
29
|
+
makeIndexType,
|
|
30
|
+
AdapterGuesser,
|
|
31
|
+
getFileName,
|
|
32
|
+
TrackTypeGuesser,
|
|
33
|
+
} from '@jbrowse/core/util/tracks'
|
|
26
34
|
|
|
27
35
|
export default class VariantsPlugin extends Plugin {
|
|
28
36
|
name = 'VariantsPlugin'
|
|
@@ -37,6 +45,43 @@ export default class VariantsPlugin extends Plugin {
|
|
|
37
45
|
import('./VcfTabixAdapter/VcfTabixAdapter').then(r => r.default),
|
|
38
46
|
}),
|
|
39
47
|
)
|
|
48
|
+
pluginManager.addToExtensionPoint(
|
|
49
|
+
'Core-guessAdapterForLocation',
|
|
50
|
+
(adapterGuesser: AdapterGuesser) => {
|
|
51
|
+
return (
|
|
52
|
+
file: FileLocation,
|
|
53
|
+
index?: FileLocation,
|
|
54
|
+
adapterHint?: string,
|
|
55
|
+
) => {
|
|
56
|
+
const regexGuess = /\.vcf\.b?gz$/i
|
|
57
|
+
const adapterName = 'VcfTabixAdapter'
|
|
58
|
+
const fileName = getFileName(file)
|
|
59
|
+
const indexName = index && getFileName(index)
|
|
60
|
+
if (regexGuess.test(fileName) || adapterHint === adapterName) {
|
|
61
|
+
return {
|
|
62
|
+
type: adapterName,
|
|
63
|
+
vcfGzLocation: file,
|
|
64
|
+
index: {
|
|
65
|
+
location: index || makeIndex(file, '.tbi'),
|
|
66
|
+
indexType: makeIndexType(indexName, 'CSI', 'TBI'),
|
|
67
|
+
},
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return adapterGuesser(file, index, adapterHint)
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
)
|
|
74
|
+
pluginManager.addToExtensionPoint(
|
|
75
|
+
'Core-guessTrackTypeForLocation',
|
|
76
|
+
(trackTypeGuesser: TrackTypeGuesser) => {
|
|
77
|
+
return (adapterName: string) => {
|
|
78
|
+
if (adapterName === 'VcfTabixAdapter') {
|
|
79
|
+
return 'VariantTrack'
|
|
80
|
+
}
|
|
81
|
+
return trackTypeGuesser(adapterName)
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
)
|
|
40
85
|
|
|
41
86
|
pluginManager.addAdapterType(
|
|
42
87
|
() =>
|
|
@@ -48,6 +93,28 @@ export default class VariantsPlugin extends Plugin {
|
|
|
48
93
|
}),
|
|
49
94
|
)
|
|
50
95
|
|
|
96
|
+
pluginManager.addToExtensionPoint(
|
|
97
|
+
'Core-guessAdapterForLocation',
|
|
98
|
+
(adapterGuesser: AdapterGuesser) => {
|
|
99
|
+
return (
|
|
100
|
+
file: FileLocation,
|
|
101
|
+
index?: FileLocation,
|
|
102
|
+
adapterHint?: string,
|
|
103
|
+
) => {
|
|
104
|
+
const regexGuess = /\.vcf$/i
|
|
105
|
+
const adapterName = 'VcfAdapter'
|
|
106
|
+
const fileName = getFileName(file)
|
|
107
|
+
if (regexGuess.test(fileName) || adapterHint === adapterName) {
|
|
108
|
+
return {
|
|
109
|
+
type: adapterName,
|
|
110
|
+
vcfLocation: file,
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return adapterGuesser(file, index, adapterHint)
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
)
|
|
117
|
+
|
|
51
118
|
pluginManager.addRendererType(() =>
|
|
52
119
|
pluginManager.jbrequire(StructuralVariantChordRendererFactory),
|
|
53
120
|
)
|
|
@@ -73,9 +140,8 @@ export default class VariantsPlugin extends Plugin {
|
|
|
73
140
|
)
|
|
74
141
|
|
|
75
142
|
pluginManager.addDisplayType(() => {
|
|
76
|
-
const configSchema =
|
|
77
|
-
pluginManager
|
|
78
|
-
)
|
|
143
|
+
const configSchema =
|
|
144
|
+
linearVariantDisplayConfigSchemaFactory(pluginManager)
|
|
79
145
|
return new DisplayType({
|
|
80
146
|
name: 'LinearVariantDisplay',
|
|
81
147
|
configSchema,
|