Skip to content
1 change: 1 addition & 0 deletions src/pages/patientView/PatientViewPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ export class PatientViewPageInner extends React.Component<

this.patientViewPageStore = new PatientViewPageStore(
this.props.appStore,
this.urlWrapper,
this.urlWrapper.query.studyId!,
this.urlWrapper.query.caseId!,
this.urlWrapper.query.sampleId,
Expand Down
12 changes: 12 additions & 0 deletions src/pages/patientView/PatientViewPageTabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ import { HelpWidget } from 'shared/components/HelpWidget/HelpWidget';
import MutationTableWrapper from './mutation/MutationTableWrapper';
import { PatientViewPageInner } from 'pages/patientView/PatientViewPage';
import { Else, If } from 'react-if';
import PlotsTab from 'shared/components/plots/PlotsTab';
import { PatientViewPlotsTabWrapper } from './PatientViewPlotsTabWrapper';

export enum PatientViewPageTabs {
Summary = 'summary',
Expand All @@ -49,6 +51,7 @@ export enum PatientViewPageTabs {
TrialMatchTab = 'trialMatchTab',
MutationalSignatures = 'mutationalSignatures',
PathwayMapper = 'pathways',
Plots = 'plots',
}

export const PatientViewResourceTabPrefix = 'openResource_';
Expand Down Expand Up @@ -488,6 +491,15 @@ export function tabs(
</MSKTab>
);

tabs.push(
<MSKTab key={9} id={PatientViewPageTabs.Plots} linkText="Plots">
<PatientViewPlotsTabWrapper
store={pageComponent.patientViewPageStore}
urlWrapper={urlWrapper}
/>
</MSKTab>
);

tabs.push(
<MSKTab
key={8}
Expand Down
129 changes: 129 additions & 0 deletions src/pages/patientView/PatientViewPlotsTabWrapper.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
import * as React from 'react';
import { PatientViewPageStore } from './clinicalInformation/PatientViewPageStore';
import PatientViewUrlWrapper from './PatientViewUrlWrapper';
import { observer } from 'mobx-react';
import PlotsTab from 'shared/components/plots/PlotsTab';
import CohortSelector from 'shared/components/plots/CohortSelector';
import { SamplePointLabel } from 'shared/components/sampleLabel/SampleLabel';

export enum CohortOptions {
WholeStudy = 'WholeStudy',
CancerType = 'CancerType',
CancerTypeDetailed = 'CancerTypeDetailed',
}

export const PatientViewPlotsTabWrapper: React.FunctionComponent<{
store: PatientViewPageStore;
urlWrapper: PatientViewUrlWrapper;
}> = observer(function({ store, urlWrapper }) {
const cohortSelector = () => (
<CohortSelector
study={store.studies.result![0].name}
cancerTypes={
store.patientViewPlotsStore.highlightedCancerTypes.result
}
cancerTypesDetailed={
store.patientViewPlotsStore.highlightedDetailedCancerTypes
.result
}
cohortSelection={store.patientViewPlotsStore.cohortSelection}
handleCohortChange={store.patientViewPlotsStore.handleCohortChange}
/>
);

const customSamplePointComponent = (sampleId: string, mouseEvents: any) => (
<SamplePointLabel
label={(
store.sampleManager.result!.sampleIndex[sampleId] + 1
).toString()}
events={mouseEvents}
/>
);

return (
<PlotsTab
filteredSamplesByDetailedCancerType={
store.patientViewPlotsStore.filteredSamplesByDetailedCancerType
}
mutations={store.mutationData}
studies={store.studies}
molecularProfileIdSuffixToMolecularProfiles={
store.patientViewPlotsStore
.molecularProfileIdSuffixToMolecularProfiles
}
entrezGeneIdToGene={
store.patientViewPlotsStore.entrezGeneIdToGeneAll
}
sampleKeyToSample={store.patientViewPlotsStore.sampleSetByKey}
genes={store.patientViewPlotsStore.allGenes}
clinicalAttributes={store.patientViewPlotsStore.clinicalAttributes}
genesets={store.patientViewPlotsStore.genesets}
genericAssayEntitiesGroupByMolecularProfileId={
store.patientViewPlotsStore
.genericAssayEntitiesGroupedByProfileId
}
customAttributes={store.patientViewPlotsStore.customAttributes}
studyIds={store.patientViewPlotsStore.queriedPhysicalStudyIds}
molecularProfilesWithData={store.molecularProfilesInStudy}
molecularProfilesInStudies={store.molecularProfilesInStudy}
annotatedCnaCache={store.patientViewPlotsStore.annotatedCnaCache}
annotatedMutationCache={
store.patientViewPlotsStore.annotatedMutationCache
}
structuralVariantCache={
store.patientViewPlotsStore.structuralVariantCache
}
studyToMutationMolecularProfile={
store.patientViewPlotsStore.studyToMutationMolecularProfile
}
studyToMolecularProfileDiscreteCna={
store.patientViewPlotsStore.studyToMolecularProfileDiscreteCna
}
clinicalDataCache={store.patientViewPlotsStore.clinicalDataCache}
patientKeyToFilteredSamples={
store.patientViewPlotsStore.patientKeyToFilteredSamples
}
numericGeneMolecularDataCache={
store.patientViewPlotsStore.numericGeneMolecularDataCache
}
coverageInformation={
store.patientViewPlotsStore.coverageInformationForAllSamples
}
filteredSamples={store.patientViewPlotsStore.selectedCohortSamples}
genesetMolecularDataCache={
store.patientViewPlotsStore.genesetMolecularDataCache
}
genericAssayMolecularDataCache={
store.patientViewPlotsStore.genericAssayMolecularDataCache
}
studyToStructuralVariantMolecularProfile={
store.patientViewPlotsStore
.studyToStructuralVariantMolecularProfile
}
driverAnnotationSettings={
store.patientViewPlotsStore.driverAnnotationSettings
}
studyIdToStudy={store.studyIdToStudy.result}
structuralVariants={store.structuralVariantData.result}
hugoGeneSymbols={
store.patientViewPlotsStore.allHugoGeneSymbols.result
}
selectedGenericAssayEntitiesGroupByMolecularProfileId={
store.patientViewPlotsStore
.selectedGenericAssayEntitiesGroupByMolecularProfileId
}
molecularProfileIdToMolecularProfile={
store.molecularProfileIdToMolecularProfile
}
urlWrapper={urlWrapper}
hasNoQueriedGenes={true}
genePanelDataForAllProfiles={
store.patientViewPlotsStore.genePanelDataForAllProfiles.result
}
patients={store.patientViewPlotsStore.allPatientsInStudy}
highlightedSamples={store.sampleIds}
additionalControls={cohortSelector}
customSamplePointComponent={customSamplePointComponent}
/>
);
});
57 changes: 57 additions & 0 deletions src/pages/patientView/PatientViewUrlWrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,49 @@ export type PatientViewUrlQuery = {

showOnlySelectedMutationsInTable?: string;
};
plots_horz_selection: PlotsSelectionParam;
plots_vert_selection: PlotsSelectionParam;
plots_coloring_selection: PlotsColoringParam;
geneset_list: any;
generic_assay_groups: any;
};

export type PlotsSelectionParam = {
selectedGeneOption?: string;
selectedGenesetOption?: string;
selectedGenericAssayOption?: string;
dataType?: string;
selectedDataSourceOption?: string;
mutationCountBy?: string;
structuralVariantCountBy?: string;
logScale?: string;
};

const PlotsSelectionParamProps: Required<PlotsSelectionParam> = {
selectedGeneOption: '',
selectedGenesetOption: '',
selectedGenericAssayOption: '',
dataType: '',
selectedDataSourceOption: '',
mutationCountBy: '',
structuralVariantCountBy: '',
logScale: '',
};

export type PlotsColoringParam = {
selectedOption?: string;
logScale?: string;
colorByMutationType?: string;
colorByCopyNumber?: string;
colorBySv?: string;
};

const PlotsColoringParamProps: Required<PlotsColoringParam> = {
selectedOption: '',
logScale: '',
colorByMutationType: '',
colorByCopyNumber: '',
colorBySv: '',
};

export default class PatientViewUrlWrapper extends URLWrapper<
Expand Down Expand Up @@ -49,6 +92,20 @@ export default class PatientViewUrlWrapper extends URLWrapper<
showOnlySelectedMutationsInTable: '',
},
},
plots_horz_selection: {
isSessionProp: false,
nestedObjectProps: PlotsSelectionParamProps,
},
plots_vert_selection: {
isSessionProp: false,
nestedObjectProps: PlotsSelectionParamProps,
},
plots_coloring_selection: {
isSessionProp: false,
nestedObjectProps: PlotsColoringParamProps,
},
geneset_list: { isSessionProp: true },
generic_assay_groups: { isSessionProp: false },
});
makeObservable(this);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,19 @@ import {
} from './PatientViewPageStore';
import { assert } from 'chai';
import { AppStore } from '../../../AppStore';
import PatientViewUrlWrapper from '../PatientViewUrlWrapper';

describe('PatientViewPageStore', () => {
let store: PatientViewPageStore;
let urlWrapper: PatientViewUrlWrapper;

beforeAll(() => {
store = new PatientViewPageStore(new AppStore(), 'someId', '');
store = new PatientViewPageStore(
new AppStore(),
urlWrapper,
'someId',
''
);
});

it('if there are pdf items in response and their name starts with a given patientId, return collection, otherwise returns empty array', () => {
Expand Down
16 changes: 16 additions & 0 deletions src/pages/patientView/clinicalInformation/PatientViewPageStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,13 @@ import {
tumorTypeResolver,
evaluatePutativeDriverInfoWithHotspots,
evaluatePutativeDriverInfo,
IDataQueryFilter,
generateDataQueryFilter,
} from 'shared/lib/StoreUtils';
import {
computeGenePanelInformation,
CoverageInformation,
getCoverageInformation,
} from 'shared/lib/GenePanelUtils';
import {
fetchCivicGenes,
Expand Down Expand Up @@ -172,6 +175,7 @@ import {
TMB_H_THRESHOLD,
AlterationTypeConstants,
DataTypeConstants,
REQUEST_ARG_ENUM,
} from 'shared/constants';
import {
OTHER_BIOMARKER_HUGO_SYMBOL,
Expand All @@ -186,6 +190,7 @@ import {
import {
getGenericAssayMetaPropertyOrDefault,
getGenericAssayCategoryFromName,
fetchGenericAssayMetaByMolecularProfileIdsGroupByMolecularProfileId,
} from 'shared/lib/GenericAssayUtils/GenericAssayCommonUtils';
import { GenericAssayTypeConstants } from 'shared/lib/GenericAssayUtils/GenericAssayConfig';

Expand All @@ -201,6 +206,8 @@ import { buildNamespaceColumnConfig } from 'shared/components/namespaceColumns/n
import { SiteError } from 'shared/model/appMisc';
import { AnnotatedExtendedAlteration } from 'shared/model/AnnotatedExtendedAlteration';
import { CustomDriverNumericGeneMolecularData } from 'shared/model/CustomDriverNumericGeneMolecularData';
import PatientViewUrlWrapper from '../PatientViewUrlWrapper';
import { PatientViewPlotsStore } from './PatientViewPlotsStore';

type PageMode = 'patient' | 'sample';
type ResourceId = string;
Expand Down Expand Up @@ -323,6 +330,7 @@ function transformClinicalInformationToStoreShape(
export class PatientViewPageStore {
constructor(
private appStore: AppStore,
private urlWrapper: PatientViewUrlWrapper,
studyId: string,
patientId: string,
sampleId: string = '',
Expand All @@ -340,8 +348,16 @@ export class PatientViewPageStore {
this._sampleId = sampleId;

this.studyId = studyId;

this.patientViewPlotsStore = new PatientViewPlotsStore(
appStore,
urlWrapper,
this
);
}

public patientViewPlotsStore: PatientViewPlotsStore;

public internalClient: CBioPortalAPIInternal;

@observable public activeLocus: string | undefined;
Expand Down
Loading
Loading