Skip to content

Commit

Permalink
Impl. heatmap tracks for treatment profiles and treatment selection menu
Browse files Browse the repository at this point in the history
  • Loading branch information
pvannierop committed Jul 3, 2019
1 parent ce7a535 commit ab01c09
Show file tree
Hide file tree
Showing 32 changed files with 2,240 additions and 447 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
42 changes: 42 additions & 0 deletions end-to-end-test/local/specs/treatment.screenshot.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
var assert = require('assert');
var goToUrlAndSetLocalStorage = require('../../shared/specUtils').goToUrlAndSetLocalStorage;
var assertScreenShotMatch = require('../../shared/lib/testUtils').assertScreenShotMatch;
var waitForOncoprint = require('../../shared/specUtils').waitForOncoprint;
var selectReactSelectOption = require('../../shared/specUtils').selectReactSelectOption;
var oncoprintTabUrl = require('./treatment.spec').oncoprintTabUrl;
var openHeatmapMenu = require('./treatment.spec').openHeatmapMenu;

describe('treatment feature', () => {

describe('oncoprint tab', () => {

beforeEach(()=>{
goToUrlAndSetLocalStorage(oncoprintTabUrl);
waitForOncoprint();
});

it('shows treatment profile heatmap track for treatment', () => {
openHeatmapMenu();
selectReactSelectOption( $('.oncoprint__controls__heatmap_menu'), 'IC50 values of compounds on cellular phenotype readout');
$('.oncoprint__controls__heatmap_menu textarea').setValue('17-AAG');
$('div.icon-area div.icon').waitForExist();
$('button=Add Treatments to Heatmap').click();
openHeatmapMenu();
waitForOncoprint();
var res = browser.checkElement('[id=oncoprintDiv]');
assertScreenShotMatch(res);
});

it('selects treatment in treatment select box when icon present', () => {
openHeatmapMenu();
selectReactSelectOption( $('.oncoprint__controls__heatmap_menu'), 'IC50 values of compounds on cellular phenotype readout');
$('.oncoprint__controls__heatmap_menu textarea').setValue('17-AAG');
$('div.icon-area div.icon').waitForExist();
$('.treatment-selector .Select-control').click();
var res = browser.checkElement('.Select-option*=17-AAG');
assertScreenShotMatch(res);
});

});

});
134 changes: 134 additions & 0 deletions end-to-end-test/local/specs/treatment.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
var assert = require('assert');
var goToUrlAndSetLocalStorage = require('../../shared/specUtils').goToUrlAndSetLocalStorage;
var waitForOncoprint = require('../../shared/specUtils').waitForOncoprint;
var reactSelectOption = require('../../shared/specUtils').reactSelectOption;
var getReactSelectOptions = require('../../shared/specUtils').getReactSelectOptions;
var selectReactSelectOption = require('../../shared/specUtils').selectReactSelectOption;
var useExternalFrontend = require('../../shared/specUtils').useExternalFrontend;

const CBIOPORTAL_URL = process.env.CBIOPORTAL_URL.replace(/\/$/, "");
const oncoprintTabUrl = CBIOPORTAL_URL+'/results/oncoprint?Action=Submit&RPPA_SCORE_THRESHOLD=2.0&Z_SCORE_THRESHOLD=2.0&cancer_study_list=study_es_0&case_set_id=study_es_0_all&clinicallist=NUM_SAMPLES_PER_PATIENT%2CPROFILED_IN_study_es_0_mutations%2CPROFILED_IN_study_es_0_gistic&data_priority=0&gene_list=CDKN2A%2520MDM2%2520MDM4%2520TP53&geneset_list=%20&genetic_profile_ids_PROFILE_COPY_NUMBER_ALTERATION=study_es_0_gistic&genetic_profile_ids_PROFILE_MUTATION_EXTENDED=study_es_0_mutations&show_samples=false&tab_index=tab_visualize'

describe('treatment feature', function() {

this.retries(2);

if (useExternalFrontend) {

describe('oncoprint tab', () => {

beforeEach(()=>{
goToUrlAndSetLocalStorage(oncoprintTabUrl);
waitForOncoprint();
});

it('shows treatment data type option in heatmap menu', () => {
openHeatmapMenu();
assert( reactSelectOption( $('.oncoprint__controls__heatmap_menu'), 'EC50 values of compounds on cellular phenotype readout') );
assert( reactSelectOption( $('.oncoprint__controls__heatmap_menu'), 'IC50 values of compounds on cellular phenotype readout') );
});

it('shows treatment text area box in heatmap menu when treatment data type is selected', () => {
openHeatmapMenu();
selectReactSelectOption( $('.oncoprint__controls__heatmap_menu'), 'IC50 values of compounds on cellular phenotype readout');
assert( $('.oncoprint__controls__heatmap_menu.text-icon-area') );
});

it('does not show genes of gene text area in treatment text area,and vice versa', () => {
openHeatmapMenu();
var geneText = $('.oncoprint__controls__heatmap_menu textarea').getText();
selectReactSelectOption( $('.oncoprint__controls__heatmap_menu'), 'IC50 values of compounds on cellular phenotype readout');
var treatmentText = $('.oncoprint__controls__heatmap_menu textarea').getText();
assert.notEqual(geneText, treatmentText);
selectReactSelectOption( $('.oncoprint__controls__heatmap_menu'), 'mRNA expression (microarray) Z-Score normalized');
assert.equal($('.oncoprint__controls__heatmap_menu textarea').getText(), geneText);
});

it('shows treatment selection box in heatmap menu when treatment data type is selected', () => {
openHeatmapMenu();
selectReactSelectOption( $('.oncoprint__controls__heatmap_menu'), 'IC50 values of compounds on cellular phenotype readout');
assert( $('.oncoprint__controls__heatmap_menu.treatment-selector') );
});

it('adds icon when entering a valid treatment in treatment text area', () => {
openHeatmapMenu();
selectReactSelectOption( $('.oncoprint__controls__heatmap_menu'), 'IC50 values of compounds on cellular phenotype readout');
$('.oncoprint__controls__heatmap_menu textarea').setValue('17-AAG');
$('div.icon*=17-AAG').waitForExist();
assert( $('div.icon*=17-AAG') );
});

it('click of icon remove button removes icon', () => {
openHeatmapMenu();
selectReactSelectOption( $('.oncoprint__controls__heatmap_menu'), 'IC50 values of compounds on cellular phenotype readout');
$('.oncoprint__controls__heatmap_menu textarea').setValue('17-AAG');
$('div.icon-area div.icon').waitForExist();
var iconButton = $('div.icon-area div.icon-button');
iconButton.click();
$('div.icon-area div.icon').waitForExist(undefined, true);
assert( ! $('div.icon-area div.icon').isExisting() );
});

it('removes valid treatment from treatment text area when recognized', () => {
openHeatmapMenu();
selectReactSelectOption( $('.oncoprint__controls__heatmap_menu'), 'IC50 values of compounds on cellular phenotype readout');
$('.oncoprint__controls__heatmap_menu textarea').setValue('17-AAG');
$('div.icon-area div.icon').waitForExist();
assert( ! $('.oncoprint__controls__heatmap_menu textarea').getValue() );
});

it('shows all treatments in the treatment select box', () => {
openHeatmapMenu();
selectReactSelectOption( $('.oncoprint__controls__heatmap_menu'), 'IC50 values of compounds on cellular phenotype readout');
var treatments = getReactSelectOptions( $('.oncoprint__controls__heatmap_menu .treatment-selector') );
assert.equal(treatments.length, 10);
});

it('adds treatment to icons when selected in treatment select box', () => {
openHeatmapMenu();
selectReactSelectOption( $('.oncoprint__controls__heatmap_menu'), 'IC50 values of compounds on cellular phenotype readout');
var treatments = getReactSelectOptions( $('.oncoprint__controls__heatmap_menu .treatment-selector') );
var treatment = treatments[0];
var treatmentName = treatment.getText();
treatmentName = treatmentName.replace(/.*\((.*)\).*/, "$1")
treatment.click();
$('div.icon*='+treatmentName).waitForExist();
assert( $('div.icon*='+treatmentName) );
});

it('filters treatment select options when using search of treatment select box', () => {
openHeatmapMenu();
selectReactSelectOption( $('.oncoprint__controls__heatmap_menu'), 'IC50 values of compounds on cellular phenotype readout');
var searchBox = $('.oncoprint__controls__heatmap_menu .treatment-selector .Select-control input');
searchBox.setValue('17-AAG');
var treatments = getReactSelectOptions( $('.oncoprint__controls__heatmap_menu .treatment-selector') );
assert(treatments.length, 1);
});

it('sets `treatment_list` URL parameter', () => {
openHeatmapMenu();
selectReactSelectOption( $('.oncoprint__controls__heatmap_menu'), 'IC50 values of compounds on cellular phenotype readout');
$('.oncoprint__controls__heatmap_menu textarea').setValue('17-AAG');
$('div.icon-area div.icon').waitForExist();
$('button=Add Treatments to Heatmap').click();
waitForOncoprint();
var url = browser.url().value;
var regex = /treatment_list=17-AAG/;
assert(url.match(regex));
});

});

}

});

var openHeatmapMenu = () => {
var heatmapButton = browser.$('button[id=heatmapDropdown]');
heatmapButton.click();
}

module.exports = {
oncoprintTabUrl: oncoprintTabUrl,
openHeatmapMenu: openHeatmapMenu,
};
87 changes: 77 additions & 10 deletions src/pages/resultsView/ResultsViewPageStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,10 @@ import {MergedGeneQuery} from '../../shared/lib/oql/oql-parser';
import GeneMolecularDataCache from "../../shared/cache/GeneMolecularDataCache";
import GenesetMolecularDataCache from "../../shared/cache/GenesetMolecularDataCache";
import GenesetCorrelatedGeneCache from "../../shared/cache/GenesetCorrelatedGeneCache";
import TreatmentMolecularDataCache from "../../shared/cache/TreatmentMolecularDataCache";
import GeneCache from "../../shared/cache/GeneCache";
import GenesetCache from "../../shared/cache/GenesetCache";
import TreatmentCache from "../../shared/cache/TreatmentCache";
import {IOncoKbData} from "../../shared/model/OncoKB";
import {generateQueryVariantId} from "../../public-lib/lib/OncoKbUtils";
import {
Expand All @@ -90,7 +92,9 @@ import {
ExpressionEnrichment,
Geneset,
GenesetDataFilterCriteria,
GenesetMolecularData
GenesetMolecularData,
Treatment,
TreatmentFilter
} from "../../shared/api/generated/CBioPortalAPIInternal";
import internalClient from "../../shared/api/cbioportalInternalClientInstance";
import {CancerGene, IndicatorQueryResp} from "../../shared/api/generated/OncoKbAPI";
Expand Down Expand Up @@ -175,7 +179,8 @@ export const AlterationTypeConstants = {
PROTEIN_LEVEL: 'PROTEIN_LEVEL',
FUSION: 'FUSION',
GENESET_SCORE: 'GENESET_SCORE',
METHYLATION: 'METHYLATION'
METHYLATION: 'METHYLATION',
GENERIC_ASSAY: 'GENERIC_ASSAY'
};

export const AlterationTypeDisplayConstants = {
Expand Down Expand Up @@ -884,7 +889,8 @@ export class ResultsViewPageStore {
this.molecularProfilesInStudies,
this.studyToDataQueryFilter,
this.genes,
this.genesets
this.genesets,
this.treatmentsInStudies
],
invoke:async()=>{
const ret:MolecularProfile[] = [];
Expand Down Expand Up @@ -918,7 +924,9 @@ export class ResultsViewPageStore {
ret.push(profile);
}
}));
} else if (profile.molecularAlterationType === AlterationTypeConstants.GENESET_SCORE) {
} else if (profile.molecularAlterationType === AlterationTypeConstants.GENESET_SCORE
|| profile.molecularAlterationType === AlterationTypeConstants.GENERIC_ASSAY
) {
// geneset profile, we dont have the META projection for geneset data, so just add it
/*promises.push(internalClient.fetchGeneticDataItemsUsingPOST({
geneticProfileId: molecularProfileId,
Expand Down Expand Up @@ -2079,19 +2087,21 @@ export class ResultsViewPageStore {
const MRNA_EXPRESSION = AlterationTypeConstants.MRNA_EXPRESSION;
const PROTEIN_LEVEL = AlterationTypeConstants.PROTEIN_LEVEL;
const METHYLATION = AlterationTypeConstants.METHYLATION;
const GENERIC_ASSAY = AlterationTypeConstants.GENERIC_ASSAY;
const selectedMolecularProfileIds = stringListToSet(
this.selectedMolecularProfiles.result!.map((profile)=>profile.molecularProfileId)
);

const expressionHeatmaps = _.sortBy(
_.filter(this.molecularProfilesInStudies.result!, profile=>{
return ((profile.molecularAlterationType === MRNA_EXPRESSION ||
profile.molecularAlterationType === PROTEIN_LEVEL) && profile.showProfileInAnalysisTab) ||
profile.molecularAlterationType === METHYLATION;
profile.molecularAlterationType === PROTEIN_LEVEL ||
profile.molecularAlterationType === GENERIC_ASSAY) && profile.showProfileInAnalysisTab) ||
profile.molecularAlterationType === METHYLATION
}
),
profile=>{
// Sort order: selected and [mrna, protein, methylation], unselected and [mrna, protein, meth]
// Sort order: selected and [mrna, protein, methylation, treatment], unselected and [mrna, protein, meth, treatment]
if (profile.molecularProfileId in selectedMolecularProfileIds) {
switch (profile.molecularAlterationType) {
case MRNA_EXPRESSION:
Expand All @@ -2100,15 +2110,19 @@ export class ResultsViewPageStore {
return 1;
case METHYLATION:
return 2;
case GENERIC_ASSAY:
return 3;
}
} else {
switch(profile.molecularAlterationType) {
case MRNA_EXPRESSION:
return 3;
case PROTEIN_LEVEL:
return 4;
case METHYLATION:
case PROTEIN_LEVEL:
return 5;
case METHYLATION:
return 6;
case GENERIC_ASSAY:
return 7;
}
}
}
Expand Down Expand Up @@ -2280,6 +2294,27 @@ export class ResultsViewPageStore {
geneticEntityId: geneset.genesetId, cytoband: "-", geneticEntityData: geneset});
}
return Promise.resolve(res);

}
});

readonly treatmentsInStudies = remoteData<Treatment[]>({
await:()=>[this.studyIds],
invoke: async () => {
return internalClient.fetchTreatmentsUsingPOST({
treatmentFilter: { studyIds:this.studyIds.result! } as TreatmentFilter
})
},
onResult:(treatments:Treatment[])=>{
this.treatmentCache.addData(treatments);
}
});

readonly selectedTreatments = remoteData<Treatment[]>({
await: ()=>[this.treatmentsInStudies],
invoke: () => {
const treatmentIdFromUrl = this.rvQuery.treatmentIds;
return Promise.resolve(_.filter(this.treatmentsInStudies.result!, (d:Treatment) => treatmentIdFromUrl.includes(d.treatmentId)));
}
});

Expand All @@ -2305,6 +2340,23 @@ export class ResultsViewPageStore {
}
});

readonly treatmentLinkMap = remoteData<{[treatmentId: string]: string}>({
invoke: async () => {
if (this.rvQuery.treatmentIds && this.rvQuery.treatmentIds.length) {
const treatments = await internalClient.fetchTreatmentsUsingPOST({
treatmentFilter: { studyIds:this.studyIds.result! } as TreatmentFilter
});
const linkMap: {[treatmentId: string]: string} = {};
treatments.forEach(({treatmentId, refLink}) => {
linkMap[treatmentId] = refLink;
});
return linkMap;
} else {
return {};
}
}
});

readonly customDriverAnnotationReport = remoteData<{ hasBinary:boolean, tiers:string[] }>({
await:()=>[
this.mutations
Expand Down Expand Up @@ -3107,6 +3159,17 @@ export class ResultsViewPageStore {
)
});

readonly treatmentMolecularDataCache = remoteData({
await:() => [
this.molecularProfileIdToDataQueryFilter
],
invoke: () => Promise.resolve(
new TreatmentMolecularDataCache(
this.molecularProfileIdToDataQueryFilter.result!
)
)
});

@cached get geneCache() {
return new GeneCache();
}
Expand All @@ -3115,6 +3178,10 @@ export class ResultsViewPageStore {
return new GenesetCache();
}

@cached get treatmentCache() {
return new TreatmentCache();
}

public numericGeneMolecularDataCache = new MobxPromiseCache<{entrezGeneId:number, molecularProfileId:string}, NumericGeneMolecularData[]>(
q=>({
await: ()=>[
Expand Down
3 changes: 2 additions & 1 deletion src/pages/resultsView/ResultsViewPageStoreUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,8 @@ export function getMolecularProfiles(query:any){
query.genetic_profile_ids_PROFILE_COPY_NUMBER_ALTERATION,
query.genetic_profile_ids_PROFILE_MRNA_EXPRESSION,
query.genetic_profile_ids_PROFILE_PROTEIN_EXPRESSION,
query.genetic_profile_ids_PROFILE_GENESET_SCORE
query.genetic_profile_ids_PROFILE_GENESET_SCORE,
query.genetic_profile_ids_GENERIC_ASSAY
].filter((profile:string|undefined)=>!!profile);

// append 'genetic_profile_ids' which is sometimes in use
Expand Down
9 changes: 9 additions & 0 deletions src/pages/resultsView/ResultsViewQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export class ResultsViewQuery {
@observable public _rppaScoreThreshold:number|undefined;
@observable public _zScoreThreshold:number|undefined;
@observable public genesetIds:string[] = [];
@observable public treatmentIds:string[] = [];
@observable public cohortIdsList:string[] = [];//queried id(any combination of physical and virtual studies)
@observable public oqlQuery:string = "";

Expand Down Expand Up @@ -103,6 +104,14 @@ export function updateResultsViewQuery(
}
}

if (urlQuery.treatment_list) {
// we have to trim because for some reason we get a single space from submission
const parsedTreatmentList = urlQuery.treatment_list.trim().length ? (urlQuery.treatment_list.trim().split(/;/)) : [];
if (!_.isEqual(parsedTreatmentList, rvQuery.treatmentIds)) {
rvQuery.treatmentIds = parsedTreatmentList;
}
}

// cohortIdsList will contain virtual study ids (physicalstudies will contain the phsyical studies which comprise the virtual studies)
// although resultsViewStore does
if (!rvQuery.cohortIdsList || !_.isEqual(_.sortBy(rvQuery.cohortIdsList), _.sortBy(cancerStudyIds))) {
Expand Down
Loading

0 comments on commit ab01c09

Please sign in to comment.