Skip to content

Commit

Permalink
Expression Enrichments: replace MinBoxPlot with BoxScatterPlot
Browse files Browse the repository at this point in the history
  • Loading branch information
kalletlak committed Nov 15, 2019
1 parent be61dcc commit f149e2c
Show file tree
Hide file tree
Showing 17 changed files with 358 additions and 428 deletions.
37 changes: 23 additions & 14 deletions src/pages/groupComparison/ClinicalData.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ import {MakeMobxView} from "shared/components/MobxView";
import OverlapExclusionIndicator from "./OverlapExclusionIndicator";
import {RESERVED_CLINICAL_VALUE_COLORS} from "../../shared/lib/Colors";
import ErrorMessage from "../../shared/components/ErrorMessage";
import ComplexKeyMap from "shared/lib/complexKeyDataStructures/ComplexKeyMap";
import { Sample } from "shared/api/generated/CBioPortalAPI";

export interface IClinicalDataProps {
store: GroupComparisonStore
Expand Down Expand Up @@ -254,31 +256,38 @@ export default class ClinicalData extends React.Component<IClinicalDataProps, {}
}
});

private readonly groupSampleDataPromise = remoteData({
await: () => [this.props.store.sampleKeyToActiveGroups, this.props.store.uidToGroup, this.props.store._originalGroups],
public readonly groupSampleAxisData = remoteData({
await: () => [this.props.store.sampleSet, this.props.store.activeGroups],
invoke: async () => {
const categoryOrder = _.map(this.props.store._originalGroups.result!, group => group.nameWithOrdinal);
const axisData = { data: [], datatype: "string", categoryOrder } as IAxisData;
const uidToGroup = this.props.store.uidToGroup.result!;
if (this.highlightedRow) {
const axisData_Data = axisData.data;
_.forEach(this.props.store.sampleKeyToActiveGroups.result!, (groupUids, uniqueSampleKey)=>{
axisData_Data.push({
uniqueSampleKey,
value: groupUids.map(uid=>uidToGroup[uid].nameWithOrdinal),
const categoryOrder = _.map(this.props.store.activeGroups.result!, group => group.nameWithOrdinal);
const axisData = { data: [], datatype: "string", categoryOrder } as IStringAxisData;
const sampleSet = this.props.store.sampleSet.result || new ComplexKeyMap<Sample>();

axisData.data = _.reduce(this.props.store.activeGroups.result, (acc, group) => {
group.studies.forEach(studyEntry => {
studyEntry.samples.forEach(sampleId => {
if (sampleSet.has({ studyId: studyEntry.id, sampleId })) {
const uniqueSampleKey = sampleSet.get({ studyId: studyEntry.id, sampleId })!.uniqueSampleKey;
acc.push({
uniqueSampleKey,
value: group.nameWithOrdinal
});
}
});
});
}
return acc;
}, [] as { uniqueSampleKey: string, value: string }[]);

return Promise.resolve(axisData);
}
});

@computed get vertAxisDataPromise() {
return this.swapAxes ? this.groupSampleDataPromise : this.clinicalDataPromise;
return this.swapAxes ? this.groupSampleAxisData : this.clinicalDataPromise;
}

@computed get horzAxisDataPromise() {
return this.swapAxes ? this.clinicalDataPromise : this.groupSampleDataPromise;
return this.swapAxes ? this.clinicalDataPromise : this.groupSampleAxisData;
}

@computed get horzLabel() {
Expand Down
24 changes: 1 addition & 23 deletions src/pages/groupComparison/GroupComparisonStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ import {ISurvivalDescription} from "pages/resultsView/survival/SurvivalDescripti
import GroupComparisonURLWrapper from "./GroupComparisonURLWrapper";
import {CancerStudyQueryUrlParams} from "../../shared/components/query/QueryStore";
import {fetchAllReferenceGenomeGenes} from "shared/lib/StoreUtils";
import { IStringAxisData } from "pages/resultsView/plots/PlotsTabUtils";

export enum OverlapStrategy {
INCLUDE = "Include",
Expand Down Expand Up @@ -882,29 +883,6 @@ export default class GroupComparisonStore {
}
});

public readonly sampleKeyToActiveGroups = remoteData({
await:()=>[
this.activeGroups,
this.sampleSet
],
invoke:()=>{
const sampleKeyToGroups:{[sampleKey:string]:string[]} = {};
const sampleSet = this.sampleSet.result!;
for (const group of this.activeGroups.result!) {
for (const studyEntry of group.studies) {
for (const sampleId of studyEntry.samples) {
const sample = sampleSet.get({ studyId: studyEntry.id, sampleId });
if (sample) {
sampleKeyToGroups[sample.uniqueSampleKey] = sampleKeyToGroups[sample.uniqueSampleKey] || [];
sampleKeyToGroups[sample.uniqueSampleKey].push(group.uid);
}
}
}
}
return Promise.resolve(sampleKeyToGroups);
}
});

public readonly patientsVennPartition = remoteData({
await:()=>[
this._activeGroupsNotOverlapRemoved,
Expand Down
35 changes: 26 additions & 9 deletions src/pages/groupComparison/MRNAEnrichments.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as React from "react";
import {observer} from "mobx-react";
import autobind from "autobind-decorator";
import {MolecularProfile} from "../../shared/api/generated/CBioPortalAPI";
import {MolecularProfile, Sample} from "../../shared/api/generated/CBioPortalAPI";
import {MakeMobxView} from "../../shared/components/MobxView";
import EnrichmentsDataSetDropdown from "../resultsView/enrichments/EnrichmentsDataSetDropdown";
import LoadingIndicator from "../../shared/components/loadingIndicator/LoadingIndicator";
Expand All @@ -10,6 +10,7 @@ import GroupComparisonStore from "./GroupComparisonStore";
import ExpressionEnrichmentContainer from "../resultsView/enrichments/ExpressionEnrichmentsContainer";
import {MakeEnrichmentsTabUI, getNumSamples} from "./GroupComparisonUtils";
import { remoteData } from "cbioportal-frontend-commons";
import ComplexKeyMap from "shared/lib/complexKeyDataStructures/ComplexKeyMap";

export interface IMRNAEnrichmentsProps {
store: GroupComparisonStore
Expand All @@ -23,14 +24,28 @@ export default class MRNAEnrichments extends React.Component<IMRNAEnrichmentsPro
}

private readonly enrichmentAnalysisGroups = remoteData({
await: () => [this.props.store.activeGroups],
await: () => [this.props.store.activeGroups, this.props.store.sampleSet],
invoke: () => {
const groups = this.props.store.activeGroups.result!.map(group => ({
name: group.nameWithOrdinal,
description: `samples in ${group.nameWithOrdinal}`,
count: getNumSamples(group),
color: group.color
}));
const sampleSet = this.props.store.sampleSet.result || new ComplexKeyMap<Sample>();
const groups = this.props.store.activeGroups.result!.map(group => {
const uniqueSampleKeys: string[] = [];
group.studies.forEach(studyEntry => {
const studyId = studyEntry.id;
studyEntry.samples.forEach(sampleId => {
if (sampleSet.has({ studyId: studyId, sampleId })) {
const uniqueSampleKey = sampleSet.get({ studyId: studyId, sampleId })!.uniqueSampleKey;
uniqueSampleKeys.push(uniqueSampleKey);
}
});
});
return {
name: group.nameWithOrdinal,
description: `samples in ${group.nameWithOrdinal}`,
count: getNumSamples(group),
color: group.color,
uniqueSampleKeys
}
});
return Promise.resolve(groups);
}
});
Expand All @@ -42,7 +57,8 @@ export default class MRNAEnrichments extends React.Component<IMRNAEnrichmentsPro
this.props.store.mRNAEnrichmentData,
this.props.store.selectedmRNAEnrichmentProfileMap,
this.enrichmentAnalysisGroups,
this.props.store.studies
this.props.store.studies,
this.props.store.sampleKeyToSample
],
render:()=>{
// since mRNA enrichments tab is enabled only for one study, selectedProteinEnrichmentProfileMap
Expand All @@ -63,6 +79,7 @@ export default class MRNAEnrichments extends React.Component<IMRNAEnrichmentsPro
groups={this.enrichmentAnalysisGroups.result}
selectedProfile={selectedProfile}
alteredVsUnalteredMode={false}
sampleKeyToSample={this.props.store.sampleKeyToSample.result!}
/>
</div>
);
Expand Down
30 changes: 23 additions & 7 deletions src/pages/groupComparison/ProteinEnrichments.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import ErrorMessage from "../../shared/components/ErrorMessage";
import GroupComparisonStore from "./GroupComparisonStore";
import {MakeEnrichmentsTabUI, getNumSamples} from "./GroupComparisonUtils";
import { remoteData } from "cbioportal-frontend-commons";
import ComplexKeyMap from "shared/lib/complexKeyDataStructures/ComplexKeyMap";
import { Sample } from "shared/api/generated/CBioPortalAPIInternal";

export interface IProteinEnrichmentsProps {
store: GroupComparisonStore
Expand All @@ -23,14 +25,28 @@ export default class ProteinEnrichments extends React.Component<IProteinEnrichme
}

private readonly enrichmentAnalysisGroups = remoteData({
await: () => [this.props.store.activeGroups],
await: () => [this.props.store.activeGroups, this.props.store.sampleSet],
invoke: () => {
const groups = this.props.store.activeGroups.result!.map(group => ({
name: group.nameWithOrdinal,
description: `samples in ${group.nameWithOrdinal}`,
count: getNumSamples(group),
color: group.color
}));
const sampleSet = this.props.store.sampleSet.result || new ComplexKeyMap<Sample>();
const groups = this.props.store.activeGroups.result!.map(group => {
const uniqueSampleKeys: string[] = [];
group.studies.forEach(studyEntry => {
const studyId = studyEntry.id;
studyEntry.samples.forEach(sampleId => {
if (sampleSet.has({ studyId: studyId, sampleId })) {
const uniqueSampleKey = sampleSet.get({ studyId: studyId, sampleId })!.uniqueSampleKey;
uniqueSampleKeys.push(uniqueSampleKey);
}
});
});
return {
name: group.nameWithOrdinal,
description: `samples in ${group.nameWithOrdinal}`,
count: getNumSamples(group),
color: group.color,
uniqueSampleKeys
}
});
return Promise.resolve(groups);
}
});
Expand Down
1 change: 1 addition & 0 deletions src/pages/resultsView/ResultsViewPageStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ import {
} from 'pages/studyView/StudyViewPageStore';
import { IVirtualStudyProps } from 'pages/studyView/virtualStudy/VirtualStudy';
import { decideMolecularProfileSortingOrder } from './download/DownloadUtils';
import { IStringAxisData } from './plots/PlotsTabUtils';

type Optional<T> =
| { isApplicable: true; value: T }
Expand Down
1 change: 0 additions & 1 deletion src/pages/resultsView/enrichments/AddCheckedGenes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import DefaultTooltip from "public-lib/components/defaultTooltip/DefaultTooltip"

export interface IAddCheckedGenesProps {
checkedGenes: string[];
store: ResultsViewPageStore;
}

@observer
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ export default class AlterationEnrichmentContainer extends React.Component<IAlte
<div>
<div>
<h3>{this.props.headerName}</h3>
{this.props.store && <AddCheckedGenes checkedGenes={this.checkedGenes} store={this.props.store} />}
{this.props.store && <AddCheckedGenes checkedGenes={this.checkedGenes}/>}
</div>
<div className={styles.Checkboxes}>
<div style={{ width: 250, marginRight: 7 }} >
Expand Down
93 changes: 2 additions & 91 deletions src/pages/resultsView/enrichments/EnrichmentsUtil.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { assert } from 'chai';
import { calculateExpressionTendency,
formatPercentage, getAlterationScatterData, getExpressionScatterData,
getAlterationRowData, getExpressionRowData, getFilteredData, getBarChartTooltipContent, getBoxPlotScatterData,
getDownloadContent, getAlterationsTooltipContent, shortenGenesLabel, getBoxPlotModels, getAlterationEnrichmentColumns, getEnrichmentBarPlotData, getGeneListOptions
getAlterationRowData, getExpressionRowData, getFilteredData, getBarChartTooltipContent,
getAlterationsTooltipContent, shortenGenesLabel, getAlterationEnrichmentColumns, getEnrichmentBarPlotData, getGeneListOptions
} from "./EnrichmentsUtil";
import expect from 'expect';
import expectJSX from 'expect-jsx';
Expand Down Expand Up @@ -595,14 +595,6 @@ describe("EnrichmentsUtil", () => {
});
});

describe("#getDownloadContent()", () => {
it("returns correct download content", () => {
assert.equal(getDownloadContent(exampleBoxPlotScatterData, "EGFR", "acc_tcga_rna_seq_v2_mrna"), "Sample ID\tEGFR, " +
"acc_tcga_rna_seq_v2_mrna\tAlteration\nTCGA-OR-A5J1-01\t9.940678152790728\t\nTCGA-OR-A5J2-01\t8.34481740339671\t\n" +
"TCGA-OR-A5J3-01\t9.660310790006957\t");
});
});

describe("#getAlterationsTooltipContent()", () => {
it("returns correct tooltip content", () => {
assert.equal(getAlterationsTooltipContent(exampleAlterations), "EGFR: MUT; AMP; ");
Expand All @@ -619,87 +611,6 @@ describe("EnrichmentsUtil", () => {
});
});

describe("#getBoxPlotModels()", () => {
it("returns correct boxplot model", () => {
assert.deepEqual(getBoxPlotModels(exampleBoxPlotScatterData.concat([
{
x: 1,
y: 5,
sampleId: "TCGA-OR-A5F1-01",
studyId: "acc_tcga",
alterations: ""
},
{
x: 1,
y: 4,
sampleId: "TCGA-OR-A5O1-01",
studyId: "acc_tcga",
alterations: ""
},
{
x: 1,
y: 7,
sampleId: "TCGA-OR-A5Q1-01",
studyId: "acc_tcga",
alterations: ""
}
])), [
{
q1: 4,
q2: 5,
q3: 5,
IQR: 1,
median: 5,
whiskerUpper: 6.5,
whiskerLower: 4,
max: 6.5,
min: 4,
outliersUpper: {
outliers: [],
suspectedOutliers: [7]
},
outliersLower: {
outliers: [],
suspectedOutliers: []
},
x: 1
},
{
q1: 8.34481740339671,
q2: 9.660310790006957,
q3: 9.660310790006957,
IQR: 1.315493386610246,
median: 9.660310790006957,
whiskerUpper: 9.940678152790728,
whiskerLower: 8.34481740339671,
max: 9.940678152790728,
min: 8.34481740339671,
outliersUpper: {
outliers: [],
suspectedOutliers: []
},
outliersLower: {
outliers: [],
suspectedOutliers: []
},
x: 2
}
]);
});
});

describe("#getBoxPlotScatterData()", () => {
it("returns correct box plot scatter data", () => {
const sampleAlterations = {
"VENHQS1PUi1BNUoxLTAxOmFjY190Y2dh": [],
"VENHQS1PUi1BNUoyLTAxOmFjY190Y2dh": [],
"VENHQS1PUi1BNUozLTAxOmFjY190Y2dh": []
}
assert.deepEqual(getBoxPlotScatterData(exampleMolecularData, "acc_tcga_rna_seq_v2_mrna", sampleAlterations, []),
exampleBoxPlotScatterData);
});
});

describe("#getGroupColumns()", () => {
it("returns correct group columns", () => {
assert.deepEqual(getAlterationEnrichmentColumns([]),[]);
Expand Down

0 comments on commit f149e2c

Please sign in to comment.