diff --git a/docs/About-Us.md b/docs/About-Us.md index da0e1d8da27..eb821670a42 100644 --- a/docs/About-Us.md +++ b/docs/About-Us.md @@ -42,6 +42,7 @@ The cBioPortal for Cancer Genomics was originally developed at [Memorial Sloan K ## Caris Life Sciences * Jianjiong Gao * Priti Kumari +* Karthik Kalletla ## The Hyve * Oleguer Plantalech @@ -82,7 +83,6 @@ The cBioPortal for Cancer Genomics was originally developed at [Memorial Sloan K * Zachary Heins * Michael Heuer * Anders Jacobsen -* Karthik Kalletla * Peter Kok * Erik Larsson * Dong Li diff --git a/docs/deployment/customization/portal.properties-Reference.md b/docs/deployment/customization/portal.properties-Reference.md index 19273b2d38a..5eca5c5988b 100644 --- a/docs/deployment/customization/portal.properties-Reference.md +++ b/docs/deployment/customization/portal.properties-Reference.md @@ -153,6 +153,13 @@ Different samples of a patient may have been analyzed with different gene panels skin.patientview.filter_genes_profiled_all_samples= ``` +### Control default settings of the VAF line chart in the genomic evolution tab of patient view +If you want to enable log scale and sequential mode by default, set this property to `true`: +``` +vaf.log_scale.default=true|false +vaf.sequential_mode.default=true|false +``` + ### Control unauthorized studies to be displayed on the home page By default, on an authenticated portal the home page will only show studies for which the current user is authorized. By setting the _skin.home\_page.show\_unauthorized\_studies_ property to _true_ the home page will also show unauthorized studies. The unauthorized studies will appear greyed out and cannot be selected for downstream analysis in Results View or Study View. @@ -436,6 +443,11 @@ oncoprint.oncokb.default=true|false oncoprint.hotspots.default=true|false ``` +If you want to enable oncoprint heatmap clustering by default, set this property to `true`: +``` +oncoprint.clustered.default=true|false +``` + **Automatic hiding of variants of unknown significance (VUS)** By default, the selection box to hide VUS mutations is unchecked. If you want to automatically hide VUS, set this property to `true`. Default is `false`. diff --git a/model/src/main/java/org/cbioportal/model/GenomicDataCountItem.java b/model/src/main/java/org/cbioportal/model/GenomicDataCountItem.java new file mode 100644 index 00000000000..bd9ae14cdaf --- /dev/null +++ b/model/src/main/java/org/cbioportal/model/GenomicDataCountItem.java @@ -0,0 +1,35 @@ +package org.cbioportal.model; + +import java.io.Serializable; +import java.util.List; + +public class GenomicDataCountItem implements Serializable { + + private String hugoGeneSymbol; + private String profileType; + private List counts; + + public String getHugoGeneSymbol() { + return hugoGeneSymbol; + } + + public void setHugoGeneSymbol(String hugoGeneSymbol) { + this.hugoGeneSymbol = hugoGeneSymbol; + } + + public String getProfileType() { + return profileType; + } + + public void setProfileType(String profileType) { + this.profileType = profileType; + } + + public List getCounts() { + return counts; + } + + public void setCounts(List counts) { + this.counts = counts; + } +} diff --git a/pom.xml b/pom.xml index 3f38fbcb38d..d44663bed5e 100644 --- a/pom.xml +++ b/pom.xml @@ -276,7 +276,7 @@ - v5.3.16 + v5.3.17 com.github.cbioportal 5.2.20.RELEASE 5.3.0.RELEASE diff --git a/portal/src/main/webapp/config_service.jsp b/portal/src/main/webapp/config_service.jsp index a34b50522bc..3e7dc6ec00f 100644 --- a/portal/src/main/webapp/config_service.jsp +++ b/portal/src/main/webapp/config_service.jsp @@ -37,6 +37,7 @@ "oncoprint.custom_driver_annotation.binary.default", "oncoprint.oncokb.default", "oncoprint.hotspots.default", + "oncoprint.clustered.default", "genomenexus.url", "genomenexus.url.grch38", "google_analytics_profile_id", @@ -146,7 +147,9 @@ "skin.patient_view.structural_variant_table.columns.show_on_init", "comparison.categorical_na_values", "study_download_url", - "skin.home_page.show_reference_genome" + "skin.home_page.show_reference_genome", + "vaf.sequential_mode.default", + "vaf.log_scale.default" }; diff --git a/service/src/main/java/org/cbioportal/service/StudyViewService.java b/service/src/main/java/org/cbioportal/service/StudyViewService.java index e3fdeb890c7..67191ea7588 100644 --- a/service/src/main/java/org/cbioportal/service/StudyViewService.java +++ b/service/src/main/java/org/cbioportal/service/StudyViewService.java @@ -1,6 +1,8 @@ package org.cbioportal.service; +import org.apache.commons.math3.util.Pair; import org.cbioportal.model.*; +import org.cbioportal.service.exception.MolecularProfileNotFoundException; import org.cbioportal.service.exception.StudyNotFoundException; import java.util.List; @@ -19,6 +21,8 @@ List getStructuralVariantAlterationCountByGenes(List getCNAAlterationCountByGenes(List studyIds, List sampleIds, AlterationFilter annotationFilter) throws StudyNotFoundException; + List getCNAAlterationCountsByGeneSpecific(List studyIds, List sampleIds, List> genomicDataFilters); + List fetchGenericAssayDataCounts(List sampleIds, List studyIds, List stableIds, List profileTypes); } diff --git a/service/src/main/java/org/cbioportal/service/impl/StudyViewServiceImpl.java b/service/src/main/java/org/cbioportal/service/impl/StudyViewServiceImpl.java index 234452da89d..510fa8f0206 100644 --- a/service/src/main/java/org/cbioportal/service/impl/StudyViewServiceImpl.java +++ b/service/src/main/java/org/cbioportal/service/impl/StudyViewServiceImpl.java @@ -2,6 +2,7 @@ import org.apache.commons.collections4.map.MultiKeyMap; import org.apache.commons.lang3.StringUtils; +import org.apache.commons.math3.util.Pair; import org.cbioportal.model.*; import org.cbioportal.model.util.Select; import org.cbioportal.persistence.AlterationRepository; @@ -15,6 +16,7 @@ import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; +import java.util.stream.Stream; @Service public class StudyViewServiceImpl implements StudyViewService { @@ -37,6 +39,12 @@ public class StudyViewServiceImpl implements StudyViewService { @Autowired private AlterationRepository alterationRepository; + @Autowired + private GeneService geneService; + + @Autowired + private MolecularDataService molecularDataService; + @Override public List getGenomicDataCounts(List studyIds, List sampleIds) { List molecularProfileSampleIdentifiers = @@ -154,7 +162,7 @@ public List getCNAAlterationCountByGenes(List stu throws StudyNotFoundException { List caseIdentifiers = molecularProfileService.getFirstDiscreteCNAProfileCaseIdentifiers(studyIds, sampleIds); - Select cnaTypes = Select.byValues(CNA_TYPES_AMP_AND_HOMDEL); + List copyNumberCountByGenes = alterationCountService.getSampleCnaGeneCounts( caseIdentifiers, Select.all(), @@ -186,6 +194,96 @@ public List getCNAAlterationCountByGenes(List stu return copyNumberCountByGenes; } + @Override + public List getCNAAlterationCountsByGeneSpecific(List studyIds, + List sampleIds, + List> genomicDataFilters) { + + List molecularProfiles = molecularProfileService.getMolecularProfilesInStudies(studyIds, + "SUMMARY"); + + Map> molecularProfileMap = molecularProfileUtil + .categorizeMolecularProfilesByStableIdSuffixes(molecularProfiles); + + Set hugoGeneSymbols = genomicDataFilters.stream().map(Pair::getKey) + .collect(Collectors.toSet()); + + Map geneSymbolIdMap = geneService + .fetchGenes(new ArrayList<>(hugoGeneSymbols), "HUGO_GENE_SYMBOL", + "SUMMARY") + .stream().collect(Collectors.toMap(Gene::getHugoGeneSymbol, Gene::getEntrezGeneId)); + + return genomicDataFilters + .stream() + .flatMap(gdFilter -> { + GenomicDataCountItem genomicDataCountItem = new GenomicDataCountItem(); + String hugoGeneSymbol = gdFilter.getKey(); + String profileType = gdFilter.getValue(); + genomicDataCountItem.setHugoGeneSymbol(hugoGeneSymbol); + genomicDataCountItem.setProfileType(profileType); + + List stableIds = Arrays.asList(geneSymbolIdMap.get(hugoGeneSymbol).toString()); + + Map studyIdToMolecularProfileIdMap = molecularProfileMap + .getOrDefault(profileType, new ArrayList()).stream() + .collect(Collectors.toMap(MolecularProfile::getCancerStudyIdentifier, + MolecularProfile::getStableId)); + + List mappedSampleIds = new ArrayList<>(); + List mappedProfileIds = new ArrayList<>(); + + for (int i = 0; i < sampleIds.size(); i++) { + String studyId = studyIds.get(i); + if (studyIdToMolecularProfileIdMap.containsKey(studyId)) { + mappedSampleIds.add(sampleIds.get(i)); + mappedProfileIds.add(studyIdToMolecularProfileIdMap.get(studyId)); + } + } + + if (mappedSampleIds.isEmpty()) { + return Stream.of(); + } + + List geneMolecularDataList = molecularDataService.getMolecularDataInMultipleMolecularProfiles(mappedProfileIds, mappedSampleIds, + stableIds.stream().map(Integer::parseInt).collect(Collectors.toList()), "SUMMARY"); + + List genomicDataCounts = geneMolecularDataList + .stream() + .filter(g -> StringUtils.isNotEmpty(g.getValue()) && !g.getValue().equals("NA")) + .collect(Collectors.groupingBy(GeneMolecularData::getValue)) + .entrySet() + .stream() + .map(entry -> { + Integer alteration = Integer.valueOf(entry.getKey()); + List geneMolecularData = entry.getValue(); + int count = geneMolecularData.size(); + + String label = CNA.getByCode(alteration.shortValue()).getDescription(); + + GenomicDataCount genomicDataCount = new GenomicDataCount(); + genomicDataCount.setLabel(label); + genomicDataCount.setValue(String.valueOf(alteration)); + genomicDataCount.setCount(count); + + return genomicDataCount; + }).collect(Collectors.toList()); + + int totalCount = genomicDataCounts.stream().mapToInt(GenomicDataCount::getCount).sum(); + int naCount = sampleIds.size() - totalCount; + + if (naCount > 0) { + GenomicDataCount genomicDataCount = new GenomicDataCount(); + genomicDataCount.setLabel("NA"); + genomicDataCount.setValue("NA"); + genomicDataCount.setCount(naCount); + genomicDataCounts.add(genomicDataCount); + } + + genomicDataCountItem.setCounts(genomicDataCounts); + return Stream.of(genomicDataCountItem); + }).collect(Collectors.toList()); + }; + @Override public List fetchGenericAssayDataCounts(List sampleIds, List studyIds, List stableIds, List profileTypes) { @@ -261,5 +359,4 @@ public List fetchGenericAssayDataCounts(List }) .collect(Collectors.toList()); } - } diff --git a/service/src/test/java/org/cbioportal/service/impl/BaseServiceImplTest.java b/service/src/test/java/org/cbioportal/service/impl/BaseServiceImplTest.java index 838c4c3a67b..827a7b752a5 100644 --- a/service/src/test/java/org/cbioportal/service/impl/BaseServiceImplTest.java +++ b/service/src/test/java/org/cbioportal/service/impl/BaseServiceImplTest.java @@ -59,5 +59,7 @@ public class BaseServiceImplTest { public static final String CATEGORY_VALUE_1 = "category_value1"; public static final String CATEGORY_VALUE_2 = "category_value2"; public static final String EMPTY_VALUE_1 = ""; - public static final String EMPTY_VALUE_2 = "NA"; + public static final String EMPTY_VALUE_2 = "NA"; + public static final String PROFILE_TYPE_1 = "profile_type1"; + public static final String PROFILE_TYPE_2 = "profile_type2"; } diff --git a/service/src/test/java/org/cbioportal/service/impl/StudyViewServiceImplTest.java b/service/src/test/java/org/cbioportal/service/impl/StudyViewServiceImplTest.java index 4500e9058ea..801ab8afebf 100644 --- a/service/src/test/java/org/cbioportal/service/impl/StudyViewServiceImplTest.java +++ b/service/src/test/java/org/cbioportal/service/impl/StudyViewServiceImplTest.java @@ -14,10 +14,7 @@ import org.mockito.Spy; import org.mockito.junit.MockitoJUnitRunner; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; +import java.util.*; import static org.mockito.ArgumentMatchers.*; @@ -41,6 +38,10 @@ public class StudyViewServiceImplTest extends BaseServiceImplTest { private SignificantCopyNumberRegionService significantCopyNumberRegionService; @Mock private GenericAssayService genericAssayService; + @Mock + private MolecularDataService molecularDataService; + @Mock + private GeneService geneService; private AlterationFilter alterationFilter = new AlterationFilter(); @Test @@ -255,6 +256,79 @@ public void getCNAAlterationCountByGenes() throws Exception { Assert.assertEquals(1, result.size()); } + @Test + public void getCNAAlterationCountByGeneSpecific() throws Exception { + + List sampleIds = Arrays.asList(BaseServiceImplTest.SAMPLE_ID1, BaseServiceImplTest.SAMPLE_ID2, BaseServiceImplTest.SAMPLE_ID3); + List studyIds = Collections.nCopies(3, BaseServiceImplTest.STUDY_ID); + List> genomicDataFilters = new ArrayList<>(); + Pair genomicDataFilter1 = new Pair<>(BaseServiceImplTest.HUGO_GENE_SYMBOL_1, BaseServiceImplTest.PROFILE_TYPE_1); + Pair genomicDataFilter2 = new Pair<>(BaseServiceImplTest.HUGO_GENE_SYMBOL_2, BaseServiceImplTest.PROFILE_TYPE_2); + genomicDataFilters.add(genomicDataFilter1); + genomicDataFilters.add(genomicDataFilter2); + + List molecularProfiles = new ArrayList<>(); + MolecularProfile molecularProfile = new MolecularProfile(); + molecularProfile.setCancerStudyIdentifier(BaseServiceImplTest.STUDY_ID); + molecularProfile.setStableId(BaseServiceImplTest.STUDY_ID + "_" + BaseServiceImplTest.MOLECULAR_PROFILE_ID_A); + molecularProfiles.add(molecularProfile); + + Mockito.when(molecularProfileService.getMolecularProfilesInStudies(studyIds, "SUMMARY")) + .thenReturn(molecularProfiles); + + Map> molecularProfileMap = new HashMap<>(); + molecularProfileMap.put(BaseServiceImplTest.PROFILE_TYPE_1, molecularProfiles); + molecularProfileMap.put(BaseServiceImplTest.PROFILE_TYPE_2, molecularProfiles); + + Mockito.when(molecularProfileUtil.categorizeMolecularProfilesByStableIdSuffixes(molecularProfiles)) + .thenReturn(molecularProfileMap); + + List genes = new ArrayList<>(); + Gene gene1 = new Gene(); + gene1.setEntrezGeneId(BaseServiceImplTest.ENTREZ_GENE_ID_1); + gene1.setHugoGeneSymbol(BaseServiceImplTest.HUGO_GENE_SYMBOL_1); + Gene gene2 = new Gene(); + gene2.setEntrezGeneId(BaseServiceImplTest.ENTREZ_GENE_ID_2); + gene2.setHugoGeneSymbol(BaseServiceImplTest.HUGO_GENE_SYMBOL_2); + genes.add(gene1); + genes.add(gene2); + + Mockito.when(geneService.fetchGenes(anyList(), anyString(), anyString())) + .thenReturn(genes); + + List geneMolecularData = new ArrayList<>(); + GeneMolecularData geneMolecularData1 = new GeneMolecularData(); + geneMolecularData1.setValue("-2"); + GeneMolecularData geneMolecularData2 = new GeneMolecularData(); + geneMolecularData2.setValue("-2"); + GeneMolecularData geneMolecularData3 = new GeneMolecularData(); + geneMolecularData3.setValue("2"); + GeneMolecularData geneMolecularData4 = new GeneMolecularData(); + geneMolecularData4.setValue("2"); + geneMolecularData.add(geneMolecularData1); + geneMolecularData.add(geneMolecularData2); + geneMolecularData.add(geneMolecularData3); + geneMolecularData.add(geneMolecularData4); + + Mockito.when(molecularDataService.getMolecularDataInMultipleMolecularProfiles( + anyList(), + anyList(), + anyList(), + anyString())) + .thenReturn(geneMolecularData); + + List result = studyViewService.getCNAAlterationCountsByGeneSpecific(studyIds, sampleIds, genomicDataFilters); + Assert.assertEquals(2, result.size()); + Assert.assertEquals(BaseServiceImplTest.HUGO_GENE_SYMBOL_1, result.get(0).getHugoGeneSymbol()); + Assert.assertEquals(BaseServiceImplTest.PROFILE_TYPE_1, result.get(0).getProfileType()); + Assert.assertEquals(2, result.get(0).getCounts().get(0).getCount().intValue()); + Assert.assertEquals(2, result.get(0).getCounts().get(1).getCount().intValue()); + Assert.assertEquals(BaseServiceImplTest.HUGO_GENE_SYMBOL_2, result.get(1).getHugoGeneSymbol()); + Assert.assertEquals(BaseServiceImplTest.PROFILE_TYPE_2, result.get(1).getProfileType()); + Assert.assertEquals(2, result.get(1).getCounts().get(0).getCount().intValue()); + Assert.assertEquals(2, result.get(1).getCounts().get(1).getCount().intValue()); + } + @Test public void fetchGenericAssayDataCounts() throws Exception { diff --git a/src/main/resources/portal.properties.EXAMPLE b/src/main/resources/portal.properties.EXAMPLE index 78b02eb08ac..49aecf9c4d5 100644 --- a/src/main/resources/portal.properties.EXAMPLE +++ b/src/main/resources/portal.properties.EXAMPLE @@ -317,6 +317,7 @@ oncoprint.oncokb.default=true oncoprint.hotspots.default=true # oncoprint.hide_vus.default=true # oncoprint.clinical_tracks.config_json=classpath:/oncoprint-default-tracks.json +# oncoprint.clustered.default=true # Custom gene sets # querypage.setsofgenes.location=file:/ @@ -436,4 +437,7 @@ persistence.cache_type=no-cache # Allows download links within DataSets Tab (See Portal.Properties documentation for more info) # study_download_url= -# download_group= \ No newline at end of file +# download_group= + +# vaf.sequential_mode.default=false +# vaf.log_scale.default=false diff --git a/web/src/main/java/org/cbioportal/web/StudyViewController.java b/web/src/main/java/org/cbioportal/web/StudyViewController.java index 1b0093fe408..f4ca464cf50 100644 --- a/web/src/main/java/org/cbioportal/web/StudyViewController.java +++ b/web/src/main/java/org/cbioportal/web/StudyViewController.java @@ -9,6 +9,7 @@ import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.math3.stat.correlation.PearsonsCorrelation; import org.apache.commons.math3.stat.correlation.SpearmansCorrelation; +import org.apache.commons.math3.util.Pair; import org.cbioportal.model.*; import org.cbioportal.service.*; import org.cbioportal.service.exception.StudyNotFoundException; @@ -16,7 +17,6 @@ import org.cbioportal.web.config.annotation.InternalApi; import org.cbioportal.model.AlterationFilter; import org.cbioportal.web.parameter.*; -import org.cbioportal.web.parameter.sort.ClinicalDataSortBy; import org.cbioportal.web.util.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.annotation.Cacheable; @@ -861,6 +861,47 @@ public ResponseEntity> fetchGenomicDataBinCounts( return new ResponseEntity<>(studyViewFilterApplier.getDataBins(dataBinMethod, interceptedGenomicDataBinCountFilter), HttpStatus.OK); } + @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") + @RequestMapping(value = "/genomic-data-counts/fetch", method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) + @ApiOperation("Fetch genomic data counts by GenomicDataCountFilter") + public ResponseEntity> fetchGenomicDataCounts( + @ApiParam(required = true, value = "Genomic data count filter") @Valid @RequestBody(required = false) GenomicDataCountFilter genomicDataCountFilter, + @ApiIgnore // prevent reference to this attribute in the swagger-ui interface + @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, + @ApiParam(required = true, value = "Intercepted Genomic Data Count Filter") + @ApiIgnore + @Valid @RequestAttribute(required = false, value = "interceptedGenomicDataCountFilter") GenomicDataCountFilter interceptedGenomicDataCountFilter + ) throws StudyNotFoundException { + List gdFilters = interceptedGenomicDataCountFilter.getGenomicDataFilters(); + StudyViewFilter studyViewFilter = interceptedGenomicDataCountFilter.getStudyViewFilter(); + // when there is only one filter, it means study view is doing a single chart filter operation + // remove filter from studyViewFilter to return all data counts + // the reason we do this is to make sure after chart get filtered, user can still see unselected portion of the chart + if (gdFilters.size() == 1) { + studyViewFilterUtil.removeSelfFromGenomicDataFilter( + gdFilters.get(0).getHugoGeneSymbol(), + gdFilters.get(0).getProfileType(), + studyViewFilter); + } + List filteredSampleIdentifiers = studyViewFilterApplier.apply(studyViewFilter); + + if (filteredSampleIdentifiers.isEmpty()) { + return new ResponseEntity<>(new ArrayList<>(), HttpStatus.OK); + } + + List studyIds = new ArrayList<>(); + List sampleIds = new ArrayList<>(); + studyViewFilterUtil.extractStudyAndSampleIds(filteredSampleIdentifiers, studyIds, sampleIds); + + List result = studyViewService.getCNAAlterationCountsByGeneSpecific( + studyIds, + sampleIds, + gdFilters.stream().map(gdFilter -> new Pair<>(gdFilter.getHugoGeneSymbol(), gdFilter.getProfileType())).collect(Collectors.toList())); + + return new ResponseEntity<>(result, HttpStatus.OK); + } + @PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection', T(org.cbioportal.utils.security.AccessLevel).READ)") @RequestMapping(value = "/generic-assay-data-counts/fetch", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) @ApiOperation("Fetch generic assay data counts by study view filter") diff --git a/web/src/main/java/org/cbioportal/web/parameter/GenomicDataCountFilter.java b/web/src/main/java/org/cbioportal/web/parameter/GenomicDataCountFilter.java new file mode 100644 index 00000000000..c01ec7696c1 --- /dev/null +++ b/web/src/main/java/org/cbioportal/web/parameter/GenomicDataCountFilter.java @@ -0,0 +1,26 @@ +package org.cbioportal.web.parameter; + +import java.io.Serializable; +import java.util.List; + +public class GenomicDataCountFilter implements Serializable { + + private List genomicDataFilters; + private StudyViewFilter studyViewFilter; + + public List getGenomicDataFilters() { + return genomicDataFilters; + } + + public void setGenomicDataFilters(List genomicDataFilters) { + this.genomicDataFilters = genomicDataFilters; + } + + public StudyViewFilter getStudyViewFilter() { + return studyViewFilter; + } + + public void setStudyViewFilter(StudyViewFilter studyViewFilter) { + this.studyViewFilter = studyViewFilter; + } +} diff --git a/web/src/main/java/org/cbioportal/web/util/InvolvedCancerStudyExtractorInterceptor.java b/web/src/main/java/org/cbioportal/web/util/InvolvedCancerStudyExtractorInterceptor.java index ff5c7aaf4ca..f56a51727b0 100644 --- a/web/src/main/java/org/cbioportal/web/util/InvolvedCancerStudyExtractorInterceptor.java +++ b/web/src/main/java/org/cbioportal/web/util/InvolvedCancerStudyExtractorInterceptor.java @@ -75,6 +75,7 @@ public class InvolvedCancerStudyExtractorInterceptor extends HandlerInterceptorA public static final String STUDY_VIEW_CLINICAL_DATA_BIN_COUNTS_PATH = "/clinical-data-bin-counts/fetch"; public static final String STUDY_VIEW_CUSTOM_DATA_BIN_COUNTS_PATH = "/custom-data-bin-counts/fetch"; public static final String STUDY_VIEW_GENOMICL_DATA_BIN_COUNTS_PATH = "/genomic-data-bin-counts/fetch"; + public static final String STUDY_VIEW_GENOMICL_DATA_COUNTS_PATH = "/genomic-data-counts/fetch"; public static final String STUDY_VIEW_GENERIC_ASSAY_DATA_BIN_COUNTS_PATH = "/generic-assay-data-bin-counts/fetch"; public static final String STUDY_VIEW_GENERIC_ASSAY_DATA_COUNTS_PATH = "/generic-assay-data-counts/fetch"; public static final String STUDY_VIEW_CLINICAL_DATA_COUNTS_PATH = "/clinical-data-counts/fetch"; @@ -130,6 +131,8 @@ public class InvolvedCancerStudyExtractorInterceptor extends HandlerInterceptorA return extractAttributesFromClinicalDataBinCountFilter(request); } else if (requestPathInfo.equals(STUDY_VIEW_GENOMICL_DATA_BIN_COUNTS_PATH)) { return extractAttributesFromGenomicDataBinCountFilter(request); + } else if (requestPathInfo.equals(STUDY_VIEW_GENOMICL_DATA_COUNTS_PATH)) { + return extractAttributesFromGenomicDataCountFilter(request); } else if (requestPathInfo.equals(STUDY_VIEW_GENERIC_ASSAY_DATA_BIN_COUNTS_PATH)) { return extractAttributesFromGenericAssayDataBinCountFilter(request); } else if (requestPathInfo.equals(STUDY_VIEW_GENERIC_ASSAY_DATA_COUNTS_PATH)) { @@ -137,7 +140,7 @@ public class InvolvedCancerStudyExtractorInterceptor extends HandlerInterceptorA } else if (Arrays.asList(STUDY_VIEW_CLINICAL_DATA_COUNTS_PATH, STUDY_VIEW_CUSTOM_DATA_COUNTS_PATH) .contains(requestPathInfo)) { return extractAttributesFromClinicalDataCountFilter(request); - } else if (Arrays.asList(STUDY_VIEW_CLINICAL_DATA_DENSITY_PATH, STUDY_VIEW_CLINICAL_DATA_VIOLIN_PATH, STUDY_VIEW_CNA_GENES, + } else if (Arrays.asList(STUDY_VIEW_CLINICAL_DATA_DENSITY_PATH, STUDY_VIEW_CLINICAL_DATA_VIOLIN_PATH, STUDY_VIEW_CNA_GENES, STUDY_VIEW_FILTERED_SAMPLES, STUDY_VIEW_MUTATED_GENES, STUDY_VIEW_STRUCTURAL_VARIANT_GENES, STUDY_VIEW_STRUCTURAL_VARIANT_COUNTS, STUDY_VIEW_SAMPLE_COUNTS, STUDY_VIEW_SAMPLE_LIST_COUNTS_PATH, STUDY_VIEW_CLINICAL_TABLE_DATA_FETCH_PATH, TREATMENTS_PATIENT_PATH, TREATMENTS_SAMPLE_PATH, STUDY_VIEW_PROFILE_SAMPLE_COUNTS_PATH, CLINICAL_EVENT_TYPE_COUNT_FETCH_PATH @@ -477,6 +480,26 @@ private boolean extractAttributesFromGenomicDataBinCountFilter(HttpServletReques return true; } + private boolean extractAttributesFromGenomicDataCountFilter(HttpServletRequest request) { + try { + GenomicDataCountFilter genomicDataCountFilter = objectMapper.readValue(request.getInputStream(), + GenomicDataCountFilter.class); + LOG.debug("extracted genomicDataCountFilter: " + genomicDataCountFilter.toString()); + LOG.debug("setting interceptedGenomicDataCountFilter to " + genomicDataCountFilter); + request.setAttribute("interceptedGenomicDataCountFilter", genomicDataCountFilter); + if (cacheMapUtil.hasCacheEnabled()) { + Collection cancerStudyIdCollection = extractCancerStudyIdsFromGenomicDataCountFilter( + genomicDataCountFilter); + LOG.debug("setting involvedCancerStudies to " + cancerStudyIdCollection); + request.setAttribute("involvedCancerStudies", cancerStudyIdCollection); + } + } catch (Exception e) { + LOG.error("exception thrown during extraction of genomicDataCountFilter: " + e); + return false; + } + return true; + } + private boolean extractAttributesFromGenericAssayDataBinCountFilter(HttpServletRequest request) { try { GenericAssayDataBinCountFilter genericAssayDataBinCountFilter = objectMapper @@ -722,6 +745,14 @@ private Set extractCancerStudyIdsFromGenomicDataBinCountFilter( return new HashSet(); } + private Set extractCancerStudyIdsFromGenomicDataCountFilter( + GenomicDataCountFilter genomicDataCountFilter) { + if (genomicDataCountFilter.getStudyViewFilter() != null) { + return extractCancerStudyIdsFromStudyViewFilter(genomicDataCountFilter.getStudyViewFilter()); + } + return new HashSet(); + } + private Set extractCancerStudyIdsFromGenericAssayDataBinCountFilter( GenericAssayDataBinCountFilter genericAssayDataBinCountFilter) { if (genericAssayDataBinCountFilter.getStudyViewFilter() != null) { diff --git a/web/src/main/java/org/cbioportal/web/util/StudyViewFilterApplier.java b/web/src/main/java/org/cbioportal/web/util/StudyViewFilterApplier.java index 47b3b7505ec..0b97b6df954 100644 --- a/web/src/main/java/org/cbioportal/web/util/StudyViewFilterApplier.java +++ b/web/src/main/java/org/cbioportal/web/util/StudyViewFilterApplier.java @@ -166,8 +166,39 @@ public List apply(StudyViewFilter studyViewFilter, Boolean neg molecularProfiles = molecularProfileService.getMolecularProfilesInStudies(studyIds, "SUMMARY"); } - sampleIdentifiers = intervalFilterExpressionData(sampleIdentifiers, molecularProfiles, - studyViewFilter.getGenomicDataFilters(), negateFilters); + List genomicDataEqualityFilters = new ArrayList<>(); + List genomicDataIntervalFilters = new ArrayList<>(); + + List genomicDataFilters = studyViewFilter.getGenomicDataFilters(); + + if (!CollectionUtils.isEmpty(genomicDataFilters)) { + Map molecularProfileMapByType = molecularProfileUtil + .categorizeMolecularProfilesByStableIdSuffixes(molecularProfiles) + .entrySet() + .stream() + .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().get(0))); + + genomicDataFilters.forEach(genomicDataFilter -> { + String profileType = genomicDataFilter.getProfileType(); + if (molecularProfileMapByType.containsKey(profileType)) { + if (molecularProfileMapByType.get(profileType).getDatatype().equals("DISCRETE")) { + genomicDataEqualityFilters.add(genomicDataFilter); + } else { + genomicDataIntervalFilters.add(genomicDataFilter); + } + } + }); + } + + if (!CollectionUtils.isEmpty(genomicDataEqualityFilters)) { + sampleIdentifiers = equalityFilterExpressionData(sampleIdentifiers, molecularProfiles, + genomicDataEqualityFilters, negateFilters); + } + + if (!CollectionUtils.isEmpty(genomicDataIntervalFilters)) { + sampleIdentifiers = intervalFilterExpressionData(sampleIdentifiers, molecularProfiles, + genomicDataIntervalFilters, negateFilters); + } sampleIdentifiers = intervalFilterExpressionData(sampleIdentifiers, molecularProfiles, studyViewFilter.getGenericAssayDataFilters(), negateFilters); @@ -847,99 +878,39 @@ private GenericAssayDataBin dataBintoGenericAssayDataBin(GenericAssayDataBinFilt } public List intervalFilterExpressionData( - List sampleIdentifiers, List molecularProfiles, List dataFilters, - Boolean negateFilters) { - - if (!CollectionUtils.isEmpty(dataFilters) && !CollectionUtils.isEmpty(sampleIdentifiers)) { - - Map> molecularProfileMap = molecularProfileUtil - .categorizeMolecularProfilesByStableIdSuffixes(molecularProfiles); + List sampleIdentifiers, List molecularProfiles, List dataFilters, + Boolean negateFilters) { - List studyIds = new ArrayList<>(); - List sampleIds = new ArrayList<>(); - studyViewFilterUtil.extractStudyAndSampleIds(sampleIdentifiers, studyIds, sampleIds); - List clinicalDatas = new ArrayList<>(); - List attributes = new ArrayList<>(); - if (dataFilters.get(0) instanceof GenomicDataFilter) { - List genomicDataIntervalFilters = (List) dataFilters; - Set hugoGeneSymbols = genomicDataIntervalFilters.stream() - .map(GenomicDataFilter::getHugoGeneSymbol).collect(Collectors.toSet()); - Map geneNameIdMap = geneService - .fetchGenes(new ArrayList<>(hugoGeneSymbols), GeneIdType.HUGO_GENE_SYMBOL.name(), - Projection.SUMMARY.name()) - .stream().collect(Collectors.toMap(Gene::getHugoGeneSymbol, Gene::getEntrezGeneId)); - - clinicalDatas = genomicDataIntervalFilters.stream().flatMap(genomicDataFilter -> { - - Map studyIdToMolecularProfileIdMap = molecularProfileMap - .getOrDefault(genomicDataFilter.getProfileType(), new ArrayList<>()) - .stream().collect(Collectors.toMap(MolecularProfile::getCancerStudyIdentifier, - MolecularProfile::getStableId)); - - GenomicDataBinFilter genomicDataBinFilter = new GenomicDataBinFilter(); - genomicDataBinFilter.setHugoGeneSymbol(genomicDataFilter.getHugoGeneSymbol()); - genomicDataBinFilter.setProfileType(genomicDataFilter.getProfileType()); - return invokeDataFunc(sampleIds, studyIds, - Arrays.asList(geneNameIdMap.get(genomicDataFilter.getHugoGeneSymbol()).toString()), - studyIdToMolecularProfileIdMap, genomicDataBinFilter, fetchMolecularData); - }).collect(Collectors.toList()); - - attributes = genomicDataIntervalFilters.stream().map(genomicDataIntervalFilter -> { - String attributeId = studyViewFilterUtil.getGenomicDataFilterUniqueKey( - genomicDataIntervalFilter.getHugoGeneSymbol(), genomicDataIntervalFilter.getProfileType()); - ClinicalDataFilter clinicalDataIntervalFilter = new ClinicalDataFilter(); - clinicalDataIntervalFilter.setAttributeId(attributeId); - clinicalDataIntervalFilter.setValues(genomicDataIntervalFilter.getValues()); - return clinicalDataIntervalFilter; - }).collect(Collectors.toList()); - } else { - List genericAssayDataFilters = (List) dataFilters; - - clinicalDatas = genericAssayDataFilters.stream().flatMap(genericAssayDataFilter -> { + return filterExpressionData(sampleIdentifiers, molecularProfiles, dataFilters, negateFilters, clinicalDataIntervalFilterApplier); + } - Map studyIdToMolecularProfileIdMap = molecularProfileMap - .getOrDefault(genericAssayDataFilter.getProfileType(), new ArrayList()) - .stream().collect(Collectors.toMap(MolecularProfile::getCancerStudyIdentifier, - MolecularProfile::getStableId)); - GenericAssayDataBinFilter genericAssayDataBinFilter = new GenericAssayDataBinFilter(); - genericAssayDataBinFilter.setStableId(genericAssayDataFilter.getStableId()); - genericAssayDataBinFilter.setProfileType(genericAssayDataFilter.getProfileType()); + public List equalityFilterExpressionData( + List sampleIdentifiers, List molecularProfiles, List dataFilters, + Boolean negateFilters) { - // get original data stream from invokeDataFunc - Stream dataStream = invokeDataFunc(sampleIds, studyIds, Arrays.asList(genericAssayDataBinFilter.getStableId()), - studyIdToMolecularProfileIdMap, genericAssayDataBinFilter, fetchGenericAssayData); - // For patient level generic assay profile, only keep the one sample per patient - List profiles = molecularProfileMap.getOrDefault(genericAssayDataFilter.getProfileType(), new ArrayList()); - if (profiles.size() > 0 && profiles.get(0).getPatientLevel() == true) { - dataStream = dataStream.collect(Collectors.groupingBy(d -> d.getPatientId())).values().stream() - .flatMap(d -> d.stream().limit(1)); - } - // don't change anything for non patient level data - return dataStream; - }).collect(Collectors.toList()); + return filterExpressionData(sampleIdentifiers, molecularProfiles, dataFilters, negateFilters, clinicalDataEqualityFilterApplier); + } - attributes = genericAssayDataFilters.stream().map(genericAssayDataFilter -> { - String attributeId = studyViewFilterUtil.getGenericAssayDataFilterUniqueKey( - genericAssayDataFilter.getStableId(), genericAssayDataFilter.getProfileType()); - ClinicalDataFilter clinicalDataIntervalFilter = new ClinicalDataFilter(); - clinicalDataIntervalFilter.setAttributeId(attributeId); - clinicalDataIntervalFilter.setValues(genericAssayDataFilter.getValues()); - return clinicalDataIntervalFilter; - }).collect(Collectors.toList()); - } + public List filterExpressionData( + List sampleIdentifiers, List molecularProfiles, List dataFilters, + Boolean negateFilters, ClinicalDataFilterApplier clinicalDataFilterApplier) { + if (!CollectionUtils.isEmpty(dataFilters) && !CollectionUtils.isEmpty(sampleIdentifiers)) { + List clinicalDatas = + fetchDataAndTransformToClinicalDataList(sampleIdentifiers, molecularProfiles, dataFilters); + List attributes =transformToClinicalDataFilter(dataFilters); MultiKeyMap clinicalDataMap = new MultiKeyMap(); clinicalDatas.forEach(clinicalData -> { clinicalDataMap.put(clinicalData.getStudyId(), clinicalData.getSampleId(), clinicalData.getAttrId(), - clinicalData.getAttrValue()); + clinicalData.getAttrValue()); }); List newSampleIdentifiers = new ArrayList<>(); for (SampleIdentifier sampleIdentifier : sampleIdentifiers) { - int count = clinicalDataIntervalFilterApplier.apply(attributes, clinicalDataMap, - sampleIdentifier.getSampleId(), sampleIdentifier.getStudyId(), negateFilters); + int count = clinicalDataFilterApplier.apply(attributes, clinicalDataMap, + sampleIdentifier.getSampleId(), sampleIdentifier.getStudyId(), negateFilters); if (count == attributes.size()) { newSampleIdentifiers.add(sampleIdentifier); @@ -951,4 +922,86 @@ public List intervalFilterExpressionDat return sampleIdentifiers; } + + private List fetchDataAndTransformToClinicalDataList( + List sampleIdentifiers, List molecularProfiles, List dataFilters) { + Map> molecularProfileMap = molecularProfileUtil + .categorizeMolecularProfilesByStableIdSuffixes(molecularProfiles); + + List studyIds = new ArrayList<>(); + List sampleIds = new ArrayList<>(); + studyViewFilterUtil.extractStudyAndSampleIds(sampleIdentifiers, studyIds, sampleIds); + + if (dataFilters.get(0) instanceof GenomicDataFilter) { + List genomicDataIntervalFilters = (List) dataFilters; + Set hugoGeneSymbols = genomicDataIntervalFilters.stream() + .map(GenomicDataFilter::getHugoGeneSymbol).collect(Collectors.toSet()); + Map geneNameIdMap = geneService + .fetchGenes(new ArrayList<>(hugoGeneSymbols), GeneIdType.HUGO_GENE_SYMBOL.name(), + Projection.SUMMARY.name()) + .stream().collect(Collectors.toMap(Gene::getHugoGeneSymbol, Gene::getEntrezGeneId)); + + return genomicDataIntervalFilters.stream().flatMap(genomicDataFilter -> { + + Map studyIdToMolecularProfileIdMap = molecularProfileMap + .getOrDefault(genomicDataFilter.getProfileType(), new ArrayList<>()) + .stream().collect(Collectors.toMap(MolecularProfile::getCancerStudyIdentifier, + MolecularProfile::getStableId)); + + GenomicDataBinFilter genomicDataBinFilter = new GenomicDataBinFilter(); + genomicDataBinFilter.setHugoGeneSymbol(genomicDataFilter.getHugoGeneSymbol()); + genomicDataBinFilter.setProfileType(genomicDataFilter.getProfileType()); + return invokeDataFunc(sampleIds, studyIds, + Collections.singletonList(geneNameIdMap.get(genomicDataFilter.getHugoGeneSymbol()).toString()), + studyIdToMolecularProfileIdMap, genomicDataBinFilter, fetchMolecularData); + }).collect(Collectors.toList()); + + } else { + + return ((List) dataFilters).stream().flatMap(genericAssayDataFilter -> { + + Map studyIdToMolecularProfileIdMap = molecularProfileMap + .getOrDefault(genericAssayDataFilter.getProfileType(), new ArrayList()) + .stream().collect(Collectors.toMap(MolecularProfile::getCancerStudyIdentifier, + MolecularProfile::getStableId)); + GenericAssayDataBinFilter genericAssayDataBinFilter = new GenericAssayDataBinFilter(); + genericAssayDataBinFilter.setStableId(genericAssayDataFilter.getStableId()); + genericAssayDataBinFilter.setProfileType(genericAssayDataFilter.getProfileType()); + + // get original data stream from invokeDataFunc + Stream dataStream = invokeDataFunc(sampleIds, studyIds, Collections.singletonList(genericAssayDataBinFilter.getStableId()), + studyIdToMolecularProfileIdMap, genericAssayDataBinFilter, fetchGenericAssayData); + // For patient level generic assay profile, only keep the one sample per patient + List profiles = molecularProfileMap.getOrDefault(genericAssayDataFilter.getProfileType(), new ArrayList<>()); + if (profiles.size() > 0 && profiles.get(0).getPatientLevel()) { + dataStream = dataStream.collect(Collectors.groupingBy(ClinicalData::getPatientId)).values().stream() + .flatMap(d -> d.stream().limit(1)); + } + // don't change anything for non patient level data + return dataStream; + }).collect(Collectors.toList()); + + } + } + + private List transformToClinicalDataFilter(List dataFilters) { + List attributes; + attributes = dataFilters.stream().map(dataFilter -> { + String attributeId; + if (dataFilter instanceof GenomicDataFilter) { + GenomicDataFilter genomicDataFilter = (GenomicDataFilter) dataFilter; + attributeId = studyViewFilterUtil.getGenomicDataFilterUniqueKey(genomicDataFilter.getHugoGeneSymbol(), genomicDataFilter.getProfileType()); + } else { + GenericAssayDataFilter genericAssayDataFilter = (GenericAssayDataFilter) dataFilter; + attributeId = studyViewFilterUtil.getGenericAssayDataFilterUniqueKey( + genericAssayDataFilter.getStableId(), genericAssayDataFilter.getProfileType()); + } + + ClinicalDataFilter clinicalDataFilter = new ClinicalDataFilter(); + clinicalDataFilter.setAttributeId(attributeId); + clinicalDataFilter.setValues(dataFilter.getValues()); + return clinicalDataFilter; + }).collect(Collectors.toList()); + return attributes; + } } diff --git a/web/src/main/java/org/cbioportal/web/util/StudyViewFilterUtil.java b/web/src/main/java/org/cbioportal/web/util/StudyViewFilterUtil.java index 0c92bb446a5..ecf5bdab85c 100644 --- a/web/src/main/java/org/cbioportal/web/util/StudyViewFilterUtil.java +++ b/web/src/main/java/org/cbioportal/web/util/StudyViewFilterUtil.java @@ -45,19 +45,27 @@ public void extractStudyAndSampleIds( } public void removeSelfFromFilter(String attributeId, StudyViewFilter studyViewFilter) { - if (studyViewFilter!= null && studyViewFilter.getClinicalDataFilters() != null) { + if (studyViewFilter != null && studyViewFilter.getClinicalDataFilters() != null) { studyViewFilter.getClinicalDataFilters().removeIf(f -> f.getAttributeId().equals(attributeId)); } } + + public void removeSelfFromGenomicDataFilter(String hugoGeneSymbol, String profileType, StudyViewFilter studyViewFilter) { + if (studyViewFilter != null && studyViewFilter.getGenomicDataFilters() != null) { + studyViewFilter.getGenomicDataFilters().removeIf(f -> + f.getHugoGeneSymbol().equals(hugoGeneSymbol) && f.getProfileType().equals(profileType) + ); + } + } public void removeSelfFromGenericAssayFilter(String stableId, StudyViewFilter studyViewFilter) { - if (studyViewFilter!= null && studyViewFilter.getGenericAssayDataFilters() != null) { + if (studyViewFilter != null && studyViewFilter.getGenericAssayDataFilters() != null) { studyViewFilter.getGenericAssayDataFilters().removeIf(f -> f.getStableId().equals(stableId)); } } public void removeSelfCustomDataFromFilter(String attributeId, StudyViewFilter studyViewFilter) { - if (studyViewFilter!= null && studyViewFilter.getCustomDataFilters() != null) { + if (studyViewFilter != null && studyViewFilter.getCustomDataFilters() != null) { studyViewFilter.getCustomDataFilters().removeIf(f -> f.getAttributeId().equals(attributeId)); } } diff --git a/web/src/test/java/org/cbioportal/web/StudyViewControllerTest.java b/web/src/test/java/org/cbioportal/web/StudyViewControllerTest.java index cc78e1522dc..3951e57b963 100644 --- a/web/src/test/java/org/cbioportal/web/StudyViewControllerTest.java +++ b/web/src/test/java/org/cbioportal/web/StudyViewControllerTest.java @@ -62,6 +62,11 @@ public class StudyViewControllerTest { private static final String TEST_GENERIC_ASSAY_DATA_VALUE_2 = "value2"; private static final String TEST_CLINICAL_EVENT_TYPE = "STATUS"; private static final Integer TEST_CLINICAL_EVENT_TYPE_COUNT = 513; + private static final String TEST_CNA_ALTERATION_NAME_1 = "test_cna_event_type_1"; + private static final String TEST_CNA_ALTERATION_NAME_2 = "test_cna_event_type_2"; + private static final String TEST_CNA_ALTERATION_VALUE_1 = "2"; + private static final String TEST_CNA_ALTERATION_VALUE_2 = "-2"; + private static final String TEST_MOLECULAR_PROFILE_TYPE = "test_molecular_profile_type"; private List filteredSampleIdentifiers = new ArrayList<>(); private List clinicalData = new ArrayList<>(); @@ -506,6 +511,92 @@ public void fetchSampleCounts() throws Exception { .andExpect(MockMvcResultMatchers.jsonPath("$[1].count").value(2)); } + + @Test + public void fetchGenomicDataCounts() throws Exception { + + when(studyViewFilterApplier.apply(any())).thenReturn(filteredSampleIdentifiers); + + List genomicDataCountItems = new ArrayList<>(); + + GenomicDataCount genomicDataCount1 = new GenomicDataCount(); + genomicDataCount1.setLabel(TEST_CNA_ALTERATION_NAME_1); + genomicDataCount1.setValue(TEST_CNA_ALTERATION_VALUE_1); + genomicDataCount1.setCount(1); + + GenomicDataCount genomicDataCount2 = new GenomicDataCount(); + genomicDataCount2.setLabel(TEST_CNA_ALTERATION_NAME_2); + genomicDataCount2.setValue(TEST_CNA_ALTERATION_VALUE_2); + genomicDataCount2.setCount(1); + + GenomicDataCountItem genomicDataCountItem1 = new GenomicDataCountItem(); + List genomicDataCounts1 = new ArrayList<>(); + genomicDataCounts1.add(genomicDataCount1); + genomicDataCounts1.add(genomicDataCount2); + genomicDataCountItem1.setHugoGeneSymbol(TEST_HUGO_GENE_SYMBOL_1); + genomicDataCountItem1.setProfileType(TEST_MOLECULAR_PROFILE_TYPE); + genomicDataCountItem1.setCounts(genomicDataCounts1); + + GenomicDataCountItem genomicDataCountItem2 = new GenomicDataCountItem(); + List genomicDataCounts2 = new ArrayList<>(); + genomicDataCounts2.add(genomicDataCount1); + genomicDataCounts2.add(genomicDataCount2); + genomicDataCountItem2.setHugoGeneSymbol(TEST_HUGO_GENE_SYMBOL_2); + genomicDataCountItem2.setProfileType(TEST_MOLECULAR_PROFILE_TYPE); + genomicDataCountItem2.setCounts(genomicDataCounts2); + + genomicDataCountItems.add(genomicDataCountItem1); + genomicDataCountItems.add(genomicDataCountItem2); + + when(studyViewService.getCNAAlterationCountsByGeneSpecific( + anyList(), + anyList(), + anyList())) + .thenReturn(genomicDataCountItems); + + GenomicDataCountFilter genomicDataCountFilter = new GenomicDataCountFilter(); + List genomicDataFilters = new ArrayList<>(); + + GenomicDataFilter genomicDataFilter1 = new GenomicDataFilter(); + genomicDataFilter1.setHugoGeneSymbol(TEST_HUGO_GENE_SYMBOL_1); + genomicDataFilter1.setProfileType(TEST_MOLECULAR_PROFILE_TYPE); + genomicDataFilters.add(genomicDataFilter1); + + GenomicDataFilter genomicDataFilter2 = new GenomicDataFilter(); + genomicDataFilter2.setHugoGeneSymbol(TEST_HUGO_GENE_SYMBOL_2); + genomicDataFilter2.setProfileType(TEST_MOLECULAR_PROFILE_TYPE); + genomicDataFilters.add(genomicDataFilter2); + + genomicDataCountFilter.setGenomicDataFilters(genomicDataFilters); + + StudyViewFilter studyViewFilter = new StudyViewFilter(); + studyViewFilter.setStudyIds(Arrays.asList(TEST_STUDY_ID)); + genomicDataCountFilter.setStudyViewFilter(studyViewFilter); + + mockMvc.perform(MockMvcRequestBuilders.post("/genomic-data-counts/fetch") + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(genomicDataCountFilter))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].hugoGeneSymbol").value(TEST_HUGO_GENE_SYMBOL_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].profileType").value(TEST_MOLECULAR_PROFILE_TYPE)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].counts[0].label").value(TEST_CNA_ALTERATION_NAME_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].counts[0].value").value(TEST_CNA_ALTERATION_VALUE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].counts[0].count").value(1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].counts[1].label").value(TEST_CNA_ALTERATION_NAME_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].counts[1].value").value(TEST_CNA_ALTERATION_VALUE_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[0].counts[1].count").value(1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].hugoGeneSymbol").value(TEST_HUGO_GENE_SYMBOL_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].profileType").value(TEST_MOLECULAR_PROFILE_TYPE)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].counts[0].label").value(TEST_CNA_ALTERATION_NAME_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].counts[0].value").value(TEST_CNA_ALTERATION_VALUE_1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].counts[0].count").value(1)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].counts[1].label").value(TEST_CNA_ALTERATION_NAME_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].counts[1].value").value(TEST_CNA_ALTERATION_VALUE_2)) + .andExpect(MockMvcResultMatchers.jsonPath("$[1].counts[1].count").value(1)); + } + @Ignore("Skip StudyViewControllerTest.fetchClinicalDataDensityPlot due to assertion errors") @Test public void fetchClinicalDataDensityPlot() throws Exception {