Skip to content

Commit

Permalink
Add constraint metrics table for mitochondrial genes
Browse files Browse the repository at this point in the history
  • Loading branch information
phildarnowsky-broad committed May 7, 2024
1 parent 99c951f commit ed33d6b
Show file tree
Hide file tree
Showing 5 changed files with 2,334 additions and 137 deletions.
72 changes: 70 additions & 2 deletions browser/src/ConstraintTable/ConstraintTable.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ import { BrowserRouter } from 'react-router-dom'
import ConstraintTable from './ConstraintTable'
import { ExacConstraint } from './ExacConstraintTable'
import { GnomadConstraint } from './GnomadConstraintTable'
import {
ProteinMitochondrialGeneConstraint,
RNAMitochondrialGeneConstraint,
} from '../GenePage/GenePage'

const exacConstraintFactory = Factory.define<ExacConstraint>(() => ({
exp_lof: 0.123,
Expand Down Expand Up @@ -42,6 +46,34 @@ const gnomadConstraintFactory = Factory.define<GnomadConstraint>(() => ({
oe_syn_upper: 0.95,
}))

const proteinMitochondrialConstraintFactory = Factory.define<ProteinMitochondrialGeneConstraint>(
() => ({
exp_lof: 0.123,
exp_syn: 0.234,
exp_mis: 0.345,
oe_lof: 0.789,
oe_lof_lower: 0.6,
oe_lof_upper: 0.9,
oe_mis: 0.891,
oe_mis_lower: 0.8,
oe_mis_upper: 0.99,
oe_syn: 0.912,
oe_syn_lower: 0.8,
oe_syn_upper: 0.95,
obs_lof: 0.111,
obs_syn: 0.222,
obs_mis: 0.333,
})
)

const rnaMitochondrialConstraintFactory = Factory.define<RNAMitochondrialGeneConstraint>(() => ({
observed: 0.11,
expected: 0.22,
oe: 0.33,
oe_lower: 0.31,
oe_upper: 0.35,
}))

forAllDatasets('ConstraintTable with "%s" dataset selected', (datasetId) => {
describe('with a minimal gene', () => {
test('has no unexpected changes', () => {
Expand All @@ -65,20 +97,56 @@ forAllDatasets('ConstraintTable with "%s" dataset selected', (datasetId) => {
})
})

describe('with a mitochondrial gene', () => {
describe('with a mitochondrial protein gene', () => {
test('has no unexpected changes', () => {
const constraint = proteinMitochondrialConstraintFactory.build()
const tree = renderer.create(
<BrowserRouter>
<ConstraintTable
datasetId={datasetId}
geneOrTranscript={geneFactory.build({
chrom: 'M',
mitochondrial_constraint: constraint,
})}
/>
</BrowserRouter>
)
expect(tree).toMatchSnapshot()
})
})

describe('with a mitochondrial RNA gene', () => {
test('has no unexpected changes', () => {
const constraint = rnaMitochondrialConstraintFactory.build()
const tree = renderer.create(
<BrowserRouter>
<ConstraintTable
datasetId={datasetId}
geneOrTranscript={geneFactory.build({ chrom: 'M' })}
geneOrTranscript={geneFactory.build({
chrom: 'M',
mitochondrial_constraint: constraint,
})}
/>
</BrowserRouter>
)
expect(tree).toMatchSnapshot()
})
})

describe('with a mitochondrial gene missing constraint data', () => {
const tree = renderer.create(
<BrowserRouter>
<ConstraintTable
datasetId={datasetId}
geneOrTranscript={geneFactory.build({
chrom: 'M',
})}
/>
</BrowserRouter>
)
expect(tree).toMatchSnapshot()
})

describe('with a mitochondrial transcript', () => {
test('has no unexpected changes', () => {
const tree = renderer.create(
Expand Down
17 changes: 8 additions & 9 deletions browser/src/ConstraintTable/ConstraintTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import Link from '../Link'

import ExacConstraintTable from './ExacConstraintTable'
import GnomadConstraintTable from './GnomadConstraintTable'
import MitochondrialConstraintTable from './MitochondrialConstraintTable'

type Props = {
datasetId: DatasetId
Expand Down Expand Up @@ -65,18 +66,16 @@ const ConstraintTable = ({ datasetId, geneOrTranscript }: Props) => {
const { transcriptId, transcriptVersion, transcriptDescription } =
transcriptDetails(geneOrTranscript)

const gnomadConstraint = geneOrTranscript.gnomad_constraint
const exacConstraint = geneOrTranscript.exac_constraint

if (geneOrTranscript.chrom === 'M') {
return (
<p>
Constraint is not available for mitochondrial{' '}
{isGene(geneOrTranscript) ? 'genes' : 'transcripts'}
</p>
)
if (isGene(geneOrTranscript)) {
return <MitochondrialConstraintTable constraint={geneOrTranscript.mitochondrial_constraint} />
}
return <p>Constraint is not available for mitochondrial transcripts</p>
}

const gnomadConstraint = geneOrTranscript.gnomad_constraint
const exacConstraint = geneOrTranscript.exac_constraint

if (datasetId === 'exac') {
if (!exacConstraint) {
return (
Expand Down
136 changes: 136 additions & 0 deletions browser/src/ConstraintTable/MitochondrialConstraintTable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
import React from 'react'
import {
MitochondrialGeneConstraint,
ProteinMitochondrialGeneConstraint,
RNAMitochondrialGeneConstraint,
} from '../GenePage/GenePage'
import { BaseTable } from '@gnomad/ui'

const isProteinMitochondrialGeneConstraint = (
constraint: MitochondrialGeneConstraint
): constraint is ProteinMitochondrialGeneConstraint =>
Object.prototype.hasOwnProperty.call(constraint, 'exp_lof')

const ConstraintRow = ({
category,
expected,
observed,
oe,
oeLower,
oeUpper,
}: {
category: string
expected: number
observed: number
oe: number
oeLower: number
oeUpper: number
}) => (
<tr>
<th scope="row">{category}</th>
<td>{expected.toFixed(1)}</td>
<td>{observed.toFixed(1)}</td>
<td>
{oe.toFixed(2)} ({oeLower.toFixed(2)}-{oeUpper.toFixed(2)})
</td>
</tr>
)

const ProteinConstraintMetrics = ({
constraint,
}: {
constraint: ProteinMitochondrialGeneConstraint
}) => {
const {
exp_lof,
exp_mis,
exp_syn,
obs_lof,
obs_mis,
obs_syn,
oe_lof,
oe_lof_lower,
oe_lof_upper,
oe_mis,
oe_mis_lower,
oe_mis_upper,
oe_syn,
oe_syn_lower,
oe_syn_upper,
} = constraint
return (
<tbody>
<ConstraintRow
category="Synonymous"
expected={exp_syn}
observed={obs_syn}
oe={oe_syn}
oeLower={oe_syn_lower}
oeUpper={oe_syn_upper}
/>
<ConstraintRow
category="Missense"
expected={exp_mis}
observed={obs_mis}
oe={oe_mis}
oeLower={oe_mis_lower}
oeUpper={oe_mis_upper}
/>
<ConstraintRow
category="pLoF"
expected={exp_lof}
observed={obs_lof}
oe={oe_lof}
oeLower={oe_lof_lower}
oeUpper={oe_lof_upper}
/>
</tbody>
)
}

const RNAConstraintMetrics = ({ constraint }: { constraint: RNAMitochondrialGeneConstraint }) => {
const { expected, observed, oe, oe_lower, oe_upper } = constraint
return (
<tbody>
<ConstraintRow
category="RNA variant"
expected={expected}
observed={observed}
oe={oe}
oeLower={oe_lower}
oeUpper={oe_upper}
/>
</tbody>
)
}

const MitochondrialConstraintTable = ({
constraint,
}: {
constraint: MitochondrialGeneConstraint | null
}) => {
if (constraint === null) {
return <p>Constraint is not available on this gene</p>
}

return (
// @ts-expect-error
<BaseTable>
<thead>
<tr>
<th scope="col">Category</th>
<th scope="col">Expected SNVs</th>
<th scope="col">Observed SNVs</th>
<th scope="col">Observed/Expected</th>
</tr>
</thead>
{isProteinMitochondrialGeneConstraint(constraint) ? (
<ProteinConstraintMetrics constraint={constraint} />
) : (
<RNAConstraintMetrics constraint={constraint} />
)}
</BaseTable>
)
}

export default MitochondrialConstraintTable
Loading

0 comments on commit ed33d6b

Please sign in to comment.