Skip to content

Commit

Permalink
revamp mutationDataFilters logic to support intersection and union
Browse files Browse the repository at this point in the history
  • Loading branch information
qlu-cls committed Dec 6, 2023
1 parent 0c93591 commit c483c96
Show file tree
Hide file tree
Showing 7 changed files with 187 additions and 52 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

public enum MutationFilterOption {
MUTATED("Mutated"),
NOT_MUTATED("Not mutated"),
NOT_PROFILED("Not profiled"),
NOT_MUTATED("Not Mutated"),
NOT_PROFILED("Not Profiled"),
;

private final String mutationFilterOption;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,7 @@
SELECT
gene.HUGO_GENE_SYMBOL as hugoGeneSymbol,
#{profileType} as profileType,
mutation_event.MUTATION_TYPE AS label,
REPLACE(mutation_event.MUTATION_TYPE, '_', ' ') AS label,
mutation_event.MUTATION_TYPE AS value,
COUNT(*) AS count,
COUNT(DISTINCT(sample.INTERNAL_ID)) AS uniqueCount
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,26 +174,26 @@ public List<GenomicDataCountItem> getMutationCountsByGeneSpecific(List<String> s

if (CollectionUtils.isEmpty(genomicDataCounts)) {
GenomicDataCount genomicDataCountMutated = new GenomicDataCount();
genomicDataCountMutated.setLabel(MutationFilterOption.MUTATED.name());
genomicDataCountMutated.setLabel(MutationFilterOption.MUTATED.getMutationType());
genomicDataCountMutated.setValue(MutationFilterOption.MUTATED.name());
genomicDataCountMutated.setCount(mutatedCount);
genomicDataCountMutated.setUniqueCount(mutatedCount);
genomicDataCounts.add(genomicDataCountMutated);
if (genomicDataCountMutated.getCount() > 0) genomicDataCounts.add(genomicDataCountMutated);
}

GenomicDataCount genomicDataCountNotMutated = new GenomicDataCount();
genomicDataCountNotMutated.setLabel(MutationFilterOption.NOT_MUTATED.name());
genomicDataCountNotMutated.setLabel(MutationFilterOption.NOT_MUTATED.getMutationType());
genomicDataCountNotMutated.setValue(MutationFilterOption.NOT_MUTATED.name());
genomicDataCountNotMutated.setCount(profiledCount - mutatedCount);
genomicDataCountNotMutated.setUniqueCount(profiledCount - mutatedCount);
genomicDataCounts.add(genomicDataCountNotMutated);
if (genomicDataCountNotMutated.getCount() > 0) genomicDataCounts.add(genomicDataCountNotMutated);

GenomicDataCount genomicDataCountNotProfiled = new GenomicDataCount();
genomicDataCountNotProfiled.setLabel(MutationFilterOption.NOT_PROFILED.name());
genomicDataCountNotProfiled.setLabel(MutationFilterOption.NOT_PROFILED.getMutationType());
genomicDataCountNotProfiled.setValue(MutationFilterOption.NOT_PROFILED.name());
genomicDataCountNotProfiled.setCount(totalCount - profiledCount);
genomicDataCountNotProfiled.setUniqueCount(totalCount - profiledCount);
genomicDataCounts.add(genomicDataCountNotProfiled);
if (genomicDataCountNotProfiled.getCount() > 0) genomicDataCounts.add(genomicDataCountNotProfiled);

genomicDataCountItem.setCounts(genomicDataCounts);

Expand Down Expand Up @@ -226,14 +226,18 @@ public List<GenomicDataCountItem> getMutationTypeCountsByGeneSpecific(List<Strin
List<String> mappedSampleIds = sampleAndProfileIds.getFirst();
List<String> mappedProfileIds = sampleAndProfileIds.getSecond();

if (mappedSampleIds.isEmpty()) {
if (mappedSampleIds.isEmpty() || mappedProfileIds.isEmpty()) {
return Stream.of();
}

GenomicDataCountItem genomicDataCountItem = mutationService.getMutationCountsByType(mappedProfileIds,
mappedSampleIds, stableIds, profileType);

return Stream.of(genomicDataCountItem);
if (genomicDataCountItem != null) {
return Stream.of(genomicDataCountItem);
} else {
return Stream.empty();
}
})
.collect(Collectors.toList());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1096,9 +1096,10 @@ public ResponseEntity<List<GenomicDataCountItem>> fetchMutationDataCounts(
// 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(
studyViewFilterUtil.removeSelfFromMutationDataFilter(
gdFilters.get(0).getHugoGeneSymbol(),
gdFilters.get(0).getProfileType(),
projection == Projection.SUMMARY ? MutationOption.MUTATED : MutationOption.EVENT,
studyViewFilter);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,48 @@
import com.fasterxml.jackson.annotation.JsonInclude;

import javax.validation.constraints.NotNull;
import java.util.List;

import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL;

@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(NON_NULL)
public class MutationDataFilter extends GenomicDataFilter {
public class MutationDataFilter {
private String hugoGeneSymbol;
private String profileType;
@NotNull
private MutationOption categorization;

private List<List<DataFilterValue>> values;

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 MutationOption getCategorization() { return categorization; }

public void setCategorization(MutationOption categorization) {
this.categorization = categorization;
}

public List<List<DataFilterValue>> getValues() {
return values;
}

public void setValues(List<List<DataFilterValue>> values) {
this.values = values;
}
}

155 changes: 120 additions & 35 deletions web/src/main/java/org/cbioportal/web/util/StudyViewFilterApplier.java
Original file line number Diff line number Diff line change
Expand Up @@ -310,13 +310,13 @@ public List<SampleIdentifier> apply(StudyViewFilter studyViewFilter, Boolean neg
}

if (!CollectionUtils.isEmpty(mutationOptionDataFilters)) {
sampleIdentifiers = equalityFilterExpressionData(sampleIdentifiers, molecularProfiles,
mutationOptionDataFilters, negateFilters);
sampleIdentifiers = filterMutationData(sampleIdentifiers, molecularProfiles,
mutationOptionDataFilters, negateFilters, clinicalDataEqualityFilterApplier);
}

if (!CollectionUtils.isEmpty(mutationTypeDataFilters)) {
sampleIdentifiers = equalityFilterExpressionData(sampleIdentifiers, molecularProfiles,
mutationTypeDataFilters, negateFilters);
sampleIdentifiers = filterMutationData(sampleIdentifiers, molecularProfiles,
mutationTypeDataFilters, negateFilters, clinicalDataEqualityFilterApplier);
}

return chainSubFilters(studyViewFilter, sampleIdentifiers);
Expand Down Expand Up @@ -559,6 +559,56 @@ private List<SampleIdentifier> filterCNAGenes(List<GeneFilter> cnaGeneFilters,
return sampleIdentifiers;
}

private List<SampleIdentifier> filterMutationData(List<SampleIdentifier> sampleIdentifiers,
List<MolecularProfile> molecularProfiles, List<MutationDataFilter> mutationDataFilters,
Boolean negateFilters, ClinicalDataFilterApplier clinicalDataFilterApplier) {
if (!CollectionUtils.isEmpty(mutationDataFilters) && !CollectionUtils.isEmpty(sampleIdentifiers)) {
List<ClinicalData> clinicalDatas =
fetchMutationDataAndTransformToClinicalDataList(sampleIdentifiers, molecularProfiles, mutationDataFilters);


MultiKeyMap clinicalDataMap;
if (clinicalDataFilterApplier instanceof ClinicalDataEqualityFilterApplier) {
clinicalDataMap = ClinicalDataEqualityFilterApplier.buildClinicalDataMap(clinicalDatas);
} else {
clinicalDataMap = ClinicalDataIntervalFilterApplier.buildClinicalDataMap(clinicalDatas);
}

List<SampleIdentifier> newSampleIdentifiers = new ArrayList<>();

for (MutationDataFilter mutationDataFilter: mutationDataFilters) {
for (List<DataFilterValue> values: mutationDataFilter.getValues()) {
ClinicalDataFilter clinicalDataFilter = new ClinicalDataFilter();
clinicalDataFilter.setAttributeId(mutationDataFilter.getHugoGeneSymbol() + mutationDataFilter.getProfileType());
clinicalDataFilter.setValues(values);

List<ClinicalDataFilter> attributes = Collections.singletonList(clinicalDataFilter);

List<SampleIdentifier> filteredSampleIdentifiers = new ArrayList<>();

for (SampleIdentifier sampleIdentifier : sampleIdentifiers) {
int count = clinicalDataFilterApplier.apply(attributes, clinicalDataMap,
sampleIdentifier.getSampleId(), sampleIdentifier.getStudyId(), negateFilters);

if (count == attributes.size()) {
filteredSampleIdentifiers.add(sampleIdentifier);
}
}

if (newSampleIdentifiers.isEmpty()) {
newSampleIdentifiers = filteredSampleIdentifiers;
} else {
newSampleIdentifiers.retainAll(filteredSampleIdentifiers);
}
}
}

return newSampleIdentifiers.stream().distinct().collect(Collectors.toList());
}

return sampleIdentifiers;
}

private void splitGeneFiltersByMolecularAlterationType(List<GeneFilter> genefilters,
Map<String, MolecularProfile> molecularProfileMap, List<GeneFilter> mutatedGeneFilters,
List<GeneFilter> structuralVariantGeneFilters, List<GeneFilter> cnaGeneFilters) {
Expand Down Expand Up @@ -936,34 +986,7 @@ private <S extends DataFilter> List<ClinicalData> fetchDataAndTransformToClinica
List<String> sampleIds = new ArrayList<>();
studyViewFilterUtil.extractStudyAndSampleIds(sampleIdentifiers, studyIds, sampleIds);

if (dataFilters.get(0) instanceof MutationDataFilter) {
List<MutationDataFilter> mutationDataFilters = (List<MutationDataFilter>) dataFilters;

Set<String> hugoGeneSymbols = mutationDataFilters.stream()
.map(MutationDataFilter::getHugoGeneSymbol).collect(Collectors.toSet());
Map<String, Integer> geneNameIdMap = geneService
.fetchGenes(new ArrayList<>(hugoGeneSymbols), GeneIdType.HUGO_GENE_SYMBOL.name(),
Projection.SUMMARY.name())
.stream().collect(Collectors.toMap(Gene::getHugoGeneSymbol, Gene::getEntrezGeneId));

return mutationDataFilters.stream().flatMap(mutationDataFilter -> {
List<MolecularProfile> subMolecularProfiles = molecularProfileMap
.getOrDefault(mutationDataFilter.getProfileType(), new ArrayList<>());
Map<String, String> studyIdToMolecularProfileIdMap = subMolecularProfiles
.stream().collect(Collectors.toMap(MolecularProfile::getCancerStudyIdentifier,
MolecularProfile::getStableId));

if (mutationDataFilter.getCategorization() == MutationOption.EVENT) {
// fetch mutation type data
return invokeDataFunc(sampleIds, studyIds,
Collections.singletonList(geneNameIdMap.get(mutationDataFilter.getHugoGeneSymbol()).toString()),
studyIdToMolecularProfileIdMap, studyViewFilterUtil.getDataFilterUniqueKey(mutationDataFilter), fetchMutationData);
} else {
return fetchMutatedAndProfiledMutationData(sampleIdentifiers, geneNameIdMap,
mutationDataFilter, studyIdToMolecularProfileIdMap);
}
}).collect(Collectors.toList());
} else if (dataFilters.get(0) instanceof GenomicDataFilter) {
if (dataFilters.get(0) instanceof GenomicDataFilter) {
List<GenomicDataFilter> genomicDataIntervalFilters = (List<GenomicDataFilter>) dataFilters;
Set<String> hugoGeneSymbols = genomicDataIntervalFilters.stream()
.map(GenomicDataFilter::getHugoGeneSymbol).collect(Collectors.toSet());
Expand Down Expand Up @@ -1009,6 +1032,68 @@ private <S extends DataFilter> List<ClinicalData> fetchDataAndTransformToClinica
}
}

private List<ClinicalData> fetchMutationDataAndTransformToClinicalDataList(
List<SampleIdentifier> sampleIdentifiers, List<MolecularProfile> molecularProfiles, List<MutationDataFilter> mutationDataFilters
) {
Map<String, List<MolecularProfile>> molecularProfileMap = molecularProfileUtil
.categorizeMolecularProfilesByStableIdSuffixes(molecularProfiles);

List<String> studyIds = new ArrayList<>();
List<String> sampleIds = new ArrayList<>();
studyViewFilterUtil.extractStudyAndSampleIds(sampleIdentifiers, studyIds, sampleIds);

Set<String> hugoGeneSymbols = mutationDataFilters.stream()
.map(MutationDataFilter::getHugoGeneSymbol).collect(Collectors.toSet());
Map<String, Integer> geneNameIdMap = geneService
.fetchGenes(new ArrayList<>(hugoGeneSymbols), GeneIdType.HUGO_GENE_SYMBOL.name(),
Projection.SUMMARY.name())
.stream().collect(Collectors.toMap(Gene::getHugoGeneSymbol, Gene::getEntrezGeneId));

return mutationDataFilters.stream().flatMap(mutationDataFilter -> {
List<MolecularProfile> subMolecularProfiles = molecularProfileMap
.getOrDefault(mutationDataFilter.getProfileType(), new ArrayList<>());
Map<String, String> studyIdToMolecularProfileIdMap = subMolecularProfiles
.stream().collect(Collectors.toMap(MolecularProfile::getCancerStudyIdentifier,
MolecularProfile::getStableId));

Stream<ClinicalData> res = Stream.of();
List<DataFilterValue> customFilters = new ArrayList<>();

if (mutationDataFilter.getCategorization() == MutationOption.EVENT) {
customFilters = mutationDataFilter.getValues()
.stream()
.flatMap(value ->
value.stream().filter(x -> x.getValue().equalsIgnoreCase(MutationFilterOption.
MUTATED
.name()) ||
x.getValue().equalsIgnoreCase(MutationFilterOption.
NOT_PROFILED
.name()) ||
x.getValue().equalsIgnoreCase(MutationFilterOption.
NOT_MUTATED
.name()))
).collect(Collectors.toList());


// fetch mutation type data
res = invokeDataFunc(sampleIds, studyIds, Collections.singletonList(
geneNameIdMap.get(mutationDataFilter.getHugoGeneSymbol()).toString()),
studyIdToMolecularProfileIdMap,
studyViewFilterUtil.getMutationDataFilterUniqueKey(mutationDataFilter),
fetchMutationData);

}
if (mutationDataFilter.getCategorization() == MutationOption.MUTATED ||
CollectionUtils.isNotEmpty(customFilters)) {

Stream<ClinicalData> res1 = fetchMutatedAndProfiledMutationData(
sampleIdentifiers, geneNameIdMap, mutationDataFilter,
studyIdToMolecularProfileIdMap);
res = Stream.concat(res, res1);
}
return res;
}).collect(Collectors.toList());
}
private <S extends DataFilter> List<ClinicalDataFilter> transformToClinicalDataFilter(List<S> dataFilters) {
List<ClinicalDataFilter> attributes;
attributes = dataFilters.stream().map(dataFilter -> {
Expand Down Expand Up @@ -1116,7 +1201,7 @@ private Stream<ClinicalData> fetchMutatedAndProfiledMutationData(
// mutated
List<ClinicalData> mutatedClinicalDatas = invokeDataFunc(sampleIds, studyIds,
Collections.singletonList(geneNameIdMap.get(mutationDataFilter.getHugoGeneSymbol()).toString()),
studyIdToMolecularProfileIdMap, studyViewFilterUtil.getDataFilterUniqueKey(mutationDataFilter),
studyIdToMolecularProfileIdMap, studyViewFilterUtil.getMutationDataFilterUniqueKey(mutationDataFilter),
fetchMutatedData).collect(Collectors.toList());

List<SampleIdentifier> mutatedSampleIdentifiers = mutatedClinicalDatas
Expand All @@ -1137,7 +1222,7 @@ private Stream<ClinicalData> fetchMutatedAndProfiledMutationData(

List<ClinicalData> notProfiledClinicalDatas = transformSampleIdentifiersToClinicalData(
notProfiledSampleIdentifiers,
studyViewFilterUtil.getDataFilterUniqueKey(mutationDataFilter),
studyViewFilterUtil.getMutationDataFilterUniqueKey(mutationDataFilter),
MutationFilterOption.NOT_PROFILED.name()
);

Expand All @@ -1151,7 +1236,7 @@ private Stream<ClinicalData> fetchMutatedAndProfiledMutationData(

List<ClinicalData> notMutatedClinicalDatas = transformSampleIdentifiersToClinicalData(
notMutatedSampleIdentifiers,
studyViewFilterUtil.getDataFilterUniqueKey(mutationDataFilter),
studyViewFilterUtil.getMutationDataFilterUniqueKey(mutationDataFilter),
MutationFilterOption.NOT_MUTATED.name()
);

Expand Down
Loading

0 comments on commit c483c96

Please sign in to comment.