Skip to content

Commit

Permalink
Update to add QValue for Alteration Count Services (#11034)
Browse files Browse the repository at this point in the history
* Update to add QValue for Alteration Count Services

* Update to return List instead of Set

* Update to only add mut_sig to mutated_genes

* Remove unneeded Exception

* Add Qvalue for Structural Variant and CNA

* Update logic to add gistic to map
  • Loading branch information
haynescd authored Oct 2, 2024
1 parent ceed01f commit 2d913e9
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -79,9 +80,9 @@ Pair<List<CopyNumberCountByGene>, Long> getPatientCnaGeneCounts(List<MolecularPr
boolean includeMissingAlterationsFromGenePanel,
AlterationFilter alterationFilter);

List<AlterationCountByGene> getMutatedGenes(StudyViewFilterContext studyViewFilterContext);
List<CopyNumberCountByGene> getCnaGenes(StudyViewFilterContext studyViewFilterContext);
List<AlterationCountByGene> getMutatedGenes(StudyViewFilterContext studyViewFilterContext) throws StudyNotFoundException;
List<CopyNumberCountByGene> getCnaGenes(StudyViewFilterContext studyViewFilterContext) throws StudyNotFoundException;

List<AlterationCountByGene> getStructuralVariantGenes(StudyViewFilterContext studyViewFilterContext);
List<AlterationCountByGene> getStructuralVariantGenes(StudyViewFilterContext studyViewFilterContext) throws StudyNotFoundException;

}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -23,9 +24,9 @@ public interface StudyViewColumnarService {

List<Sample> getFilteredSamples(StudyViewFilter studyViewFilter);

List<AlterationCountByGene> getMutatedGenes(StudyViewFilter interceptedStudyViewFilter);
List<CopyNumberCountByGene> getCnaGenes(StudyViewFilter interceptedStudyViewFilter);
List<AlterationCountByGene> getStructuralVariantGenes(StudyViewFilter studyViewFilter);
List<AlterationCountByGene> getMutatedGenes(StudyViewFilter interceptedStudyViewFilter) throws StudyNotFoundException;
List<CopyNumberCountByGene> getCnaGenes(StudyViewFilter interceptedStudyViewFilter) throws StudyNotFoundException;
List<AlterationCountByGene> getStructuralVariantGenes(StudyViewFilter studyViewFilter) throws StudyNotFoundException;

Map<String, ClinicalDataType> getClinicalAttributeDatatypeMap();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -41,8 +48,9 @@ public class AlterationCountServiceImpl implements AlterationCountService {
private final AlterationEnrichmentUtil<CopyNumberCountByGene> alterationEnrichmentUtilCna;
private final AlterationEnrichmentUtil<AlterationCountByStructuralVariant> 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";

Expand All @@ -52,13 +60,16 @@ public AlterationCountServiceImpl(AlterationRepository alterationRepository, Alt
AlterationEnrichmentUtil<CopyNumberCountByGene> alterationEnrichmentUtilCna,
AlterationEnrichmentUtil<AlterationCountByStructuralVariant> 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<List<AlterationCountByGene>, Long> getSampleAlterationGeneCounts(List<MolecularProfileCaseIdentifier> molecularProfileCaseIdentifiers,
Expand Down Expand Up @@ -253,30 +264,32 @@ public Pair<List<CopyNumberCountByGene>, Long> getPatientCnaGeneCounts(List<Mole
}

@Override
public List<AlterationCountByGene> getMutatedGenes(StudyViewFilterContext studyViewFilterContext) {
var alterationCountByGenes = studyViewRepository.getMutatedGenes(studyViewFilterContext);
return populateAlterationCounts(combineAlterationCountsWithConflictingHugoSymbols(alterationCountByGenes), studyViewFilterContext, AlterationType.MUTATION_EXTENDED);
public List<AlterationCountByGene> getMutatedGenes(StudyViewFilterContext studyViewFilterContext) throws StudyNotFoundException {
var alterationCountByGenes = populateAlterationCounts(combineAlterationCountsWithConflictingHugoSymbols( studyViewRepository.getMutatedGenes(studyViewFilterContext)),
studyViewFilterContext, AlterationType.MUTATION_EXTENDED);
return populateAlterationCountsWithMutSigQValue(alterationCountByGenes, studyViewFilterContext);
}

public List<CopyNumberCountByGene> getCnaGenes(StudyViewFilterContext studyViewFilterContext) {
var copyNumberCountByGenes = studyViewRepository.getCnaGenes(studyViewFilterContext);
return populateAlterationCounts(combineCopyNumberCountsWithConflictingHugoSymbols(copyNumberCountByGenes), studyViewFilterContext, AlterationType.COPY_NUMBER_ALTERATION);
public List<CopyNumberCountByGene> getCnaGenes(StudyViewFilterContext studyViewFilterContext) throws StudyNotFoundException {
var copyNumberAlterationCounts = populateAlterationCounts(combineCopyNumberCountsWithConflictingHugoSymbols(studyViewRepository.getCnaGenes(studyViewFilterContext)), studyViewFilterContext, AlterationType.COPY_NUMBER_ALTERATION);
return populateAlterationCountsWithCNASigQValue(copyNumberAlterationCounts, studyViewFilterContext);
}

@Override
public List<AlterationCountByGene> getStructuralVariantGenes(StudyViewFilterContext studyViewFilterContext) {
var alterationCountByGenes = studyViewRepository.getStructuralVariantGenes(studyViewFilterContext);
return populateAlterationCounts(combineAlterationCountsWithConflictingHugoSymbols(alterationCountByGenes), studyViewFilterContext, AlterationType.STRUCTURAL_VARIANT);
public List<AlterationCountByGene> 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<T> populateAlterationCounts(@NonNull List<T> alterationCounts,
@NonNull StudyViewFilterContext studyViewFilterContext,
@NonNull AlterationType alterationType) {
final int profiledCountWithoutGenePanelData = studyViewRepository.getTotalProfiledCountsByAlterationType(studyViewFilterContext, alterationType.toString());
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();
Expand All @@ -290,10 +303,38 @@ private < T extends AlterationCountByGene> List<T> populateAlterationCounts(@Non
alterationCountByGene.setNumberOfProfiledCases(totalProfiledCount);

alterationCountByGene.setMatchingGenePanelIds(matchingGenePanelIds);

});
return alterationCounts;
}

private List<AlterationCountByGene> populateAlterationCountsWithMutSigQValue(List<AlterationCountByGene> 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<CopyNumberCountByGene> populateAlterationCountsWithCNASigQValue(List<CopyNumberCountByGene> 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
Expand Down Expand Up @@ -349,6 +390,50 @@ private boolean hasGenePanelData(@NonNull Set<String> matchingGenePanelIds) {
&& matchingGenePanelIds.size() > 1 || !matchingGenePanelIds.contains(WHOLE_EXOME_SEQUENCING) && !matchingGenePanelIds.isEmpty();
}

private Map<String, MutSig> getMutSigs(StudyViewFilterContext studyViewFilterContext) throws StudyNotFoundException {
var distinctStudyIds = new HashSet<>(studyViewFilterContext.studyViewFilter().getStudyIds()).stream().toList();
Map<String, MutSig> 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<Pair<String, Integer>, Gistic> getGisticMap(StudyViewFilterContext studyViewFilterContext) throws StudyNotFoundException {
var distinctStudyIds = new HashSet<>(studyViewFilterContext.studyViewFilter().getStudyIds()).stream().toList();
Map<Pair<String, Integer>, Gistic> gisticMap = new HashMap<>();
if (distinctStudyIds.size() == 1) {
var studyId = distinctStudyIds.getFirst();
List<Gistic> 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 <S extends AlterationCountBase> Pair<List<S>, Long> getAlterationGeneCounts(
List<MolecularProfileCaseIdentifier> molecularProfileCaseIdentifiers,
boolean includeFrequency,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -59,7 +60,7 @@ public List<Sample> getFilteredSamples(StudyViewFilter studyViewFilter) {
}

@Override
public List<AlterationCountByGene> getMutatedGenes(StudyViewFilter studyViewFilter) {
public List<AlterationCountByGene> getMutatedGenes(StudyViewFilter studyViewFilter) throws StudyNotFoundException {
return alterationCountService.getMutatedGenes(createContext(studyViewFilter));
}

Expand Down Expand Up @@ -93,12 +94,12 @@ public List<ClinicalDataCountItem> getGenericAssayDataBinCounts(StudyViewFilter
return generateDataCountItemsFromDataCounts(studyViewRepository.getGenericAssayDataBinCounts(createContext(studyViewFilter), filteredAttributes));
}

public List<CopyNumberCountByGene> getCnaGenes(StudyViewFilter studyViewFilter) {
public List<CopyNumberCountByGene> getCnaGenes(StudyViewFilter studyViewFilter) throws StudyNotFoundException {
return alterationCountService.getCnaGenes(createContext(studyViewFilter));
}

@Override
public List<AlterationCountByGene> getStructuralVariantGenes(StudyViewFilter studyViewFilter) {
public List<AlterationCountByGene> getStructuralVariantGenes(StudyViewFilter studyViewFilter) throws StudyNotFoundException {
return alterationCountService.getStructuralVariantGenes(createContext(studyViewFilter));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ public ResponseEntity<List<CopyNumberCountByGene>> fetchCnaGenes(
@RequestBody(required = false) StudyViewFilter studyViewFilter,
@RequestAttribute(required = false, value = "involvedCancerStudies") Collection<String> involvedCancerStudies,
@RequestAttribute(required = false, value = "interceptedStudyViewFilter") StudyViewFilter interceptedStudyViewFilter
) {
) throws StudyNotFoundException {
return new ResponseEntity<>(
studyViewColumnarService.getCnaGenes(interceptedStudyViewFilter),
HttpStatus.OK
Expand All @@ -187,7 +187,7 @@ public ResponseEntity<List<AlterationCountByGene>> fetchStructuralVariantGenes(
@RequestAttribute(required = false, value = "involvedCancerStudies") Collection<String> 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);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<MolecularProfileCaseIdentifier> caseIdentifiers = Arrays.asList(new MolecularProfileCaseIdentifier("A", MOLECULAR_PROFILE_ID));
Select<MutationEventType> mutationEventTypes = Select.byValues(Arrays.asList(MutationEventType.missense_mutation));
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit 2d913e9

Please sign in to comment.