@jbrowse/plugin-alignments 1.4.1 → 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/AlignmentsFeatureDetail/index.d.ts +7 -4
- package/dist/AlignmentsTrack/index.d.ts +2 -0
- package/dist/BamAdapter/index.d.ts +2 -4
- package/dist/CramAdapter/index.d.ts +1 -4
- package/dist/HtsgetBamAdapter/HtsgetBamAdapter.d.ts +2 -1
- package/dist/HtsgetBamAdapter/index.d.ts +2 -4
- package/dist/LinearAlignmentsDisplay/index.d.ts +2 -3
- package/dist/LinearAlignmentsDisplay/models/model.d.ts +6 -6
- package/dist/LinearPileupDisplay/index.d.ts +2 -2
- package/dist/LinearPileupDisplay/model.d.ts +9 -10
- package/dist/LinearSNPCoverageDisplay/components/Tooltip.d.ts +1 -1
- package/dist/LinearSNPCoverageDisplay/index.d.ts +2 -2
- package/dist/LinearSNPCoverageDisplay/models/model.d.ts +3 -2
- package/dist/PileupRPC/rpcMethods.d.ts +2 -16
- package/dist/PileupRenderer/PileupRenderer.d.ts +20 -7
- package/dist/PileupRenderer/index.d.ts +2 -3
- package/dist/SNPCoverageAdapter/SNPCoverageAdapter.d.ts +38 -26
- package/dist/SNPCoverageAdapter/index.d.ts +1 -5
- package/dist/SNPCoverageRenderer/index.d.ts +3 -3
- package/dist/plugin-alignments.cjs.development.js +4488 -4254
- package/dist/plugin-alignments.cjs.development.js.map +1 -1
- package/dist/plugin-alignments.cjs.production.min.js +1 -1
- package/dist/plugin-alignments.cjs.production.min.js.map +1 -1
- package/dist/plugin-alignments.esm.js +4485 -4251
- package/dist/plugin-alignments.esm.js.map +1 -1
- package/package.json +4 -4
- package/src/AlignmentsFeatureDetail/index.test.js +2 -4
- package/src/AlignmentsFeatureDetail/{index.js → index.ts} +19 -3
- package/src/AlignmentsTrack/index.ts +36 -0
- package/src/BamAdapter/BamAdapter.test.ts +8 -0
- package/src/BamAdapter/BamAdapter.ts +11 -5
- package/src/BamAdapter/BamSlightlyLazyFeature.ts +9 -19
- package/src/BamAdapter/MismatchParser.test.ts +24 -2
- package/src/BamAdapter/MismatchParser.ts +6 -5
- package/src/BamAdapter/configSchema.ts +5 -2
- package/src/BamAdapter/index.ts +11 -5
- package/src/CramAdapter/CramAdapter.test.ts +6 -0
- package/src/CramAdapter/CramAdapter.ts +4 -2
- package/src/CramAdapter/CramTestAdapters.ts +2 -1
- package/src/CramAdapter/configSchema.ts +8 -2
- package/src/CramAdapter/index.ts +11 -4
- package/src/HtsgetBamAdapter/HtsgetBamAdapter.ts +2 -2
- package/src/HtsgetBamAdapter/index.ts +18 -5
- package/src/LinearAlignmentsDisplay/index.ts +20 -3
- package/src/LinearAlignmentsDisplay/models/configSchema.test.js +8 -69
- package/src/LinearPileupDisplay/configSchema.test.js +2 -13
- package/src/LinearPileupDisplay/configSchema.ts +4 -6
- package/src/LinearPileupDisplay/index.ts +19 -2
- package/src/LinearPileupDisplay/model.ts +53 -51
- package/src/LinearSNPCoverageDisplay/components/Tooltip.tsx +17 -12
- package/src/LinearSNPCoverageDisplay/index.ts +19 -2
- package/src/LinearSNPCoverageDisplay/models/configSchema.test.js +2 -13
- package/src/LinearSNPCoverageDisplay/models/model.ts +23 -6
- package/src/PileupRPC/rpcMethods.ts +8 -2
- package/src/PileupRenderer/PileupRenderer.tsx +154 -128
- package/src/PileupRenderer/components/PileupRendering.tsx +4 -8
- package/src/PileupRenderer/configSchema.ts +2 -2
- package/src/PileupRenderer/index.ts +16 -3
- package/src/SNPCoverageAdapter/SNPCoverageAdapter.ts +95 -25
- package/src/SNPCoverageAdapter/index.ts +17 -5
- package/src/SNPCoverageRenderer/SNPCoverageRenderer.ts +62 -15
- package/src/SNPCoverageRenderer/configSchema.js +5 -0
- package/src/SNPCoverageRenderer/index.ts +24 -0
- package/src/index.ts +91 -165
- package/src/SNPCoverageAdapter/SNPCoverageAdapter.test.ts +0 -269
- package/src/SNPCoverageAdapter/__snapshots__/SNPCoverageAdapter.test.ts.snap +0 -579
- package/src/SNPCoverageRenderer/index.js +0 -11
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jbrowse/plugin-alignments",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.2",
|
|
4
4
|
"description": "JBrowse 2 alignments adapters, tracks, etc.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"jbrowse",
|
|
@@ -35,14 +35,14 @@
|
|
|
35
35
|
"useSrc": "node ../../scripts/useSrc.js"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@gmod/bam": "^1.1.
|
|
38
|
+
"@gmod/bam": "^1.1.9",
|
|
39
39
|
"@gmod/cram": "^1.5.9",
|
|
40
40
|
"@material-ui/icons": "^4.9.1",
|
|
41
41
|
"abortable-promise-cache": "^1.1.3",
|
|
42
42
|
"color": "^3.1.2",
|
|
43
43
|
"copy-to-clipboard": "^3.3.1",
|
|
44
44
|
"fast-deep-equal": "^3.1.3",
|
|
45
|
-
"generic-filehandle": "^2.
|
|
45
|
+
"generic-filehandle": "^2.2.2",
|
|
46
46
|
"json-stable-stringify": "^1.0.1",
|
|
47
47
|
"react-d3-axis": "^0.1.2"
|
|
48
48
|
},
|
|
@@ -61,5 +61,5 @@
|
|
|
61
61
|
"publishConfig": {
|
|
62
62
|
"access": "public"
|
|
63
63
|
},
|
|
64
|
-
"gitHead": "
|
|
64
|
+
"gitHead": "94fdfbc34787ab8f12a87e00038da74b247b42fa"
|
|
65
65
|
}
|
|
@@ -20,14 +20,12 @@ test('open up a widget', () => {
|
|
|
20
20
|
widget: { type: 'AlignmentsFeatureWidget' },
|
|
21
21
|
})
|
|
22
22
|
session.widget.setFeatureData({
|
|
23
|
-
seq:
|
|
24
|
-
'TTGTTGCGGAGTTGAACAACGGCATTAGGAACACTTCCGTCTCTCACTTTTATACGATTATGATTGGTTCTTTAGCCTTGGTTTAGATTGGTAGTAGTAG',
|
|
23
|
+
seq: 'TTGTTGCGGAGTTGAACAACGGCATTAGGAACACTTCCGTCTCTCACTTTTATACGATTATGATTGGTTCTTTAGCCTTGGTTTAGATTGGTAGTAGTAG',
|
|
25
24
|
start: 2,
|
|
26
25
|
end: 102,
|
|
27
26
|
strand: 1,
|
|
28
27
|
score: 37,
|
|
29
|
-
qual:
|
|
30
|
-
'17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17',
|
|
28
|
+
qual: '17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17',
|
|
31
29
|
MQ: 37,
|
|
32
30
|
CIGAR: '100M',
|
|
33
31
|
length_on_ref: 100,
|
|
@@ -1,10 +1,13 @@
|
|
|
1
|
+
import { lazy } from 'react'
|
|
2
|
+
import PluginManager from '@jbrowse/core/PluginManager'
|
|
1
3
|
import { ConfigurationSchema } from '@jbrowse/core/configuration'
|
|
2
4
|
import { ElementId } from '@jbrowse/core/util/types/mst'
|
|
3
5
|
import { types } from 'mobx-state-tree'
|
|
6
|
+
import WidgetType from '@jbrowse/core/pluggableElementTypes/WidgetType'
|
|
4
7
|
|
|
5
8
|
const configSchema = ConfigurationSchema('AlignmentsFeatureWidget', {})
|
|
6
9
|
|
|
7
|
-
export
|
|
10
|
+
export function stateModelFactory(pluginManager: PluginManager) {
|
|
8
11
|
return types
|
|
9
12
|
.model('AlignmentsFeatureWidget', {
|
|
10
13
|
id: ElementId,
|
|
@@ -15,7 +18,7 @@ export default function stateModelFactory(pluginManager) {
|
|
|
15
18
|
),
|
|
16
19
|
})
|
|
17
20
|
.actions(self => ({
|
|
18
|
-
setFeatureData(data) {
|
|
21
|
+
setFeatureData(data: unknown) {
|
|
19
22
|
self.featureData = data
|
|
20
23
|
},
|
|
21
24
|
clearFeatureData() {
|
|
@@ -24,4 +27,17 @@ export default function stateModelFactory(pluginManager) {
|
|
|
24
27
|
}))
|
|
25
28
|
}
|
|
26
29
|
|
|
27
|
-
export
|
|
30
|
+
export default function register(pluginManager: PluginManager) {
|
|
31
|
+
pluginManager.addWidgetType(
|
|
32
|
+
() =>
|
|
33
|
+
new WidgetType({
|
|
34
|
+
name: 'AlignmentsFeatureWidget',
|
|
35
|
+
heading: 'Feature details',
|
|
36
|
+
configSchema,
|
|
37
|
+
stateModel: stateModelFactory(pluginManager),
|
|
38
|
+
ReactComponent: lazy(() => import('./AlignmentsFeatureDetail')),
|
|
39
|
+
}),
|
|
40
|
+
)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export { configSchema }
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import PluginManager from '@jbrowse/core/PluginManager'
|
|
2
|
+
import TrackType from '@jbrowse/core/pluggableElementTypes/TrackType'
|
|
3
|
+
import { ConfigurationSchema } from '@jbrowse/core/configuration'
|
|
4
|
+
import {
|
|
5
|
+
createBaseTrackConfig,
|
|
6
|
+
createBaseTrackModel,
|
|
7
|
+
} from '@jbrowse/core/pluggableElementTypes/models'
|
|
8
|
+
function configSchemaFactory(pluginManager: PluginManager) {
|
|
9
|
+
return ConfigurationSchema(
|
|
10
|
+
'AlignmentsTrack',
|
|
11
|
+
{},
|
|
12
|
+
{ baseConfiguration: createBaseTrackConfig(pluginManager) },
|
|
13
|
+
)
|
|
14
|
+
}
|
|
15
|
+
export default function register(pluginManager: PluginManager) {
|
|
16
|
+
pluginManager.addTrackType(() => {
|
|
17
|
+
const configSchema = configSchemaFactory(pluginManager)
|
|
18
|
+
const track = new TrackType({
|
|
19
|
+
name: 'AlignmentsTrack',
|
|
20
|
+
configSchema,
|
|
21
|
+
stateModel: createBaseTrackModel(
|
|
22
|
+
pluginManager,
|
|
23
|
+
'AlignmentsTrack',
|
|
24
|
+
configSchema,
|
|
25
|
+
),
|
|
26
|
+
})
|
|
27
|
+
const linearAlignmentsDisplay = pluginManager.getDisplayType(
|
|
28
|
+
'LinearAlignmentsDisplay',
|
|
29
|
+
)
|
|
30
|
+
// Add LinearAlignmentsDisplay here so that it has priority over the other
|
|
31
|
+
// linear displays (defaults to order the displays are added, but we have
|
|
32
|
+
// to add the Pileup and SNPCoverage displays first).
|
|
33
|
+
track.addDisplayType(linearAlignmentsDisplay)
|
|
34
|
+
return track
|
|
35
|
+
})
|
|
36
|
+
}
|
|
@@ -7,10 +7,12 @@ test('adapter can fetch features from volvox.bam', async () => {
|
|
|
7
7
|
configSchema.create({
|
|
8
8
|
bamLocation: {
|
|
9
9
|
localPath: require.resolve('../../test_data/volvox-sorted.bam'),
|
|
10
|
+
locationType: 'LocalPathLocation',
|
|
10
11
|
},
|
|
11
12
|
index: {
|
|
12
13
|
location: {
|
|
13
14
|
localPath: require.resolve('../../test_data/volvox-sorted.bam.bai'),
|
|
15
|
+
locationType: 'LocalPathLocation',
|
|
14
16
|
},
|
|
15
17
|
},
|
|
16
18
|
}),
|
|
@@ -38,11 +40,13 @@ test('adapter can fetch features from volvox.bam', async () => {
|
|
|
38
40
|
configSchema.create({
|
|
39
41
|
bamLocation: {
|
|
40
42
|
localPath: require.resolve('../../test_data/volvox-sorted.bam'),
|
|
43
|
+
locationType: 'LocalPathLocation',
|
|
41
44
|
},
|
|
42
45
|
index: {
|
|
43
46
|
indexType: 'CSI',
|
|
44
47
|
location: {
|
|
45
48
|
localPath: require.resolve('../../test_data/volvox-sorted.bam.csi'),
|
|
49
|
+
locationType: 'LocalPathLocation',
|
|
46
50
|
},
|
|
47
51
|
},
|
|
48
52
|
}),
|
|
@@ -64,10 +68,12 @@ test('test usage of BamSlightlyLazyFeature toJSON (used in the widget)', async (
|
|
|
64
68
|
configSchema.create({
|
|
65
69
|
bamLocation: {
|
|
66
70
|
localPath: require.resolve('../../test_data/volvox-sorted.bam'),
|
|
71
|
+
locationType: 'LocalPathLocation',
|
|
67
72
|
},
|
|
68
73
|
index: {
|
|
69
74
|
location: {
|
|
70
75
|
localPath: require.resolve('../../test_data/volvox-sorted.bam.bai'),
|
|
76
|
+
locationType: 'LocalPathLocation',
|
|
71
77
|
},
|
|
72
78
|
indexType: 'BAI',
|
|
73
79
|
},
|
|
@@ -93,10 +99,12 @@ test('test usage of BamSlightlyLazyFeature for extended CIGAR', async () => {
|
|
|
93
99
|
configSchema.create({
|
|
94
100
|
bamLocation: {
|
|
95
101
|
localPath: require.resolve('../../test_data/extended_cigar.bam'),
|
|
102
|
+
locationType: 'LocalPathLocation',
|
|
96
103
|
},
|
|
97
104
|
index: {
|
|
98
105
|
location: {
|
|
99
106
|
localPath: require.resolve('../../test_data/extended_cigar.bam.bai'),
|
|
107
|
+
locationType: 'LocalPathLocation',
|
|
100
108
|
},
|
|
101
109
|
indexType: 'BAI',
|
|
102
110
|
},
|
|
@@ -37,9 +37,15 @@ export default class BamAdapter extends BaseFeatureDataAdapter {
|
|
|
37
37
|
const chunkSizeLimit = readConfObject(this.config, 'chunkSizeLimit')
|
|
38
38
|
const fetchSizeLimit = readConfObject(this.config, 'fetchSizeLimit')
|
|
39
39
|
const bam = new BamFile({
|
|
40
|
-
bamFilehandle: openLocation(bamLocation),
|
|
41
|
-
csiFilehandle:
|
|
42
|
-
|
|
40
|
+
bamFilehandle: openLocation(bamLocation, this.pluginManager),
|
|
41
|
+
csiFilehandle:
|
|
42
|
+
indexType === 'CSI'
|
|
43
|
+
? openLocation(location, this.pluginManager)
|
|
44
|
+
: undefined,
|
|
45
|
+
baiFilehandle:
|
|
46
|
+
indexType !== 'CSI'
|
|
47
|
+
? openLocation(location, this.pluginManager)
|
|
48
|
+
: undefined,
|
|
43
49
|
chunkSizeLimit,
|
|
44
50
|
fetchSizeLimit,
|
|
45
51
|
})
|
|
@@ -128,8 +134,8 @@ export default class BamAdapter extends BaseFeatureDataAdapter {
|
|
|
128
134
|
|
|
129
135
|
const trimmed: string[] = []
|
|
130
136
|
seqChunks
|
|
131
|
-
.sort((a
|
|
132
|
-
.forEach(
|
|
137
|
+
.sort((a, b) => a.get('start') - b.get('start'))
|
|
138
|
+
.forEach(chunk => {
|
|
133
139
|
const chunkStart = chunk.get('start')
|
|
134
140
|
const chunkEnd = chunk.get('end')
|
|
135
141
|
const trimStart = Math.max(start - chunkStart, 0)
|
|
@@ -153,16 +153,12 @@ export default class BamSlightlyLazyFeature implements Feature {
|
|
|
153
153
|
}
|
|
154
154
|
|
|
155
155
|
toJSON(): SimpleFeatureSerialized {
|
|
156
|
-
const tags = Object.fromEntries(
|
|
157
|
-
this.tags()
|
|
158
|
-
.map(t => {
|
|
159
|
-
return [t, this.get(t)]
|
|
160
|
-
})
|
|
161
|
-
.filter(elt => elt[1] !== undefined),
|
|
162
|
-
)
|
|
163
|
-
|
|
164
156
|
return {
|
|
165
|
-
...
|
|
157
|
+
...Object.fromEntries(
|
|
158
|
+
this.tags()
|
|
159
|
+
.map(t => [t, this.get(t)])
|
|
160
|
+
.filter(elt => elt[1] !== undefined),
|
|
161
|
+
),
|
|
166
162
|
uniqueId: this.id(),
|
|
167
163
|
}
|
|
168
164
|
}
|
|
@@ -201,24 +197,18 @@ export default class BamSlightlyLazyFeature implements Feature {
|
|
|
201
197
|
|
|
202
198
|
// parse the CIGAR tag if it has one
|
|
203
199
|
const cigarString = this.get(cigarAttributeName)
|
|
200
|
+
const seq = this.get('seq')
|
|
201
|
+
const qual = this.qualRaw()
|
|
204
202
|
if (cigarString) {
|
|
205
203
|
cigarOps = parseCigar(cigarString)
|
|
206
|
-
mismatches = mismatches.concat(
|
|
207
|
-
cigarToMismatches(cigarOps, this.get('seq'), this.qualRaw()),
|
|
208
|
-
)
|
|
204
|
+
mismatches = mismatches.concat(cigarToMismatches(cigarOps, seq, qual))
|
|
209
205
|
}
|
|
210
206
|
|
|
211
207
|
// now let's look for CRAM or MD mismatches
|
|
212
208
|
const mdString = this.get(mdAttributeName)
|
|
213
209
|
if (mdString) {
|
|
214
210
|
mismatches = mismatches.concat(
|
|
215
|
-
mdToMismatches(
|
|
216
|
-
mdString,
|
|
217
|
-
cigarOps,
|
|
218
|
-
mismatches,
|
|
219
|
-
this.get('seq'),
|
|
220
|
-
this.qualRaw(),
|
|
221
|
-
),
|
|
211
|
+
mdToMismatches(mdString, cigarOps, mismatches, seq, qual),
|
|
222
212
|
)
|
|
223
213
|
}
|
|
224
214
|
|
|
@@ -225,7 +225,8 @@ test('clipping', () => {
|
|
|
225
225
|
})
|
|
226
226
|
|
|
227
227
|
test('md generation', () => {
|
|
228
|
-
const query =
|
|
228
|
+
const query =
|
|
229
|
+
`CACACTAGCCCGTCAGCGAACGCGTGCGCGGCCGCTGCCCTGCAGCGAATGGGGCTAACGACGCATAAAACGCCCGCATA
|
|
229
230
|
ACCACTCGAGCTACGGGAAATTCACTCAGGCTGTGTTGCTTCGACGTGTAGATCTCATTCACATATCATAATACCTCCAA
|
|
230
231
|
GACCAACGGCTGCTCATGACTCTCTTACCTTGTTAGGGACATTTCGGCACTAGGGAAGAGCTGAGGACTTTGAAAACGTC
|
|
231
232
|
GATAAAACCATCGCGGGAACTAGCCTGCGTTAGAACTCCCATATTTTACGGGTCGCAAGCTTGAGAGTCCTGTCCCGGCA
|
|
@@ -448,7 +449,8 @@ ttagtgggccaaatcgcaaccctgctcccctcccttacgccttatacacttcagtgcaaa
|
|
|
448
449
|
ttcatgcgttcagcgaacaactggacttctgttgtacgtagtccacgggggcttattcat
|
|
449
450
|
tatagaaagccccctactgtcaccgttatatggttcacacatgagctgatcacctagaga
|
|
450
451
|
gtcgtcatgcacattcgcctaacaaggacatatgagtaaccgggaggg`.replace(/[\r\n]+/gm, '')
|
|
451
|
-
const cigar =
|
|
452
|
+
const cigar =
|
|
453
|
+
`8M1D10M1I3M1I36M1I37M1I13M2I18M1I7M1I4M1D119M1I13M1I27M1I46M1I13M1D2M1D19M1I22M1
|
|
452
454
|
D19M2I43M1I21M1I16M1I6M1I55M1I20M1I34M1I4M1D23M1I18M1D10M3I8M1I11M1I15M1I17M1I41
|
|
453
455
|
M1I45M1I3M1I3M2I5M1I10M1I35M1I16M1I70M1I8M1I8M1D17M1I5M1I59M1I25M2I29M1I34M1I25M
|
|
454
456
|
1I12M1I26M1D38M1D39M1I17M1I12M1I4M1I31M1I3M1I36M3I30M1I11M1I31M1I36M1I64M1I20M1I
|
|
@@ -496,3 +498,23 @@ test('getModificationPositions', () => {
|
|
|
496
498
|
)
|
|
497
499
|
expect(positions[0]).toEqual({ type: 'm', positions: [6, 17, 20, 31, 34] })
|
|
498
500
|
})
|
|
501
|
+
|
|
502
|
+
// ? means "modification status of the skipped bases provided."
|
|
503
|
+
test('getModificationPositions with unknown (?)', () => {
|
|
504
|
+
const positions = getModificationPositions(
|
|
505
|
+
'C+m?,2,2,1,4,1',
|
|
506
|
+
'AGCTCTCCAGAGTCGNACGCCATYCGCGCGCCACCA',
|
|
507
|
+
1,
|
|
508
|
+
)
|
|
509
|
+
expect(positions[0]).toEqual({ type: 'm', positions: [6, 17, 20, 31, 34] })
|
|
510
|
+
})
|
|
511
|
+
|
|
512
|
+
// . means "modification status of the skipped bases is low probability"
|
|
513
|
+
test('getModificationPositions with unknown (.)', () => {
|
|
514
|
+
const positions = getModificationPositions(
|
|
515
|
+
'C+m.,2,2,1,4,1',
|
|
516
|
+
'AGCTCTCCAGAGTCGNACGCCATYCGCGCGCCACCA',
|
|
517
|
+
1,
|
|
518
|
+
)
|
|
519
|
+
expect(positions[0]).toEqual({ type: 'm', positions: [6, 17, 20, 31, 34] })
|
|
520
|
+
})
|
|
@@ -153,15 +153,16 @@ export function mdToMismatches(
|
|
|
153
153
|
const md = mdstring.match(/(\d+|\^[a-z]+|[a-z])/gi) || []
|
|
154
154
|
for (let i = 0; i < md.length; i++) {
|
|
155
155
|
const token = md[i]
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
156
|
+
const num = +token
|
|
157
|
+
if (!Number.isNaN(num)) {
|
|
158
|
+
curr.start += num
|
|
159
|
+
} else if (token.startsWith('^')) {
|
|
159
160
|
curr.length = token.length - 1
|
|
160
161
|
curr.base = '*'
|
|
161
162
|
curr.type = 'deletion'
|
|
162
163
|
curr.seq = token.substring(1)
|
|
163
164
|
nextRecord()
|
|
164
|
-
} else
|
|
165
|
+
} else {
|
|
165
166
|
// mismatch
|
|
166
167
|
for (let j = 0; j < token.length; j += 1) {
|
|
167
168
|
curr.length = 1
|
|
@@ -328,7 +329,7 @@ export function getModificationPositions(
|
|
|
328
329
|
const [basemod, ...skips] = mod.split(',')
|
|
329
330
|
|
|
330
331
|
// regexes based on parse_mm.pl from hts-specs
|
|
331
|
-
const matches = basemod.match(/([A-Z])([-+])([
|
|
332
|
+
const matches = basemod.match(/([A-Z])([-+])([^,.?]+)([.?])?/)
|
|
332
333
|
if (!matches) {
|
|
333
334
|
throw new Error('bad format for MM tag')
|
|
334
335
|
}
|
|
@@ -7,7 +7,7 @@ export default types.late(() =>
|
|
|
7
7
|
{
|
|
8
8
|
bamLocation: {
|
|
9
9
|
type: 'fileLocation',
|
|
10
|
-
defaultValue: { uri: '/path/to/my.bam' },
|
|
10
|
+
defaultValue: { uri: '/path/to/my.bam', locationType: 'UriLocation' },
|
|
11
11
|
},
|
|
12
12
|
index: ConfigurationSchema('BamIndex', {
|
|
13
13
|
indexType: {
|
|
@@ -17,7 +17,10 @@ export default types.late(() =>
|
|
|
17
17
|
},
|
|
18
18
|
location: {
|
|
19
19
|
type: 'fileLocation',
|
|
20
|
-
defaultValue: {
|
|
20
|
+
defaultValue: {
|
|
21
|
+
uri: '/path/to/my.bam.bai',
|
|
22
|
+
locationType: 'UriLocation',
|
|
23
|
+
},
|
|
21
24
|
},
|
|
22
25
|
}),
|
|
23
26
|
chunkSizeLimit: {
|
package/src/BamAdapter/index.ts
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
|
+
import PluginManager from '@jbrowse/core/PluginManager'
|
|
2
|
+
import AdapterType from '@jbrowse/core/pluggableElementTypes/AdapterType'
|
|
1
3
|
import configSchema from './configSchema'
|
|
2
4
|
|
|
3
|
-
export default (
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
export default (pluginManager: PluginManager) => {
|
|
6
|
+
pluginManager.addAdapterType(
|
|
7
|
+
() =>
|
|
8
|
+
new AdapterType({
|
|
9
|
+
name: 'BamAdapter',
|
|
10
|
+
configSchema,
|
|
11
|
+
getAdapterClass: () => import('./BamAdapter').then(r => r.default),
|
|
12
|
+
}),
|
|
13
|
+
)
|
|
8
14
|
}
|
|
@@ -23,12 +23,15 @@ test('adapter can fetch features from volvox-sorted.cram', async () => {
|
|
|
23
23
|
configSchema.create({
|
|
24
24
|
cramLocation: {
|
|
25
25
|
localPath: require.resolve('../../test_data/volvox-sorted.cram'),
|
|
26
|
+
locationType: 'LocalPathLocation',
|
|
26
27
|
},
|
|
27
28
|
craiLocation: {
|
|
28
29
|
localPath: require.resolve('../../test_data/volvox-sorted.cram.crai'),
|
|
30
|
+
locationType: 'LocalPathLocation',
|
|
29
31
|
},
|
|
30
32
|
}),
|
|
31
33
|
getVolvoxSequenceSubAdapter,
|
|
34
|
+
pluginManager,
|
|
32
35
|
)
|
|
33
36
|
|
|
34
37
|
const features = adapter.getFeatures({
|
|
@@ -55,12 +58,15 @@ test('test usage of cramSlightlyLazyFeature toJSON (used in the widget)', async
|
|
|
55
58
|
configSchema.create({
|
|
56
59
|
cramLocation: {
|
|
57
60
|
localPath: require.resolve('../../test_data/volvox-sorted.cram'),
|
|
61
|
+
locationType: 'LocalPathLocation',
|
|
58
62
|
},
|
|
59
63
|
craiLocation: {
|
|
60
64
|
localPath: require.resolve('../../test_data/volvox-sorted.cram.crai'),
|
|
65
|
+
locationType: 'LocalPathLocation',
|
|
61
66
|
},
|
|
62
67
|
}),
|
|
63
68
|
getVolvoxSequenceSubAdapter,
|
|
69
|
+
pluginManager,
|
|
64
70
|
)
|
|
65
71
|
|
|
66
72
|
const features = adapter.getFeatures({
|
|
@@ -49,8 +49,10 @@ export default class CramAdapter extends BaseFeatureDataAdapter {
|
|
|
49
49
|
throw new Error('missing craiLocation argument')
|
|
50
50
|
}
|
|
51
51
|
this.cram = new IndexedCramFile({
|
|
52
|
-
cramFilehandle: openLocation(cramLocation),
|
|
53
|
-
index: new CraiIndex({
|
|
52
|
+
cramFilehandle: openLocation(cramLocation, this.pluginManager),
|
|
53
|
+
index: new CraiIndex({
|
|
54
|
+
filehandle: openLocation(craiLocation, this.pluginManager),
|
|
55
|
+
}),
|
|
54
56
|
seqFetch: this.seqFetch.bind(this),
|
|
55
57
|
checkSequenceMD5: false,
|
|
56
58
|
fetchSizeLimit: this.config.fetchSizeLimit || 600000000,
|
|
@@ -2,6 +2,7 @@ import { GenericFilehandle } from 'generic-filehandle'
|
|
|
2
2
|
import { Observable } from 'rxjs'
|
|
3
3
|
import SimpleFeature from '@jbrowse/core/util/simpleFeature'
|
|
4
4
|
import { BaseFeatureDataAdapter } from '@jbrowse/core/data_adapters/BaseAdapter'
|
|
5
|
+
import { ConfigurationSchema } from '@jbrowse/core/configuration/configurationSchema'
|
|
5
6
|
|
|
6
7
|
// setup for Cram Adapter Testing
|
|
7
8
|
export function parseSmallFasta(text: string) {
|
|
@@ -51,7 +52,7 @@ export class SequenceAdapter extends BaseFeatureDataAdapter {
|
|
|
51
52
|
refNames: string[] = []
|
|
52
53
|
|
|
53
54
|
constructor(filehandle: FileHandle) {
|
|
54
|
-
super()
|
|
55
|
+
super(ConfigurationSchema('empty', {}).create())
|
|
55
56
|
this.fasta = new FetchableSmallFasta(filehandle)
|
|
56
57
|
}
|
|
57
58
|
|
|
@@ -9,11 +9,17 @@ export default (pluginManager: PluginManager) => {
|
|
|
9
9
|
{
|
|
10
10
|
cramLocation: {
|
|
11
11
|
type: 'fileLocation',
|
|
12
|
-
defaultValue: {
|
|
12
|
+
defaultValue: {
|
|
13
|
+
uri: '/path/to/my.cram',
|
|
14
|
+
locationType: 'UriLocation',
|
|
15
|
+
},
|
|
13
16
|
},
|
|
14
17
|
craiLocation: {
|
|
15
18
|
type: 'fileLocation',
|
|
16
|
-
defaultValue: {
|
|
19
|
+
defaultValue: {
|
|
20
|
+
uri: '/path/to/my.cram.crai',
|
|
21
|
+
locationType: 'UriLocation',
|
|
22
|
+
},
|
|
17
23
|
},
|
|
18
24
|
sequenceAdapter: pluginManager.pluggableConfigSchemaType('adapter'),
|
|
19
25
|
},
|
package/src/CramAdapter/index.ts
CHANGED
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
import PluginManager from '@jbrowse/core/PluginManager'
|
|
2
|
+
import AdapterType from '@jbrowse/core/pluggableElementTypes/AdapterType'
|
|
3
|
+
|
|
4
|
+
// locals
|
|
2
5
|
import configSchemaF from './configSchema'
|
|
3
6
|
|
|
4
7
|
export default (pluginManager: PluginManager) => {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
8
|
+
pluginManager.addAdapterType(
|
|
9
|
+
() =>
|
|
10
|
+
new AdapterType({
|
|
11
|
+
name: 'CramAdapter',
|
|
12
|
+
configSchema: pluginManager.load(configSchemaF),
|
|
13
|
+
getAdapterClass: () => import('./CramAdapter').then(r => r.default),
|
|
14
|
+
}),
|
|
15
|
+
)
|
|
9
16
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { HtsgetFile } from '@gmod/bam'
|
|
1
|
+
import { BamFile, HtsgetFile } from '@gmod/bam'
|
|
2
2
|
import { readConfObject } from '@jbrowse/core/configuration'
|
|
3
3
|
import { BaseFeatureDataAdapter } from '@jbrowse/core/data_adapters/BaseAdapter'
|
|
4
4
|
import BamAdapter from '../BamAdapter/BamAdapter'
|
|
@@ -11,7 +11,7 @@ export default class HtsgetBamAdapter extends BamAdapter {
|
|
|
11
11
|
const bam = new HtsgetFile({
|
|
12
12
|
baseUrl: htsgetBase,
|
|
13
13
|
trackId: htsgetTrackId,
|
|
14
|
-
})
|
|
14
|
+
}) as unknown as BamFile
|
|
15
15
|
|
|
16
16
|
const adapterConfig = readConfObject(this.config, 'sequenceAdapter')
|
|
17
17
|
if (adapterConfig && this.getSubAdapter) {
|
|
@@ -1,8 +1,21 @@
|
|
|
1
1
|
import configSchema from './configSchema'
|
|
2
|
+
import PluginManager from '@jbrowse/core/PluginManager'
|
|
3
|
+
import AdapterType from '@jbrowse/core/pluggableElementTypes/AdapterType'
|
|
2
4
|
|
|
3
|
-
export default (
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
export default (pluginManager: PluginManager) => {
|
|
6
|
+
pluginManager.addAdapterType(
|
|
7
|
+
() =>
|
|
8
|
+
new AdapterType({
|
|
9
|
+
name: 'HtsgetBamAdapter',
|
|
10
|
+
adapterMetadata: {
|
|
11
|
+
category: null,
|
|
12
|
+
hiddenFromGUI: true,
|
|
13
|
+
displayName: null,
|
|
14
|
+
description: null,
|
|
15
|
+
},
|
|
16
|
+
configSchema,
|
|
17
|
+
getAdapterClass: () =>
|
|
18
|
+
import('./HtsgetBamAdapter').then(r => r.default),
|
|
19
|
+
}),
|
|
20
|
+
)
|
|
8
21
|
}
|
|
@@ -1,3 +1,20 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import DisplayType from '@jbrowse/core/pluggableElementTypes/DisplayType'
|
|
2
|
+
import PluginManager from '@jbrowse/core/PluginManager'
|
|
3
|
+
// locals
|
|
4
|
+
import configSchemaFactory from './models/configSchema'
|
|
5
|
+
import modelFactory from './models/model'
|
|
6
|
+
import ReactComponent from './components/AlignmentsDisplay'
|
|
7
|
+
|
|
8
|
+
export default function (pluginManager: PluginManager) {
|
|
9
|
+
pluginManager.addDisplayType(() => {
|
|
10
|
+
const configSchema = configSchemaFactory(pluginManager)
|
|
11
|
+
return new DisplayType({
|
|
12
|
+
name: 'LinearAlignmentsDisplay',
|
|
13
|
+
configSchema,
|
|
14
|
+
stateModel: modelFactory(pluginManager, configSchema),
|
|
15
|
+
trackType: 'AlignmentsTrack',
|
|
16
|
+
viewType: 'LinearGenomeView',
|
|
17
|
+
ReactComponent,
|
|
18
|
+
})
|
|
19
|
+
})
|
|
20
|
+
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import DisplayType from '@jbrowse/core/pluggableElementTypes/DisplayType'
|
|
2
1
|
import Plugin from '@jbrowse/core/Plugin'
|
|
3
2
|
import PluginManager from '@jbrowse/core/PluginManager'
|
|
4
3
|
import BoxRendererType from '@jbrowse/core/pluggableElementTypes/renderers/BoxRendererType'
|
|
@@ -6,24 +5,10 @@ import {
|
|
|
6
5
|
svgFeatureRendererConfigSchema,
|
|
7
6
|
SvgFeatureRendererReactComponent,
|
|
8
7
|
} from '@jbrowse/plugin-svg'
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
import
|
|
12
|
-
|
|
13
|
-
ReactComponent as PileupRendererReactComponent,
|
|
14
|
-
} from '../../PileupRenderer'
|
|
15
|
-
import SNPCoverageRenderer, {
|
|
16
|
-
configSchema as snpCoverageRendererConfigSchema,
|
|
17
|
-
ReactComponent as SNPCoverageRendererReactComponent,
|
|
18
|
-
} from '../../SNPCoverageRenderer'
|
|
19
|
-
import {
|
|
20
|
-
configSchemaFactory as linearPileupDisplayConfigSchemaFactory,
|
|
21
|
-
modelFactory as linearPileupDisplayModelFactory,
|
|
22
|
-
} from '../../LinearPileupDisplay'
|
|
23
|
-
import {
|
|
24
|
-
configSchemaFactory as linearSNPCoverageDisplayConfigSchemaFactory,
|
|
25
|
-
modelFactory as linearSNPCoverageDisplayModelFactory,
|
|
26
|
-
} from '../../LinearSNPCoverageDisplay'
|
|
8
|
+
import PileupRenderer from '../../PileupRenderer'
|
|
9
|
+
import SNPCoverageRenderer from '../../SNPCoverageRenderer'
|
|
10
|
+
import LinearPileupDisplay from '../../LinearPileupDisplay'
|
|
11
|
+
import LinearSNPCoverageDisplay from '../../LinearSNPCoverageDisplay'
|
|
27
12
|
import configSchemaFactory from './configSchema'
|
|
28
13
|
|
|
29
14
|
// mock warnings to avoid unnecessary outputs
|
|
@@ -37,15 +22,7 @@ afterEach(() => {
|
|
|
37
22
|
|
|
38
23
|
class AlignmentsPlugin extends Plugin {
|
|
39
24
|
install(pluginManager) {
|
|
40
|
-
pluginManager
|
|
41
|
-
() =>
|
|
42
|
-
new PileupRenderer({
|
|
43
|
-
name: 'PileupRenderer',
|
|
44
|
-
ReactComponent: PileupRendererReactComponent,
|
|
45
|
-
configSchema: pileupRendererConfigSchema,
|
|
46
|
-
pluginManager,
|
|
47
|
-
}),
|
|
48
|
-
)
|
|
25
|
+
PileupRenderer(pluginManager)
|
|
49
26
|
|
|
50
27
|
pluginManager.addRendererType(
|
|
51
28
|
() =>
|
|
@@ -57,47 +34,9 @@ class AlignmentsPlugin extends Plugin {
|
|
|
57
34
|
}),
|
|
58
35
|
)
|
|
59
36
|
|
|
60
|
-
pluginManager
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
name: 'SNPCoverageRenderer',
|
|
64
|
-
ReactComponent: SNPCoverageRendererReactComponent,
|
|
65
|
-
configSchema: snpCoverageRendererConfigSchema,
|
|
66
|
-
pluginManager,
|
|
67
|
-
}),
|
|
68
|
-
)
|
|
69
|
-
|
|
70
|
-
pluginManager.addDisplayType(() => {
|
|
71
|
-
const configSchema = linearPileupDisplayConfigSchemaFactory(pluginManager)
|
|
72
|
-
return new DisplayType({
|
|
73
|
-
name: 'LinearPileupDisplay',
|
|
74
|
-
configSchema,
|
|
75
|
-
stateModel: linearPileupDisplayModelFactory(
|
|
76
|
-
pluginManager,
|
|
77
|
-
configSchema,
|
|
78
|
-
),
|
|
79
|
-
trackType: 'AlignmentsTrack',
|
|
80
|
-
viewType: 'LinearGenomeView',
|
|
81
|
-
ReactComponent: BaseLinearDisplayComponent,
|
|
82
|
-
})
|
|
83
|
-
})
|
|
84
|
-
|
|
85
|
-
pluginManager.addDisplayType(() => {
|
|
86
|
-
const configSchema = linearSNPCoverageDisplayConfigSchemaFactory(
|
|
87
|
-
pluginManager,
|
|
88
|
-
)
|
|
89
|
-
return new DisplayType({
|
|
90
|
-
name: 'LinearSNPCoverageDisplay',
|
|
91
|
-
configSchema,
|
|
92
|
-
stateModel: linearSNPCoverageDisplayModelFactory(
|
|
93
|
-
pluginManager,
|
|
94
|
-
configSchema,
|
|
95
|
-
),
|
|
96
|
-
trackType: 'AlignmentsTrack',
|
|
97
|
-
viewType: 'LinearGenomeView',
|
|
98
|
-
ReactComponent: LinearWiggleDisplayReactComponent,
|
|
99
|
-
})
|
|
100
|
-
})
|
|
37
|
+
SNPCoverageRenderer(pluginManager)
|
|
38
|
+
LinearPileupDisplay(pluginManager)
|
|
39
|
+
LinearSNPCoverageDisplay(pluginManager)
|
|
101
40
|
}
|
|
102
41
|
}
|
|
103
42
|
|