From a4264d800164e5856a3865f033a64fa94357b7cb Mon Sep 17 00:00:00 2001 From: Gaofei Zhao <15748980+dippindots@users.noreply.github.com> Date: Fri, 11 Oct 2024 10:29:45 -0400 Subject: [PATCH] Reduce api calls for generic assay meta in study view page --- src/pages/studyView/StudyViewPageStore.ts | 60 +++++++++---------- .../addChartButton/AddChartButton.tsx | 33 ++++------ .../GenericAssayCommonUtils.ts | 33 ++++++++++ 3 files changed, 73 insertions(+), 53 deletions(-) diff --git a/src/pages/studyView/StudyViewPageStore.ts b/src/pages/studyView/StudyViewPageStore.ts index cafc79680de..c8d0cb7efcd 100644 --- a/src/pages/studyView/StudyViewPageStore.ts +++ b/src/pages/studyView/StudyViewPageStore.ts @@ -284,8 +284,8 @@ import { CNA_HOMDEL_VALUE, } from 'pages/resultsView/enrichments/EnrichmentsUtil'; import { - fetchGenericAssayMetaByMolecularProfileIdsGroupByMolecularProfileId, fetchGenericAssayMetaByMolecularProfileIdsGroupedByGenericAssayType, + fetchGenericAssayMetaGroupedByMolecularProfileIdSuffix, } from 'shared/lib/GenericAssayUtils/GenericAssayCommonUtils'; import { buildDriverAnnotationSettings, @@ -6013,17 +6013,6 @@ export class StudyViewPageStore default: [], }); - readonly genericAssayEntitiesGroupedByGenericAssayType = remoteData<{ - [genericAssayType: string]: GenericAssayMeta[]; - }>({ - await: () => [this.genericAssayProfiles], - invoke: async () => { - return await fetchGenericAssayMetaByMolecularProfileIdsGroupedByGenericAssayType( - this.genericAssayProfiles.result - ); - }, - }); - readonly genericAssayEntitiesGroupedByProfileId = remoteData<{ [profileId: string]: GenericAssayMeta[]; }>({ @@ -6035,20 +6024,13 @@ export class StudyViewPageStore }, }); - readonly genericAssayStableIdToMeta = remoteData<{ - [genericAssayStableId: string]: GenericAssayMeta; + readonly genericAssayEntitiesGroupedByProfileIdSuffix = remoteData<{ + [profileIdSuffix: string]: GenericAssayMeta[]; }>({ - await: () => [this.genericAssayEntitiesGroupedByGenericAssayType], - invoke: () => { - return Promise.resolve( - _.chain( - this.genericAssayEntitiesGroupedByGenericAssayType.result - ) - .values() - .flatten() - .uniqBy(meta => meta.stableId) - .keyBy(meta => meta.stableId) - .value() + await: () => [this.genericAssayProfiles], + invoke: async () => { + return await fetchGenericAssayMetaGroupedByMolecularProfileIdSuffix( + this.genericAssayProfiles.result ); }, }); @@ -6067,20 +6049,32 @@ export class StudyViewPageStore default: [], }); + readonly genericAssayProfilesGroupedByGenericAssayType = remoteData({ + await: () => [this.genericAssayProfiles], + invoke: () => { + return Promise.resolve( + _.groupBy( + this.genericAssayProfiles.result, + profile => profile.genericAssayType + ) + ); + }, + default: {}, + }); + readonly genericAssayProfileOptionsByType = remoteData({ await: () => [ - this.genericAssayProfiles, + this.genericAssayProfilesGroupedByGenericAssayType, this.molecularProfileSampleCountSet, ], invoke: () => { return Promise.resolve( - _.chain(this.genericAssayProfiles.result) - .filter( - profile => - profile.molecularAlterationType === - AlterationTypeConstants.GENERIC_ASSAY - ) - .groupBy(profile => profile.genericAssayType) + // Each Generic Assay Profile has a type "profile.genericAssayType" + // But one Generic Assay Type can then have different suffix, meaning they are the same Generic Assay Type but different kind of data + // Then we need to distinguish them using suffix of the profile id + _.chain( + this.genericAssayProfilesGroupedByGenericAssayType.result + ) .mapValues(profiles => { return _.chain(profiles) .groupBy(molecularProfile => diff --git a/src/pages/studyView/addChartButton/AddChartButton.tsx b/src/pages/studyView/addChartButton/AddChartButton.tsx index 0955e19b9fd..e8ea3e5ca7a 100644 --- a/src/pages/studyView/addChartButton/AddChartButton.tsx +++ b/src/pages/studyView/addChartButton/AddChartButton.tsx @@ -365,7 +365,7 @@ class AddChartTabs extends React.Component { return ( this.props.disableGenericAssayTabs || !this.props.store.genericAssayProfiles.isComplete || - !this.props.store.genericAssayEntitiesGroupedByProfileId + !this.props.store.genericAssayEntitiesGroupedByProfileIdSuffix .isComplete || (this.props.store.genericAssayProfiles.isComplete && _.isEmpty(this.props.store.genericAssayProfiles.result)) @@ -536,25 +536,17 @@ class AddChartTabs extends React.Component { // And one tab can only has one selected profile at a time // selectedGenericAssayProfileIdByType been initialzed at the begining // so we know we can always find a selected profile for each Generic Assay type - const molecularProfileIdsInType = - options.find( - option => - option.value === - this.selectedGenericAssayProfileIdByType.get(type) - )?.profileIds || []; - - const entityMap = molecularProfileIdsInType.reduce( - (acc, profileId) => { - this.props.store.genericAssayEntitiesGroupedByProfileId.result![ - profileId - ].forEach(meta => { - acc[meta.stableId] = meta; - }); - return acc; - }, - {} as { [stableId: string]: GenericAssayMeta } + const molecularProfileIdSuffix = this.selectedGenericAssayProfileIdByType.get( + type + )!; + + const entityMap = _.keyBy( + this.props.store + .genericAssayEntitiesGroupedByProfileIdSuffix.result![ + molecularProfileIdSuffix + ], + meta => meta.stableId ); - const genericAssayEntityOptions = _.map( entityMap, makeGenericAssayOption @@ -1158,7 +1150,8 @@ export default class AddChartButton extends React.Component< return ( this.props.store.genericAssayProfileOptionsByType.isPending || this.props.store.molecularProfileOptions.isPending || - this.props.store.genericAssayEntitiesGroupedByProfileId.isPending + this.props.store.genericAssayEntitiesGroupedByProfileIdSuffix + .isPending ); } diff --git a/src/shared/lib/GenericAssayUtils/GenericAssayCommonUtils.ts b/src/shared/lib/GenericAssayUtils/GenericAssayCommonUtils.ts index 9fbf8dc77f8..112f8780a99 100644 --- a/src/shared/lib/GenericAssayUtils/GenericAssayCommonUtils.ts +++ b/src/shared/lib/GenericAssayUtils/GenericAssayCommonUtils.ts @@ -18,6 +18,7 @@ import { GenericAssayTypeConstants, } from 'shared/lib/GenericAssayUtils/GenericAssayConfig'; import * as Pluralize from 'pluralize'; +import { getSuffixOfMolecularProfile } from 'shared/lib/molecularProfileUtils'; export const NOT_APPLICABLE_VALUE = 'NA'; export const COMMON_GENERIC_ASSAY_PROPERTY = { @@ -109,6 +110,38 @@ export async function fetchGenericAssayMetaByMolecularProfileIdsGroupByMolecular return genericAssayMetaGroupByMolecularProfileId; } +export async function fetchGenericAssayMetaGroupedByMolecularProfileIdSuffix( + genericAssayProfiles: MolecularProfile[] +) { + const genericAssayProfilesGroupedByProfileIdSuffix = _.groupBy( + genericAssayProfiles, + getSuffixOfMolecularProfile + ); + const profileSuffixes = _.keys( + genericAssayProfilesGroupedByProfileIdSuffix + ); + + const genericAssayMetaGroupedByProfileIdSuffix: { + [profileIdSuffix: string]: GenericAssayMeta[]; + } = {}; + + await Promise.all( + profileSuffixes.map(profileSuffix => + fetchGenericAssayMetaByProfileIds( + _.map( + genericAssayProfilesGroupedByProfileIdSuffix[profileSuffix], + profile => profile.molecularProfileId + ) + ).then(genericAssayMeta => { + genericAssayMetaGroupedByProfileIdSuffix[ + profileSuffix + ] = genericAssayMeta; + }) + ) + ); + return genericAssayMetaGroupedByProfileIdSuffix; +} + export function fetchGenericAssayMetaByProfileIds( genericAssayProfileIds: string[] ) {