Skip to content

Commit

Permalink
Add Clinical Events Timeline counts endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
haynescd committed Jul 18, 2024
1 parent 0dfb346 commit 70454bb
Show file tree
Hide file tree
Showing 12 changed files with 254 additions and 90 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import org.cbioportal.model.CaseListDataCount;
import org.cbioportal.model.ClinicalData;
import org.cbioportal.model.ClinicalDataCount;
import org.cbioportal.model.ClinicalEventTypeCount;
import org.cbioportal.model.CopyNumberCountByGene;
import org.cbioportal.model.GenomicDataCount;
import org.cbioportal.model.Sample;
Expand Down Expand Up @@ -44,4 +45,6 @@ public interface StudyViewRepository {
Map<String, Set<String>> getMatchingGenePanelIds(StudyViewFilter studyViewFilter, String alterationType);

int getTotalProfiledCountsByAlterationType(StudyViewFilter studyViewFilter, String alterationType);

List<ClinicalEventTypeCount> getClinicalEventTypeCounts(StudyViewFilter studyViewFilter);
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import org.cbioportal.model.ClinicalAttribute;
import org.cbioportal.model.ClinicalData;
import org.cbioportal.model.ClinicalDataCount;
import org.cbioportal.model.ClinicalEventTypeCount;
import org.cbioportal.model.CopyNumberCountByGene;
import org.cbioportal.model.GenePanelToGene;
import org.cbioportal.model.GenomicDataCount;
Expand Down Expand Up @@ -51,4 +52,6 @@ List<ClinicalDataCount> getClinicalDataCounts(StudyViewFilter studyViewFilter, C
List<GenePanelToGene> getMatchingGenePanelIds(StudyViewFilter studyViewFilter, CategorizedClinicalDataCountFilter categorizedClinicalDataCountFilter, boolean applyPatientIdFilters, String alterationType);

int getTotalProfiledCountByAlterationType(StudyViewFilter studyViewFilter, CategorizedClinicalDataCountFilter categorizedClinicalDataCountFilter, boolean applyPatientIdFilters, String alterationType);

List<ClinicalEventTypeCount> getClinicalEventTypeCounts(StudyViewFilter studyViewFilter, CategorizedClinicalDataCountFilter categorizedClinicalDataCountFilter, boolean applyPatientIdFilters);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import org.cbioportal.model.CaseListDataCount;
import org.cbioportal.model.ClinicalData;
import org.cbioportal.model.ClinicalDataCount;
import org.cbioportal.model.ClinicalEventTypeCount;
import org.cbioportal.model.GenePanelToGene;
import org.cbioportal.model.GenomicDataCount;
import org.cbioportal.model.CopyNumberCountByGene;
Expand Down Expand Up @@ -39,44 +40,46 @@ public StudyViewMyBatisRepository(StudyViewMapper mapper) {
@Override
public List<Sample> getFilteredSamples(StudyViewFilter studyViewFilter) {
CategorizedClinicalDataCountFilter categorizedClinicalDataCountFilter = extractClinicalDataCountFilters(studyViewFilter);
return mapper.getFilteredSamples(studyViewFilter, categorizedClinicalDataCountFilter, shouldApplyPatientIdFilters(categorizedClinicalDataCountFilter));
return mapper.getFilteredSamples(studyViewFilter, categorizedClinicalDataCountFilter, shouldApplyPatientIdFilters(studyViewFilter,categorizedClinicalDataCountFilter));
}

@Override
public List<AlterationCountByGene> getMutatedGenes(StudyViewFilter studyViewFilter) {
CategorizedClinicalDataCountFilter categorizedClinicalDataCountFilter = extractClinicalDataCountFilters(studyViewFilter);
return mapper.getMutatedGenes(studyViewFilter, categorizedClinicalDataCountFilter,
shouldApplyPatientIdFilters(categorizedClinicalDataCountFilter),
shouldApplyPatientIdFilters(studyViewFilter,categorizedClinicalDataCountFilter),
AlterationFilterHelper.build(studyViewFilter.getAlterationFilter()));
}

@Override
public List<CopyNumberCountByGene> getCnaGenes(StudyViewFilter studyViewFilter) {
CategorizedClinicalDataCountFilter categorizedClinicalDataCountFilter = extractClinicalDataCountFilters(studyViewFilter);
return mapper.getCnaGenes(studyViewFilter, categorizedClinicalDataCountFilter,
shouldApplyPatientIdFilters(categorizedClinicalDataCountFilter),
shouldApplyPatientIdFilters(studyViewFilter,categorizedClinicalDataCountFilter),
AlterationFilterHelper.build(studyViewFilter.getAlterationFilter()));
}

@Override
public List<AlterationCountByGene> getStructuralVariantGenes(StudyViewFilter studyViewFilter) {
CategorizedClinicalDataCountFilter categorizedClinicalDataCountFilter = extractClinicalDataCountFilters(studyViewFilter);
return mapper.getStructuralVariantGenes(studyViewFilter, categorizedClinicalDataCountFilter,
shouldApplyPatientIdFilters(categorizedClinicalDataCountFilter),
shouldApplyPatientIdFilters(studyViewFilter,categorizedClinicalDataCountFilter),
AlterationFilterHelper.build(studyViewFilter.getAlterationFilter()));
}

@Override
public List<ClinicalDataCount> getClinicalDataCounts(StudyViewFilter studyViewFilter, List<String> filteredAttributes) {
CategorizedClinicalDataCountFilter categorizedClinicalDataCountFilter = extractClinicalDataCountFilters(studyViewFilter);
return mapper.getClinicalDataCounts(studyViewFilter, categorizedClinicalDataCountFilter, shouldApplyPatientIdFilters(categorizedClinicalDataCountFilter),
return mapper.getClinicalDataCounts(studyViewFilter, categorizedClinicalDataCountFilter,
shouldApplyPatientIdFilters(studyViewFilter,categorizedClinicalDataCountFilter),
filteredAttributes, FILTERED_CLINICAL_ATTR_VALUES );
}

@Override
public List<GenomicDataCount> getGenomicDataCounts(StudyViewFilter studyViewFilter) {
CategorizedClinicalDataCountFilter categorizedClinicalDataCountFilter = extractClinicalDataCountFilters(studyViewFilter);
return mapper.getGenomicDataCounts(studyViewFilter, categorizedClinicalDataCountFilter, shouldApplyPatientIdFilters(categorizedClinicalDataCountFilter));
return mapper.getGenomicDataCounts(studyViewFilter, categorizedClinicalDataCountFilter,
shouldApplyPatientIdFilters(studyViewFilter,categorizedClinicalDataCountFilter));
}

@Override
Expand Down Expand Up @@ -106,46 +109,47 @@ public Map<String, ClinicalDataType> getClinicalAttributeDatatypeMap() {
@Override
public List<CaseListDataCount> getCaseListDataCounts(StudyViewFilter studyViewFilter) {
CategorizedClinicalDataCountFilter categorizedClinicalDataCountFilter = extractClinicalDataCountFilters(studyViewFilter);
return mapper.getCaseListDataCounts(studyViewFilter, categorizedClinicalDataCountFilter, shouldApplyPatientIdFilters(categorizedClinicalDataCountFilter));
return mapper.getCaseListDataCounts(studyViewFilter, categorizedClinicalDataCountFilter, shouldApplyPatientIdFilters(studyViewFilter,categorizedClinicalDataCountFilter));
}


private boolean shouldApplyPatientIdFilters(CategorizedClinicalDataCountFilter categorizedClinicalDataCountFilter) {
return categorizedClinicalDataCountFilter.getPatientCategoricalClinicalDataFilters() != null && !categorizedClinicalDataCountFilter.getPatientCategoricalClinicalDataFilters().isEmpty()
private boolean shouldApplyPatientIdFilters(StudyViewFilter studyViewFilter, CategorizedClinicalDataCountFilter categorizedClinicalDataCountFilter) {
return studyViewFilter.getClinicalEventFilters() != null && !studyViewFilter.getClinicalEventFilters().isEmpty()
|| categorizedClinicalDataCountFilter.getPatientCategoricalClinicalDataFilters() != null && !categorizedClinicalDataCountFilter.getPatientCategoricalClinicalDataFilters().isEmpty()
|| categorizedClinicalDataCountFilter.getPatientNumericalClinicalDataFilters() != null && !categorizedClinicalDataCountFilter.getPatientNumericalClinicalDataFilters().isEmpty();
}

@Override
public List<ClinicalData> getSampleClinicalData(StudyViewFilter studyViewFilter, List<String> attributeIds) {
CategorizedClinicalDataCountFilter categorizedClinicalDataCountFilter = extractClinicalDataCountFilters(studyViewFilter);
return mapper.getSampleClinicalDataFromStudyViewFilter(studyViewFilter, categorizedClinicalDataCountFilter, shouldApplyPatientIdFilters(categorizedClinicalDataCountFilter), attributeIds);
return mapper.getSampleClinicalDataFromStudyViewFilter(studyViewFilter, categorizedClinicalDataCountFilter, shouldApplyPatientIdFilters(studyViewFilter,categorizedClinicalDataCountFilter), attributeIds);
}

@Override
public List<ClinicalData> getPatientClinicalData(StudyViewFilter studyViewFilter, List<String> attributeIds) {
CategorizedClinicalDataCountFilter categorizedClinicalDataCountFilter = extractClinicalDataCountFilters(studyViewFilter);
return mapper.getPatientClinicalDataFromStudyViewFilter(studyViewFilter, categorizedClinicalDataCountFilter, shouldApplyPatientIdFilters(categorizedClinicalDataCountFilter), attributeIds);
return mapper.getPatientClinicalDataFromStudyViewFilter(studyViewFilter, categorizedClinicalDataCountFilter, shouldApplyPatientIdFilters(studyViewFilter,categorizedClinicalDataCountFilter), attributeIds);
}

@Override
public Map<String, AlterationCountByGene> getTotalProfiledCounts(StudyViewFilter studyViewFilter, String alterationType) {
CategorizedClinicalDataCountFilter categorizedClinicalDataCountFilter = extractClinicalDataCountFilters(studyViewFilter);
return mapper.getTotalProfiledCounts(studyViewFilter, categorizedClinicalDataCountFilter,
shouldApplyPatientIdFilters(categorizedClinicalDataCountFilter), alterationType);
shouldApplyPatientIdFilters(studyViewFilter,categorizedClinicalDataCountFilter), alterationType);
}

@Override
public int getFilteredSamplesCount(StudyViewFilter studyViewFilter) {
CategorizedClinicalDataCountFilter categorizedClinicalDataCountFilter = extractClinicalDataCountFilters(studyViewFilter);
return mapper.getFilteredSamplesCount(studyViewFilter, categorizedClinicalDataCountFilter,
shouldApplyPatientIdFilters(categorizedClinicalDataCountFilter));
shouldApplyPatientIdFilters(studyViewFilter,categorizedClinicalDataCountFilter));
}

@Override
public Map<String, Set<String>> getMatchingGenePanelIds(StudyViewFilter studyViewFilter, String alterationType) {
CategorizedClinicalDataCountFilter categorizedClinicalDataCountFilter = extractClinicalDataCountFilters(studyViewFilter);
return mapper.getMatchingGenePanelIds(studyViewFilter, categorizedClinicalDataCountFilter,
shouldApplyPatientIdFilters(categorizedClinicalDataCountFilter), alterationType)
shouldApplyPatientIdFilters(studyViewFilter,categorizedClinicalDataCountFilter), alterationType)
.stream()
.collect(Collectors.groupingBy(GenePanelToGene::getHugoGeneSymbol,
Collectors.mapping(GenePanelToGene::getGenePanelId, Collectors.toSet())));
Expand All @@ -155,7 +159,14 @@ public Map<String, Set<String>> getMatchingGenePanelIds(StudyViewFilter studyVie
public int getTotalProfiledCountsByAlterationType(StudyViewFilter studyViewFilter, String alterationType) {
CategorizedClinicalDataCountFilter categorizedClinicalDataCountFilter = extractClinicalDataCountFilters(studyViewFilter);
return mapper.getTotalProfiledCountByAlterationType(studyViewFilter, categorizedClinicalDataCountFilter,
shouldApplyPatientIdFilters(categorizedClinicalDataCountFilter), alterationType);
shouldApplyPatientIdFilters(studyViewFilter,categorizedClinicalDataCountFilter), alterationType);
}

@Override
public List<ClinicalEventTypeCount> getClinicalEventTypeCounts(StudyViewFilter studyViewFilter) {
CategorizedClinicalDataCountFilter categorizedClinicalDataCountFilter = extractClinicalDataCountFilters(studyViewFilter);
return mapper.getClinicalEventTypeCounts(studyViewFilter, categorizedClinicalDataCountFilter,
shouldApplyPatientIdFilters(studyViewFilter,categorizedClinicalDataCountFilter));
}

private void buildClinicalAttributeNameMap() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import org.cbioportal.model.CaseListDataCount;
import org.cbioportal.model.ClinicalData;
import org.cbioportal.model.ClinicalDataCountItem;
import org.cbioportal.model.ClinicalEventTypeCount;
import org.cbioportal.model.GenomicDataCount;
import org.cbioportal.model.CopyNumberCountByGene;
import org.cbioportal.model.Sample;
Expand Down Expand Up @@ -32,5 +33,7 @@ public interface StudyViewColumnarService {
List<ClinicalData> getSampleClinicalData(StudyViewFilter studyViewFilter, List<String> attributeIds);

List<GenomicDataCount> getGenomicDataCounts(StudyViewFilter studyViewFilter);

List<ClinicalEventTypeCount> getClinicalEventTypeCounts(StudyViewFilter studyViewFilter);

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import org.cbioportal.model.ClinicalData;
import org.cbioportal.model.ClinicalDataCount;
import org.cbioportal.model.ClinicalDataCountItem;
import org.cbioportal.model.ClinicalEventTypeCount;
import org.cbioportal.model.CopyNumberCountByGene;
import org.cbioportal.model.GenomicDataCount;
import org.cbioportal.model.Sample;
Expand Down Expand Up @@ -50,7 +51,12 @@ public List<AlterationCountByGene> getMutatedGenes(StudyViewFilter studyViewFilt
public List<GenomicDataCount> getGenomicDataCounts(StudyViewFilter studyViewFilter) {
return studyViewRepository.getGenomicDataCounts(studyViewFilter);
}


@Override
public List<ClinicalEventTypeCount> getClinicalEventTypeCounts(StudyViewFilter studyViewFilter) {
return studyViewRepository.getClinicalEventTypeCounts(studyViewFilter);
}

public List<CopyNumberCountByGene> getCnaGenes(StudyViewFilter studyViewFilter) {
return alterationCountService.getCnaGenes(studyViewFilter);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@
import org.cbioportal.model.ClinicalData;
import org.cbioportal.model.ClinicalDataBin;
import org.cbioportal.model.ClinicalDataCountItem;
import org.cbioportal.model.ClinicalEventTypeCount;
import org.cbioportal.model.ClinicalViolinPlotData;
import org.cbioportal.model.DensityPlotData;
import org.cbioportal.model.CopyNumberCountByGene;
import org.cbioportal.model.DensityPlotData;
import org.cbioportal.model.GenomicDataCount;
import org.cbioportal.model.Sample;
import org.cbioportal.service.ClinicalDataDensityPlotService;
Expand All @@ -28,9 +29,11 @@
import org.cbioportal.web.parameter.ClinicalDataCountFilter;
import org.cbioportal.web.parameter.ClinicalDataFilter;
import org.cbioportal.web.parameter.DataBinMethod;
import org.cbioportal.web.parameter.SampleIdentifier;
import org.cbioportal.web.parameter.StudyViewFilter;
import org.cbioportal.web.util.DensityPlotParameters;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
Expand Down Expand Up @@ -325,4 +328,28 @@ public ResponseEntity<ClinicalViolinPlotData> fetchClinicalDataViolinPlots(

return new ResponseEntity<>(result, HttpStatus.OK);
}

@PreAuthorize("hasPermission(#involvedCancerStudies, 'Collection<CancerStudyId>', T(org.cbioportal.utils.security.AccessLevel).READ)")
@PostMapping(value = "/column-store/clinical-event-type-counts/fetch", consumes = MediaType.APPLICATION_JSON_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(description = "Get Counts of Clinical Event Types by Study View Filter")
@ApiResponse(responseCode = "200", description = "OK",
content = @Content(array = @ArraySchema(schema = @Schema(implementation = ClinicalEventTypeCount.class))))
public ResponseEntity<List<ClinicalEventTypeCount>> getClinicalEventTypeCounts(
@Parameter(required = true, description = "Study view filter")
@Valid
@RequestBody(required = false)
StudyViewFilter studyViewFilter,

@Parameter(hidden = true) // prevent reference to this attribute in the swagger-ui interface
@RequestAttribute(required = false, value = "involvedCancerStudies")
Collection<String> involvedCancerStudies,

@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
) {
return new ResponseEntity<>(studyViewColumnarService.getClinicalEventTypeCounts(interceptedStudyViewFilter), HttpStatus.OK);
}
}
29 changes: 29 additions & 0 deletions src/main/resources/db-scripts/clickhouse/clickhouse.sql
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ DROP TABLE IF EXISTS gene_panel_to_gene_derived;
DROP TABLE IF EXISTS sample_derived;
DROP TABLE IF EXISTS genomic_event_derived;
DROP TABLE IF EXISTS clinical_data_derived;
DROP TABLE IF EXISTS clinical_event_derived;


CREATE TABLE sample_to_gene_panel_derived
Expand Down Expand Up @@ -249,8 +250,36 @@ FROM patient AS p
ON (p.internal_id = clinpat.internal_id) AND (clinpat.attr_id = cam.attr_id)
WHERE cam.patient_attribute = 1;

CREATE TABLE clinical_event_derived
(
patient_unique_id String,
key String,
value String,
start_date Int32,
stop_date Int32 DEFAULT 0,
event_type LowCardinality(String),
cancer_study_identifier LowCardinality(String)
)
ENGINE = MergeTree
ORDER BY (event_type, patient_unique_id, cancer_study_identifier);

INSERT INTO clinical_event_derived
SELECT
concat(cs.cancer_study_identifier, '_', p.stable_id) AS patient_unique_id,
ced.key AS key,
ced.value AS value,
ce.start_date AS start_date,
ifNull(ce.stop_date, 0) AS stop_date,
ce.event_type AS event_type,
cs.cancer_study_identifier
FROM clinical_event ce
LEFT JOIN clinical_event_data ced ON ce.clinical_event_id = ced.clinical_event_id
INNER JOIN patient p ON ce.patient_id = p.internal_id
INNER JOIN cancer_study cs ON p.cancer_study_id = cs.cancer_study_id;

OPTIMIZE TABLE sample_to_gene_panel_derived;
OPTIMIZE TABLE gene_panel_to_gene_derived;
OPTIMIZE TABLE sample_derived;
OPTIMIZE TABLE genomic_event_derived;
OPTIMIZE TABLE clinical_data_derived;
OPTIMIZE TABLE clinical_event_derived;
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,20 @@
</trim>
</sql>

<sql id="applyClinicalEventTypeFilter">
<foreach item="clinicalEventFilter" collection="studyViewFilter.getClinicalEventFilters()" open="INTERSECT"
separator="INTERSECT">
SELECT patient_unique_id
FROM clinical_event_derived
<where>
<foreach item="dataFilterValue" collection="clinicalEventFilter.values" open="(" separator=") OR ("
close=")">
event_type = '${dataFilterValue.value}'
</foreach>
</where>
</foreach>
</sql>

<sql id="patientUniqueIdsFromStudyViewFilter">
<trim prefixOverrides="INTERSECT">
<if test="categorizedClinicalDataCountFilter.getPatientNumericalClinicalDataFilters() != null and !categorizedClinicalDataCountFilter.getPatientNumericalClinicalDataFilters().isEmpty()">
Expand All @@ -129,6 +143,10 @@
</include>
</foreach>
</if>
<!-- Clinical Event Filter -->
<if test="studyViewFilter.clinicalEventFilters != null and !studyViewFilter.clinicalEventFilters.isEmpty()">
<include refid="applyClinicalEventTypeFilter"/>
</if>
</trim>
</sql>

Expand Down
Loading

0 comments on commit 70454bb

Please sign in to comment.