Skip to content

Commit

Permalink
display interpretation instead of ClinVar id
Browse files Browse the repository at this point in the history
Signed-off-by: Onur Sumer <s.onur.sumer@gmail.com>
  • Loading branch information
onursumer committed Jan 15, 2021
1 parent a66de29 commit 6c7bbed
Show file tree
Hide file tree
Showing 10 changed files with 209 additions and 159 deletions.
6 changes: 3 additions & 3 deletions end-to-end-test/remote/specs/core/mutationTable.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -168,20 +168,20 @@ describe('Mutation Table', function() {
);
});

it('should show the ClinVar id after adding the ClinVar column', () => {
it('should show the ClinVar interpretation after adding the ClinVar column', () => {
// click on column button
browser.click('button*=Columns');
// scroll down to activated "ClinVar" selection
browser.scroll(1000, 1000);
// click "clinvar"
browser.click('//*[text()="ClinVar ID"]');
browser.click('//*[text()="ClinVar"]');
let res;
browser.waitUntil(
() => {
res = executeInBrowser(
() => $('[data-test="clinvar-data"]').length
);
return res == 25;
return res === 25;
},
60000,
`Failed: There's 25 clinvar rows in table (${res} found)`
Expand Down
56 changes: 0 additions & 56 deletions packages/react-mutation-mapper/src/component/clinvar/ClinVarId.tsx

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
import {
DefaultTooltip,
pluralize,
TruncatedText,
} from 'cbioportal-frontend-commons';
import { getClinVarId } from 'cbioportal-utils';
import { ClinVar, MyVariantInfo } from 'genome-nexus-ts-api-client';
import _ from 'lodash';
import * as React from 'react';

export type ClinVarSummaryProps = {
myVariantInfo?: MyVariantInfo;
};

export enum ClinVarOrigin {
GERMLINE = 'germline',
SOMATIC = 'somatic',
}

export type RcvData = {
origin: string;
evidences: {
clinicalSignificance: string;
count: number;
}[];
};

export type RcvCountMap = {
[origin: string]: { [clinicalSignificance: string]: number };
};

export function getRcvCountMap(clinVar: ClinVar): RcvCountMap {
const filteredRcv = clinVar.rcv.filter(
rcv =>
rcv.origin === ClinVarOrigin.GERMLINE ||
rcv.origin === ClinVarOrigin.SOMATIC
);

// first map by origin, then count evidence number for each origin group
const rcvMap = _.groupBy(filteredRcv, d => d.origin);

return _.mapValues(rcvMap, rcvs =>
_.countBy(rcvs, rcv => rcv.clinicalSignificance)
);
}

export function getRcvData(rcvCountMap: RcvCountMap): RcvData[] {
return _.map(rcvCountMap, (clinicalSignificanceCountMap, origin) => ({
origin,
evidences: _.map(
clinicalSignificanceCountMap,
(count, clinicalSignificance) => ({ clinicalSignificance, count })
),
}));
}

export function formatClinicalSignificanceText(rcvData: RcvData[]) {
return _.uniq(
_.flatten(
rcvData.map(d => d.evidences.map(e => e.clinicalSignificance))
)
).join(', ');
}

export const ClinVarRcvInterpretation = (props: {
rcvData: RcvData[];
className?: string;
}) => {
return (
<div className={props.className}>
{props.rcvData.map(d => (
<div key={d.origin}>
<strong>{`${_.upperFirst(d.origin)}: `}</strong>
{d.evidences
.map(
e =>
`${e.clinicalSignificance} (${
e.count
} ${pluralize('evidence', e.count)})`
)
.join(', ')}
</div>
))}
</div>
);
};

const NoClinVarData = () => {
return (
<DefaultTooltip
placement="topLeft"
overlay={<span>Variant has no ClinVar data.</span>}
>
<span
style={{
height: '100%',
width: '100%',
display: 'block',
overflow: 'hidden',
}}
>
&nbsp;
</span>
</DefaultTooltip>
);
};

const ClinVarSummary = (props: ClinVarSummaryProps) => {
const clinVar = props.myVariantInfo
? props.myVariantInfo.clinVar
: undefined;

if (!clinVar) {
return <NoClinVarData />;
} else {
const clinVarId = getClinVarId(props.myVariantInfo);
const clinVarLink = `https://www.ncbi.nlm.nih.gov/clinvar/variation/${clinVarId}/`;
const rcvData = getRcvData(getRcvCountMap(clinVar));

return (
<TruncatedText
maxLength={30}
text={
rcvData.length > 0
? formatClinicalSignificanceText(rcvData)
: 'Unknown'
}
addTooltip="always"
tooltip={
<div style={{ maxWidth: 300 }}>
<ClinVarRcvInterpretation rcvData={rcvData} />
<div>
(ClinVar ID:{' '}
<a href={clinVarLink} target="_blank">
{clinVarId}
</a>
)
</div>
</div>
}
/>
);
}
};

export default ClinVarSummary;
38 changes: 17 additions & 21 deletions packages/react-mutation-mapper/src/component/column/ClinVar.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import autobind from 'autobind-decorator';
import { getClinVarId } from 'cbioportal-utils';
import { MyVariantInfo } from 'genome-nexus-ts-api-client';
import { observer } from 'mobx-react';
import * as React from 'react';

import { defaultSortMethod } from '../../util/ReactTableUtils';
import ClinVarId from '../clinvar/ClinVarId';
import ClinVarSummary, {
formatClinicalSignificanceText,
getRcvCountMap,
getRcvData,
} from '../clinvar/ClinVarSummary';
import {
MyVariantInfoProps,
renderMyVariantInfoContent,
Expand All @@ -17,28 +18,23 @@ export function download(myVariantInfo?: MyVariantInfo): string {
return value ? value.toString() : '';
}

export function sortValue(myVariantInfo?: MyVariantInfo): number | null {
const id = getClinVarId(myVariantInfo);
export function sortValue(myVariantInfo?: MyVariantInfo): string | null {
const rcvData =
myVariantInfo && myVariantInfo.clinVar
? getRcvData(getRcvCountMap(myVariantInfo.clinVar))
: undefined;

return id ? parseInt(id, 10) : null;
return rcvData ? formatClinicalSignificanceText(rcvData) : null;
}

export function clinVarSortMethod(a: MyVariantInfo, b: MyVariantInfo) {
return defaultSortMethod(sortValue(a), sortValue(b));
}

@observer
export default class ClinVar extends React.Component<MyVariantInfoProps, {}> {
public static defaultProps: Partial<MyVariantInfoProps> = {
className: 'pull-right mr-1',
};
const ClinVar = (props: MyVariantInfoProps) => {
return renderMyVariantInfoContent(props, (myVariantInfo: MyVariantInfo) => (
<ClinVarSummary myVariantInfo={myVariantInfo} />
));
};

public render() {
return renderMyVariantInfoContent(this.props, this.getContent);
}

@autobind
public getContent(myVariantInfo: MyVariantInfo) {
return <ClinVarId myVariantInfo={myVariantInfo} />;
}
}
export default ClinVar;
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export type MyVariantInfoProps = {
indexedVariantAnnotations?: RemoteData<
{ [genomicLocation: string]: VariantAnnotation } | undefined
>;
indexedMyVariantInfoAnnotations: RemoteData<
indexedMyVariantInfoAnnotations?: RemoteData<
{ [genomicLocation: string]: MyVariantInfo } | undefined
>;
className?: string;
Expand All @@ -28,7 +28,7 @@ export function renderMyVariantInfoContent(
) => JSX.Element
) {
let content;
const status = props.indexedMyVariantInfoAnnotations.status;
const status = props.indexedMyVariantInfoAnnotations?.status || 'complete';
const variantAnnotation = props.indexedVariantAnnotations
? getVariantAnnotation(
props.mutation,
Expand All @@ -37,7 +37,7 @@ export function renderMyVariantInfoContent(
: undefined;
const myVariantInfo = getMyVariantInfoAnnotation(
props.mutation,
props.indexedMyVariantInfoAnnotations.result
props.indexedMyVariantInfoAnnotations?.result
);

if (status === 'pending') {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export enum MutationColumn {
HGVSG = 'hgvsg',
HGVSC = 'hgvsc',
GNOMAD = 'gnomad',
CLINVAR = 'clinVarId',
CLINVAR = 'clinVar',
DBSNP = 'dbsnp',
}

Expand All @@ -46,7 +46,7 @@ export enum MutationColumnName {
HGVSG = 'HGVSg',
HGVSC = 'HGVSc',
GNOMAD = 'gnomAD',
CLINVAR = 'ClinVar ID',
CLINVAR = 'ClinVar',
DBSNP = 'dbSNP',
}

Expand Down Expand Up @@ -178,7 +178,7 @@ export const MUTATION_COLUMN_HEADERS = {
[MutationColumn.CLINVAR]: (
<ColumnHeader
headerContent={
<span className="pull-right mr-3">
<span className="pull-left">
{MutationColumnName.CLINVAR}{' '}
<i className="fa fa-info-circle" />
</span>
Expand Down
9 changes: 8 additions & 1 deletion packages/react-mutation-mapper/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,14 @@ export {
download as civicDownload,
sortValue as civicSortValue,
} from './component/civic/Civic';
export { default as ClinVarId } from './component/clinvar/ClinVarId';
export {
default as ClinVarSummary,
ClinVarRcvInterpretation,
getRcvCountMap,
getRcvData,
RcvCountMap,
RcvData,
} from './component/clinvar/ClinVarSummary';
export {
AnnotationProps,
default as Annotation,
Expand Down
Loading

0 comments on commit 6c7bbed

Please sign in to comment.