Skip to content

Commit

Permalink
Add total mutations as clinical variable in plots tab
Browse files Browse the repository at this point in the history
  • Loading branch information
oplantalech committed Jul 19, 2018
1 parent 6205d15 commit cb61b40
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 41 deletions.
1 change: 1 addition & 0 deletions end-to-end-tests/specs/screenshot.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,7 @@ describe("plots tab screenshot tests", function() {
});
it("plots tab clinical vs molecular", function() {
browser.click('input[data-test="HorizontalAxisClinicalAttributeRadio"]');
browser.execute(function() { resultsViewPlotsTab.onHorizontalAxisClinicalAttributeSelect({ value: "AGE" }); });
waitForAndCheckPlotsTab();
});
it("plots tab clinical vs molecular boxplot", function() {
Expand Down
39 changes: 32 additions & 7 deletions src/pages/resultsView/plots/PlotsTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ export interface IPlotsTabProps {
store:ResultsViewPageStore;
};

export enum SpecialClinicalAttribute {
TotalMutations = "TOTAL_MUTATIONS",
}

const searchInputTimeoutMs = 600;

class PlotsTabScatterPlot extends ScatterPlot<IScatterPlotData> {}
Expand Down Expand Up @@ -420,21 +424,40 @@ export default class PlotsTab extends React.Component<IPlotsTabProps,{}> {

@computed get clinicalAttributeIdToClinicalAttribute():{[clinicalAttributeId:string]:ClinicalAttribute} {
if (this.props.store.clinicalAttributes.isComplete) {
return this.props.store.clinicalAttributes.result.reduce((map:{[clinicalAttributeId:string]:ClinicalAttribute}, next)=>{
map[next.clinicalAttributeId] = next;
return map;
}, {});
let _map: {[clinicalAttributeId: string]: ClinicalAttribute} = _.keyBy(this.props.store.clinicalAttributes.result, c=>c.clinicalAttributeId)
if (this.props.store.studyIds.isComplete) {
_map[SpecialClinicalAttribute.TotalMutations] = {
clinicalAttributeId: SpecialClinicalAttribute.TotalMutations,
datatype: "NUMBER",
description: "Total mutations",
displayName: "Total mutations",
patientAttribute: false,
priority: "1",
studyId: this.props.store.studyIds.result[0],
count: 0
};
};
return _map;
} else {
return {};
}
}

@computed get clinicalAttributeOptions() {
if (this.props.store.clinicalAttributes.isComplete) {
return this.props.store.clinicalAttributes.result.map(attribute=>({
let _clinicalAttributes: {value: string, label: string}[] = [];
_clinicalAttributes.push({
value: SpecialClinicalAttribute.TotalMutations,
label: "Total mutations"
});

this.props.store.clinicalAttributes.result.map(attribute=>(
_clinicalAttributes.push({
value: attribute.clinicalAttributeId,
label: attribute.displayName
}));
})));

return _clinicalAttributes;
} else {
return [];
}
Expand Down Expand Up @@ -585,6 +608,7 @@ export default class PlotsTab extends React.Component<IPlotsTabProps,{}> {
this.props.store.entrezGeneIdToGene,
this.props.store.clinicalDataCache,
this.props.store.numericGeneMolecularDataCache,
this.props.store.studyToMutationMolecularProfile
);
}

Expand All @@ -596,7 +620,8 @@ export default class PlotsTab extends React.Component<IPlotsTabProps,{}> {
this.props.store.patientKeyToSamples,
this.props.store.entrezGeneIdToGene,
this.props.store.clinicalDataCache,
this.props.store.numericGeneMolecularDataCache
this.props.store.numericGeneMolecularDataCache,
this.props.store.studyToMutationMolecularProfile
);
}

Expand Down
110 changes: 76 additions & 34 deletions src/pages/resultsView/plots/PlotsTabUtils.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {AxisMenuSelection, AxisType, ViewType} from "./PlotsTab";
import {AxisMenuSelection, AxisType, ViewType, SpecialClinicalAttribute} from "./PlotsTab";
import {MobxPromise} from "mobxpromise";
import {
CancerStudy,
Expand Down Expand Up @@ -30,6 +30,7 @@ import {IBoxScatterPlotData} from "../../../shared/components/plots/BoxScatterPl
import {AlterationTypeConstants, AnnotatedMutation} from "../ResultsViewPageStore";
import numeral from "numeral";
import {getUniqueSampleKeyToCategories} from "../../../shared/components/plots/TablePlotUtils";
import client from "../../../shared/api/cbioportalClientInstance";

export const molecularProfileTypeToDisplayType:{[s:string]:string} = {
"COPY_NUMBER_ALTERATION": "Copy Number",
Expand Down Expand Up @@ -306,44 +307,83 @@ function makeAxisDataPromise_Clinical(
attribute:ClinicalAttribute,
clinicalDataCache:MobxPromiseCache<ClinicalAttribute, ClinicalData[]>,
patientKeyToSamples:MobxPromise<{[uniquePatientKey:string]:Sample[]}>,
studyToMutationMolecularProfile: MobxPromise<{[studyId: string]: MolecularProfile}>
):MobxPromise<IAxisData> {
const promise = clinicalDataCache.get(attribute);
return remoteData({
await:()=>[promise, patientKeyToSamples],
invoke:()=>{
const _patientKeyToSamples = patientKeyToSamples.result!;
const data:ClinicalData[] = promise.result!;
const axisData:IAxisData = { data:[], datatype:attribute.datatype.toLowerCase() };
const shouldParseFloat = attribute.datatype.toLowerCase() === "number";
const axisData_Data = axisData.data;
if (attribute.patientAttribute) {
// produce sample data from patient clinical data
for (const d of data) {
const samples = _patientKeyToSamples[d.uniquePatientKey];
for (const sample of samples) {
let ret:MobxPromise<IAxisData>;
switch(attribute.clinicalAttributeId) {
case SpecialClinicalAttribute.TotalMutations:
let mutationCounts = remoteData({
await:()=>[patientKeyToSamples, studyToMutationMolecularProfile],
invoke:()=>{
const _patientKeyToSamples = patientKeyToSamples.result!;
const _studyToMutationMolecularProfile = studyToMutationMolecularProfile.result!;
// get all samples
let samples = _.flatten(_.values(_patientKeyToSamples));
// produce sample data from patient clinical data
let mutationCounts = client.fetchMutationCountsInMolecularProfileUsingPOST({
molecularProfileId: _studyToMutationMolecularProfile[attribute.studyId].molecularProfileId,
sampleIds: samples.map(s=>s.sampleId)
});
return Promise.resolve(mutationCounts);
}
});
ret = remoteData({
await:()=>[mutationCounts],
invoke:()=>{
const _mutationCounts = mutationCounts.result!;
const axisData:IAxisData = { data:[], datatype:attribute.datatype.toLowerCase() };
const axisData_Data = axisData.data;
for (const mutationCount of _mutationCounts) {
axisData_Data.push({
uniqueSampleKey: sample.uniqueSampleKey,
value: d.value,
uniqueSampleKey: mutationCount.uniqueSampleKey,
value: mutationCount.mutationCount,
});
}
return Promise.resolve(axisData);
}
} else {
// produce sample data from sample clinical data
for (const d of data) {
axisData_Data.push({
uniqueSampleKey: d.uniqueSampleKey,
value: d.value
});
}
}
if (shouldParseFloat) {
for (const d of axisData_Data) {
d.value = parseFloat(d.value as string); // we know its a string bc all clinical data comes back as string
});
break;
default:
ret = remoteData({
await:()=>[promise, patientKeyToSamples],
invoke:()=>{
const _patientKeyToSamples = patientKeyToSamples.result!;
const data:ClinicalData[] = promise.result!;
const axisData:IAxisData = { data:[], datatype:attribute.datatype.toLowerCase() };
const shouldParseFloat = attribute.datatype.toLowerCase() === "number";
const axisData_Data = axisData.data;
if (attribute.patientAttribute) {
// produce sample data from patient clinical data
for (const d of data) {
const samples = _patientKeyToSamples[d.uniquePatientKey];
for (const sample of samples) {
axisData_Data.push({
uniqueSampleKey: sample.uniqueSampleKey,
value: d.value,
});
}
}
} else {
// produce sample data from sample clinical data
for (const d of data) {
axisData_Data.push({
uniqueSampleKey: d.uniqueSampleKey,
value: d.value
});
}
}
if (shouldParseFloat) {
for (const d of axisData_Data) {
d.value = parseFloat(d.value as string); // we know its a string bc all clinical data comes back as string
}
}
return Promise.resolve(axisData);
}
}
return Promise.resolve(axisData);
}
});
});
break;
}
return ret;
}

function makeAxisDataPromise_Molecular(
Expand Down Expand Up @@ -393,15 +433,17 @@ export function makeAxisDataPromise(
patientKeyToSamples:MobxPromise<{[uniquePatientKey:string]:Sample[]}>,
entrezGeneIdToGene:MobxPromise<{[entrezGeneId:number]:Gene}>,
clinicalDataCache:MobxPromiseCache<ClinicalAttribute, ClinicalData[]>,
numericGeneMolecularDataCache:MobxPromiseCache<{entrezGeneId:number, molecularProfileId:string}, NumericGeneMolecularData[]>
numericGeneMolecularDataCache:MobxPromiseCache<{entrezGeneId:number, molecularProfileId:string}, NumericGeneMolecularData[]>,
studyToMutationMolecularProfile: MobxPromise<{[studyId: string]: MolecularProfile}>

):MobxPromise<IAxisData> {

let ret:MobxPromise<IAxisData> = remoteData(()=>new Promise<IAxisData>(()=>0)); // always isPending
switch (selection.axisType) {
case AxisType.clinicalAttribute:
if (selection.clinicalAttributeId !== undefined) {
const attribute = clinicalAttributeIdToClinicalAttribute[selection.clinicalAttributeId];
ret = makeAxisDataPromise_Clinical(attribute, clinicalDataCache, patientKeyToSamples);
ret = makeAxisDataPromise_Clinical(attribute, clinicalDataCache, patientKeyToSamples, studyToMutationMolecularProfile);
}
break;
case AxisType.molecularProfile:
Expand Down

0 comments on commit cb61b40

Please sign in to comment.