Skip to content

Commit 11563e3

Browse files
authored
Calculate most frequent non-ref allele for multi-variant renderer (#4826)
* Intermediate * Small types * Misc * Move files around * Misc * wow * Mov * Async * Most frequent alt
1 parent ec30a72 commit 11563e3

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+962
-887
lines changed

plugins/hic/src/HicRenderer/HicRenderer.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ export interface RenderArgsDeserialized
4242
export interface RenderArgsDeserializedWithFeatures
4343
extends RenderArgsDeserialized {
4444
features: HicFeature[]
45+
statusCallback?: (arg: string) => void
4546
}
4647

4748
export type ResultsSerialized = ServerSideResultsSerialized
@@ -95,10 +96,9 @@ export default class HicRenderer extends ServerSideRendererType {
9596
.getFeatures(regions[0]!, args)
9697
.pipe(toArray()),
9798
)
98-
// cast to any to avoid return-type conflict, because the
99-
// types of features returned by our getFeatures are quite
100-
// different from the base interface
10199

100+
// cast to any to avoid return-type conflict, because the types of features
101+
// returned by our getFeatures are quite different from the base interface
102102
return features as any
103103
}
104104
}

plugins/hic/src/HicRenderer/makeImageData.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ export async function makeImageData(
4343
} = props
4444

4545
const { statusCallback = () => {} } = props
46-
// @ts-expect-error
4746
statusCallback('Drawing Hi-C matrix')
4847
const region = regions[0]!
4948
const { dataAdapter } = await getAdapter(

plugins/variants/src/MultiLinearVariantDisplay/components/Crosshair.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { getContainingView } from '@jbrowse/core/util'
22
import { observer } from 'mobx-react'
33
import { makeStyles } from 'tss-react/mui'
44

5-
import MultiVariantTooltip from '../../shared/MultiVariantTooltip'
5+
import MultiVariantTooltip from '../../shared/components/MultiVariantTooltip'
66

77
import type { MultiLinearVariantDisplayModel } from '../model'
88
import type { LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view'

plugins/variants/src/MultiLinearVariantDisplay/components/VariantDisplayComponent.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { BaseLinearDisplayComponent } from '@jbrowse/plugin-linear-genome-view'
44
import { observer } from 'mobx-react'
55

66
import Crosshair from './Crosshair'
7-
import LegendBar from '../../shared/LegendBar'
7+
import LegendBar from '../../shared/components/LegendBar'
88

99
import type { MultiLinearVariantDisplayModel } from '../model'
1010

plugins/variants/src/MultiLinearVariantDisplay/renderSvg.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { getContainingView } from '@jbrowse/core/util'
22
import { when } from 'mobx'
33

44
// locals
5-
import LegendBar from '../shared/LegendBar'
5+
import LegendBar from '../shared/components/LegendBar'
66

77
import type { MultiLinearVariantDisplayModel } from './model'
88
import type {

plugins/variants/src/MultiLinearVariantMatrixDisplay/components/Crosshair.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { getContainingView } from '@jbrowse/core/util'
22
import { observer } from 'mobx-react'
33
import { makeStyles } from 'tss-react/mui'
44

5-
import MultiVariantTooltip from '../../shared/MultiVariantTooltip'
5+
import MultiVariantTooltip from '../../shared/components/MultiVariantTooltip'
66

77
import type { MultiLinearVariantMatrixDisplayModel } from '../model'
88
import type { LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view'

plugins/variants/src/MultiLinearVariantMatrixDisplay/components/VariantDisplayComponent.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { observer } from 'mobx-react'
55

66
import Crosshair from './Crosshair'
77
import LinesConnectingMatrixToGenomicPosition from './LinesConnectingMatrixToGenomicPosition'
8-
import LegendBar from '../../shared/LegendBar'
8+
import LegendBar from '../../shared/components/LegendBar'
99

1010
import type { MultiLinearVariantMatrixDisplayModel } from '../model'
1111

plugins/variants/src/MultiLinearVariantMatrixDisplay/renderSvg.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
import { getContainingView } from '@jbrowse/core/util'
22
import { when } from 'mobx'
33

4-
// locals
5-
import LegendBar from '../shared/LegendBar'
64
import LinesConnectingMatrixToGenomicPosition from './components/LinesConnectingMatrixToGenomicPosition'
5+
import LegendBar from '../shared/components/LegendBar'
76

87
import type { MultiLinearVariantMatrixDisplayModel } from './model'
98
import type {

plugins/variants/src/MultiLinearVariantMatrixRenderer/LinearVariantMatrixRenderer.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,13 @@ export default class LinearVariantMatrixRenderer extends BoxRendererType {
4545
...res,
4646
features: new Map(),
4747
simplifiedFeatures: mafs.map(
48-
(s: Feature) =>
48+
({ feature }: { feature: Feature }) =>
4949
new SimpleFeature({
50-
id: s.id(),
50+
id: feature.id(),
5151
data: {
52-
start: s.get('start'),
53-
end: s.get('end'),
54-
refName: s.get('refName'),
52+
start: feature.get('start'),
53+
end: feature.get('end'),
54+
refName: feature.get('refName'),
5555
},
5656
}),
5757
),

plugins/variants/src/MultiLinearVariantMatrixRenderer/makeImageData.ts

Lines changed: 55 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,15 @@
1-
import {
2-
getColorAlleleCount,
3-
getColorPhased,
4-
getColorPhasedWithPhaseSet,
5-
} from '../shared/multiVariantColor'
6-
import { getFeaturesThatPassMinorAlleleFrequencyFilter } from '../util'
1+
import { updateStatus } from '@jbrowse/core/util'
72

8-
import type { RenderArgsDeserializedWithFeaturesAndLayout } from './types'
9-
10-
const fudgeFactor = 0.6
11-
const f2 = fudgeFactor / 2
3+
import { f2 } from '../shared/constants'
4+
import { drawColorAlleleCount } from '../shared/drawAlleleCount'
5+
import { drawPhased } from '../shared/drawPhased'
6+
import { getFeaturesThatPassMinorAlleleFrequencyFilter } from '../shared/minorAlleleFrequencyUtils'
127

13-
function drawColorAlleleCount(
14-
alleles: string[],
15-
ctx: CanvasRenderingContext2D,
16-
x: number,
17-
y: number,
18-
w: number,
19-
h: number,
20-
) {
21-
ctx.fillStyle = getColorAlleleCount(alleles)
22-
ctx.fillRect(x - f2, y - f2, w + f2, h + f2)
23-
}
8+
import type { RenderArgsDeserializedWithFeaturesAndLayout } from './types'
249

25-
function drawPhased(
26-
alleles: string[],
27-
ctx: CanvasRenderingContext2D,
28-
x: number,
29-
y: number,
30-
w: number,
31-
h: number,
32-
HP: number,
33-
PS?: string,
34-
) {
35-
ctx.fillStyle =
36-
PS !== undefined
37-
? getColorPhasedWithPhaseSet(alleles, HP, PS)
38-
: getColorPhased(alleles, HP)
39-
ctx.fillRect(x - f2, y - f2, w + f2, h + f2)
40-
}
10+
type SampleGenotype = Record<string, string[]>
4111

42-
export function makeImageData({
12+
export async function makeImageData({
4313
ctx,
4414
canvasWidth,
4515
canvasHeight,
@@ -58,78 +28,78 @@ export function makeImageData({
5828
} = renderArgs
5929

6030
const { statusCallback = () => {} } = renderArgs
61-
// @ts-expect-error
62-
statusCallback('Drawing variant matrix')
6331
const h = canvasHeight / sources.length
6432
const mafs = getFeaturesThatPassMinorAlleleFrequencyFilter(
6533
features.values(),
6634
minorAlleleFrequencyFilter,
6735
)
68-
6936
const arr = [] as string[][]
7037
const m = mafs.length
7138
const w = canvasWidth / m
72-
for (let i = 0; i < m; i++) {
73-
const arr2 = [] as string[]
74-
const f = mafs[i]!
75-
const hasPhaseSet = (f.get('format') as string).includes('PS')
76-
if (hasPhaseSet) {
77-
const samp = f.get('samples') as Record<string, Record<string, string[]>>
78-
const x = (i / mafs.length) * canvasWidth
79-
const sln = sources.length
80-
for (let j = 0; j < sln; j++) {
81-
const y = (j / sln) * canvasHeight
82-
const { name, HP } = sources[j]!
83-
const s = samp[name]
84-
if (s) {
85-
const genotype = s.GT?.[0]
39+
40+
await updateStatus('Drawing variant matrix', statusCallback, () => {
41+
for (let i = 0; i < m; i++) {
42+
const arr2 = [] as string[]
43+
const { feature, mostFrequentAlt } = mafs[i]!
44+
const hasPhaseSet = (feature.get('format') as string).includes('PS')
45+
if (hasPhaseSet) {
46+
const samp = feature.get('samples') as Record<string, SampleGenotype>
47+
const x = (i / mafs.length) * canvasWidth
48+
const sln = sources.length
49+
for (let j = 0; j < sln; j++) {
50+
const y = (j / sln) * canvasHeight
51+
const { name, HP } = sources[j]!
52+
const s = samp[name]
53+
if (s) {
54+
const genotype = s.GT?.[0]
55+
if (genotype) {
56+
arr2.push(genotype)
57+
const isPhased = genotype.includes('|')
58+
if (renderingMode === 'phased') {
59+
if (isPhased) {
60+
const PS = s.PS?.[0]
61+
const alleles = genotype.split('|')
62+
drawPhased(alleles, ctx, x, y, w, h, HP!, PS)
63+
} else {
64+
ctx.fillStyle = 'black'
65+
ctx.fillRect(x - f2, y - f2, w + f2, h + f2)
66+
}
67+
} else {
68+
const alleles = genotype.split(/[/|]/)
69+
drawColorAlleleCount(alleles, ctx, x, y, w, h, mostFrequentAlt)
70+
}
71+
}
72+
}
73+
}
74+
} else {
75+
const samp = feature.get('genotypes') as Record<string, string>
76+
const x = (i / mafs.length) * canvasWidth
77+
const sln = sources.length
78+
for (let j = 0; j < sln; j++) {
79+
const y = (j / sln) * canvasHeight
80+
const { name, HP } = sources[j]!
81+
const genotype = samp[name]
8682
if (genotype) {
8783
arr2.push(genotype)
8884
const isPhased = genotype.includes('|')
8985
if (renderingMode === 'phased') {
9086
if (isPhased) {
91-
const PS = s.PS?.[0]
9287
const alleles = genotype.split('|')
93-
drawPhased(alleles, ctx, x, y, w, h, HP!, PS)
88+
drawPhased(alleles, ctx, x, y, w, h, HP!)
9489
} else {
9590
ctx.fillStyle = 'black'
9691
ctx.fillRect(x - f2, y - f2, w + f2, h + f2)
9792
}
9893
} else {
9994
const alleles = genotype.split(/[/|]/)
100-
drawColorAlleleCount(alleles, ctx, x, y, w, h)
95+
drawColorAlleleCount(alleles, ctx, x, y, w, h, mostFrequentAlt)
10196
}
10297
}
10398
}
10499
}
105-
} else {
106-
const samp = f.get('genotypes') as Record<string, string>
107-
const x = (i / mafs.length) * canvasWidth
108-
const sln = sources.length
109-
for (let j = 0; j < sln; j++) {
110-
const y = (j / sln) * canvasHeight
111-
const { name, HP } = sources[j]!
112-
const genotype = samp[name]
113-
if (genotype) {
114-
arr2.push(genotype)
115-
const isPhased = genotype.includes('|')
116-
if (renderingMode === 'phased') {
117-
if (isPhased) {
118-
const alleles = genotype.split('|')
119-
drawPhased(alleles, ctx, x, y, w, h, HP!)
120-
} else {
121-
ctx.fillStyle = 'black'
122-
ctx.fillRect(x - f2, y - f2, w + f2, h + f2)
123-
}
124-
} else {
125-
const alleles = genotype.split(/[/|]/)
126-
drawColorAlleleCount(alleles, ctx, x, y, w, h)
127-
}
128-
}
129-
}
100+
arr.push(arr2)
130101
}
131-
arr.push(arr2)
132-
}
102+
})
133103
return {
134104
mafs,
135105
arr,

plugins/variants/src/MultiLinearVariantMatrixRenderer/types.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { Source } from '../types'
1+
import type { Source } from '../shared/types'
22
import type { RenderArgsDeserialized as BoxRenderArgsDeserialized } from '@jbrowse/core/pluggableElementTypes/renderers/BoxRendererType'
33
import type { Feature } from '@jbrowse/core/util'
44

@@ -15,4 +15,5 @@ export interface RenderArgsDeserializedWithFeaturesAndLayout
1515
sources: Source[]
1616
features: Map<string, Feature>
1717
renderingMode: string
18+
statusCallback?: (arg: string) => void
1819
}

plugins/variants/src/MultiLinearVariantRenderer/MultiVariantRendering.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { PrerenderedCanvas } from '@jbrowse/core/ui'
44
import { observer } from 'mobx-react'
55
import RBush from 'rbush'
66

7-
import type { Source } from '../types'
7+
import type { Source } from '../shared/types'
88
import type { Feature } from '@jbrowse/core/util'
99
import type { Region } from '@jbrowse/core/util/types'
1010

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import { useMemo, useRef } from 'react'
2+
3+
import { PrerenderedCanvas } from '@jbrowse/core/ui'
4+
import { observer } from 'mobx-react'
5+
import RBush from 'rbush'
6+
7+
import type { Source } from '../../shared/types'
8+
import type { Feature } from '@jbrowse/core/util'
9+
import type { Region } from '@jbrowse/core/util/types'
10+
11+
const MultiVariantRendering = observer(function (props: {
12+
regions: Region[]
13+
features: Map<string, Feature>
14+
bpPerPx: number
15+
width: number
16+
height: number
17+
sources: Source[]
18+
scrollTop: number
19+
totalHeight: number
20+
rbush: RBush<{ genotype: string }>
21+
displayModel: any
22+
onMouseLeave?: (event: React.MouseEvent) => void
23+
onMouseMove?: (event: React.MouseEvent, arg?: Feature) => void
24+
onFeatureClick?: (event: React.MouseEvent, arg?: Feature) => void
25+
}) {
26+
const { totalHeight, scrollTop } = props
27+
const { rbush, displayModel } = props
28+
const ref = useRef<HTMLDivElement>(null)
29+
const rbush2 = useMemo(
30+
() => new RBush<{ genotype: string }>().fromJSON(rbush),
31+
[rbush],
32+
)
33+
34+
function getFeatureUnderMouse(eventClientX: number, eventClientY: number) {
35+
let offsetX = 0
36+
let offsetY = 0
37+
if (ref.current) {
38+
const r = ref.current.getBoundingClientRect()
39+
offsetX = eventClientX - r.left
40+
offsetY = eventClientY - r.top
41+
}
42+
const ret = rbush2.search({
43+
minX: offsetX,
44+
maxX: offsetX + 3,
45+
minY: offsetY,
46+
maxY: offsetY + 3,
47+
})
48+
return ret[0]?.genotype
49+
}
50+
51+
return (
52+
<div
53+
ref={ref}
54+
onMouseMove={e =>
55+
displayModel.setHoveredGenotype?.(
56+
getFeatureUnderMouse(e.clientX, e.clientY),
57+
)
58+
}
59+
onMouseLeave={() => {
60+
displayModel.setHoveredGenotype?.(undefined)
61+
}}
62+
onMouseOut={() => {
63+
displayModel.setHoveredGenotype?.(undefined)
64+
}}
65+
style={{
66+
overflow: 'visible',
67+
position: 'relative',
68+
height: totalHeight,
69+
}}
70+
>
71+
<PrerenderedCanvas
72+
{...props}
73+
style={{
74+
position: 'absolute',
75+
left: 0,
76+
top: scrollTop,
77+
}}
78+
/>
79+
</div>
80+
)
81+
})
82+
83+
export default MultiVariantRendering

plugins/variants/src/MultiLinearVariantRenderer/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import MultiVariantRenderer from './MultiVariantRenderer'
2-
import ReactComponent from './MultiVariantRendering'
2+
import ReactComponent from './components/MultiVariantRendering'
33
import configSchema from './configSchema'
44

55
import type PluginManager from '@jbrowse/core/PluginManager'

0 commit comments

Comments
 (0)