Skip to content

Commit

Permalink
Paginated download of data for Clinical Data tab in Study View (#4786)
Browse files Browse the repository at this point in the history
* Implement server side filtering and sorting mode and limit record count

* implement data fetcher

* Update clinical data collection data type

* Pass attribute id for sort

Instead of display name.

* Fix sort direction passed by table component

* Fix total item count for paginated results

* Allow override of the total count label

* Do not render the clinical data table unutil visible attributes is populated to avoid flash of two column table (premature)

* Point e2e at beta

* run against custom backend

* Fix LazyMobxTable unit tests

* Update api client

* Address duplicate imports

---------

Co-authored-by: lismana <lismanBusiness@gmail.com>
Co-authored-by: Zhaoyuan (Ryan) Fu <fuzhaoyuan@gmail.com>
  • Loading branch information
3 people authored May 7, 2024
1 parent 2e8222e commit 4642088
Show file tree
Hide file tree
Showing 11 changed files with 428 additions and 354 deletions.
3 changes: 2 additions & 1 deletion env/master.sh
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export CBIOPORTAL_URL="${CBIOPORTAL_URL:-https://www.cbioportal.org}"
export CBIOPORTAL_URL="${CBIOPORTAL_URL:-https://beta.cbioportal.org}"
export GENOME_NEXUS_URL="${GENOME_NEXUS_URL:-https://www.genomenexus.org}"
export BACKEND=cbioportal:demo-fix-clinical-table-sorting
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@
},
{
"default": 0,
"description": "Page number of the result list",
"description": "Page number of the result list. Zero represents the first page.",
"format": "int32",
"in": "query",
"minimum": 0,
Expand Down Expand Up @@ -428,7 +428,7 @@
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/ClinicalDataCollection"
"$ref": "#/definitions/SampleClinicalDataCollection"
}
}
},
Expand Down Expand Up @@ -3639,23 +3639,6 @@
},
"type": "object"
},
"ClinicalDataCollection": {
"properties": {
"patientClinicalData": {
"items": {
"$ref": "#/definitions/ClinicalData"
},
"type": "array"
},
"sampleClinicalData": {
"items": {
"$ref": "#/definitions/ClinicalData"
},
"type": "array"
}
},
"type": "object"
},
"ClinicalDataCount": {
"properties": {
"count": {
Expand Down Expand Up @@ -5417,6 +5400,20 @@
],
"type": "object"
},
"SampleClinicalDataCollection": {
"properties": {
"byUniqueSampleKey": {
"additionalProperties": {
"items": {
"$ref": "#/definitions/ClinicalData"
},
"type": "array"
},
"type": "object"
}
},
"type": "object"
},
"SampleIdentifier": {
"properties": {
"sampleId": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,12 +186,6 @@ export type ClinicalDataBinFilter = {

'start': number

};
export type ClinicalDataCollection = {
'patientClinicalData': Array < ClinicalData >

'sampleClinicalData': Array < ClinicalData >

};
export type ClinicalDataCount = {
'count': number
Expand Down Expand Up @@ -964,6 +958,10 @@ export type Sample = {

'uniqueSampleKey': string

};
export type SampleClinicalDataCollection = {
'byUniqueSampleKey': {}

};
export type SampleIdentifier = {
'sampleId': string
Expand Down Expand Up @@ -1981,7 +1979,7 @@ export default class CBioPortalAPIInternal {
* @method
* @name CBioPortalAPIInternal#fetchClinicalDataClinicalTableUsingPOST
* @param {integer} pageSize - Page size of the result list
* @param {integer} pageNumber - Page number of the result list
* @param {integer} pageNumber - Page number of the result list. Zero represents the first page.
* @param {string} searchTerm - Search term to filter sample rows. Samples are returned with a partial match to the search term for any sample clinical attribute.
* @param {string} sortBy - sampleId, patientId, or the ATTR_ID to sorted by
* @param {string} direction - Direction of the sort
Expand Down Expand Up @@ -2050,7 +2048,7 @@ export default class CBioPortalAPIInternal {
* @method
* @name CBioPortalAPIInternal#fetchClinicalDataClinicalTableUsingPOST
* @param {integer} pageSize - Page size of the result list
* @param {integer} pageNumber - Page number of the result list
* @param {integer} pageNumber - Page number of the result list. Zero represents the first page.
* @param {string} searchTerm - Search term to filter sample rows. Samples are returned with a partial match to the search term for any sample clinical attribute.
* @param {string} sortBy - sampleId, patientId, or the ATTR_ID to sorted by
* @param {string} direction - Direction of the sort
Expand All @@ -2065,7 +2063,7 @@ export default class CBioPortalAPIInternal {
'studyViewFilter' ? : StudyViewFilter,
$queryParameters ? : any,
$domain ? : string
}): Promise < ClinicalDataCollection > {
}): Promise < SampleClinicalDataCollection > {
return this.fetchClinicalDataClinicalTableUsingPOSTWithHttpInfo(parameters).then(function(response: request.Response) {
return response.body;
});
Expand Down
2 changes: 1 addition & 1 deletion packages/cbioportal-ts-api-client/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export {
BinsGeneratorConfig,
ClinicalDataBinFilter,
ClinicalDataBinCountFilter,
ClinicalDataCollection,
SampleClinicalDataCollection,
ClinicalDataCount,
ClinicalDataCountFilter,
ClinicalDataCountItem,
Expand Down
61 changes: 22 additions & 39 deletions src/pages/studyView/StudyViewPageStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,7 @@ import {
PlotsColoringParam,
PlotsSelectionParam,
} from 'pages/resultsView/ResultsViewURLWrapper';
import { SortDirection } from 'shared/components/lazyMobXTable/LazyMobXTable';

export const STUDY_VIEW_FILTER_AUTOSUBMIT = 'study_view_filter_autosubmit';

Expand Down Expand Up @@ -5864,6 +5865,13 @@ export class StudyViewPageStore
},
});

readonly clinicalAttributeDisplayNameToClinicalAttribute = remoteData({
await: () => [this.clinicalAttributes],
invoke: async () => {
return _.keyBy(this.clinicalAttributes.result!, 'displayName');
},
});

readonly clinicalAttributeIdToDataType = remoteData({
await: () => [this.clinicalAttributes],
invoke: async () => {
Expand Down Expand Up @@ -9241,39 +9249,6 @@ export class StudyViewPageStore
default: {},
});

readonly getDataForClinicalDataTab = remoteData({
await: () => [
this.clinicalAttributes,
this.selectedSamples,
this.sampleSetByKey,
],
onError: () => {},
invoke: async () => {
if (this.selectedSamples.result.length === 0) {
return Promise.resolve([]);
}
let sampleClinicalDataMap = await getAllClinicalDataByStudyViewFilter(
this.filters
);

const sampleClinicalDataArray = _.mapValues(
sampleClinicalDataMap,
(attrs, uniqueSampleId) => {
const sample = this.sampleSetByKey.result![uniqueSampleId];
return {
studyId: sample.studyId,
patientId: sample.patientId,
sampleId: sample.sampleId,
...attrs,
};
}
);

return _.values(sampleClinicalDataArray);
},
default: [],
});

readonly clinicalAttributeProduct = remoteData({
await: () => [this.clinicalAttributes, this.selectedSamples],
invoke: async () => {
Expand Down Expand Up @@ -9815,8 +9790,10 @@ export class StudyViewPageStore
if (this.selectedSamples.result.length === 0) {
return Promise.resolve('');
}
let sampleClinicalDataMap = await getAllClinicalDataByStudyViewFilter(
this.filters
let sampleClinicalDataResponse = await getAllClinicalDataByStudyViewFilter(
this.filters,
undefined,
undefined
);

let clinicalAttributesNameSet = _.reduce(
Expand All @@ -9836,13 +9813,19 @@ export class StudyViewPageStore
let dataRows = _.reduce(
this.selectedSamples.result,
(acc, next) => {
let sampleData: { [attributeId: string]: string } = {
const sampleData = {
studyId: next.studyId,
patientId: next.patientId,
sampleId: next.sampleId,
...(sampleClinicalDataMap[next.uniqueSampleKey] || {}),
};

} as { [attributeId: string]: string };
const clinicalData =
sampleClinicalDataResponse.data[next.uniqueSampleKey];
_.forEach(
clinicalData,
(attr: ClinicalData) =>
(sampleData[attr['clinicalAttributeId']] =
attr['value'])
);
acc.push(
_.map(
Object.keys(clinicalAttributesNameSet),
Expand Down
82 changes: 0 additions & 82 deletions src/pages/studyView/StudyViewUtils.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ import {
isLogScaleByValues,
isOccupied,
makePatientToClinicalAnalysisGroup,
mergeClinicalDataCollection,
needAdditionShiftForLogScaleBarChart,
pickClinicalDataColors,
shouldShowChart,
Expand All @@ -72,7 +71,6 @@ import {
CancerStudy,
ClinicalAttribute,
ClinicalData,
ClinicalDataCollection,
DataFilterValue,
Sample,
StudyViewFilter,
Expand Down Expand Up @@ -2755,86 +2753,6 @@ describe('StudyViewUtils', () => {
});
});

describe('mergeClinicalDataCollection', () => {
it('handles merge when patient key defined in sample data', () => {
const input = ({
sampleClinicalData: [
{
sampleId: 's1',
patientId: 'p1',
studyId: 'study1',
uniqueSampleKey: 's1key',
uniquePatientKey: 'p1key',
clinicalAttributeId: 'attr1',
value: 'value1',
},
],
patientClinicalData: [
{
sampleId: undefined,
patientId: 'p1',
studyId: 'study1',
uniqueSampleKey: undefined,
uniquePatientKey: 'p1key',
clinicalAttributeId: 'attr2',
value: 'value2',
},
],
} as unknown) as ClinicalDataCollection;
const expected = {
s1key: {
attr1: 'value1',
attr2: 'value2',
},
};
assert.deepEqual(
expected,
mergeClinicalDataCollection(
(input as unknown) as ClinicalDataCollection
)
);
});

it('handles merge when patient key absent in sample data', () => {
const input = ({
sampleClinicalData: [
{
sampleId: 's1',
patientId: 'p1',
studyId: 'study1',
uniqueSampleKey: 's1key',
uniquePatientKey: 'p1key',
clinicalAttributeId: 'attr1',
value: 'value1',
},
],
patientClinicalData: [
{
sampleId: undefined,
patientId: 'p2',
studyId: 'study1',
uniqueSampleKey: undefined,
// note the patient key that does not line-up with the sample
uniquePatientKey: 'p2key',
clinicalAttributeId: 'attr2',
value: 'value2',
},
],
} as unknown) as ClinicalDataCollection;
const expected = {
s1key: {
attr1: 'value1',
},
};
assert.deepEqual(
expected,
mergeClinicalDataCollection(
(input as unknown) as ClinicalDataCollection
)
);
});
});

describe('toFixedDigit', () => {
const negativeValues = [
-666.666,
Expand Down
Loading

0 comments on commit 4642088

Please sign in to comment.