From dead210f0d06c5cbc22266e80d9da73eb4ffaac5 Mon Sep 17 00:00:00 2001 From: fnguyen Date: Thu, 22 Aug 2024 17:04:29 -0400 Subject: [PATCH 1/3] Use authorized counts when we have them --- .../clinicalGenomic/widgets/patientCounts.js | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/views/clinicalGenomic/widgets/patientCounts.js b/src/views/clinicalGenomic/widgets/patientCounts.js index 62a8c94b..c06a5253 100644 --- a/src/views/clinicalGenomic/widgets/patientCounts.js +++ b/src/views/clinicalGenomic/widgets/patientCounts.js @@ -27,22 +27,33 @@ function PatientCounts() { const context = useSearchResultsReaderContext(); const sites = context?.federation; const programs = context?.programs; + const discoveryCounts = context?.counts?.patients_per_cohort; + const clinicalCounts = context?.clinical; // Generate the map of site->cohort->numbers let siteData = []; if (Array.isArray(sites)) { siteData = sites.map((entry) => { - const counts = context?.counts?.patients_per_cohort?.[entry.location.name] || {}; + const counts = discoveryCounts?.[entry.location.name] || {}; + const realCounts = clinicalCounts?.[entry.location.name]?.summary?.patients_per_cohort || {}; let unlockedPrograms = []; + // Fill up the programs using the summary counts if (Array.isArray(programs)) { unlockedPrograms = programs .filter((search) => entry.location.name === search.location.name)?.[0] ?.results?.items?.map((program) => program.program_id); } + const finalCounts = {}; + Object.keys(counts).forEach((program) => { + finalCounts[program] = program in realCounts ? realCounts[program] : counts[program]; + }); + + // Where possible, also use the real counts + return { location: entry.location.name, - counts, + counts: finalCounts, totals: entry?.results || {}, unlockedPrograms }; From 1eede8c40d08ae899636d26ca9897ef5b486fc4d Mon Sep 17 00:00:00 2001 From: fnguyen Date: Fri, 23 Aug 2024 15:43:43 -0400 Subject: [PATCH 2/3] Fixup the patient counts and data visualizations by adding data from the authorized query where applicable --- .../clinicalGenomic/search/SearchHandler.js | 2 +- .../widgets/dataVisualization.js | 43 +++++++++++++++---- 2 files changed, 36 insertions(+), 9 deletions(-) diff --git a/src/views/clinicalGenomic/search/SearchHandler.js b/src/views/clinicalGenomic/search/SearchHandler.js index 8dd43282..4adde12e 100644 --- a/src/views/clinicalGenomic/search/SearchHandler.js +++ b/src/views/clinicalGenomic/search/SearchHandler.js @@ -85,7 +85,7 @@ function SearchHandler({ setLoading }) { } const discoveryCounts = { - diagnosis_age_count: CollateSummary(data, 'age_at_diagnosis'), + age_at_diagnosis: CollateSummary(data, 'age_at_diagnosis'), treatment_type_count: CollateSummary(data, 'treatment_type_count'), primary_site_count: CollateSummary(data, 'primary_site_count'), patients_per_cohort: {} diff --git a/src/views/clinicalGenomic/widgets/dataVisualization.js b/src/views/clinicalGenomic/widgets/dataVisualization.js index 13e18f80..fa07b768 100644 --- a/src/views/clinicalGenomic/widgets/dataVisualization.js +++ b/src/views/clinicalGenomic/widgets/dataVisualization.js @@ -23,24 +23,51 @@ import { HAS_CENSORED_DATA_MARKER } from 'utils/utils'; function DataVisualization() { // Hooks - const resultsContext = useSearchResultsReaderContext().counts; + const resultsContext = useSearchResultsReaderContext(); + const counts = resultsContext.counts; + const clinical = resultsContext.clinical; // Plan for context below see current dataVis for expected shape - // const dataVis = resultsContext || {}; - const handleCensoring = (dataObj) => { + // const dataVis = counts || {}; + const isCensored = (datum) => typeof datum === 'string' && datum.startsWith('<'); + const handleCensoring = (dataKey, transformer = (site, input) => input, isObject = false) => { + const dataObj = counts?.[dataKey]; if (dataObj === null || typeof dataObj === 'undefined') { return {}; } let hasCensoredData = false; const newDataObj = {}; + // Copy over the data into a new object, substituting 0 instead of any censored data Object.keys(dataObj).forEach((key) => { - if (typeof dataObj[key] === 'string' && dataObj[key].startsWith('<')) { + newDataObj[key] = 0; + if (isCensored(dataObj[key])) { newDataObj[key] = 0; hasCensoredData = true; } else { newDataObj[key] = dataObj[key]; } }); + + // If clinical data hasn't returned yet, exit here + if (!clinical) { + return newDataObj; + } + + // Check the clinical results to see if we can fill in any censored data with real ones + Object.entries(clinical).forEach(([siteName, site]) => { + Object.keys(site.summary?.[dataKey]).forEach((key) => { + if (isObject) { + Object.keys(site.summary[dataKey]).forEach((innerKey) => { + if (isCensored(dataObj[transformer(siteName, key)][innerKey])) { + newDataObj[transformer(siteName, key)][innerKey] = site.summary[dataKey][innerKey]; + } + }); + } else if (isCensored(dataObj[transformer(siteName, key)])) { + newDataObj[transformer(site, key)] += site.summary[dataKey][key]; + } + }); + }); + if (hasCensoredData) { newDataObj[HAS_CENSORED_DATA_MARKER] = true; } @@ -48,10 +75,10 @@ function DataVisualization() { }; const dataVis = { - patients_per_cohort: handleCensoring(resultsContext?.patients_per_cohort) || {}, - diagnosis_age_count: handleCensoring(resultsContext?.diagnosis_age_count) || {}, - treatment_type_count: handleCensoring(resultsContext?.treatment_type_count) || {}, - primary_site_count: handleCensoring(resultsContext?.primary_site_count) || {} + patients_per_cohort: handleCensoring('patients_per_cohort', (site, _) => site, true) || {}, + diagnosis_age_count: handleCensoring('age_at_diagnosis', (_, age) => age.replace(/ Years$/, '')) || {}, + treatment_type_count: handleCensoring('treatment_type_count') || {}, + primary_site_count: handleCensoring('primary_site_count') || {} }; const theme = useTheme(); From af6c27623150d0f6719c94a2bbd6c7e9304b9267 Mon Sep 17 00:00:00 2001 From: fnguyen Date: Fri, 23 Aug 2024 16:44:54 -0400 Subject: [PATCH 3/3] Remove unused import --- src/views/clinicalGenomic/search/SearchHandler.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/views/clinicalGenomic/search/SearchHandler.js b/src/views/clinicalGenomic/search/SearchHandler.js index 4adde12e..5a049ba5 100644 --- a/src/views/clinicalGenomic/search/SearchHandler.js +++ b/src/views/clinicalGenomic/search/SearchHandler.js @@ -1,4 +1,4 @@ -import { useEffect, useState, useRef } from 'react'; +import { useEffect, useRef } from 'react'; import PropTypes from 'prop-types'; import { trackPromise } from 'react-promise-tracker';