Skip to content

Commit

Permalink
fetch missing patient clinical data for the density plot
Browse files Browse the repository at this point in the history
  • Loading branch information
onursumer committed Oct 28, 2024
1 parent 219d894 commit d89cabd
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -68,15 +68,12 @@

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static org.cbioportal.web.columnar.util.ClinicalDataViolinPlotUtil.convertPatientClinicalDataToSampleClinicalData;
import static org.cbioportal.web.columnar.util.ClinicalDataViolinPlotUtil.filterNonEmptyClinicalData;
import static org.cbioportal.web.columnar.util.ClinicalDataXyPlotUtil.fetchClinicalDataForXyPlot;

@InternalApi
@RestController()
Expand Down Expand Up @@ -291,9 +288,8 @@ public ResponseEntity<DensityPlotData> fetchClinicalDataDensityPlot(
@Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface. this attribute is needed for the @PreAuthorize tag above.
@Valid @RequestAttribute(required = false, value = "interceptedStudyViewFilter") StudyViewFilter interceptedStudyViewFilter,
@Parameter(required = true, description = "Study view filter")
@RequestBody(required = false) StudyViewFilter studyViewFilter) {

List<String> xyAttributeId = new ArrayList<>(Arrays.asList(xAxisAttributeId, yAxisAttributeId));
@RequestBody(required = false) StudyViewFilter studyViewFilter
) {
DensityPlotParameters densityPlotParameters =
new DensityPlotParameters.Builder()
.xAxisAttributeId(xAxisAttributeId)
Expand All @@ -308,8 +304,18 @@ public ResponseEntity<DensityPlotData> fetchClinicalDataDensityPlot(
.yAxisLogScale(yAxisLogScale)
.build();

List<ClinicalData> sampleClinicalDataList = studyViewColumnarService.getSampleClinicalData(interceptedStudyViewFilter, xyAttributeId);
DensityPlotData result = clinicalDataDensityPlotService.getDensityPlotData(sampleClinicalDataList, densityPlotParameters, interceptedStudyViewFilter);
List<ClinicalData> combinedClinicalDataList = fetchClinicalDataForXyPlot(
studyViewColumnarService,
interceptedStudyViewFilter,
List.of(xAxisAttributeId, yAxisAttributeId),
false
);

DensityPlotData result = clinicalDataDensityPlotService.getDensityPlotData(
combinedClinicalDataList,
densityPlotParameters,
interceptedStudyViewFilter
);

return new ResponseEntity<>(result, HttpStatus.OK);
}
Expand Down Expand Up @@ -341,46 +347,30 @@ public ResponseEntity<ClinicalViolinPlotData> fetchClinicalDataViolinPlots(
@Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface. this attribute is needed for the @PreAuthorize tag above.
@Valid @RequestAttribute(required = false, value = "interceptedStudyViewFilter") StudyViewFilter interceptedStudyViewFilter,
@Parameter(required = true, description = "Study view filter")
@Valid @RequestBody(required = false) StudyViewFilter studyViewFilter) {
@Valid @RequestBody(required = false) StudyViewFilter studyViewFilter
) {
// fetch the samples by using the provided study view filter
List<Sample> filteredSamples = studyViewColumnarService.getFilteredSamples(interceptedStudyViewFilter);

// remove the numerical clinical data filter from the study view filter.
// this new modified filter is used to fetch sample and patient clinical data.
// this is required to get the complete violin plot data.
// filteredSamples reflects only the original unmodified study view filter.
// we will need to fetch samples again to get the samples corresponding to this modified filter,
// otherwise patient to sample mapping may be incomplete.
if (interceptedStudyViewFilter.getClinicalDataFilters() != null) {
interceptedStudyViewFilter.getClinicalDataFilters().stream()
.filter(f->f.getAttributeId().equals(numericalAttributeId))
.findAny()
.ifPresent(f->interceptedStudyViewFilter.getClinicalDataFilters().remove(f));
}

List<String> attributeIds = List.of(numericalAttributeId, categoricalAttributeId);

// Filter out clinical data with empty attribute values due to Clickhouse migration
List<ClinicalData> sampleClinicalDataList = filterNonEmptyClinicalData(
studyViewColumnarService.getSampleClinicalData(interceptedStudyViewFilter, attributeIds)
List<ClinicalData> combinedClinicalDataList = fetchClinicalDataForXyPlot(
studyViewColumnarService,
interceptedStudyViewFilter,
List.of(numericalAttributeId, categoricalAttributeId),
true // filter out clinical data with empty attribute values due to Clickhouse migration
);
List<ClinicalData> patientClinicalDataList = filterNonEmptyClinicalData(
studyViewColumnarService.getPatientClinicalData(interceptedStudyViewFilter, attributeIds)
);

List<ClinicalData> combinedClinicalDataList;
if (patientClinicalDataList.isEmpty()) {
combinedClinicalDataList = sampleClinicalDataList;
} else {
// we previously fetched sample and patient clinical data with the modified study view filter,
// however filteredSamples reflects only the original unmodified study view filter.
// we need to fetch samples again to get the samples corresponding to this modified filter,
// otherwise patient to sample mapping may be incomplete.
List<Sample> samplesWithoutNumericalFilter = studyViewColumnarService.getFilteredSamples(interceptedStudyViewFilter);

combinedClinicalDataList = Stream.concat(
sampleClinicalDataList.stream(),
convertPatientClinicalDataToSampleClinicalData(patientClinicalDataList, samplesWithoutNumericalFilter).stream()
).toList();
}

// Only mutation count can use log scale
boolean useLogScale = logScale && numericalAttributeId.equals("MUTATION_COUNT");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,47 @@

import org.cbioportal.model.ClinicalData;
import org.cbioportal.model.Sample;
import org.cbioportal.service.StudyViewColumnarService;
import org.cbioportal.web.parameter.StudyViewFilter;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class ClinicalDataViolinPlotUtil {
public class ClinicalDataXyPlotUtil {
public static List<ClinicalData> fetchClinicalDataForXyPlot(
StudyViewColumnarService studyViewColumnarService,
StudyViewFilter studyViewFilter,
List<String> attributeIds,
boolean shouldFilterNonEmptyClinicalData
) {
List<ClinicalData> combinedClinicalDataList;
List<ClinicalData> sampleClinicalDataList = studyViewColumnarService.getSampleClinicalData(studyViewFilter, attributeIds);
List<ClinicalData> patientClinicalDataList = studyViewColumnarService.getPatientClinicalData(studyViewFilter, attributeIds);

if (shouldFilterNonEmptyClinicalData) {
sampleClinicalDataList = filterNonEmptyClinicalData(sampleClinicalDataList);
patientClinicalDataList = filterNonEmptyClinicalData(patientClinicalDataList);
}

if (patientClinicalDataList.isEmpty()) {
combinedClinicalDataList = sampleClinicalDataList;
} else {
// fetch samples for the given study view filter.
// we need this to construct the complete patient to sample map.
List<Sample> samples = studyViewColumnarService.getFilteredSamples(studyViewFilter);

combinedClinicalDataList = Stream.concat(
sampleClinicalDataList.stream(),
convertPatientClinicalDataToSampleClinicalData(patientClinicalDataList, samples).stream()
).toList();
}

return combinedClinicalDataList;
}

public static List<ClinicalData> filterNonEmptyClinicalData(List<ClinicalData> clinicalData) {
return clinicalData
.stream()
Expand Down

0 comments on commit d89cabd

Please sign in to comment.