diff --git a/src/pages/patientView/PatientViewPage.tsx b/src/pages/patientView/PatientViewPage.tsx index 2653b280469..e1f897cea1b 100644 --- a/src/pages/patientView/PatientViewPage.tsx +++ b/src/pages/patientView/PatientViewPage.tsx @@ -958,6 +958,11 @@ export default class PatientViewPage extends React.Component< .patientViewPageStore .genomeNexusCache } + genomeNexusMutationAssessorCache={ + this + .patientViewPageStore + .genomeNexusMutationAssessorCache + } genomeNexusMyVariantInfoCache={ this .patientViewPageStore diff --git a/src/pages/patientView/clinicalInformation/PatientViewPageStore.ts b/src/pages/patientView/clinicalInformation/PatientViewPageStore.ts index cffad401c98..ed1c0a3f7b5 100644 --- a/src/pages/patientView/clinicalInformation/PatientViewPageStore.ts +++ b/src/pages/patientView/clinicalInformation/PatientViewPageStore.ts @@ -31,6 +31,7 @@ import { import OncoKbEvidenceCache from 'shared/cache/OncoKbEvidenceCache'; import PubMedCache from 'shared/cache/PubMedCache'; import GenomeNexusCache from 'shared/cache/GenomeNexusCache'; +import GenomeNexusMutationAssessorCache from 'shared/cache/GenomeNexusMutationAssessorCache'; import GenomeNexusMyVariantInfoCache from 'shared/cache/GenomeNexusMyVariantInfoCache'; import { IOncoKbData } from 'shared/model/OncoKB'; import { IHotspotIndex, indexHotspotsData } from 'react-mutation-mapper'; @@ -1391,6 +1392,10 @@ export class PatientViewPageStore { return new GenomeNexusMyVariantInfoCache(); } + @cached get genomeNexusMutationAssessorCache() { + return new GenomeNexusMutationAssessorCache(); + } + @cached get pubMedCache() { return new PubMedCache(); } diff --git a/src/pages/resultsView/ResultsViewPageStore.ts b/src/pages/resultsView/ResultsViewPageStore.ts index a66f06f8237..0522eb945e8 100644 --- a/src/pages/resultsView/ResultsViewPageStore.ts +++ b/src/pages/resultsView/ResultsViewPageStore.ts @@ -42,6 +42,7 @@ import { cached, labelMobxPromises, MobxPromise } from 'mobxpromise'; import OncoKbEvidenceCache from 'shared/cache/OncoKbEvidenceCache'; import PubMedCache from 'shared/cache/PubMedCache'; import GenomeNexusCache from 'shared/cache/GenomeNexusCache'; +import GenomeNexusMutationAssessorCache from 'shared/cache/GenomeNexusMutationAssessorCache'; import GenomeNexusMyVariantInfoCache from 'shared/cache/GenomeNexusMyVariantInfoCache'; import CancerTypeCache from 'shared/cache/CancerTypeCache'; import MutationCountCache from 'shared/cache/MutationCountCache'; @@ -2958,6 +2959,7 @@ export class ResultsViewPageStore { ] || [], () => this.mutationCountCache, () => this.genomeNexusCache, + () => this.genomeNexusMutationAssessorCache, () => this.genomeNexusMyVariantInfoCache, () => this.discreteCNACache, this.studyToMolecularProfileDiscrete.result!, @@ -4870,6 +4872,10 @@ export class ResultsViewPageStore { return new GenomeNexusCache(); } + @cached get genomeNexusMutationAssessorCache() { + return new GenomeNexusMutationAssessorCache(); + } + @cached get genomeNexusMyVariantInfoCache() { return new GenomeNexusMyVariantInfoCache(); } diff --git a/src/pages/resultsView/mutation/Mutations.tsx b/src/pages/resultsView/mutation/Mutations.tsx index 6c3c459d708..cab08bc61ae 100644 --- a/src/pages/resultsView/mutation/Mutations.tsx +++ b/src/pages/resultsView/mutation/Mutations.tsx @@ -152,6 +152,10 @@ export default class Mutations extends React.Component< this.props.store.mutationCountCache } genomeNexusCache={this.props.store.genomeNexusCache} + genomeNexusMutationAssessorCache={ + this.props.store + .genomeNexusMutationAssessorCache + } genomeNexusMyVariantInfoCache={ this.props.store.genomeNexusMyVariantInfoCache } diff --git a/src/pages/resultsView/mutation/ResultsViewMutationMapper.tsx b/src/pages/resultsView/mutation/ResultsViewMutationMapper.tsx index 8684c4e5ad3..9b40af36f71 100644 --- a/src/pages/resultsView/mutation/ResultsViewMutationMapper.tsx +++ b/src/pages/resultsView/mutation/ResultsViewMutationMapper.tsx @@ -113,6 +113,9 @@ export default class ResultsViewMutationMapper extends MutationMapper< pubMedCache={this.props.pubMedCache} mutationCountCache={this.props.mutationCountCache} genomeNexusCache={this.props.genomeNexusCache} + genomeNexusMutationAssessorCache={ + this.props.genomeNexusMutationAssessorCache + } genomeNexusMyVariantInfoCache={ this.props.genomeNexusMyVariantInfoCache } diff --git a/src/pages/resultsView/mutation/ResultsViewMutationMapperStore.ts b/src/pages/resultsView/mutation/ResultsViewMutationMapperStore.ts index 076939b0cd8..6f78bf2fbc5 100644 --- a/src/pages/resultsView/mutation/ResultsViewMutationMapperStore.ts +++ b/src/pages/resultsView/mutation/ResultsViewMutationMapperStore.ts @@ -23,6 +23,7 @@ import { import MutationCountCache from 'shared/cache/MutationCountCache'; import DiscreteCNACache from 'shared/cache/DiscreteCNACache'; import GenomeNexusCache from 'shared/cache/GenomeNexusCache'; +import GenomeNexusMutationAssessorCache from 'shared/cache/GenomeNexusMutationAssessorCache'; import GenomeNexusMyVariantInfoCache from 'shared/cache/GenomeNexusMyVariantInfoCache'; import { MutationTableDownloadDataFetcher } from 'shared/lib/MutationTableDownloadDataFetcher'; import MutationMapperStore, { @@ -47,6 +48,7 @@ export default class ResultsViewMutationMapperStore extends MutationMapperStore getMutations: () => Mutation[], private getMutationCountCache: () => MutationCountCache, private getGenomeNexusCache: () => GenomeNexusCache, + private getGenomeNexusMutationAssessorCache: () => GenomeNexusMutationAssessorCache, private getGenomeNexusMyVariantInfoCache: () => GenomeNexusMyVariantInfoCache, private getDiscreteCNACache: () => DiscreteCNACache, public studyToMolecularProfileDiscrete: { @@ -132,6 +134,7 @@ export default class ResultsViewMutationMapperStore extends MutationMapperStore this.mutationData, this.studyToMolecularProfileDiscrete, this.getGenomeNexusCache, + this.getGenomeNexusMutationAssessorCache, this.getGenomeNexusMyVariantInfoCache, this.getMutationCountCache, this.getDiscreteCNACache diff --git a/src/pages/staticPages/tools/mutationMapper/MutationMapperTool.tsx b/src/pages/staticPages/tools/mutationMapper/MutationMapperTool.tsx index 02821fec210..0974d81dcb0 100644 --- a/src/pages/staticPages/tools/mutationMapper/MutationMapperTool.tsx +++ b/src/pages/staticPages/tools/mutationMapper/MutationMapperTool.tsx @@ -469,6 +469,9 @@ export default class MutationMapperTool extends React.Component< } downloadDataFetcher={this.store.downloadDataFetcher} genomeNexusCache={this.store.genomeNexusCache} + genomeNexusMutationAssessorCache={ + this.store.genomeNexusMutationAssessorCache + } genomeNexusMyVariantInfoCache={ this.store.genomeNexusMyVariantInfoCache } diff --git a/src/pages/staticPages/tools/mutationMapper/MutationMapperToolStore.ts b/src/pages/staticPages/tools/mutationMapper/MutationMapperToolStore.ts index fb7f3a6eb16..1027019095a 100644 --- a/src/pages/staticPages/tools/mutationMapper/MutationMapperToolStore.ts +++ b/src/pages/staticPages/tools/mutationMapper/MutationMapperToolStore.ts @@ -42,6 +42,7 @@ import { fetchHotspotsData } from 'shared/lib/CancerHotspotsUtils'; import OncoKbEvidenceCache from 'shared/cache/OncoKbEvidenceCache'; import PubMedCache from 'shared/cache/PubMedCache'; import GenomeNexusCache from 'shared/cache/GenomeNexusCache'; +import GenomeNexusMutationAssessorCache from 'shared/cache/GenomeNexusMutationAssessorCache'; import GenomeNexusMyVariantInfoCache from 'shared/cache/GenomeNexusMyVariantInfoCache'; import PdbHeaderCache from 'shared/cache/PdbHeaderCache'; import MutationMapperStore from 'shared/components/mutationMapper/MutationMapperStore'; @@ -380,6 +381,10 @@ export default class MutationMapperToolStore { return new GenomeNexusCache(); } + @cached get genomeNexusMutationAssessorCache() { + return new GenomeNexusMutationAssessorCache(); + } + @cached get genomeNexusMyVariantInfoCache() { return new GenomeNexusMyVariantInfoCache(); } @@ -397,6 +402,7 @@ export default class MutationMapperToolStore { this.mutations, undefined, () => this.genomeNexusCache, + () => this.genomeNexusMutationAssessorCache, () => this.genomeNexusMyVariantInfoCache ); } diff --git a/src/pages/staticPages/tools/mutationMapper/StandaloneMutationMapper.tsx b/src/pages/staticPages/tools/mutationMapper/StandaloneMutationMapper.tsx index d863dcb3953..35110cb0f6a 100644 --- a/src/pages/staticPages/tools/mutationMapper/StandaloneMutationMapper.tsx +++ b/src/pages/staticPages/tools/mutationMapper/StandaloneMutationMapper.tsx @@ -30,6 +30,9 @@ export default class StandaloneMutationMapper extends MutationMapper< this.props.store.indexedVariantAnnotations } genomeNexusCache={this.props.genomeNexusCache} + genomeNexusMutationAssessorCache={ + this.props.genomeNexusMutationAssessorCache + } genomeNexusMyVariantInfoCache={ this.props.genomeNexusMyVariantInfoCache } diff --git a/src/shared/cache/GenomeNexusCache.ts b/src/shared/cache/GenomeNexusCache.ts index cb971ae97f6..222c14454f9 100644 --- a/src/shared/cache/GenomeNexusCache.ts +++ b/src/shared/cache/GenomeNexusCache.ts @@ -1,20 +1,18 @@ -import { fetchVariantAnnotationsByMutation } from 'shared/lib/StoreUtils'; -import { - extractGenomicLocation, - genomicLocationString, -} from 'shared/lib/MutationUtils'; -import { VariantAnnotation } from 'cbioportal-frontend-commons'; -import { Mutation } from 'shared/api/generated/CBioPortalAPI'; -import LazyMobXCache, { CacheData } from 'shared/lib/LazyMobXCache'; -import AppConfig from 'appConfig'; +import {fetchVariantAnnotationsByMutation} from "shared/lib/StoreUtils"; +import {extractGenomicLocation, genomicLocationString} from "shared/lib/MutationUtils"; +import {VariantAnnotation} from "cbioportal-frontend-commons"; +import {Mutation} from "shared/api/generated/CBioPortalAPI"; +import LazyMobXCache, {CacheData} from "shared/lib/LazyMobXCache"; +import AppConfig from "appConfig"; export type GenomeNexusCacheDataType = CacheData; -export function fetch(queries: Mutation[]): Promise { + +export function fetch(queries: Mutation[]):Promise { if (queries.length > 0) { return fetchVariantAnnotationsByMutation( queries, - ['annotation_summary', 'mutation_assessor'], + ['annotation_summary'], AppConfig.serverConfig.isoformOverrideSource ); } else { diff --git a/src/shared/cache/GenomeNexusMutationAssessorCache.ts b/src/shared/cache/GenomeNexusMutationAssessorCache.ts new file mode 100644 index 00000000000..d133b3fdda1 --- /dev/null +++ b/src/shared/cache/GenomeNexusMutationAssessorCache.ts @@ -0,0 +1,49 @@ +import * as _ from 'lodash'; +import { fetchVariantAnnotationsByMutation } from 'shared/lib/StoreUtils'; +import { + extractGenomicLocation, + genomicLocationString, +} from 'shared/lib/MutationUtils'; +import { Mutation } from 'shared/api/generated/CBioPortalAPI'; +import LazyMobXCache, { CacheData } from 'shared/lib/LazyMobXCache'; +import AppConfig from 'appConfig'; +import { VariantAnnotation } from 'cbioportal-frontend-commons'; + +export type GenomeNexusCacheDataType = CacheData; + +export function fetch(queries: Mutation[]): Promise { + if (queries.length > 0) { + return fetchVariantAnnotationsByMutation( + queries, + ['annotation_summary', 'mutation_assessor'], + AppConfig.serverConfig.isoformOverrideSource + ); + } else { + return Promise.resolve([]); + } +} + +export function queryToKey(m: Mutation) { + const genomicLocation = extractGenomicLocation(m); + if (genomicLocation) { + return genomicLocationString(genomicLocation); + } else { + // TODO: might be a better way to handle mutations w/o genomic location + // info. They should maybe not be fed to the cache in the first place + return ''; + } +} + +export default class GenomeNexusMutationAssessorCache extends LazyMobXCache< + VariantAnnotation, + Mutation +> { + constructor() { + super( + (m: Mutation) => queryToKey(m), // queryToKey + (v: VariantAnnotation) => + genomicLocationString(v.annotation_summary.genomicLocation), // dataToKey + fetch + ); + } +} diff --git a/src/shared/components/annotation/genomeNexus/MutationAssessor.tsx b/src/shared/components/annotation/genomeNexus/MutationAssessor.tsx index 9f37ed9544c..e8ddd9d251b 100644 --- a/src/shared/components/annotation/genomeNexus/MutationAssessor.tsx +++ b/src/shared/components/annotation/genomeNexus/MutationAssessor.tsx @@ -9,7 +9,7 @@ import { import mutationAssessorColumn from './styles/mutationAssessorColumn.module.scss'; export interface IMutationAssessorProps { - mutationAssessor: MutationAssessorData; + mutationAssessor: MutationAssessorData | undefined; } export function hideArrow(tooltipEl: any) { @@ -35,7 +35,7 @@ export default class MutationAssessor extends React.Component< if (mutationAssessorData) { return `impact: ${mutationAssessorData.functionalImpact}, score: ${mutationAssessorData.functionalImpactScore}`; } else { - return 'Error'; + return 'NA'; } } @@ -78,102 +78,109 @@ export default class MutationAssessor extends React.Component< } private tooltipContent() { - const maData = this.props.mutationAssessor; - const xVarLink = MutationAssessor.maLink( - `http://mutationassessor.org/r3/?cm=var&p=${maData.uniprotId}&var=${maData.variant}` - ); - const msaLink = MutationAssessor.maLink(maData.msaLink); - const pdbLink = MutationAssessor.maLink(maData.pdbLink); - - const impact = maData.functionalImpact ? ( -
- - - - - - - - - - {(maData.functionalImpactScore || - maData.functionalImpactScore === 0) && ( + if (this.props.mutationAssessor) { + const maData = this.props.mutationAssessor; + const xVarLink = MutationAssessor.maLink( + `http://mutationassessor.org/r3/?cm=var&p=${maData.uniprotId}&var=${maData.variant}` + ); + const msaLink = MutationAssessor.maLink(maData.msaLink); + const pdbLink = MutationAssessor.maLink(maData.pdbLink); + + const impact = maData.functionalImpact ? ( +
+
Source - - MutationAssessor - -
Impact - - {maData.functionalImpact} - -
- + - )} -
ScoreSource - {maData.functionalImpactScore.toFixed(2)} + + MutationAssessor +
-
- ) : null; - - const xVar = xVarLink ? ( - - ) : null; - - const msa = msaLink ? ( - - ) : null; - - const pdb = pdbLink ? ( - - ) : null; - - return ( - - {impact} - {msa} - {pdb} - {xVar} - - ); + + Impact + + + {maData.functionalImpact} + + + + {(maData.functionalImpactScore || + maData.functionalImpactScore === 0) && ( + + Score + + + {maData.functionalImpactScore.toFixed( + 2 + )} + + + + )} + + + ) : null; + + const xVar = xVarLink ? ( + + ) : null; + + const msa = msaLink ? ( + + ) : null; + + const pdb = pdbLink ? ( + + ) : null; + + return ( + + {impact} + {msa} + {pdb} + {xVar} + + ); + } } - // This is mostly to make the legacy MA links work public static maLink(link: string | undefined) { let url = null; diff --git a/src/shared/components/annotation/genomeNexus/PolyPhen2.tsx b/src/shared/components/annotation/genomeNexus/PolyPhen2.tsx index 4c8fdc87c64..5b86451d368 100644 --- a/src/shared/components/annotation/genomeNexus/PolyPhen2.tsx +++ b/src/shared/components/annotation/genomeNexus/PolyPhen2.tsx @@ -5,8 +5,8 @@ import classNames from 'classnames'; import tooltipStyles from './styles/polyPhen2Tooltip.module.scss'; export interface IPolyPhen2Props { - polyPhenPrediction: string; // benign, possibly_damaging, probably_damging - polyPhenScore: number; + polyPhenPrediction: string | undefined; // benign, possibly_damaging, probably_damging + polyPhenScore: number | undefined; } export function hideArrow(tooltipEl: any) { @@ -23,10 +23,14 @@ export default class PolyPhen2 extends React.Component { } public static download( - polyPhenScore: number, - polyPhenPrediction: string + polyPhenScore: number | undefined, + polyPhenPrediction: string | undefined ): string { - return `impact: ${polyPhenPrediction}, score: ${polyPhenScore}`; + if (polyPhenScore || polyPhenPrediction) { + return `impact: ${polyPhenPrediction}, score: ${polyPhenScore}`; + } else { + return 'NA'; + } } public render() { diff --git a/src/shared/components/annotation/genomeNexus/Sift.tsx b/src/shared/components/annotation/genomeNexus/Sift.tsx index a29e1b7a0a4..26ddcfa4237 100644 --- a/src/shared/components/annotation/genomeNexus/Sift.tsx +++ b/src/shared/components/annotation/genomeNexus/Sift.tsx @@ -5,8 +5,8 @@ import classNames from 'classnames'; import tooltipStyles from './styles/siftTooltip.module.scss'; export interface ISiftProps { - siftPrediction: string; // deleterious, deleterious_low_confidence, tolerated, tolerated_low_confidence - siftScore: number; + siftPrediction: string | undefined; // deleterious, deleterious_low_confidence, tolerated, tolerated_low_confidence + siftScore: number | undefined; } export function hideArrow(tooltipEl: any) { @@ -22,8 +22,15 @@ export default class Sift extends React.Component { this.tooltipContent = this.tooltipContent.bind(this); } - public static download(siftScore: number, siftPrediction: string): string { - return `impact: ${siftPrediction}, score: ${siftScore}`; + public static download( + siftScore: number | undefined, + siftPrediction: string | undefined + ): string { + if (siftScore || siftPrediction) { + return `impact: ${siftPrediction}, score: ${siftScore}`; + } else { + return 'NA'; + } } public render() { diff --git a/src/shared/components/mutationMapper/MutationMapper.tsx b/src/shared/components/mutationMapper/MutationMapper.tsx index 5c374487f9a..b61c7458de9 100644 --- a/src/shared/components/mutationMapper/MutationMapper.tsx +++ b/src/shared/components/mutationMapper/MutationMapper.tsx @@ -25,6 +25,7 @@ import StructureViewerPanel from 'shared/components/structureViewer/StructureVie import OncoKbEvidenceCache from 'shared/cache/OncoKbEvidenceCache'; import PubMedCache from 'shared/cache/PubMedCache'; import GenomeNexusCache from 'shared/cache/GenomeNexusCache'; +import GenomeNexusMutationAssessorCache from 'shared/cache/GenomeNexusMutationAssessorCache'; import GenomeNexusMyVariantInfoCache from 'shared/cache/GenomeNexusMyVariantInfoCache'; import { IMyCancerGenomeData } from 'shared/model/MyCancerGenome'; import PdbHeaderCache from 'shared/cache/PdbHeaderCache'; @@ -60,6 +61,7 @@ export interface IMutationMapperProps { pdbHeaderCache?: PdbHeaderCache; oncoKbEvidenceCache?: OncoKbEvidenceCache; genomeNexusCache?: GenomeNexusCache; + genomeNexusMutationAssessorCache?: GenomeNexusMutationAssessorCache; genomeNexusMyVariantInfoCache?: GenomeNexusMyVariantInfoCache; // server config properties genomeNexusUrl?: string; diff --git a/src/shared/components/mutationTable/MutationTable.tsx b/src/shared/components/mutationTable/MutationTable.tsx index 07697115396..1c6c6d57728 100644 --- a/src/shared/components/mutationTable/MutationTable.tsx +++ b/src/shared/components/mutationTable/MutationTable.tsx @@ -53,6 +53,7 @@ import VariantCountCache from 'shared/cache/VariantCountCache'; import PubMedCache from 'shared/cache/PubMedCache'; import MutationCountCache from 'shared/cache/MutationCountCache'; import GenomeNexusCache from 'shared/cache/GenomeNexusCache'; +import GenomeNexusMutationAssessorCache from 'shared/cache/GenomeNexusMutationAssessorCache'; import GenomeNexusMyVariantInfoCache from 'shared/cache/GenomeNexusMyVariantInfoCache'; import { ILazyMobXTableApplicationDataStore } from 'shared/lib/ILazyMobXTableApplicationDataStore'; import { ILazyMobXTableApplicationLazyDownloadDataFetcher } from 'shared/lib/ILazyMobXTableApplicationLazyDownloadDataFetcher'; @@ -88,6 +89,7 @@ export interface IMutationTableProps { pubMedCache?: PubMedCache; mutationCountCache?: MutationCountCache; genomeNexusCache?: GenomeNexusCache; + genomeNexusMutationAssessorCache?: GenomeNexusMutationAssessorCache; genomeNexusMyVariantInfoCache?: GenomeNexusMyVariantInfoCache; mutSigData?: IMutSigData; enableOncoKb?: boolean; @@ -664,18 +666,27 @@ export default class MutationTable< this._columns[MutationTableColumnType.FUNCTIONAL_IMPACT] = { name: 'Functional Impact', - render: (d: Mutation[]) => - this.props.genomeNexusCache ? ( - FunctionalImpactColumnFormatter.renderFunction( + render: (d: Mutation[]) => { + if ( + this.props.genomeNexusCache || + this.props.genomeNexusMutationAssessorCache + ) { + return FunctionalImpactColumnFormatter.renderFunction( d, - this.props.genomeNexusCache - ) - ) : ( - - ), + this.props.genomeNexusCache, + this.props.genomeNexusMutationAssessorCache + ); + } else { + return ; + } + }, download: (d: Mutation[]) => - FunctionalImpactColumnFormatter.download(d, this.props - .genomeNexusCache as GenomeNexusCache), + FunctionalImpactColumnFormatter.download( + d, + this.props.genomeNexusCache as GenomeNexusCache, + this.props + .genomeNexusMutationAssessorCache as GenomeNexusMutationAssessorCache + ), headerRender: FunctionalImpactColumnFormatter.headerRender, visible: false, shouldExclude: () => !this.props.enableFunctionalImpact, diff --git a/src/shared/components/mutationTable/column/FunctionalImpactColumnFormatter.tsx b/src/shared/components/mutationTable/column/FunctionalImpactColumnFormatter.tsx index a4ec157ce4a..06784bea23d 100644 --- a/src/shared/components/mutationTable/column/FunctionalImpactColumnFormatter.tsx +++ b/src/shared/components/mutationTable/column/FunctionalImpactColumnFormatter.tsx @@ -20,6 +20,7 @@ import siftStyles from 'shared/components/annotation/genomeNexus/styles/siftTool import polyPhen2Styles from 'shared/components/annotation/genomeNexus/styles/polyPhen2Tooltip.module.scss'; import mutationAssessorStyles from 'shared/components/annotation/genomeNexus/styles/mutationAssessorColumn.module.scss'; import annotationStyles from 'shared/components/annotation/styles/annotation.module.scss'; +import GenomeNexusMutationAssessorCache from 'shared/cache/GenomeNexusMutationAssessorCache'; import GenomeNexusCache, { GenomeNexusCacheDataType, } from 'shared/cache/GenomeNexusCache'; @@ -32,12 +33,18 @@ interface IFunctionalImpactColumnTooltipState { active: 'mutationAssessor' | 'sift' | 'polyPhen2'; } -interface IFunctionalImpactData { - mutationAssessor: MutationAssessorData; - siftScore: number; - siftPrediction: string; - polyPhenScore: number; - polyPhenPrediction: string; +enum FunctionalImpactColumnsName { + MUTATION_ASSESSOR, + SIFT, + POLYPHEN2, +} + +interface FunctionalImpactData { + mutationAssessor: MutationAssessorData | undefined; + siftScore: number | undefined; + siftPrediction: string | undefined; + polyPhenScore: number | undefined; + polyPhenPrediction: string | undefined; } class FunctionalImpactColumnTooltip extends React.Component< @@ -374,45 +381,110 @@ export default class FunctionalImpactColumnFormatter { } public static getData( - genomeNexusData: VariantAnnotation | null - ): IFunctionalImpactData | null { - if (!genomeNexusData) { - return null; - } + data: Mutation[], + siftPolyphenCache: GenomeNexusCache, + mutationAssessorCache: GenomeNexusMutationAssessorCache + ): FunctionalImpactData { + const siftPolyphenCacheData = FunctionalImpactColumnFormatter.getDataFromCache( + data, + siftPolyphenCache + ); + const mutationAssessorCacheData = FunctionalImpactColumnFormatter.getDataFromCache( + data, + mutationAssessorCache + ); - // TODO: handle multiple transcripts instead of just picking the first one - const mutationAssessor = - genomeNexusData.mutation_assessor && - genomeNexusData.mutation_assessor.annotation; - const siftScore = genomeNexusData.transcript_consequences[0].sift_score; - const siftPrediction = - genomeNexusData.transcript_consequences[0].sift_prediction; - const polyPhenScore = - genomeNexusData.transcript_consequences[0].polyphen_score; + const siftData = siftPolyphenCacheData + ? this.getSiftData(siftPolyphenCacheData.data) + : undefined; + const polyphenData = siftPolyphenCacheData + ? this.getPolyphenData(siftPolyphenCacheData.data) + : undefined; + const mutationAssessor = mutationAssessorCacheData + ? this.getMutationAssessorData(mutationAssessorCacheData.data) + : undefined; + + const siftScore = siftData && siftData.siftScore; + const siftPrediction = siftData && siftData.siftPrediction; + const polyPhenScore = polyphenData && polyphenData.polyPhenScore; const polyPhenPrediction = - genomeNexusData.transcript_consequences[0].polyphen_prediction; + polyphenData && polyphenData.polyPhenPrediction; - return { + const functionalImpactData: FunctionalImpactData = { mutationAssessor, siftScore, siftPrediction, polyPhenScore, polyPhenPrediction, }; + return functionalImpactData; + } + + public static getSiftData(siftDataCache: VariantAnnotation | null) { + const siftScore = + siftDataCache && siftDataCache.transcript_consequences[0] + ? siftDataCache.transcript_consequences[0].sift_score + : undefined; + const siftPrediction = siftDataCache + ? siftDataCache.transcript_consequences[0].sift_prediction + : undefined; + return { + siftScore, + siftPrediction, + }; + } + + public static getPolyphenData(polyphenDataCache: VariantAnnotation | null) { + const polyPhenScore = polyphenDataCache + ? polyphenDataCache.transcript_consequences[0].polyphen_score + : undefined; + const polyPhenPrediction = polyphenDataCache + ? polyphenDataCache.transcript_consequences[0].polyphen_prediction + : undefined; + return { + polyPhenScore, + polyPhenPrediction, + }; + } + + public static getMutationAssessorData( + mutationAssessorDataCache: VariantAnnotation | null + ): MutationAssessorData | undefined { + if (!mutationAssessorDataCache) { + return undefined; + } else { + return mutationAssessorDataCache.mutation_assessor + ? mutationAssessorDataCache.mutation_assessor.annotation + : undefined; + } } public static renderFunction( data: Mutation[], - genomeNexusCache: GenomeNexusCache | undefined + siftPolyphenCache: GenomeNexusCache | undefined, + mutationAssessorCache: GenomeNexusMutationAssessorCache | undefined ) { - const genomeNexusCacheData = FunctionalImpactColumnFormatter.getGenomeNexusDataFromCache( + const siftPolyphenCacheData = FunctionalImpactColumnFormatter.getDataFromCache( + data, + siftPolyphenCache + ); + const mutationAssessorCacheData = FunctionalImpactColumnFormatter.getDataFromCache( data, - genomeNexusCache + mutationAssessorCache ); return (
{FunctionalImpactColumnFormatter.makeFunctionalImpactViz( - genomeNexusCacheData + mutationAssessorCacheData, + FunctionalImpactColumnsName.MUTATION_ASSESSOR + )} + {FunctionalImpactColumnFormatter.makeFunctionalImpactViz( + siftPolyphenCacheData, + FunctionalImpactColumnsName.SIFT + )} + {FunctionalImpactColumnFormatter.makeFunctionalImpactViz( + siftPolyphenCacheData, + FunctionalImpactColumnsName.POLYPHEN2 )}
); @@ -420,38 +492,37 @@ export default class FunctionalImpactColumnFormatter { public static download( data: Mutation[], - genomeNexusCache: GenomeNexusCache + siftPolyphenCache: GenomeNexusCache, + mutationAssessorCache: GenomeNexusMutationAssessorCache ): string { - const genomeNexusData = FunctionalImpactColumnFormatter.getGenomeNexusDataFromCache( - data, - genomeNexusCache - ); - const functionalImpactData = - genomeNexusData && - FunctionalImpactColumnFormatter.getData(genomeNexusData.data); - - if (!functionalImpactData) { - return ''; + if (siftPolyphenCache || mutationAssessorCache) { + const functionalImpactData = FunctionalImpactColumnFormatter.getData( + data, + siftPolyphenCache, + mutationAssessorCache + ); + if (functionalImpactData) { + return [ + `MutationAssessor: ${MutationAssessor.download( + functionalImpactData.mutationAssessor + )}`, + `SIFT: ${Sift.download( + functionalImpactData.siftScore, + functionalImpactData.siftPrediction + )}`, + `Polyphen-2: ${PolyPhen2.download( + functionalImpactData.polyPhenScore, + functionalImpactData.polyPhenPrediction + )}`, + ].join(';'); + } } - - return [ - `MutationAssessor: ${MutationAssessor.download( - functionalImpactData.mutationAssessor - )}`, - `SIFT: ${Sift.download( - functionalImpactData.siftScore, - functionalImpactData.siftPrediction - )}`, - `Polyphen-2: ${PolyPhen2.download( - functionalImpactData.polyPhenScore, - functionalImpactData.polyPhenPrediction - )}`, - ].join(';'); + return ''; } - private static getGenomeNexusDataFromCache( + private static getDataFromCache( data: Mutation[], - cache: GenomeNexusCache | undefined + cache: GenomeNexusCache | GenomeNexusMutationAssessorCache | undefined ): GenomeNexusCacheDataType | null { if (data.length === 0 || !cache) { return null; @@ -460,42 +531,52 @@ export default class FunctionalImpactColumnFormatter { } private static makeFunctionalImpactViz( - genomeNexusCacheData: GenomeNexusCacheDataType | null + cacheData: GenomeNexusCacheDataType | null, + column: FunctionalImpactColumnsName ) { let status: TableCellStatus | null = null; - if (genomeNexusCacheData === null) { + if (cacheData === null) { status = TableCellStatus.LOADING; - } else if (genomeNexusCacheData.status === 'error') { + } else if (cacheData.status === 'error') { status = TableCellStatus.ERROR; - } else if (genomeNexusCacheData.data === null) { + } else if (cacheData.data === null) { status = TableCellStatus.NA; } else { - const functionalImpactData = FunctionalImpactColumnFormatter.getData( - genomeNexusCacheData.data - ); - - return ( - functionalImpactData && ( -
+ let functionalImpactData; + switch (column) { + case FunctionalImpactColumnsName.MUTATION_ASSESSOR: + functionalImpactData = FunctionalImpactColumnFormatter.getMutationAssessorData( + cacheData.data + ); + return ( + ); + case FunctionalImpactColumnsName.SIFT: + functionalImpactData = FunctionalImpactColumnFormatter.getSiftData( + cacheData.data + ); + return ( + ); + case FunctionalImpactColumnsName.POLYPHEN2: + functionalImpactData = FunctionalImpactColumnFormatter.getPolyphenData( + cacheData.data + ); + return ( -
- ) - ); + ); + } } if (status !== null) { @@ -503,7 +584,7 @@ export default class FunctionalImpactColumnFormatter { if (status === TableCellStatus.LOADING) { return ( GenomeNexusCache, + private genomeNexusMutationAssessorCache?: () => GenomeNexusMutationAssessorCache, private genomeNexusMyVariantInfoCache?: () => GenomeNexusMyVariantInfoCache, private mutationCountCache?: () => MutationCountCache, private discreteCNACache?: () => DiscreteCNACache @@ -68,13 +73,30 @@ export class MutationTableDownloadDataFetcher const caches: LazyMobXCache[] = []; if (this.genomeNexusCache) { - promises.push(this.fetchAllGenomeNexusData()); - caches.push(this.genomeNexusCache()); + if (this.mutationData.result) { + promises.push(fetchGenomeNexusData(this.mutationData.result)); + caches.push(this.genomeNexusCache()); + } + } + + if (this.genomeNexusMutationAssessorCache) { + if (this.mutationData.result) { + promises.push( + fetchGenomeNexusMutationAssessorData( + this.mutationData.result + ) + ); + caches.push(this.genomeNexusMutationAssessorCache()); + } } if (this.genomeNexusMyVariantInfoCache) { - promises.push(this.fetchAllGenomeNexusMyVariantInfoData()); - caches.push(this.genomeNexusMyVariantInfoCache()); + if (this.mutationData.result) { + promises.push( + fetchGenomeNexusMyVariantInfoData(this.mutationData.result) + ); + caches.push(this.genomeNexusMyVariantInfoCache()); + } } if (this.mutationCountCache) { @@ -90,24 +112,6 @@ export class MutationTableDownloadDataFetcher return { promises, caches }; } - private async fetchAllGenomeNexusData() { - if (this.mutationData.result) { - return await fetchGenomeNexusData(this.mutationData.result); - } else { - return undefined; - } - } - - private async fetchAllGenomeNexusMyVariantInfoData() { - if (this.mutationData.result) { - return await fetchGenomeNexusMyVariantInfoData( - this.mutationData.result - ); - } else { - return undefined; - } - } - private async fetchAllMutationCountData() { if (this.mutationData.result) { const queries = this.mutationData.result.map(mutation => ({