From fa5e395f5405500543314cc8e5994aa711105c16 Mon Sep 17 00:00:00 2001 From: Eleanor Lewis Date: Tue, 28 Jan 2025 11:31:03 -0800 Subject: [PATCH 1/4] add backwards compatible kbmatch table loading --- app/common.d.ts | 1 + .../ReportView/components/KbMatches/index.tsx | 159 +++++++++--------- 2 files changed, 81 insertions(+), 79 deletions(-) diff --git a/app/common.d.ts b/app/common.d.ts index fb831a21b..89903d6de 100644 --- a/app/common.d.ts +++ b/app/common.d.ts @@ -177,6 +177,7 @@ type KbMatchedStatementType = { kbData: { inferred: boolean; recruitment_status: string; + kbmatchTag: string | null; } | null; kbMatches: T[]; kbStatementId: string; diff --git a/app/views/ReportView/components/KbMatches/index.tsx b/app/views/ReportView/components/KbMatches/index.tsx index ce1fd2852..d086dedfa 100644 --- a/app/views/ReportView/components/KbMatches/index.tsx +++ b/app/views/ReportView/components/KbMatches/index.tsx @@ -70,50 +70,51 @@ const KbMatches = ({ try { const baseUri = `/reports/${report.ident}/kb-matches/kb-matched-statements`; const apiCalls = new ApiCallSet([ - api.get(`${baseUri}?approvedTherapy=false&category=therapeutic`, {}), - api.get(`${baseUri}?approvedTherapy=false&category=biological`, {}), - api.get(`${baseUri}?approvedTherapy=false&category=diagnostic`, {}), - api.get(`${baseUri}?approvedTherapy=false&category=prognostic`, {}), - api.get(`${baseUri}?category=unknown,novel`, {}), - api.get(`${baseUri}?approvedTherapy=true&category=therapeutic&matchedCancer=true&iprEvidenceLevel=IPR-A,IPR-B`, {}), api.get(`/reports/${report.ident}/probe-results`, {}), - api.get(`${baseUri}?category=pharmacogenomic`, {}), - api.get(`${baseUri}?category=cancer predisposition`, {}), + api.get(`${baseUri}`, {}), ]); const [ - therapeuticResp, - biologicalResp, - diagnosticResp, - prognosticResp, - unknownResp, - highEvidenceResp, targetedSomaticGenesResp, - pharmacogenomicResp, - cancerPredisResp, + allKbMatchesResp, ] = await apiCalls.request() as [ - KbMatchedStatementType[], - KbMatchedStatementType[], - KbMatchedStatementType[], - KbMatchedStatementType[], - KbMatchedStatementType[], - KbMatchedStatementType[], ProbeResultsType[], KbMatchedStatementType[], - KbMatchedStatementType[], ]; + // TODO this is here for backwards compatibility; consider removing after datafix + const oldStmts = allKbMatchesResp.filter(stmt => !stmt.kbData?.kbmatchTag); + const oldHighEvidence = oldStmts.filter(item => + item.category === 'therapeutic' && + item.approvedTherapy && + ['IPR-A', 'IPR-B'].includes(item?.iprEvidenceLevel) + ); + + // therapeutic but not best therapeutic. might be inconsistent with existing filtering - + // currently items that are therapeutic and approved but not with high evidence level are just + // not displayed (there may currently not be any such items). the difference will be + // that some items that were not previously displayed at all might now be displayed + // in this table + const oldTherapeutic = oldStmts.filter(item => + item.category === 'therapeutic' && + !oldHighEvidence.some(obj => obj.ident === item.ident) + ); + + const oldBiological = oldStmts.filter(item => item.category === 'biological') + const oldDiagnostic = oldStmts.filter(item => item.category === 'diagnostic') + const oldPrognostic = oldStmts.filter(item => item.category === 'prognostic') + const oldUnknown = oldStmts.filter(item => ['unknown', 'novel'].includes(item.category)) + const oldPcp = oldStmts.filter(item => ['cancer-predisposition', 'pharmacogenomic'].includes(item.category)) + + const taggedKbMatches = allKbMatchesResp.filter((stmt) => stmt?.kbData?.kbmatchTag) setGroupedMatches({ - highEvidence: coalesceEntries(highEvidenceResp), - therapeutic: coalesceEntries(therapeuticResp), - biological: coalesceEntries(biologicalResp), - diagnostic: coalesceEntries(diagnosticResp), - prognostic: coalesceEntries(prognosticResp), - unknown: coalesceEntries(unknownResp), - targetedGermlineGenes: coalesceEntries([ - ...pharmacogenomicResp, - ...cancerPredisResp.filter(({ kbMatches }) => (kbMatches as any)?.variant?.germline), - ]), + highEvidence: coalesceEntries([...oldHighEvidence, ...taggedKbMatches.filter((stmt) => stmt?.kbData?.kbmatchTag === 'bestTherapeutic')]), + therapeutic: coalesceEntries([...oldTherapeutic, ...taggedKbMatches.filter((stmt) => stmt?.kbData?.kbmatchTag === 'therapeutic')]), + biological: coalesceEntries([...oldBiological, ...taggedKbMatches.filter((stmt) => stmt?.kbData?.kbmatchTag === 'biological')]), + diagnostic: coalesceEntries([...oldDiagnostic, ...taggedKbMatches.filter((stmt) => stmt?.kbData?.kbmatchTag === 'diagnostic')]), + prognostic: coalesceEntries([...oldPrognostic, ...taggedKbMatches.filter((stmt) => stmt?.kbData?.kbmatchTag === 'prognostic')]), + unknown: coalesceEntries([...oldUnknown, ...taggedKbMatches.filter((stmt) => stmt?.kbData?.kbmatchTag === 'other')]), + targetedGermlineGenes: coalesceEntries([...oldPcp, ...taggedKbMatches.filter((stmt) => stmt?.kbData?.kbmatchTag === 'pcp')]), targetedSomaticGenes: targetedSomaticGenesResp.filter((tg) => !/germline/.test(tg?.sample)), }); } catch (err) { @@ -176,59 +177,59 @@ const KbMatches = ({ const kbMatchedTables = useMemo(() => Object.keys(TITLE_MAP).map((key) => ( { - ( - (report?.template.name !== 'probe' && report?.template.name !== 'rapid') - || (key !== 'targetedSomaticGenes' && key !== 'targetedGermlineGenes') - ) && ( - - ) - } + ( + (report?.template.name !== 'probe' && report?.template.name !== 'rapid') + || (key !== 'targetedSomaticGenes' && key !== 'targetedGermlineGenes') + ) && ( + + ) + } )), [canEdit, debouncedFilterText, groupedMatches, handleDelete, isPrint, report?.template.name]); return ( !isLoading && ( -
- - Tumour alterations with specific therapeutic, prognostic, diagnostic or biological - associations are identified using the knowledgebase GraphKB, which integrates information - from sources including cancer databases, drug databases, clinical tests, and the literature. - Associations are listed by the level of evidence for the use of that drug in the context of - the observed alteration, including those that are approved in this or other cancer types, - and those that have early clinical or preclinical evidence. - - {!isPrint && ( -
- - - - ), - }} - /> -
- )}
- {kbMatchedTables} + + Tumour alterations with specific therapeutic, prognostic, diagnostic or biological + associations are identified using the knowledgebase GraphKB, which integrates information + from sources including cancer databases, drug databases, clinical tests, and the literature. + Associations are listed by the level of evidence for the use of that drug in the context of + the observed alteration, including those that are approved in this or other cancer types, + and those that have early clinical or preclinical evidence. + + {!isPrint && ( +
+ + + + ), + }} + /> +
+ )} +
+ {kbMatchedTables} +
-
) ); }; From 44dfe6e34366549ee9b55015b9a4e507d5d4e168 Mon Sep 17 00:00:00 2001 From: Eleanor Lewis Date: Tue, 28 Jan 2025 11:57:05 -0800 Subject: [PATCH 2/4] put everything not matched in other --- .../ReportView/components/KbMatches/index.tsx | 28 +++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/app/views/ReportView/components/KbMatches/index.tsx b/app/views/ReportView/components/KbMatches/index.tsx index d086dedfa..94c0493a4 100644 --- a/app/views/ReportView/components/KbMatches/index.tsx +++ b/app/views/ReportView/components/KbMatches/index.tsx @@ -100,21 +100,33 @@ const KbMatches = ({ !oldHighEvidence.some(obj => obj.ident === item.ident) ); + // might be inconsistent with existing filtering - currently items that have + // 'approvedTherapy' True but not category 'therapeutic' are not displayed. + // (there are no examples in the db currently). here, we ignore approvedTherapy + // except for therapeutic stmts, so it's possible for items that previously + // would never be displayed, to be displayed here const oldBiological = oldStmts.filter(item => item.category === 'biological') const oldDiagnostic = oldStmts.filter(item => item.category === 'diagnostic') const oldPrognostic = oldStmts.filter(item => item.category === 'prognostic') - const oldUnknown = oldStmts.filter(item => ['unknown', 'novel'].includes(item.category)) const oldPcp = oldStmts.filter(item => ['cancer-predisposition', 'pharmacogenomic'].includes(item.category)) const taggedKbMatches = allKbMatchesResp.filter((stmt) => stmt?.kbData?.kbmatchTag) + + const highEvidence = coalesceEntries([...oldHighEvidence, ...taggedKbMatches.filter((stmt) => stmt?.kbData?.kbmatchTag === 'bestTherapeutic')]) + const therapeutic = coalesceEntries([...oldTherapeutic, ...taggedKbMatches.filter((stmt) => stmt?.kbData?.kbmatchTag === 'therapeutic')]) + const biological = coalesceEntries([...oldBiological, ...taggedKbMatches.filter((stmt) => stmt?.kbData?.kbmatchTag === 'biological')]) + const diagnostic = coalesceEntries([...oldDiagnostic, ...taggedKbMatches.filter((stmt) => stmt?.kbData?.kbmatchTag === 'diagnostic')]) + const prognostic = coalesceEntries([...oldPrognostic, ...taggedKbMatches.filter((stmt) => stmt?.kbData?.kbmatchTag === 'prognostic')]) + const targetedGermlineGenes = coalesceEntries([...oldPcp, ...taggedKbMatches.filter((stmt) => stmt?.kbData?.kbmatchTag === 'pcp')]) + setGroupedMatches({ - highEvidence: coalesceEntries([...oldHighEvidence, ...taggedKbMatches.filter((stmt) => stmt?.kbData?.kbmatchTag === 'bestTherapeutic')]), - therapeutic: coalesceEntries([...oldTherapeutic, ...taggedKbMatches.filter((stmt) => stmt?.kbData?.kbmatchTag === 'therapeutic')]), - biological: coalesceEntries([...oldBiological, ...taggedKbMatches.filter((stmt) => stmt?.kbData?.kbmatchTag === 'biological')]), - diagnostic: coalesceEntries([...oldDiagnostic, ...taggedKbMatches.filter((stmt) => stmt?.kbData?.kbmatchTag === 'diagnostic')]), - prognostic: coalesceEntries([...oldPrognostic, ...taggedKbMatches.filter((stmt) => stmt?.kbData?.kbmatchTag === 'prognostic')]), - unknown: coalesceEntries([...oldUnknown, ...taggedKbMatches.filter((stmt) => stmt?.kbData?.kbmatchTag === 'other')]), - targetedGermlineGenes: coalesceEntries([...oldPcp, ...taggedKbMatches.filter((stmt) => stmt?.kbData?.kbmatchTag === 'pcp')]), + highEvidence, + therapeutic, + biological, + diagnostic, + prognostic, + targetedGermlineGenes, + unknown: coalesceEntries(allKbMatchesResp.filter((stmt) => ![...highEvidence, ...therapeutic, ...biological, ...diagnostic, ...prognostic, ...targetedGermlineGenes].some(obj => obj.ident === stmt.ident))), targetedSomaticGenes: targetedSomaticGenesResp.filter((tg) => !/germline/.test(tg?.sample)), }); } catch (err) { From e7124259bc4da473b5ed130b7f5b3bfbe92bafa7 Mon Sep 17 00:00:00 2001 From: Eleanor Lewis Date: Mon, 10 Feb 2025 13:53:18 -0800 Subject: [PATCH 3/4] add matchedCancer check --- app/views/ReportView/components/KbMatches/index.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/views/ReportView/components/KbMatches/index.tsx b/app/views/ReportView/components/KbMatches/index.tsx index 94c0493a4..c8f2e3d34 100644 --- a/app/views/ReportView/components/KbMatches/index.tsx +++ b/app/views/ReportView/components/KbMatches/index.tsx @@ -87,7 +87,8 @@ const KbMatches = ({ const oldHighEvidence = oldStmts.filter(item => item.category === 'therapeutic' && item.approvedTherapy && - ['IPR-A', 'IPR-B'].includes(item?.iprEvidenceLevel) + ['IPR-A', 'IPR-B'].includes(item?.iprEvidenceLevel) && + item.matchedCancer ); // therapeutic but not best therapeutic. might be inconsistent with existing filtering - From 4246283c0d3a7e6c89c1fe29b6705f139d0841a5 Mon Sep 17 00:00:00 2001 From: Eleanor Lewis Date: Mon, 10 Feb 2025 15:13:03 -0800 Subject: [PATCH 4/4] fix filter --- app/views/ReportView/components/KbMatches/index.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/ReportView/components/KbMatches/index.tsx b/app/views/ReportView/components/KbMatches/index.tsx index c8f2e3d34..4cd543928 100644 --- a/app/views/ReportView/components/KbMatches/index.tsx +++ b/app/views/ReportView/components/KbMatches/index.tsx @@ -87,8 +87,8 @@ const KbMatches = ({ const oldHighEvidence = oldStmts.filter(item => item.category === 'therapeutic' && item.approvedTherapy && - ['IPR-A', 'IPR-B'].includes(item?.iprEvidenceLevel) && - item.matchedCancer + item.matchedCancer && + ['IPR-A', 'IPR-B'].includes(item?.iprEvidenceLevel) ); // therapeutic but not best therapeutic. might be inconsistent with existing filtering -