Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: group clades in mutation tooltips on gene map
- Loading branch information
1 parent
e5df009
commit 6971f9c
Showing
5 changed files
with
111 additions
and
75 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import { groupBy, uniqBy } from 'lodash' | ||
|
||
import type { Nucleotide, Substitutions, CladeDataFlat, CladeDataGrouped } from 'src/algorithms/types' | ||
|
||
import { VIRUSES } from 'src/algorithms/viruses' | ||
|
||
export function cladesFlatten(clades: Substitutions): CladeDataFlat[] { | ||
return Object.entries(clades).reduce((result, [cladeName, substitutions]) => { | ||
const subs = substitutions.map(({ pos, nuc }) => { | ||
return { cladeName, pos, nuc } | ||
}) | ||
|
||
return [...result, ...subs] | ||
}, [] as CladeDataFlat[]) | ||
} | ||
|
||
export function groupClades(clades: Substitutions): CladeDataGrouped[] { | ||
const cladesFlat = cladesFlatten(clades) | ||
|
||
// TODO: there should probably be a simpler and cleaner way to do this | ||
const cladesGroupedByNuc = cladesFlat.map(({ pos }) => { | ||
const subsList = cladesFlat | ||
.filter((candidate) => pos === candidate.pos) | ||
.map(({ cladeName, nuc }) => ({ cladeName, nuc })) | ||
|
||
const subsRaw = groupBy(subsList, ({ nuc }) => nuc) | ||
|
||
const subsEntriesSimplified = Object.entries(subsRaw).map(([nuc, arr]) => [ | ||
nuc, | ||
arr.map(({ cladeName }) => cladeName), | ||
]) | ||
|
||
const subs = Object.fromEntries(subsEntriesSimplified) as Record<Nucleotide, string[]> | ||
return { pos, subs } | ||
}) | ||
|
||
return uniqBy(cladesGroupedByNuc, ({ pos }) => pos) | ||
} | ||
|
||
export const cladesGrouped = groupClades(VIRUSES['SARS-CoV-2'].clades) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import React, { SVGProps, useState } from 'react' | ||
|
||
import { useTranslation } from 'react-i18next' | ||
|
||
import { BASE_MIN_WIDTH_PX } from 'src/constants' | ||
|
||
import type { CladeDataGrouped } from 'src/algorithms/types' | ||
import { getSafeId } from 'src/helpers/getSafeId' | ||
import { Tooltip } from 'src/components/Results/Tooltip' | ||
|
||
const GENE_MAP_CLADE_MARK_COLOR = '#444444aa' as const | ||
|
||
export interface CladeMarkerProps extends SVGProps<SVGRectElement> { | ||
cladeDatum: CladeDataGrouped | ||
pixelsPerBase: number | ||
} | ||
|
||
export function CladeMarker({ cladeDatum, pixelsPerBase, ...rest }: CladeMarkerProps) { | ||
const { t } = useTranslation() | ||
const [showTooltip, setShowTooltip] = useState(false) | ||
const { pos, subs } = cladeDatum | ||
|
||
const id = getSafeId('clade-marker', { pos }) | ||
const fill = GENE_MAP_CLADE_MARK_COLOR | ||
const x = pos * pixelsPerBase | ||
const width = Math.max(BASE_MIN_WIDTH_PX, 1 * pixelsPerBase) | ||
|
||
const mutationItems = Object.entries(subs as Record<string, string[]>).map(([nuc, clades]) => { | ||
return <li key={nuc}>{`${nuc}: ${clades.join(', ')}`}</li> | ||
}) | ||
|
||
return ( | ||
<rect | ||
id={id} | ||
fill={fill} | ||
x={x} | ||
y={-10} | ||
width={width} | ||
height="30" | ||
{...rest} | ||
onMouseEnter={() => setShowTooltip(true)} | ||
onMouseLeave={() => setShowTooltip(false)} | ||
> | ||
<Tooltip target={id} isOpen={showTooltip}> | ||
<div>{t('Position: {{position}}', { position: pos })}</div> | ||
<div>{t('Signature mutations:')}</div> | ||
<div> | ||
<ul>{mutationItems}</ul> | ||
</div> | ||
</Tooltip> | ||
</rect> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters