Skip to content

Commit

Permalink
Phase set handling
Browse files Browse the repository at this point in the history
  • Loading branch information
cmdcolin committed Jan 29, 2025
1 parent 06c5f9f commit 66e21be
Show file tree
Hide file tree
Showing 9 changed files with 103 additions and 62 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ const LinesConnectingMatrixToGenomicPosition = observer(function ({
}) {
const { assemblyManager } = getSession(model)
const view = getContainingView(model) as LinearGenomeViewModel
const { featuresVolatile } = model
const { lineZoneHeight, featuresVolatile } = model
const { offsetPx, assemblyNames, dynamicBlocks } = view
const assembly = assemblyManager.get(assemblyNames[0]!)
const b0 = dynamicBlocks.contentBlocks[0]?.widthPx || 0
Expand All @@ -60,11 +60,11 @@ const LinesConnectingMatrixToGenomicPosition = observer(function ({
})?.offsetPx || 0) - l
return (
<line
stroke="#0006"
stroke="#0004"
key={f.id()}
x1={i * w + w / 2}
x2={c}
y1={20}
y1={lineZoneHeight}
y2={0}
/>
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
getColorAlleleCount,
getColorPhased,
getColorPhasedWithPhaseSet,
} from '../shared/multiVariantColor'
import { getFeaturesThatPassMinorAlleleFrequencyFilter } from '../util'

Expand Down Expand Up @@ -29,8 +30,11 @@ function drawPhased(
w: number,
h: number,
HP: number,
PS?: string,
) {
ctx.fillStyle = getColorPhased(alleles, HP)
ctx.fillStyle = PS
? getColorPhasedWithPhaseSet(alleles, HP, PS)
: getColorPhased(alleles, HP)
ctx.fillRect(x - f2, y - f2, w + f2, h + f2)
}

Expand Down Expand Up @@ -65,30 +69,62 @@ export function makeImageData({
const m = mafs.length
const w = canvasWidth / m
for (let i = 0; i < m; i++) {
const f = mafs[i]!
const samp = f.get('genotypes') as Record<string, string>

const x = (i / mafs.length) * canvasWidth
const s = sources.length
const arr2 = [] as string[]
for (let j = 0; j < s; j++) {
const y = (j / s) * canvasHeight
const { name, HP } = sources[j]!
const genotype = samp[name]
if (genotype) {
arr2.push(genotype)
const isPhased = genotype.includes('|')
if (renderingMode === 'phased') {
if (isPhased) {
const alleles = genotype.split('|')
drawPhased(alleles, ctx, x, y, w, h, HP!)
const f = mafs[i]!
const hasPhaseSet = (f.get('format') as string).includes('PS')
if (hasPhaseSet) {
const samp = f.get('samples') as Record<string, Record<string, string[]>>
const x = (i / mafs.length) * canvasWidth
const sln = sources.length
for (let j = 0; j < sln; j++) {
const y = (j / sln) * canvasHeight
const { name, HP } = sources[j]!
const s = samp[name]
if (s) {
const genotype = s.GT?.[0]
if (genotype) {
arr2.push(genotype)
const isPhased = genotype.includes('|')
if (renderingMode === 'phased') {
if (isPhased) {
const PS = s.PS?.[0]
const alleles = genotype.split('|')
drawPhased(alleles, ctx, x, y, w, h, HP!, PS)
} else {
ctx.fillStyle = 'black'
ctx.fillRect(x - f2, y - f2, w + f2, h + f2)
}
} else {
const alleles = genotype.split(/[/|]/)
drawColorAlleleCount(alleles, ctx, x, y, w, h)
}
}
}
}
} else {
const samp = f.get('genotypes') as Record<string, string>
const x = (i / mafs.length) * canvasWidth
const sln = sources.length
const arr2 = [] as string[]
for (let j = 0; j < sln; j++) {
const y = (j / sln) * canvasHeight
const { name, HP } = sources[j]!
const genotype = samp[name]
if (genotype) {
arr2.push(genotype)
const isPhased = genotype.includes('|')
if (renderingMode === 'phased') {
if (isPhased) {
const alleles = genotype.split('|')
drawPhased(alleles, ctx, x, y, w, h, HP!)
} else {
ctx.fillStyle = 'black'
ctx.fillRect(x - f2, y - f2, w + f2, h + f2)
}
} else {
ctx.fillStyle = 'black'
ctx.fillRect(x - f2, y - f2, w + f2, h + f2)
const alleles = genotype.split(/[/|]/)
drawColorAlleleCount(alleles, ctx, x, y, w, h)
}
} else {
const alleles = genotype.split(/[/|]/)
drawColorAlleleCount(alleles, ctx, x, y, w, h)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ exports[`adapter can fetch variants from volvox.vcf 2`] = `
],
"CHROM": "ctgA",
"FILTER": undefined,
"FORMAT": "GT:PL:GQ",
"ID": undefined,
"INFO": {
"AC1": [
Expand Down Expand Up @@ -75,7 +74,6 @@ exports[`adapter can fetch variants from volvox.vcf 2`] = `
],
"CHROM": "ctgA",
"FILTER": undefined,
"FORMAT": "GT:PL:GQ",
"ID": undefined,
"INFO": {
"AC1": [
Expand Down Expand Up @@ -142,7 +140,6 @@ exports[`adapter can fetch variants from volvox.vcf 2`] = `
],
"CHROM": "ctgA",
"FILTER": undefined,
"FORMAT": "GT:PL:GQ",
"ID": undefined,
"INFO": {
"AC1": [
Expand Down Expand Up @@ -209,7 +206,6 @@ exports[`adapter can fetch variants from volvox.vcf 2`] = `
],
"CHROM": "ctgA",
"FILTER": undefined,
"FORMAT": "GT:PL:GQ",
"ID": undefined,
"INFO": {
"AC1": [
Expand Down Expand Up @@ -270,7 +266,6 @@ exports[`adapter can fetch variants from volvox.vcf 2`] = `
],
"CHROM": "ctgA",
"FILTER": undefined,
"FORMAT": "GT:PL:GQ",
"ID": undefined,
"INFO": {
"AC1": [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ exports[`null ALT 1`] = `
"ALT": undefined,
"CHROM": "chr1",
"FILTER": "PASS",
"FORMAT": undefined,
"ID": [
"rs123",
],
Expand Down
3 changes: 2 additions & 1 deletion plugins/variants/src/VcfFeature/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import type { Feature } from '@jbrowse/core/util'
type FeatureData = ReturnType<typeof dataFromVariant>

function dataFromVariant(variant: Variant, parser: VCFParser) {
const { REF = '', ALT, POS, CHROM, ID } = variant
const { FORMAT, REF = '', ALT, POS, CHROM, ID } = variant
const start = POS - 1
const [type, description] = getSOTermAndDescription(REF, ALT, parser)

Expand All @@ -19,6 +19,7 @@ function dataFromVariant(variant: Variant, parser: VCFParser) {
type,
name: ID?.join(','),
aliases: ID && ID.length > 1 ? ID.slice(1) : undefined,
format: FORMAT,
}
}
function getEnd(variant: Variant) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ exports[`adapter can fetch variants from volvox.vcf.gz 2`] = `
],
"CHROM": "ctgA",
"FILTER": undefined,
"FORMAT": "GT:PL:GQ",
"ID": undefined,
"INFO": {
"AC1": [
Expand Down Expand Up @@ -75,7 +74,6 @@ exports[`adapter can fetch variants from volvox.vcf.gz 2`] = `
],
"CHROM": "ctgA",
"FILTER": undefined,
"FORMAT": "GT:PL:GQ",
"ID": undefined,
"INFO": {
"AC1": [
Expand Down Expand Up @@ -142,7 +140,6 @@ exports[`adapter can fetch variants from volvox.vcf.gz 2`] = `
],
"CHROM": "ctgA",
"FILTER": undefined,
"FORMAT": "GT:PL:GQ",
"ID": undefined,
"INFO": {
"AC1": [
Expand Down Expand Up @@ -209,7 +206,6 @@ exports[`adapter can fetch variants from volvox.vcf.gz 2`] = `
],
"CHROM": "ctgA",
"FILTER": undefined,
"FORMAT": "GT:PL:GQ",
"ID": undefined,
"INFO": {
"AC1": [
Expand Down Expand Up @@ -270,7 +266,6 @@ exports[`adapter can fetch variants from volvox.vcf.gz 2`] = `
],
"CHROM": "ctgA",
"FILTER": undefined,
"FORMAT": "GT:PL:GQ",
"ID": undefined,
"INFO": {
"AC1": [
Expand Down
47 changes: 24 additions & 23 deletions plugins/variants/src/shared/MultiVariantBaseModel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { stopStopToken } from '@jbrowse/core/util/stopToken'
import { linearBareDisplayStateModelFactory } from '@jbrowse/plugin-linear-genome-view'
import FilterListIcon from '@mui/icons-material/FilterList'
import HeightIcon from '@mui/icons-material/Height'
import PaletteIcon from '@mui/icons-material/Palette'
import SplitscreenIcon from '@mui/icons-material/Splitscreen'
import VisibilityIcon from '@mui/icons-material/Visibility'
import deepEqual from 'fast-deep-equal'
import { types } from 'mobx-state-tree'
Expand Down Expand Up @@ -314,29 +314,30 @@ export default function MultiVariantBaseModelF(
],
},
{
label: 'Color by',
icon: PaletteIcon,
label: 'Rendering mode',
icon: SplitscreenIcon,
subMenu: [
...(self.hasPhased
? [
{
label: 'Allele count',
type: 'radio',
checked: self.renderingMode === 'alleleCount',
onClick: () => {
self.setPhasedMode('alleleCount')
},
},
{
label: 'Phased',
checked: self.renderingMode === 'phased',
type: 'radio',
onClick: () => {
self.setPhasedMode('phased')
},
},
]
: []),
{
label: 'Allele count',
type: 'radio',
checked: self.renderingMode === 'alleleCount',
onClick: () => {
self.setPhasedMode('alleleCount')
},
},
{
label:
'Phased' +
(self.hasPhased
? ' (disabled, no phased variants found)'
: ''),
disabled: self.hasPhased,
checked: self.renderingMode === 'phased',
type: 'radio',
onClick: () => {
self.setPhasedMode('phased')
},
},
],
},
{
Expand Down
11 changes: 11 additions & 0 deletions plugins/variants/src/shared/multiVariantColor.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { set1 } from '@jbrowse/core/ui/colors'
import { colord } from '@jbrowse/core/util/colord'

import { colorify } from '../util'

export function getColorAlleleCount(alleles: string[]) {
const total = alleles.length
let alt = 0
Expand Down Expand Up @@ -39,3 +41,12 @@ export function getColorPhased(alleles: string[], HP: number) {
const c = +alleles[HP]!
return c ? set1[c - 1] || 'black' : '#ccc'
}

export function getColorPhasedWithPhaseSet(
alleles: string[],
HP: number,
PS: string,
) {
const c = +alleles[HP]!
return c ? colorify(+PS) || 'black' : '#ccc'
}
7 changes: 5 additions & 2 deletions plugins/variants/src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,12 @@ export function randomColor(str: string) {
for (let i = 0; i < str.length; i++) {
sum += str.charCodeAt(i)
}
return `hsl(${sum * 10}, 50%, 50%)`
return `hsl(${colorify(sum * 10)}, 50%, 50%)`
}

export function colorify(n: number) {
return `hsl(${n % 255}, 50%, 50%)`
}
// used for calculating minor allele
export function findSecondLargest(arr: Iterable<number>) {
let firstMax = 0
Expand Down Expand Up @@ -91,7 +94,7 @@ export function getFeaturesThatPassMinorAlleleFrequencyFilter(
) {
const mafs = [] as Feature[]
for (const feat of feats) {
if (calculateMinorAlleleFrequency(feat) > minorAlleleFrequencyFilter) {
if (calculateMinorAlleleFrequency(feat) >= minorAlleleFrequencyFilter) {
mafs.push(feat)
}
}
Expand Down

0 comments on commit 66e21be

Please sign in to comment.