@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.
Files changed (67) hide show
  1. package/dist/AlignmentsFeatureDetail/index.d.ts +7 -4
  2. package/dist/AlignmentsTrack/index.d.ts +2 -0
  3. package/dist/BamAdapter/index.d.ts +2 -4
  4. package/dist/CramAdapter/index.d.ts +1 -4
  5. package/dist/HtsgetBamAdapter/HtsgetBamAdapter.d.ts +2 -1
  6. package/dist/HtsgetBamAdapter/index.d.ts +2 -4
  7. package/dist/LinearAlignmentsDisplay/index.d.ts +2 -3
  8. package/dist/LinearAlignmentsDisplay/models/model.d.ts +6 -6
  9. package/dist/LinearPileupDisplay/index.d.ts +2 -2
  10. package/dist/LinearPileupDisplay/model.d.ts +9 -10
  11. package/dist/LinearSNPCoverageDisplay/components/Tooltip.d.ts +1 -1
  12. package/dist/LinearSNPCoverageDisplay/index.d.ts +2 -2
  13. package/dist/LinearSNPCoverageDisplay/models/model.d.ts +3 -2
  14. package/dist/PileupRPC/rpcMethods.d.ts +2 -16
  15. package/dist/PileupRenderer/PileupRenderer.d.ts +20 -7
  16. package/dist/PileupRenderer/index.d.ts +2 -3
  17. package/dist/SNPCoverageAdapter/SNPCoverageAdapter.d.ts +38 -26
  18. package/dist/SNPCoverageAdapter/index.d.ts +1 -5
  19. package/dist/SNPCoverageRenderer/index.d.ts +3 -3
  20. package/dist/plugin-alignments.cjs.development.js +4488 -4254
  21. package/dist/plugin-alignments.cjs.development.js.map +1 -1
  22. package/dist/plugin-alignments.cjs.production.min.js +1 -1
  23. package/dist/plugin-alignments.cjs.production.min.js.map +1 -1
  24. package/dist/plugin-alignments.esm.js +4485 -4251
  25. package/dist/plugin-alignments.esm.js.map +1 -1
  26. package/package.json +4 -4
  27. package/src/AlignmentsFeatureDetail/index.test.js +2 -4
  28. package/src/AlignmentsFeatureDetail/{index.js → index.ts} +19 -3
  29. package/src/AlignmentsTrack/index.ts +36 -0
  30. package/src/BamAdapter/BamAdapter.test.ts +8 -0
  31. package/src/BamAdapter/BamAdapter.ts +11 -5
  32. package/src/BamAdapter/BamSlightlyLazyFeature.ts +9 -19
  33. package/src/BamAdapter/MismatchParser.test.ts +24 -2
  34. package/src/BamAdapter/MismatchParser.ts +6 -5
  35. package/src/BamAdapter/configSchema.ts +5 -2
  36. package/src/BamAdapter/index.ts +11 -5
  37. package/src/CramAdapter/CramAdapter.test.ts +6 -0
  38. package/src/CramAdapter/CramAdapter.ts +4 -2
  39. package/src/CramAdapter/CramTestAdapters.ts +2 -1
  40. package/src/CramAdapter/configSchema.ts +8 -2
  41. package/src/CramAdapter/index.ts +11 -4
  42. package/src/HtsgetBamAdapter/HtsgetBamAdapter.ts +2 -2
  43. package/src/HtsgetBamAdapter/index.ts +18 -5
  44. package/src/LinearAlignmentsDisplay/index.ts +20 -3
  45. package/src/LinearAlignmentsDisplay/models/configSchema.test.js +8 -69
  46. package/src/LinearPileupDisplay/configSchema.test.js +2 -13
  47. package/src/LinearPileupDisplay/configSchema.ts +4 -6
  48. package/src/LinearPileupDisplay/index.ts +19 -2
  49. package/src/LinearPileupDisplay/model.ts +53 -51
  50. package/src/LinearSNPCoverageDisplay/components/Tooltip.tsx +17 -12
  51. package/src/LinearSNPCoverageDisplay/index.ts +19 -2
  52. package/src/LinearSNPCoverageDisplay/models/configSchema.test.js +2 -13
  53. package/src/LinearSNPCoverageDisplay/models/model.ts +23 -6
  54. package/src/PileupRPC/rpcMethods.ts +8 -2
  55. package/src/PileupRenderer/PileupRenderer.tsx +154 -128
  56. package/src/PileupRenderer/components/PileupRendering.tsx +4 -8
  57. package/src/PileupRenderer/configSchema.ts +2 -2
  58. package/src/PileupRenderer/index.ts +16 -3
  59. package/src/SNPCoverageAdapter/SNPCoverageAdapter.ts +95 -25
  60. package/src/SNPCoverageAdapter/index.ts +17 -5
  61. package/src/SNPCoverageRenderer/SNPCoverageRenderer.ts +62 -15
  62. package/src/SNPCoverageRenderer/configSchema.js +5 -0
  63. package/src/SNPCoverageRenderer/index.ts +24 -0
  64. package/src/index.ts +91 -165
  65. package/src/SNPCoverageAdapter/SNPCoverageAdapter.test.ts +0 -269
  66. package/src/SNPCoverageAdapter/__snapshots__/SNPCoverageAdapter.test.ts.snap +0 -579
  67. package/src/SNPCoverageRenderer/index.js +0 -11
@@ -2,7 +2,7 @@ import {
2
2
  BaseFeatureDataAdapter,
3
3
  BaseOptions,
4
4
  } from '@jbrowse/core/data_adapters/BaseAdapter'
5
- import { Region } from '@jbrowse/core/util/types'
5
+ import { AugmentedRegion as Region } from '@jbrowse/core/util/types'
6
6
  import SimpleFeature, { Feature } from '@jbrowse/core/util/simpleFeature'
7
7
  import { readConfObject } from '@jbrowse/core/configuration'
8
8
  import SerializableFilterChain from '@jbrowse/core/pluggableElementTypes/renderers/util/serializableFilterChain'
@@ -81,7 +81,11 @@ export default class SNPCoverageAdapter extends BaseFeatureDataAdapter {
81
81
  stream = stream.pipe(filter(f => filters.passes(f, opts)))
82
82
  }
83
83
 
84
- const bins = await this.generateCoverageBins(stream, region, opts)
84
+ const { bins, skipmap } = await this.generateCoverageBins(
85
+ stream,
86
+ region,
87
+ opts,
88
+ )
85
89
 
86
90
  bins.forEach((bin, index) => {
87
91
  if (bin.total) {
@@ -100,6 +104,23 @@ export default class SNPCoverageAdapter extends BaseFeatureDataAdapter {
100
104
  }
101
105
  })
102
106
 
107
+ // make fake features from the coverage
108
+ Object.entries(skipmap).forEach(([key, skip]) => {
109
+ observer.next(
110
+ new SimpleFeature({
111
+ id: key,
112
+ data: {
113
+ type: 'skip',
114
+ start: skip.start,
115
+ end: skip.end,
116
+ strand: skip.strand,
117
+ score: skip.score,
118
+ xs: skip.xs,
119
+ },
120
+ }),
121
+ )
122
+ })
123
+
103
124
  observer.complete()
104
125
  }, opts.signal)
105
126
  }
@@ -126,9 +147,20 @@ export default class SNPCoverageAdapter extends BaseFeatureDataAdapter {
126
147
  ) {
127
148
  const { colorBy } = opts
128
149
  const { sequenceAdapter } = await this.configure()
129
- const { refName, start, end } = region
150
+ const { originalRefName, refName, start, end } = region
130
151
  const binMax = Math.ceil(region.end - region.start)
131
152
 
153
+ const skipmap = {} as {
154
+ [key: string]: {
155
+ score: number
156
+ feature: unknown
157
+ start: number
158
+ end: number
159
+ strand: number
160
+ xs: string
161
+ }
162
+ }
163
+
132
164
  // bins contain cov feature if they contribute to coverage, or noncov which
133
165
  // are interbase or other features that don't contribute to coverage.
134
166
  // delskips are elements that don't contribute to coverage, but should be
@@ -148,13 +180,18 @@ export default class SNPCoverageAdapter extends BaseFeatureDataAdapter {
148
180
 
149
181
  if (sequenceAdapter) {
150
182
  const [feat] = await sequenceAdapter
151
- .getFeatures({ refName, start, end: end + 1, assemblyName: 'na' })
183
+ .getFeatures({
184
+ refName: originalRefName || refName,
185
+ start,
186
+ end: end + 1,
187
+ assemblyName: 'na',
188
+ })
152
189
  .pipe(toArray())
153
190
  .toPromise()
154
191
  regionSeq = feat?.get('seq')
155
192
  }
156
193
 
157
- return features
194
+ const bins = await features
158
195
  .pipe(
159
196
  reduce((bins, feature) => {
160
197
  const cigar = feature.get('CIGAR')
@@ -262,30 +299,61 @@ export default class SNPCoverageAdapter extends BaseFeatureDataAdapter {
262
299
 
263
300
  // normal SNP based coloring
264
301
  else {
265
- const mismatches = feature.get('mismatches')
266
- for (let i = 0; i < mismatches?.length; i++) {
267
- const mismatch = mismatches[i] as Mismatch
268
- const mstart = fstart + mismatch.start
269
- for (let j = mstart; j < mstart + mismatchLen(mismatch); j++) {
270
- const epos = j - region.start
271
- if (epos >= 0 && epos < bins.length) {
272
- const bin = bins[epos]
273
- const { base, type } = mismatch
274
- const interbase = isInterbase(type)
275
- if (!interbase) {
276
- dec(bin, fstrand, 'ref', 'ref')
277
- } else {
278
- inc(bin, fstrand, 'noncov', type)
279
- }
302
+ const mismatches = feature.get('mismatches') as
303
+ | Mismatch[]
304
+ | undefined
305
+
306
+ if (mismatches) {
307
+ for (let i = 0; i < mismatches.length; i++) {
308
+ const mismatch = mismatches[i]
309
+ const mstart = fstart + mismatch.start
310
+ for (let j = mstart; j < mstart + mismatchLen(mismatch); j++) {
311
+ const epos = j - region.start
312
+ if (epos >= 0 && epos < bins.length) {
313
+ const bin = bins[epos]
314
+ const { base, type } = mismatch
315
+ const interbase = isInterbase(type)
316
+ if (!interbase) {
317
+ dec(bin, fstrand, 'ref', 'ref')
318
+ } else {
319
+ inc(bin, fstrand, 'noncov', type)
320
+ }
280
321
 
281
- if (type === 'deletion' || type === 'skip') {
282
- inc(bin, fstrand, 'delskips', type)
283
- bin.total--
284
- } else if (!interbase) {
285
- inc(bin, fstrand, 'cov', base)
322
+ if (type === 'deletion' || type === 'skip') {
323
+ inc(bin, fstrand, 'delskips', type)
324
+ bin.total--
325
+ } else if (!interbase) {
326
+ inc(bin, fstrand, 'cov', base)
327
+ }
286
328
  }
287
329
  }
288
330
  }
331
+
332
+ mismatches
333
+ .filter(mismatch => mismatch.type === 'skip')
334
+ .forEach(mismatch => {
335
+ const mstart = feature.get('start') + mismatch.start
336
+ const start = mstart
337
+ const end = mstart + mismatch.length
338
+ const strand = feature.get('strand')
339
+ const hash = `${start}_${end}_${strand}`
340
+ if (!skipmap[hash]) {
341
+ skipmap[hash] = {
342
+ feature: feature,
343
+ start,
344
+ end,
345
+ strand,
346
+ xs:
347
+ feature.get('xs') ||
348
+ feature.get('ts') ||
349
+ feature.get('tags').XS ||
350
+ feature.get('tags').TS,
351
+ score: 1,
352
+ }
353
+ } else {
354
+ skipmap[hash].score++
355
+ }
356
+ })
289
357
  }
290
358
  }
291
359
 
@@ -293,6 +361,8 @@ export default class SNPCoverageAdapter extends BaseFeatureDataAdapter {
293
361
  }, initBins),
294
362
  )
295
363
  .toPromise()
364
+
365
+ return { bins, skipmap }
296
366
  }
297
367
  }
298
368
 
@@ -1,11 +1,23 @@
1
1
  import PluginManager from '@jbrowse/core/PluginManager'
2
+ import AdapterType from '@jbrowse/core/pluggableElementTypes/AdapterType'
2
3
  import configSchemaFactory from './configSchema'
3
4
  import { capabilities } from './SNPCoverageAdapter'
4
5
 
5
6
  export default (pluginManager: PluginManager) => {
6
- return {
7
- getAdapterClass: () => import('./SNPCoverageAdapter').then(r => r.default),
8
- configSchema: configSchemaFactory(pluginManager),
9
- adapterCapabilities: capabilities,
10
- }
7
+ pluginManager.addAdapterType(
8
+ () =>
9
+ new AdapterType({
10
+ name: 'SNPCoverageAdapter',
11
+ adapterMetadata: {
12
+ category: null,
13
+ displayName: null,
14
+ hiddenFromGUI: true,
15
+ description: null,
16
+ },
17
+ getAdapterClass: () =>
18
+ import('./SNPCoverageAdapter').then(r => r.default),
19
+ configSchema: configSchemaFactory(pluginManager),
20
+ adapterCapabilities: capabilities,
21
+ }),
22
+ )
11
23
  }
@@ -2,6 +2,7 @@ import { createJBrowseTheme } from '@jbrowse/core/ui'
2
2
  import { featureSpanPx } from '@jbrowse/core/util'
3
3
  import { Feature } from '@jbrowse/core/util/simpleFeature'
4
4
  import { readConfObject } from '@jbrowse/core/configuration'
5
+ import { bpSpanPx } from '@jbrowse/core/util'
5
6
  import { RenderArgsDeserialized as FeatureRenderArgsDeserialized } from '@jbrowse/core/pluggableElementTypes/renderers/FeatureRendererType'
6
7
  import {
7
8
  getOrigin,
@@ -26,6 +27,16 @@ export interface RenderArgsDeserializedWithFeatures
26
27
  modificationTagMap: Record<string, string>
27
28
  }
28
29
 
30
+ type Counts = {
31
+ [key: string]: { total: number; strands: { [key: string]: number } }
32
+ }
33
+
34
+ interface SNPInfo {
35
+ cov: Counts
36
+ noncov: Counts
37
+ total: number
38
+ }
39
+
29
40
  export default class SNPCoverageRenderer extends WiggleBaseRenderer {
30
41
  // note: the snps are drawn on linear scale even if the data is drawn in log
31
42
  // scape hence the two different scales being used
@@ -37,13 +48,13 @@ export default class SNPCoverageRenderer extends WiggleBaseRenderer {
37
48
  features,
38
49
  regions,
39
50
  bpPerPx,
51
+ displayCrossHatches,
52
+ modificationTagMap,
40
53
  scaleOpts,
41
54
  height: unadjustedHeight,
42
55
  theme: configTheme,
43
56
  config: cfg,
44
- displayCrossHatches,
45
57
  ticks: { values },
46
- modificationTagMap,
47
58
  } = props
48
59
  const theme = createJBrowseTheme(configTheme)
49
60
  const [region] = regions
@@ -63,14 +74,15 @@ export default class SNPCoverageRenderer extends WiggleBaseRenderer {
63
74
 
64
75
  const indicatorThreshold = readConfObject(cfg, 'indicatorThreshold')
65
76
  const drawInterbaseCounts = readConfObject(cfg, 'drawInterbaseCounts')
77
+ const drawArcs = readConfObject(cfg, 'drawArcs')
66
78
  const drawIndicators = readConfObject(cfg, 'drawIndicators')
67
79
 
68
80
  // get the y coordinate that we are plotting at, this can be log scale
69
- const toY = (n: number) => height - viewScale(n) + offset
81
+ const toY = (n: number) => height - (viewScale(n) || 0) + offset
70
82
  const toHeight = (n: number) => toY(originY) - toY(n)
71
83
 
72
84
  // this is always linear scale, even when plotted on top of log scale
73
- const snpToY = (n: number) => height - snpViewScale(n) + offset
85
+ const snpToY = (n: number) => height - (snpViewScale(n) || 0) + offset
74
86
  const snpToHeight = (n: number) => snpToY(snpOriginY) - snpToY(n)
75
87
 
76
88
  const colorForBase: { [key: string]: string } = {
@@ -87,15 +99,19 @@ export default class SNPCoverageRenderer extends WiggleBaseRenderer {
87
99
  ref: 'lightgrey',
88
100
  }
89
101
 
102
+ const feats = [...features.values()]
103
+ const coverage = feats.filter(f => f.get('type') !== 'skip')
104
+ const skips = feats.filter(f => f.get('type') === 'skip')
105
+
90
106
  // Use two pass rendering, which helps in visualizing the SNPs at higher
91
107
  // bpPerPx First pass: draw the gray background
92
108
  ctx.fillStyle = colorForBase.total
93
- for (const feature of features.values()) {
109
+ coverage.forEach(feature => {
94
110
  const [leftPx, rightPx] = featureSpanPx(feature, region, bpPerPx)
95
111
  const w = rightPx - leftPx + 0.3
96
112
  const score = feature.get('score') as number
97
113
  ctx.fillRect(leftPx, toY(score), w, toHeight(score))
98
- }
114
+ })
99
115
  ctx.fillStyle = 'grey'
100
116
  ctx.beginPath()
101
117
  ctx.lineTo(0, 0)
@@ -105,16 +121,10 @@ export default class SNPCoverageRenderer extends WiggleBaseRenderer {
105
121
  // Second pass: draw the SNP data, and add a minimum feature width of 1px
106
122
  // which can be wider than the actual bpPerPx This reduces overdrawing of
107
123
  // the grey background over the SNPs
108
- for (const feature of features.values()) {
124
+ coverage.forEach(feature => {
109
125
  const [leftPx, rightPx] = featureSpanPx(feature, region, bpPerPx)
110
- type Counts = {
111
- [key: string]: { total: number; strands: { [key: string]: number } }
112
- }
113
- const snpinfo = feature.get('snpinfo') as {
114
- cov: Counts
115
- noncov: Counts
116
- total: number
117
- }
126
+
127
+ const snpinfo = feature.get('snpinfo') as SNPInfo
118
128
  const w = Math.max(rightPx - leftPx + 0.3, 1)
119
129
  const totalScore = snpinfo.total
120
130
 
@@ -175,6 +185,43 @@ export default class SNPCoverageRenderer extends WiggleBaseRenderer {
175
185
  ctx.fill()
176
186
  }
177
187
  }
188
+ })
189
+
190
+ ctx.globalAlpha = 0.7
191
+
192
+ if (drawArcs) {
193
+ skips.forEach(f => {
194
+ const [left, right] = bpSpanPx(
195
+ f.get('start'),
196
+ f.get('end'),
197
+ region,
198
+ bpPerPx,
199
+ )
200
+
201
+ ctx.beginPath()
202
+ const str = f.get('strand') as number
203
+ const xs = f.get('xs') as string
204
+ const pos = 'rgb(255,200,200)'
205
+ const neg = 'rgb(200,200,255)'
206
+ const neutral = 'rgb(200,200,200)'
207
+
208
+ if (xs === '+') {
209
+ ctx.strokeStyle = pos
210
+ } else if (xs === '-') {
211
+ ctx.strokeStyle = neg
212
+ } else if (str === 1) {
213
+ ctx.strokeStyle = pos
214
+ } else if (str === -1) {
215
+ ctx.strokeStyle = neg
216
+ } else {
217
+ ctx.strokeStyle = neutral
218
+ }
219
+
220
+ ctx.lineWidth = Math.log(f.get('score') + 1)
221
+ ctx.moveTo(left, height - offset * 2)
222
+ ctx.bezierCurveTo(left, 0, right, 0, right, height - offset * 2)
223
+ ctx.stroke()
224
+ })
178
225
  }
179
226
 
180
227
  if (displayCrossHatches) {
@@ -14,6 +14,11 @@ export default ConfigurationSchema(
14
14
  'the proportion of reads containing a insertion/clip indicator',
15
15
  defaultValue: 0.3,
16
16
  },
17
+ drawArcs: {
18
+ type: 'boolean',
19
+ description: 'Draw sashimi-style arcs for intron features',
20
+ defaultValue: true,
21
+ },
17
22
  drawInterbaseCounts: {
18
23
  type: 'boolean',
19
24
  description:
@@ -0,0 +1,24 @@
1
+ import { ConfigurationSchema } from '@jbrowse/core/configuration'
2
+ import ConfigSchema from './configSchema'
3
+ import PluginManager from '@jbrowse/core/PluginManager'
4
+ import SNPCoverageRenderer from './SNPCoverageRenderer'
5
+
6
+ import { WiggleRendering } from '@jbrowse/plugin-wiggle'
7
+
8
+ export const configSchema = ConfigurationSchema(
9
+ 'SNPCoverageRenderer',
10
+ {},
11
+ { baseConfiguration: ConfigSchema, explicitlyTyped: true },
12
+ )
13
+
14
+ export default function register(pluginManager: PluginManager) {
15
+ pluginManager.addRendererType(
16
+ () =>
17
+ new SNPCoverageRenderer({
18
+ name: 'SNPCoverageRenderer',
19
+ ReactComponent: WiggleRendering,
20
+ configSchema,
21
+ pluginManager,
22
+ }),
23
+ )
24
+ }
package/src/index.ts CHANGED
@@ -1,52 +1,32 @@
1
- import { lazy } from 'react'
2
- import { ConfigurationSchema } from '@jbrowse/core/configuration'
3
- import AdapterType from '@jbrowse/core/pluggableElementTypes/AdapterType'
4
- import DisplayType from '@jbrowse/core/pluggableElementTypes/DisplayType'
5
- import {
6
- createBaseTrackConfig,
7
- createBaseTrackModel,
8
- } from '@jbrowse/core/pluggableElementTypes/models'
9
- import TrackType from '@jbrowse/core/pluggableElementTypes/TrackType'
10
- import WidgetType from '@jbrowse/core/pluggableElementTypes/WidgetType'
1
+ import { FileLocation } from '@jbrowse/core/util/types'
11
2
  import Plugin from '@jbrowse/core/Plugin'
12
3
  import PluginManager from '@jbrowse/core/PluginManager'
13
- import { BaseLinearDisplayComponent } from '@jbrowse/plugin-linear-genome-view'
14
- import { LinearWiggleDisplayReactComponent } from '@jbrowse/plugin-wiggle'
15
- import {
16
- configSchema as alignmentsFeatureDetailConfigSchema,
17
- stateModelFactory as alignmentsFeatureDetailStateModelFactory,
18
- } from './AlignmentsFeatureDetail'
19
- import BamAdapterF from './BamAdapter'
20
4
  import * as MismatchParser from './BamAdapter/MismatchParser'
21
- import CramAdapterF from './CramAdapter'
22
- import HtsgetBamAdapterF from './HtsgetBamAdapter'
23
- import {
24
- configSchemaFactory as linearAligmentsDisplayConfigSchemaFactory,
25
- modelFactory as linearAlignmentsDisplayModelFactory,
26
- ReactComponent as LinearAlignmentsDisplayReactComponent,
27
- } from './LinearAlignmentsDisplay'
28
- import {
29
- configSchemaFactory as linearPileupDisplayConfigSchemaFactory,
30
- modelFactory as linearPileupDisplayModelFactory,
31
- } from './LinearPileupDisplay'
32
5
  import { LinearPileupDisplayModel } from './LinearPileupDisplay/model'
33
- import {
34
- configSchemaFactory as linearSNPCoverageDisplayConfigSchemaFactory,
35
- modelFactory as linearSNPCoverageDisplayModelFactory,
36
- } from './LinearSNPCoverageDisplay'
37
- import PileupRenderer, {
38
- configSchema as pileupRendererConfigSchema,
39
- ReactComponent as PileupRendererReactComponent,
40
- } from './PileupRenderer'
6
+
7
+ import BamAdapterF from './CramAdapter'
8
+ import CramAdapterF from './BamAdapter'
9
+ import HtsgetBamAdapterF from './HtsgetBamAdapter'
41
10
  import SNPCoverageAdapterF from './SNPCoverageAdapter'
42
- import SNPCoverageRenderer, {
43
- configSchema as SNPCoverageRendererConfigSchema,
44
- ReactComponent as SNPCoverageRendererReactComponent,
45
- } from './SNPCoverageRenderer'
11
+ import SNPCoverageRendererF from './SNPCoverageRenderer'
12
+ import PileupRendererF from './PileupRenderer'
13
+ import LinearAlignmentsDisplayF from './LinearAlignmentsDisplay'
14
+ import LinearSNPCoverageDisplayF from './LinearSNPCoverageDisplay'
15
+ import LinearPileupDisplayF from './LinearPileupDisplay'
16
+ import AlignmentsTrackF from './AlignmentsTrack'
17
+ import AlignmentsFeatureWidgetF from './AlignmentsFeatureDetail'
18
+
46
19
  import {
47
20
  PileupGetGlobalValueForTag,
48
21
  PileupGetVisibleModifications,
49
22
  } from './PileupRPC/rpcMethods'
23
+ import {
24
+ makeIndex,
25
+ makeIndexType,
26
+ getFileName,
27
+ AdapterGuesser,
28
+ TrackTypeGuesser,
29
+ } from '@jbrowse/core/util/tracks'
50
30
 
51
31
  export { MismatchParser }
52
32
  export type { LinearPileupDisplayModel }
@@ -55,133 +35,79 @@ export default class AlignmentsPlugin extends Plugin {
55
35
  name = 'AlignmentsPlugin'
56
36
 
57
37
  install(pluginManager: PluginManager) {
58
- pluginManager.addTrackType(() => {
59
- const configSchema = ConfigurationSchema(
60
- 'AlignmentsTrack',
61
- {},
62
- { baseConfiguration: createBaseTrackConfig(pluginManager) },
63
- )
64
- const track = new TrackType({
65
- name: 'AlignmentsTrack',
66
- configSchema,
67
- stateModel: createBaseTrackModel(
68
- pluginManager,
69
- 'AlignmentsTrack',
70
- configSchema,
71
- ),
72
- })
73
- const linearAlignmentsDisplay = pluginManager.getDisplayType(
74
- 'LinearAlignmentsDisplay',
75
- )
76
- // Add LinearAlignmentsDisplay here so that it has priority over the other
77
- // linear displays (defaults to order the displays are added, but we have
78
- // to add the Pileup and SNPCoverage displays first).
79
- track.addDisplayType(linearAlignmentsDisplay)
80
- return track
81
- })
82
- pluginManager.addDisplayType(() => {
83
- const configSchema = linearPileupDisplayConfigSchemaFactory(pluginManager)
84
- return new DisplayType({
85
- name: 'LinearPileupDisplay',
86
- configSchema,
87
- stateModel: linearPileupDisplayModelFactory(
88
- pluginManager,
89
- configSchema,
90
- ),
91
- trackType: 'AlignmentsTrack',
92
- viewType: 'LinearGenomeView',
93
- ReactComponent: BaseLinearDisplayComponent,
94
- })
95
- })
96
- pluginManager.addDisplayType(() => {
97
- const configSchema = linearSNPCoverageDisplayConfigSchemaFactory(
98
- pluginManager,
99
- )
100
- return new DisplayType({
101
- name: 'LinearSNPCoverageDisplay',
102
- configSchema,
103
- stateModel: linearSNPCoverageDisplayModelFactory(
104
- pluginManager,
105
- configSchema,
106
- ),
107
- trackType: 'AlignmentsTrack',
108
- viewType: 'LinearGenomeView',
109
- ReactComponent: LinearWiggleDisplayReactComponent,
110
- })
111
- })
112
- pluginManager.addDisplayType(() => {
113
- const configSchema = linearAligmentsDisplayConfigSchemaFactory(
114
- pluginManager,
115
- )
116
- return new DisplayType({
117
- name: 'LinearAlignmentsDisplay',
118
- configSchema,
119
- stateModel: linearAlignmentsDisplayModelFactory(
120
- pluginManager,
121
- configSchema,
122
- ),
123
- trackType: 'AlignmentsTrack',
124
- viewType: 'LinearGenomeView',
125
- ReactComponent: LinearAlignmentsDisplayReactComponent,
126
- })
127
- })
128
- pluginManager.addWidgetType(
129
- () =>
130
- new WidgetType({
131
- name: 'AlignmentsFeatureWidget',
132
- heading: 'Feature details',
133
- configSchema: alignmentsFeatureDetailConfigSchema,
134
- stateModel: alignmentsFeatureDetailStateModelFactory(pluginManager),
135
- ReactComponent: lazy(
136
- () => import('./AlignmentsFeatureDetail/AlignmentsFeatureDetail'),
137
- ),
138
- }),
139
- )
140
- pluginManager.addAdapterType(
141
- () =>
142
- new AdapterType({
143
- name: 'BamAdapter',
144
- ...pluginManager.load(BamAdapterF),
145
- }),
146
- )
147
- pluginManager.addAdapterType(
148
- () =>
149
- new AdapterType({
150
- name: 'SNPCoverageAdapter',
151
- ...pluginManager.load(SNPCoverageAdapterF),
152
- }),
153
- )
154
- pluginManager.addAdapterType(
155
- () =>
156
- new AdapterType({
157
- name: 'CramAdapter',
158
- ...pluginManager.load(CramAdapterF),
159
- }),
160
- )
161
- pluginManager.addAdapterType(
162
- () =>
163
- new AdapterType({
164
- name: 'HtsgetBamAdapter',
165
- ...pluginManager.load(HtsgetBamAdapterF),
166
- }),
38
+ ;[
39
+ CramAdapterF,
40
+ BamAdapterF,
41
+ LinearPileupDisplayF,
42
+ LinearSNPCoverageDisplayF,
43
+ AlignmentsTrackF,
44
+ SNPCoverageAdapterF,
45
+ HtsgetBamAdapterF,
46
+ PileupRendererF,
47
+ SNPCoverageRendererF,
48
+ LinearAlignmentsDisplayF,
49
+ AlignmentsFeatureWidgetF,
50
+ ].map(f => f(pluginManager))
51
+
52
+ pluginManager.addToExtensionPoint(
53
+ 'Core-guessAdapterForLocation',
54
+ (adapterGuesser: AdapterGuesser) => {
55
+ return (
56
+ file: FileLocation,
57
+ index?: FileLocation,
58
+ adapterHint?: string,
59
+ ) => {
60
+ const regexGuess = /\.cram$/i
61
+ const adapterName = 'CramAdapter'
62
+ const fileName = getFileName(file)
63
+ if (regexGuess.test(fileName) || adapterHint === adapterName) {
64
+ return {
65
+ type: adapterName,
66
+ cramLocation: file,
67
+ craiLocation: index || makeIndex(file, '.crai'),
68
+ }
69
+ }
70
+ return adapterGuesser(file, index, adapterHint)
71
+ }
72
+ },
167
73
  )
168
- pluginManager.addRendererType(
169
- () =>
170
- new PileupRenderer({
171
- name: 'PileupRenderer',
172
- ReactComponent: PileupRendererReactComponent,
173
- configSchema: pileupRendererConfigSchema,
174
- pluginManager,
175
- }),
74
+
75
+ pluginManager.addToExtensionPoint(
76
+ 'Core-guessAdapterForLocation',
77
+ (adapterGuesser: AdapterGuesser) => {
78
+ return (
79
+ file: FileLocation,
80
+ index?: FileLocation,
81
+ adapterHint?: string,
82
+ ) => {
83
+ const regexGuess = /\.bam$/i
84
+ const adapterName = 'BamAdapter'
85
+ const fileName = getFileName(file)
86
+ const indexName = index && getFileName(index)
87
+ if (regexGuess.test(fileName) || adapterHint === adapterName) {
88
+ return {
89
+ type: adapterName,
90
+ bamLocation: file,
91
+ index: {
92
+ location: index || makeIndex(file, '.bai'),
93
+ indexType: makeIndexType(indexName, 'CSI', 'BAI'),
94
+ },
95
+ }
96
+ }
97
+ return adapterGuesser(file, index, adapterHint)
98
+ }
99
+ },
176
100
  )
177
- pluginManager.addRendererType(
178
- () =>
179
- new SNPCoverageRenderer({
180
- name: 'SNPCoverageRenderer',
181
- ReactComponent: SNPCoverageRendererReactComponent,
182
- configSchema: SNPCoverageRendererConfigSchema,
183
- pluginManager,
184
- }),
101
+ pluginManager.addToExtensionPoint(
102
+ 'Core-guessTrackTypeForLocation',
103
+ (trackTypeGuesser: TrackTypeGuesser) => {
104
+ return (adapterName: string) => {
105
+ if (adapterName === 'BamAdapter' || adapterName === 'CramAdapter') {
106
+ return 'AlignmentsTrack'
107
+ }
108
+ return trackTypeGuesser(adapterName)
109
+ }
110
+ },
185
111
  )
186
112
 
187
113
  pluginManager.addRpcMethod(