Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow numeric data type for custom data charts #4533

Merged
merged 1 commit into from
Mar 28, 2023

Conversation

TJMKuijpers
Copy link
Contributor

@TJMKuijpers TJMKuijpers commented Mar 2, 2023

Pull Request frontend implementation of custom numerical data

This pull request adds the functionality of uploading custom numerical data to cBioPortal via the add custom graph option. In the original frontend code of cBioPortal, it is only possible to upload custom categorical data. Here, we implemented the option to upload numerical data. (Note this PR cannot be merged before Binning of custom data #10039 is merged).

New functionality

  • Modal to upload custom data is extended with a radio button to select categorical/numerical data type.
  • Group comparison is implemented for the numerical custom data
  • Users can change the binning method based on quartile / median/ bin generator or custom bins

Screenshot test

  • Screenshot test added to test if the numerical/categorical radio button is present (core functionality needed in the frontend)

Screenshots
image
image

This also allows to have numerical custom data after we query based on genes (custom data 2 in the image):
image
image

Notify reviewers

Read our Pull request merging
policy
. It can help to figure out who worked on the
file before you. Please use git blame <filename> to determine that
and notify them either through slack or by assigning them as a reviewer on the PR

@pvannierop pvannierop changed the title Custom numerical chart Numeric data type for custom data charts Mar 6, 2023
@pvannierop pvannierop changed the title Numeric data type for custom data charts Allow numeric data type for custom data charts Mar 6, 2023
chartMeta.uniqueKey
);
props.onDataBinSelection = this.handlers.onDataBinSelection;
if (chartMeta.dataType === 'Custom_Data') {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we make "Custom_Data" into a constant somewhere?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can make use of the following:

if (  this.store.isUserDefinedCustomDataChart(
       chartMeta.uniqueKey
    )

In case of ChartTypeEnum.BAR_CHART and isUserDefinedCustomDataChart are both true, the custom data has a numerical type.

In other cases, we can make use of ChartMetaDataTypeEnum.CUSTOM_DATA

@@ -377,6 +377,12 @@ export enum BinMethodOption {
CUSTOM = 'CUSTOM',
}

type CustomDataType = 'CATEGORICAL' | 'NUMERICAL';
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return true;
if (this._customDataBinFilterSet.has(uniqueKey)) {
const filter = this._customDataBinFilterSet.get(uniqueKey);
const showNA = filter ? filter.showNA : undefined;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this logic seems kind of painful. i would just do

// default to true
return filter.showNA === undefined ? true : filter.showNA;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated to :

            const filter = this._customDataBinFilterSet.get(uniqueKey);
            return filter === undefined ? true : (filter!.showNA as boolean);

@@ -1182,6 +1208,59 @@ export class StudyViewPageStore
this.molecularProfileMapByType,
selectedSamples
);
} else if (chartMeta.dataType === 'Custom_Data') {
const clinicalAttribute = chartMeta.clinicalAttribute;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lets move all this logic into a tested helper function that accepts chartMeta and sampleKeyToData as args

Copy link
Contributor Author

@TJMKuijpers TJMKuijpers Mar 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has been moved to the function transformSampleDataToSelectedSampleClinicalData in StudyViewUtils.tsx with a test in StudyViewUtils.spec.tsx.

);
// Combine selectedSamples with sampleKeyToData to get the desired data object
let merged = [];
for (
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

try to avoid using for loops. this is a mapping operation so it should be

const merged = selectedSamples.map(sample=>{...});

});
}

const inputObject: any[] = merged.filter(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why would uniqueSampleKey ever be undefined?

if there is a valid reason, this filter operation can be chained with the map above.

const mergedWhatevers = arr.map(...)
    .filter(...);



Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The uniqueSampleKey is undefined in the selectedSampleData when the sample is not in selectedSamples. When we filter based on the uniqueSampleKey, we only send the selected samples in the studyview filter to the group comparison. (I think an inner join would have been better)

item =>
item.uniqueSampleKey !== undefined
);
const outputObject: any[] = inputObject.map(
Copy link
Collaborator

@alisman alisman Mar 6, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also, we should almost never use the any type in our logic. i see that the existing promise above does use any. we should try to improve this. maybe we can meet about it

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can define a new type comparisonCustomData with the following code to generate the selectedSampleData:

const selectedSampleData: comparisonCustomData[] = 
sampleInformation.map(
              sample =>
                ({ ...sample,                                       
                    ...selectedSamples.find(                                                   
                                           itmInner =>                                                       
                                           itmInner.sampleId ===                                                        
                                           sample.sampleId),
                } as comparisonCustomData)

and:

data = selectedSampleData.map(item => {
                     return {
                            clinicalAttribute: clinicalAttribute,
                            clinicalAttributeId:
                                              clinicalAttribute.clinicalAttributeId,
                            ...item,
                                        } as ClinicalData;
                                    })

): void {
const values: DataFilterValue[] = getDataIntervalFilterValues(dataBins);
this.setCustomChartNumericalFilters(chartUniqueKey, values);
if (!this._customDataBinFilterSet.has(chartUniqueKey)) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems strange that we update two different things here. lets discuss. at very least lets put some comments explaining why two different things need to be set.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This now is implemented in getCustomDataNumerical(). When the user uploads a custom data set, we don't know the data bin values beforehand (unlike a custom categorical data where we know the categories). After obtaining the binned data from the API, we need to set the bins in the filter.

@@ -2718,7 +2815,29 @@ export class StudyViewPageStore
this.updateClinicalDataIntervalFilters
);
}

@action.bound
setCustomChartNumericalFilters(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i see below that we have a method
setCustomChartFilters
if this is in fact categorical, we should change the name to avoid confusion with the new numerical option

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I renamed setCustomChartFilters to setCustomChartCategoricalFilters. This filter takes input values (string[]) to filter categorical data. The setCustomChartNumericalFilters takes dataBins (DataBin[]) as input. It makes sense to have a more explicit name for the custom categorical data filter.

@TJMKuijpers TJMKuijpers force-pushed the custom-numerical-chart branch 3 times, most recently from d680944 to 91300e0 Compare March 8, 2023 13:38
@inodb inodb marked this pull request as ready for review March 13, 2023 14:59
@TJMKuijpers TJMKuijpers force-pushed the custom-numerical-chart branch 2 times, most recently from 856e424 to c988ba9 Compare March 14, 2023 09:48
@inodb
Copy link
Member

inodb commented Mar 23, 2023

@TJMKuijpers Great work! Could you help fix the conflict? I think it's good to go otherwise

@TJMKuijpers
Copy link
Contributor Author

@inodb, resolved the conflict.

@inodb
Copy link
Member

inodb commented Mar 27, 2023

@TJMKuijpers there are some updated screenshots. The barcharts now show "NA" in text rather than as a bar (maybe that's the default we want but just want to make sure - if the change is desired, the screenshot needs to be updated):

https://output.circle-artifacts.com/output/job/15424c4c-7e39-40cd-bf65-4c63a78bdfea/artifacts/0/imageCompare.html

@alisman alisman merged commit 5757156 into cBioPortal:master Mar 28, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants