-
Notifications
You must be signed in to change notification settings - Fork 537
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Columnar Study View Controller /api/column-store
- Loading branch information
Showing
8 changed files
with
288 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
22 changes: 22 additions & 0 deletions
22
src/main/java/org/cbioportal/service/StudyViewColumnarService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package org.cbioportal.service; | ||
|
||
import org.cbioportal.model.AlterationCountByGene; | ||
import org.cbioportal.model.ClinicalData; | ||
import org.cbioportal.model.ClinicalDataCountItem; | ||
import org.cbioportal.model.Sample; | ||
import org.cbioportal.web.parameter.StudyViewFilter; | ||
|
||
import java.util.List; | ||
|
||
public interface StudyViewColumnarService { | ||
|
||
List<Sample> getFilteredSamples(StudyViewFilter studyViewFilter); | ||
|
||
List<AlterationCountByGene> getMutatedGenes(StudyViewFilter interceptedStudyViewFilter); | ||
|
||
List<ClinicalDataCountItem> getClinicalDataCounts(StudyViewFilter studyViewFilter, List<String> filteredAttributes); | ||
|
||
List<ClinicalData> getPatientClinicalData(StudyViewFilter studyViewFilter, List<String> attributeIds); | ||
|
||
List<ClinicalData> getSampleClinicalData(StudyViewFilter studyViewFilter, List<String> attributeIds); | ||
} |
114 changes: 114 additions & 0 deletions
114
src/main/java/org/cbioportal/service/impl/StudyViewColumnarServiceImpl.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
package org.cbioportal.service.impl; | ||
|
||
import org.cbioportal.model.AlterationCountByGene; | ||
import org.cbioportal.model.ClinicalData; | ||
import org.cbioportal.model.ClinicalDataCount; | ||
import org.cbioportal.model.ClinicalDataCountItem; | ||
import org.cbioportal.model.Sample; | ||
import org.cbioportal.persistence.StudyViewRepository; | ||
import org.cbioportal.persistence.enums.ClinicalAttributeDataSource; | ||
import org.cbioportal.persistence.enums.ClinicalAttributeDataType; | ||
import org.cbioportal.service.StudyViewColumnarService; | ||
import org.cbioportal.web.parameter.CategorizedClinicalDataCountFilter; | ||
import org.cbioportal.web.parameter.StudyViewFilter; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.stereotype.Service; | ||
|
||
import java.util.HashMap; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.stream.Collectors; | ||
|
||
@Service | ||
public class StudyViewColumnarServiceImpl implements StudyViewColumnarService { | ||
|
||
private final Map<String, List<String>> clinicalAttributeNameMap = new HashMap<>(); | ||
|
||
|
||
private final StudyViewRepository studyViewRepository; | ||
|
||
@Autowired | ||
public StudyViewColumnarServiceImpl(StudyViewRepository studyViewRepository) { | ||
this.studyViewRepository = studyViewRepository; | ||
} | ||
|
||
@Override | ||
public List<Sample> getFilteredSamples(StudyViewFilter studyViewFilter) { | ||
CategorizedClinicalDataCountFilter categorizedClinicalDataCountFilter = extractClinicalDataCountFilters(studyViewFilter); | ||
return studyViewRepository.getFilteredSamples(studyViewFilter, categorizedClinicalDataCountFilter); | ||
} | ||
|
||
@Override | ||
public List<AlterationCountByGene> getMutatedGenes(StudyViewFilter studyViewFilter) { | ||
CategorizedClinicalDataCountFilter categorizedClinicalDataCountFilter = extractClinicalDataCountFilters(studyViewFilter); | ||
return studyViewRepository.getMutatedGenes(studyViewFilter, categorizedClinicalDataCountFilter); | ||
} | ||
|
||
@Override | ||
public List<ClinicalDataCountItem> getClinicalDataCounts(StudyViewFilter studyViewFilter, List<String> filteredAttributes) { | ||
CategorizedClinicalDataCountFilter categorizedClinicalDataCountFilter = extractClinicalDataCountFilters(studyViewFilter); | ||
|
||
return studyViewRepository.getClinicalDataCounts(studyViewFilter, categorizedClinicalDataCountFilter, filteredAttributes) | ||
.stream().collect(Collectors.groupingBy(ClinicalDataCount::getAttributeId)) | ||
.entrySet().parallelStream().map(e -> { | ||
ClinicalDataCountItem item = new ClinicalDataCountItem(); | ||
item.setAttributeId(e.getKey()); | ||
item.setCounts(e.getValue()); | ||
return item; | ||
}).collect(Collectors.toList()); | ||
} | ||
|
||
private CategorizedClinicalDataCountFilter extractClinicalDataCountFilters(final StudyViewFilter studyViewFilter) { | ||
if(clinicalAttributeNameMap.isEmpty()) { | ||
buildClinicalAttributeNameMap(); | ||
} | ||
|
||
if(studyViewFilter.getClinicalDataFilters() == null) { | ||
return CategorizedClinicalDataCountFilter.getBuilder().build(); | ||
} | ||
|
||
final String patientCategoricalKey = ClinicalAttributeDataSource.PATIENT.getValue() + ClinicalAttributeDataType.CATEGORICAL.getValue(); | ||
final String patientNumericKey = ClinicalAttributeDataSource.PATIENT.getValue() + ClinicalAttributeDataType.NUMERIC.getValue(); | ||
final String sampleCategoricalKey = ClinicalAttributeDataSource.SAMPLE.getValue() + ClinicalAttributeDataType.CATEGORICAL.getValue(); | ||
final String sampleNumericKey = ClinicalAttributeDataSource.SAMPLE.getValue() + ClinicalAttributeDataType.NUMERIC.getValue(); | ||
|
||
return CategorizedClinicalDataCountFilter.getBuilder() | ||
.setPatientCategoricalClinicalDataFilters(studyViewFilter.getClinicalDataFilters() | ||
.stream().filter(clinicalDataFilter -> clinicalAttributeNameMap.get(patientCategoricalKey).contains(clinicalDataFilter.getAttributeId())) | ||
.collect(Collectors.toList())) | ||
.setPatientNumericalClinicalDataFilters(studyViewFilter.getClinicalDataFilters().stream() | ||
.filter(clinicalDataFilter -> clinicalAttributeNameMap.get(patientNumericKey).contains(clinicalDataFilter.getAttributeId())) | ||
.collect(Collectors.toList())) | ||
.setSampleCategoricalClinicalDataFilters(studyViewFilter.getClinicalDataFilters().stream() | ||
.filter(clinicalDataFilter -> clinicalAttributeNameMap.get(sampleCategoricalKey).contains(clinicalDataFilter.getAttributeId())) | ||
.collect(Collectors.toList())) | ||
.setSampleNumericalClinicalDataFilters(studyViewFilter.getClinicalDataFilters().stream() | ||
.filter(clinicalDataFilter -> clinicalAttributeNameMap.get(sampleNumericKey).contains(clinicalDataFilter.getAttributeId())) | ||
.collect(Collectors.toList())) | ||
.build(); | ||
} | ||
|
||
private void buildClinicalAttributeNameMap() { | ||
List<ClinicalAttributeDataSource> clinicalAttributeDataSources = List.of(ClinicalAttributeDataSource.values()); | ||
for(ClinicalAttributeDataSource clinicalAttributeDataSource : clinicalAttributeDataSources) { | ||
String categoricalKey = clinicalAttributeDataSource.getValue() + ClinicalAttributeDataType.CATEGORICAL; | ||
String numericKey = clinicalAttributeDataSource.getValue() + ClinicalAttributeDataType.NUMERIC; | ||
clinicalAttributeNameMap.put(categoricalKey, studyViewRepository.getClinicalDataAttributeNames(clinicalAttributeDataSource, ClinicalAttributeDataType.CATEGORICAL)); | ||
clinicalAttributeNameMap.put(numericKey, studyViewRepository.getClinicalDataAttributeNames(clinicalAttributeDataSource, ClinicalAttributeDataType.NUMERIC)); | ||
} | ||
} | ||
|
||
@Override | ||
public List<ClinicalData> getPatientClinicalData(StudyViewFilter studyViewFilter, List<String> attributeIds) { | ||
CategorizedClinicalDataCountFilter categorizedClinicalDataCountFilter = extractClinicalDataCountFilters(studyViewFilter); | ||
return studyViewRepository.getPatientClinicalData(studyViewFilter, attributeIds, categorizedClinicalDataCountFilter); | ||
} | ||
|
||
@Override | ||
public List<ClinicalData> getSampleClinicalData(StudyViewFilter studyViewFilter, List<String> attributeIds) { | ||
CategorizedClinicalDataCountFilter categorizedClinicalDataCountFilter = extractClinicalDataCountFilters(studyViewFilter); | ||
return studyViewRepository.getSampleClinicalData(studyViewFilter, attributeIds, categorizedClinicalDataCountFilter); | ||
} | ||
|
||
|
||
} |
129 changes: 129 additions & 0 deletions
129
src/main/java/org/cbioportal/web/columnar/StudyViewColumnStoreController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
package org.cbioportal.web.columnar; | ||
|
||
import org.cbioportal.model.AlterationCountByGene; | ||
import org.cbioportal.model.AlterationFilter; | ||
import org.cbioportal.model.ClinicalDataBin; | ||
import org.cbioportal.model.ClinicalDataCountItem; | ||
import org.cbioportal.model.Sample; | ||
import org.cbioportal.service.StudyViewColumnarService; | ||
import org.cbioportal.service.StudyViewService; | ||
import org.cbioportal.service.exception.StudyNotFoundException; | ||
import org.cbioportal.web.columnar.util.NewStudyViewFilterUtil; | ||
import org.cbioportal.web.config.annotation.InternalApi; | ||
import org.cbioportal.web.parameter.ClinicalDataBinCountFilter; | ||
import org.cbioportal.web.parameter.ClinicalDataCountFilter; | ||
import org.cbioportal.web.parameter.ClinicalDataFilter; | ||
import org.cbioportal.web.parameter.DataBinMethod; | ||
import org.cbioportal.web.parameter.StudyViewFilter; | ||
import org.cbioportal.web.util.ClinicalDataBinUtil; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.http.HttpStatus; | ||
import org.springframework.http.MediaType; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.security.access.prepost.PreAuthorize; | ||
import org.springframework.validation.annotation.Validated; | ||
import org.springframework.web.bind.annotation.PostMapping; | ||
import org.springframework.web.bind.annotation.RequestAttribute; | ||
import org.springframework.web.bind.annotation.RequestBody; | ||
import org.springframework.web.bind.annotation.RequestMapping; | ||
import org.springframework.web.bind.annotation.RequestMethod; | ||
import org.springframework.web.bind.annotation.RequestParam; | ||
import org.springframework.web.bind.annotation.RestController; | ||
|
||
import java.util.ArrayList; | ||
import java.util.Collection; | ||
import java.util.List; | ||
import java.util.stream.Collectors; | ||
|
||
@InternalApi | ||
@RestController() | ||
@RequestMapping("/api") | ||
@Validated | ||
public class StudyViewColumnStoreController { | ||
|
||
private final StudyViewColumnarService studyViewColumnarService; | ||
private final StudyViewService studyViewService; | ||
private final ClinicalDataBinUtil clinicalDataBinUtil; | ||
|
||
@Autowired | ||
public StudyViewColumnStoreController(StudyViewColumnarService studyViewColumnarService, StudyViewService studyViewService, ClinicalDataBinUtil clinicalDataBinUtil) { | ||
this.studyViewColumnarService = studyViewColumnarService; | ||
this.studyViewService = studyViewService; | ||
this.clinicalDataBinUtil = clinicalDataBinUtil; | ||
} | ||
|
||
@PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection<CancerStudyId>', T(org.cbioportal.utils.security.AccessLevel).READ)") | ||
@PostMapping(value = "/column-store/filtered-samples/fetch", | ||
consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) | ||
public ResponseEntity<List<Sample>> fetchFilteredSamples( | ||
@RequestParam(defaultValue = "false") Boolean negateFilters, | ||
@RequestAttribute(required = false, value = "involvedCancerStudies") Collection<String> involvedCancerStudies, | ||
@RequestAttribute(required = false, value = "interceptedStudyViewFilter") StudyViewFilter interceptedStudyViewFilter, | ||
@RequestBody(required = false) StudyViewFilter studyViewFilter) { | ||
return new ResponseEntity<>( | ||
studyViewColumnarService.getFilteredSamples(interceptedStudyViewFilter), | ||
HttpStatus.OK | ||
); | ||
} | ||
|
||
@PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection<CancerStudyId>', T(org.cbioportal.utils.security.AccessLevel).READ)") | ||
@PostMapping(value = "/column-store/mutated-genes/fetch", | ||
consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) | ||
public ResponseEntity<List<AlterationCountByGene>> fetchMutatedGenes( | ||
@RequestBody(required = false) StudyViewFilter studyViewFilter, | ||
@RequestAttribute(required = false, value = "involvedCancerStudies") Collection<String> involvedCancerStudies, | ||
@RequestAttribute(required = false, value = "interceptedStudyViewFilter") StudyViewFilter interceptedStudyViewFilter | ||
) throws StudyNotFoundException { | ||
AlterationFilter annotationFilters = interceptedStudyViewFilter.getAlterationFilter(); | ||
List<Sample> samples = studyViewColumnarService.getFilteredSamples(interceptedStudyViewFilter); | ||
List<String> studyIds = new ArrayList<>(); | ||
List<String> sampleIds = new ArrayList<>(); | ||
for(Sample sample : samples) { | ||
studyIds.add(sample.getCancerStudyIdentifier()); | ||
sampleIds.add(sample.getStableId()); | ||
} | ||
return new ResponseEntity<>( | ||
studyViewService.getMutationAlterationCountByGenes(studyIds, sampleIds, annotationFilters), | ||
HttpStatus.OK | ||
); | ||
} | ||
|
||
@PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection<CancerStudyId>', T(org.cbioportal.utils.security.AccessLevel).READ)") | ||
@PostMapping(value = "/column-store/clinical-data-counts/fetch", | ||
consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) | ||
public ResponseEntity<List<ClinicalDataCountItem>> fetchClinicalDataCounts( | ||
@RequestBody(required = false) ClinicalDataCountFilter clinicalDataCountFilter, | ||
@RequestAttribute(required = false, value = "involvedCancerStudies") Collection<String> involvedCancerStudies, | ||
@RequestAttribute(required = false, value = "interceptedClinicalDataCountFilter") ClinicalDataCountFilter interceptedClinicalDataCountFilter) { | ||
|
||
List<ClinicalDataFilter> attributes = interceptedClinicalDataCountFilter.getAttributes(); | ||
StudyViewFilter studyViewFilter = interceptedClinicalDataCountFilter.getStudyViewFilter(); | ||
|
||
if (attributes.size() == 1) { | ||
NewStudyViewFilterUtil.removeSelfFromFilter(attributes.get(0).getAttributeId(), studyViewFilter); | ||
} | ||
// boolean singleStudyUnfiltered = studyViewFilterUtil.isSingleStudyUnfiltered(studyViewFilter); | ||
List<ClinicalDataCountItem> result = studyViewColumnarService.getClinicalDataCounts(studyViewFilter, | ||
attributes.stream().map(ClinicalDataFilter::getAttributeId).collect(Collectors.toList())); | ||
//studyIds, sampleIds, attributes.stream().map(a -> a.getAttributeId()).collect(Collectors.toList())); | ||
return new ResponseEntity<>(result, HttpStatus.OK); | ||
|
||
} | ||
|
||
@PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection<CancerStudyId>', T(org.cbioportal.utils.security.AccessLevel).READ)") | ||
@RequestMapping(value = "/column-store/clinical-data-bin-counts/fetch", method = RequestMethod.POST, | ||
consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) | ||
public ResponseEntity<List<ClinicalDataBin>> fetchClinicalDataBinCounts( | ||
@RequestParam(defaultValue = "DYNAMIC") DataBinMethod dataBinMethod, | ||
@RequestBody(required = false) ClinicalDataBinCountFilter clinicalDataBinCountFilter, | ||
@RequestAttribute(required = false, value = "involvedCancerStudies") Collection<String> involvedCancerStudies, | ||
@RequestAttribute(required = false, value = "interceptedClinicalDataBinCountFilter") ClinicalDataBinCountFilter interceptedClinicalDataBinCountFilter | ||
) { | ||
List<ClinicalDataBin> clinicalDataBins = clinicalDataBinUtil.fetchClinicalDataBinCounts( | ||
dataBinMethod, | ||
interceptedClinicalDataBinCountFilter, | ||
true | ||
); | ||
return new ResponseEntity<>(clinicalDataBins, HttpStatus.OK); | ||
} | ||
} |
13 changes: 13 additions & 0 deletions
13
src/main/java/org/cbioportal/web/columnar/util/NewStudyViewFilterUtil.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package org.cbioportal.web.columnar.util; | ||
|
||
|
||
import org.cbioportal.web.parameter.StudyViewFilter; | ||
|
||
public class NewStudyViewFilterUtil { | ||
|
||
public static void removeSelfFromFilter(String attributeId, StudyViewFilter studyViewFilter) { | ||
if (studyViewFilter!= null && studyViewFilter.getClinicalDataFilters() != null) { | ||
studyViewFilter.getClinicalDataFilters().removeIf(f -> f.getAttributeId().equals(attributeId)); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
src/main/resources/org/cbioportal/persistence/mybatiscolumnar/StudyViewMapper.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters