From 57c824e35bbf401c3055972c4c248eae6c88deda Mon Sep 17 00:00:00 2001 From: Ali Mourey <90707472+alimourey@users.noreply.github.com> Date: Thu, 1 Aug 2024 20:55:59 -0400 Subject: [PATCH 1/4] Add drug counts to data page data availability graph --- frontend/packages/portal-frontend/src/dAPI.ts | 1 + .../components/DataAvailabilityPlot.tsx | 19 ++++++++- .../src/dataPage/components/DataPage.tsx | 6 +++ .../components/DataPageDatatypeSelector.tsx | 27 +++++++++++- .../src/dataPage/components/utils.ts | 2 +- .../src/dataPage/models/types.ts | 2 + .../dataPage/styles/DataAvailabilityPlot.scss | 20 +++------ .../src/plot/components/Heatmap.tsx | 2 +- portal-backend/depmap/data_page/api.py | 32 +++++++++++++++ portal-backend/tests/conftest.py | 5 +++ .../data_page/test_all_data_avail_partial.csv | 5 ++- .../tests/depmap/data_page/test_api.py | 41 +++++++++++++++++-- 12 files changed, 140 insertions(+), 22 deletions(-) diff --git a/frontend/packages/portal-frontend/src/dAPI.ts b/frontend/packages/portal-frontend/src/dAPI.ts index 342a5059..506fac02 100644 --- a/frontend/packages/portal-frontend/src/dAPI.ts +++ b/frontend/packages/portal-frontend/src/dAPI.ts @@ -657,6 +657,7 @@ export class DepmapApi { // mapped to color category integers. The integer maps to Heatmap.tsx's // color scale. data_type_url_mapping: boolSummary.data_type_url_mapping, + drug_count_mapping: boolSummary.drug_count_mapping, values: dataAvailVals, data_types: boolSummary.data_types, }; diff --git a/frontend/packages/portal-frontend/src/dataPage/components/DataAvailabilityPlot.tsx b/frontend/packages/portal-frontend/src/dataPage/components/DataAvailabilityPlot.tsx index a7b84fba..b027ad26 100644 --- a/frontend/packages/portal-frontend/src/dataPage/components/DataAvailabilityPlot.tsx +++ b/frontend/packages/portal-frontend/src/dataPage/components/DataAvailabilityPlot.tsx @@ -97,6 +97,22 @@ const DataAvailabilityPlot = ({ return graphSectionUrlMapping; }; + + const getDrugCountMapping = (categoryKey: string) => { + const graphSectionDrugCountMapping: { + [key: string]: number | undefined; + } = {}; + dataValuesByDataTypeCategory[categoryKey].forEach((category: any) => { + const dataTypeString = getDataPageDataTypeString(category.dataType); + + const count = + currentReleaseDataAvil.drug_count_mapping[category.dataType]; + + graphSectionDrugCountMapping[dataTypeString] = count; + }); + + return graphSectionDrugCountMapping; + }; return (
{dataValuesByDataTypeCategory && ( @@ -112,6 +128,7 @@ const DataAvailabilityPlot = ({ (category: any) => category.dataType )} dataTypeUrlMapping={getDataTypeUrlMapping(categoryKey)} + drugCountMapping={getDrugCountMapping(categoryKey)} dataTypeGroupName={categoryKey} isCurrentRelease={isCurrentRelease} /> @@ -131,7 +148,7 @@ const DataAvailabilityPlot = ({ BAR_THICKNESS * dataValuesByDataTypeCategory[categoryKey].length } - customWidth={400} + customWidth={350} customColorScale={COLOR_SCALE} margin={{ l: 0, diff --git a/frontend/packages/portal-frontend/src/dataPage/components/DataPage.tsx b/frontend/packages/portal-frontend/src/dataPage/components/DataPage.tsx index e63b86a7..1b0dcbc0 100644 --- a/frontend/packages/portal-frontend/src/dataPage/components/DataPage.tsx +++ b/frontend/packages/portal-frontend/src/dataPage/components/DataPage.tsx @@ -33,6 +33,7 @@ export const DataPage = ({ const [allDataAvail, setAllDataAvail] = useState({ all_depmap_ids: [], data_type_url_mapping: {}, + drug_count_mapping: {}, data_types: [], values: [], }); @@ -42,6 +43,7 @@ export const DataPage = ({ ] = useState({ all_depmap_ids: [], data_type_url_mapping: {}, + drug_count_mapping: {}, data_types: [], values: [], }); @@ -65,18 +67,22 @@ export const DataPage = ({ const currentDataValues: number[][] = []; const currentDataTypes: string[] = []; const currentDataTypeUrlMapping: { [key: string]: string } = {}; + const currentDataTypeDrugCountMapping: { [key: string]: number } = {}; dataAvail.data_types.forEach((data_type: string, index: number) => { if (currentReleaseDatasets.includes(data_type)) { currentDataTypes.push(data_type); currentDataValues.push(dataAvail.values[index]); currentDataTypeUrlMapping[data_type] = dataAvail.data_type_url_mapping[data_type]; + currentDataTypeDrugCountMapping[data_type] = + dataAvail.drug_count_mapping[data_type]; } }); setCurrentReleaseDataAvail({ all_depmap_ids: dataAvail.all_depmap_ids, data_type_url_mapping: currentDataTypeUrlMapping, + drug_count_mapping: currentDataTypeDrugCountMapping, data_types: currentDataTypes, values: currentDataValues, }); diff --git a/frontend/packages/portal-frontend/src/dataPage/components/DataPageDatatypeSelector.tsx b/frontend/packages/portal-frontend/src/dataPage/components/DataPageDatatypeSelector.tsx index e369694d..4d533316 100644 --- a/frontend/packages/portal-frontend/src/dataPage/components/DataPageDatatypeSelector.tsx +++ b/frontend/packages/portal-frontend/src/dataPage/components/DataPageDatatypeSelector.tsx @@ -7,6 +7,7 @@ interface Props { datatypes: string[]; dataTypeGroupName: string; dataTypeUrlMapping: { [key: string]: string | undefined }; + drugCountMapping: { [data_type: string]: number | undefined }; isCurrentRelease: boolean; } @@ -14,10 +15,23 @@ const DataPageDatatypeSelector = ({ datatypes, dataTypeGroupName, dataTypeUrlMapping, + drugCountMapping, isCurrentRelease, }: Props) => { const display: any = []; + const getDrugCountLabel = (dataType: string) => { + if ( + Object.keys(drugCountMapping).includes(dataType) && + drugCountMapping[dataType] !== null && + drugCountMapping[dataType] !== undefined + ) { + return `(${drugCountMapping[dataType]} drugs)`; + } + + return ""; + }; + // If the data type is in the current release, add an asterisk. const getDataTypeLabel = ( dataType: string, @@ -37,6 +51,15 @@ const DataPageDatatypeSelector = ({ ); const inCurrentRelease = currentReleaseDatasets.includes(datatype); + if (!isCurrentRelease) { + console.log("datatype"); + console.log(datatype); + console.log("dataTypeDisplayName"); + console.log(dataTypeDisplayName); + console.log("dataTypeUrlMapping"); + console.log(dataTypeUrlMapping); + } + display.push(
{Object.keys(dataTypeUrlMapping).includes(dataTypeDisplayName) && @@ -47,7 +70,9 @@ const DataPageDatatypeSelector = ({ target="_blank" rel="noreferrer" > - {getDataTypeLabel(dataTypeDisplayName, inCurrentRelease)} + {`${getDataTypeLabel(dataTypeDisplayName, inCurrentRelease)}`} +
+ {getDrugCountLabel(dataTypeDisplayName)} ) : (

{getDataTypeLabel(dataTypeDisplayName, inCurrentRelease)}

diff --git a/frontend/packages/portal-frontend/src/dataPage/components/utils.ts b/frontend/packages/portal-frontend/src/dataPage/components/utils.ts index 56df0bbd..e991c08f 100644 --- a/frontend/packages/portal-frontend/src/dataPage/components/utils.ts +++ b/frontend/packages/portal-frontend/src/dataPage/components/utils.ts @@ -1,4 +1,4 @@ -export const BAR_THICKNESS = 42; +export const BAR_THICKNESS = 43; export const currentReleaseDatasets = [ "Sequencing_WES_Broad", diff --git a/frontend/packages/portal-frontend/src/dataPage/models/types.ts b/frontend/packages/portal-frontend/src/dataPage/models/types.ts index 98635aa8..e16c0cf4 100644 --- a/frontend/packages/portal-frontend/src/dataPage/models/types.ts +++ b/frontend/packages/portal-frontend/src/dataPage/models/types.ts @@ -21,6 +21,7 @@ export const COLOR_SCALE = [ export interface DataAvailSummary { all_depmap_ids: [number, string][]; data_type_url_mapping: { [data_type: string]: string }; + drug_count_mapping: { [data_type: string]: number }; data_types: string[]; values: boolean[][]; } @@ -38,6 +39,7 @@ export interface DataSummary { export interface DataAvailability { all_depmap_ids: [number, string][]; data_type_url_mapping: { [data_type: string]: string }; + drug_count_mapping: { [data_type: string]: number }; values: number[][]; data_types: string[]; } diff --git a/frontend/packages/portal-frontend/src/dataPage/styles/DataAvailabilityPlot.scss b/frontend/packages/portal-frontend/src/dataPage/styles/DataAvailabilityPlot.scss index ae234fa3..9baeb977 100644 --- a/frontend/packages/portal-frontend/src/dataPage/styles/DataAvailabilityPlot.scss +++ b/frontend/packages/portal-frontend/src/dataPage/styles/DataAvailabilityPlot.scss @@ -1,30 +1,22 @@ .dataAvailabilityPlotContainer { - width: 290px; - min-width: 290px; + width: 275px; + min-width: 275px; margin-top: 2px; border-bottom: 1px solid black; padding-bottom: 0px; margin-right: 8px; - @media (max-width: 910px) { - width: 200px; - min-width: 200px; - } .datatypeSelector { - margin-left: 5px; - font-size: 16px; - min-width: 101px; - - @media (max-width: 910px) { - font-size: 14px; - } + margin-left: 4px; + font-size: 14px; + min-width: 150px; .groupContainer { display: grid; grid-template-columns: repeat(2, 1fr); .groupLabel { grid-column: 1; - margin-right: 20px; + margin-right: 10px; align-self: normal; font-family: roboto; font-size: 16px; diff --git a/frontend/packages/portal-frontend/src/plot/components/Heatmap.tsx b/frontend/packages/portal-frontend/src/plot/components/Heatmap.tsx index a62fa93e..f117df46 100644 --- a/frontend/packages/portal-frontend/src/plot/components/Heatmap.tsx +++ b/frontend/packages/portal-frontend/src/plot/components/Heatmap.tsx @@ -107,7 +107,7 @@ function Heatmap({ height, margin, - width: 400, + width: customWidth, } : { title: "", diff --git a/portal-backend/depmap/data_page/api.py b/portal-backend/depmap/data_page/api.py index e8efe961..621e45f7 100644 --- a/portal-backend/depmap/data_page/api.py +++ b/portal-backend/depmap/data_page/api.py @@ -4,6 +4,7 @@ from depmap.download.utils import get_download_url from depmap.enums import BiomarkerEnum, DependencyEnum from flask_restplus import Namespace, Resource +from depmap.data_access import interface as data_access from flask import current_app import pandas as pd @@ -39,6 +40,33 @@ ] +def _get_drug_count_mapping(data_types: List[str]): + def _get_drug_count(dataset_name: str): + dataset = DependencyDataset.get_dataset_by_name(dataset_name) + + if not dataset: + return None + + return len(data_access.get_dataset_feature_ids_by_label(dataset_name)) + + drug_counts_by_data_type = { + "Drug_CTD_Broad": _get_drug_count(DependencyEnum.CTRP_AUC.name), + "Drug_Repurposing_Broad": _get_drug_count( + DependencyEnum.Rep_all_single_pt.name + ), + "Drug_GDSC_Sanger": _get_drug_count(DependencyEnum.GDSC2_AUC.name), + "Drug_OncRef_Broad": _get_drug_count(DependencyEnum.Prism_oncology_AUC.name), + } + + current_env_mapping = { + data_type_name: drug_count + for data_type_name, drug_count in drug_counts_by_data_type.items() + if data_type_name in data_types + } + + return current_env_mapping + + def _get_data_type_url_mapping(data_types: List[str]): def _get_dataset_url(dataset_name, isDependencyDataset=True) -> Union[str, None]: data_page_endpoint = "data_page.view_data_page" @@ -118,9 +146,12 @@ def _get_formatted_all_data_avail_df(overall_summary: pd.DataFrame) -> pd.DataFr def _format_data_availability_summary_dict(summary_df: pd.DataFrame): data_types_by_url = _get_data_type_url_mapping(summary_df.index.values.tolist()) + drug_count_mapping = _get_drug_count_mapping(summary_df.index.values.tolist()) + summary = { "values": [row.values.tolist() for _, row in summary_df.iterrows()], "data_type_url_mapping": data_types_by_url, + "drug_count_mapping": drug_count_mapping, # For keeping track of data_type order "data_types": summary_df.index.values.tolist(), } @@ -145,4 +176,5 @@ def get(self): all_data_df = _get_all_data_avail_df() formatted_df = _get_formatted_all_data_avail_df(all_data_df) all_data_dict = _format_data_availability_summary_dict(formatted_df) + return all_data_dict diff --git a/portal-backend/tests/conftest.py b/portal-backend/tests/conftest.py index 15100daa..b12e7148 100755 --- a/portal-backend/tests/conftest.py +++ b/portal-backend/tests/conftest.py @@ -186,6 +186,11 @@ def _get_mutations_taiga_id(cls): return "this-is-test-nonsense-that-should-never-be-checked-against.1/except-for-taiga-alias-loading" +class InteractiveConfigFakeDrugDataset(InteractiveConfig): + def is_standard(self, dataset_id): + return True + + class DefaultDictMock(defaultdict): def __contains__(self, item): """ diff --git a/portal-backend/tests/depmap/data_page/test_all_data_avail_partial.csv b/portal-backend/tests/depmap/data_page/test_all_data_avail_partial.csv index ef293048..179cdb9f 100644 --- a/portal-backend/tests/depmap/data_page/test_all_data_avail_partial.csv +++ b/portal-backend/tests/depmap/data_page/test_all_data_avail_partial.csv @@ -1,2 +1,5 @@ ModelID,Drug_CTD_Broad,Drug_Repurposing_Broad,CRISPR_Achilles_Broad -ACH-000019,True,False,True \ No newline at end of file +ACH-000019,False,False,True +ACH-000020,True,False,False +ACH-000021,True,False,False +ACH-000022,True,False,False \ No newline at end of file diff --git a/portal-backend/tests/depmap/data_page/test_api.py b/portal-backend/tests/depmap/data_page/test_api.py index 06440138..6c618653 100644 --- a/portal-backend/tests/depmap/data_page/test_api.py +++ b/portal-backend/tests/depmap/data_page/test_api.py @@ -6,8 +6,12 @@ DependencyDatasetFactory, DepmapModelFactory, GeneFactory, + CompoundFactory, + CompoundExperimentFactory, MatrixFactory, ) +import numpy as np +from tests.utilities import interactive_test_utils def test_get_data_availability(populated_db): @@ -19,6 +23,7 @@ def test_get_data_availability(populated_db): assert list(data_availablity.keys()) == [ "values", "data_type_url_mapping", + "drug_count_mapping", "data_types", "all_depmap_ids", ] @@ -65,7 +70,23 @@ def test_get_data_availability_not_all_data_types_present( ) dataset = DependencyDatasetFactory(matrix=matrix, name=dataset_name, priority=1,) + drug_dataset_name = DependencyDataset.DependencyEnum.CTRP_AUC + cell_lines = [ + DepmapModelFactory(model_id="ACH-000020"), + DepmapModelFactory(model_id="ACH-000021"), + DepmapModelFactory(model_id="ACH-000022"), + ] + compounds = [CompoundFactory() for _ in range(3)] + compound_experiments = [CompoundExperimentFactory(compound=c) for c in compounds] + matrix = MatrixFactory( + data=[[2, 3, 4], [0, 2, 1], [np.NaN, np.NaN, np.NaN]], + cell_lines=cell_lines, + entities=compound_experiments, + using_depmap_model_table=True, + ) + DependencyDatasetFactory(matrix=matrix, name=drug_dataset_name, priority=1) empty_db_mock_downloads.session.flush() + interactive_test_utils.reload_interactive_config() def mock_get_all_data_avail_df(): with open( @@ -77,16 +98,25 @@ def mock_get_all_data_avail_df(): monkeypatch.setattr( data_page_api, "_get_all_data_avail_df", mock_get_all_data_avail_df ) + with empty_db_mock_downloads.app.test_client() as c: r = c.get( url_for("api.data_page_data_availability"), content_type="application/json", ) data_availability = r.json assert data_availability == { - "values": [[True], [True], [False]], + "values": [ + [True, False, False, False], + [False, True, True, True], + [False, False, False, False], + ], "data_type_url_mapping": { "CRISPR_Achilles_Broad": "/data_page/?release=test+name+version&file=test+file+name+2", - "Drug_CTD_Broad": None, + "Drug_CTD_Broad": "/data_page/?release=test+name+version&file=test+file+name+2", + "Drug_Repurposing_Broad": None, + }, + "drug_count_mapping": { + "Drug_CTD_Broad": 3, "Drug_Repurposing_Broad": None, }, "data_types": [ @@ -94,5 +124,10 @@ def mock_get_all_data_avail_df(): "Drug_CTD_Broad", "Drug_Repurposing_Broad", ], - "all_depmap_ids": [[0, "ACH-000019"]], + "all_depmap_ids": [ + [0, "ACH-000019"], + [1, "ACH-000020"], + [2, "ACH-000021"], + [3, "ACH-000022"], + ], } From 5ed5a4a3a884c5b9a577e92e262fb9d1250ee4c5 Mon Sep 17 00:00:00 2001 From: Ali Mourey <90707472+alimourey@users.noreply.github.com> Date: Thu, 1 Aug 2024 20:59:11 -0400 Subject: [PATCH 2/4] Remove code that was just for debugging --- .../src/dataPage/components/DataPageDatatypeSelector.tsx | 9 --------- 1 file changed, 9 deletions(-) diff --git a/frontend/packages/portal-frontend/src/dataPage/components/DataPageDatatypeSelector.tsx b/frontend/packages/portal-frontend/src/dataPage/components/DataPageDatatypeSelector.tsx index 4d533316..330fcf30 100644 --- a/frontend/packages/portal-frontend/src/dataPage/components/DataPageDatatypeSelector.tsx +++ b/frontend/packages/portal-frontend/src/dataPage/components/DataPageDatatypeSelector.tsx @@ -51,15 +51,6 @@ const DataPageDatatypeSelector = ({ ); const inCurrentRelease = currentReleaseDatasets.includes(datatype); - if (!isCurrentRelease) { - console.log("datatype"); - console.log(datatype); - console.log("dataTypeDisplayName"); - console.log(dataTypeDisplayName); - console.log("dataTypeUrlMapping"); - console.log(dataTypeUrlMapping); - } - display.push(
{Object.keys(dataTypeUrlMapping).includes(dataTypeDisplayName) && From 771b4b5d041ae01d16cfd358976c44119201e204 Mon Sep 17 00:00:00 2001 From: Ali Mourey <90707472+alimourey@users.noreply.github.com> Date: Thu, 1 Aug 2024 21:00:00 -0400 Subject: [PATCH 3/4] Remove experimental code --- portal-backend/tests/conftest.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/portal-backend/tests/conftest.py b/portal-backend/tests/conftest.py index b12e7148..15100daa 100755 --- a/portal-backend/tests/conftest.py +++ b/portal-backend/tests/conftest.py @@ -186,11 +186,6 @@ def _get_mutations_taiga_id(cls): return "this-is-test-nonsense-that-should-never-be-checked-against.1/except-for-taiga-alias-loading" -class InteractiveConfigFakeDrugDataset(InteractiveConfig): - def is_standard(self, dataset_id): - return True - - class DefaultDictMock(defaultdict): def __contains__(self, item): """ From 99581d45398ae1001e91a243c83854eebb63d1f0 Mon Sep 17 00:00:00 2001 From: Ali Mourey <90707472+alimourey@users.noreply.github.com> Date: Thu, 1 Aug 2024 21:02:16 -0400 Subject: [PATCH 4/4] Add drug counts even if not in current release --- .../src/dataPage/components/DataPageDatatypeSelector.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/frontend/packages/portal-frontend/src/dataPage/components/DataPageDatatypeSelector.tsx b/frontend/packages/portal-frontend/src/dataPage/components/DataPageDatatypeSelector.tsx index 330fcf30..2d2e7d49 100644 --- a/frontend/packages/portal-frontend/src/dataPage/components/DataPageDatatypeSelector.tsx +++ b/frontend/packages/portal-frontend/src/dataPage/components/DataPageDatatypeSelector.tsx @@ -66,7 +66,10 @@ const DataPageDatatypeSelector = ({ {getDrugCountLabel(dataTypeDisplayName)} ) : ( -

{getDataTypeLabel(dataTypeDisplayName, inCurrentRelease)}

+

+ {getDataTypeLabel(dataTypeDisplayName, inCurrentRelease)}
+ {getDrugCountLabel(dataTypeDisplayName)} +

)}
);