@jbrowse/plugin-variants 2.3.1 → 2.3.3
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/VcfAdapter/VcfAdapter.d.ts +1 -2
- package/dist/VcfAdapter/VcfAdapter.js +2 -2
- package/dist/VcfAdapter/VcfAdapter.js.map +1 -1
- package/dist/{VcfTabixAdapter/VcfFeature.d.ts → VcfFeature/index.d.ts} +3 -15
- package/dist/VcfFeature/index.js +59 -0
- package/dist/VcfFeature/index.js.map +1 -0
- package/dist/VcfFeature/util.d.ts +7 -0
- package/dist/VcfFeature/util.js +129 -0
- package/dist/VcfFeature/util.js.map +1 -0
- package/dist/VcfTabixAdapter/VcfTabixAdapter.d.ts +2 -19
- package/dist/VcfTabixAdapter/VcfTabixAdapter.js +1 -35
- package/dist/VcfTabixAdapter/VcfTabixAdapter.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/esm/VcfAdapter/VcfAdapter.d.ts +1 -2
- package/esm/VcfAdapter/VcfAdapter.js +2 -2
- package/esm/VcfAdapter/VcfAdapter.js.map +1 -1
- package/esm/{VcfTabixAdapter/VcfFeature.d.ts → VcfFeature/index.d.ts} +3 -15
- package/esm/VcfFeature/index.js +56 -0
- package/esm/VcfFeature/index.js.map +1 -0
- package/esm/VcfFeature/util.d.ts +7 -0
- package/esm/VcfFeature/util.js +123 -0
- package/esm/VcfFeature/util.js.map +1 -0
- package/esm/VcfTabixAdapter/VcfTabixAdapter.d.ts +2 -19
- package/esm/VcfTabixAdapter/VcfTabixAdapter.js +1 -35
- package/esm/VcfTabixAdapter/VcfTabixAdapter.js.map +1 -1
- package/esm/index.d.ts +1 -1
- package/esm/index.js +1 -1
- package/esm/index.js.map +1 -1
- package/package.json +3 -3
- package/src/VariantFeatureWidget/VariantFeatureWidget.test.tsx +42 -0
- package/src/VariantFeatureWidget/__snapshots__/{VariantFeatureWidget.test.js.snap → VariantFeatureWidget.test.tsx.snap} +1 -1
- package/src/VcfAdapter/VcfAdapter.test.ts +4 -5
- package/src/VcfAdapter/VcfAdapter.ts +3 -4
- package/src/VcfFeature/index.test.ts +132 -0
- package/src/VcfFeature/index.ts +104 -0
- package/src/VcfFeature/util.ts +140 -0
- package/src/VcfTabixAdapter/VcfTabixAdapter.test.ts +9 -10
- package/src/VcfTabixAdapter/VcfTabixAdapter.ts +3 -51
- package/src/__snapshots__/{index.test.js.snap → index.test.ts.snap} +0 -0
- package/src/{index.test.js → index.test.ts} +0 -1
- package/src/index.ts +1 -1
- package/dist/VcfTabixAdapter/VcfFeature.js +0 -187
- package/dist/VcfTabixAdapter/VcfFeature.js.map +0 -1
- package/esm/VcfTabixAdapter/VcfFeature.js +0 -184
- package/esm/VcfTabixAdapter/VcfFeature.js.map +0 -1
- package/src/LinearVariantDisplay/configSchema.test.js +0 -55
- package/src/VariantFeatureWidget/VariantFeatureWidget.test.js +0 -41
- package/src/VcfTabixAdapter/VcfFeature.test.ts +0 -118
- package/src/VcfTabixAdapter/VcfFeature.ts +0 -250
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import BoxRendererType from '@jbrowse/core/pluggableElementTypes/renderers/BoxRendererType'
|
|
2
|
-
import Plugin from '@jbrowse/core/Plugin'
|
|
3
|
-
import PluginManager from '@jbrowse/core/PluginManager'
|
|
4
|
-
import PileupRenderer from '@jbrowse/plugin-alignments/src/PileupRenderer'
|
|
5
|
-
import {
|
|
6
|
-
configSchema as svgFeatureRendererConfigSchema,
|
|
7
|
-
ReactComponent as SvgFeatureRendererReactComponent,
|
|
8
|
-
} from '@jbrowse/plugin-svg/src/SvgFeatureRenderer'
|
|
9
|
-
import configSchemaFactory from './configSchema'
|
|
10
|
-
|
|
11
|
-
// mock warnings to avoid unnecessary outputs
|
|
12
|
-
beforeEach(() => {
|
|
13
|
-
jest.spyOn(console, 'warn').mockImplementation(() => {})
|
|
14
|
-
})
|
|
15
|
-
|
|
16
|
-
afterEach(() => {
|
|
17
|
-
console.warn.mockRestore()
|
|
18
|
-
})
|
|
19
|
-
|
|
20
|
-
class PileupRendererPlugin extends Plugin {
|
|
21
|
-
install(pluginManager) {
|
|
22
|
-
PileupRenderer(pluginManager)
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
class SvgFeatureRendererPlugin extends Plugin {
|
|
27
|
-
install(pluginManager) {
|
|
28
|
-
pluginManager.addRendererType(
|
|
29
|
-
() =>
|
|
30
|
-
new BoxRendererType({
|
|
31
|
-
name: 'SvgFeatureRenderer',
|
|
32
|
-
ReactComponent: SvgFeatureRendererReactComponent,
|
|
33
|
-
configSchema: svgFeatureRendererConfigSchema,
|
|
34
|
-
pluginManager,
|
|
35
|
-
}),
|
|
36
|
-
)
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
test('has a viewType attr', () => {
|
|
41
|
-
const configSchema = configSchemaFactory(
|
|
42
|
-
new PluginManager([
|
|
43
|
-
new PileupRendererPlugin(),
|
|
44
|
-
new SvgFeatureRendererPlugin(),
|
|
45
|
-
])
|
|
46
|
-
.createPluggableElements()
|
|
47
|
-
.configure(),
|
|
48
|
-
)
|
|
49
|
-
const config = configSchema.create({
|
|
50
|
-
type: 'LinearVariantDisplay',
|
|
51
|
-
displayId: 'displayId0',
|
|
52
|
-
name: 'Zonker Display',
|
|
53
|
-
})
|
|
54
|
-
expect(config.type).toEqual('LinearVariantDisplay')
|
|
55
|
-
})
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
import { render } from '@testing-library/react'
|
|
3
|
-
import { types } from 'mobx-state-tree'
|
|
4
|
-
import { ConfigurationSchema } from '@jbrowse/core/configuration'
|
|
5
|
-
import PluginManager from '@jbrowse/core/PluginManager'
|
|
6
|
-
import { stateModelFactory } from '.'
|
|
7
|
-
|
|
8
|
-
import VariantFeatureDetails from './VariantFeatureWidget'
|
|
9
|
-
|
|
10
|
-
describe('VariantTrack widget', () => {
|
|
11
|
-
it('renders with just the required model elements', () => {
|
|
12
|
-
console.warn = jest.fn()
|
|
13
|
-
const pluginManager = new PluginManager([])
|
|
14
|
-
const Session = types.model({
|
|
15
|
-
rpcManager: types.optional(types.frozen(), {}),
|
|
16
|
-
configuration: ConfigurationSchema('test', {}),
|
|
17
|
-
widget: stateModelFactory(pluginManager),
|
|
18
|
-
})
|
|
19
|
-
const model = Session.create(
|
|
20
|
-
{
|
|
21
|
-
widget: { type: 'VariantFeatureWidget' },
|
|
22
|
-
},
|
|
23
|
-
{ pluginManager },
|
|
24
|
-
)
|
|
25
|
-
model.widget.setFeatureData({
|
|
26
|
-
refName: 'ctgA',
|
|
27
|
-
start: 176,
|
|
28
|
-
end: 177,
|
|
29
|
-
name: 'rs123',
|
|
30
|
-
REF: 'A',
|
|
31
|
-
ALT: ['<TRA>'],
|
|
32
|
-
QUAL: 10.4,
|
|
33
|
-
INFO: {
|
|
34
|
-
MQ: 5,
|
|
35
|
-
},
|
|
36
|
-
})
|
|
37
|
-
|
|
38
|
-
const { container } = render(<VariantFeatureDetails model={model.widget} />)
|
|
39
|
-
expect(container.firstChild).toMatchSnapshot()
|
|
40
|
-
})
|
|
41
|
-
})
|
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
import VcfParser from '@gmod/vcf'
|
|
2
|
-
import VcfFeature from './VcfFeature'
|
|
3
|
-
|
|
4
|
-
test('test usage of the VcfFeature', () => {
|
|
5
|
-
const parser = new VcfParser({
|
|
6
|
-
header: `#CHROM\tPOS\tID\tREF\tALT\tQUAL\tFILTER\tINFO\tFORMAT\tBAMs/caudaus.sorted.sam`,
|
|
7
|
-
})
|
|
8
|
-
const line = `lcl|Scaffald_1\t80465\trs118266897\tR\tA\t29\tPASS\tNS=3;0,14;AF=0.5;DB;112;PG2.1`
|
|
9
|
-
|
|
10
|
-
const variant = parser.parseLine(line)
|
|
11
|
-
|
|
12
|
-
const f = new VcfFeature({
|
|
13
|
-
parser,
|
|
14
|
-
variant,
|
|
15
|
-
id: 'myuniqueid',
|
|
16
|
-
})
|
|
17
|
-
expect(f.id()).toEqual('myuniqueid')
|
|
18
|
-
expect(f.get('name')).toEqual('rs118266897')
|
|
19
|
-
})
|
|
20
|
-
|
|
21
|
-
test('try INS feature with END less than start', () => {
|
|
22
|
-
const parser = new VcfParser({
|
|
23
|
-
header: `#CHROM\tPOS\tID\tREF\tALT\tQUAL\tFILTER\tINFO\tFORMAT\tBAMs/caudaus.sorted.sam`,
|
|
24
|
-
})
|
|
25
|
-
const line = `chr1\t100\trs123\tR\tA\t29\tPASS\tEND=1;SVTYPE=INS`
|
|
26
|
-
|
|
27
|
-
const variant = parser.parseLine(line)
|
|
28
|
-
|
|
29
|
-
const f = new VcfFeature({
|
|
30
|
-
parser,
|
|
31
|
-
variant,
|
|
32
|
-
id: 'myuniqueid',
|
|
33
|
-
})
|
|
34
|
-
expect(f.id()).toEqual('myuniqueid')
|
|
35
|
-
expect(f.get('start')).toEqual(99)
|
|
36
|
-
expect(f.get('end')).toEqual(100)
|
|
37
|
-
})
|
|
38
|
-
|
|
39
|
-
test('try DEL feature with END info field valid', () => {
|
|
40
|
-
const parser = new VcfParser({
|
|
41
|
-
header: `#CHROM\tPOS\tID\tREF\tALT\tQUAL\tFILTER\tINFO\tFORMAT\tBAMs/caudaus.sorted.sam`,
|
|
42
|
-
})
|
|
43
|
-
const line = `chr1\t100\trs123\tR\t<DEL>\t29\tPASS\tEND=1000;SVTYPE=DEL`
|
|
44
|
-
|
|
45
|
-
const variant = parser.parseLine(line)
|
|
46
|
-
|
|
47
|
-
const f = new VcfFeature({
|
|
48
|
-
parser,
|
|
49
|
-
variant,
|
|
50
|
-
id: 'myuniqueid',
|
|
51
|
-
})
|
|
52
|
-
expect(f.id()).toEqual('myuniqueid')
|
|
53
|
-
expect(f.get('start')).toEqual(99)
|
|
54
|
-
expect(f.get('end')).toEqual(1000)
|
|
55
|
-
})
|
|
56
|
-
|
|
57
|
-
describe('test SV description', () => {
|
|
58
|
-
it('multiple SVs', () => {
|
|
59
|
-
const parser = new VcfParser({
|
|
60
|
-
header: `#CHROM\tPOS\tID\tREF\tALT\tQUAL\tFILTER\tINFO\tFORMAT\tBAMs/caudaus.sorted.sam`,
|
|
61
|
-
})
|
|
62
|
-
const line = `chr1\t100\trs123\tR\t<INVDUP>,<INV>\t29\tPASS\tEND=1000;SVTYPE=DEL`
|
|
63
|
-
|
|
64
|
-
const variant = parser.parseLine(line)
|
|
65
|
-
|
|
66
|
-
const f = new VcfFeature({
|
|
67
|
-
parser,
|
|
68
|
-
variant,
|
|
69
|
-
id: 'myuniqueid',
|
|
70
|
-
})
|
|
71
|
-
expect(f.get('description')).toEqual('<INVDUP>,<INV>')
|
|
72
|
-
})
|
|
73
|
-
it('BND', () => {
|
|
74
|
-
const parser = new VcfParser({
|
|
75
|
-
header: `#CHROM\tPOS\tID\tREF\tALT\tQUAL\tFILTER\tINFO\tFORMAT\tBAMs/caudaus.sorted.sam`,
|
|
76
|
-
})
|
|
77
|
-
const line = `chr1\t100\trs123\tR\tG[ctgA:34200[\t29\tPASS\tEND=1000;SVTYPE=BND`
|
|
78
|
-
|
|
79
|
-
const variant = parser.parseLine(line)
|
|
80
|
-
|
|
81
|
-
const f = new VcfFeature({
|
|
82
|
-
parser,
|
|
83
|
-
variant,
|
|
84
|
-
id: 'myuniqueid',
|
|
85
|
-
})
|
|
86
|
-
expect(f.get('description')).toEqual('G[ctgA:34200[')
|
|
87
|
-
})
|
|
88
|
-
it('multiple BND', () => {
|
|
89
|
-
const parser = new VcfParser({
|
|
90
|
-
header: `#CHROM\tPOS\tID\tREF\tALT\tQUAL\tFILTER\tINFO\tFORMAT\tBAMs/caudaus.sorted.sam`,
|
|
91
|
-
})
|
|
92
|
-
const line = `chr1\t100\trs123\tR\tG[ctgA:34200[,G[ctgA:44200[\t29\tPASS\tEND=1000;SVTYPE=BND`
|
|
93
|
-
|
|
94
|
-
const variant = parser.parseLine(line)
|
|
95
|
-
|
|
96
|
-
const f = new VcfFeature({
|
|
97
|
-
parser,
|
|
98
|
-
variant,
|
|
99
|
-
id: 'myuniqueid',
|
|
100
|
-
})
|
|
101
|
-
expect(f.get('description')).toEqual('G[ctgA:34200[,G[ctgA:44200[')
|
|
102
|
-
})
|
|
103
|
-
it('multiple SNV', () => {
|
|
104
|
-
const parser = new VcfParser({
|
|
105
|
-
header: `#CHROM\tPOS\tID\tREF\tALT\tQUAL\tFILTER\tINFO\tFORMAT\tBAMs/caudaus.sorted.sam`,
|
|
106
|
-
})
|
|
107
|
-
const line = `chr1\t100\trs123\tG\tA,C\t29\tPASS\tHELLO=world`
|
|
108
|
-
|
|
109
|
-
const variant = parser.parseLine(line)
|
|
110
|
-
|
|
111
|
-
const f = new VcfFeature({
|
|
112
|
-
parser,
|
|
113
|
-
variant,
|
|
114
|
-
id: 'myuniqueid',
|
|
115
|
-
})
|
|
116
|
-
expect(f.get('description')).toEqual('SNV G -> A,C')
|
|
117
|
-
})
|
|
118
|
-
})
|
|
@@ -1,250 +0,0 @@
|
|
|
1
|
-
import { Feature } from '@jbrowse/core/util/simpleFeature'
|
|
2
|
-
import { parseBreakend } from '@gmod/vcf'
|
|
3
|
-
|
|
4
|
-
/* eslint-disable no-underscore-dangle */
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* VCF Feature creation with lazy genotype evaluation.
|
|
8
|
-
*/
|
|
9
|
-
interface Samples {
|
|
10
|
-
[key: string]: {
|
|
11
|
-
[key: string]: { values: string[] | number[] | null }
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
interface FeatureData {
|
|
16
|
-
[key: string]: unknown
|
|
17
|
-
refName: string
|
|
18
|
-
start: number
|
|
19
|
-
end: number
|
|
20
|
-
description?: string
|
|
21
|
-
type?: string
|
|
22
|
-
name?: string
|
|
23
|
-
aliases?: string[]
|
|
24
|
-
samples?: Samples
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export default class VCFFeature implements Feature {
|
|
28
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
29
|
-
private variant: any
|
|
30
|
-
|
|
31
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
32
|
-
private parser: any
|
|
33
|
-
|
|
34
|
-
private data: FeatureData
|
|
35
|
-
|
|
36
|
-
private _id: string
|
|
37
|
-
|
|
38
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
39
|
-
constructor(args: { variant: any; parser: any; id: string }) {
|
|
40
|
-
this.variant = args.variant
|
|
41
|
-
this.parser = args.parser
|
|
42
|
-
this.data = this.dataFromVariant(this.variant)
|
|
43
|
-
this._id = args.id
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
47
|
-
get(field: string): any {
|
|
48
|
-
return field === 'samples'
|
|
49
|
-
? this.variant.SAMPLES
|
|
50
|
-
: this.data[field] || this.variant[field]
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
set(): void {}
|
|
54
|
-
|
|
55
|
-
parent(): undefined {
|
|
56
|
-
return undefined
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
children(): undefined {
|
|
60
|
-
return undefined
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
tags(): string[] {
|
|
64
|
-
const t = [
|
|
65
|
-
...Object.keys(this.data),
|
|
66
|
-
...Object.keys(this.variant),
|
|
67
|
-
'samples',
|
|
68
|
-
]
|
|
69
|
-
return t
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
id(): string {
|
|
73
|
-
return this._id
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
dataFromVariant(variant: {
|
|
77
|
-
REF: string
|
|
78
|
-
POS: number
|
|
79
|
-
ALT: string[]
|
|
80
|
-
CHROM: string
|
|
81
|
-
INFO: any // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
82
|
-
ID: string[]
|
|
83
|
-
}): FeatureData {
|
|
84
|
-
const { REF, ALT, POS, CHROM, INFO, ID } = variant
|
|
85
|
-
const start = POS - 1
|
|
86
|
-
const [SO_term, description] = this._getSOTermAndDescription(REF, ALT)
|
|
87
|
-
const isTRA = ALT?.some(f => f === '<TRA>')
|
|
88
|
-
const isSymbolic = ALT?.some(f => f.indexOf('<') !== -1)
|
|
89
|
-
|
|
90
|
-
return {
|
|
91
|
-
refName: CHROM,
|
|
92
|
-
start,
|
|
93
|
-
end: isSymbolic && INFO.END && !isTRA ? +INFO.END[0] : start + REF.length,
|
|
94
|
-
description,
|
|
95
|
-
type: SO_term,
|
|
96
|
-
name: ID?.join(','),
|
|
97
|
-
aliases: ID && ID.length > 1 ? variant.ID.slice(1) : undefined,
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* Get a sequence ontology (SO) term that describes the variant type
|
|
103
|
-
*/
|
|
104
|
-
_getSOTermAndDescription(
|
|
105
|
-
ref: string,
|
|
106
|
-
alt: string[],
|
|
107
|
-
): [string, string] | [undefined, undefined] {
|
|
108
|
-
// it's just a remark if there are no alternate alleles
|
|
109
|
-
if (!alt || alt.length === 0) {
|
|
110
|
-
return ['remark', 'no alternative alleles']
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
const soTerms = new Set<string>()
|
|
114
|
-
let descriptions = new Set<string>()
|
|
115
|
-
alt.forEach(a => {
|
|
116
|
-
let [soTerm, description] = this._getSOAndDescFromAltDefs(ref, a)
|
|
117
|
-
|
|
118
|
-
if (!soTerm) {
|
|
119
|
-
;[soTerm, description] = this._getSOAndDescByExamination(ref, a)
|
|
120
|
-
}
|
|
121
|
-
if (soTerm && description) {
|
|
122
|
-
soTerms.add(soTerm)
|
|
123
|
-
descriptions.add(description)
|
|
124
|
-
}
|
|
125
|
-
})
|
|
126
|
-
|
|
127
|
-
// Combine descriptions like ["SNV G -> A", "SNV G -> T"] to ["SNV G -> A,T"]
|
|
128
|
-
if (descriptions.size > 1) {
|
|
129
|
-
const prefixes = new Set(
|
|
130
|
-
[...descriptions].map(desc => {
|
|
131
|
-
const prefix = desc.split('->')
|
|
132
|
-
return prefix[1] ? prefix[0] : desc
|
|
133
|
-
}),
|
|
134
|
-
)
|
|
135
|
-
|
|
136
|
-
const new_descs = [...prefixes].map(prefix => {
|
|
137
|
-
const suffixes = [...descriptions]
|
|
138
|
-
.map(desc => {
|
|
139
|
-
const pref = desc.split('-> ')
|
|
140
|
-
return pref[1] && pref[0] === prefix ? pref[1] : ''
|
|
141
|
-
})
|
|
142
|
-
.filter(f => !!f)
|
|
143
|
-
|
|
144
|
-
return suffixes.length
|
|
145
|
-
? prefix + '-> ' + suffixes.join(',')
|
|
146
|
-
: [...descriptions].join(',')
|
|
147
|
-
})
|
|
148
|
-
|
|
149
|
-
descriptions = new Set(new_descs)
|
|
150
|
-
}
|
|
151
|
-
if (soTerms.size) {
|
|
152
|
-
return [[...soTerms].join(','), [...descriptions].join(',')]
|
|
153
|
-
}
|
|
154
|
-
return [undefined, undefined]
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
static _altTypeToSO: { [key: string]: string | undefined } = {
|
|
158
|
-
DEL: 'deletion',
|
|
159
|
-
INS: 'insertion',
|
|
160
|
-
DUP: 'duplication',
|
|
161
|
-
INV: 'inversion',
|
|
162
|
-
INVDUP: 'inverted duplication',
|
|
163
|
-
CNV: 'copy_number_variation',
|
|
164
|
-
TRA: 'translocation',
|
|
165
|
-
'DUP:TANDEM': 'tandem_duplication',
|
|
166
|
-
NON_REF: 'sequence_variant',
|
|
167
|
-
'*': 'sequence_variant',
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
_getSOAndDescFromAltDefs(
|
|
171
|
-
ref: string,
|
|
172
|
-
alt: string,
|
|
173
|
-
): [string, string] | [undefined, undefined] {
|
|
174
|
-
if (typeof alt === 'string' && !alt.startsWith('<')) {
|
|
175
|
-
return [undefined, undefined]
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
// look for a definition with an SO type for this
|
|
179
|
-
let soTerm = VCFFeature._altTypeToSO[alt]
|
|
180
|
-
// if no SO term but ALT is in metadata, assume sequence_variant
|
|
181
|
-
if (!soTerm && this.parser.getMetadata('ALT', alt)) {
|
|
182
|
-
soTerm = 'sequence_variant'
|
|
183
|
-
}
|
|
184
|
-
if (soTerm) {
|
|
185
|
-
return [soTerm, alt]
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
// try to look for a definition for a parent term if we can
|
|
189
|
-
const modAlt = alt.split(':')
|
|
190
|
-
if (modAlt.length > 1) {
|
|
191
|
-
return this._getSOAndDescFromAltDefs(
|
|
192
|
-
ref,
|
|
193
|
-
`<${modAlt.slice(0, modAlt.length - 1).join(':')}>`,
|
|
194
|
-
)
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
// no parent
|
|
198
|
-
return [undefined, undefined]
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
// note: term SNV is used instead of SNP because SO definition of SNP says
|
|
202
|
-
// abundance must be at least 1% in population, and can't be sure we meet
|
|
203
|
-
// that
|
|
204
|
-
_getSOAndDescByExamination(ref: string, alt: string): [string, string] {
|
|
205
|
-
const bnd = parseBreakend(alt)
|
|
206
|
-
if (bnd) {
|
|
207
|
-
return ['breakend', alt]
|
|
208
|
-
} else if (ref.length === 1 && alt.length === 1) {
|
|
209
|
-
return ['SNV', this._makeDescriptionString('SNV', ref, alt)]
|
|
210
|
-
} else if (alt === '<INS>') {
|
|
211
|
-
return ['insertion', alt]
|
|
212
|
-
} else if (alt === '<DEL>') {
|
|
213
|
-
return ['deletion', alt]
|
|
214
|
-
} else if (alt === '<INV>') {
|
|
215
|
-
return ['deletion', alt]
|
|
216
|
-
} else if (alt === '<TRA>') {
|
|
217
|
-
return ['translocation', alt]
|
|
218
|
-
} else if (alt.includes('<')) {
|
|
219
|
-
return ['sv', alt]
|
|
220
|
-
} else if (ref.length === alt.length) {
|
|
221
|
-
if (ref.split('').reverse().join('') === alt) {
|
|
222
|
-
return ['inversion', this._makeDescriptionString('inversion', ref, alt)]
|
|
223
|
-
}
|
|
224
|
-
return [
|
|
225
|
-
'substitution',
|
|
226
|
-
this._makeDescriptionString('substitution', ref, alt),
|
|
227
|
-
]
|
|
228
|
-
} else if (ref.length <= alt.length) {
|
|
229
|
-
return ['insertion', this._makeDescriptionString('insertion', ref, alt)]
|
|
230
|
-
} else if (ref.length > alt.length) {
|
|
231
|
-
return ['deletion', this._makeDescriptionString('deletion', ref, alt)]
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
return ['indel', this._makeDescriptionString('indel', ref, alt)]
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
_makeDescriptionString(soTerm: string, ref: string, alt: string): string {
|
|
238
|
-
return `${soTerm} ${ref} -> ${alt}`
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
242
|
-
toJSON(): any {
|
|
243
|
-
return {
|
|
244
|
-
uniqueId: this._id,
|
|
245
|
-
...this.variant,
|
|
246
|
-
...this.data,
|
|
247
|
-
samples: this.variant.SAMPLES,
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
}
|