From c7c7ea8b6214dcb1129a9a28f0f4ab831c23a4bf Mon Sep 17 00:00:00 2001 From: Manuel Holtgrewe Date: Tue, 9 Jan 2024 09:16:54 +0100 Subject: [PATCH] feat: integrate PanelApp in gene details card (#373) --- .../components/GeneDetails/ConditionsCard.vue | 159 ++++++++++++++++++ 1 file changed, 159 insertions(+) diff --git a/frontend/src/components/GeneDetails/ConditionsCard.vue b/frontend/src/components/GeneDetails/ConditionsCard.vue index 00ccb287..e426dbe8 100644 --- a/frontend/src/components/GeneDetails/ConditionsCard.vue +++ b/frontend/src/components/GeneDetails/ConditionsCard.vue @@ -46,6 +46,137 @@ const hpoTermsToShow = computed(() => { return props.hpoTerms.slice(0, maxHpoTerms) } }) + +// -- code for PanelApp conditions ------------------------------------------- + +/** Enumeration for PanelApp confidence levels. */ +enum PanelAppConfidenceLevel { + Green = 'CONFIDENCE_LEVEL_GREEN', + Amber = 'CONFIDENCE_LEVEL_AMBER', + Red = 'CONFIDENCE_LEVEL_RED' +} + +/** Compare `PanelAppConfidenceLevel` in a sort-compatible way */ +const comparePanelAppConfidenceLevel = ( + lhs: PanelAppConfidenceLevel, + rhs: PanelAppConfidenceLevel +): number => { + switch (lhs) { + case PanelAppConfidenceLevel.Green: + switch (rhs) { + case PanelAppConfidenceLevel.Green: + return 0 + case PanelAppConfidenceLevel.Amber: + case PanelAppConfidenceLevel.Red: + return -1 + } + case PanelAppConfidenceLevel.Amber: + switch (rhs) { + case PanelAppConfidenceLevel.Green: + return 1 + case PanelAppConfidenceLevel.Amber: + return 0 + case PanelAppConfidenceLevel.Red: + return -1 + } + case PanelAppConfidenceLevel.Red: + switch (rhs) { + case PanelAppConfidenceLevel.Green: + case PanelAppConfidenceLevel.Amber: + return 1 + case PanelAppConfidenceLevel.Red: + return 0 + } + } +} + +/** Return label for `PanelAppConfidenceLevel`. */ +const confidenceLabel = (level: PanelAppConfidenceLevel): string => { + switch (level) { + case PanelAppConfidenceLevel.Green: + return 'green' + case PanelAppConfidenceLevel.Amber: + return 'amber' + case PanelAppConfidenceLevel.Red: + return 'red' + } +} + +/** + * Representation of a PanelApp. + */ +interface PanelAppCondition { + panelId: number + title: string + confidence: PanelAppConfidenceLevel +} + +/** + * Return list of PanelApp conditions with reduced redundancy. + * + * Note that proper redundancy removal can only be done with proper named + * entity normalization which is on our TODO list. + */ +const panelAppConditions = computed(() => { + if (!props.geneInfo?.panelapp) { + return [] + } + + // seen conditions + const seen = new Map() + + /** Normalize phenotype name. */ + const normalizeName = (name: string): string => { + const match = [...name.matchAll(/\{(.*)\}/g)] + let result: string + if (match.length) { + result = match[0][1] + } else { + result = name + } + + result = result + .replace(/,? \d{6,6}$/, '') + .replace(/,? MONDO:\d{6,6}/, '') + .replace(/,? O?MIM:\d{6,6}/, '') + .replace(/,? \(\d{6,6}\)/, '') + + return result + } + + // Collect phenotypes by panel in a somewhat non-redundant way. + for (const entry of props.geneInfo.panelapp) { + if (entry.phenotypes?.length) { + const phenotype = normalizeName(entry.phenotypes[0]) + const seenEntry = seen.get(phenotype.toLowerCase()) + let entryOverridesSeen = true + if (seenEntry) { + entryOverridesSeen = + comparePanelAppConfidenceLevel(entry.confidenceLevel, seenEntry.confidence) < 0 + } + if (entryOverridesSeen) { + seen.set(phenotype.toLowerCase(), { + panelId: entry.panel?.id, + title: phenotype, + confidence: entry.confidenceLevel + }) + } + } + } + + // Obtain list of conditions, sorted by confidence level. + const result = Array.from(seen.values()) + result.sort((lhs, rhs) => { + const tmp = comparePanelAppConfidenceLevel(lhs.confidence, rhs.confidence) + if (tmp == 0) { + return lhs.title.localeCompare(rhs.title) + } else { + return tmp + } + }) + + return result +})
No OMIM diseases annotated in dbNSFP.
+ + +
+ PanelApp Conditions + ({{ panelAppConditions.length }}) +
+
+ +
+
No PanelApp conditions found.