From 7fbf2722534ffaf7102f3a9c40a8350ab6806169 Mon Sep 17 00:00:00 2001 From: Dennis Hendriksen Date: Fri, 1 Jul 2022 07:56:46 +0200 Subject: [PATCH 1/2] fix:exact gene hyperlink for EntrezGene genes --- src/components/record/info/ClinVar.tsx | 10 ++++---- src/components/record/info/Gene.tsx | 33 ++++++++++++++++++++++---- src/utils/csqUtils.ts | 10 ++++++++ 3 files changed, 44 insertions(+), 9 deletions(-) diff --git a/src/components/record/info/ClinVar.tsx b/src/components/record/info/ClinVar.tsx index 37a1a863..b0a167ad 100644 --- a/src/components/record/info/ClinVar.tsx +++ b/src/components/record/info/ClinVar.tsx @@ -1,8 +1,8 @@ import { Component, Show } from "solid-js"; import { FieldProps } from "../field/Field"; -import { Value } from "@molgenis/vip-report-vcf/src/ValueParser"; import { Anchor } from "../../Anchor"; import { Abbr } from "../../Abbr"; +import { getCsqInfo, getCsqInfoIndex } from "../../../utils/csqUtils"; export const ClinVar: Component = (props) => { const label = () => { @@ -32,14 +32,14 @@ export const ClinVar: Component = (props) => { }; const href = () => { - const clinVarIdsField = props.infoMeta.parent?.nested?.items.findIndex((item) => item.id === "clinVar"); - const clinVarIds = clinVarIdsField ? ((props.info.valueParent as Value[])[clinVarIdsField] as number[]) : []; + const clinVarIdsField = getCsqInfoIndex(props.infoMeta, "clinVar"); + const clinVarIds = clinVarIdsField ? (getCsqInfo(props.info, clinVarIdsField) as number[]) : []; return clinVarIds.length === 1 ? `https://www.ncbi.nlm.nih.gov/clinvar/variation/${clinVarIds[0]}/` : undefined; }; const description = () => { - const statusField = props.infoMeta.parent?.nested?.items.findIndex((item) => item.id === "clinVar_CLNREVSTAT"); - const status = statusField ? ((props.info.valueParent as Value[])[statusField] as string[]) : []; + const statusField = getCsqInfoIndex(props.infoMeta, "clinVar_CLNREVSTAT"); + const status = statusField ? (getCsqInfo(props.info, statusField) as string[]) : []; if (status.length === 0) return; let description; diff --git a/src/components/record/info/Gene.tsx b/src/components/record/info/Gene.tsx index 990a37eb..c096ab3b 100644 --- a/src/components/record/info/Gene.tsx +++ b/src/components/record/info/Gene.tsx @@ -1,15 +1,40 @@ -import { Component, Show } from "solid-js"; +import { Component, createMemo, Show } from "solid-js"; import { Anchor } from "../../Anchor"; import { FieldProps } from "../field/Field"; import { ValueString } from "@molgenis/vip-report-vcf/src/ValueParser"; +import { getCsqInfo, getCsqInfoIndex } from "../../../utils/csqUtils"; export const Gene: Component = (props) => { - const symbol = () => props.info.value as ValueString; - // TODO use gene source and gene id to build hyperlinks, e.g. https://www.genenames.org/data/gene-symbol-report/#!/hgnc_id/HGNC:24086 + const symbol = (): string | null => props.info.value as ValueString; + + const symbolSource = createMemo((): string | undefined => { + if (symbol() === null) return undefined; + + const symbolSourceFieldIndex = getCsqInfoIndex(props.infoMeta, "SYMBOL_SOURCE"); + return symbolSourceFieldIndex !== -1 ? (getCsqInfo(props.info, symbolSourceFieldIndex) as string) : undefined; + }); + + const geneId = createMemo((): string | undefined => { + if (symbol() === null) return undefined; + + const geneFieldIndex = getCsqInfoIndex(props.infoMeta, "Gene"); + return geneFieldIndex !== -1 ? (getCsqInfo(props.info, geneFieldIndex) as string) : undefined; + }); + + const href = (): string | undefined => { + if (symbol() === null) return undefined; + + const queryString = + symbolSource() === "EntrezGene" && geneId() + ? `query=ncbi_gene_id:${geneId()!}` + : `query=${encodeURIComponent(symbol()!)}&filter=document_type:%22gene%22`; + return `https://www.genenames.org/tools/search/#!/?${queryString}`; + }; + return ( {(symbol) => ( - + {symbol} )} diff --git a/src/utils/csqUtils.ts b/src/utils/csqUtils.ts index 47cd7358..9dc6606b 100644 --- a/src/utils/csqUtils.ts +++ b/src/utils/csqUtils.ts @@ -1,4 +1,6 @@ import { FieldMetadata } from "@molgenis/vip-report-vcf/src/MetadataParser"; +import { FieldValue } from "../components/record/field/Field"; +import { Value } from "@molgenis/vip-report-vcf/src/ValueParser"; function is(infoMeta: FieldMetadata, id: string) { return infoMeta.id === id; @@ -15,3 +17,11 @@ export function isCsqInfo(infoMeta: FieldMetadata, id: string) { export function isAnyCsqInfo(infoMeta: FieldMetadata, ids: string[]) { return isCsq(infoMeta) && ids.some((id) => is(infoMeta, id)); } + +export function getCsqInfoIndex(infoMeta: FieldMetadata, id: string): number { + return infoMeta.parent?.nested?.items.findIndex((item) => item.id === id) || -1; +} + +export function getCsqInfo(info: FieldValue, infoIndex: number): Value { + return (info.valueParent as Value[])[infoIndex]; +} From 6f0da321f6ddbf5ce842403aea820eedff960ff7 Mon Sep 17 00:00:00 2001 From: Dennis Hendriksen Date: Fri, 1 Jul 2022 08:08:12 +0200 Subject: [PATCH 2/2] feat:replace incomplete penetrance column with gene indicator --- src/components/record/info/Gene.tsx | 31 ++++++++++++++++++++--------- src/views/SampleVariants.tsx | 1 - 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/src/components/record/info/Gene.tsx b/src/components/record/info/Gene.tsx index c096ab3b..49e9e6e2 100644 --- a/src/components/record/info/Gene.tsx +++ b/src/components/record/info/Gene.tsx @@ -1,24 +1,25 @@ import { Component, createMemo, Show } from "solid-js"; import { Anchor } from "../../Anchor"; import { FieldProps } from "../field/Field"; -import { ValueString } from "@molgenis/vip-report-vcf/src/ValueParser"; +import { ValueFlag, ValueString } from "@molgenis/vip-report-vcf/src/ValueParser"; import { getCsqInfo, getCsqInfoIndex } from "../../../utils/csqUtils"; +import { Abbr } from "../../Abbr"; export const Gene: Component = (props) => { - const symbol = (): string | null => props.info.value as ValueString; + const symbol = (): ValueString => props.info.value as ValueString; - const symbolSource = createMemo((): string | undefined => { + const symbolSource = createMemo((): ValueString | undefined => { if (symbol() === null) return undefined; const symbolSourceFieldIndex = getCsqInfoIndex(props.infoMeta, "SYMBOL_SOURCE"); - return symbolSourceFieldIndex !== -1 ? (getCsqInfo(props.info, symbolSourceFieldIndex) as string) : undefined; + return symbolSourceFieldIndex !== -1 ? (getCsqInfo(props.info, symbolSourceFieldIndex) as ValueString) : undefined; }); - const geneId = createMemo((): string | undefined => { + const geneId = createMemo((): ValueString | undefined => { if (symbol() === null) return undefined; const geneFieldIndex = getCsqInfoIndex(props.infoMeta, "Gene"); - return geneFieldIndex !== -1 ? (getCsqInfo(props.info, geneFieldIndex) as string) : undefined; + return geneFieldIndex !== -1 ? (getCsqInfo(props.info, geneFieldIndex) as ValueString) : undefined; }); const href = (): string | undefined => { @@ -31,12 +32,24 @@ export const Gene: Component = (props) => { return `https://www.genenames.org/tools/search/#!/?${queryString}`; }; + const incompletePenetrance = (): ValueFlag | undefined => { + const ipFieldIndex = getCsqInfoIndex(props.infoMeta, "IncompletePenetrance"); + return ipFieldIndex !== -1 ? (getCsqInfo(props.info, ipFieldIndex) as ValueFlag) : undefined; + }; + return ( {(symbol) => ( - - {symbol} - + <> + + {symbol} + + {incompletePenetrance() && ( + + + + )} + )} ); diff --git a/src/views/SampleVariants.tsx b/src/views/SampleVariants.tsx index 315032bb..f14d827e 100644 --- a/src/views/SampleVariants.tsx +++ b/src/views/SampleVariants.tsx @@ -122,7 +122,6 @@ export const SampleVariants: Component<{ "Consequence", "SYMBOL", "InheritanceModesGene", - "IncompletePenetrance", "HPO", "HGVSc", "HGVSp",