diff --git a/.circleci/config.yml b/.circleci/config.yml
index d2c7f2c1465..bceed08e1ca 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -223,6 +223,134 @@ jobs:
DOCKER_IMAGE_SESSION_SERVICE: cbioportal/session-service:0.5.0
FRONTEND_TEST_DO_NOT_LOAD_EXTERNAL_FRONTEND: true
+ pull_cbioportal_test_codebase:
+ machine:
+ image: ubuntu-2204:2024.08.1
+ resource_class: medium
+ working_directory: /tmp/repos
+ steps:
+ - run:
+ name: Checkout cbioportal/cbioportal-test
+ environment:
+ TEST_REPO_URL: https://github.com/cBioPortal/cbioportal-test
+ command: |
+ git clone ${TEST_REPO_URL}
+ - persist_to_workspace:
+ root: /tmp/repos
+ paths:
+ - cbioportal-test
+
+ pull_cbioportal_frontend_codebase:
+ machine:
+ image: ubuntu-2204:2024.08.1
+ resource_class: medium
+ working_directory: /tmp/repos
+ steps:
+ - run:
+ name: Checkout cbioportal/cbioportal-frontend
+ environment:
+ FRONTEND_REPO_URL: https://github.com/cBioPortal/cbioportal-frontend.git
+ FRONTEND_REPO_BRANCH: clickhouse
+ command: |
+ git clone -b ${FRONTEND_REPO_BRANCH} --single-branch ${FRONTEND_REPO_URL}
+ - persist_to_workspace:
+ root: /tmp/repos
+ paths:
+ - cbioportal-frontend
+
+ build_push_image:
+ machine:
+ image: ubuntu-2204:2024.08.1
+ resource_class: medium
+ working_directory: /tmp/repos
+ steps:
+ - attach_workspace:
+ at: /tmp/repos
+ - checkout:
+ path: /tmp/repos/cbioportal
+ - run:
+ name: Build cBioPortal docker image
+ environment:
+ DOCKER_REPO: cbioportal/cbioportal-dev
+ command: |
+ export DOCKER_TAG=$CIRCLE_SHA1
+ URL="https://hub.docker.com/v2/repositories/cbioportal/cbioportal-dev/tags/$DOCKER_TAG-web-shenandoah"
+ TAG_FOUND=$(curl -s $URL | jq -r .name)
+ if [ $TAG_FOUND = "$DOCKER_TAG-web-shenandoah" ]; then
+ echo "Image already exists. Skipping build step!"
+ exit 0
+ fi
+ cd cbioportal-test
+ ./scripts/build-push-image.sh --src=/tmp/repos/cbioportal --push=true --skip_web_and_data=true
+ EXISTS=$(docker manifest inspect $DOCKER_REPO:$DOCKER_TAG-web-shenandoah > /dev/null; echo $?)
+ if [ $EXISTS -eq 0 ]; then
+ echo "Build succeeded!"
+ else
+ echo "Build failed!"
+ exit 1
+ fi
+
+ run_api_tests:
+ machine:
+ image: ubuntu-2204:2024.08.1
+ docker_layer_caching: true
+ resource_class: large
+ working_directory: /tmp/repos
+ steps:
+ - attach_workspace:
+ at: /tmp/repos
+ - checkout:
+ path: /tmp/repos/cbioportal
+ - run:
+ name: Instantiate a cbioportal instance
+ environment:
+ DOCKER_REPO: cbioportal/cbioportal-dev
+ APP_CLICKHOUSE_MODE: "true"
+ command: |
+ cd cbioportal-test
+ export DOCKER_IMAGE_CBIOPORTAL=$DOCKER_REPO:$CIRCLE_SHA1-web-shenandoah
+ nohup ./scripts/docker-compose.sh >> /tmp/repos/docker-compose-logs.txt 2>&1 &
+ - run:
+ name: Wait for cbioportal to be live at localhost
+ command: |
+ cd cbioportal-test
+ ./utils/check-connection.sh --url=localhost:8080
+ - run:
+ name: Confirm cbioportal config matches PR
+ command: |
+ cd cbioportal
+ echo "Matching gitCommitId..."
+ INSTANCE_COMMIT_ID=$(curl -s http://localhost:8080/api/info | jq -r '.["gitCommitId"]')
+ PR_COMMIT_ID=$CIRCLE_SHA1
+ if [ "$INSTANCE_COMMIT_ID" = "$PR_COMMIT_ID" ]; then
+ echo "gitCommitId successfully matched!"
+ echo "cBioPortal is ready:"
+ curl -s http://localhost:8080/api/info | jq
+ exit 0
+ else
+ echo "gitCommitIds do not match!"
+ echo "Instance Commit ID: $INSTANCE_COMMIT_ID"
+ echo "PR Commit ID: $PR_COMMIT_ID"
+ exit 1
+ fi
+ - run:
+ name: Run API Tests
+ environment:
+ API_TEST_HOST: http://localhost:8080
+ BACKEND_ROOT: /tmp/repos/cbioportal
+ command: |
+ cd cbioportal-frontend
+ nvm install 15.2.1
+ nvm use 15.2.1
+ npm install -g yarn@1.22.5
+ yarn --ignore-engines
+ yarn run apitests
+
+ - store_artifacts:
+ path: /tmp/repos/cbioportal-test/web-metadata.json
+ - store_artifacts:
+ path: /tmp/repos/docker-compose-logs.txt
+
workflows:
version: 2
@@ -238,3 +366,26 @@ workflows:
- build_backend
- pull_frontend_codebase
- install_yarn
+ api_tests:
+ jobs:
+ - pull_cbioportal_test_codebase
+ - pull_cbioportal_frontend_codebase
+ - wait_for_approval:
+ type: approval
+ requires:
+ - pull_cbioportal_test_codebase
+ - pull_cbioportal_frontend_codebase
+ - build_push_image:
+ context:
+ - api-tests
+ requires:
+ - wait_for_approval
+ - pull_cbioportal_test_codebase
+ - run_api_tests:
+ context:
+ - api-tests
+ requires:
+ - wait_for_approval
+ - pull_cbioportal_test_codebase
+ - pull_cbioportal_frontend_codebase
+ - build_push_image
diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml
index a87c052d155..080f26af165 100644
--- a/.github/workflows/sonarcloud.yml
+++ b/.github/workflows/sonarcloud.yml
@@ -34,7 +34,7 @@ jobs:
cp src/main/resources/application.properties.EXAMPLE src/main/resources/application.properties
- name: Build and analyze
env:
- SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
+ SONAR_TOKEN: de1b5cc660cd210dde840f492c371da6cc801763
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: mvn clean install verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar
- name: 'Add host.testcontainers.internal to /etc/hosts'
@@ -45,6 +45,6 @@ jobs:
mvn verify -Pintegration-test
- name: Code Coverage
env:
- SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
+ SONAR_TOKEN: de1b5cc660cd210dde840f492c371da6cc801763
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: mvn sonar:sonar -Pcoverage
diff --git a/pom.xml b/pom.xml
index 2dd05f792ae..ca7f21587da 100644
--- a/pom.xml
+++ b/pom.xml
@@ -99,6 +99,7 @@
4.17.0
7.1.0
5.2.1
+ 1.19.7
@@ -354,6 +355,31 @@
test
+
+ com.clickhouse
+ clickhouse-jdbc
+ 0.6.2
+
+ all
+
+
+ org.testcontainers
+ clickhouse
+ ${clickhouse_testcontainer.version}
+ test
+
+
+ org.mybatis.spring.boot
+ mybatis-spring-boot-test-autoconfigure
+ 3.0.3
+ test
+
+
+ org.springframework.boot
+ spring-boot-testcontainers
+ test
+
@@ -418,9 +444,25 @@
cgds.sql
migration.sql
+ clickhouse/clickhouse.sql
+ clickhouse/materialized_views.sql
+
+
+ src/main/resources/db-scripts
+ false
+
+ clickhouse/clickhouse.sql
+ clickhouse/materialized_views.sql
+
+
+
+ src/test/resources
+ false
+
+
diff --git a/src/main/java/org/cbioportal/PortalApplication.java b/src/main/java/org/cbioportal/PortalApplication.java
index c64043a1dbc..bfe458a121b 100644
--- a/src/main/java/org/cbioportal/PortalApplication.java
+++ b/src/main/java/org/cbioportal/PortalApplication.java
@@ -6,6 +6,7 @@
import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.annotation.PropertySources;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
@SpringBootApplication(exclude = {
MongoAutoConfiguration.class,
@@ -18,6 +19,7 @@
@PropertySource(ignoreResourceNotFound = true, value = "classpath:git.properties"),
@PropertySource(ignoreResourceNotFound = true, value = "classpath:springdoc.properties")
})
+@EnableTransactionManagement
public class PortalApplication {
public static void main(String[] args) {
SpringApplication.run(PortalApplication.class, args);
diff --git a/src/main/java/org/cbioportal/WebAppConfig.java b/src/main/java/org/cbioportal/WebAppConfig.java
index 0105465e96b..2f951690c33 100644
--- a/src/main/java/org/cbioportal/WebAppConfig.java
+++ b/src/main/java/org/cbioportal/WebAppConfig.java
@@ -2,6 +2,7 @@
import java.util.List;
+import org.cbioportal.web.ExecuterTimeInterceptor;
import org.cbioportal.web.util.InvolvedCancerStudyExtractorInterceptor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
@@ -12,6 +13,7 @@
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+import org.springframework.web.servlet.handler.WebRequestHandlerInterceptorAdapter;
// TODO Consider creating separate DispatcherServlets as in the original web.xml
// See: https://stackoverflow.com/a/30686733/11651683
@@ -75,6 +77,9 @@ public HandlerInterceptor involvedCancerStudyExtractorInterceptor() {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(involvedCancerStudyExtractorInterceptor());
+ registry.addInterceptor(new WebRequestHandlerInterceptorAdapter(
+ new ExecuterTimeInterceptor()
+ )).addPathPatterns("/**");
}
@Override
diff --git a/src/main/java/org/cbioportal/model/AlterationType.java b/src/main/java/org/cbioportal/model/AlterationType.java
index c7b77bea59d..b20a642669d 100644
--- a/src/main/java/org/cbioportal/model/AlterationType.java
+++ b/src/main/java/org/cbioportal/model/AlterationType.java
@@ -1,6 +1,8 @@
package org.cbioportal.model;
public enum AlterationType {
- MUTATION,
- COPY_NUMBER_ALTERATION
+ MUTATION_EXTENDED,
+ COPY_NUMBER_ALTERATION,
+ STRUCTURAL_VARIANT,
+ GENERIC_ASSAY;
}
diff --git a/src/main/java/org/cbioportal/model/CaseListDataCount.java b/src/main/java/org/cbioportal/model/CaseListDataCount.java
index 645c12282db..218a83ffd3c 100644
--- a/src/main/java/org/cbioportal/model/CaseListDataCount.java
+++ b/src/main/java/org/cbioportal/model/CaseListDataCount.java
@@ -1,6 +1,8 @@
package org.cbioportal.model;
-public class CaseListDataCount {
+import java.io.Serializable;
+
+public class CaseListDataCount implements Serializable {
private String label;
private String value;
diff --git a/src/main/java/org/cbioportal/model/ClinicalViolinPlotBoxData.java b/src/main/java/org/cbioportal/model/ClinicalViolinPlotBoxData.java
index d8d56d8d3bd..c2e24d4d4e2 100644
--- a/src/main/java/org/cbioportal/model/ClinicalViolinPlotBoxData.java
+++ b/src/main/java/org/cbioportal/model/ClinicalViolinPlotBoxData.java
@@ -1,6 +1,8 @@
package org.cbioportal.model;
-public class ClinicalViolinPlotBoxData {
+import java.io.Serializable;
+
+public class ClinicalViolinPlotBoxData implements Serializable {
private double whiskerLower;
private double whiskerUpper;
private double median;
diff --git a/src/main/java/org/cbioportal/model/ClinicalViolinPlotData.java b/src/main/java/org/cbioportal/model/ClinicalViolinPlotData.java
index 89f9fc469c1..452cabf0bcd 100644
--- a/src/main/java/org/cbioportal/model/ClinicalViolinPlotData.java
+++ b/src/main/java/org/cbioportal/model/ClinicalViolinPlotData.java
@@ -1,8 +1,9 @@
package org.cbioportal.model;
+import java.io.Serializable;
import java.util.List;
-public class ClinicalViolinPlotData {
+public class ClinicalViolinPlotData implements Serializable {
private List rows;
private Double axisStart;
private Double axisEnd;
diff --git a/src/main/java/org/cbioportal/model/ClinicalViolinPlotIndividualPoint.java b/src/main/java/org/cbioportal/model/ClinicalViolinPlotIndividualPoint.java
index ede3c6b5267..7cff49930b0 100644
--- a/src/main/java/org/cbioportal/model/ClinicalViolinPlotIndividualPoint.java
+++ b/src/main/java/org/cbioportal/model/ClinicalViolinPlotIndividualPoint.java
@@ -1,6 +1,8 @@
package org.cbioportal.model;
-public class ClinicalViolinPlotIndividualPoint {
+import java.io.Serializable;
+
+public class ClinicalViolinPlotIndividualPoint implements Serializable {
private String sampleId;
private String studyId;
private double value;
diff --git a/src/main/java/org/cbioportal/model/ClinicalViolinPlotRowData.java b/src/main/java/org/cbioportal/model/ClinicalViolinPlotRowData.java
index d89c601b0c8..3a2ef647e35 100644
--- a/src/main/java/org/cbioportal/model/ClinicalViolinPlotRowData.java
+++ b/src/main/java/org/cbioportal/model/ClinicalViolinPlotRowData.java
@@ -1,8 +1,9 @@
package org.cbioportal.model;
+import java.io.Serializable;
import java.util.List;
-public class ClinicalViolinPlotRowData {
+public class ClinicalViolinPlotRowData implements Serializable {
private String category;
private Integer numSamples;
private List curveData;
diff --git a/src/main/java/org/cbioportal/model/GenericAssayDataCount.java b/src/main/java/org/cbioportal/model/GenericAssayDataCount.java
index 78cd96be221..62c14562fca 100644
--- a/src/main/java/org/cbioportal/model/GenericAssayDataCount.java
+++ b/src/main/java/org/cbioportal/model/GenericAssayDataCount.java
@@ -7,6 +7,13 @@ public class GenericAssayDataCount implements Serializable {
private String value;
private Integer count;
+ public GenericAssayDataCount() {}
+
+ public GenericAssayDataCount(String value, Integer count) {
+ this.value = value;
+ this.count = count;
+ }
+
public String getValue() {
return value;
}
diff --git a/src/main/java/org/cbioportal/model/GenericAssayDataCountItem.java b/src/main/java/org/cbioportal/model/GenericAssayDataCountItem.java
index 70824a10531..c272b617f87 100644
--- a/src/main/java/org/cbioportal/model/GenericAssayDataCountItem.java
+++ b/src/main/java/org/cbioportal/model/GenericAssayDataCountItem.java
@@ -7,6 +7,13 @@ public class GenericAssayDataCountItem implements Serializable {
private String stableId;
private List counts;
+ public GenericAssayDataCountItem() {}
+
+ public GenericAssayDataCountItem(String stableId, List counts) {
+ this.stableId = stableId;
+ this.counts = counts;
+ }
+
public String getStableId() {
return stableId;
}
diff --git a/src/main/java/org/cbioportal/model/GenomicDataCount.java b/src/main/java/org/cbioportal/model/GenomicDataCount.java
index fcc8587c69c..f86fda5bc8f 100644
--- a/src/main/java/org/cbioportal/model/GenomicDataCount.java
+++ b/src/main/java/org/cbioportal/model/GenomicDataCount.java
@@ -10,6 +10,21 @@ public class GenomicDataCount implements Serializable {
private Integer count;
private Integer uniqueCount;
+ public GenomicDataCount() {}
+
+ public GenomicDataCount(String label, String value, Integer count) {
+ this.label = label;
+ this.value = value;
+ this.count = count;
+ }
+
+ public GenomicDataCount(String label, String value, Integer count, Integer uniqueCount) {
+ this.label = label;
+ this.value = value;
+ this.count = count;
+ this.uniqueCount = uniqueCount;
+ }
+
public String getLabel() {
return label;
}
diff --git a/src/main/java/org/cbioportal/model/GenomicDataCountItem.java b/src/main/java/org/cbioportal/model/GenomicDataCountItem.java
index bd9ae14cdaf..a2123a9386c 100644
--- a/src/main/java/org/cbioportal/model/GenomicDataCountItem.java
+++ b/src/main/java/org/cbioportal/model/GenomicDataCountItem.java
@@ -9,6 +9,14 @@ public class GenomicDataCountItem implements Serializable {
private String profileType;
private List counts;
+ public GenomicDataCountItem() {}
+
+ public GenomicDataCountItem(String hugoGeneSymbol, String profileType, List counts) {
+ this.hugoGeneSymbol = hugoGeneSymbol;
+ this.profileType = profileType;
+ this.counts = counts;
+ }
+
public String getHugoGeneSymbol() {
return hugoGeneSymbol;
}
diff --git a/src/main/java/org/cbioportal/model/PatientTreatment.java b/src/main/java/org/cbioportal/model/PatientTreatment.java
new file mode 100644
index 00000000000..c838d23777e
--- /dev/null
+++ b/src/main/java/org/cbioportal/model/PatientTreatment.java
@@ -0,0 +1,7 @@
+package org.cbioportal.model;
+
+import java.io.Serializable;
+
+public record PatientTreatment (String treatment, int count) implements Serializable {
+
+}
diff --git a/src/main/java/org/cbioportal/model/PatientTreatmentReport.java b/src/main/java/org/cbioportal/model/PatientTreatmentReport.java
new file mode 100644
index 00000000000..d09a2276f06
--- /dev/null
+++ b/src/main/java/org/cbioportal/model/PatientTreatmentReport.java
@@ -0,0 +1,11 @@
+package org.cbioportal.model;
+
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.List;
+
+public record PatientTreatmentReport (int totalPatients, int totalSamples, List patientTreatments) implements Serializable {
+ public PatientTreatmentReport(int totalPatients, int totalSamples) {
+ this(totalPatients, totalSamples, Collections.emptyList());
+ }
+}
diff --git a/src/main/java/org/cbioportal/model/SampleTreatment.java b/src/main/java/org/cbioportal/model/SampleTreatment.java
new file mode 100644
index 00000000000..edf9ef7541a
--- /dev/null
+++ b/src/main/java/org/cbioportal/model/SampleTreatment.java
@@ -0,0 +1,4 @@
+package org.cbioportal.model;
+
+public record SampleTreatment(String treatment, int preSampleCount, int postSampleCount) {
+}
diff --git a/src/main/java/org/cbioportal/model/SampleTreatmentReport.java b/src/main/java/org/cbioportal/model/SampleTreatmentReport.java
new file mode 100644
index 00000000000..12cf93f4fa6
--- /dev/null
+++ b/src/main/java/org/cbioportal/model/SampleTreatmentReport.java
@@ -0,0 +1,6 @@
+package org.cbioportal.model;
+
+import java.util.Collection;
+
+public record SampleTreatmentReport(int totalSamples, Collection treatments) {
+}
diff --git a/src/main/java/org/cbioportal/model/StudyViewFilterContext.java b/src/main/java/org/cbioportal/model/StudyViewFilterContext.java
new file mode 100644
index 00000000000..e23e5f7d9d4
--- /dev/null
+++ b/src/main/java/org/cbioportal/model/StudyViewFilterContext.java
@@ -0,0 +1,14 @@
+package org.cbioportal.model;
+
+import org.cbioportal.web.parameter.CustomSampleIdentifier;
+import org.cbioportal.web.parameter.StudyViewFilter;
+
+import java.util.List;
+
+public record StudyViewFilterContext(
+ StudyViewFilter studyViewFilter,
+ List customDataFilterSamples,
+ List involvedCancerStudies
+) {
+
+}
diff --git a/src/main/java/org/cbioportal/persistence/CacheEnabledConfig.java b/src/main/java/org/cbioportal/persistence/CacheEnabledConfig.java
index af04bac392c..45b22f5bbf4 100644
--- a/src/main/java/org/cbioportal/persistence/CacheEnabledConfig.java
+++ b/src/main/java/org/cbioportal/persistence/CacheEnabledConfig.java
@@ -16,8 +16,11 @@ public class CacheEnabledConfig {
@Value("${persistence.cache_type:no-cache}")
private String cacheType;
+ @Value("${persistence.cache_type_clickhouse:no-cache}")
+ private String cacheTypeClickhouse;
private boolean enabled;
+ private boolean enabledClickhouse;
public static final String EHCACHE_DISK = "ehcache-disk";
public static final String EHCACHE_HEAP = "ehcache-heap";
@@ -30,6 +33,8 @@ public class CacheEnabledConfig {
public void init() {
this.enabled = enableCache(cacheType);
LOG.info("Cache is enabled: " + this.enabled);
+ this.enabledClickhouse = enableCache(cacheTypeClickhouse);
+ LOG.info("Cache is enabled for clickhouse: " + this.enabledClickhouse);
}
public static boolean enableCache(String cacheType) {
@@ -53,4 +58,16 @@ public boolean isEnabled() {
return enabled;
}
+ public String getEnabledClickhouse() {
+ if (enabledClickhouse) {
+ return "true";
+ } else {
+ return "false";
+ }
+ }
+
+ public boolean isEnabledClickhouse() {
+ return enabledClickhouse;
+ }
+
}
diff --git a/src/main/java/org/cbioportal/persistence/StudyViewRepository.java b/src/main/java/org/cbioportal/persistence/StudyViewRepository.java
new file mode 100644
index 00000000000..c39158ad433
--- /dev/null
+++ b/src/main/java/org/cbioportal/persistence/StudyViewRepository.java
@@ -0,0 +1,92 @@
+package org.cbioportal.persistence;
+
+import org.cbioportal.model.AlterationCountByGene;
+import org.cbioportal.model.ClinicalAttribute;
+import org.cbioportal.model.CaseListDataCount;
+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.GenericAssayDataCountItem;
+import org.cbioportal.model.GenomicDataCountItem;
+import org.cbioportal.model.GenomicDataCount;
+import org.cbioportal.model.MolecularProfile;
+import org.cbioportal.model.PatientTreatment;
+import org.cbioportal.model.Sample;
+import org.cbioportal.model.SampleTreatment;
+import org.cbioportal.model.StudyViewFilterContext;
+import org.cbioportal.web.parameter.ClinicalDataType;
+import org.cbioportal.web.parameter.GenericAssayDataBinFilter;
+import org.cbioportal.web.parameter.GenericAssayDataFilter;
+import org.cbioportal.web.parameter.GenomicDataBinFilter;
+import org.cbioportal.web.parameter.GenomicDataFilter;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public interface StudyViewRepository {
+ List getFilteredSamples(StudyViewFilterContext studyViewFilterContext);
+
+ List getFilteredStudyIds(StudyViewFilterContext studyViewFilterContext);
+
+ List getSampleClinicalData(StudyViewFilterContext studyViewFilterContext, List attributeIds);
+
+ List getPatientClinicalData(StudyViewFilterContext studyViewFilterContext, List attributeIds);
+
+ List getMutatedGenes(StudyViewFilterContext studyViewFilterContext);
+
+ List getStructuralVariantGenes(StudyViewFilterContext studyViewFilterContext);
+ List getCnaGenes(StudyViewFilterContext studyViewFilterContext);
+
+ List getClinicalDataCounts(StudyViewFilterContext studyViewFilterContext, List filteredAttributes);
+
+ List getMolecularProfileSampleCounts(StudyViewFilterContext studyViewFilterContext);
+
+ Map getClinicalAttributeDatatypeMap();
+
+ List getCaseListDataCountsPerStudy(StudyViewFilterContext studyViewFilterContext);
+
+ Map getTotalProfiledCounts(StudyViewFilterContext studyViewFilterContext, String alterationType, List molecularProfiles);
+
+ List getClinicalAttributes();
+
+ List getClinicalAttributesForStudies(List studyIds);
+
+ int getFilteredSamplesCount(StudyViewFilterContext studyViewFilterContext);
+
+ int getFilteredPatientCount(StudyViewFilterContext studyViewFilterContext);
+
+ Map> getMatchingGenePanelIds(StudyViewFilterContext studyViewFilterContext, String alterationType);
+
+ int getTotalProfiledCountsByAlterationType(StudyViewFilterContext studyViewFilterContext, String alterationType);
+
+ int getSampleProfileCountWithoutPanelData(StudyViewFilterContext studyViewFilterContext, String alterationType);
+
+ List getClinicalEventTypeCounts(StudyViewFilterContext studyViewFilterContext);
+
+ List getPatientTreatments(StudyViewFilterContext studyViewFilterContext);
+
+ int getTotalPatientTreatmentCount(StudyViewFilterContext studyViewFilterContext);
+
+ List getSampleTreatments(StudyViewFilterContext studyViewFilterContext);
+
+ int getTotalSampleTreatmentCount(StudyViewFilterContext studyViewFilterContext);
+
+ List getCNACounts(StudyViewFilterContext studyViewFilterContext, List genomicDataFilters);
+
+ List getGenericAssayDataCounts(StudyViewFilterContext studyViewFilterContext, List genericAssayDataFilters);
+
+ Map getMutationCounts(StudyViewFilterContext studyViewFilterContext, GenomicDataFilter genomicDataFilter);
+
+ List getMutationCountsByType(StudyViewFilterContext studyViewFilterContext, List genomicDataFilters);
+
+ List getGenomicDataBinCounts(StudyViewFilterContext studyViewFilterContext, List genomicDataBinFilters);
+
+ List getGenericAssayDataBinCounts(StudyViewFilterContext studyViewFilterContext, List genericAssayDataBinFilters);
+
+ List getGenericAssayProfiles();
+
+ List getFilteredMolecularProfilesByAlterationType(StudyViewFilterContext studyViewFilterContext, String alterationType);
+}
diff --git a/src/main/java/org/cbioportal/persistence/cachemaputil/SpringManagedCacheMapUtil.java b/src/main/java/org/cbioportal/persistence/cachemaputil/SpringManagedCacheMapUtil.java
index e58f04b6cf5..c492b2400b0 100644
--- a/src/main/java/org/cbioportal/persistence/cachemaputil/SpringManagedCacheMapUtil.java
+++ b/src/main/java/org/cbioportal/persistence/cachemaputil/SpringManagedCacheMapUtil.java
@@ -57,6 +57,8 @@ public class SpringManagedCacheMapUtil implements CacheMapUtil {
@Value("${persistence.cache_type:no-cache}")
private String cacheType;
+ @Value("${persistence.cache_type_clickhouse:no-cache}")
+ private String cacheTypeClickhouse;
@Value("${cache.cache-map-utils.spring-managed}")
private boolean springManagedCacheMapUtils;
@@ -67,7 +69,7 @@ public class SpringManagedCacheMapUtil implements CacheMapUtil {
@PostConstruct
public void init() {
// Make sure the user does not have a conflicting configuration. Explode if there is.
- if (cacheType.equals("no-cache") && springManagedCacheMapUtils) {
+ if (cacheType.equals("no-cache") && cacheTypeClickhouse.equals("no-cache") && springManagedCacheMapUtils) {
throw new RuntimeException("cache.cache-map-utils.spring-managed property is set to 'true' but the portal is not " +
"configured with a cache-implementation (persistence.cache_type property is 'no-cache'). Please set to 'false'" +
" or configure the cache.");
diff --git a/src/main/java/org/cbioportal/persistence/config/RedisConfig.java b/src/main/java/org/cbioportal/persistence/config/RedisConfig.java
index 2da81e8787c..99c225a33bd 100644
--- a/src/main/java/org/cbioportal/persistence/config/RedisConfig.java
+++ b/src/main/java/org/cbioportal/persistence/config/RedisConfig.java
@@ -3,8 +3,8 @@
import org.cbioportal.persistence.util.CustomKeyGenerator;
import org.cbioportal.persistence.util.CustomRedisCachingProvider;
import org.cbioportal.persistence.util.LoggingCacheErrorHandler;
-import org.cbioportal.utils.config.annotation.ConditionalOnProperty;
import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
@@ -18,7 +18,9 @@
@Configuration
@EnableCaching
-@ConditionalOnProperty(name = "persistence.cache_type", havingValue = {"redis"})
+@ConditionalOnExpression(
+ "#{environment['persistence.cache_type'] == 'redis' or environment['persistence.cache_type_clickhouse'] == 'redis'}"
+)
public class RedisConfig extends CachingConfigurerSupport {
@Value("${redis.name:cbioportal}")
diff --git a/src/main/java/org/cbioportal/persistence/enums/ClinicalAttributeDataType.java b/src/main/java/org/cbioportal/persistence/enums/ClinicalAttributeDataType.java
new file mode 100644
index 00000000000..591f67e117d
--- /dev/null
+++ b/src/main/java/org/cbioportal/persistence/enums/ClinicalAttributeDataType.java
@@ -0,0 +1,16 @@
+package org.cbioportal.persistence.enums;
+
+public enum ClinicalAttributeDataType {
+ CATEGORICAL("CATEGORICAL"),
+ NUMERIC("NUMERIC");
+
+ private final String value;
+
+ ClinicalAttributeDataType(String value) {
+ this.value = value;
+ }
+
+ public String getValue() {
+ return this.value;
+ }
+}
diff --git a/src/main/java/org/cbioportal/persistence/enums/DataSource.java b/src/main/java/org/cbioportal/persistence/enums/DataSource.java
new file mode 100644
index 00000000000..09b81b79edb
--- /dev/null
+++ b/src/main/java/org/cbioportal/persistence/enums/DataSource.java
@@ -0,0 +1,15 @@
+package org.cbioportal.persistence.enums;
+
+public enum DataSource {
+ PATIENT("PATIENT"),SAMPLE("SAMPLE");
+
+ private final String value;
+
+ DataSource(String value) {
+ this.value = value;
+ }
+
+ public String getValue() {
+ return this.value;
+ }
+}
diff --git a/src/main/java/org/cbioportal/persistence/helper/AlterationFilterHelper.java b/src/main/java/org/cbioportal/persistence/helper/AlterationFilterHelper.java
new file mode 100644
index 00000000000..1d8f63a55f2
--- /dev/null
+++ b/src/main/java/org/cbioportal/persistence/helper/AlterationFilterHelper.java
@@ -0,0 +1,151 @@
+package org.cbioportal.persistence.helper;
+
+import org.cbioportal.model.AlterationFilter;
+import org.cbioportal.model.CNA;
+import org.cbioportal.model.MutationEventType;
+import org.cbioportal.model.util.Select;
+import org.springframework.lang.NonNull;
+import org.springframework.lang.Nullable;
+
+import java.util.Objects;
+
+public final class AlterationFilterHelper {
+
+ public static AlterationFilterHelper build(@Nullable AlterationFilter alterationFilter) {
+ if (Objects.isNull(alterationFilter)) {
+ alterationFilter = new AlterationFilter();
+ }
+ return new AlterationFilterHelper(alterationFilter);
+ }
+
+ private final AlterationFilter alterationFilter;
+ private final Select mappedMutationTypes;
+
+ private final Select mappedCnaTypes;
+
+ private AlterationFilterHelper(@NonNull AlterationFilter alterationFilter){
+ this.alterationFilter = alterationFilter;
+ this.mappedMutationTypes = buildMutationTypeList();
+ this.mappedCnaTypes = buildCnaTypeList();
+ }
+
+ private Select buildMutationTypeList() {
+ if (alterationFilter.getMutationTypeSelect().hasNone()) {
+ return Select.none();
+ }
+ if (alterationFilter.getMutationTypeSelect().hasAll()) {
+ return Select.all();
+ }
+ Select typeSelects = alterationFilter.getMutationTypeSelect().map(MutationEventType::getMutationType);
+ typeSelects.inverse(alterationFilter.getMutationTypeSelect().inverse());
+
+ return typeSelects;
+ }
+
+ public Select getMutationTypeList() {
+ return mappedMutationTypes;
+ }
+
+ public Select getCnaTypeList() {
+ return mappedCnaTypes;
+ }
+
+ public Select buildCnaTypeList() {
+ if (alterationFilter.getCNAEventTypeSelect().hasNone()) {
+ return Select.none();
+ }
+ if (alterationFilter.getCNAEventTypeSelect().hasAll()) {
+ return Select.all();
+ }
+ return alterationFilter.getCNAEventTypeSelect().map(CNA::getCode);
+ }
+
+ public boolean hasDriver() {
+ return alterationFilter.getIncludeDriver();
+ }
+
+ public boolean hasVUSDriver() {
+ return alterationFilter.getIncludeVUS();
+ }
+
+ public boolean hasUnknownOncogenicity() {
+ return alterationFilter.getIncludeUnknownOncogenicity();
+ }
+
+ public boolean hasGermline() {
+ return alterationFilter.getIncludeGermline();
+ }
+
+ public boolean hasSomatic() {
+ return alterationFilter.getIncludeSomatic();
+ }
+
+ public boolean hasUnknownMutationStatus() {
+ return alterationFilter.getIncludeUnknownStatus();
+ }
+
+ public Select getSelectedTiers() {
+ return alterationFilter.getSelectedTiers();
+ }
+
+ public boolean hasUnknownTier() {
+ return alterationFilter.getIncludeUnknownTier();
+ }
+
+ public boolean isAllDriverAnnotationSelected() {
+ return alterationFilter.getIncludeDriver() && alterationFilter.getIncludeVUS() && alterationFilter.getIncludeUnknownOncogenicity();
+ }
+
+ public boolean isNoDriverAnnotationSelected() {
+ return !alterationFilter.getIncludeDriver() && !alterationFilter.getIncludeVUS() && !alterationFilter.getIncludeUnknownOncogenicity();
+ }
+
+ public boolean isSomeDriverAnnotationsSelected() {
+ return !isAllDriverAnnotationSelected() && !isNoDriverAnnotationSelected();
+ }
+
+ public boolean isAllMutationStatusSelected() {
+ return alterationFilter.getIncludeGermline()
+ && alterationFilter.getIncludeSomatic()
+ && alterationFilter.getIncludeUnknownStatus();
+ }
+
+ public boolean isNoMutationStatusSelected() {
+ return !alterationFilter.getIncludeGermline()
+ && !alterationFilter.getIncludeSomatic()
+ && !alterationFilter.getIncludeUnknownStatus();
+ }
+
+ public boolean isSomeMutationStatusSelected() {
+ return !isAllMutationStatusSelected() && !isNoMutationStatusSelected();
+ }
+
+ public boolean isAllTierOptionsSelected() {
+ return !Objects.isNull(alterationFilter.getSelectedTiers())
+ && alterationFilter.getSelectedTiers().hasAll()
+ && alterationFilter.getIncludeUnknownTier();
+ }
+
+ public boolean isNoTierOptionsSelected() {
+ return (Objects.isNull(alterationFilter.getSelectedTiers()) || alterationFilter.getSelectedTiers().hasNone())
+ && !alterationFilter.getIncludeUnknownTier();
+ }
+
+ public boolean isSomeTierOptionsSelected() {
+ return !isAllTierOptionsSelected() && !isNoTierOptionsSelected();
+ }
+
+ public boolean shouldApplyMutationAlterationFilter() {
+ return isSomeDriverAnnotationsSelected()
+ || isSomeMutationStatusSelected()
+ || isSomeTierOptionsSelected()
+ || mappedMutationTypes.hasNone()
+ || (!mappedMutationTypes.hasNone() && !mappedMutationTypes.hasAll());
+ }
+
+ public boolean shouldApplyCnaAlterationFilter() {
+ return isSomeDriverAnnotationsSelected()
+ || mappedCnaTypes.hasNone()
+ || (!mappedCnaTypes.hasNone() && !mappedCnaTypes.hasAll());
+ }
+}
diff --git a/src/main/java/org/cbioportal/persistence/helper/StudyViewFilterHelper.java b/src/main/java/org/cbioportal/persistence/helper/StudyViewFilterHelper.java
new file mode 100644
index 00000000000..23615be0ef4
--- /dev/null
+++ b/src/main/java/org/cbioportal/persistence/helper/StudyViewFilterHelper.java
@@ -0,0 +1,172 @@
+package org.cbioportal.persistence.helper;
+
+import org.cbioportal.model.MolecularProfile;
+import org.cbioportal.persistence.enums.DataSource;
+import org.cbioportal.web.parameter.ClinicalDataFilter;
+import org.cbioportal.web.parameter.CategorizedGenericAssayDataCountFilter;
+import org.cbioportal.web.parameter.CustomSampleIdentifier;
+import org.cbioportal.web.parameter.DataFilter;
+import org.cbioportal.web.parameter.DataFilterValue;
+import org.cbioportal.web.parameter.GenericAssayDataFilter;
+import org.cbioportal.web.parameter.GenomicDataFilter;
+import org.cbioportal.web.parameter.StudyViewFilter;
+import org.springframework.lang.NonNull;
+import org.springframework.lang.Nullable;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.EnumMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+public final class StudyViewFilterHelper {
+ public static StudyViewFilterHelper build(@Nullable StudyViewFilter studyViewFilter,
+ @Nullable Map> genericAssayProfilesMap,
+ @Nullable List customDataSamples,
+ @Nullable List involvedCancerStudies) {
+ if (Objects.isNull(studyViewFilter)) {
+ studyViewFilter = new StudyViewFilter();
+ }
+ if (Objects.isNull(genericAssayProfilesMap)) {
+ genericAssayProfilesMap = new EnumMap<>(DataSource.class);
+ }
+ if (Objects.isNull(customDataSamples)) {
+ customDataSamples = new ArrayList<>();
+ }
+ if (Objects.isNull(involvedCancerStudies)) {
+ involvedCancerStudies = new ArrayList<>();
+ }
+ if (studyViewFilter.getGenomicDataFilters() != null && !studyViewFilter.getGenomicDataFilters().isEmpty()) {
+ List mergedGenomicDataFilters = mergeDataFilters(studyViewFilter.getGenomicDataFilters());
+ studyViewFilter.setGenomicDataFilters(mergedGenomicDataFilters);
+ }
+ if (studyViewFilter.getClinicalDataFilters() != null && !studyViewFilter.getClinicalDataFilters().isEmpty()) {
+ List mergedClinicalDataFilters = mergeDataFilters(studyViewFilter.getClinicalDataFilters());
+ studyViewFilter.setClinicalDataFilters(mergedClinicalDataFilters);
+ }
+ if (studyViewFilter.getGenericAssayDataFilters() != null && !studyViewFilter.getGenericAssayDataFilters().isEmpty()) {
+ List mergedGenericAssayDataFilters = mergeDataFilters(studyViewFilter.getGenericAssayDataFilters());
+ studyViewFilter.setGenericAssayDataFilters(mergedGenericAssayDataFilters);
+ }
+ return new StudyViewFilterHelper(studyViewFilter, genericAssayProfilesMap, customDataSamples, involvedCancerStudies);
+ }
+
+ private final StudyViewFilter studyViewFilter;
+ private final CategorizedGenericAssayDataCountFilter categorizedGenericAssayDataCountFilter;
+ private final List customDataSamples;
+ private final List involvedCancerStudies;
+
+ private StudyViewFilterHelper(@NonNull StudyViewFilter studyViewFilter,
+ @NonNull Map> genericAssayProfilesMap,
+ @NonNull List customDataSamples,
+ @NonNull List involvedCancerStudies) {
+ this.studyViewFilter = studyViewFilter;
+ this.categorizedGenericAssayDataCountFilter = extractGenericAssayDataCountFilters(studyViewFilter, genericAssayProfilesMap);
+ this.customDataSamples = customDataSamples;
+ this.involvedCancerStudies = involvedCancerStudies;
+ }
+
+ public StudyViewFilter studyViewFilter() {
+ return studyViewFilter;
+ }
+
+ public CategorizedGenericAssayDataCountFilter categorizedGenericAssayDataCountFilter() {
+ return categorizedGenericAssayDataCountFilter;
+ }
+
+ public List customDataSamples() {
+ return this.customDataSamples;
+ }
+
+ public List involvedCancerStudies() {
+ return involvedCancerStudies;
+ }
+
+ private CategorizedGenericAssayDataCountFilter extractGenericAssayDataCountFilters(final StudyViewFilter studyViewFilter, Map> genericAssayProfilesMap) {
+ if ((studyViewFilter.getGenericAssayDataFilters() == null || genericAssayProfilesMap.isEmpty()))
+ {
+ return CategorizedGenericAssayDataCountFilter.getBuilder().build();
+ }
+
+ CategorizedGenericAssayDataCountFilter.Builder builder = CategorizedGenericAssayDataCountFilter.getBuilder();
+
+ // No BINARY in the database yet
+ List sampleNumericalProfileTypes = genericAssayProfilesMap.get(DataSource.SAMPLE)
+ .stream().filter(profile -> profile.getDatatype().equals("LIMIT-VALUE"))
+ .map(profile -> profile.getStableId().replace(profile.getCancerStudyIdentifier() + "_", ""))
+ .toList();
+ builder.setSampleNumericalGenericAssayDataFilters(studyViewFilter.getGenericAssayDataFilters().stream()
+ .filter(genericAssayDataFilter -> sampleNumericalProfileTypes.contains(genericAssayDataFilter.getProfileType()))
+ .toList());
+ List sampleCategoricalProfileTypes = genericAssayProfilesMap.get(DataSource.SAMPLE)
+ .stream().filter(profile -> profile.getDatatype().equals("CATEGORICAL") || profile.getDatatype().equals("BINARY"))
+ .map(profile -> profile.getStableId().replace(profile.getCancerStudyIdentifier() + "_", ""))
+ .toList();
+ builder.setSampleCategoricalGenericAssayDataFilters(studyViewFilter.getGenericAssayDataFilters().stream()
+ .filter(genericAssayDataFilter -> sampleCategoricalProfileTypes.contains(genericAssayDataFilter.getProfileType()))
+ .toList());
+ List patientCategoricalProfileTypes = genericAssayProfilesMap.get(DataSource.PATIENT)
+ .stream().filter(profile -> profile.getDatatype().equals("CATEGORICAL") || profile.getDatatype().equals("BINARY"))
+ .map(profile -> profile.getStableId().replace(profile.getCancerStudyIdentifier() + "_", ""))
+ .toList();
+ builder.setPatientCategoricalGenericAssayDataFilters(studyViewFilter.getGenericAssayDataFilters().stream()
+ .filter(genericAssayDataFilter -> patientCategoricalProfileTypes.contains(genericAssayDataFilter.getProfileType()))
+ .toList());
+ return builder.build();
+ }
+
+ public boolean isCategoricalClinicalDataFilter(ClinicalDataFilter clinicalDataFilter) {
+ var filterValue = clinicalDataFilter.getValues().getFirst();
+ return filterValue.getValue() != null;
+ }
+
+ /**
+ * Merge the range of numerical bins in DataFilters to reduce the number of scans that runs on the database when filtering.
+ */
+ public static List mergeDataFilters(List filters) {
+ boolean isNonNumericalOnly = true;
+ List mergedDataFilters = new ArrayList<>();
+
+ for (T filter : filters) {
+ List mergedValues = new ArrayList<>();
+ List nonNumericalValues = new ArrayList<>();
+
+ BigDecimal mergedStart = null;
+ BigDecimal mergedEnd = null;
+ for (DataFilterValue dataFilterValue : filter.getValues()) {
+ // leave non-numerical values as they are
+ if (dataFilterValue.getValue() != null) {
+ nonNumericalValues.add(dataFilterValue);
+ }
+ // merge adjacent numerical bins
+ else {
+ isNonNumericalOnly = false;
+ BigDecimal start = dataFilterValue.getStart();
+ BigDecimal end = dataFilterValue.getEnd();
+
+ if (mergedStart == null && mergedEnd == null) {
+ mergedStart = start;
+ mergedEnd = end;
+ }
+ else if (mergedEnd.equals(start)) {
+ mergedEnd = end;
+ } else {
+ mergedValues.add(new DataFilterValue(mergedStart, mergedEnd, null));
+ mergedStart = start;
+ mergedEnd = end;
+ }
+ }
+ }
+
+ if (!isNonNumericalOnly) {
+ mergedValues.add(new DataFilterValue(mergedStart, mergedEnd, null));
+ }
+ mergedValues.addAll(nonNumericalValues);
+ filter.setValues(mergedValues);
+ mergedDataFilters.add(filter);
+ }
+
+ return mergedDataFilters;
+ }
+}
diff --git a/src/main/java/org/cbioportal/persistence/model/SampleAcquisitionEventRecord.java b/src/main/java/org/cbioportal/persistence/model/SampleAcquisitionEventRecord.java
new file mode 100644
index 00000000000..b02c24c7100
--- /dev/null
+++ b/src/main/java/org/cbioportal/persistence/model/SampleAcquisitionEventRecord.java
@@ -0,0 +1,4 @@
+package org.cbioportal.persistence.model;
+
+public record SampleAcquisitionEventRecord(String sampleId, String patientUniqueId, String cancerStudyId, int timeTaken) {
+}
diff --git a/src/main/java/org/cbioportal/persistence/model/TreatmentRecord.java b/src/main/java/org/cbioportal/persistence/model/TreatmentRecord.java
new file mode 100644
index 00000000000..aeeac35723b
--- /dev/null
+++ b/src/main/java/org/cbioportal/persistence/model/TreatmentRecord.java
@@ -0,0 +1,4 @@
+package org.cbioportal.persistence.model;
+
+public record TreatmentRecord(String patientUniqueId, String treatment, int startTime, int stopTime) {
+}
diff --git a/src/main/java/org/cbioportal/persistence/mybatis/UnImplementedStudyViewMyBatisRepository.java b/src/main/java/org/cbioportal/persistence/mybatis/UnImplementedStudyViewMyBatisRepository.java
new file mode 100644
index 00000000000..bb34c5e040b
--- /dev/null
+++ b/src/main/java/org/cbioportal/persistence/mybatis/UnImplementedStudyViewMyBatisRepository.java
@@ -0,0 +1,198 @@
+package org.cbioportal.persistence.mybatis;
+
+import org.cbioportal.model.AlterationCountByGene;
+import org.cbioportal.model.CaseListDataCount;
+import org.cbioportal.model.ClinicalAttribute;
+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.GenericAssayDataCountItem;
+import org.cbioportal.model.GenomicDataCount;
+import org.cbioportal.model.GenomicDataCountItem;
+import org.cbioportal.model.MolecularProfile;
+import org.cbioportal.model.PatientTreatment;
+import org.cbioportal.model.Sample;
+import org.cbioportal.model.SampleTreatment;
+import org.cbioportal.model.StudyViewFilterContext;
+import org.cbioportal.persistence.StudyViewRepository;
+import org.cbioportal.utils.config.annotation.ConditionalOnProperty;
+import org.cbioportal.web.parameter.ClinicalDataType;
+import org.cbioportal.web.parameter.GenericAssayDataBinFilter;
+import org.cbioportal.web.parameter.GenericAssayDataFilter;
+import org.cbioportal.web.parameter.GenomicDataBinFilter;
+import org.cbioportal.web.parameter.GenomicDataFilter;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+@Repository
+@ConditionalOnProperty(name = "clickhouse_mode", havingValue = "false", matchIfMissing = true)
+public class UnImplementedStudyViewMyBatisRepository implements StudyViewRepository {
+
+ private static final String UNSUPPORTED_OPERATION = "StudyViewRepository Feature Not supported... Contact cbio admin.";
+
+ @Override
+ public List getFilteredSamples(StudyViewFilterContext studyViewFilterContext) {
+ throw new UnsupportedOperationException(UNSUPPORTED_OPERATION);
+ }
+
+ @Override
+ public List getFilteredStudyIds(StudyViewFilterContext studyViewFilterContext) {
+ throw new UnsupportedOperationException(UNSUPPORTED_OPERATION);
+ }
+
+ @Override
+ public List getSampleClinicalData(StudyViewFilterContext studyViewFilterContext, List attributeIds) {
+ throw new UnsupportedOperationException(UNSUPPORTED_OPERATION);
+ }
+
+ @Override
+ public List getPatientClinicalData(StudyViewFilterContext studyViewFilterContext, List attributeIds) {
+ throw new UnsupportedOperationException(UNSUPPORTED_OPERATION);
+
+ }
+
+ @Override
+ public List getMutatedGenes(StudyViewFilterContext studyViewFilterContext) {
+ throw new UnsupportedOperationException(UNSUPPORTED_OPERATION);
+ }
+
+ @Override
+ public List getStructuralVariantGenes(StudyViewFilterContext studyViewFilterContext) {
+ throw new UnsupportedOperationException(UNSUPPORTED_OPERATION);
+ }
+
+ @Override
+ public List getCnaGenes(StudyViewFilterContext studyViewFilterContext) {
+ throw new UnsupportedOperationException(UNSUPPORTED_OPERATION);
+ }
+
+ @Override
+ public List getClinicalDataCounts(StudyViewFilterContext studyViewFilterContext, List filteredAttributes) {
+ throw new UnsupportedOperationException(UNSUPPORTED_OPERATION);
+ }
+
+ @Override
+ public List getMolecularProfileSampleCounts(StudyViewFilterContext studyViewFilterContext) {
+ throw new UnsupportedOperationException(UNSUPPORTED_OPERATION);
+ }
+
+ @Override
+ public Map getClinicalAttributeDatatypeMap() {
+ throw new UnsupportedOperationException(UNSUPPORTED_OPERATION);
+ }
+
+ @Override
+ public List getCaseListDataCountsPerStudy(StudyViewFilterContext studyViewFilterContext) {
+ throw new UnsupportedOperationException(UNSUPPORTED_OPERATION);
+ }
+
+ @Override
+ public Map getTotalProfiledCounts(StudyViewFilterContext studyViewFilterContext, String alterationType, List molecularProfiles) {
+ throw new UnsupportedOperationException(UNSUPPORTED_OPERATION);
+ }
+
+ @Override
+ public List getClinicalAttributes() {
+ throw new UnsupportedOperationException(UNSUPPORTED_OPERATION);
+ }
+
+ @Override
+ public List getClinicalAttributesForStudies(List studyIds) {
+ throw new UnsupportedOperationException(UNSUPPORTED_OPERATION);
+ }
+
+ @Override
+ public int getFilteredSamplesCount(StudyViewFilterContext studyViewFilterContext) {
+ throw new UnsupportedOperationException(UNSUPPORTED_OPERATION);
+ }
+
+ @Override
+ public int getFilteredPatientCount(StudyViewFilterContext studyViewFilterContext) {
+ throw new UnsupportedOperationException(UNSUPPORTED_OPERATION);
+ }
+
+ @Override
+ public Map> getMatchingGenePanelIds(StudyViewFilterContext studyViewFilterContext, String alterationType) {
+ throw new UnsupportedOperationException(UNSUPPORTED_OPERATION);
+ }
+
+ @Override
+ public int getTotalProfiledCountsByAlterationType(StudyViewFilterContext studyViewFilterContext, String alterationType) {
+ throw new UnsupportedOperationException(UNSUPPORTED_OPERATION);
+ }
+
+ @Override
+ public int getSampleProfileCountWithoutPanelData(StudyViewFilterContext studyViewFilterContext, String alterationType) {
+ throw new UnsupportedOperationException(UNSUPPORTED_OPERATION);
+ }
+
+ @Override
+ public List getClinicalEventTypeCounts(StudyViewFilterContext studyViewFilterContext) {
+ throw new UnsupportedOperationException(UNSUPPORTED_OPERATION);
+ }
+
+ @Override
+ public List getPatientTreatments(StudyViewFilterContext studyViewFilterContext) {
+ throw new UnsupportedOperationException(UNSUPPORTED_OPERATION);
+ }
+
+ @Override
+ public int getTotalPatientTreatmentCount(StudyViewFilterContext studyViewFilterContext) {
+ throw new UnsupportedOperationException(UNSUPPORTED_OPERATION);
+ }
+
+ @Override
+ public List getSampleTreatments(StudyViewFilterContext studyViewFilterContext) {
+ throw new UnsupportedOperationException(UNSUPPORTED_OPERATION);
+ }
+
+ @Override
+ public int getTotalSampleTreatmentCount(StudyViewFilterContext studyViewFilterContext) {
+ throw new UnsupportedOperationException(UNSUPPORTED_OPERATION);
+ }
+
+ @Override
+ public List getCNACounts(StudyViewFilterContext studyViewFilterContext, List genomicDataFilters) {
+ throw new UnsupportedOperationException(UNSUPPORTED_OPERATION);
+ }
+
+ @Override
+ public List getGenericAssayDataCounts(StudyViewFilterContext studyViewFilterContext, List genericAssayDataFilters) {
+ throw new UnsupportedOperationException(UNSUPPORTED_OPERATION);
+ }
+
+ @Override
+ public Map getMutationCounts(StudyViewFilterContext studyViewFilterContext, GenomicDataFilter genomicDataFilter) {
+ throw new UnsupportedOperationException(UNSUPPORTED_OPERATION);
+ }
+
+ @Override
+ public List getMutationCountsByType(StudyViewFilterContext studyViewFilterContext, List genomicDataFilters) {
+ return List.of();
+ }
+
+ @Override
+ public List getGenomicDataBinCounts(StudyViewFilterContext studyViewFilterContext, List genomicDataBinFilters) {
+ return List.of();
+ }
+
+ @Override
+ public List getGenericAssayDataBinCounts(StudyViewFilterContext studyViewFilterContext, List genericAssayDataBinFilters) {
+ return List.of();
+ }
+
+ @Override
+ public List getGenericAssayProfiles() {
+ return List.of();
+ }
+
+ @Override
+ public List getFilteredMolecularProfilesByAlterationType(StudyViewFilterContext studyViewFilterContext, String alterationType) {
+ return List.of();
+ }
+}
diff --git a/src/main/java/org/cbioportal/persistence/mybatis/config/PersistenceConfig.java b/src/main/java/org/cbioportal/persistence/mybatis/config/PersistenceConfig.java
index 933be27cc4a..b8dba141ae4 100644
--- a/src/main/java/org/cbioportal/persistence/mybatis/config/PersistenceConfig.java
+++ b/src/main/java/org/cbioportal/persistence/mybatis/config/PersistenceConfig.java
@@ -2,19 +2,22 @@
import org.cbioportal.model.Sample;
import org.cbioportal.persistence.mybatis.typehandler.SampleTypeTypeHandler;
+import org.cbioportal.utils.config.annotation.ConditionalOnProperty;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.mybatis.spring.boot.autoconfigure.ConfigurationCustomizer;
+import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
+import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import javax.sql.DataSource;
import java.io.IOException;
@Configuration
-@MapperScan("org.cbioportal.persistence.mybatis")
+@MapperScan(value="org.cbioportal.persistence.mybatis", sqlSessionFactoryRef="sqlSessionFactory")
public class PersistenceConfig {
// This is the only way I was able to register the SampleType TypeHandler to MyBatis.
@@ -30,8 +33,20 @@ public void customize(org.apache.ibatis.session.Configuration configuration) {
};
}
- @Bean
- public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource, ApplicationContext applicationContext) throws IOException {
+ @Bean("sqlSessionFactory")
+ @ConditionalOnProperty(name = "clickhouse_mode", havingValue = "true")
+ public SqlSessionFactoryBean sqlSessionFactorySpecifyDataSource(@Qualifier("mysqlDataSource") DataSource dataSource, ApplicationContext applicationContext) throws IOException {
+ return sqlSessionFactory(dataSource, applicationContext);
+ }
+
+ @Bean("sqlSessionFactory")
+ @ConditionalOnProperty(name = "clickhouse_mode", havingValue = "false", matchIfMissing = true)
+ public SqlSessionFactoryBean sqlSessionFactoryDefault(DataSource dataSource, ApplicationContext applicationContext) throws IOException {
+ return sqlSessionFactory(dataSource, applicationContext);
+ }
+
+
+ private SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource, ApplicationContext applicationContext) throws IOException {
SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
sessionFactory.setDataSource(dataSource);
sessionFactory.setMapperLocations(
@@ -40,5 +55,10 @@ public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource, Applicatio
sessionFactory.setTypeHandlers(new SampleTypeTypeHandler());
return sessionFactory;
}
-
+
+ @Bean
+ @ConditionalOnProperty(name = "clickhouse_mode", havingValue = "true")
+ public DataSourceTransactionManager transactionManager(@Qualifier("mysqlDataSource") DataSource dataSource) {
+ return new DataSourceTransactionManager(dataSource);
+ }
}
diff --git a/src/main/java/org/cbioportal/persistence/mybatisclickhouse/StudyViewMapper.java b/src/main/java/org/cbioportal/persistence/mybatisclickhouse/StudyViewMapper.java
new file mode 100644
index 00000000000..dca5ad64125
--- /dev/null
+++ b/src/main/java/org/cbioportal/persistence/mybatisclickhouse/StudyViewMapper.java
@@ -0,0 +1,90 @@
+package org.cbioportal.persistence.mybatisclickhouse;
+
+import org.apache.ibatis.annotations.Param;
+import org.cbioportal.model.AlterationCountByGene;
+import org.cbioportal.model.CaseListDataCount;
+import org.cbioportal.model.ClinicalAttribute;
+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.GenePanelToGene;
+import org.cbioportal.model.GenericAssayDataCountItem;
+import org.cbioportal.model.GenomicDataCount;
+import org.cbioportal.model.GenomicDataCountItem;
+import org.cbioportal.model.PatientTreatment;
+import org.cbioportal.model.MolecularProfile;
+import org.cbioportal.model.Sample;
+import org.cbioportal.model.SampleTreatment;
+import org.cbioportal.persistence.helper.AlterationFilterHelper;
+import org.cbioportal.persistence.helper.StudyViewFilterHelper;
+import org.cbioportal.web.parameter.GenericAssayDataBinFilter;
+import org.cbioportal.web.parameter.GenericAssayDataFilter;
+import org.cbioportal.web.parameter.GenomicDataBinFilter;
+import org.cbioportal.web.parameter.GenomicDataFilter;
+
+import java.util.List;
+import java.util.Map;
+
+
+public interface StudyViewMapper {
+ List getFilteredSamples(@Param("studyViewFilterHelper") StudyViewFilterHelper studyViewFilterHelper);
+
+ List getFilteredStudyIds(@Param("studyViewFilterHelper") StudyViewFilterHelper studyViewFilterHelper);
+
+ List getMolecularProfileSampleCounts(@Param("studyViewFilterHelper") StudyViewFilterHelper studyViewFilterHelper);
+
+ List getMutatedGenes(StudyViewFilterHelper studyViewFilterHelper, AlterationFilterHelper alterationFilterHelper);
+
+ List getCnaGenes(StudyViewFilterHelper studyViewFilterHelper, AlterationFilterHelper alterationFilterHelper);
+
+ List getStructuralVariantGenes(StudyViewFilterHelper studyViewFilterHelper, AlterationFilterHelper alterationFilterHelper);
+
+ List getClinicalDataCounts(StudyViewFilterHelper studyViewFilterHelper, List attributeIds, List filteredAttributeValues);
+
+ List getCaseListDataCountsPerStudy(@Param("studyViewFilterHelper") StudyViewFilterHelper studyViewFilterHelper);
+
+ List getClinicalAttributes();
+
+ List getClinicalAttributesForStudies(List studyIds);
+
+ List getSampleClinicalDataFromStudyViewFilter(StudyViewFilterHelper studyViewFilterHelper, List attributeIds);
+
+ List getPatientClinicalDataFromStudyViewFilter(StudyViewFilterHelper studyViewFilterHelper, List attributeIds);
+
+ List getTotalProfiledCounts(StudyViewFilterHelper studyViewFilterHelper, String alterationType, List molecularProfiles);
+
+ int getFilteredSamplesCount(@Param("studyViewFilterHelper") StudyViewFilterHelper studyViewFilterHelper);
+
+ int getFilteredPatientsCount(@Param("studyViewFilterHelper") StudyViewFilterHelper studyViewFilterHelper);
+
+ List getMatchingGenePanelIds(StudyViewFilterHelper studyViewFilterHelper, String alterationType);
+
+ int getTotalProfiledCountByAlterationType(StudyViewFilterHelper studyViewFilterHelper, String alterationType);
+
+ int getSampleProfileCountWithoutPanelData(StudyViewFilterHelper studyViewFilterHelper, String alterationType);
+
+ List getClinicalEventTypeCounts(@Param("studyViewFilterHelper") StudyViewFilterHelper studyViewFilterHelper);
+
+ List getPatientTreatments(@Param("studyViewFilterHelper") StudyViewFilterHelper studyViewFilterHelper);
+ int getPatientTreatmentCounts(@Param("studyViewFilterHelper") StudyViewFilterHelper studyViewFilterHelper);
+ List getSampleTreatmentCounts(@Param("studyViewFilterHelper") StudyViewFilterHelper studyViewFilterHelper);
+ int getTotalSampleTreatmentCounts(@Param("studyViewFilterHelper") StudyViewFilterHelper studyViewFilterHelper);
+
+ List getCNACounts(StudyViewFilterHelper studyViewFilterHelper, List genomicDataFilters);
+
+ List getGenericAssayDataCounts(StudyViewFilterHelper studyViewFilterHelper, List genericAssayDataFilters);
+
+ Map getMutationCounts(StudyViewFilterHelper studyViewFilterHelper, GenomicDataFilter genomicDataFilter);
+
+ List getMutationCountsByType(StudyViewFilterHelper studyViewFilterHelper, List genomicDataFilters);
+
+ List getGenomicDataBinCounts(StudyViewFilterHelper studyViewFilterHelper, List genomicDataBinFilters);
+
+ List getGenericAssayDataBinCounts(StudyViewFilterHelper studyViewFilterHelper, List genericAssayDataBinFilters);
+
+ List getGenericAssayProfiles();
+
+ List getFilteredMolecularProfilesByAlterationType(StudyViewFilterHelper studyViewFilterHelper, String alterationType);
+}
diff --git a/src/main/java/org/cbioportal/persistence/mybatisclickhouse/StudyViewMyBatisRepository.java b/src/main/java/org/cbioportal/persistence/mybatisclickhouse/StudyViewMyBatisRepository.java
new file mode 100644
index 00000000000..d3f594d61be
--- /dev/null
+++ b/src/main/java/org/cbioportal/persistence/mybatisclickhouse/StudyViewMyBatisRepository.java
@@ -0,0 +1,271 @@
+package org.cbioportal.persistence.mybatisclickhouse;
+import org.cbioportal.model.AlterationCountByGene;
+import org.cbioportal.model.ClinicalAttribute;
+import org.cbioportal.model.CaseListDataCount;
+import org.cbioportal.model.ClinicalData;
+import org.cbioportal.model.ClinicalDataCount;
+import org.cbioportal.model.ClinicalDataCountItem;
+import org.cbioportal.model.ClinicalEventTypeCount;
+import org.cbioportal.model.GenePanelToGene;
+import org.cbioportal.model.GenericAssayDataCountItem;
+import org.cbioportal.model.GenomicDataCountItem;
+import org.cbioportal.model.GenomicDataCount;
+import org.cbioportal.model.CopyNumberCountByGene;
+import org.cbioportal.model.MolecularProfile;
+import org.cbioportal.model.PatientTreatment;
+import org.cbioportal.model.Sample;
+import org.cbioportal.model.SampleTreatment;
+import org.cbioportal.model.StudyViewFilterContext;
+import org.cbioportal.persistence.StudyViewRepository;
+import org.cbioportal.persistence.enums.DataSource;
+import org.cbioportal.persistence.helper.AlterationFilterHelper;
+import org.cbioportal.persistence.helper.StudyViewFilterHelper;
+import org.cbioportal.service.util.StudyViewColumnarServiceUtil;
+import org.cbioportal.utils.config.annotation.ConditionalOnProperty;
+import org.cbioportal.web.parameter.ClinicalDataType;
+import org.cbioportal.web.parameter.GenericAssayDataBinFilter;
+import org.cbioportal.web.parameter.GenericAssayDataFilter;
+import org.cbioportal.web.parameter.GenomicDataBinFilter;
+import org.cbioportal.web.parameter.GenomicDataFilter;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Repository;
+
+import java.util.Collections;
+import java.util.EnumMap;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+@Repository
+@ConditionalOnProperty(name = "clickhouse_mode", havingValue = "true")
+public class StudyViewMyBatisRepository implements StudyViewRepository {
+
+ private final StudyViewMapper studyViewMapper;
+ private Map> clinicalAttributesMap = new EnumMap<>(DataSource.class);
+ private Map> genericAssayProfilesMap = new EnumMap<>(DataSource.class);
+
+ private static final List FILTERED_CLINICAL_ATTR_VALUES = Collections.emptyList();
+ private final StudyViewMapper mapper;
+
+ @Autowired
+ public StudyViewMyBatisRepository(StudyViewMapper mapper, StudyViewMapper studyViewMapper) {
+ this.mapper = mapper;
+ this.studyViewMapper = studyViewMapper;
+ }
+
+ @Override
+ public List getFilteredSamples(StudyViewFilterContext studyViewFilterContext) {
+ return mapper.getFilteredSamples(createStudyViewFilterHelper(studyViewFilterContext));
+ }
+
+ @Override
+ public List getFilteredStudyIds(StudyViewFilterContext studyViewFilterContext) {
+ return mapper.getFilteredStudyIds(createStudyViewFilterHelper(studyViewFilterContext));
+ }
+
+ @Override
+ public List getMutatedGenes(StudyViewFilterContext studyViewFilterContext) {
+ return mapper.getMutatedGenes(createStudyViewFilterHelper(studyViewFilterContext),
+ AlterationFilterHelper.build(studyViewFilterContext.studyViewFilter().getAlterationFilter()));
+ }
+
+ @Override
+ public List getCnaGenes(StudyViewFilterContext studyViewFilterContext) {
+ return mapper.getCnaGenes(createStudyViewFilterHelper(studyViewFilterContext),
+ AlterationFilterHelper.build(studyViewFilterContext.studyViewFilter().getAlterationFilter()));
+ }
+
+ @Override
+ public List getStructuralVariantGenes(StudyViewFilterContext studyViewFilterContext) {
+ return mapper.getStructuralVariantGenes(createStudyViewFilterHelper(studyViewFilterContext),
+ AlterationFilterHelper.build(studyViewFilterContext.studyViewFilter().getAlterationFilter()));
+ }
+
+ @Override
+ public List getClinicalDataCounts(StudyViewFilterContext studyViewFilterContext, List filteredAttributes) {
+ return mapper.getClinicalDataCounts(createStudyViewFilterHelper(studyViewFilterContext),
+ filteredAttributes, FILTERED_CLINICAL_ATTR_VALUES);
+ }
+
+ @Override
+ public List getMolecularProfileSampleCounts(StudyViewFilterContext studyViewFilterContext) {
+ var sampleCounts = mapper.getMolecularProfileSampleCounts(createStudyViewFilterHelper(studyViewFilterContext));
+ return StudyViewColumnarServiceUtil.mergeGenomicDataCounts(sampleCounts);
+
+ }
+
+ public StudyViewFilterHelper createStudyViewFilterHelper(StudyViewFilterContext studyViewFilterContext) {
+ return StudyViewFilterHelper.build(
+ studyViewFilterContext.studyViewFilter(),
+ getGenericAssayProfilesMap(),
+ studyViewFilterContext.customDataFilterSamples(),
+ studyViewFilterContext.involvedCancerStudies()
+ );
+ }
+
+ @Override
+ public List getClinicalAttributes() {
+ return mapper.getClinicalAttributes();
+ }
+
+ @Override
+ public List getGenericAssayProfiles() {
+ return mapper.getGenericAssayProfiles();
+ }
+
+ @Override
+ public List getFilteredMolecularProfilesByAlterationType(StudyViewFilterContext studyViewFilterContext, String alterationType) {
+ return studyViewMapper.getFilteredMolecularProfilesByAlterationType(createStudyViewFilterHelper(studyViewFilterContext), alterationType);
+ }
+
+ @Override
+ public Map getClinicalAttributeDatatypeMap() {
+ if (clinicalAttributesMap.isEmpty()) {
+ buildClinicalAttributeNameMap();
+ }
+
+ Map attributeDatatypeMap = new HashMap<>();
+
+ clinicalAttributesMap
+ .get(DataSource.SAMPLE)
+ .forEach(attribute -> attributeDatatypeMap.put(attribute.getAttrId(), ClinicalDataType.SAMPLE));
+
+ clinicalAttributesMap
+ .get(DataSource.PATIENT)
+ .forEach(attribute -> attributeDatatypeMap.put(attribute.getAttrId(), ClinicalDataType.PATIENT));
+
+ return attributeDatatypeMap;
+ }
+
+ @Override
+ public List getClinicalAttributesForStudies(List studyIds) {
+ return mapper.getClinicalAttributesForStudies(studyIds);
+ }
+
+ @Override
+ public List getCaseListDataCountsPerStudy(StudyViewFilterContext studyViewFilterContext) {
+ return mapper.getCaseListDataCountsPerStudy(createStudyViewFilterHelper(studyViewFilterContext));
+ }
+
+ @Override
+ public List getSampleClinicalData(StudyViewFilterContext studyViewFilterContext, List attributeIds) {
+ return mapper.getSampleClinicalDataFromStudyViewFilter(createStudyViewFilterHelper(studyViewFilterContext), attributeIds);
+ }
+
+ @Override
+ public List getPatientClinicalData(StudyViewFilterContext studyViewFilterContext, List attributeIds) {
+ return mapper.getPatientClinicalDataFromStudyViewFilter(createStudyViewFilterHelper(studyViewFilterContext), attributeIds);
+ }
+
+ @Override
+ public Map getTotalProfiledCounts(StudyViewFilterContext studyViewFilterContext, String alterationType, List molecularProfiles) {
+ return mapper.getTotalProfiledCounts(createStudyViewFilterHelper(studyViewFilterContext), alterationType, molecularProfiles)
+ .stream()
+ .collect(Collectors.groupingBy(AlterationCountByGene::getHugoGeneSymbol,
+ Collectors.mapping(AlterationCountByGene::getNumberOfProfiledCases, Collectors.summingInt(Integer::intValue))));
+ }
+
+ @Override
+ public int getFilteredSamplesCount(StudyViewFilterContext studyViewFilterContext) {
+ return mapper.getFilteredSamplesCount(createStudyViewFilterHelper(studyViewFilterContext));
+ }
+
+ @Override
+ public int getFilteredPatientCount(StudyViewFilterContext studyViewFilterContext) {
+ return mapper.getFilteredPatientsCount(createStudyViewFilterHelper(studyViewFilterContext));
+ }
+
+ @Override
+ public Map> getMatchingGenePanelIds(StudyViewFilterContext studyViewFilterContext, String alterationType) {
+ return mapper.getMatchingGenePanelIds(createStudyViewFilterHelper(studyViewFilterContext), alterationType)
+ .stream()
+ .collect(Collectors.groupingBy(GenePanelToGene::getHugoGeneSymbol,
+ Collectors.mapping(GenePanelToGene::getGenePanelId, Collectors.toSet())));
+ }
+
+ @Override
+ public int getTotalProfiledCountsByAlterationType(StudyViewFilterContext studyViewFilterContext, String alterationType) {
+ return mapper.getTotalProfiledCountByAlterationType(createStudyViewFilterHelper(studyViewFilterContext), alterationType);
+ }
+
+ @Override
+ public int getSampleProfileCountWithoutPanelData(StudyViewFilterContext studyViewFilterContext, String alterationType) {
+ return mapper.getSampleProfileCountWithoutPanelData(createStudyViewFilterHelper(studyViewFilterContext), alterationType);
+ }
+
+
+ @Override
+ public List getClinicalEventTypeCounts(StudyViewFilterContext studyViewFilterContext) {
+ return mapper.getClinicalEventTypeCounts(createStudyViewFilterHelper(studyViewFilterContext));
+ }
+
+ @Override
+ public List getPatientTreatments(StudyViewFilterContext studyViewFilterContext) {
+ return mapper.getPatientTreatments(createStudyViewFilterHelper(studyViewFilterContext));
+ }
+
+ @Override
+ public int getTotalPatientTreatmentCount(StudyViewFilterContext studyViewFilterContext) {
+ return mapper.getPatientTreatmentCounts(createStudyViewFilterHelper(studyViewFilterContext));
+ }
+
+ @Override
+ public List getSampleTreatments(StudyViewFilterContext studyViewFilterContext) {
+ return mapper.getSampleTreatmentCounts(createStudyViewFilterHelper(studyViewFilterContext));
+ }
+
+ @Override
+ public int getTotalSampleTreatmentCount(StudyViewFilterContext studyViewFilterContext) {
+ return mapper.getTotalSampleTreatmentCounts(createStudyViewFilterHelper(studyViewFilterContext));
+ }
+
+ @Override
+ public List getGenomicDataBinCounts(StudyViewFilterContext studyViewFilterContext, List genomicDataBinFilters) {
+ return mapper.getGenomicDataBinCounts(createStudyViewFilterHelper(studyViewFilterContext), genomicDataBinFilters);
+ }
+
+ @Override
+ public List getGenericAssayDataBinCounts(StudyViewFilterContext studyViewFilterContext, List genericAssayDataBinFilters) {
+ return mapper.getGenericAssayDataBinCounts(createStudyViewFilterHelper(studyViewFilterContext), genericAssayDataBinFilters);
+ }
+
+ private void buildClinicalAttributeNameMap() {
+ clinicalAttributesMap = this.getClinicalAttributes()
+ .stream()
+ .collect(Collectors.groupingBy(ca -> ca.getPatientAttribute().booleanValue() ? DataSource.PATIENT : DataSource.SAMPLE));
+ }
+
+ private void buildGenericAssayProfilesMap() {
+ genericAssayProfilesMap = this.getGenericAssayProfiles()
+ .stream()
+ .collect(Collectors.groupingBy(ca -> ca.getPatientLevel().booleanValue() ? DataSource.PATIENT : DataSource.SAMPLE));
+ }
+
+ private Map> getGenericAssayProfilesMap() {
+ if (genericAssayProfilesMap.isEmpty()) {
+ buildGenericAssayProfilesMap();
+ }
+ return genericAssayProfilesMap;
+ }
+
+ @Override
+ public List getCNACounts(StudyViewFilterContext studyViewFilterContext, List genomicDataFilters) {
+ return mapper.getCNACounts(createStudyViewFilterHelper(studyViewFilterContext), genomicDataFilters);
+ }
+
+ @Override
+ public List getGenericAssayDataCounts(StudyViewFilterContext studyViewFilterContext, List genericAssayDataFilters) {
+ return mapper.getGenericAssayDataCounts(createStudyViewFilterHelper(studyViewFilterContext), genericAssayDataFilters);
+ }
+
+ public Map getMutationCounts(StudyViewFilterContext studyViewFilterContext, GenomicDataFilter genomicDataFilter) {
+ return mapper.getMutationCounts(createStudyViewFilterHelper(studyViewFilterContext), genomicDataFilter);
+ }
+
+ public List getMutationCountsByType(StudyViewFilterContext studyViewFilterContext, List genomicDataFilters) {
+ return mapper.getMutationCountsByType(createStudyViewFilterHelper(studyViewFilterContext), genomicDataFilters);
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/org/cbioportal/persistence/mybatisclickhouse/config/PersistenceColumnarConfig.java b/src/main/java/org/cbioportal/persistence/mybatisclickhouse/config/PersistenceColumnarConfig.java
new file mode 100644
index 00000000000..7acea62ecec
--- /dev/null
+++ b/src/main/java/org/cbioportal/persistence/mybatisclickhouse/config/PersistenceColumnarConfig.java
@@ -0,0 +1,32 @@
+package org.cbioportal.persistence.mybatisclickhouse.config;
+
+import org.cbioportal.persistence.mybatis.typehandler.SampleTypeTypeHandler;
+import org.cbioportal.utils.config.annotation.ConditionalOnProperty;
+import org.mybatis.spring.SqlSessionFactoryBean;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import javax.sql.DataSource;
+import java.io.IOException;
+
+
+@Configuration
+@ConditionalOnProperty(name = "clickhouse_mode", havingValue = "true")
+@MapperScan(value= "org.cbioportal.persistence.mybatisclickhouse", sqlSessionFactoryRef ="sqlColumnarSessionFactory")
+public class PersistenceColumnarConfig {
+
+ @Bean("sqlColumnarSessionFactory")
+ public SqlSessionFactoryBean sqlColumnarSessionFactory(@Qualifier("clickhouseDataSource") DataSource dataSource, ApplicationContext applicationContext) throws IOException {
+ SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
+ sessionFactory.setDataSource(dataSource);
+ sessionFactory.setMapperLocations(
+ applicationContext.getResources("classpath:org/cbioportal/persistence/mybatisclickhouse/*.xml")
+ );
+ sessionFactory.setTypeHandlers(new SampleTypeTypeHandler());
+ return sessionFactory;
+ }
+
+}
diff --git a/src/main/java/org/cbioportal/persistence/util/CustomKeyGenerator.java b/src/main/java/org/cbioportal/persistence/util/CustomKeyGenerator.java
index 1ae254cef05..948d5d344c5 100644
--- a/src/main/java/org/cbioportal/persistence/util/CustomKeyGenerator.java
+++ b/src/main/java/org/cbioportal/persistence/util/CustomKeyGenerator.java
@@ -64,7 +64,7 @@ public class CustomKeyGenerator implements KeyGenerator {
private static final Logger LOG = LoggerFactory.getLogger(CustomKeyGenerator.class);
public Object generate(Object target, Method method, Object... params) {
- if (!cacheEnabledConfig.isEnabled()) {
+ if (!cacheEnabledConfig.isEnabled() && !cacheEnabledConfig.isEnabledClickhouse()) {
return "";
}
String key = target.getClass().getSimpleName() + CACHE_KEY_PARAM_DELIMITER
diff --git a/src/main/java/org/cbioportal/persistence/util/RedisCacheUtils.java b/src/main/java/org/cbioportal/persistence/util/RedisCacheUtils.java
index 67639dc75b5..ec5579c544d 100644
--- a/src/main/java/org/cbioportal/persistence/util/RedisCacheUtils.java
+++ b/src/main/java/org/cbioportal/persistence/util/RedisCacheUtils.java
@@ -3,9 +3,9 @@
import static org.cbioportal.persistence.util.CustomRedisCache.DELIMITER;
-import org.cbioportal.utils.config.annotation.ConditionalOnProperty;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.stereotype.Component;
@@ -14,7 +14,9 @@
import java.util.stream.Collectors;
@Component
-@ConditionalOnProperty(name = "persistence.cache_type", havingValue = "redis")
+@ConditionalOnExpression(
+ "#{environment['persistence.cache_type'] == 'redis' or environment['persistence.cache_type_clickhouse'] == 'redis'}"
+)
public class RedisCacheUtils implements CacheUtils {
@Autowired
diff --git a/src/main/java/org/cbioportal/properties/CustomDataSourceConfiguration.java b/src/main/java/org/cbioportal/properties/CustomDataSourceConfiguration.java
new file mode 100644
index 00000000000..f71d07b1393
--- /dev/null
+++ b/src/main/java/org/cbioportal/properties/CustomDataSourceConfiguration.java
@@ -0,0 +1,39 @@
+package org.cbioportal.properties;
+
+import org.cbioportal.utils.config.annotation.ConditionalOnProperty;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import javax.sql.DataSource;
+
+@Configuration
+@ConditionalOnProperty(name = "clickhouse_mode", havingValue = "true")
+public class CustomDataSourceConfiguration {
+ @Bean
+ @ConfigurationProperties("spring.datasource.mysql")
+ public DataSourceProperties mysqlDataSourceProperties() {
+ return new DataSourceProperties();
+ }
+
+ @Bean
+ @ConfigurationProperties("spring.datasource.clickhouse")
+ public DataSourceProperties clickhouseDatSourceProperties() {
+ return new DataSourceProperties();
+ }
+
+ @Bean("mysqlDataSource")
+ public DataSource mysqlDataSource() {
+ return mysqlDataSourceProperties()
+ .initializeDataSourceBuilder()
+ .build();
+ }
+
+ @Bean("clickhouseDataSource")
+ public DataSource clickhouseDataSource() {
+ return clickhouseDatSourceProperties()
+ .initializeDataSourceBuilder()
+ .build();
+ }
+}
diff --git a/src/main/java/org/cbioportal/security/config/CorsConfig.java b/src/main/java/org/cbioportal/security/config/CorsConfig.java
index cd92394da49..d96050013cc 100644
--- a/src/main/java/org/cbioportal/security/config/CorsConfig.java
+++ b/src/main/java/org/cbioportal/security/config/CorsConfig.java
@@ -30,7 +30,7 @@ CorsConfigurationSource corsConfigurationSource() {
configuration.setAllowedHeaders(List.of("user-agent", "Origin", "Accept", "X-Requested-With","Content-Type",
"Access-Control-Request-Method","Access-Control-Request-Headers","Content-Encoding",
"X-Proxy-User-Agreement", "x-current-url"));
- configuration.setExposedHeaders(List.of("total-count", "sample-count"));
+ configuration.setExposedHeaders(List.of("total-count", "sample-count", "elapsed-time"));
source.registerCorsConfiguration("/**", configuration);
return source;
}
diff --git a/src/main/java/org/cbioportal/service/AlterationCountService.java b/src/main/java/org/cbioportal/service/AlterationCountService.java
index 5966f725a8d..eaec004682e 100644
--- a/src/main/java/org/cbioportal/service/AlterationCountService.java
+++ b/src/main/java/org/cbioportal/service/AlterationCountService.java
@@ -3,6 +3,11 @@
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;
+import org.cbioportal.web.parameter.StudyViewFilter;
import java.util.List;
@@ -75,4 +80,9 @@ Pair, Long> getPatientCnaGeneCounts(List getMutatedGenes(StudyViewFilterContext studyViewFilterContext) throws StudyNotFoundException;
+ List getCnaGenes(StudyViewFilterContext studyViewFilterContext) throws StudyNotFoundException;
+
+ List getStructuralVariantGenes(StudyViewFilterContext studyViewFilterContext) throws StudyNotFoundException;
+
}
diff --git a/src/main/java/org/cbioportal/service/ClinicalDataDensityPlotService.java b/src/main/java/org/cbioportal/service/ClinicalDataDensityPlotService.java
new file mode 100644
index 00000000000..211963e11b8
--- /dev/null
+++ b/src/main/java/org/cbioportal/service/ClinicalDataDensityPlotService.java
@@ -0,0 +1,13 @@
+package org.cbioportal.service;
+
+import org.cbioportal.model.ClinicalData;
+import org.cbioportal.model.DensityPlotData;
+import org.cbioportal.web.parameter.StudyViewFilter;
+import org.cbioportal.web.util.DensityPlotParameters;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+public interface ClinicalDataDensityPlotService {
+ DensityPlotData getDensityPlotData(List filteredClinicalData, DensityPlotParameters densityPlotParameters, StudyViewFilter studyViewFilter);
+}
diff --git a/src/main/java/org/cbioportal/service/FrontendPropertiesServiceImpl.java b/src/main/java/org/cbioportal/service/FrontendPropertiesServiceImpl.java
index 429f3346a77..abe7f299226 100644
--- a/src/main/java/org/cbioportal/service/FrontendPropertiesServiceImpl.java
+++ b/src/main/java/org/cbioportal/service/FrontendPropertiesServiceImpl.java
@@ -192,8 +192,12 @@ public enum FrontendProperty {
download_custom_buttons_json("download_custom_buttons_json", null),
enable_study_tags("enable_study_tags", null),
- enable_darwin("enable_darwin", null);
+ enable_darwin("enable_darwin", null),
+ clickhouse_mode("clickhouse_mode", "false");
+
+
+
private final String propertyName;
private final String defaultValue;
diff --git a/src/main/java/org/cbioportal/service/StudyViewColumnarService.java b/src/main/java/org/cbioportal/service/StudyViewColumnarService.java
new file mode 100644
index 00000000000..4f13dc68f78
--- /dev/null
+++ b/src/main/java/org/cbioportal/service/StudyViewColumnarService.java
@@ -0,0 +1,61 @@
+package org.cbioportal.service;
+
+import org.cbioportal.model.AlterationCountByGene;
+import org.cbioportal.model.CaseListDataCount;
+import org.cbioportal.model.ClinicalData;
+import org.cbioportal.model.ClinicalDataCountItem;
+import org.cbioportal.model.ClinicalEventTypeCount;
+import org.cbioportal.model.GenericAssayDataCountItem;
+import org.cbioportal.model.GenomicDataCountItem;
+import org.cbioportal.model.GenomicDataCount;
+import org.cbioportal.model.CopyNumberCountByGene;
+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.GenericAssayDataBinFilter;
+import org.cbioportal.web.parameter.GenericAssayDataFilter;
+import org.cbioportal.web.parameter.GenomicDataBinFilter;
+import org.cbioportal.web.parameter.GenomicDataFilter;
+import org.cbioportal.web.parameter.StudyViewFilter;
+
+import java.util.List;
+import java.util.Map;
+
+public interface StudyViewColumnarService {
+
+ List getFilteredSamples(StudyViewFilter studyViewFilter);
+
+ List getMutatedGenes(StudyViewFilter interceptedStudyViewFilter) throws StudyNotFoundException;
+ List getCnaGenes(StudyViewFilter interceptedStudyViewFilter) throws StudyNotFoundException;
+ List getStructuralVariantGenes(StudyViewFilter studyViewFilter) throws StudyNotFoundException;
+
+ Map getClinicalAttributeDatatypeMap(StudyViewFilter studyViewFilter);
+
+ List getClinicalDataCounts(StudyViewFilter studyViewFilter, List filteredAttributes);
+
+ List getCaseListDataCounts(StudyViewFilter studyViewFilter);
+
+ List getPatientClinicalData(StudyViewFilter studyViewFilter, List attributeIds);
+
+ List getSampleClinicalData(StudyViewFilter studyViewFilter, List attributeIds);
+
+ List getMolecularProfileSampleCounts(StudyViewFilter studyViewFilter);
+
+ List getClinicalEventTypeCounts(StudyViewFilter studyViewFilter);
+ PatientTreatmentReport getPatientTreatmentReport(StudyViewFilter studyViewFilter);
+ SampleTreatmentReport getSampleTreatmentReport(StudyViewFilter studyViewFilter);
+
+ List getCNACountsByGeneSpecific(StudyViewFilter studyViewFilter, List genomicDataFilters);
+
+ List getGenericAssayDataCounts(StudyViewFilter studyViewFilter, List genericAssayDataFilters);
+
+ List getMutationCountsByGeneSpecific(StudyViewFilter studyViewFilter, List genomicDataFilters);
+
+ List getGenomicDataBinCounts(StudyViewFilter studyViewFilter, List genomicDataBinFilters);
+
+ List getGenericAssayDataBinCounts(StudyViewFilter studyViewFilter, List genericAssayDataBinFilters);
+
+ List getMutationTypeCountsByGeneSpecific(StudyViewFilter studyViewFilter, List genomicDataFilters);
+}
diff --git a/src/main/java/org/cbioportal/service/ViolinPlotService.java b/src/main/java/org/cbioportal/service/ViolinPlotService.java
index 2737ffc24a1..37eade2f739 100644
--- a/src/main/java/org/cbioportal/service/ViolinPlotService.java
+++ b/src/main/java/org/cbioportal/service/ViolinPlotService.java
@@ -3,6 +3,7 @@
import org.cbioportal.model.ClinicalData;
import org.cbioportal.model.ClinicalViolinPlotData;
import org.cbioportal.model.Sample;
+import org.cbioportal.web.parameter.StudyViewFilter;
import java.math.BigDecimal;
import java.util.List;
@@ -15,6 +16,7 @@ ClinicalViolinPlotData getClinicalViolinPlotData(
BigDecimal axisEnd,
BigDecimal numCurvePoints,
Boolean useLogScale,
- BigDecimal sigmaMultiplier
+ BigDecimal sigmaMultiplier,
+ StudyViewFilter studyViewFilter
);
}
diff --git a/src/main/java/org/cbioportal/service/impl/AlterationCountServiceImpl.java b/src/main/java/org/cbioportal/service/impl/AlterationCountServiceImpl.java
index 4175ce3cf10..28f3d34611f 100644
--- a/src/main/java/org/cbioportal/service/impl/AlterationCountServiceImpl.java
+++ b/src/main/java/org/cbioportal/service/impl/AlterationCountServiceImpl.java
@@ -1,17 +1,40 @@
package org.cbioportal.service.impl;
-import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.math3.util.Pair;
-import org.cbioportal.model.*;
+import org.cbioportal.model.AlterationCountBase;
+import org.cbioportal.model.AlterationCountByGene;
+import org.cbioportal.model.AlterationCountByStructuralVariant;
+import org.cbioportal.model.AlterationFilter;
+import org.cbioportal.model.AlterationType;
+import org.cbioportal.model.CopyNumberCountByGene;
+import org.cbioportal.model.Gistic;
+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.AlterationCountServiceUtil;
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;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.BiFunction;
import java.util.function.Function;
@@ -20,17 +43,32 @@
@Service
public class AlterationCountServiceImpl implements AlterationCountService {
- @Autowired
- private AlterationRepository alterationRepository;
- @Autowired
- private AlterationEnrichmentUtil alterationEnrichmentUtil;
- @Autowired
- private AlterationEnrichmentUtil alterationEnrichmentUtilCna;
- @Autowired
- private AlterationEnrichmentUtil alterationEnrichmentUtilStructVar;
- @Autowired
- private MolecularProfileRepository molecularProfileRepository;
+ private final AlterationRepository alterationRepository;
+ private final AlterationEnrichmentUtil alterationEnrichmentUtil;
+ private final AlterationEnrichmentUtil alterationEnrichmentUtilCna;
+ private final AlterationEnrichmentUtil alterationEnrichmentUtilStructVar;
+ private final MolecularProfileRepository molecularProfileRepository;
+ private final SignificantlyMutatedGeneService significantlyMutatedGeneService;
+ private final StudyViewRepository studyViewRepository;
+ private final SignificantCopyNumberRegionService significantCopyNumberRegionService;
+
+ @Autowired
+ public AlterationCountServiceImpl(AlterationRepository alterationRepository, AlterationEnrichmentUtil alterationEnrichmentUtil,
+ AlterationEnrichmentUtil alterationEnrichmentUtilCna,
+ AlterationEnrichmentUtil alterationEnrichmentUtilStructVar,
+ MolecularProfileRepository molecularProfileRepository,
+ 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, Long> getSampleAlterationGeneCounts(List molecularProfileCaseIdentifiers,
Select entrezGeneIds,
@@ -223,6 +261,105 @@ public Pair, Long> getPatientCnaGeneCounts(List getMutatedGenes(StudyViewFilterContext studyViewFilterContext) throws StudyNotFoundException {
+ var alterationCountByGenes = populateAlterationCounts(AlterationCountServiceUtil.combineAlterationCountsWithConflictingHugoSymbols( studyViewRepository.getMutatedGenes(studyViewFilterContext)),
+ studyViewFilterContext, AlterationType.MUTATION_EXTENDED);
+ return populateAlterationCountsWithMutSigQValue(alterationCountByGenes, studyViewFilterContext);
+ }
+
+ public List getCnaGenes(StudyViewFilterContext studyViewFilterContext) throws StudyNotFoundException {
+ var copyNumberAlterationCounts = populateAlterationCounts(AlterationCountServiceUtil.combineCopyNumberCountsWithConflictingHugoSymbols(studyViewRepository.getCnaGenes(studyViewFilterContext)), studyViewFilterContext, AlterationType.COPY_NUMBER_ALTERATION);
+ return populateAlterationCountsWithCNASigQValue(copyNumberAlterationCounts, studyViewFilterContext);
+ }
+
+ @Override
+ public List getStructuralVariantGenes(StudyViewFilterContext studyViewFilterContext) throws StudyNotFoundException {
+ var alterationCountByGenes = populateAlterationCounts(AlterationCountServiceUtil.combineAlterationCountsWithConflictingHugoSymbols(studyViewRepository.getStructuralVariantGenes(studyViewFilterContext)),
+ studyViewFilterContext, AlterationType.STRUCTURAL_VARIANT);
+ return populateAlterationCountsWithMutSigQValue(alterationCountByGenes, studyViewFilterContext);
+ }
+
+ private < T extends AlterationCountByGene> List populateAlterationCounts(@NonNull List alterationCounts,
+ @NonNull StudyViewFilterContext studyViewFilterContext,
+ @NonNull AlterationType alterationType) {
+ final var firstMolecularProfileForEachStudy = getFirstMolecularProfileGroupedByStudy(studyViewFilterContext, alterationType);
+ final int totalProfiledCount = studyViewRepository.getTotalProfiledCountsByAlterationType(studyViewFilterContext, alterationType.toString());
+ var profiledCountsMap = studyViewRepository.getTotalProfiledCounts(studyViewFilterContext, alterationType.toString(), firstMolecularProfileForEachStudy);
+ final var matchingGenePanelIdsMap = studyViewRepository.getMatchingGenePanelIds(studyViewFilterContext, alterationType.toString());
+ final int sampleProfileCountWithoutGenePanelData = studyViewRepository.getSampleProfileCountWithoutPanelData(studyViewFilterContext, alterationType.toString());
+
+ alterationCounts.parallelStream()
+ .forEach(alterationCountByGene -> {
+ String hugoGeneSymbol = alterationCountByGene.getHugoGeneSymbol();
+ Set matchingGenePanelIds = matchingGenePanelIdsMap.get(hugoGeneSymbol) != null ?
+ matchingGenePanelIdsMap.get(hugoGeneSymbol) : Collections.emptySet();
+
+ int alterationTotalProfiledCount = AlterationCountServiceUtil.computeTotalProfiledCount(AlterationCountServiceUtil.hasGenePanelData(matchingGenePanelIds),
+ profiledCountsMap.getOrDefault(hugoGeneSymbol, 0),
+ sampleProfileCountWithoutGenePanelData, totalProfiledCount);
+
+ alterationCountByGene.setNumberOfProfiledCases(alterationTotalProfiledCount);
+
+ alterationCountByGene.setMatchingGenePanelIds(matchingGenePanelIds);
+
+ });
+ return alterationCounts;
+ }
+
+ private List populateAlterationCountsWithMutSigQValue(List alterationCountByGenes, StudyViewFilterContext studyViewFilterContext) throws StudyNotFoundException {
+ final var mutSigs = getMutSigs(studyViewFilterContext);
+ // If MutSig is not empty update Mutated Genes
+ return AlterationCountServiceUtil.updateAlterationCountsWithMutSigQValue(alterationCountByGenes, mutSigs);
+ }
+
+ private List populateAlterationCountsWithCNASigQValue(List alterationCountByGenes, StudyViewFilterContext studyViewFilterContext) throws StudyNotFoundException {
+ final var gisticMap = getGisticMap(studyViewFilterContext);
+
+ return AlterationCountServiceUtil.updateAlterationCountsWithCNASigQValue(alterationCountByGenes, gisticMap);
+ }
+
+ private List getFirstMolecularProfileGroupedByStudy(StudyViewFilterContext studyViewFilterContext, AlterationType alterationType) {
+ final var molecularProfiles = studyViewRepository.getFilteredMolecularProfilesByAlterationType(studyViewFilterContext, alterationType.toString());
+
+ return AlterationCountServiceUtil.getFirstMolecularProfileGroupedByStudy(molecularProfiles);
+ }
+
+ private Map getMutSigs(StudyViewFilterContext studyViewFilterContext) throws StudyNotFoundException {
+ var distinctStudyIds = studyViewRepository.getFilteredStudyIds(studyViewFilterContext);
+ Map 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, Gistic> getGisticMap(StudyViewFilterContext studyViewFilterContext) throws StudyNotFoundException {
+ var distinctStudyIds = studyViewRepository.getFilteredStudyIds(studyViewFilterContext);
+ Map, Gistic> gisticMap = new HashMap<>();
+ if (distinctStudyIds.size() == 1) {
+ var studyId = distinctStudyIds.getFirst();
+ List gisticList = significantCopyNumberRegionService.getSignificantCopyNumberRegions(
+ studyId,
+ Projection.SUMMARY.name(),
+ null,
+ null,
+ null,
+ null);
+ AlterationCountServiceUtil.setupGisticMap(gisticList, gisticMap);
+ }
+ return gisticMap;
+ }
+
private Pair