diff --git a/src/main/java/org/cbioportal/service/AlterationCountService.java b/src/main/java/org/cbioportal/service/AlterationCountService.java index e86420a7509..eaec004682e 100644 --- a/src/main/java/org/cbioportal/service/AlterationCountService.java +++ b/src/main/java/org/cbioportal/service/AlterationCountService.java @@ -3,6 +3,7 @@ import org.apache.commons.math3.util.Pair; import org.cbioportal.model.*; import org.cbioportal.model.util.Select; +import org.cbioportal.service.exception.StudyNotFoundException; import org.cbioportal.web.parameter.CategorizedClinicalDataCountFilter; import org.cbioportal.web.parameter.CustomSampleIdentifier; import org.cbioportal.web.parameter.SampleIdentifier; @@ -79,9 +80,9 @@ Pair, Long> getPatientCnaGeneCounts(List getMutatedGenes(StudyViewFilterContext studyViewFilterContext); - List getCnaGenes(StudyViewFilterContext studyViewFilterContext); + List getMutatedGenes(StudyViewFilterContext studyViewFilterContext) throws StudyNotFoundException; + List getCnaGenes(StudyViewFilterContext studyViewFilterContext) throws StudyNotFoundException; - List getStructuralVariantGenes(StudyViewFilterContext studyViewFilterContext); + List getStructuralVariantGenes(StudyViewFilterContext studyViewFilterContext) throws StudyNotFoundException; } diff --git a/src/main/java/org/cbioportal/service/StudyViewColumnarService.java b/src/main/java/org/cbioportal/service/StudyViewColumnarService.java index 63112da8dd6..219e93a637c 100644 --- a/src/main/java/org/cbioportal/service/StudyViewColumnarService.java +++ b/src/main/java/org/cbioportal/service/StudyViewColumnarService.java @@ -11,6 +11,7 @@ import org.cbioportal.model.PatientTreatmentReport; import org.cbioportal.model.Sample; import org.cbioportal.model.SampleTreatmentReport; +import org.cbioportal.service.exception.StudyNotFoundException; import org.cbioportal.web.parameter.ClinicalDataType; import org.cbioportal.web.parameter.GenomicDataBinFilter; import org.cbioportal.web.parameter.GenomicDataFilter; @@ -23,9 +24,9 @@ public interface StudyViewColumnarService { List getFilteredSamples(StudyViewFilter studyViewFilter); - List getMutatedGenes(StudyViewFilter interceptedStudyViewFilter); - List getCnaGenes(StudyViewFilter interceptedStudyViewFilter); - List getStructuralVariantGenes(StudyViewFilter studyViewFilter); + List getMutatedGenes(StudyViewFilter interceptedStudyViewFilter) throws StudyNotFoundException; + List getCnaGenes(StudyViewFilter interceptedStudyViewFilter) throws StudyNotFoundException; + List getStructuralVariantGenes(StudyViewFilter studyViewFilter) throws StudyNotFoundException; Map getClinicalAttributeDatatypeMap(); diff --git a/src/main/java/org/cbioportal/service/impl/AlterationCountServiceImpl.java b/src/main/java/org/cbioportal/service/impl/AlterationCountServiceImpl.java index 5597d02fb6b..19161d45fcf 100644 --- a/src/main/java/org/cbioportal/service/impl/AlterationCountServiceImpl.java +++ b/src/main/java/org/cbioportal/service/impl/AlterationCountServiceImpl.java @@ -7,15 +7,22 @@ import org.cbioportal.model.AlterationFilter; import org.cbioportal.model.AlterationType; import org.cbioportal.model.CopyNumberCountByGene; +import org.cbioportal.model.Gistic; +import org.cbioportal.model.GisticToGene; import org.cbioportal.model.MolecularProfile; import org.cbioportal.model.MolecularProfileCaseIdentifier; +import org.cbioportal.model.MutSig; import org.cbioportal.model.StudyViewFilterContext; import org.cbioportal.model.util.Select; import org.cbioportal.persistence.AlterationRepository; import org.cbioportal.persistence.MolecularProfileRepository; import org.cbioportal.persistence.StudyViewRepository; import org.cbioportal.service.AlterationCountService; +import org.cbioportal.service.SignificantCopyNumberRegionService; +import org.cbioportal.service.SignificantlyMutatedGeneService; +import org.cbioportal.service.exception.StudyNotFoundException; import org.cbioportal.service.util.AlterationEnrichmentUtil; +import org.cbioportal.web.parameter.Projection; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.lang.NonNull; import org.springframework.stereotype.Service; @@ -41,8 +48,9 @@ public class AlterationCountServiceImpl implements AlterationCountService { private final AlterationEnrichmentUtil alterationEnrichmentUtilCna; private final AlterationEnrichmentUtil alterationEnrichmentUtilStructVar; private final MolecularProfileRepository molecularProfileRepository; - + private final SignificantlyMutatedGeneService significantlyMutatedGeneService; private final StudyViewRepository studyViewRepository; + private final SignificantCopyNumberRegionService significantCopyNumberRegionService; private static final String WHOLE_EXOME_SEQUENCING = "WES"; @@ -52,13 +60,16 @@ public AlterationCountServiceImpl(AlterationRepository alterationRepository, Alt AlterationEnrichmentUtil alterationEnrichmentUtilCna, AlterationEnrichmentUtil alterationEnrichmentUtilStructVar, MolecularProfileRepository molecularProfileRepository, - StudyViewRepository studyViewRepository) { + StudyViewRepository studyViewRepository, SignificantlyMutatedGeneService significantlyMutatedGeneService, + SignificantCopyNumberRegionService significantCopyNumberRegionService) { this.alterationRepository = alterationRepository; this.alterationEnrichmentUtil = alterationEnrichmentUtil; this.alterationEnrichmentUtilCna = alterationEnrichmentUtilCna; this.alterationEnrichmentUtilStructVar = alterationEnrichmentUtilStructVar; this.molecularProfileRepository = molecularProfileRepository; this.studyViewRepository = studyViewRepository; + this.significantlyMutatedGeneService = significantlyMutatedGeneService; + this.significantCopyNumberRegionService = significantCopyNumberRegionService; } @Override public Pair, Long> getSampleAlterationGeneCounts(List molecularProfileCaseIdentifiers, @@ -253,22 +264,24 @@ public Pair, Long> getPatientCnaGeneCounts(List getMutatedGenes(StudyViewFilterContext studyViewFilterContext) { - var alterationCountByGenes = studyViewRepository.getMutatedGenes(studyViewFilterContext); - return populateAlterationCounts(combineAlterationCountsWithConflictingHugoSymbols(alterationCountByGenes), studyViewFilterContext, AlterationType.MUTATION_EXTENDED); + public List getMutatedGenes(StudyViewFilterContext studyViewFilterContext) throws StudyNotFoundException { + var alterationCountByGenes = populateAlterationCounts(combineAlterationCountsWithConflictingHugoSymbols( studyViewRepository.getMutatedGenes(studyViewFilterContext)), + studyViewFilterContext, AlterationType.MUTATION_EXTENDED); + return populateAlterationCountsWithMutSigQValue(alterationCountByGenes, studyViewFilterContext); } - public List getCnaGenes(StudyViewFilterContext studyViewFilterContext) { - var copyNumberCountByGenes = studyViewRepository.getCnaGenes(studyViewFilterContext); - return populateAlterationCounts(combineCopyNumberCountsWithConflictingHugoSymbols(copyNumberCountByGenes), studyViewFilterContext, AlterationType.COPY_NUMBER_ALTERATION); + public List getCnaGenes(StudyViewFilterContext studyViewFilterContext) throws StudyNotFoundException { + var copyNumberAlterationCounts = populateAlterationCounts(combineCopyNumberCountsWithConflictingHugoSymbols(studyViewRepository.getCnaGenes(studyViewFilterContext)), studyViewFilterContext, AlterationType.COPY_NUMBER_ALTERATION); + return populateAlterationCountsWithCNASigQValue(copyNumberAlterationCounts, studyViewFilterContext); } @Override - public List getStructuralVariantGenes(StudyViewFilterContext studyViewFilterContext) { - var alterationCountByGenes = studyViewRepository.getStructuralVariantGenes(studyViewFilterContext); - return populateAlterationCounts(combineAlterationCountsWithConflictingHugoSymbols(alterationCountByGenes), studyViewFilterContext, AlterationType.STRUCTURAL_VARIANT); + public List getStructuralVariantGenes(StudyViewFilterContext studyViewFilterContext) throws StudyNotFoundException { + var alterationCountByGenes = populateAlterationCounts(combineAlterationCountsWithConflictingHugoSymbols(studyViewRepository.getStructuralVariantGenes(studyViewFilterContext)), + studyViewFilterContext, AlterationType.STRUCTURAL_VARIANT); + return populateAlterationCountsWithMutSigQValue(alterationCountByGenes, studyViewFilterContext); } - + private < T extends AlterationCountByGene> List populateAlterationCounts(@NonNull List alterationCounts, @NonNull StudyViewFilterContext studyViewFilterContext, @NonNull AlterationType alterationType) { @@ -276,7 +289,7 @@ private < T extends AlterationCountByGene> List populateAlterationCounts(@Non var profiledCountsMap = studyViewRepository.getTotalProfiledCounts(studyViewFilterContext, alterationType.toString()); final var matchingGenePanelIdsMap = studyViewRepository.getMatchingGenePanelIds(studyViewFilterContext, alterationType.toString()); final int sampleProfileCountWithoutGenePanelData = studyViewRepository.getSampleProfileCountWithoutPanelData(studyViewFilterContext, alterationType.toString()); - + alterationCounts.parallelStream() .forEach(alterationCountByGene -> { String hugoGeneSymbol = alterationCountByGene.getHugoGeneSymbol(); @@ -290,10 +303,38 @@ private < T extends AlterationCountByGene> List populateAlterationCounts(@Non alterationCountByGene.setNumberOfProfiledCases(totalProfiledCount); alterationCountByGene.setMatchingGenePanelIds(matchingGenePanelIds); + }); return alterationCounts; } + private List populateAlterationCountsWithMutSigQValue(List alterationCountByGenes, StudyViewFilterContext studyViewFilterContext) throws StudyNotFoundException { + final var mutSigs = getMutSigs(studyViewFilterContext); + // If MutSig is not empty update Mutated Genes + if (!mutSigs.isEmpty()) { + alterationCountByGenes.parallelStream() + .filter(alterationCount -> mutSigs.containsKey(alterationCount.getHugoGeneSymbol())) + .forEach(alterationCount -> + alterationCount.setqValue(mutSigs.get(alterationCount.getHugoGeneSymbol()).getqValue()) + ); + } + return alterationCountByGenes; + } + + private List populateAlterationCountsWithCNASigQValue(List alterationCountByGenes, StudyViewFilterContext studyViewFilterContext) throws StudyNotFoundException { + final var gisticMap = getGisticMap(studyViewFilterContext); + + if(!gisticMap.isEmpty()) { + alterationCountByGenes.parallelStream() + .filter(alterationCount -> gisticMap.containsKey(Pair.create(alterationCount.getHugoGeneSymbol(), alterationCount.getAlteration()))) + .forEach(alterationCount -> { + alterationCount.setqValue(gisticMap.get(Pair.create(alterationCount.getHugoGeneSymbol(), alterationCount.getAlteration())).getqValue()); + }); + } + return alterationCountByGenes; + } + + /** * Combines alteration counts by Hugo gene symbols. If multiple entries exist for the same * gene symbol, their number of altered cases and total counts are summed up. Returns a @@ -349,6 +390,50 @@ private boolean hasGenePanelData(@NonNull Set matchingGenePanelIds) { && matchingGenePanelIds.size() > 1 || !matchingGenePanelIds.contains(WHOLE_EXOME_SEQUENCING) && !matchingGenePanelIds.isEmpty(); } + private Map getMutSigs(StudyViewFilterContext studyViewFilterContext) throws StudyNotFoundException { + var distinctStudyIds = new HashSet<>(studyViewFilterContext.studyViewFilter().getStudyIds()).stream().toList(); + Map mutSigs = new HashMap<>(); + if (distinctStudyIds.size() == 1) { + var studyId = distinctStudyIds.getFirst(); + mutSigs = significantlyMutatedGeneService.getSignificantlyMutatedGenes( + studyId, + Projection.SUMMARY.name(), + null, + null, + null, + null) + .stream() + .collect(Collectors.toMap(MutSig::getHugoGeneSymbol, Function.identity())); + } + return mutSigs; + } + + private Map, Gistic> getGisticMap(StudyViewFilterContext studyViewFilterContext) throws StudyNotFoundException { + var distinctStudyIds = new HashSet<>(studyViewFilterContext.studyViewFilter().getStudyIds()).stream().toList(); + Map, Gistic> gisticMap = new HashMap<>(); + if (distinctStudyIds.size() == 1) { + var studyId = distinctStudyIds.getFirst(); + List gisticList = significantCopyNumberRegionService.getSignificantCopyNumberRegions( + studyId, + Projection.SUMMARY.name(), + null, + null, + null, + null); + for(Gistic gistic : gisticList) { + var amp = (gistic.getAmp()) ? 2 : -2; + for (GisticToGene gene : gistic.getGenes()) { + var key = Pair.create(gene.getHugoGeneSymbol(), amp); + Gistic currentGistic = gisticMap.get(key); + if (currentGistic == null || gistic.getqValue().compareTo(currentGistic.getqValue()) < 0) { + gisticMap.put(key, gistic); + } + } + } + } + return gisticMap; + } + private Pair, Long> getAlterationGeneCounts( List molecularProfileCaseIdentifiers, boolean includeFrequency, diff --git a/src/main/java/org/cbioportal/service/impl/StudyViewColumnarServiceImpl.java b/src/main/java/org/cbioportal/service/impl/StudyViewColumnarServiceImpl.java index ae1b93318ff..c6cd45c538f 100644 --- a/src/main/java/org/cbioportal/service/impl/StudyViewColumnarServiceImpl.java +++ b/src/main/java/org/cbioportal/service/impl/StudyViewColumnarServiceImpl.java @@ -16,6 +16,7 @@ import org.cbioportal.persistence.StudyViewRepository; import org.cbioportal.service.AlterationCountService; import org.cbioportal.service.StudyViewColumnarService; +import org.cbioportal.service.exception.StudyNotFoundException; import org.cbioportal.service.treatment.TreatmentCountReportService; import org.cbioportal.web.parameter.ClinicalDataType; import org.cbioportal.web.parameter.CustomSampleIdentifier; @@ -59,7 +60,7 @@ public List getFilteredSamples(StudyViewFilter studyViewFilter) { } @Override - public List getMutatedGenes(StudyViewFilter studyViewFilter) { + public List getMutatedGenes(StudyViewFilter studyViewFilter) throws StudyNotFoundException { return alterationCountService.getMutatedGenes(createContext(studyViewFilter)); } @@ -93,12 +94,12 @@ public List getGenericAssayDataBinCounts(StudyViewFilter return generateDataCountItemsFromDataCounts(studyViewRepository.getGenericAssayDataBinCounts(createContext(studyViewFilter), filteredAttributes)); } - public List getCnaGenes(StudyViewFilter studyViewFilter) { + public List getCnaGenes(StudyViewFilter studyViewFilter) throws StudyNotFoundException { return alterationCountService.getCnaGenes(createContext(studyViewFilter)); } @Override - public List getStructuralVariantGenes(StudyViewFilter studyViewFilter) { + public List getStructuralVariantGenes(StudyViewFilter studyViewFilter) throws StudyNotFoundException { return alterationCountService.getStructuralVariantGenes(createContext(studyViewFilter)); } diff --git a/src/main/java/org/cbioportal/web/columnar/StudyViewColumnStoreController.java b/src/main/java/org/cbioportal/web/columnar/StudyViewColumnStoreController.java index c5d3f314e33..0d0df0de0ef 100644 --- a/src/main/java/org/cbioportal/web/columnar/StudyViewColumnStoreController.java +++ b/src/main/java/org/cbioportal/web/columnar/StudyViewColumnStoreController.java @@ -167,7 +167,7 @@ public ResponseEntity> fetchCnaGenes( @RequestBody(required = false) StudyViewFilter studyViewFilter, @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, @RequestAttribute(required = false, value = "interceptedStudyViewFilter") StudyViewFilter interceptedStudyViewFilter - ) { + ) throws StudyNotFoundException { return new ResponseEntity<>( studyViewColumnarService.getCnaGenes(interceptedStudyViewFilter), HttpStatus.OK @@ -187,7 +187,7 @@ public ResponseEntity> fetchStructuralVariantGenes( @RequestAttribute(required = false, value = "involvedCancerStudies") Collection involvedCancerStudies, @Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface. @Valid @RequestAttribute(required = false, value = "interceptedStudyViewFilter") StudyViewFilter interceptedStudyViewFilter - ) { + ) throws StudyNotFoundException { return new ResponseEntity<>(studyViewColumnarService.getStructuralVariantGenes(interceptedStudyViewFilter), HttpStatus.OK); } diff --git a/src/test/java/org/cbioportal/service/impl/AlterationCountServiceImplTest.java b/src/test/java/org/cbioportal/service/impl/AlterationCountServiceImplTest.java index c000835c32d..45e181d7598 100644 --- a/src/test/java/org/cbioportal/service/impl/AlterationCountServiceImplTest.java +++ b/src/test/java/org/cbioportal/service/impl/AlterationCountServiceImplTest.java @@ -13,6 +13,7 @@ import org.cbioportal.persistence.AlterationRepository; import org.cbioportal.persistence.MolecularProfileRepository; import org.cbioportal.persistence.StudyViewRepository; +import org.cbioportal.service.SignificantlyMutatedGeneService; import org.cbioportal.service.exception.MolecularProfileNotFoundException; import org.cbioportal.service.util.AlterationEnrichmentUtil; import org.cbioportal.service.util.MolecularProfileUtil; @@ -57,6 +58,10 @@ public class AlterationCountServiceImplTest extends BaseServiceImplTest { private MolecularProfileRepository molecularProfileRepository; @Mock private StudyViewRepository studyViewRepository; + @Mock + private SignificantlyMutatedGeneService significantlyMutatedGeneService; + @Mock + private SignificantCopyNumberRegionServiceImpl significantCopyNumberRegionService; List caseIdentifiers = Arrays.asList(new MolecularProfileCaseIdentifier("A", MOLECULAR_PROFILE_ID)); Select mutationEventTypes = Select.byValues(Arrays.asList(MutationEventType.missense_mutation)); @@ -85,7 +90,8 @@ public void setup() { MockitoAnnotations.openMocks(this); alterationCountService = new AlterationCountServiceImpl(alterationRepository, alterationEnrichmentUtil, - alterationEnrichmentUtilCna, alterationEnrichmentUtilStructVar, molecularProfileRepository, studyViewRepository); + alterationEnrichmentUtilCna, alterationEnrichmentUtilStructVar, molecularProfileRepository, + studyViewRepository, significantlyMutatedGeneService, significantCopyNumberRegionService); MolecularProfile molecularProfile = new MolecularProfile(); molecularProfile.setStableId(MOLECULAR_PROFILE_ID);