@jbrowse/plugin-alignments 1.6.5 → 1.6.8
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 +1 -1
- package/dist/BamAdapter/BamSlightlyLazyFeature.d.ts +2 -10
- package/dist/BamAdapter/MismatchParser.d.ts +3 -5
- package/dist/BamAdapter/configSchema.d.ts +1 -1
- package/dist/CramAdapter/CramSlightlyLazyFeature.d.ts +1 -2
- package/dist/CramAdapter/configSchema.d.ts +1 -1
- package/dist/HtsgetBamAdapter/configSchema.d.ts +1 -1
- package/dist/LinearAlignmentsDisplay/models/configSchema.d.ts +1 -1
- package/dist/LinearAlignmentsDisplay/models/model.d.ts +1 -1
- package/dist/LinearPileupDisplay/configSchema.d.ts +1 -1
- package/dist/LinearSNPCoverageDisplay/components/Tooltip.d.ts +1 -1
- package/dist/LinearSNPCoverageDisplay/models/configSchema.d.ts +1 -1
- package/dist/LinearSNPCoverageDisplay/models/model.d.ts +2 -2
- package/dist/PileupRenderer/PileupRenderer.d.ts +20 -6
- package/dist/PileupRenderer/configSchema.d.ts +1 -1
- package/dist/SNPCoverageAdapter/SNPCoverageAdapter.d.ts +3 -11
- package/dist/SNPCoverageAdapter/configSchema.d.ts +1 -1
- package/dist/SNPCoverageRenderer/SNPCoverageRenderer.d.ts +1 -1
- package/dist/SNPCoverageRenderer/configSchema.d.ts +1 -1
- package/dist/SNPCoverageRenderer/index.d.ts +1 -1
- package/dist/plugin-alignments.cjs.development.js +795 -682
- 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 +797 -684
- package/dist/plugin-alignments.esm.js.map +1 -1
- package/dist/util.d.ts +4 -0
- package/package.json +4 -4
- package/src/AlignmentsFeatureDetail/AlignmentsFeatureDetail.tsx +23 -14
- package/src/BamAdapter/BamAdapter.ts +10 -7
- package/src/BamAdapter/BamSlightlyLazyFeature.ts +11 -75
- package/src/BamAdapter/MismatchParser.test.ts +53 -297
- package/src/BamAdapter/MismatchParser.ts +54 -116
- package/src/BamAdapter/configSchema.ts +0 -4
- package/src/CramAdapter/CramSlightlyLazyFeature.ts +3 -10
- package/src/LinearAlignmentsDisplay/components/AlignmentsDisplay.tsx +38 -30
- package/src/LinearAlignmentsDisplay/models/model.tsx +10 -9
- package/src/LinearPileupDisplay/components/ColorByModifications.tsx +76 -80
- package/src/LinearPileupDisplay/components/ColorByTag.tsx +24 -23
- package/src/LinearPileupDisplay/components/FilterByTag.tsx +73 -68
- package/src/LinearPileupDisplay/components/SetFeatureHeight.tsx +28 -26
- package/src/LinearPileupDisplay/components/SetMaxHeight.tsx +24 -13
- package/src/LinearPileupDisplay/components/SortByTag.tsx +29 -21
- package/src/LinearPileupDisplay/model.ts +12 -6
- package/src/LinearSNPCoverageDisplay/components/Tooltip.tsx +5 -3
- package/src/LinearSNPCoverageDisplay/models/configSchema.ts +4 -5
- package/src/PileupRenderer/PileupRenderer.tsx +202 -70
- package/src/PileupRenderer/components/PileupRendering.tsx +5 -3
- package/src/SNPCoverageAdapter/SNPCoverageAdapter.ts +192 -237
- package/src/SNPCoverageRenderer/SNPCoverageRenderer.ts +91 -60
- package/src/SNPCoverageRenderer/configSchema.js +1 -1
- package/src/util.ts +25 -0
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { createJBrowseTheme } from '@jbrowse/core/ui'
|
|
2
|
-
import { featureSpanPx } from '@jbrowse/core/util'
|
|
2
|
+
import { featureSpanPx, bpSpanPx } 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'
|
|
6
5
|
import { RenderArgsDeserialized as FeatureRenderArgsDeserialized } from '@jbrowse/core/pluggableElementTypes/renderers/FeatureRendererType'
|
|
7
6
|
import {
|
|
8
7
|
getOrigin,
|
|
@@ -24,7 +23,7 @@ export interface RenderArgsDeserializedWithFeatures
|
|
|
24
23
|
features: Map<string, Feature>
|
|
25
24
|
ticks: { values: number[] }
|
|
26
25
|
displayCrossHatches: boolean
|
|
27
|
-
modificationTagMap
|
|
26
|
+
modificationTagMap?: Record<string, string>
|
|
28
27
|
}
|
|
29
28
|
|
|
30
29
|
type Counts = {
|
|
@@ -49,12 +48,12 @@ export default class SNPCoverageRenderer extends WiggleBaseRenderer {
|
|
|
49
48
|
regions,
|
|
50
49
|
bpPerPx,
|
|
51
50
|
displayCrossHatches,
|
|
52
|
-
modificationTagMap,
|
|
51
|
+
modificationTagMap = {},
|
|
53
52
|
scaleOpts,
|
|
54
53
|
height: unadjustedHeight,
|
|
55
54
|
theme: configTheme,
|
|
56
55
|
config: cfg,
|
|
57
|
-
ticks
|
|
56
|
+
ticks,
|
|
58
57
|
} = props
|
|
59
58
|
const theme = createJBrowseTheme(configTheme)
|
|
60
59
|
const [region] = regions
|
|
@@ -66,11 +65,20 @@ export default class SNPCoverageRenderer extends WiggleBaseRenderer {
|
|
|
66
65
|
const offset = YSCALEBAR_LABEL_OFFSET
|
|
67
66
|
const height = unadjustedHeight - offset * 2
|
|
68
67
|
|
|
68
|
+
const { domain } = scaleOpts
|
|
69
|
+
if (!domain) {
|
|
70
|
+
return
|
|
71
|
+
}
|
|
69
72
|
const opts = { ...scaleOpts, range: [0, height] }
|
|
70
73
|
const viewScale = getScale(opts)
|
|
71
|
-
|
|
74
|
+
|
|
75
|
+
// clipping and insertion indicators, uses a smaller height/2 scale
|
|
76
|
+
const indicatorViewScale = getScale({
|
|
77
|
+
...opts,
|
|
78
|
+
range: [0, height / 2],
|
|
79
|
+
scaleType: 'linear',
|
|
80
|
+
})
|
|
72
81
|
const originY = getOrigin(scaleOpts.scaleType)
|
|
73
|
-
const snpOriginY = getOrigin('linear')
|
|
74
82
|
|
|
75
83
|
const indicatorThreshold = readConfObject(cfg, 'indicatorThreshold')
|
|
76
84
|
const drawInterbaseCounts = readConfObject(cfg, 'drawInterbaseCounts')
|
|
@@ -81,9 +89,10 @@ export default class SNPCoverageRenderer extends WiggleBaseRenderer {
|
|
|
81
89
|
const toY = (n: number) => height - (viewScale(n) || 0) + offset
|
|
82
90
|
const toHeight = (n: number) => toY(originY) - toY(n)
|
|
83
91
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
const
|
|
92
|
+
const indicatorToY = (n: number) =>
|
|
93
|
+
height - (indicatorViewScale(n) || 0) + offset
|
|
94
|
+
const indicatorToHeight = (n: number) =>
|
|
95
|
+
indicatorToY(getOrigin('linear')) - indicatorToY(n)
|
|
87
96
|
|
|
88
97
|
const colorForBase: { [key: string]: string } = {
|
|
89
98
|
A: theme.palette.bases.A.main,
|
|
@@ -106,91 +115,113 @@ export default class SNPCoverageRenderer extends WiggleBaseRenderer {
|
|
|
106
115
|
// Use two pass rendering, which helps in visualizing the SNPs at higher
|
|
107
116
|
// bpPerPx First pass: draw the gray background
|
|
108
117
|
ctx.fillStyle = colorForBase.total
|
|
109
|
-
coverage.
|
|
118
|
+
for (let i = 0; i < coverage.length; i++) {
|
|
119
|
+
const feature = coverage[i]
|
|
110
120
|
const [leftPx, rightPx] = featureSpanPx(feature, region, bpPerPx)
|
|
111
121
|
const w = rightPx - leftPx + 0.3
|
|
112
122
|
const score = feature.get('score') as number
|
|
113
123
|
ctx.fillRect(leftPx, toY(score), w, toHeight(score))
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Keep track of previous total which we will use it to draw the interbase
|
|
127
|
+
// indicator (if there is a sudden clip, there will be no read coverage but
|
|
128
|
+
// there will be "clip" coverage) at that position beyond the read. if the
|
|
129
|
+
// clip is right at a block boundary then prevTotal will not be available,
|
|
130
|
+
// so this is a best attempt to plot interbase indicator at the "cliffs"
|
|
131
|
+
let prevTotal = 0
|
|
132
|
+
|
|
133
|
+
// extraHorizontallyFlippedOffset is used to draw interbase items, which
|
|
134
|
+
// are located to the left when forward and right when reversed
|
|
135
|
+
const extraHorizontallyFlippedOffset = region.reversed ? 1 / bpPerPx : 0
|
|
120
136
|
|
|
121
137
|
// Second pass: draw the SNP data, and add a minimum feature width of 1px
|
|
122
138
|
// which can be wider than the actual bpPerPx This reduces overdrawing of
|
|
123
139
|
// the grey background over the SNPs
|
|
124
|
-
|
|
140
|
+
|
|
141
|
+
for (let i = 0; i < coverage.length; i++) {
|
|
142
|
+
const feature = coverage[i]
|
|
125
143
|
const [leftPx, rightPx] = featureSpanPx(feature, region, bpPerPx)
|
|
126
144
|
|
|
145
|
+
const score = feature.get('score') as number
|
|
127
146
|
const snpinfo = feature.get('snpinfo') as SNPInfo
|
|
128
147
|
const w = Math.max(rightPx - leftPx + 0.3, 1)
|
|
129
148
|
const totalScore = snpinfo.total
|
|
149
|
+
const keys = Object.keys(snpinfo.cov).sort()
|
|
130
150
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
+
let curr = 0
|
|
152
|
+
for (let i = 0; i < keys.length; i++) {
|
|
153
|
+
const base = keys[i]
|
|
154
|
+
const { total } = snpinfo.cov[base]
|
|
155
|
+
ctx.fillStyle =
|
|
156
|
+
colorForBase[base] ||
|
|
157
|
+
modificationTagMap[base.replace('mod_', '')] ||
|
|
158
|
+
'#888'
|
|
159
|
+
|
|
160
|
+
const height = toHeight(score)
|
|
161
|
+
const bottom = toY(score) + height
|
|
162
|
+
ctx.fillRect(
|
|
163
|
+
leftPx,
|
|
164
|
+
bottom - ((total + curr) / score) * height,
|
|
165
|
+
w,
|
|
166
|
+
(total / score) * height,
|
|
167
|
+
)
|
|
168
|
+
curr += total
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const interbaseEvents = Object.keys(snpinfo.noncov)
|
|
151
172
|
const indicatorHeight = 4.5
|
|
152
173
|
if (drawInterbaseCounts) {
|
|
153
|
-
|
|
174
|
+
let curr = 0
|
|
175
|
+
for (let i = 0; i < interbaseEvents.length; i++) {
|
|
176
|
+
const base = interbaseEvents[i]
|
|
177
|
+
const { total } = snpinfo.noncov[base]
|
|
154
178
|
ctx.fillStyle = colorForBase[base]
|
|
155
179
|
ctx.fillRect(
|
|
156
|
-
leftPx - 0.6,
|
|
157
|
-
indicatorHeight +
|
|
180
|
+
leftPx - 0.6 + extraHorizontallyFlippedOffset,
|
|
181
|
+
indicatorHeight + indicatorToHeight(curr),
|
|
158
182
|
1.2,
|
|
159
|
-
|
|
183
|
+
indicatorToHeight(total),
|
|
160
184
|
)
|
|
161
|
-
|
|
162
|
-
}
|
|
185
|
+
curr += total
|
|
186
|
+
}
|
|
163
187
|
}
|
|
164
188
|
|
|
165
189
|
if (drawIndicators) {
|
|
166
190
|
let accum = 0
|
|
167
191
|
let max = 0
|
|
168
192
|
let maxBase = ''
|
|
169
|
-
|
|
193
|
+
for (let i = 0; i < interbaseEvents.length; i++) {
|
|
194
|
+
const base = interbaseEvents[i]
|
|
195
|
+
const { total } = snpinfo.noncov[base]
|
|
170
196
|
accum += total
|
|
171
197
|
if (total > max) {
|
|
172
198
|
max = total
|
|
173
199
|
maxBase = base
|
|
174
200
|
}
|
|
175
|
-
}
|
|
201
|
+
}
|
|
176
202
|
|
|
177
203
|
// avoid drawing a bunch of indicators if coverage is very low e.g.
|
|
178
|
-
// less than 7
|
|
179
|
-
|
|
204
|
+
// less than 7, uses the prev total in the case of the "cliff"
|
|
205
|
+
const indicatorComparatorScore = Math.max(totalScore, prevTotal)
|
|
206
|
+
if (
|
|
207
|
+
accum > indicatorComparatorScore * indicatorThreshold &&
|
|
208
|
+
indicatorComparatorScore > 7
|
|
209
|
+
) {
|
|
180
210
|
ctx.fillStyle = colorForBase[maxBase]
|
|
181
211
|
ctx.beginPath()
|
|
182
|
-
|
|
183
|
-
ctx.
|
|
184
|
-
ctx.lineTo(
|
|
212
|
+
const l = leftPx + extraHorizontallyFlippedOffset
|
|
213
|
+
ctx.moveTo(l - 3.5, 0)
|
|
214
|
+
ctx.lineTo(l + 3.5, 0)
|
|
215
|
+
ctx.lineTo(l, indicatorHeight)
|
|
185
216
|
ctx.fill()
|
|
186
217
|
}
|
|
187
218
|
}
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
ctx.globalAlpha = 0.7
|
|
219
|
+
prevTotal = totalScore
|
|
220
|
+
}
|
|
191
221
|
|
|
192
222
|
if (drawArcs) {
|
|
193
|
-
skips.
|
|
223
|
+
for (let i = 0; i < skips.length; i++) {
|
|
224
|
+
const f = skips[i]
|
|
194
225
|
const [left, right] = bpSpanPx(
|
|
195
226
|
f.get('start'),
|
|
196
227
|
f.get('end'),
|
|
@@ -201,9 +232,9 @@ export default class SNPCoverageRenderer extends WiggleBaseRenderer {
|
|
|
201
232
|
ctx.beginPath()
|
|
202
233
|
const str = f.get('strand') as number
|
|
203
234
|
const xs = f.get('xs') as string
|
|
204
|
-
const pos = '
|
|
205
|
-
const neg = '
|
|
206
|
-
const neutral = '
|
|
235
|
+
const pos = 'rgba(255,200,200,0.7)'
|
|
236
|
+
const neg = 'rgba(200,200,255,0.7)'
|
|
237
|
+
const neutral = 'rgba(200,200,200,0.7)'
|
|
207
238
|
|
|
208
239
|
if (xs === '+') {
|
|
209
240
|
ctx.strokeStyle = pos
|
|
@@ -221,13 +252,13 @@ export default class SNPCoverageRenderer extends WiggleBaseRenderer {
|
|
|
221
252
|
ctx.moveTo(left, height - offset * 2)
|
|
222
253
|
ctx.bezierCurveTo(left, 0, right, 0, right, height - offset * 2)
|
|
223
254
|
ctx.stroke()
|
|
224
|
-
}
|
|
255
|
+
}
|
|
225
256
|
}
|
|
226
257
|
|
|
227
258
|
if (displayCrossHatches) {
|
|
228
259
|
ctx.lineWidth = 1
|
|
229
260
|
ctx.strokeStyle = 'rgba(140,140,140,0.8)'
|
|
230
|
-
values.forEach(tick => {
|
|
261
|
+
ticks.values.forEach(tick => {
|
|
231
262
|
ctx.beginPath()
|
|
232
263
|
ctx.moveTo(0, Math.round(toY(tick)))
|
|
233
264
|
ctx.lineTo(width, Math.round(toY(tick)))
|
package/src/util.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
+
import { BaseFeatureDataAdapter } from '@jbrowse/core/data_adapters/BaseAdapter'
|
|
2
|
+
import { toArray } from 'rxjs/operators'
|
|
1
3
|
import { Feature } from '@jbrowse/core/util/simpleFeature'
|
|
4
|
+
import { AugmentedRegion } from '@jbrowse/core/util'
|
|
2
5
|
// get tag from BAM or CRAM feature, where CRAM uses feature.get('tags') and
|
|
3
6
|
// BAM does not
|
|
4
7
|
export function getTag(feature: Feature, tag: string) {
|
|
@@ -76,3 +79,25 @@ export function getColorWGBS(strand: number, base: string) {
|
|
|
76
79
|
}
|
|
77
80
|
return '#888'
|
|
78
81
|
}
|
|
82
|
+
|
|
83
|
+
export async function fetchSequence(
|
|
84
|
+
region: AugmentedRegion,
|
|
85
|
+
adapter: BaseFeatureDataAdapter,
|
|
86
|
+
) {
|
|
87
|
+
const { end, originalRefName, refName } = region
|
|
88
|
+
|
|
89
|
+
const feats = await adapter
|
|
90
|
+
.getFeatures({
|
|
91
|
+
...region,
|
|
92
|
+
refName: originalRefName || refName,
|
|
93
|
+
end: end + 1,
|
|
94
|
+
})
|
|
95
|
+
.pipe(toArray())
|
|
96
|
+
.toPromise()
|
|
97
|
+
return feats[0]?.get('seq')
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// has to check underlying C-G (aka CpG) on the reference sequence
|
|
101
|
+
export function shouldFetchReferenceSequence(type?: string) {
|
|
102
|
+
return type === 'methylation'
|
|
103
|
+
}
|