Skip to content

Commit

Permalink
Merge pull request #3010 from kalletlak/fix-7046
Browse files Browse the repository at this point in the history
Study view: support old chart Ids when retrieving user preference settings

Former-commit-id: 1d4aec541e08bdec851f9a508c5f959c3eaa85f9
  • Loading branch information
alisman authored Jan 30, 2020
2 parents 0a2245e + acf2436 commit 5d8bc8b
Show file tree
Hide file tree
Showing 3 changed files with 168 additions and 61 deletions.
68 changes: 7 additions & 61 deletions src/pages/studyView/StudyViewPageStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ import {
getFilteredAndCompressedDataIntervalFilters,
getUniqueKeyFromMolecularProfileIds,
getMolecularProfileIdsFromUniqueKey,
getClinicalDataBySamples,
updateSavedUserPreferenceChartIds,
} from './StudyViewUtils';
import MobxPromise from 'mobxpromise';
import { SingleGeneQuery } from 'shared/lib/oql/oql-parser';
Expand Down Expand Up @@ -2198,62 +2200,6 @@ export class StudyViewPageStore {
return this.clinicalDataBinPromises[uniqueKey];
}

private async getClinicalDataBySamples(samples: Sample[]) {
let clinicalData: {
[sampleId: string]: { [attributeId: string]: string };
} = {};

let sampleClinicalData = await defaultClient.fetchClinicalDataUsingPOST(
{
clinicalDataType: 'SAMPLE',
clinicalDataMultiStudyFilter: {
identifiers: _.map(samples, sample => {
return {
entityId: sample.sampleId,
studyId: sample.studyId,
};
}),
} as ClinicalDataMultiStudyFilter,
}
);

_.forEach(sampleClinicalData, item => {
clinicalData[item.uniqueSampleKey] = {
...(clinicalData[item.uniqueSampleKey] || {}),
[item.clinicalAttributeId]: item.value,
};
});

let patientClinicalData = await defaultClient.fetchClinicalDataUsingPOST(
{
clinicalDataType: ClinicalDataTypeEnum.PATIENT,
clinicalDataMultiStudyFilter: {
identifiers: _.map(samples, sample => {
return {
entityId: sample.patientId,
studyId: sample.studyId,
};
}),
} as ClinicalDataMultiStudyFilter,
}
);

const patientSamplesMap = _.groupBy(
samples,
sample => sample.uniquePatientKey
);

_.forEach(patientClinicalData, item => {
(patientSamplesMap[item.uniquePatientKey] || []).forEach(sample => {
clinicalData[sample.uniqueSampleKey] = {
...(clinicalData[sample.uniqueSampleKey] || {}),
[item.clinicalAttributeId]: item.value,
};
});
});
return clinicalData;
}

readonly molecularProfiles = remoteData<MolecularProfile[]>({
await: () => [this.queriedPhysicalStudyIds],
invoke: async () => {
Expand Down Expand Up @@ -3198,7 +3144,9 @@ export class StudyViewPageStore {
toJS(this.studyIds)
);
if (userSettings) {
return userSettings.chartSettings || [];
return updateSavedUserPreferenceChartIds(
userSettings.chartSettings
);
}
}
return [];
Expand Down Expand Up @@ -4734,9 +4682,7 @@ export class StudyViewPageStore {
invoke: async () => {
let sampleClinicalDataMap: {
[attributeId: string]: { [attributeId: string]: string };
} = await this.getClinicalDataBySamples(
this.selectedSamples.result
);
} = await getClinicalDataBySamples(this.selectedSamples.result);
return _.reduce(
this.selectedSamples.result,
(acc, next) => {
Expand Down Expand Up @@ -4998,7 +4944,7 @@ export class StudyViewPageStore {

@autobind
public async getDownloadDataPromise() {
let sampleClinicalDataMap = await this.getClinicalDataBySamples(
let sampleClinicalDataMap = await getClinicalDataBySamples(
this.selectedSamples.result
);

Expand Down
60 changes: 60 additions & 0 deletions src/pages/studyView/StudyViewUtils.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ import {
getBinName,
getGroupedClinicalDataByBins,
getFilteredAndCompressedDataIntervalFilters,
updateSavedUserPreferenceChartIds,
} from 'pages/studyView/StudyViewUtils';
import {
DataBin,
Expand Down Expand Up @@ -82,6 +83,7 @@ import {
} from 'shared/lib/Colors';
import { IStudyViewDensityScatterPlotDatum } from './charts/scatterPlot/StudyViewDensityScatterPlot';
import { shallow } from 'enzyme';
import { ChartUserSetting } from './StudyViewPageStore';

describe('StudyViewUtils', () => {
const emptyStudyViewFilter: StudyViewFilter = {
Expand Down Expand Up @@ -3328,4 +3330,62 @@ describe('StudyViewUtils', () => {
);
});
});

describe('updateChartIds', () => {
const chartSetting1: ChartUserSetting = {
id: 'SAMPLE_CANCER_TYPE',
chartType: 'PIE_CHART',
layout: {
x: 0,
y: 0,
w: 1,
h: 1,
},
patientAttribute: false,
};
const chartSetting2: ChartUserSetting = {
id: 'SAMPLE_SAMPLE_TYPE',
chartType: 'PIE_CHART',
layout: {
x: 0,
y: 0,
w: 1,
h: 1,
},
patientAttribute: false,
};

it('should return correct chart settings', () => {
assert.deepEqual(
updateSavedUserPreferenceChartIds([chartSetting1]),
[{ ...chartSetting1, id: 'CANCER_TYPE' }]
);
assert.deepEqual(
updateSavedUserPreferenceChartIds([
{ ...chartSetting1, id: 'CANCER_TYPE' },
]),
[{ ...chartSetting1, id: 'CANCER_TYPE' }]
);
assert.deepEqual(
updateSavedUserPreferenceChartIds([
chartSetting1,
chartSetting2,
]),
[
{ ...chartSetting1, id: 'CANCER_TYPE' },
{ ...chartSetting2, id: 'SAMPLE_TYPE' },
]
);
assert.deepEqual(
updateSavedUserPreferenceChartIds([
{ ...chartSetting1, id: 'CANCER_TYPE' },
{ ...chartSetting2, id: 'SAMPLE_TYPE' },
]),
[
{ ...chartSetting1, id: 'CANCER_TYPE' },
{ ...chartSetting2, id: 'SAMPLE_TYPE' },
]
);
});
});
});
101 changes: 101 additions & 0 deletions src/pages/studyView/StudyViewUtils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
PatientIdentifier,
Sample,
ClinicalData,
ClinicalDataMultiStudyFilter,
} from 'shared/api/generated/CBioPortalAPI';
import * as React from 'react';
import { buildCBioPortalPageUrl } from '../../shared/api/urls';
Expand Down Expand Up @@ -2417,3 +2418,103 @@ export function getFilteredAndCompressedDataIntervalFilters(
: undefined;
return { start, end } as any;
}

export async function getClinicalDataBySamples(samples: Sample[]) {
let clinicalData: {
[sampleId: string]: { [attributeId: string]: string };
} = {};

let sampleClinicalData = await defaultClient.fetchClinicalDataUsingPOST({
clinicalDataType: 'SAMPLE',
clinicalDataMultiStudyFilter: {
identifiers: _.map(samples, sample => {
return {
entityId: sample.sampleId,
studyId: sample.studyId,
};
}),
} as ClinicalDataMultiStudyFilter,
});

_.forEach(sampleClinicalData, item => {
clinicalData[item.uniqueSampleKey] = {
...(clinicalData[item.uniqueSampleKey] || {}),
[item.clinicalAttributeId]: item.value,
};
});

let patientClinicalData = await defaultClient.fetchClinicalDataUsingPOST({
clinicalDataType: ClinicalDataTypeEnum.PATIENT,
clinicalDataMultiStudyFilter: {
identifiers: _.map(samples, sample => {
return {
entityId: sample.patientId,
studyId: sample.studyId,
};
}),
} as ClinicalDataMultiStudyFilter,
});

const patientSamplesMap = _.groupBy(
samples,
sample => sample.uniquePatientKey
);

_.forEach(patientClinicalData, item => {
(patientSamplesMap[item.uniquePatientKey] || []).forEach(sample => {
clinicalData[sample.uniqueSampleKey] = {
...(clinicalData[sample.uniqueSampleKey] || {}),
[item.clinicalAttributeId]: item.value,
};
});
});
return clinicalData;
}

export function updateSavedUserPreferenceChartIds(
chartSettings: ChartUserSetting[]
): ChartUserSetting[] {
const customChartRegex = /^CUSTOM_FILTERS_\d+/i;
const chartIdWithDataTypeRegex = /^(?:PATIENT_|SAMPLE_)([a-zA-Z0-9_]+)/i;
let numberOfClinicalAttributeCharts = 0;
let numberOfChartRequiringUpdates = 0;
const specialChartKeySet = _.reduce(
UniqueKey,
(acc, next) => {
acc[next] = true;
return acc;
},
{} as { [id: string]: boolean }
);

chartSettings.forEach(chartSetting => {
let customChartmatch = chartSetting.id.match(customChartRegex);
if (
!customChartmatch &&
specialChartKeySet[chartSetting.id] === undefined
) {
numberOfClinicalAttributeCharts++;
let match = chartSetting.id.match(chartIdWithDataTypeRegex);
if (!!match) {
numberOfChartRequiringUpdates++;
}
}
});

// Some of the clinical attributes id contains SAMPLE_ or PATIENT_ prefix. Updating them would not show those charts.
// Only way is to check if the chart ids requires update is to see if the
// number of clinical attribute charts shown is same as the number of chart ids requiring updates
if (numberOfClinicalAttributeCharts === numberOfChartRequiringUpdates) {
return chartSettings.map(chartSetting => {
let match = chartSetting.id.match(chartIdWithDataTypeRegex);
if (!!match) {
return {
...chartSetting,
id: match[1],
};
}
return chartSetting;
});
}
return chartSettings;
}

0 comments on commit 5d8bc8b

Please sign in to comment.